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