2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
22 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
23 */
24
25 /*
26 * SMB/CIFS share cache implementation.
27 */
28
29 #include <errno.h>
30 #include <synch.h>
31 #include <stdlib.h>
32 #include <strings.h>
33 #include <syslog.h>
34 #include <thread.h>
35 #include <pthread.h>
36 #include <assert.h>
37 #include <libshare.h>
38 #include <libzfs.h>
39 #include <priv_utils.h>
40 #include <sys/types.h>
41 #include <sys/wait.h>
42 #include <unistd.h>
372 return (share);
373 }
374
375 /*
376 * Adds the given share to cache, publishes the share in ADS
377 * if it has an AD container, calls kernel to take a hold on
378 * the shared file system. If it can't take a hold on the
379 * shared file system, it's either because shared directory
380 * does not exist or some other error has occurred, in any
381 * case the share is removed from the cache.
382 *
383 * If the specified share is an autohome share which already
384 * exists in the cache, just increments the reference count.
385 */
386 uint32_t
387 smb_shr_add(smb_share_t *si)
388 {
389 struct stat st;
390 smb_share_t *cached_si;
391 nvlist_t *shrlist;
392 uint32_t status;
393 int rc;
394
395 assert(si != NULL);
396
397 if (smb_name_validate_share(si->shr_name) != ERROR_SUCCESS)
398 return (ERROR_INVALID_NAME);
399
400 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
401 return (NERR_InternalError);
402
403 cached_si = smb_shr_cache_findent(si->shr_name);
404 if (cached_si) {
405 if (si->shr_flags & SMB_SHRF_AUTOHOME) {
406 cached_si->shr_refcnt++;
407 status = NERR_Success;
408 } else {
409 status = NERR_DuplicateShare;
410 }
411 smb_shr_cache_unlock();
412 return (status);
413 }
414
415 if (STYPE_ISDSK(si->shr_type)) {
416 /*
417 * If share type is STYPE_DISKTREE then the path to the
418 * share should exist so that we can add the share to cache.
419 */
420 rc = stat(si->shr_path, &st);
421 if (rc != 0) {
422 smb_shr_cache_unlock();
423 return (NERR_ItemNotFound);
424 }
425 }
426
427 if ((status = smb_shr_cache_addent(si)) != NERR_Success) {
428 smb_shr_cache_unlock();
429 return (status);
430 }
431
432 /* don't hold the lock across door call */
433 smb_shr_cache_unlock();
434
435 if ((rc = smb_shr_encode(si, &shrlist)) == 0) {
436 /* send the share to kernel */
437 rc = smb_kmod_share(shrlist);
438 nvlist_free(shrlist);
439
440 if (rc == 0) {
441 smb_shr_publish(si->shr_name, si->shr_container);
442
443 /* If path is ZFS, add the .zfs/shares/<share> entry. */
444 smb_shr_zfs_add(si);
445
446 if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0)
447 dfs_namespace_load(si->shr_name);
448
449 return (NERR_Success);
450 }
451 }
452
453 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) {
454 smb_shr_cache_delent(si->shr_name);
455 smb_shr_cache_unlock();
456 }
457
458 /*
459 * rc == ENOENT means the shared directory doesn't exist
460 */
461 return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError);
462 }
463
464 /*
465 * Removes the specified share from cache, removes it from AD
466 * if it has an AD container, and calls the kernel to release
467 * the hold on the shared file system.
468 *
469 * If this is an autohome share then decrement the reference
470 * count. If it reaches 0 then it proceeds with removing steps.
471 */
472 uint32_t
473 smb_shr_remove(char *sharename)
474 {
475 smb_share_t *si;
476 char container[MAXPATHLEN];
477 boolean_t dfsroot;
488 if ((si = smb_shr_cache_findent(sharename)) == NULL) {
489 smb_shr_cache_unlock();
490 return (NERR_NetNameNotFound);
491 }
492
493 if (STYPE_ISIPC(si->shr_type)) {
494 /* IPC$ share cannot be removed */
495 smb_shr_cache_unlock();
496 return (ERROR_ACCESS_DENIED);
497 }
498
499 if (si->shr_flags & SMB_SHRF_AUTOHOME) {
500 if ((--si->shr_refcnt) > 0) {
501 smb_shr_cache_unlock();
502 return (NERR_Success);
503 }
504 }
505
506 /*
507 * If path is ZFS, remove the .zfs/shares/<share> entry. Need
508 * to remove before cleanup of cache occurs.
509 */
510 smb_shr_zfs_remove(si);
511 (void) smb_shr_encode(si, &shrlist);
512
513 (void) strlcpy(container, si->shr_container, sizeof (container));
514 dfsroot = ((si->shr_flags & SMB_SHRF_DFSROOT) != 0);
515 smb_shr_cache_delent(sharename);
516 smb_shr_cache_unlock();
517
518 smb_shr_unpublish(sharename, container);
519
520 /* call kernel to release the hold on the shared file system */
521 if (shrlist != NULL) {
522 (void) smb_kmod_unshare(shrlist);
523 nvlist_free(shrlist);
524 }
525
526 if (dfsroot)
527 dfs_namespace_unload(sharename);
528
529 return (NERR_Success);
530 }
553
554 if ((from_si = smb_shr_cache_findent(from_name)) == NULL) {
555 smb_shr_cache_unlock();
556 return (NERR_NetNameNotFound);
557 }
558
559 if (STYPE_ISIPC(from_si->shr_type)) {
560 /* IPC$ share cannot be renamed */
561 smb_shr_cache_unlock();
562 return (ERROR_ACCESS_DENIED);
563 }
564
565 if (smb_shr_cache_findent(to_name) != NULL) {
566 smb_shr_cache_unlock();
567 return (NERR_DuplicateShare);
568 }
569
570 bcopy(from_si, &to_si, sizeof (smb_share_t));
571 (void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name));
572
573
574 /* If path is ZFS, rename the .zfs/shares/<share> entry. */
575 smb_shr_zfs_rename(from_si, &to_si);
576
577 if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) {
578 smb_shr_cache_unlock();
579 return (status);
580 }
581
582 smb_shr_cache_delent(from_name);
583 smb_shr_cache_unlock();
584
585 if (smb_shr_encode(from_si, &shrlist) == 0) {
586 (void) smb_kmod_unshare(shrlist);
587 nvlist_free(shrlist);
588
589 if (smb_shr_encode(&to_si, &shrlist) == 0) {
590 (void) smb_kmod_share(shrlist);
591 nvlist_free(shrlist);
592 }
593 }
594
595 smb_shr_unpublish(from_name, to_si.shr_container);
596 smb_shr_publish(to_name, to_si.shr_container);
611 uint32_t status;
612
613 if (sharename == NULL || *sharename == '\0')
614 return (NERR_NetNameNotFound);
615
616 if ((status = smb_shr_lookup(sharename, si)) == NERR_Success)
617 return (status);
618
619 if ((status = smb_shr_sa_loadbyname(sharename)) == NERR_Success)
620 status = smb_shr_lookup(sharename, si);
621
622 return (status);
623 }
624
625 /*
626 * Modifies an existing share. Properties that can be modified are:
627 *
628 * o comment
629 * o AD container
630 * o host access
631 * o abe
632 */
633 uint32_t
634 smb_shr_modify(smb_share_t *new_si)
635 {
636 smb_share_t *si;
637 boolean_t adc_changed = B_FALSE;
638 char old_container[MAXPATHLEN];
639 uint32_t access, flag;
640 nvlist_t *shrlist;
641
642 assert(new_si != NULL);
643
644 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
645 return (NERR_InternalError);
646
647 if ((si = smb_shr_cache_findent(new_si->shr_name)) == NULL) {
648 smb_shr_cache_unlock();
649 return (NERR_NetNameNotFound);
650 }
651
652 if (STYPE_ISIPC(si->shr_type)) {
653 /* IPC$ share cannot be modified */
654 smb_shr_cache_unlock();
655 return (ERROR_ACCESS_DENIED);
656 }
657
658 (void) strlcpy(si->shr_cmnt, new_si->shr_cmnt, sizeof (si->shr_cmnt));
659
660 adc_changed = (strcmp(new_si->shr_container, si->shr_container) != 0);
661 if (adc_changed) {
662 /* save current container - needed for unpublishing */
663 (void) strlcpy(old_container, si->shr_container,
664 sizeof (old_container));
665 (void) strlcpy(si->shr_container, new_si->shr_container,
666 sizeof (si->shr_container));
667 }
668
669 flag = (new_si->shr_flags & SMB_SHRF_ABE);
670 si->shr_flags &= ~SMB_SHRF_ABE;
671 si->shr_flags |= flag;
672
673 flag = (new_si->shr_flags & SMB_SHRF_CATIA);
674 si->shr_flags &= ~SMB_SHRF_CATIA;
675 si->shr_flags |= flag;
676
677 flag = (new_si->shr_flags & SMB_SHRF_GUEST_OK);
678 si->shr_flags &= ~SMB_SHRF_GUEST_OK;
679 si->shr_flags |= flag;
680
681 flag = (new_si->shr_flags & SMB_SHRF_DFSROOT);
682 si->shr_flags &= ~SMB_SHRF_DFSROOT;
683 si->shr_flags |= flag;
684
685 flag = (new_si->shr_flags & SMB_SHRF_CSC_MASK);
686 si->shr_flags &= ~SMB_SHRF_CSC_MASK;
687 si->shr_flags |= flag;
688
689 access = (new_si->shr_flags & SMB_SHRF_ACC_ALL);
690 si->shr_flags &= ~SMB_SHRF_ACC_ALL;
691 si->shr_flags |= access;
692
693 if (access & SMB_SHRF_ACC_NONE)
694 (void) strlcpy(si->shr_access_none, new_si->shr_access_none,
695 sizeof (si->shr_access_none));
696
697 if (access & SMB_SHRF_ACC_RO)
698 (void) strlcpy(si->shr_access_ro, new_si->shr_access_ro,
699 sizeof (si->shr_access_ro));
700
701 if (access & SMB_SHRF_ACC_RW)
702 (void) strlcpy(si->shr_access_rw, new_si->shr_access_rw,
703 sizeof (si->shr_access_rw));
704
705 smb_shr_cache_unlock();
706
707 if (smb_shr_encode(si, &shrlist) == 0) {
708 (void) smb_kmod_unshare(shrlist);
709 nvlist_free(shrlist);
710
711 if (smb_shr_encode(new_si, &shrlist) == 0) {
712 (void) smb_kmod_share(shrlist);
713 nvlist_free(shrlist);
714 }
715 }
716
717 if (adc_changed) {
718 smb_shr_unpublish(new_si->shr_name, old_container);
719 smb_shr_publish(new_si->shr_name, new_si->shr_container);
720 }
721
722 return (NERR_Success);
723 }
724
725 /*
726 * smb_shr_exists
727 *
728 * Returns B_TRUE if the share exists. Otherwise returns B_FALSE
729 */
730 boolean_t
731 smb_shr_exists(char *sharename)
732 {
733 boolean_t exists = B_FALSE;
734
735 if (sharename == NULL || *sharename == '\0')
736 return (B_FALSE);
737
738 if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
739 exists = (smb_shr_cache_findent(sharename) != NULL);
740 smb_shr_cache_unlock();
741 }
1419
1420 /*
1421 * Call back to free the given cache entry.
1422 */
1423 static void
1424 smb_shr_cache_freent(HT_ITEM *item)
1425 {
1426 if (item && item->hi_data)
1427 free(item->hi_data);
1428 }
1429
1430 /*
1431 * ============================================
1432 * Interfaces to sharemgr
1433 *
1434 * All functions in this section are private
1435 * ============================================
1436 */
1437
1438 /*
1439 * Load shares from sharemgr
1440 */
1441 /*ARGSUSED*/
1442 void *
1443 smb_shr_load(void *args)
1444 {
1445 sa_handle_t handle;
1446 sa_group_t group, subgroup;
1447 char *gstate;
1448 boolean_t gdisabled;
1449
1450 (void) mutex_lock(&smb_shr_exec_mtx);
1451 (void) smb_config_get_execinfo(smb_shr_exec_map, smb_shr_exec_unmap,
1452 MAXPATHLEN);
1453 (void) mutex_unlock(&smb_shr_exec_mtx);
1454
1455 if ((handle = smb_shr_sa_enter()) == NULL) {
1456 syslog(LOG_ERR, "smb_shr_load: load failed");
1457 return (NULL);
1458 }
1459
1460 for (group = sa_get_group(handle, NULL);
1461 group != NULL; group = sa_get_next_group(group)) {
1462 gstate = sa_get_group_attr(group, "state");
1463 if (gstate == NULL)
1464 continue;
1465
1466 gdisabled = (strcasecmp(gstate, "disabled") == 0);
1467 sa_free_attr_string(gstate);
1468 if (gdisabled)
1469 continue;
1470
1471 smb_shr_sa_loadgrp(group);
1472
1473 for (subgroup = sa_get_sub_group(group);
1474 subgroup != NULL;
1475 subgroup = sa_get_next_group(subgroup)) {
1476 smb_shr_sa_loadgrp(subgroup);
1477 }
1478
1479 }
1480 smb_shr_sa_exit();
1481 return (NULL);
1482 }
1483
1484 /*
1485 * Load the shares contained in the specified group.
1486 *
1487 * Don't process groups on which the smb protocol is disabled.
1488 * The top level ZFS group won't have the smb protocol enabled
1489 * but sub-groups will.
1490 *
1491 * We will tolerate a limited number of errors and then give
1492 * up on the current group. A typical error might be that the
1493 * shared directory no longer exists.
1494 */
1495 static void
1496 smb_shr_sa_loadgrp(sa_group_t group)
1497 {
1498 sa_share_t share;
1499 sa_resource_t resource;
1500 int error_count = 0;
1501
1502 if (sa_get_optionset(group, SMB_PROTOCOL_NAME) == NULL)
1503 return;
1504
1518 if (error_count > SMB_SHR_ERROR_THRESHOLD)
1519 break;
1520 }
1521 }
1522
1523 /*
1524 * Load a share definition from sharemgr and add it to the cache.
1525 * If the share is already in the cache then it doesn't do anything.
1526 *
1527 * This function does not report duplicate shares as error since
1528 * a share might have been added by smb_shr_get() while load is
1529 * in progress.
1530 */
1531 static uint32_t
1532 smb_shr_sa_load(sa_share_t share, sa_resource_t resource)
1533 {
1534 smb_share_t si;
1535 char *sharename;
1536 uint32_t status;
1537 boolean_t loaded;
1538
1539 if ((sharename = sa_get_resource_attr(resource, "name")) == NULL)
1540 return (NERR_InternalError);
1541
1542 loaded = smb_shr_exists(sharename);
1543 sa_free_attr_string(sharename);
1544
1545 if (loaded)
1546 return (NERR_Success);
1547
1548 if ((status = smb_shr_sa_get(share, resource, &si)) != NERR_Success) {
1549 syslog(LOG_DEBUG, "share: failed to load %s (%d)",
1550 si.shr_name, status);
1551 return (status);
1552 }
1553
1554 status = smb_shr_add(&si);
1555 if ((status != NERR_Success) && (status != NERR_DuplicateShare)) {
1556 syslog(LOG_DEBUG, "share: failed to cache %s (%d)",
1557 si.shr_name, status);
1558 return (status);
1559 }
1560
1561 return (NERR_Success);
1562 }
1563
1564 static char *
1565 smb_shr_sa_getprop(sa_optionset_t opts, char *propname)
1566 {
1567 sa_property_t prop;
1568 char *val = NULL;
1569
1570 prop = sa_get_property(opts, propname);
1571 if (prop != NULL)
1572 val = sa_get_property_attr(prop, "value");
1573
1574 return (val);
1575 }
1576
1577 /*
1578 * Read the specified share information from sharemgr and return
1579 * it in the given smb_share_t structure.
1580 *
1631 }
1632
1633 val = smb_shr_sa_getprop(opts, SHOPT_ABE);
1634 if (val != NULL) {
1635 smb_shr_sa_setflag(val, si, SMB_SHRF_ABE);
1636 free(val);
1637 }
1638
1639 val = smb_shr_sa_getprop(opts, SHOPT_GUEST);
1640 if (val != NULL) {
1641 smb_shr_sa_setflag(val, si, SMB_SHRF_GUEST_OK);
1642 free(val);
1643 }
1644
1645 val = smb_shr_sa_getprop(opts, SHOPT_DFSROOT);
1646 if (val != NULL) {
1647 smb_shr_sa_setflag(val, si, SMB_SHRF_DFSROOT);
1648 free(val);
1649 }
1650
1651 val = smb_shr_sa_getprop(opts, SHOPT_CSC);
1652 if (val != NULL) {
1653 smb_shr_sa_csc_option(val, si);
1654 free(val);
1655 }
1656
1657 val = smb_shr_sa_getprop(opts, SHOPT_NONE);
1658 if (val != NULL) {
1659 (void) strlcpy(si->shr_access_none, val,
1660 sizeof (si->shr_access_none));
1661 free(val);
1662 si->shr_flags |= SMB_SHRF_ACC_NONE;
1663 }
1664
1665 val = smb_shr_sa_getprop(opts, SHOPT_RO);
1666 if (val != NULL) {
1667 (void) strlcpy(si->shr_access_ro, val,
1668 sizeof (si->shr_access_ro));
1669 free(val);
1670 si->shr_flags |= SMB_SHRF_ACC_RO;
2006 free(shr);
2007 }
2008 }
2009
2010 /*
2011 * Flush all remaining items from the specified list/queue.
2012 */
2013 static void
2014 smb_shr_publisher_flush(list_t *lst)
2015 {
2016 smb_shr_pitem_t *shr;
2017
2018 while ((shr = list_head(lst)) != NULL) {
2019 list_remove(lst, shr);
2020 free(shr);
2021 }
2022 }
2023
2024 /*
2025 * If the share path refers to a ZFS file system, add the
2026 * .zfs/shares/<share> object and call smb_quota_add_fs()
2027 * to initialize quota support for the share.
2028 */
2029 static void
2030 smb_shr_zfs_add(smb_share_t *si)
2031 {
2032 libzfs_handle_t *libhd;
2033 zfs_handle_t *zfshd;
2034 int ret;
2035 char buf[MAXPATHLEN]; /* dataset or mountpoint */
2036
2037 if (smb_getdataset(si->shr_path, buf, MAXPATHLEN) != 0)
2038 return;
2039
2040 if ((libhd = libzfs_init()) == NULL)
2041 return;
2042
2043 if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) {
2044 libzfs_fini(libhd);
2045 return;
2046 }
2047
2048 errno = 0;
2049 ret = zfs_smb_acl_add(libhd, buf, si->shr_path, si->shr_name);
2050 if (ret != 0 && errno != EAGAIN && errno != EEXIST)
2051 syslog(LOG_INFO, "share: failed to add ACL object: %s: %s\n",
2052 si->shr_name, strerror(errno));
2053
2054 if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, buf, MAXPATHLEN,
2055 NULL, NULL, 0, B_FALSE) == 0) {
2056 smb_quota_add_fs(buf);
2057 }
2058
2059
2060 zfs_close(zfshd);
2061 libzfs_fini(libhd);
2062 }
2063
2064 /*
2065 * If the share path refers to a ZFS file system, remove the
2066 * .zfs/shares/<share> object, and call smb_quota_remove_fs()
2067 * to end quota support for the share.
2068 */
2069 static void
2070 smb_shr_zfs_remove(smb_share_t *si)
2071 {
2072 libzfs_handle_t *libhd;
2073 zfs_handle_t *zfshd;
2074 int ret;
2075 char buf[MAXPATHLEN]; /* dataset or mountpoint */
2076
2077 if (smb_getdataset(si->shr_path, buf, MAXPATHLEN) != 0)
2078 return;
2079
2080 if ((libhd = libzfs_init()) == NULL)
2081 return;
2082
2083 if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) {
2084 libzfs_fini(libhd);
2085 return;
2086 }
2087
2088 errno = 0;
2089 ret = zfs_smb_acl_remove(libhd, buf, si->shr_path, si->shr_name);
2090 if (ret != 0 && errno != EAGAIN)
2091 syslog(LOG_INFO, "share: failed to remove ACL object: %s: %s\n",
2092 si->shr_name, strerror(errno));
2093
2094 if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, buf, MAXPATHLEN,
2095 NULL, NULL, 0, B_FALSE) == 0) {
2096 smb_quota_remove_fs(buf);
2097 }
2098
2099 zfs_close(zfshd);
2100 libzfs_fini(libhd);
2101 }
2102
2103 /*
2104 * If the share path refers to a ZFS file system, rename the
2105 * .zfs/shares/<share> object.
2106 */
2107 static void
2108 smb_shr_zfs_rename(smb_share_t *from, smb_share_t *to)
2109 {
2110 libzfs_handle_t *libhd;
2111 zfs_handle_t *zfshd;
2112 int ret;
2113 char dataset[MAXPATHLEN];
2114
2115 if (smb_getdataset(from->shr_path, dataset, MAXPATHLEN) != 0)
2116 return;
2117
2118 if ((libhd = libzfs_init()) == NULL)
2119 return;
2120
2121 if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) {
2122 libzfs_fini(libhd);
2123 return;
2124 }
2125
2126 errno = 0;
2127 ret = zfs_smb_acl_rename(libhd, dataset, from->shr_path,
2128 from->shr_name, to->shr_name);
2129 if (ret != 0 && errno != EAGAIN)
2130 syslog(LOG_INFO, "share: failed to rename ACL object: %s: %s\n",
2131 from->shr_name, strerror(errno));
2132
2133 zfs_close(zfshd);
2134 libzfs_fini(libhd);
2135 }
2136
2137 /*
2138 * Enable all privileges in the inheritable set to execute command.
2139 */
2398 rc |= nvlist_add_string(share, "path", si->shr_path);
2399 rc |= nvlist_add_string(share, "desc", si->shr_cmnt);
2400
2401 /* smb protocol properties */
2402 rc = nvlist_add_string(smb, SHOPT_AD_CONTAINER, si->shr_container);
2403 if ((si->shr_flags & SMB_SHRF_ACC_NONE) != 0)
2404 rc |= nvlist_add_string(smb, SHOPT_NONE, si->shr_access_none);
2405 if ((si->shr_flags & SMB_SHRF_ACC_RO) != 0)
2406 rc |= nvlist_add_string(smb, SHOPT_RO, si->shr_access_ro);
2407 if ((si->shr_flags & SMB_SHRF_ACC_RW) != 0)
2408 rc |= nvlist_add_string(smb, SHOPT_RW, si->shr_access_rw);
2409
2410 if ((si->shr_flags & SMB_SHRF_ABE) != 0)
2411 rc |= nvlist_add_string(smb, SHOPT_ABE, "true");
2412 if ((si->shr_flags & SMB_SHRF_CATIA) != 0)
2413 rc |= nvlist_add_string(smb, SHOPT_CATIA, "true");
2414 if ((si->shr_flags & SMB_SHRF_GUEST_OK) != 0)
2415 rc |= nvlist_add_string(smb, SHOPT_GUEST, "true");
2416 if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0)
2417 rc |= nvlist_add_string(smb, SHOPT_DFSROOT, "true");
2418
2419 if ((si->shr_flags & SMB_SHRF_AUTOHOME) != 0) {
2420 rc |= nvlist_add_string(smb, "Autohome", "true");
2421 rc |= nvlist_add_uint32(smb, "uid", si->shr_uid);
2422 rc |= nvlist_add_uint32(smb, "gid", si->shr_gid);
2423 }
2424
2425 if ((csc = smb_shr_sa_csc_name(si)) != NULL)
2426 rc |= nvlist_add_string(smb, SHOPT_CSC, csc);
2427
2428 rc |= nvlist_add_uint32(smb, "type", si->shr_type);
2429
2430 rc |= nvlist_add_nvlist(share, "smb", smb);
2431 rc |= nvlist_add_nvlist(list, si->shr_name, share);
2432
2433 nvlist_free(share);
2434 nvlist_free(smb);
2435
2436 if (rc != 0)
2437 nvlist_free(list);
2438 else
2439 *nvlist = list;
2440
|
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
22 * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
23 */
24
25 /*
26 * SMB/CIFS share cache implementation.
27 */
28
29 #include <errno.h>
30 #include <synch.h>
31 #include <stdlib.h>
32 #include <strings.h>
33 #include <syslog.h>
34 #include <thread.h>
35 #include <pthread.h>
36 #include <assert.h>
37 #include <libshare.h>
38 #include <libzfs.h>
39 #include <priv_utils.h>
40 #include <sys/types.h>
41 #include <sys/wait.h>
42 #include <unistd.h>
372 return (share);
373 }
374
375 /*
376 * Adds the given share to cache, publishes the share in ADS
377 * if it has an AD container, calls kernel to take a hold on
378 * the shared file system. If it can't take a hold on the
379 * shared file system, it's either because shared directory
380 * does not exist or some other error has occurred, in any
381 * case the share is removed from the cache.
382 *
383 * If the specified share is an autohome share which already
384 * exists in the cache, just increments the reference count.
385 */
386 uint32_t
387 smb_shr_add(smb_share_t *si)
388 {
389 struct stat st;
390 smb_share_t *cached_si;
391 nvlist_t *shrlist;
392 boolean_t created_zfs = B_FALSE;
393 uint32_t status;
394 int rc;
395
396 assert(si != NULL);
397
398 if (smb_name_validate_share(si->shr_name) != ERROR_SUCCESS)
399 return (ERROR_INVALID_NAME);
400
401 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
402 return (NERR_InternalError);
403
404 cached_si = smb_shr_cache_findent(si->shr_name);
405 if (cached_si) {
406 if (si->shr_flags & SMB_SHRF_AUTOHOME) {
407 cached_si->shr_refcnt++;
408 status = NERR_Success;
409 } else {
410 status = NERR_DuplicateShare;
411 }
412 smb_shr_cache_unlock();
413 return (status);
414 }
415
416 if (STYPE_ISDSK(si->shr_type)) {
417 /*
418 * If share type is STYPE_DISKTREE then the path to the
419 * share should exist so that we can add the share to cache.
420 * If path is ZFS, add the .zfs/shares/<share> entry.
421 *
422 * Both actions may require privileges that main dropped,
423 * so we need to temporarily make those effective.
424 */
425 if (smb_proc_takesem() == 0) {
426
427 (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
428 PRIV_FILE_DAC_READ,
429 PRIV_FILE_DAC_SEARCH,
430 PRIV_FILE_DAC_WRITE,
431 NULL);
432
433 rc = stat(si->shr_path, &st);
434 if (rc == 0) {
435 smb_shr_zfs_add(si);
436 created_zfs = B_TRUE;
437 }
438
439 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
440 PRIV_FILE_DAC_READ,
441 PRIV_FILE_DAC_SEARCH,
442 PRIV_FILE_DAC_WRITE,
443 NULL);
444 smb_proc_givesem();
445 } else {
446 rc = NERR_InternalError;
447 }
448 if (rc != 0) {
449 smb_shr_cache_unlock();
450 return (NERR_ItemNotFound);
451 }
452 }
453
454 if ((status = smb_shr_cache_addent(si)) != NERR_Success) {
455 /* This error should be impossible after findent above. */
456 smb_shr_cache_unlock();
457 return (status);
458 }
459
460 /* don't hold the lock across door call */
461 smb_shr_cache_unlock();
462
463 if ((rc = smb_shr_encode(si, &shrlist)) == 0) {
464 /* send the share to kernel */
465 rc = smb_kmod_share(shrlist);
466 nvlist_free(shrlist);
467
468 if (rc == 0) {
469 smb_shr_publish(si->shr_name, si->shr_container);
470
471 if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0)
472 dfs_namespace_load(si->shr_name);
473
474 return (NERR_Success);
475 }
476 }
477
478 /*
479 * Error code path, i.e. when the kernel could not accept
480 * the new share for some reason.
481 */
482 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) {
483 smb_shr_cache_delent(si->shr_name);
484 smb_shr_cache_unlock();
485 }
486
487 if (created_zfs && smb_proc_takesem() == 0) {
488
489 (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
490 PRIV_FILE_DAC_READ,
491 PRIV_FILE_DAC_SEARCH,
492 PRIV_FILE_DAC_WRITE,
493 NULL);
494
495 smb_shr_zfs_remove(si);
496
497 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
498 PRIV_FILE_DAC_READ,
499 PRIV_FILE_DAC_SEARCH,
500 PRIV_FILE_DAC_WRITE,
501 NULL);
502
503 smb_proc_givesem();
504 }
505
506 /*
507 * rc == ENOENT means the shared directory doesn't exist
508 */
509 return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError);
510 }
511
512 /*
513 * Removes the specified share from cache, removes it from AD
514 * if it has an AD container, and calls the kernel to release
515 * the hold on the shared file system.
516 *
517 * If this is an autohome share then decrement the reference
518 * count. If it reaches 0 then it proceeds with removing steps.
519 */
520 uint32_t
521 smb_shr_remove(char *sharename)
522 {
523 smb_share_t *si;
524 char container[MAXPATHLEN];
525 boolean_t dfsroot;
536 if ((si = smb_shr_cache_findent(sharename)) == NULL) {
537 smb_shr_cache_unlock();
538 return (NERR_NetNameNotFound);
539 }
540
541 if (STYPE_ISIPC(si->shr_type)) {
542 /* IPC$ share cannot be removed */
543 smb_shr_cache_unlock();
544 return (ERROR_ACCESS_DENIED);
545 }
546
547 if (si->shr_flags & SMB_SHRF_AUTOHOME) {
548 if ((--si->shr_refcnt) > 0) {
549 smb_shr_cache_unlock();
550 return (NERR_Success);
551 }
552 }
553
554 /*
555 * If path is ZFS, remove the .zfs/shares/<share> entry. Need
556 * to remove before cleanup of cache occurs. These actions
557 * require temporary elevation of privileges.
558 */
559 if (smb_proc_takesem() == 0) {
560
561 (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
562 PRIV_FILE_DAC_READ,
563 PRIV_FILE_DAC_SEARCH,
564 PRIV_FILE_DAC_WRITE,
565 NULL);
566
567 smb_shr_zfs_remove(si);
568
569 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
570 PRIV_FILE_DAC_READ,
571 PRIV_FILE_DAC_SEARCH,
572 PRIV_FILE_DAC_WRITE,
573 NULL);
574
575 smb_proc_givesem();
576 }
577
578 (void) smb_shr_encode(si, &shrlist);
579
580 (void) strlcpy(container, si->shr_container, sizeof (container));
581 dfsroot = ((si->shr_flags & SMB_SHRF_DFSROOT) != 0);
582 smb_shr_cache_delent(sharename);
583 smb_shr_cache_unlock();
584
585 smb_shr_unpublish(sharename, container);
586
587 /* call kernel to release the hold on the shared file system */
588 if (shrlist != NULL) {
589 (void) smb_kmod_unshare(shrlist);
590 nvlist_free(shrlist);
591 }
592
593 if (dfsroot)
594 dfs_namespace_unload(sharename);
595
596 return (NERR_Success);
597 }
620
621 if ((from_si = smb_shr_cache_findent(from_name)) == NULL) {
622 smb_shr_cache_unlock();
623 return (NERR_NetNameNotFound);
624 }
625
626 if (STYPE_ISIPC(from_si->shr_type)) {
627 /* IPC$ share cannot be renamed */
628 smb_shr_cache_unlock();
629 return (ERROR_ACCESS_DENIED);
630 }
631
632 if (smb_shr_cache_findent(to_name) != NULL) {
633 smb_shr_cache_unlock();
634 return (NERR_DuplicateShare);
635 }
636
637 bcopy(from_si, &to_si, sizeof (smb_share_t));
638 (void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name));
639
640 /* If path is ZFS, rename the .zfs/shares/<share> entry. */
641 if (smb_proc_takesem() == 0) {
642
643 (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
644 PRIV_FILE_DAC_READ,
645 PRIV_FILE_DAC_SEARCH,
646 PRIV_FILE_DAC_WRITE,
647 NULL);
648
649 smb_shr_zfs_rename(from_si, &to_si);
650
651 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
652 PRIV_FILE_DAC_READ,
653 PRIV_FILE_DAC_SEARCH,
654 PRIV_FILE_DAC_WRITE,
655 NULL);
656
657 smb_proc_givesem();
658 }
659
660 if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) {
661 smb_shr_cache_unlock();
662 return (status);
663 }
664
665 smb_shr_cache_delent(from_name);
666 smb_shr_cache_unlock();
667
668 if (smb_shr_encode(from_si, &shrlist) == 0) {
669 (void) smb_kmod_unshare(shrlist);
670 nvlist_free(shrlist);
671
672 if (smb_shr_encode(&to_si, &shrlist) == 0) {
673 (void) smb_kmod_share(shrlist);
674 nvlist_free(shrlist);
675 }
676 }
677
678 smb_shr_unpublish(from_name, to_si.shr_container);
679 smb_shr_publish(to_name, to_si.shr_container);
694 uint32_t status;
695
696 if (sharename == NULL || *sharename == '\0')
697 return (NERR_NetNameNotFound);
698
699 if ((status = smb_shr_lookup(sharename, si)) == NERR_Success)
700 return (status);
701
702 if ((status = smb_shr_sa_loadbyname(sharename)) == NERR_Success)
703 status = smb_shr_lookup(sharename, si);
704
705 return (status);
706 }
707
708 /*
709 * Modifies an existing share. Properties that can be modified are:
710 *
711 * o comment
712 * o AD container
713 * o host access
714 * o flags
715 */
716 uint32_t
717 smb_shr_modify(smb_share_t *new_si)
718 {
719 smb_share_t old_si;
720 smb_share_t *si;
721 boolean_t adc_changed = B_FALSE;
722 boolean_t quota_flag_changed = B_FALSE;
723 uint32_t access, flag;
724 nvlist_t *shrlist;
725
726 assert(new_si != NULL);
727
728 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
729 return (NERR_InternalError);
730
731 if ((si = smb_shr_cache_findent(new_si->shr_name)) == NULL) {
732 smb_shr_cache_unlock();
733 return (NERR_NetNameNotFound);
734 }
735
736 if (STYPE_ISIPC(si->shr_type)) {
737 /* IPC$ share cannot be modified */
738 smb_shr_cache_unlock();
739 return (ERROR_ACCESS_DENIED);
740 }
741
742 /*
743 * Keep a copy of what the share entry looks like before we
744 * modify it. We need this for things like unpublishing
745 * from the old share container, removing the quota dir.
746 */
747 bcopy(si, &old_si, sizeof (old_si));
748
749 /* Share comment */
750 (void) strlcpy(si->shr_cmnt, new_si->shr_cmnt, sizeof (si->shr_cmnt));
751
752 /* Container */
753 (void) strlcpy(si->shr_container, new_si->shr_container,
754 sizeof (si->shr_container));
755 adc_changed = (strcmp(old_si.shr_container, si->shr_container) != 0);
756
757 flag = (new_si->shr_flags & SMB_SHRF_ABE);
758 si->shr_flags &= ~SMB_SHRF_ABE;
759 si->shr_flags |= flag;
760
761 flag = (new_si->shr_flags & SMB_SHRF_CATIA);
762 si->shr_flags &= ~SMB_SHRF_CATIA;
763 si->shr_flags |= flag;
764
765 flag = (new_si->shr_flags & SMB_SHRF_GUEST_OK);
766 si->shr_flags &= ~SMB_SHRF_GUEST_OK;
767 si->shr_flags |= flag;
768
769 flag = (new_si->shr_flags & SMB_SHRF_DFSROOT);
770 si->shr_flags &= ~SMB_SHRF_DFSROOT;
771 si->shr_flags |= flag;
772
773 flag = (new_si->shr_flags & SMB_SHRF_CA);
774 si->shr_flags &= ~SMB_SHRF_CA;
775 si->shr_flags |= flag;
776
777 flag = (new_si->shr_flags & SMB_SHRF_FSO);
778 si->shr_flags &= ~SMB_SHRF_FSO;
779 si->shr_flags |= flag;
780
781 flag = (new_si->shr_flags & SMB_SHRF_QUOTAS);
782 si->shr_flags &= ~SMB_SHRF_QUOTAS;
783 si->shr_flags |= flag;
784 if ((old_si.shr_flags ^ si->shr_flags) & SMB_SHRF_QUOTAS)
785 quota_flag_changed = B_TRUE;
786
787 flag = (new_si->shr_flags & SMB_SHRF_CSC_MASK);
788 si->shr_flags &= ~SMB_SHRF_CSC_MASK;
789 si->shr_flags |= flag;
790
791 access = (new_si->shr_flags & SMB_SHRF_ACC_ALL);
792 si->shr_flags &= ~SMB_SHRF_ACC_ALL;
793 si->shr_flags |= access;
794
795 si->shr_encrypt = new_si->shr_encrypt;
796
797 if (access & SMB_SHRF_ACC_NONE)
798 (void) strlcpy(si->shr_access_none, new_si->shr_access_none,
799 sizeof (si->shr_access_none));
800
801 if (access & SMB_SHRF_ACC_RO)
802 (void) strlcpy(si->shr_access_ro, new_si->shr_access_ro,
803 sizeof (si->shr_access_ro));
804
805 if (access & SMB_SHRF_ACC_RW)
806 (void) strlcpy(si->shr_access_rw, new_si->shr_access_rw,
807 sizeof (si->shr_access_rw));
808
809 smb_shr_cache_unlock();
810
811 if (smb_shr_encode(si, &shrlist) == 0) {
812 (void) smb_kmod_unshare(shrlist);
813 nvlist_free(shrlist);
814
815 if (smb_shr_encode(new_si, &shrlist) == 0) {
816 (void) smb_kmod_share(shrlist);
817 nvlist_free(shrlist);
818 }
819 }
820
821 if (adc_changed) {
822 smb_shr_unpublish(old_si.shr_name, old_si.shr_container);
823 smb_shr_publish(new_si->shr_name, new_si->shr_container);
824 }
825
826 /* The following required privileges we dropped. */
827 if (quota_flag_changed && smb_proc_takesem() == 0) {
828
829 (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
830 PRIV_FILE_DAC_READ,
831 PRIV_FILE_DAC_SEARCH,
832 PRIV_FILE_DAC_WRITE,
833 NULL);
834
835 smb_shr_zfs_remove(&old_si);
836 smb_shr_zfs_add(si);
837
838 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
839 PRIV_FILE_DAC_READ,
840 PRIV_FILE_DAC_SEARCH,
841 PRIV_FILE_DAC_WRITE,
842 NULL);
843
844 smb_proc_givesem();
845 }
846
847 return (NERR_Success);
848 }
849
850 /*
851 * smb_shr_exists
852 *
853 * Returns B_TRUE if the share exists. Otherwise returns B_FALSE
854 */
855 boolean_t
856 smb_shr_exists(char *sharename)
857 {
858 boolean_t exists = B_FALSE;
859
860 if (sharename == NULL || *sharename == '\0')
861 return (B_FALSE);
862
863 if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
864 exists = (smb_shr_cache_findent(sharename) != NULL);
865 smb_shr_cache_unlock();
866 }
1544
1545 /*
1546 * Call back to free the given cache entry.
1547 */
1548 static void
1549 smb_shr_cache_freent(HT_ITEM *item)
1550 {
1551 if (item && item->hi_data)
1552 free(item->hi_data);
1553 }
1554
1555 /*
1556 * ============================================
1557 * Interfaces to sharemgr
1558 *
1559 * All functions in this section are private
1560 * ============================================
1561 */
1562
1563 /*
1564 * Loads the SMB shares, from sharemgr, then:
1565 * - calls smb_shr_add which:
1566 * - adds the share into the share cache
1567 * - adds the share into in-kernel kshare table
1568 * - publishes the share in ADS
1569 * - updates the share list in sharefs/sharetab
1570 */
1571 /*ARGSUSED*/
1572 void *
1573 smb_shr_load(void *args)
1574 {
1575 sa_handle_t handle;
1576 sa_group_t group, subgroup;
1577 char *gstate;
1578 boolean_t gdisabled;
1579
1580 smb_shr_load_execinfo();
1581
1582 if ((handle = smb_shr_sa_enter()) == NULL) {
1583 syslog(LOG_ERR, "smb_shr_load: load failed");
1584 return (NULL);
1585 }
1586
1587 for (group = sa_get_group(handle, NULL);
1588 group != NULL; group = sa_get_next_group(group)) {
1589 gstate = sa_get_group_attr(group, "state");
1590 if (gstate == NULL)
1591 continue;
1592
1593 gdisabled = (strcasecmp(gstate, "disabled") == 0);
1594 sa_free_attr_string(gstate);
1595 if (gdisabled)
1596 continue;
1597
1598 smb_shr_sa_loadgrp(group);
1599
1600 for (subgroup = sa_get_sub_group(group);
1601 subgroup != NULL;
1602 subgroup = sa_get_next_group(subgroup)) {
1603 smb_shr_sa_loadgrp(subgroup);
1604 }
1605
1606 }
1607 smb_shr_sa_exit();
1608 return (NULL);
1609 }
1610
1611 void
1612 smb_shr_load_execinfo()
1613 {
1614 (void) mutex_lock(&smb_shr_exec_mtx);
1615 (void) smb_config_get_execinfo(smb_shr_exec_map, smb_shr_exec_unmap,
1616 MAXPATHLEN);
1617 (void) mutex_unlock(&smb_shr_exec_mtx);
1618 }
1619
1620 /*
1621 * Handles disabling shares in sharefs when stoping smbd
1622 */
1623 void
1624 smb_shr_unload()
1625 {
1626 smb_shriter_t iterator;
1627 smb_share_t *si;
1628 sa_handle_t handle;
1629 int rc;
1630
1631 if ((handle = smb_shr_sa_enter()) == NULL) {
1632 syslog(LOG_ERR, "smb_shr_unload: failed");
1633 return;
1634 }
1635
1636 smb_shr_iterinit(&iterator);
1637
1638 while ((si = smb_shr_iterate(&iterator)) != NULL) {
1639
1640 /* Skip transient shares, IPC$, ... */
1641 if ((si->shr_flags & SMB_SHRF_TRANS) ||
1642 STYPE_ISIPC(si->shr_type))
1643 continue;
1644
1645 rc = sa_delete_sharetab(handle, si->shr_path, "smb");
1646 if (rc) {
1647 syslog(LOG_ERR,
1648 "sharefs remove %s failed, rc=%d, err=%d",
1649 si->shr_path, rc, errno);
1650 }
1651 }
1652 smb_shr_sa_exit();
1653 }
1654
1655 /*
1656 * Load the shares contained in the specified group.
1657 *
1658 * Don't process groups on which the smb protocol is disabled.
1659 * The top level ZFS group won't have the smb protocol enabled
1660 * but sub-groups will.
1661 *
1662 * We will tolerate a limited number of errors and then give
1663 * up on the current group. A typical error might be that the
1664 * shared directory no longer exists.
1665 */
1666 static void
1667 smb_shr_sa_loadgrp(sa_group_t group)
1668 {
1669 sa_share_t share;
1670 sa_resource_t resource;
1671 int error_count = 0;
1672
1673 if (sa_get_optionset(group, SMB_PROTOCOL_NAME) == NULL)
1674 return;
1675
1689 if (error_count > SMB_SHR_ERROR_THRESHOLD)
1690 break;
1691 }
1692 }
1693
1694 /*
1695 * Load a share definition from sharemgr and add it to the cache.
1696 * If the share is already in the cache then it doesn't do anything.
1697 *
1698 * This function does not report duplicate shares as error since
1699 * a share might have been added by smb_shr_get() while load is
1700 * in progress.
1701 */
1702 static uint32_t
1703 smb_shr_sa_load(sa_share_t share, sa_resource_t resource)
1704 {
1705 smb_share_t si;
1706 char *sharename;
1707 uint32_t status;
1708 boolean_t loaded;
1709 int rc;
1710
1711 if ((sharename = sa_get_resource_attr(resource, "name")) == NULL)
1712 return (NERR_InternalError);
1713
1714 loaded = smb_shr_exists(sharename);
1715 sa_free_attr_string(sharename);
1716
1717 if (loaded)
1718 return (NERR_Success);
1719
1720 if ((status = smb_shr_sa_get(share, resource, &si)) != NERR_Success) {
1721 syslog(LOG_DEBUG, "share: failed to load %s (%d)",
1722 si.shr_name, status);
1723 return (status);
1724 }
1725
1726 status = smb_shr_add(&si);
1727 if ((status != NERR_Success) && (status != NERR_DuplicateShare)) {
1728 syslog(LOG_DEBUG, "share: failed to cache %s (%d)",
1729 si.shr_name, status);
1730 return (status);
1731 }
1732
1733 rc = sa_update_sharetab(share, "smb");
1734 if (rc) {
1735 syslog(LOG_ERR, "sharefs add %s failed, rc=%d, err=%d",
1736 sharename, rc, errno);
1737 }
1738
1739 return (NERR_Success);
1740 }
1741
1742 static char *
1743 smb_shr_sa_getprop(sa_optionset_t opts, char *propname)
1744 {
1745 sa_property_t prop;
1746 char *val = NULL;
1747
1748 prop = sa_get_property(opts, propname);
1749 if (prop != NULL)
1750 val = sa_get_property_attr(prop, "value");
1751
1752 return (val);
1753 }
1754
1755 /*
1756 * Read the specified share information from sharemgr and return
1757 * it in the given smb_share_t structure.
1758 *
1809 }
1810
1811 val = smb_shr_sa_getprop(opts, SHOPT_ABE);
1812 if (val != NULL) {
1813 smb_shr_sa_setflag(val, si, SMB_SHRF_ABE);
1814 free(val);
1815 }
1816
1817 val = smb_shr_sa_getprop(opts, SHOPT_GUEST);
1818 if (val != NULL) {
1819 smb_shr_sa_setflag(val, si, SMB_SHRF_GUEST_OK);
1820 free(val);
1821 }
1822
1823 val = smb_shr_sa_getprop(opts, SHOPT_DFSROOT);
1824 if (val != NULL) {
1825 smb_shr_sa_setflag(val, si, SMB_SHRF_DFSROOT);
1826 free(val);
1827 }
1828
1829 val = smb_shr_sa_getprop(opts, SHOPT_CA);
1830 if (val != NULL) {
1831 smb_shr_sa_setflag(val, si, SMB_SHRF_CA);
1832 free(val);
1833 }
1834
1835 val = smb_shr_sa_getprop(opts, SHOPT_FSO);
1836 if (val != NULL) {
1837 smb_shr_sa_setflag(val, si, SMB_SHRF_FSO);
1838 free(val);
1839 }
1840
1841 val = smb_shr_sa_getprop(opts, SHOPT_QUOTAS);
1842 if (val != NULL) {
1843 /* Turn the flag on or off */
1844 smb_shr_sa_setflag(val, si, SMB_SHRF_QUOTAS);
1845 free(val);
1846 } else {
1847 /* Default for this is enabled. */
1848 si->shr_flags |= SMB_SHRF_QUOTAS;
1849 }
1850
1851 val = smb_shr_sa_getprop(opts, SHOPT_ENCRYPT);
1852 if (val != NULL) {
1853 smb_cfg_set_require(val, &si->shr_encrypt);
1854 free(val);
1855 }
1856
1857 val = smb_shr_sa_getprop(opts, SHOPT_CSC);
1858 if (val != NULL) {
1859 smb_shr_sa_csc_option(val, si);
1860 free(val);
1861 }
1862
1863 val = smb_shr_sa_getprop(opts, SHOPT_NONE);
1864 if (val != NULL) {
1865 (void) strlcpy(si->shr_access_none, val,
1866 sizeof (si->shr_access_none));
1867 free(val);
1868 si->shr_flags |= SMB_SHRF_ACC_NONE;
1869 }
1870
1871 val = smb_shr_sa_getprop(opts, SHOPT_RO);
1872 if (val != NULL) {
1873 (void) strlcpy(si->shr_access_ro, val,
1874 sizeof (si->shr_access_ro));
1875 free(val);
1876 si->shr_flags |= SMB_SHRF_ACC_RO;
2212 free(shr);
2213 }
2214 }
2215
2216 /*
2217 * Flush all remaining items from the specified list/queue.
2218 */
2219 static void
2220 smb_shr_publisher_flush(list_t *lst)
2221 {
2222 smb_shr_pitem_t *shr;
2223
2224 while ((shr = list_head(lst)) != NULL) {
2225 list_remove(lst, shr);
2226 free(shr);
2227 }
2228 }
2229
2230 /*
2231 * If the share path refers to a ZFS file system, add the
2232 * .zfs/shares/<share> object and add or remove the special
2233 * directory and file telling clients about quota support.
2234 */
2235 static void
2236 smb_shr_zfs_add(smb_share_t *si)
2237 {
2238 libzfs_handle_t *libhd;
2239 zfs_handle_t *zfshd;
2240 int ret;
2241 char buf[MAXPATHLEN]; /* dataset or mountpoint */
2242
2243 if ((libhd = libzfs_init()) == NULL)
2244 return;
2245
2246 if (smb_getdataset(libhd, si->shr_path, buf, MAXPATHLEN) != 0) {
2247 libzfs_fini(libhd);
2248 return;
2249 }
2250
2251 if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) {
2252 libzfs_fini(libhd);
2253 return;
2254 }
2255
2256 errno = 0;
2257 ret = zfs_smb_acl_add(libhd, buf, si->shr_path, si->shr_name);
2258 if (ret != 0 && errno != EAGAIN && errno != EEXIST)
2259 syslog(LOG_INFO, "share: failed to add ACL object: %s: %s\n",
2260 si->shr_name, strerror(errno));
2261
2262 ret = zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT,
2263 buf, MAXPATHLEN, NULL, NULL, 0, B_FALSE);
2264 if (ret != 0) {
2265 syslog(LOG_INFO, "share: failed to get mountpoint: "
2266 "%s\n", si->shr_name);
2267 } else {
2268 if ((si->shr_flags & SMB_SHRF_QUOTAS) != 0) {
2269 smb_quota_add_fs(buf);
2270 } else {
2271 smb_quota_remove_fs(buf);
2272 }
2273 }
2274
2275 zfs_close(zfshd);
2276 libzfs_fini(libhd);
2277 }
2278
2279 /*
2280 * If the share path refers to a ZFS file system, remove the
2281 * .zfs/shares/<share> object.
2282 */
2283 static void
2284 smb_shr_zfs_remove(smb_share_t *si)
2285 {
2286 libzfs_handle_t *libhd;
2287 int ret;
2288 char buf[MAXPATHLEN]; /* dataset or mountpoint */
2289
2290 if ((libhd = libzfs_init()) == NULL)
2291 return;
2292
2293 if (smb_getdataset(libhd, si->shr_path, buf, MAXPATHLEN) != 0) {
2294 libzfs_fini(libhd);
2295 return;
2296 }
2297
2298 errno = 0;
2299 ret = zfs_smb_acl_remove(libhd, buf, si->shr_path, si->shr_name);
2300 if (ret != 0 && errno != EAGAIN)
2301 syslog(LOG_INFO, "share: failed to remove ACL object: %s: %s\n",
2302 si->shr_name, strerror(errno));
2303
2304 /*
2305 * We could remove the quotas directory here, but that adds
2306 * significantly to the time required for a zpool export,
2307 * so just leave it here and fixup when we share next.
2308 */
2309
2310 libzfs_fini(libhd);
2311 }
2312
2313 /*
2314 * If the share path refers to a ZFS file system, rename the
2315 * .zfs/shares/<share> object.
2316 */
2317 static void
2318 smb_shr_zfs_rename(smb_share_t *from, smb_share_t *to)
2319 {
2320 libzfs_handle_t *libhd;
2321 zfs_handle_t *zfshd;
2322 int ret;
2323 char dataset[MAXPATHLEN];
2324
2325 if ((libhd = libzfs_init()) == NULL)
2326 return;
2327
2328 if (smb_getdataset(libhd, from->shr_path, dataset, MAXPATHLEN) != 0) {
2329 libzfs_fini(libhd);
2330 return;
2331 }
2332
2333 if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) {
2334 libzfs_fini(libhd);
2335 return;
2336 }
2337
2338 errno = 0;
2339 ret = zfs_smb_acl_rename(libhd, dataset, from->shr_path,
2340 from->shr_name, to->shr_name);
2341 if (ret != 0 && errno != EAGAIN)
2342 syslog(LOG_INFO, "share: failed to rename ACL object: %s: %s\n",
2343 from->shr_name, strerror(errno));
2344
2345 zfs_close(zfshd);
2346 libzfs_fini(libhd);
2347 }
2348
2349 /*
2350 * Enable all privileges in the inheritable set to execute command.
2351 */
2610 rc |= nvlist_add_string(share, "path", si->shr_path);
2611 rc |= nvlist_add_string(share, "desc", si->shr_cmnt);
2612
2613 /* smb protocol properties */
2614 rc = nvlist_add_string(smb, SHOPT_AD_CONTAINER, si->shr_container);
2615 if ((si->shr_flags & SMB_SHRF_ACC_NONE) != 0)
2616 rc |= nvlist_add_string(smb, SHOPT_NONE, si->shr_access_none);
2617 if ((si->shr_flags & SMB_SHRF_ACC_RO) != 0)
2618 rc |= nvlist_add_string(smb, SHOPT_RO, si->shr_access_ro);
2619 if ((si->shr_flags & SMB_SHRF_ACC_RW) != 0)
2620 rc |= nvlist_add_string(smb, SHOPT_RW, si->shr_access_rw);
2621
2622 if ((si->shr_flags & SMB_SHRF_ABE) != 0)
2623 rc |= nvlist_add_string(smb, SHOPT_ABE, "true");
2624 if ((si->shr_flags & SMB_SHRF_CATIA) != 0)
2625 rc |= nvlist_add_string(smb, SHOPT_CATIA, "true");
2626 if ((si->shr_flags & SMB_SHRF_GUEST_OK) != 0)
2627 rc |= nvlist_add_string(smb, SHOPT_GUEST, "true");
2628 if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0)
2629 rc |= nvlist_add_string(smb, SHOPT_DFSROOT, "true");
2630 if ((si->shr_flags & SMB_SHRF_CA) != 0)
2631 rc |= nvlist_add_string(smb, SHOPT_CA, "true");
2632 if ((si->shr_flags & SMB_SHRF_FSO) != 0)
2633 rc |= nvlist_add_string(smb, SHOPT_FSO, "true");
2634 if ((si->shr_flags & SMB_SHRF_QUOTAS) != 0)
2635 rc |= nvlist_add_string(smb, SHOPT_QUOTAS, "true");
2636
2637 if (si->shr_encrypt == SMB_CONFIG_REQUIRED)
2638 rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "required");
2639 else if (si->shr_encrypt == SMB_CONFIG_ENABLED)
2640 rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "enabled");
2641 else
2642 rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "disabled");
2643
2644 if ((si->shr_flags & SMB_SHRF_AUTOHOME) != 0) {
2645 rc |= nvlist_add_string(smb, SHOPT_AUTOHOME, "true");
2646 rc |= nvlist_add_uint32(smb, "uid", si->shr_uid);
2647 rc |= nvlist_add_uint32(smb, "gid", si->shr_gid);
2648 }
2649
2650 if ((csc = smb_shr_sa_csc_name(si)) != NULL)
2651 rc |= nvlist_add_string(smb, SHOPT_CSC, csc);
2652
2653 rc |= nvlist_add_uint32(smb, "type", si->shr_type);
2654
2655 rc |= nvlist_add_nvlist(share, "smb", smb);
2656 rc |= nvlist_add_nvlist(list, si->shr_name, share);
2657
2658 nvlist_free(share);
2659 nvlist_free(smb);
2660
2661 if (rc != 0)
2662 nvlist_free(list);
2663 else
2664 *nvlist = list;
2665
|