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