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