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