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