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 2017 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_FSO); 774 si->shr_flags &= ~SMB_SHRF_FSO; 775 si->shr_flags |= flag; 776 777 flag = (new_si->shr_flags & SMB_SHRF_QUOTAS); 778 si->shr_flags &= ~SMB_SHRF_QUOTAS; 779 si->shr_flags |= flag; 780 if ((old_si.shr_flags ^ si->shr_flags) & SMB_SHRF_QUOTAS) 781 quota_flag_changed = B_TRUE; 782 783 flag = (new_si->shr_flags & SMB_SHRF_CSC_MASK); 784 si->shr_flags &= ~SMB_SHRF_CSC_MASK; 785 si->shr_flags |= flag; 786 787 access = (new_si->shr_flags & SMB_SHRF_ACC_ALL); 788 si->shr_flags &= ~SMB_SHRF_ACC_ALL; 789 si->shr_flags |= access; 790 791 si->shr_encrypt = new_si->shr_encrypt; 792 793 if (access & SMB_SHRF_ACC_NONE) 794 (void) strlcpy(si->shr_access_none, new_si->shr_access_none, 795 sizeof (si->shr_access_none)); 796 797 if (access & SMB_SHRF_ACC_RO) 798 (void) strlcpy(si->shr_access_ro, new_si->shr_access_ro, 799 sizeof (si->shr_access_ro)); 800 801 if (access & SMB_SHRF_ACC_RW) 802 (void) strlcpy(si->shr_access_rw, new_si->shr_access_rw, 803 sizeof (si->shr_access_rw)); 804 805 smb_shr_cache_unlock(); 806 807 if (smb_shr_encode(si, &shrlist) == 0) { 808 (void) smb_kmod_unshare(shrlist); 809 nvlist_free(shrlist); 810 811 if (smb_shr_encode(new_si, &shrlist) == 0) { 812 (void) smb_kmod_share(shrlist); 813 nvlist_free(shrlist); 814 } 815 } 816 817 if (adc_changed) { 818 smb_shr_unpublish(old_si.shr_name, old_si.shr_container); 819 smb_shr_publish(new_si->shr_name, new_si->shr_container); 820 } 821 822 /* The following required privileges we dropped. */ 823 if (quota_flag_changed && smb_proc_takesem() == 0) { 824 825 (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, 826 PRIV_FILE_DAC_READ, 827 PRIV_FILE_DAC_SEARCH, 828 PRIV_FILE_DAC_WRITE, 829 NULL); 830 831 smb_shr_zfs_remove(&old_si); 832 smb_shr_zfs_add(si); 833 834 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, 835 PRIV_FILE_DAC_READ, 836 PRIV_FILE_DAC_SEARCH, 837 PRIV_FILE_DAC_WRITE, 838 NULL); 839 840 smb_proc_givesem(); 841 } 842 843 return (NERR_Success); 844 } 845 846 /* 847 * smb_shr_exists 848 * 849 * Returns B_TRUE if the share exists. Otherwise returns B_FALSE 850 */ 851 boolean_t 852 smb_shr_exists(char *sharename) 853 { 854 boolean_t exists = B_FALSE; 855 856 if (sharename == NULL || *sharename == '\0') 857 return (B_FALSE); 858 859 if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 860 exists = (smb_shr_cache_findent(sharename) != NULL); 861 smb_shr_cache_unlock(); 862 } 863 864 return (exists); 865 } 866 867 /* 868 * If the shared directory does not begin with a /, one will be 869 * inserted as a prefix. If ipaddr is not zero, then also return 870 * information about access based on the host level access lists, if 871 * present. Also return access check if there is an IP address and 872 * shr_accflags. 873 * 874 * The value of smb_chk_hostaccess is checked for an access match. 875 * -1 is wildcard match 876 * 0 is no match 877 * 1 is match 878 * 879 * Precedence is none is checked first followed by ro then rw if 880 * needed. If x is wildcard (< 0) then check to see if the other 881 * values are a match. If a match, that wins. 882 */ 883 uint32_t 884 smb_shr_hostaccess(smb_inaddr_t *ipaddr, char *none_list, char *ro_list, 885 char *rw_list, uint32_t flag) 886 { 887 uint32_t acc = SMB_SHRF_ACC_NONE; 888 int none = 0; 889 int ro = 0; 890 int rw = 0; 891 892 if (!smb_inet_iszero(ipaddr)) { 893 if ((flag & SMB_SHRF_ACC_NONE) != 0) 894 none = smb_chk_hostaccess(ipaddr, none_list); 895 if ((flag & SMB_SHRF_ACC_RO) != 0) 896 ro = smb_chk_hostaccess(ipaddr, ro_list); 897 if ((flag & SMB_SHRF_ACC_RW) != 0) 898 rw = smb_chk_hostaccess(ipaddr, rw_list); 899 900 /* make first pass to get basic value */ 901 if (none != 0) 902 acc = SMB_SHRF_ACC_NONE; 903 else if (ro != 0) 904 acc = SMB_SHRF_ACC_RO; 905 else if (rw != 0) 906 acc = SMB_SHRF_ACC_RW; 907 908 /* make second pass to handle '*' case */ 909 if (none < 0) { 910 acc = SMB_SHRF_ACC_NONE; 911 if (ro > 0) 912 acc = SMB_SHRF_ACC_RO; 913 else if (rw > 0) 914 acc = SMB_SHRF_ACC_RW; 915 } else if (ro < 0) { 916 acc = SMB_SHRF_ACC_RO; 917 if (none > 0) 918 acc = SMB_SHRF_ACC_NONE; 919 else if (rw > 0) 920 acc = SMB_SHRF_ACC_RW; 921 } else if (rw < 0) { 922 acc = SMB_SHRF_ACC_RW; 923 if (none > 0) 924 acc = SMB_SHRF_ACC_NONE; 925 else if (ro > 0) 926 acc = SMB_SHRF_ACC_RO; 927 } 928 } 929 930 return (acc); 931 } 932 933 /* 934 * smb_shr_is_special 935 * 936 * Special share reserved for interprocess communication (IPC$) or 937 * remote administration of the server (ADMIN$). Can also refer to 938 * administrative shares such as C$, D$, E$, and so forth. 939 */ 940 int 941 smb_shr_is_special(char *sharename) 942 { 943 int len; 944 945 if (sharename == NULL) 946 return (0); 947 948 if ((len = strlen(sharename)) == 0) 949 return (0); 950 951 if (sharename[len - 1] == '$') 952 return (STYPE_SPECIAL); 953 954 return (0); 955 } 956 957 /* 958 * smb_shr_is_restricted 959 * 960 * Check whether or not there is a restriction on a share. Restricted 961 * shares are generally STYPE_SPECIAL, for example, IPC$. All the 962 * administration share names are restricted: C$, D$ etc. Returns B_TRUE 963 * if the share is restricted. Otherwise B_FALSE is returned to indicate 964 * that there are no restrictions. 965 */ 966 boolean_t 967 smb_shr_is_restricted(char *sharename) 968 { 969 static char *restricted[] = { 970 "IPC$" 971 }; 972 973 int i; 974 975 if (sharename == NULL) 976 return (B_FALSE); 977 978 for (i = 0; i < sizeof (restricted)/sizeof (restricted[0]); i++) { 979 if (smb_strcasecmp(restricted[i], sharename, 0) == 0) 980 return (B_TRUE); 981 } 982 983 return (smb_shr_is_admin(sharename)); 984 } 985 986 /* 987 * smb_shr_is_admin 988 * 989 * Check whether or not access to the share should be restricted to 990 * administrators. This is a bit of a hack because what we're doing 991 * is checking for the default admin shares: C$, D$ etc.. There are 992 * other shares that have restrictions: see smb_shr_is_restricted(). 993 * 994 * Returns B_TRUE if the shares is an admin share. Otherwise B_FALSE 995 * is returned to indicate that there are no restrictions. 996 */ 997 boolean_t 998 smb_shr_is_admin(char *sharename) 999 { 1000 if (sharename == NULL) 1001 return (B_FALSE); 1002 1003 if (strlen(sharename) == 2 && 1004 smb_isalpha(sharename[0]) && sharename[1] == '$') { 1005 return (B_TRUE); 1006 } 1007 1008 return (B_FALSE); 1009 } 1010 1011 char 1012 smb_shr_drive_letter(const char *path) 1013 { 1014 smb_transient_t *ts; 1015 int i; 1016 1017 if (path == NULL) 1018 return ('\0'); 1019 1020 for (i = 0; i < sizeof (tshare)/sizeof (tshare[0]); ++i) { 1021 ts = &tshare[i]; 1022 1023 if (ts->path == NULL) 1024 continue; 1025 1026 if (strcasecmp(ts->path, path) == 0) 1027 return (ts->drive); 1028 } 1029 1030 return ('\0'); 1031 } 1032 1033 /* 1034 * Returns true if the specified directory is empty, 1035 * otherwise returns false. 1036 */ 1037 static boolean_t 1038 smb_shr_is_empty(const char *path) 1039 { 1040 DIR *dirp; 1041 struct dirent *dp; 1042 1043 if (path == NULL) 1044 return (B_TRUE); 1045 1046 if ((dirp = opendir(path)) == NULL) 1047 return (B_TRUE); 1048 1049 while ((dp = readdir(dirp)) != NULL) { 1050 if (!smb_shr_is_dot_or_dotdot(dp->d_name)) 1051 return (B_FALSE); 1052 } 1053 1054 (void) closedir(dirp); 1055 return (B_TRUE); 1056 } 1057 1058 /* 1059 * Returns true if name is "." or "..", otherwise returns false. 1060 */ 1061 static boolean_t 1062 smb_shr_is_dot_or_dotdot(const char *name) 1063 { 1064 if (*name != '.') 1065 return (B_FALSE); 1066 1067 if ((name[1] == '\0') || (name[1] == '.' && name[2] == '\0')) 1068 return (B_TRUE); 1069 1070 return (B_FALSE); 1071 } 1072 1073 /* 1074 * smb_shr_get_realpath 1075 * 1076 * Derive the real path for a share from the path provided by a client. 1077 * For instance, the real path of C:\ may be /cvol or the real path of 1078 * F:\home may be /vol1/home. 1079 * 1080 * clntpath - path provided by the Windows client is in the 1081 * format of <drive letter>:\<dir> 1082 * realpath - path that will be stored as the directory field of 1083 * the smb_share_t structure of the share. 1084 * maxlen - maximum length of the realpath buffer 1085 * 1086 * Return LAN Manager network error code. 1087 */ 1088 uint32_t 1089 smb_shr_get_realpath(const char *clntpath, char *realpath, int maxlen) 1090 { 1091 const char *p; 1092 int len; 1093 1094 if ((p = strchr(clntpath, ':')) != NULL) 1095 ++p; 1096 else 1097 p = clntpath; 1098 1099 (void) strlcpy(realpath, p, maxlen); 1100 (void) strcanon(realpath, "/\\"); 1101 (void) strsubst(realpath, '\\', '/'); 1102 1103 len = strlen(realpath); 1104 if ((len > 1) && (realpath[len - 1] == '/')) 1105 realpath[len - 1] = '\0'; 1106 1107 return (NERR_Success); 1108 } 1109 1110 void 1111 smb_shr_list(int offset, smb_shrlist_t *list) 1112 { 1113 smb_shriter_t iterator; 1114 smb_share_t *si; 1115 int n = 0; 1116 1117 bzero(list, sizeof (smb_shrlist_t)); 1118 smb_shr_iterinit(&iterator); 1119 1120 while ((si = smb_shr_iterate(&iterator)) != NULL) { 1121 if (--offset > 0) 1122 continue; 1123 1124 if ((si->shr_flags & SMB_SHRF_TRANS) && 1125 (!STYPE_ISIPC(si->shr_type))) { 1126 bcopy(si, &list->sl_shares[n], sizeof (smb_share_t)); 1127 if (++n == LMSHARES_PER_REQUEST) 1128 break; 1129 } 1130 } 1131 1132 list->sl_cnt = n; 1133 } 1134 1135 /* 1136 * Executes the map/unmap command associated with a share. 1137 * 1138 * Returns 0 on success. Otherwise non-zero for errors. 1139 */ 1140 int 1141 smb_shr_exec(smb_shr_execinfo_t *subs) 1142 { 1143 char cmd[MAXPATHLEN], **cmd_tokens, *path, *ptr; 1144 pid_t child_pid; 1145 int child_status; 1146 struct sigaction pact, cact; 1147 smb_share_t si; 1148 1149 if (smb_shr_get(subs->e_sharename, &si) != 0) 1150 return (-1); 1151 1152 *cmd = '\0'; 1153 1154 (void) mutex_lock(&smb_shr_exec_mtx); 1155 1156 switch (subs->e_type) { 1157 case SMB_EXEC_MAP: 1158 (void) strlcpy(cmd, smb_shr_exec_map, sizeof (cmd)); 1159 break; 1160 case SMB_EXEC_UNMAP: 1161 (void) strlcpy(cmd, smb_shr_exec_unmap, sizeof (cmd)); 1162 break; 1163 default: 1164 (void) mutex_unlock(&smb_shr_exec_mtx); 1165 return (-1); 1166 } 1167 1168 (void) mutex_unlock(&smb_shr_exec_mtx); 1169 1170 if (*cmd == '\0') 1171 return (0); 1172 1173 if (smb_proc_takesem() != 0) 1174 return (-1); 1175 1176 pact.sa_handler = smb_shr_sig_child; 1177 pact.sa_flags = 0; 1178 (void) sigemptyset(&pact.sa_mask); 1179 sigaction(SIGCHLD, &pact, NULL); 1180 1181 (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL); 1182 1183 if ((child_pid = fork()) == -1) { 1184 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL); 1185 smb_proc_givesem(); 1186 return (-1); 1187 } 1188 1189 if (child_pid == 0) { 1190 1191 /* child process */ 1192 1193 cact.sa_handler = smb_shr_sig_abnormal_term; 1194 cact.sa_flags = 0; 1195 (void) sigemptyset(&cact.sa_mask); 1196 sigaction(SIGTERM, &cact, NULL); 1197 sigaction(SIGABRT, &cact, NULL); 1198 sigaction(SIGSEGV, &cact, NULL); 1199 1200 if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_EXEC, 1201 PRIV_FILE_DAC_EXECUTE, NULL)) 1202 _exit(-1); 1203 1204 if (smb_shr_enable_all_privs()) 1205 _exit(-1); 1206 1207 smb_proc_initsem(); 1208 1209 (void) trim_whitespace(cmd); 1210 (void) strcanon(cmd, " "); 1211 1212 if ((cmd_tokens = smb_shr_tokenize_cmd(cmd)) != NULL) { 1213 1214 if (smb_shr_expand_subs(cmd_tokens, &si, subs) != 0) { 1215 free(cmd_tokens[0]); 1216 free(cmd_tokens); 1217 _exit(-1); 1218 } 1219 1220 ptr = cmd; 1221 path = strsep(&ptr, " "); 1222 1223 (void) execv(path, cmd_tokens); 1224 } 1225 1226 _exit(-1); 1227 } 1228 1229 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL); 1230 smb_proc_givesem(); 1231 1232 /* parent process */ 1233 1234 while (waitpid(child_pid, &child_status, 0) < 0) { 1235 if (errno != EINTR) 1236 break; 1237 1238 /* continue if waitpid got interrupted by a signal */ 1239 errno = 0; 1240 continue; 1241 } 1242 1243 if (WIFEXITED(child_status)) 1244 return (WEXITSTATUS(child_status)); 1245 1246 return (child_status); 1247 } 1248 1249 /* 1250 * Locking for process-wide settings (i.e. privileges) 1251 */ 1252 void 1253 smb_proc_initsem(void) 1254 { 1255 (void) sema_init(&smb_proc_sem, 1, USYNC_THREAD, NULL); 1256 } 1257 1258 int 1259 smb_proc_takesem(void) 1260 { 1261 return (sema_wait(&smb_proc_sem)); 1262 } 1263 1264 void 1265 smb_proc_givesem(void) 1266 { 1267 (void) sema_post(&smb_proc_sem); 1268 } 1269 1270 /* 1271 * ============================================ 1272 * Private helper/utility functions 1273 * ============================================ 1274 */ 1275 1276 /* 1277 * Looks up the given share in the cache and return 1278 * the info in 'si' 1279 */ 1280 static uint32_t 1281 smb_shr_lookup(char *sharename, smb_share_t *si) 1282 { 1283 smb_share_t *cached_si; 1284 uint32_t status = NERR_NetNameNotFound; 1285 1286 if (sharename == NULL || *sharename == '\0') 1287 return (NERR_NetNameNotFound); 1288 if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 1289 cached_si = smb_shr_cache_findent(sharename); 1290 if (cached_si != NULL) { 1291 bcopy(cached_si, si, sizeof (smb_share_t)); 1292 status = NERR_Success; 1293 } 1294 1295 smb_shr_cache_unlock(); 1296 } 1297 return (status); 1298 } 1299 1300 /* 1301 * Add IPC$ or Admin shares to the cache upon startup. 1302 */ 1303 static uint32_t 1304 smb_shr_add_transient(char *name, char *cmnt, char *path) 1305 { 1306 smb_share_t trans; 1307 uint32_t status = NERR_InternalError; 1308 1309 if (name == NULL) 1310 return (status); 1311 1312 bzero(&trans, sizeof (smb_share_t)); 1313 (void) strlcpy(trans.shr_name, name, MAXNAMELEN); 1314 if (cmnt) 1315 (void) strlcpy(trans.shr_cmnt, cmnt, SMB_SHARE_CMNT_MAX); 1316 1317 if (path) 1318 (void) strlcpy(trans.shr_path, path, MAXPATHLEN); 1319 1320 if (strcasecmp(name, "IPC$") == 0) 1321 trans.shr_type = STYPE_IPC; 1322 1323 trans.shr_flags = SMB_SHRF_TRANS; 1324 1325 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) { 1326 status = smb_shr_cache_addent(&trans); 1327 smb_shr_cache_unlock(); 1328 } 1329 1330 return (status); 1331 } 1332 1333 /* 1334 * ============================================ 1335 * Cache management functions 1336 * 1337 * All cache functions are private 1338 * ============================================ 1339 */ 1340 1341 /* 1342 * Create the share cache (hash table). 1343 */ 1344 static uint32_t 1345 smb_shr_cache_create(void) 1346 { 1347 uint32_t status = NERR_Success; 1348 1349 (void) mutex_lock(&smb_shr_cache.sc_mtx); 1350 switch (smb_shr_cache.sc_state) { 1351 case SMB_SHR_CACHE_STATE_NONE: 1352 smb_shr_cache.sc_cache = ht_create_table(SMB_SHR_HTAB_SZ, 1353 MAXNAMELEN, 0); 1354 if (smb_shr_cache.sc_cache == NULL) { 1355 status = NERR_InternalError; 1356 break; 1357 } 1358 1359 (void) ht_register_callback(smb_shr_cache.sc_cache, 1360 smb_shr_cache_freent); 1361 smb_shr_cache.sc_nops = 0; 1362 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_CREATED; 1363 break; 1364 1365 default: 1366 assert(0); 1367 status = NERR_InternalError; 1368 break; 1369 } 1370 (void) mutex_unlock(&smb_shr_cache.sc_mtx); 1371 1372 return (status); 1373 } 1374 1375 /* 1376 * Destroy the share cache (hash table). 1377 * Wait for inflight/pending operations to finish or abort before 1378 * destroying the cache. 1379 */ 1380 static void 1381 smb_shr_cache_destroy(void) 1382 { 1383 (void) mutex_lock(&smb_shr_cache.sc_mtx); 1384 if (smb_shr_cache.sc_state == SMB_SHR_CACHE_STATE_CREATED) { 1385 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_DESTROYING; 1386 while (smb_shr_cache.sc_nops > 0) 1387 (void) cond_wait(&smb_shr_cache.sc_cv, 1388 &smb_shr_cache.sc_mtx); 1389 1390 smb_shr_cache.sc_cache = NULL; 1391 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_NONE; 1392 } 1393 (void) mutex_unlock(&smb_shr_cache.sc_mtx); 1394 } 1395 1396 /* 1397 * If the cache is in "created" state, lock the cache for read 1398 * or read/write based on the specified mode. 1399 * 1400 * Whenever a lock is granted, the number of inflight cache 1401 * operations is incremented. 1402 */ 1403 static uint32_t 1404 smb_shr_cache_lock(int mode) 1405 { 1406 (void) mutex_lock(&smb_shr_cache.sc_mtx); 1407 if (smb_shr_cache.sc_state != SMB_SHR_CACHE_STATE_CREATED) { 1408 (void) mutex_unlock(&smb_shr_cache.sc_mtx); 1409 return (NERR_InternalError); 1410 } 1411 smb_shr_cache.sc_nops++; 1412 (void) mutex_unlock(&smb_shr_cache.sc_mtx); 1413 1414 /* 1415 * Lock has to be taken outside the mutex otherwise 1416 * there could be a deadlock 1417 */ 1418 if (mode == SMB_SHR_CACHE_RDLOCK) 1419 (void) rw_rdlock(&smb_shr_cache.sc_cache_lck); 1420 else 1421 (void) rw_wrlock(&smb_shr_cache.sc_cache_lck); 1422 1423 return (NERR_Success); 1424 } 1425 1426 /* 1427 * Decrement the number of inflight operations and then unlock. 1428 */ 1429 static void 1430 smb_shr_cache_unlock(void) 1431 { 1432 (void) mutex_lock(&smb_shr_cache.sc_mtx); 1433 assert(smb_shr_cache.sc_nops > 0); 1434 smb_shr_cache.sc_nops--; 1435 (void) cond_broadcast(&smb_shr_cache.sc_cv); 1436 (void) mutex_unlock(&smb_shr_cache.sc_mtx); 1437 1438 (void) rw_unlock(&smb_shr_cache.sc_cache_lck); 1439 } 1440 1441 /* 1442 * Return the total number of shares 1443 */ 1444 static int 1445 smb_shr_cache_count(void) 1446 { 1447 return (ht_get_total_items(smb_shr_cache.sc_cache)); 1448 } 1449 1450 /* 1451 * looks up the given share name in the cache and if it 1452 * finds a match returns a pointer to the cached entry. 1453 * Note that since a pointer is returned this function 1454 * MUST be protected by smb_shr_cache_lock/unlock pair 1455 */ 1456 static smb_share_t * 1457 smb_shr_cache_findent(char *sharename) 1458 { 1459 HT_ITEM *item; 1460 1461 (void) smb_strlwr(sharename); 1462 item = ht_find_item(smb_shr_cache.sc_cache, sharename); 1463 if (item && item->hi_data) 1464 return ((smb_share_t *)item->hi_data); 1465 1466 return (NULL); 1467 } 1468 1469 /* 1470 * Return a pointer to the first/next entry in 1471 * the cache based on the given iterator. 1472 * 1473 * Calls to this function MUST be protected by 1474 * smb_shr_cache_lock/unlock. 1475 */ 1476 static smb_share_t * 1477 smb_shr_cache_iterate(smb_shriter_t *shi) 1478 { 1479 HT_ITEM *item; 1480 1481 if (shi->si_first) { 1482 item = ht_findfirst(smb_shr_cache.sc_cache, &shi->si_hashiter); 1483 shi->si_first = B_FALSE; 1484 } else { 1485 item = ht_findnext(&shi->si_hashiter); 1486 } 1487 1488 if (item && item->hi_data) 1489 return ((smb_share_t *)item->hi_data); 1490 1491 return (NULL); 1492 } 1493 1494 /* 1495 * Add the specified share to the cache. Memory needs to be allocated 1496 * for the cache entry and the passed information is copied to the 1497 * allocated space. 1498 */ 1499 static uint32_t 1500 smb_shr_cache_addent(smb_share_t *si) 1501 { 1502 smb_share_t *cache_ent; 1503 uint32_t status = NERR_Success; 1504 1505 if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL) 1506 return (ERROR_NOT_ENOUGH_MEMORY); 1507 1508 (void) smb_strlwr(si->shr_name); 1509 1510 si->shr_type |= smb_shr_is_special(cache_ent->shr_name); 1511 1512 if (smb_shr_is_admin(cache_ent->shr_name)) 1513 si->shr_flags |= SMB_SHRF_ADMIN; 1514 1515 bcopy(si, cache_ent, sizeof (smb_share_t)); 1516 1517 if (si->shr_flags & SMB_SHRF_AUTOHOME) 1518 cache_ent->shr_refcnt = 1; 1519 1520 if (ht_add_item(smb_shr_cache.sc_cache, cache_ent->shr_name, cache_ent) 1521 == NULL) { 1522 syslog(LOG_DEBUG, "share: %s: cache update failed", 1523 cache_ent->shr_name); 1524 free(cache_ent); 1525 status = NERR_InternalError; 1526 } 1527 1528 return (status); 1529 } 1530 1531 /* 1532 * Delete the specified share from the cache. 1533 */ 1534 static void 1535 smb_shr_cache_delent(char *sharename) 1536 { 1537 (void) smb_strlwr(sharename); 1538 (void) ht_remove_item(smb_shr_cache.sc_cache, sharename); 1539 } 1540 1541 /* 1542 * Call back to free the given cache entry. 1543 */ 1544 static void 1545 smb_shr_cache_freent(HT_ITEM *item) 1546 { 1547 if (item && item->hi_data) 1548 free(item->hi_data); 1549 } 1550 1551 /* 1552 * ============================================ 1553 * Interfaces to sharemgr 1554 * 1555 * All functions in this section are private 1556 * ============================================ 1557 */ 1558 1559 /* 1560 * Loads the SMB shares, from sharemgr, then: 1561 * - calls smb_shr_add which: 1562 * - adds the share into the share cache 1563 * - adds the share into in-kernel kshare table 1564 * - publishes the share in ADS 1565 * - updates the share list in sharefs/sharetab 1566 */ 1567 /*ARGSUSED*/ 1568 void * 1569 smb_shr_load(void *args) 1570 { 1571 sa_handle_t handle; 1572 sa_group_t group, subgroup; 1573 char *gstate; 1574 boolean_t gdisabled; 1575 1576 smb_shr_load_execinfo(); 1577 1578 if ((handle = smb_shr_sa_enter()) == NULL) { 1579 syslog(LOG_ERR, "smb_shr_load: load failed"); 1580 return (NULL); 1581 } 1582 1583 for (group = sa_get_group(handle, NULL); 1584 group != NULL; group = sa_get_next_group(group)) { 1585 gstate = sa_get_group_attr(group, "state"); 1586 if (gstate == NULL) 1587 continue; 1588 1589 gdisabled = (strcasecmp(gstate, "disabled") == 0); 1590 sa_free_attr_string(gstate); 1591 if (gdisabled) 1592 continue; 1593 1594 smb_shr_sa_loadgrp(group); 1595 1596 for (subgroup = sa_get_sub_group(group); 1597 subgroup != NULL; 1598 subgroup = sa_get_next_group(subgroup)) { 1599 smb_shr_sa_loadgrp(subgroup); 1600 } 1601 1602 } 1603 smb_shr_sa_exit(); 1604 return (NULL); 1605 } 1606 1607 void 1608 smb_shr_load_execinfo() 1609 { 1610 (void) mutex_lock(&smb_shr_exec_mtx); 1611 (void) smb_config_get_execinfo(smb_shr_exec_map, smb_shr_exec_unmap, 1612 MAXPATHLEN); 1613 (void) mutex_unlock(&smb_shr_exec_mtx); 1614 } 1615 1616 /* 1617 * Handles disabling shares in sharefs when stoping smbd 1618 */ 1619 void 1620 smb_shr_unload() 1621 { 1622 smb_shriter_t iterator; 1623 smb_share_t *si; 1624 sa_handle_t handle; 1625 int rc; 1626 1627 if ((handle = smb_shr_sa_enter()) == NULL) { 1628 syslog(LOG_ERR, "smb_shr_unload: failed"); 1629 return; 1630 } 1631 1632 smb_shr_iterinit(&iterator); 1633 1634 while ((si = smb_shr_iterate(&iterator)) != NULL) { 1635 1636 /* Skip transient shares, IPC$, ... */ 1637 if ((si->shr_flags & SMB_SHRF_TRANS) || 1638 STYPE_ISIPC(si->shr_type)) 1639 continue; 1640 1641 rc = sa_delete_sharetab(handle, si->shr_path, "smb"); 1642 if (rc) { 1643 syslog(LOG_ERR, 1644 "sharefs remove %s failed, rc=%d, err=%d", 1645 si->shr_path, rc, errno); 1646 } 1647 } 1648 smb_shr_sa_exit(); 1649 } 1650 1651 /* 1652 * Load the shares contained in the specified group. 1653 * 1654 * Don't process groups on which the smb protocol is disabled. 1655 * The top level ZFS group won't have the smb protocol enabled 1656 * but sub-groups will. 1657 * 1658 * We will tolerate a limited number of errors and then give 1659 * up on the current group. A typical error might be that the 1660 * shared directory no longer exists. 1661 */ 1662 static void 1663 smb_shr_sa_loadgrp(sa_group_t group) 1664 { 1665 sa_share_t share; 1666 sa_resource_t resource; 1667 int error_count = 0; 1668 1669 if (sa_get_optionset(group, SMB_PROTOCOL_NAME) == NULL) 1670 return; 1671 1672 for (share = sa_get_share(group, NULL); 1673 share != NULL; 1674 share = sa_get_next_share(share)) { 1675 for (resource = sa_get_share_resource(share, NULL); 1676 resource != NULL; 1677 resource = sa_get_next_resource(resource)) { 1678 if (smb_shr_sa_load(share, resource)) 1679 ++error_count; 1680 1681 if (error_count > SMB_SHR_ERROR_THRESHOLD) 1682 break; 1683 } 1684 1685 if (error_count > SMB_SHR_ERROR_THRESHOLD) 1686 break; 1687 } 1688 } 1689 1690 /* 1691 * Load a share definition from sharemgr and add it to the cache. 1692 * If the share is already in the cache then it doesn't do anything. 1693 * 1694 * This function does not report duplicate shares as error since 1695 * a share might have been added by smb_shr_get() while load is 1696 * in progress. 1697 */ 1698 static uint32_t 1699 smb_shr_sa_load(sa_share_t share, sa_resource_t resource) 1700 { 1701 smb_share_t si; 1702 char *sharename; 1703 uint32_t status; 1704 boolean_t loaded; 1705 int rc; 1706 1707 if ((sharename = sa_get_resource_attr(resource, "name")) == NULL) 1708 return (NERR_InternalError); 1709 1710 loaded = smb_shr_exists(sharename); 1711 sa_free_attr_string(sharename); 1712 1713 if (loaded) 1714 return (NERR_Success); 1715 1716 if ((status = smb_shr_sa_get(share, resource, &si)) != NERR_Success) { 1717 syslog(LOG_DEBUG, "share: failed to load %s (%d)", 1718 si.shr_name, status); 1719 return (status); 1720 } 1721 1722 status = smb_shr_add(&si); 1723 if ((status != NERR_Success) && (status != NERR_DuplicateShare)) { 1724 syslog(LOG_DEBUG, "share: failed to cache %s (%d)", 1725 si.shr_name, status); 1726 return (status); 1727 } 1728 1729 rc = sa_update_sharetab(share, "smb"); 1730 if (rc) { 1731 syslog(LOG_ERR, "sharefs add %s failed, rc=%d, err=%d", 1732 sharename, rc, errno); 1733 } 1734 1735 return (NERR_Success); 1736 } 1737 1738 static char * 1739 smb_shr_sa_getprop(sa_optionset_t opts, char *propname) 1740 { 1741 sa_property_t prop; 1742 char *val = NULL; 1743 1744 prop = sa_get_property(opts, propname); 1745 if (prop != NULL) 1746 val = sa_get_property_attr(prop, "value"); 1747 1748 return (val); 1749 } 1750 1751 /* 1752 * Read the specified share information from sharemgr and return 1753 * it in the given smb_share_t structure. 1754 * 1755 * Shares read from sharemgr are marked as permanent/persistent. 1756 */ 1757 static uint32_t 1758 smb_shr_sa_get(sa_share_t share, sa_resource_t resource, smb_share_t *si) 1759 { 1760 sa_optionset_t opts; 1761 char *val = NULL; 1762 char *path; 1763 char *rname; 1764 1765 if ((path = sa_get_share_attr(share, "path")) == NULL) 1766 return (NERR_InternalError); 1767 1768 if ((rname = sa_get_resource_attr(resource, "name")) == NULL) { 1769 sa_free_attr_string(path); 1770 return (NERR_InternalError); 1771 } 1772 1773 bzero(si, sizeof (smb_share_t)); 1774 si->shr_flags = SMB_SHRF_PERM; 1775 1776 (void) strlcpy(si->shr_path, path, sizeof (si->shr_path)); 1777 (void) strlcpy(si->shr_name, rname, sizeof (si->shr_name)); 1778 sa_free_attr_string(path); 1779 sa_free_attr_string(rname); 1780 1781 val = sa_get_resource_description(resource); 1782 if (val == NULL) 1783 val = sa_get_share_description(share); 1784 1785 if (val != NULL) { 1786 (void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt)); 1787 sa_free_share_description(val); 1788 } 1789 1790 opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1); 1791 if (opts == NULL) 1792 return (NERR_Success); 1793 1794 val = smb_shr_sa_getprop(opts, SHOPT_AD_CONTAINER); 1795 if (val != NULL) { 1796 (void) strlcpy(si->shr_container, val, 1797 sizeof (si->shr_container)); 1798 free(val); 1799 } 1800 1801 val = smb_shr_sa_getprop(opts, SHOPT_CATIA); 1802 if (val != NULL) { 1803 smb_shr_sa_setflag(val, si, SMB_SHRF_CATIA); 1804 free(val); 1805 } 1806 1807 val = smb_shr_sa_getprop(opts, SHOPT_ABE); 1808 if (val != NULL) { 1809 smb_shr_sa_setflag(val, si, SMB_SHRF_ABE); 1810 free(val); 1811 } 1812 1813 val = smb_shr_sa_getprop(opts, SHOPT_GUEST); 1814 if (val != NULL) { 1815 smb_shr_sa_setflag(val, si, SMB_SHRF_GUEST_OK); 1816 free(val); 1817 } 1818 1819 val = smb_shr_sa_getprop(opts, SHOPT_DFSROOT); 1820 if (val != NULL) { 1821 smb_shr_sa_setflag(val, si, SMB_SHRF_DFSROOT); 1822 free(val); 1823 } 1824 1825 val = smb_shr_sa_getprop(opts, SHOPT_FSO); 1826 if (val != NULL) { 1827 smb_shr_sa_setflag(val, si, SMB_SHRF_FSO); 1828 free(val); 1829 } 1830 1831 val = smb_shr_sa_getprop(opts, SHOPT_QUOTAS); 1832 if (val != NULL) { 1833 /* Turn the flag on or off */ 1834 smb_shr_sa_setflag(val, si, SMB_SHRF_QUOTAS); 1835 free(val); 1836 } else { 1837 /* Default for this is enabled. */ 1838 si->shr_flags |= SMB_SHRF_QUOTAS; 1839 } 1840 1841 val = smb_shr_sa_getprop(opts, SHOPT_ENCRYPT); 1842 if (val != NULL) { 1843 smb_cfg_set_require(val, &si->shr_encrypt); 1844 free(val); 1845 } 1846 1847 val = smb_shr_sa_getprop(opts, SHOPT_CSC); 1848 if (val != NULL) { 1849 smb_shr_sa_csc_option(val, si); 1850 free(val); 1851 } 1852 1853 val = smb_shr_sa_getprop(opts, SHOPT_NONE); 1854 if (val != NULL) { 1855 (void) strlcpy(si->shr_access_none, val, 1856 sizeof (si->shr_access_none)); 1857 free(val); 1858 si->shr_flags |= SMB_SHRF_ACC_NONE; 1859 } 1860 1861 val = smb_shr_sa_getprop(opts, SHOPT_RO); 1862 if (val != NULL) { 1863 (void) strlcpy(si->shr_access_ro, val, 1864 sizeof (si->shr_access_ro)); 1865 free(val); 1866 si->shr_flags |= SMB_SHRF_ACC_RO; 1867 } 1868 1869 val = smb_shr_sa_getprop(opts, SHOPT_RW); 1870 if (val != NULL) { 1871 (void) strlcpy(si->shr_access_rw, val, 1872 sizeof (si->shr_access_rw)); 1873 free(val); 1874 si->shr_flags |= SMB_SHRF_ACC_RW; 1875 } 1876 1877 sa_free_derived_optionset(opts); 1878 return (NERR_Success); 1879 } 1880 1881 /* 1882 * Map a client-side caching (CSC) option to the appropriate share 1883 * flag. Only one option is allowed; an error will be logged if 1884 * multiple options have been specified. We don't need to do anything 1885 * about multiple values here because the SRVSVC will not recognize 1886 * a value containing multiple flags and will return the default value. 1887 * 1888 * If the option value is not recognized, it will be ignored: invalid 1889 * values will typically be caught and rejected by sharemgr. 1890 */ 1891 void 1892 smb_shr_sa_csc_option(const char *value, smb_share_t *si) 1893 { 1894 int i; 1895 1896 for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) { 1897 if (strcasecmp(value, cscopt[i].value) == 0) { 1898 si->shr_flags |= cscopt[i].flag; 1899 break; 1900 } 1901 } 1902 1903 switch (si->shr_flags & SMB_SHRF_CSC_MASK) { 1904 case 0: 1905 case SMB_SHRF_CSC_DISABLED: 1906 case SMB_SHRF_CSC_MANUAL: 1907 case SMB_SHRF_CSC_AUTO: 1908 case SMB_SHRF_CSC_VDO: 1909 break; 1910 1911 default: 1912 syslog(LOG_INFO, "csc option conflict: 0x%08x", 1913 si->shr_flags & SMB_SHRF_CSC_MASK); 1914 break; 1915 } 1916 } 1917 1918 /* 1919 * Return the option name for the first CSC flag (there should be only 1920 * one) encountered in the share flags. 1921 */ 1922 char * 1923 smb_shr_sa_csc_name(const smb_share_t *si) 1924 { 1925 int i; 1926 1927 for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) { 1928 if (si->shr_flags & cscopt[i].flag) 1929 return (cscopt[i].value); 1930 } 1931 1932 return (NULL); 1933 } 1934 1935 /* 1936 * Takes the value of a boolean share property and set/clear the 1937 * specified flag based on the property's value. 1938 */ 1939 void 1940 smb_shr_sa_setflag(const char *value, smb_share_t *si, uint32_t flag) 1941 { 1942 if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0)) 1943 si->shr_flags |= flag; 1944 else 1945 si->shr_flags &= ~flag; 1946 } 1947 1948 /* 1949 * looks up sharemgr for the given share (resource) and loads 1950 * the definition into cache if lookup is successful 1951 */ 1952 static uint32_t 1953 smb_shr_sa_loadbyname(char *sharename) 1954 { 1955 sa_handle_t handle; 1956 sa_share_t share; 1957 sa_resource_t resource; 1958 uint32_t status; 1959 1960 if ((handle = smb_shr_sa_enter()) == NULL) 1961 return (NERR_InternalError); 1962 1963 resource = sa_find_resource(handle, sharename); 1964 if (resource == NULL) { 1965 smb_shr_sa_exit(); 1966 return (NERR_NetNameNotFound); 1967 } 1968 1969 share = sa_get_resource_parent(resource); 1970 if (share == NULL) { 1971 smb_shr_sa_exit(); 1972 return (NERR_InternalError); 1973 } 1974 1975 status = smb_shr_sa_load(share, resource); 1976 1977 smb_shr_sa_exit(); 1978 return (status); 1979 } 1980 1981 /* 1982 * ============================================ 1983 * Share publishing functions 1984 * 1985 * All the functions are private 1986 * ============================================ 1987 */ 1988 1989 static void 1990 smb_shr_publish(const char *sharename, const char *container) 1991 { 1992 smb_shr_publisher_queue(sharename, container, SMB_SHR_PUBLISH); 1993 } 1994 1995 static void 1996 smb_shr_unpublish(const char *sharename, const char *container) 1997 { 1998 smb_shr_publisher_queue(sharename, container, SMB_SHR_UNPUBLISH); 1999 } 2000 2001 /* 2002 * In domain mode, put a share on the publisher queue. 2003 * This is a no-op if the smb service is in Workgroup mode. 2004 */ 2005 static void 2006 smb_shr_publisher_queue(const char *sharename, const char *container, char op) 2007 { 2008 smb_shr_pitem_t *item = NULL; 2009 2010 if (container == NULL || *container == '\0') 2011 return; 2012 2013 if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 2014 return; 2015 2016 (void) mutex_lock(&ad_queue.spq_mtx); 2017 switch (ad_queue.spq_state) { 2018 case SMB_SHR_PQS_READY: 2019 case SMB_SHR_PQS_PUBLISHING: 2020 break; 2021 default: 2022 (void) mutex_unlock(&ad_queue.spq_mtx); 2023 return; 2024 } 2025 (void) mutex_unlock(&ad_queue.spq_mtx); 2026 2027 if ((item = malloc(sizeof (smb_shr_pitem_t))) == NULL) 2028 return; 2029 2030 item->spi_op = op; 2031 (void) strlcpy(item->spi_name, sharename, sizeof (item->spi_name)); 2032 (void) strlcpy(item->spi_container, container, 2033 sizeof (item->spi_container)); 2034 2035 (void) mutex_lock(&ad_queue.spq_mtx); 2036 list_insert_tail(&ad_queue.spq_list, item); 2037 (void) cond_signal(&ad_queue.spq_cv); 2038 (void) mutex_unlock(&ad_queue.spq_mtx); 2039 } 2040 2041 /* 2042 * Publishing won't be activated if the smb service is running in 2043 * Workgroup mode. 2044 */ 2045 static int 2046 smb_shr_publisher_start(void) 2047 { 2048 pthread_t publish_thr; 2049 pthread_attr_t tattr; 2050 int rc; 2051 2052 if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 2053 return (0); 2054 2055 (void) mutex_lock(&ad_queue.spq_mtx); 2056 if (ad_queue.spq_state != SMB_SHR_PQS_NOQUEUE) { 2057 (void) mutex_unlock(&ad_queue.spq_mtx); 2058 errno = EINVAL; 2059 return (-1); 2060 } 2061 2062 list_create(&ad_queue.spq_list, sizeof (smb_shr_pitem_t), 2063 offsetof(smb_shr_pitem_t, spi_lnd)); 2064 ad_queue.spq_state = SMB_SHR_PQS_READY; 2065 (void) mutex_unlock(&ad_queue.spq_mtx); 2066 2067 (void) pthread_attr_init(&tattr); 2068 (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 2069 rc = pthread_create(&publish_thr, &tattr, smb_shr_publisher, 0); 2070 (void) pthread_attr_destroy(&tattr); 2071 2072 return (rc); 2073 } 2074 2075 static void 2076 smb_shr_publisher_stop(void) 2077 { 2078 if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 2079 return; 2080 2081 (void) mutex_lock(&ad_queue.spq_mtx); 2082 switch (ad_queue.spq_state) { 2083 case SMB_SHR_PQS_READY: 2084 case SMB_SHR_PQS_PUBLISHING: 2085 ad_queue.spq_state = SMB_SHR_PQS_STOPPING; 2086 (void) cond_signal(&ad_queue.spq_cv); 2087 break; 2088 default: 2089 break; 2090 } 2091 (void) mutex_unlock(&ad_queue.spq_mtx); 2092 } 2093 2094 /* 2095 * This is the publisher daemon thread. While running, the thread waits 2096 * on a conditional variable until notified that a share needs to be 2097 * [un]published or that the thread should be terminated. 2098 * 2099 * Entries may remain in the outgoing queue if the Active Directory 2100 * service is inaccessible, in which case the thread wakes up every 60 2101 * seconds to retry. 2102 */ 2103 /*ARGSUSED*/ 2104 static void * 2105 smb_shr_publisher(void *arg) 2106 { 2107 smb_ads_handle_t *ah; 2108 smb_shr_pitem_t *shr; 2109 list_t publist; 2110 timestruc_t pubretry; 2111 char hostname[MAXHOSTNAMELEN]; 2112 2113 (void) mutex_lock(&ad_queue.spq_mtx); 2114 if (ad_queue.spq_state != SMB_SHR_PQS_READY) { 2115 (void) mutex_unlock(&ad_queue.spq_mtx); 2116 return (NULL); 2117 } 2118 ad_queue.spq_state = SMB_SHR_PQS_PUBLISHING; 2119 (void) mutex_unlock(&ad_queue.spq_mtx); 2120 2121 (void) smb_gethostname(hostname, MAXHOSTNAMELEN, 2122 SMB_CASE_PRESERVE); 2123 2124 list_create(&publist, sizeof (smb_shr_pitem_t), 2125 offsetof(smb_shr_pitem_t, spi_lnd)); 2126 2127 for (;;) { 2128 (void) mutex_lock(&ad_queue.spq_mtx); 2129 2130 while (list_is_empty(&ad_queue.spq_list) && 2131 (ad_queue.spq_state == SMB_SHR_PQS_PUBLISHING)) { 2132 if (list_is_empty(&publist)) { 2133 (void) cond_wait(&ad_queue.spq_cv, 2134 &ad_queue.spq_mtx); 2135 } else { 2136 pubretry.tv_sec = 60; 2137 pubretry.tv_nsec = 0; 2138 (void) cond_reltimedwait(&ad_queue.spq_cv, 2139 &ad_queue.spq_mtx, &pubretry); 2140 break; 2141 } 2142 } 2143 2144 if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) { 2145 (void) mutex_unlock(&ad_queue.spq_mtx); 2146 break; 2147 } 2148 2149 /* 2150 * Transfer queued items to the local list so that 2151 * the mutex can be released. 2152 */ 2153 while ((shr = list_head(&ad_queue.spq_list)) != NULL) { 2154 list_remove(&ad_queue.spq_list, shr); 2155 list_insert_tail(&publist, shr); 2156 } 2157 2158 (void) mutex_unlock(&ad_queue.spq_mtx); 2159 2160 if ((ah = smb_ads_open()) != NULL) { 2161 smb_shr_publisher_send(ah, &publist, hostname); 2162 smb_ads_close(ah); 2163 } 2164 } 2165 2166 (void) mutex_lock(&ad_queue.spq_mtx); 2167 smb_shr_publisher_flush(&ad_queue.spq_list); 2168 list_destroy(&ad_queue.spq_list); 2169 ad_queue.spq_state = SMB_SHR_PQS_NOQUEUE; 2170 (void) mutex_unlock(&ad_queue.spq_mtx); 2171 2172 smb_shr_publisher_flush(&publist); 2173 list_destroy(&publist); 2174 return (NULL); 2175 } 2176 2177 /* 2178 * Remove items from the specified queue and [un]publish them. 2179 */ 2180 static void 2181 smb_shr_publisher_send(smb_ads_handle_t *ah, list_t *publist, const char *host) 2182 { 2183 smb_shr_pitem_t *shr; 2184 2185 while ((shr = list_head(publist)) != NULL) { 2186 (void) mutex_lock(&ad_queue.spq_mtx); 2187 if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) { 2188 (void) mutex_unlock(&ad_queue.spq_mtx); 2189 return; 2190 } 2191 (void) mutex_unlock(&ad_queue.spq_mtx); 2192 2193 list_remove(publist, shr); 2194 2195 if (shr->spi_op == SMB_SHR_PUBLISH) 2196 (void) smb_ads_publish_share(ah, shr->spi_name, 2197 NULL, shr->spi_container, host); 2198 else 2199 (void) smb_ads_remove_share(ah, shr->spi_name, 2200 NULL, shr->spi_container, host); 2201 2202 free(shr); 2203 } 2204 } 2205 2206 /* 2207 * Flush all remaining items from the specified list/queue. 2208 */ 2209 static void 2210 smb_shr_publisher_flush(list_t *lst) 2211 { 2212 smb_shr_pitem_t *shr; 2213 2214 while ((shr = list_head(lst)) != NULL) { 2215 list_remove(lst, shr); 2216 free(shr); 2217 } 2218 } 2219 2220 /* 2221 * If the share path refers to a ZFS file system, add the 2222 * .zfs/shares/<share> object and add or remove the special 2223 * directory and file telling clients about quota support. 2224 */ 2225 static void 2226 smb_shr_zfs_add(smb_share_t *si) 2227 { 2228 libzfs_handle_t *libhd; 2229 zfs_handle_t *zfshd; 2230 int ret; 2231 char buf[MAXPATHLEN]; /* dataset or mountpoint */ 2232 2233 if (smb_getdataset(si->shr_path, buf, MAXPATHLEN) != 0) 2234 return; 2235 2236 if ((libhd = libzfs_init()) == NULL) 2237 return; 2238 2239 if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) { 2240 libzfs_fini(libhd); 2241 return; 2242 } 2243 2244 errno = 0; 2245 ret = zfs_smb_acl_add(libhd, buf, si->shr_path, si->shr_name); 2246 if (ret != 0 && errno != EAGAIN && errno != EEXIST) 2247 syslog(LOG_INFO, "share: failed to add ACL object: %s: %s\n", 2248 si->shr_name, strerror(errno)); 2249 2250 ret = zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, 2251 buf, MAXPATHLEN, NULL, NULL, 0, B_FALSE); 2252 if (ret != 0) { 2253 syslog(LOG_INFO, "share: failed to get mountpoint: " 2254 "%s\n", si->shr_name); 2255 } else { 2256 if ((si->shr_flags & SMB_SHRF_QUOTAS) != 0) { 2257 smb_quota_add_fs(buf); 2258 } else { 2259 smb_quota_remove_fs(buf); 2260 } 2261 } 2262 2263 zfs_close(zfshd); 2264 libzfs_fini(libhd); 2265 } 2266 2267 /* 2268 * If the share path refers to a ZFS file system, remove the 2269 * .zfs/shares/<share> object. 2270 */ 2271 static void 2272 smb_shr_zfs_remove(smb_share_t *si) 2273 { 2274 libzfs_handle_t *libhd; 2275 int ret; 2276 char buf[MAXPATHLEN]; /* dataset or mountpoint */ 2277 2278 if (smb_getdataset(si->shr_path, buf, MAXPATHLEN) != 0) 2279 return; 2280 2281 if ((libhd = libzfs_init()) == NULL) 2282 return; 2283 2284 errno = 0; 2285 ret = zfs_smb_acl_remove(libhd, buf, si->shr_path, si->shr_name); 2286 if (ret != 0 && errno != EAGAIN) 2287 syslog(LOG_INFO, "share: failed to remove ACL object: %s: %s\n", 2288 si->shr_name, strerror(errno)); 2289 2290 /* 2291 * We could remove the quotas directory here, but that adds 2292 * significantly to the time required for a zpool export, 2293 * so just leave it here and fixup when we share next. 2294 */ 2295 2296 libzfs_fini(libhd); 2297 } 2298 2299 /* 2300 * If the share path refers to a ZFS file system, rename the 2301 * .zfs/shares/<share> object. 2302 */ 2303 static void 2304 smb_shr_zfs_rename(smb_share_t *from, smb_share_t *to) 2305 { 2306 libzfs_handle_t *libhd; 2307 zfs_handle_t *zfshd; 2308 int ret; 2309 char dataset[MAXPATHLEN]; 2310 2311 if (smb_getdataset(from->shr_path, dataset, MAXPATHLEN) != 0) 2312 return; 2313 2314 if ((libhd = libzfs_init()) == NULL) 2315 return; 2316 2317 if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) { 2318 libzfs_fini(libhd); 2319 return; 2320 } 2321 2322 errno = 0; 2323 ret = zfs_smb_acl_rename(libhd, dataset, from->shr_path, 2324 from->shr_name, to->shr_name); 2325 if (ret != 0 && errno != EAGAIN) 2326 syslog(LOG_INFO, "share: failed to rename ACL object: %s: %s\n", 2327 from->shr_name, strerror(errno)); 2328 2329 zfs_close(zfshd); 2330 libzfs_fini(libhd); 2331 } 2332 2333 /* 2334 * Enable all privileges in the inheritable set to execute command. 2335 */ 2336 static int 2337 smb_shr_enable_all_privs(void) 2338 { 2339 priv_set_t *pset; 2340 2341 pset = priv_allocset(); 2342 if (pset == NULL) 2343 return (-1); 2344 2345 if (getppriv(PRIV_LIMIT, pset)) { 2346 priv_freeset(pset); 2347 return (-1); 2348 } 2349 2350 if (setppriv(PRIV_ON, PRIV_INHERITABLE, pset)) { 2351 priv_freeset(pset); 2352 return (-1); 2353 } 2354 2355 priv_freeset(pset); 2356 return (0); 2357 } 2358 2359 /* 2360 * Tokenizes the command string and returns the list of tokens in an array. 2361 * 2362 * Returns NULL if there are no tokens. 2363 */ 2364 static char ** 2365 smb_shr_tokenize_cmd(char *cmdstr) 2366 { 2367 char *cmd, *buf, *bp, *value; 2368 char **argv, **ap; 2369 int argc, i; 2370 2371 if (cmdstr == NULL || *cmdstr == '\0') 2372 return (NULL); 2373 2374 if ((buf = malloc(MAXPATHLEN)) == NULL) 2375 return (NULL); 2376 2377 (void) strlcpy(buf, cmdstr, MAXPATHLEN); 2378 2379 for (argc = 2, bp = cmdstr; *bp != '\0'; ++bp) 2380 if (*bp == ' ') 2381 ++argc; 2382 2383 if ((argv = calloc(argc, sizeof (char *))) == NULL) { 2384 free(buf); 2385 return (NULL); 2386 } 2387 2388 ap = argv; 2389 for (bp = buf, i = 0; i < argc; ++i) { 2390 do { 2391 if ((value = strsep(&bp, " ")) == NULL) 2392 break; 2393 } while (*value == '\0'); 2394 2395 if (value == NULL) 2396 break; 2397 2398 *ap++ = value; 2399 } 2400 2401 /* get the filename of the command from the path */ 2402 if ((cmd = strrchr(argv[0], '/')) != NULL) 2403 (void) strlcpy(argv[0], ++cmd, strlen(argv[0])); 2404 2405 return (argv); 2406 } 2407 2408 /* 2409 * Expands the command string for the following substitution tokens: 2410 * 2411 * %U - Windows username 2412 * %D - Name of the domain or workgroup of %U 2413 * %h - The server hostname 2414 * %M - The client hostname 2415 * %L - The server NetBIOS name 2416 * %m - The client NetBIOS name. This option is only valid for NetBIOS 2417 * connections (port 139). 2418 * %I - The IP address of the client machine 2419 * %i - The local IP address to which the client is connected 2420 * %S - The name of the share 2421 * %P - The root directory of the share 2422 * %u - The UID of the Unix user 2423 * 2424 * Returns 0 on success. Otherwise -1. 2425 */ 2426 static int 2427 smb_shr_expand_subs(char **cmd_toks, smb_share_t *si, smb_shr_execinfo_t *subs) 2428 { 2429 char *fmt, *sub_chr, *ptr; 2430 boolean_t unknown; 2431 char hostname[MAXHOSTNAMELEN]; 2432 char ip_str[INET6_ADDRSTRLEN]; 2433 char name[SMB_PI_MAX_HOST]; 2434 smb_wchar_t wbuf[SMB_PI_MAX_HOST]; 2435 int i; 2436 2437 if (cmd_toks == NULL || *cmd_toks == NULL) 2438 return (-1); 2439 2440 for (i = 1; cmd_toks[i]; i++) { 2441 fmt = cmd_toks[i]; 2442 if (*fmt == '%') { 2443 sub_chr = fmt + 1; 2444 unknown = B_FALSE; 2445 2446 switch (*sub_chr) { 2447 case 'U': 2448 ptr = strdup(subs->e_winname); 2449 break; 2450 case 'D': 2451 ptr = strdup(subs->e_userdom); 2452 break; 2453 case 'h': 2454 if (gethostname(hostname, MAXHOSTNAMELEN) != 0) 2455 unknown = B_TRUE; 2456 else 2457 ptr = strdup(hostname); 2458 break; 2459 case 'M': 2460 if (smb_getnameinfo(&subs->e_cli_ipaddr, 2461 hostname, sizeof (hostname), 0) != 0) 2462 unknown = B_TRUE; 2463 else 2464 ptr = strdup(hostname); 2465 break; 2466 case 'L': 2467 if (smb_getnetbiosname(hostname, 2468 NETBIOS_NAME_SZ) != 0) 2469 unknown = B_TRUE; 2470 else 2471 ptr = strdup(hostname); 2472 break; 2473 case 'm': 2474 if (*subs->e_cli_netbiosname == '\0') 2475 unknown = B_TRUE; 2476 else { 2477 (void) smb_mbstowcs(wbuf, 2478 subs->e_cli_netbiosname, 2479 SMB_PI_MAX_HOST - 1); 2480 2481 if (ucstooem(name, wbuf, 2482 SMB_PI_MAX_HOST, OEM_CPG_850) == 0) 2483 (void) strlcpy(name, 2484 subs->e_cli_netbiosname, 2485 SMB_PI_MAX_HOST); 2486 2487 ptr = strdup(name); 2488 } 2489 break; 2490 case 'I': 2491 if (smb_inet_ntop(&subs->e_cli_ipaddr, ip_str, 2492 SMB_IPSTRLEN(subs->e_cli_ipaddr.a_family)) 2493 != NULL) 2494 ptr = strdup(ip_str); 2495 else 2496 unknown = B_TRUE; 2497 break; 2498 case 'i': 2499 if (smb_inet_ntop(&subs->e_srv_ipaddr, ip_str, 2500 SMB_IPSTRLEN(subs->e_srv_ipaddr.a_family)) 2501 != NULL) 2502 ptr = strdup(ip_str); 2503 else 2504 unknown = B_TRUE; 2505 break; 2506 case 'S': 2507 ptr = strdup(si->shr_name); 2508 break; 2509 case 'P': 2510 ptr = strdup(si->shr_path); 2511 break; 2512 case 'u': 2513 (void) snprintf(name, sizeof (name), "%u", 2514 subs->e_uid); 2515 ptr = strdup(name); 2516 break; 2517 default: 2518 /* unknown sub char */ 2519 unknown = B_TRUE; 2520 break; 2521 } 2522 2523 if (unknown) 2524 ptr = strdup(""); 2525 2526 } else /* first char of cmd's arg is not '%' char */ 2527 ptr = strdup(""); 2528 2529 cmd_toks[i] = ptr; 2530 2531 if (ptr == NULL) { 2532 for (i = 1; cmd_toks[i]; i++) 2533 free(cmd_toks[i]); 2534 2535 return (-1); 2536 } 2537 } 2538 2539 return (0); 2540 } 2541 2542 /*ARGSUSED*/ 2543 static void 2544 smb_shr_sig_abnormal_term(int sig_val) 2545 { 2546 /* 2547 * Calling _exit() prevents parent process from getting SIGTERM/SIGINT 2548 * signal. 2549 */ 2550 _exit(-1); 2551 } 2552 2553 /*ARGSUSED*/ 2554 static void 2555 smb_shr_sig_child(int sig_val) 2556 { 2557 /* 2558 * Catch the signal and allow the exit status of the child process 2559 * to be available for reaping. 2560 */ 2561 } 2562 2563 /* 2564 * This is a temporary function which converts the given smb_share_t 2565 * structure to the nvlist format that will be provided by libsharev2 2566 */ 2567 static int 2568 smb_shr_encode(smb_share_t *si, nvlist_t **nvlist) 2569 { 2570 nvlist_t *list; 2571 nvlist_t *share; 2572 nvlist_t *smb; 2573 char *csc; 2574 int rc = 0; 2575 2576 *nvlist = NULL; 2577 2578 if ((rc = nvlist_alloc(&list, NV_UNIQUE_NAME, 0)) != 0) 2579 return (rc); 2580 2581 if ((rc = nvlist_alloc(&share, NV_UNIQUE_NAME, 0)) != 0) { 2582 nvlist_free(list); 2583 return (rc); 2584 } 2585 2586 if ((rc = nvlist_alloc(&smb, NV_UNIQUE_NAME, 0)) != 0) { 2587 nvlist_free(share); 2588 nvlist_free(list); 2589 return (rc); 2590 } 2591 2592 /* global share properties */ 2593 rc |= nvlist_add_string(share, "name", si->shr_name); 2594 rc |= nvlist_add_string(share, "path", si->shr_path); 2595 rc |= nvlist_add_string(share, "desc", si->shr_cmnt); 2596 2597 /* smb protocol properties */ 2598 rc = nvlist_add_string(smb, SHOPT_AD_CONTAINER, si->shr_container); 2599 if ((si->shr_flags & SMB_SHRF_ACC_NONE) != 0) 2600 rc |= nvlist_add_string(smb, SHOPT_NONE, si->shr_access_none); 2601 if ((si->shr_flags & SMB_SHRF_ACC_RO) != 0) 2602 rc |= nvlist_add_string(smb, SHOPT_RO, si->shr_access_ro); 2603 if ((si->shr_flags & SMB_SHRF_ACC_RW) != 0) 2604 rc |= nvlist_add_string(smb, SHOPT_RW, si->shr_access_rw); 2605 2606 if ((si->shr_flags & SMB_SHRF_ABE) != 0) 2607 rc |= nvlist_add_string(smb, SHOPT_ABE, "true"); 2608 if ((si->shr_flags & SMB_SHRF_CATIA) != 0) 2609 rc |= nvlist_add_string(smb, SHOPT_CATIA, "true"); 2610 if ((si->shr_flags & SMB_SHRF_GUEST_OK) != 0) 2611 rc |= nvlist_add_string(smb, SHOPT_GUEST, "true"); 2612 if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0) 2613 rc |= nvlist_add_string(smb, SHOPT_DFSROOT, "true"); 2614 if ((si->shr_flags & SMB_SHRF_FSO) != 0) 2615 rc |= nvlist_add_string(smb, SHOPT_FSO, "true"); 2616 if ((si->shr_flags & SMB_SHRF_QUOTAS) != 0) 2617 rc |= nvlist_add_string(smb, SHOPT_QUOTAS, "true"); 2618 2619 if (si->shr_encrypt == SMB_CONFIG_REQUIRED) 2620 rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "required"); 2621 else if (si->shr_encrypt == SMB_CONFIG_ENABLED) 2622 rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "enabled"); 2623 else 2624 rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "disabled"); 2625 2626 if ((si->shr_flags & SMB_SHRF_AUTOHOME) != 0) { 2627 rc |= nvlist_add_string(smb, SHOPT_AUTOHOME, "true"); 2628 rc |= nvlist_add_uint32(smb, "uid", si->shr_uid); 2629 rc |= nvlist_add_uint32(smb, "gid", si->shr_gid); 2630 } 2631 2632 if ((csc = smb_shr_sa_csc_name(si)) != NULL) 2633 rc |= nvlist_add_string(smb, SHOPT_CSC, csc); 2634 2635 rc |= nvlist_add_uint32(smb, "type", si->shr_type); 2636 2637 rc |= nvlist_add_nvlist(share, "smb", smb); 2638 rc |= nvlist_add_nvlist(list, si->shr_name, share); 2639 2640 nvlist_free(share); 2641 nvlist_free(smb); 2642 2643 if (rc != 0) 2644 nvlist_free(list); 2645 else 2646 *nvlist = list; 2647 2648 return (rc); 2649 } 2650