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