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