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