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