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