1 /* 2 * Copyright (c) 2011 - 2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 /* 25 * Copyright 2018 Nexenta Systems, Inc. All rights reserved. 26 * Copyright 2024 RackTop Systems, Inc. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/kmem.h> 32 #include <sys/proc.h> 33 #include <sys/lock.h> 34 #include <sys/socket.h> 35 #include <sys/uio.h> 36 #include <sys/random.h> 37 #include <sys/note.h> 38 #include <sys/errno.h> 39 #include <sys/cmn_err.h> 40 41 #include <smb/ntaccess.h> 42 #include <smb/winioctl.h> 43 44 #include <netsmb/smb_osdep.h> 45 46 #include <netsmb/smb.h> 47 #include <netsmb/smb2.h> 48 #include <netsmb/smb_conn.h> 49 #include <netsmb/smb_subr.h> 50 #include <netsmb/smb_tran.h> 51 #include <netsmb/smb_rq.h> 52 #include <netsmb/smb2_rq.h> 53 54 /* 55 * Supported dialects. Keep sorted by number because of how the 56 * vc_maxver check below may truncate this list. 57 */ 58 #define NDIALECTS 3 59 static const uint16_t smb2_dialects[NDIALECTS] = { 60 SMB2_DIALECT_0210, 61 SMB2_DIALECT_0300, 62 SMB2_DIALECT_0302, 63 }; 64 65 /* Optional capabilities we advertise (none yet). */ 66 uint32_t smb2_clnt_caps = 67 SMB2_CAP_LARGE_MTU | 68 SMB2_CAP_ENCRYPTION; 69 70 /* How many credits to ask for during ssn. setup. */ 71 uint16_t smb2_ss_req_credits = 64; 72 73 /* 74 * Default timeout values, all in seconds. 75 * Make these tunable (only via mdb for now). 76 */ 77 int smb2_timo_notice = 15; 78 int smb2_timo_default = 30; 79 int smb2_timo_logon = 45; 80 int smb2_timo_open = 45; 81 int smb2_timo_read = 45; 82 int smb2_timo_write = 60; 83 int smb2_timo_append = 90; 84 85 /* 86 * This is a special handler for the odd SMB1-to-SMB2 negotiate 87 * response, where an SMB1 request gets an SMB2 response. 88 * 89 * Unlike most parse functions here, this needs to parse both 90 * the SMB2 header and the nego. response body. Note that 91 * the only "SMB2" dialect our SMB1 negotiate offered was 92 * { SMB_DIALECT_SMB2_FF, "SMB 2.???"} so the only valid 93 * SMB2 dialect we should get is: SMB2_DIALECT_02ff 94 */ 95 int 96 smb2_parse_smb1nego_resp(struct smb_rq *rqp) 97 { 98 struct smb_vc *vcp = rqp->sr_vc; 99 struct smb_sopt *sp = &vcp->vc_sopt; 100 struct mdchain *mdp; 101 uint16_t length = 0; 102 int error; 103 104 /* Get pointer to response data */ 105 smb_rq_getreply(rqp, &mdp); 106 107 error = smb2_rq_parsehdr(rqp); 108 if (error != 0) 109 return (error); 110 111 /* 112 * Parse SMB 2/3 Negotiate Response 113 * We are already pointing to begining of Response data 114 */ 115 116 /* Check structure size is 65 */ 117 md_get_uint16le(mdp, &length); 118 if (length != 65) 119 return (EBADRPC); 120 121 /* Get Security Mode */ 122 md_get_uint16le(mdp, &sp->sv2_security_mode); 123 124 /* Get Dialect. */ 125 error = md_get_uint16le(mdp, &sp->sv_proto); 126 if (error != 0) 127 return (error); 128 129 /* What dialect did we get? */ 130 if (sp->sv_proto != SMB2_DIALECT_02ff) { 131 SMBERROR("Unknown dialect 0x%x\n", sp->sv_proto); 132 return (EINVAL); 133 } 134 /* Set our (internal) SMB1 dialect also. */ 135 sp->sv_proto = SMB_DIALECT_SMB2_FF; 136 137 /* 138 * This request did not go through smb2_iod_addrq and 139 * smb2_iod_process() so the SMB2 message ID state is 140 * behind what we need it to be. Fix that. 141 */ 142 vcp->vc2_next_message_id = 1; 143 vcp->vc2_limit_message_id = 2; 144 145 /* 146 * Skip parsing the rest. We'll get a normal 147 * SMB2 negotiate next and do negotiate then. 148 */ 149 return (0); 150 } 151 152 int 153 smb2_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred) 154 { 155 smb_sopt_t *sp = &vcp->vc_sopt; 156 smbioc_ssn_work_t *wk = &vcp->vc_work; 157 struct smb_rq *rqp = NULL; 158 struct mbchain *mbp = NULL; 159 struct mdchain *mdp = NULL; 160 uint16_t *ndialects_p; 161 uint16_t ndialects = NDIALECTS; 162 boolean_t will_sign = B_FALSE; 163 uint16_t length = 0; 164 uint16_t security_mode; 165 uint16_t sec_buf_off; 166 uint16_t sec_buf_len; 167 int err, i; 168 169 /* 170 * Compute security mode 171 */ 172 if (vcp->vc_vopt & SMBVOPT_SIGNING_REQUIRED) { 173 security_mode = SMB2_NEGOTIATE_SIGNING_REQUIRED; 174 } else { 175 security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED; 176 } 177 178 err = smb_rq_alloc(VCTOCP(vcp), SMB2_NEGOTIATE, scred, &rqp); 179 if (err) 180 return (err); 181 182 /* 183 * Build the SMB2 negotiate request. 184 */ 185 smb_rq_getrequest(rqp, &mbp); 186 mb_put_uint16le(mbp, 36); /* Struct Size */ 187 ndialects_p = mb_reserve(mbp, 2); /* Dialect Count */ 188 mb_put_uint16le(mbp, security_mode); 189 mb_put_uint16le(mbp, 0); /* Reserved */ 190 mb_put_uint32le(mbp, smb2_clnt_caps); 191 mb_put_mem(mbp, vcp->vc_cl_guid, 16, MB_MSYSTEM); 192 mb_put_uint64le(mbp, 0); /* Start Time */ 193 for (i = 0; i < ndialects; i++) { /* Dialects */ 194 if (smb2_dialects[i] > vcp->vc_maxver) 195 break; 196 mb_put_uint16le(mbp, smb2_dialects[i]); 197 } 198 *ndialects_p = htoles(i); 199 200 /* 201 * Do the OTW call. 202 */ 203 err = smb2_rq_internal(rqp, smb2_timo_default); 204 if (err) { 205 goto errout; 206 } 207 /* Should only get status success. */ 208 if (rqp->sr_error != NT_STATUS_SUCCESS) { 209 err = ENOTSUP; 210 goto errout; 211 } 212 213 /* 214 * Decode the negotiate response 215 */ 216 smb_rq_getreply(rqp, &mdp); 217 218 md_get_uint16le(mdp, &length); /* Struct size */ 219 if (length != 65) { 220 err = EBADRPC; 221 goto errout; 222 } 223 224 md_get_uint16le(mdp, &sp->sv2_security_mode); 225 md_get_uint16le(mdp, &sp->sv_proto); /* dialect */ 226 md_get_uint16le(mdp, NULL); /* reserved */ 227 md_get_mem(mdp, sp->sv2_guid, 16, MB_MSYSTEM); 228 md_get_uint32le(mdp, &sp->sv2_capabilities); 229 md_get_uint32le(mdp, &sp->sv2_maxtransact); 230 md_get_uint32le(mdp, &sp->sv2_maxread); 231 md_get_uint32le(mdp, &sp->sv2_maxwrite); 232 md_get_uint64le(mdp, NULL); /* curr_time */ 233 md_get_uint64le(mdp, NULL); /* boot_time */ 234 235 /* Get Security Blob offset and length */ 236 md_get_uint16le(mdp, &sec_buf_off); 237 err = md_get_uint16le(mdp, &sec_buf_len); 238 if (err != 0) 239 goto errout; 240 md_get_uint32le(mdp, NULL); /* reserved */ 241 242 /* 243 * Security buffer offset is from the beginning of SMB 2 Header 244 * Calculate how much further we have to go to get to it. 245 * Current offset is: SMB2_HDRLEN + 64 246 */ 247 if (sec_buf_len != 0) { 248 int skip = (int)sec_buf_off - (SMB2_HDRLEN + 64); 249 if (skip < 0) { 250 err = EBADRPC; 251 goto errout; 252 } 253 if (skip > 0) { 254 md_get_mem(mdp, NULL, skip, MB_MSYSTEM); 255 } 256 257 /* 258 * Copy the security blob out to user space. 259 * Buffer addr,size in vc_auth_rbuf,rlen 260 */ 261 if (wk->wk_u_auth_rlen < sec_buf_len) { 262 SMBSDEBUG("vc_auth_rbuf too small"); 263 /* Give caller required size. */ 264 wk->wk_u_auth_rlen = sec_buf_len; 265 err = EMSGSIZE; 266 goto errout; 267 } 268 wk->wk_u_auth_rlen = sec_buf_len; 269 err = md_get_mem(mdp, wk->wk_u_auth_rbuf.lp_ptr, 270 sec_buf_len, MB_MUSER); 271 if (err) { 272 goto errout; 273 } 274 } 275 276 /* 277 * Decoded everything. Now decisions. 278 */ 279 280 /* 281 * Turn on signing if either Server or client requires it, 282 * except: anonymous sessions can't sign. 283 */ 284 if ((sp->sv2_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) || 285 (vcp->vc_vopt & SMBVOPT_SIGNING_REQUIRED)) 286 will_sign = B_TRUE; 287 if (vcp->vc_vopt & SMBVOPT_ANONYMOUS) 288 will_sign = B_FALSE; 289 SMBSDEBUG("Security signatures: %d", (int)will_sign); 290 if (will_sign) 291 vcp->vc_flags |= SMBV_SIGNING; 292 293 /* 294 * ToDo - too many places are looking at sv_caps, so for now 295 * set the SMB1 capabilities too. Later we should use the 296 * sv2_capabilities for SMB 2+. 297 */ 298 sp->sv_caps = (SMB_CAP_UNICODE | 299 SMB_CAP_LARGE_FILES | 300 SMB_CAP_STATUS32 | 301 SMB_CAP_LARGE_READX | 302 SMB_CAP_LARGE_WRITEX | 303 SMB_CAP_EXT_SECURITY); 304 if (sp->sv2_capabilities & SMB2_CAP_DFS) 305 sp->sv_caps |= SMB_CAP_DFS; 306 307 if (sp->sv_proto >= SMB2_DIALECT_0300 && 308 (sp->sv2_capabilities & SMB2_CAP_ENCRYPTION) != 0) { 309 nsmb_crypt_init_mech(vcp); 310 } 311 312 /* 313 * A few sanity checks on what we received, 314 * becuse we will send these in ssnsetup. 315 * 316 * Maximum outstanding requests (we care), 317 * and Max. VCs (we only use one). Also, 318 * MaxBufferSize lower limit per spec. 319 */ 320 if (sp->sv2_maxread < 0x8000) { 321 SMBSDEBUG("maxread too small\n"); 322 err = ENOTSUP; 323 goto errout; 324 } 325 if (sp->sv2_maxwrite < 0x8000) { 326 SMBSDEBUG("maxwrite too small\n"); 327 err = ENOTSUP; 328 goto errout; 329 } 330 if (sp->sv2_maxtransact < 0x4000) { 331 SMBSDEBUG("maxtransact too small\n"); 332 err = ENOTSUP; 333 goto errout; 334 } 335 336 /* Here too, fill SMB1 fields */ 337 vcp->vc_rxmax = sp->sv2_maxread; 338 vcp->vc_wxmax = sp->sv2_maxwrite; 339 vcp->vc_txmax = sp->sv2_maxtransact; 340 341 smb_rq_done(rqp); 342 return (0); 343 344 errout: 345 smb_rq_done(rqp); 346 if (err == 0) 347 err = EBADRPC; 348 return (err); 349 } 350 351 int 352 smb2_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred) 353 { 354 smbioc_ssn_work_t *wk = &vcp->vc_work; 355 struct smb_rq *rqp = NULL; 356 struct mbchain *mbp = NULL; 357 struct mdchain *mdp = NULL; 358 char *sb; 359 int err, ret; 360 uint16_t sblen; 361 uint16_t length = 0; 362 uint16_t session_flags; 363 uint16_t sec_buf_off; 364 uint16_t sec_buf_len; 365 uint8_t security_mode; 366 367 /* 368 * Compute security mode 369 */ 370 if (vcp->vc_vopt & SMBVOPT_SIGNING_REQUIRED) { 371 security_mode = SMB2_NEGOTIATE_SIGNING_REQUIRED; 372 } else { 373 security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED; 374 } 375 376 sb = wk->wk_u_auth_wbuf.lp_ptr; 377 sblen = (uint16_t)wk->wk_u_auth_wlen; 378 379 err = smb_rq_alloc(VCTOCP(vcp), SMB2_SESSION_SETUP, scred, &rqp); 380 if (err != 0) { 381 ret = err; 382 goto out; 383 } 384 385 /* 386 * Always ask for some credits. The server usually will 387 * only grant these credits once we've authenticated. 388 */ 389 rqp->sr2_creditsrequested = smb2_ss_req_credits; 390 391 /* 392 * Build the SMB Session Setup request. 393 */ 394 smb_rq_getrequest(rqp, &mbp); 395 396 mb_put_uint16le(mbp, 25); /* Struct size */ 397 mb_put_uint8(mbp, 0); /* VcNumber */ 398 mb_put_uint8(mbp, security_mode); 399 mb_put_uint32le(mbp, smb2_clnt_caps); /* Capabilities */ 400 mb_put_uint32le(mbp, 0); /* Channel - always 0 */ 401 402 /* 403 * Security buffer offset and length. Normally would use 404 * ptr = mb_reserve() and fill in later, but since only a 405 * small amount of fixed-size stuff follows (12 bytes) 406 * we can just compute the offset now. 407 */ 408 mb_put_uint16le(mbp, mbp->mb_count + 12); 409 mb_put_uint16le(mbp, sblen); 410 mb_put_uint64le(mbp, vcp->vc2_prev_session_id); 411 err = mb_put_mem(mbp, sb, sblen, MB_MUSER); 412 if (err != 0) { 413 ret = err; 414 goto out; 415 } 416 417 /* 418 * Run the request. The return value here should be the 419 * return from this function, unless we fail decoding. 420 * Note: NT_STATUS_MORE_PROCESSING_REQUIRED is OK, and 421 * the caller expects EINPROGRESS for that case. 422 */ 423 ret = smb2_rq_internal(rqp, smb2_timo_logon); 424 if (ret != 0) 425 goto out; 426 switch (rqp->sr_error) { 427 case NT_STATUS_SUCCESS: 428 break; 429 case NT_STATUS_MORE_PROCESSING_REQUIRED: 430 /* Keep going, but return... */ 431 ret = EINPROGRESS; 432 break; 433 default: 434 ret = EAUTH; 435 goto out; 436 } 437 438 /* 439 * After the first Session Setup Response, 440 * save the session ID. 441 */ 442 if (vcp->vc2_session_id == 0) 443 vcp->vc2_session_id = rqp->sr2_rspsessionid; 444 445 /* 446 * Decode the session setup response 447 */ 448 smb_rq_getreply(rqp, &mdp); 449 450 md_get_uint16le(mdp, &length); /* Struct size */ 451 if (length != 9) { 452 ret = EBADRPC; 453 goto out; 454 } 455 456 md_get_uint16le(mdp, &session_flags); 457 md_get_uint16le(mdp, &sec_buf_off); 458 err = md_get_uint16le(mdp, &sec_buf_len); 459 if (err != 0) { 460 ret = err; 461 goto out; 462 } 463 464 /* 465 * Security buffer offset is from the beginning of SMB 2 Header 466 * Calculate how much further we have to go to get to it. 467 * Current offset is: SMB2_HDRLEN + 8 468 */ 469 if (sec_buf_len != 0) { 470 int skip = (int)sec_buf_off - (SMB2_HDRLEN + 8); 471 if (skip < 0) { 472 ret = EBADRPC; 473 goto out; 474 } 475 if (skip > 0) { 476 md_get_mem(mdp, NULL, skip, MB_MSYSTEM); 477 } 478 479 /* 480 * Copy the security blob out to user space. 481 * Buffer addr,size in vc_auth_rbuf,rlen 482 */ 483 if (wk->wk_u_auth_rlen < sec_buf_len) { 484 SMBSDEBUG("vc_auth_rbuf too small"); 485 /* Give caller required size. */ 486 wk->wk_u_auth_rlen = sec_buf_len; 487 ret = EMSGSIZE; 488 goto out; 489 } 490 wk->wk_u_auth_rlen = sec_buf_len; 491 err = md_get_mem(mdp, wk->wk_u_auth_rbuf.lp_ptr, 492 sec_buf_len, MB_MUSER); 493 if (err != 0) { 494 ret = err; 495 goto out; 496 } 497 } 498 499 if (ret == 0) { 500 /* 501 * Final session setup response 502 */ 503 vcp->vc_sopt.sv2_sessflags = session_flags; 504 if ((vcp->vc_sopt.sv2_sessflags & 505 SMB2_SESSION_FLAG_ENCRYPT_DATA) != 0 && 506 vcp->vc3_crypt_mech == NULL) { 507 cmn_err(CE_NOTE, "SMB server requires encryption" 508 " but no crypto mechanism found"); 509 ret = ENOTSUP; 510 goto out; 511 } 512 } 513 514 out: 515 if (err != 0 && err != EINPROGRESS) { 516 /* Session ID no longer valid. */ 517 vcp->vc2_session_id = 0; 518 } 519 if (rqp) 520 smb_rq_done(rqp); 521 522 return (ret); 523 } 524 525 int 526 smb2_smb_logoff(struct smb_vc *vcp, struct smb_cred *scred) 527 { 528 struct smb_rq *rqp; 529 struct mbchain *mbp; 530 int error; 531 532 if (vcp->vc2_session_id == 0) 533 return (0); 534 535 error = smb_rq_alloc(VCTOCP(vcp), SMB2_LOGOFF, scred, &rqp); 536 if (error) 537 return (error); 538 539 /* 540 * Fill in Logoff part 541 */ 542 smb_rq_getrequest(rqp, &mbp); 543 mb_put_uint16le(mbp, 4); /* Struct size */ 544 mb_put_uint16le(mbp, 0); /* Reserved */ 545 546 /* 547 * Run this with a relatively short timeout. (5 sec.) 548 * We don't really care about the result here. 549 * Also, don't reconnect for this, of course! 550 */ 551 rqp->sr_flags |= SMBR_NORECONNECT; 552 error = smb2_rq_internal(rqp, 5); 553 smb_rq_done(rqp); 554 return (error); 555 } 556 557 int 558 smb2_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred) 559 { 560 struct smb_vc *vcp; 561 struct smb_rq *rqp = NULL; 562 struct mbchain *mbp; 563 struct mdchain *mdp; 564 char *unc_name = NULL; 565 int error, unc_len; 566 uint16_t plen, *plenp; 567 uint16_t options = 0; 568 uint_t cnt0; 569 uint32_t net_stype; 570 uint16_t structure_size = 0; 571 uint8_t smb2stype; 572 573 vcp = SSTOVC(ssp); 574 575 /* 576 * Make this a "VC-level" request, so it will have 577 * rqp->sr_share == NULL, and smb_iod_sendrq() 578 * will send it with TID = SMB_TID_UNKNOWN 579 * 580 * This also serves to bypass the wait for 581 * share state changes, which this call is 582 * trying to carry out. 583 */ 584 error = smb_rq_alloc(VCTOCP(vcp), SMB2_TREE_CONNECT, scred, &rqp); 585 if (error) 586 return (error); 587 588 /* 589 * Build the UNC name, i.e. "//server/share" 590 * but with backslashes of course. 591 * size math: three slashes, one null. 592 */ 593 unc_len = 4 + strlen(vcp->vc_srvname) + strlen(ssp->ss_name); 594 unc_name = kmem_alloc(unc_len, KM_SLEEP); 595 (void) snprintf(unc_name, unc_len, "\\\\%s\\%s", 596 vcp->vc_srvname, ssp->ss_name); 597 SMBSDEBUG("unc_name: \"%s\"", unc_name); 598 599 /* 600 * Build the request. 601 */ 602 mbp = &rqp->sr_rq; 603 604 mb_put_uint16le(mbp, 9); /* Struct size */ 605 mb_put_uint16le(mbp, 0); /* Reserved */ 606 mb_put_uint16le(mbp, 72); /* Path Offset */ 607 608 /* 609 * Fill in path length after we put the string, so we know 610 * the length after conversion from UTF-8 to UCS-2. 611 */ 612 plenp = mb_reserve(mbp, 2); 613 cnt0 = mbp->mb_count; 614 615 /* UNC resource name (without the null) */ 616 error = smb_put_dmem(mbp, vcp, unc_name, unc_len - 1, 617 SMB_CS_NONE, NULL); 618 if (error) 619 goto out; 620 621 /* Now go back and fill in the path length. */ 622 plen = (uint16_t)(mbp->mb_count - cnt0); 623 *plenp = htoles(plen); 624 625 /* 626 * Run the request. 627 * 628 * Using NOINTR_RECV because we don't want to risk 629 * missing a successful tree connect response, 630 * which would "leak" Tree IDs. 631 */ 632 rqp->sr_flags |= SMBR_NOINTR_RECV; 633 error = smb2_rq_simple(rqp); 634 SMBSDEBUG("%d\n", error); 635 if (error) { 636 /* 637 * If we get the server name wrong, i.e. due to 638 * mis-configured name services, this will be 639 * NT_STATUS_DUPLICATE_NAME. Log this error. 640 */ 641 SMBERROR("(%s) failed, status=0x%x", 642 unc_name, rqp->sr_error); 643 goto out; 644 } 645 646 /* 647 * Parse the tree connect response 648 */ 649 smb_rq_getreply(rqp, &mdp); 650 651 /* Check structure size is 16 */ 652 md_get_uint16le(mdp, &structure_size); 653 if (structure_size != 16) { 654 error = EBADRPC; 655 goto out; 656 } 657 658 md_get_uint8(mdp, &smb2stype); 659 md_get_uint8(mdp, NULL); /* reserved */ 660 md_get_uint32le(mdp, &ssp->ss2_share_flags); 661 md_get_uint32le(mdp, &ssp->ss2_share_caps); 662 error = md_get_uint32le(mdp, NULL); /* maxAccessRights */ 663 if (error) 664 goto out; 665 666 /* 667 * If the share requires encryption, make sure we can. 668 */ 669 if ((ssp->ss2_share_flags & SMB2_SHAREFLAG_ENCRYPT_DATA) != 0 && 670 vcp->vc3_crypt_mech == NULL) { 671 cmn_err(CE_NOTE, "SMB share requires encryption" 672 " but no crypto mechanism found"); 673 error = ENOTSUP; 674 goto out; 675 } 676 677 /* 678 * Convert SMB2 share type to NetShareEnum share type 679 */ 680 switch (smb2stype) { 681 case SMB2_SHARE_TYPE_DISK: 682 net_stype = STYPE_DISKTREE; 683 break; 684 case SMB2_SHARE_TYPE_PIPE: 685 net_stype = STYPE_IPC; 686 break; 687 case SMB2_SHARE_TYPE_PRINT: 688 net_stype = STYPE_PRINTQ; 689 break; 690 default: 691 net_stype = STYPE_UNKNOWN; 692 break; 693 } 694 ssp->ss_type = net_stype; 695 696 /* 697 * Map SMB 2/3 capabilities to SMB 1 options, 698 * for common code that looks there. 699 */ 700 if (ssp->ss2_share_caps & SMB2_SHARE_CAP_DFS) 701 options |= SMB_SHARE_IS_IN_DFS; 702 703 /* Update share state */ 704 SMB_SS_LOCK(ssp); 705 ssp->ss2_tree_id = rqp->sr2_rsptreeid; 706 ssp->ss_vcgenid = vcp->vc_genid; 707 ssp->ss_options = options; 708 ssp->ss_flags |= SMBS_CONNECTED; 709 SMB_SS_UNLOCK(ssp); 710 711 out: 712 if (unc_name) 713 kmem_free(unc_name, unc_len); 714 smb_rq_done(rqp); 715 return (error); 716 } 717 718 int 719 smb2_smb_treedisconnect(struct smb_share *ssp, struct smb_cred *scred) 720 { 721 struct smb_vc *vcp; 722 struct smb_rq *rqp; 723 struct mbchain *mbp; 724 int error; 725 726 if (ssp->ss2_tree_id == SMB2_TID_UNKNOWN) 727 return (0); 728 729 /* 730 * Build this as a "VC-level" request, so it will 731 * avoid testing the _GONE flag on the share, 732 * which has already been set at this point. 733 * Add the share pointer "by hand" below, so 734 * smb_iod_sendrq will plug in the TID. 735 */ 736 vcp = SSTOVC(ssp); 737 error = smb_rq_alloc(VCTOCP(vcp), SMB2_TREE_DISCONNECT, scred, &rqp); 738 if (error) 739 return (error); 740 rqp->sr_share = ssp; /* See "by hand" above. */ 741 742 /* 743 * Fill in SMB2 Tree Disconnect part 744 */ 745 smb_rq_getrequest(rqp, &mbp); 746 mb_put_uint16le(mbp, 4); /* Struct size */ 747 mb_put_uint16le(mbp, 0); /* Reserved */ 748 749 /* 750 * Run this with a relatively short timeout. (5 sec.) 751 * We don't really care about the result here, but we 752 * do need to make sure we send this out, or we could 753 * "leak" active tree IDs on interrupt or timeout. 754 * The NOINTR_SEND flag makes this request immune to 755 * interrupt or timeout until the send is done. 756 * Also, don't reconnect for this, of course! 757 */ 758 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT); 759 error = smb2_rq_simple_timed(rqp, 5); 760 761 smb_rq_done(rqp); 762 763 /* Whether we get an error or not... */ 764 ssp->ss2_tree_id = SMB2_TID_UNKNOWN; 765 766 return (error); 767 } 768 769 /* 770 * Put the name, first skipping a leading slash. 771 */ 772 static int 773 put_name_skip_slash(struct mbchain *mbp, struct mbchain *name_mbp) 774 { 775 mblk_t *m; 776 777 if (name_mbp == NULL) 778 return (0); 779 m = name_mbp->mb_top; 780 if (m == NULL) 781 return (0); 782 783 /* Use a dup of the message to leave the passed one untouched. */ 784 m = dupmsg(m); 785 if (m == NULL) 786 return (ENOSR); 787 788 if (MBLKL(m) >= 2 && 789 m->b_rptr[0] == '\\' && 790 m->b_rptr[1] == '\0') 791 m->b_rptr += 2; 792 793 return (mb_put_mbuf(mbp, m)); 794 } 795 796 /* 797 * Modern create/open of file or directory. 798 * 799 * The passed name is a full path relative to the share root. 800 * Callers prepare paths with a leading slash (backslash) 801 * because that's what SMB1 expected. SMB2 does not allow the 802 * leading slash here. To make life simpler for callers skip a 803 * leading slash here. That allows callers use use common logic 804 * for building paths without needing to know if the connection 805 * is using SMB1 or SMB2 (just build paths with a leading slash). 806 */ 807 int 808 smb2_smb_ntcreate( 809 struct smb_share *ssp, 810 struct mbchain *name_mb, 811 struct mbchain *cctx_in, 812 struct mdchain *cctx_out, 813 uint32_t cr_flags, /* create flags */ 814 uint32_t req_acc, /* requested access */ 815 uint32_t efa, /* ext. file attrs (DOS attr +) */ 816 uint32_t share_acc, 817 uint32_t open_disp, /* open disposition */ 818 uint32_t createopt, /* NTCREATEX_OPTIONS_ */ 819 uint32_t impersonate, /* NTCREATEX_IMPERSONATION_... */ 820 struct smb_cred *scrp, 821 smb2fid_t *fidp, /* returned FID */ 822 uint32_t *cr_act_p, /* optional create action */ 823 struct smbfattr *fap) /* optional attributes */ 824 { 825 struct smbfattr fa; 826 struct smb_rq *rqp; 827 struct mbchain *mbp; 828 struct mdchain *mdp; 829 uint16_t *name_offp; 830 uint16_t *name_lenp; 831 uint32_t *cctx_offp; 832 uint32_t *cctx_lenp; 833 uint32_t rcc_off, rcc_len; 834 smb2fid_t smb2_fid; 835 uint64_t llongint; 836 uint32_t longint, createact; 837 uint_t off, len; 838 int error; 839 uint16_t StructSize = 57; // [MS-SMB2] 840 841 bzero(&fa, sizeof (fa)); 842 843 error = smb_rq_alloc(SSTOCP(ssp), SMB2_CREATE, scrp, &rqp); 844 if (error) 845 return (error); 846 847 /* 848 * Todo: Assemble creat contexts (if needed) 849 * into an mbchain. 850 */ 851 852 /* 853 * Build the SMB 2/3 Create Request 854 */ 855 smb_rq_getrequest(rqp, &mbp); 856 mb_put_uint16le(mbp, StructSize); 857 mb_put_uint8(mbp, 0); /* Security flags */ 858 mb_put_uint8(mbp, SMB2_OPLOCK_LEVEL_NONE); /* Oplock level */ 859 mb_put_uint32le(mbp, impersonate); /* Impersonation Level */ 860 mb_put_uint64le(mbp, cr_flags); 861 mb_put_uint64le(mbp, 0); /* Reserved */ 862 mb_put_uint32le(mbp, req_acc); 863 mb_put_uint32le(mbp, efa); /* File attributes */ 864 mb_put_uint32le(mbp, share_acc); /* Share access */ 865 mb_put_uint32le(mbp, open_disp); /* Create disposition */ 866 mb_put_uint32le(mbp, createopt); /* Create options */ 867 868 name_offp = mb_reserve(mbp, 2); /* Name offset */ 869 name_lenp = mb_reserve(mbp, 2); /* Name len */ 870 871 cctx_offp = mb_reserve(mbp, 4); /* Context offset */ 872 cctx_lenp = mb_reserve(mbp, 4); /* Context len */ 873 874 /* 875 * Put the file name, which is provided in an mbchain. 876 * If there's a leading slash, skip it (see above). 877 */ 878 off = mbp->mb_count; 879 *name_offp = htoles((uint16_t)off); 880 error = put_name_skip_slash(mbp, name_mb); 881 if (error) 882 goto out; 883 len = mbp->mb_count - off; 884 *name_lenp = htoles((uint16_t)len); 885 886 /* 887 * Now the create contexts (if provided) 888 */ 889 if (cctx_in != NULL) { 890 off = mbp->mb_count; 891 *cctx_offp = htolel((uint32_t)off); 892 mb_put_mbchain(mbp, cctx_in); 893 len = mbp->mb_count - off; 894 *cctx_lenp = htolel((uint32_t)len); 895 } else { 896 *cctx_offp = 0; 897 *cctx_lenp = 0; 898 } 899 900 /* 901 * If we didn't put any variable-sized data, we'll have 902 * put exactly 56 bytes of data, and we need to pad out 903 * this request to the 57 bytes StructSize indicated. 904 */ 905 if (mbp->mb_count < (StructSize + SMB2_HDRLEN)) 906 mb_put_uint8(mbp, 0); 907 908 /* 909 * Don't want to risk missing a successful 910 * open response, or we could "leak" FIDs. 911 */ 912 rqp->sr_flags |= SMBR_NOINTR_RECV; 913 error = smb2_rq_simple_timed(rqp, smb2_timo_open); 914 if (error) 915 goto out; 916 917 /* 918 * Parse SMB 2/3 Create Response 919 */ 920 smb_rq_getreply(rqp, &mdp); 921 922 /* Check structure size is 89 */ 923 error = md_get_uint16le(mdp, &StructSize); 924 if (StructSize != 89) { 925 error = EBADRPC; 926 goto out; 927 } 928 929 md_get_uint8(mdp, NULL); /* oplock lvl granted */ 930 md_get_uint8(mdp, NULL); /* mbz */ 931 md_get_uint32le(mdp, &createact); /* create_action */ 932 md_get_uint64le(mdp, &llongint); /* creation time */ 933 smb_time_NT2local(llongint, &fa.fa_createtime); 934 md_get_uint64le(mdp, &llongint); /* access time */ 935 smb_time_NT2local(llongint, &fa.fa_atime); 936 md_get_uint64le(mdp, &llongint); /* write time */ 937 smb_time_NT2local(llongint, &fa.fa_mtime); 938 md_get_uint64le(mdp, &llongint); /* change time */ 939 smb_time_NT2local(llongint, &fa.fa_ctime); 940 md_get_uint64le(mdp, &llongint); /* allocation size */ 941 fa.fa_allocsz = llongint; 942 md_get_uint64le(mdp, &llongint); /* EOF position */ 943 fa.fa_size = llongint; 944 md_get_uint32le(mdp, &longint); /* attributes */ 945 fa.fa_attr = longint; 946 md_get_uint32le(mdp, NULL); /* reserved */ 947 948 /* Get SMB 2/3 File ID and create user fid to return */ 949 md_get_uint64le(mdp, &smb2_fid.fid_persistent); 950 error = md_get_uint64le(mdp, &smb2_fid.fid_volatile); 951 if (error) 952 goto out; 953 954 /* Get Context Offset */ 955 error = md_get_uint32le(mdp, &rcc_off); 956 if (error) 957 goto out; 958 /* Get Context Length */ 959 error = md_get_uint32le(mdp, &rcc_len); 960 if (error) 961 goto out; 962 963 /* 964 * If the caller wants the returned create contexts, parse. 965 * Context offset is from the beginning of SMB 2/3 Header 966 * Calculate how much further we have to go to get to it. 967 * Current offset is: SMB2_HDRLEN + 88 968 */ 969 if (rcc_len != 0) { 970 int skip = (int)rcc_off - (SMB2_HDRLEN + 88); 971 if (skip < 0) { 972 error = EBADRPC; 973 goto out; 974 } 975 if (skip > 0) { 976 md_get_mem(mdp, NULL, skip, MB_MSYSTEM); 977 } 978 if (cctx_out != NULL) { 979 mblk_t *m = NULL; 980 error = md_get_mbuf(mdp, rcc_len, &m); 981 if (error) 982 goto out; 983 md_initm(cctx_out, m); 984 } 985 } 986 987 out: 988 smb_rq_done(rqp); 989 if (error) 990 return (error); 991 992 *fidp = smb2_fid; 993 if (cr_act_p) 994 *cr_act_p = createact; 995 if (fap) 996 *fap = fa; /* struct copy */ 997 998 return (0); 999 } 1000 1001 int 1002 smb2_smb_close(struct smb_share *ssp, smb2fid_t *fid, struct smb_cred *scrp) 1003 { 1004 struct smb_rq *rqp; 1005 struct mbchain *mbp; 1006 int error; 1007 1008 error = smb_rq_alloc(SSTOCP(ssp), SMB2_CLOSE, scrp, &rqp); 1009 if (error) 1010 return (error); 1011 1012 /* 1013 * Build the SMB 2/3 Close Request 1014 */ 1015 smb_rq_getrequest(rqp, &mbp); 1016 mb_put_uint16le(mbp, 24); /* Struct size */ 1017 mb_put_uint16le(mbp, 0); /* Flags */ 1018 mb_put_uint32le(mbp, 0); /* Reserved */ 1019 1020 mb_put_uint64le(mbp, fid->fid_persistent); 1021 mb_put_uint64le(mbp, fid->fid_volatile); 1022 1023 /* Make sure we send, but only if already connected */ 1024 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT); 1025 error = smb2_rq_simple(rqp); 1026 smb_rq_done(rqp); 1027 return (error); 1028 } 1029 1030 int 1031 smb2_smb_ioctl( 1032 struct smb_share *ssp, 1033 smb2fid_t *fid, 1034 struct mbchain *data_in, 1035 struct mdchain *data_out, 1036 uint32_t *data_out_sz, /* max / returned */ 1037 uint32_t ctl_code, 1038 struct smb_cred *scrp) 1039 { 1040 struct smb_rq *rqp; 1041 struct mbchain *mbp; 1042 struct mdchain *mdp; 1043 uint32_t *data_in_offp; 1044 uint32_t *data_in_lenp; 1045 uint32_t data_out_off; 1046 uint32_t data_out_len; 1047 uint16_t length = 0; 1048 uint_t off, len; 1049 int error; 1050 1051 error = smb_rq_alloc(SSTOCP(ssp), SMB2_IOCTL, scrp, &rqp); 1052 if (error) 1053 return (error); 1054 1055 /* 1056 * Build the SMB 2 IOCTL Request 1057 */ 1058 smb_rq_getrequest(rqp, &mbp); 1059 mb_put_uint16le(mbp, 57); /* Struct size */ 1060 mb_put_uint16le(mbp, 0); /* Reserved */ 1061 mb_put_uint32le(mbp, ctl_code); 1062 1063 mb_put_uint64le(mbp, fid->fid_persistent); 1064 mb_put_uint64le(mbp, fid->fid_volatile); 1065 1066 data_in_offp = mb_reserve(mbp, 4); 1067 data_in_lenp = mb_reserve(mbp, 4); 1068 mb_put_uint32le(mbp, 0); /* Max input resp */ 1069 1070 mb_put_uint32le(mbp, 0); /* Output offset */ 1071 mb_put_uint32le(mbp, 0); /* Output count */ 1072 mb_put_uint32le(mbp, *data_out_sz); 1073 1074 mb_put_uint32le(mbp, SMB2_IOCTL_IS_FSCTL); /* Flags */ 1075 mb_put_uint32le(mbp, 0); /* Reserved2 */ 1076 1077 /* 1078 * Now data_in (if provided) 1079 */ 1080 if (data_in != NULL) { 1081 off = mbp->mb_count; 1082 *data_in_offp = htolel((uint32_t)off); 1083 mb_put_mbchain(mbp, data_in); 1084 len = mbp->mb_count - off; 1085 *data_in_lenp = htolel((uint32_t)len); 1086 } else { 1087 *data_in_offp = 0; 1088 *data_in_lenp = 0; 1089 } 1090 1091 /* 1092 * Run the request 1093 */ 1094 error = smb2_rq_simple_timed(rqp, smb2_timo_default); 1095 if (error) 1096 goto out; 1097 1098 /* 1099 * Parse SMB 2 Ioctl Response 1100 */ 1101 smb_rq_getreply(rqp, &mdp); 1102 1103 /* Check structure size is 49 */ 1104 md_get_uint16le(mdp, &length); 1105 if (length != 49) { 1106 error = EBADRPC; 1107 goto out; 1108 } 1109 md_get_uint16le(mdp, NULL); /* reserved */ 1110 md_get_uint32le(mdp, NULL); /* Get CtlCode */ 1111 md_get_uint64le(mdp, NULL); /* fid_persistent */ 1112 md_get_uint64le(mdp, NULL); /* fid_volatile */ 1113 md_get_uint32le(mdp, NULL); /* Get Input offset */ 1114 md_get_uint32le(mdp, NULL); /* Get Input count */ 1115 1116 error = md_get_uint32le(mdp, &data_out_off); 1117 if (error) 1118 goto out; 1119 error = md_get_uint32le(mdp, &data_out_len); 1120 if (error) 1121 goto out; 1122 1123 md_get_uint32le(mdp, NULL); /* Flags */ 1124 md_get_uint32le(mdp, NULL); /* reserved */ 1125 1126 /* 1127 * If the caller wants the ioctl output data, parse. 1128 * Current offset is: SMB2_HDRLEN + 48 1129 * Always return the received length. 1130 */ 1131 *data_out_sz = data_out_len; 1132 if (data_out_len != 0) { 1133 int skip = (int)data_out_off - (SMB2_HDRLEN + 48); 1134 if (skip < 0) { 1135 error = EBADRPC; 1136 goto out; 1137 } 1138 if (skip > 0) { 1139 md_get_mem(mdp, NULL, skip, MB_MSYSTEM); 1140 } 1141 if (data_out != NULL) { 1142 mblk_t *m = NULL; 1143 error = md_get_mbuf(mdp, data_out_len, &m); 1144 if (error) 1145 goto out; 1146 md_initm(data_out, m); 1147 } 1148 } 1149 1150 out: 1151 smb_rq_done(rqp); 1152 1153 return (error); 1154 } 1155 1156 int 1157 smb2_smb_read(smb_fh_t *fhp, uint32_t *lenp, 1158 uio_t *uiop, smb_cred_t *scred, int timo) 1159 { 1160 struct smb_share *ssp = FHTOSS(fhp); 1161 struct smb_rq *rqp; 1162 struct mbchain *mbp; 1163 struct mdchain *mdp; 1164 int error; 1165 uint64_t off64 = uiop->uio_loffset; 1166 uint32_t rlen; 1167 uint16_t length = 0; 1168 uint8_t data_offset; 1169 1170 error = smb_rq_alloc(SSTOCP(ssp), SMB2_READ, scred, &rqp); 1171 if (error) 1172 return (error); 1173 1174 /* 1175 * Build the SMB 2 Read Request 1176 */ 1177 smb_rq_getrequest(rqp, &mbp); 1178 mb_put_uint16le(mbp, 49); /* Struct size */ 1179 mb_put_uint16le(mbp, 0); /* Padding and Reserved */ 1180 1181 mb_put_uint32le(mbp, *lenp); /* Length of read */ 1182 mb_put_uint64le(mbp, off64); /* Offset */ 1183 1184 mb_put_uint64le(mbp, fhp->fh_fid2.fid_persistent); 1185 mb_put_uint64le(mbp, fhp->fh_fid2.fid_volatile); 1186 1187 mb_put_uint32le(mbp, 1); /* MinCount */ 1188 /* (only indicates blocking) */ 1189 1190 mb_put_uint32le(mbp, 0); /* Channel */ 1191 mb_put_uint32le(mbp, 0); /* Remaining */ 1192 mb_put_uint32le(mbp, 0); /* Channel offset/len */ 1193 mb_put_uint8(mbp, 0); /* data "blob" (pad) */ 1194 1195 if (timo == 0) 1196 timo = smb2_timo_read; 1197 error = smb2_rq_simple_timed(rqp, timo); 1198 if (error) 1199 goto out; 1200 1201 /* 1202 * Parse SMB 2 Read Response 1203 */ 1204 smb_rq_getreply(rqp, &mdp); 1205 1206 /* Check structure size is 17 */ 1207 md_get_uint16le(mdp, &length); 1208 if (length != 17) { 1209 error = EBADRPC; 1210 goto out; 1211 } 1212 md_get_uint8(mdp, &data_offset); 1213 md_get_uint8(mdp, NULL); /* reserved */ 1214 1215 /* Get Data Length read */ 1216 error = md_get_uint32le(mdp, &rlen); 1217 if (error) 1218 goto out; 1219 1220 md_get_uint32le(mdp, NULL); /* Data Remaining (always 0) */ 1221 md_get_uint32le(mdp, NULL); /* Get Reserved2 (always 0) */ 1222 1223 /* 1224 * Data offset is from the beginning of SMB 2/3 Header 1225 * Calculate how much further we have to go to get to it. 1226 */ 1227 if (data_offset < (SMB2_HDRLEN + 16)) { 1228 error = EBADRPC; 1229 goto out; 1230 } 1231 if (data_offset > (SMB2_HDRLEN + 16)) { 1232 int skip = data_offset - (SMB2_HDRLEN + 16); 1233 md_get_mem(mdp, NULL, skip, MB_MSYSTEM); 1234 } 1235 1236 /* 1237 * Get the data 1238 */ 1239 if (rlen == 0) { 1240 *lenp = rlen; 1241 goto out; 1242 } 1243 /* paranoid */ 1244 if (rlen > *lenp) { 1245 SMBSDEBUG("bad server! rlen %d, len %d\n", 1246 rlen, *lenp); 1247 rlen = *lenp; 1248 } 1249 1250 error = md_get_uio(mdp, uiop, rlen); 1251 if (error) 1252 goto out; 1253 1254 /* Success */ 1255 *lenp = rlen; 1256 1257 out: 1258 smb_rq_done(rqp); 1259 return (error); 1260 } 1261 1262 int 1263 smb2_smb_write(smb_fh_t *fhp, uint32_t *lenp, 1264 uio_t *uiop, smb_cred_t *scred, int timo) 1265 { 1266 struct smb_share *ssp = FHTOSS(fhp); 1267 struct smb_rq *rqp; 1268 struct mbchain *mbp; 1269 struct mdchain *mdp; 1270 int error; 1271 uint64_t off64 = uiop->uio_loffset; 1272 uint32_t rlen; 1273 uint16_t data_offset; 1274 uint16_t length = 0; 1275 1276 error = smb_rq_alloc(SSTOCP(ssp), SMB2_WRITE, scred, &rqp); 1277 if (error) 1278 return (error); 1279 1280 /* 1281 * Build the SMB 2 Write Request 1282 */ 1283 smb_rq_getrequest(rqp, &mbp); 1284 mb_put_uint16le(mbp, 49); /* Struct size */ 1285 data_offset = SMB2_HDRLEN + 48; 1286 mb_put_uint16le(mbp, data_offset); /* Data Offset */ 1287 mb_put_uint32le(mbp, *lenp); /* Length of write */ 1288 mb_put_uint64le(mbp, off64); /* Offset */ 1289 1290 mb_put_uint64le(mbp, fhp->fh_fid2.fid_persistent); 1291 mb_put_uint64le(mbp, fhp->fh_fid2.fid_volatile); 1292 1293 mb_put_uint32le(mbp, 0); /* Channel */ 1294 mb_put_uint32le(mbp, 0); /* Remaining */ 1295 mb_put_uint32le(mbp, 0); /* Channel offset/len */ 1296 mb_put_uint32le(mbp, 0); /* Write flags */ 1297 1298 error = mb_put_uio(mbp, uiop, *lenp); 1299 if (error) 1300 goto out; 1301 1302 if (timo == 0) 1303 timo = smb2_timo_write; 1304 error = smb2_rq_simple_timed(rqp, timo); 1305 if (error) 1306 goto out; 1307 1308 /* 1309 * Parse SMB 2/3 Write Response 1310 */ 1311 smb_rq_getreply(rqp, &mdp); 1312 1313 /* Check structure size is 17 */ 1314 md_get_uint16le(mdp, &length); 1315 if (length != 17) { 1316 error = EBADRPC; 1317 goto out; 1318 } 1319 1320 md_get_uint16le(mdp, NULL); /* Get Reserved */ 1321 1322 /* Get Data Length written */ 1323 error = md_get_uint32le(mdp, &rlen); 1324 if (error) 1325 goto out; 1326 1327 /* Get Data Remaining (always 0) */ 1328 md_get_uint32le(mdp, NULL); 1329 1330 /* Get Reserved2 (always 0) */ 1331 md_get_uint32le(mdp, NULL); 1332 1333 /* Success */ 1334 *lenp = rlen; 1335 1336 out: 1337 smb_rq_done(rqp); 1338 return (error); 1339 } 1340 1341 /* 1342 * Note: the IOD calls this, so this request must not wait for 1343 * connection state changes, etc. (uses smb2_rq_internal) 1344 */ 1345 int 1346 smb2_smb_echo(struct smb_vc *vcp, struct smb_cred *scred, int timo) 1347 { 1348 struct smb_rq *rqp; 1349 struct mbchain *mbp; 1350 int error; 1351 1352 error = smb_rq_alloc(VCTOCP(vcp), SMB2_ECHO, scred, &rqp); 1353 if (error) 1354 return (error); 1355 1356 /* 1357 * Build the SMB 2 Echo Request 1358 */ 1359 smb_rq_getrequest(rqp, &mbp); 1360 mb_put_uint16le(mbp, 4); /* Struct size */ 1361 mb_put_uint16le(mbp, 0); /* Reserved */ 1362 1363 rqp->sr_flags |= SMBR_NORECONNECT; 1364 error = smb2_rq_internal(rqp, timo); 1365 1366 smb_rq_done(rqp); 1367 return (error); 1368 } 1369