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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* 26 * SMB/CIFS share cache implementation. 27 */ 28 29 #include <errno.h> 30 #include <synch.h> 31 #include <stdlib.h> 32 #include <strings.h> 33 #include <syslog.h> 34 #include <thread.h> 35 #include <pthread.h> 36 #include <assert.h> 37 #include <libshare.h> 38 #include <libzfs.h> 39 #include <priv_utils.h> 40 #include <sys/types.h> 41 #include <sys/wait.h> 42 #include <unistd.h> 43 #include <pwd.h> 44 #include <signal.h> 45 #include <dirent.h> 46 47 #include <smbsrv/libsmb.h> 48 #include <smbsrv/libsmbns.h> 49 #include <smbsrv/libmlsvc.h> 50 #include <smbsrv/smb_share.h> 51 #include <smbsrv/smb.h> 52 #include <mlsvc.h> 53 #include <dfs.h> 54 55 #define SMB_SHR_ERROR_THRESHOLD 3 56 #define SMB_SHR_CSC_BUFSZ 64 57 58 typedef struct smb_transient { 59 char *name; 60 char *cmnt; 61 char *path; 62 char drive; 63 boolean_t check; 64 } smb_transient_t; 65 66 static smb_transient_t tshare[] = { 67 { "IPC$", "Remote IPC", NULL, '\0', B_FALSE }, 68 { "c$", "Default Share", SMB_CVOL, 'C', B_FALSE }, 69 { "vss$", "VSS", SMB_VSS, 'V', B_TRUE } 70 }; 71 72 static struct { 73 char *value; 74 uint32_t flag; 75 } cscopt[] = { 76 { "disabled", SMB_SHRF_CSC_DISABLED }, 77 { "manual", SMB_SHRF_CSC_MANUAL }, 78 { "auto", SMB_SHRF_CSC_AUTO }, 79 { "vdo", SMB_SHRF_CSC_VDO } 80 }; 81 82 /* 83 * Cache functions and vars 84 */ 85 #define SMB_SHR_HTAB_SZ 1024 86 87 /* 88 * Cache handle 89 * 90 * Shares cache is a hash table. 91 * 92 * sc_cache pointer to hash table handle 93 * sc_cache_lck synchronize cache read/write accesses 94 * sc_state cache state machine values 95 * sc_nops number of inflight/pending cache operations 96 * sc_mtx protects handle fields 97 */ 98 typedef struct smb_shr_cache { 99 HT_HANDLE *sc_cache; 100 rwlock_t sc_cache_lck; 101 mutex_t sc_mtx; 102 cond_t sc_cv; 103 uint32_t sc_state; 104 uint32_t sc_nops; 105 } smb_shr_cache_t; 106 107 /* 108 * Cache states 109 */ 110 #define SMB_SHR_CACHE_STATE_NONE 0 111 #define SMB_SHR_CACHE_STATE_CREATED 1 112 #define SMB_SHR_CACHE_STATE_DESTROYING 2 113 114 /* 115 * Cache lock modes 116 */ 117 #define SMB_SHR_CACHE_RDLOCK 0 118 #define SMB_SHR_CACHE_WRLOCK 1 119 120 static smb_shr_cache_t smb_shr_cache; 121 122 static uint32_t smb_shr_cache_create(void); 123 static void smb_shr_cache_destroy(void); 124 static uint32_t smb_shr_cache_lock(int); 125 static void smb_shr_cache_unlock(void); 126 static int smb_shr_cache_count(void); 127 static smb_share_t *smb_shr_cache_iterate(smb_shriter_t *); 128 129 static smb_share_t *smb_shr_cache_findent(char *); 130 static uint32_t smb_shr_cache_addent(smb_share_t *); 131 static void smb_shr_cache_delent(char *); 132 static void smb_shr_cache_freent(HT_ITEM *); 133 134 static boolean_t smb_shr_is_empty(const char *); 135 static boolean_t smb_shr_is_dot_or_dotdot(const char *); 136 137 /* 138 * sharemgr functions 139 */ 140 static void *smb_shr_sa_loadall(void *); 141 static void smb_shr_sa_loadgrp(sa_group_t); 142 static uint32_t smb_shr_sa_load(sa_share_t, sa_resource_t); 143 static uint32_t smb_shr_sa_loadbyname(char *); 144 static uint32_t smb_shr_sa_get(sa_share_t, sa_resource_t, smb_share_t *); 145 146 /* 147 * .ZFS management functions 148 */ 149 static void smb_shr_zfs_add(smb_share_t *); 150 static void smb_shr_zfs_remove(smb_share_t *); 151 static void smb_shr_zfs_rename(smb_share_t *, smb_share_t *); 152 153 /* 154 * share publishing 155 */ 156 #define SMB_SHR_PUBLISH 0 157 #define SMB_SHR_UNPUBLISH 1 158 159 typedef struct smb_shr_pitem { 160 list_node_t spi_lnd; 161 char spi_name[MAXNAMELEN]; 162 char spi_container[MAXPATHLEN]; 163 char spi_op; 164 } smb_shr_pitem_t; 165 166 /* 167 * publish queue states 168 */ 169 #define SMB_SHR_PQS_NOQUEUE 0 170 #define SMB_SHR_PQS_READY 1 /* the queue is ready */ 171 #define SMB_SHR_PQS_PUBLISHING 2 /* publisher thread is running */ 172 #define SMB_SHR_PQS_STOPPING 3 173 174 /* 175 * share publishing queue 176 */ 177 typedef struct smb_shr_pqueue { 178 list_t spq_list; 179 mutex_t spq_mtx; 180 cond_t spq_cv; 181 uint32_t spq_state; 182 } smb_shr_pqueue_t; 183 184 static smb_shr_pqueue_t ad_queue; 185 186 static int smb_shr_publisher_start(void); 187 static void smb_shr_publisher_stop(void); 188 static void smb_shr_publisher_send(smb_ads_handle_t *, list_t *, const char *); 189 static void smb_shr_publisher_queue(const char *, const char *, char); 190 static void *smb_shr_publisher(void *); 191 static void smb_shr_publisher_flush(list_t *); 192 static void smb_shr_publish(const char *, const char *); 193 static void smb_shr_unpublish(const char *, const char *); 194 195 /* 196 * Utility/helper functions 197 */ 198 static uint32_t smb_shr_lookup(char *, smb_share_t *); 199 static uint32_t smb_shr_add_transient(char *, char *, char *); 200 static int smb_shr_enable_all_privs(void); 201 static int smb_shr_expand_subs(char **, smb_share_t *, smb_shr_execinfo_t *); 202 static char **smb_shr_tokenize_cmd(char *); 203 static void smb_shr_sig_abnormal_term(int); 204 static void smb_shr_sig_child(int); 205 static int smb_shr_encode(smb_share_t *, nvlist_t **); 206 207 /* 208 * libshare handle and synchronization 209 */ 210 typedef struct smb_sa_handle { 211 sa_handle_t sa_handle; 212 mutex_t sa_mtx; 213 boolean_t sa_in_service; 214 } smb_sa_handle_t; 215 216 static smb_sa_handle_t smb_sa_handle; 217 218 static char smb_shr_exec_map[MAXPATHLEN]; 219 static char smb_shr_exec_unmap[MAXPATHLEN]; 220 static mutex_t smb_shr_exec_mtx; 221 222 /* 223 * Semaphore held during temporary, process-wide changes 224 * such as process privileges. It is a seamaphore and 225 * not a mutex so a child of fork can reset it. 226 */ 227 static sema_t smb_proc_sem = DEFAULTSEMA; 228 229 /* 230 * Creates and initializes the cache and starts the publisher 231 * thread. 232 */ 233 int 234 smb_shr_start(void) 235 { 236 smb_transient_t *ts; 237 uint32_t nerr; 238 int i; 239 240 (void) mutex_lock(&smb_sa_handle.sa_mtx); 241 smb_sa_handle.sa_in_service = B_TRUE; 242 (void) mutex_unlock(&smb_sa_handle.sa_mtx); 243 244 if (smb_shr_cache_create() != NERR_Success) 245 return (ENOMEM); 246 247 for (i = 0; i < sizeof (tshare)/sizeof (tshare[0]); ++i) { 248 ts = &tshare[i]; 249 250 if (ts->check && smb_shr_is_empty(ts->path)) 251 continue; 252 253 nerr = smb_shr_add_transient(ts->name, ts->cmnt, ts->path); 254 if (nerr != NERR_Success) 255 return (ENOMEM); 256 } 257 258 return (smb_shr_publisher_start()); 259 } 260 261 void 262 smb_shr_stop(void) 263 { 264 smb_shr_cache_destroy(); 265 smb_shr_publisher_stop(); 266 267 (void) mutex_lock(&smb_sa_handle.sa_mtx); 268 smb_sa_handle.sa_in_service = B_FALSE; 269 270 if (smb_sa_handle.sa_handle != NULL) { 271 sa_fini(smb_sa_handle.sa_handle); 272 smb_sa_handle.sa_handle = NULL; 273 } 274 275 (void) mutex_unlock(&smb_sa_handle.sa_mtx); 276 } 277 278 /* 279 * Get a handle and exclusive access to the libshare API. 280 */ 281 sa_handle_t 282 smb_shr_sa_enter(void) 283 { 284 (void) mutex_lock(&smb_sa_handle.sa_mtx); 285 if (!smb_sa_handle.sa_in_service) { 286 (void) mutex_unlock(&smb_sa_handle.sa_mtx); 287 return (NULL); 288 } 289 290 if (smb_sa_handle.sa_handle == NULL) { 291 smb_sa_handle.sa_handle = sa_init(SA_INIT_SHARE_API); 292 if (smb_sa_handle.sa_handle == NULL) { 293 syslog(LOG_ERR, "share: failed to get libshare handle"); 294 (void) mutex_unlock(&smb_sa_handle.sa_mtx); 295 return (NULL); 296 } 297 } 298 299 return (smb_sa_handle.sa_handle); 300 } 301 302 /* 303 * Release exclusive access to the libshare API. 304 */ 305 void 306 smb_shr_sa_exit(void) 307 { 308 (void) mutex_unlock(&smb_sa_handle.sa_mtx); 309 } 310 311 /* 312 * Launches a thread to populate the share cache by share information 313 * stored in sharemgr 314 */ 315 int 316 smb_shr_load(void) 317 { 318 pthread_t load_thr; 319 pthread_attr_t tattr; 320 int rc; 321 322 (void) pthread_attr_init(&tattr); 323 (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 324 rc = pthread_create(&load_thr, &tattr, smb_shr_sa_loadall, 0); 325 (void) pthread_attr_destroy(&tattr); 326 327 (void) mutex_lock(&smb_shr_exec_mtx); 328 (void) smb_config_get_execinfo(smb_shr_exec_map, smb_shr_exec_unmap, 329 MAXPATHLEN); 330 (void) mutex_unlock(&smb_shr_exec_mtx); 331 332 return (rc); 333 } 334 335 /* 336 * Return the total number of shares 337 */ 338 int 339 smb_shr_count(void) 340 { 341 int n_shares = 0; 342 343 if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 344 n_shares = smb_shr_cache_count(); 345 smb_shr_cache_unlock(); 346 } 347 348 return (n_shares); 349 } 350 351 /* 352 * smb_shr_iterinit 353 * 354 * Initialize given iterator for traversing hash table. 355 */ 356 void 357 smb_shr_iterinit(smb_shriter_t *shi) 358 { 359 bzero(shi, sizeof (smb_shriter_t)); 360 shi->si_first = B_TRUE; 361 } 362 363 /* 364 * smb_shr_iterate 365 * 366 * Iterate on the shares in the hash table. The iterator must be initialized 367 * before the first iteration. On subsequent calls, the iterator must be 368 * passed unchanged. 369 * 370 * Returns NULL on failure or when all shares are visited, otherwise 371 * returns information of visited share. 372 */ 373 smb_share_t * 374 smb_shr_iterate(smb_shriter_t *shi) 375 { 376 smb_share_t *share = NULL; 377 smb_share_t *cached_si; 378 379 if (shi == NULL) 380 return (NULL); 381 382 if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 383 if ((cached_si = smb_shr_cache_iterate(shi)) != NULL) { 384 share = &shi->si_share; 385 bcopy(cached_si, share, sizeof (smb_share_t)); 386 } 387 smb_shr_cache_unlock(); 388 } 389 390 return (share); 391 } 392 393 /* 394 * Adds the given share to cache, publishes the share in ADS 395 * if it has an AD container, calls kernel to take a hold on 396 * the shared file system. If it can't take a hold on the 397 * shared file system, it's either because shared directory 398 * does not exist or some other error has occurred, in any 399 * case the share is removed from the cache. 400 * 401 * If the specified share is an autohome share which already 402 * exists in the cache, just increments the reference count. 403 */ 404 uint32_t 405 smb_shr_add(smb_share_t *si) 406 { 407 smb_share_t *cached_si; 408 nvlist_t *shrlist; 409 uint32_t status; 410 int rc; 411 412 assert(si != NULL); 413 414 if (smb_name_validate_share(si->shr_name) != ERROR_SUCCESS) 415 return (ERROR_INVALID_NAME); 416 417 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 418 return (NERR_InternalError); 419 420 cached_si = smb_shr_cache_findent(si->shr_name); 421 if (cached_si) { 422 if (si->shr_flags & SMB_SHRF_AUTOHOME) { 423 cached_si->shr_refcnt++; 424 status = NERR_Success; 425 } else { 426 status = NERR_DuplicateShare; 427 } 428 smb_shr_cache_unlock(); 429 return (status); 430 } 431 432 if ((status = smb_shr_cache_addent(si)) != NERR_Success) { 433 smb_shr_cache_unlock(); 434 return (status); 435 } 436 437 /* don't hold the lock across door call */ 438 smb_shr_cache_unlock(); 439 440 if ((rc = smb_shr_encode(si, &shrlist)) == 0) { 441 /* send the share to kernel */ 442 rc = smb_kmod_share(shrlist); 443 nvlist_free(shrlist); 444 445 if (rc == 0) { 446 smb_shr_publish(si->shr_name, si->shr_container); 447 448 /* If path is ZFS, add the .zfs/shares/<share> entry. */ 449 smb_shr_zfs_add(si); 450 451 return (NERR_Success); 452 } 453 } 454 455 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) { 456 smb_shr_cache_delent(si->shr_name); 457 smb_shr_cache_unlock(); 458 } 459 460 /* 461 * rc == ENOENT means the shared directory doesn't exist 462 */ 463 return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError); 464 } 465 466 /* 467 * Removes the specified share from cache, removes it from AD 468 * if it has an AD container, and calls the kernel to release 469 * the hold on the shared file system. 470 * 471 * If this is an autohome share then decrement the reference 472 * count. If it reaches 0 then it proceeds with removing steps. 473 */ 474 uint32_t 475 smb_shr_remove(char *sharename) 476 { 477 smb_share_t *si; 478 char container[MAXPATHLEN]; 479 boolean_t dfsroot; 480 nvlist_t *shrlist; 481 482 assert(sharename != NULL); 483 484 if (smb_name_validate_share(sharename) != ERROR_SUCCESS) 485 return (ERROR_INVALID_NAME); 486 487 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 488 return (NERR_InternalError); 489 490 if ((si = smb_shr_cache_findent(sharename)) == NULL) { 491 smb_shr_cache_unlock(); 492 return (NERR_NetNameNotFound); 493 } 494 495 if (si->shr_type & STYPE_IPC) { 496 /* IPC$ share cannot be removed */ 497 smb_shr_cache_unlock(); 498 return (ERROR_ACCESS_DENIED); 499 } 500 501 if (si->shr_flags & SMB_SHRF_AUTOHOME) { 502 if ((--si->shr_refcnt) > 0) { 503 smb_shr_cache_unlock(); 504 return (NERR_Success); 505 } 506 } 507 508 /* 509 * If path is ZFS, remove the .zfs/shares/<share> entry. Need 510 * to remove before cleanup of cache occurs. 511 */ 512 smb_shr_zfs_remove(si); 513 (void) smb_shr_encode(si, &shrlist); 514 515 (void) strlcpy(container, si->shr_container, sizeof (container)); 516 dfsroot = ((si->shr_flags & SMB_SHRF_DFSROOT) != 0); 517 smb_shr_cache_delent(sharename); 518 smb_shr_cache_unlock(); 519 520 smb_shr_unpublish(sharename, container); 521 522 /* call kernel to release the hold on the shared file system */ 523 if (shrlist != NULL) { 524 (void) smb_kmod_unshare(shrlist); 525 nvlist_free(shrlist); 526 } 527 528 if (dfsroot) 529 dfs_namespace_unload(sharename); 530 531 return (NERR_Success); 532 } 533 534 /* 535 * Rename a share. Check that the current name exists and the new name 536 * doesn't exist. The rename is performed by deleting the current share 537 * definition and creating a new share with the new name. 538 */ 539 uint32_t 540 smb_shr_rename(char *from_name, char *to_name) 541 { 542 smb_share_t *from_si; 543 smb_share_t to_si; 544 uint32_t status; 545 nvlist_t *shrlist; 546 547 assert((from_name != NULL) && (to_name != NULL)); 548 549 if (smb_name_validate_share(from_name) != ERROR_SUCCESS || 550 smb_name_validate_share(to_name) != ERROR_SUCCESS) 551 return (ERROR_INVALID_NAME); 552 553 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 554 return (NERR_InternalError); 555 556 if ((from_si = smb_shr_cache_findent(from_name)) == NULL) { 557 smb_shr_cache_unlock(); 558 return (NERR_NetNameNotFound); 559 } 560 561 if (from_si->shr_type & STYPE_IPC) { 562 /* IPC$ share cannot be renamed */ 563 smb_shr_cache_unlock(); 564 return (ERROR_ACCESS_DENIED); 565 } 566 567 if (smb_shr_cache_findent(to_name) != NULL) { 568 smb_shr_cache_unlock(); 569 return (NERR_DuplicateShare); 570 } 571 572 bcopy(from_si, &to_si, sizeof (smb_share_t)); 573 (void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name)); 574 575 /* If path is ZFS, rename the .zfs/shares/<share> entry. */ 576 smb_shr_zfs_rename(from_si, &to_si); 577 578 if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) { 579 smb_shr_cache_unlock(); 580 return (status); 581 } 582 583 smb_shr_cache_delent(from_name); 584 smb_shr_cache_unlock(); 585 586 if (smb_shr_encode(from_si, &shrlist) == 0) { 587 (void) smb_kmod_unshare(shrlist); 588 nvlist_free(shrlist); 589 590 if (smb_shr_encode(&to_si, &shrlist) == 0) { 591 (void) smb_kmod_share(shrlist); 592 nvlist_free(shrlist); 593 } 594 } 595 596 smb_shr_unpublish(from_name, to_si.shr_container); 597 smb_shr_publish(to_name, to_si.shr_container); 598 599 return (NERR_Success); 600 } 601 602 /* 603 * Load the information for the specified share into the supplied share 604 * info structure. 605 * 606 * First looks up the cache to see if the specified share exists, if there 607 * is a miss then it looks up sharemgr. 608 */ 609 uint32_t 610 smb_shr_get(char *sharename, smb_share_t *si) 611 { 612 uint32_t status; 613 614 if (sharename == NULL || *sharename == '\0') 615 return (NERR_NetNameNotFound); 616 617 if ((status = smb_shr_lookup(sharename, si)) == NERR_Success) 618 return (status); 619 620 if ((status = smb_shr_sa_loadbyname(sharename)) == NERR_Success) 621 status = smb_shr_lookup(sharename, si); 622 623 return (status); 624 } 625 626 /* 627 * Modifies an existing share. Properties that can be modified are: 628 * 629 * o comment 630 * o AD container 631 * o host access 632 * o abe 633 */ 634 uint32_t 635 smb_shr_modify(smb_share_t *new_si) 636 { 637 smb_share_t *si; 638 boolean_t adc_changed = B_FALSE; 639 char old_container[MAXPATHLEN]; 640 uint32_t access, flag; 641 nvlist_t *shrlist; 642 643 assert(new_si != NULL); 644 645 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 646 return (NERR_InternalError); 647 648 if ((si = smb_shr_cache_findent(new_si->shr_name)) == NULL) { 649 smb_shr_cache_unlock(); 650 return (NERR_NetNameNotFound); 651 } 652 653 if (si->shr_type & STYPE_IPC) { 654 /* IPC$ share cannot be modified */ 655 smb_shr_cache_unlock(); 656 return (ERROR_ACCESS_DENIED); 657 } 658 659 (void) strlcpy(si->shr_cmnt, new_si->shr_cmnt, sizeof (si->shr_cmnt)); 660 661 adc_changed = (strcmp(new_si->shr_container, si->shr_container) != 0); 662 if (adc_changed) { 663 /* save current container - needed for unpublishing */ 664 (void) strlcpy(old_container, si->shr_container, 665 sizeof (old_container)); 666 (void) strlcpy(si->shr_container, new_si->shr_container, 667 sizeof (si->shr_container)); 668 } 669 670 flag = (new_si->shr_flags & SMB_SHRF_ABE); 671 si->shr_flags &= ~SMB_SHRF_ABE; 672 si->shr_flags |= flag; 673 674 flag = (new_si->shr_flags & SMB_SHRF_CATIA); 675 si->shr_flags &= ~SMB_SHRF_CATIA; 676 si->shr_flags |= flag; 677 678 flag = (new_si->shr_flags & SMB_SHRF_GUEST_OK); 679 si->shr_flags &= ~SMB_SHRF_GUEST_OK; 680 si->shr_flags |= flag; 681 682 flag = (new_si->shr_flags & SMB_SHRF_DFSROOT); 683 si->shr_flags &= ~SMB_SHRF_DFSROOT; 684 si->shr_flags |= flag; 685 686 flag = (new_si->shr_flags & SMB_SHRF_CSC_MASK); 687 si->shr_flags &= ~SMB_SHRF_CSC_MASK; 688 si->shr_flags |= flag; 689 690 access = (new_si->shr_flags & SMB_SHRF_ACC_ALL); 691 si->shr_flags &= ~SMB_SHRF_ACC_ALL; 692 si->shr_flags |= access; 693 694 if (access & SMB_SHRF_ACC_NONE) 695 (void) strlcpy(si->shr_access_none, new_si->shr_access_none, 696 sizeof (si->shr_access_none)); 697 698 if (access & SMB_SHRF_ACC_RO) 699 (void) strlcpy(si->shr_access_ro, new_si->shr_access_ro, 700 sizeof (si->shr_access_ro)); 701 702 if (access & SMB_SHRF_ACC_RW) 703 (void) strlcpy(si->shr_access_rw, new_si->shr_access_rw, 704 sizeof (si->shr_access_rw)); 705 706 smb_shr_cache_unlock(); 707 708 if (smb_shr_encode(si, &shrlist) == 0) { 709 (void) smb_kmod_unshare(shrlist); 710 nvlist_free(shrlist); 711 712 if (smb_shr_encode(new_si, &shrlist) == 0) { 713 (void) smb_kmod_share(shrlist); 714 nvlist_free(shrlist); 715 } 716 } 717 718 if (adc_changed) { 719 smb_shr_unpublish(new_si->shr_name, old_container); 720 smb_shr_publish(new_si->shr_name, new_si->shr_container); 721 } 722 723 return (NERR_Success); 724 } 725 726 /* 727 * smb_shr_exists 728 * 729 * Returns B_TRUE if the share exists. Otherwise returns B_FALSE 730 */ 731 boolean_t 732 smb_shr_exists(char *sharename) 733 { 734 boolean_t exists = B_FALSE; 735 736 if (sharename == NULL || *sharename == '\0') 737 return (B_FALSE); 738 739 if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 740 exists = (smb_shr_cache_findent(sharename) != NULL); 741 smb_shr_cache_unlock(); 742 } 743 744 return (exists); 745 } 746 747 /* 748 * If the shared directory does not begin with a /, one will be 749 * inserted as a prefix. If ipaddr is not zero, then also return 750 * information about access based on the host level access lists, if 751 * present. Also return access check if there is an IP address and 752 * shr_accflags. 753 * 754 * The value of smb_chk_hostaccess is checked for an access match. 755 * -1 is wildcard match 756 * 0 is no match 757 * 1 is match 758 * 759 * Precedence is none is checked first followed by ro then rw if 760 * needed. If x is wildcard (< 0) then check to see if the other 761 * values are a match. If a match, that wins. 762 * 763 * ipv6 is wide open (returns SMB_SHRF_ACC_OPEN) for now until the underlying 764 * functions support ipv6. 765 */ 766 uint32_t 767 smb_shr_hostaccess(smb_inaddr_t *ipaddr, char *none_list, char *ro_list, 768 char *rw_list, uint32_t flag) 769 { 770 uint32_t acc = SMB_SHRF_ACC_NONE; 771 int none = 0; 772 int ro = 0; 773 int rw = 0; 774 775 if (!smb_inet_iszero(ipaddr)) { 776 777 if (ipaddr->a_family == AF_INET6) 778 return (SMB_SHRF_ACC_OPEN); 779 780 if ((flag & SMB_SHRF_ACC_NONE) != 0) 781 none = smb_chk_hostaccess(ipaddr, none_list); 782 if ((flag & SMB_SHRF_ACC_RO) != 0) 783 ro = smb_chk_hostaccess(ipaddr, ro_list); 784 if ((flag & SMB_SHRF_ACC_RW) != 0) 785 rw = smb_chk_hostaccess(ipaddr, rw_list); 786 787 /* make first pass to get basic value */ 788 if (none != 0) 789 acc = SMB_SHRF_ACC_NONE; 790 else if (ro != 0) 791 acc = SMB_SHRF_ACC_RO; 792 else if (rw != 0) 793 acc = SMB_SHRF_ACC_RW; 794 795 /* make second pass to handle '*' case */ 796 if (none < 0) { 797 acc = SMB_SHRF_ACC_NONE; 798 if (ro > 0) 799 acc = SMB_SHRF_ACC_RO; 800 else if (rw > 0) 801 acc = SMB_SHRF_ACC_RW; 802 } else if (ro < 0) { 803 acc = SMB_SHRF_ACC_RO; 804 if (none > 0) 805 acc = SMB_SHRF_ACC_NONE; 806 else if (rw > 0) 807 acc = SMB_SHRF_ACC_RW; 808 } else if (rw < 0) { 809 acc = SMB_SHRF_ACC_RW; 810 if (none > 0) 811 acc = SMB_SHRF_ACC_NONE; 812 else if (ro > 0) 813 acc = SMB_SHRF_ACC_RO; 814 } 815 } 816 817 return (acc); 818 } 819 820 /* 821 * smb_shr_is_special 822 * 823 * Special share reserved for interprocess communication (IPC$) or 824 * remote administration of the server (ADMIN$). Can also refer to 825 * administrative shares such as C$, D$, E$, and so forth. 826 */ 827 int 828 smb_shr_is_special(char *sharename) 829 { 830 int len; 831 832 if (sharename == NULL) 833 return (0); 834 835 if ((len = strlen(sharename)) == 0) 836 return (0); 837 838 if (sharename[len - 1] == '$') 839 return (STYPE_SPECIAL); 840 841 return (0); 842 } 843 844 /* 845 * smb_shr_is_restricted 846 * 847 * Check whether or not there is a restriction on a share. Restricted 848 * shares are generally STYPE_SPECIAL, for example, IPC$. All the 849 * administration share names are restricted: C$, D$ etc. Returns B_TRUE 850 * if the share is restricted. Otherwise B_FALSE is returned to indicate 851 * that there are no restrictions. 852 */ 853 boolean_t 854 smb_shr_is_restricted(char *sharename) 855 { 856 static char *restricted[] = { 857 "IPC$" 858 }; 859 860 int i; 861 862 if (sharename == NULL) 863 return (B_FALSE); 864 865 for (i = 0; i < sizeof (restricted)/sizeof (restricted[0]); i++) { 866 if (smb_strcasecmp(restricted[i], sharename, 0) == 0) 867 return (B_TRUE); 868 } 869 870 return (smb_shr_is_admin(sharename)); 871 } 872 873 /* 874 * smb_shr_is_admin 875 * 876 * Check whether or not access to the share should be restricted to 877 * administrators. This is a bit of a hack because what we're doing 878 * is checking for the default admin shares: C$, D$ etc.. There are 879 * other shares that have restrictions: see smb_shr_is_restricted(). 880 * 881 * Returns B_TRUE if the shares is an admin share. Otherwise B_FALSE 882 * is returned to indicate that there are no restrictions. 883 */ 884 boolean_t 885 smb_shr_is_admin(char *sharename) 886 { 887 if (sharename == NULL) 888 return (B_FALSE); 889 890 if (strlen(sharename) == 2 && 891 smb_isalpha(sharename[0]) && sharename[1] == '$') { 892 return (B_TRUE); 893 } 894 895 return (B_FALSE); 896 } 897 898 char 899 smb_shr_drive_letter(const char *path) 900 { 901 smb_transient_t *ts; 902 int i; 903 904 if (path == NULL) 905 return ('\0'); 906 907 for (i = 0; i < sizeof (tshare)/sizeof (tshare[0]); ++i) { 908 ts = &tshare[i]; 909 910 if (ts->path == NULL) 911 continue; 912 913 if (strcasecmp(ts->path, path) == 0) 914 return (ts->drive); 915 } 916 917 return ('\0'); 918 } 919 920 /* 921 * Returns true if the specified directory is empty, 922 * otherwise returns false. 923 */ 924 static boolean_t 925 smb_shr_is_empty(const char *path) 926 { 927 DIR *dirp; 928 struct dirent *dp; 929 930 if (path == NULL) 931 return (B_TRUE); 932 933 if ((dirp = opendir(path)) == NULL) 934 return (B_TRUE); 935 936 while ((dp = readdir(dirp)) != NULL) { 937 if (!smb_shr_is_dot_or_dotdot(dp->d_name)) 938 return (B_FALSE); 939 } 940 941 (void) closedir(dirp); 942 return (B_TRUE); 943 } 944 945 /* 946 * Returns true if name is "." or "..", otherwise returns false. 947 */ 948 static boolean_t 949 smb_shr_is_dot_or_dotdot(const char *name) 950 { 951 if (*name != '.') 952 return (B_FALSE); 953 954 if ((name[1] == '\0') || (name[1] == '.' && name[2] == '\0')) 955 return (B_TRUE); 956 957 return (B_FALSE); 958 } 959 960 /* 961 * smb_shr_get_realpath 962 * 963 * Derive the real path for a share from the path provided by a client. 964 * For instance, the real path of C:\ may be /cvol or the real path of 965 * F:\home may be /vol1/home. 966 * 967 * clntpath - path provided by the Windows client is in the 968 * format of <drive letter>:\<dir> 969 * realpath - path that will be stored as the directory field of 970 * the smb_share_t structure of the share. 971 * maxlen - maximum length of the realpath buffer 972 * 973 * Return LAN Manager network error code. 974 */ 975 uint32_t 976 smb_shr_get_realpath(const char *clntpath, char *realpath, int maxlen) 977 { 978 const char *p; 979 int len; 980 981 if ((p = strchr(clntpath, ':')) != NULL) 982 ++p; 983 else 984 p = clntpath; 985 986 (void) strlcpy(realpath, p, maxlen); 987 (void) strcanon(realpath, "/\\"); 988 (void) strsubst(realpath, '\\', '/'); 989 990 len = strlen(realpath); 991 if ((len > 1) && (realpath[len - 1] == '/')) 992 realpath[len - 1] = '\0'; 993 994 return (NERR_Success); 995 } 996 997 void 998 smb_shr_list(int offset, smb_shrlist_t *list) 999 { 1000 smb_shriter_t iterator; 1001 smb_share_t *si; 1002 int n = 0; 1003 1004 bzero(list, sizeof (smb_shrlist_t)); 1005 smb_shr_iterinit(&iterator); 1006 1007 while ((si = smb_shr_iterate(&iterator)) != NULL) { 1008 if (--offset > 0) 1009 continue; 1010 1011 if ((si->shr_flags & SMB_SHRF_TRANS) && 1012 ((si->shr_type & STYPE_IPC) == 0)) { 1013 bcopy(si, &list->sl_shares[n], sizeof (smb_share_t)); 1014 if (++n == LMSHARES_PER_REQUEST) 1015 break; 1016 } 1017 } 1018 1019 list->sl_cnt = n; 1020 } 1021 1022 /* 1023 * Executes the map/unmap command associated with a share. 1024 * 1025 * Returns 0 on success. Otherwise non-zero for errors. 1026 */ 1027 int 1028 smb_shr_exec(smb_shr_execinfo_t *subs) 1029 { 1030 char cmd[MAXPATHLEN], **cmd_tokens, *path, *ptr; 1031 pid_t child_pid; 1032 int child_status; 1033 struct sigaction pact, cact; 1034 smb_share_t si; 1035 1036 if (smb_shr_get(subs->e_sharename, &si) != 0) 1037 return (-1); 1038 1039 *cmd = '\0'; 1040 1041 (void) mutex_lock(&smb_shr_exec_mtx); 1042 1043 switch (subs->e_type) { 1044 case SMB_EXEC_MAP: 1045 (void) strlcpy(cmd, smb_shr_exec_map, sizeof (cmd)); 1046 break; 1047 case SMB_EXEC_UNMAP: 1048 (void) strlcpy(cmd, smb_shr_exec_unmap, sizeof (cmd)); 1049 break; 1050 default: 1051 (void) mutex_unlock(&smb_shr_exec_mtx); 1052 return (-1); 1053 } 1054 1055 (void) mutex_unlock(&smb_shr_exec_mtx); 1056 1057 if (*cmd == '\0') 1058 return (0); 1059 1060 if (smb_proc_takesem() != 0) 1061 return (-1); 1062 1063 pact.sa_handler = smb_shr_sig_child; 1064 pact.sa_flags = 0; 1065 (void) sigemptyset(&pact.sa_mask); 1066 sigaction(SIGCHLD, &pact, NULL); 1067 1068 (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL); 1069 1070 if ((child_pid = fork()) == -1) { 1071 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL); 1072 smb_proc_givesem(); 1073 return (-1); 1074 } 1075 1076 if (child_pid == 0) { 1077 1078 /* child process */ 1079 1080 cact.sa_handler = smb_shr_sig_abnormal_term; 1081 cact.sa_flags = 0; 1082 (void) sigemptyset(&cact.sa_mask); 1083 sigaction(SIGTERM, &cact, NULL); 1084 sigaction(SIGABRT, &cact, NULL); 1085 sigaction(SIGSEGV, &cact, NULL); 1086 1087 if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_EXEC, 1088 PRIV_FILE_DAC_EXECUTE, NULL)) 1089 _exit(-1); 1090 1091 if (smb_shr_enable_all_privs()) 1092 _exit(-1); 1093 1094 smb_proc_initsem(); 1095 1096 (void) trim_whitespace(cmd); 1097 (void) strcanon(cmd, " "); 1098 1099 if ((cmd_tokens = smb_shr_tokenize_cmd(cmd)) != NULL) { 1100 1101 if (smb_shr_expand_subs(cmd_tokens, &si, subs) != 0) { 1102 free(cmd_tokens[0]); 1103 free(cmd_tokens); 1104 _exit(-1); 1105 } 1106 1107 ptr = cmd; 1108 path = strsep(&ptr, " "); 1109 1110 (void) execv(path, cmd_tokens); 1111 } 1112 1113 _exit(-1); 1114 } 1115 1116 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL); 1117 smb_proc_givesem(); 1118 1119 /* parent process */ 1120 1121 while (waitpid(child_pid, &child_status, 0) < 0) { 1122 if (errno != EINTR) 1123 break; 1124 1125 /* continue if waitpid got interrupted by a signal */ 1126 errno = 0; 1127 continue; 1128 } 1129 1130 if (WIFEXITED(child_status)) 1131 return (WEXITSTATUS(child_status)); 1132 1133 return (child_status); 1134 } 1135 1136 /* 1137 * Locking for process-wide settings (i.e. privileges) 1138 */ 1139 void 1140 smb_proc_initsem(void) 1141 { 1142 (void) sema_init(&smb_proc_sem, 1, USYNC_THREAD, NULL); 1143 } 1144 1145 int 1146 smb_proc_takesem(void) 1147 { 1148 return (sema_wait(&smb_proc_sem)); 1149 } 1150 1151 void 1152 smb_proc_givesem(void) 1153 { 1154 (void) sema_post(&smb_proc_sem); 1155 } 1156 1157 /* 1158 * ============================================ 1159 * Private helper/utility functions 1160 * ============================================ 1161 */ 1162 1163 /* 1164 * Looks up the given share in the cache and return 1165 * the info in 'si' 1166 */ 1167 static uint32_t 1168 smb_shr_lookup(char *sharename, smb_share_t *si) 1169 { 1170 smb_share_t *cached_si; 1171 uint32_t status = NERR_NetNameNotFound; 1172 1173 if (sharename == NULL || *sharename == '\0') 1174 return (NERR_NetNameNotFound); 1175 if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 1176 cached_si = smb_shr_cache_findent(sharename); 1177 if (cached_si != NULL) { 1178 bcopy(cached_si, si, sizeof (smb_share_t)); 1179 status = NERR_Success; 1180 } 1181 1182 smb_shr_cache_unlock(); 1183 } 1184 return (status); 1185 } 1186 1187 /* 1188 * Add IPC$ or Admin shares to the cache upon startup. 1189 */ 1190 static uint32_t 1191 smb_shr_add_transient(char *name, char *cmnt, char *path) 1192 { 1193 smb_share_t trans; 1194 uint32_t status = NERR_InternalError; 1195 1196 if (name == NULL) 1197 return (status); 1198 1199 bzero(&trans, sizeof (smb_share_t)); 1200 (void) strlcpy(trans.shr_name, name, MAXNAMELEN); 1201 if (cmnt) 1202 (void) strlcpy(trans.shr_cmnt, cmnt, SMB_SHARE_CMNT_MAX); 1203 1204 if (path) 1205 (void) strlcpy(trans.shr_path, path, MAXPATHLEN); 1206 1207 if (strcasecmp(name, "IPC$") == 0) 1208 trans.shr_type = STYPE_IPC; 1209 1210 trans.shr_flags = SMB_SHRF_TRANS; 1211 1212 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) { 1213 status = smb_shr_cache_addent(&trans); 1214 smb_shr_cache_unlock(); 1215 } 1216 1217 return (status); 1218 } 1219 1220 /* 1221 * ============================================ 1222 * Cache management functions 1223 * 1224 * All cache functions are private 1225 * ============================================ 1226 */ 1227 1228 /* 1229 * Create the share cache (hash table). 1230 */ 1231 static uint32_t 1232 smb_shr_cache_create(void) 1233 { 1234 uint32_t status = NERR_Success; 1235 1236 (void) mutex_lock(&smb_shr_cache.sc_mtx); 1237 switch (smb_shr_cache.sc_state) { 1238 case SMB_SHR_CACHE_STATE_NONE: 1239 smb_shr_cache.sc_cache = ht_create_table(SMB_SHR_HTAB_SZ, 1240 MAXNAMELEN, 0); 1241 if (smb_shr_cache.sc_cache == NULL) { 1242 status = NERR_InternalError; 1243 break; 1244 } 1245 1246 (void) ht_register_callback(smb_shr_cache.sc_cache, 1247 smb_shr_cache_freent); 1248 smb_shr_cache.sc_nops = 0; 1249 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_CREATED; 1250 break; 1251 1252 default: 1253 assert(0); 1254 status = NERR_InternalError; 1255 break; 1256 } 1257 (void) mutex_unlock(&smb_shr_cache.sc_mtx); 1258 1259 return (status); 1260 } 1261 1262 /* 1263 * Destroy the share cache (hash table). 1264 * Wait for inflight/pending operations to finish or abort before 1265 * destroying the cache. 1266 */ 1267 static void 1268 smb_shr_cache_destroy(void) 1269 { 1270 (void) mutex_lock(&smb_shr_cache.sc_mtx); 1271 if (smb_shr_cache.sc_state == SMB_SHR_CACHE_STATE_CREATED) { 1272 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_DESTROYING; 1273 while (smb_shr_cache.sc_nops > 0) 1274 (void) cond_wait(&smb_shr_cache.sc_cv, 1275 &smb_shr_cache.sc_mtx); 1276 1277 smb_shr_cache.sc_cache = NULL; 1278 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_NONE; 1279 } 1280 (void) mutex_unlock(&smb_shr_cache.sc_mtx); 1281 } 1282 1283 /* 1284 * If the cache is in "created" state, lock the cache for read 1285 * or read/write based on the specified mode. 1286 * 1287 * Whenever a lock is granted, the number of inflight cache 1288 * operations is incremented. 1289 */ 1290 static uint32_t 1291 smb_shr_cache_lock(int mode) 1292 { 1293 (void) mutex_lock(&smb_shr_cache.sc_mtx); 1294 if (smb_shr_cache.sc_state != SMB_SHR_CACHE_STATE_CREATED) { 1295 (void) mutex_unlock(&smb_shr_cache.sc_mtx); 1296 return (NERR_InternalError); 1297 } 1298 smb_shr_cache.sc_nops++; 1299 (void) mutex_unlock(&smb_shr_cache.sc_mtx); 1300 1301 /* 1302 * Lock has to be taken outside the mutex otherwise 1303 * there could be a deadlock 1304 */ 1305 if (mode == SMB_SHR_CACHE_RDLOCK) 1306 (void) rw_rdlock(&smb_shr_cache.sc_cache_lck); 1307 else 1308 (void) rw_wrlock(&smb_shr_cache.sc_cache_lck); 1309 1310 return (NERR_Success); 1311 } 1312 1313 /* 1314 * Decrement the number of inflight operations and then unlock. 1315 */ 1316 static void 1317 smb_shr_cache_unlock(void) 1318 { 1319 (void) mutex_lock(&smb_shr_cache.sc_mtx); 1320 assert(smb_shr_cache.sc_nops > 0); 1321 smb_shr_cache.sc_nops--; 1322 (void) cond_broadcast(&smb_shr_cache.sc_cv); 1323 (void) mutex_unlock(&smb_shr_cache.sc_mtx); 1324 1325 (void) rw_unlock(&smb_shr_cache.sc_cache_lck); 1326 } 1327 1328 /* 1329 * Return the total number of shares 1330 */ 1331 static int 1332 smb_shr_cache_count(void) 1333 { 1334 return (ht_get_total_items(smb_shr_cache.sc_cache)); 1335 } 1336 1337 /* 1338 * looks up the given share name in the cache and if it 1339 * finds a match returns a pointer to the cached entry. 1340 * Note that since a pointer is returned this function 1341 * MUST be protected by smb_shr_cache_lock/unlock pair 1342 */ 1343 static smb_share_t * 1344 smb_shr_cache_findent(char *sharename) 1345 { 1346 HT_ITEM *item; 1347 1348 (void) smb_strlwr(sharename); 1349 item = ht_find_item(smb_shr_cache.sc_cache, sharename); 1350 if (item && item->hi_data) 1351 return ((smb_share_t *)item->hi_data); 1352 1353 return (NULL); 1354 } 1355 1356 /* 1357 * Return a pointer to the first/next entry in 1358 * the cache based on the given iterator. 1359 * 1360 * Calls to this function MUST be protected by 1361 * smb_shr_cache_lock/unlock. 1362 */ 1363 static smb_share_t * 1364 smb_shr_cache_iterate(smb_shriter_t *shi) 1365 { 1366 HT_ITEM *item; 1367 1368 if (shi->si_first) { 1369 item = ht_findfirst(smb_shr_cache.sc_cache, &shi->si_hashiter); 1370 shi->si_first = B_FALSE; 1371 } else { 1372 item = ht_findnext(&shi->si_hashiter); 1373 } 1374 1375 if (item && item->hi_data) 1376 return ((smb_share_t *)item->hi_data); 1377 1378 return (NULL); 1379 } 1380 1381 /* 1382 * Add the specified share to the cache. Memory needs to be allocated 1383 * for the cache entry and the passed information is copied to the 1384 * allocated space. 1385 */ 1386 static uint32_t 1387 smb_shr_cache_addent(smb_share_t *si) 1388 { 1389 smb_share_t *cache_ent; 1390 uint32_t status = NERR_Success; 1391 1392 if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL) 1393 return (ERROR_NOT_ENOUGH_MEMORY); 1394 1395 (void) smb_strlwr(si->shr_name); 1396 1397 if ((si->shr_type & STYPE_IPC) == 0) 1398 si->shr_type = STYPE_DISKTREE; 1399 si->shr_type |= smb_shr_is_special(cache_ent->shr_name); 1400 1401 if (smb_shr_is_admin(cache_ent->shr_name)) 1402 si->shr_flags |= SMB_SHRF_ADMIN; 1403 1404 bcopy(si, cache_ent, sizeof (smb_share_t)); 1405 1406 if (si->shr_flags & SMB_SHRF_AUTOHOME) 1407 cache_ent->shr_refcnt = 1; 1408 1409 if (ht_add_item(smb_shr_cache.sc_cache, cache_ent->shr_name, cache_ent) 1410 == NULL) { 1411 syslog(LOG_DEBUG, "share: %s: cache update failed", 1412 cache_ent->shr_name); 1413 free(cache_ent); 1414 status = NERR_InternalError; 1415 } 1416 1417 return (status); 1418 } 1419 1420 /* 1421 * Delete the specified share from the cache. 1422 */ 1423 static void 1424 smb_shr_cache_delent(char *sharename) 1425 { 1426 (void) smb_strlwr(sharename); 1427 (void) ht_remove_item(smb_shr_cache.sc_cache, sharename); 1428 } 1429 1430 /* 1431 * Call back to free the given cache entry. 1432 */ 1433 static void 1434 smb_shr_cache_freent(HT_ITEM *item) 1435 { 1436 if (item && item->hi_data) 1437 free(item->hi_data); 1438 } 1439 1440 /* 1441 * ============================================ 1442 * Interfaces to sharemgr 1443 * 1444 * All functions in this section are private 1445 * ============================================ 1446 */ 1447 1448 /* 1449 * Load shares from sharemgr 1450 */ 1451 /*ARGSUSED*/ 1452 static void * 1453 smb_shr_sa_loadall(void *args) 1454 { 1455 sa_handle_t handle; 1456 sa_group_t group, subgroup; 1457 char *gstate; 1458 boolean_t gdisabled; 1459 1460 if ((handle = smb_shr_sa_enter()) == NULL) 1461 return (NULL); 1462 1463 for (group = sa_get_group(handle, NULL); 1464 group != NULL; group = sa_get_next_group(group)) { 1465 gstate = sa_get_group_attr(group, "state"); 1466 if (gstate == NULL) 1467 continue; 1468 1469 gdisabled = (strcasecmp(gstate, "disabled") == 0); 1470 sa_free_attr_string(gstate); 1471 if (gdisabled) 1472 continue; 1473 1474 smb_shr_sa_loadgrp(group); 1475 1476 for (subgroup = sa_get_sub_group(group); 1477 subgroup != NULL; 1478 subgroup = sa_get_next_group(subgroup)) { 1479 smb_shr_sa_loadgrp(subgroup); 1480 } 1481 1482 } 1483 1484 smb_shr_sa_exit(); 1485 return (NULL); 1486 } 1487 1488 /* 1489 * Load the shares contained in the specified group. 1490 * 1491 * Don't process groups on which the smb protocol is disabled. 1492 * The top level ZFS group won't have the smb protocol enabled 1493 * but sub-groups will. 1494 * 1495 * We will tolerate a limited number of errors and then give 1496 * up on the current group. A typical error might be that the 1497 * shared directory no longer exists. 1498 */ 1499 static void 1500 smb_shr_sa_loadgrp(sa_group_t group) 1501 { 1502 sa_share_t share; 1503 sa_resource_t resource; 1504 int error_count = 0; 1505 1506 if (sa_get_optionset(group, SMB_PROTOCOL_NAME) == NULL) 1507 return; 1508 1509 for (share = sa_get_share(group, NULL); 1510 share != NULL; 1511 share = sa_get_next_share(share)) { 1512 for (resource = sa_get_share_resource(share, NULL); 1513 resource != NULL; 1514 resource = sa_get_next_resource(resource)) { 1515 if (smb_shr_sa_load(share, resource)) 1516 ++error_count; 1517 1518 if (error_count > SMB_SHR_ERROR_THRESHOLD) 1519 break; 1520 } 1521 1522 if (error_count > SMB_SHR_ERROR_THRESHOLD) 1523 break; 1524 } 1525 } 1526 1527 /* 1528 * Load a share definition from sharemgr and add it to the cache. 1529 * If the share is already in the cache then it doesn't do anything. 1530 * 1531 * This function does not report duplicate shares as error since 1532 * a share might have been added by smb_shr_get() while load is 1533 * in progress. 1534 */ 1535 static uint32_t 1536 smb_shr_sa_load(sa_share_t share, sa_resource_t resource) 1537 { 1538 smb_share_t si; 1539 char *sharename; 1540 uint32_t status; 1541 boolean_t loaded; 1542 1543 if ((sharename = sa_get_resource_attr(resource, "name")) == NULL) 1544 return (NERR_InternalError); 1545 1546 loaded = smb_shr_exists(sharename); 1547 sa_free_attr_string(sharename); 1548 1549 if (loaded) 1550 return (NERR_Success); 1551 1552 if ((status = smb_shr_sa_get(share, resource, &si)) != NERR_Success) { 1553 syslog(LOG_DEBUG, "share: failed to load %s (%d)", 1554 si.shr_name, status); 1555 return (status); 1556 } 1557 1558 status = smb_shr_add(&si); 1559 if ((status != NERR_Success) && (status != NERR_DuplicateShare)) { 1560 syslog(LOG_DEBUG, "share: failed to cache %s (%d)", 1561 si.shr_name, status); 1562 return (status); 1563 } 1564 1565 if ((si.shr_flags & SMB_SHRF_DFSROOT) != 0) 1566 dfs_namespace_load(si.shr_name); 1567 1568 return (NERR_Success); 1569 } 1570 1571 static char * 1572 smb_shr_sa_getprop(sa_optionset_t opts, char *propname) 1573 { 1574 sa_property_t prop; 1575 char *val = NULL; 1576 1577 prop = sa_get_property(opts, propname); 1578 if (prop != NULL) 1579 val = sa_get_property_attr(prop, "value"); 1580 1581 return (val); 1582 } 1583 1584 /* 1585 * Read the specified share information from sharemgr and return 1586 * it in the given smb_share_t structure. 1587 * 1588 * Shares read from sharemgr are marked as permanent/persistent. 1589 */ 1590 static uint32_t 1591 smb_shr_sa_get(sa_share_t share, sa_resource_t resource, smb_share_t *si) 1592 { 1593 sa_optionset_t opts; 1594 char *val = NULL; 1595 char *path; 1596 char *rname; 1597 1598 if ((path = sa_get_share_attr(share, "path")) == NULL) 1599 return (NERR_InternalError); 1600 1601 if ((rname = sa_get_resource_attr(resource, "name")) == NULL) { 1602 sa_free_attr_string(path); 1603 return (NERR_InternalError); 1604 } 1605 1606 bzero(si, sizeof (smb_share_t)); 1607 si->shr_flags = SMB_SHRF_PERM; 1608 1609 (void) strlcpy(si->shr_path, path, sizeof (si->shr_path)); 1610 (void) strlcpy(si->shr_name, rname, sizeof (si->shr_name)); 1611 sa_free_attr_string(path); 1612 sa_free_attr_string(rname); 1613 1614 val = sa_get_resource_description(resource); 1615 if (val == NULL) 1616 val = sa_get_share_description(share); 1617 1618 if (val != NULL) { 1619 (void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt)); 1620 sa_free_share_description(val); 1621 } 1622 1623 opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1); 1624 if (opts == NULL) 1625 return (NERR_Success); 1626 1627 val = smb_shr_sa_getprop(opts, SHOPT_AD_CONTAINER); 1628 if (val != NULL) { 1629 (void) strlcpy(si->shr_container, val, 1630 sizeof (si->shr_container)); 1631 free(val); 1632 } 1633 1634 val = smb_shr_sa_getprop(opts, SHOPT_CATIA); 1635 if (val != NULL) { 1636 smb_shr_sa_setflag(val, si, SMB_SHRF_CATIA); 1637 free(val); 1638 } 1639 1640 val = smb_shr_sa_getprop(opts, SHOPT_ABE); 1641 if (val != NULL) { 1642 smb_shr_sa_setflag(val, si, SMB_SHRF_ABE); 1643 free(val); 1644 } 1645 1646 val = smb_shr_sa_getprop(opts, SHOPT_GUEST); 1647 if (val != NULL) { 1648 smb_shr_sa_setflag(val, si, SMB_SHRF_GUEST_OK); 1649 free(val); 1650 } 1651 1652 val = smb_shr_sa_getprop(opts, SHOPT_DFSROOT); 1653 if (val != NULL) { 1654 smb_shr_sa_setflag(val, si, SMB_SHRF_DFSROOT); 1655 free(val); 1656 } 1657 1658 val = smb_shr_sa_getprop(opts, SHOPT_CSC); 1659 if (val != NULL) { 1660 smb_shr_sa_csc_option(val, si); 1661 free(val); 1662 } 1663 1664 val = smb_shr_sa_getprop(opts, SHOPT_NONE); 1665 if (val != NULL) { 1666 (void) strlcpy(si->shr_access_none, val, 1667 sizeof (si->shr_access_none)); 1668 free(val); 1669 si->shr_flags |= SMB_SHRF_ACC_NONE; 1670 } 1671 1672 val = smb_shr_sa_getprop(opts, SHOPT_RO); 1673 if (val != NULL) { 1674 (void) strlcpy(si->shr_access_ro, val, 1675 sizeof (si->shr_access_ro)); 1676 free(val); 1677 si->shr_flags |= SMB_SHRF_ACC_RO; 1678 } 1679 1680 val = smb_shr_sa_getprop(opts, SHOPT_RW); 1681 if (val != NULL) { 1682 (void) strlcpy(si->shr_access_rw, val, 1683 sizeof (si->shr_access_rw)); 1684 free(val); 1685 si->shr_flags |= SMB_SHRF_ACC_RW; 1686 } 1687 1688 sa_free_derived_optionset(opts); 1689 return (NERR_Success); 1690 } 1691 1692 /* 1693 * Map a client-side caching (CSC) option to the appropriate share 1694 * flag. Only one option is allowed; an error will be logged if 1695 * multiple options have been specified. We don't need to do anything 1696 * about multiple values here because the SRVSVC will not recognize 1697 * a value containing multiple flags and will return the default value. 1698 * 1699 * If the option value is not recognized, it will be ignored: invalid 1700 * values will typically be caught and rejected by sharemgr. 1701 */ 1702 void 1703 smb_shr_sa_csc_option(const char *value, smb_share_t *si) 1704 { 1705 int i; 1706 1707 for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) { 1708 if (strcasecmp(value, cscopt[i].value) == 0) { 1709 si->shr_flags |= cscopt[i].flag; 1710 break; 1711 } 1712 } 1713 1714 switch (si->shr_flags & SMB_SHRF_CSC_MASK) { 1715 case 0: 1716 case SMB_SHRF_CSC_DISABLED: 1717 case SMB_SHRF_CSC_MANUAL: 1718 case SMB_SHRF_CSC_AUTO: 1719 case SMB_SHRF_CSC_VDO: 1720 break; 1721 1722 default: 1723 syslog(LOG_INFO, "csc option conflict: 0x%08x", 1724 si->shr_flags & SMB_SHRF_CSC_MASK); 1725 break; 1726 } 1727 } 1728 1729 /* 1730 * Return the option name for the first CSC flag (there should be only 1731 * one) encountered in the share flags. 1732 */ 1733 char * 1734 smb_shr_sa_csc_name(const smb_share_t *si) 1735 { 1736 int i; 1737 1738 for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) { 1739 if (si->shr_flags & cscopt[i].flag) 1740 return (cscopt[i].value); 1741 } 1742 1743 return (NULL); 1744 } 1745 1746 /* 1747 * Takes the value of a boolean share property and set/clear the 1748 * specified flag based on the property's value. 1749 */ 1750 void 1751 smb_shr_sa_setflag(const char *value, smb_share_t *si, uint32_t flag) 1752 { 1753 if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0)) 1754 si->shr_flags |= flag; 1755 else 1756 si->shr_flags &= ~flag; 1757 } 1758 1759 /* 1760 * looks up sharemgr for the given share (resource) and loads 1761 * the definition into cache if lookup is successful 1762 */ 1763 static uint32_t 1764 smb_shr_sa_loadbyname(char *sharename) 1765 { 1766 sa_handle_t handle; 1767 sa_share_t share; 1768 sa_resource_t resource; 1769 uint32_t status; 1770 1771 if ((handle = smb_shr_sa_enter()) == NULL) 1772 return (NERR_InternalError); 1773 1774 resource = sa_find_resource(handle, sharename); 1775 if (resource == NULL) { 1776 smb_shr_sa_exit(); 1777 return (NERR_NetNameNotFound); 1778 } 1779 1780 share = sa_get_resource_parent(resource); 1781 if (share == NULL) { 1782 smb_shr_sa_exit(); 1783 return (NERR_InternalError); 1784 } 1785 1786 status = smb_shr_sa_load(share, resource); 1787 1788 smb_shr_sa_exit(); 1789 return (status); 1790 } 1791 1792 /* 1793 * ============================================ 1794 * Share publishing functions 1795 * 1796 * All the functions are private 1797 * ============================================ 1798 */ 1799 1800 static void 1801 smb_shr_publish(const char *sharename, const char *container) 1802 { 1803 smb_shr_publisher_queue(sharename, container, SMB_SHR_PUBLISH); 1804 } 1805 1806 static void 1807 smb_shr_unpublish(const char *sharename, const char *container) 1808 { 1809 smb_shr_publisher_queue(sharename, container, SMB_SHR_UNPUBLISH); 1810 } 1811 1812 /* 1813 * In domain mode, put a share on the publisher queue. 1814 * This is a no-op if the smb service is in Workgroup mode. 1815 */ 1816 static void 1817 smb_shr_publisher_queue(const char *sharename, const char *container, char op) 1818 { 1819 smb_shr_pitem_t *item = NULL; 1820 1821 if (container == NULL || *container == '\0') 1822 return; 1823 1824 if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 1825 return; 1826 1827 (void) mutex_lock(&ad_queue.spq_mtx); 1828 switch (ad_queue.spq_state) { 1829 case SMB_SHR_PQS_READY: 1830 case SMB_SHR_PQS_PUBLISHING: 1831 break; 1832 default: 1833 (void) mutex_unlock(&ad_queue.spq_mtx); 1834 return; 1835 } 1836 (void) mutex_unlock(&ad_queue.spq_mtx); 1837 1838 if ((item = malloc(sizeof (smb_shr_pitem_t))) == NULL) 1839 return; 1840 1841 item->spi_op = op; 1842 (void) strlcpy(item->spi_name, sharename, sizeof (item->spi_name)); 1843 (void) strlcpy(item->spi_container, container, 1844 sizeof (item->spi_container)); 1845 1846 (void) mutex_lock(&ad_queue.spq_mtx); 1847 list_insert_tail(&ad_queue.spq_list, item); 1848 (void) cond_signal(&ad_queue.spq_cv); 1849 (void) mutex_unlock(&ad_queue.spq_mtx); 1850 } 1851 1852 /* 1853 * Publishing won't be activated if the smb service is running in 1854 * Workgroup mode. 1855 */ 1856 static int 1857 smb_shr_publisher_start(void) 1858 { 1859 pthread_t publish_thr; 1860 pthread_attr_t tattr; 1861 int rc; 1862 1863 if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 1864 return (0); 1865 1866 (void) mutex_lock(&ad_queue.spq_mtx); 1867 if (ad_queue.spq_state != SMB_SHR_PQS_NOQUEUE) { 1868 (void) mutex_unlock(&ad_queue.spq_mtx); 1869 errno = EINVAL; 1870 return (-1); 1871 } 1872 1873 list_create(&ad_queue.spq_list, sizeof (smb_shr_pitem_t), 1874 offsetof(smb_shr_pitem_t, spi_lnd)); 1875 ad_queue.spq_state = SMB_SHR_PQS_READY; 1876 (void) mutex_unlock(&ad_queue.spq_mtx); 1877 1878 (void) pthread_attr_init(&tattr); 1879 (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 1880 rc = pthread_create(&publish_thr, &tattr, smb_shr_publisher, 0); 1881 (void) pthread_attr_destroy(&tattr); 1882 1883 return (rc); 1884 } 1885 1886 static void 1887 smb_shr_publisher_stop(void) 1888 { 1889 if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 1890 return; 1891 1892 (void) mutex_lock(&ad_queue.spq_mtx); 1893 switch (ad_queue.spq_state) { 1894 case SMB_SHR_PQS_READY: 1895 case SMB_SHR_PQS_PUBLISHING: 1896 ad_queue.spq_state = SMB_SHR_PQS_STOPPING; 1897 (void) cond_signal(&ad_queue.spq_cv); 1898 break; 1899 default: 1900 break; 1901 } 1902 (void) mutex_unlock(&ad_queue.spq_mtx); 1903 } 1904 1905 /* 1906 * This is the publisher daemon thread. While running, the thread waits 1907 * on a conditional variable until notified that a share needs to be 1908 * [un]published or that the thread should be terminated. 1909 * 1910 * Entries may remain in the outgoing queue if the Active Directory 1911 * service is inaccessible, in which case the thread wakes up every 60 1912 * seconds to retry. 1913 */ 1914 /*ARGSUSED*/ 1915 static void * 1916 smb_shr_publisher(void *arg) 1917 { 1918 smb_ads_handle_t *ah; 1919 smb_shr_pitem_t *shr; 1920 list_t publist; 1921 timestruc_t pubretry; 1922 char hostname[MAXHOSTNAMELEN]; 1923 1924 (void) mutex_lock(&ad_queue.spq_mtx); 1925 if (ad_queue.spq_state != SMB_SHR_PQS_READY) { 1926 (void) mutex_unlock(&ad_queue.spq_mtx); 1927 return (NULL); 1928 } 1929 ad_queue.spq_state = SMB_SHR_PQS_PUBLISHING; 1930 (void) mutex_unlock(&ad_queue.spq_mtx); 1931 1932 (void) smb_gethostname(hostname, MAXHOSTNAMELEN, 1933 SMB_CASE_PRESERVE); 1934 1935 list_create(&publist, sizeof (smb_shr_pitem_t), 1936 offsetof(smb_shr_pitem_t, spi_lnd)); 1937 1938 for (;;) { 1939 (void) mutex_lock(&ad_queue.spq_mtx); 1940 1941 while (list_is_empty(&ad_queue.spq_list) && 1942 (ad_queue.spq_state == SMB_SHR_PQS_PUBLISHING)) { 1943 if (list_is_empty(&publist)) { 1944 (void) cond_wait(&ad_queue.spq_cv, 1945 &ad_queue.spq_mtx); 1946 } else { 1947 pubretry.tv_sec = 60; 1948 pubretry.tv_nsec = 0; 1949 (void) cond_reltimedwait(&ad_queue.spq_cv, 1950 &ad_queue.spq_mtx, &pubretry); 1951 break; 1952 } 1953 } 1954 1955 if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) { 1956 (void) mutex_unlock(&ad_queue.spq_mtx); 1957 break; 1958 } 1959 1960 /* 1961 * Transfer queued items to the local list so that 1962 * the mutex can be released. 1963 */ 1964 while ((shr = list_head(&ad_queue.spq_list)) != NULL) { 1965 list_remove(&ad_queue.spq_list, shr); 1966 list_insert_tail(&publist, shr); 1967 } 1968 1969 (void) mutex_unlock(&ad_queue.spq_mtx); 1970 1971 if ((ah = smb_ads_open()) != NULL) { 1972 smb_shr_publisher_send(ah, &publist, hostname); 1973 smb_ads_close(ah); 1974 } 1975 } 1976 1977 (void) mutex_lock(&ad_queue.spq_mtx); 1978 smb_shr_publisher_flush(&ad_queue.spq_list); 1979 list_destroy(&ad_queue.spq_list); 1980 ad_queue.spq_state = SMB_SHR_PQS_NOQUEUE; 1981 (void) mutex_unlock(&ad_queue.spq_mtx); 1982 1983 smb_shr_publisher_flush(&publist); 1984 list_destroy(&publist); 1985 return (NULL); 1986 } 1987 1988 /* 1989 * Remove items from the specified queue and [un]publish them. 1990 */ 1991 static void 1992 smb_shr_publisher_send(smb_ads_handle_t *ah, list_t *publist, const char *host) 1993 { 1994 smb_shr_pitem_t *shr; 1995 1996 while ((shr = list_head(publist)) != NULL) { 1997 (void) mutex_lock(&ad_queue.spq_mtx); 1998 if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) { 1999 (void) mutex_unlock(&ad_queue.spq_mtx); 2000 return; 2001 } 2002 (void) mutex_unlock(&ad_queue.spq_mtx); 2003 2004 list_remove(publist, shr); 2005 2006 if (shr->spi_op == SMB_SHR_PUBLISH) 2007 (void) smb_ads_publish_share(ah, shr->spi_name, 2008 NULL, shr->spi_container, host); 2009 else 2010 (void) smb_ads_remove_share(ah, shr->spi_name, 2011 NULL, shr->spi_container, host); 2012 2013 free(shr); 2014 } 2015 } 2016 2017 /* 2018 * Flush all remaining items from the specified list/queue. 2019 */ 2020 static void 2021 smb_shr_publisher_flush(list_t *lst) 2022 { 2023 smb_shr_pitem_t *shr; 2024 2025 while ((shr = list_head(lst)) != NULL) { 2026 list_remove(lst, shr); 2027 free(shr); 2028 } 2029 } 2030 2031 /* 2032 * If the share path refers to a ZFS file system, add the 2033 * .zfs/shares/<share> object and call smb_quota_add_fs() 2034 * to initialize quota support for the share. 2035 */ 2036 static void 2037 smb_shr_zfs_add(smb_share_t *si) 2038 { 2039 libzfs_handle_t *libhd; 2040 zfs_handle_t *zfshd; 2041 int ret; 2042 char buf[MAXPATHLEN]; /* dataset or mountpoint */ 2043 2044 if (smb_getdataset(si->shr_path, buf, MAXPATHLEN) != 0) 2045 return; 2046 2047 if ((libhd = libzfs_init()) == NULL) 2048 return; 2049 2050 if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) { 2051 libzfs_fini(libhd); 2052 return; 2053 } 2054 2055 errno = 0; 2056 ret = zfs_smb_acl_add(libhd, buf, si->shr_path, si->shr_name); 2057 if (ret != 0 && errno != EAGAIN && errno != EEXIST) 2058 syslog(LOG_INFO, "share: failed to add ACL object: %s: %s\n", 2059 si->shr_name, strerror(errno)); 2060 2061 if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, buf, MAXPATHLEN, 2062 NULL, NULL, 0, B_FALSE) == 0) { 2063 smb_quota_add_fs(buf); 2064 } 2065 2066 2067 zfs_close(zfshd); 2068 libzfs_fini(libhd); 2069 } 2070 2071 /* 2072 * If the share path refers to a ZFS file system, remove the 2073 * .zfs/shares/<share> object, and call smb_quota_remove_fs() 2074 * to end quota support for the share. 2075 */ 2076 static void 2077 smb_shr_zfs_remove(smb_share_t *si) 2078 { 2079 libzfs_handle_t *libhd; 2080 zfs_handle_t *zfshd; 2081 int ret; 2082 char buf[MAXPATHLEN]; /* dataset or mountpoint */ 2083 2084 if (smb_getdataset(si->shr_path, buf, MAXPATHLEN) != 0) 2085 return; 2086 2087 if ((libhd = libzfs_init()) == NULL) 2088 return; 2089 2090 if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) { 2091 libzfs_fini(libhd); 2092 return; 2093 } 2094 2095 errno = 0; 2096 ret = zfs_smb_acl_remove(libhd, buf, si->shr_path, si->shr_name); 2097 if (ret != 0 && errno != EAGAIN) 2098 syslog(LOG_INFO, "share: failed to remove ACL object: %s: %s\n", 2099 si->shr_name, strerror(errno)); 2100 2101 if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, buf, MAXPATHLEN, 2102 NULL, NULL, 0, B_FALSE) == 0) { 2103 smb_quota_remove_fs(buf); 2104 } 2105 2106 zfs_close(zfshd); 2107 libzfs_fini(libhd); 2108 } 2109 2110 /* 2111 * If the share path refers to a ZFS file system, rename the 2112 * .zfs/shares/<share> object. 2113 */ 2114 static void 2115 smb_shr_zfs_rename(smb_share_t *from, smb_share_t *to) 2116 { 2117 libzfs_handle_t *libhd; 2118 zfs_handle_t *zfshd; 2119 int ret; 2120 char dataset[MAXPATHLEN]; 2121 2122 if (smb_getdataset(from->shr_path, dataset, MAXPATHLEN) != 0) 2123 return; 2124 2125 if ((libhd = libzfs_init()) == NULL) 2126 return; 2127 2128 if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) { 2129 libzfs_fini(libhd); 2130 return; 2131 } 2132 2133 errno = 0; 2134 ret = zfs_smb_acl_rename(libhd, dataset, from->shr_path, 2135 from->shr_name, to->shr_name); 2136 if (ret != 0 && errno != EAGAIN) 2137 syslog(LOG_INFO, "share: failed to rename ACL object: %s: %s\n", 2138 from->shr_name, strerror(errno)); 2139 2140 zfs_close(zfshd); 2141 libzfs_fini(libhd); 2142 } 2143 2144 /* 2145 * Enable all privileges in the inheritable set to execute command. 2146 */ 2147 static int 2148 smb_shr_enable_all_privs(void) 2149 { 2150 priv_set_t *pset; 2151 2152 pset = priv_allocset(); 2153 if (pset == NULL) 2154 return (-1); 2155 2156 if (getppriv(PRIV_LIMIT, pset)) { 2157 priv_freeset(pset); 2158 return (-1); 2159 } 2160 2161 if (setppriv(PRIV_ON, PRIV_INHERITABLE, pset)) { 2162 priv_freeset(pset); 2163 return (-1); 2164 } 2165 2166 priv_freeset(pset); 2167 return (0); 2168 } 2169 2170 /* 2171 * Tokenizes the command string and returns the list of tokens in an array. 2172 * 2173 * Returns NULL if there are no tokens. 2174 */ 2175 static char ** 2176 smb_shr_tokenize_cmd(char *cmdstr) 2177 { 2178 char *cmd, *buf, *bp, *value; 2179 char **argv, **ap; 2180 int argc, i; 2181 2182 if (cmdstr == NULL || *cmdstr == '\0') 2183 return (NULL); 2184 2185 if ((buf = malloc(MAXPATHLEN)) == NULL) 2186 return (NULL); 2187 2188 (void) strlcpy(buf, cmdstr, MAXPATHLEN); 2189 2190 for (argc = 2, bp = cmdstr; *bp != '\0'; ++bp) 2191 if (*bp == ' ') 2192 ++argc; 2193 2194 if ((argv = calloc(argc, sizeof (char *))) == NULL) { 2195 free(buf); 2196 return (NULL); 2197 } 2198 2199 ap = argv; 2200 for (bp = buf, i = 0; i < argc; ++i) { 2201 do { 2202 if ((value = strsep(&bp, " ")) == NULL) 2203 break; 2204 } while (*value == '\0'); 2205 2206 if (value == NULL) 2207 break; 2208 2209 *ap++ = value; 2210 } 2211 2212 /* get the filename of the command from the path */ 2213 if ((cmd = strrchr(argv[0], '/')) != NULL) 2214 (void) strlcpy(argv[0], ++cmd, strlen(argv[0])); 2215 2216 return (argv); 2217 } 2218 2219 /* 2220 * Expands the command string for the following substitution tokens: 2221 * 2222 * %U - Windows username 2223 * %D - Name of the domain or workgroup of %U 2224 * %h - The server hostname 2225 * %M - The client hostname 2226 * %L - The server NetBIOS name 2227 * %m - The client NetBIOS name. This option is only valid for NetBIOS 2228 * connections (port 139). 2229 * %I - The IP address of the client machine 2230 * %i - The local IP address to which the client is connected 2231 * %S - The name of the share 2232 * %P - The root directory of the share 2233 * %u - The UID of the Unix user 2234 * 2235 * Returns 0 on success. Otherwise -1. 2236 */ 2237 static int 2238 smb_shr_expand_subs(char **cmd_toks, smb_share_t *si, smb_shr_execinfo_t *subs) 2239 { 2240 char *fmt, *sub_chr, *ptr; 2241 boolean_t unknown; 2242 char hostname[MAXHOSTNAMELEN]; 2243 char ip_str[INET6_ADDRSTRLEN]; 2244 char name[SMB_PI_MAX_HOST]; 2245 smb_wchar_t wbuf[SMB_PI_MAX_HOST]; 2246 int i; 2247 2248 if (cmd_toks == NULL || *cmd_toks == NULL) 2249 return (-1); 2250 2251 for (i = 1; cmd_toks[i]; i++) { 2252 fmt = cmd_toks[i]; 2253 if (*fmt == '%') { 2254 sub_chr = fmt + 1; 2255 unknown = B_FALSE; 2256 2257 switch (*sub_chr) { 2258 case 'U': 2259 ptr = strdup(subs->e_winname); 2260 break; 2261 case 'D': 2262 ptr = strdup(subs->e_userdom); 2263 break; 2264 case 'h': 2265 if (gethostname(hostname, MAXHOSTNAMELEN) != 0) 2266 unknown = B_TRUE; 2267 else 2268 ptr = strdup(hostname); 2269 break; 2270 case 'M': 2271 if (smb_getnameinfo(&subs->e_cli_ipaddr, 2272 hostname, sizeof (hostname), 0) != 0) 2273 unknown = B_TRUE; 2274 else 2275 ptr = strdup(hostname); 2276 break; 2277 case 'L': 2278 if (smb_getnetbiosname(hostname, 2279 NETBIOS_NAME_SZ) != 0) 2280 unknown = B_TRUE; 2281 else 2282 ptr = strdup(hostname); 2283 break; 2284 case 'm': 2285 if (*subs->e_cli_netbiosname == '\0') 2286 unknown = B_TRUE; 2287 else { 2288 (void) smb_mbstowcs(wbuf, 2289 subs->e_cli_netbiosname, 2290 SMB_PI_MAX_HOST - 1); 2291 2292 if (ucstooem(name, wbuf, 2293 SMB_PI_MAX_HOST, OEM_CPG_850) == 0) 2294 (void) strlcpy(name, 2295 subs->e_cli_netbiosname, 2296 SMB_PI_MAX_HOST); 2297 2298 ptr = strdup(name); 2299 } 2300 break; 2301 case 'I': 2302 if (smb_inet_ntop(&subs->e_cli_ipaddr, ip_str, 2303 SMB_IPSTRLEN(subs->e_cli_ipaddr.a_family)) 2304 != NULL) 2305 ptr = strdup(ip_str); 2306 else 2307 unknown = B_TRUE; 2308 break; 2309 case 'i': 2310 if (smb_inet_ntop(&subs->e_srv_ipaddr, ip_str, 2311 SMB_IPSTRLEN(subs->e_srv_ipaddr.a_family)) 2312 != NULL) 2313 ptr = strdup(ip_str); 2314 else 2315 unknown = B_TRUE; 2316 break; 2317 case 'S': 2318 ptr = strdup(si->shr_name); 2319 break; 2320 case 'P': 2321 ptr = strdup(si->shr_path); 2322 break; 2323 case 'u': 2324 (void) snprintf(name, sizeof (name), "%u", 2325 subs->e_uid); 2326 ptr = strdup(name); 2327 break; 2328 default: 2329 /* unknown sub char */ 2330 unknown = B_TRUE; 2331 break; 2332 } 2333 2334 if (unknown) 2335 ptr = strdup(""); 2336 2337 } else /* first char of cmd's arg is not '%' char */ 2338 ptr = strdup(""); 2339 2340 cmd_toks[i] = ptr; 2341 2342 if (ptr == NULL) { 2343 for (i = 1; cmd_toks[i]; i++) 2344 free(cmd_toks[i]); 2345 2346 return (-1); 2347 } 2348 } 2349 2350 return (0); 2351 } 2352 2353 /*ARGSUSED*/ 2354 static void 2355 smb_shr_sig_abnormal_term(int sig_val) 2356 { 2357 /* 2358 * Calling _exit() prevents parent process from getting SIGTERM/SIGINT 2359 * signal. 2360 */ 2361 _exit(-1); 2362 } 2363 2364 /*ARGSUSED*/ 2365 static void 2366 smb_shr_sig_child(int sig_val) 2367 { 2368 /* 2369 * Catch the signal and allow the exit status of the child process 2370 * to be available for reaping. 2371 */ 2372 } 2373 2374 /* 2375 * This is a temporary function which converts the given smb_share_t 2376 * structure to the nvlist format that will be provided by libsharev2 2377 */ 2378 static int 2379 smb_shr_encode(smb_share_t *si, nvlist_t **nvlist) 2380 { 2381 nvlist_t *list; 2382 nvlist_t *share; 2383 nvlist_t *smb; 2384 char *csc; 2385 int rc = 0; 2386 2387 *nvlist = NULL; 2388 2389 if ((rc = nvlist_alloc(&list, NV_UNIQUE_NAME, 0)) != 0) 2390 return (rc); 2391 2392 if ((rc = nvlist_alloc(&share, NV_UNIQUE_NAME, 0)) != 0) { 2393 nvlist_free(list); 2394 return (rc); 2395 } 2396 2397 if ((rc = nvlist_alloc(&smb, NV_UNIQUE_NAME, 0)) != 0) { 2398 nvlist_free(share); 2399 nvlist_free(list); 2400 return (rc); 2401 } 2402 2403 /* global share properties */ 2404 rc |= nvlist_add_string(share, "name", si->shr_name); 2405 rc |= nvlist_add_string(share, "path", si->shr_path); 2406 rc |= nvlist_add_string(share, "desc", si->shr_cmnt); 2407 2408 /* smb protocol properties */ 2409 rc = nvlist_add_string(smb, SHOPT_AD_CONTAINER, si->shr_container); 2410 if ((si->shr_flags & SMB_SHRF_ACC_NONE) != 0) 2411 rc |= nvlist_add_string(smb, SHOPT_NONE, si->shr_access_none); 2412 if ((si->shr_flags & SMB_SHRF_ACC_RO) != 0) 2413 rc |= nvlist_add_string(smb, SHOPT_RO, si->shr_access_ro); 2414 if ((si->shr_flags & SMB_SHRF_ACC_RW) != 0) 2415 rc |= nvlist_add_string(smb, SHOPT_RW, si->shr_access_rw); 2416 2417 if ((si->shr_flags & SMB_SHRF_ABE) != 0) 2418 rc |= nvlist_add_string(smb, SHOPT_ABE, "true"); 2419 if ((si->shr_flags & SMB_SHRF_CATIA) != 0) 2420 rc |= nvlist_add_string(smb, SHOPT_CATIA, "true"); 2421 if ((si->shr_flags & SMB_SHRF_GUEST_OK) != 0) 2422 rc |= nvlist_add_string(smb, SHOPT_GUEST, "true"); 2423 if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0) 2424 rc |= nvlist_add_string(smb, SHOPT_DFSROOT, "true"); 2425 2426 if ((si->shr_flags & SMB_SHRF_AUTOHOME) != 0) { 2427 rc |= nvlist_add_string(smb, "Autohome", "true"); 2428 rc |= nvlist_add_uint32(smb, "uid", si->shr_uid); 2429 rc |= nvlist_add_uint32(smb, "gid", si->shr_gid); 2430 } 2431 2432 if ((csc = smb_shr_sa_csc_name(si)) != NULL) 2433 rc |= nvlist_add_string(smb, SHOPT_CSC, csc); 2434 2435 rc |= nvlist_add_nvlist(share, "smb", smb); 2436 rc |= nvlist_add_nvlist(list, si->shr_name, share); 2437 2438 nvlist_free(share); 2439 nvlist_free(smb); 2440 2441 if (rc != 0) 2442 nvlist_free(list); 2443 else 2444 *nvlist = list; 2445 2446 return (rc); 2447 } 2448