3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
24 */
25
26 /*
27 * Authentication support for SMB session setup
28 */
29
30 #include <sys/types.h>
31 #include <sys/sid.h>
32 #include <sys/priv_names.h>
33 #include <sys/socket.h>
34 #include <sys/un.h>
35 #include <netinet/in.h>
36 #include <smbsrv/smb_idmap.h>
37 #include <smbsrv/smb_kproto.h>
38 #include <smbsrv/smb_token.h>
39
40 static uint32_t smb_authsock_open(smb_user_t *);
41 static int smb_authsock_send(ksocket_t, void *, size_t);
42 static int smb_authsock_recv(ksocket_t, void *, size_t);
43 static uint32_t smb_authsock_sendrecv(smb_user_t *, smb_lsa_msg_hdr_t *hdr,
44 void *sndbuf, void **recvbuf);
45 /* void smb_authsock_close(smb_user_t *); kproto.h */
46
47 static uint32_t smb_auth_do_clinfo(smb_request_t *);
48 static uint32_t smb_auth_do_oldreq(smb_request_t *);
49 static uint32_t smb_auth_get_token(smb_request_t *);
50 static uint32_t smb_priv_xlate(smb_token_t *);
51
52 /*
53 * Handle old-style session setup (non-extended security)
54 *
55 * The user information is passed to smbd for authentication.
56 * If smbd can authenticate the user an access token is returned and we
57 * generate a cred and new user based on the token.
58 */
59 int
60 smb_authenticate_old(smb_request_t *sr)
61 {
62 smb_user_t *user = NULL;
63 uint32_t status;
64
65 user = smb_user_new(sr->session);
66 if (user == NULL)
67 return (NT_STATUS_TOO_MANY_SESSIONS);
68
69 /* user cleanup in smb_request_free */
70 sr->uid_user = user;
71 sr->smb_uid = user->u_uid;
72
73 /*
74 * Open a connection to the local logon service.
75 * If we can't, it may be busy, or not running.
76 * Don't log here - this may be frequent.
77 */
78 if ((status = smb_authsock_open(user)) != 0)
79 goto errout;
80
81 /*
82 * Tell the auth. svc who this client is.
83 */
84 if ((status = smb_auth_do_clinfo(sr)) != 0)
85 goto errout;
86
87 /*
88 * Authentication proper
89 */
90 if ((status = smb_auth_do_oldreq(sr)) != 0)
91 goto errout;
92
93 /*
94 * Get the final auth. token.
95 */
96 if ((status = smb_auth_get_token(sr)) != 0)
97 goto errout;
98
99 return (0);
100
101 errout:
102 smb_user_logoff(user);
103 return (status);
104 }
105
106 /*
107 * Build an authentication request message and
108 * send it to the local logon service.
109 */
110 static uint32_t
111 smb_auth_do_oldreq(smb_request_t *sr)
112 {
113 smb_lsa_msg_hdr_t msg_hdr;
114 smb_logon_t user_info;
115 XDR xdrs;
116 smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
117 smb_user_t *user = sr->uid_user;
118 void *sbuf = NULL;
119 void *rbuf = NULL;
120 uint32_t slen = 0;
121 uint32_t rlen = 0;
122 uint32_t status;
123 bool_t ok;
124
125 bzero(&user_info, sizeof (smb_logon_t));
126
127 user_info.lg_level = NETR_NETWORK_LOGON;
128 user_info.lg_username = sinfo->ssi_user;
129 user_info.lg_domain = sinfo->ssi_domain;
130 user_info.lg_workstation = sr->session->workstation;
131 user_info.lg_clnt_ipaddr = sr->session->ipaddr;
132 user_info.lg_local_ipaddr = sr->session->local_ipaddr;
133 user_info.lg_local_port = sr->session->s_local_port;
134 user_info.lg_challenge_key.val = sr->session->challenge_key;
135 user_info.lg_challenge_key.len = sr->session->challenge_len;
136 user_info.lg_nt_password.val = sinfo->ssi_ntpwd;
137 user_info.lg_nt_password.len = sinfo->ssi_ntpwlen;
138 user_info.lg_lm_password.val = sinfo->ssi_lmpwd;
139 user_info.lg_lm_password.len = sinfo->ssi_lmpwlen;
140 user_info.lg_native_os = sr->session->native_os;
141 user_info.lg_native_lm = sr->session->native_lm;
142 /* lg_flags? */
143
144 slen = xdr_sizeof(smb_logon_xdr, &user_info);
145 sbuf = kmem_alloc(slen, KM_SLEEP);
146 xdrmem_create(&xdrs, sbuf, slen, XDR_ENCODE);
147 ok = smb_logon_xdr(&xdrs, &user_info);
148 xdr_destroy(&xdrs);
149 if (!ok) {
150 status = RPC_NT_BAD_STUB_DATA;
151 goto out;
152 }
153
154 msg_hdr.lmh_msgtype = LSA_MTYPE_OLDREQ;
155 msg_hdr.lmh_msglen = slen;
156 status = smb_authsock_sendrecv(user, &msg_hdr, sbuf, &rbuf);
157 if (status != 0)
158 goto out;
159 rlen = msg_hdr.lmh_msglen;
160 kmem_free(sbuf, slen);
161 sbuf = NULL;
162
163 /*
164 * Decode the response message.
165 */
166 switch (msg_hdr.lmh_msgtype) {
167
168 case LSA_MTYPE_OK:
169 status = 0;
170 break;
171
172 case LSA_MTYPE_ERROR:
173 if (rlen == sizeof (smb_lsa_eresp_t)) {
174 smb_lsa_eresp_t *ler = rbuf;
175 status = ler->ler_ntstatus;
176 break;
215 * Outline:
216 * (a) On the first request (UID==0) create a USER object,
217 * and on subsequent requests, find USER by SMB UID.
218 * (b) Send message / recv. response as above,
219 * (c) If response says "we're done", close authsock
220 * (both success and failure must close authsock)
221 */
222 int
223 smb_authenticate_ext(smb_request_t *sr)
224 {
225 smb_lsa_msg_hdr_t msg_hdr;
226 smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
227 smb_user_t *user = NULL;
228 void *rbuf = NULL;
229 uint32_t rlen = 0;
230 uint32_t status;
231
232 ASSERT(sr->uid_user == NULL);
233
234 /*
235 * On the first request (UID==0) create a USER object.
236 * On subsequent requests (UID!=0) find the USER object.
237 * Either way, sr->uid_user is set, so our ref. on the
238 * user object is dropped during normal cleanup work
239 * for the smb_request (sr). Ditto u_authsock.
240 */
241 if (sr->smb_uid == 0) {
242 user = smb_user_new(sr->session);
243 if (user == NULL)
244 return (NT_STATUS_TOO_MANY_SESSIONS);
245
246 /* user cleanup in smb_request_free */
247 sr->uid_user = user;
248 sr->smb_uid = user->u_uid;
249
250 /*
251 * Open a connection to the local logon service.
252 * If we can't, it may be busy, or not running.
253 * Don't log here - this may be frequent.
254 */
255 if ((status = smb_authsock_open(user)) != 0)
256 goto errout;
257
258 /*
259 * Tell the auth. svc who this client is.
260 */
261 if ((status = smb_auth_do_clinfo(sr)) != 0)
262 goto errout;
263
264 msg_hdr.lmh_msgtype = LSA_MTYPE_ESFIRST;
265 } else {
266 user = smb_session_lookup_uid_st(sr->session,
267 sr->smb_uid, SMB_USER_STATE_LOGGING_ON);
268 if (user == NULL)
269 return (NT_STATUS_USER_SESSION_DELETED);
270
271 /* user cleanup in smb_request_free */
272 sr->uid_user = user;
273
274 msg_hdr.lmh_msgtype = LSA_MTYPE_ESNEXT;
275 }
276
277 /*
278 * Wrap the "security blob" with our header
279 * (LSA_MTYPE_ESFIRST or LSA_MTYPE_ESNEXT)
280 * and send it up the authsock with either
281 */
282 msg_hdr.lmh_msglen = sinfo->ssi_iseclen;
283 status = smb_authsock_sendrecv(user, &msg_hdr,
284 sinfo->ssi_isecblob, &rbuf);
285 if (status != 0)
286 goto errout;
287 rlen = msg_hdr.lmh_msglen;
288
289 /*
290 * Decode the response message.
291 * Note: allocated rbuf
292 */
293 switch (msg_hdr.lmh_msgtype) {
294
295 case LSA_MTYPE_ES_CONT:
296 sinfo->ssi_oseclen = (uint16_t)rlen;
297 sinfo->ssi_osecblob = smb_srm_alloc(sr, sinfo->ssi_oseclen);
298 bcopy(rbuf, sinfo->ssi_osecblob, sinfo->ssi_oseclen);
299 /*
300 * This is not really an error, but tells the client
301 * it should send another session setup request.
302 */
303 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
333
334 if (status != 0 && status != NT_STATUS_MORE_PROCESSING_REQUIRED) {
335 errout:
336 smb_user_logoff(user);
337 }
338
339 if (rbuf != NULL)
340 kmem_free(rbuf, rlen);
341
342 return (status);
343 }
344
345 /*
346 * Send the "client info" up to the auth service.
347 */
348 static uint32_t
349 smb_auth_do_clinfo(smb_request_t *sr)
350 {
351 smb_lsa_msg_hdr_t msg_hdr;
352 smb_lsa_clinfo_t clinfo;
353 smb_user_t *user = sr->uid_user;
354 void *rbuf = NULL;
355 uint32_t status;
356
357 /*
358 * Send a message with info. about the client
359 * (IP address, etc) and wait for an ACK.
360 */
361 msg_hdr.lmh_msgtype = LSA_MTYPE_CLINFO;
362 msg_hdr.lmh_msglen = sizeof (clinfo);
363 clinfo.lci_clnt_ipaddr = sr->session->ipaddr;
364 (void) memcpy(clinfo.lci_challenge_key,
365 sr->session->challenge_key,
366 sizeof (clinfo.lci_challenge_key));
367 status = smb_authsock_sendrecv(user, &msg_hdr, &clinfo, &rbuf);
368 /* We don't use this response. */
369 if (rbuf != NULL) {
370 kmem_free(rbuf, msg_hdr.lmh_msglen);
371 rbuf = NULL;
372 }
373
374 return (status);
375 }
376
377 /*
378 * After a successful authentication, ask the authsvc to
379 * send us the authentication token.
380 */
381 static uint32_t
382 smb_auth_get_token(smb_request_t *sr)
383 {
384 smb_lsa_msg_hdr_t msg_hdr;
385 XDR xdrs;
386 smb_user_t *user = sr->uid_user;
387 smb_token_t *token = NULL;
388 cred_t *cr = NULL;
389 void *rbuf = NULL;
390 uint32_t rlen = 0;
391 uint32_t privileges;
392 uint32_t status;
393 int rc;
394 bool_t ok;
395
396 msg_hdr.lmh_msgtype = LSA_MTYPE_GETTOK;
397 msg_hdr.lmh_msglen = 0;
398
399 status = smb_authsock_sendrecv(user, &msg_hdr, NULL, &rbuf);
400 if (status != 0)
401 goto errout;
402
403 rlen = msg_hdr.lmh_msglen;
404 switch (msg_hdr.lmh_msgtype) {
405
406 case LSA_MTYPE_TOKEN:
407 status = 0;
408 break;
409
410 case LSA_MTYPE_ERROR:
411 if (rlen == sizeof (smb_lsa_eresp_t)) {
412 smb_lsa_eresp_t *ler = rbuf;
413 status = ler->ler_ntstatus;
414 goto errout;
415 }
416 /* FALLTHROUGH */
417
418 default:
419 status = NT_STATUS_INTERNAL_ERROR;
420 goto errout;
421 }
422
423 /*
424 * Authenticated. Decode the LSA_MTYPE_TOKEN.
425 */
426 xdrmem_create(&xdrs, rbuf, rlen, XDR_DECODE);
427 token = kmem_zalloc(sizeof (smb_token_t), KM_SLEEP);
428 ok = smb_token_xdr(&xdrs, token);
429 xdr_destroy(&xdrs);
430 if (!ok) {
431 status = RPC_NT_BAD_STUB_DATA;
432 goto errout;
433 }
434 kmem_free(rbuf, rlen);
435 rbuf = NULL;
436
437 /*
438 * Setup the logon object.
439 */
440 cr = smb_cred_create(token);
441 if (cr == NULL)
442 goto errout;
443 privileges = smb_priv_xlate(token);
444 (void) smb_user_logon(user, cr,
445 token->tkn_domain_name, token->tkn_account_name,
446 token->tkn_flags, privileges, token->tkn_audit_sid);
447 crfree(cr);
448
449 /*
450 * Save the session key, and (maybe) enable signing,
451 * but only for real logon (not ANON or GUEST).
452 */
453 if ((token->tkn_flags & (SMB_ATF_GUEST | SMB_ATF_ANON)) == 0) {
454 if (sr->session->dialect >= SMB_VERS_2_BASE) {
455 rc = smb2_sign_begin(sr, token);
456 } else {
457 rc = smb_sign_begin(sr, token);
458 }
459 if (rc != 0) {
460 status = NT_STATUS_INTERNAL_ERROR;
461 goto errout;
462 }
463 }
464
465 smb_token_free(token);
466
467 sr->user_cr = user->u_cred;
468 return (0);
469
470 errout:
471 if (rbuf != NULL)
472 kmem_free(rbuf, rlen);
473 if (token != NULL)
474 smb_token_free(token);
475 return (status);
476 }
477
478 /*
479 * Tokens are allocated in the kernel via XDR.
480 * Call xdr_free before freeing the token structure.
481 */
482 void
483 smb_token_free(smb_token_t *token)
484 {
485 if (token != NULL) {
486 xdr_free(smb_token_xdr, (char *)token);
487 kmem_free(token, sizeof (smb_token_t));
488 }
489 }
490
491 /*
492 * Convert access token privileges to local definitions.
493 */
494 static uint32_t
495 smb_priv_xlate(smb_token_t *token)
496 {
497 uint32_t privileges = 0;
498
499 if (smb_token_query_privilege(token, SE_BACKUP_LUID))
500 privileges |= SMB_USER_PRIV_BACKUP;
501
502 if (smb_token_query_privilege(token, SE_RESTORE_LUID))
503 privileges |= SMB_USER_PRIV_RESTORE;
504
505 if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID))
506 privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP;
507
508 if (smb_token_query_privilege(token, SE_SECURITY_LUID))
509 privileges |= SMB_USER_PRIV_SECURITY;
510
511 return (privileges);
512 }
513
514 /*
515 * Send/recv a request/reply sequence on the auth socket.
516 * Returns zero or an NT status.
517 *
518 * Errors here mean we can't communicate with the smbd_authsvc.
519 * With limited authsock instances, this should be rare.
520 */
521 static uint32_t
522 smb_authsock_sendrecv(smb_user_t *user, smb_lsa_msg_hdr_t *hdr,
523 void *sndbuf, void **recvbuf)
524 {
525 ksocket_t so;
526 uint32_t status;
527 int rc;
528
529 /*
530 * Get a hold on the auth socket.
531 */
532 mutex_enter(&user->u_mutex);
533 so = user->u_authsock;
534 if (so == NULL) {
535 mutex_exit(&user->u_mutex);
536 return (NT_STATUS_INTERNAL_ERROR);
537 }
538 ksocket_hold(so);
539 mutex_exit(&user->u_mutex);
540
541 rc = smb_authsock_send(so, hdr, sizeof (*hdr));
542 if (rc == 0 && hdr->lmh_msglen != 0) {
543 rc = smb_authsock_send(so, sndbuf, hdr->lmh_msglen);
544 }
545 if (rc)
546 goto out;
547
548 rc = smb_authsock_recv(so, hdr, sizeof (*hdr));
549 if (rc == 0 && hdr->lmh_msglen != 0) {
550 *recvbuf = kmem_alloc(hdr->lmh_msglen, KM_SLEEP);
551 rc = smb_authsock_recv(so, *recvbuf, hdr->lmh_msglen);
552 if (rc) {
553 kmem_free(*recvbuf, hdr->lmh_msglen);
554 *recvbuf = NULL;
555 }
556 }
557
558 out:
559 ksocket_rele(so);
560 switch (rc) {
561 case 0:
562 status = 0;
563 break;
564 case EIO:
565 status = RPC_NT_COMM_FAILURE;
566 break;
567 case ENOTCONN:
568 status = RPC_NT_PIPE_CLOSED;
569 break;
570 default:
571 status = RPC_NT_CALL_FAILED;
572 break;
573 }
574
575 return (status);
576 }
577
578 /*
579 * Hope this is interpreted per-zone...
580 */
581 static struct sockaddr_un smbauth_sockname = {
582 AF_UNIX, SMB_AUTHSVC_SOCKNAME };
583
584 /*
585 * Limit how long smb_authsock_sendrecv() will wait for a
586 * response from the local authentication service.
587 */
588 struct timeval smb_auth_recv_tmo = { 45, 0 };
589
590 /*
591 * Also limit the time smb_authsock_sendrecv() will wait
592 * trying to send a request to the authentication service.
593 */
594 struct timeval smb_auth_send_tmo = { 15, 0 };
595
596 static uint32_t
597 smb_authsock_open(smb_user_t *user)
598 {
599 smb_server_t *sv = user->u_server;
600 ksocket_t so = NULL;
601 uint32_t status;
602 int rc;
603
604 /*
605 * If the auth. service is busy, wait our turn.
606 * This may be frequent, so don't log.
607 */
608 if ((rc = smb_threshold_enter(&sv->sv_ssetup_ct)) != 0)
609 return (NT_STATUS_NO_LOGON_SERVERS);
610
611 rc = ksocket_socket(&so, AF_UNIX, SOCK_STREAM, 0,
612 KSOCKET_SLEEP, CRED());
613 if (rc != 0) {
614 cmn_err(CE_NOTE, "smb_authsock_open: socket, rc=%d", rc);
615 status = NT_STATUS_INSUFF_SERVER_RESOURCES;
616 goto errout;
617 }
618
619 /*
620 * Set the send/recv timeouts.
621 */
622 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_SNDTIMEO,
623 &smb_auth_send_tmo, sizeof (smb_auth_send_tmo), CRED());
624 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO,
625 &smb_auth_recv_tmo, sizeof (smb_auth_recv_tmo), CRED());
626
627 /*
628 * Connect to the smbd auth. service.
629 *
630 * Would like to set the connect timeout too, but there's
631 * apparently no easy way to do that for AF_UNIX.
632 */
633 rc = ksocket_connect(so, (struct sockaddr *)&smbauth_sockname,
634 sizeof (smbauth_sockname), CRED());
635 if (rc != 0) {
636 DTRACE_PROBE1(error, int, rc);
637 status = NT_STATUS_NETLOGON_NOT_STARTED;
638 goto errout;
639 }
640
641 /* Note: u_authsock cleanup in smb_authsock_close() */
642 mutex_enter(&user->u_mutex);
643 if (user->u_authsock != NULL) {
644 mutex_exit(&user->u_mutex);
645 status = NT_STATUS_INTERNAL_ERROR;
646 goto errout;
647 }
648 user->u_authsock = so;
649 mutex_exit(&user->u_mutex);
650 return (0);
651
652 errout:
653 if (so != NULL)
654 (void) ksocket_close(so, CRED());
655 smb_threshold_exit(&sv->sv_ssetup_ct);
656
657 return (status);
658 }
659
660 static int
661 smb_authsock_send(ksocket_t so, void *buf, size_t len)
662 {
663 int rc;
664 size_t iocnt = 0;
665
666 rc = ksocket_send(so, buf, len, 0, &iocnt, CRED());
667 if (rc == 0 && iocnt != len) {
668 DTRACE_PROBE1(short, size_t, iocnt);
669 rc = EIO;
670 }
671 if (rc != 0) {
672 DTRACE_PROBE1(error, int, rc);
673 }
674
675 return (rc);
676 }
682 size_t iocnt = 0;
683
684 rc = ksocket_recv(so, buf, len, MSG_WAITALL, &iocnt, CRED());
685 if (rc == 0) {
686 if (iocnt == 0) {
687 DTRACE_PROBE1(discon, struct sonode *, so);
688 rc = ENOTCONN;
689 } else if (iocnt != len) {
690 /* Should not happen with MSG_WAITALL */
691 DTRACE_PROBE1(short, size_t, iocnt);
692 rc = EIO;
693 }
694 }
695 if (rc != 0) {
696 DTRACE_PROBE1(error, int, rc);
697 }
698
699 return (rc);
700 }
701
702 void
703 smb_authsock_close(smb_user_t *user)
704 {
705
706 ASSERT(MUTEX_HELD(&user->u_mutex));
707 if (user->u_authsock == NULL)
708 return;
709 (void) ksocket_close(user->u_authsock, CRED());
710 user->u_authsock = NULL;
711 smb_threshold_exit(&user->u_server->sv_ssetup_ct);
712 }
|
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2019 Nexenta Systems, Inc. All rights reserved.
24 */
25
26 /*
27 * Authentication support for SMB session setup
28 */
29
30 #include <sys/types.h>
31 #include <sys/sid.h>
32 #include <sys/priv_names.h>
33 #include <sys/socket.h>
34 #include <sys/un.h>
35 #include <netinet/in.h>
36 #include <smbsrv/smb_idmap.h>
37 #include <smbsrv/smb_kproto.h>
38 #include <smbsrv/smb_token.h>
39
40 static uint32_t smb_authsock_open(smb_request_t *);
41 static int smb_authsock_send(ksocket_t, void *, size_t);
42 static int smb_authsock_recv(ksocket_t, void *, size_t);
43 static uint32_t smb_authsock_sendrecv(smb_request_t *, smb_lsa_msg_hdr_t *hdr,
44 void *sndbuf, void **recvbuf);
45 /* void smb_authsock_close(smb_user_t *); kproto.h */
46
47 static uint32_t smb_auth_do_clinfo(smb_request_t *);
48 static uint32_t smb_auth_do_oldreq(smb_request_t *);
49 static uint32_t smb_auth_get_token(smb_request_t *);
50 static uint32_t smb_priv_xlate(smb_token_t *);
51
52 /*
53 * Handle old-style session setup (non-extended security)
54 * Note: Used only by SMB1
55 *
56 * The user information is passed to smbd for authentication.
57 * If smbd can authenticate the user an access token is returned and we
58 * generate a cred and new user based on the token.
59 */
60 int
61 smb_authenticate_old(smb_request_t *sr)
62 {
63 smb_user_t *user = NULL;
64 uint32_t status;
65
66 user = smb_user_new(sr->session);
67 if (user == NULL)
68 return (NT_STATUS_TOO_MANY_SESSIONS);
69
70 /* user cleanup in smb_request_free */
71 sr->uid_user = user;
72 sr->smb_uid = user->u_uid;
73 sr->smb2_ssnid = 0;
74
75 /*
76 * Open a connection to the local logon service.
77 * If we can't, it may be busy, or not running.
78 * Don't log here - this may be frequent.
79 */
80 if ((status = smb_authsock_open(sr)) != 0)
81 goto errout;
82
83 /*
84 * Tell the auth. svc who this client is.
85 */
86 if ((status = smb_auth_do_clinfo(sr)) != 0)
87 goto errout;
88
89 /*
90 * Authentication proper
91 */
92 if ((status = smb_auth_do_oldreq(sr)) != 0)
93 goto errout;
94
95 /*
96 * Get the final auth. token.
97 */
98 if ((status = smb_auth_get_token(sr)) != 0)
99 goto errout;
100
101 return (0);
102
103 errout:
104 smb_user_logoff(user);
105 return (status);
106 }
107
108 /*
109 * Build an authentication request message and
110 * send it to the local logon service.
111 */
112 static uint32_t
113 smb_auth_do_oldreq(smb_request_t *sr)
114 {
115 smb_lsa_msg_hdr_t msg_hdr;
116 smb_logon_t user_info;
117 XDR xdrs;
118 smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
119 void *sbuf = NULL;
120 void *rbuf = NULL;
121 uint32_t slen = 0;
122 uint32_t rlen = 0;
123 uint32_t status;
124 bool_t ok;
125
126 bzero(&user_info, sizeof (smb_logon_t));
127
128 user_info.lg_level = NETR_NETWORK_LOGON;
129 user_info.lg_username = sinfo->ssi_user;
130 user_info.lg_domain = sinfo->ssi_domain;
131 user_info.lg_workstation = sr->session->workstation;
132 user_info.lg_clnt_ipaddr = sr->session->ipaddr;
133 user_info.lg_local_ipaddr = sr->session->local_ipaddr;
134 user_info.lg_local_port = sr->session->s_local_port;
135 user_info.lg_challenge_key.val = sr->session->challenge_key;
136 user_info.lg_challenge_key.len = sr->session->challenge_len;
137 user_info.lg_nt_password.val = sinfo->ssi_ntpwd;
138 user_info.lg_nt_password.len = sinfo->ssi_ntpwlen;
139 user_info.lg_lm_password.val = sinfo->ssi_lmpwd;
140 user_info.lg_lm_password.len = sinfo->ssi_lmpwlen;
141 user_info.lg_native_os = sr->session->native_os;
142 user_info.lg_native_lm = sr->session->native_lm;
143 /* lg_flags? */
144
145 slen = xdr_sizeof(smb_logon_xdr, &user_info);
146 sbuf = kmem_alloc(slen, KM_SLEEP);
147 xdrmem_create(&xdrs, sbuf, slen, XDR_ENCODE);
148 ok = smb_logon_xdr(&xdrs, &user_info);
149 xdr_destroy(&xdrs);
150 if (!ok) {
151 status = RPC_NT_BAD_STUB_DATA;
152 goto out;
153 }
154
155 msg_hdr.lmh_msgtype = LSA_MTYPE_OLDREQ;
156 msg_hdr.lmh_msglen = slen;
157 status = smb_authsock_sendrecv(sr, &msg_hdr, sbuf, &rbuf);
158 if (status != 0)
159 goto out;
160 rlen = msg_hdr.lmh_msglen;
161 kmem_free(sbuf, slen);
162 sbuf = NULL;
163
164 /*
165 * Decode the response message.
166 */
167 switch (msg_hdr.lmh_msgtype) {
168
169 case LSA_MTYPE_OK:
170 status = 0;
171 break;
172
173 case LSA_MTYPE_ERROR:
174 if (rlen == sizeof (smb_lsa_eresp_t)) {
175 smb_lsa_eresp_t *ler = rbuf;
176 status = ler->ler_ntstatus;
177 break;
216 * Outline:
217 * (a) On the first request (UID==0) create a USER object,
218 * and on subsequent requests, find USER by SMB UID.
219 * (b) Send message / recv. response as above,
220 * (c) If response says "we're done", close authsock
221 * (both success and failure must close authsock)
222 */
223 int
224 smb_authenticate_ext(smb_request_t *sr)
225 {
226 smb_lsa_msg_hdr_t msg_hdr;
227 smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
228 smb_user_t *user = NULL;
229 void *rbuf = NULL;
230 uint32_t rlen = 0;
231 uint32_t status;
232
233 ASSERT(sr->uid_user == NULL);
234
235 /*
236 * Paranoid: While finding/creating the user object, make sure
237 * SMB2 ignores smb_uid, and SMB1 ignores smb2_ssnid. The
238 * logic below assumes the "other" one is always zero; both
239 * the "first request" tests and smb_session_lookup_uid_st.
240 */
241 if (sr->session->dialect >= SMB_VERS_2_BASE) {
242 /* SMB2+ ignores smb_uid */
243 ASSERT(sr->smb_uid == 0);
244 sr->smb_uid = 0;
245 } else {
246 /* SMB1 ignores smb2_ssnid */
247 ASSERT(sr->smb2_ssnid == 0);
248 sr->smb2_ssnid = 0;
249 }
250
251 /*
252 * On the first request (UID/ssnid==0) create a USER object.
253 * On subsequent requests (UID/ssnid!=0) find the USER object.
254 * Either way, sr->uid_user is set, so our ref. on the
255 * user object is dropped during normal cleanup work
256 * for the smb_request (sr). Ditto u_authsock.
257 */
258 if (sr->smb2_ssnid == 0 && sr->smb_uid == 0) {
259 user = smb_user_new(sr->session);
260 if (user == NULL)
261 return (NT_STATUS_TOO_MANY_SESSIONS);
262
263 /* user cleanup in smb_request_free */
264 sr->uid_user = user;
265 if (sr->session->dialect >= SMB_VERS_2_BASE) {
266 /* Intentionally leave smb_uid=0 for SMB2 */
267 sr->smb2_ssnid = user->u_ssnid;
268 } else {
269 /* Intentionally leave smb2_ssnid=0 for SMB1 */
270 sr->smb_uid = user->u_uid;
271 }
272
273 /*
274 * Open a connection to the local logon service.
275 * If we can't, it may be busy, or not running.
276 * Don't log here - this may be frequent.
277 */
278 if ((status = smb_authsock_open(sr)) != 0)
279 goto errout;
280
281 /*
282 * Tell the auth. svc who this client is.
283 */
284 if ((status = smb_auth_do_clinfo(sr)) != 0)
285 goto errout;
286
287 msg_hdr.lmh_msgtype = LSA_MTYPE_ESFIRST;
288 } else {
289 user = smb_session_lookup_uid_st(sr->session,
290 sr->smb2_ssnid, sr->smb_uid, SMB_USER_STATE_LOGGING_ON);
291 if (user == NULL)
292 return (NT_STATUS_USER_SESSION_DELETED);
293
294 /* user cleanup in smb_request_free */
295 sr->uid_user = user;
296
297 msg_hdr.lmh_msgtype = LSA_MTYPE_ESNEXT;
298 }
299
300 /*
301 * Wrap the "security blob" with our header
302 * (LSA_MTYPE_ESFIRST or LSA_MTYPE_ESNEXT)
303 * and send it up the authsock with either
304 */
305 msg_hdr.lmh_msglen = sinfo->ssi_iseclen;
306 status = smb_authsock_sendrecv(sr, &msg_hdr,
307 sinfo->ssi_isecblob, &rbuf);
308 if (status != 0)
309 goto errout;
310 rlen = msg_hdr.lmh_msglen;
311
312 /*
313 * Decode the response message.
314 * Note: allocated rbuf
315 */
316 switch (msg_hdr.lmh_msgtype) {
317
318 case LSA_MTYPE_ES_CONT:
319 sinfo->ssi_oseclen = (uint16_t)rlen;
320 sinfo->ssi_osecblob = smb_srm_alloc(sr, sinfo->ssi_oseclen);
321 bcopy(rbuf, sinfo->ssi_osecblob, sinfo->ssi_oseclen);
322 /*
323 * This is not really an error, but tells the client
324 * it should send another session setup request.
325 */
326 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
356
357 if (status != 0 && status != NT_STATUS_MORE_PROCESSING_REQUIRED) {
358 errout:
359 smb_user_logoff(user);
360 }
361
362 if (rbuf != NULL)
363 kmem_free(rbuf, rlen);
364
365 return (status);
366 }
367
368 /*
369 * Send the "client info" up to the auth service.
370 */
371 static uint32_t
372 smb_auth_do_clinfo(smb_request_t *sr)
373 {
374 smb_lsa_msg_hdr_t msg_hdr;
375 smb_lsa_clinfo_t clinfo;
376 void *rbuf = NULL;
377 uint32_t status;
378
379 /*
380 * Send a message with info. about the client
381 * (IP address, etc) and wait for an ACK.
382 */
383 msg_hdr.lmh_msgtype = LSA_MTYPE_CLINFO;
384 msg_hdr.lmh_msglen = sizeof (clinfo);
385 clinfo.lci_clnt_ipaddr = sr->session->ipaddr;
386 (void) memcpy(clinfo.lci_challenge_key,
387 sr->session->challenge_key,
388 sizeof (clinfo.lci_challenge_key));
389 status = smb_authsock_sendrecv(sr, &msg_hdr, &clinfo, &rbuf);
390 /* We don't use this response. */
391 if (rbuf != NULL) {
392 kmem_free(rbuf, msg_hdr.lmh_msglen);
393 rbuf = NULL;
394 }
395
396 return (status);
397 }
398
399 /*
400 * After a successful authentication, ask the authsvc to
401 * send us the authentication token.
402 */
403 static uint32_t
404 smb_auth_get_token(smb_request_t *sr)
405 {
406 smb_lsa_msg_hdr_t msg_hdr;
407 XDR xdrs;
408 smb_user_t *user = sr->uid_user;
409 smb_token_t *token = NULL;
410 cred_t *cr = NULL;
411 void *rbuf = NULL;
412 uint32_t rlen = 0;
413 uint32_t privileges;
414 uint32_t status;
415 bool_t ok;
416
417 msg_hdr.lmh_msgtype = LSA_MTYPE_GETTOK;
418 msg_hdr.lmh_msglen = 0;
419
420 status = smb_authsock_sendrecv(sr, &msg_hdr, NULL, &rbuf);
421 if (status != 0)
422 goto errout;
423
424 rlen = msg_hdr.lmh_msglen;
425 switch (msg_hdr.lmh_msgtype) {
426
427 case LSA_MTYPE_TOKEN:
428 status = 0;
429 break;
430
431 case LSA_MTYPE_ERROR:
432 if (rlen == sizeof (smb_lsa_eresp_t)) {
433 smb_lsa_eresp_t *ler = rbuf;
434 status = ler->ler_ntstatus;
435 goto errout;
436 }
437 /* FALLTHROUGH */
438
439 default:
440 status = NT_STATUS_INTERNAL_ERROR;
441 goto errout;
442 }
443
444 /*
445 * Authenticated. Decode the LSA_MTYPE_TOKEN.
446 */
447 xdrmem_create(&xdrs, rbuf, rlen, XDR_DECODE);
448 token = kmem_zalloc(sizeof (smb_token_t), KM_SLEEP);
449 ok = smb_token_xdr(&xdrs, token);
450 xdr_destroy(&xdrs);
451 if (!ok) {
452 status = RPC_NT_BAD_STUB_DATA;
453 goto errout;
454 }
455 kmem_free(rbuf, rlen);
456 rbuf = NULL;
457
458 /*
459 * Setup the logon object.
460 */
461 cr = smb_cred_create(token, sr->session);
462 if (cr == NULL)
463 goto errout;
464 privileges = smb_priv_xlate(token);
465 (void) smb_user_logon(user, cr,
466 token->tkn_domain_name, token->tkn_account_name,
467 token->tkn_flags, privileges, token->tkn_audit_sid);
468 crfree(cr);
469
470 /*
471 * Some basic processing for encryption needs to be done,
472 * even for anonymous/guest sessions. In particular,
473 * we need to set Session.EncryptData.
474 *
475 * Windows handling of anon/guest and encryption is strange.
476 * It allows these accounts to get through session setup,
477 * even when they provide no key material.
478 * Additionally, Windows somehow manages to have key material
479 * for anonymous accounts under unknown circumstances.
480 * As such, We set EncryptData on anon/guest to behave like Windows,
481 * at least through Session Setup.
482 */
483 if (sr->session->dialect >= SMB_VERS_3_0)
484 smb3_encrypt_begin(sr, token);
485
486 /*
487 * Save the session key, and (maybe) enable signing,
488 * but only for real logon (not ANON or GUEST).
489 */
490 if ((token->tkn_flags & (SMB_ATF_GUEST | SMB_ATF_ANON)) == 0) {
491 if (sr->session->dialect >= SMB_VERS_2_BASE) {
492 smb2_sign_begin(sr, token);
493 } else {
494 smb_sign_begin(sr, token);
495 }
496 }
497
498 smb_token_free(token);
499
500 sr->user_cr = user->u_cred;
501 return (0);
502
503 errout:
504 if (rbuf != NULL)
505 kmem_free(rbuf, rlen);
506 if (token != NULL)
507 smb_token_free(token);
508 return (status);
509 }
510
511 /*
512 * Tokens are allocated in the kernel via XDR.
513 * Call xdr_free before freeing the token structure.
514 */
515 void
516 smb_token_free(smb_token_t *token)
517 {
518 if (token != NULL) {
519 xdr_free(smb_token_xdr, (char *)token);
520 kmem_free(token, sizeof (smb_token_t));
521 }
522 }
523
524 /*
525 * Convert access token privileges to local definitions.
526 */
527 static uint32_t
528 smb_priv_xlate(smb_token_t *token)
529 {
530 uint32_t privileges = 0;
531
532 if (smb_token_query_privilege(token, SE_SECURITY_LUID))
533 privileges |= SMB_USER_PRIV_SECURITY;
534
535 if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID))
536 privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP;
537
538 if (smb_token_query_privilege(token, SE_BACKUP_LUID))
539 privileges |= SMB_USER_PRIV_BACKUP;
540
541 if (smb_token_query_privilege(token, SE_RESTORE_LUID))
542 privileges |= SMB_USER_PRIV_RESTORE;
543
544 if (smb_token_query_privilege(token, SE_CHANGE_NOTIFY_LUID))
545 privileges |= SMB_USER_PRIV_CHANGE_NOTIFY;
546
547 return (privileges);
548 }
549
550 /*
551 * Unblock a request that might be blocked reading some
552 * authentication socket. This can happen when either the
553 * client cancels a session setup or closes the connection.
554 */
555 static void
556 smb_authsock_cancel(smb_request_t *sr)
557 {
558 smb_user_t *user = sr->cancel_arg2;
559 ksocket_t authsock = NULL;
560
561 if (user == NULL)
562 return;
563 ASSERT(user == sr->uid_user);
564
565 /*
566 * Check user state, and get a hold on the auth socket.
567 */
568 mutex_enter(&user->u_mutex);
569 if (user->u_state == SMB_USER_STATE_LOGGING_ON) {
570 if ((authsock = user->u_authsock) != NULL)
571 ksocket_hold(authsock);
572 }
573 mutex_exit(&user->u_mutex);
574
575 if (authsock != NULL) {
576 (void) ksocket_shutdown(authsock, SHUT_RDWR, sr->user_cr);
577 ksocket_rele(authsock);
578 }
579 }
580
581 /*
582 * Send/recv a request/reply sequence on the auth socket.
583 * Returns zero or an NT status.
584 *
585 * Errors here mean we can't communicate with the smbd_authsvc.
586 * With limited authsock instances, this should be rare.
587 */
588 static uint32_t
589 smb_authsock_sendrecv(smb_request_t *sr, smb_lsa_msg_hdr_t *hdr,
590 void *sndbuf, void **recvbuf)
591 {
592 smb_user_t *user = sr->uid_user;
593 ksocket_t so;
594 uint32_t status;
595 int rc;
596
597 /*
598 * Get a hold on the auth socket.
599 */
600 mutex_enter(&user->u_mutex);
601 so = user->u_authsock;
602 if (so == NULL) {
603 mutex_exit(&user->u_mutex);
604 return (NT_STATUS_INTERNAL_ERROR);
605 }
606 ksocket_hold(so);
607 mutex_exit(&user->u_mutex);
608
609 mutex_enter(&sr->sr_mutex);
610 if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
611 mutex_exit(&sr->sr_mutex);
612 status = NT_STATUS_CANCELLED;
613 goto out;
614 }
615 sr->sr_state = SMB_REQ_STATE_WAITING_AUTH;
616 sr->cancel_method = smb_authsock_cancel;
617 sr->cancel_arg2 = user;
618 mutex_exit(&sr->sr_mutex);
619
620 rc = smb_authsock_send(so, hdr, sizeof (*hdr));
621 if (rc == 0 && hdr->lmh_msglen != 0) {
622 rc = smb_authsock_send(so, sndbuf, hdr->lmh_msglen);
623 }
624 if (rc == 0)
625 rc = smb_authsock_recv(so, hdr, sizeof (*hdr));
626 if (rc == 0 && hdr->lmh_msglen != 0) {
627 *recvbuf = kmem_alloc(hdr->lmh_msglen, KM_SLEEP);
628 rc = smb_authsock_recv(so, *recvbuf, hdr->lmh_msglen);
629 }
630
631 switch (rc) {
632 case 0:
633 status = 0;
634 break;
635 case EIO:
636 status = RPC_NT_COMM_FAILURE;
637 break;
638 case ENOTCONN:
639 status = RPC_NT_PIPE_CLOSED;
640 break;
641 default:
642 status = RPC_NT_CALL_FAILED;
643 break;
644 }
645
646 mutex_enter(&sr->sr_mutex);
647 sr->cancel_method = NULL;
648 sr->cancel_arg2 = NULL;
649 switch (sr->sr_state) {
650 case SMB_REQ_STATE_WAITING_AUTH:
651 sr->sr_state = SMB_REQ_STATE_ACTIVE;
652 break;
653 case SMB_REQ_STATE_CANCEL_PENDING:
654 sr->sr_state = SMB_REQ_STATE_CANCELLED;
655 status = NT_STATUS_CANCELLED;
656 break;
657 default:
658 status = NT_STATUS_INTERNAL_ERROR;
659 break;
660 }
661 mutex_exit(&sr->sr_mutex);
662
663 out:
664 ksocket_rele(so);
665
666 if (status != 0 && *recvbuf != NULL) {
667 kmem_free(*recvbuf, hdr->lmh_msglen);
668 *recvbuf = NULL;
669 }
670 return (status);
671 }
672
673 /*
674 * Hope this is interpreted per-zone...
675 */
676 static struct sockaddr_un smbauth_sockname = {
677 AF_UNIX, SMB_AUTHSVC_SOCKNAME };
678
679 /*
680 * Limit how long smb_authsock_sendrecv() will wait for a
681 * response from the local authentication service.
682 */
683 struct timeval smb_auth_recv_tmo = { 45, 0 };
684
685 /*
686 * Also limit the time smb_authsock_sendrecv() will wait
687 * trying to send a request to the authentication service.
688 */
689 struct timeval smb_auth_send_tmo = { 15, 0 };
690
691 /*
692 * Maximum time a user object may stay in state LOGGING_ON
693 */
694 int smb_auth_total_tmo = 45; /* seconds */
695
696 static uint32_t
697 smb_authsock_open(smb_request_t *sr)
698 {
699 smb_user_t *user = sr->uid_user;
700 smb_server_t *sv = sr->sr_server;
701 ksocket_t so = NULL;
702 uint32_t status = 0;
703 int rc;
704
705 /*
706 * If the auth. service is busy, wait our turn. This threshold
707 * limits the number of auth sockets we might have trying to
708 * communicate with the auth. service up in smbd. Until we've
709 * set u_authsock, we need to "exit this threshold" in any
710 * error code paths after this "enter".
711 *
712 * Failure to "enter" may be frequent, so don't log.
713 */
714 if ((rc = smb_threshold_enter(&sv->sv_ssetup_ct)) != 0)
715 return (NT_STATUS_NO_LOGON_SERVERS);
716
717 rc = ksocket_socket(&so, AF_UNIX, SOCK_STREAM, 0,
718 KSOCKET_SLEEP, CRED());
719 if (rc != 0) {
720 cmn_err(CE_NOTE, "smb_authsock_open: socket, rc=%d", rc);
721 smb_threshold_exit(&sv->sv_ssetup_ct);
722 status = NT_STATUS_INSUFF_SERVER_RESOURCES;
723 goto errout;
724 }
725
726 /*
727 * This (new) user object now gets an authsocket.
728 * Note: u_authsock cleanup in smb_user_logoff.
729 * After we've set u_authsock, smb_threshold_exit
730 * is done in smb_authsock_close(). If we somehow
731 * already have an authsock, close the new one and
732 * error out.
733 */
734 mutex_enter(&user->u_mutex);
735 if (user->u_authsock != NULL) {
736 mutex_exit(&user->u_mutex);
737 smb_authsock_close(user, so);
738 status = NT_STATUS_INTERNAL_ERROR;
739 goto errout;
740 }
741 user->u_authsock = so;
742 if (smb_auth_total_tmo != 0) {
743 user->u_auth_tmo = timeout(smb_user_auth_tmo, user,
744 SEC_TO_TICK(smb_auth_total_tmo));
745 }
746 mutex_exit(&user->u_mutex);
747
748 /*
749 * Set the send/recv timeouts.
750 */
751 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_SNDTIMEO,
752 &smb_auth_send_tmo, sizeof (smb_auth_send_tmo), CRED());
753 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO,
754 &smb_auth_recv_tmo, sizeof (smb_auth_recv_tmo), CRED());
755
756 /*
757 * Connect to the smbd auth. service.
758 *
759 * Would like to set the connect timeout too, but there's
760 * apparently no easy way to do that for AF_UNIX.
761 */
762 mutex_enter(&sr->sr_mutex);
763 if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
764 mutex_exit(&sr->sr_mutex);
765 status = NT_STATUS_CANCELLED;
766 goto errout;
767 }
768 sr->sr_state = SMB_REQ_STATE_WAITING_AUTH;
769 sr->cancel_method = smb_authsock_cancel;
770 sr->cancel_arg2 = user;
771 mutex_exit(&sr->sr_mutex);
772
773 rc = ksocket_connect(so, (struct sockaddr *)&smbauth_sockname,
774 sizeof (smbauth_sockname), CRED());
775 if (rc != 0) {
776 DTRACE_PROBE1(error, int, rc);
777 status = NT_STATUS_NETLOGON_NOT_STARTED;
778 }
779
780 mutex_enter(&sr->sr_mutex);
781 sr->cancel_method = NULL;
782 sr->cancel_arg2 = NULL;
783 switch (sr->sr_state) {
784 case SMB_REQ_STATE_WAITING_AUTH:
785 sr->sr_state = SMB_REQ_STATE_ACTIVE;
786 break;
787 case SMB_REQ_STATE_CANCEL_PENDING:
788 sr->sr_state = SMB_REQ_STATE_CANCELLED;
789 status = NT_STATUS_CANCELLED;
790 break;
791 default:
792 status = NT_STATUS_INTERNAL_ERROR;
793 break;
794 }
795 mutex_exit(&sr->sr_mutex);
796
797 errout:
798 return (status);
799 }
800
801 static int
802 smb_authsock_send(ksocket_t so, void *buf, size_t len)
803 {
804 int rc;
805 size_t iocnt = 0;
806
807 rc = ksocket_send(so, buf, len, 0, &iocnt, CRED());
808 if (rc == 0 && iocnt != len) {
809 DTRACE_PROBE1(short, size_t, iocnt);
810 rc = EIO;
811 }
812 if (rc != 0) {
813 DTRACE_PROBE1(error, int, rc);
814 }
815
816 return (rc);
817 }
823 size_t iocnt = 0;
824
825 rc = ksocket_recv(so, buf, len, MSG_WAITALL, &iocnt, CRED());
826 if (rc == 0) {
827 if (iocnt == 0) {
828 DTRACE_PROBE1(discon, struct sonode *, so);
829 rc = ENOTCONN;
830 } else if (iocnt != len) {
831 /* Should not happen with MSG_WAITALL */
832 DTRACE_PROBE1(short, size_t, iocnt);
833 rc = EIO;
834 }
835 }
836 if (rc != 0) {
837 DTRACE_PROBE1(error, int, rc);
838 }
839
840 return (rc);
841 }
842
843 /*
844 * Caller has cleared user->u_authsock, passing the last ref
845 * as the 2nd arg here. This can block, so it's called
846 * after exiting u_mutex.
847 */
848 void
849 smb_authsock_close(smb_user_t *user, ksocket_t so)
850 {
851
852 (void) ksocket_shutdown(so, SHUT_RDWR, CRED());
853 (void) ksocket_close(so, CRED());
854 smb_threshold_exit(&user->u_server->sv_ssetup_ct);
855 }
|