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