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 2007 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_cifs_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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_cifs_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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, ERRSRV, ERRaccess); 422 /* NOTREACHED */ 423 424 case NT_TRANSACT_SET_QUOTA: 425 smbsr_raise_error(sr, ERRSRV, ERRaccess); 426 /* NOTREACHED */ 427 428 default: 429 smbsr_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_error(sr, 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_raise_cifs_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_raise_error(sr, 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_raise_error(sr, 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_raise_cifs_error(sr, 1930 NT_STATUS_INVALID_HANDLE, 1931 ERRDOS, ERRbadfid); 1932 /* NOTREACHED */ 1933 } 1934 1935 rc = smb_decode_mbc(&xa->req_data_mb, "#B", 1936 xa->smb_tdscnt, &vdb); 1937 if (rc != 0) 1938 goto trans_err_not_supported; 1939 1940 rc = smb_rpc_transact(sr, &vdb.uio); 1941 break; 1942 1943 case TRANS_WAIT_NMPIPE: 1944 if (is_supported_pipe(xa->xa_smb_trans_name) == 0) { 1945 smbsr_raise_error(sr, ERRDOS, ERRbadfile); 1946 /* NOT REACHED */ 1947 } 1948 rc = SDRC_NORMAL_REPLY; 1949 break; 1950 1951 default: 1952 goto trans_err_not_supported; 1953 } 1954 } else { 1955 if ((utf8_strcasecmp(xa->xa_smb_trans_name, 1956 PIPE_LANMAN) != 0) && 1957 (utf8_strcasecmp( 1958 xa->xa_smb_trans_name, MAILSLOT_LANMAN) != 0) && 1959 (utf8_strcasecmp( 1960 xa->xa_smb_trans_name, MAILSLOT_BROWSE) != 0) && 1961 (utf8_strcasecmp( 1962 xa->xa_smb_trans_name, MAILSLOT_MSBROWSE) != 0)) 1963 goto trans_err_not_supported; 1964 1965 if ((rc = smb_decode_mbc(&xa->req_param_mb, "%wss\b", sr, 1966 &opcode, &req_fmt, &rep_fmt)) != 0) 1967 goto trans_err_not_supported; 1968 1969 /* for now, only respond to the */ 1970 switch (opcode) { 1971 case API_WshareEnum: 1972 rc = smb_trans_net_share_enum(sr, xa); 1973 break; 1974 1975 case API_WshareGetInfo: 1976 rc = smb_trans_net_share_get_info(sr, xa); 1977 break; 1978 1979 case API_WserverGetInfo: 1980 rc = smb_trans_server_get_info(sr, xa); 1981 break; 1982 1983 case API_WUserGetInfo: 1984 rc = smb_trans_net_user_get_info(sr, xa); 1985 break; 1986 1987 case API_WWkstaGetInfo: 1988 rc = smb_trans_net_workstation_get_info(sr, xa); 1989 break; 1990 1991 case API_NetServerEnum2: 1992 rc = smb_trans_net_server_enum2(sr, xa); 1993 break; 1994 1995 default: 1996 goto trans_err_not_supported; 1997 } 1998 } 1999 2000 switch (rc) { 2001 case SDRC_NORMAL_REPLY: 2002 break; 2003 2004 case SDRC_DROP_VC: 2005 case SDRC_NO_REPLY: 2006 case SDRC_ERROR_REPLY: 2007 return (rc); 2008 2009 case SDRC_UNIMPLEMENTED: 2010 case SDRC_UNSUPPORTED: 2011 goto trans_err_not_supported; 2012 2013 default: 2014 break; 2015 } 2016 2017 n_setup = MBC_LENGTH(&xa->rep_setup_mb); 2018 n_param = MBC_LENGTH(&xa->rep_param_mb); 2019 n_data = MBC_LENGTH(&xa->rep_data_mb); 2020 2021 if (xa->smb_msrcnt < n_setup || 2022 xa->smb_mprcnt < n_param || 2023 xa->smb_mdrcnt < n_data) { 2024 goto trans_err_too_small; 2025 } 2026 2027 /* neato, blast it over there */ 2028 2029 n_setup = (n_setup + 1) / 2; /* Convert to setup words */ 2030 param_pad = 1; /* always one */ 2031 param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 2032 data_pad = (param_off + n_param) & 1; /* Pad to short */ 2033 /* Param off from hdr start */ 2034 data_off = param_off + n_param + data_pad; 2035 total_bytes = param_pad + n_param + data_pad + n_data; 2036 2037 smbsr_encode_result(sr, 10+n_setup, total_bytes, 2038 "b ww 2. www www b . C w #. C #. C", 2039 10 + n_setup, /* wct */ 2040 n_param, /* Total Parameter Bytes */ 2041 n_data, /* Total Data Bytes */ 2042 n_param, /* Total Parameter Bytes this buffer */ 2043 param_off, /* Param offset from header start */ 2044 0, /* Param displacement */ 2045 n_data, /* Total Data Bytes this buffer */ 2046 data_off, /* Data offset from header start */ 2047 0, /* Data displacement */ 2048 n_setup, /* suwcnt */ 2049 &xa->rep_setup_mb, /* setup[] */ 2050 total_bytes, /* Total data bytes */ 2051 param_pad, 2052 &xa->rep_param_mb, 2053 data_pad, 2054 &xa->rep_data_mb); 2055 return (SDRC_NORMAL_REPLY); 2056 2057 trans_err_too_small: 2058 rc = NERR_BufTooSmall; 2059 goto trans_err; 2060 2061 trans_err_not_supported: 2062 rc = ERROR_NOT_SUPPORTED; 2063 goto trans_err; 2064 2065 trans_err: 2066 pos = MBC_LENGTH(&sr->reply) + 23; 2067 smbsr_encode_result(sr, 10, 4, "b ww 2. www www b . w ww", 2068 10, /* wct */ 2069 4, 0, /* tpscnt tdscnt */ 2070 4, pos, 0, /* pscnt psoff psdisp */ 2071 0, 0, 0, /* dscnt dsoff dsdisp */ 2072 0, /* suwcnt */ 2073 4, /* bcc */ 2074 rc, 2075 0); /* converter word? */ 2076 2077 return (SDRC_NORMAL_REPLY); 2078 } 2079 2080 int 2081 smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) 2082 { 2083 int rc, pos; 2084 int total_bytes, n_setup, n_param, n_data; 2085 int param_off, param_pad, data_off, data_pad; 2086 uint16_t opcode; 2087 uint16_t nt_unknown_secret = 0x0100; 2088 char *fmt; 2089 2090 n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200; 2091 n_setup++; 2092 n_setup = n_setup & ~0x0001; 2093 n_param = (xa->smb_mprcnt < smb_maxbufsize) 2094 ? xa->smb_mprcnt : smb_maxbufsize; 2095 n_param++; 2096 n_param = n_param & ~0x0001; 2097 rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param); 2098 n_data = (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc; 2099 MBC_INIT(&xa->rep_setup_mb, n_setup * 2); 2100 MBC_INIT(&xa->rep_param_mb, n_param); 2101 MBC_INIT(&xa->rep_data_mb, n_data); 2102 2103 if (smb_decode_mbc(&xa->req_setup_mb, "w", &opcode) != 0) 2104 goto trans_err_not_supported; 2105 2106 /* 2107 * Save this for /proc to read later. 2108 */ 2109 xa->smb_func = opcode; 2110 2111 /* for now, only respond to the */ 2112 switch (opcode) { 2113 case TRANS2_CREATE_DIRECTORY: 2114 rc = smb_com_trans2_create_directory(sr, xa); 2115 break; 2116 2117 case TRANS2_FIND_FIRST2: 2118 /* 2119 * Should have enough room to send the response 2120 * data back to client. 2121 */ 2122 if (n_data == 0) { 2123 smbsr_raise_cifs_error(sr, 2124 NT_STATUS_INFO_LENGTH_MISMATCH, 2125 ERRDOS, ERROR_BAD_LENGTH); 2126 /* NOT REACHED */ 2127 } 2128 rc = smb_com_trans2_find_first2(sr, xa); 2129 break; 2130 2131 case TRANS2_FIND_NEXT2: 2132 /* 2133 * Should have enough room to send the response 2134 * data back to client. 2135 */ 2136 if (n_data == 0) { 2137 smbsr_raise_cifs_error(sr, 2138 NT_STATUS_INFO_LENGTH_MISMATCH, 2139 ERRDOS, ERROR_BAD_LENGTH); 2140 /* NOT REACHED */ 2141 } 2142 rc = smb_com_trans2_find_next2(sr, xa); 2143 break; 2144 2145 case TRANS2_QUERY_FS_INFORMATION: 2146 /* 2147 * Should have enough room to send the response 2148 * data back to client. 2149 */ 2150 if (n_data == 0) { 2151 smbsr_raise_cifs_error(sr, 2152 NT_STATUS_INFO_LENGTH_MISMATCH, 2153 ERRDOS, ERROR_BAD_LENGTH); 2154 /* NOT REACHED */ 2155 } 2156 rc = smb_com_trans2_query_fs_information(sr, xa); 2157 break; 2158 2159 case TRANS2_QUERY_PATH_INFORMATION: 2160 /* 2161 * Should have enough room to send the response 2162 * data back to client. 2163 */ 2164 if (n_data == 0) { 2165 smbsr_raise_cifs_error(sr, 2166 NT_STATUS_INFO_LENGTH_MISMATCH, 2167 ERRDOS, ERROR_BAD_LENGTH); 2168 /* NOT REACHED */ 2169 } 2170 rc = smb_com_trans2_query_path_information(sr, xa); 2171 break; 2172 2173 case TRANS2_QUERY_FILE_INFORMATION: 2174 /* 2175 * Should have enough room to send the response 2176 * data back to client. 2177 */ 2178 if (n_data == 0) { 2179 smbsr_raise_cifs_error(sr, 2180 NT_STATUS_INFO_LENGTH_MISMATCH, 2181 ERRDOS, ERROR_BAD_LENGTH); 2182 /* NOT REACHED */ 2183 } 2184 rc = smb_com_trans2_query_file_information(sr, xa); 2185 break; 2186 2187 case TRANS2_SET_PATH_INFORMATION: 2188 rc = smb_com_trans2_set_path_information(sr, xa); 2189 break; 2190 2191 case TRANS2_SET_FILE_INFORMATION: 2192 rc = smb_com_trans2_set_file_information(sr, xa); 2193 break; 2194 default: 2195 goto trans_err_not_supported; 2196 } 2197 2198 switch (rc) { 2199 case SDRC_NORMAL_REPLY: 2200 break; 2201 2202 case SDRC_DROP_VC: 2203 case SDRC_NO_REPLY: 2204 case SDRC_ERROR_REPLY: 2205 return (rc); 2206 2207 case SDRC_UNIMPLEMENTED: 2208 case SDRC_UNSUPPORTED: 2209 goto trans_err_not_supported; 2210 2211 default: 2212 break; 2213 } 2214 2215 n_setup = MBC_LENGTH(&xa->rep_setup_mb); 2216 n_param = MBC_LENGTH(&xa->rep_param_mb); 2217 n_data = MBC_LENGTH(&xa->rep_data_mb); 2218 2219 if (xa->smb_msrcnt < n_setup || 2220 xa->smb_mprcnt < n_param || 2221 xa->smb_mdrcnt < n_data) { 2222 goto trans_err_too_small; 2223 } 2224 2225 /* neato, blast it over there */ 2226 2227 n_setup = (n_setup + 1) / 2; /* Conver to setup words */ 2228 param_pad = 1; /* must be one */ 2229 param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 2230 2231 /* 2232 * Including the nt_unknown_secret value persuades netmon to 2233 * display the correct data format for QueryPathInfo and 2234 * QueryFileInfo. 2235 */ 2236 if (opcode == TRANS2_QUERY_FILE_INFORMATION || 2237 opcode == TRANS2_QUERY_PATH_INFORMATION) { 2238 data_pad = sizeof (uint16_t); 2239 data_off = param_off + n_param + data_pad; 2240 fmt = "b ww 2. www www b . C w #. C w C"; 2241 nt_unknown_secret = 0x0100; 2242 } 2243 else 2244 { 2245 data_pad = (param_off + n_param) & 1; /* Pad to short */ 2246 /* Param off from hdr start */ 2247 data_off = param_off + n_param + data_pad; 2248 fmt = "b ww 2. www www b . C w #. C #. C"; 2249 /*LINTED E_ASSIGN_NARROW_CONV*/ 2250 nt_unknown_secret = data_pad; 2251 } 2252 2253 total_bytes = param_pad + n_param + data_pad + n_data; 2254 2255 smbsr_encode_result(sr, 10+n_setup, total_bytes, 2256 fmt, 2257 10 + n_setup, /* wct */ 2258 n_param, /* Total Parameter Bytes */ 2259 n_data /* + data_pad */, /* Total Data Bytes */ 2260 n_param, /* Total Parameter Bytes this buffer */ 2261 param_off, /* Param offset from header start */ 2262 0, /* Param displacement */ 2263 n_data /* + data_pad */, /* Total Data Bytes this buffer */ 2264 data_off, /* Data offset from header start */ 2265 0, /* Data displacement */ 2266 n_setup, /* suwcnt */ 2267 &xa->rep_setup_mb, /* setup[] */ 2268 total_bytes, /* Total data bytes */ 2269 param_pad, 2270 &xa->rep_param_mb, 2271 nt_unknown_secret, 2272 &xa->rep_data_mb); 2273 return (SDRC_NORMAL_REPLY); 2274 2275 trans_err_too_small: 2276 rc = NERR_BufTooSmall; 2277 goto trans_err; 2278 2279 trans_err_not_supported: 2280 rc = ERROR_NOT_SUPPORTED; 2281 goto trans_err; 2282 2283 trans_err: 2284 pos = MBC_LENGTH(&sr->reply) + 23; 2285 smbsr_encode_result(sr, 10, 4, "b ww 2. www www b . w ww", 2286 10, /* wct */ 2287 4, 0, /* tpscnt tdscnt */ 2288 4, pos, 0, /* pscnt psoff psdisp */ 2289 0, 0, 0, /* dscnt dsoff dsdisp */ 2290 0, /* suwcnt */ 2291 4, /* bcc */ 2292 rc, 2293 0); /* converter word? */ 2294 return (SDRC_NORMAL_REPLY); 2295 } 2296 2297 smb_xa_t * 2298 smb_xa_create( 2299 smb_session_t *session, 2300 smb_request_t *sr, 2301 uint32_t total_parameter_count, 2302 uint32_t total_data_count, 2303 uint32_t max_parameter_count, 2304 uint32_t max_data_count, 2305 uint32_t max_setup_count, 2306 uint32_t setup_word_count) 2307 { 2308 smb_xa_t *xa, *nxa; 2309 smb_llist_t *xlist; 2310 2311 xa = MEM_ZALLOC("xa", sizeof (smb_xa_t)); 2312 xa->xa_refcnt = 1; 2313 xa->smb_com = sr->smb_com; 2314 xa->smb_flg = sr->smb_flg; 2315 xa->smb_flg2 = sr->smb_flg2; 2316 xa->smb_tid = sr->smb_tid; 2317 xa->smb_pid = sr->smb_pid; 2318 xa->smb_uid = sr->smb_uid; 2319 xa->xa_smb_mid = sr->smb_mid; 2320 xa->reply_seqnum = sr->reply_seqnum; 2321 xa->smb_tpscnt = total_parameter_count; 2322 xa->smb_tdscnt = total_data_count; 2323 xa->smb_mprcnt = max_parameter_count; 2324 xa->smb_mdrcnt = max_data_count; 2325 xa->smb_msrcnt = max_setup_count; 2326 xa->smb_suwcnt = setup_word_count; 2327 xa->xa_session = session; 2328 xa->xa_magic = SMB_XA_MAGIC; 2329 2330 /* 2331 * The new xa structure is checked against the current list to see 2332 * if it exists already. 2333 */ 2334 xlist = &session->s_xa_list; 2335 smb_llist_enter(xlist, RW_WRITER); 2336 nxa = smb_llist_head(xlist); 2337 while (nxa) { 2338 ASSERT(nxa->xa_magic == SMB_XA_MAGIC); 2339 if (nxa->xa_smb_mid == xa->xa_smb_mid && 2340 nxa->smb_pid == xa->smb_pid && 2341 !SMB_XA_CLOSED(nxa) && 2342 !(nxa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 2343 smb_llist_exit(xlist); 2344 MEM_FREE("xa", xa); 2345 return (NULL); 2346 } 2347 nxa = smb_llist_next(xlist, nxa); 2348 } 2349 smb_llist_insert_tail(xlist, xa); 2350 smb_llist_exit(xlist); 2351 return (xa); 2352 } 2353 2354 void 2355 smb_xa_delete(smb_xa_t *xa) 2356 { 2357 ASSERT(xa->xa_refcnt == 0); 2358 ASSERT(SMB_XA_CLOSED(xa)); 2359 2360 if (xa->xa_smb_trans_name) 2361 MEM_FREE("smb", xa->xa_smb_trans_name); 2362 2363 if (xa->rep_setup_mb.chain != NULL) 2364 m_freem(xa->rep_setup_mb.chain); 2365 if (xa->rep_param_mb.chain != NULL) 2366 m_freem(xa->rep_param_mb.chain); 2367 if (xa->rep_data_mb.chain != NULL) 2368 m_freem(xa->rep_data_mb.chain); 2369 2370 xa->xa_magic = (uint32_t)~SMB_XA_MAGIC; 2371 MEM_FREE("xa", xa); 2372 } 2373 2374 smb_xa_t * 2375 smb_xa_hold(smb_xa_t *xa) 2376 { 2377 mutex_enter(&xa->xa_mutex); 2378 xa->xa_refcnt++; 2379 ASSERT(xa->xa_refcnt); 2380 mutex_exit(&xa->xa_mutex); 2381 return (xa); 2382 } 2383 2384 void 2385 smb_xa_rele(smb_session_t *session, smb_xa_t *xa) 2386 { 2387 mutex_enter(&xa->xa_mutex); 2388 ASSERT(xa->xa_refcnt); 2389 xa->xa_refcnt--; 2390 if (SMB_XA_CLOSED(xa) && (xa->xa_refcnt == 0)) { 2391 mutex_exit(&xa->xa_mutex); 2392 smb_llist_enter(&session->s_xa_list, RW_WRITER); 2393 smb_llist_remove(&session->s_xa_list, xa); 2394 smb_llist_exit(&session->s_xa_list); 2395 smb_xa_delete(xa); 2396 return; 2397 } 2398 mutex_exit(&xa->xa_mutex); 2399 } 2400 2401 int 2402 smb_xa_open(smb_xa_t *xa) 2403 { 2404 int rc; 2405 2406 mutex_enter(&xa->xa_mutex); 2407 2408 ASSERT((xa->xa_flags & SMB_XA_FLAG_OPEN) == 0); 2409 2410 if ((xa->xa_flags & SMB_XA_FLAG_CLOSE) == 0) { 2411 xa->xa_flags |= SMB_XA_FLAG_OPEN; 2412 rc = 0; 2413 } else { 2414 rc = ERROR_INVALID_HANDLE; 2415 } 2416 2417 mutex_exit(&xa->xa_mutex); 2418 2419 return (rc); 2420 } 2421 2422 void 2423 smb_xa_close(smb_xa_t *xa) 2424 { 2425 mutex_enter(&xa->xa_mutex); 2426 xa->xa_flags |= SMB_XA_FLAG_CLOSE; 2427 xa->xa_flags &= ~SMB_XA_FLAG_OPEN; 2428 2429 if (xa->xa_refcnt == 0) { 2430 mutex_exit(&xa->xa_mutex); 2431 smb_llist_enter(&xa->xa_session->s_xa_list, RW_WRITER); 2432 smb_llist_remove(&xa->xa_session->s_xa_list, xa); 2433 smb_llist_exit(&xa->xa_session->s_xa_list); 2434 smb_xa_delete(xa); 2435 return; 2436 } 2437 2438 mutex_exit(&xa->xa_mutex); 2439 } 2440 2441 int 2442 smb_xa_complete(smb_xa_t *xa) 2443 { 2444 int rc; 2445 2446 mutex_enter(&xa->xa_mutex); 2447 if (xa->xa_flags & (SMB_XA_FLAG_COMPLETE | SMB_XA_FLAG_CLOSE)) { 2448 rc = 0; 2449 } else { 2450 rc = 1; 2451 xa->xa_flags |= SMB_XA_FLAG_COMPLETE; 2452 } 2453 mutex_exit(&xa->xa_mutex); 2454 return (rc); 2455 } 2456 2457 smb_xa_t * 2458 smb_xa_find( 2459 smb_session_t *session, 2460 uint16_t pid, 2461 uint16_t mid) 2462 { 2463 smb_xa_t *xa; 2464 smb_llist_t *xlist; 2465 2466 xlist = &session->s_xa_list; 2467 smb_llist_enter(xlist, RW_READER); 2468 xa = smb_llist_head(xlist); 2469 while (xa) { 2470 mutex_enter(&xa->xa_mutex); 2471 if (xa->xa_smb_mid == mid && 2472 xa->smb_pid == pid && 2473 !SMB_XA_CLOSED(xa) && 2474 !(xa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 2475 xa->xa_refcnt++; 2476 ASSERT(xa->xa_refcnt); 2477 mutex_exit(&xa->xa_mutex); 2478 break; 2479 } 2480 mutex_exit(&xa->xa_mutex); 2481 xa = smb_llist_next(xlist, xa); 2482 } 2483 smb_llist_exit(xlist); 2484 return (xa); 2485 } 2486