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