1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <sys/param.h> 26 #include <sys/types.h> 27 #include <sys/tzfile.h> 28 #include <sys/atomic.h> 29 #include <sys/kidmap.h> 30 #include <sys/time.h> 31 #include <sys/cpuvar.h> 32 #include <smbsrv/smb_kproto.h> 33 #include <smbsrv/smb_fsops.h> 34 #include <smbsrv/smbinfo.h> 35 #include <smbsrv/smb_xdr.h> 36 #include <smbsrv/smb_vops.h> 37 #include <smbsrv/smb_idmap.h> 38 39 #include <sys/sid.h> 40 #include <sys/priv_names.h> 41 42 static kmem_cache_t *smb_dtor_cache; 43 static boolean_t smb_llist_initialized = B_FALSE; 44 45 static boolean_t smb_thread_continue_timedwait_locked(smb_thread_t *, int); 46 47 time_t tzh_leapcnt = 0; 48 49 struct tm 50 *smb_gmtime_r(time_t *clock, struct tm *result); 51 52 time_t 53 smb_timegm(struct tm *tm); 54 55 struct tm { 56 int tm_sec; 57 int tm_min; 58 int tm_hour; 59 int tm_mday; 60 int tm_mon; 61 int tm_year; 62 int tm_wday; 63 int tm_yday; 64 int tm_isdst; 65 }; 66 67 static int days_in_month[] = { 68 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 69 }; 70 71 int 72 smb_ascii_or_unicode_strlen(struct smb_request *sr, char *str) 73 { 74 if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) 75 return (smb_wcequiv_strlen(str)); 76 return (strlen(str)); 77 } 78 79 int 80 smb_ascii_or_unicode_strlen_null(struct smb_request *sr, char *str) 81 { 82 if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) 83 return (smb_wcequiv_strlen(str) + 2); 84 return (strlen(str) + 1); 85 } 86 87 int 88 smb_ascii_or_unicode_null_len(struct smb_request *sr) 89 { 90 if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) 91 return (2); 92 return (1); 93 } 94 95 /* 96 * Return B_TRUE if pattern contains wildcards 97 */ 98 boolean_t 99 smb_contains_wildcards(const char *pattern) 100 { 101 static const char *wildcards = "*?"; 102 103 return (strpbrk(pattern, wildcards) != NULL); 104 } 105 106 /* 107 * When converting wildcards a '.' in a name is treated as a base and 108 * extension separator even if the name is longer than 8.3. 109 * 110 * The '*' character matches an entire part of the name. For example, 111 * "*.abc" matches any name with an extension of "abc". 112 * 113 * The '?' character matches a single character. 114 * If the base contains all ? (8 or more) then it is treated as *. 115 * If the extension contains all ? (3 or more) then it is treated as *. 116 * 117 * Clients convert ASCII wildcards to Unicode wildcards as follows: 118 * 119 * ? is converted to > 120 * . is converted to " if it is followed by ? or * 121 * * is converted to < if it is followed by . 122 * 123 * Note that clients convert "*." to '< and drop the '.' but "*.txt" 124 * is sent as "<.TXT", i.e. 125 * 126 * dir *. -> dir < 127 * dir *.txt -> dir <.TXT 128 * 129 * Since " and < are illegal in Windows file names, we always convert 130 * these Unicode wildcards without checking the following character. 131 */ 132 void 133 smb_convert_wildcards(char *pattern) 134 { 135 static char *match_all[] = { 136 "*.", 137 "*.*" 138 }; 139 char *extension; 140 char *p; 141 int len; 142 int i; 143 144 /* 145 * Special case "<" for "dir *.", and fast-track for "*". 146 */ 147 if ((*pattern == '<') || (*pattern == '*')) { 148 if (*(pattern + 1) == '\0') { 149 *pattern = '*'; 150 return; 151 } 152 } 153 154 for (p = pattern; *p != '\0'; ++p) { 155 switch (*p) { 156 case '<': 157 *p = '*'; 158 break; 159 case '>': 160 *p = '?'; 161 break; 162 case '\"': 163 *p = '.'; 164 break; 165 default: 166 break; 167 } 168 } 169 170 /* 171 * Replace "????????.ext" with "*.ext". 172 */ 173 p = pattern; 174 p += strspn(p, "?"); 175 if (*p == '.') { 176 *p = '\0'; 177 len = strlen(pattern); 178 *p = '.'; 179 if (len >= SMB_NAME83_BASELEN) { 180 *pattern = '*'; 181 (void) strlcpy(pattern + 1, p, MAXPATHLEN - 1); 182 } 183 } 184 185 /* 186 * Replace "base.???" with 'base.*'. 187 */ 188 if ((extension = strrchr(pattern, '.')) != NULL) { 189 p = ++extension; 190 p += strspn(p, "?"); 191 if (*p == '\0') { 192 len = strlen(extension); 193 if (len >= SMB_NAME83_EXTLEN) { 194 *extension = '\0'; 195 (void) strlcat(pattern, "*", MAXPATHLEN); 196 } 197 } 198 } 199 200 /* 201 * Replace anything that matches an entry in match_all with "*". 202 */ 203 for (i = 0; i < sizeof (match_all) / sizeof (match_all[0]); ++i) { 204 if (strcmp(pattern, match_all[i]) == 0) { 205 (void) strlcpy(pattern, "*", MAXPATHLEN); 206 break; 207 } 208 } 209 } 210 211 /* 212 * smb_sattr_check 213 * 214 * Check file attributes against a search attribute (sattr) mask. 215 * 216 * Normal files, which includes READONLY and ARCHIVE, always pass 217 * this check. If the DIRECTORY, HIDDEN or SYSTEM special attributes 218 * are set then they must appear in the search mask. The special 219 * attributes are inclusive, i.e. all special attributes that appear 220 * in sattr must also appear in the file attributes for the check to 221 * pass. 222 * 223 * The following examples show how this works: 224 * 225 * fileA: READONLY 226 * fileB: 0 (no attributes = normal file) 227 * fileC: READONLY, ARCHIVE 228 * fileD: HIDDEN 229 * fileE: READONLY, HIDDEN, SYSTEM 230 * dirA: DIRECTORY 231 * 232 * search attribute: 0 233 * Returns: fileA, fileB and fileC. 234 * search attribute: HIDDEN 235 * Returns: fileA, fileB, fileC and fileD. 236 * search attribute: SYSTEM 237 * Returns: fileA, fileB and fileC. 238 * search attribute: DIRECTORY 239 * Returns: fileA, fileB, fileC and dirA. 240 * search attribute: HIDDEN and SYSTEM 241 * Returns: fileA, fileB, fileC, fileD and fileE. 242 * 243 * Returns true if the file and sattr match; otherwise, returns false. 244 */ 245 boolean_t 246 smb_sattr_check(uint16_t dosattr, uint16_t sattr) 247 { 248 if ((dosattr & FILE_ATTRIBUTE_DIRECTORY) && 249 !(sattr & FILE_ATTRIBUTE_DIRECTORY)) 250 return (B_FALSE); 251 252 if ((dosattr & FILE_ATTRIBUTE_HIDDEN) && 253 !(sattr & FILE_ATTRIBUTE_HIDDEN)) 254 return (B_FALSE); 255 256 if ((dosattr & FILE_ATTRIBUTE_SYSTEM) && 257 !(sattr & FILE_ATTRIBUTE_SYSTEM)) 258 return (B_FALSE); 259 260 return (B_TRUE); 261 } 262 263 int 264 microtime(timestruc_t *tvp) 265 { 266 tvp->tv_sec = gethrestime_sec(); 267 tvp->tv_nsec = 0; 268 return (0); 269 } 270 271 int32_t 272 clock_get_milli_uptime() 273 { 274 return (TICK_TO_MSEC(ddi_get_lbolt())); 275 } 276 277 int /*ARGSUSED*/ 278 smb_noop(void *p, size_t size, int foo) 279 { 280 return (0); 281 } 282 283 /* 284 * smb_idpool_increment 285 * 286 * This function increments the ID pool by doubling the current size. This 287 * function assumes the caller entered the mutex of the pool. 288 */ 289 static int 290 smb_idpool_increment( 291 smb_idpool_t *pool) 292 { 293 uint8_t *new_pool; 294 uint32_t new_size; 295 296 ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC); 297 298 new_size = pool->id_size * 2; 299 if (new_size <= SMB_IDPOOL_MAX_SIZE) { 300 new_pool = kmem_alloc(new_size / 8, KM_NOSLEEP); 301 if (new_pool) { 302 bzero(new_pool, new_size / 8); 303 bcopy(pool->id_pool, new_pool, pool->id_size / 8); 304 kmem_free(pool->id_pool, pool->id_size / 8); 305 pool->id_pool = new_pool; 306 pool->id_free_counter += new_size - pool->id_size; 307 pool->id_max_free_counter += new_size - pool->id_size; 308 pool->id_size = new_size; 309 pool->id_idx_msk = (new_size / 8) - 1; 310 if (new_size >= SMB_IDPOOL_MAX_SIZE) { 311 /* id -1 made unavailable */ 312 pool->id_pool[pool->id_idx_msk] = 0x80; 313 pool->id_free_counter--; 314 pool->id_max_free_counter--; 315 } 316 return (0); 317 } 318 } 319 return (-1); 320 } 321 322 /* 323 * smb_idpool_constructor 324 * 325 * This function initializes the pool structure provided. 326 */ 327 int 328 smb_idpool_constructor( 329 smb_idpool_t *pool) 330 { 331 332 ASSERT(pool->id_magic != SMB_IDPOOL_MAGIC); 333 334 pool->id_size = SMB_IDPOOL_MIN_SIZE; 335 pool->id_idx_msk = (SMB_IDPOOL_MIN_SIZE / 8) - 1; 336 pool->id_free_counter = SMB_IDPOOL_MIN_SIZE - 1; 337 pool->id_max_free_counter = SMB_IDPOOL_MIN_SIZE - 1; 338 pool->id_bit = 0x02; 339 pool->id_bit_idx = 1; 340 pool->id_idx = 0; 341 pool->id_pool = (uint8_t *)kmem_alloc((SMB_IDPOOL_MIN_SIZE / 8), 342 KM_SLEEP); 343 bzero(pool->id_pool, (SMB_IDPOOL_MIN_SIZE / 8)); 344 /* -1 id made unavailable */ 345 pool->id_pool[0] = 0x01; /* id 0 made unavailable */ 346 mutex_init(&pool->id_mutex, NULL, MUTEX_DEFAULT, NULL); 347 pool->id_magic = SMB_IDPOOL_MAGIC; 348 return (0); 349 } 350 351 /* 352 * smb_idpool_destructor 353 * 354 * This function tears down and frees the resources associated with the 355 * pool provided. 356 */ 357 void 358 smb_idpool_destructor( 359 smb_idpool_t *pool) 360 { 361 ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC); 362 ASSERT(pool->id_free_counter == pool->id_max_free_counter); 363 pool->id_magic = (uint32_t)~SMB_IDPOOL_MAGIC; 364 mutex_destroy(&pool->id_mutex); 365 kmem_free(pool->id_pool, (size_t)(pool->id_size / 8)); 366 } 367 368 /* 369 * smb_idpool_alloc 370 * 371 * This function allocates an ID from the pool provided. 372 */ 373 int 374 smb_idpool_alloc( 375 smb_idpool_t *pool, 376 uint16_t *id) 377 { 378 uint32_t i; 379 uint8_t bit; 380 uint8_t bit_idx; 381 uint8_t byte; 382 383 ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC); 384 385 mutex_enter(&pool->id_mutex); 386 if ((pool->id_free_counter == 0) && smb_idpool_increment(pool)) { 387 mutex_exit(&pool->id_mutex); 388 return (-1); 389 } 390 391 i = pool->id_size; 392 while (i) { 393 bit = pool->id_bit; 394 bit_idx = pool->id_bit_idx; 395 byte = pool->id_pool[pool->id_idx]; 396 while (bit) { 397 if (byte & bit) { 398 bit = bit << 1; 399 bit_idx++; 400 continue; 401 } 402 pool->id_pool[pool->id_idx] |= bit; 403 *id = (uint16_t)(pool->id_idx * 8 + (uint32_t)bit_idx); 404 pool->id_free_counter--; 405 pool->id_bit = bit; 406 pool->id_bit_idx = bit_idx; 407 mutex_exit(&pool->id_mutex); 408 return (0); 409 } 410 pool->id_bit = 1; 411 pool->id_bit_idx = 0; 412 pool->id_idx++; 413 pool->id_idx &= pool->id_idx_msk; 414 --i; 415 } 416 /* 417 * This section of code shouldn't be reached. If there are IDs 418 * available and none could be found there's a problem. 419 */ 420 ASSERT(0); 421 mutex_exit(&pool->id_mutex); 422 return (-1); 423 } 424 425 /* 426 * smb_idpool_free 427 * 428 * This function frees the ID provided. 429 */ 430 void 431 smb_idpool_free( 432 smb_idpool_t *pool, 433 uint16_t id) 434 { 435 ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC); 436 ASSERT(id != 0); 437 ASSERT(id != 0xFFFF); 438 439 mutex_enter(&pool->id_mutex); 440 if (pool->id_pool[id >> 3] & (1 << (id & 7))) { 441 pool->id_pool[id >> 3] &= ~(1 << (id & 7)); 442 pool->id_free_counter++; 443 ASSERT(pool->id_free_counter <= pool->id_max_free_counter); 444 mutex_exit(&pool->id_mutex); 445 return; 446 } 447 /* Freeing a free ID. */ 448 ASSERT(0); 449 mutex_exit(&pool->id_mutex); 450 } 451 452 /* 453 * Initialize the llist delete queue object cache. 454 */ 455 void 456 smb_llist_init(void) 457 { 458 if (smb_llist_initialized) 459 return; 460 461 smb_dtor_cache = kmem_cache_create("smb_dtor_cache", 462 sizeof (smb_dtor_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 463 464 smb_llist_initialized = B_TRUE; 465 } 466 467 /* 468 * Destroy the llist delete queue object cache. 469 */ 470 void 471 smb_llist_fini(void) 472 { 473 if (!smb_llist_initialized) 474 return; 475 476 kmem_cache_destroy(smb_dtor_cache); 477 smb_llist_initialized = B_FALSE; 478 } 479 480 /* 481 * smb_llist_constructor 482 * 483 * This function initializes a locked list. 484 */ 485 void 486 smb_llist_constructor( 487 smb_llist_t *ll, 488 size_t size, 489 size_t offset) 490 { 491 rw_init(&ll->ll_lock, NULL, RW_DEFAULT, NULL); 492 mutex_init(&ll->ll_mutex, NULL, MUTEX_DEFAULT, NULL); 493 list_create(&ll->ll_list, size, offset); 494 list_create(&ll->ll_deleteq, sizeof (smb_dtor_t), 495 offsetof(smb_dtor_t, dt_lnd)); 496 ll->ll_count = 0; 497 ll->ll_wrop = 0; 498 ll->ll_deleteq_count = 0; 499 } 500 501 /* 502 * Flush the delete queue and destroy a locked list. 503 */ 504 void 505 smb_llist_destructor( 506 smb_llist_t *ll) 507 { 508 smb_llist_flush(ll); 509 510 ASSERT(ll->ll_count == 0); 511 ASSERT(ll->ll_deleteq_count == 0); 512 513 rw_destroy(&ll->ll_lock); 514 list_destroy(&ll->ll_list); 515 list_destroy(&ll->ll_deleteq); 516 mutex_destroy(&ll->ll_mutex); 517 } 518 519 /* 520 * Post an object to the delete queue. The delete queue will be processed 521 * during list exit or list destruction. Objects are often posted for 522 * deletion during list iteration (while the list is locked) but that is 523 * not required, and an object can be posted at any time. 524 */ 525 void 526 smb_llist_post(smb_llist_t *ll, void *object, smb_dtorproc_t dtorproc) 527 { 528 smb_dtor_t *dtor; 529 530 ASSERT((object != NULL) && (dtorproc != NULL)); 531 532 dtor = kmem_cache_alloc(smb_dtor_cache, KM_SLEEP); 533 bzero(dtor, sizeof (smb_dtor_t)); 534 dtor->dt_magic = SMB_DTOR_MAGIC; 535 dtor->dt_object = object; 536 dtor->dt_proc = dtorproc; 537 538 mutex_enter(&ll->ll_mutex); 539 list_insert_tail(&ll->ll_deleteq, dtor); 540 ++ll->ll_deleteq_count; 541 mutex_exit(&ll->ll_mutex); 542 } 543 544 /* 545 * Exit the list lock and process the delete queue. 546 */ 547 void 548 smb_llist_exit(smb_llist_t *ll) 549 { 550 rw_exit(&ll->ll_lock); 551 smb_llist_flush(ll); 552 } 553 554 /* 555 * Flush the list delete queue. The mutex is dropped across the destructor 556 * call in case this leads to additional objects being posted to the delete 557 * queue. 558 */ 559 void 560 smb_llist_flush(smb_llist_t *ll) 561 { 562 smb_dtor_t *dtor; 563 564 mutex_enter(&ll->ll_mutex); 565 566 dtor = list_head(&ll->ll_deleteq); 567 while (dtor != NULL) { 568 SMB_DTOR_VALID(dtor); 569 ASSERT((dtor->dt_object != NULL) && (dtor->dt_proc != NULL)); 570 list_remove(&ll->ll_deleteq, dtor); 571 --ll->ll_deleteq_count; 572 mutex_exit(&ll->ll_mutex); 573 574 dtor->dt_proc(dtor->dt_object); 575 576 dtor->dt_magic = (uint32_t)~SMB_DTOR_MAGIC; 577 kmem_cache_free(smb_dtor_cache, dtor); 578 mutex_enter(&ll->ll_mutex); 579 dtor = list_head(&ll->ll_deleteq); 580 } 581 582 mutex_exit(&ll->ll_mutex); 583 } 584 585 /* 586 * smb_llist_upgrade 587 * 588 * This function tries to upgrade the lock of the locked list. It assumes the 589 * locked has already been entered in RW_READER mode. It first tries using the 590 * Solaris function rw_tryupgrade(). If that call fails the lock is released 591 * and reentered in RW_WRITER mode. In that last case a window is opened during 592 * which the contents of the list may have changed. The return code indicates 593 * whether or not the list was modified when the lock was exited. 594 */ 595 int smb_llist_upgrade( 596 smb_llist_t *ll) 597 { 598 uint64_t wrop; 599 600 if (rw_tryupgrade(&ll->ll_lock) != 0) { 601 return (0); 602 } 603 wrop = ll->ll_wrop; 604 rw_exit(&ll->ll_lock); 605 rw_enter(&ll->ll_lock, RW_WRITER); 606 return (wrop != ll->ll_wrop); 607 } 608 609 /* 610 * smb_llist_insert_head 611 * 612 * This function inserts the object passed a the beginning of the list. This 613 * function assumes the lock of the list has already been entered. 614 */ 615 void 616 smb_llist_insert_head( 617 smb_llist_t *ll, 618 void *obj) 619 { 620 list_insert_head(&ll->ll_list, obj); 621 ++ll->ll_wrop; 622 ++ll->ll_count; 623 } 624 625 /* 626 * smb_llist_insert_tail 627 * 628 * This function appends to the object passed to the list. This function assumes 629 * the lock of the list has already been entered. 630 * 631 */ 632 void 633 smb_llist_insert_tail( 634 smb_llist_t *ll, 635 void *obj) 636 { 637 list_insert_tail(&ll->ll_list, obj); 638 ++ll->ll_wrop; 639 ++ll->ll_count; 640 } 641 642 /* 643 * smb_llist_remove 644 * 645 * This function removes the object passed from the list. This function assumes 646 * the lock of the list has already been entered. 647 */ 648 void 649 smb_llist_remove( 650 smb_llist_t *ll, 651 void *obj) 652 { 653 list_remove(&ll->ll_list, obj); 654 ++ll->ll_wrop; 655 --ll->ll_count; 656 } 657 658 /* 659 * smb_llist_get_count 660 * 661 * This function returns the number of elements in the specified list. 662 */ 663 uint32_t 664 smb_llist_get_count( 665 smb_llist_t *ll) 666 { 667 return (ll->ll_count); 668 } 669 670 /* 671 * smb_slist_constructor 672 * 673 * Synchronized list constructor. 674 */ 675 void 676 smb_slist_constructor( 677 smb_slist_t *sl, 678 size_t size, 679 size_t offset) 680 { 681 mutex_init(&sl->sl_mutex, NULL, MUTEX_DEFAULT, NULL); 682 cv_init(&sl->sl_cv, NULL, CV_DEFAULT, NULL); 683 list_create(&sl->sl_list, size, offset); 684 sl->sl_count = 0; 685 sl->sl_waiting = B_FALSE; 686 } 687 688 /* 689 * smb_slist_destructor 690 * 691 * Synchronized list destructor. 692 */ 693 void 694 smb_slist_destructor( 695 smb_slist_t *sl) 696 { 697 ASSERT(sl->sl_count == 0); 698 699 mutex_destroy(&sl->sl_mutex); 700 cv_destroy(&sl->sl_cv); 701 list_destroy(&sl->sl_list); 702 } 703 704 /* 705 * smb_slist_insert_head 706 * 707 * This function inserts the object passed a the beginning of the list. 708 */ 709 void 710 smb_slist_insert_head( 711 smb_slist_t *sl, 712 void *obj) 713 { 714 mutex_enter(&sl->sl_mutex); 715 list_insert_head(&sl->sl_list, obj); 716 ++sl->sl_count; 717 mutex_exit(&sl->sl_mutex); 718 } 719 720 /* 721 * smb_slist_insert_tail 722 * 723 * This function appends the object passed to the list. 724 */ 725 void 726 smb_slist_insert_tail( 727 smb_slist_t *sl, 728 void *obj) 729 { 730 mutex_enter(&sl->sl_mutex); 731 list_insert_tail(&sl->sl_list, obj); 732 ++sl->sl_count; 733 mutex_exit(&sl->sl_mutex); 734 } 735 736 /* 737 * smb_llist_remove 738 * 739 * This function removes the object passed by the caller from the list. 740 */ 741 void 742 smb_slist_remove( 743 smb_slist_t *sl, 744 void *obj) 745 { 746 mutex_enter(&sl->sl_mutex); 747 list_remove(&sl->sl_list, obj); 748 if ((--sl->sl_count == 0) && (sl->sl_waiting)) { 749 sl->sl_waiting = B_FALSE; 750 cv_broadcast(&sl->sl_cv); 751 } 752 mutex_exit(&sl->sl_mutex); 753 } 754 755 /* 756 * smb_slist_move_tail 757 * 758 * This function transfers all the contents of the synchronized list to the 759 * list_t provided. It returns the number of objects transferred. 760 */ 761 uint32_t 762 smb_slist_move_tail( 763 list_t *lst, 764 smb_slist_t *sl) 765 { 766 uint32_t rv; 767 768 mutex_enter(&sl->sl_mutex); 769 rv = sl->sl_count; 770 if (sl->sl_count) { 771 list_move_tail(lst, &sl->sl_list); 772 sl->sl_count = 0; 773 if (sl->sl_waiting) { 774 sl->sl_waiting = B_FALSE; 775 cv_broadcast(&sl->sl_cv); 776 } 777 } 778 mutex_exit(&sl->sl_mutex); 779 return (rv); 780 } 781 782 /* 783 * smb_slist_obj_move 784 * 785 * This function moves an object from one list to the end of the other list. It 786 * assumes the mutex of each list has been entered. 787 */ 788 void 789 smb_slist_obj_move( 790 smb_slist_t *dst, 791 smb_slist_t *src, 792 void *obj) 793 { 794 ASSERT(dst->sl_list.list_offset == src->sl_list.list_offset); 795 ASSERT(dst->sl_list.list_size == src->sl_list.list_size); 796 797 list_remove(&src->sl_list, obj); 798 list_insert_tail(&dst->sl_list, obj); 799 dst->sl_count++; 800 src->sl_count--; 801 if ((src->sl_count == 0) && (src->sl_waiting)) { 802 src->sl_waiting = B_FALSE; 803 cv_broadcast(&src->sl_cv); 804 } 805 } 806 807 /* 808 * smb_slist_wait_for_empty 809 * 810 * This function waits for a list to be emptied. 811 */ 812 void 813 smb_slist_wait_for_empty( 814 smb_slist_t *sl) 815 { 816 mutex_enter(&sl->sl_mutex); 817 while (sl->sl_count) { 818 sl->sl_waiting = B_TRUE; 819 cv_wait(&sl->sl_cv, &sl->sl_mutex); 820 } 821 mutex_exit(&sl->sl_mutex); 822 } 823 824 /* 825 * smb_slist_exit 826 * 827 * This function exits the muetx of the list and signal the condition variable 828 * if the list is empty. 829 */ 830 void 831 smb_slist_exit(smb_slist_t *sl) 832 { 833 if ((sl->sl_count == 0) && (sl->sl_waiting)) { 834 sl->sl_waiting = B_FALSE; 835 cv_broadcast(&sl->sl_cv); 836 } 837 mutex_exit(&sl->sl_mutex); 838 } 839 840 /* 841 * smb_thread_entry_point 842 * 843 * Common entry point for all the threads created through smb_thread_start. 844 * The state of the thread is set to "running" at the beginning and moved to 845 * "exiting" just before calling thread_exit(). The condition variable is 846 * also signaled. 847 */ 848 static void 849 smb_thread_entry_point( 850 smb_thread_t *thread) 851 { 852 ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 853 mutex_enter(&thread->sth_mtx); 854 ASSERT(thread->sth_state == SMB_THREAD_STATE_STARTING); 855 thread->sth_th = curthread; 856 thread->sth_did = thread->sth_th->t_did; 857 858 if (!thread->sth_kill) { 859 thread->sth_state = SMB_THREAD_STATE_RUNNING; 860 cv_signal(&thread->sth_cv); 861 mutex_exit(&thread->sth_mtx); 862 thread->sth_ep(thread, thread->sth_ep_arg); 863 mutex_enter(&thread->sth_mtx); 864 } 865 thread->sth_th = NULL; 866 thread->sth_state = SMB_THREAD_STATE_EXITING; 867 cv_broadcast(&thread->sth_cv); 868 mutex_exit(&thread->sth_mtx); 869 thread_exit(); 870 } 871 872 /* 873 * smb_thread_init 874 */ 875 void 876 smb_thread_init( 877 smb_thread_t *thread, 878 char *name, 879 smb_thread_ep_t ep, 880 void *ep_arg, 881 smb_thread_aw_t aw, 882 void *aw_arg) 883 { 884 ASSERT(thread->sth_magic != SMB_THREAD_MAGIC); 885 886 bzero(thread, sizeof (*thread)); 887 888 (void) strlcpy(thread->sth_name, name, sizeof (thread->sth_name)); 889 thread->sth_ep = ep; 890 thread->sth_ep_arg = ep_arg; 891 thread->sth_aw = aw; 892 thread->sth_aw_arg = aw_arg; 893 thread->sth_state = SMB_THREAD_STATE_EXITED; 894 mutex_init(&thread->sth_mtx, NULL, MUTEX_DEFAULT, NULL); 895 cv_init(&thread->sth_cv, NULL, CV_DEFAULT, NULL); 896 thread->sth_magic = SMB_THREAD_MAGIC; 897 } 898 899 /* 900 * smb_thread_destroy 901 */ 902 void 903 smb_thread_destroy( 904 smb_thread_t *thread) 905 { 906 ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 907 ASSERT(thread->sth_state == SMB_THREAD_STATE_EXITED); 908 thread->sth_magic = 0; 909 mutex_destroy(&thread->sth_mtx); 910 cv_destroy(&thread->sth_cv); 911 } 912 913 /* 914 * smb_thread_start 915 * 916 * This function starts a thread with the parameters provided. It waits until 917 * the state of the thread has been moved to running. 918 */ 919 /*ARGSUSED*/ 920 int 921 smb_thread_start( 922 smb_thread_t *thread) 923 { 924 int rc = 0; 925 kthread_t *tmpthread; 926 927 ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 928 929 mutex_enter(&thread->sth_mtx); 930 switch (thread->sth_state) { 931 case SMB_THREAD_STATE_EXITED: 932 thread->sth_state = SMB_THREAD_STATE_STARTING; 933 mutex_exit(&thread->sth_mtx); 934 tmpthread = thread_create(NULL, 0, smb_thread_entry_point, 935 thread, 0, &p0, TS_RUN, minclsyspri); 936 ASSERT(tmpthread != NULL); 937 mutex_enter(&thread->sth_mtx); 938 while (thread->sth_state == SMB_THREAD_STATE_STARTING) 939 cv_wait(&thread->sth_cv, &thread->sth_mtx); 940 if (thread->sth_state != SMB_THREAD_STATE_RUNNING) 941 rc = -1; 942 break; 943 default: 944 ASSERT(0); 945 rc = -1; 946 break; 947 } 948 mutex_exit(&thread->sth_mtx); 949 return (rc); 950 } 951 952 /* 953 * smb_thread_stop 954 * 955 * This function signals a thread to kill itself and waits until the "exiting" 956 * state has been reached. 957 */ 958 void 959 smb_thread_stop( 960 smb_thread_t *thread) 961 { 962 ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 963 964 mutex_enter(&thread->sth_mtx); 965 switch (thread->sth_state) { 966 case SMB_THREAD_STATE_RUNNING: 967 case SMB_THREAD_STATE_STARTING: 968 if (!thread->sth_kill) { 969 thread->sth_kill = B_TRUE; 970 if (thread->sth_aw) 971 thread->sth_aw(thread, thread->sth_aw_arg); 972 cv_broadcast(&thread->sth_cv); 973 while (thread->sth_state != SMB_THREAD_STATE_EXITING) 974 cv_wait(&thread->sth_cv, &thread->sth_mtx); 975 mutex_exit(&thread->sth_mtx); 976 thread_join(thread->sth_did); 977 mutex_enter(&thread->sth_mtx); 978 thread->sth_state = SMB_THREAD_STATE_EXITED; 979 thread->sth_did = 0; 980 thread->sth_kill = B_FALSE; 981 cv_broadcast(&thread->sth_cv); 982 break; 983 } 984 /*FALLTHRU*/ 985 986 case SMB_THREAD_STATE_EXITING: 987 if (thread->sth_kill) { 988 while (thread->sth_state != SMB_THREAD_STATE_EXITED) 989 cv_wait(&thread->sth_cv, &thread->sth_mtx); 990 } else { 991 thread->sth_state = SMB_THREAD_STATE_EXITED; 992 thread->sth_did = 0; 993 } 994 break; 995 996 case SMB_THREAD_STATE_EXITED: 997 break; 998 999 default: 1000 ASSERT(0); 1001 break; 1002 } 1003 mutex_exit(&thread->sth_mtx); 1004 } 1005 1006 /* 1007 * smb_thread_signal 1008 * 1009 * This function signals a thread. 1010 */ 1011 void 1012 smb_thread_signal( 1013 smb_thread_t *thread) 1014 { 1015 ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 1016 1017 mutex_enter(&thread->sth_mtx); 1018 switch (thread->sth_state) { 1019 case SMB_THREAD_STATE_RUNNING: 1020 if (thread->sth_aw) 1021 thread->sth_aw(thread, thread->sth_aw_arg); 1022 cv_signal(&thread->sth_cv); 1023 break; 1024 1025 default: 1026 break; 1027 } 1028 mutex_exit(&thread->sth_mtx); 1029 } 1030 1031 boolean_t 1032 smb_thread_continue(smb_thread_t *thread) 1033 { 1034 boolean_t result; 1035 1036 ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 1037 1038 mutex_enter(&thread->sth_mtx); 1039 result = smb_thread_continue_timedwait_locked(thread, 0); 1040 mutex_exit(&thread->sth_mtx); 1041 1042 return (result); 1043 } 1044 1045 boolean_t 1046 smb_thread_continue_nowait(smb_thread_t *thread) 1047 { 1048 boolean_t result; 1049 1050 ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 1051 1052 mutex_enter(&thread->sth_mtx); 1053 /* 1054 * Setting ticks=-1 requests a non-blocking check. We will 1055 * still block if the thread is in "suspend" state. 1056 */ 1057 result = smb_thread_continue_timedwait_locked(thread, -1); 1058 mutex_exit(&thread->sth_mtx); 1059 1060 return (result); 1061 } 1062 1063 boolean_t 1064 smb_thread_continue_timedwait(smb_thread_t *thread, int seconds) 1065 { 1066 boolean_t result; 1067 1068 ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 1069 1070 mutex_enter(&thread->sth_mtx); 1071 result = smb_thread_continue_timedwait_locked(thread, 1072 SEC_TO_TICK(seconds)); 1073 mutex_exit(&thread->sth_mtx); 1074 1075 return (result); 1076 } 1077 1078 /* 1079 * smb_thread_continue_timedwait_locked 1080 * 1081 * Internal only. Ticks==-1 means don't block, Ticks == 0 means wait 1082 * indefinitely 1083 */ 1084 static boolean_t 1085 smb_thread_continue_timedwait_locked(smb_thread_t *thread, int ticks) 1086 { 1087 boolean_t result; 1088 1089 /* -1 means don't block */ 1090 if (ticks != -1 && !thread->sth_kill) { 1091 if (ticks == 0) { 1092 cv_wait(&thread->sth_cv, &thread->sth_mtx); 1093 } else { 1094 (void) cv_reltimedwait(&thread->sth_cv, 1095 &thread->sth_mtx, (clock_t)ticks, TR_CLOCK_TICK); 1096 } 1097 } 1098 result = (thread->sth_kill == 0); 1099 1100 return (result); 1101 } 1102 1103 void 1104 smb_thread_set_awaken(smb_thread_t *thread, smb_thread_aw_t new_aw_fn, 1105 void *new_aw_arg) 1106 { 1107 ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 1108 1109 mutex_enter(&thread->sth_mtx); 1110 thread->sth_aw = new_aw_fn; 1111 thread->sth_aw_arg = new_aw_arg; 1112 mutex_exit(&thread->sth_mtx); 1113 } 1114 1115 /* 1116 * smb_rwx_init 1117 */ 1118 void 1119 smb_rwx_init( 1120 smb_rwx_t *rwx) 1121 { 1122 bzero(rwx, sizeof (smb_rwx_t)); 1123 cv_init(&rwx->rwx_cv, NULL, CV_DEFAULT, NULL); 1124 mutex_init(&rwx->rwx_mutex, NULL, MUTEX_DEFAULT, NULL); 1125 rw_init(&rwx->rwx_lock, NULL, RW_DEFAULT, NULL); 1126 } 1127 1128 /* 1129 * smb_rwx_destroy 1130 */ 1131 void 1132 smb_rwx_destroy( 1133 smb_rwx_t *rwx) 1134 { 1135 mutex_destroy(&rwx->rwx_mutex); 1136 cv_destroy(&rwx->rwx_cv); 1137 rw_destroy(&rwx->rwx_lock); 1138 } 1139 1140 /* 1141 * smb_rwx_rwexit 1142 */ 1143 void 1144 smb_rwx_rwexit( 1145 smb_rwx_t *rwx) 1146 { 1147 if (rw_write_held(&rwx->rwx_lock)) { 1148 ASSERT(rw_owner(&rwx->rwx_lock) == curthread); 1149 mutex_enter(&rwx->rwx_mutex); 1150 if (rwx->rwx_waiting) { 1151 rwx->rwx_waiting = B_FALSE; 1152 cv_broadcast(&rwx->rwx_cv); 1153 } 1154 mutex_exit(&rwx->rwx_mutex); 1155 } 1156 rw_exit(&rwx->rwx_lock); 1157 } 1158 1159 /* 1160 * smb_rwx_rwupgrade 1161 */ 1162 krw_t 1163 smb_rwx_rwupgrade( 1164 smb_rwx_t *rwx) 1165 { 1166 if (rw_write_held(&rwx->rwx_lock)) { 1167 ASSERT(rw_owner(&rwx->rwx_lock) == curthread); 1168 return (RW_WRITER); 1169 } 1170 if (!rw_tryupgrade(&rwx->rwx_lock)) { 1171 rw_exit(&rwx->rwx_lock); 1172 rw_enter(&rwx->rwx_lock, RW_WRITER); 1173 } 1174 return (RW_READER); 1175 } 1176 1177 /* 1178 * smb_rwx_rwrestore 1179 */ 1180 void 1181 smb_rwx_rwdowngrade( 1182 smb_rwx_t *rwx, 1183 krw_t mode) 1184 { 1185 ASSERT(rw_write_held(&rwx->rwx_lock)); 1186 ASSERT(rw_owner(&rwx->rwx_lock) == curthread); 1187 1188 if (mode == RW_WRITER) { 1189 return; 1190 } 1191 ASSERT(mode == RW_READER); 1192 mutex_enter(&rwx->rwx_mutex); 1193 if (rwx->rwx_waiting) { 1194 rwx->rwx_waiting = B_FALSE; 1195 cv_broadcast(&rwx->rwx_cv); 1196 } 1197 mutex_exit(&rwx->rwx_mutex); 1198 rw_downgrade(&rwx->rwx_lock); 1199 } 1200 1201 /* 1202 * smb_rwx_wait 1203 * 1204 * This function assumes the smb_rwx lock was enter in RW_READER or RW_WRITER 1205 * mode. It will: 1206 * 1207 * 1) release the lock and save its current mode. 1208 * 2) wait until the condition variable is signaled. This can happen for 1209 * 2 reasons: When a writer releases the lock or when the time out (if 1210 * provided) expires. 1211 * 3) re-acquire the lock in the mode saved in (1). 1212 */ 1213 int 1214 smb_rwx_rwwait( 1215 smb_rwx_t *rwx, 1216 clock_t timeout) 1217 { 1218 int rc; 1219 krw_t mode; 1220 1221 mutex_enter(&rwx->rwx_mutex); 1222 rwx->rwx_waiting = B_TRUE; 1223 mutex_exit(&rwx->rwx_mutex); 1224 1225 if (rw_write_held(&rwx->rwx_lock)) { 1226 ASSERT(rw_owner(&rwx->rwx_lock) == curthread); 1227 mode = RW_WRITER; 1228 } else { 1229 ASSERT(rw_read_held(&rwx->rwx_lock)); 1230 mode = RW_READER; 1231 } 1232 rw_exit(&rwx->rwx_lock); 1233 1234 mutex_enter(&rwx->rwx_mutex); 1235 if (rwx->rwx_waiting) { 1236 if (timeout == -1) { 1237 rc = 1; 1238 cv_wait(&rwx->rwx_cv, &rwx->rwx_mutex); 1239 } else { 1240 rc = cv_reltimedwait(&rwx->rwx_cv, &rwx->rwx_mutex, 1241 timeout, TR_CLOCK_TICK); 1242 } 1243 } 1244 mutex_exit(&rwx->rwx_mutex); 1245 1246 rw_enter(&rwx->rwx_lock, mode); 1247 return (rc); 1248 } 1249 1250 /* 1251 * SMB ID mapping 1252 * 1253 * Solaris ID mapping service (aka Winchester) works with domain SIDs 1254 * and RIDs where domain SIDs are in string format. CIFS service works 1255 * with binary SIDs understandable by CIFS clients. A layer of SMB ID 1256 * mapping functions are implemeted to hide the SID conversion details 1257 * and also hide the handling of array of batch mapping requests. 1258 * 1259 * IMPORTANT NOTE The Winchester API requires a zone. Because CIFS server 1260 * currently only runs in the global zone the global zone is specified. 1261 * This needs to be fixed when the CIFS server supports zones. 1262 */ 1263 1264 static int smb_idmap_batch_binsid(smb_idmap_batch_t *sib); 1265 1266 /* 1267 * smb_idmap_getid 1268 * 1269 * Maps the given Windows SID to a Solaris ID using the 1270 * simple mapping API. 1271 */ 1272 idmap_stat 1273 smb_idmap_getid(smb_sid_t *sid, uid_t *id, int *idtype) 1274 { 1275 smb_idmap_t sim; 1276 char sidstr[SMB_SID_STRSZ]; 1277 1278 smb_sid_tostr(sid, sidstr); 1279 if (smb_sid_splitstr(sidstr, &sim.sim_rid) != 0) 1280 return (IDMAP_ERR_SID); 1281 sim.sim_domsid = sidstr; 1282 sim.sim_id = id; 1283 1284 switch (*idtype) { 1285 case SMB_IDMAP_USER: 1286 sim.sim_stat = kidmap_getuidbysid(global_zone, sim.sim_domsid, 1287 sim.sim_rid, sim.sim_id); 1288 break; 1289 1290 case SMB_IDMAP_GROUP: 1291 sim.sim_stat = kidmap_getgidbysid(global_zone, sim.sim_domsid, 1292 sim.sim_rid, sim.sim_id); 1293 break; 1294 1295 case SMB_IDMAP_UNKNOWN: 1296 sim.sim_stat = kidmap_getpidbysid(global_zone, sim.sim_domsid, 1297 sim.sim_rid, sim.sim_id, &sim.sim_idtype); 1298 break; 1299 1300 default: 1301 ASSERT(0); 1302 return (IDMAP_ERR_ARG); 1303 } 1304 1305 *idtype = sim.sim_idtype; 1306 1307 return (sim.sim_stat); 1308 } 1309 1310 /* 1311 * smb_idmap_getsid 1312 * 1313 * Maps the given Solaris ID to a Windows SID using the 1314 * simple mapping API. 1315 */ 1316 idmap_stat 1317 smb_idmap_getsid(uid_t id, int idtype, smb_sid_t **sid) 1318 { 1319 smb_idmap_t sim; 1320 1321 switch (idtype) { 1322 case SMB_IDMAP_USER: 1323 sim.sim_stat = kidmap_getsidbyuid(global_zone, id, 1324 (const char **)&sim.sim_domsid, &sim.sim_rid); 1325 break; 1326 1327 case SMB_IDMAP_GROUP: 1328 sim.sim_stat = kidmap_getsidbygid(global_zone, id, 1329 (const char **)&sim.sim_domsid, &sim.sim_rid); 1330 break; 1331 1332 case SMB_IDMAP_EVERYONE: 1333 /* Everyone S-1-1-0 */ 1334 sim.sim_domsid = "S-1-1"; 1335 sim.sim_rid = 0; 1336 sim.sim_stat = IDMAP_SUCCESS; 1337 break; 1338 1339 default: 1340 ASSERT(0); 1341 return (IDMAP_ERR_ARG); 1342 } 1343 1344 if (sim.sim_stat != IDMAP_SUCCESS) 1345 return (sim.sim_stat); 1346 1347 if (sim.sim_domsid == NULL) 1348 return (IDMAP_ERR_NOMAPPING); 1349 1350 sim.sim_sid = smb_sid_fromstr(sim.sim_domsid); 1351 if (sim.sim_sid == NULL) 1352 return (IDMAP_ERR_INTERNAL); 1353 1354 *sid = smb_sid_splice(sim.sim_sid, sim.sim_rid); 1355 smb_sid_free(sim.sim_sid); 1356 if (*sid == NULL) 1357 sim.sim_stat = IDMAP_ERR_INTERNAL; 1358 1359 return (sim.sim_stat); 1360 } 1361 1362 /* 1363 * smb_idmap_batch_create 1364 * 1365 * Creates and initializes the context for batch ID mapping. 1366 */ 1367 idmap_stat 1368 smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags) 1369 { 1370 ASSERT(sib); 1371 1372 bzero(sib, sizeof (smb_idmap_batch_t)); 1373 1374 sib->sib_idmaph = kidmap_get_create(global_zone); 1375 1376 sib->sib_flags = flags; 1377 sib->sib_nmap = nmap; 1378 sib->sib_size = nmap * sizeof (smb_idmap_t); 1379 sib->sib_maps = kmem_zalloc(sib->sib_size, KM_SLEEP); 1380 1381 return (IDMAP_SUCCESS); 1382 } 1383 1384 /* 1385 * smb_idmap_batch_destroy 1386 * 1387 * Frees the batch ID mapping context. 1388 * If ID mapping is Solaris -> Windows it frees memories 1389 * allocated for binary SIDs. 1390 */ 1391 void 1392 smb_idmap_batch_destroy(smb_idmap_batch_t *sib) 1393 { 1394 char *domsid; 1395 int i; 1396 1397 ASSERT(sib); 1398 ASSERT(sib->sib_maps); 1399 1400 if (sib->sib_idmaph) 1401 kidmap_get_destroy(sib->sib_idmaph); 1402 1403 if (sib->sib_flags & SMB_IDMAP_ID2SID) { 1404 /* 1405 * SIDs are allocated only when mapping 1406 * UID/GID to SIDs 1407 */ 1408 for (i = 0; i < sib->sib_nmap; i++) 1409 smb_sid_free(sib->sib_maps[i].sim_sid); 1410 } else if (sib->sib_flags & SMB_IDMAP_SID2ID) { 1411 /* 1412 * SID prefixes are allocated only when mapping 1413 * SIDs to UID/GID 1414 */ 1415 for (i = 0; i < sib->sib_nmap; i++) { 1416 domsid = sib->sib_maps[i].sim_domsid; 1417 if (domsid) 1418 smb_mem_free(domsid); 1419 } 1420 } 1421 1422 if (sib->sib_size && sib->sib_maps) 1423 kmem_free(sib->sib_maps, sib->sib_size); 1424 } 1425 1426 /* 1427 * smb_idmap_batch_getid 1428 * 1429 * Queue a request to map the given SID to a UID or GID. 1430 * 1431 * sim->sim_id should point to variable that's supposed to 1432 * hold the returned UID/GID. This needs to be setup by caller 1433 * of this function. 1434 * 1435 * If requested ID type is known, it's passed as 'idtype', 1436 * if it's unknown it'll be returned in sim->sim_idtype. 1437 */ 1438 idmap_stat 1439 smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim, 1440 smb_sid_t *sid, int idtype) 1441 { 1442 char strsid[SMB_SID_STRSZ]; 1443 idmap_stat idm_stat; 1444 1445 ASSERT(idmaph); 1446 ASSERT(sim); 1447 ASSERT(sid); 1448 1449 smb_sid_tostr(sid, strsid); 1450 if (smb_sid_splitstr(strsid, &sim->sim_rid) != 0) 1451 return (IDMAP_ERR_SID); 1452 sim->sim_domsid = smb_mem_strdup(strsid); 1453 1454 switch (idtype) { 1455 case SMB_IDMAP_USER: 1456 idm_stat = kidmap_batch_getuidbysid(idmaph, sim->sim_domsid, 1457 sim->sim_rid, sim->sim_id, &sim->sim_stat); 1458 break; 1459 1460 case SMB_IDMAP_GROUP: 1461 idm_stat = kidmap_batch_getgidbysid(idmaph, sim->sim_domsid, 1462 sim->sim_rid, sim->sim_id, &sim->sim_stat); 1463 break; 1464 1465 case SMB_IDMAP_UNKNOWN: 1466 idm_stat = kidmap_batch_getpidbysid(idmaph, sim->sim_domsid, 1467 sim->sim_rid, sim->sim_id, &sim->sim_idtype, 1468 &sim->sim_stat); 1469 break; 1470 1471 default: 1472 ASSERT(0); 1473 return (IDMAP_ERR_ARG); 1474 } 1475 1476 return (idm_stat); 1477 } 1478 1479 /* 1480 * smb_idmap_batch_getsid 1481 * 1482 * Queue a request to map the given UID/GID to a SID. 1483 * 1484 * sim->sim_domsid and sim->sim_rid will contain the mapping 1485 * result upon successful process of the batched request. 1486 */ 1487 idmap_stat 1488 smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim, 1489 uid_t id, int idtype) 1490 { 1491 idmap_stat idm_stat; 1492 1493 switch (idtype) { 1494 case SMB_IDMAP_USER: 1495 idm_stat = kidmap_batch_getsidbyuid(idmaph, id, 1496 (const char **)&sim->sim_domsid, &sim->sim_rid, 1497 &sim->sim_stat); 1498 break; 1499 1500 case SMB_IDMAP_GROUP: 1501 idm_stat = kidmap_batch_getsidbygid(idmaph, id, 1502 (const char **)&sim->sim_domsid, &sim->sim_rid, 1503 &sim->sim_stat); 1504 break; 1505 1506 case SMB_IDMAP_OWNERAT: 1507 /* Current Owner S-1-5-32-766 */ 1508 sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR; 1509 sim->sim_rid = SECURITY_CURRENT_OWNER_RID; 1510 sim->sim_stat = IDMAP_SUCCESS; 1511 idm_stat = IDMAP_SUCCESS; 1512 break; 1513 1514 case SMB_IDMAP_GROUPAT: 1515 /* Current Group S-1-5-32-767 */ 1516 sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR; 1517 sim->sim_rid = SECURITY_CURRENT_GROUP_RID; 1518 sim->sim_stat = IDMAP_SUCCESS; 1519 idm_stat = IDMAP_SUCCESS; 1520 break; 1521 1522 case SMB_IDMAP_EVERYONE: 1523 /* Everyone S-1-1-0 */ 1524 sim->sim_domsid = NT_WORLD_AUTH_SIDSTR; 1525 sim->sim_rid = 0; 1526 sim->sim_stat = IDMAP_SUCCESS; 1527 idm_stat = IDMAP_SUCCESS; 1528 break; 1529 1530 default: 1531 ASSERT(0); 1532 return (IDMAP_ERR_ARG); 1533 } 1534 1535 return (idm_stat); 1536 } 1537 1538 /* 1539 * smb_idmap_batch_binsid 1540 * 1541 * Convert sidrids to binary sids 1542 * 1543 * Returns 0 if successful and non-zero upon failure. 1544 */ 1545 static int 1546 smb_idmap_batch_binsid(smb_idmap_batch_t *sib) 1547 { 1548 smb_sid_t *sid; 1549 smb_idmap_t *sim; 1550 int i; 1551 1552 if (sib->sib_flags & SMB_IDMAP_SID2ID) 1553 /* This operation is not required */ 1554 return (0); 1555 1556 sim = sib->sib_maps; 1557 for (i = 0; i < sib->sib_nmap; sim++, i++) { 1558 ASSERT(sim->sim_domsid); 1559 if (sim->sim_domsid == NULL) 1560 return (1); 1561 1562 if ((sid = smb_sid_fromstr(sim->sim_domsid)) == NULL) 1563 return (1); 1564 1565 sim->sim_sid = smb_sid_splice(sid, sim->sim_rid); 1566 smb_sid_free(sid); 1567 } 1568 1569 return (0); 1570 } 1571 1572 /* 1573 * smb_idmap_batch_getmappings 1574 * 1575 * trigger ID mapping service to get the mappings for queued 1576 * requests. 1577 * 1578 * Checks the result of all the queued requests. 1579 * If this is a Solaris -> Windows mapping it generates 1580 * binary SIDs from returned (domsid, rid) pairs. 1581 */ 1582 idmap_stat 1583 smb_idmap_batch_getmappings(smb_idmap_batch_t *sib) 1584 { 1585 idmap_stat idm_stat = IDMAP_SUCCESS; 1586 int i; 1587 1588 idm_stat = kidmap_get_mappings(sib->sib_idmaph); 1589 if (idm_stat != IDMAP_SUCCESS) 1590 return (idm_stat); 1591 1592 /* 1593 * Check the status for all the queued requests 1594 */ 1595 for (i = 0; i < sib->sib_nmap; i++) { 1596 if (sib->sib_maps[i].sim_stat != IDMAP_SUCCESS) 1597 return (sib->sib_maps[i].sim_stat); 1598 } 1599 1600 if (smb_idmap_batch_binsid(sib) != 0) 1601 idm_stat = IDMAP_ERR_OTHER; 1602 1603 return (idm_stat); 1604 } 1605 1606 uint64_t 1607 smb_time_unix_to_nt(timestruc_t *unix_time) 1608 { 1609 uint64_t nt_time; 1610 1611 if ((unix_time->tv_sec == 0) && (unix_time->tv_nsec == 0)) 1612 return (0); 1613 1614 nt_time = unix_time->tv_sec; 1615 nt_time *= 10000000; /* seconds to 100ns */ 1616 nt_time += unix_time->tv_nsec / 100; 1617 return (nt_time + NT_TIME_BIAS); 1618 } 1619 1620 void 1621 smb_time_nt_to_unix(uint64_t nt_time, timestruc_t *unix_time) 1622 { 1623 uint32_t seconds; 1624 1625 ASSERT(unix_time); 1626 1627 if ((nt_time == 0) || (nt_time == -1)) { 1628 unix_time->tv_sec = 0; 1629 unix_time->tv_nsec = 0; 1630 return; 1631 } 1632 1633 nt_time -= NT_TIME_BIAS; 1634 seconds = nt_time / 10000000; 1635 unix_time->tv_sec = seconds; 1636 unix_time->tv_nsec = (nt_time % 10000000) * 100; 1637 } 1638 1639 /* 1640 * smb_time_gmt_to_local, smb_time_local_to_gmt 1641 * 1642 * Apply the gmt offset to convert between local time and gmt 1643 */ 1644 int32_t 1645 smb_time_gmt_to_local(smb_request_t *sr, int32_t gmt) 1646 { 1647 if ((gmt == 0) || (gmt == -1)) 1648 return (0); 1649 1650 return (gmt - sr->sr_gmtoff); 1651 } 1652 1653 int32_t 1654 smb_time_local_to_gmt(smb_request_t *sr, int32_t local) 1655 { 1656 if ((local == 0) || (local == -1)) 1657 return (0); 1658 1659 return (local + sr->sr_gmtoff); 1660 } 1661 1662 1663 /* 1664 * smb_time_dos_to_unix 1665 * 1666 * Convert SMB_DATE & SMB_TIME values to a unix timestamp. 1667 * 1668 * A date/time field of 0 means that that server file system 1669 * assigned value need not be changed. The behaviour when the 1670 * date/time field is set to -1 is not documented but is 1671 * generally treated like 0. 1672 * If date or time is 0 or -1 the unix time is returned as 0 1673 * so that the caller can identify and handle this special case. 1674 */ 1675 int32_t 1676 smb_time_dos_to_unix(int16_t date, int16_t time) 1677 { 1678 struct tm atm; 1679 1680 if (((date == 0) || (time == 0)) || 1681 ((date == -1) || (time == -1))) { 1682 return (0); 1683 } 1684 1685 atm.tm_year = ((date >> 9) & 0x3F) + 80; 1686 atm.tm_mon = ((date >> 5) & 0x0F) - 1; 1687 atm.tm_mday = ((date >> 0) & 0x1F); 1688 atm.tm_hour = ((time >> 11) & 0x1F); 1689 atm.tm_min = ((time >> 5) & 0x3F); 1690 atm.tm_sec = ((time >> 0) & 0x1F) << 1; 1691 1692 return (smb_timegm(&atm)); 1693 } 1694 1695 void 1696 smb_time_unix_to_dos(int32_t ux_time, int16_t *date_p, int16_t *time_p) 1697 { 1698 struct tm atm; 1699 int i; 1700 time_t tmp_time; 1701 1702 if (ux_time == 0) { 1703 *date_p = 0; 1704 *time_p = 0; 1705 return; 1706 } 1707 1708 tmp_time = (time_t)ux_time; 1709 (void) smb_gmtime_r(&tmp_time, &atm); 1710 1711 if (date_p) { 1712 i = 0; 1713 i += atm.tm_year - 80; 1714 i <<= 4; 1715 i += atm.tm_mon + 1; 1716 i <<= 5; 1717 i += atm.tm_mday; 1718 1719 *date_p = (short)i; 1720 } 1721 if (time_p) { 1722 i = 0; 1723 i += atm.tm_hour; 1724 i <<= 6; 1725 i += atm.tm_min; 1726 i <<= 5; 1727 i += atm.tm_sec >> 1; 1728 1729 *time_p = (short)i; 1730 } 1731 } 1732 1733 1734 /* 1735 * smb_gmtime_r 1736 * 1737 * Thread-safe version of smb_gmtime. Returns a null pointer if either 1738 * input parameter is a null pointer. Otherwise returns a pointer 1739 * to result. 1740 * 1741 * Day of the week calculation: the Epoch was a thursday. 1742 * 1743 * There are no timezone corrections so tm_isdst and tm_gmtoff are 1744 * always zero, and the zone is always WET. 1745 */ 1746 struct tm * 1747 smb_gmtime_r(time_t *clock, struct tm *result) 1748 { 1749 time_t tsec; 1750 int year; 1751 int month; 1752 int sec_per_month; 1753 1754 if (clock == 0 || result == 0) 1755 return (0); 1756 1757 bzero(result, sizeof (struct tm)); 1758 tsec = *clock; 1759 tsec -= tzh_leapcnt; 1760 1761 result->tm_wday = tsec / SECSPERDAY; 1762 result->tm_wday = (result->tm_wday + TM_THURSDAY) % DAYSPERWEEK; 1763 1764 year = EPOCH_YEAR; 1765 while (tsec >= (isleap(year) ? (SECSPERDAY * DAYSPERLYEAR) : 1766 (SECSPERDAY * DAYSPERNYEAR))) { 1767 if (isleap(year)) 1768 tsec -= SECSPERDAY * DAYSPERLYEAR; 1769 else 1770 tsec -= SECSPERDAY * DAYSPERNYEAR; 1771 1772 ++year; 1773 } 1774 1775 result->tm_year = year - TM_YEAR_BASE; 1776 result->tm_yday = tsec / SECSPERDAY; 1777 1778 for (month = TM_JANUARY; month <= TM_DECEMBER; ++month) { 1779 sec_per_month = days_in_month[month] * SECSPERDAY; 1780 1781 if (month == TM_FEBRUARY && isleap(year)) 1782 sec_per_month += SECSPERDAY; 1783 1784 if (tsec < sec_per_month) 1785 break; 1786 1787 tsec -= sec_per_month; 1788 } 1789 1790 result->tm_mon = month; 1791 result->tm_mday = (tsec / SECSPERDAY) + 1; 1792 tsec %= SECSPERDAY; 1793 result->tm_sec = tsec % 60; 1794 tsec /= 60; 1795 result->tm_min = tsec % 60; 1796 tsec /= 60; 1797 result->tm_hour = (int)tsec; 1798 1799 return (result); 1800 } 1801 1802 1803 /* 1804 * smb_timegm 1805 * 1806 * Converts the broken-down time in tm to a time value, i.e. the number 1807 * of seconds since the Epoch (00:00:00 UTC, January 1, 1970). This is 1808 * not a POSIX or ANSI function. Per the man page, the input values of 1809 * tm_wday and tm_yday are ignored and, as the input data is assumed to 1810 * represent GMT, we force tm_isdst and tm_gmtoff to 0. 1811 * 1812 * Before returning the clock time, we use smb_gmtime_r to set up tm_wday 1813 * and tm_yday, and bring the other fields within normal range. I don't 1814 * think this is really how it should be done but it's convenient for 1815 * now. 1816 */ 1817 time_t 1818 smb_timegm(struct tm *tm) 1819 { 1820 time_t tsec; 1821 int dd; 1822 int mm; 1823 int yy; 1824 int year; 1825 1826 if (tm == 0) 1827 return (-1); 1828 1829 year = tm->tm_year + TM_YEAR_BASE; 1830 tsec = tzh_leapcnt; 1831 1832 for (yy = EPOCH_YEAR; yy < year; ++yy) { 1833 if (isleap(yy)) 1834 tsec += SECSPERDAY * DAYSPERLYEAR; 1835 else 1836 tsec += SECSPERDAY * DAYSPERNYEAR; 1837 } 1838 1839 for (mm = TM_JANUARY; mm < tm->tm_mon; ++mm) { 1840 dd = days_in_month[mm] * SECSPERDAY; 1841 1842 if (mm == TM_FEBRUARY && isleap(year)) 1843 dd += SECSPERDAY; 1844 1845 tsec += dd; 1846 } 1847 1848 tsec += (tm->tm_mday - 1) * SECSPERDAY; 1849 tsec += tm->tm_sec; 1850 tsec += tm->tm_min * SECSPERMIN; 1851 tsec += tm->tm_hour * SECSPERHOUR; 1852 1853 tm->tm_isdst = 0; 1854 (void) smb_gmtime_r(&tsec, tm); 1855 return (tsec); 1856 } 1857 1858 /* 1859 * smb_cred_set_sid 1860 * 1861 * Initialize the ksid based on the given smb_id_t. 1862 */ 1863 static void 1864 smb_cred_set_sid(smb_id_t *id, ksid_t *ksid) 1865 { 1866 char sidstr[SMB_SID_STRSZ]; 1867 int rc; 1868 1869 ASSERT(id); 1870 ASSERT(id->i_sid); 1871 1872 ksid->ks_id = id->i_id; 1873 smb_sid_tostr(id->i_sid, sidstr); 1874 rc = smb_sid_splitstr(sidstr, &ksid->ks_rid); 1875 ASSERT(rc == 0); 1876 1877 ksid->ks_attr = id->i_attrs; 1878 ksid->ks_domain = ksid_lookupdomain(sidstr); 1879 } 1880 1881 /* 1882 * smb_cred_set_sidlist 1883 * 1884 * Allocate and initialize the ksidlist based on the Windows group list of the 1885 * access token. 1886 */ 1887 static ksidlist_t * 1888 smb_cred_set_sidlist(smb_ids_t *token_grps) 1889 { 1890 int i; 1891 ksidlist_t *lp; 1892 1893 lp = kmem_zalloc(KSIDLIST_MEM(token_grps->i_cnt), KM_SLEEP); 1894 lp->ksl_ref = 1; 1895 lp->ksl_nsid = token_grps->i_cnt; 1896 lp->ksl_neid = 0; 1897 1898 for (i = 0; i < lp->ksl_nsid; i++) { 1899 smb_cred_set_sid(&token_grps->i_ids[i], &lp->ksl_sids[i]); 1900 if (lp->ksl_sids[i].ks_id > IDMAP_WK__MAX_GID) 1901 lp->ksl_neid++; 1902 } 1903 1904 return (lp); 1905 } 1906 1907 /* 1908 * A Solaris credential (cred_t structure) will be allocated and 1909 * initialized based on the given Windows style user access token. 1910 * 1911 * cred's gid is set to the primary group of the mapped Solaris user. 1912 * When there is no such mapped user (i.e. the mapped UID is ephemeral) 1913 * or his/her primary group could not be obtained, cred's gid is set to 1914 * the mapped Solaris group of token's primary group. 1915 */ 1916 cred_t * 1917 smb_cred_create(smb_token_t *token, uint32_t *privileges) 1918 { 1919 ksid_t ksid; 1920 ksidlist_t *ksidlist = NULL; 1921 smb_posix_grps_t *posix_grps; 1922 cred_t *cr; 1923 gid_t gid; 1924 1925 ASSERT(token); 1926 ASSERT(token->tkn_posix_grps); 1927 posix_grps = token->tkn_posix_grps; 1928 1929 ASSERT(privileges); 1930 1931 cr = crget(); 1932 ASSERT(cr != NULL); 1933 1934 if (!IDMAP_ID_IS_EPHEMERAL(token->tkn_user.i_id) && 1935 (posix_grps->pg_ngrps != 0)) { 1936 gid = posix_grps->pg_grps[0]; 1937 } else { 1938 gid = token->tkn_primary_grp.i_id; 1939 } 1940 1941 if (crsetugid(cr, token->tkn_user.i_id, gid) != 0) { 1942 crfree(cr); 1943 return (NULL); 1944 } 1945 1946 if (crsetgroups(cr, posix_grps->pg_ngrps, posix_grps->pg_grps) != 0) { 1947 crfree(cr); 1948 return (NULL); 1949 } 1950 1951 smb_cred_set_sid(&token->tkn_user, &ksid); 1952 crsetsid(cr, &ksid, KSID_USER); 1953 smb_cred_set_sid(&token->tkn_primary_grp, &ksid); 1954 crsetsid(cr, &ksid, KSID_GROUP); 1955 smb_cred_set_sid(&token->tkn_owner, &ksid); 1956 crsetsid(cr, &ksid, KSID_OWNER); 1957 ksidlist = smb_cred_set_sidlist(&token->tkn_win_grps); 1958 crsetsidlist(cr, ksidlist); 1959 1960 *privileges = 0; 1961 1962 if (smb_token_query_privilege(token, SE_BACKUP_LUID)) 1963 *privileges |= SMB_USER_PRIV_BACKUP; 1964 1965 if (smb_token_query_privilege(token, SE_RESTORE_LUID)) 1966 *privileges |= SMB_USER_PRIV_RESTORE; 1967 1968 if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID)) { 1969 *privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP; 1970 (void) crsetpriv(cr, PRIV_FILE_CHOWN, NULL); 1971 } 1972 1973 if (smb_token_query_privilege(token, SE_SECURITY_LUID)) 1974 *privileges |= SMB_USER_PRIV_SECURITY; 1975 1976 return (cr); 1977 } 1978 1979 /* 1980 * smb_cred_rele 1981 * 1982 * The reference count of the user's credential will get decremented if it 1983 * is non-zero. Otherwise, the credential will be freed. 1984 */ 1985 void 1986 smb_cred_rele(cred_t *cr) 1987 { 1988 ASSERT(cr); 1989 crfree(cr); 1990 } 1991 1992 /* 1993 * smb_cred_is_member 1994 * 1995 * Same as smb_token_is_member. The only difference is that 1996 * we compare the given SID against user SID and the ksidlist 1997 * of the user's cred. 1998 */ 1999 int 2000 smb_cred_is_member(cred_t *cr, smb_sid_t *sid) 2001 { 2002 ksidlist_t *ksidlist; 2003 ksid_t ksid1, *ksid2; 2004 smb_id_t id; 2005 int i, rc = 0; 2006 2007 ASSERT(cr); 2008 2009 bzero(&id, sizeof (smb_id_t)); 2010 id.i_sid = sid; 2011 smb_cred_set_sid(&id, &ksid1); 2012 2013 ksidlist = crgetsidlist(cr); 2014 ASSERT(ksidlist); 2015 ASSERT(ksid1.ks_domain); 2016 ASSERT(ksid1.ks_domain->kd_name); 2017 2018 i = 0; 2019 ksid2 = crgetsid(cr, KSID_USER); 2020 do { 2021 ASSERT(ksid2->ks_domain); 2022 ASSERT(ksid2->ks_domain->kd_name); 2023 2024 if (strcmp(ksid1.ks_domain->kd_name, 2025 ksid2->ks_domain->kd_name) == 0 && 2026 ksid1.ks_rid == ksid2->ks_rid) { 2027 rc = 1; 2028 break; 2029 } 2030 2031 ksid2 = &ksidlist->ksl_sids[i]; 2032 } while (i++ < ksidlist->ksl_nsid); 2033 2034 ksid_rele(&ksid1); 2035 return (rc); 2036 } 2037 2038 /* 2039 * smb_cred_create_privs 2040 * 2041 * Creates a duplicate credential that contains system privileges for 2042 * certain SMB privileges: Backup and Restore. 2043 * 2044 */ 2045 cred_t * 2046 smb_cred_create_privs(cred_t *user_cr, uint32_t privileges) 2047 { 2048 cred_t *cr = NULL; 2049 2050 ASSERT(user_cr != NULL); 2051 2052 if (privileges & (SMB_USER_PRIV_BACKUP | SMB_USER_PRIV_RESTORE)) 2053 cr = crdup(user_cr); 2054 2055 if (cr == NULL) 2056 return (NULL); 2057 2058 if (privileges & SMB_USER_PRIV_BACKUP) { 2059 (void) crsetpriv(cr, PRIV_FILE_DAC_READ, 2060 PRIV_FILE_DAC_SEARCH, PRIV_SYS_MOUNT, NULL); 2061 } 2062 2063 if (privileges & SMB_USER_PRIV_RESTORE) { 2064 (void) crsetpriv(cr, PRIV_FILE_DAC_WRITE, 2065 PRIV_FILE_CHOWN, PRIV_FILE_CHOWN_SELF, 2066 PRIV_FILE_DAC_SEARCH, PRIV_FILE_LINK_ANY, 2067 PRIV_FILE_OWNER, PRIV_FILE_SETID, PRIV_SYS_LINKDIR, 2068 PRIV_SYS_MOUNT, NULL); 2069 } 2070 2071 return (cr); 2072 } 2073 2074 /* 2075 * smb_pad_align 2076 * 2077 * Returns the number of bytes required to pad an offset to the 2078 * specified alignment. 2079 */ 2080 uint32_t 2081 smb_pad_align(uint32_t offset, uint32_t align) 2082 { 2083 uint32_t pad = offset % align; 2084 2085 if (pad != 0) 2086 pad = align - pad; 2087 2088 return (pad); 2089 } 2090 2091 /* 2092 * smb_panic 2093 * 2094 * Logs the file name, function name and line number passed in and panics the 2095 * system. 2096 */ 2097 void 2098 smb_panic(char *file, const char *func, int line) 2099 { 2100 cmn_err(CE_PANIC, "%s:%s:%d\n", file, func, line); 2101 } 2102