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