1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2017 Nexenta Systems, Inc. All rights reserved. 14 */ 15 16 17 #include <smbsrv/smb2_kproto.h> 18 #include <smbsrv/smb_kstat.h> 19 #include <smbsrv/smb2.h> 20 21 #define SMB2_ASYNCID(sr) (sr->smb2_messageid ^ (1ULL << 62)) 22 23 smb_sdrc_t smb2_invalid_cmd(smb_request_t *); 24 static void smb2_tq_work(void *); 25 static void smb2sr_run_postwork(smb_request_t *); 26 static int smb3_decrypt_msg(smb_request_t *); 27 28 static const smb_disp_entry_t 29 smb2_disp_table[SMB2__NCMDS] = { 30 31 /* text-name, pre, func, post, cmd-code, dialect, flags */ 32 33 { "smb2_negotiate", NULL, 34 smb2_negotiate, NULL, 0, 0, 35 SDDF_SUPPRESS_TID | SDDF_SUPPRESS_UID }, 36 37 { "smb2_session_setup", NULL, 38 smb2_session_setup, NULL, 0, 0, 39 SDDF_SUPPRESS_TID | SDDF_SUPPRESS_UID }, 40 41 { "smb2_logoff", NULL, 42 smb2_logoff, NULL, 0, 0, 43 SDDF_SUPPRESS_TID }, 44 45 { "smb2_tree_connect", NULL, 46 smb2_tree_connect, NULL, 0, 0, 47 SDDF_SUPPRESS_TID }, 48 49 { "smb2_tree_disconn", NULL, 50 smb2_tree_disconn, NULL, 0, 0 }, 51 52 { "smb2_create", NULL, 53 smb2_create, NULL, 0, 0 }, 54 55 { "smb2_close", NULL, 56 smb2_close, NULL, 0, 0 }, 57 58 { "smb2_flush", NULL, 59 smb2_flush, NULL, 0, 0 }, 60 61 { "smb2_read", NULL, 62 smb2_read, NULL, 0, 0 }, 63 64 { "smb2_write", NULL, 65 smb2_write, NULL, 0, 0 }, 66 67 { "smb2_lock", NULL, 68 smb2_lock, NULL, 0, 0 }, 69 70 { "smb2_ioctl", NULL, 71 smb2_ioctl, NULL, 0, 0 }, 72 73 { "smb2_cancel", NULL, 74 smb2_cancel, NULL, 0, 0, 75 SDDF_SUPPRESS_UID | SDDF_SUPPRESS_TID }, 76 77 { "smb2_echo", NULL, 78 smb2_echo, NULL, 0, 0, 79 SDDF_SUPPRESS_UID | SDDF_SUPPRESS_TID }, 80 81 { "smb2_query_dir", NULL, 82 smb2_query_dir, NULL, 0, 0 }, 83 84 { "smb2_change_notify", NULL, 85 smb2_change_notify, NULL, 0, 0 }, 86 87 { "smb2_query_info", NULL, 88 smb2_query_info, NULL, 0, 0 }, 89 90 { "smb2_set_info", NULL, 91 smb2_set_info, NULL, 0, 0 }, 92 93 { "smb2_oplock_break_ack", NULL, 94 smb2_oplock_break_ack, NULL, 0, 0 }, 95 96 { "smb2_invalid_cmd", NULL, 97 smb2_invalid_cmd, NULL, 0, 0, 98 SDDF_SUPPRESS_UID | SDDF_SUPPRESS_TID }, 99 }; 100 101 smb_sdrc_t 102 smb2_invalid_cmd(smb_request_t *sr) 103 { 104 #ifdef DEBUG 105 cmn_err(CE_NOTE, "clnt %s bad SMB2 cmd code", 106 sr->session->ip_addr_str); 107 #endif 108 sr->smb2_status = NT_STATUS_INVALID_PARAMETER; 109 return (SDRC_DROP_VC); 110 } 111 112 /* 113 * This is the SMB2 handler for new smb requests, called from 114 * smb_session_reader after SMB negotiate is done. For most SMB2 115 * requests, we just enqueue them for the smb_session_worker to 116 * execute via the task queue, so they can block for resources 117 * without stopping the reader thread. A few protocol messages 118 * are special cases and are handled directly here in the reader 119 * thread so they don't wait for taskq scheduling. 120 * 121 * This function must either enqueue the new request for 122 * execution via the task queue, or execute it directly 123 * and then free it. If this returns non-zero, the caller 124 * will drop the session. 125 */ 126 int 127 smb2sr_newrq(smb_request_t *sr) 128 { 129 struct mbuf_chain *mbc = &sr->command; 130 uint32_t magic; 131 int rc, skip; 132 133 if (smb_mbc_peek(mbc, 0, "l", &magic) != 0) 134 goto drop; 135 136 /* 0xFD S M B */ 137 if (magic == SMB3_ENCRYPTED_MAGIC) { 138 if (smb3_decrypt_msg(sr) != 0) 139 goto drop; 140 /* 141 * Should now be looking at an un-encrypted 142 * SMB2 message header. 143 */ 144 if (smb_mbc_peek(mbc, 0, "l", &magic) != 0) 145 goto drop; 146 } 147 148 if (magic != SMB2_PROTOCOL_MAGIC) 149 goto drop; 150 151 /* 152 * Walk the SMB2 commands in this compound message and 153 * keep track of the range of message IDs it uses. 154 */ 155 for (;;) { 156 if (smb2_decode_header(sr) != 0) 157 goto drop; 158 159 /* 160 * Cancel requests are special: They refer to 161 * an earlier message ID (or an async. ID), 162 * never a new ID, and are never compounded. 163 * This is intentionally not "goto drop" 164 * because rc may be zero (success). 165 */ 166 if (sr->smb2_cmd_code == SMB2_CANCEL) { 167 rc = smb2_newrq_cancel(sr); 168 smb_request_free(sr); 169 return (rc); 170 } 171 172 /* 173 * Keep track of the total credits in this compound 174 * and the first (real) message ID (not: 0, -1) 175 * While we're looking, verify that all (real) IDs 176 * are (first <= ID < (first + msg_credits)) 177 */ 178 if (sr->smb2_credit_charge == 0) 179 sr->smb2_credit_charge = 1; 180 sr->smb2_total_credits += sr->smb2_credit_charge; 181 182 if (sr->smb2_messageid != 0 && 183 sr->smb2_messageid != UINT64_MAX) { 184 185 if (sr->smb2_first_msgid == 0) 186 sr->smb2_first_msgid = sr->smb2_messageid; 187 188 if (sr->smb2_messageid < sr->smb2_first_msgid || 189 sr->smb2_messageid >= (sr->smb2_first_msgid + 190 sr->smb2_total_credits)) { 191 long long id = (long long) sr->smb2_messageid; 192 cmn_err(CE_WARN, "clnt %s msg ID 0x%llx " 193 "out of sequence in compound", 194 sr->session->ip_addr_str, id); 195 } 196 } 197 198 /* Normal loop exit on next == zero */ 199 if (sr->smb2_next_command == 0) 200 break; 201 202 /* Abundance of caution... */ 203 if (sr->smb2_next_command < SMB2_HDR_SIZE) 204 goto drop; 205 206 /* Advance to the next header. */ 207 skip = sr->smb2_next_command - SMB2_HDR_SIZE; 208 if (MBC_ROOM_FOR(mbc, skip) == 0) 209 goto drop; 210 mbc->chain_offset += skip; 211 } 212 /* Rewind back to the top. */ 213 mbc->chain_offset = 0; 214 215 /* 216 * Submit the request to the task queue, which calls 217 * smb2_tq_work when the workload permits. 218 */ 219 sr->sr_time_submitted = gethrtime(); 220 sr->sr_state = SMB_REQ_STATE_SUBMITTED; 221 smb_srqueue_waitq_enter(sr->session->s_srqueue); 222 (void) taskq_dispatch(sr->sr_server->sv_worker_pool, 223 smb2_tq_work, sr, TQ_SLEEP); 224 return (0); 225 226 drop: 227 smb_request_free(sr); 228 return (-1); 229 } 230 231 static void 232 smb2_tq_work(void *arg) 233 { 234 smb_request_t *sr; 235 smb_srqueue_t *srq; 236 237 sr = (smb_request_t *)arg; 238 SMB_REQ_VALID(sr); 239 240 srq = sr->session->s_srqueue; 241 smb_srqueue_waitq_to_runq(srq); 242 sr->sr_worker = curthread; 243 sr->sr_time_active = gethrtime(); 244 245 /* 246 * Always dispatch to the work function, because cancelled 247 * requests need an error reply (NT_STATUS_CANCELLED). 248 */ 249 mutex_enter(&sr->sr_mutex); 250 if (sr->sr_state == SMB_REQ_STATE_SUBMITTED) 251 sr->sr_state = SMB_REQ_STATE_ACTIVE; 252 mutex_exit(&sr->sr_mutex); 253 254 smb2sr_work(sr); 255 256 smb_srqueue_runq_exit(srq); 257 } 258 259 static int 260 smb3_decrypt_msg(smb_request_t *sr) 261 { 262 int save_offset; 263 264 if (sr->session->dialect < SMB_VERS_3_0) { 265 cmn_err(CE_WARN, "encrypted message in SMB 2.x"); 266 return (-1); 267 } 268 269 sr->encrypted = B_TRUE; 270 save_offset = sr->command.chain_offset; 271 if (smb3_decode_tform_header(sr) != 0) { 272 cmn_err(CE_WARN, "bad transform header"); 273 return (-1); 274 } 275 sr->command.chain_offset = save_offset; 276 277 sr->tform_ssn = smb_session_lookup_ssnid(sr->session, 278 sr->smb3_tform_ssnid); 279 if (sr->tform_ssn == NULL) { 280 cmn_err(CE_WARN, "transform header: session not found"); 281 return (-1); 282 } 283 284 if (smb3_decrypt_sr(sr) != 0) { 285 cmn_err(CE_WARN, "smb3 decryption failed"); 286 return (-1); 287 } 288 289 return (0); 290 } 291 292 /* 293 * SMB2 credits determine how many simultaneous commands the 294 * client may issue, and bounds the range of message IDs those 295 * commands may use. With multi-credit support, commands may 296 * use ranges of message IDs, where the credits used by each 297 * command are proportional to their data transfer size. 298 * 299 * Every command may request an increase or decrease of 300 * the currently granted credits, based on the difference 301 * between the credit request and the credit charge. 302 * [MS-SMB2] 3.3.1.2 Algorithm for the Granting of Credits 303 * 304 * Most commands have credit_request=1, credit_charge=1, 305 * which keeps the credit grant unchanged. 306 * 307 * All we're really doing here (for now) is reducing the 308 * credit_response if the client requests a credit increase 309 * that would take their credit over the maximum, and 310 * limiting the decrease so they don't run out of credits. 311 * 312 * Later, this could do something dynamic based on load. 313 * 314 * One other non-obvious bit about credits: We keep the 315 * session s_max_credits low until the 1st authentication, 316 * at which point we'll set the normal maximum_credits. 317 * Some clients ask for more credits with session setup, 318 * and we need to handle that requested increase _after_ 319 * the command-specific handler returns so it won't be 320 * restricted to the lower (pre-auth) limit. 321 */ 322 static inline void 323 smb2_credit_decrease(smb_request_t *sr) 324 { 325 smb_session_t *session = sr->session; 326 uint16_t cur, d; 327 328 mutex_enter(&session->s_credits_mutex); 329 cur = session->s_cur_credits; 330 331 /* Handle credit decrease. */ 332 d = sr->smb2_credit_charge - sr->smb2_credit_request; 333 cur -= d; 334 if (cur & 0x8000) { 335 /* 336 * underflow (bad credit charge or request) 337 * leave credits unchanged (response=charge) 338 */ 339 cur = session->s_cur_credits; 340 sr->smb2_credit_response = sr->smb2_credit_charge; 341 DTRACE_PROBE1(smb2__credit__neg, smb_request_t *, sr); 342 } 343 344 /* 345 * The server MUST ensure that the number of credits 346 * held by the client is never reduced to zero. 347 * [MS-SMB2] 3.3.1.2 348 */ 349 if (cur == 0) { 350 cur = 1; 351 sr->smb2_credit_response += 1; 352 DTRACE_PROBE1(smb2__credit__min, smb_request_t *, sr); 353 } 354 355 DTRACE_PROBE3(smb2__credit__decrease, 356 smb_request_t *, sr, int, (int)cur, 357 int, (int)session->s_cur_credits); 358 359 session->s_cur_credits = cur; 360 mutex_exit(&session->s_credits_mutex); 361 } 362 363 /* 364 * Second half of SMB2 credit handling (increases) 365 */ 366 static inline void 367 smb2_credit_increase(smb_request_t *sr) 368 { 369 smb_session_t *session = sr->session; 370 uint16_t cur, d; 371 372 mutex_enter(&session->s_credits_mutex); 373 cur = session->s_cur_credits; 374 375 /* Handle credit increase. */ 376 d = sr->smb2_credit_request - sr->smb2_credit_charge; 377 cur += d; 378 379 /* 380 * If new credits would be above max, 381 * reduce the credit grant. 382 */ 383 if (cur > session->s_max_credits) { 384 d = cur - session->s_max_credits; 385 cur = session->s_max_credits; 386 sr->smb2_credit_response -= d; 387 DTRACE_PROBE1(smb2__credit__max, smb_request_t, sr); 388 } 389 390 DTRACE_PROBE3(smb2__credit__increase, 391 smb_request_t *, sr, int, (int)cur, 392 int, (int)session->s_cur_credits); 393 394 session->s_cur_credits = cur; 395 mutex_exit(&session->s_credits_mutex); 396 } 397 398 /* 399 * Record some statistics: latency, rx bytes, tx bytes 400 * per: server, session & kshare. 401 */ 402 static inline void 403 smb2_record_stats(smb_request_t *sr, smb_disp_stats_t *sds, boolean_t tx_only) 404 { 405 hrtime_t dt; 406 int64_t rxb; 407 int64_t txb; 408 409 dt = gethrtime() - sr->sr_time_start; 410 rxb = (int64_t)(sr->command.chain_offset - sr->smb2_cmd_hdr); 411 txb = (int64_t)(sr->reply.chain_offset - sr->smb2_reply_hdr); 412 413 if (!tx_only) { 414 smb_server_inc_req(sr->sr_server); 415 smb_latency_add_sample(&sds->sdt_lat, dt); 416 atomic_add_64(&sds->sdt_rxb, rxb); 417 } 418 atomic_add_64(&sds->sdt_txb, txb); 419 } 420 421 /* 422 * smb2sr_work 423 * 424 * This function processes each SMB command in the current request 425 * (which may be a compound request) building a reply containing 426 * SMB reply messages, one-to-one with the SMB commands. Some SMB 427 * commands (change notify, blocking locks) may require both an 428 * "interim response" and a later "async response" at completion. 429 * In such cases, we'll encode the interim response in the reply 430 * compound we're building, and put the (now async) command on a 431 * list of commands that need further processing. After we've 432 * finished processing the commands in this compound and building 433 * the compound reply, we'll send the compound reply, and finally 434 * process the list of async commands. 435 * 436 * As we work our way through the compound request and reply, 437 * we need to keep track of the bounds of the current request 438 * and reply. For the request, this uses an MBC_SHADOW_CHAIN 439 * that begins at smb2_cmd_hdr. The reply is appended to the 440 * sr->reply chain starting at smb2_reply_hdr. 441 * 442 * This function must always free the smb request, or arrange 443 * for it to be completed and free'd later (if SDRC_SR_KEPT). 444 */ 445 void 446 smb2sr_work(struct smb_request *sr) 447 { 448 const smb_disp_entry_t *sdd; 449 smb_disp_stats_t *sds; 450 smb_session_t *session; 451 uint32_t msg_len; 452 uint16_t cmd_idx; 453 int rc = 0; 454 boolean_t disconnect = B_FALSE; 455 boolean_t related; 456 457 session = sr->session; 458 459 ASSERT(sr->smb2_async == B_FALSE); 460 ASSERT(sr->tid_tree == 0); 461 ASSERT(sr->uid_user == 0); 462 ASSERT(sr->fid_ofile == 0); 463 sr->smb_fid = (uint16_t)-1; 464 sr->smb2_status = 0; 465 466 /* temporary until we identify a user */ 467 sr->user_cr = zone_kcred(); 468 469 cmd_start: 470 /* 471 * Note that we don't check sr_state here and abort the 472 * compound if cancelled (etc.) because some SMB2 command 473 * handlers need to do work even when cancelled. 474 * 475 * We treat some status codes as if "sticky", meaning 476 * once they're set after some command handler returns, 477 * all remaining commands get this status without even 478 * calling the command-specific handler. 479 */ 480 if (sr->smb2_status != NT_STATUS_CANCELLED && 481 sr->smb2_status != NT_STATUS_INSUFFICIENT_RESOURCES) 482 sr->smb2_status = 0; 483 484 /* 485 * Decode the request header 486 * 487 * Most problems with decoding will result in the error 488 * STATUS_INVALID_PARAMETER. If the decoding problem 489 * prevents continuing, we'll close the connection. 490 * [MS-SMB2] 3.3.5.2.6 Handling Incorrectly Formatted... 491 */ 492 sr->smb2_cmd_hdr = sr->command.chain_offset; 493 if ((rc = smb2_decode_header(sr)) != 0) { 494 cmn_err(CE_WARN, "clnt %s bad SMB2 header", 495 session->ip_addr_str); 496 disconnect = B_TRUE; 497 goto cleanup; 498 } 499 500 /* 501 * The SMB2_FLAGS_SERVER_TO_REDIR should only appear 502 * in messages from the server back to the client. 503 */ 504 if ((sr->smb2_hdr_flags & SMB2_FLAGS_SERVER_TO_REDIR) != 0) { 505 cmn_err(CE_WARN, "clnt %s bad SMB2 flags", 506 session->ip_addr_str); 507 disconnect = B_TRUE; 508 goto cleanup; 509 } 510 related = (sr->smb2_hdr_flags & SMB2_FLAGS_RELATED_OPERATIONS); 511 sr->smb2_hdr_flags |= SMB2_FLAGS_SERVER_TO_REDIR; 512 if (sr->smb2_hdr_flags & SMB2_FLAGS_ASYNC_COMMAND) { 513 /* Probably an async cancel. */ 514 DTRACE_PROBE1(smb2__dispatch__async, smb_request_t *, sr); 515 } else if (sr->smb2_async) { 516 /* Previous command in compound went async. */ 517 sr->smb2_hdr_flags |= SMB2_FLAGS_ASYNC_COMMAND; 518 sr->smb2_async_id = SMB2_ASYNCID(sr); 519 } 520 521 /* 522 * In case we bail out with an error before we get to the 523 * section that computes the credit grant, initialize the 524 * response header fields so that credits won't change. 525 * Note: SMB 2.02 clients may send credit charge zero. 526 */ 527 if (sr->smb2_credit_charge == 0) 528 sr->smb2_credit_charge = 1; 529 sr->smb2_credit_response = sr->smb2_credit_charge; 530 531 /* 532 * Write a tentative reply header. 533 * 534 * We could just leave this blank, but if we're using the 535 * mdb module feature that extracts packets, it's useful 536 * to have the header mostly correct here. 537 * 538 * If we have already exhausted the output space, then the 539 * client is trying something funny. Log it and kill 'em. 540 */ 541 sr->smb2_next_reply = 0; 542 ASSERT((sr->reply.chain_offset & 7) == 0); 543 sr->smb2_reply_hdr = sr->reply.chain_offset; 544 if ((rc = smb2_encode_header(sr, B_FALSE)) != 0) { 545 cmn_err(CE_WARN, "clnt %s excessive reply", 546 session->ip_addr_str); 547 disconnect = B_TRUE; 548 goto cleanup; 549 } 550 551 /* 552 * Figure out the length of data following the SMB2 header. 553 * It ends at either the next SMB2 header if there is one 554 * (smb2_next_command != 0) or at the end of the message. 555 */ 556 if (sr->smb2_next_command != 0) { 557 /* [MS-SMB2] says this is 8-byte aligned */ 558 msg_len = sr->smb2_next_command; 559 if ((msg_len & 7) != 0 || (msg_len < SMB2_HDR_SIZE) || 560 ((sr->smb2_cmd_hdr + msg_len) > sr->command.max_bytes)) { 561 cmn_err(CE_WARN, "clnt %s bad SMB2 next cmd", 562 session->ip_addr_str); 563 disconnect = B_TRUE; 564 goto cleanup; 565 } 566 } else { 567 msg_len = sr->command.max_bytes - sr->smb2_cmd_hdr; 568 } 569 570 /* 571 * Setup a shadow chain for this SMB2 command, starting 572 * with the header and ending at either the next command 573 * or the end of the message. The signing check below 574 * needs the entire SMB2 command. After that's done, we 575 * advance chain_offset to the end of the header where 576 * the command specific handlers continue decoding. 577 */ 578 (void) MBC_SHADOW_CHAIN(&sr->smb_data, &sr->command, 579 sr->smb2_cmd_hdr, msg_len); 580 581 /* 582 * We will consume the data for this request from smb_data. 583 * That effectively consumes msg_len bytes from sr->command 584 * but doesn't update its chain_offset, so we need to update 585 * that here to make later received bytes accounting work. 586 */ 587 sr->command.chain_offset = sr->smb2_cmd_hdr + msg_len; 588 ASSERT(sr->command.chain_offset <= sr->command.max_bytes); 589 590 /* 591 * Validate the commmand code, get dispatch table entries. 592 * [MS-SMB2] 3.3.5.2.6 Handling Incorrectly Formatted... 593 * 594 * The last slot in the dispatch table is used to handle 595 * invalid commands. Same for statistics. 596 */ 597 if (sr->smb2_cmd_code < SMB2_INVALID_CMD) 598 cmd_idx = sr->smb2_cmd_code; 599 else 600 cmd_idx = SMB2_INVALID_CMD; 601 sdd = &smb2_disp_table[cmd_idx]; 602 sds = &session->s_server->sv_disp_stats2[cmd_idx]; 603 604 /* 605 * If this command is NOT "related" to the previous, 606 * clear out the UID, TID, FID state that might be 607 * left over from the previous command. 608 * 609 * If the command IS related, any new IDs are ignored, 610 * and we simply continue with the previous user, tree, 611 * and open file. 612 */ 613 if (!related) { 614 /* 615 * Drop user, tree, file; carefully ordered to 616 * avoid dangling references: file, tree, user 617 */ 618 if (sr->fid_ofile != NULL) { 619 smb_ofile_release(sr->fid_ofile); 620 sr->fid_ofile = NULL; 621 } 622 if (sr->tid_tree != NULL) { 623 smb_tree_release(sr->tid_tree); 624 sr->tid_tree = NULL; 625 } 626 if (sr->uid_user != NULL) { 627 smb_user_release(sr->uid_user); 628 sr->uid_user = NULL; 629 sr->user_cr = zone_kcred(); 630 } 631 } 632 633 /* 634 * Make sure we have a user and tree as needed 635 * according to the flags for the this command. 636 * Note that we may have inherited these. 637 */ 638 if ((sdd->sdt_flags & SDDF_SUPPRESS_UID) == 0) { 639 /* 640 * This command requires a user session. 641 */ 642 if (related) { 643 /* 644 * Previous command should have given us a user. 645 * [MS-SMB2] 3.3.5.2 Handling Related Requests 646 */ 647 if (sr->uid_user == NULL) { 648 smb2sr_put_error(sr, 649 NT_STATUS_INVALID_PARAMETER); 650 goto cmd_done; 651 } 652 sr->smb2_ssnid = sr->uid_user->u_ssnid; 653 } else { 654 /* 655 * Lookup the UID 656 * [MS-SMB2] 3.3.5.2 Verifying the Session 657 */ 658 ASSERT(sr->uid_user == NULL); 659 /* 660 * [MS-SMB2] 3.3.5.2.7 Handling Compounded Requests 661 * 662 * If this is an encrypted compound request, 663 * ensure that the ssnid in the request 664 * is the same as the tform ssnid if this 665 * message is not related. 666 * 667 * The reasons this is done seem to apply equally 668 * to uncompounded requests, so we apply it to all. 669 */ 670 671 if (sr->encrypted && 672 sr->smb2_ssnid != sr->smb3_tform_ssnid) { 673 disconnect = B_TRUE; 674 goto cleanup; /* just do this for now */ 675 } 676 677 sr->uid_user = smb_session_lookup_ssnid(session, 678 sr->smb2_ssnid); 679 if (sr->uid_user == NULL) { 680 smb2sr_put_error(sr, 681 NT_STATUS_USER_SESSION_DELETED); 682 goto cmd_done; 683 } 684 685 /* 686 * [MS-SMB2] 3.3.5.2.9 Verifying the Session 687 * 688 * If we're talking 3.x, 689 * RejectUnencryptedAccess is TRUE, 690 * Session.EncryptData is TRUE, 691 * and the message wasn't encrypted, 692 * return ACCESS_DENIED. 693 * 694 * Note that Session.EncryptData can only be TRUE when 695 * we're talking 3.x. 696 */ 697 698 if (sr->uid_user->u_encrypt == 699 SMB_CONFIG_REQUIRED && 700 !sr->encrypted) { 701 smb2sr_put_error(sr, 702 NT_STATUS_ACCESS_DENIED); 703 goto cmd_done; 704 } 705 706 sr->user_cr = smb_user_getcred(sr->uid_user); 707 } 708 ASSERT(sr->uid_user != NULL); 709 710 /* 711 * Encrypt if: 712 * - The cmd is not SESSION_SETUP or NEGOTIATE; AND 713 * - Session.EncryptData is TRUE 714 * 715 * Those commands suppress UID, so they can't be the cmd here. 716 */ 717 if (sr->uid_user->u_encrypt != SMB_CONFIG_DISABLED && 718 sr->tform_ssn == NULL) { 719 smb_user_hold_internal(sr->uid_user); 720 sr->tform_ssn = sr->uid_user; 721 sr->smb3_tform_ssnid = sr->smb2_ssnid; 722 } 723 } 724 725 if ((sdd->sdt_flags & SDDF_SUPPRESS_TID) == 0) { 726 /* 727 * This command requires a tree connection. 728 */ 729 if (related) { 730 /* 731 * Previous command should have given us a tree. 732 * [MS-SMB2] 3.3.5.2 Handling Related Requests 733 */ 734 if (sr->tid_tree == NULL) { 735 smb2sr_put_error(sr, 736 NT_STATUS_INVALID_PARAMETER); 737 goto cmd_done; 738 } 739 sr->smb_tid = sr->tid_tree->t_tid; 740 } else { 741 /* 742 * Lookup the TID 743 * [MS-SMB2] 3.3.5.2 Verifying the Tree Connect 744 */ 745 ASSERT(sr->tid_tree == NULL); 746 sr->tid_tree = smb_session_lookup_tree(session, 747 sr->smb_tid); 748 if (sr->tid_tree == NULL) { 749 smb2sr_put_error(sr, 750 NT_STATUS_NETWORK_NAME_DELETED); 751 goto cmd_done; 752 } 753 754 /* 755 * [MS-SMB2] 3.3.5.2.11 Verifying the Tree Connect 756 * 757 * If we support 3.x, RejectUnencryptedAccess is TRUE, 758 * if Tcon.EncryptData is TRUE or 759 * global EncryptData is TRUE and 760 * the message wasn't encrypted, or 761 * if Tcon.EncryptData is TRUE or 762 * global EncryptData is TRUE or 763 * the request was encrypted and 764 * the connection doesn't support encryption, 765 * return ACCESS_DENIED. 766 * 767 * If RejectUnencryptedAccess is TRUE, we force 768 * max_protocol to at least 3.0. Additionally, 769 * if the tree requires encryption, we don't care 770 * what we support, we still enforce encryption. 771 */ 772 if (sr->tid_tree->t_encrypt == SMB_CONFIG_REQUIRED && 773 (!sr->encrypted || 774 (session->srv_cap & SMB2_CAP_ENCRYPTION) == 0)) { 775 smb2sr_put_error(sr, 776 NT_STATUS_ACCESS_DENIED); 777 goto cmd_done; 778 } 779 } 780 ASSERT(sr->tid_tree != NULL); 781 782 /* 783 * Encrypt if: 784 * - The cmd is not TREE_CONNECT; AND 785 * - Tree.EncryptData is TRUE 786 * 787 * TREE_CONNECT suppresses TID, so that can't be the cmd here. 788 * NOTE: assumes we can't have a tree without a user 789 */ 790 if (sr->tid_tree->t_encrypt != SMB_CONFIG_DISABLED && 791 sr->tform_ssn == NULL) { 792 smb_user_hold_internal(sr->uid_user); 793 sr->tform_ssn = sr->uid_user; 794 sr->smb3_tform_ssnid = sr->smb2_ssnid; 795 } 796 } 797 798 /* 799 * SMB2 signature verification, two parts: 800 * (a) Require SMB2_FLAGS_SIGNED (for most request types) 801 * (b) If SMB2_FLAGS_SIGNED is set, check the signature. 802 * [MS-SMB2] 3.3.5.2.4 Verifying the Signature 803 */ 804 805 /* 806 * No user session means no signature check. That's OK, 807 * i.e. for commands marked SDDF_SUPPRESS_UID above. 808 * Note, this also means we won't sign the reply. 809 */ 810 if (sr->uid_user == NULL) 811 sr->smb2_hdr_flags &= ~SMB2_FLAGS_SIGNED; 812 813 /* 814 * The SDDF_SUPPRESS_UID dispatch is set for requests that 815 * don't need a UID (user). These also don't require a 816 * signature check here. 817 * 818 * [MS-SMB2] 3.3.5.2.4 Verifying the Signature 819 * 820 * If the packet was successfully decrypted, the message 821 * signature has already been verified, so we can skip this. 822 */ 823 if ((sdd->sdt_flags & SDDF_SUPPRESS_UID) == 0 && 824 !sr->encrypted && sr->uid_user != NULL && 825 (sr->uid_user->u_sign_flags & SMB_SIGNING_CHECK) != 0) { 826 /* 827 * This request type should be signed, and 828 * we're configured to require signatures. 829 */ 830 if ((sr->smb2_hdr_flags & SMB2_FLAGS_SIGNED) == 0) { 831 smb2sr_put_error(sr, NT_STATUS_ACCESS_DENIED); 832 goto cmd_done; 833 } 834 rc = smb2_sign_check_request(sr); 835 if (rc != 0) { 836 DTRACE_PROBE1(smb2__sign__check, smb_request_t *, sr); 837 smb2sr_put_error(sr, NT_STATUS_ACCESS_DENIED); 838 goto cmd_done; 839 } 840 } 841 842 /* 843 * Now that the signing check is done with smb_data, 844 * advance past the SMB2 header we decoded earlier. 845 * This leaves sr->smb_data correctly positioned 846 * for command-specific decoding in the dispatch 847 * function called next. 848 */ 849 sr->smb_data.chain_offset = sr->smb2_cmd_hdr + SMB2_HDR_SIZE; 850 851 /* 852 * Credit adjustments (decrease) 853 * 854 * If we've gone async, credit adjustments were done 855 * when we sent the interim reply. 856 */ 857 if (!sr->smb2_async) { 858 sr->smb2_credit_response = sr->smb2_credit_request; 859 if (sr->smb2_credit_request < sr->smb2_credit_charge) { 860 smb2_credit_decrease(sr); 861 } 862 } 863 864 /* 865 * The real work: call the SMB2 command handler 866 * (except for "sticky" smb2_status - see above) 867 */ 868 sr->sr_time_start = gethrtime(); 869 rc = SDRC_SUCCESS; 870 if (sr->smb2_status == 0) { 871 /* NB: not using pre_op */ 872 rc = (*sdd->sdt_function)(sr); 873 /* NB: not using post_op */ 874 } else { 875 smb2sr_put_error(sr, sr->smb2_status); 876 } 877 878 /* 879 * When the sdt_function returns SDRC_SR_KEPT, it means 880 * this SR may have been passed to another thread so we 881 * MUST NOT touch it anymore. 882 */ 883 if (rc == SDRC_SR_KEPT) 884 return; 885 886 MBC_FLUSH(&sr->raw_data); 887 888 /* 889 * Credit adjustments (increase) 890 */ 891 if (!sr->smb2_async) { 892 if (sr->smb2_credit_request > sr->smb2_credit_charge) { 893 smb2_credit_increase(sr); 894 } 895 } 896 897 cmd_done: 898 switch (rc) { 899 case SDRC_SUCCESS: 900 break; 901 default: 902 /* 903 * SMB2 does not use the other dispatch return codes. 904 * If we see something else, log an event so we'll 905 * know something is returning bogus status codes. 906 * If you see these in the log, use dtrace to find 907 * the code returning something else. 908 */ 909 #ifdef DEBUG 910 cmn_err(CE_NOTE, "handler for %u returned 0x%x", 911 sr->smb2_cmd_code, rc); 912 #endif 913 sr->smb2_status = NT_STATUS_INTERNAL_ERROR; 914 break; 915 case SDRC_ERROR: 916 /* 917 * Many command handlers return SDRC_ERROR for any 918 * problems decoding the request, and don't bother 919 * setting smb2_status. For those cases, the best 920 * status return would be "invalid parameter". 921 */ 922 if (sr->smb2_status == 0) 923 sr->smb2_status = NT_STATUS_INVALID_PARAMETER; 924 break; 925 case SDRC_DROP_VC: 926 disconnect = B_TRUE; 927 goto cleanup; 928 929 case SDRC_NO_REPLY: 930 /* will free sr */ 931 goto cleanup; 932 } 933 934 /* 935 * Pad the reply to align(8) if there will be another. 936 * (We don't compound async replies.) 937 */ 938 if (!sr->smb2_async && sr->smb2_next_command != 0) 939 (void) smb_mbc_put_align(&sr->reply, 8); 940 941 /* 942 * Record some statistics. Uses: 943 * rxb = command.chain_offset - smb2_cmd_hdr; 944 * txb = reply.chain_offset - smb2_reply_hdr; 945 * which at this point represent the current cmd/reply. 946 * 947 * Note: If async, this does txb only, and 948 * skips the smb_latency_add_sample() calls. 949 */ 950 smb2_record_stats(sr, sds, sr->smb2_async); 951 952 /* 953 * If there's a next command, figure out where it starts, 954 * and fill in the next header offset for the reply. 955 * Note: We sanity checked smb2_next_command above. 956 */ 957 if (sr->smb2_next_command != 0) { 958 sr->command.chain_offset = 959 sr->smb2_cmd_hdr + sr->smb2_next_command; 960 sr->smb2_next_reply = 961 sr->reply.chain_offset - sr->smb2_reply_hdr; 962 } else { 963 ASSERT(sr->smb2_next_reply == 0); 964 } 965 966 /* 967 * Overwrite the (now final) SMB2 header for this response. 968 */ 969 (void) smb2_encode_header(sr, B_TRUE); 970 971 /* Don't sign if we're going to encrypt */ 972 if (sr->tform_ssn == NULL && 973 (sr->smb2_hdr_flags & SMB2_FLAGS_SIGNED) != 0) 974 smb2_sign_reply(sr); 975 976 /* 977 * Non-async runs the whole compound before send. 978 * When we've gone async, send each individually. 979 */ 980 if (!sr->smb2_async && sr->smb2_next_command != 0) 981 goto cmd_start; 982 smb2_send_reply(sr); 983 if (sr->smb2_async && sr->smb2_next_command != 0) { 984 MBC_FLUSH(&sr->reply); /* New reply buffer. */ 985 ASSERT(sr->reply.max_bytes == sr->session->reply_max_bytes); 986 goto cmd_start; 987 } 988 989 cleanup: 990 if (disconnect) 991 smb_session_disconnect(session); 992 993 if (sr->sr_postwork != NULL) 994 smb2sr_run_postwork(sr); 995 996 mutex_enter(&sr->sr_mutex); 997 sr->sr_state = SMB_REQ_STATE_COMPLETED; 998 mutex_exit(&sr->sr_mutex); 999 1000 smb_request_free(sr); 1001 } 1002 1003 /* 1004 * Build interim responses for the current and all following 1005 * requests in this compound, then send the compound response, 1006 * leaving the SR state so that smb2sr_work() can continue its 1007 * processing of this compound in "async mode". 1008 * 1009 * If we agree to "go async", this should return STATUS_SUCCESS. 1010 * Otherwise return STATUS_INSUFFICIENT_RESOURCES for this and 1011 * all requests following this request. (See the comments re. 1012 * "sticky" smb2_status values in smb2sr_work). 1013 * 1014 * Note: the Async ID we assign here is arbitrary, and need only 1015 * be unique among pending async responses on this connection, so 1016 * this just uses a modified messageID, which is already unique. 1017 * 1018 * Credits: All credit changes should happen via the interim 1019 * responses, so we have to manage credits here. After this 1020 * returns to smb2sr_work, the final replies for all these 1021 * commands will have smb2_credit_response = smb2_credit_charge 1022 * (meaning no further changes to the clients' credits). 1023 */ 1024 uint32_t 1025 smb2sr_go_async(smb_request_t *sr) 1026 { 1027 smb_session_t *session; 1028 smb_disp_stats_t *sds; 1029 uint16_t cmd_idx; 1030 int32_t saved_com_offset; 1031 uint32_t saved_cmd_hdr; 1032 uint16_t saved_cred_resp; 1033 uint32_t saved_hdr_flags; 1034 uint32_t saved_reply_hdr; 1035 uint32_t msg_len; 1036 boolean_t disconnect = B_FALSE; 1037 1038 if (sr->smb2_async) { 1039 /* already went async in some previous cmd. */ 1040 return (NT_STATUS_SUCCESS); 1041 } 1042 sr->smb2_async = B_TRUE; 1043 1044 /* The "server" session always runs async. */ 1045 session = sr->session; 1046 if (session->sock == NULL) 1047 return (NT_STATUS_SUCCESS); 1048 1049 sds = NULL; 1050 saved_com_offset = sr->command.chain_offset; 1051 saved_cmd_hdr = sr->smb2_cmd_hdr; 1052 saved_cred_resp = sr->smb2_credit_response; 1053 saved_hdr_flags = sr->smb2_hdr_flags; 1054 saved_reply_hdr = sr->smb2_reply_hdr; 1055 1056 /* 1057 * The command-specific handler should not yet have put any 1058 * data in the reply except for the (place holder) header. 1059 */ 1060 if (sr->reply.chain_offset != sr->smb2_reply_hdr + SMB2_HDR_SIZE) { 1061 ASSERT3U(sr->reply.chain_offset, ==, 1062 sr->smb2_reply_hdr + SMB2_HDR_SIZE); 1063 return (NT_STATUS_INTERNAL_ERROR); 1064 } 1065 1066 /* 1067 * Rewind to the start of the current header in both the 1068 * command and reply bufers, so the loop below can just 1069 * decode/encode just in every pass. This means the 1070 * current command header is decoded again, but that 1071 * avoids having to special-case the first loop pass. 1072 */ 1073 sr->command.chain_offset = sr->smb2_cmd_hdr; 1074 sr->reply.chain_offset = sr->smb2_reply_hdr; 1075 1076 /* 1077 * This command processing loop is a simplified version of 1078 * smb2sr_work() that just puts an "interim response" for 1079 * every command in the compound (NT_STATUS_PENDING). 1080 */ 1081 cmd_start: 1082 sr->smb2_status = NT_STATUS_PENDING; 1083 1084 /* 1085 * Decode the request header 1086 */ 1087 sr->smb2_cmd_hdr = sr->command.chain_offset; 1088 if ((smb2_decode_header(sr)) != 0) { 1089 cmn_err(CE_WARN, "clnt %s bad SMB2 header", 1090 session->ip_addr_str); 1091 disconnect = B_TRUE; 1092 goto cleanup; 1093 } 1094 sr->smb2_hdr_flags |= (SMB2_FLAGS_SERVER_TO_REDIR | 1095 SMB2_FLAGS_ASYNC_COMMAND); 1096 sr->smb2_async_id = SMB2_ASYNCID(sr); 1097 1098 /* 1099 * In case we bail out... 1100 */ 1101 if (sr->smb2_credit_charge == 0) 1102 sr->smb2_credit_charge = 1; 1103 sr->smb2_credit_response = sr->smb2_credit_charge; 1104 1105 /* 1106 * Write a tentative reply header. 1107 */ 1108 sr->smb2_next_reply = 0; 1109 ASSERT((sr->reply.chain_offset & 7) == 0); 1110 sr->smb2_reply_hdr = sr->reply.chain_offset; 1111 if ((smb2_encode_header(sr, B_FALSE)) != 0) { 1112 cmn_err(CE_WARN, "clnt %s excessive reply", 1113 session->ip_addr_str); 1114 disconnect = B_TRUE; 1115 goto cleanup; 1116 } 1117 1118 /* 1119 * Figure out the length of data... 1120 */ 1121 if (sr->smb2_next_command != 0) { 1122 /* [MS-SMB2] says this is 8-byte aligned */ 1123 msg_len = sr->smb2_next_command; 1124 if ((msg_len & 7) != 0 || (msg_len < SMB2_HDR_SIZE) || 1125 ((sr->smb2_cmd_hdr + msg_len) > sr->command.max_bytes)) { 1126 cmn_err(CE_WARN, "clnt %s bad SMB2 next cmd", 1127 session->ip_addr_str); 1128 disconnect = B_TRUE; 1129 goto cleanup; 1130 } 1131 } else { 1132 msg_len = sr->command.max_bytes - sr->smb2_cmd_hdr; 1133 } 1134 1135 /* 1136 * We just skip any data, so no shadow chain etc. 1137 */ 1138 sr->command.chain_offset = sr->smb2_cmd_hdr + msg_len; 1139 ASSERT(sr->command.chain_offset <= sr->command.max_bytes); 1140 1141 /* 1142 * Validate the commmand code... 1143 */ 1144 if (sr->smb2_cmd_code < SMB2_INVALID_CMD) 1145 cmd_idx = sr->smb2_cmd_code; 1146 else 1147 cmd_idx = SMB2_INVALID_CMD; 1148 sds = &session->s_server->sv_disp_stats2[cmd_idx]; 1149 1150 /* 1151 * Don't change (user, tree, file) because we want them 1152 * exactly as they were when we entered. That also means 1153 * we may not have the right user in sr->uid_user for 1154 * signature checks, so leave that until smb2sr_work 1155 * runs these commands "for real". Therefore, here 1156 * we behave as if: (sr->uid_user == NULL) 1157 */ 1158 sr->smb2_hdr_flags &= ~SMB2_FLAGS_SIGNED; 1159 1160 /* 1161 * Credit adjustments (decrease) 1162 * 1163 * NOTE: interim responses are not signed. 1164 * Any attacker can modify the credit grant 1165 * in the response. Because of this property, 1166 * it is no worse to assume the credit charge and grant 1167 * are sane without verifying the signature, 1168 * and that saves us a whole lot of work. 1169 * If the credits WERE modified, we'll find out 1170 * when we verify the signature later, 1171 * which nullifies any changes caused here. 1172 * 1173 * Skip this on the first command, because the 1174 * credit decrease was done by the caller. 1175 */ 1176 if (sr->smb2_cmd_hdr != saved_cmd_hdr) { 1177 sr->smb2_credit_response = sr->smb2_credit_request; 1178 if (sr->smb2_credit_request < sr->smb2_credit_charge) { 1179 smb2_credit_decrease(sr); 1180 } 1181 } 1182 1183 /* 1184 * The real work: ... (would be here) 1185 */ 1186 smb2sr_put_error(sr, sr->smb2_status); 1187 1188 /* 1189 * Credit adjustments (increase) 1190 */ 1191 if (sr->smb2_credit_request > sr->smb2_credit_charge) { 1192 smb2_credit_increase(sr); 1193 } 1194 1195 /* cmd_done: label */ 1196 1197 /* 1198 * Pad the reply to align(8) if there will be another. 1199 * This (interim) reply uses compounding. 1200 */ 1201 if (sr->smb2_next_command != 0) 1202 (void) smb_mbc_put_align(&sr->reply, 8); 1203 1204 /* 1205 * Record some statistics. Uses: 1206 * rxb = command.chain_offset - smb2_cmd_hdr; 1207 * txb = reply.chain_offset - smb2_reply_hdr; 1208 * which at this point represent the current cmd/reply. 1209 * 1210 * Note: We're doing smb_latency_add_sample() for all 1211 * remaining commands NOW, which means we won't include 1212 * the async part of their work in latency statistics. 1213 * That's intentional, as the async part of a command 1214 * would otherwise skew our latency statistics. 1215 */ 1216 smb2_record_stats(sr, sds, B_FALSE); 1217 1218 /* 1219 * If there's a next command, figure out where it starts, 1220 * and fill in the next header offset for the reply. 1221 * Note: We sanity checked smb2_next_command above. 1222 */ 1223 if (sr->smb2_next_command != 0) { 1224 sr->command.chain_offset = 1225 sr->smb2_cmd_hdr + sr->smb2_next_command; 1226 sr->smb2_next_reply = 1227 sr->reply.chain_offset - sr->smb2_reply_hdr; 1228 } else { 1229 ASSERT(sr->smb2_next_reply == 0); 1230 } 1231 1232 /* 1233 * Overwrite the (now final) SMB2 header for this response. 1234 */ 1235 (void) smb2_encode_header(sr, B_TRUE); 1236 1237 /* 1238 * Process whole compound before sending. 1239 */ 1240 if (sr->smb2_next_command != 0) 1241 goto cmd_start; 1242 smb2_send_reply(sr); 1243 1244 ASSERT(!disconnect); 1245 1246 cleanup: 1247 /* 1248 * Restore caller's command processing state. 1249 */ 1250 sr->smb2_cmd_hdr = saved_cmd_hdr; 1251 sr->command.chain_offset = saved_cmd_hdr; 1252 (void) smb2_decode_header(sr); 1253 sr->command.chain_offset = saved_com_offset; 1254 1255 sr->smb2_credit_response = saved_cred_resp; 1256 sr->smb2_hdr_flags = saved_hdr_flags; 1257 sr->smb2_status = NT_STATUS_SUCCESS; 1258 1259 /* 1260 * In here, the "disconnect" flag just means we had an 1261 * error decoding or encoding something. Rather than 1262 * actually disconnect here, let's assume whatever 1263 * problem we encountered will be seen by the caller 1264 * as they continue processing the compound, and just 1265 * restore everything and return an error. 1266 */ 1267 if (disconnect) { 1268 sr->smb2_async = B_FALSE; 1269 sr->smb2_reply_hdr = saved_reply_hdr; 1270 sr->reply.chain_offset = sr->smb2_reply_hdr; 1271 (void) smb2_encode_header(sr, B_FALSE); 1272 return (NT_STATUS_INVALID_PARAMETER); 1273 } 1274 1275 /* 1276 * The compound reply buffer we sent is now gone. 1277 * Setup a new reply buffer for the caller. 1278 */ 1279 sr->smb2_hdr_flags |= SMB2_FLAGS_ASYNC_COMMAND; 1280 sr->smb2_async_id = SMB2_ASYNCID(sr); 1281 sr->smb2_next_reply = 0; 1282 MBC_FLUSH(&sr->reply); 1283 ASSERT(sr->reply.max_bytes == sr->session->reply_max_bytes); 1284 ASSERT(sr->reply.chain_offset == 0); 1285 sr->smb2_reply_hdr = 0; 1286 (void) smb2_encode_header(sr, B_FALSE); 1287 1288 return (NT_STATUS_SUCCESS); 1289 } 1290 1291 int 1292 smb3_decode_tform_header(smb_request_t *sr) 1293 { 1294 uint16_t flags; 1295 int rc; 1296 uint32_t protocolid; 1297 1298 rc = smb_mbc_decodef( 1299 &sr->command, "l16c16cl..wq", 1300 &protocolid, /* l */ 1301 sr->smb2_sig, /* 16c */ 1302 sr->nonce, /* 16c */ 1303 &sr->msgsize, /* l */ 1304 /* reserved .. */ 1305 &flags, /* w */ 1306 &sr->smb3_tform_ssnid); /* q */ 1307 if (rc) 1308 return (rc); 1309 1310 ASSERT3U(protocolid, ==, SMB3_ENCRYPTED_MAGIC); 1311 1312 if (flags != 1) { 1313 #ifdef DEBUG 1314 cmn_err(CE_NOTE, "flags field not 1: %x", flags); 1315 #endif 1316 return (-1); 1317 } 1318 1319 /* 1320 * MsgSize is the amount of data the client tell us to decrypt. 1321 * Make sure this value is not too big and not too small. 1322 */ 1323 if (sr->msgsize < SMB2_HDR_SIZE || 1324 sr->msgsize > sr->session->cmd_max_bytes || 1325 sr->msgsize > sr->command.max_bytes - SMB3_TFORM_HDR_SIZE) 1326 return (-1); 1327 1328 return (rc); 1329 } 1330 1331 int 1332 smb3_encode_tform_header(smb_request_t *sr, struct mbuf_chain *mbc) 1333 { 1334 int rc; 1335 1336 /* Signature and Nonce are added in smb3_encrypt_sr */ 1337 rc = smb_mbc_encodef( 1338 mbc, "l32.lwwq", 1339 SMB3_ENCRYPTED_MAGIC, /* l */ 1340 /* signature(16), nonce(16) 32. */ 1341 sr->msgsize, /* l */ 1342 0, /* reserved w */ 1343 1, /* flags w */ 1344 sr->smb3_tform_ssnid); /* q */ 1345 1346 return (rc); 1347 } 1348 1349 int 1350 smb2_decode_header(smb_request_t *sr) 1351 { 1352 uint32_t pid, tid; 1353 uint16_t hdr_len; 1354 int rc; 1355 1356 rc = smb_mbc_decodef( 1357 &sr->command, "Nwww..wwllqllq16c", 1358 &hdr_len, /* w */ 1359 &sr->smb2_credit_charge, /* w */ 1360 &sr->smb2_chan_seq, /* w */ 1361 /* reserved .. */ 1362 &sr->smb2_cmd_code, /* w */ 1363 &sr->smb2_credit_request, /* w */ 1364 &sr->smb2_hdr_flags, /* l */ 1365 &sr->smb2_next_command, /* l */ 1366 &sr->smb2_messageid, /* q */ 1367 &pid, /* l */ 1368 &tid, /* l */ 1369 &sr->smb2_ssnid, /* q */ 1370 sr->smb2_sig); /* 16c */ 1371 if (rc) 1372 return (rc); 1373 1374 if (hdr_len != SMB2_HDR_SIZE) 1375 return (-1); 1376 1377 if (sr->smb2_hdr_flags & SMB2_FLAGS_ASYNC_COMMAND) { 1378 sr->smb2_async_id = pid | 1379 ((uint64_t)tid) << 32; 1380 sr->smb_pid = 0; 1381 sr->smb_tid = 0; 1382 } else { 1383 sr->smb2_async_id = 0; 1384 sr->smb_pid = pid; 1385 sr->smb_tid = (uint16_t)tid; /* XXX wide TIDs */ 1386 } 1387 1388 return (rc); 1389 } 1390 1391 int 1392 smb2_encode_header(smb_request_t *sr, boolean_t overwrite) 1393 { 1394 uint64_t pid_tid_aid; /* pid+tid, or async id */ 1395 int rc; 1396 1397 if (sr->smb2_hdr_flags & SMB2_FLAGS_ASYNC_COMMAND) { 1398 pid_tid_aid = sr->smb2_async_id; 1399 } else { 1400 pid_tid_aid = sr->smb_pid | 1401 ((uint64_t)sr->smb_tid) << 32; 1402 } 1403 1404 if (overwrite) { 1405 rc = smb_mbc_poke(&sr->reply, 1406 sr->smb2_reply_hdr, 1407 "Nwwlwwllqqq16c", 1408 SMB2_HDR_SIZE, /* w */ 1409 sr->smb2_credit_charge, /* w */ 1410 sr->smb2_status, /* l */ 1411 sr->smb2_cmd_code, /* w */ 1412 sr->smb2_credit_response, /* w */ 1413 sr->smb2_hdr_flags, /* l */ 1414 sr->smb2_next_reply, /* l */ 1415 sr->smb2_messageid, /* q */ 1416 pid_tid_aid, /* q */ 1417 sr->smb2_ssnid, /* q */ 1418 sr->smb2_sig); /* 16c */ 1419 } else { 1420 rc = smb_mbc_encodef(&sr->reply, 1421 "Nwwlwwllqqq16c", 1422 SMB2_HDR_SIZE, /* w */ 1423 sr->smb2_credit_charge, /* w */ 1424 sr->smb2_status, /* l */ 1425 sr->smb2_cmd_code, /* w */ 1426 sr->smb2_credit_response, /* w */ 1427 sr->smb2_hdr_flags, /* l */ 1428 sr->smb2_next_reply, /* l */ 1429 sr->smb2_messageid, /* q */ 1430 pid_tid_aid, /* q */ 1431 sr->smb2_ssnid, /* q */ 1432 sr->smb2_sig); /* 16c */ 1433 } 1434 1435 return (rc); 1436 } 1437 1438 void 1439 smb2_send_reply(smb_request_t *sr) 1440 { 1441 struct mbuf_chain enc_reply; 1442 smb_session_t *session = sr->session; 1443 void *tmpbuf; 1444 size_t buflen; 1445 struct mbuf_chain tmp; 1446 1447 /* 1448 * [MS-SMB2] 3.3.4.1.4 Encrypting the Message 1449 * 1450 * When the connection supports encryption and the dialect 1451 * is 3.x, encrypt if: 1452 * - The request was encrypted OR 1453 * - The cmd is not SESSION_SETUP or NEGOTIATE AND 1454 * -- Session.EncryptData is TRUE OR 1455 * -- The cmd is not TREE_CONNECT AND 1456 * --- Tree.EncryptData is TRUE 1457 * 1458 * This boils down to sr->tform_ssn != NULL, and the rest 1459 * is enforced when tform_ssn is set. 1460 */ 1461 1462 if ((session->capabilities & SMB2_CAP_ENCRYPTION) == 0 || 1463 sr->tform_ssn == NULL) { 1464 if (smb_session_send(sr->session, 0, &sr->reply) == 0) 1465 sr->reply.chain = 0; 1466 return; 1467 } 1468 1469 sr->msgsize = sr->reply.chain_offset; 1470 (void) MBC_SHADOW_CHAIN(&tmp, &sr->reply, 1471 0, sr->msgsize); 1472 1473 buflen = SMB3_TFORM_HDR_SIZE + sr->msgsize; 1474 1475 /* taken from smb_request_init_command_mbuf */ 1476 tmpbuf = kmem_alloc(buflen, KM_SLEEP); 1477 MBC_ATTACH_BUF(&enc_reply, tmpbuf, buflen); 1478 enc_reply.flags = 0; 1479 enc_reply.shadow_of = NULL; 1480 1481 if (smb3_encode_tform_header(sr, &enc_reply) != 0) { 1482 cmn_err(CE_WARN, "couldn't encode transform header"); 1483 goto errout; 1484 } 1485 if (smb3_encrypt_sr(sr, &tmp, &enc_reply) != 0) { 1486 cmn_err(CE_WARN, "smb3 encryption failed"); 1487 goto errout; 1488 } 1489 1490 if (smb_session_send(sr->session, 0, &enc_reply) == 0) 1491 enc_reply.chain = 0; 1492 return; 1493 1494 errout: 1495 kmem_free(tmpbuf, buflen); 1496 smb_session_disconnect(sr->session); 1497 } 1498 1499 /* 1500 * This wrapper function exists to help catch calls to smbsr_status() 1501 * (which is SMB1-specific) in common code. See smbsr_status(). 1502 * If the log message below is seen, put a dtrace probe on this 1503 * function with a stack() action to see who is calling the SMB1 1504 * "put error" from common code, and fix it. 1505 */ 1506 void 1507 smbsr_status_smb2(smb_request_t *sr, DWORD status) 1508 { 1509 const char *name; 1510 1511 if (sr->smb2_cmd_code < SMB2__NCMDS) 1512 name = smb2_disp_table[sr->smb2_cmd_code].sdt_name; 1513 else 1514 name = "<unknown>"; 1515 #ifdef DEBUG 1516 cmn_err(CE_NOTE, "smbsr_status called for %s", name); 1517 #endif 1518 1519 smb2sr_put_error_data(sr, status, NULL); 1520 } 1521 1522 void 1523 smb2sr_put_errno(struct smb_request *sr, int errnum) 1524 { 1525 uint32_t status = smb_errno2status(errnum); 1526 smb2sr_put_error_data(sr, status, NULL); 1527 } 1528 1529 void 1530 smb2sr_put_error(smb_request_t *sr, uint32_t status) 1531 { 1532 smb2sr_put_error_data(sr, status, NULL); 1533 } 1534 1535 /* 1536 * Build an SMB2 error response. [MS-SMB2] 2.2.2 1537 */ 1538 void 1539 smb2sr_put_error_data(smb_request_t *sr, uint32_t status, mbuf_chain_t *mbc) 1540 { 1541 DWORD len; 1542 1543 /* 1544 * The common dispatch code writes this when it 1545 * updates the SMB2 header before sending. 1546 */ 1547 sr->smb2_status = status; 1548 1549 /* Rewind to the end of the SMB header. */ 1550 sr->reply.chain_offset = sr->smb2_reply_hdr + SMB2_HDR_SIZE; 1551 1552 /* 1553 * NB: Must provide at least one byte of error data, 1554 * per [MS-SMB2] 2.2.2 1555 */ 1556 if (mbc != NULL && (len = MBC_LENGTH(mbc)) != 0) { 1557 (void) smb_mbc_encodef( 1558 &sr->reply, 1559 "wwlC", 1560 9, /* StructSize */ /* w */ 1561 0, /* reserved */ /* w */ 1562 len, /* l */ 1563 mbc); /* C */ 1564 } else { 1565 (void) smb_mbc_encodef( 1566 &sr->reply, 1567 "wwl.", 1568 9, /* StructSize */ /* w */ 1569 0, /* reserved */ /* w */ 1570 0); /* l. */ 1571 } 1572 } 1573 1574 /* 1575 * smb2sr_lookup_fid 1576 * 1577 * Setup sr->fid_ofile, either inherited from a related command, 1578 * or obtained via FID lookup. Similar inheritance logic as in 1579 * smb2sr_work. 1580 */ 1581 uint32_t 1582 smb2sr_lookup_fid(smb_request_t *sr, smb2fid_t *fid) 1583 { 1584 boolean_t related = sr->smb2_hdr_flags & 1585 SMB2_FLAGS_RELATED_OPERATIONS; 1586 1587 if (related) { 1588 if (sr->fid_ofile == NULL) 1589 return (NT_STATUS_INVALID_PARAMETER); 1590 sr->smb_fid = sr->fid_ofile->f_fid; 1591 return (0); 1592 } 1593 1594 /* 1595 * If we could be sure this is called only once per cmd, 1596 * we could simply ASSERT(sr->fid_ofile == NULL) here. 1597 * However, there are cases where it can be called again 1598 * handling the same command, so let's tolerate that. 1599 */ 1600 if (sr->fid_ofile == NULL) { 1601 sr->smb_fid = (uint16_t)fid->temporal; 1602 sr->fid_ofile = smb_ofile_lookup_by_fid(sr, sr->smb_fid); 1603 } 1604 if (sr->fid_ofile == NULL || 1605 sr->fid_ofile->f_persistid != fid->persistent) 1606 return (NT_STATUS_FILE_CLOSED); 1607 1608 return (0); 1609 } 1610 1611 /* 1612 * smb2_dispatch_stats_init 1613 * 1614 * Initializes dispatch statistics for SMB2. 1615 * See also smb_dispatch_stats_init(), which fills in 1616 * the lower part of the statistics array, from zero 1617 * through SMB_COM_NUM; 1618 */ 1619 void 1620 smb2_dispatch_stats_init(smb_server_t *sv) 1621 { 1622 smb_disp_stats_t *sds = sv->sv_disp_stats2; 1623 smb_kstat_req_t *ksr; 1624 int i; 1625 1626 ksr = ((smbsrv_kstats_t *)sv->sv_ksp->ks_data)->ks_reqs2; 1627 1628 for (i = 0; i < SMB2__NCMDS; i++, ksr++) { 1629 smb_latency_init(&sds[i].sdt_lat); 1630 (void) strlcpy(ksr->kr_name, smb2_disp_table[i].sdt_name, 1631 sizeof (ksr->kr_name)); 1632 } 1633 } 1634 1635 /* 1636 * smb2_dispatch_stats_fini 1637 * 1638 * Frees and destroyes the resources used for statistics. 1639 */ 1640 void 1641 smb2_dispatch_stats_fini(smb_server_t *sv) 1642 { 1643 smb_disp_stats_t *sds = sv->sv_disp_stats2; 1644 int i; 1645 1646 for (i = 0; i < SMB2__NCMDS; i++) 1647 smb_latency_destroy(&sds[i].sdt_lat); 1648 } 1649 1650 void 1651 smb2_dispatch_stats_update(smb_server_t *sv, 1652 smb_kstat_req_t *ksr, int first, int nreq) 1653 { 1654 smb_disp_stats_t *sds = sv->sv_disp_stats2; 1655 int i; 1656 int last; 1657 1658 last = first + nreq - 1; 1659 1660 if ((first < SMB2__NCMDS) && (last < SMB2__NCMDS)) { 1661 for (i = first; i <= last; i++, ksr++) { 1662 ksr->kr_rxb = sds[i].sdt_rxb; 1663 ksr->kr_txb = sds[i].sdt_txb; 1664 mutex_enter(&sds[i].sdt_lat.ly_mutex); 1665 ksr->kr_nreq = sds[i].sdt_lat.ly_a_nreq; 1666 ksr->kr_sum = sds[i].sdt_lat.ly_a_sum; 1667 ksr->kr_a_mean = sds[i].sdt_lat.ly_a_mean; 1668 ksr->kr_a_stddev = 1669 sds[i].sdt_lat.ly_a_stddev; 1670 ksr->kr_d_mean = sds[i].sdt_lat.ly_d_mean; 1671 ksr->kr_d_stddev = 1672 sds[i].sdt_lat.ly_d_stddev; 1673 sds[i].sdt_lat.ly_d_mean = 0; 1674 sds[i].sdt_lat.ly_d_nreq = 0; 1675 sds[i].sdt_lat.ly_d_stddev = 0; 1676 sds[i].sdt_lat.ly_d_sum = 0; 1677 mutex_exit(&sds[i].sdt_lat.ly_mutex); 1678 } 1679 } 1680 } 1681 1682 /* 1683 * Append new_sr to the postwork queue. sr->smb2_cmd_code encodes 1684 * the action that should be run by this sr. 1685 * 1686 * This queue is rarely used (and normally empty) so we're OK 1687 * using a simple "walk to tail and insert" here. 1688 */ 1689 void 1690 smb2sr_append_postwork(smb_request_t *top_sr, smb_request_t *new_sr) 1691 { 1692 smb_request_t *last_sr; 1693 1694 ASSERT(top_sr->session->dialect >= SMB_VERS_2_BASE); 1695 1696 last_sr = top_sr; 1697 while (last_sr->sr_postwork != NULL) 1698 last_sr = last_sr->sr_postwork; 1699 1700 last_sr->sr_postwork = new_sr; 1701 } 1702 1703 /* 1704 * Run any "post work" that was appended to the main SR while it 1705 * was running. This is called after the request has been sent 1706 * for the main SR, and used in cases i.e. the oplock code, where 1707 * we need to send something to the client only _after_ the main 1708 * sr request has gone out. 1709 */ 1710 static void 1711 smb2sr_run_postwork(smb_request_t *top_sr) 1712 { 1713 smb_request_t *post_sr; /* the one we're running */ 1714 smb_request_t *next_sr; 1715 1716 while ((post_sr = top_sr->sr_postwork) != NULL) { 1717 next_sr = post_sr->sr_postwork; 1718 top_sr->sr_postwork = next_sr; 1719 post_sr->sr_postwork = NULL; 1720 1721 post_sr->sr_worker = top_sr->sr_worker; 1722 post_sr->sr_state = SMB_REQ_STATE_ACTIVE; 1723 1724 switch (post_sr->smb2_cmd_code) { 1725 case SMB2_OPLOCK_BREAK: 1726 smb_oplock_send_brk(post_sr); 1727 break; 1728 default: 1729 ASSERT(0); 1730 } 1731 post_sr->sr_state = SMB_REQ_STATE_COMPLETED; 1732 smb_request_free(post_sr); 1733 } 1734 } 1735