1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright 2018 Nexenta Systems, Inc. All rights reserved. 25 * Copyright 2022 RackTop Systems, Inc. 26 */ 27 28 #include <smbsrv/smb_kproto.h> 29 #include <smbsrv/smb_fsops.h> 30 #include <smbsrv/smb_share.h> 31 #include <smbsrv/string.h> 32 #include <smbsrv/nmpipes.h> 33 #include <smbsrv/mailslot.h> 34 #include <smb/winioctl.h> 35 36 /* 37 * count of bytes in server response packet 38 * except parameters and data. Note that setup 39 * word count is zero. 40 */ 41 #define RESP_HEADER_LEN 24 42 43 /* 44 * We started by using common functions for transaction/transaction2 45 * and transaction_secondary/transaction2_secondary because they 46 * are respectively so similar. However, it turned out to be a bad 47 * idea because of quirky differences. Be sure if you modify one 48 * of these four functions to check and see if the modification should 49 * be applied to its peer. 50 */ 51 52 static int smb_trans_ready(smb_xa_t *); 53 static smb_sdrc_t smb_trans_dispatch(smb_request_t *, smb_xa_t *); 54 static smb_sdrc_t smb_trans2_dispatch(smb_request_t *, smb_xa_t *); 55 56 smb_sdrc_t 57 smb_pre_transaction(smb_request_t *sr) 58 { 59 DTRACE_SMB_START(op__Transaction, smb_request_t *, sr); 60 return (SDRC_SUCCESS); 61 } 62 63 void 64 smb_post_transaction(smb_request_t *sr) 65 { 66 DTRACE_SMB_DONE(op__Transaction, smb_request_t *, sr); 67 } 68 69 smb_sdrc_t 70 smb_com_transaction(smb_request_t *sr) 71 { 72 int rc; 73 unsigned char msrcnt, suwcnt; 74 uint16_t tpscnt, tdscnt, mprcnt, mdrcnt, flags; 75 uint16_t pscnt, psoff, dscnt, dsoff; 76 uint32_t timeo; 77 struct smb_xa *xa; 78 char *stn; 79 int ready; 80 81 if (!STYPE_ISIPC(sr->tid_tree->t_res_type)) { 82 smbsr_error(sr, 0, ERRDOS, ERRnoaccess); 83 return (SDRC_ERROR); 84 } 85 86 rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, 87 &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &msrcnt, &flags, 88 &timeo, &pscnt, &psoff, &dscnt, &dsoff, &suwcnt); 89 90 if (rc != 0) 91 return (SDRC_ERROR); 92 93 xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, 94 msrcnt, suwcnt); 95 if (xa == NULL) { 96 smbsr_error(sr, 0, ERRSRV, ERRnoroom); 97 return (SDRC_ERROR); 98 } 99 100 /* Should be some alignment stuff here in SMB? */ 101 if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) { 102 rc = smbsr_decode_data(sr, "%.U", sr, &stn); 103 } else { 104 rc = smbsr_decode_data(sr, "%s", sr, &stn); 105 } 106 if (rc != 0) { 107 smb_xa_rele(sr->session, xa); 108 return (SDRC_ERROR); 109 } 110 111 xa->xa_pipe_name = smb_mem_strdup(stn); 112 xa->smb_flags = flags; 113 xa->smb_timeout = timeo; 114 xa->req_disp_param = pscnt; 115 xa->req_disp_data = dscnt; 116 117 if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv, 118 sr->smb_vwv.chain_offset, suwcnt * 2)) { 119 smb_xa_rele(sr->session, xa); 120 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 121 return (SDRC_ERROR); 122 } 123 if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 124 smb_xa_rele(sr->session, xa); 125 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 126 return (SDRC_ERROR); 127 } 128 if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 129 smb_xa_rele(sr->session, xa); 130 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 131 return (SDRC_ERROR); 132 } 133 134 ready = smb_trans_ready(xa); 135 136 if (smb_xa_open(xa)) { 137 smb_xa_rele(sr->session, xa); 138 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 139 return (SDRC_ERROR); 140 } 141 sr->r_xa = xa; 142 143 if (!ready) { 144 rc = smbsr_encode_empty_result(sr); 145 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 146 } 147 148 if (!smb_xa_complete(xa)) { 149 smb_xa_close(xa); 150 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 151 return (SDRC_ERROR); 152 } 153 154 return (smb_trans_dispatch(sr, xa)); 155 } 156 157 smb_sdrc_t 158 smb_pre_transaction_secondary(smb_request_t *sr) 159 { 160 DTRACE_SMB_START(op__TransactionSecondary, smb_request_t *, sr); 161 return (SDRC_SUCCESS); 162 } 163 164 void 165 smb_post_transaction_secondary(smb_request_t *sr) 166 { 167 DTRACE_SMB_DONE(op__TransactionSecondary, smb_request_t *, sr); 168 } 169 170 smb_sdrc_t 171 smb_com_transaction_secondary(smb_request_t *sr) 172 { 173 uint16_t tpscnt, tdscnt, pscnt, psdisp; 174 uint16_t dscnt, dsoff, dsdisp, psoff; 175 smb_xa_t *xa; 176 int rc; 177 178 if ((xa = smbsr_lookup_xa(sr)) == 0) { 179 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 180 return (SDRC_ERROR); 181 } 182 183 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 184 if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { 185 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 186 ERRDOS, ERRnoaccess); 187 return (SDRC_ERROR); 188 } 189 } 190 191 if (xa->smb_com != SMB_COM_TRANSACTION) { 192 return (SDRC_DROP_VC); 193 } 194 195 rc = smbsr_decode_vwv(sr, SMB_TRANSSHDR_ED_FMT, &tpscnt, &tdscnt, 196 &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp); 197 198 if (rc != 0) 199 return (SDRC_ERROR); 200 201 mutex_enter(&xa->xa_mutex); 202 if (xa->smb_tpscnt > tpscnt) 203 xa->smb_tpscnt = tpscnt; 204 if (xa->smb_tdscnt > tdscnt) 205 xa->smb_tdscnt = tdscnt; 206 xa->req_disp_param = psdisp + pscnt; 207 xa->req_disp_data = dsdisp + dscnt; 208 209 /* 210 * The words psdisp, dsdisp, tell us what displacement 211 * into the entire trans parameter and data buffers 212 * where we should put the params & data that are 213 * delivered by this request. [MS-CIFS] says all the 214 * parameters and data SHOULD be sent sequentially, so 215 * so we can normally reassemble by simply appending. 216 * However, the components MAY come out of order, so 217 * check and set the current offset. This is rare, 218 * and we might like to know when this happens, so 219 * fire some static dtrace probes when it does. 220 */ 221 if (xa->req_param_mb.chain_offset != psdisp) { 222 DTRACE_PROBE2(trans_param_disp, 223 smb_xa_t *, xa, uint16_t, psdisp); 224 xa->req_param_mb.chain_offset = psdisp; 225 } 226 if (xa->req_data_mb.chain_offset != dsdisp) { 227 DTRACE_PROBE2(trans_data_disp, 228 smb_xa_t *, xa, uint16_t, dsdisp); 229 xa->req_data_mb.chain_offset = dsdisp; 230 } 231 232 if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 233 mutex_exit(&xa->xa_mutex); 234 smb_xa_close(xa); 235 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 236 return (SDRC_ERROR); 237 } 238 if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 239 mutex_exit(&xa->xa_mutex); 240 smb_xa_close(xa); 241 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 242 return (SDRC_ERROR); 243 } 244 mutex_exit(&xa->xa_mutex); 245 246 if (!smb_trans_ready(xa)) 247 return (SDRC_NO_REPLY); 248 249 if (!smb_xa_complete(xa)) 250 return (SDRC_NO_REPLY); 251 252 return (smb_trans_dispatch(sr, xa)); 253 } 254 255 smb_sdrc_t 256 smb_pre_ioctl(smb_request_t *sr) 257 { 258 DTRACE_SMB_START(op__Ioctl, smb_request_t *, sr); 259 return (SDRC_SUCCESS); 260 } 261 262 void 263 smb_post_ioctl(smb_request_t *sr) 264 { 265 DTRACE_SMB_DONE(op__Ioctl, smb_request_t *, sr); 266 } 267 268 smb_sdrc_t 269 smb_com_ioctl(smb_request_t *sr) 270 { 271 uint16_t fid, category, function, tpscnt, tdscnt, mprcnt; 272 uint16_t mdrcnt, pscnt, pdoff, dscnt, dsoff; 273 uint32_t timeout; 274 int rc; 275 276 rc = smbsr_decode_vwv(sr, "wwwwwwwl2.wwww", &fid, &category, &function, 277 &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &timeout, &pscnt, 278 &pdoff, &dscnt, &dsoff); 279 280 if (rc != 0) 281 return (SDRC_ERROR); 282 283 return (SDRC_NOT_IMPLEMENTED); 284 } 285 286 smb_sdrc_t 287 smb_pre_transaction2(smb_request_t *sr) 288 { 289 DTRACE_SMB_START(op__Transaction2, smb_request_t *, sr); 290 return (SDRC_SUCCESS); 291 } 292 293 void 294 smb_post_transaction2(smb_request_t *sr) 295 { 296 DTRACE_SMB_DONE(op__Transaction2, smb_request_t *, sr); 297 } 298 299 smb_sdrc_t 300 smb_com_transaction2(struct smb_request *sr) 301 { 302 unsigned char msrcnt, suwcnt; 303 uint16_t tpscnt, tdscnt, mprcnt, mdrcnt, flags; 304 uint16_t pscnt, psoff, dscnt, dsoff; 305 uint32_t timeo; 306 smb_xa_t *xa; 307 int ready; 308 int rc; 309 310 rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, &tpscnt, &tdscnt, 311 &mprcnt, &mdrcnt, &msrcnt, &flags, &timeo, &pscnt, &psoff, &dscnt, 312 &dsoff, &suwcnt); 313 314 if (rc != 0) 315 return (SDRC_ERROR); 316 317 xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, 318 msrcnt, suwcnt); 319 if (xa == 0) { 320 smbsr_error(sr, 0, ERRSRV, ERRnoroom); 321 return (SDRC_ERROR); 322 } 323 324 xa->smb_flags = flags; 325 xa->smb_timeout = timeo; 326 xa->req_disp_param = pscnt; 327 xa->req_disp_data = dscnt; 328 329 if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv, 330 sr->smb_vwv.chain_offset, suwcnt*2)) { 331 smb_xa_rele(sr->session, xa); 332 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 333 return (SDRC_ERROR); 334 } 335 if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 336 smb_xa_rele(sr->session, xa); 337 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 338 return (SDRC_ERROR); 339 } 340 if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 341 smb_xa_rele(sr->session, xa); 342 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 343 return (SDRC_ERROR); 344 } 345 346 ready = smb_trans_ready(xa); 347 348 if (smb_xa_open(xa)) { 349 smb_xa_rele(sr->session, xa); 350 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 351 return (SDRC_ERROR); 352 } 353 sr->r_xa = xa; 354 355 if (!ready) { 356 rc = smbsr_encode_empty_result(sr); 357 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 358 } 359 360 if (!smb_xa_complete(xa)) { 361 smb_xa_close(xa); 362 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 363 return (SDRC_ERROR); 364 } 365 366 return (smb_trans2_dispatch(sr, xa)); 367 } 368 369 smb_sdrc_t 370 smb_pre_transaction2_secondary(smb_request_t *sr) 371 { 372 DTRACE_SMB_START(op__Transaction2Secondary, smb_request_t *, sr); 373 return (SDRC_SUCCESS); 374 } 375 376 void 377 smb_post_transaction2_secondary(smb_request_t *sr) 378 { 379 DTRACE_SMB_DONE(op__Transaction2Secondary, smb_request_t *, sr); 380 } 381 382 smb_sdrc_t 383 smb_com_transaction2_secondary(smb_request_t *sr) 384 { 385 uint16_t tpscnt, tdscnt, fid; 386 uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp; 387 smb_xa_t *xa; 388 int rc; 389 390 if ((xa = smbsr_lookup_xa(sr)) == 0) { 391 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 392 return (SDRC_ERROR); 393 } 394 395 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 396 if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { 397 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 398 ERRDOS, ERRnoaccess); 399 return (SDRC_ERROR); 400 } 401 } 402 403 if (xa->smb_com != SMB_COM_TRANSACTION2) { 404 return (SDRC_DROP_VC); 405 } 406 407 rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt, 408 &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid); 409 410 if (rc != 0) 411 return (SDRC_ERROR); 412 413 mutex_enter(&xa->xa_mutex); 414 if (xa->smb_tpscnt > tpscnt) 415 xa->smb_tpscnt = tpscnt; 416 if (xa->smb_tdscnt > tdscnt) 417 xa->smb_tdscnt = tdscnt; 418 if (fid != 0xFFFF) 419 xa->xa_smb_fid = fid; 420 xa->req_disp_param = psdisp + pscnt; 421 xa->req_disp_data = dsdisp + dscnt; 422 423 /* 424 * See comment in smb_com_transaction_secondary 425 */ 426 if (xa->req_param_mb.chain_offset != psdisp) { 427 DTRACE_PROBE2(trans_param_disp, 428 smb_xa_t *, xa, uint16_t, psdisp); 429 xa->req_param_mb.chain_offset = psdisp; 430 } 431 if (xa->req_data_mb.chain_offset != dsdisp) { 432 DTRACE_PROBE2(trans_data_disp, 433 smb_xa_t *, xa, uint16_t, dsdisp); 434 xa->req_data_mb.chain_offset = dsdisp; 435 } 436 437 if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 438 mutex_exit(&xa->xa_mutex); 439 smb_xa_close(xa); 440 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 441 return (SDRC_ERROR); 442 } 443 if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 444 mutex_exit(&xa->xa_mutex); 445 smb_xa_close(xa); 446 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 447 return (SDRC_ERROR); 448 } 449 mutex_exit(&xa->xa_mutex); 450 451 if (!smb_trans_ready(xa)) 452 return (SDRC_NO_REPLY); 453 454 if (!smb_xa_complete(xa)) 455 return (SDRC_NO_REPLY); 456 457 return (smb_trans2_dispatch(sr, xa)); 458 } 459 460 static smb_sdrc_t 461 smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) 462 { 463 int rc; 464 int total_bytes, n_setup, n_param, n_data; 465 int param_off, param_pad, data_off, data_pad; 466 467 switch (xa->smb_func) { 468 case NT_TRANSACT_CREATE: 469 if ((rc = smb_pre_nt_transact_create(sr, xa)) == 0) 470 rc = smb_nt_transact_create(sr, xa); 471 smb_post_nt_transact_create(sr, xa); 472 break; 473 case NT_TRANSACT_NOTIFY_CHANGE: 474 rc = smb_nt_transact_notify_change(sr, xa); 475 break; 476 case NT_TRANSACT_QUERY_SECURITY_DESC: 477 rc = smb_nt_transact_query_security_info(sr, xa); 478 break; 479 case NT_TRANSACT_SET_SECURITY_DESC: 480 rc = smb_nt_transact_set_security_info(sr, xa); 481 break; 482 case NT_TRANSACT_IOCTL: 483 rc = smb_nt_transact_ioctl(sr, xa); 484 break; 485 case NT_TRANSACT_QUERY_QUOTA: 486 rc = smb_nt_transact_query_quota(sr, xa); 487 break; 488 case NT_TRANSACT_SET_QUOTA: 489 rc = smb_nt_transact_set_quota(sr, xa); 490 break; 491 case NT_TRANSACT_RENAME: 492 rc = smb_nt_transact_rename(sr, xa); 493 break; 494 495 default: 496 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); 497 return (SDRC_ERROR); 498 } 499 500 switch (rc) { 501 case SDRC_SUCCESS: 502 break; 503 504 case SDRC_DROP_VC: 505 case SDRC_NO_REPLY: 506 case SDRC_ERROR: 507 case SDRC_SR_KEPT: 508 return (rc); 509 510 case SDRC_NOT_IMPLEMENTED: 511 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); 512 return (SDRC_ERROR); 513 514 default: 515 break; 516 } 517 518 n_setup = MBC_LENGTH(&xa->rep_setup_mb); 519 n_param = MBC_LENGTH(&xa->rep_param_mb); 520 n_data = MBC_LENGTH(&xa->rep_data_mb); 521 522 if (xa->smb_msrcnt < n_setup || 523 xa->smb_mprcnt < n_param || 524 xa->smb_mdrcnt < n_data) { 525 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); 526 return (SDRC_ERROR); 527 } 528 529 /* neato, blast it over there */ 530 531 n_setup = (n_setup + 1) / 2; /* Conver to setup words */ 532 param_pad = 1; /* must be one */ 533 param_off = param_pad + 32 + 37 + (n_setup << 1) + 2; 534 data_pad = (4 - ((param_off + n_param) & 3)) % 4; /* Pad to 4 byte */ 535 data_off = param_off + n_param + data_pad; /* Param off from hdr */ 536 total_bytes = param_pad + n_param + data_pad + n_data; 537 538 rc = smbsr_encode_result(sr, 18+n_setup, total_bytes, 539 "b3.llllllllbCw#.C#.C", 540 18 + n_setup, /* wct */ 541 n_param, /* Total Parameter Bytes */ 542 n_data, /* Total Data Bytes */ 543 n_param, /* Total Parameter Bytes this buffer */ 544 param_off, /* Param offset from header start */ 545 0, /* Param displacement */ 546 n_data, /* Total Data Bytes this buffer */ 547 data_off, /* Data offset from header start */ 548 0, /* Data displacement */ 549 n_setup, /* suwcnt */ 550 &xa->rep_setup_mb, /* setup[] */ 551 total_bytes, /* Total data bytes */ 552 param_pad, 553 &xa->rep_param_mb, 554 data_pad, 555 &xa->rep_data_mb); 556 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 557 } 558 559 smb_sdrc_t 560 smb_pre_nt_transact(smb_request_t *sr) 561 { 562 DTRACE_SMB_START(op__NtTransact, smb_request_t *, sr); 563 return (SDRC_SUCCESS); 564 } 565 566 void 567 smb_post_nt_transact(smb_request_t *sr) 568 { 569 DTRACE_SMB_DONE(op__NtTransact, smb_request_t *, sr); 570 } 571 572 smb_sdrc_t 573 smb_com_nt_transact(struct smb_request *sr) 574 { 575 uint16_t Function; 576 unsigned char MaxSetupCount, SetupCount; 577 uint32_t TotalParameterCount, TotalDataCount; 578 uint32_t MaxParameterCount, MaxDataCount, pscnt; 579 uint32_t psoff, dscnt, dsoff; 580 smb_xa_t *xa; 581 int ready; 582 int rc; 583 584 rc = smbsr_decode_vwv(sr, SMB_NT_TRANSHDR_ED_FMT, &MaxSetupCount, 585 &TotalParameterCount, &TotalDataCount, &MaxParameterCount, 586 &MaxDataCount, &pscnt, &psoff, &dscnt, 587 &dsoff, &SetupCount, &Function); 588 589 if (rc != 0) 590 return (SDRC_ERROR); 591 592 xa = smb_xa_create(sr->session, sr, TotalParameterCount, TotalDataCount, 593 MaxParameterCount, MaxDataCount, MaxSetupCount, SetupCount); 594 if (xa == 0) { 595 smbsr_error(sr, 0, ERRSRV, ERRnoroom); 596 return (SDRC_ERROR); 597 } 598 599 xa->smb_flags = 0; 600 xa->smb_timeout = 0; 601 xa->smb_func = Function; 602 xa->req_disp_param = pscnt; 603 xa->req_disp_data = dscnt; 604 605 if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv, 606 sr->smb_vwv.chain_offset, SetupCount * 2)) { 607 smb_xa_rele(sr->session, xa); 608 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 609 return (SDRC_ERROR); 610 } 611 if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 612 smb_xa_rele(sr->session, xa); 613 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 614 return (SDRC_ERROR); 615 } 616 if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 617 smb_xa_rele(sr->session, xa); 618 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 619 return (SDRC_ERROR); 620 } 621 622 ready = smb_trans_ready(xa); 623 624 if (smb_xa_open(xa)) { 625 smb_xa_rele(sr->session, xa); 626 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 627 return (SDRC_ERROR); 628 } 629 sr->r_xa = xa; 630 631 if (!ready) { 632 rc = smbsr_encode_empty_result(sr); 633 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 634 } 635 636 if (!smb_xa_complete(xa)) { 637 smb_xa_close(xa); 638 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 639 return (SDRC_ERROR); 640 } 641 642 return (smb_nt_trans_dispatch(sr, xa)); 643 } 644 645 smb_sdrc_t 646 smb_pre_nt_transact_secondary(smb_request_t *sr) 647 { 648 DTRACE_SMB_START(op__NtTransactSecondary, smb_request_t *, sr); 649 return (SDRC_SUCCESS); 650 } 651 652 void 653 smb_post_nt_transact_secondary(smb_request_t *sr) 654 { 655 DTRACE_SMB_DONE(op__NtTransactSecondary, smb_request_t *, sr); 656 } 657 658 smb_sdrc_t 659 smb_com_nt_transact_secondary(struct smb_request *sr) 660 { 661 uint16_t tpscnt, tdscnt, fid; 662 uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp; 663 smb_xa_t *xa; 664 int rc; 665 666 if ((xa = smbsr_lookup_xa(sr)) == 0) { 667 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 668 return (SDRC_ERROR); 669 } 670 671 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 672 if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { 673 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 674 ERRDOS, ERRnoaccess); 675 return (SDRC_ERROR); 676 } 677 } 678 679 if (xa->smb_com != SMB_COM_TRANSACTION2) { 680 return (SDRC_DROP_VC); 681 } 682 683 rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt, 684 &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid); 685 686 if (rc != 0) 687 return (SDRC_ERROR); 688 689 mutex_enter(&xa->xa_mutex); 690 if (xa->smb_tpscnt > tpscnt) 691 xa->smb_tpscnt = tpscnt; 692 if (xa->smb_tdscnt > tdscnt) 693 xa->smb_tdscnt = tdscnt; 694 if (fid != 0xFFFF) 695 xa->xa_smb_fid = fid; 696 xa->req_disp_param = psdisp + pscnt; 697 xa->req_disp_data = dsdisp + dscnt; 698 699 /* 700 * See comment in smb_com_transaction_secondary 701 */ 702 if (xa->req_param_mb.chain_offset != psdisp) { 703 DTRACE_PROBE2(trans_param_disp, 704 smb_xa_t *, xa, uint16_t, psdisp); 705 xa->req_param_mb.chain_offset = psdisp; 706 } 707 if (xa->req_data_mb.chain_offset != dsdisp) { 708 DTRACE_PROBE2(trans_data_disp, 709 smb_xa_t *, xa, uint16_t, dsdisp); 710 xa->req_data_mb.chain_offset = dsdisp; 711 } 712 713 if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 714 mutex_exit(&xa->xa_mutex); 715 smb_xa_close(xa); 716 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 717 return (SDRC_ERROR); 718 } 719 if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 720 mutex_exit(&xa->xa_mutex); 721 smb_xa_close(xa); 722 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 723 return (SDRC_ERROR); 724 } 725 mutex_exit(&xa->xa_mutex); 726 727 if (!smb_trans_ready(xa)) 728 return (SDRC_NO_REPLY); 729 730 if (!smb_xa_complete(xa)) 731 return (SDRC_NO_REPLY); 732 733 return (smb_nt_trans_dispatch(sr, xa)); 734 } 735 736 static int 737 smb_trans_ready(smb_xa_t *xa) 738 { 739 int rc; 740 741 mutex_enter(&xa->xa_mutex); 742 rc = xa->req_disp_data >= xa->smb_tdscnt && 743 xa->req_disp_param >= xa->smb_tpscnt; 744 mutex_exit(&xa->xa_mutex); 745 746 return (rc); 747 } 748 749 static void 750 smb_encode_SHARE_INFO_1(struct mbuf_chain *output, struct mbuf_chain *text, 751 char *oem_name, uint16_t type, char *comment) 752 { 753 (void) smb_mbc_encodef(output, "13c.wl", oem_name, 754 type, MBC_LENGTH(text)); 755 756 (void) smb_mbc_encodef(text, "s", comment ? comment : ""); 757 } 758 759 static void 760 smb_encode_SHARE_INFO_2(struct mbuf_chain *output, struct mbuf_chain *text, 761 smb_request_t *sr, char *oem_name, uint16_t type, 762 char *comment, uint16_t access, char *path, char *password) 763 { 764 unsigned char pword[9]; 765 766 bzero(pword, sizeof (pword)); 767 (void) strncpy((char *)pword, password, sizeof (pword)); 768 smb_encode_SHARE_INFO_1(output, text, oem_name, type, comment); 769 (void) smb_mbc_encodef(output, "wwwl9c.", 770 access, 771 sr->sr_cfg->skc_maxconnections, 772 smb_server_get_session_count(sr->sr_server), 773 MBC_LENGTH(text), 774 pword); 775 (void) smb_mbc_encodef(text, "s", path); 776 } 777 778 int smb_trans_share_enum = 0; 779 780 /* 781 * This is a legacy interface, no longer supported. 782 * Clients now use MS-RPC for share enumeration. 783 * Does not implement access-based enumeration (ABE) 784 * so do not enable if you care about share list ABE. 785 */ 786 int 787 smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa) 788 { 789 uint16_t pid_hi, pid_lo; 790 791 /* 792 * Number of data bytes that will 793 * be sent in the current response 794 */ 795 uint16_t data_scnt; 796 797 /* 798 * Total number of data bytes that 799 * are sent till now. This is only 800 * used for calculating current data 801 * displacement 802 */ 803 uint16_t tot_data_scnt; 804 805 /* 806 * Number of parameter bytes should 807 * be sent for the current response. 808 * It is 8 for the 1st response and 809 * 0 for others 810 */ 811 uint16_t param_scnt; 812 813 /* number of setup and parameter bytes */ 814 uint16_t n_setup, n_param; 815 816 /* data and parameter displacement */ 817 uint16_t data_disp, param_disp; 818 819 /* parameter and data offset and pad */ 820 int param_off, param_pad, data_off, data_pad; 821 822 /* 823 * total bytes of parameters and data 824 * in the packet, plus the pad bytes. 825 */ 826 int tot_packet_bytes; 827 828 boolean_t first_resp; 829 830 char fmt[16]; 831 struct mbuf_chain reply; 832 833 uint16_t level; 834 uint16_t pkt_bufsize; 835 smb_enumshare_info_t esi; 836 char *sent_buf; 837 838 ASSERT(sr->uid_user); 839 840 if (smb_trans_share_enum == 0) 841 return (SDRC_NOT_IMPLEMENTED); 842 843 if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level, 844 &esi.es_bufsize) != 0) 845 return (SDRC_NOT_IMPLEMENTED); 846 847 if (level != 1) { 848 /* 849 * Only level 1 is valid for NetShareEnum 850 * None of the error codes in the spec are meaningful 851 * here. This error code is returned by Windows. 852 */ 853 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 854 ERROR_INVALID_LEVEL, 0, 0, 0); 855 return (SDRC_SUCCESS); 856 } 857 858 esi.es_buf = smb_srm_zalloc(sr, esi.es_bufsize); 859 esi.es_posix_uid = crgetuid(sr->uid_user->u_cred); 860 smb_kshare_enum(sr->sr_server, &esi); 861 862 /* client buffer size is not big enough to hold any shares */ 863 if (esi.es_nsent == 0) { 864 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 865 ERROR_MORE_DATA, 0, esi.es_nsent, esi.es_ntotal); 866 return (SDRC_SUCCESS); 867 } 868 869 /* 870 * Initialize the reply mbuf chain. Note that we re-initialize 871 * this on each pass through the loop below. 872 */ 873 MBC_SETUP(&reply, smb_maxbufsize); 874 875 /* 876 * The rep_setup_mb is already initialized in smb_trans_dispatch(). 877 * Calling MBC_INIT() will initialized the structure and so the 878 * pointer to the mbuf chains will be lost. Therefore, we need 879 * to free the resources before calling MBC_INIT() again. 880 */ 881 n_setup = 0; /* Setup count for NetShareEnum SMB is 0 */ 882 MBC_FLUSH(&xa->rep_setup_mb); 883 884 n_param = 8; 885 pkt_bufsize = sr->session->smb_msg_size - 886 (SMB_HEADER_ED_LEN + RESP_HEADER_LEN + n_param); 887 888 tot_data_scnt = 0; 889 sent_buf = esi.es_buf; 890 first_resp = B_TRUE; 891 892 while (tot_data_scnt < esi.es_datasize) { 893 data_scnt = esi.es_datasize - tot_data_scnt; 894 if (data_scnt > pkt_bufsize) 895 data_scnt = pkt_bufsize; 896 MBC_FLUSH(&xa->rep_data_mb); 897 898 (void) sprintf(fmt, "%dc", data_scnt); 899 (void) smb_mbc_encodef(&xa->rep_data_mb, fmt, sent_buf); 900 901 sent_buf += data_scnt; 902 tot_data_scnt += data_scnt; 903 904 /* Only the 1st response packet contains parameters */ 905 param_scnt = (first_resp) ? n_param : 0; 906 param_pad = 1; /* always one */ 907 param_off = SMB_HEADER_ED_LEN + RESP_HEADER_LEN; 908 param_disp = (first_resp) ? 0 : n_param; 909 910 MBC_FLUSH(&xa->rep_param_mb); 911 912 if (first_resp) { 913 first_resp = B_FALSE; 914 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 915 (esi.es_ntotal > esi.es_nsent) 916 ? ERROR_MORE_DATA : 0, 917 0, esi.es_nsent, esi.es_ntotal); 918 } 919 920 data_pad = (param_off + n_param) & 1; /* Pad to short */ 921 922 /* data off from hdr start */ 923 data_off = param_off + param_scnt + data_pad; 924 data_disp = tot_data_scnt - data_scnt; 925 tot_packet_bytes = param_pad + param_scnt + data_pad + 926 data_scnt; 927 928 pid_hi = sr->smb_pid >> 16; 929 pid_lo = (uint16_t)sr->smb_pid; 930 931 MBC_FLUSH(&reply); 932 (void) smb_mbc_encodef(&reply, SMB_HEADER_ED_FMT, 933 sr->first_smb_com, 934 sr->smb_rcls, 935 sr->smb_reh, 936 sr->smb_err, 937 sr->smb_flg | SMB_FLAGS_REPLY, 938 sr->smb_flg2, 939 pid_hi, 940 sr->smb_sig, 941 sr->smb_tid, 942 pid_lo, 943 sr->smb_uid, 944 sr->smb_mid); 945 946 (void) smb_mbc_encodef(&reply, 947 "bww2.wwwwwwb.Cw#.C#.C", 948 10 + n_setup, /* wct */ 949 n_param, /* Total Parameter Bytes */ 950 esi.es_datasize, /* Total Data Bytes */ 951 param_scnt, /* Total Parameter Bytes this buffer */ 952 param_off, /* Param offset from header start */ 953 param_disp, /* Param displacement */ 954 data_scnt, /* Total Data Bytes this buffer */ 955 data_off, /* Data offset from header start */ 956 data_disp, /* Data displacement */ 957 n_setup, /* suwcnt */ 958 &xa->rep_setup_mb, /* setup[] */ 959 tot_packet_bytes, /* Total data bytes */ 960 param_pad, 961 &xa->rep_param_mb, 962 data_pad, 963 &xa->rep_data_mb); 964 965 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) 966 smb_sign_reply(sr, &reply); 967 968 (void) smb_session_send(sr->session, 0, &reply); 969 970 } 971 972 m_freem(reply.chain); 973 974 return (SDRC_NO_REPLY); 975 } 976 977 int smb_trans_share_getinfo = 0; 978 979 /* 980 * This is a legacy interface, no longer supported. 981 * Clients now use MS-RPC to get share information. 982 * Does not implement access-based enumeration (ABE) 983 * so do not enable if you care about share list ABE. 984 */ 985 int 986 smb_trans_net_share_getinfo(smb_request_t *sr, struct smb_xa *xa) 987 { 988 uint16_t level, max_bytes, access; 989 struct mbuf_chain str_mb; 990 char *share; 991 char *password; 992 smb_kshare_t *si; 993 994 if (smb_trans_share_getinfo == 0) 995 return (SDRC_NOT_IMPLEMENTED); 996 997 if (smb_mbc_decodef(&xa->req_param_mb, "%sww", sr, 998 &share, &level, &max_bytes) != 0) 999 return (SDRC_NOT_IMPLEMENTED); 1000 1001 si = smb_kshare_lookup(sr->sr_server, share); 1002 if ((si == NULL) || (si->shr_oemname == NULL)) { 1003 (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 1004 NERR_NetNameNotFound, 0, 0); 1005 if (si) 1006 smb_kshare_release(sr->sr_server, si); 1007 return (SDRC_SUCCESS); 1008 } 1009 1010 access = SHARE_ACCESS_ALL; 1011 password = ""; 1012 1013 MBC_INIT(&str_mb, max_bytes); 1014 1015 switch (level) { 1016 case 0 : 1017 (void) smb_mbc_encodef(&xa->rep_data_mb, "13c", 1018 si->shr_oemname); 1019 break; 1020 1021 case 1 : 1022 smb_encode_SHARE_INFO_1(&xa->rep_data_mb, &str_mb, 1023 si->shr_oemname, si->shr_type, si->shr_cmnt); 1024 break; 1025 1026 case 2 : 1027 smb_encode_SHARE_INFO_2(&xa->rep_data_mb, &str_mb, sr, 1028 si->shr_oemname, si->shr_type, si->shr_cmnt, access, 1029 si->shr_path, password); 1030 break; 1031 1032 default: 1033 smb_kshare_release(sr->sr_server, si); 1034 (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 1035 ERROR_INVALID_LEVEL, 0, 0); 1036 m_freem(str_mb.chain); 1037 return (SDRC_NOT_IMPLEMENTED); 1038 } 1039 1040 smb_kshare_release(sr->sr_server, si); 1041 (void) smb_mbc_encodef(&xa->rep_param_mb, "www", NERR_Success, 1042 -MBC_LENGTH(&xa->rep_data_mb), 1043 MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb)); 1044 (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb); 1045 m_freem(str_mb.chain); 1046 return (SDRC_SUCCESS); 1047 } 1048 1049 int 1050 smb_trans_net_workstation_getinfo(struct smb_request *sr, struct smb_xa *xa) 1051 { 1052 uint16_t level, max_bytes; 1053 struct mbuf_chain str_mb; 1054 char *domain; 1055 char *hostname; 1056 1057 if ((smb_mbc_decodef(&xa->req_param_mb, "ww", 1058 &level, &max_bytes) != 0) || 1059 (level != 10)) { 1060 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 1061 NERR_BadTransactConfig, 0, 0, 0); 1062 return (SDRC_SUCCESS); 1063 } 1064 1065 domain = sr->sr_cfg->skc_nbdomain; 1066 hostname = sr->sr_cfg->skc_hostname; 1067 1068 MBC_INIT(&str_mb, max_bytes); 1069 1070 (void) smb_mbc_encodef(&str_mb, "."); /* Prevent NULL pointers */ 1071 1072 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 1073 (void) smb_mbc_encodef(&str_mb, "s", hostname); 1074 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 1075 (void) smb_mbc_encodef(&str_mb, "s", "nobody"); 1076 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 1077 (void) smb_mbc_encodef(&str_mb, "s", domain); 1078 (void) smb_mbc_encodef(&xa->rep_data_mb, "bbl", 1079 (uint8_t)sr->sr_cfg->skc_version.sv_major, 1080 (uint8_t)sr->sr_cfg->skc_version.sv_minor, 1081 MBC_LENGTH(&str_mb)); 1082 (void) smb_mbc_encodef(&str_mb, "s", domain); 1083 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 1084 (void) smb_mbc_encodef(&str_mb, "s", domain); 1085 1086 (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 0, 1087 -MBC_LENGTH(&xa->rep_data_mb), 1088 MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb)); 1089 (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb); 1090 m_freem(str_mb.chain); 1091 return (SDRC_SUCCESS); 1092 } 1093 1094 int 1095 smb_trans_net_user_getinfo(struct smb_request *sr, struct smb_xa *xa) 1096 { 1097 uint16_t level, max_bytes; 1098 unsigned char *user; 1099 int rc; 1100 1101 rc = smb_mbc_decodef(&xa->req_param_mb, "%sww", sr, 1102 &user, 1103 &level, 1104 &max_bytes); 1105 1106 if (rc != 0) 1107 return (SDRC_NOT_IMPLEMENTED); 1108 1109 (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 1110 NERR_UserNotFound, 0, 0); 1111 return (SDRC_SUCCESS); 1112 } 1113 1114 smb_sdrc_t 1115 smb_trans_net_server_getinfo(struct smb_request *sr, struct smb_xa *xa) 1116 { 1117 uint16_t level, buf_size; 1118 uint16_t avail_data, max_data; 1119 char server_name[16]; 1120 struct mbuf_chain str_mb; 1121 1122 if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level, &buf_size) != 0) 1123 return (SDRC_ERROR); 1124 1125 max_data = MBC_MAXBYTES(&xa->rep_data_mb); 1126 1127 MBC_INIT(&str_mb, buf_size); 1128 1129 bzero(server_name, sizeof (server_name)); 1130 (void) strncpy(server_name, sr->sr_cfg->skc_hostname, 1131 sizeof (server_name)); 1132 1133 /* valid levels are 0 and 1 */ 1134 switch (level) { 1135 case 0: 1136 (void) smb_mbc_encodef(&xa->rep_data_mb, "16c", server_name); 1137 break; 1138 1139 case 1: 1140 (void) smb_mbc_encodef(&str_mb, "s", 1141 sr->sr_cfg->skc_system_comment); 1142 (void) smb_mbc_encodef(&xa->rep_data_mb, "16cbbll", server_name, 1143 (uint8_t)sr->sr_cfg->skc_version.sv_major, 1144 (uint8_t)sr->sr_cfg->skc_version.sv_minor, 1145 MY_SERVER_TYPE, max_data - MBC_LENGTH(&str_mb)); 1146 break; 1147 1148 default: 1149 (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 1150 ERROR_INVALID_LEVEL, 0, 0); 1151 m_freem(str_mb.chain); 1152 return (SDRC_SUCCESS); 1153 } 1154 1155 avail_data = MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb); 1156 (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 1157 NERR_Success, max_data - avail_data, avail_data); 1158 (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb); 1159 m_freem(str_mb.chain); 1160 return (SDRC_SUCCESS); 1161 } 1162 1163 /* 1164 * 6.4 The NetServerEnum2 RAP Service 1165 * 1166 * The NetServerEnum2 RAP service lists all computers of the specified type 1167 * or types that are visible in the specified domains. It may also 1168 * enumerate domains. 1169 * 1170 * The following definition uses the notation and terminology defined in 1171 * the CIFS Remote Administration Protocol specification, which is required 1172 * in order to make it well-defined. The definition is: 1173 * 1174 * uint16_t NetServerEnum2 ( 1175 * uint16_t sLevel, 1176 * RCVBUF pbBuffer, 1177 * RCVBUFLEN cbBuffer, 1178 * ENTCOUNT pcEntriesRead, 1179 * uint16_t *pcTotalAvail, 1180 * uint32_t fServerType, 1181 * char *pszDomain, 1182 * ); 1183 * 1184 * where: 1185 * 1186 * sLevel specifies the level of detail (0 or 1) requested. 1187 * 1188 * pbBuffer points to the buffer to receive the returned data. If the 1189 * function is successful, the buffer contains a sequence of 1190 * server_info_x structures, where x is 0 or 1, depending on the 1191 * level of detail requested. 1192 * 1193 * cbBuffer specifies the size, in bytes, of the buffer pointed to by 1194 * the pbBuffer parameter. 1195 * 1196 * pcEntriesRead points to a 16 bit variable that receives a count of 1197 * the number of servers enumerated in the buffer. This count is 1198 * valid only if NetServerEnum2 returns the NERR_Success or 1199 * ERROR_MORE_DATA values. 1200 * 1201 * pcTotal Avail points to a 16 bit variable that receives a count of 1202 * the total number of available entries. This count is valid only if 1203 * NetServerEnum2 returns the NERR_Success or ERROR_MORE_DATA values. 1204 * 1205 * fServerType specifies the type or types of computers to enumerate. 1206 * Computers that match at least one of the specified types are 1207 * returned in the buffer. Possible values are defined in the request 1208 * parameters section. 1209 * 1210 * pszDomain points to a null-terminated string that contains the 1211 * name of the workgroup in which to enumerate computers of the 1212 * specified type or types. If the pszDomain parameter is a null 1213 * string or a null pointer, servers are enumerated for the current 1214 * domain of the computer. 1215 * 1216 * 6.4.1 Transaction Request Parameters section 1217 * 1218 * The Transaction request parameters section in this instance contains: 1219 * . The 16 bit function number for NetServerEnum2 which is 104. 1220 * . The parameter descriptor string which is "WrLehDz". 1221 * . The data descriptor string for the (returned) data which is "B16" for 1222 * level detail 0 or "B16BBDz" for level detail 1. 1223 * . The actual parameters as described by the parameter descriptor 1224 * string. 1225 * 1226 * The parameters are: 1227 * . A 16 bit integer with a value of 0 or 1 (corresponding to the "W" in 1228 * the parameter descriptor string. This represents the level of detail 1229 * the server is expected to return 1230 * . A 16 bit integer that contains the size of the receive buffer. 1231 * . A 32 bit integer that represents the type of servers the function 1232 * should enumerate. The possible values may be any of the following or 1233 * a combination of the following: 1234 * 1235 * SV_TYPE_WORKSTATION 0x00000001 All workstations 1236 * SV_TYPE_SERVER 0x00000002 All servers 1237 * SV_TYPE_SQLSERVER 0x00000004 Any server running with SQL 1238 * server 1239 * SV_TYPE_DOMAIN_CTRL 0x00000008 Primary domain controller 1240 * SV_TYPE_DOMAIN_BAKCTRL 0x00000010 Backup domain controller 1241 * SV_TYPE_TIME_SOURCE 0x00000020 Server running the timesource 1242 * service 1243 * SV_TYPE_AFP 0x00000040 Apple File Protocol servers 1244 * SV_TYPE_NOVELL 0x00000080 Novell servers 1245 * SV_TYPE_DOMAIN_MEMBER 0x00000100 Domain Member 1246 * SV_TYPE_PRINTQ_SERVER 0x00000200 Server sharing print queue 1247 * SV_TYPE_DIALIN_SERVER 0x00000400 Server running dialin service. 1248 * SV_TYPE_XENIX_SERVER 0x00000800 Xenix server 1249 * SV_TYPE_NT 0x00001000 NT server 1250 * SV_TYPE_WFW 0x00002000 Server running Windows for 1251 * Workgroups 1252 * SV_TYPE_SERVER_NT 0x00008000 Windows NT non DC server 1253 * SV_TYPE_POTENTIAL_BROWSER 0x00010000 Server that can run the browser 1254 * service 1255 * SV_TYPE_BACKUP_BROWSER 0x00020000 Backup browser server 1256 * SV_TYPE_MASTER_BROWSER 0x00040000 Master browser server 1257 * SV_TYPE_DOMAIN_MASTER 0x00080000 Domain Master Browser server 1258 * SV_TYPE_LOCAL_LIST_ONLY 0x40000000 Enumerate only entries marked 1259 * "local" 1260 * SV_TYPE_DOMAIN_ENUM 0x80000000 Enumerate Domains. The pszDomain 1261 * parameter must be NULL. 1262 * 1263 * . A null terminated ASCII string representing the pszDomain parameter 1264 * described above 1265 * 1266 * 6.4.2 Transaction Request Data section 1267 * 1268 * There is no data or auxiliary data to send as part of the request. 1269 * 1270 * 6.4.3 Transaction Response Parameters section 1271 * 1272 * The transaction response parameters section consists of: 1273 * . A 16 bit word indicating the return status. The possible values are: 1274 * 1275 * Code Value Description 1276 * NERR_Success 0 No errors encountered 1277 * ERROR_MORE_DATA 234 Additional data is available 1278 * NERR_ServerNotStarted 2114 The RAP service on the remote computer 1279 * is not running 1280 * NERR_BadTransactConfig 2141 The server is not configured for 1281 * transactions, IPC$ is not shared 1282 * 1283 * . A 16 bit "converter" word. 1284 * . A 16 bit number representing the number of entries returned. 1285 * . A 16 bit number representing the total number of available entries. 1286 * If the supplied buffer is large enough, this will equal the number of 1287 * entries returned. 1288 * 1289 * 6.4.4 Transaction Response Data section 1290 * 1291 * The return data section consists of a number of SERVER_INFO_1 structures. 1292 * The number of such structures present is determined by the third entry 1293 * (described above) in the return parameters section. 1294 * 1295 * At level detail 0, the Transaction response data section contains a 1296 * number of SERVER_INFO_0 data structure. The number of such structures is 1297 * equal to the 16 bit number returned by the server in the third parameter 1298 * in the Transaction response parameter section. The SERVER_INFO_0 data 1299 * structure is defined as: 1300 * 1301 * struct SERVER_INFO_0 { 1302 * char sv0_name[16]; 1303 * }; 1304 * 1305 * where: 1306 * 1307 * sv0_name is a null-terminated string that specifies the name of a 1308 * computer or domain . 1309 * 1310 * At level detail 1, the Transaction response data section contains a 1311 * number of SERVER_INFO_1 data structure. The number of such structures is 1312 * equal to the 16 bit number returned by the server in the third parameter 1313 * in the Transaction response parameter section. The SERVER_INFO_1 data 1314 * structure is defined as: 1315 * 1316 * struct SERVER_INFO_1 { 1317 * char sv1_name[16]; 1318 * char sv1_version_major; 1319 * char sv1_version_minor; 1320 * uint32_t sv1_type; 1321 * char *sv1_comment_or_master_browser; 1322 * }; 1323 * 1324 * sv1_name contains a null-terminated string that specifies the name 1325 * of a computer, or a domain name if SV_TYPE_DOMAIN_ENUM is set in 1326 * sv1_type. 1327 * 1328 * sv1_version_major whatever was specified in the HostAnnouncement 1329 * or DomainAnnouncement frame with which the entry was registered. 1330 * 1331 * sv1_version_minor whatever was specified in the HostAnnouncement 1332 * or DomainAnnouncement frame with which the entry was registered. 1333 * 1334 * sv1_type specifies the type of software the computer is running. 1335 * The member can be one or a combination of the values defined above 1336 * in the Transaction request parameters section for fServerType. 1337 * 1338 * 1339 * sv1_comment_or_master_browser points to a null-terminated string. If 1340 * the sv1_type indicates that the entry is for a domain, this 1341 * specifies the name of server running the domain master browser; 1342 * otherwise, it specifies a comment describing the server. The comment 1343 * can be a null string or the pointer may be a null pointer. 1344 * 1345 * In case there are multiple SERVER_INFO_1 data structures to 1346 * return, the server may put all these fixed length structures in 1347 * the return buffer, leave some space and then put all the variable 1348 * length data (the actual value of the sv1_comment strings) at the 1349 * end of the buffer. 1350 * 1351 * There is no auxiliary data to receive. 1352 */ 1353 1354 int 1355 smb_trans_net_server_enum2(struct smb_request *sr, struct smb_xa *xa) 1356 { 1357 uint16_t opcode, level, max_bytes; 1358 uint32_t server_type; 1359 unsigned char *domain; 1360 struct mbuf_chain str_mb; 1361 char *hostname, *s; 1362 smb_kmod_cfg_t *si; 1363 1364 if (smb_mbc_decodef(&xa->req_param_mb, 1365 "%wsswwls", sr, &opcode, &s, &s, 1366 &level, &max_bytes, &server_type, &domain) != 0) 1367 return (SDRC_NOT_IMPLEMENTED); 1368 1369 si = sr->sr_cfg; 1370 1371 if (smb_strcasecmp(si->skc_nbdomain, (char *)domain, 0) != 0) { 1372 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0); 1373 return (SDRC_SUCCESS); 1374 } 1375 1376 if ((server_type & MY_SERVER_TYPE) == 0) { 1377 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0); 1378 return (SDRC_SUCCESS); 1379 } 1380 1381 MBC_INIT(&str_mb, max_bytes); 1382 1383 hostname = si->skc_hostname; 1384 1385 (void) smb_mbc_encodef(&xa->rep_data_mb, "16c", hostname); 1386 if (level == 1) { 1387 (void) smb_mbc_encodef(&xa->rep_data_mb, "bbll", 1388 (uint8_t)sr->sr_cfg->skc_version.sv_major, 1389 (uint8_t)sr->sr_cfg->skc_version.sv_minor, 1390 MY_SERVER_TYPE, MBC_LENGTH(&str_mb)); 1391 (void) smb_mbc_encodef(&str_mb, "s", si->skc_system_comment); 1392 } 1393 1394 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 1395 -MBC_LENGTH(&xa->rep_data_mb), 1, 1); 1396 (void) smb_mbc_encodef(&xa->rep_data_mb, "m", str_mb.chain); 1397 return (SDRC_SUCCESS); 1398 } 1399 1400 static boolean_t 1401 is_supported_mailslot(const char *mailslot) 1402 { 1403 static char *mailslots[] = { 1404 PIPE_LANMAN, 1405 MAILSLOT_LANMAN, 1406 MAILSLOT_BROWSE, 1407 MAILSLOT_MSBROWSE 1408 }; 1409 1410 int i; 1411 1412 for (i = 0; i < sizeof (mailslots)/sizeof (mailslots[0]); ++i) 1413 if (smb_strcasecmp(mailslot, mailslots[i], 0) == 0) 1414 return (B_TRUE); 1415 1416 return (B_FALSE); 1417 } 1418 1419 /* 1420 * smb_trans_nmpipe 1421 * 1422 * This is used for RPC bind and request transactions. 1423 * 1424 * If the data available from the pipe is larger than the maximum 1425 * data size requested by the client, return as much as requested. 1426 * The residual data remains in the pipe until the client comes back 1427 * with a read request or closes the pipe. 1428 * 1429 * When we read less than what's available, we MUST return the 1430 * status NT_STATUS_BUFFER_OVERFLOW (or ERRDOS/ERROR_MORE_DATA) 1431 */ 1432 static smb_sdrc_t 1433 smb_trans_nmpipe(smb_request_t *sr, smb_xa_t *xa) 1434 { 1435 smb_fsctl_t fsctl; 1436 uint32_t status; 1437 1438 smbsr_lookup_file(sr); 1439 if (sr->fid_ofile == NULL) { 1440 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 1441 ERRDOS, ERRbadfid); 1442 return (SDRC_ERROR); 1443 } 1444 1445 /* 1446 * A little confusing perhaps, but the fsctl "input" is what we 1447 * write to the pipe (from the transaction "send" data), and the 1448 * fsctl "output" is what we read from the pipe (and becomes the 1449 * transaction receive data). 1450 */ 1451 fsctl.CtlCode = FSCTL_PIPE_TRANSCEIVE; 1452 fsctl.InputCount = xa->smb_tdscnt; /* write count */ 1453 fsctl.OutputCount = 0; /* minimum to read from the pipe */ 1454 fsctl.MaxOutputResp = xa->smb_mdrcnt; /* max to read */ 1455 fsctl.in_mbc = &xa->req_data_mb; /* write from here */ 1456 fsctl.out_mbc = &xa->rep_data_mb; /* read into here */ 1457 1458 status = smb_opipe_transceive(sr, &fsctl); 1459 if (status) { 1460 smbsr_status(sr, status, 0, 0); 1461 if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR) 1462 return (SDRC_ERROR); 1463 /* Warnings like NT_STATUS_BUFFER_OVERFLOW are OK */ 1464 } 1465 1466 return (SDRC_SUCCESS); 1467 } 1468 1469 static smb_sdrc_t 1470 smb_trans_dispatch(smb_request_t *sr, smb_xa_t *xa) 1471 { 1472 int rc, pos; 1473 int total_bytes, n_setup, n_param, n_data; 1474 int param_off, param_pad, data_off, data_pad; 1475 uint16_t opcode; 1476 uint16_t devstate; 1477 char *req_fmt; 1478 char *rep_fmt; 1479 1480 if (xa->smb_suwcnt > 0) { 1481 rc = smb_mbc_decodef(&xa->req_setup_mb, "ww", &opcode, 1482 &sr->smb_fid); 1483 if (rc != 0) 1484 goto trans_err_not_supported; 1485 switch (opcode) { 1486 case TRANS_SET_NMPIPE_STATE: 1487 if ((rc = smb_mbc_decodef(&xa->req_param_mb, "w", 1488 &devstate)) != 0) 1489 goto trans_err_not_supported; 1490 1491 rc = SDRC_SUCCESS; 1492 break; 1493 1494 case TRANS_TRANSACT_NMPIPE: 1495 rc = smb_trans_nmpipe(sr, xa); 1496 break; 1497 1498 case TRANS_WAIT_NMPIPE: 1499 delay(SEC_TO_TICK(1)); 1500 rc = SDRC_SUCCESS; 1501 break; 1502 1503 default: 1504 goto trans_err_not_supported; 1505 } 1506 } else { 1507 if (!is_supported_mailslot(xa->xa_pipe_name)) 1508 goto trans_err_not_supported; 1509 1510 if ((rc = smb_mbc_decodef(&xa->req_param_mb, "%wss", sr, 1511 &opcode, &req_fmt, &rep_fmt)) != 0) 1512 goto trans_err_not_supported; 1513 1514 switch (opcode) { 1515 case API_WshareEnum: 1516 rc = smb_trans_net_share_enum(sr, xa); 1517 break; 1518 1519 case API_WshareGetInfo: 1520 rc = smb_trans_net_share_getinfo(sr, xa); 1521 break; 1522 1523 case API_WserverGetInfo: 1524 rc = smb_trans_net_server_getinfo(sr, xa); 1525 break; 1526 1527 case API_WUserGetInfo: 1528 rc = smb_trans_net_user_getinfo(sr, xa); 1529 break; 1530 1531 case API_WWkstaGetInfo: 1532 rc = smb_trans_net_workstation_getinfo(sr, xa); 1533 break; 1534 1535 case API_NetServerEnum2: 1536 rc = smb_trans_net_server_enum2(sr, xa); 1537 break; 1538 1539 default: 1540 goto trans_err_not_supported; 1541 } 1542 } 1543 1544 switch (rc) { 1545 case SDRC_SUCCESS: 1546 break; 1547 1548 case SDRC_DROP_VC: 1549 case SDRC_NO_REPLY: 1550 case SDRC_ERROR: 1551 return (rc); 1552 1553 case SDRC_NOT_IMPLEMENTED: 1554 goto trans_err_not_supported; 1555 1556 default: 1557 break; 1558 } 1559 1560 n_setup = MBC_LENGTH(&xa->rep_setup_mb); 1561 n_param = MBC_LENGTH(&xa->rep_param_mb); 1562 n_data = MBC_LENGTH(&xa->rep_data_mb); 1563 1564 if (xa->smb_msrcnt < n_setup || 1565 xa->smb_mprcnt < n_param || 1566 xa->smb_mdrcnt < n_data) { 1567 goto trans_err_too_small; 1568 } 1569 1570 /* neato, blast it over there */ 1571 1572 n_setup = (n_setup + 1) / 2; /* Convert to setup words */ 1573 param_pad = 1; /* always one */ 1574 param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 1575 data_pad = (param_off + n_param) & 1; /* Pad to short */ 1576 /* Param off from hdr start */ 1577 data_off = param_off + n_param + data_pad; 1578 total_bytes = param_pad + n_param + data_pad + n_data; 1579 1580 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, 1581 "bww2.wwwwwwb.Cw#.C#.C", 1582 10 + n_setup, /* wct */ 1583 n_param, /* Total Parameter Bytes */ 1584 n_data, /* Total Data Bytes */ 1585 n_param, /* Total Parameter Bytes this buffer */ 1586 param_off, /* Param offset from header start */ 1587 0, /* Param displacement */ 1588 n_data, /* Total Data Bytes this buffer */ 1589 data_off, /* Data offset from header start */ 1590 0, /* Data displacement */ 1591 n_setup, /* suwcnt */ 1592 &xa->rep_setup_mb, /* setup[] */ 1593 total_bytes, /* Total data bytes */ 1594 param_pad, 1595 &xa->rep_param_mb, 1596 data_pad, 1597 &xa->rep_data_mb); 1598 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1599 1600 trans_err_too_small: 1601 rc = NERR_BufTooSmall; 1602 goto trans_err; 1603 1604 trans_err_not_supported: 1605 rc = ERROR_NOT_SUPPORTED; 1606 goto trans_err; 1607 1608 trans_err: 1609 pos = MBC_LENGTH(&sr->reply) + 23; 1610 rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www", 1611 10, /* wct */ 1612 4, 0, /* tpscnt tdscnt */ 1613 4, pos, 0, /* pscnt psoff psdisp */ 1614 0, 0, 0, /* dscnt dsoff dsdisp */ 1615 0, /* suwcnt */ 1616 4, /* bcc */ 1617 rc, 1618 0); /* converter word? */ 1619 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1620 } 1621 1622 static smb_sdrc_t 1623 smb_trans2_dispatch(smb_request_t *sr, smb_xa_t *xa) 1624 { 1625 int rc, pos; 1626 int total_bytes, n_setup, n_param, n_data; 1627 int param_off, param_pad, data_off; 1628 uint16_t data_pad; 1629 uint16_t opcode; 1630 uint16_t nt_unknown_secret = 0x0100; 1631 char *fmt; 1632 1633 n_data = xa->smb_mdrcnt; 1634 1635 if (smb_mbc_decodef(&xa->req_setup_mb, "w", &opcode) != 0) 1636 goto trans_err_not_supported; 1637 1638 /* 1639 * Save this for /proc to read later. 1640 */ 1641 xa->smb_func = opcode; 1642 1643 /* for now, only respond to the */ 1644 switch (opcode) { 1645 case TRANS2_OPEN2: 1646 rc = smb_com_trans2_open2(sr, xa); 1647 break; 1648 1649 case TRANS2_CREATE_DIRECTORY: 1650 rc = smb_com_trans2_create_directory(sr, xa); 1651 break; 1652 1653 case TRANS2_FIND_FIRST2: 1654 /* 1655 * Should have enough room to send the response 1656 * data back to client. 1657 */ 1658 if (n_data == 0) { 1659 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1660 ERRDOS, ERROR_BAD_LENGTH); 1661 return (SDRC_ERROR); 1662 } 1663 rc = smb_com_trans2_find_first2(sr, xa); 1664 break; 1665 1666 case TRANS2_FIND_NEXT2: 1667 /* 1668 * Should have enough room to send the response 1669 * data back to client. 1670 */ 1671 if (n_data == 0) { 1672 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1673 ERRDOS, ERROR_BAD_LENGTH); 1674 return (SDRC_ERROR); 1675 } 1676 rc = smb_com_trans2_find_next2(sr, xa); 1677 break; 1678 1679 case TRANS2_QUERY_FS_INFORMATION: 1680 /* 1681 * Should have enough room to send the response 1682 * data back to client. 1683 */ 1684 if (n_data == 0) { 1685 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1686 ERRDOS, ERROR_BAD_LENGTH); 1687 return (SDRC_ERROR); 1688 } 1689 rc = smb_com_trans2_query_fs_information(sr, xa); 1690 break; 1691 1692 case TRANS2_SET_FS_INFORMATION: 1693 rc = smb_com_trans2_set_fs_information(sr, xa); 1694 break; 1695 1696 case TRANS2_QUERY_PATH_INFORMATION: 1697 /* 1698 * Should have enough room to send the response 1699 * data back to client. 1700 */ 1701 if (n_data == 0) { 1702 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1703 ERRDOS, ERROR_BAD_LENGTH); 1704 return (SDRC_ERROR); 1705 } 1706 rc = smb_com_trans2_query_path_information(sr, xa); 1707 break; 1708 1709 case TRANS2_QUERY_FILE_INFORMATION: 1710 /* 1711 * Should have enough room to send the response 1712 * data back to client. 1713 */ 1714 if (n_data == 0) { 1715 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1716 ERRDOS, ERROR_BAD_LENGTH); 1717 return (SDRC_ERROR); 1718 } 1719 rc = smb_com_trans2_query_file_information(sr, xa); 1720 break; 1721 1722 case TRANS2_SET_PATH_INFORMATION: 1723 rc = smb_com_trans2_set_path_information(sr, xa); 1724 break; 1725 1726 case TRANS2_SET_FILE_INFORMATION: 1727 rc = smb_com_trans2_set_file_information(sr, xa); 1728 break; 1729 1730 case TRANS2_GET_DFS_REFERRAL: 1731 rc = smb_com_trans2_get_dfs_referral(sr, xa); 1732 break; 1733 1734 default: 1735 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 1736 goto trans_err_not_supported; 1737 } 1738 1739 switch (rc) { 1740 case SDRC_SUCCESS: 1741 break; 1742 1743 case SDRC_DROP_VC: 1744 case SDRC_NO_REPLY: 1745 case SDRC_ERROR: 1746 return (rc); 1747 1748 case SDRC_NOT_IMPLEMENTED: 1749 goto trans_err_not_supported; 1750 1751 default: 1752 break; 1753 } 1754 1755 n_setup = MBC_LENGTH(&xa->rep_setup_mb); 1756 n_param = MBC_LENGTH(&xa->rep_param_mb); 1757 n_data = MBC_LENGTH(&xa->rep_data_mb); 1758 1759 if (xa->smb_msrcnt < n_setup || 1760 xa->smb_mprcnt < n_param || 1761 xa->smb_mdrcnt < n_data) { 1762 goto trans_err_too_small; 1763 } 1764 1765 /* neato, blast it over there */ 1766 1767 n_setup = (n_setup + 1) / 2; /* Conver to setup words */ 1768 param_pad = 1; /* must be one */ 1769 param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 1770 1771 /* 1772 * Including the nt_unknown_secret value persuades netmon to 1773 * display the correct data format for QueryPathInfo and 1774 * QueryFileInfo. 1775 */ 1776 if (opcode == TRANS2_QUERY_FILE_INFORMATION || 1777 opcode == TRANS2_QUERY_PATH_INFORMATION) { 1778 data_pad = sizeof (uint16_t); 1779 data_off = param_off + n_param + data_pad; 1780 fmt = "bww2.wwwwwwb.Cw#.CwC"; 1781 nt_unknown_secret = 0x0100; 1782 } 1783 else 1784 { 1785 data_pad = (param_off + n_param) & 1; /* Pad to short */ 1786 /* Param off from hdr start */ 1787 data_off = param_off + n_param + data_pad; 1788 fmt = "bww2.wwwwwwb.Cw#.C#.C"; 1789 nt_unknown_secret = data_pad; 1790 } 1791 1792 total_bytes = param_pad + n_param + data_pad + n_data; 1793 1794 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, 1795 fmt, 1796 10 + n_setup, /* wct */ 1797 n_param, /* Total Parameter Bytes */ 1798 n_data /* + data_pad */, /* Total Data Bytes */ 1799 n_param, /* Total Parameter Bytes this buffer */ 1800 param_off, /* Param offset from header start */ 1801 0, /* Param displacement */ 1802 n_data /* + data_pad */, /* Total Data Bytes this buffer */ 1803 data_off, /* Data offset from header start */ 1804 0, /* Data displacement */ 1805 n_setup, /* suwcnt */ 1806 &xa->rep_setup_mb, /* setup[] */ 1807 total_bytes, /* Total data bytes */ 1808 param_pad, 1809 &xa->rep_param_mb, 1810 nt_unknown_secret, 1811 &xa->rep_data_mb); 1812 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1813 1814 trans_err_too_small: 1815 rc = NERR_BufTooSmall; 1816 goto trans_err; 1817 1818 trans_err_not_supported: 1819 rc = ERROR_NOT_SUPPORTED; 1820 goto trans_err; 1821 1822 trans_err: 1823 pos = MBC_LENGTH(&sr->reply) + 23; 1824 rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www", 1825 10, /* wct */ 1826 4, 0, /* tpscnt tdscnt */ 1827 4, pos, 0, /* pscnt psoff psdisp */ 1828 0, 0, 0, /* dscnt dsoff dsdisp */ 1829 0, /* suwcnt */ 1830 4, /* bcc */ 1831 rc, 1832 0); /* converter word? */ 1833 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1834 } 1835 1836 static uint32_t smb_xa_max_setup_count = 200; 1837 static uint32_t smb_xa_max_param_count = 32 * 1024; 1838 static uint32_t smb_xa_max_data_count = 64 * 1024; 1839 1840 smb_xa_t * 1841 smb_xa_create( 1842 smb_session_t *session, 1843 smb_request_t *sr, 1844 uint32_t total_parameter_count, 1845 uint32_t total_data_count, 1846 uint32_t max_parameter_count, 1847 uint32_t max_data_count, 1848 uint32_t max_setup_count, 1849 uint32_t setup_word_count) 1850 { 1851 smb_xa_t *xa, *nxa; 1852 smb_llist_t *xlist; 1853 1854 /* 1855 * Sanity check what the client says it will send. 1856 * Caller handles NULL return as ERRnoroom. 1857 */ 1858 if (setup_word_count > smb_xa_max_setup_count) 1859 return (NULL); 1860 if (total_parameter_count > smb_xa_max_param_count) 1861 return (NULL); 1862 if (total_data_count > smb_xa_max_data_count) 1863 return (NULL); 1864 1865 /* 1866 * Limit what the client asks us to allocate for 1867 * returned setup, params, data. 1868 */ 1869 if (max_setup_count > smb_xa_max_setup_count) 1870 max_setup_count = smb_xa_max_setup_count; 1871 if (max_parameter_count > smb_xa_max_param_count) 1872 max_parameter_count = smb_xa_max_param_count; 1873 if (max_data_count > smb_xa_max_data_count) 1874 max_data_count = smb_xa_max_data_count; 1875 1876 xa = kmem_zalloc(sizeof (smb_xa_t), KM_SLEEP); 1877 xa->xa_refcnt = 1; 1878 xa->smb_com = sr->smb_com; 1879 xa->smb_flg = sr->smb_flg; 1880 xa->smb_flg2 = sr->smb_flg2; 1881 xa->smb_tid = sr->smb_tid; 1882 xa->smb_pid = sr->smb_pid; 1883 xa->smb_uid = sr->smb_uid; 1884 xa->xa_smb_mid = sr->smb_mid; 1885 xa->xa_smb_fid = 0xFFFF; 1886 xa->reply_seqnum = sr->reply_seqnum; 1887 xa->smb_tpscnt = total_parameter_count; 1888 xa->smb_tdscnt = total_data_count; 1889 xa->smb_mprcnt = max_parameter_count; 1890 xa->smb_mdrcnt = max_data_count; 1891 xa->smb_msrcnt = max_setup_count; 1892 xa->smb_suwcnt = setup_word_count; 1893 xa->xa_session = session; 1894 xa->xa_magic = SMB_XA_MAGIC; 1895 1896 /* request parts */ 1897 xa->req_setup_mb.max_bytes = setup_word_count * 2; 1898 xa->req_param_mb.max_bytes = total_parameter_count; 1899 xa->req_data_mb.max_bytes = total_data_count; 1900 1901 /* reply parts */ 1902 xa->rep_setup_mb.max_bytes = max_setup_count * 2; 1903 xa->rep_param_mb.max_bytes = max_parameter_count; 1904 xa->rep_data_mb.max_bytes = max_data_count; 1905 1906 /* 1907 * The new xa structure is checked against the current list to see 1908 * if it exists already. 1909 */ 1910 xlist = &session->s_xa_list; 1911 smb_llist_enter(xlist, RW_WRITER); 1912 nxa = smb_llist_head(xlist); 1913 while (nxa) { 1914 ASSERT(nxa->xa_magic == SMB_XA_MAGIC); 1915 if (nxa->xa_smb_mid == xa->xa_smb_mid && 1916 nxa->smb_pid == xa->smb_pid && 1917 !SMB_XA_CLOSED(nxa) && 1918 !(nxa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 1919 smb_llist_exit(xlist); 1920 kmem_free(xa, sizeof (smb_xa_t)); 1921 return (NULL); 1922 } 1923 nxa = smb_llist_next(xlist, nxa); 1924 } 1925 smb_llist_insert_tail(xlist, xa); 1926 smb_llist_exit(xlist); 1927 return (xa); 1928 } 1929 1930 void 1931 smb_xa_delete(smb_xa_t *xa) 1932 { 1933 ASSERT(xa->xa_refcnt == 0); 1934 ASSERT(SMB_XA_CLOSED(xa)); 1935 1936 if (xa->xa_pipe_name) 1937 smb_mem_free(xa->xa_pipe_name); 1938 1939 /* request parts */ 1940 if (xa->req_setup_mb.chain != NULL) 1941 m_freem(xa->req_setup_mb.chain); 1942 if (xa->req_param_mb.chain != NULL) 1943 m_freem(xa->req_param_mb.chain); 1944 if (xa->req_data_mb.chain != NULL) 1945 m_freem(xa->req_data_mb.chain); 1946 1947 /* reply parts */ 1948 if (xa->rep_setup_mb.chain != NULL) 1949 m_freem(xa->rep_setup_mb.chain); 1950 if (xa->rep_param_mb.chain != NULL) 1951 m_freem(xa->rep_param_mb.chain); 1952 if (xa->rep_data_mb.chain != NULL) 1953 m_freem(xa->rep_data_mb.chain); 1954 1955 xa->xa_magic = (uint32_t)~SMB_XA_MAGIC; 1956 kmem_free(xa, sizeof (smb_xa_t)); 1957 } 1958 1959 smb_xa_t * 1960 smb_xa_hold(smb_xa_t *xa) 1961 { 1962 mutex_enter(&xa->xa_mutex); 1963 xa->xa_refcnt++; 1964 ASSERT(xa->xa_refcnt); 1965 mutex_exit(&xa->xa_mutex); 1966 return (xa); 1967 } 1968 1969 void 1970 smb_xa_rele(smb_session_t *session, smb_xa_t *xa) 1971 { 1972 mutex_enter(&xa->xa_mutex); 1973 ASSERT(xa->xa_refcnt); 1974 xa->xa_refcnt--; 1975 if (SMB_XA_CLOSED(xa) && (xa->xa_refcnt == 0)) { 1976 mutex_exit(&xa->xa_mutex); 1977 smb_llist_enter(&session->s_xa_list, RW_WRITER); 1978 smb_llist_remove(&session->s_xa_list, xa); 1979 smb_llist_exit(&session->s_xa_list); 1980 smb_xa_delete(xa); 1981 return; 1982 } 1983 mutex_exit(&xa->xa_mutex); 1984 } 1985 1986 int 1987 smb_xa_open(smb_xa_t *xa) 1988 { 1989 int rc; 1990 1991 mutex_enter(&xa->xa_mutex); 1992 1993 ASSERT((xa->xa_flags & SMB_XA_FLAG_OPEN) == 0); 1994 1995 if ((xa->xa_flags & SMB_XA_FLAG_CLOSE) == 0) { 1996 xa->xa_flags |= SMB_XA_FLAG_OPEN; 1997 rc = 0; 1998 } else { 1999 rc = ERROR_INVALID_HANDLE; 2000 } 2001 2002 mutex_exit(&xa->xa_mutex); 2003 2004 return (rc); 2005 } 2006 2007 void 2008 smb_xa_close(smb_xa_t *xa) 2009 { 2010 mutex_enter(&xa->xa_mutex); 2011 xa->xa_flags |= SMB_XA_FLAG_CLOSE; 2012 xa->xa_flags &= ~SMB_XA_FLAG_OPEN; 2013 2014 if (xa->xa_refcnt == 0) { 2015 mutex_exit(&xa->xa_mutex); 2016 smb_llist_enter(&xa->xa_session->s_xa_list, RW_WRITER); 2017 smb_llist_remove(&xa->xa_session->s_xa_list, xa); 2018 smb_llist_exit(&xa->xa_session->s_xa_list); 2019 smb_xa_delete(xa); 2020 return; 2021 } 2022 2023 mutex_exit(&xa->xa_mutex); 2024 } 2025 2026 int 2027 smb_xa_complete(smb_xa_t *xa) 2028 { 2029 int rc; 2030 2031 mutex_enter(&xa->xa_mutex); 2032 if (xa->xa_flags & (SMB_XA_FLAG_COMPLETE | SMB_XA_FLAG_CLOSE)) { 2033 rc = 0; /* error ("not complete") */ 2034 } else { 2035 rc = 1; /* Yes, "complete" */ 2036 xa->xa_flags |= SMB_XA_FLAG_COMPLETE; 2037 2038 /* 2039 * During trans & trans-secondary processing, 2040 * we copied the request data into these. 2041 * Now we want to parse them, so we need to 2042 * move the "finger" back to the beginning. 2043 */ 2044 xa->req_setup_mb.chain_offset = 0; 2045 xa->req_param_mb.chain_offset = 0; 2046 xa->req_data_mb.chain_offset = 0; 2047 } 2048 2049 mutex_exit(&xa->xa_mutex); 2050 return (rc); 2051 } 2052 2053 smb_xa_t * 2054 smb_xa_find( 2055 smb_session_t *session, 2056 uint32_t pid, 2057 uint16_t mid) 2058 { 2059 smb_xa_t *xa; 2060 smb_llist_t *xlist; 2061 2062 xlist = &session->s_xa_list; 2063 smb_llist_enter(xlist, RW_READER); 2064 xa = smb_llist_head(xlist); 2065 while (xa) { 2066 mutex_enter(&xa->xa_mutex); 2067 if (xa->xa_smb_mid == mid && 2068 xa->smb_pid == pid && 2069 !SMB_XA_CLOSED(xa) && 2070 !(xa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 2071 xa->xa_refcnt++; 2072 ASSERT(xa->xa_refcnt); 2073 mutex_exit(&xa->xa_mutex); 2074 break; 2075 } 2076 mutex_exit(&xa->xa_mutex); 2077 xa = smb_llist_next(xlist, xa); 2078 } 2079 smb_llist_exit(xlist); 2080 return (xa); 2081 } 2082