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