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