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 boolean_t shortnames = B_TRUE; 1334 1335 switch (si->shr_flags & SMB_SHRF_CSC_MASK) { 1336 case SMB_SHRF_CSC_DISABLED: 1337 flags |= CSC_CACHE_NONE; 1338 break; 1339 case SMB_SHRF_CSC_AUTO: 1340 flags |= CSC_CACHE_AUTO_REINT; 1341 break; 1342 case SMB_SHRF_CSC_VDO: 1343 flags |= CSC_CACHE_VDO; 1344 break; 1345 case SMB_SHRF_CSC_MANUAL: 1346 default: 1347 /* 1348 * Default to CSC_CACHE_MANUAL_REINT. 1349 */ 1350 break; 1351 } 1352 1353 if (si->shr_flags & SMB_SHRF_ABE) 1354 flags |= SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM; 1355 1356 /* if 'smb' zfs property: shortnames=disabled */ 1357 if ((smb_kmod_shareinfo(si->shr_name, &shortnames) == 0) && 1358 (shortnames == B_FALSE)) { 1359 flags |= SHI1005_FLAGS_ALLOW_NAMESPACE_CACHING; 1360 } 1361 1362 return (flags); 1363 } 1364 1365 /* 1366 * srvsvc_s_NetSessionEnum 1367 * 1368 * Level 1 request is made by (Server Manager (srvmgr) on NT Server when 1369 * the user info icon is selected. 1370 * 1371 * On success, the return value is NERR_Success. 1372 * On error, the return value can be one of the following error codes: 1373 * 1374 * ERROR_ACCESS_DENIED The user does not have access to the requested 1375 * information. 1376 * ERROR_INVALID_LEVEL The value specified for the level is invalid. 1377 * ERROR_INVALID_PARAMETER The specified parameter is invalid. 1378 * ERROR_MORE_DATA More entries are available. Specify a large 1379 * enough buffer to receive all entries. 1380 * ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available. 1381 * NERR_ClientNameNotFound A session does not exist with the computer name. 1382 * NERR_InvalidComputer The computer name is invalid. 1383 * NERR_UserNotFound The user name could not be found. 1384 */ 1385 static int 1386 srvsvc_s_NetSessionEnum(void *arg, ndr_xa_t *mxa) 1387 { 1388 struct mslm_NetSessionEnum *param = arg; 1389 srvsvc_infonres_t *info; 1390 smb_netsvc_t *ns; 1391 smb_svcenum_t se; 1392 DWORD status = ERROR_SUCCESS; 1393 1394 if (!ndr_is_admin(mxa)) { 1395 status = ERROR_ACCESS_DENIED; 1396 goto srvsvc_netsessionenum_error; 1397 } 1398 1399 if ((info = NDR_NEW(mxa, srvsvc_infonres_t)) == NULL) { 1400 status = ERROR_NOT_ENOUGH_MEMORY; 1401 goto srvsvc_netsessionenum_error; 1402 } 1403 1404 info->entriesread = 0; 1405 info->entries = NULL; 1406 param->result.level = param->level; 1407 param->result.bufptr.p = info; 1408 1409 if ((param->total_entries = srvsvc_open_sessions()) == 0) { 1410 param->resume_handle = NULL; 1411 param->status = ERROR_SUCCESS; 1412 return (NDR_DRC_OK); 1413 } 1414 1415 bzero(&se, sizeof (smb_svcenum_t)); 1416 se.se_type = SMB_SVCENUM_TYPE_USER; 1417 se.se_level = param->level; 1418 se.se_ntotal = param->total_entries; 1419 se.se_nlimit = se.se_ntotal; 1420 1421 if (param->resume_handle) { 1422 se.se_resume = *param->resume_handle; 1423 se.se_nskip = se.se_resume; 1424 *param->resume_handle = 0; 1425 } 1426 1427 switch (param->level) { 1428 case 0: 1429 info->entries = NDR_NEWN(mxa, struct mslm_SESSION_INFO_0, 1430 se.se_nlimit); 1431 break; 1432 case 1: 1433 info->entries = NDR_NEWN(mxa, struct mslm_SESSION_INFO_1, 1434 se.se_nlimit); 1435 break; 1436 case 2: 1437 info->entries = NDR_NEWN(mxa, struct mslm_SESSION_INFO_2, 1438 se.se_nlimit); 1439 break; 1440 case 10: 1441 info->entries = NDR_NEWN(mxa, struct mslm_SESSION_INFO_10, 1442 se.se_nlimit); 1443 break; 1444 case 502: 1445 info->entries = NDR_NEWN(mxa, struct mslm_SESSION_INFO_502, 1446 se.se_nlimit); 1447 break; 1448 default: 1449 bzero(param, sizeof (struct mslm_NetSessionEnum)); 1450 param->status = ERROR_INVALID_LEVEL; 1451 return (NDR_DRC_OK); 1452 } 1453 1454 if (info->entries == NULL) { 1455 status = ERROR_NOT_ENOUGH_MEMORY; 1456 goto srvsvc_netsessionenum_error; 1457 } 1458 1459 if ((ns = smb_kmod_enum_init(&se)) == NULL) { 1460 status = ERROR_NOT_ENOUGH_MEMORY; 1461 goto srvsvc_netsessionenum_error; 1462 } 1463 1464 status = srvsvc_NetSessionEnumCommon(mxa, info, ns, &se); 1465 smb_kmod_enum_fini(ns); 1466 1467 if (status != ERROR_SUCCESS) 1468 goto srvsvc_netsessionenum_error; 1469 1470 if (param->resume_handle && 1471 param->pref_max_len != SMB_SRVSVC_MAXPREFLEN) { 1472 if (se.se_resume < param->total_entries) { 1473 *param->resume_handle = se.se_resume; 1474 status = ERROR_MORE_DATA; 1475 } 1476 } 1477 1478 param->total_entries = info->entriesread; 1479 param->status = status; 1480 return (NDR_DRC_OK); 1481 1482 srvsvc_netsessionenum_error: 1483 bzero(param, sizeof (struct mslm_NetSessionEnum)); 1484 param->status = status; 1485 return (NDR_DRC_OK); 1486 } 1487 1488 static uint32_t 1489 srvsvc_NetSessionEnumCommon(ndr_xa_t *mxa, srvsvc_infonres_t *info, 1490 smb_netsvc_t *ns, smb_svcenum_t *se) 1491 { 1492 struct mslm_SESSION_INFO_0 *info0 = info->entries; 1493 struct mslm_SESSION_INFO_1 *info1 = info->entries; 1494 struct mslm_SESSION_INFO_2 *info2 = info->entries; 1495 struct mslm_SESSION_INFO_10 *info10 = info->entries; 1496 struct mslm_SESSION_INFO_502 *info502 = info->entries; 1497 smb_netsvcitem_t *item; 1498 smb_netuserinfo_t *user; 1499 char *workstation; 1500 char account[MAXNAMELEN]; 1501 char ipaddr_buf[INET6_ADDRSTRLEN]; 1502 uint32_t logon_time; 1503 uint32_t flags; 1504 uint32_t entries_read = 0; 1505 1506 if (smb_kmod_enum(ns) != 0) 1507 return (ERROR_INTERNAL_ERROR); 1508 1509 item = list_head(&ns->ns_list); 1510 while (item != NULL) { 1511 user = &item->nsi_un.nsi_user; 1512 1513 workstation = user->ui_workstation; 1514 if (workstation == NULL || *workstation == '\0') { 1515 (void) smb_inet_ntop(&user->ui_ipaddr, ipaddr_buf, 1516 SMB_IPSTRLEN(user->ui_ipaddr.a_family)); 1517 workstation = ipaddr_buf; 1518 } 1519 1520 (void) snprintf(account, MAXNAMELEN, "%s\\%s", 1521 user->ui_domain, user->ui_account); 1522 1523 logon_time = time(0) - user->ui_logon_time; 1524 flags = (user->ui_flags & SMB_ATF_GUEST) ? SESS_GUEST : 0; 1525 1526 switch (se->se_level) { 1527 case 0: 1528 info0->sesi0_cname = NDR_STRDUP(mxa, workstation); 1529 if (info0->sesi0_cname == NULL) 1530 return (ERROR_NOT_ENOUGH_MEMORY); 1531 ++info0; 1532 break; 1533 1534 case 1: 1535 info1->sesi1_cname = NDR_STRDUP(mxa, workstation); 1536 info1->sesi1_uname = NDR_STRDUP(mxa, account); 1537 1538 if (info1->sesi1_cname == NULL || 1539 info1->sesi1_uname == NULL) 1540 return (ERROR_NOT_ENOUGH_MEMORY); 1541 1542 info1->sesi1_nopens = user->ui_numopens; 1543 info1->sesi1_time = logon_time; 1544 info1->sesi1_itime = 0; 1545 info1->sesi1_uflags = flags; 1546 ++info1; 1547 break; 1548 1549 case 2: 1550 info2->sesi2_cname = NDR_STRDUP(mxa, workstation); 1551 info2->sesi2_uname = NDR_STRDUP(mxa, account); 1552 1553 if (info2->sesi2_cname == NULL || 1554 info2->sesi2_uname == NULL) 1555 return (ERROR_NOT_ENOUGH_MEMORY); 1556 1557 info2->sesi2_nopens = user->ui_numopens; 1558 info2->sesi2_time = logon_time; 1559 info2->sesi2_itime = 0; 1560 info2->sesi2_uflags = flags; 1561 info2->sesi2_cltype_name = (uint8_t *)""; 1562 ++info2; 1563 break; 1564 1565 case 10: 1566 info10->sesi10_cname = NDR_STRDUP(mxa, workstation); 1567 info10->sesi10_uname = NDR_STRDUP(mxa, account); 1568 1569 if (info10->sesi10_cname == NULL || 1570 info10->sesi10_uname == NULL) 1571 return (ERROR_NOT_ENOUGH_MEMORY); 1572 1573 info10->sesi10_time = logon_time; 1574 info10->sesi10_itime = 0; 1575 ++info10; 1576 break; 1577 1578 case 502: 1579 info502->sesi502_cname = NDR_STRDUP(mxa, workstation); 1580 info502->sesi502_uname = NDR_STRDUP(mxa, account); 1581 1582 if (info502->sesi502_cname == NULL || 1583 info502->sesi502_uname == NULL) 1584 return (ERROR_NOT_ENOUGH_MEMORY); 1585 1586 info502->sesi502_nopens = user->ui_numopens; 1587 info502->sesi502_time = logon_time; 1588 info502->sesi502_itime = 0; 1589 info502->sesi502_uflags = flags; 1590 info502->sesi502_cltype_name = (uint8_t *)""; 1591 info502->sesi502_transport = (uint8_t *)""; 1592 ++info502; 1593 break; 1594 1595 default: 1596 return (ERROR_INVALID_LEVEL); 1597 } 1598 1599 ++entries_read; 1600 item = list_next(&ns->ns_list, item); 1601 } 1602 1603 info->entriesread = entries_read; 1604 return (ERROR_SUCCESS); 1605 } 1606 1607 /* 1608 * srvsvc_s_NetSessionDel 1609 * 1610 * Ends a network session between a server and a workstation. 1611 * On NT only members of the Administrators or Account Operators 1612 * local groups are permitted to use NetSessionDel. 1613 * 1614 * If unc_clientname is NULL, all sessions associated with the 1615 * specified user will be disconnected. 1616 * 1617 * If username is NULL, all sessions from the specified client 1618 * will be disconnected. 1619 * 1620 * Return Values 1621 * On success, the return value is NERR_Success/ERROR_SUCCESS. 1622 * On failure, the return value can be one of the following errors: 1623 * 1624 * ERROR_ACCESS_DENIED The user does not have access to the 1625 * requested information. 1626 * ERROR_INVALID_PARAMETER The specified parameter is invalid. 1627 * ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available. 1628 * NERR_ClientNameNotFound A session does not exist with that 1629 * computer name. 1630 */ 1631 static int 1632 srvsvc_s_NetSessionDel(void *arg, ndr_xa_t *mxa) 1633 { 1634 static struct { 1635 int errnum; 1636 int nerr; 1637 } errmap[] = { 1638 0, ERROR_SUCCESS, 1639 EACCES, ERROR_ACCESS_DENIED, 1640 EPERM, ERROR_ACCESS_DENIED, 1641 EINVAL, ERROR_INVALID_PARAMETER, 1642 ENOMEM, ERROR_NOT_ENOUGH_MEMORY, 1643 ENOENT, NERR_ClientNameNotFound 1644 }; 1645 1646 struct mslm_NetSessionDel *param = arg; 1647 int i; 1648 int rc; 1649 1650 if (!ndr_is_admin(mxa)) { 1651 param->status = ERROR_ACCESS_DENIED; 1652 return (NDR_DRC_OK); 1653 } 1654 1655 rc = smb_kmod_session_close((char *)param->unc_clientname, 1656 (char *)param->username); 1657 1658 for (i = 0; i < (sizeof (errmap) / sizeof (errmap[0])); ++i) { 1659 if (rc == errmap[i].errnum) { 1660 param->status = errmap[i].nerr; 1661 return (NDR_DRC_OK); 1662 } 1663 } 1664 1665 param->status = ERROR_INTERNAL_ERROR; 1666 return (NDR_DRC_OK); 1667 } 1668 1669 static int 1670 srvsvc_s_NetServerGetInfo(void *arg, ndr_xa_t *mxa) 1671 { 1672 struct mslm_NetServerGetInfo *param = arg; 1673 struct mslm_SERVER_INFO_100 *info100; 1674 struct mslm_SERVER_INFO_101 *info101; 1675 struct mslm_SERVER_INFO_102 *info102; 1676 struct mslm_SERVER_INFO_502 *info502; 1677 struct mslm_SERVER_INFO_503 *info503; 1678 char sys_comment[SMB_PI_MAX_COMMENT]; 1679 char hostname[NETBIOS_NAME_SZ]; 1680 smb_version_t version; 1681 1682 if (smb_getnetbiosname(hostname, sizeof (hostname)) != 0) { 1683 netservergetinfo_no_memory: 1684 bzero(param, sizeof (struct mslm_NetServerGetInfo)); 1685 return (ERROR_NOT_ENOUGH_MEMORY); 1686 } 1687 1688 (void) smb_config_getstr(SMB_CI_SYS_CMNT, sys_comment, 1689 sizeof (sys_comment)); 1690 if (*sys_comment == '\0') 1691 (void) strcpy(sys_comment, " "); 1692 1693 smb_config_get_version(&version); 1694 1695 switch (param->level) { 1696 case 100: 1697 info100 = NDR_NEW(mxa, struct mslm_SERVER_INFO_100); 1698 if (info100 == NULL) 1699 goto netservergetinfo_no_memory; 1700 1701 bzero(info100, sizeof (struct mslm_SERVER_INFO_100)); 1702 info100->sv100_platform_id = SV_PLATFORM_ID_NT; 1703 info100->sv100_name = (uint8_t *)NDR_STRDUP(mxa, hostname); 1704 if (info100->sv100_name == NULL) 1705 goto netservergetinfo_no_memory; 1706 1707 param->result.bufptr.bufptr100 = info100; 1708 break; 1709 1710 case 101: 1711 info101 = NDR_NEW(mxa, struct mslm_SERVER_INFO_101); 1712 if (info101 == NULL) 1713 goto netservergetinfo_no_memory; 1714 1715 bzero(info101, sizeof (struct mslm_SERVER_INFO_101)); 1716 info101->sv101_platform_id = SV_PLATFORM_ID_NT; 1717 info101->sv101_version_major = version.sv_major; 1718 info101->sv101_version_minor = version.sv_minor; 1719 info101->sv101_type = SV_TYPE_DEFAULT; 1720 info101->sv101_name = (uint8_t *)NDR_STRDUP(mxa, hostname); 1721 info101->sv101_comment 1722 = (uint8_t *)NDR_STRDUP(mxa, sys_comment); 1723 1724 if (info101->sv101_name == NULL || 1725 info101->sv101_comment == NULL) 1726 goto netservergetinfo_no_memory; 1727 1728 param->result.bufptr.bufptr101 = info101; 1729 break; 1730 1731 case 102: 1732 info102 = NDR_NEW(mxa, struct mslm_SERVER_INFO_102); 1733 if (info102 == NULL) 1734 goto netservergetinfo_no_memory; 1735 1736 bzero(info102, sizeof (struct mslm_SERVER_INFO_102)); 1737 info102->sv102_platform_id = SV_PLATFORM_ID_NT; 1738 info102->sv102_version_major = version.sv_major; 1739 info102->sv102_version_minor = version.sv_minor; 1740 info102->sv102_type = SV_TYPE_DEFAULT; 1741 info102->sv102_name = (uint8_t *)NDR_STRDUP(mxa, hostname); 1742 info102->sv102_comment 1743 = (uint8_t *)NDR_STRDUP(mxa, sys_comment); 1744 1745 /* 1746 * The following level 102 fields are defaulted to zero 1747 * by virtue of the call to bzero above. 1748 * 1749 * sv102_users 1750 * sv102_disc 1751 * sv102_hidden 1752 * sv102_announce 1753 * sv102_anndelta 1754 * sv102_licenses 1755 * sv102_userpath 1756 */ 1757 if (info102->sv102_name == NULL || 1758 info102->sv102_comment == NULL) 1759 goto netservergetinfo_no_memory; 1760 1761 param->result.bufptr.bufptr102 = info102; 1762 break; 1763 1764 case 502: 1765 info502 = NDR_NEW(mxa, struct mslm_SERVER_INFO_502); 1766 if (info502 == NULL) 1767 goto netservergetinfo_no_memory; 1768 1769 bzero(info502, sizeof (struct mslm_SERVER_INFO_502)); 1770 param->result.bufptr.bufptr502 = info502; 1771 #ifdef SRVSVC_SATISFY_SMBTORTURE 1772 break; 1773 #else 1774 param->result.level = param->level; 1775 param->status = ERROR_ACCESS_DENIED; 1776 return (NDR_DRC_OK); 1777 #endif /* SRVSVC_SATISFY_SMBTORTURE */ 1778 1779 case 503: 1780 info503 = NDR_NEW(mxa, struct mslm_SERVER_INFO_503); 1781 if (info503 == NULL) 1782 goto netservergetinfo_no_memory; 1783 1784 bzero(info503, sizeof (struct mslm_SERVER_INFO_503)); 1785 param->result.bufptr.bufptr503 = info503; 1786 #ifdef SRVSVC_SATISFY_SMBTORTURE 1787 break; 1788 #else 1789 param->result.level = param->level; 1790 param->status = ERROR_ACCESS_DENIED; 1791 return (NDR_DRC_OK); 1792 #endif /* SRVSVC_SATISFY_SMBTORTURE */ 1793 1794 default: 1795 bzero(¶m->result, 1796 sizeof (struct mslm_NetServerGetInfo_result)); 1797 param->status = ERROR_ACCESS_DENIED; 1798 return (NDR_DRC_OK); 1799 } 1800 1801 param->result.level = param->level; 1802 param->status = ERROR_SUCCESS; 1803 return (NDR_DRC_OK); 1804 } 1805 1806 /* 1807 * NetRemoteTOD 1808 * 1809 * Returns information about the time of day on this server. 1810 * 1811 * typedef struct _TIME_OF_DAY_INFO { 1812 * DWORD tod_elapsedt; // seconds since 00:00:00 January 1 1970 GMT 1813 * DWORD tod_msecs; // arbitrary milliseconds (since reset) 1814 * DWORD tod_hours; // current hour [0-23] 1815 * DWORD tod_mins; // current minute [0-59] 1816 * DWORD tod_secs; // current second [0-59] 1817 * DWORD tod_hunds; // current hundredth (0.01) second [0-99] 1818 * LONG tod_timezone; // time zone of the server 1819 * DWORD tod_tinterval; // clock tick time interval 1820 * DWORD tod_day; // day of the month [1-31] 1821 * DWORD tod_month; // month of the year [1-12] 1822 * DWORD tod_year; // current year 1823 * DWORD tod_weekday; // day of the week since Sunday [0-6] 1824 * } TIME_OF_DAY_INFO; 1825 * 1826 * The time zone of the server is calculated in minutes from Greenwich 1827 * Mean Time (GMT). For time zones west of Greenwich, the value is 1828 * positive; for time zones east of Greenwich, the value is negative. 1829 * A value of -1 indicates that the time zone is undefined. 1830 * 1831 * Determine offset from GMT. If daylight saving time use altzone, 1832 * otherwise use timezone. 1833 * 1834 * The clock tick value represents a resolution of one ten-thousandth 1835 * (0.0001) second. 1836 */ 1837 static int 1838 srvsvc_s_NetRemoteTOD(void *arg, ndr_xa_t *mxa) 1839 { 1840 struct mslm_NetRemoteTOD *param = arg; 1841 struct mslm_TIME_OF_DAY_INFO *tod; 1842 struct timeval time_val; 1843 struct tm tm; 1844 time_t gmtoff; 1845 1846 1847 (void) gettimeofday(&time_val, 0); 1848 (void) gmtime_r(&time_val.tv_sec, &tm); 1849 1850 tod = NDR_NEW(mxa, struct mslm_TIME_OF_DAY_INFO); 1851 if (tod == NULL) { 1852 bzero(param, sizeof (struct mslm_NetRemoteTOD)); 1853 return (ERROR_NOT_ENOUGH_MEMORY); 1854 } 1855 1856 bzero(tod, sizeof (struct mslm_TIME_OF_DAY_INFO)); 1857 1858 tod->tod_elapsedt = time_val.tv_sec; 1859 tod->tod_msecs = time_val.tv_usec; 1860 tod->tod_hours = tm.tm_hour; 1861 tod->tod_mins = tm.tm_min; 1862 tod->tod_secs = tm.tm_sec; 1863 tod->tod_hunds = 0; 1864 tod->tod_tinterval = 1000; 1865 tod->tod_day = tm.tm_mday; 1866 tod->tod_month = tm.tm_mon+1; 1867 tod->tod_year = tm.tm_year+1900; 1868 tod->tod_weekday = tm.tm_wday; 1869 1870 (void) localtime_r(&time_val.tv_sec, &tm); 1871 gmtoff = (tm.tm_isdst) ? altzone : timezone; 1872 tod->tod_timezone = gmtoff / SECSPERMIN; 1873 1874 param->bufptr = tod; 1875 param->status = ERROR_SUCCESS; 1876 return (NDR_DRC_OK); 1877 } 1878 1879 /* 1880 * srvsvc_s_NetNameValidate 1881 * 1882 * Perform name validation. 1883 * 1884 * Returns Win32 error codes. 1885 */ 1886 /*ARGSUSED*/ 1887 static int 1888 srvsvc_s_NetNameValidate(void *arg, ndr_xa_t *mxa) 1889 { 1890 struct mslm_NetNameValidate *param = arg; 1891 char *name; 1892 int maxlen; 1893 int len; 1894 1895 if ((name = (char *)param->pathname) == NULL) { 1896 param->status = ERROR_INVALID_PARAMETER; 1897 return (NDR_DRC_OK); 1898 } 1899 1900 switch (param->type) { 1901 case NAMETYPE_SHARE: 1902 len = strlen(name); 1903 maxlen = (param->flags & NAMEFLAG_LM2) ? 1904 SMB_SHARE_OEMNAME_MAX : SMB_SHARE_NTNAME_MAX; 1905 1906 if (len > maxlen) { 1907 param->status = ERROR_INVALID_NAME; 1908 return (NDR_DRC_OK); 1909 } 1910 1911 param->status = smb_name_validate_share(name); 1912 break; 1913 1914 case NAMETYPE_USER: 1915 case NAMETYPE_GROUP: 1916 param->status = smb_name_validate_account(name); 1917 break; 1918 1919 case NAMETYPE_DOMAIN: /* NetBIOS domain name */ 1920 param->status = smb_name_validate_nbdomain(name); 1921 break; 1922 1923 case NAMETYPE_WORKGROUP: 1924 param->status = smb_name_validate_workgroup(name); 1925 break; 1926 1927 case NAMETYPE_PASSWORD: 1928 case NAMETYPE_COMPUTER: 1929 case NAMETYPE_EVENT: 1930 case NAMETYPE_SERVICE: 1931 case NAMETYPE_NET: 1932 case NAMETYPE_MESSAGE: 1933 case NAMETYPE_MESSAGEDEST: 1934 case NAMETYPE_SHAREPASSWORD: 1935 param->status = ERROR_NOT_SUPPORTED; 1936 break; 1937 1938 default: 1939 param->status = ERROR_INVALID_PARAMETER; 1940 break; 1941 } 1942 1943 return (NDR_DRC_OK); 1944 } 1945 1946 /* 1947 * srvsvc_s_NetShareAdd 1948 * 1949 * Add a new share. Only power users groups can manage shares. 1950 * 1951 * This interface is used by the rmtshare command from the NT resource 1952 * kit. Rmtshare allows a client to add or remove shares on a server 1953 * from the client's command line. 1954 * 1955 * Returns Win32 error codes. 1956 */ 1957 static int 1958 srvsvc_s_NetShareAdd(void *arg, ndr_xa_t *mxa) 1959 { 1960 static DWORD parm_err = 0; 1961 DWORD parm_stat; 1962 struct mslm_NetShareAdd *param = arg; 1963 struct mslm_NetShareInfo_2 *info2; 1964 struct mslm_NetShareInfo_502 *info502; 1965 char realpath[MAXPATHLEN]; 1966 int32_t native_os; 1967 uint8_t *sdbuf = NULL; 1968 uint32_t status; 1969 smb_share_t si; 1970 1971 native_os = ndr_native_os(mxa); 1972 1973 if (!ndr_is_poweruser(mxa)) { 1974 bzero(param, sizeof (struct mslm_NetShareAdd)); 1975 param->status = ERROR_ACCESS_DENIED; 1976 return (NDR_DRC_OK); 1977 } 1978 1979 switch (param->level) { 1980 case 2: 1981 info2 = (struct mslm_NetShareInfo_2 *)param->info.un.info2; 1982 break; 1983 1984 case 502: 1985 info502 = (struct mslm_NetShareInfo_502 *) 1986 param->info.un.info502; 1987 sdbuf = info502->shi502_security_descriptor; 1988 info2 = (struct mslm_NetShareInfo_2 *)info502; 1989 break; 1990 1991 default: 1992 bzero(param, sizeof (struct mslm_NetShareAdd)); 1993 param->status = ERROR_ACCESS_DENIED; 1994 return (NDR_DRC_OK); 1995 } 1996 1997 if (info2->shi2_netname == NULL || info2->shi2_path == NULL) { 1998 bzero(param, sizeof (struct mslm_NetShareAdd)); 1999 param->status = NERR_NetNameNotFound; 2000 return (NDR_DRC_OK); 2001 } 2002 2003 if (smb_shr_is_restricted((char *)info2->shi2_netname)) { 2004 bzero(param, sizeof (struct mslm_NetShareAdd)); 2005 param->status = ERROR_ACCESS_DENIED; 2006 return (NDR_DRC_OK); 2007 } 2008 2009 if (info2->shi2_comment == NULL) 2010 info2->shi2_comment = (uint8_t *)""; 2011 2012 /* 2013 * Derive the real path which will be stored in the 2014 * directory field of the smb_share_t structure 2015 * from the path field in this RPC request. 2016 */ 2017 parm_stat = smb_shr_get_realpath((const char *)info2->shi2_path, 2018 realpath, MAXPATHLEN); 2019 2020 if (parm_stat != NERR_Success) { 2021 bzero(param, sizeof (struct mslm_NetShareAdd)); 2022 param->status = parm_stat; 2023 param->parm_err 2024 = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err; 2025 return (NDR_DRC_OK); 2026 } 2027 2028 param->status = srvsvc_sa_add((char *)info2->shi2_netname, realpath, 2029 (char *)info2->shi2_comment); 2030 if (param->status == NERR_Success) { 2031 status = smb_shr_get((char *)info2->shi2_netname, &si); 2032 2033 if ((sdbuf != NULL) && (status == NERR_Success)) 2034 (void) srvsvc_sd_set(&si, sdbuf); 2035 } 2036 param->parm_err = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err; 2037 return (NDR_DRC_OK); 2038 } 2039 2040 /* 2041 * srvsvc_estimate_limit 2042 * 2043 * Estimate the number of objects that will fit in prefmaxlen. 2044 * nlimit is adjusted here. 2045 */ 2046 static void 2047 srvsvc_estimate_limit(smb_svcenum_t *se, uint32_t obj_size) 2048 { 2049 DWORD max_cnt; 2050 2051 if (obj_size == 0) { 2052 se->se_nlimit = 0; 2053 return; 2054 } 2055 2056 if ((max_cnt = (se->se_prefmaxlen / obj_size)) == 0) { 2057 se->se_nlimit = 0; 2058 return; 2059 } 2060 2061 if (se->se_ntotal > max_cnt) 2062 se->se_nlimit = max_cnt; 2063 else 2064 se->se_nlimit = se->se_ntotal; 2065 } 2066 2067 /* 2068 * srvsvc_s_NetShareEnum 2069 * 2070 * Enumerate all shares (see also NetShareEnumSticky). 2071 * 2072 * Request for various levels of information about our shares. 2073 * Level 0: share names. 2074 * Level 1: share name, share type and comment field. 2075 * Level 2: everything that we know about the shares. 2076 * Level 501: level 1 + flags. 2077 * Level 502: level 2 + security descriptor. 2078 */ 2079 static int 2080 srvsvc_s_NetShareEnum(void *arg, ndr_xa_t *mxa) 2081 { 2082 struct mslm_NetShareEnum *param = arg; 2083 srvsvc_infonres_t *infonres; 2084 smb_svcenum_t se; 2085 DWORD status; 2086 2087 infonres = NDR_NEW(mxa, srvsvc_infonres_t); 2088 if (infonres == NULL) { 2089 bzero(param, sizeof (struct mslm_NetShareEnum)); 2090 param->status = ERROR_NOT_ENOUGH_MEMORY; 2091 return (NDR_DRC_OK); 2092 } 2093 2094 infonres->entriesread = 0; 2095 infonres->entries = NULL; 2096 param->result.level = param->level; 2097 param->result.bufptr.p = infonres; 2098 2099 bzero(&se, sizeof (smb_svcenum_t)); 2100 se.se_type = SMB_SVCENUM_TYPE_SHARE; 2101 se.se_level = param->level; 2102 se.se_ntotal = smb_shr_count(); 2103 se.se_nlimit = se.se_ntotal; 2104 2105 if (param->prefmaxlen == SMB_SRVSVC_MAXPREFLEN || 2106 param->prefmaxlen > SMB_SRVSVC_MAXBUFLEN) 2107 se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN; 2108 else 2109 se.se_prefmaxlen = param->prefmaxlen; 2110 2111 if (param->resume_handle) { 2112 se.se_resume = *param->resume_handle; 2113 se.se_nskip = se.se_resume; 2114 *param->resume_handle = 0; 2115 } 2116 2117 switch (param->level) { 2118 case 0: 2119 status = mlsvc_NetShareEnumLevel0(mxa, infonres, &se, 0); 2120 break; 2121 2122 case 1: 2123 status = mlsvc_NetShareEnumLevel1(mxa, infonres, &se, 0); 2124 break; 2125 2126 case 2: 2127 status = mlsvc_NetShareEnumLevel2(mxa, infonres, &se, 0); 2128 break; 2129 2130 case 501: 2131 status = mlsvc_NetShareEnumLevel501(mxa, infonres, &se, 0); 2132 break; 2133 2134 case 502: 2135 status = mlsvc_NetShareEnumLevel502(mxa, infonres, &se, 0); 2136 break; 2137 2138 default: 2139 status = ERROR_INVALID_LEVEL; 2140 break; 2141 } 2142 2143 if (status != 0) { 2144 bzero(param, sizeof (struct mslm_NetShareEnum)); 2145 param->status = status; 2146 return (NDR_DRC_OK); 2147 } 2148 2149 if (se.se_nlimit == 0) { 2150 param->status = ERROR_SUCCESS; 2151 return (NDR_DRC_OK); 2152 } 2153 2154 if (param->resume_handle && 2155 param->prefmaxlen != SMB_SRVSVC_MAXPREFLEN) { 2156 if (se.se_resume < se.se_ntotal) { 2157 *param->resume_handle = se.se_resume; 2158 status = ERROR_MORE_DATA; 2159 } 2160 } 2161 2162 param->totalentries = se.se_ntotal; 2163 param->status = status; 2164 return (NDR_DRC_OK); 2165 } 2166 2167 /* 2168 * srvsvc_s_NetShareEnumSticky 2169 * 2170 * Enumerate sticky shares: all shares except those marked STYPE_SPECIAL. 2171 * Except for excluding STYPE_SPECIAL shares, NetShareEnumSticky is the 2172 * same as NetShareEnum. 2173 * 2174 * Request for various levels of information about our shares. 2175 * Level 0: share names. 2176 * Level 1: share name, share type and comment field. 2177 * Level 2: everything that we know about the shares. 2178 * Level 501: not valid for this request. 2179 * Level 502: level 2 + security descriptor. 2180 * 2181 * We set n_skip to resume_handle, which is used to find the appropriate 2182 * place to resume. The resume_handle is similar to the readdir cookie. 2183 */ 2184 static int 2185 srvsvc_s_NetShareEnumSticky(void *arg, ndr_xa_t *mxa) 2186 { 2187 struct mslm_NetShareEnum *param = arg; 2188 srvsvc_infonres_t *infonres; 2189 smb_svcenum_t se; 2190 DWORD status; 2191 2192 infonres = NDR_NEW(mxa, srvsvc_infonres_t); 2193 if (infonres == NULL) { 2194 bzero(param, sizeof (struct mslm_NetShareEnum)); 2195 param->status = ERROR_NOT_ENOUGH_MEMORY; 2196 return (NDR_DRC_OK); 2197 } 2198 2199 infonres->entriesread = 0; 2200 infonres->entries = NULL; 2201 param->result.level = param->level; 2202 param->result.bufptr.p = infonres; 2203 2204 bzero(&se, sizeof (smb_svcenum_t)); 2205 se.se_type = SMB_SVCENUM_TYPE_SHARE; 2206 se.se_level = param->level; 2207 se.se_ntotal = smb_shr_count(); 2208 se.se_nlimit = se.se_ntotal; 2209 2210 if (param->prefmaxlen == SMB_SRVSVC_MAXPREFLEN || 2211 param->prefmaxlen > SMB_SRVSVC_MAXBUFLEN) 2212 se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN; 2213 else 2214 se.se_prefmaxlen = param->prefmaxlen; 2215 2216 if (param->resume_handle) { 2217 se.se_resume = *param->resume_handle; 2218 se.se_nskip = se.se_resume; 2219 *param->resume_handle = 0; 2220 } 2221 2222 switch (param->level) { 2223 case 0: 2224 status = mlsvc_NetShareEnumLevel0(mxa, infonres, &se, 1); 2225 break; 2226 2227 case 1: 2228 status = mlsvc_NetShareEnumLevel1(mxa, infonres, &se, 1); 2229 break; 2230 2231 case 2: 2232 status = mlsvc_NetShareEnumLevel2(mxa, infonres, &se, 1); 2233 break; 2234 2235 case 502: 2236 status = mlsvc_NetShareEnumLevel502(mxa, infonres, &se, 1); 2237 break; 2238 2239 case 501: 2240 default: 2241 status = ERROR_INVALID_LEVEL; 2242 break; 2243 } 2244 2245 if (status != ERROR_SUCCESS) { 2246 bzero(param, sizeof (struct mslm_NetShareEnum)); 2247 param->status = status; 2248 return (NDR_DRC_OK); 2249 } 2250 2251 if (se.se_nlimit == 0) { 2252 param->status = ERROR_SUCCESS; 2253 return (NDR_DRC_OK); 2254 } 2255 2256 if (param->resume_handle && 2257 param->prefmaxlen != SMB_SRVSVC_MAXPREFLEN) { 2258 if (se.se_resume < se.se_ntotal) { 2259 *param->resume_handle = se.se_resume; 2260 status = ERROR_MORE_DATA; 2261 } 2262 } 2263 2264 param->totalentries = se.se_ntotal; 2265 param->status = status; 2266 return (NDR_DRC_OK); 2267 } 2268 2269 /* 2270 * NetShareEnum Level 0 2271 */ 2272 static DWORD 2273 mlsvc_NetShareEnumLevel0(ndr_xa_t *mxa, srvsvc_infonres_t *infonres, 2274 smb_svcenum_t *se, int sticky) 2275 { 2276 struct mslm_NetShareInfo_0 *info0; 2277 smb_shriter_t iterator; 2278 smb_share_t *si; 2279 DWORD status; 2280 2281 srvsvc_estimate_limit(se, 2282 sizeof (struct mslm_NetShareInfo_0) + MAXNAMELEN); 2283 if (se->se_nlimit == 0) 2284 return (ERROR_SUCCESS); 2285 2286 info0 = NDR_NEWN(mxa, struct mslm_NetShareInfo_0, se->se_nlimit); 2287 if (info0 == NULL) 2288 return (ERROR_NOT_ENOUGH_MEMORY); 2289 2290 smb_shr_iterinit(&iterator); 2291 2292 se->se_nitems = 0; 2293 while ((si = smb_shr_iterate(&iterator)) != NULL) { 2294 if (se->se_nskip > 0) { 2295 --se->se_nskip; 2296 continue; 2297 } 2298 2299 ++se->se_resume; 2300 2301 if (sticky && (si->shr_flags & SMB_SHRF_TRANS)) 2302 continue; 2303 2304 if (si->shr_flags & SMB_SHRF_AUTOHOME) 2305 continue; 2306 2307 if (se->se_nitems >= se->se_nlimit) { 2308 se->se_nitems = se->se_nlimit; 2309 break; 2310 } 2311 2312 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info0); 2313 if (status != ERROR_SUCCESS) 2314 break; 2315 2316 ++se->se_nitems; 2317 } 2318 2319 if (se->se_nitems < se->se_nlimit) { 2320 if (srvsvc_add_autohome(mxa, se, (void *)info0)) 2321 ++se->se_nitems; 2322 } 2323 2324 infonres->entriesread = se->se_nitems; 2325 infonres->entries = info0; 2326 return (ERROR_SUCCESS); 2327 } 2328 2329 /* 2330 * NetShareEnum Level 1 2331 */ 2332 static DWORD 2333 mlsvc_NetShareEnumLevel1(ndr_xa_t *mxa, srvsvc_infonres_t *infonres, 2334 smb_svcenum_t *se, int sticky) 2335 { 2336 struct mslm_NetShareInfo_1 *info1; 2337 smb_shriter_t iterator; 2338 smb_share_t *si; 2339 DWORD status; 2340 2341 srvsvc_estimate_limit(se, 2342 sizeof (struct mslm_NetShareInfo_1) + MAXNAMELEN); 2343 if (se->se_nlimit == 0) 2344 return (ERROR_SUCCESS); 2345 2346 info1 = NDR_NEWN(mxa, struct mslm_NetShareInfo_1, se->se_nlimit); 2347 if (info1 == NULL) 2348 return (ERROR_NOT_ENOUGH_MEMORY); 2349 2350 smb_shr_iterinit(&iterator); 2351 2352 se->se_nitems = 0; 2353 while ((si = smb_shr_iterate(&iterator)) != 0) { 2354 if (se->se_nskip > 0) { 2355 --se->se_nskip; 2356 continue; 2357 } 2358 2359 ++se->se_resume; 2360 2361 if (sticky && (si->shr_flags & SMB_SHRF_TRANS)) 2362 continue; 2363 2364 if (si->shr_flags & SMB_SHRF_AUTOHOME) 2365 continue; 2366 2367 if (se->se_nitems >= se->se_nlimit) { 2368 se->se_nitems = se->se_nlimit; 2369 break; 2370 } 2371 2372 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info1); 2373 if (status != ERROR_SUCCESS) 2374 break; 2375 2376 ++se->se_nitems; 2377 } 2378 2379 if (se->se_nitems < se->se_nlimit) { 2380 if (srvsvc_add_autohome(mxa, se, (void *)info1)) 2381 ++se->se_nitems; 2382 } 2383 2384 infonres->entriesread = se->se_nitems; 2385 infonres->entries = info1; 2386 return (ERROR_SUCCESS); 2387 } 2388 2389 /* 2390 * NetShareEnum Level 2 2391 */ 2392 static DWORD 2393 mlsvc_NetShareEnumLevel2(ndr_xa_t *mxa, srvsvc_infonres_t *infonres, 2394 smb_svcenum_t *se, int sticky) 2395 { 2396 struct mslm_NetShareInfo_2 *info2; 2397 smb_shriter_t iterator; 2398 smb_share_t *si; 2399 DWORD status; 2400 2401 srvsvc_estimate_limit(se, 2402 sizeof (struct mslm_NetShareInfo_2) + MAXNAMELEN); 2403 if (se->se_nlimit == 0) 2404 return (ERROR_SUCCESS); 2405 2406 info2 = NDR_NEWN(mxa, struct mslm_NetShareInfo_2, se->se_nlimit); 2407 if (info2 == NULL) 2408 return (ERROR_NOT_ENOUGH_MEMORY); 2409 2410 smb_shr_iterinit(&iterator); 2411 2412 se->se_nitems = 0; 2413 while ((si = smb_shr_iterate(&iterator)) != 0) { 2414 if (se->se_nskip > 0) { 2415 --se->se_nskip; 2416 continue; 2417 } 2418 2419 ++se->se_resume; 2420 2421 if (sticky && (si->shr_flags & SMB_SHRF_TRANS)) 2422 continue; 2423 2424 if (si->shr_flags & SMB_SHRF_AUTOHOME) 2425 continue; 2426 2427 if (se->se_nitems >= se->se_nlimit) { 2428 se->se_nitems = se->se_nlimit; 2429 break; 2430 } 2431 2432 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info2); 2433 if (status != ERROR_SUCCESS) 2434 break; 2435 2436 ++se->se_nitems; 2437 } 2438 2439 if (se->se_nitems < se->se_nlimit) { 2440 if (srvsvc_add_autohome(mxa, se, (void *)info2)) 2441 ++se->se_nitems; 2442 } 2443 2444 infonres->entriesread = se->se_nitems; 2445 infonres->entries = info2; 2446 return (ERROR_SUCCESS); 2447 } 2448 2449 /* 2450 * NetShareEnum Level 501 2451 */ 2452 static DWORD 2453 mlsvc_NetShareEnumLevel501(ndr_xa_t *mxa, srvsvc_infonres_t *infonres, 2454 smb_svcenum_t *se, int sticky) 2455 { 2456 struct mslm_NetShareInfo_501 *info501; 2457 smb_shriter_t iterator; 2458 smb_share_t *si; 2459 DWORD status; 2460 2461 srvsvc_estimate_limit(se, 2462 sizeof (struct mslm_NetShareInfo_501) + MAXNAMELEN); 2463 if (se->se_nlimit == 0) 2464 return (ERROR_SUCCESS); 2465 2466 info501 = NDR_NEWN(mxa, struct mslm_NetShareInfo_501, 2467 se->se_nlimit); 2468 if (info501 == NULL) 2469 return (ERROR_NOT_ENOUGH_MEMORY); 2470 2471 smb_shr_iterinit(&iterator); 2472 2473 se->se_nitems = 0; 2474 while ((si = smb_shr_iterate(&iterator)) != 0) { 2475 if (se->se_nskip > 0) { 2476 --se->se_nskip; 2477 continue; 2478 } 2479 2480 ++se->se_resume; 2481 2482 if (sticky && (si->shr_flags & SMB_SHRF_TRANS)) 2483 continue; 2484 2485 if (si->shr_flags & SMB_SHRF_AUTOHOME) 2486 continue; 2487 2488 if (se->se_nitems >= se->se_nlimit) { 2489 se->se_nitems = se->se_nlimit; 2490 break; 2491 } 2492 2493 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info501); 2494 if (status != ERROR_SUCCESS) 2495 break; 2496 2497 ++se->se_nitems; 2498 } 2499 2500 if (se->se_nitems < se->se_nlimit) { 2501 if (srvsvc_add_autohome(mxa, se, (void *)info501)) 2502 ++se->se_nitems; 2503 } 2504 2505 infonres->entriesread = se->se_nitems; 2506 infonres->entries = info501; 2507 return (ERROR_SUCCESS); 2508 } 2509 2510 /* 2511 * NetShareEnum Level 502 2512 */ 2513 static DWORD 2514 mlsvc_NetShareEnumLevel502(ndr_xa_t *mxa, srvsvc_infonres_t *infonres, 2515 smb_svcenum_t *se, int sticky) 2516 { 2517 struct mslm_NetShareInfo_502 *info502; 2518 smb_shriter_t iterator; 2519 smb_share_t *si; 2520 DWORD status; 2521 2522 srvsvc_estimate_limit(se, 2523 sizeof (struct mslm_NetShareInfo_502) + MAXNAMELEN); 2524 if (se->se_nlimit == 0) 2525 return (ERROR_SUCCESS); 2526 2527 info502 = NDR_NEWN(mxa, struct mslm_NetShareInfo_502, 2528 se->se_nlimit); 2529 if (info502 == NULL) 2530 return (ERROR_NOT_ENOUGH_MEMORY); 2531 2532 smb_shr_iterinit(&iterator); 2533 2534 se->se_nitems = 0; 2535 while ((si = smb_shr_iterate(&iterator)) != NULL) { 2536 if (se->se_nskip > 0) { 2537 --se->se_nskip; 2538 continue; 2539 } 2540 2541 ++se->se_resume; 2542 2543 if (sticky && (si->shr_flags & SMB_SHRF_TRANS)) 2544 continue; 2545 2546 if (si->shr_flags & SMB_SHRF_AUTOHOME) 2547 continue; 2548 2549 if (se->se_nitems >= se->se_nlimit) { 2550 se->se_nitems = se->se_nlimit; 2551 break; 2552 } 2553 2554 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info502); 2555 if (status != ERROR_SUCCESS) 2556 break; 2557 2558 ++se->se_nitems; 2559 } 2560 2561 if (se->se_nitems < se->se_nlimit) { 2562 if (srvsvc_add_autohome(mxa, se, (void *)info502)) 2563 ++se->se_nitems; 2564 } 2565 2566 infonres->entriesread = se->se_nitems; 2567 infonres->entries = info502; 2568 return (ERROR_SUCCESS); 2569 } 2570 2571 /* 2572 * mlsvc_NetShareEnumCommon 2573 * 2574 * Build the levels 0, 1, 2, 501 and 502 share information. This function 2575 * is called by the various NetShareEnum levels for each share. If 2576 * we cannot build the share data for some reason, we return an error 2577 * but the actual value of the error is not important to the caller. 2578 * The caller just needs to know not to include this info in the RPC 2579 * response. 2580 * 2581 * Returns: 2582 * ERROR_SUCCESS 2583 * ERROR_NOT_ENOUGH_MEMORY 2584 * ERROR_INVALID_LEVEL 2585 */ 2586 static DWORD 2587 mlsvc_NetShareEnumCommon(ndr_xa_t *mxa, smb_svcenum_t *se, 2588 smb_share_t *si, void *infop) 2589 { 2590 struct mslm_NetShareInfo_0 *info0; 2591 struct mslm_NetShareInfo_1 *info1; 2592 struct mslm_NetShareInfo_2 *info2; 2593 struct mslm_NetShareInfo_501 *info501; 2594 struct mslm_NetShareInfo_502 *info502; 2595 srvsvc_sd_t sd; 2596 uint8_t *netname; 2597 uint8_t *comment; 2598 uint8_t *passwd; 2599 uint8_t *path; 2600 int i = se->se_nitems; 2601 2602 netname = (uint8_t *)NDR_STRDUP(mxa, si->shr_name); 2603 comment = (uint8_t *)NDR_STRDUP(mxa, si->shr_cmnt); 2604 passwd = (uint8_t *)NDR_STRDUP(mxa, empty_string); 2605 path = (uint8_t *)srvsvc_share_mkpath(mxa, si->shr_path); 2606 2607 if (!netname || !comment || !passwd || !path) 2608 return (ERROR_NOT_ENOUGH_MEMORY); 2609 2610 switch (se->se_level) { 2611 case 0: 2612 info0 = (struct mslm_NetShareInfo_0 *)infop; 2613 info0[i].shi0_netname = netname; 2614 break; 2615 2616 case 1: 2617 info1 = (struct mslm_NetShareInfo_1 *)infop; 2618 info1[i].shi1_netname = netname; 2619 info1[i].shi1_comment = comment; 2620 info1[i].shi1_type = si->shr_type; 2621 break; 2622 2623 case 2: 2624 info2 = (struct mslm_NetShareInfo_2 *)infop; 2625 info2[i].shi2_netname = netname; 2626 info2[i].shi2_comment = comment; 2627 info2[i].shi2_path = path; 2628 info2[i].shi2_type = si->shr_type; 2629 info2[i].shi2_permissions = 0; 2630 info2[i].shi2_max_uses = SHI_USES_UNLIMITED; 2631 info2[i].shi2_current_uses = 0; 2632 info2[i].shi2_passwd = passwd; 2633 break; 2634 2635 case 501: 2636 info501 = (struct mslm_NetShareInfo_501 *)infop; 2637 info501[i].shi501_netname = netname; 2638 info501[i].shi501_comment = comment; 2639 info501[i].shi501_type = si->shr_type; 2640 info501[i].shi501_flags = srvsvc_get_share_flags(si); 2641 break; 2642 2643 case 502: 2644 info502 = (struct mslm_NetShareInfo_502 *)infop; 2645 info502[i].shi502_netname = netname; 2646 info502[i].shi502_comment = comment; 2647 info502[i].shi502_path = path; 2648 info502[i].shi502_type = si->shr_type; 2649 info502[i].shi502_permissions = 0; 2650 info502[i].shi502_max_uses = SHI_USES_UNLIMITED; 2651 info502[i].shi502_current_uses = 0; 2652 info502[i].shi502_passwd = passwd; 2653 2654 if (srvsvc_share_getsd(mxa, si, &sd) == ERROR_SUCCESS) { 2655 info502[i].shi502_reserved = sd.sd_size; 2656 info502[i].shi502_security_descriptor = sd.sd_buf; 2657 } else { 2658 info502[i].shi502_reserved = 0; 2659 info502[i].shi502_security_descriptor = NULL; 2660 } 2661 2662 break; 2663 2664 default: 2665 return (ERROR_INVALID_LEVEL); 2666 } 2667 2668 return (ERROR_SUCCESS); 2669 } 2670 2671 /* 2672 * srvsvc_add_autohome 2673 * 2674 * Add the autohome share for the user. The share must not be a permanent 2675 * share to avoid duplicates. 2676 */ 2677 static boolean_t 2678 srvsvc_add_autohome(ndr_xa_t *mxa, smb_svcenum_t *se, void *infop) 2679 { 2680 smb_netuserinfo_t *user = &mxa->pipe->np_user; 2681 char *username; 2682 smb_share_t si; 2683 DWORD status; 2684 struct passwd pw; 2685 char buf[NSS_LINELEN_PASSWD]; 2686 2687 if (IDMAP_ID_IS_EPHEMERAL(user->ui_posix_uid)) { 2688 username = user->ui_account; 2689 } else { 2690 if (getpwuid_r(user->ui_posix_uid, &pw, buf, sizeof (buf)) == 2691 NULL) 2692 return (B_FALSE); 2693 2694 username = pw.pw_name; 2695 } 2696 2697 if (smb_shr_get(username, &si) != NERR_Success) 2698 return (B_FALSE); 2699 2700 if ((si.shr_flags & SMB_SHRF_AUTOHOME) == 0) 2701 return (B_FALSE); 2702 2703 status = mlsvc_NetShareEnumCommon(mxa, se, &si, infop); 2704 return (status == ERROR_SUCCESS); 2705 } 2706 2707 /* 2708 * srvsvc_share_mkpath 2709 * 2710 * Create the share path required by the share enum calls. The path 2711 * is created in a heap buffer ready for use by the caller. 2712 * 2713 * Some Windows over-the-wire backup applications do not work unless a 2714 * drive letter is present in the share path. We don't care about the 2715 * drive letter since the path is fully qualified with the volume name. 2716 * 2717 * Windows clients seem to be mostly okay with forward slashes in 2718 * share paths but they cannot handle one immediately after the drive 2719 * letter, i.e. B:/. For consistency we convert all the slashes in 2720 * the path. 2721 * 2722 * Returns a pointer to a heap buffer containing the share path, which 2723 * could be a null pointer if the heap allocation fails. 2724 */ 2725 static char * 2726 srvsvc_share_mkpath(ndr_xa_t *mxa, char *path) 2727 { 2728 char tmpbuf[MAXPATHLEN]; 2729 char *p; 2730 char drive_letter; 2731 2732 if (strlen(path) == 0) 2733 return (NDR_STRDUP(mxa, path)); 2734 2735 drive_letter = smb_shr_drive_letter(path); 2736 if (drive_letter != '\0') { 2737 (void) snprintf(tmpbuf, MAXPATHLEN, "%c:\\", drive_letter); 2738 return (NDR_STRDUP(mxa, tmpbuf)); 2739 } 2740 2741 /* 2742 * Strip the volume name from the path (/vol1/home -> /home). 2743 */ 2744 p = path; 2745 p += strspn(p, "/"); 2746 p += strcspn(p, "/"); 2747 p += strspn(p, "/"); 2748 (void) snprintf(tmpbuf, MAXPATHLEN, "%c:/%s", 'B', p); 2749 (void) strsubst(tmpbuf, '/', '\\'); 2750 2751 return (NDR_STRDUP(mxa, tmpbuf)); 2752 } 2753 2754 static int 2755 srvsvc_s_NetShareCheck(void *arg, ndr_xa_t *mxa) 2756 { 2757 struct mslm_NetShareCheck *param = arg; 2758 smb_shriter_t iterator; 2759 smb_share_t *si; 2760 char *path; 2761 2762 if (param->path == NULL) { 2763 param->stype = STYPE_DISKTREE; 2764 param->status = NERR_NetNameNotFound; 2765 return (NDR_DRC_OK); 2766 } 2767 2768 (void) strsubst((char *)param->path, '/', '\\'); 2769 2770 smb_shr_iterinit(&iterator); 2771 2772 while ((si = smb_shr_iterate(&iterator)) != NULL) { 2773 path = srvsvc_share_mkpath(mxa, si->shr_path); 2774 2775 if (smb_strcasecmp(path, (char *)param->path, 0) == 0) { 2776 param->stype = (si->shr_type & STYPE_MASK); 2777 param->status = NERR_Success; 2778 return (NDR_DRC_OK); 2779 } 2780 } 2781 2782 param->stype = STYPE_DISKTREE; 2783 param->status = NERR_NetNameNotFound; 2784 return (NDR_DRC_OK); 2785 } 2786 2787 /* 2788 * Delete a share. Only members of the Administrators, Server Operators 2789 * or Power Users local groups are allowed to delete shares. 2790 * 2791 * This interface is used by the rmtshare command from the NT resource 2792 * kit. Rmtshare allows a client to add or remove shares on a server 2793 * from the client's command line. 2794 * 2795 * Returns Win32 error codes. 2796 */ 2797 static int 2798 srvsvc_s_NetShareDel(void *arg, ndr_xa_t *mxa) 2799 { 2800 struct mslm_NetShareDel *param = arg; 2801 smb_share_t si; 2802 2803 if (!ndr_is_poweruser(mxa) || 2804 smb_shr_is_restricted((char *)param->netname)) { 2805 param->status = ERROR_ACCESS_DENIED; 2806 return (NDR_DRC_OK); 2807 } 2808 2809 if (smb_shr_get((char *)param->netname, &si) == NERR_Success) { 2810 if (si.shr_flags & SMB_SHRF_DFSROOT) { 2811 param->status = NERR_IsDfsShare; 2812 return (NDR_DRC_OK); 2813 } 2814 } 2815 2816 param->status = srvsvc_sa_delete((char *)param->netname); 2817 return (NDR_DRC_OK); 2818 } 2819 2820 /* 2821 * srvsvc_s_NetGetFileSecurity 2822 * 2823 * Get security descriptor of the requested file/folder 2824 * 2825 * Right now, just returns ERROR_ACCESS_DENIED, because we cannot 2826 * get the requested SD here in RPC code. 2827 */ 2828 /*ARGSUSED*/ 2829 static int 2830 srvsvc_s_NetGetFileSecurity(void *arg, ndr_xa_t *mxa) 2831 { 2832 struct mslm_NetGetFileSecurity *param = arg; 2833 2834 param->length = 0; 2835 param->status = ERROR_ACCESS_DENIED; 2836 return (NDR_DRC_OK); 2837 } 2838 2839 /* 2840 * srvsvc_s_NetSetFileSecurity 2841 * 2842 * Set the given security descriptor for the requested file/folder 2843 * 2844 * Right now, just returns ERROR_ACCESS_DENIED, because we cannot 2845 * set the requested SD here in RPC code. 2846 */ 2847 /*ARGSUSED*/ 2848 static int 2849 srvsvc_s_NetSetFileSecurity(void *arg, ndr_xa_t *mxa) 2850 { 2851 struct mslm_NetSetFileSecurity *param = arg; 2852 2853 param->status = ERROR_ACCESS_DENIED; 2854 return (NDR_DRC_OK); 2855 } 2856 2857 /* 2858 * If the default "smb" share group exists then return the group 2859 * handle, otherwise create the group and return the handle. 2860 * 2861 * All shares created via the srvsvc will be added to the "smb" 2862 * group. 2863 */ 2864 static sa_group_t 2865 srvsvc_sa_get_smbgrp(sa_handle_t handle) 2866 { 2867 sa_group_t group = NULL; 2868 int err; 2869 2870 group = sa_get_group(handle, SMB_DEFAULT_SHARE_GROUP); 2871 if (group != NULL) 2872 return (group); 2873 2874 group = sa_create_group(handle, SMB_DEFAULT_SHARE_GROUP, &err); 2875 if (group == NULL) 2876 return (NULL); 2877 2878 if (sa_create_optionset(group, SMB_DEFAULT_SHARE_GROUP) == NULL) { 2879 (void) sa_remove_group(group); 2880 group = NULL; 2881 } 2882 2883 return (group); 2884 } 2885 2886 /* 2887 * Stores the given share in sharemgr 2888 */ 2889 static uint32_t 2890 srvsvc_sa_add(char *sharename, char *path, char *cmnt) 2891 { 2892 sa_handle_t handle; 2893 sa_share_t share; 2894 sa_group_t group; 2895 sa_resource_t resource; 2896 boolean_t new_share = B_FALSE; 2897 uint32_t status = NERR_Success; 2898 int err; 2899 2900 if ((handle = smb_shr_sa_enter()) == NULL) 2901 return (NERR_InternalError); 2902 2903 share = sa_find_share(handle, path); 2904 if (share == NULL) { 2905 group = srvsvc_sa_get_smbgrp(handle); 2906 if (group == NULL) { 2907 smb_shr_sa_exit(); 2908 return (NERR_InternalError); 2909 } 2910 2911 share = sa_add_share(group, path, SA_SHARE_PERMANENT, &err); 2912 if (share == NULL) { 2913 smb_shr_sa_exit(); 2914 return (NERR_InternalError); 2915 } 2916 new_share = B_TRUE; 2917 } 2918 2919 resource = sa_get_share_resource(share, sharename); 2920 if (resource == NULL) { 2921 resource = sa_add_resource(share, sharename, 2922 SA_SHARE_PERMANENT, &err); 2923 if (resource == NULL) { 2924 if (new_share) 2925 (void) sa_remove_share(share); 2926 smb_shr_sa_exit(); 2927 return (NERR_InternalError); 2928 } 2929 } 2930 2931 (void) sa_set_resource_description(resource, cmnt); 2932 2933 smb_shr_sa_exit(); 2934 return (status); 2935 } 2936 2937 /* 2938 * Removes the share from sharemgr 2939 */ 2940 static uint32_t 2941 srvsvc_sa_delete(char *sharename) 2942 { 2943 sa_handle_t handle; 2944 sa_resource_t resource; 2945 uint32_t status; 2946 2947 if ((handle = smb_shr_sa_enter()) == NULL) 2948 return (NERR_InternalError); 2949 2950 status = NERR_InternalError; 2951 if ((resource = sa_find_resource(handle, sharename)) != NULL) { 2952 if (sa_remove_resource(resource) == SA_OK) 2953 status = NERR_Success; 2954 } 2955 2956 smb_shr_sa_exit(); 2957 return (status); 2958 } 2959 2960 /* 2961 * Update the share information. 2962 */ 2963 static uint32_t 2964 srvsvc_sa_modify(smb_share_t *si, srvsvc_netshare_setinfo_t *info) 2965 { 2966 sa_handle_t handle; 2967 sa_share_t share; 2968 sa_resource_t resource; 2969 boolean_t renamed = B_FALSE, is_zfs = B_FALSE; 2970 nvlist_t *nvl; 2971 uint32_t nerr = NERR_Success; 2972 2973 if ((handle = smb_shr_sa_enter()) == NULL) 2974 return (NERR_InternalError); 2975 2976 if ((share = sa_find_share(handle, si->shr_path)) == NULL) { 2977 smb_shr_sa_exit(); 2978 return (NERR_InternalError); 2979 } 2980 2981 if ((resource = sa_get_share_resource(share, si->shr_name)) == NULL) { 2982 smb_shr_sa_exit(); 2983 return (NERR_InternalError); 2984 } 2985 2986 if (sa_group_is_zfs(sa_get_parent_group(share))) { 2987 is_zfs = B_TRUE; 2988 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { 2989 smb_shr_sa_exit(); 2990 return (NERR_InternalError); 2991 } 2992 } 2993 2994 if (info->nss_netname != NULL && info->nss_netname[0] != '\0' && 2995 smb_strcasecmp(info->nss_netname, si->shr_name, 0) != 0) { 2996 if (is_zfs) 2997 (void) nvlist_add_string(nvl, SHOPT_NAME, 2998 info->nss_netname); 2999 else 3000 (void) sa_set_resource_attr(resource, SHOPT_NAME, 3001 info->nss_netname); 3002 renamed = B_TRUE; 3003 } 3004 3005 if ((info->nss_comment != NULL) && 3006 (strcmp(info->nss_comment, si->shr_cmnt) != 0)) { 3007 if (is_zfs) 3008 (void) nvlist_add_string(nvl, SHOPT_DESCRIPTION, 3009 info->nss_comment); 3010 else 3011 (void) sa_set_resource_description(resource, 3012 info->nss_comment); 3013 (void) strlcpy(si->shr_cmnt, info->nss_comment, 3014 SMB_SHARE_CMNT_MAX); 3015 } 3016 3017 if (is_zfs) { 3018 if (sa_zfs_setprop(handle, si->shr_path, nvl) != 0) { 3019 smb_shr_sa_exit(); 3020 nvlist_free(nvl); 3021 return (NERR_InternalError); 3022 } 3023 nvlist_free(nvl); 3024 } 3025 smb_shr_sa_exit(); 3026 3027 if (renamed) { 3028 nerr = smb_shr_rename(si->shr_name, info->nss_netname); 3029 if (nerr != NERR_Success) 3030 return (nerr); 3031 3032 (void) strlcpy(si->shr_name, info->nss_netname, MAXNAMELEN); 3033 } 3034 3035 return (nerr); 3036 } 3037 3038 /* 3039 * Sets the share properties. 3040 * 3041 * This method sets share properties. If its a ZFS share, then properties 3042 * are set by calling the sa_zfs_setprop method. Else the optionset properties 3043 * of the share resource are set.The properties to be set are given as a list 3044 * of name-value pair. 3045 */ 3046 static uint32_t 3047 srvsvc_sa_setprop(smb_share_t *si, nvlist_t *nvl) 3048 { 3049 sa_handle_t handle; 3050 sa_share_t share; 3051 sa_resource_t resource; 3052 sa_property_t prop; 3053 sa_optionset_t opts; 3054 uint32_t nerr = NERR_Success; 3055 nvpair_t *cur; 3056 int err = 0; 3057 char *name, *val; 3058 3059 if ((handle = sa_init(SA_INIT_SHARE_API)) == NULL) 3060 return (NERR_InternalError); 3061 3062 if ((share = sa_find_share(handle, si->shr_path)) == NULL) { 3063 sa_fini(handle); 3064 return (NERR_InternalError); 3065 } 3066 3067 if ((resource = sa_get_share_resource(share, si->shr_name)) == NULL) { 3068 sa_fini(handle); 3069 return (NERR_InternalError); 3070 } 3071 3072 if (sa_group_is_zfs(sa_get_parent_group(share))) { 3073 if (sa_zfs_setprop(handle, si->shr_path, nvl) != 0) 3074 nerr = NERR_InternalError; 3075 sa_fini(handle); 3076 return (nerr); 3077 } 3078 3079 if ((opts = sa_get_optionset(resource, SMB_PROTOCOL_NAME)) == NULL) { 3080 opts = sa_create_optionset(resource, SMB_PROTOCOL_NAME); 3081 if (opts == NULL) { 3082 sa_fini(handle); 3083 return (NERR_InternalError); 3084 } 3085 } 3086 3087 cur = nvlist_next_nvpair(nvl, NULL); 3088 while (cur != NULL) { 3089 name = nvpair_name(cur); 3090 err = nvpair_value_string(cur, &val); 3091 if ((err != 0) || (name == NULL) || (val == NULL)) { 3092 nerr = NERR_InternalError; 3093 break; 3094 } 3095 3096 prop = NULL; 3097 if ((prop = sa_get_property(opts, name)) == NULL) { 3098 prop = sa_create_property(name, val); 3099 if (prop != NULL) { 3100 nerr = sa_valid_property(handle, opts, 3101 SMB_PROTOCOL_NAME, prop); 3102 if (nerr != NERR_Success) { 3103 (void) sa_remove_property(prop); 3104 break; 3105 } 3106 } 3107 nerr = sa_add_property(opts, prop); 3108 if (nerr != NERR_Success) 3109 break; 3110 } else { 3111 nerr = sa_update_property(prop, val); 3112 if (nerr != NERR_Success) 3113 break; 3114 } 3115 3116 cur = nvlist_next_nvpair(nvl, cur); 3117 } 3118 3119 if (nerr == NERR_Success) 3120 nerr = sa_commit_properties(opts, 0); 3121 3122 sa_fini(handle); 3123 return (nerr); 3124 } 3125 3126 static ndr_stub_table_t srvsvc_stub_table[] = { 3127 { srvsvc_s_NetConnectEnum, SRVSVC_OPNUM_NetConnectEnum }, 3128 { srvsvc_s_NetFileEnum, SRVSVC_OPNUM_NetFileEnum }, 3129 { srvsvc_s_NetFileClose, SRVSVC_OPNUM_NetFileClose }, 3130 { srvsvc_s_NetShareGetInfo, SRVSVC_OPNUM_NetShareGetInfo }, 3131 { srvsvc_s_NetShareSetInfo, SRVSVC_OPNUM_NetShareSetInfo }, 3132 { srvsvc_s_NetSessionEnum, SRVSVC_OPNUM_NetSessionEnum }, 3133 { srvsvc_s_NetSessionDel, SRVSVC_OPNUM_NetSessionDel }, 3134 { srvsvc_s_NetServerGetInfo, SRVSVC_OPNUM_NetServerGetInfo }, 3135 { srvsvc_s_NetRemoteTOD, SRVSVC_OPNUM_NetRemoteTOD }, 3136 { srvsvc_s_NetNameValidate, SRVSVC_OPNUM_NetNameValidate }, 3137 { srvsvc_s_NetShareAdd, SRVSVC_OPNUM_NetShareAdd }, 3138 { srvsvc_s_NetShareDel, SRVSVC_OPNUM_NetShareDel }, 3139 { srvsvc_s_NetShareEnum, SRVSVC_OPNUM_NetShareEnum }, 3140 { srvsvc_s_NetShareEnumSticky, SRVSVC_OPNUM_NetShareEnumSticky }, 3141 { srvsvc_s_NetShareCheck, SRVSVC_OPNUM_NetShareCheck }, 3142 { srvsvc_s_NetGetFileSecurity, SRVSVC_OPNUM_NetGetFileSecurity }, 3143 { srvsvc_s_NetSetFileSecurity, SRVSVC_OPNUM_NetSetFileSecurity }, 3144 {0} 3145 }; 3146