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