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 * Copyright 2019 RackTop Systems. 24 */ 25 26 /* 27 * SMB/CIFS share cache implementation. 28 */ 29 30 #include <errno.h> 31 #include <synch.h> 32 #include <stdlib.h> 33 #include <strings.h> 34 #include <syslog.h> 35 #include <thread.h> 36 #include <pthread.h> 37 #include <assert.h> 38 #include <libshare.h> 39 #include <libzfs.h> 40 #include <priv_utils.h> 41 #include <sys/types.h> 42 #include <sys/wait.h> 43 #include <unistd.h> 44 #include <pwd.h> 45 #include <signal.h> 46 #include <dirent.h> 47 #include <dlfcn.h> 48 49 #include <smbsrv/libsmb.h> 50 #include <smbsrv/libsmbns.h> 51 #include <smbsrv/libmlsvc.h> 52 #include <smbsrv/smb_share.h> 53 #include <smbsrv/smb.h> 54 #include <mlsvc.h> 55 #include <dfs.h> 56 57 #define SMB_SHR_ERROR_THRESHOLD 3 58 #define SMB_SHR_CSC_BUFSZ 64 59 60 typedef struct smb_transient { 61 char *name; 62 char *cmnt; 63 char *path; 64 char drive; 65 boolean_t check; 66 } smb_transient_t; 67 68 static smb_transient_t tshare[] = { 69 { "IPC$", "Remote IPC", NULL, '\0', B_FALSE }, 70 { "c$", "Default Share", SMB_CVOL, 'C', B_FALSE }, 71 { "vss$", "VSS", SMB_VSS, 'V', B_TRUE } 72 }; 73 74 static struct { 75 char *value; 76 uint32_t flag; 77 } cscopt[] = { 78 { "disabled", SMB_SHRF_CSC_DISABLED }, 79 { "manual", SMB_SHRF_CSC_MANUAL }, 80 { "auto", SMB_SHRF_CSC_AUTO }, 81 { "vdo", SMB_SHRF_CSC_VDO } 82 }; 83 84 /* 85 * Cache functions and vars 86 */ 87 #define SMB_SHR_HTAB_SZ 1024 88 89 /* 90 * Cache handle 91 * 92 * Shares cache is a hash table. 93 * 94 * sc_cache pointer to hash table handle 95 * sc_cache_lck synchronize cache read/write accesses 96 * sc_state cache state machine values 97 * sc_nops number of inflight/pending cache operations 98 * sc_mtx protects handle fields 99 */ 100 typedef struct smb_shr_cache { 101 HT_HANDLE *sc_cache; 102 rwlock_t sc_cache_lck; 103 mutex_t sc_mtx; 104 cond_t sc_cv; 105 uint32_t sc_state; 106 uint32_t sc_nops; 107 } smb_shr_cache_t; 108 109 /* 110 * Cache states 111 */ 112 #define SMB_SHR_CACHE_STATE_NONE 0 113 #define SMB_SHR_CACHE_STATE_CREATED 1 114 #define SMB_SHR_CACHE_STATE_DESTROYING 2 115 116 /* 117 * Cache lock modes 118 */ 119 #define SMB_SHR_CACHE_RDLOCK 0 120 #define SMB_SHR_CACHE_WRLOCK 1 121 122 static smb_shr_cache_t smb_shr_cache; 123 124 static uint32_t smb_shr_cache_create(void); 125 static void smb_shr_cache_destroy(void); 126 static uint32_t smb_shr_cache_lock(int); 127 static void smb_shr_cache_unlock(void); 128 static int smb_shr_cache_count(void); 129 static smb_share_t *smb_shr_cache_iterate(smb_shriter_t *); 130 131 static smb_share_t *smb_shr_cache_findent(char *); 132 static uint32_t smb_shr_cache_addent(smb_share_t *); 133 static void smb_shr_cache_delent(char *); 134 static void smb_shr_cache_freent(HT_ITEM *); 135 136 static boolean_t smb_shr_is_empty(const char *); 137 static boolean_t smb_shr_is_dot_or_dotdot(const char *); 138 139 /* 140 * sharemgr functions 141 */ 142 static void smb_shr_sa_loadgrp(sa_group_t); 143 static uint32_t smb_shr_sa_load(sa_share_t, sa_resource_t); 144 static uint32_t smb_shr_sa_loadbyname(char *); 145 static uint32_t smb_shr_sa_get(sa_share_t, sa_resource_t, smb_share_t *); 146 147 /* 148 * .ZFS management functions 149 */ 150 static void smb_shr_zfs_add(smb_share_t *); 151 static void smb_shr_zfs_remove(smb_share_t *); 152 static void smb_shr_zfs_rename(smb_share_t *, smb_share_t *); 153 154 /* 155 * share publishing 156 */ 157 #define SMB_SHR_PUBLISH 0 158 #define SMB_SHR_UNPUBLISH 1 159 160 typedef struct smb_shr_pitem { 161 list_node_t spi_lnd; 162 char spi_name[MAXNAMELEN]; 163 char spi_container[MAXPATHLEN]; 164 char spi_op; 165 } smb_shr_pitem_t; 166 167 /* 168 * publish queue states 169 */ 170 #define SMB_SHR_PQS_NOQUEUE 0 171 #define SMB_SHR_PQS_READY 1 /* the queue is ready */ 172 #define SMB_SHR_PQS_PUBLISHING 2 /* publisher thread is running */ 173 #define SMB_SHR_PQS_STOPPING 3 174 175 /* 176 * share publishing queue 177 */ 178 typedef struct smb_shr_pqueue { 179 list_t spq_list; 180 mutex_t spq_mtx; 181 cond_t spq_cv; 182 uint32_t spq_state; 183 } smb_shr_pqueue_t; 184 185 static smb_shr_pqueue_t ad_queue; 186 187 static int smb_shr_publisher_start(void); 188 static void smb_shr_publisher_stop(void); 189 static void smb_shr_publisher_send(smb_ads_handle_t *, list_t *, const char *); 190 static void smb_shr_publisher_queue(const char *, const char *, char); 191 static void *smb_shr_publisher(void *); 192 static void smb_shr_publisher_flush(list_t *); 193 static void smb_shr_publish(const char *, const char *); 194 static void smb_shr_unpublish(const char *, const char *); 195 196 /* 197 * Utility/helper functions 198 */ 199 static uint32_t smb_shr_lookup(char *, smb_share_t *); 200 static uint32_t smb_shr_add_transient(char *, char *, char *); 201 static int smb_shr_enable_all_privs(void); 202 static int smb_shr_expand_subs(char **, smb_share_t *, smb_shr_execinfo_t *); 203 static char **smb_shr_tokenize_cmd(char *); 204 static void smb_shr_sig_abnormal_term(int); 205 static void smb_shr_sig_child(int); 206 static int smb_shr_encode(smb_share_t *, nvlist_t **); 207 208 /* 209 * libshare handle and synchronization 210 */ 211 typedef struct smb_sa_handle { 212 sa_handle_t sa_handle; 213 mutex_t sa_mtx; 214 boolean_t sa_in_service; 215 } smb_sa_handle_t; 216 217 static smb_sa_handle_t smb_sa_handle; 218 219 static char smb_shr_exec_map[MAXPATHLEN]; 220 static char smb_shr_exec_unmap[MAXPATHLEN]; 221 static mutex_t smb_shr_exec_mtx; 222 223 /* 224 * Semaphore held during temporary, process-wide changes 225 * such as process privileges. It is a seamaphore and 226 * not a mutex so a child of fork can reset it. 227 */ 228 static sema_t smb_proc_sem = DEFAULTSEMA; 229 230 /* 231 * Creates and initializes the cache and starts the publisher 232 * thread. 233 */ 234 int 235 smb_shr_start(void) 236 { 237 smb_transient_t *ts; 238 uint32_t nerr; 239 int i; 240 241 (void) mutex_lock(&smb_sa_handle.sa_mtx); 242 smb_sa_handle.sa_in_service = B_TRUE; 243 (void) mutex_unlock(&smb_sa_handle.sa_mtx); 244 245 if (smb_shr_cache_create() != NERR_Success) 246 return (ENOMEM); 247 248 for (i = 0; i < sizeof (tshare)/sizeof (tshare[0]); ++i) { 249 ts = &tshare[i]; 250 251 if (ts->check && smb_shr_is_empty(ts->path)) 252 continue; 253 254 nerr = smb_shr_add_transient(ts->name, ts->cmnt, ts->path); 255 if (nerr != NERR_Success) 256 return (ENOMEM); 257 } 258 259 return (smb_shr_publisher_start()); 260 } 261 262 void 263 smb_shr_stop(void) 264 { 265 smb_shr_cache_destroy(); 266 smb_shr_publisher_stop(); 267 268 (void) mutex_lock(&smb_sa_handle.sa_mtx); 269 smb_sa_handle.sa_in_service = B_FALSE; 270 271 if (smb_sa_handle.sa_handle != NULL) { 272 sa_fini(smb_sa_handle.sa_handle); 273 smb_sa_handle.sa_handle = NULL; 274 } 275 276 (void) mutex_unlock(&smb_sa_handle.sa_mtx); 277 } 278 279 /* 280 * Get a handle and exclusive access to the libshare API. 281 */ 282 sa_handle_t 283 smb_shr_sa_enter(void) 284 { 285 (void) mutex_lock(&smb_sa_handle.sa_mtx); 286 if (!smb_sa_handle.sa_in_service) { 287 (void) mutex_unlock(&smb_sa_handle.sa_mtx); 288 return (NULL); 289 } 290 291 if (smb_sa_handle.sa_handle != NULL && 292 sa_needs_refresh(smb_sa_handle.sa_handle)) { 293 sa_fini(smb_sa_handle.sa_handle); 294 smb_sa_handle.sa_handle = NULL; 295 } 296 297 if (smb_sa_handle.sa_handle == NULL) { 298 smb_sa_handle.sa_handle = sa_init(SA_INIT_SHARE_API); 299 if (smb_sa_handle.sa_handle == NULL) { 300 syslog(LOG_ERR, "share: failed to get libshare handle"); 301 (void) mutex_unlock(&smb_sa_handle.sa_mtx); 302 return (NULL); 303 } 304 } 305 306 return (smb_sa_handle.sa_handle); 307 } 308 309 /* 310 * Release exclusive access to the libshare API. 311 */ 312 void 313 smb_shr_sa_exit(void) 314 { 315 (void) mutex_unlock(&smb_sa_handle.sa_mtx); 316 } 317 318 /* 319 * Return the total number of shares 320 */ 321 int 322 smb_shr_count(void) 323 { 324 int n_shares = 0; 325 326 if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 327 n_shares = smb_shr_cache_count(); 328 smb_shr_cache_unlock(); 329 } 330 331 return (n_shares); 332 } 333 334 /* 335 * smb_shr_iterinit 336 * 337 * Initialize given iterator for traversing hash table. 338 */ 339 void 340 smb_shr_iterinit(smb_shriter_t *shi) 341 { 342 bzero(shi, sizeof (smb_shriter_t)); 343 shi->si_first = B_TRUE; 344 } 345 346 /* 347 * smb_shr_iterate 348 * 349 * Iterate on the shares in the hash table. The iterator must be initialized 350 * before the first iteration. On subsequent calls, the iterator must be 351 * passed unchanged. 352 * 353 * Returns NULL on failure or when all shares are visited, otherwise 354 * returns information of visited share. 355 */ 356 smb_share_t * 357 smb_shr_iterate(smb_shriter_t *shi) 358 { 359 smb_share_t *share = NULL; 360 smb_share_t *cached_si; 361 362 if (shi == NULL) 363 return (NULL); 364 365 if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 366 if ((cached_si = smb_shr_cache_iterate(shi)) != NULL) { 367 share = &shi->si_share; 368 bcopy(cached_si, share, sizeof (smb_share_t)); 369 } 370 smb_shr_cache_unlock(); 371 } 372 373 return (share); 374 } 375 376 /* 377 * Adds the given share to cache, publishes the share in ADS 378 * if it has an AD container, calls kernel to take a hold on 379 * the shared file system. If it can't take a hold on the 380 * shared file system, it's either because shared directory 381 * does not exist or some other error has occurred, in any 382 * case the share is removed from the cache. 383 * 384 * If the specified share is an autohome share which already 385 * exists in the cache, just increments the reference count. 386 */ 387 uint32_t 388 smb_shr_add(smb_share_t *si) 389 { 390 struct stat st; 391 smb_share_t *cached_si; 392 nvlist_t *shrlist; 393 boolean_t created_zfs = B_FALSE; 394 uint32_t status; 395 int rc; 396 397 assert(si != NULL); 398 399 if (smb_name_validate_share(si->shr_name) != ERROR_SUCCESS) 400 return (ERROR_INVALID_NAME); 401 402 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 403 return (NERR_InternalError); 404 405 cached_si = smb_shr_cache_findent(si->shr_name); 406 if (cached_si) { 407 if (si->shr_flags & SMB_SHRF_AUTOHOME) { 408 cached_si->shr_refcnt++; 409 status = NERR_Success; 410 } else { 411 status = NERR_DuplicateShare; 412 } 413 smb_shr_cache_unlock(); 414 return (status); 415 } 416 417 if (STYPE_ISDSK(si->shr_type)) { 418 /* 419 * If share type is STYPE_DISKTREE then the path to the 420 * share should exist so that we can add the share to cache. 421 * If path is ZFS, add the .zfs/shares/<share> entry. 422 * 423 * Both actions may require privileges that main dropped, 424 * so we need to temporarily make those effective. 425 */ 426 if (smb_proc_takesem() == 0) { 427 428 (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, 429 PRIV_FILE_DAC_READ, 430 PRIV_FILE_DAC_SEARCH, 431 PRIV_FILE_DAC_WRITE, 432 NULL); 433 434 rc = stat(si->shr_path, &st); 435 if (rc == 0) { 436 smb_shr_zfs_add(si); 437 created_zfs = B_TRUE; 438 } 439 440 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, 441 PRIV_FILE_DAC_READ, 442 PRIV_FILE_DAC_SEARCH, 443 PRIV_FILE_DAC_WRITE, 444 NULL); 445 smb_proc_givesem(); 446 } else { 447 rc = NERR_InternalError; 448 } 449 if (rc != 0) { 450 smb_shr_cache_unlock(); 451 return (NERR_ItemNotFound); 452 } 453 } 454 455 if ((status = smb_shr_cache_addent(si)) != NERR_Success) { 456 /* This error should be impossible after findent above. */ 457 smb_shr_cache_unlock(); 458 return (status); 459 } 460 461 /* don't hold the lock across door call */ 462 smb_shr_cache_unlock(); 463 464 if ((rc = smb_shr_encode(si, &shrlist)) == 0) { 465 /* send the share to kernel */ 466 rc = smb_kmod_share(shrlist); 467 nvlist_free(shrlist); 468 469 if (rc == 0) { 470 smb_shr_publish(si->shr_name, si->shr_container); 471 472 if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0) 473 dfs_namespace_load(si->shr_name); 474 475 return (NERR_Success); 476 } 477 } 478 479 /* 480 * Error code path, i.e. when the kernel could not accept 481 * the new share for some reason. 482 */ 483 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) { 484 smb_shr_cache_delent(si->shr_name); 485 smb_shr_cache_unlock(); 486 } 487 488 if (created_zfs && smb_proc_takesem() == 0) { 489 490 (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, 491 PRIV_FILE_DAC_READ, 492 PRIV_FILE_DAC_SEARCH, 493 PRIV_FILE_DAC_WRITE, 494 NULL); 495 496 smb_shr_zfs_remove(si); 497 498 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, 499 PRIV_FILE_DAC_READ, 500 PRIV_FILE_DAC_SEARCH, 501 PRIV_FILE_DAC_WRITE, 502 NULL); 503 504 smb_proc_givesem(); 505 } 506 507 /* 508 * rc == ENOENT means the shared directory doesn't exist 509 */ 510 return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError); 511 } 512 513 /* 514 * Removes the specified share from cache, removes it from AD 515 * if it has an AD container, and calls the kernel to release 516 * the hold on the shared file system. 517 * 518 * If this is an autohome share then decrement the reference 519 * count. If it reaches 0 then it proceeds with removing steps. 520 */ 521 uint32_t 522 smb_shr_remove(char *sharename) 523 { 524 smb_share_t *si; 525 char container[MAXPATHLEN]; 526 boolean_t dfsroot; 527 nvlist_t *shrlist; 528 529 assert(sharename != NULL); 530 531 if (smb_name_validate_share(sharename) != ERROR_SUCCESS) 532 return (ERROR_INVALID_NAME); 533 534 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 535 return (NERR_InternalError); 536 537 if ((si = smb_shr_cache_findent(sharename)) == NULL) { 538 smb_shr_cache_unlock(); 539 return (NERR_NetNameNotFound); 540 } 541 542 if (STYPE_ISIPC(si->shr_type)) { 543 /* IPC$ share cannot be removed */ 544 smb_shr_cache_unlock(); 545 return (ERROR_ACCESS_DENIED); 546 } 547 548 if (si->shr_flags & SMB_SHRF_AUTOHOME) { 549 if ((--si->shr_refcnt) > 0) { 550 smb_shr_cache_unlock(); 551 return (NERR_Success); 552 } 553 } 554 555 /* 556 * If path is ZFS, remove the .zfs/shares/<share> entry. Need 557 * to remove before cleanup of cache occurs. These actions 558 * require temporary elevation of privileges. 559 */ 560 if (smb_proc_takesem() == 0) { 561 562 (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, 563 PRIV_FILE_DAC_READ, 564 PRIV_FILE_DAC_SEARCH, 565 PRIV_FILE_DAC_WRITE, 566 NULL); 567 568 smb_shr_zfs_remove(si); 569 570 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, 571 PRIV_FILE_DAC_READ, 572 PRIV_FILE_DAC_SEARCH, 573 PRIV_FILE_DAC_WRITE, 574 NULL); 575 576 smb_proc_givesem(); 577 } 578 579 (void) smb_shr_encode(si, &shrlist); 580 581 (void) strlcpy(container, si->shr_container, sizeof (container)); 582 dfsroot = ((si->shr_flags & SMB_SHRF_DFSROOT) != 0); 583 smb_shr_cache_delent(sharename); 584 smb_shr_cache_unlock(); 585 586 smb_shr_unpublish(sharename, container); 587 588 /* call kernel to release the hold on the shared file system */ 589 if (shrlist != NULL) { 590 (void) smb_kmod_unshare(shrlist); 591 nvlist_free(shrlist); 592 } 593 594 if (dfsroot) 595 dfs_namespace_unload(sharename); 596 597 return (NERR_Success); 598 } 599 600 /* 601 * Rename a share. Check that the current name exists and the new name 602 * doesn't exist. The rename is performed by deleting the current share 603 * definition and creating a new share with the new name. 604 */ 605 uint32_t 606 smb_shr_rename(char *from_name, char *to_name) 607 { 608 smb_share_t *from_si; 609 smb_share_t to_si; 610 uint32_t status; 611 nvlist_t *shrlist; 612 613 assert((from_name != NULL) && (to_name != NULL)); 614 615 if (smb_name_validate_share(from_name) != ERROR_SUCCESS || 616 smb_name_validate_share(to_name) != ERROR_SUCCESS) 617 return (ERROR_INVALID_NAME); 618 619 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 620 return (NERR_InternalError); 621 622 if ((from_si = smb_shr_cache_findent(from_name)) == NULL) { 623 smb_shr_cache_unlock(); 624 return (NERR_NetNameNotFound); 625 } 626 627 if (STYPE_ISIPC(from_si->shr_type)) { 628 /* IPC$ share cannot be renamed */ 629 smb_shr_cache_unlock(); 630 return (ERROR_ACCESS_DENIED); 631 } 632 633 if (smb_shr_cache_findent(to_name) != NULL) { 634 smb_shr_cache_unlock(); 635 return (NERR_DuplicateShare); 636 } 637 638 bcopy(from_si, &to_si, sizeof (smb_share_t)); 639 (void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name)); 640 641 /* If path is ZFS, rename the .zfs/shares/<share> entry. */ 642 if (smb_proc_takesem() == 0) { 643 644 (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, 645 PRIV_FILE_DAC_READ, 646 PRIV_FILE_DAC_SEARCH, 647 PRIV_FILE_DAC_WRITE, 648 NULL); 649 650 smb_shr_zfs_rename(from_si, &to_si); 651 652 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, 653 PRIV_FILE_DAC_READ, 654 PRIV_FILE_DAC_SEARCH, 655 PRIV_FILE_DAC_WRITE, 656 NULL); 657 658 smb_proc_givesem(); 659 } 660 661 if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) { 662 smb_shr_cache_unlock(); 663 return (status); 664 } 665 666 smb_shr_cache_delent(from_name); 667 smb_shr_cache_unlock(); 668 669 if (smb_shr_encode(from_si, &shrlist) == 0) { 670 (void) smb_kmod_unshare(shrlist); 671 nvlist_free(shrlist); 672 673 if (smb_shr_encode(&to_si, &shrlist) == 0) { 674 (void) smb_kmod_share(shrlist); 675 nvlist_free(shrlist); 676 } 677 } 678 679 smb_shr_unpublish(from_name, to_si.shr_container); 680 smb_shr_publish(to_name, to_si.shr_container); 681 682 return (NERR_Success); 683 } 684 685 /* 686 * Load the information for the specified share into the supplied share 687 * info structure. 688 * 689 * First looks up the cache to see if the specified share exists, if there 690 * is a miss then it looks up sharemgr. 691 */ 692 uint32_t 693 smb_shr_get(char *sharename, smb_share_t *si) 694 { 695 uint32_t status; 696 697 if (sharename == NULL || *sharename == '\0') 698 return (NERR_NetNameNotFound); 699 700 if ((status = smb_shr_lookup(sharename, si)) == NERR_Success) 701 return (status); 702 703 if ((status = smb_shr_sa_loadbyname(sharename)) == NERR_Success) 704 status = smb_shr_lookup(sharename, si); 705 706 return (status); 707 } 708 709 /* 710 * Modifies an existing share. Properties that can be modified are: 711 * 712 * o comment 713 * o AD container 714 * o host access 715 * o flags 716 */ 717 uint32_t 718 smb_shr_modify(smb_share_t *new_si) 719 { 720 smb_share_t old_si; 721 smb_share_t *si; 722 boolean_t adc_changed = B_FALSE; 723 boolean_t quota_flag_changed = B_FALSE; 724 uint32_t access, flag; 725 nvlist_t *shrlist; 726 727 assert(new_si != NULL); 728 729 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 730 return (NERR_InternalError); 731 732 if ((si = smb_shr_cache_findent(new_si->shr_name)) == NULL) { 733 smb_shr_cache_unlock(); 734 return (NERR_NetNameNotFound); 735 } 736 737 if (STYPE_ISIPC(si->shr_type)) { 738 /* IPC$ share cannot be modified */ 739 smb_shr_cache_unlock(); 740 return (ERROR_ACCESS_DENIED); 741 } 742 743 /* 744 * Keep a copy of what the share entry looks like before we 745 * modify it. We need this for things like unpublishing 746 * from the old share container, removing the quota dir. 747 */ 748 bcopy(si, &old_si, sizeof (old_si)); 749 750 /* Share comment */ 751 (void) strlcpy(si->shr_cmnt, new_si->shr_cmnt, sizeof (si->shr_cmnt)); 752 753 /* Container */ 754 (void) strlcpy(si->shr_container, new_si->shr_container, 755 sizeof (si->shr_container)); 756 adc_changed = (strcmp(old_si.shr_container, si->shr_container) != 0); 757 758 flag = (new_si->shr_flags & SMB_SHRF_ABE); 759 si->shr_flags &= ~SMB_SHRF_ABE; 760 si->shr_flags |= flag; 761 762 flag = (new_si->shr_flags & SMB_SHRF_CATIA); 763 si->shr_flags &= ~SMB_SHRF_CATIA; 764 si->shr_flags |= flag; 765 766 flag = (new_si->shr_flags & SMB_SHRF_GUEST_OK); 767 si->shr_flags &= ~SMB_SHRF_GUEST_OK; 768 si->shr_flags |= flag; 769 770 flag = (new_si->shr_flags & SMB_SHRF_DFSROOT); 771 si->shr_flags &= ~SMB_SHRF_DFSROOT; 772 si->shr_flags |= flag; 773 774 flag = (new_si->shr_flags & SMB_SHRF_CA); 775 si->shr_flags &= ~SMB_SHRF_CA; 776 si->shr_flags |= flag; 777 778 flag = (new_si->shr_flags & SMB_SHRF_FSO); 779 si->shr_flags &= ~SMB_SHRF_FSO; 780 si->shr_flags |= flag; 781 782 flag = (new_si->shr_flags & SMB_SHRF_QUOTAS); 783 si->shr_flags &= ~SMB_SHRF_QUOTAS; 784 si->shr_flags |= flag; 785 if ((old_si.shr_flags ^ si->shr_flags) & SMB_SHRF_QUOTAS) 786 quota_flag_changed = B_TRUE; 787 788 flag = (new_si->shr_flags & SMB_SHRF_CSC_MASK); 789 si->shr_flags &= ~SMB_SHRF_CSC_MASK; 790 si->shr_flags |= flag; 791 792 access = (new_si->shr_flags & SMB_SHRF_ACC_ALL); 793 si->shr_flags &= ~SMB_SHRF_ACC_ALL; 794 si->shr_flags |= access; 795 796 si->shr_encrypt = new_si->shr_encrypt; 797 798 if (access & SMB_SHRF_ACC_NONE) 799 (void) strlcpy(si->shr_access_none, new_si->shr_access_none, 800 sizeof (si->shr_access_none)); 801 802 if (access & SMB_SHRF_ACC_RO) 803 (void) strlcpy(si->shr_access_ro, new_si->shr_access_ro, 804 sizeof (si->shr_access_ro)); 805 806 if (access & SMB_SHRF_ACC_RW) 807 (void) strlcpy(si->shr_access_rw, new_si->shr_access_rw, 808 sizeof (si->shr_access_rw)); 809 810 smb_shr_cache_unlock(); 811 812 if (smb_shr_encode(si, &shrlist) == 0) { 813 (void) smb_kmod_unshare(shrlist); 814 nvlist_free(shrlist); 815 816 if (smb_shr_encode(new_si, &shrlist) == 0) { 817 (void) smb_kmod_share(shrlist); 818 nvlist_free(shrlist); 819 } 820 } 821 822 if (adc_changed) { 823 smb_shr_unpublish(old_si.shr_name, old_si.shr_container); 824 smb_shr_publish(new_si->shr_name, new_si->shr_container); 825 } 826 827 /* The following required privileges we dropped. */ 828 if (quota_flag_changed && smb_proc_takesem() == 0) { 829 830 (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, 831 PRIV_FILE_DAC_READ, 832 PRIV_FILE_DAC_SEARCH, 833 PRIV_FILE_DAC_WRITE, 834 NULL); 835 836 smb_shr_zfs_remove(&old_si); 837 smb_shr_zfs_add(si); 838 839 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, 840 PRIV_FILE_DAC_READ, 841 PRIV_FILE_DAC_SEARCH, 842 PRIV_FILE_DAC_WRITE, 843 NULL); 844 845 smb_proc_givesem(); 846 } 847 848 return (NERR_Success); 849 } 850 851 /* 852 * smb_shr_exists 853 * 854 * Returns B_TRUE if the share exists. Otherwise returns B_FALSE 855 */ 856 boolean_t 857 smb_shr_exists(char *sharename) 858 { 859 boolean_t exists = B_FALSE; 860 861 if (sharename == NULL || *sharename == '\0') 862 return (B_FALSE); 863 864 if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 865 exists = (smb_shr_cache_findent(sharename) != NULL); 866 smb_shr_cache_unlock(); 867 } 868 869 return (exists); 870 } 871 872 /* 873 * If the shared directory does not begin with a /, one will be 874 * inserted as a prefix. If ipaddr is not zero, then also return 875 * information about access based on the host level access lists, if 876 * present. Also return access check if there is an IP address and 877 * shr_accflags. 878 * 879 * The value of smb_chk_hostaccess is checked for an access match. 880 * -1 is wildcard match 881 * 0 is no match 882 * 1 is match 883 * 884 * Precedence is none is checked first followed by ro then rw if 885 * needed. If x is wildcard (< 0) then check to see if the other 886 * values are a match. If a match, that wins. 887 */ 888 uint32_t 889 smb_shr_hostaccess(smb_inaddr_t *ipaddr, char *none_list, char *ro_list, 890 char *rw_list, uint32_t flag) 891 { 892 uint32_t acc = SMB_SHRF_ACC_NONE; 893 int none = 0; 894 int ro = 0; 895 int rw = 0; 896 897 if (!smb_inet_iszero(ipaddr)) { 898 if ((flag & SMB_SHRF_ACC_NONE) != 0) 899 none = smb_chk_hostaccess(ipaddr, none_list); 900 if ((flag & SMB_SHRF_ACC_RO) != 0) 901 ro = smb_chk_hostaccess(ipaddr, ro_list); 902 if ((flag & SMB_SHRF_ACC_RW) != 0) 903 rw = smb_chk_hostaccess(ipaddr, rw_list); 904 905 /* make first pass to get basic value */ 906 if (none != 0) 907 acc = SMB_SHRF_ACC_NONE; 908 else if (ro != 0) 909 acc = SMB_SHRF_ACC_RO; 910 else if (rw != 0) 911 acc = SMB_SHRF_ACC_RW; 912 913 /* make second pass to handle '*' case */ 914 if (none < 0) { 915 acc = SMB_SHRF_ACC_NONE; 916 if (ro > 0) 917 acc = SMB_SHRF_ACC_RO; 918 else if (rw > 0) 919 acc = SMB_SHRF_ACC_RW; 920 } else if (ro < 0) { 921 acc = SMB_SHRF_ACC_RO; 922 if (none > 0) 923 acc = SMB_SHRF_ACC_NONE; 924 else if (rw > 0) 925 acc = SMB_SHRF_ACC_RW; 926 } else if (rw < 0) { 927 acc = SMB_SHRF_ACC_RW; 928 if (none > 0) 929 acc = SMB_SHRF_ACC_NONE; 930 else if (ro > 0) 931 acc = SMB_SHRF_ACC_RO; 932 } 933 } 934 935 return (acc); 936 } 937 938 /* 939 * smb_shr_is_special 940 * 941 * Special share reserved for interprocess communication (IPC$) or 942 * remote administration of the server (ADMIN$). Can also refer to 943 * administrative shares such as C$, D$, E$, and so forth. 944 */ 945 int 946 smb_shr_is_special(char *sharename) 947 { 948 int len; 949 950 if (sharename == NULL) 951 return (0); 952 953 if ((len = strlen(sharename)) == 0) 954 return (0); 955 956 if (sharename[len - 1] == '$') 957 return (STYPE_SPECIAL); 958 959 return (0); 960 } 961 962 /* 963 * smb_shr_is_restricted 964 * 965 * Check whether or not there is a restriction on a share. Restricted 966 * shares are generally STYPE_SPECIAL, for example, IPC$. All the 967 * administration share names are restricted: C$, D$ etc. Returns B_TRUE 968 * if the share is restricted. Otherwise B_FALSE is returned to indicate 969 * that there are no restrictions. 970 */ 971 boolean_t 972 smb_shr_is_restricted(char *sharename) 973 { 974 static char *restricted[] = { 975 "IPC$" 976 }; 977 978 int i; 979 980 if (sharename == NULL) 981 return (B_FALSE); 982 983 for (i = 0; i < sizeof (restricted)/sizeof (restricted[0]); i++) { 984 if (smb_strcasecmp(restricted[i], sharename, 0) == 0) 985 return (B_TRUE); 986 } 987 988 return (smb_shr_is_admin(sharename)); 989 } 990 991 /* 992 * smb_shr_is_admin 993 * 994 * Check whether or not access to the share should be restricted to 995 * administrators. This is a bit of a hack because what we're doing 996 * is checking for the default admin shares: C$, D$ etc.. There are 997 * other shares that have restrictions: see smb_shr_is_restricted(). 998 * 999 * Returns B_TRUE if the shares is an admin share. Otherwise B_FALSE 1000 * is returned to indicate that there are no restrictions. 1001 */ 1002 boolean_t 1003 smb_shr_is_admin(char *sharename) 1004 { 1005 if (sharename == NULL) 1006 return (B_FALSE); 1007 1008 if (strlen(sharename) == 2 && 1009 smb_isalpha(sharename[0]) && sharename[1] == '$') { 1010 return (B_TRUE); 1011 } 1012 1013 return (B_FALSE); 1014 } 1015 1016 char 1017 smb_shr_drive_letter(const char *path) 1018 { 1019 smb_transient_t *ts; 1020 int i; 1021 1022 if (path == NULL) 1023 return ('\0'); 1024 1025 for (i = 0; i < sizeof (tshare)/sizeof (tshare[0]); ++i) { 1026 ts = &tshare[i]; 1027 1028 if (ts->path == NULL) 1029 continue; 1030 1031 if (strcasecmp(ts->path, path) == 0) 1032 return (ts->drive); 1033 } 1034 1035 return ('\0'); 1036 } 1037 1038 /* 1039 * Returns true if the specified directory is empty, 1040 * otherwise returns false. 1041 */ 1042 static boolean_t 1043 smb_shr_is_empty(const char *path) 1044 { 1045 DIR *dirp; 1046 struct dirent *dp; 1047 1048 if (path == NULL) 1049 return (B_TRUE); 1050 1051 if ((dirp = opendir(path)) == NULL) 1052 return (B_TRUE); 1053 1054 while ((dp = readdir(dirp)) != NULL) { 1055 if (!smb_shr_is_dot_or_dotdot(dp->d_name)) 1056 return (B_FALSE); 1057 } 1058 1059 (void) closedir(dirp); 1060 return (B_TRUE); 1061 } 1062 1063 /* 1064 * Returns true if name is "." or "..", otherwise returns false. 1065 */ 1066 static boolean_t 1067 smb_shr_is_dot_or_dotdot(const char *name) 1068 { 1069 if (*name != '.') 1070 return (B_FALSE); 1071 1072 if ((name[1] == '\0') || (name[1] == '.' && name[2] == '\0')) 1073 return (B_TRUE); 1074 1075 return (B_FALSE); 1076 } 1077 1078 /* 1079 * smb_shr_get_realpath 1080 * 1081 * Derive the real path for a share from the path provided by a client. 1082 * For instance, the real path of C:\ may be /cvol or the real path of 1083 * F:\home may be /vol1/home. 1084 * 1085 * clntpath - path provided by the Windows client is in the 1086 * format of <drive letter>:\<dir> 1087 * realpath - path that will be stored as the directory field of 1088 * the smb_share_t structure of the share. 1089 * maxlen - maximum length of the realpath buffer 1090 * 1091 * Return LAN Manager network error code. 1092 */ 1093 uint32_t 1094 smb_shr_get_realpath(const char *clntpath, char *realpath, int maxlen) 1095 { 1096 const char *p; 1097 int len; 1098 1099 if ((p = strchr(clntpath, ':')) != NULL) 1100 ++p; 1101 else 1102 p = clntpath; 1103 1104 (void) strlcpy(realpath, p, maxlen); 1105 (void) strcanon(realpath, "/\\"); 1106 (void) strsubst(realpath, '\\', '/'); 1107 1108 len = strlen(realpath); 1109 if ((len > 1) && (realpath[len - 1] == '/')) 1110 realpath[len - 1] = '\0'; 1111 1112 return (NERR_Success); 1113 } 1114 1115 void 1116 smb_shr_list(int offset, smb_shrlist_t *list) 1117 { 1118 smb_shriter_t iterator; 1119 smb_share_t *si; 1120 int n = 0; 1121 1122 bzero(list, sizeof (smb_shrlist_t)); 1123 smb_shr_iterinit(&iterator); 1124 1125 while ((si = smb_shr_iterate(&iterator)) != NULL) { 1126 if (--offset > 0) 1127 continue; 1128 1129 if ((si->shr_flags & SMB_SHRF_TRANS) && 1130 (!STYPE_ISIPC(si->shr_type))) { 1131 bcopy(si, &list->sl_shares[n], sizeof (smb_share_t)); 1132 if (++n == LMSHARES_PER_REQUEST) 1133 break; 1134 } 1135 } 1136 1137 list->sl_cnt = n; 1138 } 1139 1140 /* 1141 * Executes the map/unmap command associated with a share. 1142 * 1143 * Returns 0 on success. Otherwise non-zero for errors. 1144 */ 1145 int 1146 smb_shr_exec(smb_shr_execinfo_t *subs) 1147 { 1148 char cmd[MAXPATHLEN], **cmd_tokens, *path, *ptr; 1149 pid_t child_pid; 1150 int child_status; 1151 struct sigaction pact, cact; 1152 smb_share_t si; 1153 1154 if (smb_shr_get(subs->e_sharename, &si) != 0) 1155 return (-1); 1156 1157 *cmd = '\0'; 1158 1159 (void) mutex_lock(&smb_shr_exec_mtx); 1160 1161 switch (subs->e_type) { 1162 case SMB_EXEC_MAP: 1163 (void) strlcpy(cmd, smb_shr_exec_map, sizeof (cmd)); 1164 break; 1165 case SMB_EXEC_UNMAP: 1166 (void) strlcpy(cmd, smb_shr_exec_unmap, sizeof (cmd)); 1167 break; 1168 default: 1169 (void) mutex_unlock(&smb_shr_exec_mtx); 1170 return (-1); 1171 } 1172 1173 (void) mutex_unlock(&smb_shr_exec_mtx); 1174 1175 if (*cmd == '\0') 1176 return (0); 1177 1178 if (smb_proc_takesem() != 0) 1179 return (-1); 1180 1181 pact.sa_handler = smb_shr_sig_child; 1182 pact.sa_flags = 0; 1183 (void) sigemptyset(&pact.sa_mask); 1184 sigaction(SIGCHLD, &pact, NULL); 1185 1186 (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL); 1187 1188 if ((child_pid = fork()) == -1) { 1189 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL); 1190 smb_proc_givesem(); 1191 return (-1); 1192 } 1193 1194 if (child_pid == 0) { 1195 1196 /* child process */ 1197 1198 cact.sa_handler = smb_shr_sig_abnormal_term; 1199 cact.sa_flags = 0; 1200 (void) sigemptyset(&cact.sa_mask); 1201 sigaction(SIGTERM, &cact, NULL); 1202 sigaction(SIGABRT, &cact, NULL); 1203 sigaction(SIGSEGV, &cact, NULL); 1204 1205 if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_EXEC, 1206 PRIV_FILE_DAC_EXECUTE, NULL)) 1207 _exit(-1); 1208 1209 if (smb_shr_enable_all_privs()) 1210 _exit(-1); 1211 1212 smb_proc_initsem(); 1213 1214 (void) trim_whitespace(cmd); 1215 (void) strcanon(cmd, " "); 1216 1217 if ((cmd_tokens = smb_shr_tokenize_cmd(cmd)) != NULL) { 1218 1219 if (smb_shr_expand_subs(cmd_tokens, &si, subs) != 0) { 1220 free(cmd_tokens[0]); 1221 free(cmd_tokens); 1222 _exit(-1); 1223 } 1224 1225 ptr = cmd; 1226 path = strsep(&ptr, " "); 1227 1228 (void) execv(path, cmd_tokens); 1229 } 1230 1231 _exit(-1); 1232 } 1233 1234 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL); 1235 smb_proc_givesem(); 1236 1237 /* parent process */ 1238 1239 while (waitpid(child_pid, &child_status, 0) < 0) { 1240 if (errno != EINTR) 1241 break; 1242 1243 /* continue if waitpid got interrupted by a signal */ 1244 errno = 0; 1245 continue; 1246 } 1247 1248 if (WIFEXITED(child_status)) 1249 return (WEXITSTATUS(child_status)); 1250 1251 return (child_status); 1252 } 1253 1254 /* 1255 * Locking for process-wide settings (i.e. privileges) 1256 */ 1257 void 1258 smb_proc_initsem(void) 1259 { 1260 (void) sema_init(&smb_proc_sem, 1, USYNC_THREAD, NULL); 1261 } 1262 1263 int 1264 smb_proc_takesem(void) 1265 { 1266 return (sema_wait(&smb_proc_sem)); 1267 } 1268 1269 void 1270 smb_proc_givesem(void) 1271 { 1272 (void) sema_post(&smb_proc_sem); 1273 } 1274 1275 /* 1276 * ============================================ 1277 * Private helper/utility functions 1278 * ============================================ 1279 */ 1280 1281 /* 1282 * Looks up the given share in the cache and return 1283 * the info in 'si' 1284 */ 1285 static uint32_t 1286 smb_shr_lookup(char *sharename, smb_share_t *si) 1287 { 1288 smb_share_t *cached_si; 1289 uint32_t status = NERR_NetNameNotFound; 1290 1291 if (sharename == NULL || *sharename == '\0') 1292 return (NERR_NetNameNotFound); 1293 if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 1294 cached_si = smb_shr_cache_findent(sharename); 1295 if (cached_si != NULL) { 1296 bcopy(cached_si, si, sizeof (smb_share_t)); 1297 status = NERR_Success; 1298 } 1299 1300 smb_shr_cache_unlock(); 1301 } 1302 return (status); 1303 } 1304 1305 /* 1306 * Add IPC$ or Admin shares to the cache upon startup. 1307 */ 1308 static uint32_t 1309 smb_shr_add_transient(char *name, char *cmnt, char *path) 1310 { 1311 smb_share_t trans; 1312 uint32_t status = NERR_InternalError; 1313 1314 if (name == NULL) 1315 return (status); 1316 1317 bzero(&trans, sizeof (smb_share_t)); 1318 (void) strlcpy(trans.shr_name, name, MAXNAMELEN); 1319 if (cmnt) 1320 (void) strlcpy(trans.shr_cmnt, cmnt, SMB_SHARE_CMNT_MAX); 1321 1322 if (path) 1323 (void) strlcpy(trans.shr_path, path, MAXPATHLEN); 1324 1325 if (strcasecmp(name, "IPC$") == 0) 1326 trans.shr_type = STYPE_IPC; 1327 1328 trans.shr_flags = SMB_SHRF_TRANS; 1329 1330 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) { 1331 status = smb_shr_cache_addent(&trans); 1332 smb_shr_cache_unlock(); 1333 } 1334 1335 return (status); 1336 } 1337 1338 /* 1339 * ============================================ 1340 * Cache management functions 1341 * 1342 * All cache functions are private 1343 * ============================================ 1344 */ 1345 1346 /* 1347 * Create the share cache (hash table). 1348 */ 1349 static uint32_t 1350 smb_shr_cache_create(void) 1351 { 1352 uint32_t status = NERR_Success; 1353 1354 (void) mutex_lock(&smb_shr_cache.sc_mtx); 1355 switch (smb_shr_cache.sc_state) { 1356 case SMB_SHR_CACHE_STATE_NONE: 1357 smb_shr_cache.sc_cache = ht_create_table(SMB_SHR_HTAB_SZ, 1358 MAXNAMELEN, 0); 1359 if (smb_shr_cache.sc_cache == NULL) { 1360 status = NERR_InternalError; 1361 break; 1362 } 1363 1364 (void) ht_set_cmpfn(smb_shr_cache.sc_cache, 1365 (HT_CMP)smb_strcasecmp); 1366 (void) ht_register_callback(smb_shr_cache.sc_cache, 1367 smb_shr_cache_freent); 1368 smb_shr_cache.sc_nops = 0; 1369 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_CREATED; 1370 break; 1371 1372 default: 1373 assert(0); 1374 status = NERR_InternalError; 1375 break; 1376 } 1377 (void) mutex_unlock(&smb_shr_cache.sc_mtx); 1378 1379 return (status); 1380 } 1381 1382 /* 1383 * Destroy the share cache (hash table). 1384 * Wait for inflight/pending operations to finish or abort before 1385 * destroying the cache. 1386 */ 1387 static void 1388 smb_shr_cache_destroy(void) 1389 { 1390 (void) mutex_lock(&smb_shr_cache.sc_mtx); 1391 if (smb_shr_cache.sc_state == SMB_SHR_CACHE_STATE_CREATED) { 1392 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_DESTROYING; 1393 while (smb_shr_cache.sc_nops > 0) 1394 (void) cond_wait(&smb_shr_cache.sc_cv, 1395 &smb_shr_cache.sc_mtx); 1396 1397 smb_shr_cache.sc_cache = NULL; 1398 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_NONE; 1399 } 1400 (void) mutex_unlock(&smb_shr_cache.sc_mtx); 1401 } 1402 1403 /* 1404 * If the cache is in "created" state, lock the cache for read 1405 * or read/write based on the specified mode. 1406 * 1407 * Whenever a lock is granted, the number of inflight cache 1408 * operations is incremented. 1409 */ 1410 static uint32_t 1411 smb_shr_cache_lock(int mode) 1412 { 1413 (void) mutex_lock(&smb_shr_cache.sc_mtx); 1414 if (smb_shr_cache.sc_state != SMB_SHR_CACHE_STATE_CREATED) { 1415 (void) mutex_unlock(&smb_shr_cache.sc_mtx); 1416 return (NERR_InternalError); 1417 } 1418 smb_shr_cache.sc_nops++; 1419 (void) mutex_unlock(&smb_shr_cache.sc_mtx); 1420 1421 /* 1422 * Lock has to be taken outside the mutex otherwise 1423 * there could be a deadlock 1424 */ 1425 if (mode == SMB_SHR_CACHE_RDLOCK) 1426 (void) rw_rdlock(&smb_shr_cache.sc_cache_lck); 1427 else 1428 (void) rw_wrlock(&smb_shr_cache.sc_cache_lck); 1429 1430 return (NERR_Success); 1431 } 1432 1433 /* 1434 * Decrement the number of inflight operations and then unlock. 1435 */ 1436 static void 1437 smb_shr_cache_unlock(void) 1438 { 1439 (void) mutex_lock(&smb_shr_cache.sc_mtx); 1440 assert(smb_shr_cache.sc_nops > 0); 1441 smb_shr_cache.sc_nops--; 1442 (void) cond_broadcast(&smb_shr_cache.sc_cv); 1443 (void) mutex_unlock(&smb_shr_cache.sc_mtx); 1444 1445 (void) rw_unlock(&smb_shr_cache.sc_cache_lck); 1446 } 1447 1448 /* 1449 * Return the total number of shares 1450 */ 1451 static int 1452 smb_shr_cache_count(void) 1453 { 1454 return (ht_get_total_items(smb_shr_cache.sc_cache)); 1455 } 1456 1457 /* 1458 * looks up the given share name in the cache and if it 1459 * finds a match returns a pointer to the cached entry. 1460 * Note that since a pointer is returned this function 1461 * MUST be protected by smb_shr_cache_lock/unlock pair 1462 */ 1463 static smb_share_t * 1464 smb_shr_cache_findent(char *sharename) 1465 { 1466 HT_ITEM *item; 1467 1468 item = ht_find_item(smb_shr_cache.sc_cache, sharename); 1469 if (item && item->hi_data) 1470 return ((smb_share_t *)item->hi_data); 1471 1472 return (NULL); 1473 } 1474 1475 /* 1476 * Return a pointer to the first/next entry in 1477 * the cache based on the given iterator. 1478 * 1479 * Calls to this function MUST be protected by 1480 * smb_shr_cache_lock/unlock. 1481 */ 1482 static smb_share_t * 1483 smb_shr_cache_iterate(smb_shriter_t *shi) 1484 { 1485 HT_ITEM *item; 1486 1487 if (shi->si_first) { 1488 item = ht_findfirst(smb_shr_cache.sc_cache, &shi->si_hashiter); 1489 shi->si_first = B_FALSE; 1490 } else { 1491 item = ht_findnext(&shi->si_hashiter); 1492 } 1493 1494 if (item && item->hi_data) 1495 return ((smb_share_t *)item->hi_data); 1496 1497 return (NULL); 1498 } 1499 1500 /* 1501 * Add the specified share to the cache. Memory needs to be allocated 1502 * for the cache entry and the passed information is copied to the 1503 * allocated space. 1504 */ 1505 static uint32_t 1506 smb_shr_cache_addent(smb_share_t *si) 1507 { 1508 smb_share_t *cache_ent; 1509 uint32_t status = NERR_Success; 1510 1511 if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL) 1512 return (ERROR_NOT_ENOUGH_MEMORY); 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) ht_remove_item(smb_shr_cache.sc_cache, sharename); 1542 } 1543 1544 /* 1545 * Call back to free the given cache entry. 1546 */ 1547 static void 1548 smb_shr_cache_freent(HT_ITEM *item) 1549 { 1550 if (item && item->hi_data) 1551 free(item->hi_data); 1552 } 1553 1554 /* 1555 * ============================================ 1556 * Interfaces to sharemgr 1557 * 1558 * All functions in this section are private 1559 * ============================================ 1560 */ 1561 1562 /* 1563 * Loads the SMB shares, from sharemgr, then: 1564 * - calls smb_shr_add which: 1565 * - adds the share into the share cache 1566 * - adds the share into in-kernel kshare table 1567 * - publishes the share in ADS 1568 * - updates the share list in sharefs/sharetab 1569 */ 1570 /*ARGSUSED*/ 1571 void * 1572 smb_shr_load(void *args) 1573 { 1574 sa_handle_t handle; 1575 sa_group_t group, subgroup; 1576 char *gstate; 1577 boolean_t gdisabled; 1578 1579 smb_shr_load_execinfo(); 1580 1581 if ((handle = smb_shr_sa_enter()) == NULL) { 1582 syslog(LOG_ERR, "smb_shr_load: load failed"); 1583 return (NULL); 1584 } 1585 1586 for (group = sa_get_group(handle, NULL); 1587 group != NULL; group = sa_get_next_group(group)) { 1588 gstate = sa_get_group_attr(group, "state"); 1589 if (gstate == NULL) 1590 continue; 1591 1592 gdisabled = (strcasecmp(gstate, "disabled") == 0); 1593 sa_free_attr_string(gstate); 1594 if (gdisabled) 1595 continue; 1596 1597 smb_shr_sa_loadgrp(group); 1598 1599 for (subgroup = sa_get_sub_group(group); 1600 subgroup != NULL; 1601 subgroup = sa_get_next_group(subgroup)) { 1602 smb_shr_sa_loadgrp(subgroup); 1603 } 1604 1605 } 1606 smb_shr_sa_exit(); 1607 return (NULL); 1608 } 1609 1610 void 1611 smb_shr_load_execinfo() 1612 { 1613 (void) mutex_lock(&smb_shr_exec_mtx); 1614 (void) smb_config_get_execinfo(smb_shr_exec_map, smb_shr_exec_unmap, 1615 MAXPATHLEN); 1616 (void) mutex_unlock(&smb_shr_exec_mtx); 1617 } 1618 1619 /* 1620 * Handles disabling shares in sharefs when stoping smbd 1621 */ 1622 void 1623 smb_shr_unload() 1624 { 1625 smb_shriter_t iterator; 1626 smb_share_t *si; 1627 sa_handle_t handle; 1628 int rc; 1629 1630 if ((handle = smb_shr_sa_enter()) == NULL) { 1631 syslog(LOG_ERR, "smb_shr_unload: failed"); 1632 return; 1633 } 1634 1635 smb_shr_iterinit(&iterator); 1636 1637 while ((si = smb_shr_iterate(&iterator)) != NULL) { 1638 1639 /* Skip transient shares, IPC$, ... */ 1640 if ((si->shr_flags & SMB_SHRF_TRANS) || 1641 STYPE_ISIPC(si->shr_type)) 1642 continue; 1643 1644 rc = sa_delete_sharetab(handle, si->shr_path, "smb"); 1645 if (rc) { 1646 syslog(LOG_ERR, 1647 "sharefs remove %s failed, rc=%d, err=%d", 1648 si->shr_path, rc, errno); 1649 } 1650 } 1651 smb_shr_sa_exit(); 1652 } 1653 1654 /* 1655 * Load the shares contained in the specified group. 1656 * 1657 * Don't process groups on which the smb protocol is disabled. 1658 * The top level ZFS group won't have the smb protocol enabled 1659 * but sub-groups will. 1660 * 1661 * We will tolerate a limited number of errors and then give 1662 * up on the current group. A typical error might be that the 1663 * shared directory no longer exists. 1664 */ 1665 static void 1666 smb_shr_sa_loadgrp(sa_group_t group) 1667 { 1668 sa_share_t share; 1669 sa_resource_t resource; 1670 int error_count = 0; 1671 1672 if (sa_get_optionset(group, SMB_PROTOCOL_NAME) == NULL) 1673 return; 1674 1675 for (share = sa_get_share(group, NULL); 1676 share != NULL; 1677 share = sa_get_next_share(share)) { 1678 for (resource = sa_get_share_resource(share, NULL); 1679 resource != NULL; 1680 resource = sa_get_next_resource(resource)) { 1681 if (smb_shr_sa_load(share, resource)) 1682 ++error_count; 1683 1684 if (error_count > SMB_SHR_ERROR_THRESHOLD) 1685 break; 1686 } 1687 1688 if (error_count > SMB_SHR_ERROR_THRESHOLD) 1689 break; 1690 } 1691 } 1692 1693 /* 1694 * Load a share definition from sharemgr and add it to the cache. 1695 * If the share is already in the cache then it doesn't do anything. 1696 * 1697 * This function does not report duplicate shares as error since 1698 * a share might have been added by smb_shr_get() while load is 1699 * in progress. 1700 */ 1701 static uint32_t 1702 smb_shr_sa_load(sa_share_t share, sa_resource_t resource) 1703 { 1704 smb_share_t si; 1705 char *sharename; 1706 uint32_t status; 1707 boolean_t loaded; 1708 int rc; 1709 1710 if ((sharename = sa_get_resource_attr(resource, "name")) == NULL) 1711 return (NERR_InternalError); 1712 1713 loaded = smb_shr_exists(sharename); 1714 sa_free_attr_string(sharename); 1715 1716 if (loaded) 1717 return (NERR_Success); 1718 1719 if ((status = smb_shr_sa_get(share, resource, &si)) != NERR_Success) { 1720 syslog(LOG_DEBUG, "share: failed to load %s (%d)", 1721 si.shr_name, status); 1722 return (status); 1723 } 1724 1725 status = smb_shr_add(&si); 1726 if ((status != NERR_Success) && (status != NERR_DuplicateShare)) { 1727 syslog(LOG_DEBUG, "share: failed to cache %s (%d)", 1728 si.shr_name, status); 1729 return (status); 1730 } 1731 1732 rc = sa_update_sharetab(share, "smb"); 1733 if (rc) { 1734 syslog(LOG_ERR, "sharefs add %s failed, rc=%d, err=%d", 1735 sharename, rc, errno); 1736 } 1737 1738 return (NERR_Success); 1739 } 1740 1741 static char * 1742 smb_shr_sa_getprop(sa_optionset_t opts, char *propname) 1743 { 1744 sa_property_t prop; 1745 char *val = NULL; 1746 1747 prop = sa_get_property(opts, propname); 1748 if (prop != NULL) 1749 val = sa_get_property_attr(prop, "value"); 1750 1751 return (val); 1752 } 1753 1754 /* 1755 * Read the specified share information from sharemgr and return 1756 * it in the given smb_share_t structure. 1757 * 1758 * Shares read from sharemgr are marked as permanent/persistent. 1759 */ 1760 static uint32_t 1761 smb_shr_sa_get(sa_share_t share, sa_resource_t resource, smb_share_t *si) 1762 { 1763 sa_optionset_t opts; 1764 char *val = NULL; 1765 char *path; 1766 char *rname; 1767 1768 if ((path = sa_get_share_attr(share, "path")) == NULL) 1769 return (NERR_InternalError); 1770 1771 if ((rname = sa_get_resource_attr(resource, "name")) == NULL) { 1772 sa_free_attr_string(path); 1773 return (NERR_InternalError); 1774 } 1775 1776 bzero(si, sizeof (smb_share_t)); 1777 si->shr_flags = SMB_SHRF_PERM; 1778 1779 (void) strlcpy(si->shr_path, path, sizeof (si->shr_path)); 1780 (void) strlcpy(si->shr_name, rname, sizeof (si->shr_name)); 1781 sa_free_attr_string(path); 1782 sa_free_attr_string(rname); 1783 1784 val = sa_get_resource_description(resource); 1785 if (val == NULL) 1786 val = sa_get_share_description(share); 1787 1788 if (val != NULL) { 1789 (void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt)); 1790 sa_free_share_description(val); 1791 } 1792 1793 opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1); 1794 if (opts == NULL) 1795 return (NERR_Success); 1796 1797 val = smb_shr_sa_getprop(opts, SHOPT_AD_CONTAINER); 1798 if (val != NULL) { 1799 (void) strlcpy(si->shr_container, val, 1800 sizeof (si->shr_container)); 1801 free(val); 1802 } 1803 1804 val = smb_shr_sa_getprop(opts, SHOPT_CATIA); 1805 if (val != NULL) { 1806 smb_shr_sa_setflag(val, si, SMB_SHRF_CATIA); 1807 free(val); 1808 } 1809 1810 val = smb_shr_sa_getprop(opts, SHOPT_ABE); 1811 if (val != NULL) { 1812 smb_shr_sa_setflag(val, si, SMB_SHRF_ABE); 1813 free(val); 1814 } 1815 1816 val = smb_shr_sa_getprop(opts, SHOPT_GUEST); 1817 if (val != NULL) { 1818 smb_shr_sa_setflag(val, si, SMB_SHRF_GUEST_OK); 1819 free(val); 1820 } 1821 1822 val = smb_shr_sa_getprop(opts, SHOPT_DFSROOT); 1823 if (val != NULL) { 1824 smb_shr_sa_setflag(val, si, SMB_SHRF_DFSROOT); 1825 free(val); 1826 } 1827 1828 val = smb_shr_sa_getprop(opts, SHOPT_CA); 1829 if (val != NULL) { 1830 smb_shr_sa_setflag(val, si, SMB_SHRF_CA); 1831 free(val); 1832 } 1833 1834 val = smb_shr_sa_getprop(opts, SHOPT_FSO); 1835 if (val != NULL) { 1836 smb_shr_sa_setflag(val, si, SMB_SHRF_FSO); 1837 free(val); 1838 } 1839 1840 val = smb_shr_sa_getprop(opts, SHOPT_QUOTAS); 1841 if (val != NULL) { 1842 /* Turn the flag on or off */ 1843 smb_shr_sa_setflag(val, si, SMB_SHRF_QUOTAS); 1844 free(val); 1845 } else { 1846 /* Default for this is enabled. */ 1847 si->shr_flags |= SMB_SHRF_QUOTAS; 1848 } 1849 1850 val = smb_shr_sa_getprop(opts, SHOPT_ENCRYPT); 1851 if (val != NULL) { 1852 smb_cfg_set_require(val, &si->shr_encrypt); 1853 free(val); 1854 } 1855 1856 val = smb_shr_sa_getprop(opts, SHOPT_CSC); 1857 if (val != NULL) { 1858 smb_shr_sa_csc_option(val, si); 1859 free(val); 1860 } 1861 1862 val = smb_shr_sa_getprop(opts, SHOPT_NONE); 1863 if (val != NULL) { 1864 (void) strlcpy(si->shr_access_none, val, 1865 sizeof (si->shr_access_none)); 1866 free(val); 1867 si->shr_flags |= SMB_SHRF_ACC_NONE; 1868 } 1869 1870 val = smb_shr_sa_getprop(opts, SHOPT_RO); 1871 if (val != NULL) { 1872 (void) strlcpy(si->shr_access_ro, val, 1873 sizeof (si->shr_access_ro)); 1874 free(val); 1875 si->shr_flags |= SMB_SHRF_ACC_RO; 1876 } 1877 1878 val = smb_shr_sa_getprop(opts, SHOPT_RW); 1879 if (val != NULL) { 1880 (void) strlcpy(si->shr_access_rw, val, 1881 sizeof (si->shr_access_rw)); 1882 free(val); 1883 si->shr_flags |= SMB_SHRF_ACC_RW; 1884 } 1885 1886 sa_free_derived_optionset(opts); 1887 return (NERR_Success); 1888 } 1889 1890 /* 1891 * Map a client-side caching (CSC) option to the appropriate share 1892 * flag. Only one option is allowed; an error will be logged if 1893 * multiple options have been specified. We don't need to do anything 1894 * about multiple values here because the SRVSVC will not recognize 1895 * a value containing multiple flags and will return the default value. 1896 * 1897 * If the option value is not recognized, it will be ignored: invalid 1898 * values will typically be caught and rejected by sharemgr. 1899 */ 1900 void 1901 smb_shr_sa_csc_option(const char *value, smb_share_t *si) 1902 { 1903 int i; 1904 1905 for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) { 1906 if (strcasecmp(value, cscopt[i].value) == 0) { 1907 si->shr_flags |= cscopt[i].flag; 1908 break; 1909 } 1910 } 1911 1912 switch (si->shr_flags & SMB_SHRF_CSC_MASK) { 1913 case 0: 1914 case SMB_SHRF_CSC_DISABLED: 1915 case SMB_SHRF_CSC_MANUAL: 1916 case SMB_SHRF_CSC_AUTO: 1917 case SMB_SHRF_CSC_VDO: 1918 break; 1919 1920 default: 1921 syslog(LOG_INFO, "csc option conflict: 0x%08x", 1922 si->shr_flags & SMB_SHRF_CSC_MASK); 1923 break; 1924 } 1925 } 1926 1927 /* 1928 * Return the option name for the first CSC flag (there should be only 1929 * one) encountered in the share flags. 1930 */ 1931 char * 1932 smb_shr_sa_csc_name(const smb_share_t *si) 1933 { 1934 int i; 1935 1936 for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) { 1937 if (si->shr_flags & cscopt[i].flag) 1938 return (cscopt[i].value); 1939 } 1940 1941 return (NULL); 1942 } 1943 1944 /* 1945 * Takes the value of a boolean share property and set/clear the 1946 * specified flag based on the property's value. 1947 */ 1948 void 1949 smb_shr_sa_setflag(const char *value, smb_share_t *si, uint32_t flag) 1950 { 1951 if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0)) 1952 si->shr_flags |= flag; 1953 else 1954 si->shr_flags &= ~flag; 1955 } 1956 1957 /* 1958 * looks up sharemgr for the given share (resource) and loads 1959 * the definition into cache if lookup is successful 1960 */ 1961 static uint32_t 1962 smb_shr_sa_loadbyname(char *sharename) 1963 { 1964 sa_handle_t handle; 1965 sa_share_t share; 1966 sa_resource_t resource; 1967 uint32_t status; 1968 1969 if ((handle = smb_shr_sa_enter()) == NULL) 1970 return (NERR_InternalError); 1971 1972 resource = sa_find_resource(handle, sharename); 1973 if (resource == NULL) { 1974 smb_shr_sa_exit(); 1975 return (NERR_NetNameNotFound); 1976 } 1977 1978 share = sa_get_resource_parent(resource); 1979 if (share == NULL) { 1980 smb_shr_sa_exit(); 1981 return (NERR_InternalError); 1982 } 1983 1984 status = smb_shr_sa_load(share, resource); 1985 1986 smb_shr_sa_exit(); 1987 return (status); 1988 } 1989 1990 /* 1991 * ============================================ 1992 * Share publishing functions 1993 * 1994 * All the functions are private 1995 * ============================================ 1996 */ 1997 1998 static void 1999 smb_shr_publish(const char *sharename, const char *container) 2000 { 2001 smb_shr_publisher_queue(sharename, container, SMB_SHR_PUBLISH); 2002 } 2003 2004 static void 2005 smb_shr_unpublish(const char *sharename, const char *container) 2006 { 2007 smb_shr_publisher_queue(sharename, container, SMB_SHR_UNPUBLISH); 2008 } 2009 2010 /* 2011 * In domain mode, put a share on the publisher queue. 2012 * This is a no-op if the smb service is in Workgroup mode. 2013 */ 2014 static void 2015 smb_shr_publisher_queue(const char *sharename, const char *container, char op) 2016 { 2017 smb_shr_pitem_t *item = NULL; 2018 2019 if (container == NULL || *container == '\0') 2020 return; 2021 2022 if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 2023 return; 2024 2025 (void) mutex_lock(&ad_queue.spq_mtx); 2026 switch (ad_queue.spq_state) { 2027 case SMB_SHR_PQS_READY: 2028 case SMB_SHR_PQS_PUBLISHING: 2029 break; 2030 default: 2031 (void) mutex_unlock(&ad_queue.spq_mtx); 2032 return; 2033 } 2034 (void) mutex_unlock(&ad_queue.spq_mtx); 2035 2036 if ((item = malloc(sizeof (smb_shr_pitem_t))) == NULL) 2037 return; 2038 2039 item->spi_op = op; 2040 (void) strlcpy(item->spi_name, sharename, sizeof (item->spi_name)); 2041 (void) strlcpy(item->spi_container, container, 2042 sizeof (item->spi_container)); 2043 2044 (void) mutex_lock(&ad_queue.spq_mtx); 2045 list_insert_tail(&ad_queue.spq_list, item); 2046 (void) cond_signal(&ad_queue.spq_cv); 2047 (void) mutex_unlock(&ad_queue.spq_mtx); 2048 } 2049 2050 /* 2051 * Publishing won't be activated if the smb service is running in 2052 * Workgroup mode. 2053 */ 2054 static int 2055 smb_shr_publisher_start(void) 2056 { 2057 pthread_t publish_thr; 2058 pthread_attr_t tattr; 2059 int rc; 2060 2061 if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 2062 return (0); 2063 2064 (void) mutex_lock(&ad_queue.spq_mtx); 2065 if (ad_queue.spq_state != SMB_SHR_PQS_NOQUEUE) { 2066 (void) mutex_unlock(&ad_queue.spq_mtx); 2067 errno = EINVAL; 2068 return (-1); 2069 } 2070 2071 list_create(&ad_queue.spq_list, sizeof (smb_shr_pitem_t), 2072 offsetof(smb_shr_pitem_t, spi_lnd)); 2073 ad_queue.spq_state = SMB_SHR_PQS_READY; 2074 (void) mutex_unlock(&ad_queue.spq_mtx); 2075 2076 (void) pthread_attr_init(&tattr); 2077 (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 2078 rc = pthread_create(&publish_thr, &tattr, smb_shr_publisher, 0); 2079 (void) pthread_attr_destroy(&tattr); 2080 2081 return (rc); 2082 } 2083 2084 static void 2085 smb_shr_publisher_stop(void) 2086 { 2087 if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 2088 return; 2089 2090 (void) mutex_lock(&ad_queue.spq_mtx); 2091 switch (ad_queue.spq_state) { 2092 case SMB_SHR_PQS_READY: 2093 case SMB_SHR_PQS_PUBLISHING: 2094 ad_queue.spq_state = SMB_SHR_PQS_STOPPING; 2095 (void) cond_signal(&ad_queue.spq_cv); 2096 break; 2097 default: 2098 break; 2099 } 2100 (void) mutex_unlock(&ad_queue.spq_mtx); 2101 } 2102 2103 /* 2104 * This is the publisher daemon thread. While running, the thread waits 2105 * on a conditional variable until notified that a share needs to be 2106 * [un]published or that the thread should be terminated. 2107 * 2108 * Entries may remain in the outgoing queue if the Active Directory 2109 * service is inaccessible, in which case the thread wakes up every 60 2110 * seconds to retry. 2111 */ 2112 /*ARGSUSED*/ 2113 static void * 2114 smb_shr_publisher(void *arg) 2115 { 2116 smb_ads_handle_t *ah; 2117 smb_shr_pitem_t *shr; 2118 list_t publist; 2119 timestruc_t pubretry; 2120 char hostname[MAXHOSTNAMELEN]; 2121 2122 (void) mutex_lock(&ad_queue.spq_mtx); 2123 if (ad_queue.spq_state != SMB_SHR_PQS_READY) { 2124 (void) mutex_unlock(&ad_queue.spq_mtx); 2125 return (NULL); 2126 } 2127 ad_queue.spq_state = SMB_SHR_PQS_PUBLISHING; 2128 (void) mutex_unlock(&ad_queue.spq_mtx); 2129 2130 (void) smb_gethostname(hostname, MAXHOSTNAMELEN, 2131 SMB_CASE_PRESERVE); 2132 2133 list_create(&publist, sizeof (smb_shr_pitem_t), 2134 offsetof(smb_shr_pitem_t, spi_lnd)); 2135 2136 for (;;) { 2137 (void) mutex_lock(&ad_queue.spq_mtx); 2138 2139 while (list_is_empty(&ad_queue.spq_list) && 2140 (ad_queue.spq_state == SMB_SHR_PQS_PUBLISHING)) { 2141 if (list_is_empty(&publist)) { 2142 (void) cond_wait(&ad_queue.spq_cv, 2143 &ad_queue.spq_mtx); 2144 } else { 2145 pubretry.tv_sec = 60; 2146 pubretry.tv_nsec = 0; 2147 (void) cond_reltimedwait(&ad_queue.spq_cv, 2148 &ad_queue.spq_mtx, &pubretry); 2149 break; 2150 } 2151 } 2152 2153 if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) { 2154 (void) mutex_unlock(&ad_queue.spq_mtx); 2155 break; 2156 } 2157 2158 /* 2159 * Transfer queued items to the local list so that 2160 * the mutex can be released. 2161 */ 2162 while ((shr = list_head(&ad_queue.spq_list)) != NULL) { 2163 list_remove(&ad_queue.spq_list, shr); 2164 list_insert_tail(&publist, shr); 2165 } 2166 2167 (void) mutex_unlock(&ad_queue.spq_mtx); 2168 2169 if ((ah = smb_ads_open()) != NULL) { 2170 smb_shr_publisher_send(ah, &publist, hostname); 2171 smb_ads_close(ah); 2172 } 2173 } 2174 2175 (void) mutex_lock(&ad_queue.spq_mtx); 2176 smb_shr_publisher_flush(&ad_queue.spq_list); 2177 list_destroy(&ad_queue.spq_list); 2178 ad_queue.spq_state = SMB_SHR_PQS_NOQUEUE; 2179 (void) mutex_unlock(&ad_queue.spq_mtx); 2180 2181 smb_shr_publisher_flush(&publist); 2182 list_destroy(&publist); 2183 return (NULL); 2184 } 2185 2186 /* 2187 * Remove items from the specified queue and [un]publish them. 2188 */ 2189 static void 2190 smb_shr_publisher_send(smb_ads_handle_t *ah, list_t *publist, const char *host) 2191 { 2192 smb_shr_pitem_t *shr; 2193 2194 while ((shr = list_head(publist)) != NULL) { 2195 (void) mutex_lock(&ad_queue.spq_mtx); 2196 if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) { 2197 (void) mutex_unlock(&ad_queue.spq_mtx); 2198 return; 2199 } 2200 (void) mutex_unlock(&ad_queue.spq_mtx); 2201 2202 list_remove(publist, shr); 2203 2204 if (shr->spi_op == SMB_SHR_PUBLISH) 2205 (void) smb_ads_publish_share(ah, shr->spi_name, 2206 NULL, shr->spi_container, host); 2207 else 2208 (void) smb_ads_remove_share(ah, shr->spi_name, 2209 NULL, shr->spi_container, host); 2210 2211 free(shr); 2212 } 2213 } 2214 2215 /* 2216 * Flush all remaining items from the specified list/queue. 2217 */ 2218 static void 2219 smb_shr_publisher_flush(list_t *lst) 2220 { 2221 smb_shr_pitem_t *shr; 2222 2223 while ((shr = list_head(lst)) != NULL) { 2224 list_remove(lst, shr); 2225 free(shr); 2226 } 2227 } 2228 2229 /* 2230 * If the share path refers to a ZFS file system, add the 2231 * .zfs/shares/<share> object and add or remove the special 2232 * directory and file telling clients about quota support. 2233 */ 2234 static void 2235 smb_shr_zfs_add(smb_share_t *si) 2236 { 2237 libzfs_handle_t *libhd; 2238 zfs_handle_t *zfshd; 2239 int ret; 2240 char buf[MAXPATHLEN]; /* dataset or mountpoint */ 2241 2242 if ((libhd = libzfs_init()) == NULL) 2243 return; 2244 2245 if (smb_getdataset(libhd, si->shr_path, buf, MAXPATHLEN) != 0) { 2246 libzfs_fini(libhd); 2247 return; 2248 } 2249 2250 if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) { 2251 libzfs_fini(libhd); 2252 return; 2253 } 2254 2255 errno = 0; 2256 ret = zfs_smb_acl_add(libhd, buf, si->shr_path, si->shr_name); 2257 if (ret != 0 && errno != EAGAIN && errno != EEXIST) 2258 syslog(LOG_INFO, "share: failed to add ACL object: %s: %s\n", 2259 si->shr_name, strerror(errno)); 2260 2261 ret = zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, 2262 buf, MAXPATHLEN, NULL, NULL, 0, B_FALSE); 2263 if (ret != 0) { 2264 syslog(LOG_INFO, "share: failed to get mountpoint: " 2265 "%s\n", si->shr_name); 2266 } else { 2267 if ((si->shr_flags & SMB_SHRF_QUOTAS) != 0) { 2268 smb_quota_add_fs(buf); 2269 } else { 2270 smb_quota_remove_fs(buf); 2271 } 2272 } 2273 2274 zfs_close(zfshd); 2275 libzfs_fini(libhd); 2276 } 2277 2278 /* 2279 * If the share path refers to a ZFS file system, remove the 2280 * .zfs/shares/<share> object. 2281 */ 2282 static void 2283 smb_shr_zfs_remove(smb_share_t *si) 2284 { 2285 libzfs_handle_t *libhd; 2286 int ret; 2287 char buf[MAXPATHLEN]; /* dataset or mountpoint */ 2288 2289 if ((libhd = libzfs_init()) == NULL) 2290 return; 2291 2292 if (smb_getdataset(libhd, si->shr_path, buf, MAXPATHLEN) != 0) { 2293 libzfs_fini(libhd); 2294 return; 2295 } 2296 2297 errno = 0; 2298 ret = zfs_smb_acl_remove(libhd, buf, si->shr_path, si->shr_name); 2299 if (ret != 0 && errno != EAGAIN) 2300 syslog(LOG_INFO, "share: failed to remove ACL object: %s: %s\n", 2301 si->shr_name, strerror(errno)); 2302 2303 /* 2304 * We could remove the quotas directory here, but that adds 2305 * significantly to the time required for a zpool export, 2306 * so just leave it here and fixup when we share next. 2307 */ 2308 2309 libzfs_fini(libhd); 2310 } 2311 2312 /* 2313 * If the share path refers to a ZFS file system, rename the 2314 * .zfs/shares/<share> object. 2315 */ 2316 static void 2317 smb_shr_zfs_rename(smb_share_t *from, smb_share_t *to) 2318 { 2319 libzfs_handle_t *libhd; 2320 zfs_handle_t *zfshd; 2321 int ret; 2322 char dataset[MAXPATHLEN]; 2323 2324 if ((libhd = libzfs_init()) == NULL) 2325 return; 2326 2327 if (smb_getdataset(libhd, from->shr_path, dataset, MAXPATHLEN) != 0) { 2328 libzfs_fini(libhd); 2329 return; 2330 } 2331 2332 if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) { 2333 libzfs_fini(libhd); 2334 return; 2335 } 2336 2337 errno = 0; 2338 ret = zfs_smb_acl_rename(libhd, dataset, from->shr_path, 2339 from->shr_name, to->shr_name); 2340 if (ret != 0 && errno != EAGAIN) 2341 syslog(LOG_INFO, "share: failed to rename ACL object: %s: %s\n", 2342 from->shr_name, strerror(errno)); 2343 2344 zfs_close(zfshd); 2345 libzfs_fini(libhd); 2346 } 2347 2348 /* 2349 * Enable all privileges in the inheritable set to execute command. 2350 */ 2351 static int 2352 smb_shr_enable_all_privs(void) 2353 { 2354 priv_set_t *pset; 2355 2356 pset = priv_allocset(); 2357 if (pset == NULL) 2358 return (-1); 2359 2360 if (getppriv(PRIV_LIMIT, pset)) { 2361 priv_freeset(pset); 2362 return (-1); 2363 } 2364 2365 if (setppriv(PRIV_ON, PRIV_INHERITABLE, pset)) { 2366 priv_freeset(pset); 2367 return (-1); 2368 } 2369 2370 priv_freeset(pset); 2371 return (0); 2372 } 2373 2374 /* 2375 * Tokenizes the command string and returns the list of tokens in an array. 2376 * 2377 * Returns NULL if there are no tokens. 2378 */ 2379 static char ** 2380 smb_shr_tokenize_cmd(char *cmdstr) 2381 { 2382 char *cmd, *buf, *bp, *value; 2383 char **argv, **ap; 2384 int argc, i; 2385 2386 if (cmdstr == NULL || *cmdstr == '\0') 2387 return (NULL); 2388 2389 if ((buf = malloc(MAXPATHLEN)) == NULL) 2390 return (NULL); 2391 2392 (void) strlcpy(buf, cmdstr, MAXPATHLEN); 2393 2394 for (argc = 2, bp = cmdstr; *bp != '\0'; ++bp) 2395 if (*bp == ' ') 2396 ++argc; 2397 2398 if ((argv = calloc(argc, sizeof (char *))) == NULL) { 2399 free(buf); 2400 return (NULL); 2401 } 2402 2403 ap = argv; 2404 for (bp = buf, i = 0; i < argc; ++i) { 2405 do { 2406 if ((value = strsep(&bp, " ")) == NULL) 2407 break; 2408 } while (*value == '\0'); 2409 2410 if (value == NULL) 2411 break; 2412 2413 *ap++ = value; 2414 } 2415 2416 /* get the filename of the command from the path */ 2417 if ((cmd = strrchr(argv[0], '/')) != NULL) 2418 (void) strlcpy(argv[0], ++cmd, strlen(argv[0])); 2419 2420 return (argv); 2421 } 2422 2423 /* 2424 * Expands the command string for the following substitution tokens: 2425 * 2426 * %U - Windows username 2427 * %D - Name of the domain or workgroup of %U 2428 * %h - The server hostname 2429 * %M - The client hostname 2430 * %L - The server NetBIOS name 2431 * %m - The client NetBIOS name. This option is only valid for NetBIOS 2432 * connections (port 139). 2433 * %I - The IP address of the client machine 2434 * %i - The local IP address to which the client is connected 2435 * %S - The name of the share 2436 * %P - The root directory of the share 2437 * %u - The UID of the Unix user 2438 * 2439 * Returns 0 on success. Otherwise -1. 2440 */ 2441 static int 2442 smb_shr_expand_subs(char **cmd_toks, smb_share_t *si, smb_shr_execinfo_t *subs) 2443 { 2444 char *fmt, *sub_chr, *ptr; 2445 boolean_t unknown; 2446 char hostname[MAXHOSTNAMELEN]; 2447 char ip_str[INET6_ADDRSTRLEN]; 2448 char name[SMB_PI_MAX_HOST]; 2449 smb_wchar_t wbuf[SMB_PI_MAX_HOST]; 2450 int i; 2451 2452 if (cmd_toks == NULL || *cmd_toks == NULL) 2453 return (-1); 2454 2455 for (i = 1; cmd_toks[i]; i++) { 2456 fmt = cmd_toks[i]; 2457 if (*fmt == '%') { 2458 sub_chr = fmt + 1; 2459 unknown = B_FALSE; 2460 2461 switch (*sub_chr) { 2462 case 'U': 2463 ptr = strdup(subs->e_winname); 2464 break; 2465 case 'D': 2466 ptr = strdup(subs->e_userdom); 2467 break; 2468 case 'h': 2469 if (gethostname(hostname, MAXHOSTNAMELEN) != 0) 2470 unknown = B_TRUE; 2471 else 2472 ptr = strdup(hostname); 2473 break; 2474 case 'M': 2475 if (smb_getnameinfo(&subs->e_cli_ipaddr, 2476 hostname, sizeof (hostname), 0) != 0) 2477 unknown = B_TRUE; 2478 else 2479 ptr = strdup(hostname); 2480 break; 2481 case 'L': 2482 if (smb_getnetbiosname(hostname, 2483 NETBIOS_NAME_SZ) != 0) 2484 unknown = B_TRUE; 2485 else 2486 ptr = strdup(hostname); 2487 break; 2488 case 'm': 2489 if (*subs->e_cli_netbiosname == '\0') 2490 unknown = B_TRUE; 2491 else { 2492 (void) smb_mbstowcs(wbuf, 2493 subs->e_cli_netbiosname, 2494 SMB_PI_MAX_HOST - 1); 2495 2496 if (ucstooem(name, wbuf, 2497 SMB_PI_MAX_HOST, OEM_CPG_850) == 0) 2498 (void) strlcpy(name, 2499 subs->e_cli_netbiosname, 2500 SMB_PI_MAX_HOST); 2501 2502 ptr = strdup(name); 2503 } 2504 break; 2505 case 'I': 2506 if (smb_inet_ntop(&subs->e_cli_ipaddr, ip_str, 2507 SMB_IPSTRLEN(subs->e_cli_ipaddr.a_family)) 2508 != NULL) 2509 ptr = strdup(ip_str); 2510 else 2511 unknown = B_TRUE; 2512 break; 2513 case 'i': 2514 if (smb_inet_ntop(&subs->e_srv_ipaddr, ip_str, 2515 SMB_IPSTRLEN(subs->e_srv_ipaddr.a_family)) 2516 != NULL) 2517 ptr = strdup(ip_str); 2518 else 2519 unknown = B_TRUE; 2520 break; 2521 case 'S': 2522 ptr = strdup(si->shr_name); 2523 break; 2524 case 'P': 2525 ptr = strdup(si->shr_path); 2526 break; 2527 case 'u': 2528 (void) snprintf(name, sizeof (name), "%u", 2529 subs->e_uid); 2530 ptr = strdup(name); 2531 break; 2532 default: 2533 /* unknown sub char */ 2534 unknown = B_TRUE; 2535 break; 2536 } 2537 2538 if (unknown) 2539 ptr = strdup(""); 2540 2541 } else /* first char of cmd's arg is not '%' char */ 2542 ptr = strdup(""); 2543 2544 cmd_toks[i] = ptr; 2545 2546 if (ptr == NULL) { 2547 for (i = 1; cmd_toks[i]; i++) 2548 free(cmd_toks[i]); 2549 2550 return (-1); 2551 } 2552 } 2553 2554 return (0); 2555 } 2556 2557 /*ARGSUSED*/ 2558 static void 2559 smb_shr_sig_abnormal_term(int sig_val) 2560 { 2561 /* 2562 * Calling _exit() prevents parent process from getting SIGTERM/SIGINT 2563 * signal. 2564 */ 2565 _exit(-1); 2566 } 2567 2568 /*ARGSUSED*/ 2569 static void 2570 smb_shr_sig_child(int sig_val) 2571 { 2572 /* 2573 * Catch the signal and allow the exit status of the child process 2574 * to be available for reaping. 2575 */ 2576 } 2577 2578 /* 2579 * This is a temporary function which converts the given smb_share_t 2580 * structure to the nvlist format that will be provided by libsharev2 2581 */ 2582 static int 2583 smb_shr_encode(smb_share_t *si, nvlist_t **nvlist) 2584 { 2585 nvlist_t *list; 2586 nvlist_t *share; 2587 nvlist_t *smb; 2588 char *csc; 2589 int rc = 0; 2590 2591 *nvlist = NULL; 2592 2593 if ((rc = nvlist_alloc(&list, NV_UNIQUE_NAME, 0)) != 0) 2594 return (rc); 2595 2596 if ((rc = nvlist_alloc(&share, NV_UNIQUE_NAME, 0)) != 0) { 2597 nvlist_free(list); 2598 return (rc); 2599 } 2600 2601 if ((rc = nvlist_alloc(&smb, NV_UNIQUE_NAME, 0)) != 0) { 2602 nvlist_free(share); 2603 nvlist_free(list); 2604 return (rc); 2605 } 2606 2607 /* global share properties */ 2608 rc |= nvlist_add_string(share, "name", si->shr_name); 2609 rc |= nvlist_add_string(share, "path", si->shr_path); 2610 rc |= nvlist_add_string(share, "desc", si->shr_cmnt); 2611 2612 /* smb protocol properties */ 2613 rc = nvlist_add_string(smb, SHOPT_AD_CONTAINER, si->shr_container); 2614 if ((si->shr_flags & SMB_SHRF_ACC_NONE) != 0) 2615 rc |= nvlist_add_string(smb, SHOPT_NONE, si->shr_access_none); 2616 if ((si->shr_flags & SMB_SHRF_ACC_RO) != 0) 2617 rc |= nvlist_add_string(smb, SHOPT_RO, si->shr_access_ro); 2618 if ((si->shr_flags & SMB_SHRF_ACC_RW) != 0) 2619 rc |= nvlist_add_string(smb, SHOPT_RW, si->shr_access_rw); 2620 2621 if ((si->shr_flags & SMB_SHRF_ABE) != 0) 2622 rc |= nvlist_add_string(smb, SHOPT_ABE, "true"); 2623 if ((si->shr_flags & SMB_SHRF_CATIA) != 0) 2624 rc |= nvlist_add_string(smb, SHOPT_CATIA, "true"); 2625 if ((si->shr_flags & SMB_SHRF_GUEST_OK) != 0) 2626 rc |= nvlist_add_string(smb, SHOPT_GUEST, "true"); 2627 if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0) 2628 rc |= nvlist_add_string(smb, SHOPT_DFSROOT, "true"); 2629 if ((si->shr_flags & SMB_SHRF_CA) != 0) 2630 rc |= nvlist_add_string(smb, SHOPT_CA, "true"); 2631 if ((si->shr_flags & SMB_SHRF_FSO) != 0) 2632 rc |= nvlist_add_string(smb, SHOPT_FSO, "true"); 2633 if ((si->shr_flags & SMB_SHRF_QUOTAS) != 0) 2634 rc |= nvlist_add_string(smb, SHOPT_QUOTAS, "true"); 2635 2636 if (si->shr_encrypt == SMB_CONFIG_REQUIRED) 2637 rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "required"); 2638 else if (si->shr_encrypt == SMB_CONFIG_ENABLED) 2639 rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "enabled"); 2640 else 2641 rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "disabled"); 2642 2643 if ((si->shr_flags & SMB_SHRF_AUTOHOME) != 0) { 2644 rc |= nvlist_add_string(smb, SHOPT_AUTOHOME, "true"); 2645 rc |= nvlist_add_uint32(smb, "uid", si->shr_uid); 2646 rc |= nvlist_add_uint32(smb, "gid", si->shr_gid); 2647 } 2648 2649 if ((csc = smb_shr_sa_csc_name(si)) != NULL) 2650 rc |= nvlist_add_string(smb, SHOPT_CSC, csc); 2651 2652 rc |= nvlist_add_uint32(smb, "type", si->shr_type); 2653 2654 rc |= nvlist_add_nvlist(share, "smb", smb); 2655 rc |= nvlist_add_nvlist(list, si->shr_name, share); 2656 2657 nvlist_free(share); 2658 nvlist_free(smb); 2659 2660 if (rc != 0) 2661 nvlist_free(list); 2662 else 2663 *nvlist = list; 2664 2665 return (rc); 2666 } 2667