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