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