1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Server Service RPC (SRVSVC) server-side interface definition. 28 * The server service provides a remote administration interface. 29 * 30 * This service uses NERR/Win32 error codes rather than NT status 31 * values. 32 */ 33 34 #include <sys/errno.h> 35 #include <unistd.h> 36 #include <netdb.h> 37 #include <strings.h> 38 #include <time.h> 39 #include <tzfile.h> 40 #include <time.h> 41 #include <thread.h> 42 #include <ctype.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <sys/types.h> 46 #include <sys/socket.h> 47 #include <netinet/in.h> 48 #include <arpa/inet.h> 49 #include <libshare.h> 50 51 #include <smbsrv/libsmb.h> 52 #include <smbsrv/libmlsvc.h> 53 #include <smbsrv/lmerr.h> 54 #include <smbsrv/nterror.h> 55 #include <smbsrv/nmpipes.h> 56 #include <smbsrv/cifs.h> 57 #include <smbsrv/netrauth.h> 58 #include <smbsrv/ndl/srvsvc.ndl> 59 #include <smbsrv/smb_common_door.h> 60 61 #define SV_TYPE_SENT_BY_ME (SV_TYPE_WORKSTATION | SV_TYPE_SERVER | SV_TYPE_NT) 62 63 /* 64 * Qualifier types for NetConnectEnum. 65 */ 66 #define SRVSVC_CONNECT_ENUM_NULL 0 67 #define SRVSVC_CONNECT_ENUM_SHARE 1 68 #define SRVSVC_CONNECT_ENUM_WKSTN 2 69 70 #define SMB_SRVSVC_MAXBUFLEN (8 * 1024 * 1024) 71 #define SMB_SRVSVC_MAXPREFLEN ((uint32_t)(-1)) 72 73 /* 74 * prefmaxlen: Client specified response buffer limit. 75 * resume_handle: Cookie used to track enumeration across multiple calls. 76 * n_total: Total number of entries. 77 * n_enum: Number of entries to enumerate (derived from prefmaxlen). 78 * n_skip: Number of entries to skip (from incoming resume handle). 79 * n_read: Number of objects returned for current enumeration request. 80 */ 81 typedef struct srvsvc_enum { 82 uint32_t se_level; 83 uint32_t se_prefmaxlen; 84 uint32_t se_resume_handle; 85 uint32_t se_n_total; 86 uint32_t se_n_enum; 87 uint32_t se_n_skip; 88 uint32_t se_n_read; 89 } srvsvc_enum_t; 90 91 static DWORD srvsvc_s_NetConnectEnumLevel0(ndr_xa_t *, 92 srvsvc_NetConnectInfo0_t *); 93 static DWORD srvsvc_s_NetConnectEnumLevel1(ndr_xa_t *, 94 srvsvc_NetConnectInfo1_t *); 95 96 static DWORD srvsvc_NetFileEnum2(ndr_xa_t *, 97 struct mslm_NetFileEnum *); 98 static DWORD srvsvc_NetFileEnum3(ndr_xa_t *, 99 struct mslm_NetFileEnum *); 100 101 static DWORD mlsvc_NetSessionEnumLevel0(struct mslm_infonres *, DWORD, 102 ndr_xa_t *); 103 static DWORD mlsvc_NetSessionEnumLevel1(struct mslm_infonres *, DWORD, 104 ndr_xa_t *); 105 106 static DWORD mlsvc_NetShareEnumLevel0(ndr_xa_t *, 107 struct mslm_infonres *, srvsvc_enum_t *, int); 108 static DWORD mlsvc_NetShareEnumLevel1(ndr_xa_t *, 109 struct mslm_infonres *, srvsvc_enum_t *, int); 110 static DWORD mlsvc_NetShareEnumLevel2(ndr_xa_t *, 111 struct mslm_infonres *, srvsvc_enum_t *, int); 112 static DWORD mlsvc_NetShareEnumLevel501(ndr_xa_t *, 113 struct mslm_infonres *, srvsvc_enum_t *, int); 114 static DWORD mlsvc_NetShareEnumLevel502(ndr_xa_t *, 115 struct mslm_infonres *, srvsvc_enum_t *, int); 116 static DWORD mlsvc_NetShareEnumCommon(ndr_xa_t *, 117 srvsvc_enum_t *, smb_share_t *, void *); 118 static boolean_t srvsvc_add_autohome(ndr_xa_t *, srvsvc_enum_t *, 119 void *); 120 static char *srvsvc_share_mkpath(ndr_xa_t *, char *); 121 122 static int srvsvc_netconnect_qualifier(const char *); 123 static uint32_t srvsvc_estimate_objcnt(uint32_t, uint32_t, uint32_t); 124 125 static uint32_t srvsvc_sa_add(char *, char *, char *); 126 static uint32_t srvsvc_sa_delete(char *); 127 128 static char empty_string[1]; 129 130 static ndr_stub_table_t srvsvc_stub_table[]; 131 132 static ndr_service_t srvsvc_service = { 133 "SRVSVC", /* name */ 134 "Server services", /* desc */ 135 "\\srvsvc", /* endpoint */ 136 PIPE_NTSVCS, /* sec_addr_port */ 137 "4b324fc8-1670-01d3-1278-5a47bf6ee188", 3, /* abstract */ 138 NDR_TRANSFER_SYNTAX_UUID, 2, /* transfer */ 139 0, /* no bind_instance_size */ 140 0, /* no bind_req() */ 141 0, /* no unbind_and_close() */ 142 0, /* use generic_call_stub() */ 143 &TYPEINFO(srvsvc_interface), /* interface ti */ 144 srvsvc_stub_table /* stub_table */ 145 }; 146 147 /* 148 * srvsvc_initialize 149 * 150 * This function registers the SRVSVC RPC interface with the RPC runtime 151 * library. It must be called in order to use either the client side 152 * or the server side functions. 153 */ 154 void 155 srvsvc_initialize(void) 156 { 157 (void) ndr_svc_register(&srvsvc_service); 158 } 159 160 /* 161 * srvsvc_s_NetConnectEnum 162 * 163 * List tree connections made to a share on this server or all tree 164 * connections established from a specific client. Administrator, 165 * Server Operator, Print Operator or Power User group membership 166 * is required to use this interface. 167 * 168 * There are three information levels: 0, 1, and 50. We don't support 169 * level 50, which is only used by Windows 9x clients. 170 * 171 * It seems Server Manger (srvmgr) only sends workstation as the qualifier 172 * and the Computer Management Interface on Windows 2000 doesn't request 173 * a list of connections. 174 * 175 * Return Values: 176 * ERROR_SUCCESS Success 177 * ERROR_ACCESS_DENIED Caller does not have access to this call. 178 * ERROR_INVALID_PARAMETER One of the parameters is invalid. 179 * ERROR_INVALID_LEVEL Unknown information level specified. 180 * ERROR_MORE_DATA Partial date returned, more entries available. 181 * ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available. 182 * NERR_NetNameNotFound The share qualifier cannot be found. 183 * NERR_BufTooSmall The supplied buffer is too small. 184 */ 185 static int 186 srvsvc_s_NetConnectEnum(void *arg, ndr_xa_t *mxa) 187 { 188 struct mslm_NetConnectEnum *param = arg; 189 srvsvc_NetConnectInfo0_t *info0; 190 srvsvc_NetConnectInfo1_t *info1; 191 char *qualifier; 192 int qualtype; 193 DWORD status = ERROR_SUCCESS; 194 195 if (!ndr_is_poweruser(mxa)) { 196 bzero(param, sizeof (struct mslm_NetConnectEnum)); 197 param->status = ERROR_ACCESS_DENIED; 198 return (NDR_DRC_OK); 199 } 200 201 qualifier = (char *)param->qualifier; 202 qualtype = srvsvc_netconnect_qualifier(qualifier); 203 204 if (qualtype == SRVSVC_CONNECT_ENUM_NULL) { 205 bzero(param, sizeof (struct mslm_NetConnectEnum)); 206 param->status = NERR_NetNameNotFound; 207 return (NDR_DRC_OK); 208 } 209 210 switch (param->info.level) { 211 case 0: 212 info0 = NDR_NEW(mxa, srvsvc_NetConnectInfo0_t); 213 if (info0 == NULL) { 214 status = ERROR_NOT_ENOUGH_MEMORY; 215 break; 216 } 217 218 bzero(info0, sizeof (srvsvc_NetConnectInfo0_t)); 219 param->info.ru.info0 = info0; 220 221 status = srvsvc_s_NetConnectEnumLevel0(mxa, info0); 222 223 param->total_entries = info0->entries_read; 224 param->resume_handle = NULL; 225 break; 226 227 case 1: 228 info1 = NDR_NEW(mxa, srvsvc_NetConnectInfo1_t); 229 if (info1 == NULL) { 230 status = ERROR_NOT_ENOUGH_MEMORY; 231 break; 232 } 233 234 bzero(info1, sizeof (srvsvc_NetConnectInfo1_t)); 235 param->info.ru.info1 = info1; 236 237 status = srvsvc_s_NetConnectEnumLevel1(mxa, info1); 238 239 param->total_entries = info1->entries_read; 240 param->resume_handle = NULL; 241 break; 242 243 case 50: 244 status = ERROR_NOT_SUPPORTED; 245 break; 246 247 default: 248 status = ERROR_INVALID_LEVEL; 249 break; 250 } 251 252 if (status != ERROR_SUCCESS) 253 bzero(param, sizeof (struct mslm_NetConnectEnum)); 254 255 param->status = status; 256 return (NDR_DRC_OK); 257 } 258 259 static DWORD 260 srvsvc_s_NetConnectEnumLevel0(ndr_xa_t *mxa, srvsvc_NetConnectInfo0_t *info0) 261 { 262 srvsvc_NetConnectInfoBuf0_t *ci0; 263 264 ci0 = NDR_NEW(mxa, srvsvc_NetConnectInfoBuf0_t); 265 if (ci0 == NULL) 266 return (ERROR_NOT_ENOUGH_MEMORY); 267 268 ci0->coni0_id = 0x17; 269 270 info0->ci0 = ci0; 271 info0->entries_read = 1; 272 return (ERROR_SUCCESS); 273 } 274 275 static DWORD 276 srvsvc_s_NetConnectEnumLevel1(ndr_xa_t *mxa, srvsvc_NetConnectInfo1_t *info1) 277 { 278 srvsvc_NetConnectInfoBuf1_t *ci1; 279 280 ci1 = NDR_NEW(mxa, srvsvc_NetConnectInfoBuf1_t); 281 if (ci1 == NULL) 282 return (ERROR_NOT_ENOUGH_MEMORY); 283 284 ci1->coni1_id = 0x17; 285 ci1->coni1_type = STYPE_IPC; 286 ci1->coni1_num_opens = 1; 287 ci1->coni1_num_users = 1; 288 ci1->coni1_time = 16; 289 ci1->coni1_username = (uint8_t *)NDR_STRDUP(mxa, "Administrator"); 290 ci1->coni1_netname = (uint8_t *)NDR_STRDUP(mxa, "IPC$"); 291 292 info1->ci1 = ci1; 293 info1->entries_read = 1; 294 return (ERROR_SUCCESS); 295 } 296 297 /* 298 * srvsvc_netconnect_qualifier 299 * 300 * The qualifier is a string that specifies a share name or computer name 301 * for the connections of interest. If it is a share name then all the 302 * connections made to that share name are listed. If it is a computer 303 * name (it starts with two backslash characters), then NetConnectEnum 304 * lists all connections made from that computer to the specified server. 305 */ 306 static int 307 srvsvc_netconnect_qualifier(const char *qualifier) 308 { 309 if (qualifier == NULL || *qualifier == '\0') 310 return (SRVSVC_CONNECT_ENUM_NULL); 311 312 if (strlen(qualifier) > MAXHOSTNAMELEN) 313 return (SRVSVC_CONNECT_ENUM_NULL); 314 315 if (qualifier[0] == '\\' && qualifier[1] == '\\') { 316 return (SRVSVC_CONNECT_ENUM_WKSTN); 317 } else { 318 if (!smb_shr_exists((char *)qualifier)) 319 return (SRVSVC_CONNECT_ENUM_NULL); 320 321 return (SRVSVC_CONNECT_ENUM_SHARE); 322 } 323 } 324 325 /* 326 * srvsvc_s_NetFileEnum 327 * 328 * Return information on open files or named pipes. Only members of the 329 * Administrators or Server Operators local groups are allowed to make 330 * this call. Currently, we only support Administrators. 331 * 332 * If basepath is null, all open resources are enumerated. If basepath 333 * is non-null, only resources that have basepath as a prefix should 334 * be returned. 335 * 336 * If username is specified (non-null), only files opened by username 337 * should be returned. 338 * 339 * Notes: 340 * 1. We don't validate the servername because we would have to check 341 * all primary IPs and the ROI seems unlikely to be worth it. 342 * 2. Both basepath and username are currently ignored because both 343 * Server Manger (NT 4.0) and CMI (Windows 2000) always set them to null. 344 * 345 * The level of information requested may be one of: 346 * 347 * 2 Return the file identification number. 348 * This level is not supported on Windows Me/98/95. 349 * 350 * 3 Return information about the file. 351 * This level is not supported on Windows Me/98/95. 352 * 353 * 50 Windows Me/98/95: Return information about the file. 354 * 355 * Note: 356 * If pref_max_len is unlimited and resume_handle is null, the client 357 * expects to receive all data in a single call. 358 * If we are unable to do fit all data in a single response, we would 359 * normally return ERROR_MORE_DATA with a partial list. 360 * 361 * Unfortunately, when both of these conditions occur, Server Manager 362 * pops up an error box with the message "more data available" and 363 * doesn't display any of the returned data. In this case, it is 364 * probably better to return ERROR_SUCCESS with the partial list. 365 * Windows 2000 doesn't have this problem because it always sends a 366 * non-null resume_handle. 367 * 368 * Return Values: 369 * ERROR_SUCCESS Success 370 * ERROR_ACCESS_DENIED Caller does not have access to this call. 371 * ERROR_INVALID_PARAMETER One of the parameters is invalid. 372 * ERROR_INVALID_LEVEL Unknown information level specified. 373 * ERROR_MORE_DATA Partial date returned, more entries available. 374 * ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available. 375 * NERR_BufTooSmall The supplied buffer is too small. 376 */ 377 static int 378 srvsvc_s_NetFileEnum(void *arg, ndr_xa_t *mxa) 379 { 380 struct mslm_NetFileEnum *param = arg; 381 DWORD status; 382 383 if (!ndr_is_admin(mxa)) { 384 bzero(param, sizeof (struct mslm_NetFileEnum)); 385 param->status = ERROR_ACCESS_DENIED; 386 return (NDR_DRC_OK); 387 } 388 389 switch (param->info.switch_value) { 390 case 2: 391 status = srvsvc_NetFileEnum2(mxa, param); 392 break; 393 394 case 3: 395 status = srvsvc_NetFileEnum3(mxa, param); 396 break; 397 398 case 50: 399 status = ERROR_NOT_SUPPORTED; 400 break; 401 402 default: 403 status = ERROR_INVALID_LEVEL; 404 break; 405 } 406 407 if (status != ERROR_SUCCESS) { 408 bzero(param, sizeof (struct mslm_NetFileEnum)); 409 param->status = status; 410 return (NDR_DRC_OK); 411 } 412 413 if (param->resume_handle) 414 *param->resume_handle = 0; 415 416 param->status = ERROR_SUCCESS; 417 return (NDR_DRC_OK); 418 } 419 420 /* 421 * Build level 2 file information. 422 * 423 * On success, the caller expects that the info2, fi2 and entries_read 424 * fields have been set up. 425 */ 426 static DWORD 427 srvsvc_NetFileEnum2(ndr_xa_t *mxa, struct mslm_NetFileEnum *param) 428 { 429 struct mslm_NetFileInfoBuf2 *fi2; 430 ndr_pipe_info_t pi; 431 uint32_t entries_read = 0; 432 int i; 433 434 param->info.ru.info2 = NDR_NEW(mxa, struct mslm_NetFileInfo2); 435 if (param->info.ru.info3 == NULL) 436 return (ERROR_NOT_ENOUGH_MEMORY); 437 438 fi2 = NDR_NEWN(mxa, struct mslm_NetFileInfoBuf2, 128); 439 if (fi2 == NULL) 440 return (ERROR_NOT_ENOUGH_MEMORY); 441 442 param->info.ru.info2->fi2 = fi2; 443 444 for (i = 0; i < 128; ++i) { 445 if (ndr_pipe_getinfo(i, &pi) == -1) 446 continue; 447 448 fi2->fi2_id = pi.npi_fid; 449 450 ++entries_read; 451 ++fi2; 452 } 453 454 param->info.ru.info2->entries_read = entries_read; 455 param->total_entries = entries_read; 456 return (ERROR_SUCCESS); 457 } 458 459 /* 460 * Build level 3 file information. 461 * 462 * On success, the caller expects that the info3, fi3 and entries_read 463 * fields have been set up. 464 */ 465 static DWORD 466 srvsvc_NetFileEnum3(ndr_xa_t *mxa, struct mslm_NetFileEnum *param) 467 { 468 struct mslm_NetFileInfoBuf3 *fi3; 469 ndr_pipe_info_t pi; 470 uint32_t entries_read = 0; 471 int i; 472 473 param->info.ru.info3 = NDR_NEW(mxa, struct mslm_NetFileInfo3); 474 if (param->info.ru.info3 == NULL) 475 return (ERROR_NOT_ENOUGH_MEMORY); 476 477 fi3 = NDR_NEWN(mxa, struct mslm_NetFileInfoBuf3, 128); 478 if (fi3 == NULL) 479 return (ERROR_NOT_ENOUGH_MEMORY); 480 481 param->info.ru.info3->fi3 = fi3; 482 483 for (i = 0; i < 128; ++i) { 484 if (ndr_pipe_getinfo(i, &pi) == -1) 485 continue; 486 487 fi3->fi3_id = pi.npi_fid; 488 fi3->fi3_permissions = pi.npi_permissions; 489 fi3->fi3_num_locks = pi.npi_num_locks; 490 fi3->fi3_pathname = (uint8_t *) 491 NDR_STRDUP(mxa, pi.npi_pathname); 492 fi3->fi3_username = (uint8_t *) 493 NDR_STRDUP(mxa, pi.npi_username); 494 495 ++entries_read; 496 ++fi3; 497 } 498 499 param->info.ru.info3->entries_read = entries_read; 500 param->total_entries = entries_read; 501 return (ERROR_SUCCESS); 502 } 503 504 /* 505 * srvsvc_s_NetFileClose 506 * 507 * NetFileClose forces a file to close. This function can be used when 508 * an error prevents closure by any other means. Use NetFileClose with 509 * caution because it does not flush data, cached on a client, to the 510 * file before closing the file. 511 * 512 * Return Values 513 * ERROR_SUCCESS Operation succeeded. 514 * ERROR_ACCESS_DENIED Operation denied. 515 * NERR_FileIdNotFound No open file with the specified id. 516 * 517 * Note: MSDN suggests that the error code should be ERROR_FILE_NOT_FOUND 518 * but network captures using NT show NERR_FileIdNotFound. 519 * The NetFileClose2 MSDN page has the right error code. 520 */ 521 static int 522 srvsvc_s_NetFileClose(void *arg, ndr_xa_t *mxa) 523 { 524 struct mslm_NetFileClose *param = arg; 525 526 if (!ndr_is_admin(mxa)) { 527 bzero(param, sizeof (struct mslm_NetFileClose)); 528 param->status = ERROR_ACCESS_DENIED; 529 return (NDR_DRC_OK); 530 } 531 532 bzero(param, sizeof (struct mslm_NetFileClose)); 533 param->status = ERROR_SUCCESS; 534 return (NDR_DRC_OK); 535 } 536 537 538 /* 539 * srvsvc_s_NetShareGetInfo 540 * 541 * Returns Win32 error codes. 542 */ 543 static int 544 srvsvc_s_NetShareGetInfo(void *arg, ndr_xa_t *mxa) 545 { 546 struct mlsm_NetShareGetInfo *param = arg; 547 struct mslm_NetShareGetInfo0 *info0; 548 struct mslm_NetShareGetInfo1 *info1; 549 struct mslm_NetShareGetInfo2 *info2; 550 struct mslm_NetShareGetInfo501 *info501; 551 struct mslm_NetShareGetInfo502 *info502; 552 struct mslm_NetShareGetInfo1004 *info1004; 553 struct mslm_NetShareGetInfo1005 *info1005; 554 struct mslm_NetShareGetInfo1006 *info1006; 555 smb_share_t si; 556 DWORD status; 557 558 status = smb_shr_get((char *)param->netname, &si); 559 if (status != NERR_Success) { 560 bzero(param, sizeof (struct mlsm_NetShareGetInfo)); 561 param->status = status; 562 return (NDR_DRC_OK); 563 } 564 565 switch (param->level) { 566 case 0: 567 info0 = NDR_NEW(mxa, struct mslm_NetShareGetInfo0); 568 if (info0 == NULL) { 569 status = ERROR_NOT_ENOUGH_MEMORY; 570 break; 571 } 572 573 info0->shi0_netname 574 = (uint8_t *)NDR_STRDUP(mxa, si.shr_name); 575 if (info0->shi0_netname == NULL) { 576 status = ERROR_NOT_ENOUGH_MEMORY; 577 break; 578 } 579 580 param->result.ru.info0 = info0; 581 break; 582 583 case 1: 584 info1 = NDR_NEW(mxa, struct mslm_NetShareGetInfo1); 585 if (info1 == NULL) { 586 status = ERROR_NOT_ENOUGH_MEMORY; 587 break; 588 } 589 590 info1->shi1_netname = (uint8_t *)NDR_STRDUP(mxa, si.shr_name); 591 info1->shi1_comment = (uint8_t *)NDR_STRDUP(mxa, si.shr_cmnt); 592 if (info1->shi1_netname == NULL || 593 info1->shi1_comment == NULL) { 594 status = ERROR_NOT_ENOUGH_MEMORY; 595 break; 596 } 597 598 info1->shi1_type = si.shr_type; 599 param->result.ru.info1 = info1; 600 break; 601 602 case 2: 603 info2 = NDR_NEW(mxa, struct mslm_NetShareGetInfo2); 604 if (info2 == NULL) { 605 status = ERROR_NOT_ENOUGH_MEMORY; 606 break; 607 } 608 609 info2->shi2_netname = (uint8_t *)NDR_STRDUP(mxa, si.shr_name); 610 info2->shi2_comment = (uint8_t *)NDR_STRDUP(mxa, si.shr_cmnt); 611 if (info2->shi2_netname == NULL || 612 info2->shi2_comment == NULL) { 613 status = ERROR_NOT_ENOUGH_MEMORY; 614 break; 615 } 616 617 info2->shi2_path = 618 (uint8_t *)srvsvc_share_mkpath(mxa, si.shr_path); 619 info2->shi2_passwd = 0; 620 info2->shi2_type = si.shr_type; 621 info2->shi2_permissions = 0; 622 info2->shi2_max_uses = SHI_USES_UNLIMITED; 623 info2->shi2_current_uses = 0; 624 param->result.ru.info2 = info2; 625 break; 626 627 case 1004: 628 info1004 = NDR_NEW(mxa, struct mslm_NetShareGetInfo1004); 629 if (info1004 == NULL) { 630 status = ERROR_NOT_ENOUGH_MEMORY; 631 break; 632 } 633 634 info1004->shi1004_comment = 635 (uint8_t *)NDR_STRDUP(mxa, si.shr_cmnt); 636 if (info1004->shi1004_comment == NULL) 637 status = ERROR_NOT_ENOUGH_MEMORY; 638 break; 639 640 case 1005: 641 info1005 = NDR_NEW(mxa, struct mslm_NetShareGetInfo1005); 642 if (info1005 == NULL) { 643 status = ERROR_NOT_ENOUGH_MEMORY; 644 break; 645 } 646 647 info1005->shi1005_flags = 0; 648 649 switch (si.shr_flags & SMB_SHRF_CSC_MASK) { 650 case SMB_SHRF_CSC_DISABLED: 651 info1005->shi1005_flags |= CSC_CACHE_NONE; 652 break; 653 case SMB_SHRF_CSC_AUTO: 654 info1005->shi1005_flags |= CSC_CACHE_AUTO_REINT; 655 break; 656 case SMB_SHRF_CSC_VDO: 657 info1005->shi1005_flags |= CSC_CACHE_VDO; 658 break; 659 case SMB_SHRF_CSC_MANUAL: 660 default: 661 /* 662 * Default to CSC_CACHE_MANUAL_REINT. 663 */ 664 break; 665 } 666 667 param->result.ru.info1005 = info1005; 668 break; 669 670 case 1006: 671 info1006 = NDR_NEW(mxa, struct mslm_NetShareGetInfo1006); 672 if (info1006 == NULL) { 673 status = ERROR_NOT_ENOUGH_MEMORY; 674 break; 675 } 676 info1006->shi1006_max_uses = SHI_USES_UNLIMITED; 677 param->result.ru.info1006 = info1006; 678 break; 679 680 case 501: 681 /* 682 * Level 501 provides level 1 information. 683 */ 684 info501 = NDR_NEW(mxa, struct mslm_NetShareGetInfo501); 685 if (info501 == NULL) { 686 status = ERROR_NOT_ENOUGH_MEMORY; 687 break; 688 } 689 690 info501->shi501_netname = 691 (uint8_t *)NDR_STRDUP(mxa, si.shr_name); 692 info501->shi501_comment = 693 (uint8_t *)NDR_STRDUP(mxa, si.shr_cmnt); 694 if (info501->shi501_netname == NULL || 695 info501->shi501_comment == NULL) { 696 status = ERROR_NOT_ENOUGH_MEMORY; 697 break; 698 } 699 700 info501->shi501_type = si.shr_type; 701 info501->shi501_reserved = 0; 702 param->result.ru.info501 = info501; 703 break; 704 705 case 502: 706 /* 707 * Level 502 provides level 2 information plus a 708 * security descriptor. We don't support security 709 * descriptors on shares yet. 710 */ 711 info502 = NDR_NEW(mxa, struct mslm_NetShareGetInfo502); 712 if (info502 == NULL) { 713 status = ERROR_NOT_ENOUGH_MEMORY; 714 break; 715 } 716 717 info502->shi502_netname = 718 (uint8_t *)NDR_STRDUP(mxa, si.shr_name); 719 info502->shi502_comment = 720 (uint8_t *)NDR_STRDUP(mxa, si.shr_cmnt); 721 if (info502->shi502_netname == NULL || 722 info502->shi502_comment == NULL) { 723 status = ERROR_NOT_ENOUGH_MEMORY; 724 break; 725 } 726 727 info502->shi502_path = 728 (uint8_t *)srvsvc_share_mkpath(mxa, si.shr_path); 729 info502->shi502_passwd = 0; 730 info502->shi502_type = si.shr_type; 731 info502->shi502_permissions = 0; 732 info502->shi502_max_uses = SHI_USES_UNLIMITED; 733 info502->shi502_current_uses = 0; 734 info502->shi502_reserved = 0; 735 info502->shi502_security_descriptor = 0; 736 param->result.ru.info502 = info502; 737 break; 738 739 default: 740 status = ERROR_ACCESS_DENIED; 741 break; 742 } 743 744 if (status != ERROR_SUCCESS) 745 bzero(param, sizeof (struct mlsm_NetShareGetInfo)); 746 else 747 param->result.switch_value = param->level; 748 749 param->status = status; 750 return (NDR_DRC_OK); 751 } 752 753 754 /* 755 * srvsvc_s_NetShareSetInfo 756 * 757 * This call is made by SrvMgr to set share information. 758 * Always returns ERROR_ACCESS_DENIED for now. 759 * 760 * Returns Win32 error codes. 761 */ 762 static int 763 srvsvc_s_NetShareSetInfo(void *arg, ndr_xa_t *mxa) 764 { 765 struct mlsm_NetShareSetInfo *param = arg; 766 767 (void) memset(param, 0, sizeof (struct mlsm_NetShareSetInfo)); 768 param->parm_err_ptr = (DWORD)(uintptr_t)NDR_MALLOC(mxa, 769 sizeof (DWORD)); 770 param->parm_err = 0; 771 772 if (!smb_config_getbool(SMB_CI_SRVSVC_SHRSET_ENABLE)) 773 param->status = ERROR_SUCCESS; 774 else 775 param->status = ERROR_ACCESS_DENIED; 776 777 return (NDR_DRC_OK); 778 } 779 780 /* 781 * srvsvc_s_NetSessionEnum 782 * 783 * Level 1 request is made by (Server Manager (srvmgr) on NT Server when 784 * the user info icon is selected. 785 * 786 * On success, the return value is NERR_Success. 787 * On error, the return value can be one of the following error codes: 788 * 789 * ERROR_ACCESS_DENIED The user does not have access to the requested 790 * information. 791 * ERROR_INVALID_LEVEL The value specified for the level is invalid. 792 * ERROR_INVALID_PARAMETER The specified parameter is invalid. 793 * ERROR_MORE_DATA More entries are available. Specify a large 794 * enough buffer to receive all entries. 795 * ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available. 796 * NERR_ClientNameNotFound A session does not exist with the computer name. 797 * NERR_InvalidComputer The computer name is invalid. 798 * NERR_UserNotFound The user name could not be found. 799 */ 800 static int 801 srvsvc_s_NetSessionEnum(void *arg, ndr_xa_t *mxa) 802 { 803 struct mslm_NetSessionEnum *param = arg; 804 struct mslm_infonres *infonres; 805 DWORD status; 806 DWORD n_sessions; 807 808 infonres = NDR_NEW(mxa, struct mslm_infonres); 809 if (infonres == NULL) { 810 bzero(param, sizeof (struct mslm_NetSessionEnum)); 811 param->status = ERROR_NOT_ENOUGH_MEMORY; 812 return (NDR_DRC_OK); 813 } 814 815 infonres->entriesread = 0; 816 infonres->entries = NULL; 817 param->result.level = param->level; 818 param->result.bufptr.p = infonres; 819 param->total_entries = 0; 820 param->resume_handle = NULL; 821 param->status = ERROR_SUCCESS; 822 823 if ((n_sessions = (DWORD) mlsvc_get_num_users()) == 0) 824 return (NDR_DRC_OK); 825 826 switch (param->level) { 827 case 0: 828 status = mlsvc_NetSessionEnumLevel0(infonres, n_sessions, mxa); 829 break; 830 831 case 1: 832 status = mlsvc_NetSessionEnumLevel1(infonres, n_sessions, mxa); 833 break; 834 835 default: 836 status = ERROR_INVALID_LEVEL; 837 break; 838 } 839 840 if (status != 0) { 841 bzero(param, sizeof (struct mslm_NetSessionEnum)); 842 param->status = status; 843 return (NDR_DRC_OK); 844 } 845 846 param->total_entries = infonres->entriesread; 847 param->status = status; 848 return (NDR_DRC_OK); 849 } 850 851 /* 852 * mlsvc_NetSessionEnumLevel0 853 * 854 * Build the level 0 session information. 855 */ 856 static DWORD 857 mlsvc_NetSessionEnumLevel0(struct mslm_infonres *infonres, DWORD n_sessions, 858 ndr_xa_t *mxa) 859 { 860 struct mslm_SESSION_INFO_0 *info0; 861 smb_dr_ulist_t *ulist; 862 smb_opipe_context_t *user; 863 char *workstation; 864 char ipaddr_buf[INET_ADDRSTRLEN]; 865 int n_users; 866 int offset = 0; 867 int i; 868 869 if ((ulist = malloc(sizeof (smb_dr_ulist_t))) == NULL) 870 return (ERROR_NOT_ENOUGH_MEMORY); 871 872 if ((n_users = mlsvc_get_user_list(offset, ulist)) == 0) { 873 smb_dr_ulist_free(ulist); 874 return (ERROR_NOT_ENOUGH_MEMORY); 875 } 876 877 if (n_users < n_sessions) 878 n_sessions = n_users; 879 880 info0 = NDR_NEWN(mxa, struct mslm_SESSION_INFO_0, n_sessions); 881 if (info0 == NULL) { 882 smb_dr_ulist_free(ulist); 883 return (ERROR_NOT_ENOUGH_MEMORY); 884 } 885 886 for (i = 0; i < n_sessions; ++i) { 887 user = &ulist->dul_users[i]; 888 889 workstation = user->oc_workstation; 890 if (workstation == NULL || *workstation == '\0') { 891 (void) inet_ntop(AF_INET, (char *)&user->oc_ipaddr, 892 ipaddr_buf, sizeof (ipaddr_buf)); 893 workstation = ipaddr_buf; 894 } 895 896 info0[i].sesi0_cname = NDR_STRDUP(mxa, workstation); 897 if (info0[i].sesi0_cname == NULL) { 898 smb_dr_ulist_free(ulist); 899 return (ERROR_NOT_ENOUGH_MEMORY); 900 } 901 } 902 903 smb_dr_ulist_free(ulist); 904 infonres->entriesread = n_sessions; 905 infonres->entries = info0; 906 return (ERROR_SUCCESS); 907 } 908 909 /* 910 * mlsvc_NetSessionEnumLevel1 911 * 912 * Build the level 1 session information. 913 */ 914 static DWORD 915 mlsvc_NetSessionEnumLevel1(struct mslm_infonres *infonres, DWORD n_sessions, 916 ndr_xa_t *mxa) 917 { 918 struct mslm_SESSION_INFO_1 *info1; 919 smb_dr_ulist_t *ulist; 920 smb_opipe_context_t *user; 921 char *workstation; 922 char account[MAXNAMELEN]; 923 char ipaddr_buf[INET_ADDRSTRLEN]; 924 int n_users; 925 int offset = 0; 926 int i; 927 928 if ((ulist = malloc(sizeof (smb_dr_ulist_t))) == NULL) 929 return (ERROR_NOT_ENOUGH_MEMORY); 930 931 if ((n_users = mlsvc_get_user_list(offset, ulist)) == 0) { 932 smb_dr_ulist_free(ulist); 933 return (ERROR_NOT_ENOUGH_MEMORY); 934 } 935 936 if (n_users < n_sessions) 937 n_sessions = n_users; 938 939 info1 = NDR_NEWN(mxa, struct mslm_SESSION_INFO_1, n_sessions); 940 if (info1 == NULL) { 941 smb_dr_ulist_free(ulist); 942 return (ERROR_NOT_ENOUGH_MEMORY); 943 } 944 945 for (i = 0; i < n_sessions; ++i) { 946 user = &ulist->dul_users[i]; 947 948 workstation = user->oc_workstation; 949 if (workstation == NULL || *workstation == '\0') { 950 (void) inet_ntop(AF_INET, (char *)&user->oc_ipaddr, 951 ipaddr_buf, sizeof (ipaddr_buf)); 952 workstation = ipaddr_buf; 953 } 954 955 (void) snprintf(account, MAXNAMELEN, "%s\\%s", 956 user->oc_domain, user->oc_account); 957 958 info1[i].sesi1_cname = NDR_STRDUP(mxa, workstation); 959 info1[i].sesi1_uname = NDR_STRDUP(mxa, account); 960 961 if (info1[i].sesi1_cname == NULL || 962 info1[i].sesi1_uname == NULL) { 963 smb_dr_ulist_free(ulist); 964 return (ERROR_NOT_ENOUGH_MEMORY); 965 } 966 967 info1[i].sesi1_nopens = 1; 968 info1[i].sesi1_time = time(0) - user->oc_logon_time; 969 info1[i].sesi1_itime = 0; 970 info1[i].sesi1_uflags = 971 (user->oc_flags & SMB_ATF_GUEST) ? SESS_GUEST : 0; 972 } 973 974 smb_dr_ulist_free(ulist); 975 infonres->entriesread = n_sessions; 976 infonres->entries = info1; 977 return (ERROR_SUCCESS); 978 } 979 980 /* 981 * srvsvc_s_NetSessionDel 982 * 983 * Ends a network session between a server and a workstation. 984 * On NT only members of the Administrators or Account Operators 985 * local groups are permitted to use NetSessionDel. 986 * 987 * Return Values 988 * If the function succeeds, the return value is NERR_Success/ 989 * ERROR_SUCCESS. If the function fails, the return value can be 990 * one of the following error codes: 991 * 992 * ERROR_ACCESS_DENIED The user does not have access to the 993 * requested information. 994 * ERROR_INVALID_PARAMETER The specified parameter is invalid. 995 * ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available. 996 * NERR_ClientNameNotFound A session does not exist with that 997 * computer name. 998 */ 999 static int 1000 srvsvc_s_NetSessionDel(void *arg, ndr_xa_t *mxa) 1001 { 1002 struct mslm_NetSessionDel *param = arg; 1003 1004 if (!ndr_is_poweruser(mxa)) { 1005 param->status = ERROR_ACCESS_DENIED; 1006 return (NDR_DRC_OK); 1007 } 1008 1009 param->status = ERROR_ACCESS_DENIED; 1010 return (NDR_DRC_OK); 1011 } 1012 1013 /* 1014 * SRVSVC NetServerGetInfo 1015 * 1016 * IN LPTSTR servername, 1017 * IN DWORD level, 1018 * OUT union switch(level) { 1019 * case 100: mslm_SERVER_INFO_100 *p100; 1020 * case 101: mslm_SERVER_INFO_101 *p101; 1021 * case 102: mslm_SERVER_INFO_102 *p102; 1022 * default: char *nullptr; 1023 * } bufptr, 1024 * OUT DWORD status 1025 */ 1026 static int 1027 srvsvc_s_NetServerGetInfo(void *arg, ndr_xa_t *mxa) 1028 { 1029 struct mslm_NetServerGetInfo *param = arg; 1030 struct mslm_SERVER_INFO_100 *info100; 1031 struct mslm_SERVER_INFO_101 *info101; 1032 struct mslm_SERVER_INFO_102 *info102; 1033 char sys_comment[SMB_PI_MAX_COMMENT]; 1034 char hostname[NETBIOS_NAME_SZ]; 1035 1036 if (smb_getnetbiosname(hostname, sizeof (hostname)) != 0) { 1037 netservergetinfo_no_memory: 1038 bzero(param, sizeof (struct mslm_NetServerGetInfo)); 1039 return (ERROR_NOT_ENOUGH_MEMORY); 1040 } 1041 1042 (void) smb_config_getstr(SMB_CI_SYS_CMNT, sys_comment, 1043 sizeof (sys_comment)); 1044 if (*sys_comment == '\0') 1045 (void) strcpy(sys_comment, " "); 1046 1047 switch (param->level) { 1048 case 100: 1049 info100 = NDR_NEW(mxa, struct mslm_SERVER_INFO_100); 1050 if (info100 == NULL) 1051 goto netservergetinfo_no_memory; 1052 1053 bzero(info100, sizeof (struct mslm_SERVER_INFO_100)); 1054 info100->sv100_platform_id = SV_PLATFORM_ID_NT; 1055 info100->sv100_name = (uint8_t *)NDR_STRDUP(mxa, hostname); 1056 if (info100->sv100_name == NULL) 1057 goto netservergetinfo_no_memory; 1058 1059 param->result.bufptr.bufptr100 = info100; 1060 break; 1061 1062 case 101: 1063 info101 = NDR_NEW(mxa, struct mslm_SERVER_INFO_101); 1064 if (info101 == NULL) 1065 goto netservergetinfo_no_memory; 1066 1067 bzero(info101, sizeof (struct mslm_SERVER_INFO_101)); 1068 info101->sv101_platform_id = SV_PLATFORM_ID_NT; 1069 info101->sv101_version_major = 4; 1070 info101->sv101_version_minor = 0; 1071 info101->sv101_type = SV_TYPE_SENT_BY_ME; 1072 info101->sv101_name = (uint8_t *)NDR_STRDUP(mxa, hostname); 1073 info101->sv101_comment 1074 = (uint8_t *)NDR_STRDUP(mxa, sys_comment); 1075 1076 if (info101->sv101_name == NULL || 1077 info101->sv101_comment == NULL) 1078 goto netservergetinfo_no_memory; 1079 1080 param->result.bufptr.bufptr101 = info101; 1081 break; 1082 1083 case 102: 1084 info102 = NDR_NEW(mxa, struct mslm_SERVER_INFO_102); 1085 if (info102 == NULL) 1086 goto netservergetinfo_no_memory; 1087 1088 bzero(info102, sizeof (struct mslm_SERVER_INFO_102)); 1089 info102->sv102_platform_id = SV_PLATFORM_ID_NT; 1090 info102->sv102_version_major = 4; 1091 info102->sv102_version_minor = 0; 1092 info102->sv102_type = SV_TYPE_SENT_BY_ME; 1093 info102->sv102_name = (uint8_t *)NDR_STRDUP(mxa, hostname); 1094 info102->sv102_comment 1095 = (uint8_t *)NDR_STRDUP(mxa, sys_comment); 1096 1097 /* 1098 * The following level 102 fields are defaulted to zero 1099 * by virtue of the call to bzero above. 1100 * 1101 * sv102_users 1102 * sv102_disc 1103 * sv102_hidden 1104 * sv102_announce 1105 * sv102_anndelta 1106 * sv102_licenses 1107 * sv102_userpath 1108 */ 1109 if (info102->sv102_name == NULL || 1110 info102->sv102_comment == NULL) 1111 goto netservergetinfo_no_memory; 1112 1113 param->result.bufptr.bufptr102 = info102; 1114 break; 1115 1116 default: 1117 bzero(¶m->result, 1118 sizeof (struct mslm_NetServerGetInfo_result)); 1119 param->status = ERROR_ACCESS_DENIED; 1120 return (NDR_DRC_OK); 1121 } 1122 1123 param->result.level = param->level; 1124 param->status = (ERROR_SUCCESS); 1125 return (NDR_DRC_OK); 1126 } 1127 1128 /* 1129 * NetRemoteTOD 1130 * 1131 * Returns information about the time of day on this server. 1132 * 1133 * typedef struct _TIME_OF_DAY_INFO { 1134 * DWORD tod_elapsedt; // seconds since 00:00:00 January 1 1970 GMT 1135 * DWORD tod_msecs; // arbitrary milliseconds (since reset) 1136 * DWORD tod_hours; // current hour [0-23] 1137 * DWORD tod_mins; // current minute [0-59] 1138 * DWORD tod_secs; // current second [0-59] 1139 * DWORD tod_hunds; // current hundredth (0.01) second [0-99] 1140 * LONG tod_timezone; // time zone of the server 1141 * DWORD tod_tinterval; // clock tick time interval 1142 * DWORD tod_day; // day of the month [1-31] 1143 * DWORD tod_month; // month of the year [1-12] 1144 * DWORD tod_year; // current year 1145 * DWORD tod_weekday; // day of the week since Sunday [0-6] 1146 * } TIME_OF_DAY_INFO; 1147 * 1148 * The time zone of the server is calculated in minutes from Greenwich 1149 * Mean Time (GMT). For time zones west of Greenwich, the value is 1150 * positive; for time zones east of Greenwich, the value is negative. 1151 * A value of -1 indicates that the time zone is undefined. 1152 * 1153 * The clock tick value represents a resolution of one ten-thousandth 1154 * (0.0001) second. 1155 */ 1156 static int 1157 srvsvc_s_NetRemoteTOD(void *arg, ndr_xa_t *mxa) 1158 { 1159 struct mslm_NetRemoteTOD *param = arg; 1160 struct mslm_TIME_OF_DAY_INFO *tod; 1161 struct timeval time_val; 1162 struct tm tm; 1163 1164 (void) gettimeofday(&time_val, 0); 1165 (void) gmtime_r(&time_val.tv_sec, &tm); 1166 1167 tod = NDR_NEW(mxa, struct mslm_TIME_OF_DAY_INFO); 1168 if (tod == NULL) { 1169 bzero(param, sizeof (struct mslm_NetRemoteTOD)); 1170 return (ERROR_NOT_ENOUGH_MEMORY); 1171 } 1172 1173 tod->tod_elapsedt = time_val.tv_sec; 1174 tod->tod_msecs = time_val.tv_usec; 1175 tod->tod_hours = tm.tm_hour; 1176 tod->tod_mins = tm.tm_min; 1177 tod->tod_secs = tm.tm_sec; 1178 tod->tod_hunds = 0; 1179 tod->tod_tinterval = 1000; 1180 tod->tod_day = tm.tm_mday; 1181 tod->tod_month = tm.tm_mon+1; 1182 tod->tod_year = tm.tm_year+1900; 1183 tod->tod_weekday = tm.tm_wday; 1184 1185 (void) localtime_r(&time_val.tv_sec, &tm); 1186 1187 param->bufptr = tod; 1188 param->status = ERROR_SUCCESS; 1189 return (NDR_DRC_OK); 1190 } 1191 1192 /* 1193 * srvsvc_s_NetNameValidate 1194 * 1195 * Perform name validation. 1196 * 1197 * The share name is considered invalid if it contains any of the 1198 * following character (MSDN 236388). 1199 * 1200 * " / \ [ ] : | < > + ; , ? * = 1201 * 1202 * Returns Win32 error codes. 1203 */ 1204 /*ARGSUSED*/ 1205 static int 1206 srvsvc_s_NetNameValidate(void *arg, ndr_xa_t *mxa) 1207 { 1208 struct mslm_NetNameValidate *param = arg; 1209 char *name; 1210 int len; 1211 1212 if ((name = (char *)param->pathname) == NULL) { 1213 param->status = ERROR_INVALID_PARAMETER; 1214 return (NDR_DRC_OK); 1215 } 1216 1217 len = strlen(name); 1218 1219 if ((param->flags == 0 && len > 81) || 1220 (param->flags == 0x80000000 && len > 13)) { 1221 param->status = ERROR_INVALID_NAME; 1222 return (NDR_DRC_OK); 1223 } 1224 1225 switch (param->type) { 1226 case NAMETYPE_SHARE: 1227 if (smb_shr_chkname(name)) 1228 param->status = ERROR_SUCCESS; 1229 else 1230 param->status = ERROR_INVALID_NAME; 1231 break; 1232 1233 case NAMETYPE_USER: 1234 case NAMETYPE_PASSWORD: 1235 case NAMETYPE_GROUP: 1236 case NAMETYPE_COMPUTER: 1237 case NAMETYPE_EVENT: 1238 case NAMETYPE_DOMAIN: 1239 case NAMETYPE_SERVICE: 1240 case NAMETYPE_NET: 1241 case NAMETYPE_MESSAGE: 1242 case NAMETYPE_MESSAGEDEST: 1243 case NAMETYPE_SHAREPASSWORD: 1244 case NAMETYPE_WORKGROUP: 1245 param->status = ERROR_NOT_SUPPORTED; 1246 break; 1247 1248 default: 1249 param->status = ERROR_INVALID_PARAMETER; 1250 break; 1251 } 1252 1253 return (NDR_DRC_OK); 1254 } 1255 1256 /* 1257 * srvsvc_s_NetShareAdd 1258 * 1259 * Add a new share. We support info levels 2 and 502 but ignore the 1260 * security descriptor in level 502 requests. Only the administrator, 1261 * or a member of the domain administrators group, is allowed to add 1262 * shares. 1263 * 1264 * This interface is used by the rmtshare command from the NT resource 1265 * kit. Rmtshare allows a client to add or remove shares on a server 1266 * from the client's command line. 1267 * 1268 * Note that we don't support security descriptors on a share. If the 1269 * /grant is used, the share will be created but the subsequent attempt 1270 * to manipulate the security descriptor (NetShareGetInfo) will fail. 1271 * Similarly for the /remove option. 1272 * 1273 * Returns Win32 error codes. 1274 */ 1275 static int 1276 srvsvc_s_NetShareAdd(void *arg, ndr_xa_t *mxa) 1277 { 1278 static DWORD parm_err = 0; 1279 DWORD parm_stat; 1280 struct mslm_NetShareAdd *param = arg; 1281 struct mslm_SHARE_INFO_2 *info2; 1282 char realpath[MAXPATHLEN]; 1283 int32_t native_os; 1284 1285 native_os = ndr_native_os(mxa); 1286 1287 if (!ndr_is_poweruser(mxa)) { 1288 bzero(param, sizeof (struct mslm_NetShareAdd)); 1289 param->status = ERROR_ACCESS_DENIED; 1290 return (NDR_DRC_OK); 1291 } 1292 1293 switch (param->level) { 1294 case 2: 1295 info2 = param->info.un.info2; 1296 break; 1297 1298 case 502: 1299 info2 = (struct mslm_SHARE_INFO_2 *)param->info.un.info502; 1300 break; 1301 1302 default: 1303 bzero(param, sizeof (struct mslm_NetShareAdd)); 1304 param->status = ERROR_ACCESS_DENIED; 1305 return (NDR_DRC_OK); 1306 } 1307 1308 if (info2->shi2_netname == NULL || info2->shi2_path == NULL) { 1309 bzero(param, sizeof (struct mslm_NetShareAdd)); 1310 param->status = NERR_NetNameNotFound; 1311 return (NDR_DRC_OK); 1312 } 1313 1314 if (smb_shr_is_restricted((char *)info2->shi2_netname)) { 1315 bzero(param, sizeof (struct mslm_NetShareAdd)); 1316 param->status = ERROR_ACCESS_DENIED; 1317 return (NDR_DRC_OK); 1318 } 1319 1320 if (info2->shi2_remark == NULL) 1321 info2->shi2_remark = (uint8_t *)""; 1322 1323 /* 1324 * Derive the real path which will be stored in the 1325 * directory field of the smb_share_t structure 1326 * from the path field in this RPC request. 1327 */ 1328 parm_stat = smb_shr_get_realpath((const char *)info2->shi2_path, 1329 realpath, MAXPATHLEN); 1330 1331 if (parm_stat != NERR_Success) { 1332 bzero(param, sizeof (struct mslm_NetShareAdd)); 1333 param->status = parm_stat; 1334 param->parm_err 1335 = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err; 1336 return (NDR_DRC_OK); 1337 } 1338 1339 param->status = srvsvc_sa_add((char *)info2->shi2_netname, realpath, 1340 (char *)info2->shi2_remark); 1341 if (param->status == NERR_Success) { 1342 smb_share_t si; 1343 /* 1344 * Lookup the share, which will bring it into the cache. 1345 */ 1346 (void) smb_shr_get((char *)info2->shi2_netname, &si); 1347 } 1348 param->parm_err = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err; 1349 return (NDR_DRC_OK); 1350 } 1351 1352 /* 1353 * srvsvc_estimate_objcnt 1354 * 1355 * Estimate the number of objects that will fit in prefmaxlen. 1356 */ 1357 static uint32_t 1358 srvsvc_estimate_objcnt(uint32_t prefmaxlen, uint32_t n_obj, uint32_t obj_size) 1359 { 1360 DWORD max_cnt; 1361 1362 if (obj_size == 0) 1363 return (0); 1364 1365 if ((max_cnt = (prefmaxlen / obj_size)) == 0) 1366 return (0); 1367 1368 if (n_obj > max_cnt) 1369 n_obj = max_cnt; 1370 1371 return (n_obj); 1372 } 1373 1374 /* 1375 * srvsvc_s_NetShareEnum 1376 * 1377 * Enumerate all shares (see also NetShareEnumSticky). 1378 * 1379 * Request for various levels of information about our shares. 1380 * Level 0: share names. 1381 * Level 1: share name, share type and comment field. 1382 * Level 2: everything that we know about the shares. 1383 * Level 501: level 1 + flags (flags must be zero). 1384 * Level 502: level 2 + security descriptor. 1385 */ 1386 static int 1387 srvsvc_s_NetShareEnum(void *arg, ndr_xa_t *mxa) 1388 { 1389 struct mslm_NetShareEnum *param = arg; 1390 struct mslm_infonres *infonres; 1391 srvsvc_enum_t se; 1392 DWORD status; 1393 1394 infonres = NDR_NEW(mxa, struct mslm_infonres); 1395 if (infonres == NULL) { 1396 bzero(param, sizeof (struct mslm_NetShareEnum)); 1397 param->status = ERROR_NOT_ENOUGH_MEMORY; 1398 return (NDR_DRC_OK); 1399 } 1400 1401 infonres->entriesread = 0; 1402 infonres->entries = NULL; 1403 param->result.level = param->level; 1404 param->result.bufptr.p = infonres; 1405 1406 bzero(&se, sizeof (srvsvc_enum_t)); 1407 se.se_level = param->level; 1408 se.se_n_total = smb_shr_count(); 1409 1410 if (param->prefmaxlen == SMB_SRVSVC_MAXPREFLEN || 1411 param->prefmaxlen > SMB_SRVSVC_MAXBUFLEN) 1412 se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN; 1413 else 1414 se.se_prefmaxlen = param->prefmaxlen; 1415 1416 if (param->resume_handle) { 1417 se.se_resume_handle = *param->resume_handle; 1418 se.se_n_skip = se.se_resume_handle; 1419 } 1420 1421 switch (param->level) { 1422 case 0: 1423 status = mlsvc_NetShareEnumLevel0(mxa, infonres, &se, 0); 1424 break; 1425 1426 case 1: 1427 status = mlsvc_NetShareEnumLevel1(mxa, infonres, &se, 0); 1428 break; 1429 1430 case 2: 1431 status = mlsvc_NetShareEnumLevel2(mxa, infonres, &se, 0); 1432 break; 1433 1434 case 501: 1435 status = mlsvc_NetShareEnumLevel501(mxa, infonres, &se, 0); 1436 break; 1437 1438 case 502: 1439 status = mlsvc_NetShareEnumLevel502(mxa, infonres, &se, 0); 1440 break; 1441 1442 default: 1443 status = ERROR_INVALID_PARAMETER; 1444 break; 1445 } 1446 1447 if (status != 0) { 1448 bzero(param, sizeof (struct mslm_NetShareEnum)); 1449 param->status = status; 1450 return (NDR_DRC_OK); 1451 } 1452 1453 if (se.se_n_enum == 0) { 1454 if (param->resume_handle) 1455 *param->resume_handle = 0; 1456 param->status = ERROR_SUCCESS; 1457 return (NDR_DRC_OK); 1458 } 1459 1460 if (param->resume_handle && 1461 param->prefmaxlen != SMB_SRVSVC_MAXPREFLEN) { 1462 if (se.se_resume_handle < se.se_n_total) { 1463 *param->resume_handle = se.se_resume_handle; 1464 status = ERROR_MORE_DATA; 1465 } else { 1466 *param->resume_handle = 0; 1467 } 1468 } 1469 1470 param->totalentries = se.se_n_total; 1471 param->status = status; 1472 return (NDR_DRC_OK); 1473 } 1474 1475 /* 1476 * srvsvc_s_NetShareEnumSticky 1477 * 1478 * Enumerate sticky shares: all shares except those marked STYPE_SPECIAL. 1479 * Except for excluding STYPE_SPECIAL shares, NetShareEnumSticky is the 1480 * same as NetShareEnum. 1481 * 1482 * Request for various levels of information about our shares. 1483 * Level 0: share names. 1484 * Level 1: share name, share type and comment field. 1485 * Level 2: everything that we know about the shares. 1486 * Level 501: not valid for this request. 1487 * Level 502: level 2 + security descriptor. 1488 * 1489 * We set n_skip to resume_handle, which is used to find the appropriate 1490 * place to resume. The resume_handle is similar to the readdir cookie. 1491 */ 1492 static int 1493 srvsvc_s_NetShareEnumSticky(void *arg, ndr_xa_t *mxa) 1494 { 1495 struct mslm_NetShareEnum *param = arg; 1496 struct mslm_infonres *infonres; 1497 srvsvc_enum_t se; 1498 DWORD status; 1499 1500 infonres = NDR_NEW(mxa, struct mslm_infonres); 1501 if (infonres == NULL) { 1502 bzero(param, sizeof (struct mslm_NetShareEnum)); 1503 param->status = ERROR_NOT_ENOUGH_MEMORY; 1504 return (NDR_DRC_OK); 1505 } 1506 1507 infonres->entriesread = 0; 1508 infonres->entries = NULL; 1509 param->result.level = param->level; 1510 param->result.bufptr.p = infonres; 1511 1512 bzero(&se, sizeof (srvsvc_enum_t)); 1513 se.se_level = param->level; 1514 se.se_n_total = smb_shr_count(); 1515 1516 if (param->prefmaxlen == SMB_SRVSVC_MAXPREFLEN || 1517 param->prefmaxlen > SMB_SRVSVC_MAXBUFLEN) 1518 se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN; 1519 else 1520 se.se_prefmaxlen = param->prefmaxlen; 1521 1522 if (param->resume_handle) { 1523 se.se_resume_handle = *param->resume_handle; 1524 se.se_n_skip = se.se_resume_handle; 1525 } 1526 1527 switch (param->level) { 1528 case 0: 1529 status = mlsvc_NetShareEnumLevel0(mxa, infonres, &se, 1); 1530 break; 1531 1532 case 1: 1533 status = mlsvc_NetShareEnumLevel1(mxa, infonres, &se, 1); 1534 break; 1535 1536 case 2: 1537 status = mlsvc_NetShareEnumLevel2(mxa, infonres, &se, 1); 1538 break; 1539 1540 case 502: 1541 status = mlsvc_NetShareEnumLevel502(mxa, infonres, &se, 1); 1542 break; 1543 1544 default: 1545 status = ERROR_INVALID_LEVEL; 1546 break; 1547 } 1548 1549 if (status != ERROR_SUCCESS) { 1550 bzero(param, sizeof (struct mslm_NetShareEnum)); 1551 param->status = status; 1552 return (NDR_DRC_OK); 1553 } 1554 1555 if (se.se_n_enum == 0) { 1556 if (param->resume_handle) 1557 *param->resume_handle = 0; 1558 param->status = ERROR_SUCCESS; 1559 return (NDR_DRC_OK); 1560 } 1561 1562 if (param->resume_handle && 1563 param->prefmaxlen != SMB_SRVSVC_MAXPREFLEN) { 1564 if (se.se_resume_handle < se.se_n_total) { 1565 *param->resume_handle = se.se_resume_handle; 1566 status = ERROR_MORE_DATA; 1567 } else { 1568 *param->resume_handle = 0; 1569 } 1570 } 1571 1572 param->totalentries = se.se_n_total; 1573 param->status = status; 1574 return (NDR_DRC_OK); 1575 } 1576 1577 /* 1578 * NetShareEnum Level 0 1579 */ 1580 static DWORD 1581 mlsvc_NetShareEnumLevel0(ndr_xa_t *mxa, 1582 struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky) 1583 { 1584 struct mslm_SHARE_INFO_0 *info0; 1585 smb_shriter_t iterator; 1586 smb_share_t *si; 1587 DWORD status; 1588 1589 se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen, 1590 se->se_n_total, sizeof (struct mslm_SHARE_INFO_0) + MAXNAMELEN); 1591 if (se->se_n_enum == 0) 1592 return (ERROR_SUCCESS); 1593 1594 info0 = NDR_NEWN(mxa, struct mslm_SHARE_INFO_0, se->se_n_enum); 1595 if (info0 == NULL) 1596 return (ERROR_NOT_ENOUGH_MEMORY); 1597 1598 smb_shr_iterinit(&iterator); 1599 1600 se->se_n_read = 0; 1601 while ((si = smb_shr_iterate(&iterator)) != NULL) { 1602 if (se->se_n_skip > 0) { 1603 --se->se_n_skip; 1604 continue; 1605 } 1606 1607 ++se->se_resume_handle; 1608 1609 if (sticky && (si->shr_flags & SMB_SHRF_TRANS)) 1610 continue; 1611 1612 if (si->shr_flags & SMB_SHRF_AUTOHOME) 1613 continue; 1614 1615 if (se->se_n_read >= se->se_n_enum) { 1616 se->se_n_read = se->se_n_enum; 1617 break; 1618 } 1619 1620 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info0); 1621 if (status != ERROR_SUCCESS) 1622 break; 1623 1624 ++se->se_n_read; 1625 } 1626 1627 if (se->se_n_read < se->se_n_enum) { 1628 if (srvsvc_add_autohome(mxa, se, (void *)info0)) 1629 ++se->se_n_read; 1630 } 1631 1632 infonres->entriesread = se->se_n_read; 1633 infonres->entries = info0; 1634 return (ERROR_SUCCESS); 1635 } 1636 1637 /* 1638 * NetShareEnum Level 1 1639 */ 1640 static DWORD 1641 mlsvc_NetShareEnumLevel1(ndr_xa_t *mxa, 1642 struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky) 1643 { 1644 struct mslm_SHARE_INFO_1 *info1; 1645 smb_shriter_t iterator; 1646 smb_share_t *si; 1647 DWORD status; 1648 1649 se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen, 1650 se->se_n_total, sizeof (struct mslm_SHARE_INFO_1) + MAXNAMELEN); 1651 if (se->se_n_enum == 0) 1652 return (ERROR_SUCCESS); 1653 1654 info1 = NDR_NEWN(mxa, struct mslm_SHARE_INFO_1, se->se_n_enum); 1655 if (info1 == NULL) 1656 return (ERROR_NOT_ENOUGH_MEMORY); 1657 1658 smb_shr_iterinit(&iterator); 1659 1660 se->se_n_read = 0; 1661 while ((si = smb_shr_iterate(&iterator)) != 0) { 1662 if (se->se_n_skip > 0) { 1663 --se->se_n_skip; 1664 continue; 1665 } 1666 1667 ++se->se_resume_handle; 1668 1669 if (sticky && (si->shr_flags & SMB_SHRF_TRANS)) 1670 continue; 1671 1672 if (si->shr_flags & SMB_SHRF_AUTOHOME) 1673 continue; 1674 1675 if (se->se_n_read >= se->se_n_enum) { 1676 se->se_n_read = se->se_n_enum; 1677 break; 1678 } 1679 1680 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info1); 1681 if (status != ERROR_SUCCESS) 1682 break; 1683 1684 ++se->se_n_read; 1685 } 1686 1687 if (se->se_n_read < se->se_n_enum) { 1688 if (srvsvc_add_autohome(mxa, se, (void *)info1)) 1689 ++se->se_n_read; 1690 } 1691 1692 infonres->entriesread = se->se_n_read; 1693 infonres->entries = info1; 1694 return (ERROR_SUCCESS); 1695 } 1696 1697 /* 1698 * NetShareEnum Level 2 1699 */ 1700 static DWORD 1701 mlsvc_NetShareEnumLevel2(ndr_xa_t *mxa, 1702 struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky) 1703 { 1704 struct mslm_SHARE_INFO_2 *info2; 1705 smb_shriter_t iterator; 1706 smb_share_t *si; 1707 DWORD status; 1708 1709 se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen, 1710 se->se_n_total, sizeof (struct mslm_SHARE_INFO_2) + MAXNAMELEN); 1711 if (se->se_n_enum == 0) 1712 return (ERROR_SUCCESS); 1713 1714 info2 = NDR_NEWN(mxa, struct mslm_SHARE_INFO_2, se->se_n_enum); 1715 if (info2 == NULL) 1716 return (ERROR_NOT_ENOUGH_MEMORY); 1717 1718 smb_shr_iterinit(&iterator); 1719 1720 se->se_n_read = 0; 1721 while ((si = smb_shr_iterate(&iterator)) != 0) { 1722 if (se->se_n_skip > 0) { 1723 --se->se_n_skip; 1724 continue; 1725 } 1726 1727 ++se->se_resume_handle; 1728 1729 if (sticky && (si->shr_flags & SMB_SHRF_TRANS)) 1730 continue; 1731 1732 if (si->shr_flags & SMB_SHRF_AUTOHOME) 1733 continue; 1734 1735 if (se->se_n_read >= se->se_n_enum) { 1736 se->se_n_read = se->se_n_enum; 1737 break; 1738 } 1739 1740 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info2); 1741 if (status != ERROR_SUCCESS) 1742 break; 1743 1744 ++se->se_n_read; 1745 } 1746 1747 if (se->se_n_read < se->se_n_enum) { 1748 if (srvsvc_add_autohome(mxa, se, (void *)info2)) 1749 ++se->se_n_read; 1750 } 1751 1752 infonres->entriesread = se->se_n_read; 1753 infonres->entries = info2; 1754 return (ERROR_SUCCESS); 1755 } 1756 1757 /* 1758 * NetShareEnum Level 501 1759 */ 1760 static DWORD 1761 mlsvc_NetShareEnumLevel501(ndr_xa_t *mxa, 1762 struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky) 1763 { 1764 struct mslm_SHARE_INFO_501 *info501; 1765 smb_shriter_t iterator; 1766 smb_share_t *si; 1767 DWORD status; 1768 1769 se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen, 1770 se->se_n_total, sizeof (struct mslm_SHARE_INFO_501) + MAXNAMELEN); 1771 if (se->se_n_enum == 0) 1772 return (ERROR_SUCCESS); 1773 1774 info501 = NDR_NEWN(mxa, struct mslm_SHARE_INFO_501, 1775 se->se_n_enum); 1776 if (info501 == NULL) 1777 return (ERROR_NOT_ENOUGH_MEMORY); 1778 1779 smb_shr_iterinit(&iterator); 1780 1781 se->se_n_read = 0; 1782 while ((si = smb_shr_iterate(&iterator)) != 0) { 1783 if (se->se_n_skip > 0) { 1784 --se->se_n_skip; 1785 continue; 1786 } 1787 1788 ++se->se_resume_handle; 1789 1790 if (sticky && (si->shr_flags & SMB_SHRF_TRANS)) 1791 continue; 1792 1793 if (si->shr_flags & SMB_SHRF_AUTOHOME) 1794 continue; 1795 1796 if (se->se_n_read >= se->se_n_enum) { 1797 se->se_n_read = se->se_n_enum; 1798 break; 1799 } 1800 1801 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info501); 1802 if (status != ERROR_SUCCESS) 1803 break; 1804 1805 ++se->se_n_read; 1806 } 1807 1808 if (se->se_n_read < se->se_n_enum) { 1809 if (srvsvc_add_autohome(mxa, se, (void *)info501)) 1810 ++se->se_n_read; 1811 } 1812 1813 infonres->entriesread = se->se_n_read; 1814 infonres->entries = info501; 1815 return (ERROR_SUCCESS); 1816 } 1817 1818 /* 1819 * NetShareEnum Level 502 1820 */ 1821 static DWORD 1822 mlsvc_NetShareEnumLevel502(ndr_xa_t *mxa, 1823 struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky) 1824 { 1825 struct mslm_SHARE_INFO_502 *info502; 1826 smb_shriter_t iterator; 1827 smb_share_t *si; 1828 DWORD status; 1829 1830 se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen, 1831 se->se_n_total, sizeof (struct mslm_SHARE_INFO_502) + MAXNAMELEN); 1832 if (se->se_n_enum == 0) 1833 return (ERROR_SUCCESS); 1834 1835 info502 = NDR_NEWN(mxa, struct mslm_SHARE_INFO_502, 1836 se->se_n_enum); 1837 if (info502 == NULL) 1838 return (ERROR_NOT_ENOUGH_MEMORY); 1839 1840 smb_shr_iterinit(&iterator); 1841 1842 se->se_n_read = 0; 1843 while ((si = smb_shr_iterate(&iterator)) != NULL) { 1844 if (se->se_n_skip > 0) { 1845 --se->se_n_skip; 1846 continue; 1847 } 1848 1849 ++se->se_resume_handle; 1850 1851 if (sticky && (si->shr_flags & SMB_SHRF_TRANS)) 1852 continue; 1853 1854 if (si->shr_flags & SMB_SHRF_AUTOHOME) 1855 continue; 1856 1857 if (se->se_n_read >= se->se_n_enum) { 1858 se->se_n_read = se->se_n_enum; 1859 break; 1860 } 1861 1862 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info502); 1863 if (status != ERROR_SUCCESS) 1864 break; 1865 1866 ++se->se_n_read; 1867 } 1868 1869 if (se->se_n_read < se->se_n_enum) { 1870 if (srvsvc_add_autohome(mxa, se, (void *)info502)) 1871 ++se->se_n_read; 1872 } 1873 1874 infonres->entriesread = se->se_n_read; 1875 infonres->entries = info502; 1876 return (ERROR_SUCCESS); 1877 } 1878 1879 /* 1880 * mlsvc_NetShareEnumCommon 1881 * 1882 * Build the levels 0, 1, 2, 501 and 502 share information. This function 1883 * is called by the various NetShareEnum levels for each share. If 1884 * we cannot build the share data for some reason, we return an error 1885 * but the actual value of the error is not important to the caller. 1886 * The caller just needs to know not to include this info in the RPC 1887 * response. 1888 * 1889 * Returns: 1890 * ERROR_SUCCESS 1891 * ERROR_NOT_ENOUGH_MEMORY 1892 * ERROR_INVALID_LEVEL 1893 */ 1894 static DWORD 1895 mlsvc_NetShareEnumCommon(ndr_xa_t *mxa, srvsvc_enum_t *se, 1896 smb_share_t *si, void *infop) 1897 { 1898 struct mslm_SHARE_INFO_0 *info0; 1899 struct mslm_SHARE_INFO_1 *info1; 1900 struct mslm_SHARE_INFO_2 *info2; 1901 struct mslm_SHARE_INFO_501 *info501; 1902 struct mslm_SHARE_INFO_502 *info502; 1903 int i = se->se_n_read; 1904 1905 switch (se->se_level) { 1906 case 0: 1907 info0 = (struct mslm_SHARE_INFO_0 *)infop; 1908 info0[i].shi0_netname 1909 = (uint8_t *)NDR_STRDUP(mxa, si->shr_name); 1910 1911 if (info0[i].shi0_netname == NULL) 1912 return (ERROR_NOT_ENOUGH_MEMORY); 1913 break; 1914 1915 case 1: 1916 info1 = (struct mslm_SHARE_INFO_1 *)infop; 1917 info1[i].shi1_netname 1918 = (uint8_t *)NDR_STRDUP(mxa, si->shr_name); 1919 info1[i].shi1_remark 1920 = (uint8_t *)NDR_STRDUP(mxa, si->shr_cmnt); 1921 1922 info1[i].shi1_type = si->shr_type; 1923 1924 if (!info1[i].shi1_netname || !info1[i].shi1_remark) 1925 return (ERROR_NOT_ENOUGH_MEMORY); 1926 break; 1927 1928 case 2: 1929 info2 = (struct mslm_SHARE_INFO_2 *)infop; 1930 info2[i].shi2_netname 1931 = (uint8_t *)NDR_STRDUP(mxa, si->shr_name); 1932 info2[i].shi2_remark 1933 = (uint8_t *)NDR_STRDUP(mxa, si->shr_cmnt); 1934 1935 info2[i].shi2_path 1936 = (uint8_t *)srvsvc_share_mkpath(mxa, si->shr_path); 1937 1938 info2[i].shi2_type = si->shr_type; 1939 info2[i].shi2_permissions = 0; 1940 info2[i].shi2_max_uses = SHI_USES_UNLIMITED; 1941 info2[i].shi2_current_uses = 0; 1942 info2[i].shi2_passwd 1943 = (uint8_t *)NDR_STRDUP(mxa, empty_string); 1944 1945 if (!info2[i].shi2_netname || !info2[i].shi2_remark || 1946 !info2[i].shi2_passwd || !info2[i].shi2_path) 1947 return (ERROR_NOT_ENOUGH_MEMORY); 1948 1949 break; 1950 1951 case 501: 1952 info501 = (struct mslm_SHARE_INFO_501 *)infop; 1953 info501[i].shi501_netname 1954 = (uint8_t *)NDR_STRDUP(mxa, si->shr_name); 1955 info501[i].shi501_remark 1956 = (uint8_t *)NDR_STRDUP(mxa, si->shr_cmnt); 1957 1958 info501[i].shi501_type = si->shr_type; 1959 info501[i].shi501_flags = 0; 1960 1961 if (!info501[i].shi501_netname || !info501[i].shi501_remark) 1962 return (ERROR_NOT_ENOUGH_MEMORY); 1963 break; 1964 1965 case 502: 1966 info502 = (struct mslm_SHARE_INFO_502 *)infop; 1967 info502[i].shi502_netname 1968 = (uint8_t *)NDR_STRDUP(mxa, si->shr_name); 1969 info502[i].shi502_remark 1970 = (uint8_t *)NDR_STRDUP(mxa, si->shr_cmnt); 1971 1972 info502[i].shi502_path 1973 = (uint8_t *)srvsvc_share_mkpath(mxa, si->shr_path); 1974 1975 info502[i].shi502_type = si->shr_type; 1976 info502[i].shi502_permissions = 0; 1977 info502[i].shi502_max_uses = SHI_USES_UNLIMITED; 1978 info502[i].shi502_current_uses = 0; 1979 info502[i].shi502_passwd 1980 = (uint8_t *)NDR_STRDUP(mxa, empty_string); 1981 1982 info502[i].shi502_reserved = 0; 1983 info502[i].shi502_security_descriptor = 0; 1984 1985 if (!info502[i].shi502_netname || !info502[i].shi502_remark || 1986 !info502[i].shi502_passwd || !info502[i].shi502_path) 1987 return (ERROR_NOT_ENOUGH_MEMORY); 1988 break; 1989 1990 default: 1991 return (ERROR_INVALID_LEVEL); 1992 } 1993 1994 return (ERROR_SUCCESS); 1995 } 1996 1997 /* 1998 * srvsvc_add_autohome 1999 * 2000 * Add the autohome share for the user. The share must not be a permanent 2001 * share to avoid duplicates. 2002 */ 2003 static boolean_t 2004 srvsvc_add_autohome(ndr_xa_t *mxa, srvsvc_enum_t *se, void *infop) 2005 { 2006 smb_opipe_context_t *ctx = &mxa->pipe->np_ctx; 2007 char *username = ctx->oc_account; 2008 smb_share_t si; 2009 DWORD status; 2010 2011 if (smb_shr_get(username, &si) != NERR_Success) 2012 return (B_FALSE); 2013 2014 if ((si.shr_flags & SMB_SHRF_AUTOHOME) == 0) 2015 return (B_FALSE); 2016 2017 status = mlsvc_NetShareEnumCommon(mxa, se, &si, infop); 2018 return (status == ERROR_SUCCESS); 2019 } 2020 2021 /* 2022 * srvsvc_share_mkpath 2023 * 2024 * Create the share path required by the share enum calls. The path 2025 * is created in a heap buffer ready for use by the caller. 2026 * 2027 * Some Windows over-the-wire backup applications do not work unless a 2028 * drive letter is present in the share path. We don't care about the 2029 * drive letter since the path is fully qualified with the volume name. 2030 * 2031 * Windows clients seem to be mostly okay with forward slashes in 2032 * share paths but they cannot handle one immediately after the drive 2033 * letter, i.e. B:/. For consistency we convert all the slashes in 2034 * the path. 2035 * 2036 * Returns a pointer to a heap buffer containing the share path, which 2037 * could be a null pointer if the heap allocation fails. 2038 */ 2039 static char * 2040 srvsvc_share_mkpath(ndr_xa_t *mxa, char *path) 2041 { 2042 char tmpbuf[MAXPATHLEN]; 2043 char *p; 2044 2045 if (strlen(path) == 0) 2046 return (NDR_STRDUP(mxa, path)); 2047 2048 /* 2049 * Strip the volume name from the path (/vol1/home -> /home). 2050 */ 2051 p = path; 2052 p += strspn(p, "/"); 2053 p += strcspn(p, "/"); 2054 p += strspn(p, "/"); 2055 (void) snprintf(tmpbuf, MAXPATHLEN, "%c:/%s", 'B', p); 2056 (void) strsubst(tmpbuf, '/', '\\'); 2057 2058 return (NDR_STRDUP(mxa, tmpbuf)); 2059 } 2060 2061 /* 2062 * srvsvc_s_NetShareDel 2063 * 2064 * Delete a share. Only the administrator, or a member of the domain 2065 * administrators group, is allowed to delete shares. 2066 * 2067 * This interface is used by the rmtshare command from the NT resource 2068 * kit. Rmtshare allows a client to add or remove shares on a server 2069 * from the client's command line. 2070 * 2071 * Returns Win32 error codes. 2072 */ 2073 static int 2074 srvsvc_s_NetShareDel(void *arg, ndr_xa_t *mxa) 2075 { 2076 struct mslm_NetShareDel *param = arg; 2077 2078 if (!ndr_is_poweruser(mxa) || 2079 smb_shr_is_restricted((char *)param->netname)) { 2080 param->status = ERROR_ACCESS_DENIED; 2081 return (NDR_DRC_OK); 2082 } 2083 2084 param->status = srvsvc_sa_delete((char *)param->netname); 2085 return (NDR_DRC_OK); 2086 } 2087 2088 /* 2089 * srvsvc_s_NetGetFileSecurity 2090 * 2091 * Get security descriptor of the requested file/folder 2092 * 2093 * Right now, just returns ERROR_ACCESS_DENIED, because we cannot 2094 * get the requested SD here in RPC code. 2095 */ 2096 /*ARGSUSED*/ 2097 static int 2098 srvsvc_s_NetGetFileSecurity(void *arg, ndr_xa_t *mxa) 2099 { 2100 struct mslm_NetGetFileSecurity *param = arg; 2101 2102 param->length = 0; 2103 param->status = ERROR_ACCESS_DENIED; 2104 return (NDR_DRC_OK); 2105 } 2106 2107 /* 2108 * srvsvc_s_NetSetFileSecurity 2109 * 2110 * Set the given security descriptor for the requested file/folder 2111 * 2112 * Right now, just returns ERROR_ACCESS_DENIED, because we cannot 2113 * set the requested SD here in RPC code. 2114 */ 2115 /*ARGSUSED*/ 2116 static int 2117 srvsvc_s_NetSetFileSecurity(void *arg, ndr_xa_t *mxa) 2118 { 2119 struct mslm_NetSetFileSecurity *param = arg; 2120 2121 param->status = ERROR_ACCESS_DENIED; 2122 return (NDR_DRC_OK); 2123 } 2124 2125 /* 2126 * If the default "smb" share group exists then return the group 2127 * handle, otherwise create the group and return the handle. 2128 * 2129 * All shares created via the srvsvc will be added to the "smb" 2130 * group. 2131 */ 2132 static sa_group_t 2133 srvsvc_sa_get_smbgrp(sa_handle_t handle) 2134 { 2135 sa_group_t group = NULL; 2136 int err; 2137 2138 group = sa_get_group(handle, SMB_DEFAULT_SHARE_GROUP); 2139 if (group != NULL) 2140 return (group); 2141 2142 group = sa_create_group(handle, SMB_DEFAULT_SHARE_GROUP, &err); 2143 if (group == NULL) 2144 return (NULL); 2145 2146 if (sa_create_optionset(group, SMB_DEFAULT_SHARE_GROUP) == NULL) { 2147 (void) sa_remove_group(group); 2148 group = NULL; 2149 } 2150 2151 return (group); 2152 } 2153 2154 /* 2155 * Stores the given share in sharemgr 2156 */ 2157 static uint32_t 2158 srvsvc_sa_add(char *sharename, char *path, char *cmnt) 2159 { 2160 sa_handle_t handle; 2161 sa_share_t share; 2162 sa_group_t group; 2163 sa_resource_t resource; 2164 boolean_t new_share = B_FALSE; 2165 uint32_t status = NERR_Success; 2166 int err; 2167 2168 if ((handle = smb_shr_sa_enter()) == NULL) 2169 return (NERR_InternalError); 2170 2171 share = sa_find_share(handle, path); 2172 if (share == NULL) { 2173 group = srvsvc_sa_get_smbgrp(handle); 2174 if (group == NULL) { 2175 smb_shr_sa_exit(); 2176 return (NERR_InternalError); 2177 } 2178 2179 share = sa_add_share(group, path, SA_SHARE_PERMANENT, &err); 2180 if (share == NULL) { 2181 smb_shr_sa_exit(); 2182 return (NERR_InternalError); 2183 } 2184 new_share = B_TRUE; 2185 } 2186 2187 resource = sa_get_share_resource(share, sharename); 2188 if (resource == NULL) { 2189 resource = sa_add_resource(share, sharename, 2190 SA_SHARE_PERMANENT, &err); 2191 if (resource == NULL) { 2192 if (new_share) 2193 (void) sa_remove_share(share); 2194 smb_shr_sa_exit(); 2195 return (NERR_InternalError); 2196 } 2197 } 2198 2199 (void) sa_set_resource_description(resource, cmnt); 2200 2201 smb_shr_sa_exit(); 2202 return (status); 2203 } 2204 2205 /* 2206 * Removes the share from sharemgr 2207 */ 2208 static uint32_t 2209 srvsvc_sa_delete(char *sharename) 2210 { 2211 sa_handle_t handle; 2212 sa_resource_t resource; 2213 uint32_t status; 2214 2215 if ((handle = smb_shr_sa_enter()) == NULL) 2216 return (NERR_InternalError); 2217 2218 status = NERR_InternalError; 2219 if ((resource = sa_find_resource(handle, sharename)) != NULL) { 2220 if (sa_remove_resource(resource) == SA_OK) 2221 status = NERR_Success; 2222 } 2223 2224 smb_shr_sa_exit(); 2225 return (status); 2226 } 2227 2228 static ndr_stub_table_t srvsvc_stub_table[] = { 2229 { srvsvc_s_NetConnectEnum, SRVSVC_OPNUM_NetConnectEnum }, 2230 { srvsvc_s_NetFileEnum, SRVSVC_OPNUM_NetFileEnum }, 2231 { srvsvc_s_NetFileClose, SRVSVC_OPNUM_NetFileClose }, 2232 { srvsvc_s_NetShareGetInfo, SRVSVC_OPNUM_NetShareGetInfo }, 2233 { srvsvc_s_NetShareSetInfo, SRVSVC_OPNUM_NetShareSetInfo }, 2234 { srvsvc_s_NetSessionEnum, SRVSVC_OPNUM_NetSessionEnum }, 2235 { srvsvc_s_NetSessionDel, SRVSVC_OPNUM_NetSessionDel }, 2236 { srvsvc_s_NetServerGetInfo, SRVSVC_OPNUM_NetServerGetInfo }, 2237 { srvsvc_s_NetRemoteTOD, SRVSVC_OPNUM_NetRemoteTOD }, 2238 { srvsvc_s_NetNameValidate, SRVSVC_OPNUM_NetNameValidate }, 2239 { srvsvc_s_NetShareAdd, SRVSVC_OPNUM_NetShareAdd }, 2240 { srvsvc_s_NetShareDel, SRVSVC_OPNUM_NetShareDel }, 2241 { srvsvc_s_NetShareEnum, SRVSVC_OPNUM_NetShareEnum }, 2242 { srvsvc_s_NetShareEnumSticky, SRVSVC_OPNUM_NetShareEnumSticky }, 2243 { srvsvc_s_NetGetFileSecurity, SRVSVC_OPNUM_NetGetFileSecurity }, 2244 { srvsvc_s_NetSetFileSecurity, SRVSVC_OPNUM_NetSetFileSecurity }, 2245 {0} 2246 }; 2247