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