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