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