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