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