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