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 #include <smbsrv/libsmb.h> 49 #include <smbsrv/libmlsvc.h> 50 #include <smbsrv/lmerr.h> 51 #include <smbsrv/nterror.h> 52 #include <smbsrv/nmpipes.h> 53 #include <smbsrv/cifs.h> 54 #include <smbsrv/netrauth.h> 55 #include <smbsrv/ndl/srvsvc.ndl> 56 #include <smbsrv/smb_common_door.h> 57 #include "mlsvc.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 typedef struct srvsvc_sd { 90 uint8_t *sd_buf; 91 uint32_t sd_size; 92 } srvsvc_sd_t; 93 94 typedef struct srvsvc_netshare_setinfo { 95 char *nss_netname; 96 char *nss_comment; 97 char *nss_path; 98 uint32_t nss_type; 99 srvsvc_sd_t nss_sd; 100 } srvsvc_netshare_setinfo_t; 101 102 typedef union srvsvc_netshare_getinfo { 103 struct mslm_NetShareInfo_0 nsg_info0; 104 struct mslm_NetShareInfo_1 nsg_info1; 105 struct mslm_NetShareInfo_2 nsg_info2; 106 struct mslm_NetShareInfo_501 nsg_info501; 107 struct mslm_NetShareInfo_502 nsg_info502; 108 struct mslm_NetShareInfo_503 nsg_info503; 109 struct mslm_NetShareInfo_1004 nsg_info1004; 110 struct mslm_NetShareInfo_1005 nsg_info1005; 111 struct mslm_NetShareInfo_1006 nsg_info1006; 112 struct mslm_NetShareInfo_1501 nsg_info1501; 113 } srvsvc_netshare_getinfo_t; 114 115 static DWORD srvsvc_s_NetConnectEnumLevel0(ndr_xa_t *, 116 srvsvc_NetConnectInfo0_t *); 117 static DWORD srvsvc_s_NetConnectEnumLevel1(ndr_xa_t *, 118 srvsvc_NetConnectInfo1_t *); 119 120 static DWORD srvsvc_NetFileEnum2(ndr_xa_t *, 121 struct mslm_NetFileEnum *); 122 static DWORD srvsvc_NetFileEnum3(ndr_xa_t *, 123 struct mslm_NetFileEnum *); 124 125 static DWORD mlsvc_NetSessionEnumLevel0(struct mslm_infonres *, DWORD, 126 ndr_xa_t *); 127 static DWORD mlsvc_NetSessionEnumLevel1(struct mslm_infonres *, DWORD, 128 ndr_xa_t *); 129 static DWORD mlsvc_NetSessionEnumLevel2(struct mslm_infonres *, DWORD, 130 ndr_xa_t *); 131 static DWORD mlsvc_NetSessionEnumLevel10(struct mslm_infonres *, DWORD, 132 ndr_xa_t *); 133 static DWORD mlsvc_NetSessionEnumLevel502(struct mslm_infonres *, DWORD, 134 ndr_xa_t *); 135 136 static DWORD mlsvc_NetShareEnumLevel0(ndr_xa_t *, 137 struct mslm_infonres *, srvsvc_enum_t *, int); 138 static DWORD mlsvc_NetShareEnumLevel1(ndr_xa_t *, 139 struct mslm_infonres *, srvsvc_enum_t *, int); 140 static DWORD mlsvc_NetShareEnumLevel2(ndr_xa_t *, 141 struct mslm_infonres *, srvsvc_enum_t *, int); 142 static DWORD mlsvc_NetShareEnumLevel501(ndr_xa_t *, 143 struct mslm_infonres *, srvsvc_enum_t *, int); 144 static DWORD mlsvc_NetShareEnumLevel502(ndr_xa_t *, 145 struct mslm_infonres *, srvsvc_enum_t *, int); 146 static DWORD mlsvc_NetShareEnumCommon(ndr_xa_t *, 147 srvsvc_enum_t *, smb_share_t *, void *); 148 static boolean_t srvsvc_add_autohome(ndr_xa_t *, srvsvc_enum_t *, 149 void *); 150 static char *srvsvc_share_mkpath(ndr_xa_t *, char *); 151 static uint32_t srvsvc_share_getsd(ndr_xa_t *, smb_share_t *, srvsvc_sd_t *); 152 153 static int srvsvc_netconnect_qualifier(const char *); 154 static uint32_t srvsvc_estimate_objcnt(uint32_t, uint32_t, uint32_t); 155 156 static uint32_t srvsvc_modify_share(smb_share_t *, 157 srvsvc_netshare_setinfo_t *); 158 static uint32_t srvsvc_modify_transient_share(smb_share_t *, 159 srvsvc_netshare_setinfo_t *); 160 static uint32_t srvsvc_update_share_flags(smb_share_t *, uint32_t); 161 162 static uint32_t srvsvc_sa_add(char *, char *, char *); 163 static uint32_t srvsvc_sa_delete(char *); 164 static uint32_t srvsvc_sa_modify(smb_share_t *, srvsvc_netshare_setinfo_t *); 165 static uint32_t srvsvc_sa_setattr(smb_share_t *); 166 167 static char empty_string[1]; 168 169 static ndr_stub_table_t srvsvc_stub_table[]; 170 171 static ndr_service_t srvsvc_service = { 172 "SRVSVC", /* name */ 173 "Server services", /* desc */ 174 "\\srvsvc", /* endpoint */ 175 PIPE_NTSVCS, /* sec_addr_port */ 176 "4b324fc8-1670-01d3-1278-5a47bf6ee188", 3, /* abstract */ 177 NDR_TRANSFER_SYNTAX_UUID, 2, /* transfer */ 178 0, /* no bind_instance_size */ 179 0, /* no bind_req() */ 180 0, /* no unbind_and_close() */ 181 0, /* use generic_call_stub() */ 182 &TYPEINFO(srvsvc_interface), /* interface ti */ 183 srvsvc_stub_table /* stub_table */ 184 }; 185 186 /* 187 * srvsvc_initialize 188 * 189 * This function registers the SRVSVC RPC interface with the RPC runtime 190 * library. It must be called in order to use either the client side 191 * or the server side functions. 192 */ 193 void 194 srvsvc_initialize(void) 195 { 196 (void) ndr_svc_register(&srvsvc_service); 197 } 198 199 /* 200 * srvsvc_s_NetConnectEnum 201 * 202 * List tree connections made to a share on this server or all tree 203 * connections established from a specific client. Administrator, 204 * Server Operator, Print Operator or Power User group membership 205 * is required to use this interface. 206 * 207 * There are three information levels: 0, 1, and 50. We don't support 208 * level 50, which is only used by Windows 9x clients. 209 * 210 * It seems Server Manger (srvmgr) only sends workstation as the qualifier 211 * and the Computer Management Interface on Windows 2000 doesn't request 212 * a list of connections. 213 * 214 * Return Values: 215 * ERROR_SUCCESS Success 216 * ERROR_ACCESS_DENIED Caller does not have access to this call. 217 * ERROR_INVALID_PARAMETER One of the parameters is invalid. 218 * ERROR_INVALID_LEVEL Unknown information level specified. 219 * ERROR_MORE_DATA Partial date returned, more entries available. 220 * ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available. 221 * NERR_NetNameNotFound The share qualifier cannot be found. 222 * NERR_BufTooSmall The supplied buffer is too small. 223 */ 224 static int 225 srvsvc_s_NetConnectEnum(void *arg, ndr_xa_t *mxa) 226 { 227 struct mslm_NetConnectEnum *param = arg; 228 srvsvc_NetConnectInfo0_t *info0; 229 srvsvc_NetConnectInfo1_t *info1; 230 char *qualifier; 231 int qualtype; 232 DWORD status = ERROR_SUCCESS; 233 234 if (!ndr_is_poweruser(mxa)) { 235 bzero(param, sizeof (struct mslm_NetConnectEnum)); 236 param->status = ERROR_ACCESS_DENIED; 237 return (NDR_DRC_OK); 238 } 239 240 qualifier = (char *)param->qualifier; 241 qualtype = srvsvc_netconnect_qualifier(qualifier); 242 243 if (qualtype == SRVSVC_CONNECT_ENUM_NULL) { 244 bzero(param, sizeof (struct mslm_NetConnectEnum)); 245 param->status = NERR_NetNameNotFound; 246 return (NDR_DRC_OK); 247 } 248 249 switch (param->info.level) { 250 case 0: 251 info0 = NDR_NEW(mxa, srvsvc_NetConnectInfo0_t); 252 if (info0 == NULL) { 253 status = ERROR_NOT_ENOUGH_MEMORY; 254 break; 255 } 256 257 bzero(info0, sizeof (srvsvc_NetConnectInfo0_t)); 258 param->info.ru.info0 = info0; 259 260 status = srvsvc_s_NetConnectEnumLevel0(mxa, info0); 261 262 param->total_entries = info0->entries_read; 263 param->resume_handle = NULL; 264 break; 265 266 case 1: 267 info1 = NDR_NEW(mxa, srvsvc_NetConnectInfo1_t); 268 if (info1 == NULL) { 269 status = ERROR_NOT_ENOUGH_MEMORY; 270 break; 271 } 272 273 bzero(info1, sizeof (srvsvc_NetConnectInfo1_t)); 274 param->info.ru.info1 = info1; 275 276 status = srvsvc_s_NetConnectEnumLevel1(mxa, info1); 277 278 param->total_entries = info1->entries_read; 279 param->resume_handle = NULL; 280 break; 281 282 case 50: 283 status = ERROR_NOT_SUPPORTED; 284 break; 285 286 default: 287 status = ERROR_INVALID_LEVEL; 288 break; 289 } 290 291 if (status != ERROR_SUCCESS) 292 bzero(param, sizeof (struct mslm_NetConnectEnum)); 293 294 param->status = status; 295 return (NDR_DRC_OK); 296 } 297 298 static DWORD 299 srvsvc_s_NetConnectEnumLevel0(ndr_xa_t *mxa, srvsvc_NetConnectInfo0_t *info0) 300 { 301 srvsvc_NetConnectInfoBuf0_t *ci0; 302 303 ci0 = NDR_NEW(mxa, srvsvc_NetConnectInfoBuf0_t); 304 if (ci0 == NULL) 305 return (ERROR_NOT_ENOUGH_MEMORY); 306 307 ci0->coni0_id = 0x17; 308 309 info0->ci0 = ci0; 310 info0->entries_read = 1; 311 return (ERROR_SUCCESS); 312 } 313 314 static DWORD 315 srvsvc_s_NetConnectEnumLevel1(ndr_xa_t *mxa, srvsvc_NetConnectInfo1_t *info1) 316 { 317 srvsvc_NetConnectInfoBuf1_t *ci1; 318 319 ci1 = NDR_NEW(mxa, srvsvc_NetConnectInfoBuf1_t); 320 if (ci1 == NULL) 321 return (ERROR_NOT_ENOUGH_MEMORY); 322 323 ci1->coni1_id = 0x17; 324 ci1->coni1_type = STYPE_IPC; 325 ci1->coni1_num_opens = 1; 326 ci1->coni1_num_users = 1; 327 ci1->coni1_time = 16; 328 ci1->coni1_username = (uint8_t *)NDR_STRDUP(mxa, "Administrator"); 329 ci1->coni1_netname = (uint8_t *)NDR_STRDUP(mxa, "IPC$"); 330 331 info1->ci1 = ci1; 332 info1->entries_read = 1; 333 return (ERROR_SUCCESS); 334 } 335 336 /* 337 * srvsvc_netconnect_qualifier 338 * 339 * The qualifier is a string that specifies a share name or computer name 340 * for the connections of interest. If it is a share name then all the 341 * connections made to that share name are listed. If it is a computer 342 * name (it starts with two backslash characters), then NetConnectEnum 343 * lists all connections made from that computer to the specified server. 344 */ 345 static int 346 srvsvc_netconnect_qualifier(const char *qualifier) 347 { 348 if (qualifier == NULL || *qualifier == '\0') 349 return (SRVSVC_CONNECT_ENUM_NULL); 350 351 if (strlen(qualifier) > MAXHOSTNAMELEN) 352 return (SRVSVC_CONNECT_ENUM_NULL); 353 354 if (qualifier[0] == '\\' && qualifier[1] == '\\') { 355 return (SRVSVC_CONNECT_ENUM_WKSTN); 356 } else { 357 if (!smb_shr_exists((char *)qualifier)) 358 return (SRVSVC_CONNECT_ENUM_NULL); 359 360 return (SRVSVC_CONNECT_ENUM_SHARE); 361 } 362 } 363 364 /* 365 * srvsvc_s_NetFileEnum 366 * 367 * Return information on open files or named pipes. Only members of the 368 * Administrators or Server Operators local groups are allowed to make 369 * this call. Currently, we only support Administrators. 370 * 371 * If basepath is null, all open resources are enumerated. If basepath 372 * is non-null, only resources that have basepath as a prefix should 373 * be returned. 374 * 375 * If username is specified (non-null), only files opened by username 376 * should be returned. 377 * 378 * Notes: 379 * 1. We don't validate the servername because we would have to check 380 * all primary IPs and the ROI seems unlikely to be worth it. 381 * 2. Both basepath and username are currently ignored because both 382 * Server Manger (NT 4.0) and CMI (Windows 2000) always set them to null. 383 * 384 * The level of information requested may be one of: 385 * 386 * 2 Return the file identification number. 387 * This level is not supported on Windows Me/98/95. 388 * 389 * 3 Return information about the file. 390 * This level is not supported on Windows Me/98/95. 391 * 392 * 50 Windows Me/98/95: Return information about the file. 393 * 394 * Note: 395 * If pref_max_len is unlimited and resume_handle is null, the client 396 * expects to receive all data in a single call. 397 * If we are unable to do fit all data in a single response, we would 398 * normally return ERROR_MORE_DATA with a partial list. 399 * 400 * Unfortunately, when both of these conditions occur, Server Manager 401 * pops up an error box with the message "more data available" and 402 * doesn't display any of the returned data. In this case, it is 403 * probably better to return ERROR_SUCCESS with the partial list. 404 * Windows 2000 doesn't have this problem because it always sends a 405 * non-null resume_handle. 406 * 407 * Return Values: 408 * ERROR_SUCCESS Success 409 * ERROR_ACCESS_DENIED Caller does not have access to this call. 410 * ERROR_INVALID_PARAMETER One of the parameters is invalid. 411 * ERROR_INVALID_LEVEL Unknown information level specified. 412 * ERROR_MORE_DATA Partial date returned, more entries available. 413 * ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available. 414 * NERR_BufTooSmall The supplied buffer is too small. 415 */ 416 static int 417 srvsvc_s_NetFileEnum(void *arg, ndr_xa_t *mxa) 418 { 419 struct mslm_NetFileEnum *param = arg; 420 DWORD status; 421 422 if (!ndr_is_admin(mxa)) { 423 bzero(param, sizeof (struct mslm_NetFileEnum)); 424 param->status = ERROR_ACCESS_DENIED; 425 return (NDR_DRC_OK); 426 } 427 428 switch (param->info.switch_value) { 429 case 2: 430 status = srvsvc_NetFileEnum2(mxa, param); 431 break; 432 433 case 3: 434 status = srvsvc_NetFileEnum3(mxa, param); 435 break; 436 437 case 50: 438 status = ERROR_NOT_SUPPORTED; 439 break; 440 441 default: 442 status = ERROR_INVALID_LEVEL; 443 break; 444 } 445 446 if (status != ERROR_SUCCESS) { 447 bzero(param, sizeof (struct mslm_NetFileEnum)); 448 param->status = status; 449 return (NDR_DRC_OK); 450 } 451 452 if (param->resume_handle) 453 *param->resume_handle = 0; 454 455 param->status = ERROR_SUCCESS; 456 return (NDR_DRC_OK); 457 } 458 459 /* 460 * Build level 2 file information. 461 * 462 * On success, the caller expects that the info2, fi2 and entries_read 463 * fields have been set up. 464 */ 465 static DWORD 466 srvsvc_NetFileEnum2(ndr_xa_t *mxa, struct mslm_NetFileEnum *param) 467 { 468 struct mslm_NetFileInfoBuf2 *fi2; 469 ndr_pipe_info_t pi; 470 uint32_t entries_read = 0; 471 int i; 472 473 param->info.ru.info2 = NDR_NEW(mxa, struct mslm_NetFileInfo2); 474 if (param->info.ru.info2 == NULL) 475 return (ERROR_NOT_ENOUGH_MEMORY); 476 477 fi2 = NDR_NEWN(mxa, struct mslm_NetFileInfoBuf2, 128); 478 if (fi2 == NULL) 479 return (ERROR_NOT_ENOUGH_MEMORY); 480 481 param->info.ru.info2->fi2 = fi2; 482 483 for (i = 0; i < 128; ++i) { 484 if (ndr_pipe_getinfo(i, &pi) == -1) 485 continue; 486 487 fi2->fi2_id = pi.npi_fid; 488 489 ++entries_read; 490 ++fi2; 491 } 492 493 param->info.ru.info2->entries_read = entries_read; 494 param->total_entries = entries_read; 495 return (ERROR_SUCCESS); 496 } 497 498 /* 499 * Build level 3 file information. 500 * 501 * On success, the caller expects that the info3, fi3 and entries_read 502 * fields have been set up. 503 */ 504 static DWORD 505 srvsvc_NetFileEnum3(ndr_xa_t *mxa, struct mslm_NetFileEnum *param) 506 { 507 struct mslm_NetFileInfoBuf3 *fi3; 508 ndr_pipe_info_t pi; 509 uint32_t entries_read = 0; 510 int i; 511 512 param->info.ru.info3 = NDR_NEW(mxa, struct mslm_NetFileInfo3); 513 if (param->info.ru.info3 == NULL) 514 return (ERROR_NOT_ENOUGH_MEMORY); 515 516 fi3 = NDR_NEWN(mxa, struct mslm_NetFileInfoBuf3, 128); 517 if (fi3 == NULL) 518 return (ERROR_NOT_ENOUGH_MEMORY); 519 520 param->info.ru.info3->fi3 = fi3; 521 522 for (i = 0; i < 128; ++i) { 523 if (ndr_pipe_getinfo(i, &pi) == -1) 524 continue; 525 526 fi3->fi3_id = pi.npi_fid; 527 fi3->fi3_permissions = pi.npi_permissions; 528 fi3->fi3_num_locks = pi.npi_num_locks; 529 fi3->fi3_pathname = (uint8_t *) 530 NDR_STRDUP(mxa, pi.npi_pathname); 531 fi3->fi3_username = (uint8_t *) 532 NDR_STRDUP(mxa, pi.npi_username); 533 534 ++entries_read; 535 ++fi3; 536 } 537 538 param->info.ru.info3->entries_read = entries_read; 539 param->total_entries = entries_read; 540 return (ERROR_SUCCESS); 541 } 542 543 /* 544 * srvsvc_s_NetFileClose 545 * 546 * NetFileClose forces a file to close. This function can be used when 547 * an error prevents closure by any other means. Use NetFileClose with 548 * caution because it does not flush data, cached on a client, to the 549 * file before closing the file. 550 * 551 * Return Values 552 * ERROR_SUCCESS Operation succeeded. 553 * ERROR_ACCESS_DENIED Operation denied. 554 * NERR_FileIdNotFound No open file with the specified id. 555 * 556 * Note: MSDN suggests that the error code should be ERROR_FILE_NOT_FOUND 557 * but network captures using NT show NERR_FileIdNotFound. 558 * The NetFileClose2 MSDN page has the right error code. 559 */ 560 static int 561 srvsvc_s_NetFileClose(void *arg, ndr_xa_t *mxa) 562 { 563 struct mslm_NetFileClose *param = arg; 564 565 if (!ndr_is_admin(mxa)) { 566 bzero(param, sizeof (struct mslm_NetFileClose)); 567 param->status = ERROR_ACCESS_DENIED; 568 return (NDR_DRC_OK); 569 } 570 571 bzero(param, sizeof (struct mslm_NetFileClose)); 572 param->status = ERROR_SUCCESS; 573 return (NDR_DRC_OK); 574 } 575 576 /* 577 * srvsvc_s_NetShareGetInfo 578 * 579 * Returns Win32 error codes. 580 */ 581 static int 582 srvsvc_s_NetShareGetInfo(void *arg, ndr_xa_t *mxa) 583 { 584 struct mlsm_NetShareGetInfo *param = arg; 585 struct mslm_NetShareInfo_0 *info0; 586 struct mslm_NetShareInfo_1 *info1; 587 struct mslm_NetShareInfo_2 *info2; 588 struct mslm_NetShareInfo_501 *info501; 589 struct mslm_NetShareInfo_502 *info502; 590 struct mslm_NetShareInfo_503 *info503; 591 struct mslm_NetShareInfo_1004 *info1004; 592 struct mslm_NetShareInfo_1005 *info1005; 593 struct mslm_NetShareInfo_1006 *info1006; 594 struct mslm_NetShareInfo_1501 *info1501; 595 srvsvc_netshare_getinfo_t *info; 596 uint8_t *netname; 597 uint8_t *comment; 598 smb_share_t si; 599 srvsvc_sd_t sd; 600 DWORD status; 601 602 status = smb_shr_get((char *)param->netname, &si); 603 if (status != NERR_Success) { 604 bzero(param, sizeof (struct mlsm_NetShareGetInfo)); 605 param->status = status; 606 return (NDR_DRC_OK); 607 } 608 609 netname = (uint8_t *)NDR_STRDUP(mxa, si.shr_name); 610 comment = (uint8_t *)NDR_STRDUP(mxa, si.shr_cmnt); 611 info = NDR_NEW(mxa, srvsvc_netshare_getinfo_t); 612 613 if (netname == NULL || comment == NULL || info == NULL) { 614 bzero(param, sizeof (struct mlsm_NetShareGetInfo)); 615 param->status = ERROR_NOT_ENOUGH_MEMORY; 616 return (NDR_DRC_OK); 617 } 618 619 switch (param->level) { 620 case 0: 621 info0 = &info->nsg_info0; 622 info0->shi0_netname = netname; 623 param->result.ru.info0 = info0; 624 break; 625 626 case 1: 627 info1 = &info->nsg_info1; 628 info1->shi1_netname = netname; 629 info1->shi1_comment = comment; 630 info1->shi1_type = si.shr_type; 631 param->result.ru.info1 = info1; 632 break; 633 634 case 2: 635 info2 = &info->nsg_info2; 636 info2->shi2_netname = netname; 637 info2->shi2_comment = comment; 638 info2->shi2_path = 639 (uint8_t *)srvsvc_share_mkpath(mxa, si.shr_path); 640 info2->shi2_passwd = 0; 641 info2->shi2_type = si.shr_type; 642 info2->shi2_permissions = 0; 643 info2->shi2_max_uses = SHI_USES_UNLIMITED; 644 info2->shi2_current_uses = 0; 645 param->result.ru.info2 = info2; 646 break; 647 648 case 501: 649 info501 = &info->nsg_info501; 650 info501->shi501_netname = netname; 651 info501->shi501_comment = comment; 652 info501->shi501_type = si.shr_type; 653 info501->shi501_reserved = 0; 654 param->result.ru.info501 = info501; 655 break; 656 657 case 502: 658 info502 = &info->nsg_info502; 659 info502->shi502_netname = netname; 660 info502->shi502_comment = comment; 661 info502->shi502_path = 662 (uint8_t *)srvsvc_share_mkpath(mxa, si.shr_path); 663 info502->shi502_passwd = 0; 664 info502->shi502_type = si.shr_type; 665 info502->shi502_permissions = 0; 666 info502->shi502_max_uses = SHI_USES_UNLIMITED; 667 info502->shi502_current_uses = 0; 668 669 status = srvsvc_share_getsd(mxa, &si, &sd); 670 if (status == ERROR_SUCCESS) { 671 info502->shi502_reserved = sd.sd_size; 672 info502->shi502_security_descriptor = sd.sd_buf; 673 } else { 674 info502->shi502_reserved = 0; 675 info502->shi502_security_descriptor = NULL; 676 } 677 678 param->result.ru.info502 = info502; 679 break; 680 681 case 503: 682 info503 = &info->nsg_info503; 683 info503->shi503_netname = netname; 684 info503->shi503_comment = comment; 685 info503->shi503_path = 686 (uint8_t *)srvsvc_share_mkpath(mxa, si.shr_path); 687 info503->shi503_passwd = NULL; 688 info503->shi503_type = si.shr_type; 689 info503->shi503_permissions = 0; 690 info503->shi503_max_uses = SHI_USES_UNLIMITED; 691 info503->shi503_current_uses = 0; 692 info503->shi503_servername = NULL; 693 694 status = srvsvc_share_getsd(mxa, &si, &sd); 695 if (status == ERROR_SUCCESS) { 696 info503->shi503_reserved = sd.sd_size; 697 info503->shi503_security_descriptor = sd.sd_buf; 698 } else { 699 info503->shi503_reserved = 0; 700 info503->shi503_security_descriptor = NULL; 701 } 702 703 param->result.ru.info503 = info503; 704 break; 705 706 case 1004: 707 info1004 = &info->nsg_info1004; 708 info1004->shi1004_comment = comment; 709 param->result.ru.info1004 = info1004; 710 break; 711 712 case 1005: 713 info1005 = &info->nsg_info1005; 714 info1005->shi1005_flags = 0; 715 716 switch (si.shr_flags & SMB_SHRF_CSC_MASK) { 717 case SMB_SHRF_CSC_DISABLED: 718 info1005->shi1005_flags |= CSC_CACHE_NONE; 719 break; 720 case SMB_SHRF_CSC_AUTO: 721 info1005->shi1005_flags |= CSC_CACHE_AUTO_REINT; 722 break; 723 case SMB_SHRF_CSC_VDO: 724 info1005->shi1005_flags |= CSC_CACHE_VDO; 725 break; 726 case SMB_SHRF_CSC_MANUAL: 727 default: 728 /* 729 * Default to CSC_CACHE_MANUAL_REINT. 730 */ 731 break; 732 } 733 734 param->result.ru.info1005 = info1005; 735 break; 736 737 case 1006: 738 info1006 = &info->nsg_info1006; 739 info1006->shi1006_max_uses = SHI_USES_UNLIMITED; 740 param->result.ru.info1006 = info1006; 741 break; 742 743 case 1501: 744 info1501 = &info->nsg_info1501; 745 746 status = srvsvc_share_getsd(mxa, &si, &sd); 747 if (status == ERROR_SUCCESS) { 748 info503->shi503_reserved = sd.sd_size; 749 info503->shi503_security_descriptor = sd.sd_buf; 750 } else { 751 info503->shi503_reserved = 0; 752 info503->shi503_security_descriptor = NULL; 753 } 754 755 param->result.ru.info1501 = info1501; 756 break; 757 758 default: 759 status = ERROR_ACCESS_DENIED; 760 break; 761 } 762 763 if (status != ERROR_SUCCESS) 764 bzero(param, sizeof (struct mlsm_NetShareGetInfo)); 765 else 766 param->result.switch_value = param->level; 767 768 param->status = status; 769 return (NDR_DRC_OK); 770 } 771 772 static uint32_t 773 srvsvc_share_getsd(ndr_xa_t *mxa, smb_share_t *si, srvsvc_sd_t *sd) 774 { 775 uint32_t status; 776 777 status = srvsvc_sd_get(si, NULL, &sd->sd_size); 778 if (status != ERROR_SUCCESS) { 779 if (status == ERROR_PATH_NOT_FOUND) { 780 bzero(sd, sizeof (srvsvc_sd_t)); 781 status = ERROR_SUCCESS; 782 } 783 784 return (status); 785 } 786 787 if ((sd->sd_buf = NDR_MALLOC(mxa, sd->sd_size)) == NULL) 788 return (ERROR_NOT_ENOUGH_MEMORY); 789 790 status = srvsvc_sd_get(si, sd->sd_buf, NULL); 791 if (status == ERROR_PATH_NOT_FOUND) { 792 bzero(sd, sizeof (srvsvc_sd_t)); 793 status = ERROR_SUCCESS; 794 } 795 796 return (status); 797 } 798 799 /* 800 * srvsvc_s_NetShareSetInfo 801 * 802 * This call is made by SrvMgr to set share information. 803 * Only power users groups can manage shares. 804 * 805 * To avoid misleading errors, we don't report an error 806 * when a FS doesn't support ACLs on shares. 807 * 808 * Returns Win32 error codes. 809 */ 810 static int 811 srvsvc_s_NetShareSetInfo(void *arg, ndr_xa_t *mxa) 812 { 813 struct mlsm_NetShareSetInfo *param = arg; 814 struct mslm_NetShareInfo_0 *info0; 815 struct mslm_NetShareInfo_1 *info1; 816 struct mslm_NetShareInfo_2 *info2; 817 struct mslm_NetShareInfo_501 *info501; 818 struct mslm_NetShareInfo_502 *info502; 819 struct mslm_NetShareInfo_503 *info503; 820 struct mslm_NetShareInfo_1004 *info1004; 821 struct mslm_NetShareInfo_1005 *info1005; 822 struct mslm_NetShareInfo_1501 *info1501; 823 static DWORD parm_err = 0; 824 srvsvc_netshare_setinfo_t info; 825 smb_share_t si; 826 uint8_t *sdbuf; 827 int32_t native_os; 828 DWORD status; 829 830 native_os = ndr_native_os(mxa); 831 832 if (!ndr_is_poweruser(mxa)) { 833 status = ERROR_ACCESS_DENIED; 834 goto netsharesetinfo_exit; 835 } 836 837 if (smb_shr_get((char *)param->netname, &si) != NERR_Success) { 838 status = ERROR_INVALID_NETNAME; 839 goto netsharesetinfo_exit; 840 } 841 842 if (param->result.ru.nullptr == NULL) { 843 status = ERROR_INVALID_PARAMETER; 844 goto netsharesetinfo_exit; 845 } 846 847 bzero(&info, sizeof (srvsvc_netshare_setinfo_t)); 848 849 switch (param->level) { 850 case 0: 851 info0 = (struct mslm_NetShareInfo_0 *)param->result.ru.info0; 852 info.nss_netname = (char *)info0->shi0_netname; 853 status = srvsvc_modify_share(&si, &info); 854 break; 855 856 case 1: 857 info1 = (struct mslm_NetShareInfo_1 *)param->result.ru.info1; 858 info.nss_netname = (char *)info1->shi1_netname; 859 info.nss_comment = (char *)info1->shi1_comment; 860 info.nss_type = info1->shi1_type; 861 status = srvsvc_modify_share(&si, &info); 862 break; 863 864 case 2: 865 info2 = (struct mslm_NetShareInfo_2 *)param->result.ru.info2; 866 info.nss_netname = (char *)info2->shi2_netname; 867 info.nss_comment = (char *)info2->shi2_comment; 868 info.nss_path = (char *)info2->shi2_path; 869 info.nss_type = info2->shi2_type; 870 status = srvsvc_modify_share(&si, &info); 871 break; 872 873 case 501: 874 info501 = (struct mslm_NetShareInfo_501 *) 875 param->result.ru.info501; 876 info.nss_netname = (char *)info501->shi501_netname; 877 info.nss_comment = (char *)info501->shi501_comment; 878 info.nss_type = info501->shi501_type; 879 status = srvsvc_modify_share(&si, &info); 880 break; 881 882 case 502: 883 info502 = (struct mslm_NetShareInfo_502 *) 884 param->result.ru.info502; 885 info.nss_netname = (char *)info502->shi502_netname; 886 info.nss_comment = (char *)info502->shi502_comment; 887 info.nss_path = (char *)info502->shi502_path; 888 info.nss_type = info502->shi502_type; 889 info.nss_sd.sd_buf = info502->shi502_security_descriptor; 890 status = srvsvc_modify_share(&si, &info); 891 break; 892 893 case 503: 894 info503 = (struct mslm_NetShareInfo_503 *) 895 param->result.ru.info503; 896 info.nss_netname = (char *)info503->shi503_netname; 897 info.nss_comment = (char *)info503->shi503_comment; 898 info.nss_path = (char *)info503->shi503_path; 899 info.nss_type = info503->shi503_type; 900 info.nss_sd.sd_buf = info503->shi503_security_descriptor; 901 status = srvsvc_modify_share(&si, &info); 902 break; 903 904 case 1004: 905 info1004 = (struct mslm_NetShareInfo_1004 *) 906 param->result.ru.info1004; 907 info.nss_comment = (char *)info1004->shi1004_comment; 908 status = srvsvc_modify_share(&si, &info); 909 break; 910 911 case 1005: 912 info1005 = (struct mslm_NetShareInfo_1005 *) 913 param->result.ru.info1005; 914 status = srvsvc_update_share_flags(&si, 915 info1005->shi1005_flags); 916 break; 917 918 case 1006: 919 /* 920 * We don't limit the maximum number of concurrent 921 * connections to a share. 922 */ 923 status = ERROR_SUCCESS; 924 break; 925 926 case 1501: 927 info1501 = (struct mslm_NetShareInfo_1501 *) 928 param->result.ru.info1501; 929 sdbuf = info1501->shi1501_security_descriptor; 930 status = ERROR_SUCCESS; 931 932 if (sdbuf != NULL) { 933 status = srvsvc_sd_set(&si, sdbuf); 934 if (status == ERROR_PATH_NOT_FOUND) 935 status = ERROR_SUCCESS; 936 } 937 break; 938 939 default: 940 status = ERROR_ACCESS_DENIED; 941 break; 942 } 943 944 netsharesetinfo_exit: 945 if (status != ERROR_SUCCESS) 946 bzero(param, sizeof (struct mlsm_NetShareSetInfo)); 947 948 param->parm_err = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err; 949 param->status = status; 950 return (NDR_DRC_OK); 951 } 952 953 static uint32_t 954 srvsvc_modify_share(smb_share_t *si, srvsvc_netshare_setinfo_t *info) 955 { 956 uint32_t nerr = NERR_Success; 957 958 if (si->shr_flags & SMB_SHRF_TRANS) 959 return (srvsvc_modify_transient_share(si, info)); 960 961 if (info->nss_sd.sd_buf != NULL) { 962 nerr = srvsvc_sd_set(si, info->nss_sd.sd_buf); 963 if (nerr == ERROR_PATH_NOT_FOUND) 964 nerr = NERR_Success; 965 } 966 967 if ((nerr = srvsvc_sa_modify(si, info)) == NERR_Success) 968 nerr = smb_shr_modify(si); 969 970 return (nerr); 971 } 972 973 /* 974 * Update transient shares. This includes autohome shares. 975 */ 976 static uint32_t 977 srvsvc_modify_transient_share(smb_share_t *si, srvsvc_netshare_setinfo_t *info) 978 { 979 uint32_t nerr; 980 981 if (info->nss_netname != NULL && info->nss_netname[0] != '\0' && 982 utf8_strcasecmp(info->nss_netname, si->shr_name) != 0) { 983 nerr = smb_shr_rename(si->shr_name, info->nss_netname); 984 if (nerr != NERR_Success) 985 return (nerr); 986 987 (void) strlcpy(si->shr_name, info->nss_netname, MAXNAMELEN); 988 } 989 990 if ((info->nss_comment != NULL) && 991 (strcmp(info->nss_comment, si->shr_cmnt) != 0)) { 992 (void) strlcpy(si->shr_cmnt, info->nss_comment, 993 SMB_SHARE_CMNT_MAX); 994 995 if ((nerr = smb_shr_modify(si)) != NERR_Success) 996 return (nerr); 997 } 998 999 return (NERR_Success); 1000 } 1001 1002 static uint32_t 1003 srvsvc_update_share_flags(smb_share_t *si, uint32_t shi_flags) 1004 { 1005 uint32_t cscflg = 0; 1006 uint32_t nerr = NERR_Success; 1007 1008 switch ((shi_flags & CSC_MASK)) { 1009 case CSC_CACHE_AUTO_REINT: 1010 cscflg = SMB_SHRF_CSC_AUTO; 1011 break; 1012 case CSC_CACHE_VDO: 1013 cscflg = SMB_SHRF_CSC_VDO; 1014 break; 1015 case CSC_CACHE_NONE: 1016 cscflg = SMB_SHRF_CSC_DISABLED; 1017 break; 1018 case CSC_CACHE_MANUAL_REINT: 1019 cscflg = SMB_SHRF_CSC_MANUAL; 1020 break; 1021 default: 1022 return (NERR_Success); 1023 } 1024 1025 if (cscflg == (si->shr_flags & SMB_SHRF_CSC_MASK)) 1026 return (NERR_Success); 1027 1028 si->shr_flags &= ~SMB_SHRF_CSC_MASK; 1029 si->shr_flags |= cscflg; 1030 1031 if ((si->shr_flags & SMB_SHRF_TRANS) == 0) { 1032 if ((nerr = srvsvc_sa_setattr(si)) != NERR_Success) 1033 return (nerr); 1034 } 1035 1036 return (smb_shr_modify(si)); 1037 } 1038 1039 /* 1040 * srvsvc_s_NetSessionEnum 1041 * 1042 * Level 1 request is made by (Server Manager (srvmgr) on NT Server when 1043 * the user info icon is selected. 1044 * 1045 * On success, the return value is NERR_Success. 1046 * On error, the return value can be one of the following error codes: 1047 * 1048 * ERROR_ACCESS_DENIED The user does not have access to the requested 1049 * information. 1050 * ERROR_INVALID_LEVEL The value specified for the level is invalid. 1051 * ERROR_INVALID_PARAMETER The specified parameter is invalid. 1052 * ERROR_MORE_DATA More entries are available. Specify a large 1053 * enough buffer to receive all entries. 1054 * ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available. 1055 * NERR_ClientNameNotFound A session does not exist with the computer name. 1056 * NERR_InvalidComputer The computer name is invalid. 1057 * NERR_UserNotFound The user name could not be found. 1058 */ 1059 static int 1060 srvsvc_s_NetSessionEnum(void *arg, ndr_xa_t *mxa) 1061 { 1062 struct mslm_NetSessionEnum *param = arg; 1063 struct mslm_infonres *infonres; 1064 DWORD status; 1065 DWORD n_sessions; 1066 1067 infonres = NDR_NEW(mxa, struct mslm_infonres); 1068 if (infonres == NULL) { 1069 bzero(param, sizeof (struct mslm_NetSessionEnum)); 1070 param->status = ERROR_NOT_ENOUGH_MEMORY; 1071 return (NDR_DRC_OK); 1072 } 1073 1074 infonres->entriesread = 0; 1075 infonres->entries = NULL; 1076 param->result.level = param->level; 1077 param->result.bufptr.p = infonres; 1078 param->total_entries = 0; 1079 param->resume_handle = NULL; 1080 param->status = ERROR_SUCCESS; 1081 1082 if ((n_sessions = (DWORD) mlsvc_get_num_users()) == 0) 1083 return (NDR_DRC_OK); 1084 1085 switch (param->level) { 1086 case 0: 1087 status = mlsvc_NetSessionEnumLevel0(infonres, n_sessions, mxa); 1088 break; 1089 1090 case 1: 1091 status = mlsvc_NetSessionEnumLevel1(infonres, n_sessions, mxa); 1092 break; 1093 1094 case 2: 1095 status = mlsvc_NetSessionEnumLevel2(infonres, n_sessions, mxa); 1096 break; 1097 1098 case 10: 1099 status = mlsvc_NetSessionEnumLevel10(infonres, n_sessions, mxa); 1100 break; 1101 1102 case 502: 1103 status = mlsvc_NetSessionEnumLevel502(infonres, n_sessions, 1104 mxa); 1105 break; 1106 1107 default: 1108 status = ERROR_INVALID_LEVEL; 1109 break; 1110 } 1111 1112 if (status != 0) { 1113 bzero(param, sizeof (struct mslm_NetSessionEnum)); 1114 param->status = status; 1115 return (NDR_DRC_OK); 1116 } 1117 1118 param->total_entries = infonres->entriesread; 1119 param->status = status; 1120 return (NDR_DRC_OK); 1121 } 1122 1123 /* 1124 * mlsvc_NetSessionEnumLevel0 1125 * 1126 * Build the level 0 session information. 1127 */ 1128 static DWORD 1129 mlsvc_NetSessionEnumLevel0(struct mslm_infonres *infonres, DWORD n_sessions, 1130 ndr_xa_t *mxa) 1131 { 1132 struct mslm_SESSION_INFO_0 *info0; 1133 smb_ulist_t *ulist; 1134 smb_opipe_context_t *user; 1135 char *workstation; 1136 char ipaddr_buf[INET6_ADDRSTRLEN]; 1137 int i; 1138 1139 ulist = smb_ulist_alloc(); 1140 if (ulist == NULL) 1141 return (ERROR_NOT_ENOUGH_MEMORY); 1142 1143 if (mlsvc_get_user_list(ulist) != 0) { 1144 smb_ulist_free(ulist); 1145 return (ERROR_NOT_ENOUGH_MEMORY); 1146 } 1147 1148 if (ulist->ul_cnt < n_sessions) 1149 n_sessions = ulist->ul_cnt; 1150 1151 info0 = NDR_NEWN(mxa, struct mslm_SESSION_INFO_0, n_sessions); 1152 if (info0 == NULL) { 1153 smb_ulist_free(ulist); 1154 return (ERROR_NOT_ENOUGH_MEMORY); 1155 } 1156 1157 user = ulist->ul_users; 1158 for (i = 0; i < n_sessions; ++i, user++) { 1159 workstation = user->oc_workstation; 1160 if (workstation == NULL || *workstation == '\0') { 1161 (void) smb_inet_ntop(&user->oc_ipaddr, 1162 ipaddr_buf, SMB_IPSTRLEN(user->oc_ipaddr.a_family)); 1163 workstation = ipaddr_buf; 1164 } 1165 1166 info0[i].sesi0_cname = NDR_STRDUP(mxa, workstation); 1167 if (info0[i].sesi0_cname == NULL) { 1168 smb_ulist_free(ulist); 1169 return (ERROR_NOT_ENOUGH_MEMORY); 1170 } 1171 } 1172 1173 smb_ulist_free(ulist); 1174 infonres->entriesread = n_sessions; 1175 infonres->entries = info0; 1176 return (ERROR_SUCCESS); 1177 } 1178 1179 /* 1180 * mlsvc_NetSessionEnumLevel1 1181 * 1182 * Build the level 1 session information. 1183 */ 1184 static DWORD 1185 mlsvc_NetSessionEnumLevel1(struct mslm_infonres *infonres, DWORD n_sessions, 1186 ndr_xa_t *mxa) 1187 { 1188 struct mslm_SESSION_INFO_1 *info1; 1189 smb_ulist_t *ulist; 1190 smb_opipe_context_t *user; 1191 char *workstation; 1192 char account[MAXNAMELEN]; 1193 char ipaddr_buf[INET6_ADDRSTRLEN]; 1194 int i; 1195 1196 ulist = smb_ulist_alloc(); 1197 if (ulist == NULL) 1198 return (ERROR_NOT_ENOUGH_MEMORY); 1199 1200 if (mlsvc_get_user_list(ulist) != 0) { 1201 smb_ulist_free(ulist); 1202 return (ERROR_NOT_ENOUGH_MEMORY); 1203 } 1204 1205 if (ulist->ul_cnt < n_sessions) 1206 n_sessions = ulist->ul_cnt; 1207 1208 info1 = NDR_NEWN(mxa, struct mslm_SESSION_INFO_1, n_sessions); 1209 if (info1 == NULL) { 1210 smb_ulist_free(ulist); 1211 return (ERROR_NOT_ENOUGH_MEMORY); 1212 } 1213 1214 user = ulist->ul_users; 1215 for (i = 0; i < n_sessions; ++i, user++) { 1216 workstation = user->oc_workstation; 1217 if (workstation == NULL || *workstation == '\0') { 1218 (void) smb_inet_ntop(&user->oc_ipaddr, 1219 ipaddr_buf, SMB_IPSTRLEN(user->oc_ipaddr.a_family)); 1220 workstation = ipaddr_buf; 1221 } 1222 1223 (void) snprintf(account, MAXNAMELEN, "%s\\%s", 1224 user->oc_domain, user->oc_account); 1225 1226 info1[i].sesi1_cname = NDR_STRDUP(mxa, workstation); 1227 info1[i].sesi1_uname = NDR_STRDUP(mxa, account); 1228 1229 if (info1[i].sesi1_cname == NULL || 1230 info1[i].sesi1_uname == NULL) { 1231 smb_ulist_free(ulist); 1232 return (ERROR_NOT_ENOUGH_MEMORY); 1233 } 1234 1235 info1[i].sesi1_nopens = 1; 1236 info1[i].sesi1_time = time(0) - user->oc_logon_time; 1237 info1[i].sesi1_itime = 0; 1238 info1[i].sesi1_uflags = 1239 (user->oc_flags & SMB_ATF_GUEST) ? SESS_GUEST : 0; 1240 } 1241 1242 smb_ulist_free(ulist); 1243 infonres->entriesread = n_sessions; 1244 infonres->entries = info1; 1245 return (ERROR_SUCCESS); 1246 } 1247 1248 /* 1249 * mlsvc_NetSessionEnumLevel2 1250 * 1251 * Build the level 2 session information. 1252 */ 1253 static DWORD 1254 mlsvc_NetSessionEnumLevel2(struct mslm_infonres *infonres, DWORD n_sessions, 1255 ndr_xa_t *mxa) 1256 { 1257 struct mslm_SESSION_INFO_2 *info2; 1258 smb_ulist_t *ulist; 1259 smb_opipe_context_t *user; 1260 char *workstation; 1261 char account[MAXNAMELEN]; 1262 char ipaddr_buf[INET6_ADDRSTRLEN]; 1263 int i; 1264 1265 if ((ulist = smb_ulist_alloc()) == NULL) 1266 return (ERROR_NOT_ENOUGH_MEMORY); 1267 1268 if (mlsvc_get_user_list(ulist) != 0) { 1269 smb_ulist_free(ulist); 1270 return (ERROR_NOT_ENOUGH_MEMORY); 1271 } 1272 1273 if (ulist->ul_cnt < n_sessions) 1274 n_sessions = ulist->ul_cnt; 1275 1276 info2 = NDR_NEWN(mxa, struct mslm_SESSION_INFO_2, n_sessions); 1277 if (info2 == NULL) { 1278 smb_ulist_free(ulist); 1279 return (ERROR_NOT_ENOUGH_MEMORY); 1280 } 1281 1282 user = ulist->ul_users; 1283 for (i = 0; i < n_sessions; ++i, user++) { 1284 workstation = user->oc_workstation; 1285 if (workstation == NULL || *workstation == '\0') { 1286 (void) smb_inet_ntop(&user->oc_ipaddr, 1287 ipaddr_buf, SMB_IPSTRLEN(user->oc_ipaddr.a_family)); 1288 workstation = ipaddr_buf; 1289 } 1290 1291 (void) snprintf(account, MAXNAMELEN, "%s\\%s", 1292 user->oc_domain, user->oc_account); 1293 1294 info2[i].sesi2_cname = NDR_STRDUP(mxa, workstation); 1295 info2[i].sesi2_uname = NDR_STRDUP(mxa, account); 1296 1297 if (info2[i].sesi2_cname == NULL || 1298 info2[i].sesi2_uname == NULL) { 1299 smb_ulist_free(ulist); 1300 return (ERROR_NOT_ENOUGH_MEMORY); 1301 } 1302 1303 info2[i].sesi2_nopens = 1; 1304 info2[i].sesi2_time = time(0) - user->oc_logon_time; 1305 info2[i].sesi2_itime = 0; 1306 info2[i].sesi2_uflags = 1307 (user->oc_flags & SMB_ATF_GUEST) ? SESS_GUEST : 0; 1308 info2[i].sesi2_cltype_name = (uint8_t *)""; 1309 } 1310 1311 smb_ulist_free(ulist); 1312 infonres->entriesread = n_sessions; 1313 infonres->entries = info2; 1314 return (ERROR_SUCCESS); 1315 } 1316 1317 /* 1318 * mlsvc_NetSessionEnumLevel10 1319 * 1320 * Build the level 10 session information. 1321 */ 1322 static DWORD 1323 mlsvc_NetSessionEnumLevel10(struct mslm_infonres *infonres, DWORD n_sessions, 1324 ndr_xa_t *mxa) 1325 { 1326 struct mslm_SESSION_INFO_10 *info10; 1327 smb_ulist_t *ulist; 1328 smb_opipe_context_t *user; 1329 char *workstation; 1330 char account[MAXNAMELEN]; 1331 char ipaddr_buf[INET6_ADDRSTRLEN]; 1332 int i; 1333 1334 if ((ulist = smb_ulist_alloc()) == NULL) 1335 return (ERROR_NOT_ENOUGH_MEMORY); 1336 1337 if (mlsvc_get_user_list(ulist) != 0) { 1338 smb_ulist_free(ulist); 1339 return (ERROR_NOT_ENOUGH_MEMORY); 1340 } 1341 1342 if (ulist->ul_cnt < n_sessions) 1343 n_sessions = ulist->ul_cnt; 1344 1345 info10 = NDR_NEWN(mxa, struct mslm_SESSION_INFO_10, n_sessions); 1346 if (info10 == NULL) { 1347 smb_ulist_free(ulist); 1348 return (ERROR_NOT_ENOUGH_MEMORY); 1349 } 1350 1351 user = ulist->ul_users; 1352 for (i = 0; i < n_sessions; ++i, user++) { 1353 workstation = user->oc_workstation; 1354 if (workstation == NULL || *workstation == '\0') { 1355 (void) smb_inet_ntop(&user->oc_ipaddr, 1356 ipaddr_buf, SMB_IPSTRLEN(user->oc_ipaddr.a_family)); 1357 workstation = ipaddr_buf; 1358 } 1359 1360 (void) snprintf(account, MAXNAMELEN, "%s\\%s", 1361 user->oc_domain, user->oc_account); 1362 1363 info10[i].sesi10_cname = NDR_STRDUP(mxa, workstation); 1364 info10[i].sesi10_uname = NDR_STRDUP(mxa, account); 1365 1366 if (info10[i].sesi10_cname == NULL || 1367 info10[i].sesi10_uname == NULL) { 1368 smb_ulist_free(ulist); 1369 return (ERROR_NOT_ENOUGH_MEMORY); 1370 } 1371 1372 info10[i].sesi10_time = time(0) - user->oc_logon_time; 1373 info10[i].sesi10_itime = 0; 1374 } 1375 1376 smb_ulist_free(ulist); 1377 infonres->entriesread = n_sessions; 1378 infonres->entries = info10; 1379 return (ERROR_SUCCESS); 1380 } 1381 1382 /* 1383 * mlsvc_NetSessionEnumLevel502 1384 * 1385 * Build the level 502 session information. 1386 */ 1387 static DWORD 1388 mlsvc_NetSessionEnumLevel502(struct mslm_infonres *infonres, DWORD n_sessions, 1389 ndr_xa_t *mxa) 1390 { 1391 struct mslm_SESSION_INFO_502 *info502; 1392 smb_ulist_t *ulist; 1393 smb_opipe_context_t *user; 1394 char *workstation; 1395 char account[MAXNAMELEN]; 1396 char ipaddr_buf[INET6_ADDRSTRLEN]; 1397 int i; 1398 1399 if ((ulist = smb_ulist_alloc()) == NULL) 1400 return (ERROR_NOT_ENOUGH_MEMORY); 1401 1402 if (mlsvc_get_user_list(ulist) != 0) { 1403 smb_ulist_free(ulist); 1404 return (ERROR_NOT_ENOUGH_MEMORY); 1405 } 1406 1407 if (ulist->ul_cnt < n_sessions) 1408 n_sessions = ulist->ul_cnt; 1409 1410 info502 = NDR_NEWN(mxa, struct mslm_SESSION_INFO_502, n_sessions); 1411 if (info502 == NULL) { 1412 smb_ulist_free(ulist); 1413 return (ERROR_NOT_ENOUGH_MEMORY); 1414 } 1415 1416 user = ulist->ul_users; 1417 for (i = 0; i < n_sessions; ++i, user++) { 1418 workstation = user->oc_workstation; 1419 if (workstation == NULL || *workstation == '\0') { 1420 (void) smb_inet_ntop(&user->oc_ipaddr, 1421 ipaddr_buf, SMB_IPSTRLEN(user->oc_ipaddr.a_family)); 1422 workstation = ipaddr_buf; 1423 } 1424 1425 (void) snprintf(account, MAXNAMELEN, "%s\\%s", 1426 user->oc_domain, user->oc_account); 1427 1428 info502[i].sesi502_cname = NDR_STRDUP(mxa, workstation); 1429 info502[i].sesi502_uname = NDR_STRDUP(mxa, account); 1430 1431 if (info502[i].sesi502_cname == NULL || 1432 info502[i].sesi502_uname == NULL) { 1433 smb_ulist_free(ulist); 1434 return (ERROR_NOT_ENOUGH_MEMORY); 1435 } 1436 1437 info502[i].sesi502_nopens = 1; 1438 info502[i].sesi502_time = time(0) - user->oc_logon_time; 1439 info502[i].sesi502_itime = 0; 1440 info502[i].sesi502_uflags = 1441 (user->oc_flags & SMB_ATF_GUEST) ? SESS_GUEST : 0; 1442 info502[i].sesi502_cltype_name = (uint8_t *)""; 1443 info502[i].sesi502_transport = (uint8_t *)""; 1444 } 1445 1446 smb_ulist_free(ulist); 1447 infonres->entriesread = n_sessions; 1448 infonres->entries = info502; 1449 return (ERROR_SUCCESS); 1450 } 1451 1452 /* 1453 * srvsvc_s_NetSessionDel 1454 * 1455 * Ends a network session between a server and a workstation. 1456 * On NT only members of the Administrators or Account Operators 1457 * local groups are permitted to use NetSessionDel. 1458 * 1459 * Return Values 1460 * If the function succeeds, the return value is NERR_Success/ 1461 * ERROR_SUCCESS. If the function fails, the return value can be 1462 * one of the following error codes: 1463 * 1464 * ERROR_ACCESS_DENIED The user does not have access to the 1465 * requested information. 1466 * ERROR_INVALID_PARAMETER The specified parameter is invalid. 1467 * ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available. 1468 * NERR_ClientNameNotFound A session does not exist with that 1469 * computer name. 1470 */ 1471 static int 1472 srvsvc_s_NetSessionDel(void *arg, ndr_xa_t *mxa) 1473 { 1474 struct mslm_NetSessionDel *param = arg; 1475 1476 if (!ndr_is_poweruser(mxa)) { 1477 param->status = ERROR_ACCESS_DENIED; 1478 return (NDR_DRC_OK); 1479 } 1480 1481 param->status = ERROR_ACCESS_DENIED; 1482 return (NDR_DRC_OK); 1483 } 1484 1485 /* 1486 * SRVSVC NetServerGetInfo 1487 * 1488 * IN LPTSTR servername, 1489 * IN DWORD level, 1490 * OUT union switch(level) { 1491 * case 100: mslm_SERVER_INFO_100 *p100; 1492 * case 101: mslm_SERVER_INFO_101 *p101; 1493 * case 102: mslm_SERVER_INFO_102 *p102; 1494 * ... 1495 * default: char *nullptr; 1496 * } bufptr, 1497 * OUT DWORD status 1498 */ 1499 static int 1500 srvsvc_s_NetServerGetInfo(void *arg, ndr_xa_t *mxa) 1501 { 1502 struct mslm_NetServerGetInfo *param = arg; 1503 struct mslm_SERVER_INFO_100 *info100; 1504 struct mslm_SERVER_INFO_101 *info101; 1505 struct mslm_SERVER_INFO_102 *info102; 1506 struct mslm_SERVER_INFO_502 *info502; 1507 struct mslm_SERVER_INFO_503 *info503; 1508 char sys_comment[SMB_PI_MAX_COMMENT]; 1509 char hostname[NETBIOS_NAME_SZ]; 1510 1511 if (smb_getnetbiosname(hostname, sizeof (hostname)) != 0) { 1512 netservergetinfo_no_memory: 1513 bzero(param, sizeof (struct mslm_NetServerGetInfo)); 1514 return (ERROR_NOT_ENOUGH_MEMORY); 1515 } 1516 1517 (void) smb_config_getstr(SMB_CI_SYS_CMNT, sys_comment, 1518 sizeof (sys_comment)); 1519 if (*sys_comment == '\0') 1520 (void) strcpy(sys_comment, " "); 1521 1522 switch (param->level) { 1523 case 100: 1524 info100 = NDR_NEW(mxa, struct mslm_SERVER_INFO_100); 1525 if (info100 == NULL) 1526 goto netservergetinfo_no_memory; 1527 1528 bzero(info100, sizeof (struct mslm_SERVER_INFO_100)); 1529 info100->sv100_platform_id = SV_PLATFORM_ID_NT; 1530 info100->sv100_name = (uint8_t *)NDR_STRDUP(mxa, hostname); 1531 if (info100->sv100_name == NULL) 1532 goto netservergetinfo_no_memory; 1533 1534 param->result.bufptr.bufptr100 = info100; 1535 break; 1536 1537 case 101: 1538 info101 = NDR_NEW(mxa, struct mslm_SERVER_INFO_101); 1539 if (info101 == NULL) 1540 goto netservergetinfo_no_memory; 1541 1542 bzero(info101, sizeof (struct mslm_SERVER_INFO_101)); 1543 info101->sv101_platform_id = SV_PLATFORM_ID_NT; 1544 info101->sv101_version_major = 4; 1545 info101->sv101_version_minor = 0; 1546 info101->sv101_type = SV_TYPE_SENT_BY_ME; 1547 info101->sv101_name = (uint8_t *)NDR_STRDUP(mxa, hostname); 1548 info101->sv101_comment 1549 = (uint8_t *)NDR_STRDUP(mxa, sys_comment); 1550 1551 if (info101->sv101_name == NULL || 1552 info101->sv101_comment == NULL) 1553 goto netservergetinfo_no_memory; 1554 1555 param->result.bufptr.bufptr101 = info101; 1556 break; 1557 1558 case 102: 1559 info102 = NDR_NEW(mxa, struct mslm_SERVER_INFO_102); 1560 if (info102 == NULL) 1561 goto netservergetinfo_no_memory; 1562 1563 bzero(info102, sizeof (struct mslm_SERVER_INFO_102)); 1564 info102->sv102_platform_id = SV_PLATFORM_ID_NT; 1565 info102->sv102_version_major = 4; 1566 info102->sv102_version_minor = 0; 1567 info102->sv102_type = SV_TYPE_SENT_BY_ME; 1568 info102->sv102_name = (uint8_t *)NDR_STRDUP(mxa, hostname); 1569 info102->sv102_comment 1570 = (uint8_t *)NDR_STRDUP(mxa, sys_comment); 1571 1572 /* 1573 * The following level 102 fields are defaulted to zero 1574 * by virtue of the call to bzero above. 1575 * 1576 * sv102_users 1577 * sv102_disc 1578 * sv102_hidden 1579 * sv102_announce 1580 * sv102_anndelta 1581 * sv102_licenses 1582 * sv102_userpath 1583 */ 1584 if (info102->sv102_name == NULL || 1585 info102->sv102_comment == NULL) 1586 goto netservergetinfo_no_memory; 1587 1588 param->result.bufptr.bufptr102 = info102; 1589 break; 1590 1591 case 502: 1592 info502 = NDR_NEW(mxa, struct mslm_SERVER_INFO_502); 1593 if (info502 == NULL) 1594 goto netservergetinfo_no_memory; 1595 1596 bzero(info502, sizeof (struct mslm_SERVER_INFO_502)); 1597 param->result.bufptr.bufptr502 = info502; 1598 #ifdef SRVSVC_SATISFY_SMBTORTURE 1599 break; 1600 #else 1601 param->result.level = param->level; 1602 param->status = ERROR_ACCESS_DENIED; 1603 return (NDR_DRC_OK); 1604 #endif /* SRVSVC_SATISFY_SMBTORTURE */ 1605 1606 case 503: 1607 info503 = NDR_NEW(mxa, struct mslm_SERVER_INFO_503); 1608 if (info503 == NULL) 1609 goto netservergetinfo_no_memory; 1610 1611 bzero(info503, sizeof (struct mslm_SERVER_INFO_503)); 1612 param->result.bufptr.bufptr503 = info503; 1613 #ifdef SRVSVC_SATISFY_SMBTORTURE 1614 break; 1615 #else 1616 param->result.level = param->level; 1617 param->status = ERROR_ACCESS_DENIED; 1618 return (NDR_DRC_OK); 1619 #endif /* SRVSVC_SATISFY_SMBTORTURE */ 1620 1621 default: 1622 bzero(¶m->result, 1623 sizeof (struct mslm_NetServerGetInfo_result)); 1624 param->status = ERROR_ACCESS_DENIED; 1625 return (NDR_DRC_OK); 1626 } 1627 1628 param->result.level = param->level; 1629 param->status = ERROR_SUCCESS; 1630 return (NDR_DRC_OK); 1631 } 1632 1633 /* 1634 * NetRemoteTOD 1635 * 1636 * Returns information about the time of day on this server. 1637 * 1638 * typedef struct _TIME_OF_DAY_INFO { 1639 * DWORD tod_elapsedt; // seconds since 00:00:00 January 1 1970 GMT 1640 * DWORD tod_msecs; // arbitrary milliseconds (since reset) 1641 * DWORD tod_hours; // current hour [0-23] 1642 * DWORD tod_mins; // current minute [0-59] 1643 * DWORD tod_secs; // current second [0-59] 1644 * DWORD tod_hunds; // current hundredth (0.01) second [0-99] 1645 * LONG tod_timezone; // time zone of the server 1646 * DWORD tod_tinterval; // clock tick time interval 1647 * DWORD tod_day; // day of the month [1-31] 1648 * DWORD tod_month; // month of the year [1-12] 1649 * DWORD tod_year; // current year 1650 * DWORD tod_weekday; // day of the week since Sunday [0-6] 1651 * } TIME_OF_DAY_INFO; 1652 * 1653 * The time zone of the server is calculated in minutes from Greenwich 1654 * Mean Time (GMT). For time zones west of Greenwich, the value is 1655 * positive; for time zones east of Greenwich, the value is negative. 1656 * A value of -1 indicates that the time zone is undefined. 1657 * 1658 * The clock tick value represents a resolution of one ten-thousandth 1659 * (0.0001) second. 1660 */ 1661 static int 1662 srvsvc_s_NetRemoteTOD(void *arg, ndr_xa_t *mxa) 1663 { 1664 struct mslm_NetRemoteTOD *param = arg; 1665 struct mslm_TIME_OF_DAY_INFO *tod; 1666 struct timeval time_val; 1667 struct tm tm; 1668 1669 (void) gettimeofday(&time_val, 0); 1670 (void) gmtime_r(&time_val.tv_sec, &tm); 1671 1672 tod = NDR_NEW(mxa, struct mslm_TIME_OF_DAY_INFO); 1673 if (tod == NULL) { 1674 bzero(param, sizeof (struct mslm_NetRemoteTOD)); 1675 return (ERROR_NOT_ENOUGH_MEMORY); 1676 } 1677 1678 tod->tod_elapsedt = time_val.tv_sec; 1679 tod->tod_msecs = time_val.tv_usec; 1680 tod->tod_hours = tm.tm_hour; 1681 tod->tod_mins = tm.tm_min; 1682 tod->tod_secs = tm.tm_sec; 1683 tod->tod_hunds = 0; 1684 tod->tod_tinterval = 1000; 1685 tod->tod_day = tm.tm_mday; 1686 tod->tod_month = tm.tm_mon+1; 1687 tod->tod_year = tm.tm_year+1900; 1688 tod->tod_weekday = tm.tm_wday; 1689 1690 (void) localtime_r(&time_val.tv_sec, &tm); 1691 1692 param->bufptr = tod; 1693 param->status = ERROR_SUCCESS; 1694 return (NDR_DRC_OK); 1695 } 1696 1697 /* 1698 * srvsvc_s_NetNameValidate 1699 * 1700 * Perform name validation. 1701 * 1702 * The share name is considered invalid if it contains any of the 1703 * following character (MSDN 236388). 1704 * 1705 * " / \ [ ] : | < > + ; , ? * = 1706 * 1707 * Returns Win32 error codes. 1708 */ 1709 /*ARGSUSED*/ 1710 static int 1711 srvsvc_s_NetNameValidate(void *arg, ndr_xa_t *mxa) 1712 { 1713 struct mslm_NetNameValidate *param = arg; 1714 char *name; 1715 int len; 1716 1717 if ((name = (char *)param->pathname) == NULL) { 1718 param->status = ERROR_INVALID_PARAMETER; 1719 return (NDR_DRC_OK); 1720 } 1721 1722 len = strlen(name); 1723 1724 if ((param->flags == 0 && len > 81) || 1725 (param->flags == 0x80000000 && len > 13)) { 1726 param->status = ERROR_INVALID_NAME; 1727 return (NDR_DRC_OK); 1728 } 1729 1730 switch (param->type) { 1731 case NAMETYPE_SHARE: 1732 if (smb_shr_chkname(name)) 1733 param->status = ERROR_SUCCESS; 1734 else 1735 param->status = ERROR_INVALID_NAME; 1736 break; 1737 1738 case NAMETYPE_USER: 1739 case NAMETYPE_PASSWORD: 1740 case NAMETYPE_GROUP: 1741 case NAMETYPE_COMPUTER: 1742 case NAMETYPE_EVENT: 1743 case NAMETYPE_DOMAIN: 1744 case NAMETYPE_SERVICE: 1745 case NAMETYPE_NET: 1746 case NAMETYPE_MESSAGE: 1747 case NAMETYPE_MESSAGEDEST: 1748 case NAMETYPE_SHAREPASSWORD: 1749 case NAMETYPE_WORKGROUP: 1750 param->status = ERROR_NOT_SUPPORTED; 1751 break; 1752 1753 default: 1754 param->status = ERROR_INVALID_PARAMETER; 1755 break; 1756 } 1757 1758 return (NDR_DRC_OK); 1759 } 1760 1761 /* 1762 * srvsvc_s_NetShareAdd 1763 * 1764 * Add a new share. Only power users groups can manage shares. 1765 * 1766 * This interface is used by the rmtshare command from the NT resource 1767 * kit. Rmtshare allows a client to add or remove shares on a server 1768 * from the client's command line. 1769 * 1770 * Returns Win32 error codes. 1771 */ 1772 static int 1773 srvsvc_s_NetShareAdd(void *arg, ndr_xa_t *mxa) 1774 { 1775 static DWORD parm_err = 0; 1776 DWORD parm_stat; 1777 struct mslm_NetShareAdd *param = arg; 1778 struct mslm_NetShareInfo_2 *info2; 1779 struct mslm_NetShareInfo_502 *info502; 1780 char realpath[MAXPATHLEN]; 1781 int32_t native_os; 1782 uint8_t *sdbuf = NULL; 1783 uint32_t status; 1784 smb_share_t si; 1785 1786 native_os = ndr_native_os(mxa); 1787 1788 if (!ndr_is_poweruser(mxa)) { 1789 bzero(param, sizeof (struct mslm_NetShareAdd)); 1790 param->status = ERROR_ACCESS_DENIED; 1791 return (NDR_DRC_OK); 1792 } 1793 1794 switch (param->level) { 1795 case 2: 1796 info2 = (struct mslm_NetShareInfo_2 *)param->info.un.info2; 1797 break; 1798 1799 case 502: 1800 info502 = (struct mslm_NetShareInfo_502 *) 1801 param->info.un.info502; 1802 sdbuf = info502->shi502_security_descriptor; 1803 info2 = (struct mslm_NetShareInfo_2 *)info502; 1804 break; 1805 1806 default: 1807 bzero(param, sizeof (struct mslm_NetShareAdd)); 1808 param->status = ERROR_ACCESS_DENIED; 1809 return (NDR_DRC_OK); 1810 } 1811 1812 if (info2->shi2_netname == NULL || info2->shi2_path == NULL) { 1813 bzero(param, sizeof (struct mslm_NetShareAdd)); 1814 param->status = NERR_NetNameNotFound; 1815 return (NDR_DRC_OK); 1816 } 1817 1818 if (smb_shr_is_restricted((char *)info2->shi2_netname)) { 1819 bzero(param, sizeof (struct mslm_NetShareAdd)); 1820 param->status = ERROR_ACCESS_DENIED; 1821 return (NDR_DRC_OK); 1822 } 1823 1824 if (info2->shi2_comment == NULL) 1825 info2->shi2_comment = (uint8_t *)""; 1826 1827 /* 1828 * Derive the real path which will be stored in the 1829 * directory field of the smb_share_t structure 1830 * from the path field in this RPC request. 1831 */ 1832 parm_stat = smb_shr_get_realpath((const char *)info2->shi2_path, 1833 realpath, MAXPATHLEN); 1834 1835 if (parm_stat != NERR_Success) { 1836 bzero(param, sizeof (struct mslm_NetShareAdd)); 1837 param->status = parm_stat; 1838 param->parm_err 1839 = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err; 1840 return (NDR_DRC_OK); 1841 } 1842 1843 param->status = srvsvc_sa_add((char *)info2->shi2_netname, realpath, 1844 (char *)info2->shi2_comment); 1845 if (param->status == NERR_Success) { 1846 status = smb_shr_get((char *)info2->shi2_netname, &si); 1847 1848 if ((sdbuf != NULL) && (status == NERR_Success)) 1849 (void) srvsvc_sd_set(&si, sdbuf); 1850 } 1851 param->parm_err = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err; 1852 return (NDR_DRC_OK); 1853 } 1854 1855 /* 1856 * srvsvc_estimate_objcnt 1857 * 1858 * Estimate the number of objects that will fit in prefmaxlen. 1859 */ 1860 static uint32_t 1861 srvsvc_estimate_objcnt(uint32_t prefmaxlen, uint32_t n_obj, uint32_t obj_size) 1862 { 1863 DWORD max_cnt; 1864 1865 if (obj_size == 0) 1866 return (0); 1867 1868 if ((max_cnt = (prefmaxlen / obj_size)) == 0) 1869 return (0); 1870 1871 if (n_obj > max_cnt) 1872 n_obj = max_cnt; 1873 1874 return (n_obj); 1875 } 1876 1877 /* 1878 * srvsvc_s_NetShareEnum 1879 * 1880 * Enumerate all shares (see also NetShareEnumSticky). 1881 * 1882 * Request for various levels of information about our shares. 1883 * Level 0: share names. 1884 * Level 1: share name, share type and comment field. 1885 * Level 2: everything that we know about the shares. 1886 * Level 501: level 1 + flags (flags must be zero). 1887 * Level 502: level 2 + security descriptor. 1888 */ 1889 static int 1890 srvsvc_s_NetShareEnum(void *arg, ndr_xa_t *mxa) 1891 { 1892 struct mslm_NetShareEnum *param = arg; 1893 struct mslm_infonres *infonres; 1894 srvsvc_enum_t se; 1895 DWORD status; 1896 1897 infonres = NDR_NEW(mxa, struct mslm_infonres); 1898 if (infonres == NULL) { 1899 bzero(param, sizeof (struct mslm_NetShareEnum)); 1900 param->status = ERROR_NOT_ENOUGH_MEMORY; 1901 return (NDR_DRC_OK); 1902 } 1903 1904 infonres->entriesread = 0; 1905 infonres->entries = NULL; 1906 param->result.level = param->level; 1907 param->result.bufptr.p = infonres; 1908 1909 bzero(&se, sizeof (srvsvc_enum_t)); 1910 se.se_level = param->level; 1911 se.se_n_total = smb_shr_count(); 1912 1913 if (param->prefmaxlen == SMB_SRVSVC_MAXPREFLEN || 1914 param->prefmaxlen > SMB_SRVSVC_MAXBUFLEN) 1915 se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN; 1916 else 1917 se.se_prefmaxlen = param->prefmaxlen; 1918 1919 if (param->resume_handle) { 1920 se.se_resume_handle = *param->resume_handle; 1921 se.se_n_skip = se.se_resume_handle; 1922 } 1923 1924 switch (param->level) { 1925 case 0: 1926 status = mlsvc_NetShareEnumLevel0(mxa, infonres, &se, 0); 1927 break; 1928 1929 case 1: 1930 status = mlsvc_NetShareEnumLevel1(mxa, infonres, &se, 0); 1931 break; 1932 1933 case 2: 1934 status = mlsvc_NetShareEnumLevel2(mxa, infonres, &se, 0); 1935 break; 1936 1937 case 501: 1938 status = mlsvc_NetShareEnumLevel501(mxa, infonres, &se, 0); 1939 break; 1940 1941 case 502: 1942 status = mlsvc_NetShareEnumLevel502(mxa, infonres, &se, 0); 1943 break; 1944 1945 default: 1946 status = ERROR_INVALID_LEVEL; 1947 break; 1948 } 1949 1950 if (status != 0) { 1951 bzero(param, sizeof (struct mslm_NetShareEnum)); 1952 param->status = status; 1953 return (NDR_DRC_OK); 1954 } 1955 1956 if (se.se_n_enum == 0) { 1957 if (param->resume_handle) 1958 *param->resume_handle = 0; 1959 param->status = ERROR_SUCCESS; 1960 return (NDR_DRC_OK); 1961 } 1962 1963 if (param->resume_handle && 1964 param->prefmaxlen != SMB_SRVSVC_MAXPREFLEN) { 1965 if (se.se_resume_handle < se.se_n_total) { 1966 *param->resume_handle = se.se_resume_handle; 1967 status = ERROR_MORE_DATA; 1968 } else { 1969 *param->resume_handle = 0; 1970 } 1971 } 1972 1973 param->totalentries = se.se_n_total; 1974 param->status = status; 1975 return (NDR_DRC_OK); 1976 } 1977 1978 /* 1979 * srvsvc_s_NetShareEnumSticky 1980 * 1981 * Enumerate sticky shares: all shares except those marked STYPE_SPECIAL. 1982 * Except for excluding STYPE_SPECIAL shares, NetShareEnumSticky is the 1983 * same as NetShareEnum. 1984 * 1985 * Request for various levels of information about our shares. 1986 * Level 0: share names. 1987 * Level 1: share name, share type and comment field. 1988 * Level 2: everything that we know about the shares. 1989 * Level 501: not valid for this request. 1990 * Level 502: level 2 + security descriptor. 1991 * 1992 * We set n_skip to resume_handle, which is used to find the appropriate 1993 * place to resume. The resume_handle is similar to the readdir cookie. 1994 */ 1995 static int 1996 srvsvc_s_NetShareEnumSticky(void *arg, ndr_xa_t *mxa) 1997 { 1998 struct mslm_NetShareEnum *param = arg; 1999 struct mslm_infonres *infonres; 2000 srvsvc_enum_t se; 2001 DWORD status; 2002 2003 infonres = NDR_NEW(mxa, struct mslm_infonres); 2004 if (infonres == NULL) { 2005 bzero(param, sizeof (struct mslm_NetShareEnum)); 2006 param->status = ERROR_NOT_ENOUGH_MEMORY; 2007 return (NDR_DRC_OK); 2008 } 2009 2010 infonres->entriesread = 0; 2011 infonres->entries = NULL; 2012 param->result.level = param->level; 2013 param->result.bufptr.p = infonres; 2014 2015 bzero(&se, sizeof (srvsvc_enum_t)); 2016 se.se_level = param->level; 2017 se.se_n_total = smb_shr_count(); 2018 2019 if (param->prefmaxlen == SMB_SRVSVC_MAXPREFLEN || 2020 param->prefmaxlen > SMB_SRVSVC_MAXBUFLEN) 2021 se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN; 2022 else 2023 se.se_prefmaxlen = param->prefmaxlen; 2024 2025 if (param->resume_handle) { 2026 se.se_resume_handle = *param->resume_handle; 2027 se.se_n_skip = se.se_resume_handle; 2028 } 2029 2030 switch (param->level) { 2031 case 0: 2032 status = mlsvc_NetShareEnumLevel0(mxa, infonres, &se, 1); 2033 break; 2034 2035 case 1: 2036 status = mlsvc_NetShareEnumLevel1(mxa, infonres, &se, 1); 2037 break; 2038 2039 case 2: 2040 status = mlsvc_NetShareEnumLevel2(mxa, infonres, &se, 1); 2041 break; 2042 2043 case 502: 2044 status = mlsvc_NetShareEnumLevel502(mxa, infonres, &se, 1); 2045 break; 2046 2047 case 501: 2048 default: 2049 status = ERROR_INVALID_LEVEL; 2050 break; 2051 } 2052 2053 if (status != ERROR_SUCCESS) { 2054 bzero(param, sizeof (struct mslm_NetShareEnum)); 2055 param->status = status; 2056 return (NDR_DRC_OK); 2057 } 2058 2059 if (se.se_n_enum == 0) { 2060 if (param->resume_handle) 2061 *param->resume_handle = 0; 2062 param->status = ERROR_SUCCESS; 2063 return (NDR_DRC_OK); 2064 } 2065 2066 if (param->resume_handle && 2067 param->prefmaxlen != SMB_SRVSVC_MAXPREFLEN) { 2068 if (se.se_resume_handle < se.se_n_total) { 2069 *param->resume_handle = se.se_resume_handle; 2070 status = ERROR_MORE_DATA; 2071 } else { 2072 *param->resume_handle = 0; 2073 } 2074 } 2075 2076 param->totalentries = se.se_n_total; 2077 param->status = status; 2078 return (NDR_DRC_OK); 2079 } 2080 2081 /* 2082 * NetShareEnum Level 0 2083 */ 2084 static DWORD 2085 mlsvc_NetShareEnumLevel0(ndr_xa_t *mxa, 2086 struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky) 2087 { 2088 struct mslm_NetShareInfo_0 *info0; 2089 smb_shriter_t iterator; 2090 smb_share_t *si; 2091 DWORD status; 2092 2093 se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen, 2094 se->se_n_total, sizeof (struct mslm_NetShareInfo_0) + MAXNAMELEN); 2095 if (se->se_n_enum == 0) 2096 return (ERROR_SUCCESS); 2097 2098 info0 = NDR_NEWN(mxa, struct mslm_NetShareInfo_0, se->se_n_enum); 2099 if (info0 == NULL) 2100 return (ERROR_NOT_ENOUGH_MEMORY); 2101 2102 smb_shr_iterinit(&iterator); 2103 2104 se->se_n_read = 0; 2105 while ((si = smb_shr_iterate(&iterator)) != NULL) { 2106 if (se->se_n_skip > 0) { 2107 --se->se_n_skip; 2108 continue; 2109 } 2110 2111 ++se->se_resume_handle; 2112 2113 if (sticky && (si->shr_flags & SMB_SHRF_TRANS)) 2114 continue; 2115 2116 if (si->shr_flags & SMB_SHRF_AUTOHOME) 2117 continue; 2118 2119 if (se->se_n_read >= se->se_n_enum) { 2120 se->se_n_read = se->se_n_enum; 2121 break; 2122 } 2123 2124 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info0); 2125 if (status != ERROR_SUCCESS) 2126 break; 2127 2128 ++se->se_n_read; 2129 } 2130 2131 if (se->se_n_read < se->se_n_enum) { 2132 if (srvsvc_add_autohome(mxa, se, (void *)info0)) 2133 ++se->se_n_read; 2134 } 2135 2136 infonres->entriesread = se->se_n_read; 2137 infonres->entries = info0; 2138 return (ERROR_SUCCESS); 2139 } 2140 2141 /* 2142 * NetShareEnum Level 1 2143 */ 2144 static DWORD 2145 mlsvc_NetShareEnumLevel1(ndr_xa_t *mxa, 2146 struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky) 2147 { 2148 struct mslm_NetShareInfo_1 *info1; 2149 smb_shriter_t iterator; 2150 smb_share_t *si; 2151 DWORD status; 2152 2153 se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen, 2154 se->se_n_total, sizeof (struct mslm_NetShareInfo_1) + MAXNAMELEN); 2155 if (se->se_n_enum == 0) 2156 return (ERROR_SUCCESS); 2157 2158 info1 = NDR_NEWN(mxa, struct mslm_NetShareInfo_1, se->se_n_enum); 2159 if (info1 == NULL) 2160 return (ERROR_NOT_ENOUGH_MEMORY); 2161 2162 smb_shr_iterinit(&iterator); 2163 2164 se->se_n_read = 0; 2165 while ((si = smb_shr_iterate(&iterator)) != 0) { 2166 if (se->se_n_skip > 0) { 2167 --se->se_n_skip; 2168 continue; 2169 } 2170 2171 ++se->se_resume_handle; 2172 2173 if (sticky && (si->shr_flags & SMB_SHRF_TRANS)) 2174 continue; 2175 2176 if (si->shr_flags & SMB_SHRF_AUTOHOME) 2177 continue; 2178 2179 if (se->se_n_read >= se->se_n_enum) { 2180 se->se_n_read = se->se_n_enum; 2181 break; 2182 } 2183 2184 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info1); 2185 if (status != ERROR_SUCCESS) 2186 break; 2187 2188 ++se->se_n_read; 2189 } 2190 2191 if (se->se_n_read < se->se_n_enum) { 2192 if (srvsvc_add_autohome(mxa, se, (void *)info1)) 2193 ++se->se_n_read; 2194 } 2195 2196 infonres->entriesread = se->se_n_read; 2197 infonres->entries = info1; 2198 return (ERROR_SUCCESS); 2199 } 2200 2201 /* 2202 * NetShareEnum Level 2 2203 */ 2204 static DWORD 2205 mlsvc_NetShareEnumLevel2(ndr_xa_t *mxa, 2206 struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky) 2207 { 2208 struct mslm_NetShareInfo_2 *info2; 2209 smb_shriter_t iterator; 2210 smb_share_t *si; 2211 DWORD status; 2212 2213 se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen, 2214 se->se_n_total, sizeof (struct mslm_NetShareInfo_2) + MAXNAMELEN); 2215 if (se->se_n_enum == 0) 2216 return (ERROR_SUCCESS); 2217 2218 info2 = NDR_NEWN(mxa, struct mslm_NetShareInfo_2, se->se_n_enum); 2219 if (info2 == NULL) 2220 return (ERROR_NOT_ENOUGH_MEMORY); 2221 2222 smb_shr_iterinit(&iterator); 2223 2224 se->se_n_read = 0; 2225 while ((si = smb_shr_iterate(&iterator)) != 0) { 2226 if (se->se_n_skip > 0) { 2227 --se->se_n_skip; 2228 continue; 2229 } 2230 2231 ++se->se_resume_handle; 2232 2233 if (sticky && (si->shr_flags & SMB_SHRF_TRANS)) 2234 continue; 2235 2236 if (si->shr_flags & SMB_SHRF_AUTOHOME) 2237 continue; 2238 2239 if (se->se_n_read >= se->se_n_enum) { 2240 se->se_n_read = se->se_n_enum; 2241 break; 2242 } 2243 2244 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info2); 2245 if (status != ERROR_SUCCESS) 2246 break; 2247 2248 ++se->se_n_read; 2249 } 2250 2251 if (se->se_n_read < se->se_n_enum) { 2252 if (srvsvc_add_autohome(mxa, se, (void *)info2)) 2253 ++se->se_n_read; 2254 } 2255 2256 infonres->entriesread = se->se_n_read; 2257 infonres->entries = info2; 2258 return (ERROR_SUCCESS); 2259 } 2260 2261 /* 2262 * NetShareEnum Level 501 2263 */ 2264 static DWORD 2265 mlsvc_NetShareEnumLevel501(ndr_xa_t *mxa, 2266 struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky) 2267 { 2268 struct mslm_NetShareInfo_501 *info501; 2269 smb_shriter_t iterator; 2270 smb_share_t *si; 2271 DWORD status; 2272 2273 se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen, 2274 se->se_n_total, sizeof (struct mslm_NetShareInfo_501) + MAXNAMELEN); 2275 if (se->se_n_enum == 0) 2276 return (ERROR_SUCCESS); 2277 2278 info501 = NDR_NEWN(mxa, struct mslm_NetShareInfo_501, 2279 se->se_n_enum); 2280 if (info501 == NULL) 2281 return (ERROR_NOT_ENOUGH_MEMORY); 2282 2283 smb_shr_iterinit(&iterator); 2284 2285 se->se_n_read = 0; 2286 while ((si = smb_shr_iterate(&iterator)) != 0) { 2287 if (se->se_n_skip > 0) { 2288 --se->se_n_skip; 2289 continue; 2290 } 2291 2292 ++se->se_resume_handle; 2293 2294 if (sticky && (si->shr_flags & SMB_SHRF_TRANS)) 2295 continue; 2296 2297 if (si->shr_flags & SMB_SHRF_AUTOHOME) 2298 continue; 2299 2300 if (se->se_n_read >= se->se_n_enum) { 2301 se->se_n_read = se->se_n_enum; 2302 break; 2303 } 2304 2305 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info501); 2306 if (status != ERROR_SUCCESS) 2307 break; 2308 2309 ++se->se_n_read; 2310 } 2311 2312 if (se->se_n_read < se->se_n_enum) { 2313 if (srvsvc_add_autohome(mxa, se, (void *)info501)) 2314 ++se->se_n_read; 2315 } 2316 2317 infonres->entriesread = se->se_n_read; 2318 infonres->entries = info501; 2319 return (ERROR_SUCCESS); 2320 } 2321 2322 /* 2323 * NetShareEnum Level 502 2324 */ 2325 static DWORD 2326 mlsvc_NetShareEnumLevel502(ndr_xa_t *mxa, 2327 struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky) 2328 { 2329 struct mslm_NetShareInfo_502 *info502; 2330 smb_shriter_t iterator; 2331 smb_share_t *si; 2332 DWORD status; 2333 2334 se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen, 2335 se->se_n_total, sizeof (struct mslm_NetShareInfo_502) + MAXNAMELEN); 2336 if (se->se_n_enum == 0) 2337 return (ERROR_SUCCESS); 2338 2339 info502 = NDR_NEWN(mxa, struct mslm_NetShareInfo_502, 2340 se->se_n_enum); 2341 if (info502 == NULL) 2342 return (ERROR_NOT_ENOUGH_MEMORY); 2343 2344 smb_shr_iterinit(&iterator); 2345 2346 se->se_n_read = 0; 2347 while ((si = smb_shr_iterate(&iterator)) != NULL) { 2348 if (se->se_n_skip > 0) { 2349 --se->se_n_skip; 2350 continue; 2351 } 2352 2353 ++se->se_resume_handle; 2354 2355 if (sticky && (si->shr_flags & SMB_SHRF_TRANS)) 2356 continue; 2357 2358 if (si->shr_flags & SMB_SHRF_AUTOHOME) 2359 continue; 2360 2361 if (se->se_n_read >= se->se_n_enum) { 2362 se->se_n_read = se->se_n_enum; 2363 break; 2364 } 2365 2366 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info502); 2367 if (status != ERROR_SUCCESS) 2368 break; 2369 2370 ++se->se_n_read; 2371 } 2372 2373 if (se->se_n_read < se->se_n_enum) { 2374 if (srvsvc_add_autohome(mxa, se, (void *)info502)) 2375 ++se->se_n_read; 2376 } 2377 2378 infonres->entriesread = se->se_n_read; 2379 infonres->entries = info502; 2380 return (ERROR_SUCCESS); 2381 } 2382 2383 /* 2384 * mlsvc_NetShareEnumCommon 2385 * 2386 * Build the levels 0, 1, 2, 501 and 502 share information. This function 2387 * is called by the various NetShareEnum levels for each share. If 2388 * we cannot build the share data for some reason, we return an error 2389 * but the actual value of the error is not important to the caller. 2390 * The caller just needs to know not to include this info in the RPC 2391 * response. 2392 * 2393 * Returns: 2394 * ERROR_SUCCESS 2395 * ERROR_NOT_ENOUGH_MEMORY 2396 * ERROR_INVALID_LEVEL 2397 */ 2398 static DWORD 2399 mlsvc_NetShareEnumCommon(ndr_xa_t *mxa, srvsvc_enum_t *se, 2400 smb_share_t *si, void *infop) 2401 { 2402 struct mslm_NetShareInfo_0 *info0; 2403 struct mslm_NetShareInfo_1 *info1; 2404 struct mslm_NetShareInfo_2 *info2; 2405 struct mslm_NetShareInfo_501 *info501; 2406 struct mslm_NetShareInfo_502 *info502; 2407 srvsvc_sd_t sd; 2408 uint8_t *netname; 2409 uint8_t *comment; 2410 uint8_t *passwd; 2411 uint8_t *path; 2412 int i = se->se_n_read; 2413 2414 netname = (uint8_t *)NDR_STRDUP(mxa, si->shr_name); 2415 comment = (uint8_t *)NDR_STRDUP(mxa, si->shr_cmnt); 2416 passwd = (uint8_t *)NDR_STRDUP(mxa, empty_string); 2417 path = (uint8_t *)srvsvc_share_mkpath(mxa, si->shr_path); 2418 2419 if (!netname || !comment || !passwd || !path) 2420 return (ERROR_NOT_ENOUGH_MEMORY); 2421 2422 switch (se->se_level) { 2423 case 0: 2424 info0 = (struct mslm_NetShareInfo_0 *)infop; 2425 info0[i].shi0_netname = netname; 2426 break; 2427 2428 case 1: 2429 info1 = (struct mslm_NetShareInfo_1 *)infop; 2430 info1[i].shi1_netname = netname; 2431 info1[i].shi1_comment = comment; 2432 info1[i].shi1_type = si->shr_type; 2433 break; 2434 2435 case 2: 2436 info2 = (struct mslm_NetShareInfo_2 *)infop; 2437 info2[i].shi2_netname = netname; 2438 info2[i].shi2_comment = comment; 2439 info2[i].shi2_path = path; 2440 info2[i].shi2_type = si->shr_type; 2441 info2[i].shi2_permissions = 0; 2442 info2[i].shi2_max_uses = SHI_USES_UNLIMITED; 2443 info2[i].shi2_current_uses = 0; 2444 info2[i].shi2_passwd = passwd; 2445 break; 2446 2447 case 501: 2448 info501 = (struct mslm_NetShareInfo_501 *)infop; 2449 info501[i].shi501_netname = netname; 2450 info501[i].shi501_comment = comment; 2451 info501[i].shi501_type = si->shr_type; 2452 info501[i].shi501_reserved = 0; 2453 break; 2454 2455 case 502: 2456 info502 = (struct mslm_NetShareInfo_502 *)infop; 2457 info502[i].shi502_netname = netname; 2458 info502[i].shi502_comment = comment; 2459 info502[i].shi502_path = path; 2460 info502[i].shi502_type = si->shr_type; 2461 info502[i].shi502_permissions = 0; 2462 info502[i].shi502_max_uses = SHI_USES_UNLIMITED; 2463 info502[i].shi502_current_uses = 0; 2464 info502[i].shi502_passwd = passwd; 2465 2466 if (srvsvc_share_getsd(mxa, si, &sd) == ERROR_SUCCESS) { 2467 info502[i].shi502_reserved = sd.sd_size; 2468 info502[i].shi502_security_descriptor = sd.sd_buf; 2469 } else { 2470 info502[i].shi502_reserved = 0; 2471 info502[i].shi502_security_descriptor = NULL; 2472 } 2473 2474 break; 2475 2476 default: 2477 return (ERROR_INVALID_LEVEL); 2478 } 2479 2480 return (ERROR_SUCCESS); 2481 } 2482 2483 /* 2484 * srvsvc_add_autohome 2485 * 2486 * Add the autohome share for the user. The share must not be a permanent 2487 * share to avoid duplicates. 2488 */ 2489 static boolean_t 2490 srvsvc_add_autohome(ndr_xa_t *mxa, srvsvc_enum_t *se, void *infop) 2491 { 2492 smb_opipe_context_t *ctx = &mxa->pipe->np_ctx; 2493 char *username = ctx->oc_account; 2494 smb_share_t si; 2495 DWORD status; 2496 2497 if (smb_shr_get(username, &si) != NERR_Success) 2498 return (B_FALSE); 2499 2500 if ((si.shr_flags & SMB_SHRF_AUTOHOME) == 0) 2501 return (B_FALSE); 2502 2503 status = mlsvc_NetShareEnumCommon(mxa, se, &si, infop); 2504 return (status == ERROR_SUCCESS); 2505 } 2506 2507 /* 2508 * srvsvc_share_mkpath 2509 * 2510 * Create the share path required by the share enum calls. The path 2511 * is created in a heap buffer ready for use by the caller. 2512 * 2513 * Some Windows over-the-wire backup applications do not work unless a 2514 * drive letter is present in the share path. We don't care about the 2515 * drive letter since the path is fully qualified with the volume name. 2516 * 2517 * Windows clients seem to be mostly okay with forward slashes in 2518 * share paths but they cannot handle one immediately after the drive 2519 * letter, i.e. B:/. For consistency we convert all the slashes in 2520 * the path. 2521 * 2522 * Returns a pointer to a heap buffer containing the share path, which 2523 * could be a null pointer if the heap allocation fails. 2524 */ 2525 static char * 2526 srvsvc_share_mkpath(ndr_xa_t *mxa, char *path) 2527 { 2528 char tmpbuf[MAXPATHLEN]; 2529 char *p; 2530 2531 if (strlen(path) == 0) 2532 return (NDR_STRDUP(mxa, path)); 2533 2534 /* 2535 * Strip the volume name from the path (/vol1/home -> /home). 2536 */ 2537 p = path; 2538 p += strspn(p, "/"); 2539 p += strcspn(p, "/"); 2540 p += strspn(p, "/"); 2541 (void) snprintf(tmpbuf, MAXPATHLEN, "%c:/%s", 'B', p); 2542 (void) strsubst(tmpbuf, '/', '\\'); 2543 2544 return (NDR_STRDUP(mxa, tmpbuf)); 2545 } 2546 2547 static int 2548 srvsvc_s_NetShareCheck(void *arg, ndr_xa_t *mxa) 2549 { 2550 struct mslm_NetShareCheck *param = arg; 2551 smb_shriter_t iterator; 2552 smb_share_t *si; 2553 char *path; 2554 2555 if (param->path == NULL) { 2556 param->stype = STYPE_DISKTREE; 2557 param->status = NERR_NetNameNotFound; 2558 return (NDR_DRC_OK); 2559 } 2560 2561 (void) strsubst((char *)param->path, '/', '\\'); 2562 2563 smb_shr_iterinit(&iterator); 2564 2565 while ((si = smb_shr_iterate(&iterator)) != NULL) { 2566 path = srvsvc_share_mkpath(mxa, si->shr_path); 2567 2568 if (utf8_strcasecmp(path, (char *)param->path) == 0) { 2569 param->stype = (si->shr_type & STYPE_MASK); 2570 param->status = NERR_Success; 2571 return (NDR_DRC_OK); 2572 } 2573 } 2574 2575 param->stype = STYPE_DISKTREE; 2576 param->status = NERR_NetNameNotFound; 2577 return (NDR_DRC_OK); 2578 } 2579 2580 /* 2581 * srvsvc_s_NetShareDel 2582 * 2583 * Delete a share. Only the administrator, or a member of the domain 2584 * administrators group, is allowed to delete shares. 2585 * 2586 * This interface is used by the rmtshare command from the NT resource 2587 * kit. Rmtshare allows a client to add or remove shares on a server 2588 * from the client's command line. 2589 * 2590 * Returns Win32 error codes. 2591 */ 2592 static int 2593 srvsvc_s_NetShareDel(void *arg, ndr_xa_t *mxa) 2594 { 2595 struct mslm_NetShareDel *param = arg; 2596 2597 if (!ndr_is_poweruser(mxa) || 2598 smb_shr_is_restricted((char *)param->netname)) { 2599 param->status = ERROR_ACCESS_DENIED; 2600 return (NDR_DRC_OK); 2601 } 2602 2603 param->status = srvsvc_sa_delete((char *)param->netname); 2604 return (NDR_DRC_OK); 2605 } 2606 2607 /* 2608 * srvsvc_s_NetGetFileSecurity 2609 * 2610 * Get security descriptor of the requested file/folder 2611 * 2612 * Right now, just returns ERROR_ACCESS_DENIED, because we cannot 2613 * get the requested SD here in RPC code. 2614 */ 2615 /*ARGSUSED*/ 2616 static int 2617 srvsvc_s_NetGetFileSecurity(void *arg, ndr_xa_t *mxa) 2618 { 2619 struct mslm_NetGetFileSecurity *param = arg; 2620 2621 param->length = 0; 2622 param->status = ERROR_ACCESS_DENIED; 2623 return (NDR_DRC_OK); 2624 } 2625 2626 /* 2627 * srvsvc_s_NetSetFileSecurity 2628 * 2629 * Set the given security descriptor for the requested file/folder 2630 * 2631 * Right now, just returns ERROR_ACCESS_DENIED, because we cannot 2632 * set the requested SD here in RPC code. 2633 */ 2634 /*ARGSUSED*/ 2635 static int 2636 srvsvc_s_NetSetFileSecurity(void *arg, ndr_xa_t *mxa) 2637 { 2638 struct mslm_NetSetFileSecurity *param = arg; 2639 2640 param->status = ERROR_ACCESS_DENIED; 2641 return (NDR_DRC_OK); 2642 } 2643 2644 /* 2645 * If the default "smb" share group exists then return the group 2646 * handle, otherwise create the group and return the handle. 2647 * 2648 * All shares created via the srvsvc will be added to the "smb" 2649 * group. 2650 */ 2651 static sa_group_t 2652 srvsvc_sa_get_smbgrp(sa_handle_t handle) 2653 { 2654 sa_group_t group = NULL; 2655 int err; 2656 2657 group = sa_get_group(handle, SMB_DEFAULT_SHARE_GROUP); 2658 if (group != NULL) 2659 return (group); 2660 2661 group = sa_create_group(handle, SMB_DEFAULT_SHARE_GROUP, &err); 2662 if (group == NULL) 2663 return (NULL); 2664 2665 if (sa_create_optionset(group, SMB_DEFAULT_SHARE_GROUP) == NULL) { 2666 (void) sa_remove_group(group); 2667 group = NULL; 2668 } 2669 2670 return (group); 2671 } 2672 2673 /* 2674 * Stores the given share in sharemgr 2675 */ 2676 static uint32_t 2677 srvsvc_sa_add(char *sharename, char *path, char *cmnt) 2678 { 2679 sa_handle_t handle; 2680 sa_share_t share; 2681 sa_group_t group; 2682 sa_resource_t resource; 2683 boolean_t new_share = B_FALSE; 2684 uint32_t status = NERR_Success; 2685 int err; 2686 2687 if ((handle = smb_shr_sa_enter()) == NULL) 2688 return (NERR_InternalError); 2689 2690 share = sa_find_share(handle, path); 2691 if (share == NULL) { 2692 group = srvsvc_sa_get_smbgrp(handle); 2693 if (group == NULL) { 2694 smb_shr_sa_exit(); 2695 return (NERR_InternalError); 2696 } 2697 2698 share = sa_add_share(group, path, SA_SHARE_PERMANENT, &err); 2699 if (share == NULL) { 2700 smb_shr_sa_exit(); 2701 return (NERR_InternalError); 2702 } 2703 new_share = B_TRUE; 2704 } 2705 2706 resource = sa_get_share_resource(share, sharename); 2707 if (resource == NULL) { 2708 resource = sa_add_resource(share, sharename, 2709 SA_SHARE_PERMANENT, &err); 2710 if (resource == NULL) { 2711 if (new_share) 2712 (void) sa_remove_share(share); 2713 smb_shr_sa_exit(); 2714 return (NERR_InternalError); 2715 } 2716 } 2717 2718 (void) sa_set_resource_description(resource, cmnt); 2719 2720 smb_shr_sa_exit(); 2721 return (status); 2722 } 2723 2724 /* 2725 * Removes the share from sharemgr 2726 */ 2727 static uint32_t 2728 srvsvc_sa_delete(char *sharename) 2729 { 2730 sa_handle_t handle; 2731 sa_resource_t resource; 2732 uint32_t status; 2733 2734 if ((handle = smb_shr_sa_enter()) == NULL) 2735 return (NERR_InternalError); 2736 2737 status = NERR_InternalError; 2738 if ((resource = sa_find_resource(handle, sharename)) != NULL) { 2739 if (sa_remove_resource(resource) == SA_OK) 2740 status = NERR_Success; 2741 } 2742 2743 smb_shr_sa_exit(); 2744 return (status); 2745 } 2746 2747 /* 2748 * Update the share information. 2749 */ 2750 static uint32_t 2751 srvsvc_sa_modify(smb_share_t *si, srvsvc_netshare_setinfo_t *info) 2752 { 2753 sa_handle_t handle; 2754 sa_share_t share; 2755 sa_resource_t resource; 2756 boolean_t renamed = B_FALSE; 2757 uint32_t nerr = NERR_Success; 2758 2759 if ((handle = smb_shr_sa_enter()) == NULL) 2760 return (NERR_InternalError); 2761 2762 if ((share = sa_find_share(handle, si->shr_path)) == NULL) { 2763 smb_shr_sa_exit(); 2764 return (NERR_InternalError); 2765 } 2766 2767 if ((resource = sa_get_share_resource(share, si->shr_name)) == NULL) { 2768 smb_shr_sa_exit(); 2769 return (NERR_InternalError); 2770 } 2771 2772 if (info->nss_netname != NULL && info->nss_netname[0] != '\0' && 2773 utf8_strcasecmp(info->nss_netname, si->shr_name) != 0) { 2774 (void) sa_set_resource_attr(resource, SHOPT_NAME, 2775 info->nss_netname); 2776 renamed = B_TRUE; 2777 } 2778 2779 if ((info->nss_comment != NULL) && 2780 (strcmp(info->nss_comment, si->shr_cmnt) != 0)) { 2781 (void) sa_set_resource_description(resource, info->nss_comment); 2782 (void) strlcpy(si->shr_cmnt, info->nss_comment, 2783 SMB_SHARE_CMNT_MAX); 2784 } 2785 2786 smb_shr_sa_exit(); 2787 2788 if (renamed) { 2789 nerr = smb_shr_rename(si->shr_name, info->nss_netname); 2790 if (nerr != NERR_Success) 2791 return (nerr); 2792 2793 (void) strlcpy(si->shr_name, info->nss_netname, MAXNAMELEN); 2794 } 2795 2796 return (nerr); 2797 } 2798 2799 /* 2800 * Update the share flags. 2801 */ 2802 static uint32_t 2803 srvsvc_sa_setattr(smb_share_t *si) 2804 { 2805 sa_handle_t handle; 2806 sa_share_t share; 2807 sa_resource_t resource; 2808 char *value; 2809 2810 if ((handle = smb_shr_sa_enter()) == NULL) 2811 return (NERR_InternalError); 2812 2813 if ((share = sa_find_share(handle, si->shr_path)) == NULL) { 2814 smb_shr_sa_exit(); 2815 return (NERR_InternalError); 2816 } 2817 2818 if ((resource = sa_get_share_resource(share, si->shr_name)) == NULL) { 2819 smb_shr_sa_exit(); 2820 return (NERR_InternalError); 2821 } 2822 2823 if ((value = smb_shr_sa_csc_name(si)) == NULL) { 2824 smb_shr_sa_exit(); 2825 return (NERR_InternalError); 2826 } 2827 2828 (void) sa_set_resource_attr(resource, SHOPT_CSC, value); 2829 smb_shr_sa_exit(); 2830 return (NERR_Success); 2831 } 2832 2833 static ndr_stub_table_t srvsvc_stub_table[] = { 2834 { srvsvc_s_NetConnectEnum, SRVSVC_OPNUM_NetConnectEnum }, 2835 { srvsvc_s_NetFileEnum, SRVSVC_OPNUM_NetFileEnum }, 2836 { srvsvc_s_NetFileClose, SRVSVC_OPNUM_NetFileClose }, 2837 { srvsvc_s_NetShareGetInfo, SRVSVC_OPNUM_NetShareGetInfo }, 2838 { srvsvc_s_NetShareSetInfo, SRVSVC_OPNUM_NetShareSetInfo }, 2839 { srvsvc_s_NetSessionEnum, SRVSVC_OPNUM_NetSessionEnum }, 2840 { srvsvc_s_NetSessionDel, SRVSVC_OPNUM_NetSessionDel }, 2841 { srvsvc_s_NetServerGetInfo, SRVSVC_OPNUM_NetServerGetInfo }, 2842 { srvsvc_s_NetRemoteTOD, SRVSVC_OPNUM_NetRemoteTOD }, 2843 { srvsvc_s_NetNameValidate, SRVSVC_OPNUM_NetNameValidate }, 2844 { srvsvc_s_NetShareAdd, SRVSVC_OPNUM_NetShareAdd }, 2845 { srvsvc_s_NetShareDel, SRVSVC_OPNUM_NetShareDel }, 2846 { srvsvc_s_NetShareEnum, SRVSVC_OPNUM_NetShareEnum }, 2847 { srvsvc_s_NetShareEnumSticky, SRVSVC_OPNUM_NetShareEnumSticky }, 2848 { srvsvc_s_NetShareCheck, SRVSVC_OPNUM_NetShareCheck }, 2849 { srvsvc_s_NetGetFileSecurity, SRVSVC_OPNUM_NetGetFileSecurity }, 2850 { srvsvc_s_NetSetFileSecurity, SRVSVC_OPNUM_NetSetFileSecurity }, 2851 {0} 2852 }; 2853