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