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