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