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