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 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>
  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         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;
 526         nvlist_t *shrlist;
 527 
 528         assert(sharename != NULL);
 529 
 530         if (smb_name_validate_share(sharename) != ERROR_SUCCESS)
 531                 return (ERROR_INVALID_NAME);
 532 
 533         if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
 534                 return (NERR_InternalError);
 535 
 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 }
 598 
 599 /*
 600  * Rename a share. Check that the current name exists and the new name
 601  * doesn't exist. The rename is performed by deleting the current share
 602  * definition and creating a new share with the new name.
 603  */
 604 uint32_t
 605 smb_shr_rename(char *from_name, char *to_name)
 606 {
 607         smb_share_t *from_si;
 608         smb_share_t to_si;
 609         uint32_t status;
 610         nvlist_t *shrlist;
 611 
 612         assert((from_name != NULL) && (to_name != NULL));
 613 
 614         if (smb_name_validate_share(from_name) != ERROR_SUCCESS ||
 615             smb_name_validate_share(to_name) != ERROR_SUCCESS)
 616                 return (ERROR_INVALID_NAME);
 617 
 618         if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
 619                 return (NERR_InternalError);
 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);
 680 
 681         return (NERR_Success);
 682 }
 683 
 684 /*
 685  * Load the information for the specified share into the supplied share
 686  * info structure.
 687  *
 688  * First looks up the cache to see if the specified share exists, if there
 689  * is a miss then it looks up sharemgr.
 690  */
 691 uint32_t
 692 smb_shr_get(char *sharename, smb_share_t *si)
 693 {
 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         }
 867 
 868         return (exists);
 869 }
 870 
 871 /*
 872  * If the shared directory does not begin with a /, one will be
 873  * inserted as a prefix. If ipaddr is not zero, then also return
 874  * information about access based on the host level access lists, if
 875  * present. Also return access check if there is an IP address and
 876  * shr_accflags.
 877  *
 878  * The value of smb_chk_hostaccess is checked for an access match.
 879  * -1 is wildcard match
 880  * 0 is no match
 881  * 1 is match
 882  *
 883  * Precedence is none is checked first followed by ro then rw if
 884  * needed.  If x is wildcard (< 0) then check to see if the other
 885  * values are a match. If a match, that wins.
 886  */
 887 uint32_t
 888 smb_shr_hostaccess(smb_inaddr_t *ipaddr, char *none_list, char *ro_list,
 889     char *rw_list, uint32_t flag)
 890 {
 891         uint32_t acc = SMB_SHRF_ACC_NONE;
 892         int none = 0;
 893         int ro = 0;
 894         int rw = 0;
 895 
 896         if (!smb_inet_iszero(ipaddr)) {
 897                 if ((flag & SMB_SHRF_ACC_NONE) != 0)
 898                         none = smb_chk_hostaccess(ipaddr, none_list);
 899                 if ((flag & SMB_SHRF_ACC_RO) != 0)
 900                         ro = smb_chk_hostaccess(ipaddr, ro_list);
 901                 if ((flag & SMB_SHRF_ACC_RW) != 0)
 902                         rw = smb_chk_hostaccess(ipaddr, rw_list);
 903 
 904                 /* make first pass to get basic value */
 905                 if (none != 0)
 906                         acc = SMB_SHRF_ACC_NONE;
 907                 else if (ro != 0)
 908                         acc = SMB_SHRF_ACC_RO;
 909                 else if (rw != 0)
 910                         acc = SMB_SHRF_ACC_RW;
 911 
 912                 /* make second pass to handle '*' case */
 913                 if (none < 0) {
 914                         acc = SMB_SHRF_ACC_NONE;
 915                         if (ro > 0)
 916                                 acc = SMB_SHRF_ACC_RO;
 917                         else if (rw > 0)
 918                                 acc = SMB_SHRF_ACC_RW;
 919                 } else if (ro < 0) {
 920                         acc = SMB_SHRF_ACC_RO;
 921                         if (none > 0)
 922                                 acc = SMB_SHRF_ACC_NONE;
 923                         else if (rw > 0)
 924                                 acc = SMB_SHRF_ACC_RW;
 925                 } else if (rw < 0) {
 926                         acc = SMB_SHRF_ACC_RW;
 927                         if (none > 0)
 928                                 acc = SMB_SHRF_ACC_NONE;
 929                         else if (ro > 0)
 930                                 acc = SMB_SHRF_ACC_RO;
 931                 }
 932         }
 933 
 934         return (acc);
 935 }
 936 
 937 /*
 938  * smb_shr_is_special
 939  *
 940  * Special share reserved for interprocess communication (IPC$) or
 941  * remote administration of the server (ADMIN$). Can also refer to
 942  * administrative shares such as C$, D$, E$, and so forth.
 943  */
 944 int
 945 smb_shr_is_special(char *sharename)
 946 {
 947         int len;
 948 
 949         if (sharename == NULL)
 950                 return (0);
 951 
 952         if ((len = strlen(sharename)) == 0)
 953                 return (0);
 954 
 955         if (sharename[len - 1] == '$')
 956                 return (STYPE_SPECIAL);
 957 
 958         return (0);
 959 }
 960 
 961 /*
 962  * smb_shr_is_restricted
 963  *
 964  * Check whether or not there is a restriction on a share. Restricted
 965  * shares are generally STYPE_SPECIAL, for example, IPC$. All the
 966  * administration share names are restricted: C$, D$ etc. Returns B_TRUE
 967  * if the share is restricted. Otherwise B_FALSE is returned to indicate
 968  * that there are no restrictions.
 969  */
 970 boolean_t
 971 smb_shr_is_restricted(char *sharename)
 972 {
 973         static char *restricted[] = {
 974                 "IPC$"
 975         };
 976 
 977         int i;
 978 
 979         if (sharename == NULL)
 980                 return (B_FALSE);
 981 
 982         for (i = 0; i < sizeof (restricted)/sizeof (restricted[0]); i++) {
 983                 if (smb_strcasecmp(restricted[i], sharename, 0) == 0)
 984                         return (B_TRUE);
 985         }
 986 
 987         return (smb_shr_is_admin(sharename));
 988 }
 989 
 990 /*
 991  * smb_shr_is_admin
 992  *
 993  * Check whether or not access to the share should be restricted to
 994  * administrators. This is a bit of a hack because what we're doing
 995  * is checking for the default admin shares: C$, D$ etc.. There are
 996  * other shares that have restrictions: see smb_shr_is_restricted().
 997  *
 998  * Returns B_TRUE if the shares is an admin share. Otherwise B_FALSE
 999  * is returned to indicate that there are no restrictions.
1000  */
1001 boolean_t
1002 smb_shr_is_admin(char *sharename)
1003 {
1004         if (sharename == NULL)
1005                 return (B_FALSE);
1006 
1007         if (strlen(sharename) == 2 &&
1008             smb_isalpha(sharename[0]) && sharename[1] == '$') {
1009                 return (B_TRUE);
1010         }
1011 
1012         return (B_FALSE);
1013 }
1014 
1015 char
1016 smb_shr_drive_letter(const char *path)
1017 {
1018         smb_transient_t *ts;
1019         int i;
1020 
1021         if (path == NULL)
1022                 return ('\0');
1023 
1024         for (i = 0; i < sizeof (tshare)/sizeof (tshare[0]); ++i) {
1025                 ts = &tshare[i];
1026 
1027                 if (ts->path == NULL)
1028                         continue;
1029 
1030                 if (strcasecmp(ts->path, path) == 0)
1031                         return (ts->drive);
1032         }
1033 
1034         return ('\0');
1035 }
1036 
1037 /*
1038  * Returns true if the specified directory is empty,
1039  * otherwise returns false.
1040  */
1041 static boolean_t
1042 smb_shr_is_empty(const char *path)
1043 {
1044         DIR *dirp;
1045         struct dirent *dp;
1046 
1047         if (path == NULL)
1048                 return (B_TRUE);
1049 
1050         if ((dirp = opendir(path)) == NULL)
1051                 return (B_TRUE);
1052 
1053         while ((dp = readdir(dirp)) != NULL) {
1054                 if (!smb_shr_is_dot_or_dotdot(dp->d_name))
1055                         return (B_FALSE);
1056         }
1057 
1058         (void) closedir(dirp);
1059         return (B_TRUE);
1060 }
1061 
1062 /*
1063  * Returns true if name is "." or "..", otherwise returns false.
1064  */
1065 static boolean_t
1066 smb_shr_is_dot_or_dotdot(const char *name)
1067 {
1068         if (*name != '.')
1069                 return (B_FALSE);
1070 
1071         if ((name[1] == '\0') || (name[1] == '.' && name[2] == '\0'))
1072                 return (B_TRUE);
1073 
1074         return (B_FALSE);
1075 }
1076 
1077 /*
1078  * smb_shr_get_realpath
1079  *
1080  * Derive the real path for a share from the path provided by a client.
1081  * For instance, the real path of C:\ may be /cvol or the real path of
1082  * F:\home may be /vol1/home.
1083  *
1084  * clntpath - path provided by the Windows client is in the
1085  *            format of <drive letter>:\<dir>
1086  * realpath - path that will be stored as the directory field of
1087  *            the smb_share_t structure of the share.
1088  * maxlen   - maximum length of the realpath buffer
1089  *
1090  * Return LAN Manager network error code.
1091  */
1092 uint32_t
1093 smb_shr_get_realpath(const char *clntpath, char *realpath, int maxlen)
1094 {
1095         const char *p;
1096         int len;
1097 
1098         if ((p = strchr(clntpath, ':')) != NULL)
1099                 ++p;
1100         else
1101                 p = clntpath;
1102 
1103         (void) strlcpy(realpath, p, maxlen);
1104         (void) strcanon(realpath, "/\\");
1105         (void) strsubst(realpath, '\\', '/');
1106 
1107         len = strlen(realpath);
1108         if ((len > 1) && (realpath[len - 1] == '/'))
1109                 realpath[len - 1] = '\0';
1110 
1111         return (NERR_Success);
1112 }
1113 
1114 void
1115 smb_shr_list(int offset, smb_shrlist_t *list)
1116 {
1117         smb_shriter_t iterator;
1118         smb_share_t *si;
1119         int n = 0;
1120 
1121         bzero(list, sizeof (smb_shrlist_t));
1122         smb_shr_iterinit(&iterator);
1123 
1124         while ((si = smb_shr_iterate(&iterator)) != NULL) {
1125                 if (--offset > 0)
1126                         continue;
1127 
1128                 if ((si->shr_flags & SMB_SHRF_TRANS) &&
1129                     (!STYPE_ISIPC(si->shr_type))) {
1130                         bcopy(si, &list->sl_shares[n], sizeof (smb_share_t));
1131                         if (++n == LMSHARES_PER_REQUEST)
1132                                 break;
1133                 }
1134         }
1135 
1136         list->sl_cnt = n;
1137 }
1138 
1139 /*
1140  * Executes the map/unmap command associated with a share.
1141  *
1142  * Returns 0 on success.  Otherwise non-zero for errors.
1143  */
1144 int
1145 smb_shr_exec(smb_shr_execinfo_t *subs)
1146 {
1147         char cmd[MAXPATHLEN], **cmd_tokens, *path, *ptr;
1148         pid_t child_pid;
1149         int child_status;
1150         struct sigaction pact, cact;
1151         smb_share_t si;
1152 
1153         if (smb_shr_get(subs->e_sharename, &si) != 0)
1154                 return (-1);
1155 
1156         *cmd = '\0';
1157 
1158         (void) mutex_lock(&smb_shr_exec_mtx);
1159 
1160         switch (subs->e_type) {
1161         case SMB_EXEC_MAP:
1162                 (void) strlcpy(cmd, smb_shr_exec_map, sizeof (cmd));
1163                 break;
1164         case SMB_EXEC_UNMAP:
1165                 (void) strlcpy(cmd, smb_shr_exec_unmap, sizeof (cmd));
1166                 break;
1167         default:
1168                 (void) mutex_unlock(&smb_shr_exec_mtx);
1169                 return (-1);
1170         }
1171 
1172         (void) mutex_unlock(&smb_shr_exec_mtx);
1173 
1174         if (*cmd == '\0')
1175                 return (0);
1176 
1177         if (smb_proc_takesem() != 0)
1178                 return (-1);
1179 
1180         pact.sa_handler = smb_shr_sig_child;
1181         pact.sa_flags = 0;
1182         (void) sigemptyset(&pact.sa_mask);
1183         sigaction(SIGCHLD, &pact, NULL);
1184 
1185         (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
1186 
1187         if ((child_pid = fork()) == -1) {
1188                 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
1189                 smb_proc_givesem();
1190                 return (-1);
1191         }
1192 
1193         if (child_pid == 0) {
1194 
1195                 /* child process */
1196 
1197                 cact.sa_handler = smb_shr_sig_abnormal_term;
1198                 cact.sa_flags = 0;
1199                 (void) sigemptyset(&cact.sa_mask);
1200                 sigaction(SIGTERM, &cact, NULL);
1201                 sigaction(SIGABRT, &cact, NULL);
1202                 sigaction(SIGSEGV, &cact, NULL);
1203 
1204                 if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_EXEC,
1205                     PRIV_FILE_DAC_EXECUTE, NULL))
1206                         _exit(-1);
1207 
1208                 if (smb_shr_enable_all_privs())
1209                         _exit(-1);
1210 
1211                 smb_proc_initsem();
1212 
1213                 (void) trim_whitespace(cmd);
1214                 (void) strcanon(cmd, " ");
1215 
1216                 if ((cmd_tokens = smb_shr_tokenize_cmd(cmd)) != NULL) {
1217 
1218                         if (smb_shr_expand_subs(cmd_tokens, &si, subs) != 0) {
1219                                 free(cmd_tokens[0]);
1220                                 free(cmd_tokens);
1221                                 _exit(-1);
1222                         }
1223 
1224                         ptr = cmd;
1225                         path = strsep(&ptr, " ");
1226 
1227                         (void) execv(path, cmd_tokens);
1228                 }
1229 
1230                 _exit(-1);
1231         }
1232 
1233         (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
1234         smb_proc_givesem();
1235 
1236         /* parent process */
1237 
1238         while (waitpid(child_pid, &child_status, 0) < 0) {
1239                 if (errno != EINTR)
1240                         break;
1241 
1242                 /* continue if waitpid got interrupted by a signal */
1243                 errno = 0;
1244                 continue;
1245         }
1246 
1247         if (WIFEXITED(child_status))
1248                 return (WEXITSTATUS(child_status));
1249 
1250         return (child_status);
1251 }
1252 
1253 /*
1254  * Locking for process-wide settings (i.e. privileges)
1255  */
1256 void
1257 smb_proc_initsem(void)
1258 {
1259         (void) sema_init(&smb_proc_sem, 1, USYNC_THREAD, NULL);
1260 }
1261 
1262 int
1263 smb_proc_takesem(void)
1264 {
1265         return (sema_wait(&smb_proc_sem));
1266 }
1267 
1268 void
1269 smb_proc_givesem(void)
1270 {
1271         (void) sema_post(&smb_proc_sem);
1272 }
1273 
1274 /*
1275  * ============================================
1276  * Private helper/utility functions
1277  * ============================================
1278  */
1279 
1280 /*
1281  * Looks up the given share in the cache and return
1282  * the info in 'si'
1283  */
1284 static uint32_t
1285 smb_shr_lookup(char *sharename, smb_share_t *si)
1286 {
1287         smb_share_t *cached_si;
1288         uint32_t status = NERR_NetNameNotFound;
1289 
1290         if (sharename == NULL || *sharename == '\0')
1291                 return (NERR_NetNameNotFound);
1292         if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
1293                 cached_si = smb_shr_cache_findent(sharename);
1294                 if (cached_si != NULL) {
1295                         bcopy(cached_si, si, sizeof (smb_share_t));
1296                         status = NERR_Success;
1297                 }
1298 
1299                 smb_shr_cache_unlock();
1300         }
1301         return (status);
1302 }
1303 
1304 /*
1305  * Add IPC$ or Admin shares to the cache upon startup.
1306  */
1307 static uint32_t
1308 smb_shr_add_transient(char *name, char *cmnt, char *path)
1309 {
1310         smb_share_t trans;
1311         uint32_t status = NERR_InternalError;
1312 
1313         if (name == NULL)
1314                 return (status);
1315 
1316         bzero(&trans, sizeof (smb_share_t));
1317         (void) strlcpy(trans.shr_name, name, MAXNAMELEN);
1318         if (cmnt)
1319                 (void) strlcpy(trans.shr_cmnt, cmnt, SMB_SHARE_CMNT_MAX);
1320 
1321         if (path)
1322                 (void) strlcpy(trans.shr_path, path, MAXPATHLEN);
1323 
1324         if (strcasecmp(name, "IPC$") == 0)
1325                 trans.shr_type = STYPE_IPC;
1326 
1327         trans.shr_flags = SMB_SHRF_TRANS;
1328 
1329         if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) {
1330                 status = smb_shr_cache_addent(&trans);
1331                 smb_shr_cache_unlock();
1332         }
1333 
1334         return (status);
1335 }
1336 
1337 /*
1338  * ============================================
1339  * Cache management functions
1340  *
1341  * All cache functions are private
1342  * ============================================
1343  */
1344 
1345 /*
1346  * Create the share cache (hash table).
1347  */
1348 static uint32_t
1349 smb_shr_cache_create(void)
1350 {
1351         uint32_t status = NERR_Success;
1352 
1353         (void) mutex_lock(&smb_shr_cache.sc_mtx);
1354         switch (smb_shr_cache.sc_state) {
1355         case SMB_SHR_CACHE_STATE_NONE:
1356                 smb_shr_cache.sc_cache = ht_create_table(SMB_SHR_HTAB_SZ,
1357                     MAXNAMELEN, 0);
1358                 if (smb_shr_cache.sc_cache == NULL) {
1359                         status = NERR_InternalError;
1360                         break;
1361                 }
1362 
1363                 (void) ht_register_callback(smb_shr_cache.sc_cache,
1364                     smb_shr_cache_freent);
1365                 smb_shr_cache.sc_nops = 0;
1366                 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_CREATED;
1367                 break;
1368 
1369         default:
1370                 assert(0);
1371                 status = NERR_InternalError;
1372                 break;
1373         }
1374         (void) mutex_unlock(&smb_shr_cache.sc_mtx);
1375 
1376         return (status);
1377 }
1378 
1379 /*
1380  * Destroy the share cache (hash table).
1381  * Wait for inflight/pending operations to finish or abort before
1382  * destroying the cache.
1383  */
1384 static void
1385 smb_shr_cache_destroy(void)
1386 {
1387         (void) mutex_lock(&smb_shr_cache.sc_mtx);
1388         if (smb_shr_cache.sc_state == SMB_SHR_CACHE_STATE_CREATED) {
1389                 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_DESTROYING;
1390                 while (smb_shr_cache.sc_nops > 0)
1391                         (void) cond_wait(&smb_shr_cache.sc_cv,
1392                             &smb_shr_cache.sc_mtx);
1393 
1394                 smb_shr_cache.sc_cache = NULL;
1395                 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_NONE;
1396         }
1397         (void) mutex_unlock(&smb_shr_cache.sc_mtx);
1398 }
1399 
1400 /*
1401  * If the cache is in "created" state, lock the cache for read
1402  * or read/write based on the specified mode.
1403  *
1404  * Whenever a lock is granted, the number of inflight cache
1405  * operations is incremented.
1406  */
1407 static uint32_t
1408 smb_shr_cache_lock(int mode)
1409 {
1410         (void) mutex_lock(&smb_shr_cache.sc_mtx);
1411         if (smb_shr_cache.sc_state != SMB_SHR_CACHE_STATE_CREATED) {
1412                 (void) mutex_unlock(&smb_shr_cache.sc_mtx);
1413                 return (NERR_InternalError);
1414         }
1415         smb_shr_cache.sc_nops++;
1416         (void) mutex_unlock(&smb_shr_cache.sc_mtx);
1417 
1418         /*
1419          * Lock has to be taken outside the mutex otherwise
1420          * there could be a deadlock
1421          */
1422         if (mode == SMB_SHR_CACHE_RDLOCK)
1423                 (void) rw_rdlock(&smb_shr_cache.sc_cache_lck);
1424         else
1425                 (void) rw_wrlock(&smb_shr_cache.sc_cache_lck);
1426 
1427         return (NERR_Success);
1428 }
1429 
1430 /*
1431  * Decrement the number of inflight operations and then unlock.
1432  */
1433 static void
1434 smb_shr_cache_unlock(void)
1435 {
1436         (void) mutex_lock(&smb_shr_cache.sc_mtx);
1437         assert(smb_shr_cache.sc_nops > 0);
1438         smb_shr_cache.sc_nops--;
1439         (void) cond_broadcast(&smb_shr_cache.sc_cv);
1440         (void) mutex_unlock(&smb_shr_cache.sc_mtx);
1441 
1442         (void) rw_unlock(&smb_shr_cache.sc_cache_lck);
1443 }
1444 
1445 /*
1446  * Return the total number of shares
1447  */
1448 static int
1449 smb_shr_cache_count(void)
1450 {
1451         return (ht_get_total_items(smb_shr_cache.sc_cache));
1452 }
1453 
1454 /*
1455  * looks up the given share name in the cache and if it
1456  * finds a match returns a pointer to the cached entry.
1457  * Note that since a pointer is returned this function
1458  * MUST be protected by smb_shr_cache_lock/unlock pair
1459  */
1460 static smb_share_t *
1461 smb_shr_cache_findent(char *sharename)
1462 {
1463         HT_ITEM *item;
1464 
1465         (void) smb_strlwr(sharename);
1466         item = ht_find_item(smb_shr_cache.sc_cache, sharename);
1467         if (item && item->hi_data)
1468                 return ((smb_share_t *)item->hi_data);
1469 
1470         return (NULL);
1471 }
1472 
1473 /*
1474  * Return a pointer to the first/next entry in
1475  * the cache based on the given iterator.
1476  *
1477  * Calls to this function MUST be protected by
1478  * smb_shr_cache_lock/unlock.
1479  */
1480 static smb_share_t *
1481 smb_shr_cache_iterate(smb_shriter_t *shi)
1482 {
1483         HT_ITEM *item;
1484 
1485         if (shi->si_first) {
1486                 item = ht_findfirst(smb_shr_cache.sc_cache, &shi->si_hashiter);
1487                 shi->si_first = B_FALSE;
1488         } else {
1489                 item = ht_findnext(&shi->si_hashiter);
1490         }
1491 
1492         if (item && item->hi_data)
1493                 return ((smb_share_t *)item->hi_data);
1494 
1495         return (NULL);
1496 }
1497 
1498 /*
1499  * Add the specified share to the cache.  Memory needs to be allocated
1500  * for the cache entry and the passed information is copied to the
1501  * allocated space.
1502  */
1503 static uint32_t
1504 smb_shr_cache_addent(smb_share_t *si)
1505 {
1506         smb_share_t *cache_ent;
1507         uint32_t status = NERR_Success;
1508 
1509         if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL)
1510                 return (ERROR_NOT_ENOUGH_MEMORY);
1511 
1512         (void) smb_strlwr(si->shr_name);
1513 
1514         si->shr_type |= smb_shr_is_special(cache_ent->shr_name);
1515 
1516         if (smb_shr_is_admin(cache_ent->shr_name))
1517                 si->shr_flags |= SMB_SHRF_ADMIN;
1518 
1519         bcopy(si, cache_ent, sizeof (smb_share_t));
1520 
1521         if (si->shr_flags & SMB_SHRF_AUTOHOME)
1522                 cache_ent->shr_refcnt = 1;
1523 
1524         if (ht_add_item(smb_shr_cache.sc_cache, cache_ent->shr_name, cache_ent)
1525             == NULL) {
1526                 syslog(LOG_DEBUG, "share: %s: cache update failed",
1527                     cache_ent->shr_name);
1528                 free(cache_ent);
1529                 status = NERR_InternalError;
1530         }
1531 
1532         return (status);
1533 }
1534 
1535 /*
1536  * Delete the specified share from the cache.
1537  */
1538 static void
1539 smb_shr_cache_delent(char *sharename)
1540 {
1541         (void) smb_strlwr(sharename);
1542         (void) ht_remove_item(smb_shr_cache.sc_cache, sharename);
1543 }
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 
1676         for (share = sa_get_share(group, NULL);
1677             share != NULL;
1678             share = sa_get_next_share(share)) {
1679                 for (resource = sa_get_share_resource(share, NULL);
1680                     resource != NULL;
1681                     resource = sa_get_next_resource(resource)) {
1682                         if (smb_shr_sa_load(share, resource))
1683                                 ++error_count;
1684 
1685                         if (error_count > SMB_SHR_ERROR_THRESHOLD)
1686                                 break;
1687                 }
1688 
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  *
1759  * Shares read from sharemgr are marked as permanent/persistent.
1760  */
1761 static uint32_t
1762 smb_shr_sa_get(sa_share_t share, sa_resource_t resource, smb_share_t *si)
1763 {
1764         sa_optionset_t opts;
1765         char *val = NULL;
1766         char *path;
1767         char *rname;
1768 
1769         if ((path = sa_get_share_attr(share, "path")) == NULL)
1770                 return (NERR_InternalError);
1771 
1772         if ((rname = sa_get_resource_attr(resource, "name")) == NULL) {
1773                 sa_free_attr_string(path);
1774                 return (NERR_InternalError);
1775         }
1776 
1777         bzero(si, sizeof (smb_share_t));
1778         si->shr_flags = SMB_SHRF_PERM;
1779 
1780         (void) strlcpy(si->shr_path, path, sizeof (si->shr_path));
1781         (void) strlcpy(si->shr_name, rname, sizeof (si->shr_name));
1782         sa_free_attr_string(path);
1783         sa_free_attr_string(rname);
1784 
1785         val = sa_get_resource_description(resource);
1786         if (val == NULL)
1787                 val = sa_get_share_description(share);
1788 
1789         if (val != NULL) {
1790                 (void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt));
1791                 sa_free_share_description(val);
1792         }
1793 
1794         opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1);
1795         if (opts == NULL)
1796                 return (NERR_Success);
1797 
1798         val = smb_shr_sa_getprop(opts, SHOPT_AD_CONTAINER);
1799         if (val != NULL) {
1800                 (void) strlcpy(si->shr_container, val,
1801                     sizeof (si->shr_container));
1802                 free(val);
1803         }
1804 
1805         val = smb_shr_sa_getprop(opts, SHOPT_CATIA);
1806         if (val != NULL) {
1807                 smb_shr_sa_setflag(val, si, SMB_SHRF_CATIA);
1808                 free(val);
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;
1877         }
1878 
1879         val = smb_shr_sa_getprop(opts, SHOPT_RW);
1880         if (val != NULL) {
1881                 (void) strlcpy(si->shr_access_rw, val,
1882                     sizeof (si->shr_access_rw));
1883                 free(val);
1884                 si->shr_flags |= SMB_SHRF_ACC_RW;
1885         }
1886 
1887         sa_free_derived_optionset(opts);
1888         return (NERR_Success);
1889 }
1890 
1891 /*
1892  * Map a client-side caching (CSC) option to the appropriate share
1893  * flag.  Only one option is allowed; an error will be logged if
1894  * multiple options have been specified.  We don't need to do anything
1895  * about multiple values here because the SRVSVC will not recognize
1896  * a value containing multiple flags and will return the default value.
1897  *
1898  * If the option value is not recognized, it will be ignored: invalid
1899  * values will typically be caught and rejected by sharemgr.
1900  */
1901 void
1902 smb_shr_sa_csc_option(const char *value, smb_share_t *si)
1903 {
1904         int i;
1905 
1906         for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) {
1907                 if (strcasecmp(value, cscopt[i].value) == 0) {
1908                         si->shr_flags |= cscopt[i].flag;
1909                         break;
1910                 }
1911         }
1912 
1913         switch (si->shr_flags & SMB_SHRF_CSC_MASK) {
1914         case 0:
1915         case SMB_SHRF_CSC_DISABLED:
1916         case SMB_SHRF_CSC_MANUAL:
1917         case SMB_SHRF_CSC_AUTO:
1918         case SMB_SHRF_CSC_VDO:
1919                 break;
1920 
1921         default:
1922                 syslog(LOG_INFO, "csc option conflict: 0x%08x",
1923                     si->shr_flags & SMB_SHRF_CSC_MASK);
1924                 break;
1925         }
1926 }
1927 
1928 /*
1929  * Return the option name for the first CSC flag (there should be only
1930  * one) encountered in the share flags.
1931  */
1932 char *
1933 smb_shr_sa_csc_name(const smb_share_t *si)
1934 {
1935         int i;
1936 
1937         for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) {
1938                 if (si->shr_flags & cscopt[i].flag)
1939                         return (cscopt[i].value);
1940         }
1941 
1942         return (NULL);
1943 }
1944 
1945 /*
1946  * Takes the value of a boolean share property and set/clear the
1947  * specified flag based on the property's value.
1948  */
1949 void
1950 smb_shr_sa_setflag(const char *value, smb_share_t *si, uint32_t flag)
1951 {
1952         if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0))
1953                 si->shr_flags |= flag;
1954         else
1955                 si->shr_flags &= ~flag;
1956 }
1957 
1958 /*
1959  * looks up sharemgr for the given share (resource) and loads
1960  * the definition into cache if lookup is successful
1961  */
1962 static uint32_t
1963 smb_shr_sa_loadbyname(char *sharename)
1964 {
1965         sa_handle_t handle;
1966         sa_share_t share;
1967         sa_resource_t resource;
1968         uint32_t status;
1969 
1970         if ((handle = smb_shr_sa_enter()) == NULL)
1971                 return (NERR_InternalError);
1972 
1973         resource = sa_find_resource(handle, sharename);
1974         if (resource == NULL) {
1975                 smb_shr_sa_exit();
1976                 return (NERR_NetNameNotFound);
1977         }
1978 
1979         share = sa_get_resource_parent(resource);
1980         if (share == NULL) {
1981                 smb_shr_sa_exit();
1982                 return (NERR_InternalError);
1983         }
1984 
1985         status = smb_shr_sa_load(share, resource);
1986 
1987         smb_shr_sa_exit();
1988         return (status);
1989 }
1990 
1991 /*
1992  * ============================================
1993  * Share publishing functions
1994  *
1995  * All the functions are private
1996  * ============================================
1997  */
1998 
1999 static void
2000 smb_shr_publish(const char *sharename, const char *container)
2001 {
2002         smb_shr_publisher_queue(sharename, container, SMB_SHR_PUBLISH);
2003 }
2004 
2005 static void
2006 smb_shr_unpublish(const char *sharename, const char *container)
2007 {
2008         smb_shr_publisher_queue(sharename, container, SMB_SHR_UNPUBLISH);
2009 }
2010 
2011 /*
2012  * In domain mode, put a share on the publisher queue.
2013  * This is a no-op if the smb service is in Workgroup mode.
2014  */
2015 static void
2016 smb_shr_publisher_queue(const char *sharename, const char *container, char op)
2017 {
2018         smb_shr_pitem_t *item = NULL;
2019 
2020         if (container == NULL || *container == '\0')
2021                 return;
2022 
2023         if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
2024                 return;
2025 
2026         (void) mutex_lock(&ad_queue.spq_mtx);
2027         switch (ad_queue.spq_state) {
2028         case SMB_SHR_PQS_READY:
2029         case SMB_SHR_PQS_PUBLISHING:
2030                 break;
2031         default:
2032                 (void) mutex_unlock(&ad_queue.spq_mtx);
2033                 return;
2034         }
2035         (void) mutex_unlock(&ad_queue.spq_mtx);
2036 
2037         if ((item = malloc(sizeof (smb_shr_pitem_t))) == NULL)
2038                 return;
2039 
2040         item->spi_op = op;
2041         (void) strlcpy(item->spi_name, sharename, sizeof (item->spi_name));
2042         (void) strlcpy(item->spi_container, container,
2043             sizeof (item->spi_container));
2044 
2045         (void) mutex_lock(&ad_queue.spq_mtx);
2046         list_insert_tail(&ad_queue.spq_list, item);
2047         (void) cond_signal(&ad_queue.spq_cv);
2048         (void) mutex_unlock(&ad_queue.spq_mtx);
2049 }
2050 
2051 /*
2052  * Publishing won't be activated if the smb service is running in
2053  * Workgroup mode.
2054  */
2055 static int
2056 smb_shr_publisher_start(void)
2057 {
2058         pthread_t publish_thr;
2059         pthread_attr_t tattr;
2060         int rc;
2061 
2062         if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
2063                 return (0);
2064 
2065         (void) mutex_lock(&ad_queue.spq_mtx);
2066         if (ad_queue.spq_state != SMB_SHR_PQS_NOQUEUE) {
2067                 (void) mutex_unlock(&ad_queue.spq_mtx);
2068                 errno = EINVAL;
2069                 return (-1);
2070         }
2071 
2072         list_create(&ad_queue.spq_list, sizeof (smb_shr_pitem_t),
2073             offsetof(smb_shr_pitem_t, spi_lnd));
2074         ad_queue.spq_state = SMB_SHR_PQS_READY;
2075         (void) mutex_unlock(&ad_queue.spq_mtx);
2076 
2077         (void) pthread_attr_init(&tattr);
2078         (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
2079         rc = pthread_create(&publish_thr, &tattr, smb_shr_publisher, 0);
2080         (void) pthread_attr_destroy(&tattr);
2081 
2082         return (rc);
2083 }
2084 
2085 static void
2086 smb_shr_publisher_stop(void)
2087 {
2088         if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
2089                 return;
2090 
2091         (void) mutex_lock(&ad_queue.spq_mtx);
2092         switch (ad_queue.spq_state) {
2093         case SMB_SHR_PQS_READY:
2094         case SMB_SHR_PQS_PUBLISHING:
2095                 ad_queue.spq_state = SMB_SHR_PQS_STOPPING;
2096                 (void) cond_signal(&ad_queue.spq_cv);
2097                 break;
2098         default:
2099                 break;
2100         }
2101         (void) mutex_unlock(&ad_queue.spq_mtx);
2102 }
2103 
2104 /*
2105  * This is the publisher daemon thread.  While running, the thread waits
2106  * on a conditional variable until notified that a share needs to be
2107  * [un]published or that the thread should be terminated.
2108  *
2109  * Entries may remain in the outgoing queue if the Active Directory
2110  * service is inaccessible, in which case the thread wakes up every 60
2111  * seconds to retry.
2112  */
2113 /*ARGSUSED*/
2114 static void *
2115 smb_shr_publisher(void *arg)
2116 {
2117         smb_ads_handle_t *ah;
2118         smb_shr_pitem_t *shr;
2119         list_t publist;
2120         timestruc_t pubretry;
2121         char hostname[MAXHOSTNAMELEN];
2122 
2123         (void) mutex_lock(&ad_queue.spq_mtx);
2124         if (ad_queue.spq_state != SMB_SHR_PQS_READY) {
2125                 (void) mutex_unlock(&ad_queue.spq_mtx);
2126                 return (NULL);
2127         }
2128         ad_queue.spq_state = SMB_SHR_PQS_PUBLISHING;
2129         (void) mutex_unlock(&ad_queue.spq_mtx);
2130 
2131         (void) smb_gethostname(hostname, MAXHOSTNAMELEN,
2132             SMB_CASE_PRESERVE);
2133 
2134         list_create(&publist, sizeof (smb_shr_pitem_t),
2135             offsetof(smb_shr_pitem_t, spi_lnd));
2136 
2137         for (;;) {
2138                 (void) mutex_lock(&ad_queue.spq_mtx);
2139 
2140                 while (list_is_empty(&ad_queue.spq_list) &&
2141                     (ad_queue.spq_state == SMB_SHR_PQS_PUBLISHING)) {
2142                         if (list_is_empty(&publist)) {
2143                                 (void) cond_wait(&ad_queue.spq_cv,
2144                                     &ad_queue.spq_mtx);
2145                         } else {
2146                                 pubretry.tv_sec = 60;
2147                                 pubretry.tv_nsec = 0;
2148                                 (void) cond_reltimedwait(&ad_queue.spq_cv,
2149                                     &ad_queue.spq_mtx, &pubretry);
2150                                 break;
2151                         }
2152                 }
2153 
2154                 if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) {
2155                         (void) mutex_unlock(&ad_queue.spq_mtx);
2156                         break;
2157                 }
2158 
2159                 /*
2160                  * Transfer queued items to the local list so that
2161                  * the mutex can be released.
2162                  */
2163                 while ((shr = list_head(&ad_queue.spq_list)) != NULL) {
2164                         list_remove(&ad_queue.spq_list, shr);
2165                         list_insert_tail(&publist, shr);
2166                 }
2167 
2168                 (void) mutex_unlock(&ad_queue.spq_mtx);
2169 
2170                 if ((ah = smb_ads_open()) != NULL) {
2171                         smb_shr_publisher_send(ah, &publist, hostname);
2172                         smb_ads_close(ah);
2173                 }
2174         }
2175 
2176         (void) mutex_lock(&ad_queue.spq_mtx);
2177         smb_shr_publisher_flush(&ad_queue.spq_list);
2178         list_destroy(&ad_queue.spq_list);
2179         ad_queue.spq_state = SMB_SHR_PQS_NOQUEUE;
2180         (void) mutex_unlock(&ad_queue.spq_mtx);
2181 
2182         smb_shr_publisher_flush(&publist);
2183         list_destroy(&publist);
2184         return (NULL);
2185 }
2186 
2187 /*
2188  * Remove items from the specified queue and [un]publish them.
2189  */
2190 static void
2191 smb_shr_publisher_send(smb_ads_handle_t *ah, list_t *publist, const char *host)
2192 {
2193         smb_shr_pitem_t *shr;
2194 
2195         while ((shr = list_head(publist)) != NULL) {
2196                 (void) mutex_lock(&ad_queue.spq_mtx);
2197                 if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) {
2198                         (void) mutex_unlock(&ad_queue.spq_mtx);
2199                         return;
2200                 }
2201                 (void) mutex_unlock(&ad_queue.spq_mtx);
2202 
2203                 list_remove(publist, shr);
2204 
2205                 if (shr->spi_op == SMB_SHR_PUBLISH)
2206                         (void) smb_ads_publish_share(ah, shr->spi_name,
2207                             NULL, shr->spi_container, host);
2208                 else
2209                         (void) smb_ads_remove_share(ah, shr->spi_name,
2210                             NULL, shr->spi_container, host);
2211 
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  */
2352 static int
2353 smb_shr_enable_all_privs(void)
2354 {
2355         priv_set_t *pset;
2356 
2357         pset = priv_allocset();
2358         if (pset == NULL)
2359                 return (-1);
2360 
2361         if (getppriv(PRIV_LIMIT, pset)) {
2362                 priv_freeset(pset);
2363                 return (-1);
2364         }
2365 
2366         if (setppriv(PRIV_ON, PRIV_INHERITABLE, pset)) {
2367                 priv_freeset(pset);
2368                 return (-1);
2369         }
2370 
2371         priv_freeset(pset);
2372         return (0);
2373 }
2374 
2375 /*
2376  * Tokenizes the command string and returns the list of tokens in an array.
2377  *
2378  * Returns NULL if there are no tokens.
2379  */
2380 static char **
2381 smb_shr_tokenize_cmd(char *cmdstr)
2382 {
2383         char *cmd, *buf, *bp, *value;
2384         char **argv, **ap;
2385         int argc, i;
2386 
2387         if (cmdstr == NULL || *cmdstr == '\0')
2388                 return (NULL);
2389 
2390         if ((buf = malloc(MAXPATHLEN)) == NULL)
2391                 return (NULL);
2392 
2393         (void) strlcpy(buf, cmdstr, MAXPATHLEN);
2394 
2395         for (argc = 2, bp = cmdstr; *bp != '\0'; ++bp)
2396                 if (*bp == ' ')
2397                         ++argc;
2398 
2399         if ((argv = calloc(argc, sizeof (char *))) == NULL) {
2400                 free(buf);
2401                 return (NULL);
2402         }
2403 
2404         ap = argv;
2405         for (bp = buf, i = 0; i < argc; ++i) {
2406                 do {
2407                         if ((value = strsep(&bp, " ")) == NULL)
2408                                 break;
2409                 } while (*value == '\0');
2410 
2411                 if (value == NULL)
2412                         break;
2413 
2414                 *ap++ = value;
2415         }
2416 
2417         /* get the filename of the command from the path */
2418         if ((cmd = strrchr(argv[0], '/')) != NULL)
2419                 (void) strlcpy(argv[0], ++cmd, strlen(argv[0]));
2420 
2421         return (argv);
2422 }
2423 
2424 /*
2425  * Expands the command string for the following substitution tokens:
2426  *
2427  * %U - Windows username
2428  * %D - Name of the domain or workgroup of %U
2429  * %h - The server hostname
2430  * %M - The client hostname
2431  * %L - The server NetBIOS name
2432  * %m - The client NetBIOS name. This option is only valid for NetBIOS
2433  *      connections (port 139).
2434  * %I - The IP address of the client machine
2435  * %i - The local IP address to which the client is connected
2436  * %S - The name of the share
2437  * %P - The root directory of the share
2438  * %u - The UID of the Unix user
2439  *
2440  * Returns 0 on success.  Otherwise -1.
2441  */
2442 static int
2443 smb_shr_expand_subs(char **cmd_toks, smb_share_t *si, smb_shr_execinfo_t *subs)
2444 {
2445         char *fmt, *sub_chr, *ptr;
2446         boolean_t unknown;
2447         char hostname[MAXHOSTNAMELEN];
2448         char ip_str[INET6_ADDRSTRLEN];
2449         char name[SMB_PI_MAX_HOST];
2450         smb_wchar_t wbuf[SMB_PI_MAX_HOST];
2451         int i;
2452 
2453         if (cmd_toks == NULL || *cmd_toks == NULL)
2454                 return (-1);
2455 
2456         for (i = 1; cmd_toks[i]; i++) {
2457                 fmt = cmd_toks[i];
2458                 if (*fmt == '%') {
2459                         sub_chr = fmt + 1;
2460                         unknown = B_FALSE;
2461 
2462                         switch (*sub_chr) {
2463                         case 'U':
2464                                 ptr = strdup(subs->e_winname);
2465                                 break;
2466                         case 'D':
2467                                 ptr = strdup(subs->e_userdom);
2468                                 break;
2469                         case 'h':
2470                                 if (gethostname(hostname, MAXHOSTNAMELEN) != 0)
2471                                         unknown = B_TRUE;
2472                                 else
2473                                         ptr = strdup(hostname);
2474                                 break;
2475                         case 'M':
2476                                 if (smb_getnameinfo(&subs->e_cli_ipaddr,
2477                                     hostname, sizeof (hostname), 0) != 0)
2478                                         unknown = B_TRUE;
2479                                 else
2480                                         ptr = strdup(hostname);
2481                                 break;
2482                         case 'L':
2483                                 if (smb_getnetbiosname(hostname,
2484                                     NETBIOS_NAME_SZ) != 0)
2485                                         unknown = B_TRUE;
2486                                 else
2487                                         ptr = strdup(hostname);
2488                                 break;
2489                         case 'm':
2490                                 if (*subs->e_cli_netbiosname == '\0')
2491                                         unknown = B_TRUE;
2492                                 else {
2493                                         (void) smb_mbstowcs(wbuf,
2494                                             subs->e_cli_netbiosname,
2495                                             SMB_PI_MAX_HOST - 1);
2496 
2497                                         if (ucstooem(name, wbuf,
2498                                             SMB_PI_MAX_HOST, OEM_CPG_850) == 0)
2499                                                 (void) strlcpy(name,
2500                                                     subs->e_cli_netbiosname,
2501                                                     SMB_PI_MAX_HOST);
2502 
2503                                         ptr = strdup(name);
2504                                 }
2505                                 break;
2506                         case 'I':
2507                                 if (smb_inet_ntop(&subs->e_cli_ipaddr, ip_str,
2508                                     SMB_IPSTRLEN(subs->e_cli_ipaddr.a_family))
2509                                     != NULL)
2510                                         ptr = strdup(ip_str);
2511                                 else
2512                                         unknown = B_TRUE;
2513                                 break;
2514                         case 'i':
2515                                 if (smb_inet_ntop(&subs->e_srv_ipaddr, ip_str,
2516                                     SMB_IPSTRLEN(subs->e_srv_ipaddr.a_family))
2517                                     != NULL)
2518                                         ptr = strdup(ip_str);
2519                                 else
2520                                         unknown = B_TRUE;
2521                                 break;
2522                         case 'S':
2523                                 ptr = strdup(si->shr_name);
2524                                 break;
2525                         case 'P':
2526                                 ptr = strdup(si->shr_path);
2527                                 break;
2528                         case 'u':
2529                                 (void) snprintf(name, sizeof (name), "%u",
2530                                     subs->e_uid);
2531                                 ptr = strdup(name);
2532                                 break;
2533                         default:
2534                                 /* unknown sub char */
2535                                 unknown = B_TRUE;
2536                                 break;
2537                         }
2538 
2539                         if (unknown)
2540                                 ptr = strdup("");
2541 
2542                 } else  /* first char of cmd's arg is not '%' char */
2543                         ptr = strdup("");
2544 
2545                 cmd_toks[i] = ptr;
2546 
2547                 if (ptr == NULL) {
2548                         for (i = 1; cmd_toks[i]; i++)
2549                                 free(cmd_toks[i]);
2550 
2551                         return (-1);
2552                 }
2553         }
2554 
2555         return (0);
2556 }
2557 
2558 /*ARGSUSED*/
2559 static void
2560 smb_shr_sig_abnormal_term(int sig_val)
2561 {
2562         /*
2563          * Calling _exit() prevents parent process from getting SIGTERM/SIGINT
2564          * signal.
2565          */
2566         _exit(-1);
2567 }
2568 
2569 /*ARGSUSED*/
2570 static void
2571 smb_shr_sig_child(int sig_val)
2572 {
2573         /*
2574          * Catch the signal and allow the exit status of the child process
2575          * to be available for reaping.
2576          */
2577 }
2578 
2579 /*
2580  * This is a temporary function which converts the given smb_share_t
2581  * structure to the nvlist format that will be provided by libsharev2
2582  */
2583 static int
2584 smb_shr_encode(smb_share_t *si, nvlist_t **nvlist)
2585 {
2586         nvlist_t *list;
2587         nvlist_t *share;
2588         nvlist_t *smb;
2589         char *csc;
2590         int rc = 0;
2591 
2592         *nvlist = NULL;
2593 
2594         if ((rc = nvlist_alloc(&list, NV_UNIQUE_NAME, 0)) != 0)
2595                 return (rc);
2596 
2597         if ((rc = nvlist_alloc(&share, NV_UNIQUE_NAME, 0)) != 0) {
2598                 nvlist_free(list);
2599                 return (rc);
2600         }
2601 
2602         if ((rc = nvlist_alloc(&smb, NV_UNIQUE_NAME, 0)) != 0) {
2603                 nvlist_free(share);
2604                 nvlist_free(list);
2605                 return (rc);
2606         }
2607 
2608         /* global share properties */
2609         rc |= nvlist_add_string(share, "name", si->shr_name);
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 
2666         return (rc);
2667 }