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