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