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 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; 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 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 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 } 677 678 static int 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 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