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