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