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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <smbsrv/smb_incl.h> 30 #include <smbsrv/smb_fsops.h> 31 #include <smbsrv/oem.h> 32 #include <smbsrv/nmpipes.h> 33 #include <smbsrv/mailslot.h> 34 #include <smbsrv/lmerr.h> 35 #include <smbsrv/nterror.h> 36 37 #define MAX_SHARE_NAME_LEN 13 38 #define SHARE_INFO_1_SIZE (MAX_SHARE_NAME_LEN + sizeof (char) + \ 39 sizeof (short) + sizeof (uint32_t)) 40 41 /* 42 * count of bytes in server response packet 43 * except parameters and data. Note that setup 44 * word count is zero. 45 */ 46 #define RESP_HEADER_LEN 24 47 48 /* 49 * NB. I started by using common functions for transaction/transaction2 50 * and transaction_secondary/transaction2_secondary because they 51 * are respectively so similar. However, it turned out to be a bad 52 * idea because of quirky differences. Be sure if you modify one 53 * of these four functions to check and see if the modification should 54 * be applied to its peer. 55 */ 56 57 static int smb_trans_ready(struct smb_xa *); 58 static smb_sdrc_t smb_trans_dispatch(struct smb_request *, struct smb_xa *); 59 static smb_sdrc_t smb_trans2_dispatch(struct smb_request *, struct smb_xa *); 60 static smb_sdrc_t smb_nt_transact_query_quota(struct smb_request *, 61 struct smb_xa *); 62 63 smb_sdrc_t 64 smb_pre_transaction(smb_request_t *sr) 65 { 66 DTRACE_SMB_1(op__Transaction__start, smb_request_t *, sr); 67 return (SDRC_SUCCESS); 68 } 69 70 void 71 smb_post_transaction(smb_request_t *sr) 72 { 73 DTRACE_SMB_1(op__Transaction__done, smb_request_t *, sr); 74 } 75 76 smb_sdrc_t 77 smb_com_transaction(smb_request_t *sr) 78 { 79 int rc; 80 unsigned char msrcnt, suwcnt; 81 uint16_t tpscnt, tdscnt, mprcnt, mdrcnt, flags; 82 uint16_t pscnt, psoff, dscnt, dsoff; 83 uint32_t timeo; 84 struct smb_xa *xa; 85 char *stn; 86 int ready; 87 88 rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, 89 &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &msrcnt, &flags, 90 &timeo, &pscnt, &psoff, &dscnt, &dsoff, &suwcnt); 91 92 if (rc != 0) 93 return (SDRC_ERROR); 94 95 xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, 96 msrcnt, suwcnt); 97 if (xa == NULL) { 98 smbsr_error(sr, 0, ERRSRV, ERRnoroom); 99 return (SDRC_ERROR); 100 } 101 102 /* Should be some alignment stuff here in SMB? */ 103 if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) { 104 rc = smbsr_decode_data(sr, "%.U", sr, &stn); 105 } else { 106 rc = smbsr_decode_data(sr, "%s", sr, &stn); 107 } 108 if (rc != 0) { 109 smb_xa_rele(sr->session, xa); 110 return (SDRC_ERROR); 111 } 112 xa->xa_smb_trans_name = MEM_STRDUP("smb", stn); 113 114 xa->smb_flags = flags; 115 xa->smb_timeout = timeo; 116 xa->req_disp_param = pscnt; 117 xa->req_disp_data = dscnt; 118 119 if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv, 120 sr->smb_vwv.chain_offset, suwcnt * 2)) { 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_param_mb, &sr->command, psoff, pscnt)) { 126 smb_xa_rele(sr->session, xa); 127 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 128 return (SDRC_ERROR); 129 } 130 if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 131 smb_xa_rele(sr->session, xa); 132 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 133 return (SDRC_ERROR); 134 } 135 136 ready = smb_trans_ready(xa); 137 138 if (smb_xa_open(xa)) { 139 smb_xa_rele(sr->session, xa); 140 smbsr_error(sr, 0, ERRDOS, ERRsrverror); 141 return (SDRC_ERROR); 142 } 143 sr->r_xa = xa; 144 145 if (!ready) { 146 rc = smbsr_encode_empty_result(sr); 147 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 148 } 149 150 if (!smb_xa_complete(xa)) { 151 smb_xa_close(xa); 152 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 153 return (SDRC_ERROR); 154 } 155 156 return (smb_trans_dispatch(sr, xa)); 157 } 158 159 smb_sdrc_t 160 smb_pre_transaction_secondary(smb_request_t *sr) 161 { 162 DTRACE_SMB_1(op__TransactionSecondary__start, smb_request_t *, sr); 163 return (SDRC_SUCCESS); 164 } 165 166 void 167 smb_post_transaction_secondary(smb_request_t *sr) 168 { 169 DTRACE_SMB_1(op__TransactionSecondary__done, smb_request_t *, sr); 170 } 171 172 smb_sdrc_t 173 smb_com_transaction_secondary(smb_request_t *sr) 174 { 175 uint16_t tpscnt, tdscnt, pscnt, psdisp; 176 uint16_t dscnt, dsoff, dsdisp, psoff; 177 smb_xa_t *xa; 178 int rc; 179 180 if ((xa = smbsr_lookup_xa(sr)) == 0) { 181 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 182 return (SDRC_ERROR); 183 } 184 185 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 186 if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { 187 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 188 ERRDOS, ERRnoaccess); 189 return (SDRC_ERROR); 190 } 191 } 192 193 if (xa->smb_com != SMB_COM_TRANSACTION) { 194 return (SDRC_DROP_VC); 195 } 196 197 rc = smbsr_decode_vwv(sr, SMB_TRANSSHDR_ED_FMT, &tpscnt, &tdscnt, 198 &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp); 199 200 if (rc != 0) 201 return (SDRC_ERROR); 202 203 mutex_enter(&xa->xa_mutex); 204 xa->smb_tpscnt = tpscnt; /* might have shrunk */ 205 xa->smb_tdscnt = tdscnt; /* might have shrunk */ 206 xa->req_disp_param = psdisp+pscnt; 207 xa->req_disp_data = dsdisp+dscnt; 208 209 if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 210 mutex_exit(&xa->xa_mutex); 211 smb_xa_close(xa); 212 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 213 return (SDRC_ERROR); 214 } 215 if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 216 mutex_exit(&xa->xa_mutex); 217 smb_xa_close(xa); 218 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 219 return (SDRC_ERROR); 220 } 221 mutex_exit(&xa->xa_mutex); 222 223 if (!smb_trans_ready(xa)) 224 return (SDRC_NO_REPLY); 225 226 if (!smb_xa_complete(xa)) 227 return (SDRC_NO_REPLY); 228 229 return (smb_trans_dispatch(sr, xa)); 230 } 231 232 smb_sdrc_t 233 smb_pre_ioctl(smb_request_t *sr) 234 { 235 DTRACE_SMB_1(op__Ioctl__start, smb_request_t *, sr); 236 return (SDRC_SUCCESS); 237 } 238 239 void 240 smb_post_ioctl(smb_request_t *sr) 241 { 242 DTRACE_SMB_1(op__Ioctl__done, smb_request_t *, sr); 243 } 244 245 smb_sdrc_t 246 smb_com_ioctl(smb_request_t *sr) 247 { 248 uint16_t fid, category, function, tpscnt, tdscnt, mprcnt; 249 uint16_t mdrcnt, pscnt, pdoff, dscnt, dsoff; 250 uint32_t timeout; 251 int rc; 252 253 rc = smbsr_decode_vwv(sr, "wwwwwwwl2.wwww", &fid, &category, &function, 254 &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &timeout, &pscnt, 255 &pdoff, &dscnt, &dsoff); 256 257 if (rc != 0) 258 return (SDRC_ERROR); 259 260 return (SDRC_NOT_IMPLEMENTED); 261 } 262 263 smb_sdrc_t 264 smb_pre_transaction2(smb_request_t *sr) 265 { 266 DTRACE_SMB_1(op__Transaction2__start, smb_request_t *, sr); 267 return (SDRC_SUCCESS); 268 } 269 270 void 271 smb_post_transaction2(smb_request_t *sr) 272 { 273 DTRACE_SMB_1(op__Transaction2__done, smb_request_t *, sr); 274 } 275 276 smb_sdrc_t 277 smb_com_transaction2(struct smb_request *sr) 278 { 279 unsigned char msrcnt, suwcnt; 280 uint16_t tpscnt, tdscnt, mprcnt, mdrcnt, flags; 281 uint16_t pscnt, psoff, dscnt, dsoff; 282 uint32_t timeo; 283 smb_xa_t *xa; 284 int ready; 285 int rc; 286 287 rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, &tpscnt, &tdscnt, 288 &mprcnt, &mdrcnt, &msrcnt, &flags, &timeo, &pscnt, &psoff, &dscnt, 289 &dsoff, &suwcnt); 290 291 if (rc != 0) 292 return (SDRC_ERROR); 293 294 xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, 295 msrcnt, suwcnt); 296 if (xa == 0) { 297 smbsr_error(sr, 0, ERRSRV, ERRnoroom); 298 return (SDRC_ERROR); 299 } 300 301 xa->smb_flags = flags; 302 xa->smb_timeout = timeo; 303 xa->req_disp_param = pscnt; 304 xa->req_disp_data = dscnt; 305 306 if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv, 307 sr->smb_vwv.chain_offset, suwcnt*2)) { 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_param_mb, &sr->command, psoff, pscnt)) { 313 smb_xa_rele(sr->session, xa); 314 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 315 return (SDRC_ERROR); 316 } 317 if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 318 smb_xa_rele(sr->session, xa); 319 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 320 return (SDRC_ERROR); 321 } 322 323 ready = smb_trans_ready(xa); 324 325 if (smb_xa_open(xa)) { 326 smb_xa_rele(sr->session, xa); 327 smbsr_error(sr, 0, ERRDOS, ERRsrverror); 328 return (SDRC_ERROR); 329 } 330 sr->r_xa = xa; 331 332 if (!ready) { 333 rc = smbsr_encode_empty_result(sr); 334 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 335 } 336 337 if (!smb_xa_complete(xa)) { 338 smb_xa_close(xa); 339 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 340 return (SDRC_ERROR); 341 } 342 343 return (smb_trans2_dispatch(sr, xa)); 344 } 345 346 smb_sdrc_t 347 smb_pre_transaction2_secondary(smb_request_t *sr) 348 { 349 DTRACE_SMB_1(op__Transaction2Secondary__start, smb_request_t *, sr); 350 return (SDRC_SUCCESS); 351 } 352 353 void 354 smb_post_transaction2_secondary(smb_request_t *sr) 355 { 356 DTRACE_SMB_1(op__Transaction2Secondary__done, smb_request_t *, sr); 357 } 358 359 smb_sdrc_t 360 smb_com_transaction2_secondary(smb_request_t *sr) 361 { 362 uint16_t tpscnt, tdscnt, fid; 363 uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp; 364 smb_xa_t *xa; 365 int rc; 366 367 if ((xa = smbsr_lookup_xa(sr)) == 0) { 368 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 369 return (SDRC_ERROR); 370 } 371 372 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 373 if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { 374 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 375 ERRDOS, ERRnoaccess); 376 return (SDRC_ERROR); 377 } 378 } 379 380 if (xa->smb_com != SMB_COM_TRANSACTION2) { 381 return (SDRC_DROP_VC); 382 } 383 384 rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt, 385 &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid); 386 387 if (rc != 0) 388 return (SDRC_ERROR); 389 390 mutex_enter(&xa->xa_mutex); 391 xa->smb_tpscnt = tpscnt; /* might have shrunk */ 392 xa->smb_tdscnt = tdscnt; /* might have shrunk */ 393 xa->xa_smb_fid = fid; /* overwrite rules? */ 394 xa->req_disp_param = psdisp + pscnt; 395 xa->req_disp_data = dsdisp + dscnt; 396 397 if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 398 mutex_exit(&xa->xa_mutex); 399 smb_xa_close(xa); 400 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 401 return (SDRC_ERROR); 402 } 403 if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 404 mutex_exit(&xa->xa_mutex); 405 smb_xa_close(xa); 406 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 407 return (SDRC_ERROR); 408 } 409 mutex_exit(&xa->xa_mutex); 410 411 if (!smb_trans_ready(xa)) 412 return (SDRC_NO_REPLY); 413 414 if (!smb_xa_complete(xa)) 415 return (SDRC_NO_REPLY); 416 417 return (smb_trans2_dispatch(sr, xa)); 418 } 419 420 static smb_sdrc_t 421 smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) 422 { 423 int rc; 424 int total_bytes, n_setup, n_param, n_data; 425 int param_off, param_pad, data_off, data_pad; 426 427 n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200; 428 n_setup++; 429 n_setup = n_setup & ~0x0001; 430 n_param = (xa->smb_mprcnt < smb_maxbufsize) 431 ? xa->smb_mprcnt : smb_maxbufsize; 432 n_param++; 433 n_param = n_param & ~0x0001; 434 rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param); 435 n_data = (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc; 436 MBC_INIT(&xa->rep_setup_mb, n_setup * 2); 437 MBC_INIT(&xa->rep_param_mb, n_param); 438 MBC_INIT(&xa->rep_data_mb, n_data); 439 440 switch (xa->smb_func) { 441 case NT_TRANSACT_CREATE: 442 if ((rc = smb_pre_nt_transact_create(sr, xa)) == 0) 443 rc = smb_nt_transact_create(sr, xa); 444 smb_post_nt_transact_create(sr, xa); 445 break; 446 case NT_TRANSACT_NOTIFY_CHANGE: 447 rc = smb_nt_transact_notify_change(sr, xa); 448 break; 449 case NT_TRANSACT_QUERY_SECURITY_DESC: 450 rc = smb_nt_transact_query_security_info(sr, xa); 451 break; 452 case NT_TRANSACT_SET_SECURITY_DESC: 453 rc = smb_nt_transact_set_security_info(sr, xa); 454 break; 455 case NT_TRANSACT_IOCTL: 456 rc = smb_nt_transact_ioctl(sr, xa); 457 break; 458 459 case NT_TRANSACT_QUERY_QUOTA: 460 (void) smb_nt_transact_query_quota(sr, xa); 461 smbsr_error(sr, 0, ERRSRV, ERRaccess); 462 return (SDRC_ERROR); 463 464 case NT_TRANSACT_SET_QUOTA: 465 smbsr_error(sr, 0, ERRSRV, ERRaccess); 466 return (SDRC_ERROR); 467 468 default: 469 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); 470 return (SDRC_ERROR); 471 } 472 473 switch (rc) { 474 case SDRC_SUCCESS: 475 break; 476 477 case SDRC_DROP_VC: 478 case SDRC_NO_REPLY: 479 case SDRC_ERROR: 480 return (rc); 481 482 case SDRC_NOT_IMPLEMENTED: 483 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); 484 return (SDRC_ERROR); 485 486 default: 487 break; 488 } 489 490 n_setup = MBC_LENGTH(&xa->rep_setup_mb); 491 n_param = MBC_LENGTH(&xa->rep_param_mb); 492 n_data = MBC_LENGTH(&xa->rep_data_mb); 493 494 if (xa->smb_msrcnt < n_setup || 495 xa->smb_mprcnt < n_param || 496 xa->smb_mdrcnt < n_data) { 497 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); 498 return (SDRC_ERROR); 499 } 500 501 /* neato, blast it over there */ 502 503 n_setup = (n_setup + 1) / 2; /* Conver to setup words */ 504 param_pad = 1; /* must be one */ 505 param_off = param_pad + 32 + 37 + (n_setup << 1) + 2; 506 data_pad = (4 - ((param_off + n_param) & 3)) % 4; /* Pad to 4 byte */ 507 data_off = param_off + n_param + data_pad; /* Param off from hdr */ 508 total_bytes = param_pad + n_param + data_pad + n_data; 509 510 rc = smbsr_encode_result(sr, 18+n_setup, total_bytes, 511 "b 3. llllllllb C w #. C #. C", 512 18 + n_setup, /* wct */ 513 n_param, /* Total Parameter Bytes */ 514 n_data, /* Total Data Bytes */ 515 n_param, /* Total Parameter Bytes this buffer */ 516 param_off, /* Param offset from header start */ 517 0, /* Param displacement */ 518 n_data, /* Total Data Bytes this buffer */ 519 data_off, /* Data offset from header start */ 520 0, /* Data displacement */ 521 n_setup, /* suwcnt */ 522 &xa->rep_setup_mb, /* setup[] */ 523 total_bytes, /* Total data bytes */ 524 param_pad, 525 &xa->rep_param_mb, 526 data_pad, 527 &xa->rep_data_mb); 528 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 529 } 530 531 532 /* 533 * smb_nt_transact_query_quota 534 * 535 * There are 16 parameter bytes: fid, flags and 12 zero bytes. 536 */ 537 static smb_sdrc_t 538 smb_nt_transact_query_quota(struct smb_request *sr, struct smb_xa *xa) 539 { 540 uint16_t fid; 541 uint16_t flags; 542 543 if (smb_decode_mbc(&xa->req_param_mb, "%ww", sr, &fid, &flags)) 544 return (SDRC_ERROR); 545 546 return (SDRC_SUCCESS); 547 } 548 549 smb_sdrc_t 550 smb_pre_nt_transact(smb_request_t *sr) 551 { 552 DTRACE_SMB_1(op__NtTransact__start, smb_request_t *, sr); 553 return (SDRC_SUCCESS); 554 } 555 556 void 557 smb_post_nt_transact(smb_request_t *sr) 558 { 559 DTRACE_SMB_1(op__NtTransact__done, smb_request_t *, sr); 560 } 561 562 smb_sdrc_t 563 smb_com_nt_transact(struct smb_request *sr) 564 { 565 uint16_t Function; 566 unsigned char MaxSetupCount, SetupCount; 567 uint32_t TotalParameterCount, TotalDataCount; 568 uint32_t MaxParameterCount, MaxDataCount, pscnt; 569 uint32_t psoff, dscnt, dsoff; 570 smb_xa_t *xa; 571 int ready; 572 int rc; 573 574 rc = smbsr_decode_vwv(sr, SMB_NT_TRANSHDR_ED_FMT, &MaxSetupCount, 575 &TotalParameterCount, &TotalDataCount, &MaxParameterCount, 576 &MaxDataCount, &pscnt, &psoff, &dscnt, 577 &dsoff, &SetupCount, &Function); 578 579 if (rc != 0) 580 return (SDRC_ERROR); 581 582 xa = smb_xa_create(sr->session, sr, TotalParameterCount, TotalDataCount, 583 MaxParameterCount, MaxDataCount, MaxSetupCount, SetupCount); 584 if (xa == 0) { 585 smbsr_error(sr, 0, ERRSRV, ERRnoroom); 586 return (SDRC_ERROR); 587 } 588 589 xa->smb_flags = 0; 590 xa->smb_timeout = 0; 591 xa->smb_func = Function; 592 xa->req_disp_param = pscnt; 593 xa->req_disp_data = dscnt; 594 595 if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv, 596 sr->smb_vwv.chain_offset, SetupCount * 2)) { 597 smb_xa_rele(sr->session, xa); 598 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 599 return (SDRC_ERROR); 600 } 601 if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 602 smb_xa_rele(sr->session, xa); 603 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 604 return (SDRC_ERROR); 605 } 606 if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 607 smb_xa_rele(sr->session, xa); 608 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 609 return (SDRC_ERROR); 610 } 611 612 ready = smb_trans_ready(xa); 613 614 if (smb_xa_open(xa)) { 615 smb_xa_rele(sr->session, xa); 616 smbsr_error(sr, 0, ERRDOS, ERRsrverror); 617 return (SDRC_ERROR); 618 } 619 sr->r_xa = xa; 620 621 if (!ready) { 622 rc = smbsr_encode_empty_result(sr); 623 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 624 } 625 626 if (!smb_xa_complete(xa)) { 627 smb_xa_close(xa); 628 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 629 return (SDRC_ERROR); 630 } 631 632 return (smb_nt_trans_dispatch(sr, xa)); 633 } 634 635 smb_sdrc_t 636 smb_pre_nt_transact_secondary(smb_request_t *sr) 637 { 638 DTRACE_SMB_1(op__NtTransactSecondary__start, smb_request_t *, sr); 639 return (SDRC_SUCCESS); 640 } 641 642 void 643 smb_post_nt_transact_secondary(smb_request_t *sr) 644 { 645 DTRACE_SMB_1(op__NtTransactSecondary__done, smb_request_t *, sr); 646 } 647 648 smb_sdrc_t 649 smb_com_nt_transact_secondary(struct smb_request *sr) 650 { 651 uint16_t tpscnt, tdscnt, fid; 652 uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp; 653 smb_xa_t *xa; 654 int rc; 655 656 if ((xa = smbsr_lookup_xa(sr)) == 0) { 657 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 658 return (SDRC_ERROR); 659 } 660 661 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 662 if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { 663 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 664 ERRDOS, ERRnoaccess); 665 return (SDRC_ERROR); 666 } 667 } 668 669 if (xa->smb_com != SMB_COM_TRANSACTION2) { 670 return (SDRC_DROP_VC); 671 } 672 673 rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt, 674 &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid); 675 676 if (rc != 0) 677 return (SDRC_ERROR); 678 679 mutex_enter(&xa->xa_mutex); 680 xa->smb_tpscnt = tpscnt; /* might have shrunk */ 681 xa->smb_tdscnt = tdscnt; /* might have shrunk */ 682 xa->xa_smb_fid = fid; /* overwrite rules? */ 683 xa->req_disp_param = psdisp+pscnt; 684 xa->req_disp_data = dsdisp+dscnt; 685 686 if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 687 mutex_exit(&xa->xa_mutex); 688 smb_xa_close(xa); 689 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 690 return (SDRC_ERROR); 691 } 692 if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 693 mutex_exit(&xa->xa_mutex); 694 smb_xa_close(xa); 695 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 696 return (SDRC_ERROR); 697 } 698 mutex_exit(&xa->xa_mutex); 699 700 if (!smb_trans_ready(xa)) 701 return (SDRC_NO_REPLY); 702 703 if (!smb_xa_complete(xa)) 704 return (SDRC_NO_REPLY); 705 706 return (smb_nt_trans_dispatch(sr, xa)); 707 } 708 709 static int 710 smb_trans_ready(struct smb_xa *xa) 711 { 712 int rc; 713 714 mutex_enter(&xa->xa_mutex); 715 rc = xa->req_disp_data >= xa->smb_tdscnt && 716 xa->req_disp_param >= xa->smb_tpscnt; 717 mutex_exit(&xa->xa_mutex); 718 719 return (rc); 720 } 721 722 723 /* 724 * smb_emit_SHARE_INFO_0 725 * 726 * This function will convert unicode chars to oem chars before 727 * and store the result in a fixed length, MAX_SHARE_NAME_LEN, buffer. If the 728 * length after conversion is longer than 12, -1 will be reported 729 * to indicate an error. The fixed length is a limitation of the 730 * smb protocol. 731 */ 732 static int 733 smb_emit_SHARE_INFO_0(struct mbuf_chain *output, unsigned char *name) 734 { 735 unsigned int cpid = oem_get_smb_cpid(); 736 unsigned int length; 737 char name_buf[MAX_SHARE_NAME_LEN]; 738 mts_wchar_t *unibuf; 739 char *tmpbuf; 740 int rc = 0; 741 742 tmpbuf = (name == NULL) ? "" : (char *)name; 743 length = strlen(tmpbuf) + 1; 744 745 unibuf = kmem_alloc(length * sizeof (mts_wchar_t), KM_SLEEP); 746 (void) mts_mbstowcs(unibuf, tmpbuf, length); 747 748 tmpbuf = kmem_alloc(length, KM_SLEEP); 749 if (unicodestooems(tmpbuf, unibuf, length, cpid) == 0) 750 (void) strcpy(tmpbuf, (char *)name); 751 752 if (strlen(tmpbuf) + 1 <= MAX_SHARE_NAME_LEN) { 753 bzero(name_buf, sizeof (name_buf)); 754 (void) strcpy(name_buf, tmpbuf); 755 (void) smb_encode_mbc(output, "13c", name_buf); 756 } else { 757 rc = -1; 758 } 759 760 kmem_free(unibuf, length * sizeof (mts_wchar_t)); 761 kmem_free(tmpbuf, length); 762 763 return (rc); 764 } 765 766 static int 767 smb_emit_SHARE_INFO_1(struct mbuf_chain *output, struct mbuf_chain *text, 768 unsigned char *name, uint16_t type, 769 unsigned char *comment) 770 { 771 if (smb_emit_SHARE_INFO_0(output, name) < 0) 772 return (-1); 773 774 (void) smb_encode_mbc(output, ".wl", type, MBC_LENGTH(text)); 775 (void) smb_encode_mbc(text, "s", 776 (comment ? comment : (unsigned char *)"No comment")); 777 return (0); 778 } 779 780 static void /*ARGSUSED*/ 781 smb_emit_SHARE_INFO_2(struct mbuf_chain *output, struct mbuf_chain *text, 782 struct smb_request *sr, unsigned char *name, uint16_t type, 783 unsigned char *comment, uint16_t access, char *path, char *password) 784 { 785 unsigned char pword[9]; 786 787 /* 788 * XXX PGD. Is there a bug here? We zero pword, copy password 789 * into pword then ignore it and use password for smb_encode_mbc? 790 */ 791 bzero(pword, sizeof (pword)); 792 (void) strncpy((char *)pword, password, sizeof (pword)); 793 (void) smb_emit_SHARE_INFO_1(output, text, name, type, comment); 794 (void) smb_encode_mbc(output, "wwwl9c.", 795 access, 796 sr->sr_cfg->skc_maxconnections, 797 smb_server_get_session_count(), 798 MBC_LENGTH(text), 799 password); 800 (void) smb_encode_mbc(text, "s", path); 801 } 802 803 /* 804 * is_long_sharename 805 * 806 * This function is extracted from smb_emit_SHARE_INFO_0 only for 807 * finding shares that their names are longer than MAX_SHARE_NAME_LEN. 808 * 809 * The function returns 1 for long share names and 0 when the length 810 * is Ok. 811 */ 812 static boolean_t 813 is_long_sharename(unsigned char *name) 814 { 815 unsigned int cpid = oem_get_smb_cpid(); 816 size_t length; 817 mts_wchar_t *unibuf; 818 char *tmpbuf; 819 boolean_t islong; 820 821 tmpbuf = (name == NULL) ? "" : (char *)name; 822 length = strlen(tmpbuf) + 1; 823 824 unibuf = kmem_alloc(length * sizeof (mts_wchar_t), KM_SLEEP); 825 (void) mts_mbstowcs(unibuf, tmpbuf, length); 826 827 tmpbuf = kmem_alloc(length, KM_SLEEP); 828 if (unicodestooems(tmpbuf, unibuf, length, cpid) == 0) 829 (void) strcpy(tmpbuf, (char *)name); 830 831 islong = (strlen(tmpbuf) + 1 > MAX_SHARE_NAME_LEN); 832 833 kmem_free(unibuf, length * sizeof (mts_wchar_t)); 834 kmem_free(tmpbuf, length); 835 836 return (islong); 837 } 838 839 /* 840 * This structure holds information about shares which will 841 * fit in the specified client buffer size. 842 * 843 * sei_bufsize: Client specified buffer size 844 * sei_count: Maximum number of shares that can be 845 * sent in the buffer. 846 * 847 * The return data section consists of a number of SHARE_INFO_1 structures. 848 * In case there are multiple SHARE_INFO_1 data structures to return this 849 * function put all fixed length part of these structures in the return buffer 850 * and then put all the variable length data (shares' comment) at the end of 851 * buffer. 852 * 853 * sei_info_len: Size of fixed length part of SHARE_INFO_1 854 * structures for sei_count shares 855 * sei_cmnt_len: Size of comments for sei_count shares 856 */ 857 typedef struct { 858 uint16_t sei_bufsize; 859 short sei_count; 860 int sei_infolen; 861 int sei_cmntlen; 862 } smb_share_enum_t; 863 864 /* 865 * smb_share_update_info 866 * 867 * Check to see if the given buffer has enough 868 * room to fit the information of the given share. 869 * If there is enough room update the passed max_??? 870 * information. 871 * 872 * Return 1 if buffer is not full yet, 0 if it's full. 873 */ 874 static int 875 smb_share_update_info(door_handle_t dhdl, lmshare_info_t *si, 876 smb_share_enum_t *shr_enum_info) 877 { 878 int cmnt_len; 879 int new_info_len = shr_enum_info->sei_infolen; 880 int new_cmnt_len = shr_enum_info->sei_cmntlen; 881 882 if (lmshrd_is_special(dhdl, si->share_name)) 883 cmnt_len = 1; 884 else 885 cmnt_len = (strlen(si->comment) + 1); 886 887 new_info_len += SHARE_INFO_1_SIZE; 888 new_cmnt_len += cmnt_len; 889 890 if ((new_info_len + new_cmnt_len) < shr_enum_info->sei_bufsize) { 891 shr_enum_info->sei_count++; 892 shr_enum_info->sei_infolen = new_info_len; 893 shr_enum_info->sei_cmntlen = new_cmnt_len; 894 return (1); 895 } 896 897 return (0); 898 } 899 900 /* 901 * smb_share_skip_share 902 * 903 * Determines whether the given share should be enumerated 904 * or not. The share will not be enumerated if its name is 905 * long or it's autohome share. 906 * 907 * Return 1 if the share should be skipped; otherwise returns 908 * 0 909 */ 910 static int 911 smb_share_skip_share(lmshare_info_t *si) 912 { 913 if (is_long_sharename((unsigned char *)si->share_name)) { 914 return (1); 915 } 916 917 /* Skip autohome share if autohome filter is enabled */ 918 if (si->mode == LMSHRM_TRANS) { 919 return (1); 920 } 921 922 return (0); 923 } 924 925 /* 926 * smb_share_add_autohome 927 * 928 * Determines if an autohome share should be added to shares' list 929 * for the given user. 930 * Autohome will be add when all the following conditions are true: 931 * 932 * 1. Autohome feature is enabled 933 * 2. A share with the same name as the given user exists 934 * 3. The share is not a permanent share 935 * 4. Share name is not longer than maximum allowed 936 */ 937 static int 938 smb_share_add_autohome(door_handle_t dhdl, char *username, lmshare_info_t *si) 939 { 940 int do_add = 0; 941 942 do_add = (lmshrd_getinfo(dhdl, username, si) == NERR_Success) && 943 (si->mode & LMSHRM_TRANS) && 944 (!is_long_sharename((unsigned char *)(si->share_name))); 945 946 return (do_add); 947 } 948 949 /* 950 * smb_share_total_info 951 * 952 * This function calculates following informations 953 * - Maximum number of shares that can be sent for clients 954 * according to its buffer size (cli_bufsize) 955 * - length of fixed information about above shares 956 * - length of comments of above shares 957 * - total number of shares that their names are no longer 958 * than MAX_SHARE_NAME_LEN. 959 * 960 * Added SMB user object to the parameter list to filter out other 961 * user autohome shares. 962 */ 963 static void 964 smb_share_total_info(door_handle_t dhdl, smb_share_enum_t *shr_enum_info, 965 short *tot_shares_num, smb_user_t *user) 966 { 967 uint64_t iterator; 968 lmshare_info_t *si; 969 struct lmshare_info *auto_si; 970 int more_room = 1; 971 972 si = kmem_zalloc(sizeof (lmshare_info_t), KM_SLEEP); 973 auto_si = kmem_zalloc(sizeof (struct lmshare_info), KM_SLEEP); 974 975 *tot_shares_num = 0; 976 shr_enum_info->sei_count = 0; 977 shr_enum_info->sei_infolen = 0; 978 shr_enum_info->sei_cmntlen = 0; 979 980 if (smb_share_add_autohome(dhdl, user->u_name, auto_si)) { 981 (*tot_shares_num)++; 982 more_room = smb_share_update_info(dhdl, auto_si, shr_enum_info); 983 } 984 985 iterator = lmshrd_open_iterator(dhdl, LMSHRM_ALL); 986 if (iterator == 0) { 987 kmem_free(si, sizeof (lmshare_info_t)); 988 kmem_free(auto_si, sizeof (struct lmshare_info)); 989 return; 990 } 991 992 /* check for door errors */ 993 if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) { 994 (void) lmshrd_close_iterator(dhdl, iterator); 995 kmem_free(si, sizeof (lmshare_info_t)); 996 kmem_free(auto_si, sizeof (struct lmshare_info)); 997 return; 998 } 999 1000 while (*si->share_name != 0) { 1001 if (smb_share_skip_share(si)) { 1002 /* check for door errors */ 1003 if (lmshrd_iterate(dhdl, iterator, si) != 1004 NERR_Success) { 1005 (void) lmshrd_close_iterator(dhdl, iterator); 1006 kmem_free(si, sizeof (lmshare_info_t)); 1007 kmem_free(auto_si, 1008 sizeof (struct lmshare_info)); 1009 return; 1010 } 1011 continue; 1012 } 1013 1014 (*tot_shares_num)++; 1015 1016 if (more_room) { 1017 more_room = smb_share_update_info(dhdl, si, 1018 shr_enum_info); 1019 } 1020 1021 /* check for door errors */ 1022 if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) { 1023 (void) lmshrd_close_iterator(dhdl, iterator); 1024 kmem_free(si, sizeof (lmshare_info_t)); 1025 kmem_free(auto_si, sizeof (struct lmshare_info)); 1026 return; 1027 } 1028 } 1029 1030 (void) lmshrd_close_iterator(dhdl, iterator); 1031 kmem_free(si, sizeof (lmshare_info_t)); 1032 kmem_free(auto_si, sizeof (struct lmshare_info)); 1033 } 1034 1035 /* 1036 * smb_encode_SHARE_INFO_1 1037 * 1038 * This function is extracted from smb_emit_SHARE_INFO_1 and only 1039 * encodes fixed part of SHARE_INFO_1 structure. 1040 * 1041 * The function returns -1 if encoding fails and 0 on success. 1042 */ 1043 static int 1044 smb_encode_SHARE_INFO_1(struct mbuf_chain *output, unsigned char *name, 1045 uint16_t type, int cmnt_len) 1046 { 1047 if (smb_emit_SHARE_INFO_0(output, name) < 0) 1048 return (-1); 1049 (void) smb_encode_mbc(output, ".wl", type, cmnt_len); 1050 return (0); 1051 } 1052 1053 /* 1054 * collect_shares_info 1055 * 1056 * This function encodes information of shares_num of shares 1057 * into data_mb and cmnt_str. 1058 * 1059 * Added SMB user object to the parameter list to filter out other 1060 * user autohome shares. 1061 * 1062 */ 1063 static void 1064 collect_shares_info(door_handle_t dhdl, uint64_t iterator, int shares_num, 1065 struct mbuf_chain *data_mb, char *cmnt_str, int *cmnt_len, smb_user_t *user, 1066 int first_resp) 1067 { 1068 int i = 0; 1069 lmshare_info_t *si; 1070 struct lmshare_info *tsi; 1071 int is_special; 1072 1073 si = kmem_zalloc(sizeof (lmshare_info_t), KM_SLEEP); 1074 tsi = kmem_zalloc(sizeof (struct lmshare_info), KM_SLEEP); 1075 1076 if (first_resp && smb_share_add_autohome(dhdl, user->u_name, tsi)) { 1077 if (smb_encode_SHARE_INFO_1(data_mb, 1078 (unsigned char *)tsi->share_name, 1079 tsi->stype, *cmnt_len) == 0) { 1080 (void) memcpy(cmnt_str+(*cmnt_len), 1081 tsi->comment, strlen(tsi->comment)+1); 1082 (*cmnt_len) += (strlen(tsi->comment) + 1); 1083 i++; 1084 } 1085 } 1086 1087 /* check for door errors */ 1088 if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) { 1089 kmem_free(si, sizeof (lmshare_info_t)); 1090 kmem_free(tsi, sizeof (struct lmshare_info)); 1091 return; 1092 } 1093 1094 while ((i < shares_num) && (*si->share_name != 0)) { 1095 if (smb_share_skip_share(si)) { 1096 goto next; 1097 } 1098 1099 1100 is_special = lmshrd_is_special(dhdl, si->share_name); 1101 /* check for door errors */ 1102 if (is_special == NERR_InternalError) { 1103 kmem_free(si, sizeof (lmshare_info_t)); 1104 kmem_free(tsi, sizeof (struct lmshare_info)); 1105 return; 1106 } 1107 1108 if (is_special) { 1109 si->stype |= STYPE_HIDDEN; 1110 if (smb_encode_SHARE_INFO_1(data_mb, 1111 (unsigned char *)si->share_name, 1112 si->stype, *cmnt_len) < 0) { 1113 goto next; 1114 } 1115 cmnt_str[*cmnt_len] = '\0'; 1116 (*cmnt_len)++; 1117 } else { 1118 if (smb_encode_SHARE_INFO_1(data_mb, 1119 (unsigned char *)si->share_name, si->stype, 1120 *cmnt_len) < 0) { 1121 goto next; 1122 } 1123 (void) memcpy(cmnt_str+(*cmnt_len), si->comment, 1124 strlen(si->comment)+1); 1125 (*cmnt_len) += (strlen(si->comment) + 1); 1126 } 1127 1128 next: 1129 /* check for door errors */ 1130 if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) { 1131 kmem_free(si, sizeof (lmshare_info_t)); 1132 kmem_free(tsi, sizeof (struct lmshare_info)); 1133 return; 1134 } 1135 } 1136 kmem_free(si, sizeof (lmshare_info_t)); 1137 kmem_free(tsi, sizeof (struct lmshare_info)); 1138 } 1139 1140 int 1141 smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa) 1142 { 1143 door_handle_t dhdl = sr->sr_server->sv_lmshrd; 1144 smb_share_enum_t shr_enum_info; 1145 short left_shares_cnt; /* Number of shares not sent yet */ 1146 1147 /* 1148 * Number of shares that should be sent 1149 * in the current response packet. 1150 * It can be a number between 0 and 1151 * max_share_scnt. 1152 */ 1153 short shares_scnt; 1154 1155 /* 1156 * Maximum number of shares that can be 1157 * sent in one response packet regarding 1158 * the maximum negotiated buffer size 1159 * for SMB messages. 1160 */ 1161 short max_shares_per_packet; 1162 1163 /* 1164 * Total number of shares on the server 1165 * that their name is not greater than 1166 * MAX_SHARE_NAME_LEN 1167 */ 1168 short shares_tot_num; 1169 1170 /* 1171 * Size of total data (info + cmnt) 1172 * that should be sent for client 1173 */ 1174 int shares_tot_byte; 1175 1176 /* 1177 * Maximum size of data that can be 1178 * sent in one SMB transaction response 1179 * according to the maximum negotiated 1180 * buffer size for SMB packets 1181 */ 1182 int data_buf_limit; 1183 1184 /* 1185 * Number of comment bytes that will 1186 * be sent in the current response 1187 */ 1188 uint16_t cmnt_scnt; 1189 1190 /* 1191 * Number of data bytes that will 1192 * be sent in the current response 1193 */ 1194 uint16_t data_scnt; 1195 1196 /* 1197 * Total number of data bytes that 1198 * are sent till now. This is only 1199 * used for calculating current data 1200 * displacement 1201 */ 1202 uint16_t tot_data_scnt; 1203 1204 /* 1205 * Number of parameter bytes should 1206 * be sent for the current response. 1207 * It is 8 for the 1st response and 1208 * 0 for others 1209 */ 1210 uint16_t param_scnt; 1211 1212 /* number of setup and parameter bytes */ 1213 uint16_t n_setup, n_param; 1214 1215 /* data and parameter displacement */ 1216 uint16_t data_disp, param_disp; 1217 1218 /* return status by the 1st reply */ 1219 uint16_t ret_stat; 1220 1221 /* parameter and data offset and pad */ 1222 int param_off, param_pad, data_off, data_pad; 1223 1224 /* 1225 * total bytes of parameters and data 1226 * in the packet, plus the pad bytes. 1227 */ 1228 int tot_packet_bytes; 1229 1230 char first_resp; 1231 uint16_t opcode, level, cli_bufsize; 1232 unsigned char *r_fmt; 1233 char fmt[10]; 1234 uint64_t iterator; 1235 char *cmnt_str, *cmnt_start; 1236 int cmnt_len; 1237 struct mbuf_chain reply; 1238 smb_user_t *user; 1239 size_t cmnt_size; 1240 1241 user = sr->uid_user; 1242 ASSERT(user); 1243 1244 /* 1245 * Initialize the mbuf chain of reply to zero. If it is not 1246 * zero, code inside the while loop will try to free the chain. 1247 */ 1248 bzero(&reply, sizeof (struct mbuf_chain)); 1249 1250 if (smb_decode_mbc(&xa->req_param_mb, "%wss(lev)w(size)w", sr, 1251 &opcode, &r_fmt, &r_fmt, &level, &cli_bufsize) != 0) 1252 return (SDRC_NOT_IMPLEMENTED); 1253 1254 if (level != 1) { 1255 (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 1256 NERR_BadTransactConfig, 0, 0, 0); 1257 return (SDRC_SUCCESS); 1258 } 1259 1260 n_setup = 0; /* Setup count for NetShareEnum SMB is 0 */ 1261 n_param = 8; 1262 data_buf_limit = sr->session->smb_msg_size - 1263 (SMB_HEADER_ED_LEN + RESP_HEADER_LEN + n_param); 1264 1265 shr_enum_info.sei_bufsize = cli_bufsize; 1266 smb_share_total_info(dhdl, &shr_enum_info, &shares_tot_num, user); 1267 1268 shares_tot_byte = shr_enum_info.sei_infolen + shr_enum_info.sei_cmntlen; 1269 1270 /* Check buffer to have enough space */ 1271 if (shares_tot_byte == 0) { 1272 (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 1273 ERROR_NOT_ENOUGH_MEMORY, 0, 0, 0); 1274 return (SDRC_SUCCESS); 1275 } 1276 1277 max_shares_per_packet = data_buf_limit / SHARE_INFO_1_SIZE; 1278 1279 shares_scnt = (shr_enum_info.sei_count > max_shares_per_packet) 1280 ? max_shares_per_packet : shr_enum_info.sei_count; 1281 1282 cmnt_size = shr_enum_info.sei_cmntlen * sizeof (char); 1283 cmnt_str = kmem_alloc(cmnt_size, KM_SLEEP); 1284 cmnt_len = 0; 1285 /* save start of buffer to free it at the end of function */ 1286 cmnt_start = cmnt_str; 1287 1288 iterator = lmshrd_open_iterator(dhdl, LMSHRM_ALL); 1289 1290 if (iterator == NULL) { 1291 kmem_free(cmnt_start, cmnt_size); 1292 return (SDRC_DROP_VC); 1293 } 1294 1295 /* 1296 * The rep_setup_mb is already initialized in smb_trans_dispatch(). 1297 * Calling MBC_INIT() will initialized the structure and so the 1298 * pointer to the mbuf chains will be lost. Therefore, we need 1299 * to free the resources before calling MBC_INIT() again. 1300 */ 1301 m_freem(xa->rep_setup_mb.chain); 1302 MBC_INIT(&xa->rep_setup_mb, n_setup * 2); 1303 1304 left_shares_cnt = shr_enum_info.sei_count; 1305 tot_data_scnt = 0; 1306 cmnt_scnt = 0; 1307 1308 first_resp = 1; 1309 while (tot_data_scnt < shares_tot_byte) { 1310 /* 1311 * Calling MBC_INIT() will initialized the structure and so the 1312 * pointer to the mbuf chains will be lost. Therefore, we need 1313 * to free the resources if any before calling MBC_INIT(). 1314 */ 1315 m_freem(xa->rep_data_mb.chain); 1316 MBC_INIT(&xa->rep_data_mb, data_buf_limit); 1317 collect_shares_info(dhdl, iterator, 1318 shares_scnt, &xa->rep_data_mb, cmnt_str, &cmnt_len, user, 1319 first_resp); 1320 data_scnt = shares_scnt * SHARE_INFO_1_SIZE; 1321 left_shares_cnt -= shares_scnt; 1322 if (left_shares_cnt < max_shares_per_packet) 1323 shares_scnt = left_shares_cnt; 1324 if (left_shares_cnt == 0) { 1325 /* 1326 * Now send comments. 1327 * Append comments to the end of share_info_1 1328 * structures. 1329 */ 1330 cmnt_scnt = data_buf_limit - 1331 MBC_LENGTH(&xa->rep_data_mb); 1332 if (cmnt_scnt > shr_enum_info.sei_cmntlen) { 1333 /*LINTED E_ASSIGN_NARROW_CONV*/ 1334 cmnt_scnt = shr_enum_info.sei_cmntlen; 1335 } 1336 (void) sprintf(fmt, "%dc", cmnt_scnt); 1337 (void) smb_encode_mbc(&xa->rep_data_mb, fmt, cmnt_str); 1338 cmnt_str += cmnt_scnt; 1339 shr_enum_info.sei_cmntlen -= cmnt_scnt; 1340 } 1341 data_scnt += cmnt_scnt; 1342 tot_data_scnt += data_scnt; 1343 1344 /* Only the 1st response packet contains parameters */ 1345 param_scnt = (first_resp) ? n_param : 0; 1346 param_pad = 1; /* always one */ 1347 param_off = SMB_HEADER_ED_LEN + RESP_HEADER_LEN; 1348 param_disp = (first_resp) ? 0 : n_param; 1349 1350 /* 1351 * Calling MBC_INIT() will initialized the structure and so the 1352 * pointer to the mbuf chains will be lost. Therefore, we need 1353 * to free the resources if any before calling MBC_INIT(). 1354 */ 1355 m_freem(xa->rep_param_mb.chain); 1356 MBC_INIT(&xa->rep_param_mb, param_scnt); 1357 if (first_resp) { 1358 first_resp = 0; 1359 /* Prepare parameters for the 1st response packet */ 1360 ret_stat = (shares_tot_num > shr_enum_info.sei_count) 1361 ? ERROR_MORE_DATA : 0; 1362 (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 1363 ret_stat, -shr_enum_info.sei_infolen, 1364 shr_enum_info.sei_count, 1365 shares_tot_num); 1366 } 1367 1368 data_pad = (param_off + n_param) & 1; /* Pad to short */ 1369 1370 /* data off from hdr start */ 1371 data_off = param_off + param_scnt + data_pad; 1372 data_disp = tot_data_scnt - data_scnt; 1373 tot_packet_bytes = param_pad + param_scnt + data_pad + 1374 data_scnt; 1375 1376 /* 1377 * Calling MBC_INIT() will initialized the structure and so the 1378 * pointer to the mbuf chains will be lost. Therefore, we need 1379 * to free the resources if any before calling MBC_INIT(). 1380 */ 1381 m_freem(reply.chain); 1382 MBC_INIT(&reply, SMB_HEADER_ED_LEN 1383 + sizeof (uchar_t) /* word parameters count */ 1384 + 10*sizeof (ushort_t) /* word parameters */ 1385 + n_setup*sizeof (ushort_t) /* setup parameters */ 1386 + sizeof (ushort_t) /* total data byte count */ 1387 + tot_packet_bytes); 1388 1389 (void) smb_encode_mbc(&reply, SMB_HEADER_ED_FMT, 1390 sr->first_smb_com, 1391 sr->smb_rcls, 1392 sr->smb_reh, 1393 sr->smb_err, 1394 sr->smb_flg | SMB_FLAGS_REPLY, 1395 sr->smb_flg2, 1396 sr->smb_pid_high, 1397 sr->smb_sig, 1398 sr->smb_tid, 1399 sr->smb_pid, 1400 sr->smb_uid, 1401 sr->smb_mid); 1402 1403 (void) smb_encode_mbc(&reply, 1404 "b ww 2. www www b . C w #. C #. C", 1405 10 + n_setup, /* wct */ 1406 n_param, /* Total Parameter Bytes */ 1407 shares_tot_byte, /* Total Data Bytes */ 1408 param_scnt, /* Total Parameter Bytes this buffer */ 1409 param_off, /* Param offset from header start */ 1410 param_disp, /* Param displacement */ 1411 data_scnt, /* Total Data Bytes this buffer */ 1412 data_off, /* Data offset from header start */ 1413 data_disp, /* Data displacement */ 1414 n_setup, /* suwcnt */ 1415 &xa->rep_setup_mb, /* setup[] */ 1416 tot_packet_bytes, /* Total data bytes */ 1417 param_pad, 1418 &xa->rep_param_mb, 1419 data_pad, 1420 &xa->rep_data_mb); 1421 1422 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) 1423 smb_sign_reply(sr, NULL); 1424 1425 (void) smb_session_send(sr->session, 0, &reply); 1426 } 1427 1428 (void) lmshrd_close_iterator(dhdl, iterator); 1429 kmem_free(cmnt_start, cmnt_size); 1430 return (SDRC_NO_REPLY); 1431 } 1432 1433 int 1434 smb_trans_net_share_get_info(smb_request_t *sr, struct smb_xa *xa) 1435 { 1436 uint16_t opcode, level, max_bytes, access; 1437 uint32_t type; 1438 unsigned char *req_fmt; 1439 unsigned char *rep_fmt; 1440 struct mbuf_chain str_mb; 1441 char *share; 1442 char *path; 1443 char *password; 1444 char *comment; 1445 lmshare_info_t si; 1446 int shr_found; 1447 1448 if (smb_decode_mbc(&xa->req_param_mb, "%wsss(lev)w(size)w", sr, 1449 &opcode, &req_fmt, &rep_fmt, &share, &level, &max_bytes) != 0) 1450 return (SDRC_NOT_IMPLEMENTED); 1451 1452 (void) utf8_strlwr(share); 1453 shr_found = lmshrd_getinfo(sr->sr_server->sv_lmshrd, share, &si); 1454 if (strcmp(share, "ipc$") == 0) { 1455 type = STYPE_IPC; 1456 path = ""; 1457 password = ""; 1458 access = SHARE_ACCESS_ALL; 1459 } else if (shr_found) { 1460 path = si.directory; 1461 type = STYPE_DISKTREE; 1462 if (path[strlen(path)] == '$') 1463 type |= STYPE_HIDDEN; 1464 password = ""; 1465 access = SHARE_ACCESS_ALL; 1466 } else { 1467 /* We have no idea what this share is... */ 1468 (void) smb_encode_mbc(&xa->rep_param_mb, "www", 1469 NERR_NetNameNotFound, 0, 0); 1470 return (SDRC_SUCCESS); 1471 } 1472 1473 if (shr_found) 1474 comment = si.comment; 1475 else 1476 comment = ""; 1477 1478 password = ""; 1479 1480 MBC_INIT(&str_mb, max_bytes); 1481 1482 switch (level) { 1483 case 0 : 1484 (void) smb_emit_SHARE_INFO_0(&xa->rep_data_mb, 1485 (unsigned char *)share); 1486 break; 1487 1488 case 1 : 1489 (void) smb_emit_SHARE_INFO_1(&xa->rep_data_mb, &str_mb, 1490 (unsigned char *)share, type, 1491 (unsigned char *)comment); 1492 break; 1493 1494 case 2 : 1495 smb_emit_SHARE_INFO_2(&xa->rep_data_mb, &str_mb, sr, 1496 (unsigned char *)share, type, (unsigned char *)comment, 1497 access, path, password); 1498 default: 1499 m_freem(str_mb.chain); 1500 return (SDRC_NOT_IMPLEMENTED); 1501 } 1502 1503 (void) smb_encode_mbc(&xa->rep_param_mb, "www", 0, 1504 -MBC_LENGTH(&xa->rep_data_mb), 1505 MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb)); 1506 (void) smb_encode_mbc(&xa->rep_data_mb, "C", &str_mb); 1507 m_freem(str_mb.chain); 1508 return (SDRC_SUCCESS); 1509 } 1510 1511 int 1512 smb_trans_net_workstation_get_info(struct smb_request *sr, struct smb_xa *xa) 1513 { 1514 uint16_t opcode, level, max_bytes; 1515 unsigned char *req_fmt; 1516 unsigned char *rep_fmt; 1517 struct mbuf_chain str_mb; 1518 char *domain; 1519 char *hostname; 1520 1521 if ((smb_decode_mbc(&xa->req_param_mb, "%wss(lev)w(size)w", sr, 1522 &opcode, &req_fmt, &rep_fmt, &level, &max_bytes) != 0) || 1523 (level != 10)) { 1524 (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 1525 NERR_BadTransactConfig, 0, 0, 0); 1526 return (SDRC_SUCCESS); 1527 } 1528 1529 domain = sr->sr_cfg->skc_resource_domain; 1530 hostname = sr->sr_cfg->skc_hostname; 1531 1532 MBC_INIT(&str_mb, max_bytes); 1533 1534 (void) smb_encode_mbc(&str_mb, "."); /* Prevent NULL pointers */ 1535 1536 (void) smb_encode_mbc(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 1537 (void) smb_encode_mbc(&str_mb, "s", hostname); 1538 (void) smb_encode_mbc(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 1539 (void) smb_encode_mbc(&str_mb, "s", "nobody"); 1540 (void) smb_encode_mbc(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 1541 (void) smb_encode_mbc(&str_mb, "s", domain); 1542 (void) smb_encode_mbc(&xa->rep_data_mb, "bbl", 1543 SMB_VERSION_MAJOR, SMB_VERSION_MINOR, MBC_LENGTH(&str_mb)); 1544 (void) smb_encode_mbc(&str_mb, "s", domain); 1545 (void) smb_encode_mbc(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 1546 (void) smb_encode_mbc(&str_mb, "s", domain); 1547 1548 (void) smb_encode_mbc(&xa->rep_param_mb, "www", 0, 1549 -MBC_LENGTH(&xa->rep_data_mb), 1550 MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb)); 1551 (void) smb_encode_mbc(&xa->rep_data_mb, "C", &str_mb); 1552 m_freem(str_mb.chain); 1553 return (SDRC_SUCCESS); 1554 } 1555 1556 int 1557 smb_trans_net_user_get_info(struct smb_request *sr, struct smb_xa *xa) 1558 { 1559 uint16_t opcode, level, max_bytes; 1560 unsigned char *req_fmt; 1561 unsigned char *rep_fmt; 1562 unsigned char *user; 1563 int rc; 1564 1565 rc = smb_decode_mbc(&xa->req_param_mb, "%wssww", sr, 1566 &opcode, 1567 &req_fmt, 1568 &rep_fmt, 1569 &user, 1570 &level, 1571 &max_bytes); 1572 1573 if (rc != 0) 1574 return (SDRC_NOT_IMPLEMENTED); 1575 1576 (void) smb_encode_mbc(&xa->rep_param_mb, "www", 1577 NERR_UserNotFound, 0, 0); 1578 return (SDRC_SUCCESS); 1579 } 1580 1581 smb_sdrc_t 1582 smb_trans_server_get_info(struct smb_request *sr, struct smb_xa *xa) 1583 { 1584 uint16_t opcode, level, buf_size; 1585 char *req_fmt; 1586 char *rep_fmt; 1587 char server_name[16]; 1588 struct mbuf_chain str_mb; 1589 char *hostname; 1590 char *comment; 1591 1592 if (smb_decode_mbc(&xa->req_param_mb, "%wssww", sr, 1593 &opcode, &req_fmt, &rep_fmt, &level, &buf_size) != 0) { 1594 return (SDRC_ERROR); 1595 } 1596 1597 comment = sr->sr_cfg->skc_system_comment; 1598 hostname = sr->sr_cfg->skc_hostname; 1599 1600 MBC_INIT(&str_mb, buf_size); 1601 1602 bzero(server_name, sizeof (server_name)); 1603 (void) strncpy(server_name, hostname, sizeof (server_name)); 1604 1605 switch (level) { 1606 case 0: 1607 (void) smb_encode_mbc(&xa->rep_data_mb, "16c", server_name); 1608 break; 1609 case 1: 1610 (void) smb_encode_mbc(&str_mb, "."); /* Prevent NULL pointers */ 1611 (void) smb_encode_mbc(&xa->rep_data_mb, "16cbbll", server_name, 1612 SMB_VERSION_MAJOR, SMB_VERSION_MINOR, 1613 MY_SERVER_TYPE, MBC_LENGTH(&str_mb)); 1614 (void) smb_encode_mbc(&str_mb, "s", comment); 1615 break; 1616 case 2: 1617 /* B16BBDzDDDWWzWWWWWWWB21BzWWWWWWWWWWWWWWWWWWWWWWz */ 1618 (void) smb_encode_mbc(&str_mb, "."); /* Prevent NULL pointers */ 1619 /* B16BBDz */ 1620 (void) smb_encode_mbc(&xa->rep_data_mb, "16cbbll", server_name, 1621 SMB_VERSION_MAJOR, 1622 SMB_VERSION_MINOR, MY_SERVER_TYPE, MBC_LENGTH(&str_mb)); 1623 (void) smb_encode_mbc(&str_mb, "s", comment); 1624 (void) smb_encode_mbc(&xa->rep_data_mb, "lllwwl", 1625 (uint32_t)1, 1626 (uint32_t)2, 1627 (uint32_t)3, 1628 (uint16_t)4, 1629 (uint16_t)5, 1630 MBC_LENGTH(&str_mb)); 1631 (void) smb_encode_mbc(&str_mb, "s", "str1"); 1632 (void) smb_encode_mbc(&xa->rep_data_mb, "wwwwwww21cbl", 1633 (uint16_t)6, 1634 (uint16_t)7, 1635 (uint16_t)8, 1636 (uint16_t)9, 1637 (uint16_t)10, 1638 (uint16_t)11, 1639 (uint16_t)12, 1640 "21 byte comment ", 1641 (unsigned char)13, 1642 MBC_LENGTH(&str_mb)); 1643 (void) smb_encode_mbc(&str_mb, "s", "str2"); 1644 (void) smb_encode_mbc(&xa->rep_data_mb, 1645 "wwwwwwwwwwwwwwwwwwwwwwl", 1646 (uint16_t)14, 1647 (uint16_t)15, 1648 (uint16_t)16, 1649 (uint16_t)17, 1650 (uint16_t)18, 1651 (uint16_t)19, 1652 (uint16_t)20, 1653 (uint16_t)21, 1654 (uint16_t)22, 1655 (uint16_t)23, 1656 (uint16_t)24, 1657 (uint16_t)25, 1658 (uint16_t)26, 1659 (uint16_t)27, 1660 (uint16_t)28, 1661 (uint16_t)29, 1662 (uint16_t)20, 1663 (uint16_t)31, 1664 (uint16_t)32, 1665 (uint16_t)33, 1666 (uint16_t)34, 1667 (uint16_t)35, 1668 MBC_LENGTH(&str_mb)); 1669 (void) smb_encode_mbc(&str_mb, "s", "str3"); 1670 break; 1671 default: 1672 m_freem(str_mb.chain); 1673 return (SDRC_NOT_IMPLEMENTED); 1674 } 1675 1676 (void) smb_encode_mbc(&xa->rep_param_mb, "www", 0, 1677 -MBC_LENGTH(&xa->rep_data_mb), 1678 (MBC_LENGTH(&xa->rep_data_mb)) + 1679 (MBC_LENGTH(&str_mb))); 1680 (void) smb_encode_mbc(&xa->rep_data_mb, "C", &str_mb); 1681 m_freem(str_mb.chain); 1682 return (SDRC_SUCCESS); 1683 } 1684 1685 /* 1686 * 6.4 The NetServerEnum2 RAP Service 1687 * 1688 * The NetServerEnum2 RAP service lists all computers of the specified type 1689 * or types that are visible in the specified domains. It may also 1690 * enumerate domains. 1691 * 1692 * The following definition uses the notation and terminology defined in 1693 * the CIFS Remote Administration Protocol specification, which is required 1694 * in order to make it well-defined. The definition is: 1695 * 1696 * uint16_t NetServerEnum2 ( 1697 * uint16_t sLevel, 1698 * RCVBUF pbBuffer, 1699 * RCVBUFLEN cbBuffer, 1700 * ENTCOUNT pcEntriesRead, 1701 * uint16_t *pcTotalAvail, 1702 * uint32_t fServerType, 1703 * char *pszDomain, 1704 * ); 1705 * 1706 * where: 1707 * 1708 * sLevel specifies the level of detail (0 or 1) requested. 1709 * 1710 * pbBuffer points to the buffer to receive the returned data. If the 1711 * function is successful, the buffer contains a sequence of 1712 * server_info_x structures, where x is 0 or 1, depending on the 1713 * level of detail requested. 1714 * 1715 * cbBuffer specifies the size, in bytes, of the buffer pointed to by 1716 * the pbBuffer parameter. 1717 * 1718 * pcEntriesRead points to a 16 bit variable that receives a count of 1719 * the number of servers enumerated in the buffer. This count is 1720 * valid only if NetServerEnum2 returns the NERR_Success or 1721 * ERROR_MORE_DATA values. 1722 * 1723 * pcTotal Avail points to a 16 bit variable that receives a count of 1724 * the total number of available entries. This count is valid only if 1725 * NetServerEnum2 returns the NERR_Success or ERROR_MORE_DATA values. 1726 * 1727 * fServerType specifies the type or types of computers to enumerate. 1728 * Computers that match at least one of the specified types are 1729 * returned in the buffer. Possible values are defined in the request 1730 * parameters section. 1731 * 1732 * pszDomain points to a null-terminated string that contains the 1733 * name of the workgroup in which to enumerate computers of the 1734 * specified type or types. If the pszDomain parameter is a null 1735 * string or a null pointer, servers are enumerated for the current 1736 * domain of the computer. 1737 * 1738 * 6.4.1 Transaction Request Parameters section 1739 * 1740 * The Transaction request parameters section in this instance contains: 1741 * . The 16 bit function number for NetServerEnum2 which is 104. 1742 * . The parameter descriptor string which is "WrLehDz". 1743 * . The data descriptor string for the (returned) data which is "B16" for 1744 * level detail 0 or "B16BBDz" for level detail 1. 1745 * . The actual parameters as described by the parameter descriptor 1746 * string. 1747 * 1748 * The parameters are: 1749 * . A 16 bit integer with a value of 0 or 1 (corresponding to the "W" in 1750 * the parameter descriptor string. This represents the level of detail 1751 * the server is expected to return 1752 * . A 16 bit integer that contains the size of the receive buffer. 1753 * . A 32 bit integer that represents the type of servers the function 1754 * should enumerate. The possible values may be any of the following or 1755 * a combination of the following: 1756 * 1757 * SV_TYPE_WORKSTATION 0x00000001 All workstations 1758 * SV_TYPE_SERVER 0x00000002 All servers 1759 * SV_TYPE_SQLSERVER 0x00000004 Any server running with SQL 1760 * server 1761 * SV_TYPE_DOMAIN_CTRL 0x00000008 Primary domain controller 1762 * SV_TYPE_DOMAIN_BAKCTRL 0x00000010 Backup domain controller 1763 * SV_TYPE_TIME_SOURCE 0x00000020 Server running the timesource 1764 * service 1765 * SV_TYPE_AFP 0x00000040 Apple File Protocol servers 1766 * SV_TYPE_NOVELL 0x00000080 Novell servers 1767 * SV_TYPE_DOMAIN_MEMBER 0x00000100 Domain Member 1768 * SV_TYPE_PRINTQ_SERVER 0x00000200 Server sharing print queue 1769 * SV_TYPE_DIALIN_SERVER 0x00000400 Server running dialin service. 1770 * SV_TYPE_XENIX_SERVER 0x00000800 Xenix server 1771 * SV_TYPE_NT 0x00001000 NT server 1772 * SV_TYPE_WFW 0x00002000 Server running Windows for 1773 * Workgroups 1774 * SV_TYPE_SERVER_NT 0x00008000 Windows NT non DC server 1775 * SV_TYPE_POTENTIAL_BROWSER 0x00010000 Server that can run the browser 1776 * service 1777 * SV_TYPE_BACKUP_BROWSER 0x00020000 Backup browser server 1778 * SV_TYPE_MASTER_BROWSER 0x00040000 Master browser server 1779 * SV_TYPE_DOMAIN_MASTER 0x00080000 Domain Master Browser server 1780 * SV_TYPE_LOCAL_LIST_ONLY 0x40000000 Enumerate only entries marked 1781 * "local" 1782 * SV_TYPE_DOMAIN_ENUM 0x80000000 Enumerate Domains. The pszDomain 1783 * parameter must be NULL. 1784 * 1785 * . A null terminated ASCII string representing the pszDomain parameter 1786 * described above 1787 * 1788 * 6.4.2 Transaction Request Data section 1789 * 1790 * There is no data or auxiliary data to send as part of the request. 1791 * 1792 * 6.4.3 Transaction Response Parameters section 1793 * 1794 * The transaction response parameters section consists of: 1795 * . A 16 bit word indicating the return status. The possible values are: 1796 * 1797 * Code Value Description 1798 * NERR_Success 0 No errors encountered 1799 * ERROR_MORE_DATA 234 Additional data is available 1800 * NERR_ServerNotStarted 2114 The RAP service on the remote computer 1801 * is not running 1802 * NERR_BadTransactConfig 2141 The server is not configured for 1803 * transactions, IPC$ is not shared 1804 * 1805 * . A 16 bit "converter" word. 1806 * . A 16 bit number representing the number of entries returned. 1807 * . A 16 bit number representing the total number of available entries. 1808 * If the supplied buffer is large enough, this will equal the number of 1809 * entries returned. 1810 * 1811 * 6.4.4 Transaction Response Data section 1812 * 1813 * The return data section consists of a number of SERVER_INFO_1 structures. 1814 * The number of such structures present is determined by the third entry 1815 * (described above) in the return parameters section. 1816 * 1817 * At level detail 0, the Transaction response data section contains a 1818 * number of SERVER_INFO_0 data structure. The number of such structures is 1819 * equal to the 16 bit number returned by the server in the third parameter 1820 * in the Transaction response parameter section. The SERVER_INFO_0 data 1821 * structure is defined as: 1822 * 1823 * struct SERVER_INFO_0 { 1824 * char sv0_name[16]; 1825 * }; 1826 * 1827 * where: 1828 * 1829 * sv0_name is a null-terminated string that specifies the name of a 1830 * computer or domain . 1831 * 1832 * At level detail 1, the Transaction response data section contains a 1833 * number of SERVER_INFO_1 data structure. The number of such structures is 1834 * equal to the 16 bit number returned by the server in the third parameter 1835 * in the Transaction response parameter section. The SERVER_INFO_1 data 1836 * structure is defined as: 1837 * 1838 * struct SERVER_INFO_1 { 1839 * char sv1_name[16]; 1840 * char sv1_version_major; 1841 * char sv1_version_minor; 1842 * uint32_t sv1_type; 1843 * char *sv1_comment_or_master_browser; 1844 * }; 1845 * 1846 * sv1_name contains a null-terminated string that specifies the name 1847 * of a computer, or a domain name if SV_TYPE_DOMAIN_ENUM is set in 1848 * sv1_type. 1849 * 1850 * sv1_version_major whatever was specified in the HostAnnouncement 1851 * or DomainAnnouncement frame with which the entry was registered. 1852 * 1853 * sv1_version_minor whatever was specified in the HostAnnouncement 1854 * or DomainAnnouncement frame with which the entry was registered. 1855 * 1856 * sv1_type specifies the type of software the computer is running. 1857 * The member can be one or a combination of the values defined above 1858 * in the Transaction request parameters section for fServerType. 1859 * 1860 * 1861 * sv1_comment_or_master_browser points to a null-terminated string. If 1862 * the sv1_type indicates that the entry is for a domain, this 1863 * specifies the name of server running the domain master browser; 1864 * otherwise, it specifies a comment describing the server. The comment 1865 * can be a null string or the pointer may be a null pointer. 1866 * 1867 * In case there are multiple SERVER_INFO_1 data structures to 1868 * return, the server may put all these fixed length structures in 1869 * the return buffer, leave some space and then put all the variable 1870 * length data (the actual value of the sv1_comment strings) at the 1871 * end of the buffer. 1872 * 1873 * There is no auxiliary data to receive. 1874 */ 1875 1876 int 1877 smb_trans_net_server_enum2(struct smb_request *sr, struct smb_xa *xa) 1878 { 1879 uint16_t opcode, level, max_bytes; 1880 uint32_t server_type; 1881 unsigned char *domain; 1882 struct mbuf_chain str_mb; 1883 char *hostname, *s; 1884 smb_kmod_cfg_t *si; 1885 1886 if (smb_decode_mbc(&xa->req_param_mb, 1887 "%w s(request format) s(reply format) wwls", sr, &opcode, &s, &s, 1888 &level, &max_bytes, &server_type, &domain) != 0) 1889 return (SDRC_NOT_IMPLEMENTED); 1890 1891 si = sr->sr_cfg; 1892 1893 if (utf8_strcasecmp(si->skc_resource_domain, (char *)domain) != 0) { 1894 (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 0, 0, 0, 0); 1895 return (SDRC_SUCCESS); 1896 } 1897 1898 if ((server_type & MY_SERVER_TYPE) == 0) { 1899 (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 0, 0, 0, 0); 1900 return (SDRC_SUCCESS); 1901 } 1902 1903 MBC_INIT(&str_mb, max_bytes); 1904 1905 hostname = si->skc_hostname; 1906 1907 (void) smb_encode_mbc(&xa->rep_data_mb, "16c", hostname); 1908 if (level == 1) { 1909 (void) smb_encode_mbc(&xa->rep_data_mb, "bbll", 1910 SMB_VERSION_MAJOR, SMB_VERSION_MINOR, 1911 MY_SERVER_TYPE, MBC_LENGTH(&str_mb)); 1912 (void) smb_encode_mbc(&str_mb, "s", si->skc_system_comment); 1913 } 1914 1915 (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 0, 1916 -MBC_LENGTH(&xa->rep_data_mb), 1, 1); 1917 (void) smb_encode_mbc(&xa->rep_data_mb, "m", str_mb.chain); 1918 return (SDRC_SUCCESS); 1919 } 1920 1921 /* 1922 * is_supported_pipe 1923 * 1924 * Currently, just return 0 if the pipe is \\PIPE\repl otherwise 1925 * return 1. 1926 */ 1927 int 1928 is_supported_pipe(char *pname) 1929 { 1930 if (utf8_strcasecmp(pname, PIPE_REPL) == 0) 1931 return (0); 1932 1933 return (1); 1934 } 1935 1936 static smb_sdrc_t 1937 smb_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) 1938 { 1939 int rc, pos; 1940 int total_bytes, n_setup, n_param, n_data; 1941 int param_off, param_pad, data_off, data_pad; 1942 uint16_t opcode; 1943 uint16_t devstate; 1944 char *req_fmt; 1945 char *rep_fmt; 1946 struct vardata_block vdb; 1947 1948 n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200; 1949 n_setup++; 1950 n_setup = n_setup & ~0x0001; 1951 n_param = (xa->smb_mprcnt < smb_maxbufsize) 1952 ? xa->smb_mprcnt : smb_maxbufsize; 1953 n_param++; 1954 n_param = n_param & ~0x0001; 1955 rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param); 1956 n_data = (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc; 1957 MBC_INIT(&xa->rep_setup_mb, n_setup * 2); 1958 MBC_INIT(&xa->rep_param_mb, n_param); 1959 MBC_INIT(&xa->rep_data_mb, n_data); 1960 1961 if (xa->smb_suwcnt > 0 && STYPE_ISIPC(sr->tid_tree->t_res_type)) { 1962 rc = smb_decode_mbc(&xa->req_setup_mb, "ww", &opcode, 1963 &sr->smb_fid); 1964 if (rc != 0) 1965 goto trans_err_not_supported; 1966 switch (opcode) { 1967 case TRANS_SET_NMPIPE_STATE: 1968 if ((rc = smb_decode_mbc(&xa->req_param_mb, "w", 1969 &devstate)) != 0) 1970 goto trans_err_not_supported; 1971 1972 rc = SDRC_SUCCESS; 1973 break; 1974 1975 case TRANS_TRANSACT_NMPIPE: 1976 sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, 1977 sr->smb_fid); 1978 if (sr->fid_ofile == NULL) { 1979 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 1980 ERRDOS, ERRbadfid); 1981 return (SDRC_ERROR); 1982 } 1983 1984 rc = smb_decode_mbc(&xa->req_data_mb, "#B", 1985 xa->smb_tdscnt, &vdb); 1986 if (rc != 0) 1987 goto trans_err_not_supported; 1988 1989 rc = smb_rpc_transact(sr, &vdb.uio); 1990 break; 1991 1992 case TRANS_WAIT_NMPIPE: 1993 if (is_supported_pipe(xa->xa_smb_trans_name) == 0) { 1994 smbsr_error(sr, 0, ERRDOS, ERRbadfile); 1995 return (SDRC_ERROR); 1996 } 1997 rc = SDRC_SUCCESS; 1998 break; 1999 2000 default: 2001 goto trans_err_not_supported; 2002 } 2003 } else { 2004 if ((utf8_strcasecmp(xa->xa_smb_trans_name, 2005 PIPE_LANMAN) != 0) && 2006 (utf8_strcasecmp( 2007 xa->xa_smb_trans_name, MAILSLOT_LANMAN) != 0) && 2008 (utf8_strcasecmp( 2009 xa->xa_smb_trans_name, MAILSLOT_BROWSE) != 0) && 2010 (utf8_strcasecmp( 2011 xa->xa_smb_trans_name, MAILSLOT_MSBROWSE) != 0)) 2012 goto trans_err_not_supported; 2013 2014 if ((rc = smb_decode_mbc(&xa->req_param_mb, "%wss\b", sr, 2015 &opcode, &req_fmt, &rep_fmt)) != 0) 2016 goto trans_err_not_supported; 2017 2018 /* for now, only respond to the */ 2019 switch (opcode) { 2020 case API_WshareEnum: 2021 rc = smb_trans_net_share_enum(sr, xa); 2022 break; 2023 2024 case API_WshareGetInfo: 2025 rc = smb_trans_net_share_get_info(sr, xa); 2026 break; 2027 2028 case API_WserverGetInfo: 2029 rc = smb_trans_server_get_info(sr, xa); 2030 break; 2031 2032 case API_WUserGetInfo: 2033 rc = smb_trans_net_user_get_info(sr, xa); 2034 break; 2035 2036 case API_WWkstaGetInfo: 2037 rc = smb_trans_net_workstation_get_info(sr, xa); 2038 break; 2039 2040 case API_NetServerEnum2: 2041 rc = smb_trans_net_server_enum2(sr, xa); 2042 break; 2043 2044 default: 2045 goto trans_err_not_supported; 2046 } 2047 } 2048 2049 switch (rc) { 2050 case SDRC_SUCCESS: 2051 break; 2052 2053 case SDRC_DROP_VC: 2054 case SDRC_NO_REPLY: 2055 case SDRC_ERROR: 2056 return (rc); 2057 2058 case SDRC_NOT_IMPLEMENTED: 2059 goto trans_err_not_supported; 2060 2061 default: 2062 break; 2063 } 2064 2065 n_setup = MBC_LENGTH(&xa->rep_setup_mb); 2066 n_param = MBC_LENGTH(&xa->rep_param_mb); 2067 n_data = MBC_LENGTH(&xa->rep_data_mb); 2068 2069 if (xa->smb_msrcnt < n_setup || 2070 xa->smb_mprcnt < n_param || 2071 xa->smb_mdrcnt < n_data) { 2072 goto trans_err_too_small; 2073 } 2074 2075 /* neato, blast it over there */ 2076 2077 n_setup = (n_setup + 1) / 2; /* Convert to setup words */ 2078 param_pad = 1; /* always one */ 2079 param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 2080 data_pad = (param_off + n_param) & 1; /* Pad to short */ 2081 /* Param off from hdr start */ 2082 data_off = param_off + n_param + data_pad; 2083 total_bytes = param_pad + n_param + data_pad + n_data; 2084 2085 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, 2086 "b ww 2. www www b . C w #. C #. C", 2087 10 + n_setup, /* wct */ 2088 n_param, /* Total Parameter Bytes */ 2089 n_data, /* Total Data Bytes */ 2090 n_param, /* Total Parameter Bytes this buffer */ 2091 param_off, /* Param offset from header start */ 2092 0, /* Param displacement */ 2093 n_data, /* Total Data Bytes this buffer */ 2094 data_off, /* Data offset from header start */ 2095 0, /* Data displacement */ 2096 n_setup, /* suwcnt */ 2097 &xa->rep_setup_mb, /* setup[] */ 2098 total_bytes, /* Total data bytes */ 2099 param_pad, 2100 &xa->rep_param_mb, 2101 data_pad, 2102 &xa->rep_data_mb); 2103 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 2104 2105 trans_err_too_small: 2106 rc = NERR_BufTooSmall; 2107 goto trans_err; 2108 2109 trans_err_not_supported: 2110 rc = ERROR_NOT_SUPPORTED; 2111 goto trans_err; 2112 2113 trans_err: 2114 pos = MBC_LENGTH(&sr->reply) + 23; 2115 rc = smbsr_encode_result(sr, 10, 4, "b ww 2. www www b . w ww", 2116 10, /* wct */ 2117 4, 0, /* tpscnt tdscnt */ 2118 4, pos, 0, /* pscnt psoff psdisp */ 2119 0, 0, 0, /* dscnt dsoff dsdisp */ 2120 0, /* suwcnt */ 2121 4, /* bcc */ 2122 rc, 2123 0); /* converter word? */ 2124 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 2125 } 2126 2127 static smb_sdrc_t 2128 smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) 2129 { 2130 int rc, pos; 2131 int total_bytes, n_setup, n_param, n_data; 2132 int param_off, param_pad, data_off, data_pad; 2133 uint16_t opcode; 2134 uint16_t nt_unknown_secret = 0x0100; 2135 char *fmt; 2136 2137 n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200; 2138 n_setup++; 2139 n_setup = n_setup & ~0x0001; 2140 n_param = (xa->smb_mprcnt < smb_maxbufsize) 2141 ? xa->smb_mprcnt : smb_maxbufsize; 2142 n_param++; 2143 n_param = n_param & ~0x0001; 2144 rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param); 2145 n_data = (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc; 2146 MBC_INIT(&xa->rep_setup_mb, n_setup * 2); 2147 MBC_INIT(&xa->rep_param_mb, n_param); 2148 MBC_INIT(&xa->rep_data_mb, n_data); 2149 2150 if (smb_decode_mbc(&xa->req_setup_mb, "w", &opcode) != 0) 2151 goto trans_err_not_supported; 2152 2153 /* 2154 * Save this for /proc to read later. 2155 */ 2156 xa->smb_func = opcode; 2157 2158 /* for now, only respond to the */ 2159 switch (opcode) { 2160 case TRANS2_CREATE_DIRECTORY: 2161 rc = smb_com_trans2_create_directory(sr, xa); 2162 break; 2163 2164 case TRANS2_FIND_FIRST2: 2165 /* 2166 * Should have enough room to send the response 2167 * data back to client. 2168 */ 2169 if (n_data == 0) { 2170 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 2171 ERRDOS, ERROR_BAD_LENGTH); 2172 return (SDRC_ERROR); 2173 } 2174 rc = smb_com_trans2_find_first2(sr, xa); 2175 break; 2176 2177 case TRANS2_FIND_NEXT2: 2178 /* 2179 * Should have enough room to send the response 2180 * data back to client. 2181 */ 2182 if (n_data == 0) { 2183 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 2184 ERRDOS, ERROR_BAD_LENGTH); 2185 return (SDRC_ERROR); 2186 } 2187 rc = smb_com_trans2_find_next2(sr, xa); 2188 break; 2189 2190 case TRANS2_QUERY_FS_INFORMATION: 2191 /* 2192 * Should have enough room to send the response 2193 * data back to client. 2194 */ 2195 if (n_data == 0) { 2196 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 2197 ERRDOS, ERROR_BAD_LENGTH); 2198 return (SDRC_ERROR); 2199 } 2200 rc = smb_com_trans2_query_fs_information(sr, xa); 2201 break; 2202 2203 case TRANS2_QUERY_PATH_INFORMATION: 2204 /* 2205 * Should have enough room to send the response 2206 * data back to client. 2207 */ 2208 if (n_data == 0) { 2209 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 2210 ERRDOS, ERROR_BAD_LENGTH); 2211 return (SDRC_ERROR); 2212 } 2213 rc = smb_com_trans2_query_path_information(sr, xa); 2214 break; 2215 2216 case TRANS2_QUERY_FILE_INFORMATION: 2217 /* 2218 * Should have enough room to send the response 2219 * data back to client. 2220 */ 2221 if (n_data == 0) { 2222 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 2223 ERRDOS, ERROR_BAD_LENGTH); 2224 return (SDRC_ERROR); 2225 } 2226 rc = smb_com_trans2_query_file_information(sr, xa); 2227 break; 2228 2229 case TRANS2_SET_PATH_INFORMATION: 2230 rc = smb_com_trans2_set_path_information(sr, xa); 2231 break; 2232 2233 case TRANS2_SET_FILE_INFORMATION: 2234 rc = smb_com_trans2_set_file_information(sr, xa); 2235 break; 2236 default: 2237 goto trans_err_not_supported; 2238 } 2239 2240 switch (rc) { 2241 case SDRC_SUCCESS: 2242 break; 2243 2244 case SDRC_DROP_VC: 2245 case SDRC_NO_REPLY: 2246 case SDRC_ERROR: 2247 return (rc); 2248 2249 case SDRC_NOT_IMPLEMENTED: 2250 goto trans_err_not_supported; 2251 2252 default: 2253 break; 2254 } 2255 2256 n_setup = MBC_LENGTH(&xa->rep_setup_mb); 2257 n_param = MBC_LENGTH(&xa->rep_param_mb); 2258 n_data = MBC_LENGTH(&xa->rep_data_mb); 2259 2260 if (xa->smb_msrcnt < n_setup || 2261 xa->smb_mprcnt < n_param || 2262 xa->smb_mdrcnt < n_data) { 2263 goto trans_err_too_small; 2264 } 2265 2266 /* neato, blast it over there */ 2267 2268 n_setup = (n_setup + 1) / 2; /* Conver to setup words */ 2269 param_pad = 1; /* must be one */ 2270 param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 2271 2272 /* 2273 * Including the nt_unknown_secret value persuades netmon to 2274 * display the correct data format for QueryPathInfo and 2275 * QueryFileInfo. 2276 */ 2277 if (opcode == TRANS2_QUERY_FILE_INFORMATION || 2278 opcode == TRANS2_QUERY_PATH_INFORMATION) { 2279 data_pad = sizeof (uint16_t); 2280 data_off = param_off + n_param + data_pad; 2281 fmt = "b ww 2. www www b . C w #. C w C"; 2282 nt_unknown_secret = 0x0100; 2283 } 2284 else 2285 { 2286 data_pad = (param_off + n_param) & 1; /* Pad to short */ 2287 /* Param off from hdr start */ 2288 data_off = param_off + n_param + data_pad; 2289 fmt = "b ww 2. www www b . C w #. C #. C"; 2290 /*LINTED E_ASSIGN_NARROW_CONV*/ 2291 nt_unknown_secret = data_pad; 2292 } 2293 2294 total_bytes = param_pad + n_param + data_pad + n_data; 2295 2296 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, 2297 fmt, 2298 10 + n_setup, /* wct */ 2299 n_param, /* Total Parameter Bytes */ 2300 n_data /* + data_pad */, /* Total Data Bytes */ 2301 n_param, /* Total Parameter Bytes this buffer */ 2302 param_off, /* Param offset from header start */ 2303 0, /* Param displacement */ 2304 n_data /* + data_pad */, /* Total Data Bytes this buffer */ 2305 data_off, /* Data offset from header start */ 2306 0, /* Data displacement */ 2307 n_setup, /* suwcnt */ 2308 &xa->rep_setup_mb, /* setup[] */ 2309 total_bytes, /* Total data bytes */ 2310 param_pad, 2311 &xa->rep_param_mb, 2312 nt_unknown_secret, 2313 &xa->rep_data_mb); 2314 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 2315 2316 trans_err_too_small: 2317 rc = NERR_BufTooSmall; 2318 goto trans_err; 2319 2320 trans_err_not_supported: 2321 rc = ERROR_NOT_SUPPORTED; 2322 goto trans_err; 2323 2324 trans_err: 2325 pos = MBC_LENGTH(&sr->reply) + 23; 2326 rc = smbsr_encode_result(sr, 10, 4, "b ww 2. www www b . w ww", 2327 10, /* wct */ 2328 4, 0, /* tpscnt tdscnt */ 2329 4, pos, 0, /* pscnt psoff psdisp */ 2330 0, 0, 0, /* dscnt dsoff dsdisp */ 2331 0, /* suwcnt */ 2332 4, /* bcc */ 2333 rc, 2334 0); /* converter word? */ 2335 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 2336 } 2337 2338 smb_xa_t * 2339 smb_xa_create( 2340 smb_session_t *session, 2341 smb_request_t *sr, 2342 uint32_t total_parameter_count, 2343 uint32_t total_data_count, 2344 uint32_t max_parameter_count, 2345 uint32_t max_data_count, 2346 uint32_t max_setup_count, 2347 uint32_t setup_word_count) 2348 { 2349 smb_xa_t *xa, *nxa; 2350 smb_llist_t *xlist; 2351 2352 xa = MEM_ZALLOC("xa", sizeof (smb_xa_t)); 2353 xa->xa_refcnt = 1; 2354 xa->smb_com = sr->smb_com; 2355 xa->smb_flg = sr->smb_flg; 2356 xa->smb_flg2 = sr->smb_flg2; 2357 xa->smb_tid = sr->smb_tid; 2358 xa->smb_pid = sr->smb_pid; 2359 xa->smb_uid = sr->smb_uid; 2360 xa->xa_smb_mid = sr->smb_mid; 2361 xa->reply_seqnum = sr->reply_seqnum; 2362 xa->smb_tpscnt = total_parameter_count; 2363 xa->smb_tdscnt = total_data_count; 2364 xa->smb_mprcnt = max_parameter_count; 2365 xa->smb_mdrcnt = max_data_count; 2366 xa->smb_msrcnt = max_setup_count; 2367 xa->smb_suwcnt = setup_word_count; 2368 xa->xa_session = session; 2369 xa->xa_magic = SMB_XA_MAGIC; 2370 2371 /* 2372 * The new xa structure is checked against the current list to see 2373 * if it exists already. 2374 */ 2375 xlist = &session->s_xa_list; 2376 smb_llist_enter(xlist, RW_WRITER); 2377 nxa = smb_llist_head(xlist); 2378 while (nxa) { 2379 ASSERT(nxa->xa_magic == SMB_XA_MAGIC); 2380 if (nxa->xa_smb_mid == xa->xa_smb_mid && 2381 nxa->smb_pid == xa->smb_pid && 2382 !SMB_XA_CLOSED(nxa) && 2383 !(nxa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 2384 smb_llist_exit(xlist); 2385 MEM_FREE("xa", xa); 2386 return (NULL); 2387 } 2388 nxa = smb_llist_next(xlist, nxa); 2389 } 2390 smb_llist_insert_tail(xlist, xa); 2391 smb_llist_exit(xlist); 2392 return (xa); 2393 } 2394 2395 void 2396 smb_xa_delete(smb_xa_t *xa) 2397 { 2398 ASSERT(xa->xa_refcnt == 0); 2399 ASSERT(SMB_XA_CLOSED(xa)); 2400 2401 if (xa->xa_smb_trans_name) 2402 MEM_FREE("smb", xa->xa_smb_trans_name); 2403 2404 if (xa->rep_setup_mb.chain != NULL) 2405 m_freem(xa->rep_setup_mb.chain); 2406 if (xa->rep_param_mb.chain != NULL) 2407 m_freem(xa->rep_param_mb.chain); 2408 if (xa->rep_data_mb.chain != NULL) 2409 m_freem(xa->rep_data_mb.chain); 2410 2411 xa->xa_magic = (uint32_t)~SMB_XA_MAGIC; 2412 MEM_FREE("xa", xa); 2413 } 2414 2415 smb_xa_t * 2416 smb_xa_hold(smb_xa_t *xa) 2417 { 2418 mutex_enter(&xa->xa_mutex); 2419 xa->xa_refcnt++; 2420 ASSERT(xa->xa_refcnt); 2421 mutex_exit(&xa->xa_mutex); 2422 return (xa); 2423 } 2424 2425 void 2426 smb_xa_rele(smb_session_t *session, smb_xa_t *xa) 2427 { 2428 mutex_enter(&xa->xa_mutex); 2429 ASSERT(xa->xa_refcnt); 2430 xa->xa_refcnt--; 2431 if (SMB_XA_CLOSED(xa) && (xa->xa_refcnt == 0)) { 2432 mutex_exit(&xa->xa_mutex); 2433 smb_llist_enter(&session->s_xa_list, RW_WRITER); 2434 smb_llist_remove(&session->s_xa_list, xa); 2435 smb_llist_exit(&session->s_xa_list); 2436 smb_xa_delete(xa); 2437 return; 2438 } 2439 mutex_exit(&xa->xa_mutex); 2440 } 2441 2442 int 2443 smb_xa_open(smb_xa_t *xa) 2444 { 2445 int rc; 2446 2447 mutex_enter(&xa->xa_mutex); 2448 2449 ASSERT((xa->xa_flags & SMB_XA_FLAG_OPEN) == 0); 2450 2451 if ((xa->xa_flags & SMB_XA_FLAG_CLOSE) == 0) { 2452 xa->xa_flags |= SMB_XA_FLAG_OPEN; 2453 rc = 0; 2454 } else { 2455 rc = ERROR_INVALID_HANDLE; 2456 } 2457 2458 mutex_exit(&xa->xa_mutex); 2459 2460 return (rc); 2461 } 2462 2463 void 2464 smb_xa_close(smb_xa_t *xa) 2465 { 2466 mutex_enter(&xa->xa_mutex); 2467 xa->xa_flags |= SMB_XA_FLAG_CLOSE; 2468 xa->xa_flags &= ~SMB_XA_FLAG_OPEN; 2469 2470 if (xa->xa_refcnt == 0) { 2471 mutex_exit(&xa->xa_mutex); 2472 smb_llist_enter(&xa->xa_session->s_xa_list, RW_WRITER); 2473 smb_llist_remove(&xa->xa_session->s_xa_list, xa); 2474 smb_llist_exit(&xa->xa_session->s_xa_list); 2475 smb_xa_delete(xa); 2476 return; 2477 } 2478 2479 mutex_exit(&xa->xa_mutex); 2480 } 2481 2482 int 2483 smb_xa_complete(smb_xa_t *xa) 2484 { 2485 int rc; 2486 2487 mutex_enter(&xa->xa_mutex); 2488 if (xa->xa_flags & (SMB_XA_FLAG_COMPLETE | SMB_XA_FLAG_CLOSE)) { 2489 rc = 0; 2490 } else { 2491 rc = 1; 2492 xa->xa_flags |= SMB_XA_FLAG_COMPLETE; 2493 } 2494 mutex_exit(&xa->xa_mutex); 2495 return (rc); 2496 } 2497 2498 smb_xa_t * 2499 smb_xa_find( 2500 smb_session_t *session, 2501 uint16_t pid, 2502 uint16_t mid) 2503 { 2504 smb_xa_t *xa; 2505 smb_llist_t *xlist; 2506 2507 xlist = &session->s_xa_list; 2508 smb_llist_enter(xlist, RW_READER); 2509 xa = smb_llist_head(xlist); 2510 while (xa) { 2511 mutex_enter(&xa->xa_mutex); 2512 if (xa->xa_smb_mid == mid && 2513 xa->smb_pid == pid && 2514 !SMB_XA_CLOSED(xa) && 2515 !(xa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 2516 xa->xa_refcnt++; 2517 ASSERT(xa->xa_refcnt); 2518 mutex_exit(&xa->xa_mutex); 2519 break; 2520 } 2521 mutex_exit(&xa->xa_mutex); 2522 xa = smb_llist_next(xlist, xa); 2523 } 2524 smb_llist_exit(xlist); 2525 return (xa); 2526 } 2527