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