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