1 /*
2 * CDDL HEADER START
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
smb_authenticate_old(smb_request_t * sr)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
smb_auth_do_oldreq(smb_request_t * sr)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;
177 }
178 /* FALLTHROUGH */
179
180 default: /* Bogus message type */
181 status = NT_STATUS_INTERNAL_ERROR;
182 break;
183 }
184
185 out:
186 if (rbuf != NULL)
187 kmem_free(rbuf, rlen);
188 if (sbuf != NULL)
189 kmem_free(sbuf, slen);
190
191 return (status);
192 }
193
194 /*
195 * Handle new-style (extended security) session setup.
196 * Returns zero: success, non-zero: error (value not used)
197 *
198 * Note that this style uses a sequence of session setup requests,
199 * where the first has SMB UID=0, and subsequent requests in the
200 * same authentication sequence have the SMB UID returned for that
201 * first request. We allocate a USER object when the first request
202 * in the sequence arrives (SMB_USER_STATE_LOGGING_ON) and use that
203 * to maintain state between requests in this sequence. The state
204 * for one sequence includes an AF_UNIX "authsock" connection to the
205 * user-space smbd. The neat part of this is: in smbd, the handler
206 * for the server-side of one authsock gets only request specific to
207 * one authentication sequence, simplifying it's work immensely.
208 * When the authentication sequence is finished, with either success
209 * or failure, the local side of the authsock is closed.
210 *
211 * As with the old-style authentication, if we succeed, then the
212 * last message from smbd will be an smb_token_t encoding the
213 * information about the new user.
214 *
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
smb_authenticate_ext(smb_request_t * sr)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;
304 break;
305
306 case LSA_MTYPE_ES_DONE:
307 sinfo->ssi_oseclen = (uint16_t)rlen;
308 sinfo->ssi_osecblob = smb_srm_alloc(sr, sinfo->ssi_oseclen);
309 bcopy(rbuf, sinfo->ssi_osecblob, sinfo->ssi_oseclen);
310 sinfo->ssi_ntpwlen = 0;
311 /*
312 * Get the final auth. token.
313 */
314 status = smb_auth_get_token(sr);
315 break;
316
317 case LSA_MTYPE_ERROR:
318 /*
319 * Authentication failed. Return the error
320 * provided in the reply message.
321 */
322 if (rlen == sizeof (smb_lsa_eresp_t)) {
323 smb_lsa_eresp_t *ler = rbuf;
324 status = ler->ler_ntstatus;
325 goto errout;
326 }
327 /* FALLTHROUGH */
328
329 default: /* Bogus message type */
330 status = NT_STATUS_INTERNAL_ERROR;
331 goto errout;
332 }
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
smb_auth_do_clinfo(smb_request_t * sr)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
smb_auth_get_token(smb_request_t * sr)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
smb_token_free(smb_token_t * token)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
smb_priv_xlate(smb_token_t * token)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
smb_authsock_sendrecv(smb_user_t * user,smb_lsa_msg_hdr_t * hdr,void * sndbuf,void ** recvbuf)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
smb_authsock_open(smb_user_t * user)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
smb_authsock_send(ksocket_t so,void * buf,size_t len)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 }
677
678 static int
smb_authsock_recv(ksocket_t so,void * buf,size_t len)679 smb_authsock_recv(ksocket_t so, void *buf, size_t len)
680 {
681 int rc;
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
smb_authsock_close(smb_user_t * user)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 }
713