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