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