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