1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  *
  21  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  22  * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
  23  */
  24 
  25 /*
  26  * SMB/CIFS share cache implementation.
  27  */
  28 
  29 #include <errno.h>
  30 #include <synch.h>
  31 #include <stdlib.h>
  32 #include <strings.h>
  33 #include <syslog.h>
  34 #include <thread.h>
  35 #include <pthread.h>
  36 #include <assert.h>
  37 #include <libshare.h>
  38 #include <libzfs.h>
  39 #include <priv_utils.h>
  40 #include <sys/types.h>
  41 #include <sys/wait.h>
  42 #include <unistd.h>
  43 #include <pwd.h>
  44 #include <signal.h>
  45 #include <dirent.h>
  46 #include <dlfcn.h>
  47 
  48 #include <smbsrv/libsmb.h>
  49 #include <smbsrv/libsmbns.h>
  50 #include <smbsrv/libmlsvc.h>
  51 #include <smbsrv/smb_share.h>
  52 #include <smbsrv/smb.h>
  53 #include <mlsvc.h>
  54 #include <dfs.h>
  55 
  56 #define SMB_SHR_ERROR_THRESHOLD         3
  57 #define SMB_SHR_CSC_BUFSZ               64
  58 
  59 typedef struct smb_transient {
  60         char            *name;
  61         char            *cmnt;
  62         char            *path;
  63         char            drive;
  64         boolean_t       check;
  65 } smb_transient_t;
  66 
  67 static smb_transient_t tshare[] = {
  68         { "IPC$", "Remote IPC",         NULL,           '\0', B_FALSE },
  69         { "c$",   "Default Share",      SMB_CVOL,       'C',  B_FALSE },
  70         { "vss$", "VSS",                SMB_VSS,        'V',  B_TRUE }
  71 };
  72 
  73 static struct {
  74         char *value;
  75         uint32_t flag;
  76 } cscopt[] = {
  77         { "disabled",   SMB_SHRF_CSC_DISABLED },
  78         { "manual",     SMB_SHRF_CSC_MANUAL },
  79         { "auto",       SMB_SHRF_CSC_AUTO },
  80         { "vdo",        SMB_SHRF_CSC_VDO }
  81 };
  82 
  83 /*
  84  * Cache functions and vars
  85  */
  86 #define SMB_SHR_HTAB_SZ                 1024
  87 
  88 /*
  89  * Cache handle
  90  *
  91  * Shares cache is a hash table.
  92  *
  93  * sc_cache             pointer to hash table handle
  94  * sc_cache_lck         synchronize cache read/write accesses
  95  * sc_state             cache state machine values
  96  * sc_nops              number of inflight/pending cache operations
  97  * sc_mtx               protects handle fields
  98  */
  99 typedef struct smb_shr_cache {
 100         HT_HANDLE       *sc_cache;
 101         rwlock_t        sc_cache_lck;
 102         mutex_t         sc_mtx;
 103         cond_t          sc_cv;
 104         uint32_t        sc_state;
 105         uint32_t        sc_nops;
 106 } smb_shr_cache_t;
 107 
 108 /*
 109  * Cache states
 110  */
 111 #define SMB_SHR_CACHE_STATE_NONE        0
 112 #define SMB_SHR_CACHE_STATE_CREATED     1
 113 #define SMB_SHR_CACHE_STATE_DESTROYING  2
 114 
 115 /*
 116  * Cache lock modes
 117  */
 118 #define SMB_SHR_CACHE_RDLOCK    0
 119 #define SMB_SHR_CACHE_WRLOCK    1
 120 
 121 static smb_shr_cache_t smb_shr_cache;
 122 
 123 static uint32_t smb_shr_cache_create(void);
 124 static void smb_shr_cache_destroy(void);
 125 static uint32_t smb_shr_cache_lock(int);
 126 static void smb_shr_cache_unlock(void);
 127 static int smb_shr_cache_count(void);
 128 static smb_share_t *smb_shr_cache_iterate(smb_shriter_t *);
 129 
 130 static smb_share_t *smb_shr_cache_findent(char *);
 131 static uint32_t smb_shr_cache_addent(smb_share_t *);
 132 static void smb_shr_cache_delent(char *);
 133 static void smb_shr_cache_freent(HT_ITEM *);
 134 
 135 static boolean_t smb_shr_is_empty(const char *);
 136 static boolean_t smb_shr_is_dot_or_dotdot(const char *);
 137 
 138 /*
 139  * sharemgr functions
 140  */
 141 static void smb_shr_sa_loadgrp(sa_group_t);
 142 static uint32_t smb_shr_sa_load(sa_share_t, sa_resource_t);
 143 static uint32_t smb_shr_sa_loadbyname(char *);
 144 static uint32_t smb_shr_sa_get(sa_share_t, sa_resource_t, smb_share_t *);
 145 
 146 /*
 147  * .ZFS management functions
 148  */
 149 static void smb_shr_zfs_add(smb_share_t *);
 150 static void smb_shr_zfs_remove(smb_share_t *);
 151 static void smb_shr_zfs_rename(smb_share_t *, smb_share_t *);
 152 
 153 /*
 154  * share publishing
 155  */
 156 #define SMB_SHR_PUBLISH         0
 157 #define SMB_SHR_UNPUBLISH       1
 158 
 159 typedef struct smb_shr_pitem {
 160         list_node_t     spi_lnd;
 161         char            spi_name[MAXNAMELEN];
 162         char            spi_container[MAXPATHLEN];
 163         char            spi_op;
 164 } smb_shr_pitem_t;
 165 
 166 /*
 167  * publish queue states
 168  */
 169 #define SMB_SHR_PQS_NOQUEUE     0
 170 #define SMB_SHR_PQS_READY       1       /* the queue is ready */
 171 #define SMB_SHR_PQS_PUBLISHING  2       /* publisher thread is running */
 172 #define SMB_SHR_PQS_STOPPING    3
 173 
 174 /*
 175  * share publishing queue
 176  */
 177 typedef struct smb_shr_pqueue {
 178         list_t          spq_list;
 179         mutex_t         spq_mtx;
 180         cond_t          spq_cv;
 181         uint32_t        spq_state;
 182 } smb_shr_pqueue_t;
 183 
 184 static smb_shr_pqueue_t ad_queue;
 185 
 186 static int smb_shr_publisher_start(void);
 187 static void smb_shr_publisher_stop(void);
 188 static void smb_shr_publisher_send(smb_ads_handle_t *, list_t *, const char *);
 189 static void smb_shr_publisher_queue(const char *, const char *, char);
 190 static void *smb_shr_publisher(void *);
 191 static void smb_shr_publisher_flush(list_t *);
 192 static void smb_shr_publish(const char *, const char *);
 193 static void smb_shr_unpublish(const char *, const char *);
 194 
 195 /*
 196  * Utility/helper functions
 197  */
 198 static uint32_t smb_shr_lookup(char *, smb_share_t *);
 199 static uint32_t smb_shr_add_transient(char *, char *, char *);
 200 static int smb_shr_enable_all_privs(void);
 201 static int smb_shr_expand_subs(char **, smb_share_t *, smb_shr_execinfo_t *);
 202 static char **smb_shr_tokenize_cmd(char *);
 203 static void smb_shr_sig_abnormal_term(int);
 204 static void smb_shr_sig_child(int);
 205 static int smb_shr_encode(smb_share_t *, nvlist_t **);
 206 
 207 /*
 208  * libshare handle and synchronization
 209  */
 210 typedef struct smb_sa_handle {
 211         sa_handle_t     sa_handle;
 212         mutex_t         sa_mtx;
 213         boolean_t       sa_in_service;
 214 } smb_sa_handle_t;
 215 
 216 static smb_sa_handle_t smb_sa_handle;
 217 
 218 static char smb_shr_exec_map[MAXPATHLEN];
 219 static char smb_shr_exec_unmap[MAXPATHLEN];
 220 static mutex_t smb_shr_exec_mtx;
 221 
 222 /*
 223  * Semaphore held during temporary, process-wide changes
 224  * such as process privileges.  It is a seamaphore and
 225  * not a mutex so a child of fork can reset it.
 226  */
 227 static sema_t smb_proc_sem = DEFAULTSEMA;
 228 
 229 /*
 230  * Creates and initializes the cache and starts the publisher
 231  * thread.
 232  */
 233 int
 234 smb_shr_start(void)
 235 {
 236         smb_transient_t *ts;
 237         uint32_t        nerr;
 238         int             i;
 239 
 240         (void) mutex_lock(&smb_sa_handle.sa_mtx);
 241         smb_sa_handle.sa_in_service = B_TRUE;
 242         (void) mutex_unlock(&smb_sa_handle.sa_mtx);
 243 
 244         if (smb_shr_cache_create() != NERR_Success)
 245                 return (ENOMEM);
 246 
 247         for (i = 0; i < sizeof (tshare)/sizeof (tshare[0]); ++i) {
 248                 ts = &tshare[i];
 249 
 250                 if (ts->check && smb_shr_is_empty(ts->path))
 251                         continue;
 252 
 253                 nerr = smb_shr_add_transient(ts->name, ts->cmnt, ts->path);
 254                 if (nerr != NERR_Success)
 255                         return (ENOMEM);
 256         }
 257 
 258         return (smb_shr_publisher_start());
 259 }
 260 
 261 void
 262 smb_shr_stop(void)
 263 {
 264         smb_shr_cache_destroy();
 265         smb_shr_publisher_stop();
 266 
 267         (void) mutex_lock(&smb_sa_handle.sa_mtx);
 268         smb_sa_handle.sa_in_service = B_FALSE;
 269 
 270         if (smb_sa_handle.sa_handle != NULL) {
 271                 sa_fini(smb_sa_handle.sa_handle);
 272                 smb_sa_handle.sa_handle = NULL;
 273         }
 274 
 275         (void) mutex_unlock(&smb_sa_handle.sa_mtx);
 276 }
 277 
 278 /*
 279  * Get a handle and exclusive access to the libshare API.
 280  */
 281 sa_handle_t
 282 smb_shr_sa_enter(void)
 283 {
 284         (void) mutex_lock(&smb_sa_handle.sa_mtx);
 285         if (!smb_sa_handle.sa_in_service) {
 286                 (void) mutex_unlock(&smb_sa_handle.sa_mtx);
 287                 return (NULL);
 288         }
 289 
 290         if (smb_sa_handle.sa_handle != NULL &&
 291             sa_needs_refresh(smb_sa_handle.sa_handle)) {
 292                 sa_fini(smb_sa_handle.sa_handle);
 293                 smb_sa_handle.sa_handle = NULL;
 294         }
 295 
 296         if (smb_sa_handle.sa_handle == NULL) {
 297                 smb_sa_handle.sa_handle = sa_init(SA_INIT_SHARE_API);
 298                 if (smb_sa_handle.sa_handle == NULL) {
 299                         syslog(LOG_ERR, "share: failed to get libshare handle");
 300                         (void) mutex_unlock(&smb_sa_handle.sa_mtx);
 301                         return (NULL);
 302                 }
 303         }
 304 
 305         return (smb_sa_handle.sa_handle);
 306 }
 307 
 308 /*
 309  * Release exclusive access to the libshare API.
 310  */
 311 void
 312 smb_shr_sa_exit(void)
 313 {
 314         (void) mutex_unlock(&smb_sa_handle.sa_mtx);
 315 }
 316 
 317 /*
 318  * Return the total number of shares
 319  */
 320 int
 321 smb_shr_count(void)
 322 {
 323         int n_shares = 0;
 324 
 325         if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
 326                 n_shares = smb_shr_cache_count();
 327                 smb_shr_cache_unlock();
 328         }
 329 
 330         return (n_shares);
 331 }
 332 
 333 /*
 334  * smb_shr_iterinit
 335  *
 336  * Initialize given iterator for traversing hash table.
 337  */
 338 void
 339 smb_shr_iterinit(smb_shriter_t *shi)
 340 {
 341         bzero(shi, sizeof (smb_shriter_t));
 342         shi->si_first = B_TRUE;
 343 }
 344 
 345 /*
 346  * smb_shr_iterate
 347  *
 348  * Iterate on the shares in the hash table. The iterator must be initialized
 349  * before the first iteration. On subsequent calls, the iterator must be
 350  * passed unchanged.
 351  *
 352  * Returns NULL on failure or when all shares are visited, otherwise
 353  * returns information of visited share.
 354  */
 355 smb_share_t *
 356 smb_shr_iterate(smb_shriter_t *shi)
 357 {
 358         smb_share_t *share = NULL;
 359         smb_share_t *cached_si;
 360 
 361         if (shi == NULL)
 362                 return (NULL);
 363 
 364         if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
 365                 if ((cached_si = smb_shr_cache_iterate(shi)) != NULL) {
 366                         share = &shi->si_share;
 367                         bcopy(cached_si, share, sizeof (smb_share_t));
 368                 }
 369                 smb_shr_cache_unlock();
 370         }
 371 
 372         return (share);
 373 }
 374 
 375 /*
 376  * Adds the given share to cache, publishes the share in ADS
 377  * if it has an AD container, calls kernel to take a hold on
 378  * the shared file system. If it can't take a hold on the
 379  * shared file system, it's either because shared directory
 380  * does not exist or some other error has occurred, in any
 381  * case the share is removed from the cache.
 382  *
 383  * If the specified share is an autohome share which already
 384  * exists in the cache, just increments the reference count.
 385  */
 386 uint32_t
 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;
 478         nvlist_t *shrlist;
 479 
 480         assert(sharename != NULL);
 481 
 482         if (smb_name_validate_share(sharename) != ERROR_SUCCESS)
 483                 return (ERROR_INVALID_NAME);
 484 
 485         if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
 486                 return (NERR_InternalError);
 487 
 488         if ((si = smb_shr_cache_findent(sharename)) == NULL) {
 489                 smb_shr_cache_unlock();
 490                 return (NERR_NetNameNotFound);
 491         }
 492 
 493         if (STYPE_ISIPC(si->shr_type)) {
 494                 /* IPC$ share cannot be removed */
 495                 smb_shr_cache_unlock();
 496                 return (ERROR_ACCESS_DENIED);
 497         }
 498 
 499         if (si->shr_flags & SMB_SHRF_AUTOHOME) {
 500                 if ((--si->shr_refcnt) > 0) {
 501                         smb_shr_cache_unlock();
 502                         return (NERR_Success);
 503                 }
 504         }
 505 
 506         /*
 507          * If path is ZFS, remove the .zfs/shares/<share> entry.  Need
 508          * to remove before cleanup of cache occurs.
 509          */
 510         smb_shr_zfs_remove(si);
 511         (void) smb_shr_encode(si, &shrlist);
 512 
 513         (void) strlcpy(container, si->shr_container, sizeof (container));
 514         dfsroot = ((si->shr_flags & SMB_SHRF_DFSROOT) != 0);
 515         smb_shr_cache_delent(sharename);
 516         smb_shr_cache_unlock();
 517 
 518         smb_shr_unpublish(sharename, container);
 519 
 520         /* call kernel to release the hold on the shared file system */
 521         if (shrlist != NULL) {
 522                 (void) smb_kmod_unshare(shrlist);
 523                 nvlist_free(shrlist);
 524         }
 525 
 526         if (dfsroot)
 527                 dfs_namespace_unload(sharename);
 528 
 529         return (NERR_Success);
 530 }
 531 
 532 /*
 533  * Rename a share. Check that the current name exists and the new name
 534  * doesn't exist. The rename is performed by deleting the current share
 535  * definition and creating a new share with the new name.
 536  */
 537 uint32_t
 538 smb_shr_rename(char *from_name, char *to_name)
 539 {
 540         smb_share_t *from_si;
 541         smb_share_t to_si;
 542         uint32_t status;
 543         nvlist_t *shrlist;
 544 
 545         assert((from_name != NULL) && (to_name != NULL));
 546 
 547         if (smb_name_validate_share(from_name) != ERROR_SUCCESS ||
 548             smb_name_validate_share(to_name) != ERROR_SUCCESS)
 549                 return (ERROR_INVALID_NAME);
 550 
 551         if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
 552                 return (NERR_InternalError);
 553 
 554         if ((from_si = smb_shr_cache_findent(from_name)) == NULL) {
 555                 smb_shr_cache_unlock();
 556                 return (NERR_NetNameNotFound);
 557         }
 558 
 559         if (STYPE_ISIPC(from_si->shr_type)) {
 560                 /* IPC$ share cannot be renamed */
 561                 smb_shr_cache_unlock();
 562                 return (ERROR_ACCESS_DENIED);
 563         }
 564 
 565         if (smb_shr_cache_findent(to_name) != NULL) {
 566                 smb_shr_cache_unlock();
 567                 return (NERR_DuplicateShare);
 568         }
 569 
 570         bcopy(from_si, &to_si, sizeof (smb_share_t));
 571         (void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name));
 572 
 573 
 574         /* If path is ZFS, rename the .zfs/shares/<share> entry. */
 575         smb_shr_zfs_rename(from_si, &to_si);
 576 
 577         if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) {
 578                 smb_shr_cache_unlock();
 579                 return (status);
 580         }
 581 
 582         smb_shr_cache_delent(from_name);
 583         smb_shr_cache_unlock();
 584 
 585         if (smb_shr_encode(from_si, &shrlist) == 0) {
 586                 (void) smb_kmod_unshare(shrlist);
 587                 nvlist_free(shrlist);
 588 
 589                 if (smb_shr_encode(&to_si, &shrlist) == 0) {
 590                         (void) smb_kmod_share(shrlist);
 591                         nvlist_free(shrlist);
 592                 }
 593         }
 594 
 595         smb_shr_unpublish(from_name, to_si.shr_container);
 596         smb_shr_publish(to_name, to_si.shr_container);
 597 
 598         return (NERR_Success);
 599 }
 600 
 601 /*
 602  * Load the information for the specified share into the supplied share
 603  * info structure.
 604  *
 605  * First looks up the cache to see if the specified share exists, if there
 606  * is a miss then it looks up sharemgr.
 607  */
 608 uint32_t
 609 smb_shr_get(char *sharename, smb_share_t *si)
 610 {
 611         uint32_t status;
 612 
 613         if (sharename == NULL || *sharename == '\0')
 614                 return (NERR_NetNameNotFound);
 615 
 616         if ((status = smb_shr_lookup(sharename, si)) == NERR_Success)
 617                 return (status);
 618 
 619         if ((status = smb_shr_sa_loadbyname(sharename)) == NERR_Success)
 620                 status = smb_shr_lookup(sharename, si);
 621 
 622         return (status);
 623 }
 624 
 625 /*
 626  * Modifies an existing share. Properties that can be modified are:
 627  *
 628  *   o comment
 629  *   o AD container
 630  *   o host access
 631  *   o abe
 632  */
 633 uint32_t
 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         }
 742 
 743         return (exists);
 744 }
 745 
 746 /*
 747  * If the shared directory does not begin with a /, one will be
 748  * inserted as a prefix. If ipaddr is not zero, then also return
 749  * information about access based on the host level access lists, if
 750  * present. Also return access check if there is an IP address and
 751  * shr_accflags.
 752  *
 753  * The value of smb_chk_hostaccess is checked for an access match.
 754  * -1 is wildcard match
 755  * 0 is no match
 756  * 1 is match
 757  *
 758  * Precedence is none is checked first followed by ro then rw if
 759  * needed.  If x is wildcard (< 0) then check to see if the other
 760  * values are a match. If a match, that wins.
 761  */
 762 uint32_t
 763 smb_shr_hostaccess(smb_inaddr_t *ipaddr, char *none_list, char *ro_list,
 764     char *rw_list, uint32_t flag)
 765 {
 766         uint32_t acc = SMB_SHRF_ACC_NONE;
 767         int none = 0;
 768         int ro = 0;
 769         int rw = 0;
 770 
 771         if (!smb_inet_iszero(ipaddr)) {
 772                 if ((flag & SMB_SHRF_ACC_NONE) != 0)
 773                         none = smb_chk_hostaccess(ipaddr, none_list);
 774                 if ((flag & SMB_SHRF_ACC_RO) != 0)
 775                         ro = smb_chk_hostaccess(ipaddr, ro_list);
 776                 if ((flag & SMB_SHRF_ACC_RW) != 0)
 777                         rw = smb_chk_hostaccess(ipaddr, rw_list);
 778 
 779                 /* make first pass to get basic value */
 780                 if (none != 0)
 781                         acc = SMB_SHRF_ACC_NONE;
 782                 else if (ro != 0)
 783                         acc = SMB_SHRF_ACC_RO;
 784                 else if (rw != 0)
 785                         acc = SMB_SHRF_ACC_RW;
 786 
 787                 /* make second pass to handle '*' case */
 788                 if (none < 0) {
 789                         acc = SMB_SHRF_ACC_NONE;
 790                         if (ro > 0)
 791                                 acc = SMB_SHRF_ACC_RO;
 792                         else if (rw > 0)
 793                                 acc = SMB_SHRF_ACC_RW;
 794                 } else if (ro < 0) {
 795                         acc = SMB_SHRF_ACC_RO;
 796                         if (none > 0)
 797                                 acc = SMB_SHRF_ACC_NONE;
 798                         else if (rw > 0)
 799                                 acc = SMB_SHRF_ACC_RW;
 800                 } else if (rw < 0) {
 801                         acc = SMB_SHRF_ACC_RW;
 802                         if (none > 0)
 803                                 acc = SMB_SHRF_ACC_NONE;
 804                         else if (ro > 0)
 805                                 acc = SMB_SHRF_ACC_RO;
 806                 }
 807         }
 808 
 809         return (acc);
 810 }
 811 
 812 /*
 813  * smb_shr_is_special
 814  *
 815  * Special share reserved for interprocess communication (IPC$) or
 816  * remote administration of the server (ADMIN$). Can also refer to
 817  * administrative shares such as C$, D$, E$, and so forth.
 818  */
 819 int
 820 smb_shr_is_special(char *sharename)
 821 {
 822         int len;
 823 
 824         if (sharename == NULL)
 825                 return (0);
 826 
 827         if ((len = strlen(sharename)) == 0)
 828                 return (0);
 829 
 830         if (sharename[len - 1] == '$')
 831                 return (STYPE_SPECIAL);
 832 
 833         return (0);
 834 }
 835 
 836 /*
 837  * smb_shr_is_restricted
 838  *
 839  * Check whether or not there is a restriction on a share. Restricted
 840  * shares are generally STYPE_SPECIAL, for example, IPC$. All the
 841  * administration share names are restricted: C$, D$ etc. Returns B_TRUE
 842  * if the share is restricted. Otherwise B_FALSE is returned to indicate
 843  * that there are no restrictions.
 844  */
 845 boolean_t
 846 smb_shr_is_restricted(char *sharename)
 847 {
 848         static char *restricted[] = {
 849                 "IPC$"
 850         };
 851 
 852         int i;
 853 
 854         if (sharename == NULL)
 855                 return (B_FALSE);
 856 
 857         for (i = 0; i < sizeof (restricted)/sizeof (restricted[0]); i++) {
 858                 if (smb_strcasecmp(restricted[i], sharename, 0) == 0)
 859                         return (B_TRUE);
 860         }
 861 
 862         return (smb_shr_is_admin(sharename));
 863 }
 864 
 865 /*
 866  * smb_shr_is_admin
 867  *
 868  * Check whether or not access to the share should be restricted to
 869  * administrators. This is a bit of a hack because what we're doing
 870  * is checking for the default admin shares: C$, D$ etc.. There are
 871  * other shares that have restrictions: see smb_shr_is_restricted().
 872  *
 873  * Returns B_TRUE if the shares is an admin share. Otherwise B_FALSE
 874  * is returned to indicate that there are no restrictions.
 875  */
 876 boolean_t
 877 smb_shr_is_admin(char *sharename)
 878 {
 879         if (sharename == NULL)
 880                 return (B_FALSE);
 881 
 882         if (strlen(sharename) == 2 &&
 883             smb_isalpha(sharename[0]) && sharename[1] == '$') {
 884                 return (B_TRUE);
 885         }
 886 
 887         return (B_FALSE);
 888 }
 889 
 890 char
 891 smb_shr_drive_letter(const char *path)
 892 {
 893         smb_transient_t *ts;
 894         int i;
 895 
 896         if (path == NULL)
 897                 return ('\0');
 898 
 899         for (i = 0; i < sizeof (tshare)/sizeof (tshare[0]); ++i) {
 900                 ts = &tshare[i];
 901 
 902                 if (ts->path == NULL)
 903                         continue;
 904 
 905                 if (strcasecmp(ts->path, path) == 0)
 906                         return (ts->drive);
 907         }
 908 
 909         return ('\0');
 910 }
 911 
 912 /*
 913  * Returns true if the specified directory is empty,
 914  * otherwise returns false.
 915  */
 916 static boolean_t
 917 smb_shr_is_empty(const char *path)
 918 {
 919         DIR *dirp;
 920         struct dirent *dp;
 921 
 922         if (path == NULL)
 923                 return (B_TRUE);
 924 
 925         if ((dirp = opendir(path)) == NULL)
 926                 return (B_TRUE);
 927 
 928         while ((dp = readdir(dirp)) != NULL) {
 929                 if (!smb_shr_is_dot_or_dotdot(dp->d_name))
 930                         return (B_FALSE);
 931         }
 932 
 933         (void) closedir(dirp);
 934         return (B_TRUE);
 935 }
 936 
 937 /*
 938  * Returns true if name is "." or "..", otherwise returns false.
 939  */
 940 static boolean_t
 941 smb_shr_is_dot_or_dotdot(const char *name)
 942 {
 943         if (*name != '.')
 944                 return (B_FALSE);
 945 
 946         if ((name[1] == '\0') || (name[1] == '.' && name[2] == '\0'))
 947                 return (B_TRUE);
 948 
 949         return (B_FALSE);
 950 }
 951 
 952 /*
 953  * smb_shr_get_realpath
 954  *
 955  * Derive the real path for a share from the path provided by a client.
 956  * For instance, the real path of C:\ may be /cvol or the real path of
 957  * F:\home may be /vol1/home.
 958  *
 959  * clntpath - path provided by the Windows client is in the
 960  *            format of <drive letter>:\<dir>
 961  * realpath - path that will be stored as the directory field of
 962  *            the smb_share_t structure of the share.
 963  * maxlen   - maximum length of the realpath buffer
 964  *
 965  * Return LAN Manager network error code.
 966  */
 967 uint32_t
 968 smb_shr_get_realpath(const char *clntpath, char *realpath, int maxlen)
 969 {
 970         const char *p;
 971         int len;
 972 
 973         if ((p = strchr(clntpath, ':')) != NULL)
 974                 ++p;
 975         else
 976                 p = clntpath;
 977 
 978         (void) strlcpy(realpath, p, maxlen);
 979         (void) strcanon(realpath, "/\\");
 980         (void) strsubst(realpath, '\\', '/');
 981 
 982         len = strlen(realpath);
 983         if ((len > 1) && (realpath[len - 1] == '/'))
 984                 realpath[len - 1] = '\0';
 985 
 986         return (NERR_Success);
 987 }
 988 
 989 void
 990 smb_shr_list(int offset, smb_shrlist_t *list)
 991 {
 992         smb_shriter_t iterator;
 993         smb_share_t *si;
 994         int n = 0;
 995 
 996         bzero(list, sizeof (smb_shrlist_t));
 997         smb_shr_iterinit(&iterator);
 998 
 999         while ((si = smb_shr_iterate(&iterator)) != NULL) {
1000                 if (--offset > 0)
1001                         continue;
1002 
1003                 if ((si->shr_flags & SMB_SHRF_TRANS) &&
1004                     (!STYPE_ISIPC(si->shr_type))) {
1005                         bcopy(si, &list->sl_shares[n], sizeof (smb_share_t));
1006                         if (++n == LMSHARES_PER_REQUEST)
1007                                 break;
1008                 }
1009         }
1010 
1011         list->sl_cnt = n;
1012 }
1013 
1014 /*
1015  * Executes the map/unmap command associated with a share.
1016  *
1017  * Returns 0 on success.  Otherwise non-zero for errors.
1018  */
1019 int
1020 smb_shr_exec(smb_shr_execinfo_t *subs)
1021 {
1022         char cmd[MAXPATHLEN], **cmd_tokens, *path, *ptr;
1023         pid_t child_pid;
1024         int child_status;
1025         struct sigaction pact, cact;
1026         smb_share_t si;
1027 
1028         if (smb_shr_get(subs->e_sharename, &si) != 0)
1029                 return (-1);
1030 
1031         *cmd = '\0';
1032 
1033         (void) mutex_lock(&smb_shr_exec_mtx);
1034 
1035         switch (subs->e_type) {
1036         case SMB_EXEC_MAP:
1037                 (void) strlcpy(cmd, smb_shr_exec_map, sizeof (cmd));
1038                 break;
1039         case SMB_EXEC_UNMAP:
1040                 (void) strlcpy(cmd, smb_shr_exec_unmap, sizeof (cmd));
1041                 break;
1042         default:
1043                 (void) mutex_unlock(&smb_shr_exec_mtx);
1044                 return (-1);
1045         }
1046 
1047         (void) mutex_unlock(&smb_shr_exec_mtx);
1048 
1049         if (*cmd == '\0')
1050                 return (0);
1051 
1052         if (smb_proc_takesem() != 0)
1053                 return (-1);
1054 
1055         pact.sa_handler = smb_shr_sig_child;
1056         pact.sa_flags = 0;
1057         (void) sigemptyset(&pact.sa_mask);
1058         sigaction(SIGCHLD, &pact, NULL);
1059 
1060         (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
1061 
1062         if ((child_pid = fork()) == -1) {
1063                 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
1064                 smb_proc_givesem();
1065                 return (-1);
1066         }
1067 
1068         if (child_pid == 0) {
1069 
1070                 /* child process */
1071 
1072                 cact.sa_handler = smb_shr_sig_abnormal_term;
1073                 cact.sa_flags = 0;
1074                 (void) sigemptyset(&cact.sa_mask);
1075                 sigaction(SIGTERM, &cact, NULL);
1076                 sigaction(SIGABRT, &cact, NULL);
1077                 sigaction(SIGSEGV, &cact, NULL);
1078 
1079                 if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_EXEC,
1080                     PRIV_FILE_DAC_EXECUTE, NULL))
1081                         _exit(-1);
1082 
1083                 if (smb_shr_enable_all_privs())
1084                         _exit(-1);
1085 
1086                 smb_proc_initsem();
1087 
1088                 (void) trim_whitespace(cmd);
1089                 (void) strcanon(cmd, " ");
1090 
1091                 if ((cmd_tokens = smb_shr_tokenize_cmd(cmd)) != NULL) {
1092 
1093                         if (smb_shr_expand_subs(cmd_tokens, &si, subs) != 0) {
1094                                 free(cmd_tokens[0]);
1095                                 free(cmd_tokens);
1096                                 _exit(-1);
1097                         }
1098 
1099                         ptr = cmd;
1100                         path = strsep(&ptr, " ");
1101 
1102                         (void) execv(path, cmd_tokens);
1103                 }
1104 
1105                 _exit(-1);
1106         }
1107 
1108         (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
1109         smb_proc_givesem();
1110 
1111         /* parent process */
1112 
1113         while (waitpid(child_pid, &child_status, 0) < 0) {
1114                 if (errno != EINTR)
1115                         break;
1116 
1117                 /* continue if waitpid got interrupted by a signal */
1118                 errno = 0;
1119                 continue;
1120         }
1121 
1122         if (WIFEXITED(child_status))
1123                 return (WEXITSTATUS(child_status));
1124 
1125         return (child_status);
1126 }
1127 
1128 /*
1129  * Locking for process-wide settings (i.e. privileges)
1130  */
1131 void
1132 smb_proc_initsem(void)
1133 {
1134         (void) sema_init(&smb_proc_sem, 1, USYNC_THREAD, NULL);
1135 }
1136 
1137 int
1138 smb_proc_takesem(void)
1139 {
1140         return (sema_wait(&smb_proc_sem));
1141 }
1142 
1143 void
1144 smb_proc_givesem(void)
1145 {
1146         (void) sema_post(&smb_proc_sem);
1147 }
1148 
1149 /*
1150  * ============================================
1151  * Private helper/utility functions
1152  * ============================================
1153  */
1154 
1155 /*
1156  * Looks up the given share in the cache and return
1157  * the info in 'si'
1158  */
1159 static uint32_t
1160 smb_shr_lookup(char *sharename, smb_share_t *si)
1161 {
1162         smb_share_t *cached_si;
1163         uint32_t status = NERR_NetNameNotFound;
1164 
1165         if (sharename == NULL || *sharename == '\0')
1166                 return (NERR_NetNameNotFound);
1167         if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
1168                 cached_si = smb_shr_cache_findent(sharename);
1169                 if (cached_si != NULL) {
1170                         bcopy(cached_si, si, sizeof (smb_share_t));
1171                         status = NERR_Success;
1172                 }
1173 
1174                 smb_shr_cache_unlock();
1175         }
1176         return (status);
1177 }
1178 
1179 /*
1180  * Add IPC$ or Admin shares to the cache upon startup.
1181  */
1182 static uint32_t
1183 smb_shr_add_transient(char *name, char *cmnt, char *path)
1184 {
1185         smb_share_t trans;
1186         uint32_t status = NERR_InternalError;
1187 
1188         if (name == NULL)
1189                 return (status);
1190 
1191         bzero(&trans, sizeof (smb_share_t));
1192         (void) strlcpy(trans.shr_name, name, MAXNAMELEN);
1193         if (cmnt)
1194                 (void) strlcpy(trans.shr_cmnt, cmnt, SMB_SHARE_CMNT_MAX);
1195 
1196         if (path)
1197                 (void) strlcpy(trans.shr_path, path, MAXPATHLEN);
1198 
1199         if (strcasecmp(name, "IPC$") == 0)
1200                 trans.shr_type = STYPE_IPC;
1201 
1202         trans.shr_flags = SMB_SHRF_TRANS;
1203 
1204         if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) {
1205                 status = smb_shr_cache_addent(&trans);
1206                 smb_shr_cache_unlock();
1207         }
1208 
1209         return (status);
1210 }
1211 
1212 /*
1213  * ============================================
1214  * Cache management functions
1215  *
1216  * All cache functions are private
1217  * ============================================
1218  */
1219 
1220 /*
1221  * Create the share cache (hash table).
1222  */
1223 static uint32_t
1224 smb_shr_cache_create(void)
1225 {
1226         uint32_t status = NERR_Success;
1227 
1228         (void) mutex_lock(&smb_shr_cache.sc_mtx);
1229         switch (smb_shr_cache.sc_state) {
1230         case SMB_SHR_CACHE_STATE_NONE:
1231                 smb_shr_cache.sc_cache = ht_create_table(SMB_SHR_HTAB_SZ,
1232                     MAXNAMELEN, 0);
1233                 if (smb_shr_cache.sc_cache == NULL) {
1234                         status = NERR_InternalError;
1235                         break;
1236                 }
1237 
1238                 (void) ht_register_callback(smb_shr_cache.sc_cache,
1239                     smb_shr_cache_freent);
1240                 smb_shr_cache.sc_nops = 0;
1241                 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_CREATED;
1242                 break;
1243 
1244         default:
1245                 assert(0);
1246                 status = NERR_InternalError;
1247                 break;
1248         }
1249         (void) mutex_unlock(&smb_shr_cache.sc_mtx);
1250 
1251         return (status);
1252 }
1253 
1254 /*
1255  * Destroy the share cache (hash table).
1256  * Wait for inflight/pending operations to finish or abort before
1257  * destroying the cache.
1258  */
1259 static void
1260 smb_shr_cache_destroy(void)
1261 {
1262         (void) mutex_lock(&smb_shr_cache.sc_mtx);
1263         if (smb_shr_cache.sc_state == SMB_SHR_CACHE_STATE_CREATED) {
1264                 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_DESTROYING;
1265                 while (smb_shr_cache.sc_nops > 0)
1266                         (void) cond_wait(&smb_shr_cache.sc_cv,
1267                             &smb_shr_cache.sc_mtx);
1268 
1269                 smb_shr_cache.sc_cache = NULL;
1270                 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_NONE;
1271         }
1272         (void) mutex_unlock(&smb_shr_cache.sc_mtx);
1273 }
1274 
1275 /*
1276  * If the cache is in "created" state, lock the cache for read
1277  * or read/write based on the specified mode.
1278  *
1279  * Whenever a lock is granted, the number of inflight cache
1280  * operations is incremented.
1281  */
1282 static uint32_t
1283 smb_shr_cache_lock(int mode)
1284 {
1285         (void) mutex_lock(&smb_shr_cache.sc_mtx);
1286         if (smb_shr_cache.sc_state != SMB_SHR_CACHE_STATE_CREATED) {
1287                 (void) mutex_unlock(&smb_shr_cache.sc_mtx);
1288                 return (NERR_InternalError);
1289         }
1290         smb_shr_cache.sc_nops++;
1291         (void) mutex_unlock(&smb_shr_cache.sc_mtx);
1292 
1293         /*
1294          * Lock has to be taken outside the mutex otherwise
1295          * there could be a deadlock
1296          */
1297         if (mode == SMB_SHR_CACHE_RDLOCK)
1298                 (void) rw_rdlock(&smb_shr_cache.sc_cache_lck);
1299         else
1300                 (void) rw_wrlock(&smb_shr_cache.sc_cache_lck);
1301 
1302         return (NERR_Success);
1303 }
1304 
1305 /*
1306  * Decrement the number of inflight operations and then unlock.
1307  */
1308 static void
1309 smb_shr_cache_unlock(void)
1310 {
1311         (void) mutex_lock(&smb_shr_cache.sc_mtx);
1312         assert(smb_shr_cache.sc_nops > 0);
1313         smb_shr_cache.sc_nops--;
1314         (void) cond_broadcast(&smb_shr_cache.sc_cv);
1315         (void) mutex_unlock(&smb_shr_cache.sc_mtx);
1316 
1317         (void) rw_unlock(&smb_shr_cache.sc_cache_lck);
1318 }
1319 
1320 /*
1321  * Return the total number of shares
1322  */
1323 static int
1324 smb_shr_cache_count(void)
1325 {
1326         return (ht_get_total_items(smb_shr_cache.sc_cache));
1327 }
1328 
1329 /*
1330  * looks up the given share name in the cache and if it
1331  * finds a match returns a pointer to the cached entry.
1332  * Note that since a pointer is returned this function
1333  * MUST be protected by smb_shr_cache_lock/unlock pair
1334  */
1335 static smb_share_t *
1336 smb_shr_cache_findent(char *sharename)
1337 {
1338         HT_ITEM *item;
1339 
1340         (void) smb_strlwr(sharename);
1341         item = ht_find_item(smb_shr_cache.sc_cache, sharename);
1342         if (item && item->hi_data)
1343                 return ((smb_share_t *)item->hi_data);
1344 
1345         return (NULL);
1346 }
1347 
1348 /*
1349  * Return a pointer to the first/next entry in
1350  * the cache based on the given iterator.
1351  *
1352  * Calls to this function MUST be protected by
1353  * smb_shr_cache_lock/unlock.
1354  */
1355 static smb_share_t *
1356 smb_shr_cache_iterate(smb_shriter_t *shi)
1357 {
1358         HT_ITEM *item;
1359 
1360         if (shi->si_first) {
1361                 item = ht_findfirst(smb_shr_cache.sc_cache, &shi->si_hashiter);
1362                 shi->si_first = B_FALSE;
1363         } else {
1364                 item = ht_findnext(&shi->si_hashiter);
1365         }
1366 
1367         if (item && item->hi_data)
1368                 return ((smb_share_t *)item->hi_data);
1369 
1370         return (NULL);
1371 }
1372 
1373 /*
1374  * Add the specified share to the cache.  Memory needs to be allocated
1375  * for the cache entry and the passed information is copied to the
1376  * allocated space.
1377  */
1378 static uint32_t
1379 smb_shr_cache_addent(smb_share_t *si)
1380 {
1381         smb_share_t *cache_ent;
1382         uint32_t status = NERR_Success;
1383 
1384         if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL)
1385                 return (ERROR_NOT_ENOUGH_MEMORY);
1386 
1387         (void) smb_strlwr(si->shr_name);
1388 
1389         si->shr_type |= smb_shr_is_special(cache_ent->shr_name);
1390 
1391         if (smb_shr_is_admin(cache_ent->shr_name))
1392                 si->shr_flags |= SMB_SHRF_ADMIN;
1393 
1394         bcopy(si, cache_ent, sizeof (smb_share_t));
1395 
1396         if (si->shr_flags & SMB_SHRF_AUTOHOME)
1397                 cache_ent->shr_refcnt = 1;
1398 
1399         if (ht_add_item(smb_shr_cache.sc_cache, cache_ent->shr_name, cache_ent)
1400             == NULL) {
1401                 syslog(LOG_DEBUG, "share: %s: cache update failed",
1402                     cache_ent->shr_name);
1403                 free(cache_ent);
1404                 status = NERR_InternalError;
1405         }
1406 
1407         return (status);
1408 }
1409 
1410 /*
1411  * Delete the specified share from the cache.
1412  */
1413 static void
1414 smb_shr_cache_delent(char *sharename)
1415 {
1416         (void) smb_strlwr(sharename);
1417         (void) ht_remove_item(smb_shr_cache.sc_cache, sharename);
1418 }
1419 
1420 /*
1421  * Call back to free the given cache entry.
1422  */
1423 static void
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 
1505         for (share = sa_get_share(group, NULL);
1506             share != NULL;
1507             share = sa_get_next_share(share)) {
1508                 for (resource = sa_get_share_resource(share, NULL);
1509                     resource != NULL;
1510                     resource = sa_get_next_resource(resource)) {
1511                         if (smb_shr_sa_load(share, resource))
1512                                 ++error_count;
1513 
1514                         if (error_count > SMB_SHR_ERROR_THRESHOLD)
1515                                 break;
1516                 }
1517 
1518                 if (error_count > SMB_SHR_ERROR_THRESHOLD)
1519                         break;
1520         }
1521 }
1522 
1523 /*
1524  * Load a share definition from sharemgr and add it to the cache.
1525  * If the share is already in the cache then it doesn't do anything.
1526  *
1527  * This function does not report duplicate shares as error since
1528  * a share might have been added by smb_shr_get() while load is
1529  * in progress.
1530  */
1531 static uint32_t
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  *
1581  * Shares read from sharemgr are marked as permanent/persistent.
1582  */
1583 static uint32_t
1584 smb_shr_sa_get(sa_share_t share, sa_resource_t resource, smb_share_t *si)
1585 {
1586         sa_optionset_t opts;
1587         char *val = NULL;
1588         char *path;
1589         char *rname;
1590 
1591         if ((path = sa_get_share_attr(share, "path")) == NULL)
1592                 return (NERR_InternalError);
1593 
1594         if ((rname = sa_get_resource_attr(resource, "name")) == NULL) {
1595                 sa_free_attr_string(path);
1596                 return (NERR_InternalError);
1597         }
1598 
1599         bzero(si, sizeof (smb_share_t));
1600         si->shr_flags = SMB_SHRF_PERM;
1601 
1602         (void) strlcpy(si->shr_path, path, sizeof (si->shr_path));
1603         (void) strlcpy(si->shr_name, rname, sizeof (si->shr_name));
1604         sa_free_attr_string(path);
1605         sa_free_attr_string(rname);
1606 
1607         val = sa_get_resource_description(resource);
1608         if (val == NULL)
1609                 val = sa_get_share_description(share);
1610 
1611         if (val != NULL) {
1612                 (void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt));
1613                 sa_free_share_description(val);
1614         }
1615 
1616         opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1);
1617         if (opts == NULL)
1618                 return (NERR_Success);
1619 
1620         val = smb_shr_sa_getprop(opts, SHOPT_AD_CONTAINER);
1621         if (val != NULL) {
1622                 (void) strlcpy(si->shr_container, val,
1623                     sizeof (si->shr_container));
1624                 free(val);
1625         }
1626 
1627         val = smb_shr_sa_getprop(opts, SHOPT_CATIA);
1628         if (val != NULL) {
1629                 smb_shr_sa_setflag(val, si, SMB_SHRF_CATIA);
1630                 free(val);
1631         }
1632 
1633         val = smb_shr_sa_getprop(opts, SHOPT_ABE);
1634         if (val != NULL) {
1635                 smb_shr_sa_setflag(val, si, SMB_SHRF_ABE);
1636                 free(val);
1637         }
1638 
1639         val = smb_shr_sa_getprop(opts, SHOPT_GUEST);
1640         if (val != NULL) {
1641                 smb_shr_sa_setflag(val, si, SMB_SHRF_GUEST_OK);
1642                 free(val);
1643         }
1644 
1645         val = smb_shr_sa_getprop(opts, SHOPT_DFSROOT);
1646         if (val != NULL) {
1647                 smb_shr_sa_setflag(val, si, SMB_SHRF_DFSROOT);
1648                 free(val);
1649         }
1650 
1651         val = smb_shr_sa_getprop(opts, SHOPT_CSC);
1652         if (val != NULL) {
1653                 smb_shr_sa_csc_option(val, si);
1654                 free(val);
1655         }
1656 
1657         val = smb_shr_sa_getprop(opts, SHOPT_NONE);
1658         if (val != NULL) {
1659                 (void) strlcpy(si->shr_access_none, val,
1660                     sizeof (si->shr_access_none));
1661                 free(val);
1662                 si->shr_flags |= SMB_SHRF_ACC_NONE;
1663         }
1664 
1665         val = smb_shr_sa_getprop(opts, SHOPT_RO);
1666         if (val != NULL) {
1667                 (void) strlcpy(si->shr_access_ro, val,
1668                     sizeof (si->shr_access_ro));
1669                 free(val);
1670                 si->shr_flags |= SMB_SHRF_ACC_RO;
1671         }
1672 
1673         val = smb_shr_sa_getprop(opts, SHOPT_RW);
1674         if (val != NULL) {
1675                 (void) strlcpy(si->shr_access_rw, val,
1676                     sizeof (si->shr_access_rw));
1677                 free(val);
1678                 si->shr_flags |= SMB_SHRF_ACC_RW;
1679         }
1680 
1681         sa_free_derived_optionset(opts);
1682         return (NERR_Success);
1683 }
1684 
1685 /*
1686  * Map a client-side caching (CSC) option to the appropriate share
1687  * flag.  Only one option is allowed; an error will be logged if
1688  * multiple options have been specified.  We don't need to do anything
1689  * about multiple values here because the SRVSVC will not recognize
1690  * a value containing multiple flags and will return the default value.
1691  *
1692  * If the option value is not recognized, it will be ignored: invalid
1693  * values will typically be caught and rejected by sharemgr.
1694  */
1695 void
1696 smb_shr_sa_csc_option(const char *value, smb_share_t *si)
1697 {
1698         int i;
1699 
1700         for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) {
1701                 if (strcasecmp(value, cscopt[i].value) == 0) {
1702                         si->shr_flags |= cscopt[i].flag;
1703                         break;
1704                 }
1705         }
1706 
1707         switch (si->shr_flags & SMB_SHRF_CSC_MASK) {
1708         case 0:
1709         case SMB_SHRF_CSC_DISABLED:
1710         case SMB_SHRF_CSC_MANUAL:
1711         case SMB_SHRF_CSC_AUTO:
1712         case SMB_SHRF_CSC_VDO:
1713                 break;
1714 
1715         default:
1716                 syslog(LOG_INFO, "csc option conflict: 0x%08x",
1717                     si->shr_flags & SMB_SHRF_CSC_MASK);
1718                 break;
1719         }
1720 }
1721 
1722 /*
1723  * Return the option name for the first CSC flag (there should be only
1724  * one) encountered in the share flags.
1725  */
1726 char *
1727 smb_shr_sa_csc_name(const smb_share_t *si)
1728 {
1729         int i;
1730 
1731         for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) {
1732                 if (si->shr_flags & cscopt[i].flag)
1733                         return (cscopt[i].value);
1734         }
1735 
1736         return (NULL);
1737 }
1738 
1739 /*
1740  * Takes the value of a boolean share property and set/clear the
1741  * specified flag based on the property's value.
1742  */
1743 void
1744 smb_shr_sa_setflag(const char *value, smb_share_t *si, uint32_t flag)
1745 {
1746         if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0))
1747                 si->shr_flags |= flag;
1748         else
1749                 si->shr_flags &= ~flag;
1750 }
1751 
1752 /*
1753  * looks up sharemgr for the given share (resource) and loads
1754  * the definition into cache if lookup is successful
1755  */
1756 static uint32_t
1757 smb_shr_sa_loadbyname(char *sharename)
1758 {
1759         sa_handle_t handle;
1760         sa_share_t share;
1761         sa_resource_t resource;
1762         uint32_t status;
1763 
1764         if ((handle = smb_shr_sa_enter()) == NULL)
1765                 return (NERR_InternalError);
1766 
1767         resource = sa_find_resource(handle, sharename);
1768         if (resource == NULL) {
1769                 smb_shr_sa_exit();
1770                 return (NERR_NetNameNotFound);
1771         }
1772 
1773         share = sa_get_resource_parent(resource);
1774         if (share == NULL) {
1775                 smb_shr_sa_exit();
1776                 return (NERR_InternalError);
1777         }
1778 
1779         status = smb_shr_sa_load(share, resource);
1780 
1781         smb_shr_sa_exit();
1782         return (status);
1783 }
1784 
1785 /*
1786  * ============================================
1787  * Share publishing functions
1788  *
1789  * All the functions are private
1790  * ============================================
1791  */
1792 
1793 static void
1794 smb_shr_publish(const char *sharename, const char *container)
1795 {
1796         smb_shr_publisher_queue(sharename, container, SMB_SHR_PUBLISH);
1797 }
1798 
1799 static void
1800 smb_shr_unpublish(const char *sharename, const char *container)
1801 {
1802         smb_shr_publisher_queue(sharename, container, SMB_SHR_UNPUBLISH);
1803 }
1804 
1805 /*
1806  * In domain mode, put a share on the publisher queue.
1807  * This is a no-op if the smb service is in Workgroup mode.
1808  */
1809 static void
1810 smb_shr_publisher_queue(const char *sharename, const char *container, char op)
1811 {
1812         smb_shr_pitem_t *item = NULL;
1813 
1814         if (container == NULL || *container == '\0')
1815                 return;
1816 
1817         if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
1818                 return;
1819 
1820         (void) mutex_lock(&ad_queue.spq_mtx);
1821         switch (ad_queue.spq_state) {
1822         case SMB_SHR_PQS_READY:
1823         case SMB_SHR_PQS_PUBLISHING:
1824                 break;
1825         default:
1826                 (void) mutex_unlock(&ad_queue.spq_mtx);
1827                 return;
1828         }
1829         (void) mutex_unlock(&ad_queue.spq_mtx);
1830 
1831         if ((item = malloc(sizeof (smb_shr_pitem_t))) == NULL)
1832                 return;
1833 
1834         item->spi_op = op;
1835         (void) strlcpy(item->spi_name, sharename, sizeof (item->spi_name));
1836         (void) strlcpy(item->spi_container, container,
1837             sizeof (item->spi_container));
1838 
1839         (void) mutex_lock(&ad_queue.spq_mtx);
1840         list_insert_tail(&ad_queue.spq_list, item);
1841         (void) cond_signal(&ad_queue.spq_cv);
1842         (void) mutex_unlock(&ad_queue.spq_mtx);
1843 }
1844 
1845 /*
1846  * Publishing won't be activated if the smb service is running in
1847  * Workgroup mode.
1848  */
1849 static int
1850 smb_shr_publisher_start(void)
1851 {
1852         pthread_t publish_thr;
1853         pthread_attr_t tattr;
1854         int rc;
1855 
1856         if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
1857                 return (0);
1858 
1859         (void) mutex_lock(&ad_queue.spq_mtx);
1860         if (ad_queue.spq_state != SMB_SHR_PQS_NOQUEUE) {
1861                 (void) mutex_unlock(&ad_queue.spq_mtx);
1862                 errno = EINVAL;
1863                 return (-1);
1864         }
1865 
1866         list_create(&ad_queue.spq_list, sizeof (smb_shr_pitem_t),
1867             offsetof(smb_shr_pitem_t, spi_lnd));
1868         ad_queue.spq_state = SMB_SHR_PQS_READY;
1869         (void) mutex_unlock(&ad_queue.spq_mtx);
1870 
1871         (void) pthread_attr_init(&tattr);
1872         (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
1873         rc = pthread_create(&publish_thr, &tattr, smb_shr_publisher, 0);
1874         (void) pthread_attr_destroy(&tattr);
1875 
1876         return (rc);
1877 }
1878 
1879 static void
1880 smb_shr_publisher_stop(void)
1881 {
1882         if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
1883                 return;
1884 
1885         (void) mutex_lock(&ad_queue.spq_mtx);
1886         switch (ad_queue.spq_state) {
1887         case SMB_SHR_PQS_READY:
1888         case SMB_SHR_PQS_PUBLISHING:
1889                 ad_queue.spq_state = SMB_SHR_PQS_STOPPING;
1890                 (void) cond_signal(&ad_queue.spq_cv);
1891                 break;
1892         default:
1893                 break;
1894         }
1895         (void) mutex_unlock(&ad_queue.spq_mtx);
1896 }
1897 
1898 /*
1899  * This is the publisher daemon thread.  While running, the thread waits
1900  * on a conditional variable until notified that a share needs to be
1901  * [un]published or that the thread should be terminated.
1902  *
1903  * Entries may remain in the outgoing queue if the Active Directory
1904  * service is inaccessible, in which case the thread wakes up every 60
1905  * seconds to retry.
1906  */
1907 /*ARGSUSED*/
1908 static void *
1909 smb_shr_publisher(void *arg)
1910 {
1911         smb_ads_handle_t *ah;
1912         smb_shr_pitem_t *shr;
1913         list_t publist;
1914         timestruc_t pubretry;
1915         char hostname[MAXHOSTNAMELEN];
1916 
1917         (void) mutex_lock(&ad_queue.spq_mtx);
1918         if (ad_queue.spq_state != SMB_SHR_PQS_READY) {
1919                 (void) mutex_unlock(&ad_queue.spq_mtx);
1920                 return (NULL);
1921         }
1922         ad_queue.spq_state = SMB_SHR_PQS_PUBLISHING;
1923         (void) mutex_unlock(&ad_queue.spq_mtx);
1924 
1925         (void) smb_gethostname(hostname, MAXHOSTNAMELEN,
1926             SMB_CASE_PRESERVE);
1927 
1928         list_create(&publist, sizeof (smb_shr_pitem_t),
1929             offsetof(smb_shr_pitem_t, spi_lnd));
1930 
1931         for (;;) {
1932                 (void) mutex_lock(&ad_queue.spq_mtx);
1933 
1934                 while (list_is_empty(&ad_queue.spq_list) &&
1935                     (ad_queue.spq_state == SMB_SHR_PQS_PUBLISHING)) {
1936                         if (list_is_empty(&publist)) {
1937                                 (void) cond_wait(&ad_queue.spq_cv,
1938                                     &ad_queue.spq_mtx);
1939                         } else {
1940                                 pubretry.tv_sec = 60;
1941                                 pubretry.tv_nsec = 0;
1942                                 (void) cond_reltimedwait(&ad_queue.spq_cv,
1943                                     &ad_queue.spq_mtx, &pubretry);
1944                                 break;
1945                         }
1946                 }
1947 
1948                 if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) {
1949                         (void) mutex_unlock(&ad_queue.spq_mtx);
1950                         break;
1951                 }
1952 
1953                 /*
1954                  * Transfer queued items to the local list so that
1955                  * the mutex can be released.
1956                  */
1957                 while ((shr = list_head(&ad_queue.spq_list)) != NULL) {
1958                         list_remove(&ad_queue.spq_list, shr);
1959                         list_insert_tail(&publist, shr);
1960                 }
1961 
1962                 (void) mutex_unlock(&ad_queue.spq_mtx);
1963 
1964                 if ((ah = smb_ads_open()) != NULL) {
1965                         smb_shr_publisher_send(ah, &publist, hostname);
1966                         smb_ads_close(ah);
1967                 }
1968         }
1969 
1970         (void) mutex_lock(&ad_queue.spq_mtx);
1971         smb_shr_publisher_flush(&ad_queue.spq_list);
1972         list_destroy(&ad_queue.spq_list);
1973         ad_queue.spq_state = SMB_SHR_PQS_NOQUEUE;
1974         (void) mutex_unlock(&ad_queue.spq_mtx);
1975 
1976         smb_shr_publisher_flush(&publist);
1977         list_destroy(&publist);
1978         return (NULL);
1979 }
1980 
1981 /*
1982  * Remove items from the specified queue and [un]publish them.
1983  */
1984 static void
1985 smb_shr_publisher_send(smb_ads_handle_t *ah, list_t *publist, const char *host)
1986 {
1987         smb_shr_pitem_t *shr;
1988 
1989         while ((shr = list_head(publist)) != NULL) {
1990                 (void) mutex_lock(&ad_queue.spq_mtx);
1991                 if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) {
1992                         (void) mutex_unlock(&ad_queue.spq_mtx);
1993                         return;
1994                 }
1995                 (void) mutex_unlock(&ad_queue.spq_mtx);
1996 
1997                 list_remove(publist, shr);
1998 
1999                 if (shr->spi_op == SMB_SHR_PUBLISH)
2000                         (void) smb_ads_publish_share(ah, shr->spi_name,
2001                             NULL, shr->spi_container, host);
2002                 else
2003                         (void) smb_ads_remove_share(ah, shr->spi_name,
2004                             NULL, shr->spi_container, host);
2005 
2006                 free(shr);
2007         }
2008 }
2009 
2010 /*
2011  * Flush all remaining items from the specified list/queue.
2012  */
2013 static void
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  */
2140 static int
2141 smb_shr_enable_all_privs(void)
2142 {
2143         priv_set_t *pset;
2144 
2145         pset = priv_allocset();
2146         if (pset == NULL)
2147                 return (-1);
2148 
2149         if (getppriv(PRIV_LIMIT, pset)) {
2150                 priv_freeset(pset);
2151                 return (-1);
2152         }
2153 
2154         if (setppriv(PRIV_ON, PRIV_INHERITABLE, pset)) {
2155                 priv_freeset(pset);
2156                 return (-1);
2157         }
2158 
2159         priv_freeset(pset);
2160         return (0);
2161 }
2162 
2163 /*
2164  * Tokenizes the command string and returns the list of tokens in an array.
2165  *
2166  * Returns NULL if there are no tokens.
2167  */
2168 static char **
2169 smb_shr_tokenize_cmd(char *cmdstr)
2170 {
2171         char *cmd, *buf, *bp, *value;
2172         char **argv, **ap;
2173         int argc, i;
2174 
2175         if (cmdstr == NULL || *cmdstr == '\0')
2176                 return (NULL);
2177 
2178         if ((buf = malloc(MAXPATHLEN)) == NULL)
2179                 return (NULL);
2180 
2181         (void) strlcpy(buf, cmdstr, MAXPATHLEN);
2182 
2183         for (argc = 2, bp = cmdstr; *bp != '\0'; ++bp)
2184                 if (*bp == ' ')
2185                         ++argc;
2186 
2187         if ((argv = calloc(argc, sizeof (char *))) == NULL) {
2188                 free(buf);
2189                 return (NULL);
2190         }
2191 
2192         ap = argv;
2193         for (bp = buf, i = 0; i < argc; ++i) {
2194                 do {
2195                         if ((value = strsep(&bp, " ")) == NULL)
2196                                 break;
2197                 } while (*value == '\0');
2198 
2199                 if (value == NULL)
2200                         break;
2201 
2202                 *ap++ = value;
2203         }
2204 
2205         /* get the filename of the command from the path */
2206         if ((cmd = strrchr(argv[0], '/')) != NULL)
2207                 (void) strlcpy(argv[0], ++cmd, strlen(argv[0]));
2208 
2209         return (argv);
2210 }
2211 
2212 /*
2213  * Expands the command string for the following substitution tokens:
2214  *
2215  * %U - Windows username
2216  * %D - Name of the domain or workgroup of %U
2217  * %h - The server hostname
2218  * %M - The client hostname
2219  * %L - The server NetBIOS name
2220  * %m - The client NetBIOS name. This option is only valid for NetBIOS
2221  *      connections (port 139).
2222  * %I - The IP address of the client machine
2223  * %i - The local IP address to which the client is connected
2224  * %S - The name of the share
2225  * %P - The root directory of the share
2226  * %u - The UID of the Unix user
2227  *
2228  * Returns 0 on success.  Otherwise -1.
2229  */
2230 static int
2231 smb_shr_expand_subs(char **cmd_toks, smb_share_t *si, smb_shr_execinfo_t *subs)
2232 {
2233         char *fmt, *sub_chr, *ptr;
2234         boolean_t unknown;
2235         char hostname[MAXHOSTNAMELEN];
2236         char ip_str[INET6_ADDRSTRLEN];
2237         char name[SMB_PI_MAX_HOST];
2238         smb_wchar_t wbuf[SMB_PI_MAX_HOST];
2239         int i;
2240 
2241         if (cmd_toks == NULL || *cmd_toks == NULL)
2242                 return (-1);
2243 
2244         for (i = 1; cmd_toks[i]; i++) {
2245                 fmt = cmd_toks[i];
2246                 if (*fmt == '%') {
2247                         sub_chr = fmt + 1;
2248                         unknown = B_FALSE;
2249 
2250                         switch (*sub_chr) {
2251                         case 'U':
2252                                 ptr = strdup(subs->e_winname);
2253                                 break;
2254                         case 'D':
2255                                 ptr = strdup(subs->e_userdom);
2256                                 break;
2257                         case 'h':
2258                                 if (gethostname(hostname, MAXHOSTNAMELEN) != 0)
2259                                         unknown = B_TRUE;
2260                                 else
2261                                         ptr = strdup(hostname);
2262                                 break;
2263                         case 'M':
2264                                 if (smb_getnameinfo(&subs->e_cli_ipaddr,
2265                                     hostname, sizeof (hostname), 0) != 0)
2266                                         unknown = B_TRUE;
2267                                 else
2268                                         ptr = strdup(hostname);
2269                                 break;
2270                         case 'L':
2271                                 if (smb_getnetbiosname(hostname,
2272                                     NETBIOS_NAME_SZ) != 0)
2273                                         unknown = B_TRUE;
2274                                 else
2275                                         ptr = strdup(hostname);
2276                                 break;
2277                         case 'm':
2278                                 if (*subs->e_cli_netbiosname == '\0')
2279                                         unknown = B_TRUE;
2280                                 else {
2281                                         (void) smb_mbstowcs(wbuf,
2282                                             subs->e_cli_netbiosname,
2283                                             SMB_PI_MAX_HOST - 1);
2284 
2285                                         if (ucstooem(name, wbuf,
2286                                             SMB_PI_MAX_HOST, OEM_CPG_850) == 0)
2287                                                 (void) strlcpy(name,
2288                                                     subs->e_cli_netbiosname,
2289                                                     SMB_PI_MAX_HOST);
2290 
2291                                         ptr = strdup(name);
2292                                 }
2293                                 break;
2294                         case 'I':
2295                                 if (smb_inet_ntop(&subs->e_cli_ipaddr, ip_str,
2296                                     SMB_IPSTRLEN(subs->e_cli_ipaddr.a_family))
2297                                     != NULL)
2298                                         ptr = strdup(ip_str);
2299                                 else
2300                                         unknown = B_TRUE;
2301                                 break;
2302                         case 'i':
2303                                 if (smb_inet_ntop(&subs->e_srv_ipaddr, ip_str,
2304                                     SMB_IPSTRLEN(subs->e_srv_ipaddr.a_family))
2305                                     != NULL)
2306                                         ptr = strdup(ip_str);
2307                                 else
2308                                         unknown = B_TRUE;
2309                                 break;
2310                         case 'S':
2311                                 ptr = strdup(si->shr_name);
2312                                 break;
2313                         case 'P':
2314                                 ptr = strdup(si->shr_path);
2315                                 break;
2316                         case 'u':
2317                                 (void) snprintf(name, sizeof (name), "%u",
2318                                     subs->e_uid);
2319                                 ptr = strdup(name);
2320                                 break;
2321                         default:
2322                                 /* unknown sub char */
2323                                 unknown = B_TRUE;
2324                                 break;
2325                         }
2326 
2327                         if (unknown)
2328                                 ptr = strdup("");
2329 
2330                 } else  /* first char of cmd's arg is not '%' char */
2331                         ptr = strdup("");
2332 
2333                 cmd_toks[i] = ptr;
2334 
2335                 if (ptr == NULL) {
2336                         for (i = 1; cmd_toks[i]; i++)
2337                                 free(cmd_toks[i]);
2338 
2339                         return (-1);
2340                 }
2341         }
2342 
2343         return (0);
2344 }
2345 
2346 /*ARGSUSED*/
2347 static void
2348 smb_shr_sig_abnormal_term(int sig_val)
2349 {
2350         /*
2351          * Calling _exit() prevents parent process from getting SIGTERM/SIGINT
2352          * signal.
2353          */
2354         _exit(-1);
2355 }
2356 
2357 /*ARGSUSED*/
2358 static void
2359 smb_shr_sig_child(int sig_val)
2360 {
2361         /*
2362          * Catch the signal and allow the exit status of the child process
2363          * to be available for reaping.
2364          */
2365 }
2366 
2367 /*
2368  * This is a temporary function which converts the given smb_share_t
2369  * structure to the nvlist format that will be provided by libsharev2
2370  */
2371 static int
2372 smb_shr_encode(smb_share_t *si, nvlist_t **nvlist)
2373 {
2374         nvlist_t *list;
2375         nvlist_t *share;
2376         nvlist_t *smb;
2377         char *csc;
2378         int rc = 0;
2379 
2380         *nvlist = NULL;
2381 
2382         if ((rc = nvlist_alloc(&list, NV_UNIQUE_NAME, 0)) != 0)
2383                 return (rc);
2384 
2385         if ((rc = nvlist_alloc(&share, NV_UNIQUE_NAME, 0)) != 0) {
2386                 nvlist_free(list);
2387                 return (rc);
2388         }
2389 
2390         if ((rc = nvlist_alloc(&smb, NV_UNIQUE_NAME, 0)) != 0) {
2391                 nvlist_free(share);
2392                 nvlist_free(list);
2393                 return (rc);
2394         }
2395 
2396         /* global share properties */
2397         rc |= nvlist_add_string(share, "name", si->shr_name);
2398         rc |= nvlist_add_string(share, "path", si->shr_path);
2399         rc |= nvlist_add_string(share, "desc", si->shr_cmnt);
2400 
2401         /* smb protocol properties */
2402         rc = nvlist_add_string(smb, SHOPT_AD_CONTAINER, si->shr_container);
2403         if ((si->shr_flags & SMB_SHRF_ACC_NONE) != 0)
2404                 rc |= nvlist_add_string(smb, SHOPT_NONE, si->shr_access_none);
2405         if ((si->shr_flags & SMB_SHRF_ACC_RO) != 0)
2406                 rc |= nvlist_add_string(smb, SHOPT_RO, si->shr_access_ro);
2407         if ((si->shr_flags & SMB_SHRF_ACC_RW) != 0)
2408                 rc |= nvlist_add_string(smb, SHOPT_RW, si->shr_access_rw);
2409 
2410         if ((si->shr_flags & SMB_SHRF_ABE) != 0)
2411                 rc |= nvlist_add_string(smb, SHOPT_ABE, "true");
2412         if ((si->shr_flags & SMB_SHRF_CATIA) != 0)
2413                 rc |= nvlist_add_string(smb, SHOPT_CATIA, "true");
2414         if ((si->shr_flags & SMB_SHRF_GUEST_OK) != 0)
2415                 rc |= nvlist_add_string(smb, SHOPT_GUEST, "true");
2416         if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0)
2417                 rc |= nvlist_add_string(smb, SHOPT_DFSROOT, "true");
2418 
2419         if ((si->shr_flags & SMB_SHRF_AUTOHOME) != 0) {
2420                 rc |= nvlist_add_string(smb, "Autohome", "true");
2421                 rc |= nvlist_add_uint32(smb, "uid", si->shr_uid);
2422                 rc |= nvlist_add_uint32(smb, "gid", si->shr_gid);
2423         }
2424 
2425         if ((csc = smb_shr_sa_csc_name(si)) != NULL)
2426                 rc |= nvlist_add_string(smb, SHOPT_CSC, csc);
2427 
2428         rc |= nvlist_add_uint32(smb, "type", si->shr_type);
2429 
2430         rc |= nvlist_add_nvlist(share, "smb", smb);
2431         rc |= nvlist_add_nvlist(list, si->shr_name, share);
2432 
2433         nvlist_free(share);
2434         nvlist_free(smb);
2435 
2436         if (rc != 0)
2437                 nvlist_free(list);
2438         else
2439                 *nvlist = list;
2440 
2441         return (rc);
2442 }