Print this page
NEX-17457 kernel share list fails to be updated after fs import
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Yuri Pankov <yuripv@yuripv.net>
NEX-16159 Time spent sharing SMB filesystems could be reduced by optimizing smb_getdataset for default mount points
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-10098 Disabling SMB server service does not change the sharestate of a smb share to “offline”.(cstyle)
NEX-10098 Disabling SMB server service does not change the sharestate of a smb share to “offline”.
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
NEX-5273 SMB 3 Encryption
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-6949 SMB shares with no permission for root fail after restart
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexent.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-6135 Pool cannot get exported while deletes is running
Reviewed by: Alek Pinchuk <alek@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexent.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
NEX-4865 Still creating .$EXTEND directory with quotas disabled
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-3863 Would like an SMB share property to enable/disable quotas
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-3673 CLONE NEX-2525 Customer cannot set Share Properties using MMC in Windows Server 2008 R2
Reviewed by: Alek Pinchuk <alek@nexenta.com>
NEX-1473 share unavailable after failover (copyright update)
NEX-1473 share unavailable after failover


   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