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