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