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 != 0) { 1437 m_freem(mb); 1438 smbsr_errno(sr, rc); 1439 return (SDRC_ERROR); 1440 } 1441 1442 smb_mbuf_trim(mb, xa->smb_mdrcnt - vdb.vdb_uio.uio_resid); 1443 MBC_ATTACH_MBUF(&xa->rep_data_mb, mb); 1444 1445 /* 1446 * If the output buffer holds a partial pipe message, 1447 * we're supposed to return NT_STATUS_BUFFER_OVERFLOW. 1448 * As we don't have message boundary markers, the best 1449 * we can do is return that status when we have ALL of: 1450 * Output buffer was < SMB_PIPE_MAX_MSGSIZE 1451 * We filled the output buffer (resid==0) 1452 * There's more data (ioctl FIONREAD) 1453 */ 1454 if (xa->smb_mdrcnt < SMB_PIPE_MAX_MSGSIZE && 1455 vdb.vdb_uio.uio_resid == 0) { 1456 int nread = 0; 1457 rc = smb_opipe_get_nread(sr, &nread); 1458 if (rc == 0 && nread != 0) { 1459 smbsr_status(sr, NT_STATUS_BUFFER_OVERFLOW, 1460 ERRDOS, ERROR_MORE_DATA); 1461 } 1462 } 1463 1464 return (SDRC_SUCCESS); 1465 } 1466 1467 static smb_sdrc_t 1468 smb_trans_dispatch(smb_request_t *sr, smb_xa_t *xa) 1469 { 1470 int rc, pos; 1471 int total_bytes, n_setup, n_param, n_data; 1472 int param_off, param_pad, data_off, data_pad; 1473 uint16_t opcode; 1474 uint16_t devstate; 1475 char *req_fmt; 1476 char *rep_fmt; 1477 1478 if (xa->smb_suwcnt > 0 && STYPE_ISIPC(sr->tid_tree->t_res_type)) { 1479 rc = smb_mbc_decodef(&xa->req_setup_mb, "ww", &opcode, 1480 &sr->smb_fid); 1481 if (rc != 0) 1482 goto trans_err_not_supported; 1483 switch (opcode) { 1484 case TRANS_SET_NMPIPE_STATE: 1485 if ((rc = smb_mbc_decodef(&xa->req_param_mb, "w", 1486 &devstate)) != 0) 1487 goto trans_err_not_supported; 1488 1489 rc = SDRC_SUCCESS; 1490 break; 1491 1492 case TRANS_TRANSACT_NMPIPE: 1493 rc = smb_trans_nmpipe(sr, xa); 1494 break; 1495 1496 case TRANS_WAIT_NMPIPE: 1497 delay(SEC_TO_TICK(1)); 1498 rc = SDRC_SUCCESS; 1499 break; 1500 1501 default: 1502 goto trans_err_not_supported; 1503 } 1504 } else { 1505 if (!is_supported_mailslot(xa->xa_pipe_name)) 1506 goto trans_err_not_supported; 1507 1508 if ((rc = smb_mbc_decodef(&xa->req_param_mb, "%wss", sr, 1509 &opcode, &req_fmt, &rep_fmt)) != 0) 1510 goto trans_err_not_supported; 1511 1512 switch (opcode) { 1513 case API_WshareEnum: 1514 rc = smb_trans_net_share_enum(sr, xa); 1515 break; 1516 1517 case API_WshareGetInfo: 1518 rc = smb_trans_net_share_getinfo(sr, xa); 1519 break; 1520 1521 case API_WserverGetInfo: 1522 rc = smb_trans_net_server_getinfo(sr, xa); 1523 break; 1524 1525 case API_WUserGetInfo: 1526 rc = smb_trans_net_user_getinfo(sr, xa); 1527 break; 1528 1529 case API_WWkstaGetInfo: 1530 rc = smb_trans_net_workstation_getinfo(sr, xa); 1531 break; 1532 1533 case API_NetServerEnum2: 1534 rc = smb_trans_net_server_enum2(sr, xa); 1535 break; 1536 1537 default: 1538 goto trans_err_not_supported; 1539 } 1540 } 1541 1542 switch (rc) { 1543 case SDRC_SUCCESS: 1544 break; 1545 1546 case SDRC_DROP_VC: 1547 case SDRC_NO_REPLY: 1548 case SDRC_ERROR: 1549 return (rc); 1550 1551 case SDRC_NOT_IMPLEMENTED: 1552 goto trans_err_not_supported; 1553 1554 default: 1555 break; 1556 } 1557 1558 n_setup = MBC_LENGTH(&xa->rep_setup_mb); 1559 n_param = MBC_LENGTH(&xa->rep_param_mb); 1560 n_data = MBC_LENGTH(&xa->rep_data_mb); 1561 1562 if (xa->smb_msrcnt < n_setup || 1563 xa->smb_mprcnt < n_param || 1564 xa->smb_mdrcnt < n_data) { 1565 goto trans_err_too_small; 1566 } 1567 1568 /* neato, blast it over there */ 1569 1570 n_setup = (n_setup + 1) / 2; /* Convert to setup words */ 1571 param_pad = 1; /* always one */ 1572 param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 1573 data_pad = (param_off + n_param) & 1; /* Pad to short */ 1574 /* Param off from hdr start */ 1575 data_off = param_off + n_param + data_pad; 1576 total_bytes = param_pad + n_param + data_pad + n_data; 1577 1578 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, 1579 "bww2.wwwwwwb.Cw#.C#.C", 1580 10 + n_setup, /* wct */ 1581 n_param, /* Total Parameter Bytes */ 1582 n_data, /* Total Data Bytes */ 1583 n_param, /* Total Parameter Bytes this buffer */ 1584 param_off, /* Param offset from header start */ 1585 0, /* Param displacement */ 1586 n_data, /* Total Data Bytes this buffer */ 1587 data_off, /* Data offset from header start */ 1588 0, /* Data displacement */ 1589 n_setup, /* suwcnt */ 1590 &xa->rep_setup_mb, /* setup[] */ 1591 total_bytes, /* Total data bytes */ 1592 param_pad, 1593 &xa->rep_param_mb, 1594 data_pad, 1595 &xa->rep_data_mb); 1596 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1597 1598 trans_err_too_small: 1599 rc = NERR_BufTooSmall; 1600 goto trans_err; 1601 1602 trans_err_not_supported: 1603 rc = ERROR_NOT_SUPPORTED; 1604 goto trans_err; 1605 1606 trans_err: 1607 pos = MBC_LENGTH(&sr->reply) + 23; 1608 rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www", 1609 10, /* wct */ 1610 4, 0, /* tpscnt tdscnt */ 1611 4, pos, 0, /* pscnt psoff psdisp */ 1612 0, 0, 0, /* dscnt dsoff dsdisp */ 1613 0, /* suwcnt */ 1614 4, /* bcc */ 1615 rc, 1616 0); /* converter word? */ 1617 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1618 } 1619 1620 static smb_sdrc_t 1621 smb_trans2_dispatch(smb_request_t *sr, smb_xa_t *xa) 1622 { 1623 int rc, pos; 1624 int total_bytes, n_setup, n_param, n_data; 1625 int param_off, param_pad, data_off; 1626 uint16_t data_pad; 1627 uint16_t opcode; 1628 uint16_t nt_unknown_secret = 0x0100; 1629 char *fmt; 1630 1631 n_data = xa->smb_mdrcnt; 1632 1633 if (smb_mbc_decodef(&xa->req_setup_mb, "w", &opcode) != 0) 1634 goto trans_err_not_supported; 1635 1636 /* 1637 * Save this for /proc to read later. 1638 */ 1639 xa->smb_func = opcode; 1640 1641 /* for now, only respond to the */ 1642 switch (opcode) { 1643 case TRANS2_OPEN2: 1644 rc = smb_com_trans2_open2(sr, xa); 1645 break; 1646 1647 case TRANS2_CREATE_DIRECTORY: 1648 rc = smb_com_trans2_create_directory(sr, xa); 1649 break; 1650 1651 case TRANS2_FIND_FIRST2: 1652 /* 1653 * Should have enough room to send the response 1654 * data back to client. 1655 */ 1656 if (n_data == 0) { 1657 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1658 ERRDOS, ERROR_BAD_LENGTH); 1659 return (SDRC_ERROR); 1660 } 1661 rc = smb_com_trans2_find_first2(sr, xa); 1662 break; 1663 1664 case TRANS2_FIND_NEXT2: 1665 /* 1666 * Should have enough room to send the response 1667 * data back to client. 1668 */ 1669 if (n_data == 0) { 1670 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1671 ERRDOS, ERROR_BAD_LENGTH); 1672 return (SDRC_ERROR); 1673 } 1674 rc = smb_com_trans2_find_next2(sr, xa); 1675 break; 1676 1677 case TRANS2_QUERY_FS_INFORMATION: 1678 /* 1679 * Should have enough room to send the response 1680 * data back to client. 1681 */ 1682 if (n_data == 0) { 1683 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1684 ERRDOS, ERROR_BAD_LENGTH); 1685 return (SDRC_ERROR); 1686 } 1687 rc = smb_com_trans2_query_fs_information(sr, xa); 1688 break; 1689 1690 case TRANS2_SET_FS_INFORMATION: 1691 rc = smb_com_trans2_set_fs_information(sr, xa); 1692 break; 1693 1694 case TRANS2_QUERY_PATH_INFORMATION: 1695 /* 1696 * Should have enough room to send the response 1697 * data back to client. 1698 */ 1699 if (n_data == 0) { 1700 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1701 ERRDOS, ERROR_BAD_LENGTH); 1702 return (SDRC_ERROR); 1703 } 1704 rc = smb_com_trans2_query_path_information(sr, xa); 1705 break; 1706 1707 case TRANS2_QUERY_FILE_INFORMATION: 1708 /* 1709 * Should have enough room to send the response 1710 * data back to client. 1711 */ 1712 if (n_data == 0) { 1713 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1714 ERRDOS, ERROR_BAD_LENGTH); 1715 return (SDRC_ERROR); 1716 } 1717 rc = smb_com_trans2_query_file_information(sr, xa); 1718 break; 1719 1720 case TRANS2_SET_PATH_INFORMATION: 1721 rc = smb_com_trans2_set_path_information(sr, xa); 1722 break; 1723 1724 case TRANS2_SET_FILE_INFORMATION: 1725 rc = smb_com_trans2_set_file_information(sr, xa); 1726 break; 1727 1728 case TRANS2_GET_DFS_REFERRAL: 1729 rc = smb_com_trans2_get_dfs_referral(sr, xa); 1730 break; 1731 1732 default: 1733 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 1734 goto trans_err_not_supported; 1735 } 1736 1737 switch (rc) { 1738 case SDRC_SUCCESS: 1739 break; 1740 1741 case SDRC_DROP_VC: 1742 case SDRC_NO_REPLY: 1743 case SDRC_ERROR: 1744 return (rc); 1745 1746 case SDRC_NOT_IMPLEMENTED: 1747 goto trans_err_not_supported; 1748 1749 default: 1750 break; 1751 } 1752 1753 n_setup = MBC_LENGTH(&xa->rep_setup_mb); 1754 n_param = MBC_LENGTH(&xa->rep_param_mb); 1755 n_data = MBC_LENGTH(&xa->rep_data_mb); 1756 1757 if (xa->smb_msrcnt < n_setup || 1758 xa->smb_mprcnt < n_param || 1759 xa->smb_mdrcnt < n_data) { 1760 goto trans_err_too_small; 1761 } 1762 1763 /* neato, blast it over there */ 1764 1765 n_setup = (n_setup + 1) / 2; /* Conver to setup words */ 1766 param_pad = 1; /* must be one */ 1767 param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 1768 1769 /* 1770 * Including the nt_unknown_secret value persuades netmon to 1771 * display the correct data format for QueryPathInfo and 1772 * QueryFileInfo. 1773 */ 1774 if (opcode == TRANS2_QUERY_FILE_INFORMATION || 1775 opcode == TRANS2_QUERY_PATH_INFORMATION) { 1776 data_pad = sizeof (uint16_t); 1777 data_off = param_off + n_param + data_pad; 1778 fmt = "bww2.wwwwwwb.Cw#.CwC"; 1779 nt_unknown_secret = 0x0100; 1780 } 1781 else 1782 { 1783 data_pad = (param_off + n_param) & 1; /* Pad to short */ 1784 /* Param off from hdr start */ 1785 data_off = param_off + n_param + data_pad; 1786 fmt = "bww2.wwwwwwb.Cw#.C#.C"; 1787 nt_unknown_secret = data_pad; 1788 } 1789 1790 total_bytes = param_pad + n_param + data_pad + n_data; 1791 1792 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, 1793 fmt, 1794 10 + n_setup, /* wct */ 1795 n_param, /* Total Parameter Bytes */ 1796 n_data /* + data_pad */, /* Total Data Bytes */ 1797 n_param, /* Total Parameter Bytes this buffer */ 1798 param_off, /* Param offset from header start */ 1799 0, /* Param displacement */ 1800 n_data /* + data_pad */, /* Total Data Bytes this buffer */ 1801 data_off, /* Data offset from header start */ 1802 0, /* Data displacement */ 1803 n_setup, /* suwcnt */ 1804 &xa->rep_setup_mb, /* setup[] */ 1805 total_bytes, /* Total data bytes */ 1806 param_pad, 1807 &xa->rep_param_mb, 1808 nt_unknown_secret, 1809 &xa->rep_data_mb); 1810 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1811 1812 trans_err_too_small: 1813 rc = NERR_BufTooSmall; 1814 goto trans_err; 1815 1816 trans_err_not_supported: 1817 rc = ERROR_NOT_SUPPORTED; 1818 goto trans_err; 1819 1820 trans_err: 1821 pos = MBC_LENGTH(&sr->reply) + 23; 1822 rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www", 1823 10, /* wct */ 1824 4, 0, /* tpscnt tdscnt */ 1825 4, pos, 0, /* pscnt psoff psdisp */ 1826 0, 0, 0, /* dscnt dsoff dsdisp */ 1827 0, /* suwcnt */ 1828 4, /* bcc */ 1829 rc, 1830 0); /* converter word? */ 1831 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1832 } 1833 1834 static uint32_t smb_xa_max_setup_count = 200; 1835 static uint32_t smb_xa_max_param_count = 32 * 1024; 1836 static uint32_t smb_xa_max_data_count = 64 * 1024; 1837 1838 smb_xa_t * 1839 smb_xa_create( 1840 smb_session_t *session, 1841 smb_request_t *sr, 1842 uint32_t total_parameter_count, 1843 uint32_t total_data_count, 1844 uint32_t max_parameter_count, 1845 uint32_t max_data_count, 1846 uint32_t max_setup_count, 1847 uint32_t setup_word_count) 1848 { 1849 smb_xa_t *xa, *nxa; 1850 smb_llist_t *xlist; 1851 1852 /* 1853 * Sanity check what the client says it will send. 1854 * Caller handles NULL return as ERRnoroom. 1855 */ 1856 if (setup_word_count > smb_xa_max_setup_count) 1857 return (NULL); 1858 if (total_parameter_count > smb_xa_max_param_count) 1859 return (NULL); 1860 if (total_data_count > smb_xa_max_data_count) 1861 return (NULL); 1862 1863 /* 1864 * Limit what the client asks us to allocate for 1865 * returned setup, params, data. 1866 */ 1867 if (max_setup_count > smb_xa_max_setup_count) 1868 max_setup_count = smb_xa_max_setup_count; 1869 if (max_parameter_count > smb_xa_max_param_count) 1870 max_parameter_count = smb_xa_max_param_count; 1871 if (max_data_count > smb_xa_max_data_count) 1872 max_data_count = smb_xa_max_data_count; 1873 1874 xa = kmem_zalloc(sizeof (smb_xa_t), KM_SLEEP); 1875 xa->xa_refcnt = 1; 1876 xa->smb_com = sr->smb_com; 1877 xa->smb_flg = sr->smb_flg; 1878 xa->smb_flg2 = sr->smb_flg2; 1879 xa->smb_tid = sr->smb_tid; 1880 xa->smb_pid = sr->smb_pid; 1881 xa->smb_uid = sr->smb_uid; 1882 xa->xa_smb_mid = sr->smb_mid; 1883 xa->xa_smb_fid = 0xFFFF; 1884 xa->reply_seqnum = sr->reply_seqnum; 1885 xa->smb_tpscnt = total_parameter_count; 1886 xa->smb_tdscnt = total_data_count; 1887 xa->smb_mprcnt = max_parameter_count; 1888 xa->smb_mdrcnt = max_data_count; 1889 xa->smb_msrcnt = max_setup_count; 1890 xa->smb_suwcnt = setup_word_count; 1891 xa->xa_session = session; 1892 xa->xa_magic = SMB_XA_MAGIC; 1893 1894 /* request parts */ 1895 xa->req_setup_mb.max_bytes = setup_word_count * 2; 1896 xa->req_param_mb.max_bytes = total_parameter_count; 1897 xa->req_data_mb.max_bytes = total_data_count; 1898 1899 /* reply parts */ 1900 xa->rep_setup_mb.max_bytes = max_setup_count * 2; 1901 xa->rep_param_mb.max_bytes = max_parameter_count; 1902 xa->rep_data_mb.max_bytes = max_data_count; 1903 1904 /* 1905 * The new xa structure is checked against the current list to see 1906 * if it exists already. 1907 */ 1908 xlist = &session->s_xa_list; 1909 smb_llist_enter(xlist, RW_WRITER); 1910 nxa = smb_llist_head(xlist); 1911 while (nxa) { 1912 ASSERT(nxa->xa_magic == SMB_XA_MAGIC); 1913 if (nxa->xa_smb_mid == xa->xa_smb_mid && 1914 nxa->smb_pid == xa->smb_pid && 1915 !SMB_XA_CLOSED(nxa) && 1916 !(nxa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 1917 smb_llist_exit(xlist); 1918 kmem_free(xa, sizeof (smb_xa_t)); 1919 return (NULL); 1920 } 1921 nxa = smb_llist_next(xlist, nxa); 1922 } 1923 smb_llist_insert_tail(xlist, xa); 1924 smb_llist_exit(xlist); 1925 return (xa); 1926 } 1927 1928 void 1929 smb_xa_delete(smb_xa_t *xa) 1930 { 1931 ASSERT(xa->xa_refcnt == 0); 1932 ASSERT(SMB_XA_CLOSED(xa)); 1933 1934 if (xa->xa_pipe_name) 1935 smb_mem_free(xa->xa_pipe_name); 1936 1937 /* request parts */ 1938 if (xa->req_setup_mb.chain != NULL) 1939 m_freem(xa->req_setup_mb.chain); 1940 if (xa->req_param_mb.chain != NULL) 1941 m_freem(xa->req_param_mb.chain); 1942 if (xa->req_data_mb.chain != NULL) 1943 m_freem(xa->req_data_mb.chain); 1944 1945 /* reply parts */ 1946 if (xa->rep_setup_mb.chain != NULL) 1947 m_freem(xa->rep_setup_mb.chain); 1948 if (xa->rep_param_mb.chain != NULL) 1949 m_freem(xa->rep_param_mb.chain); 1950 if (xa->rep_data_mb.chain != NULL) 1951 m_freem(xa->rep_data_mb.chain); 1952 1953 xa->xa_magic = (uint32_t)~SMB_XA_MAGIC; 1954 kmem_free(xa, sizeof (smb_xa_t)); 1955 } 1956 1957 smb_xa_t * 1958 smb_xa_hold(smb_xa_t *xa) 1959 { 1960 mutex_enter(&xa->xa_mutex); 1961 xa->xa_refcnt++; 1962 ASSERT(xa->xa_refcnt); 1963 mutex_exit(&xa->xa_mutex); 1964 return (xa); 1965 } 1966 1967 void 1968 smb_xa_rele(smb_session_t *session, smb_xa_t *xa) 1969 { 1970 mutex_enter(&xa->xa_mutex); 1971 ASSERT(xa->xa_refcnt); 1972 xa->xa_refcnt--; 1973 if (SMB_XA_CLOSED(xa) && (xa->xa_refcnt == 0)) { 1974 mutex_exit(&xa->xa_mutex); 1975 smb_llist_enter(&session->s_xa_list, RW_WRITER); 1976 smb_llist_remove(&session->s_xa_list, xa); 1977 smb_llist_exit(&session->s_xa_list); 1978 smb_xa_delete(xa); 1979 return; 1980 } 1981 mutex_exit(&xa->xa_mutex); 1982 } 1983 1984 int 1985 smb_xa_open(smb_xa_t *xa) 1986 { 1987 int rc; 1988 1989 mutex_enter(&xa->xa_mutex); 1990 1991 ASSERT((xa->xa_flags & SMB_XA_FLAG_OPEN) == 0); 1992 1993 if ((xa->xa_flags & SMB_XA_FLAG_CLOSE) == 0) { 1994 xa->xa_flags |= SMB_XA_FLAG_OPEN; 1995 rc = 0; 1996 } else { 1997 rc = ERROR_INVALID_HANDLE; 1998 } 1999 2000 mutex_exit(&xa->xa_mutex); 2001 2002 return (rc); 2003 } 2004 2005 void 2006 smb_xa_close(smb_xa_t *xa) 2007 { 2008 mutex_enter(&xa->xa_mutex); 2009 xa->xa_flags |= SMB_XA_FLAG_CLOSE; 2010 xa->xa_flags &= ~SMB_XA_FLAG_OPEN; 2011 2012 if (xa->xa_refcnt == 0) { 2013 mutex_exit(&xa->xa_mutex); 2014 smb_llist_enter(&xa->xa_session->s_xa_list, RW_WRITER); 2015 smb_llist_remove(&xa->xa_session->s_xa_list, xa); 2016 smb_llist_exit(&xa->xa_session->s_xa_list); 2017 smb_xa_delete(xa); 2018 return; 2019 } 2020 2021 mutex_exit(&xa->xa_mutex); 2022 } 2023 2024 int 2025 smb_xa_complete(smb_xa_t *xa) 2026 { 2027 int rc; 2028 2029 mutex_enter(&xa->xa_mutex); 2030 if (xa->xa_flags & (SMB_XA_FLAG_COMPLETE | SMB_XA_FLAG_CLOSE)) { 2031 rc = 0; /* error ("not complete") */ 2032 } else { 2033 rc = 1; /* Yes, "complete" */ 2034 xa->xa_flags |= SMB_XA_FLAG_COMPLETE; 2035 2036 /* 2037 * During trans & trans-secondary processing, 2038 * we copied the request data into these. 2039 * Now we want to parse them, so we need to 2040 * move the "finger" back to the beginning. 2041 */ 2042 xa->req_setup_mb.chain_offset = 0; 2043 xa->req_param_mb.chain_offset = 0; 2044 xa->req_data_mb.chain_offset = 0; 2045 } 2046 2047 mutex_exit(&xa->xa_mutex); 2048 return (rc); 2049 } 2050 2051 smb_xa_t * 2052 smb_xa_find( 2053 smb_session_t *session, 2054 uint16_t pid, 2055 uint16_t mid) 2056 { 2057 smb_xa_t *xa; 2058 smb_llist_t *xlist; 2059 2060 xlist = &session->s_xa_list; 2061 smb_llist_enter(xlist, RW_READER); 2062 xa = smb_llist_head(xlist); 2063 while (xa) { 2064 mutex_enter(&xa->xa_mutex); 2065 if (xa->xa_smb_mid == mid && 2066 xa->smb_pid == pid && 2067 !SMB_XA_CLOSED(xa) && 2068 !(xa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 2069 xa->xa_refcnt++; 2070 ASSERT(xa->xa_refcnt); 2071 mutex_exit(&xa->xa_mutex); 2072 break; 2073 } 2074 mutex_exit(&xa->xa_mutex); 2075 xa = smb_llist_next(xlist, xa); 2076 } 2077 smb_llist_exit(xlist); 2078 return (xa); 2079 } 2080