xref: /illumos-gate/usr/src/common/smbsrv/smb_sid.c (revision d9be5d44a919e9dbfe9d1e3e7a5557d9208b1de7)
1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21da6c28aaSamw /*
22148c5f43SAlan Wright  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23*d9be5d44SMatt Barden  * Copyright 2022 Tintri by DDN, Inc. All rights reserved.
24da6c28aaSamw  */
25da6c28aaSamw 
26b819cea2SGordon Ross #if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
27da6c28aaSamw #include <stdio.h>
28da6c28aaSamw #include <strings.h>
29da6c28aaSamw #include <stdlib.h>
30da6c28aaSamw #include <syslog.h>
31b819cea2SGordon Ross #else	/* !_KERNEL && !_FAKE_KERNEL */
32*d9be5d44SMatt Barden #include <sys/int_limits.h> /* Needed for _FAKE_KERNEL */
33da6c28aaSamw #include <sys/types.h>
34b819cea2SGordon Ross #include <sys/systm.h>
35da6c28aaSamw #include <sys/sunddi.h>
36b819cea2SGordon Ross #endif	/* !_KERNEL && !_FAKE_KERNEL */
37da6c28aaSamw 
386537f381Sas200622 #include <smbsrv/smb_sid.h>
39da6c28aaSamw 
406537f381Sas200622 static smb_sid_t *smb_sid_alloc(size_t);
41da6c28aaSamw 
42da6c28aaSamw /*
436537f381Sas200622  * smb_sid_isvalid
44da6c28aaSamw  *
456537f381Sas200622  * Performs a minimal SID validation.
46da6c28aaSamw  */
476537f381Sas200622 boolean_t
smb_sid_isvalid(smb_sid_t * sid)486537f381Sas200622 smb_sid_isvalid(smb_sid_t *sid)
49da6c28aaSamw {
506537f381Sas200622 	if (sid == NULL)
516537f381Sas200622 		return (B_FALSE);
52da6c28aaSamw 
536537f381Sas200622 	return ((sid->sid_revision == NT_SID_REVISION) &&
54*d9be5d44SMatt Barden 	    (sid->sid_subauthcnt <= NT_SID_SUBAUTH_MAX));
55da6c28aaSamw }
56da6c28aaSamw 
57da6c28aaSamw /*
586537f381Sas200622  * smb_sid_len
59da6c28aaSamw  *
60da6c28aaSamw  * Returns the number of bytes required to hold the sid.
61da6c28aaSamw  */
62da6c28aaSamw int
smb_sid_len(smb_sid_t * sid)636537f381Sas200622 smb_sid_len(smb_sid_t *sid)
64da6c28aaSamw {
656537f381Sas200622 	if (sid == NULL)
66da6c28aaSamw 		return (0);
67da6c28aaSamw 
686537f381Sas200622 	return (sizeof (smb_sid_t) - sizeof (uint32_t)
696537f381Sas200622 	    + (sid->sid_subauthcnt * sizeof (uint32_t)));
70da6c28aaSamw }
71da6c28aaSamw 
72da6c28aaSamw /*
736537f381Sas200622  * smb_sid_dup
74da6c28aaSamw  *
756537f381Sas200622  * Make a duplicate of the specified sid. The memory for the new sid
766537f381Sas200622  * should be freed by calling smb_sid_free().
776537f381Sas200622  * A pointer to the new sid is returned.
78da6c28aaSamw  */
796537f381Sas200622 smb_sid_t *
smb_sid_dup(smb_sid_t * sid)806537f381Sas200622 smb_sid_dup(smb_sid_t *sid)
81da6c28aaSamw {
826537f381Sas200622 	smb_sid_t *new_sid;
83da6c28aaSamw 	int size;
84da6c28aaSamw 
856537f381Sas200622 	if (sid == NULL)
866537f381Sas200622 		return (NULL);
87da6c28aaSamw 
886537f381Sas200622 	size = smb_sid_len(sid);
896537f381Sas200622 	if ((new_sid = smb_sid_alloc(size)) == NULL)
906537f381Sas200622 		return (NULL);
91da6c28aaSamw 
926537f381Sas200622 	bcopy(sid, new_sid, size);
93da6c28aaSamw 	return (new_sid);
94da6c28aaSamw }
95da6c28aaSamw 
96da6c28aaSamw 
97da6c28aaSamw /*
986537f381Sas200622  * smb_sid_splice
99da6c28aaSamw  *
1006537f381Sas200622  * Make a full sid from a domain sid and a relative id (rid).
1016537f381Sas200622  * The memory for the result sid should be freed by calling
1026537f381Sas200622  * smb_sid_free(). A pointer to the new sid is returned.
103da6c28aaSamw  */
1046537f381Sas200622 smb_sid_t *
smb_sid_splice(smb_sid_t * domain_sid,uint32_t rid)1056537f381Sas200622 smb_sid_splice(smb_sid_t *domain_sid, uint32_t rid)
106da6c28aaSamw {
1076537f381Sas200622 	smb_sid_t *sid;
108da6c28aaSamw 	int size;
109da6c28aaSamw 
1106537f381Sas200622 	if (domain_sid == NULL)
1116537f381Sas200622 		return (NULL);
112da6c28aaSamw 
1136537f381Sas200622 	size = smb_sid_len(domain_sid);
1146537f381Sas200622 	if ((sid = smb_sid_alloc(size + sizeof (rid))) == NULL)
1156537f381Sas200622 		return (NULL);
116da6c28aaSamw 
1176537f381Sas200622 	bcopy(domain_sid, sid, size);
118da6c28aaSamw 
1196537f381Sas200622 	sid->sid_subauth[domain_sid->sid_subauthcnt] = rid;
1206537f381Sas200622 	++sid->sid_subauthcnt;
121da6c28aaSamw 
122da6c28aaSamw 	return (sid);
123da6c28aaSamw }
124da6c28aaSamw 
125da6c28aaSamw /*
1266537f381Sas200622  * smb_sid_getrid
127da6c28aaSamw  *
1286537f381Sas200622  * Return the Relative Id (RID) of the specified SID. It is the
129da6c28aaSamw  * caller's responsibility to ensure that this is an appropriate SID.
130da6c28aaSamw  * All we do here is return the last sub-authority from the SID.
131da6c28aaSamw  */
132da6c28aaSamw int
smb_sid_getrid(smb_sid_t * sid,uint32_t * rid)1336537f381Sas200622 smb_sid_getrid(smb_sid_t *sid, uint32_t *rid)
134da6c28aaSamw {
1356537f381Sas200622 	if (!smb_sid_isvalid(sid) || (rid == NULL) ||
1366537f381Sas200622 	    (sid->sid_subauthcnt == 0))
137da6c28aaSamw 		return (-1);
138da6c28aaSamw 
1396537f381Sas200622 	*rid = sid->sid_subauth[sid->sid_subauthcnt - 1];
140da6c28aaSamw 	return (0);
141da6c28aaSamw }
142da6c28aaSamw 
143da6c28aaSamw /*
1446537f381Sas200622  * smb_sid_split
145da6c28aaSamw  *
1466537f381Sas200622  * Take a full sid and split it into a domain sid and a relative id (rid).
1477f667e74Sjose borrego  * The domain SID is allocated and a pointer to it will be returned. The
1487f667e74Sjose borrego  * RID value is passed back in 'rid' arg if it's not NULL. The allocated
1497f667e74Sjose borrego  * memory for the domain SID must be freed by caller.
150da6c28aaSamw  */
1517f667e74Sjose borrego smb_sid_t *
smb_sid_split(smb_sid_t * sid,uint32_t * rid)1526537f381Sas200622 smb_sid_split(smb_sid_t *sid, uint32_t *rid)
153da6c28aaSamw {
1547f667e74Sjose borrego 	smb_sid_t *domsid;
155b819cea2SGordon Ross 	int size;
156da6c28aaSamw 
1577f667e74Sjose borrego 	if (!smb_sid_isvalid(sid) || (sid->sid_subauthcnt == 0))
1587f667e74Sjose borrego 		return (NULL);
1597f667e74Sjose borrego 
160e16c88fbSGordon Ross 	/*
161e16c88fbSGordon Ross 	 * We will reduce sid_subauthcnt by one, because
162e16c88fbSGordon Ross 	 * the domain SID does not include the RID.
163e16c88fbSGordon Ross 	 */
164b819cea2SGordon Ross 	size = smb_sid_len(sid) - sizeof (uint32_t);
165b819cea2SGordon Ross 	if ((domsid = smb_sid_alloc(size)) == NULL)
1667f667e74Sjose borrego 		return (NULL);
1677f667e74Sjose borrego 
168b819cea2SGordon Ross 	bcopy(sid, domsid, size);
169b819cea2SGordon Ross 	domsid->sid_subauthcnt = sid->sid_subauthcnt - 1;
170b819cea2SGordon Ross 
171da6c28aaSamw 	if (rid)
172e16c88fbSGordon Ross 		*rid = sid->sid_subauth[sid->sid_subauthcnt - 1];
1737f667e74Sjose borrego 
1747f667e74Sjose borrego 	return (domsid);
175da6c28aaSamw }
176da6c28aaSamw 
177da6c28aaSamw /*
1786537f381Sas200622  * smb_sid_splitstr
179da6c28aaSamw  *
1806537f381Sas200622  * Takes a full sid in string form and split it into a domain sid and a
1816537f381Sas200622  * relative id (rid).
1826537f381Sas200622  *
1836537f381Sas200622  * IMPORTANT: The original sid is modified in place. This function assumes
1846537f381Sas200622  * given SID is in valid string format.
185da6c28aaSamw  */
1866537f381Sas200622 int
smb_sid_splitstr(char * strsid,uint32_t * rid)1876537f381Sas200622 smb_sid_splitstr(char *strsid, uint32_t *rid)
188da6c28aaSamw {
1896537f381Sas200622 	char *p;
190da6c28aaSamw 
1916537f381Sas200622 	if ((p = strrchr(strsid, '-')) == NULL)
1926537f381Sas200622 		return (-1);
193da6c28aaSamw 
1946537f381Sas200622 	*p++ = '\0';
1956537f381Sas200622 	if (rid) {
196b819cea2SGordon Ross #if defined(_KERNEL) || defined(_FAKE_KERNEL)
1976537f381Sas200622 		unsigned long sua = 0;
1986537f381Sas200622 		(void) ddi_strtoul(p, NULL, 10, &sua);
1996537f381Sas200622 		*rid = (uint32_t)sua;
2006537f381Sas200622 #else
2016537f381Sas200622 		*rid = strtoul(p, NULL, 10);
2026537f381Sas200622 #endif
2036537f381Sas200622 	}
2046537f381Sas200622 
205da6c28aaSamw 	return (0);
206da6c28aaSamw }
207da6c28aaSamw 
208da6c28aaSamw /*
2096537f381Sas200622  * smb_sid_cmp
210da6c28aaSamw  *
211da6c28aaSamw  * Compare two SIDs and return a boolean result. The checks are ordered
212da6c28aaSamw  * such that components that are more likely to differ are checked
213da6c28aaSamw  * first. For example, after checking that the SIDs contain the same
2146537f381Sas200622  * sid_subauthcnt, we check the sub-authorities in reverse order because
215da6c28aaSamw  * the RID is the most likely differentiator between two SIDs, i.e.
216da6c28aaSamw  * they are probably going to be in the same domain.
217da6c28aaSamw  */
2186537f381Sas200622 boolean_t
smb_sid_cmp(smb_sid_t * sid1,smb_sid_t * sid2)2196537f381Sas200622 smb_sid_cmp(smb_sid_t *sid1, smb_sid_t *sid2)
220da6c28aaSamw {
221da6c28aaSamw 	int i;
222da6c28aaSamw 
2236537f381Sas200622 	if (sid1 == NULL || sid2 == NULL)
2246537f381Sas200622 		return (B_FALSE);
225da6c28aaSamw 
2266537f381Sas200622 	if (sid1->sid_subauthcnt != sid2->sid_subauthcnt ||
2276537f381Sas200622 	    sid1->sid_revision != sid2->sid_revision)
2286537f381Sas200622 		return (B_FALSE);
229da6c28aaSamw 
2306537f381Sas200622 	for (i = sid1->sid_subauthcnt - 1; i >= 0; --i)
2316537f381Sas200622 		if (sid1->sid_subauth[i] != sid2->sid_subauth[i])
2326537f381Sas200622 			return (B_FALSE);
233da6c28aaSamw 
2346537f381Sas200622 	if (bcmp(&sid1->sid_authority, &sid2->sid_authority, NT_SID_AUTH_MAX))
2356537f381Sas200622 		return (B_FALSE);
236da6c28aaSamw 
2376537f381Sas200622 	return (B_TRUE);
238da6c28aaSamw }
239da6c28aaSamw 
240da6c28aaSamw /*
2416537f381Sas200622  * smb_sid_indomain
242da6c28aaSamw  *
243da6c28aaSamw  * Check if given SID is in given domain.
244da6c28aaSamw  */
2456537f381Sas200622 boolean_t
smb_sid_indomain(smb_sid_t * domain_sid,smb_sid_t * sid)2466537f381Sas200622 smb_sid_indomain(smb_sid_t *domain_sid, smb_sid_t *sid)
247da6c28aaSamw {
248da6c28aaSamw 	int i;
249da6c28aaSamw 
2506537f381Sas200622 	if (sid == NULL || domain_sid == NULL)
2516537f381Sas200622 		return (B_FALSE);
252da6c28aaSamw 
2536537f381Sas200622 	if (domain_sid->sid_revision != sid->sid_revision ||
2546537f381Sas200622 	    sid->sid_subauthcnt < domain_sid->sid_subauthcnt)
2556537f381Sas200622 		return (B_FALSE);
256da6c28aaSamw 
2576537f381Sas200622 	for (i = domain_sid->sid_subauthcnt - 1; i >= 0; --i)
2586537f381Sas200622 		if (domain_sid->sid_subauth[i] != sid->sid_subauth[i])
2596537f381Sas200622 			return (B_FALSE);
260da6c28aaSamw 
2616537f381Sas200622 	if (bcmp(&domain_sid->sid_authority, &sid->sid_authority,
2626537f381Sas200622 	    NT_SID_AUTH_MAX))
2636537f381Sas200622 		return (B_FALSE);
264da6c28aaSamw 
2656537f381Sas200622 	return (B_TRUE);
266da6c28aaSamw }
267da6c28aaSamw 
268da6c28aaSamw /*
2696537f381Sas200622  * smb_sid_tostr
270da6c28aaSamw  *
2716537f381Sas200622  * Fill in the passed buffer with the string form of the given
2726537f381Sas200622  * binary sid.
273da6c28aaSamw  */
274da6c28aaSamw void
smb_sid_tostr(const smb_sid_t * sid,char * strsid)275148c5f43SAlan Wright smb_sid_tostr(const smb_sid_t *sid, char *strsid)
276da6c28aaSamw {
2776537f381Sas200622 	char *p = strsid;
2786537f381Sas200622 	int i;
279da6c28aaSamw 
2806537f381Sas200622 	if (sid == NULL || strsid == NULL)
281da6c28aaSamw 		return;
282da6c28aaSamw 
2836537f381Sas200622 	(void) sprintf(p, "S-%d-", sid->sid_revision);
284da6c28aaSamw 	while (*p)
2856537f381Sas200622 		p++;
286da6c28aaSamw 
287da6c28aaSamw 	for (i = 0; i < NT_SID_AUTH_MAX; ++i) {
2886537f381Sas200622 		if (sid->sid_authority[i] != 0 || i == NT_SID_AUTH_MAX - 1) {
2896537f381Sas200622 			(void) sprintf(p, "%d", sid->sid_authority[i]);
290da6c28aaSamw 			while (*p)
2916537f381Sas200622 				p++;
292da6c28aaSamw 		}
293da6c28aaSamw 	}
294da6c28aaSamw 
2956537f381Sas200622 	for (i = 0; i < sid->sid_subauthcnt && i < NT_SID_SUBAUTH_MAX; ++i) {
2966537f381Sas200622 		(void) sprintf(p, "-%u", sid->sid_subauth[i]);
297da6c28aaSamw 		while (*p)
2986537f381Sas200622 			p++;
299da6c28aaSamw 	}
300da6c28aaSamw }
301da6c28aaSamw 
302da6c28aaSamw /*
3036537f381Sas200622  * smb_sid_fromstr
304da6c28aaSamw  *
305da6c28aaSamw  * Converts a SID in string form to a SID structure. There are lots of
306da6c28aaSamw  * simplifying assumptions in here. The memory for the SID is allocated
307da6c28aaSamw  * as if it was the largest possible SID; the caller is responsible for
308da6c28aaSamw  * freeing the memory when it is no longer required. We assume that the
309da6c28aaSamw  * string starts with "S-1-" and that the authority is held in the last
310da6c28aaSamw  * byte, which should be okay for most situations. It also assumes the
311da6c28aaSamw  * sub-authorities are in decimal format.
312da6c28aaSamw  *
313da6c28aaSamw  * On success, a pointer to a SID is returned. Otherwise a null pointer
314da6c28aaSamw  * is returned.
315da6c28aaSamw  */
316b819cea2SGordon Ross #if defined(_KERNEL) || defined(_FAKE_KERNEL)
3176537f381Sas200622 smb_sid_t *
smb_sid_fromstr(const char * sidstr)318148c5f43SAlan Wright smb_sid_fromstr(const char *sidstr)
319da6c28aaSamw {
3206537f381Sas200622 	smb_sid_t *sid;
321*d9be5d44SMatt Barden 	smb_sid_t *retsid = NULL;
322148c5f43SAlan Wright 	const char *p;
323da6c28aaSamw 	int size;
3246537f381Sas200622 	uint8_t i;
3256537f381Sas200622 	unsigned long sua;
326da6c28aaSamw 
3276537f381Sas200622 	if (sidstr == NULL)
3286537f381Sas200622 		return (NULL);
329da6c28aaSamw 
3306537f381Sas200622 	if (strncmp(sidstr, "S-1-", 4) != 0)
3316537f381Sas200622 		return (NULL);
332da6c28aaSamw 
333*d9be5d44SMatt Barden 	sua = 0;
334*d9be5d44SMatt Barden 	(void) ddi_strtoul(&sidstr[4], (char **)&p, 10, &sua);
335*d9be5d44SMatt Barden 
336*d9be5d44SMatt Barden 	/*
337*d9be5d44SMatt Barden 	 * If ddi_strtoul() did the right thing, *p will point at the first '-'
338*d9be5d44SMatt Barden 	 * after the identifier authority.
339*d9be5d44SMatt Barden 	 * The IdentifierAuthority can be up to 2^48, but all known ones
340*d9be5d44SMatt Barden 	 * currently fit into a uint8_t.
341*d9be5d44SMatt Barden 	 * TODO: support IdentifierAuthorities > 255 (those over UINT32_MAX are
342*d9be5d44SMatt Barden 	 * hex-formatted).
343*d9be5d44SMatt Barden 	 */
344*d9be5d44SMatt Barden 	if (sua > UINT8_MAX || (*p != '-' && *p != '\0'))
345*d9be5d44SMatt Barden 		return (NULL);
346*d9be5d44SMatt Barden 
3476537f381Sas200622 	size = sizeof (smb_sid_t) + (NT_SID_SUBAUTH_MAX * sizeof (uint32_t));
3486537f381Sas200622 	sid = kmem_zalloc(size, KM_SLEEP);
3496537f381Sas200622 	sid->sid_revision = NT_SID_REVISION;
3506537f381Sas200622 	sid->sid_authority[5] = (uint8_t)sua;
351da6c28aaSamw 
352*d9be5d44SMatt Barden 	for (i = 0; i < NT_SID_SUBAUTH_MAX && *p; ++i) {
353*d9be5d44SMatt Barden 		while (*p == '-')
354da6c28aaSamw 			++p;
355da6c28aaSamw 
356*d9be5d44SMatt Barden 		if (*p < '0' || *p > '9')
357*d9be5d44SMatt Barden 			goto out;
358da6c28aaSamw 
359da6c28aaSamw 		sua = 0;
360*d9be5d44SMatt Barden 		(void) ddi_strtoul(p, (char **)&p, 10, &sua);
361*d9be5d44SMatt Barden 		if (sua > UINT32_MAX)
362*d9be5d44SMatt Barden 			goto out;
3636537f381Sas200622 		sid->sid_subauth[i] = (uint32_t)sua;
364da6c28aaSamw 
365*d9be5d44SMatt Barden 		if (*p != '\0' && *p != '-')
366*d9be5d44SMatt Barden 			goto out;
367da6c28aaSamw 	}
368da6c28aaSamw 
3696537f381Sas200622 	sid->sid_subauthcnt = i;
3706537f381Sas200622 	retsid = smb_sid_dup(sid);
3716537f381Sas200622 
372*d9be5d44SMatt Barden out:
373*d9be5d44SMatt Barden 	kmem_free(sid, size);
3746537f381Sas200622 	return (retsid);
3756537f381Sas200622 }
3766537f381Sas200622 #else /* _KERNEL */
3776537f381Sas200622 smb_sid_t *
smb_sid_fromstr(const char * sidstr)378148c5f43SAlan Wright smb_sid_fromstr(const char *sidstr)
3796537f381Sas200622 {
3806537f381Sas200622 	smb_sid_t *sid;
381148c5f43SAlan Wright 	const char *p;
3826537f381Sas200622 	int size;
3836537f381Sas200622 	uint8_t i;
384*d9be5d44SMatt Barden 	unsigned long sua;
3856537f381Sas200622 
3866537f381Sas200622 	if (sidstr == NULL)
3876537f381Sas200622 		return (NULL);
3886537f381Sas200622 
3896537f381Sas200622 	if (strncmp(sidstr, "S-1-", 4) != 0)
3906537f381Sas200622 		return (NULL);
3916537f381Sas200622 
392*d9be5d44SMatt Barden 	sua = strtoul(&sidstr[4], (char **)&p, 10);
3936537f381Sas200622 
394*d9be5d44SMatt Barden 	/*
395*d9be5d44SMatt Barden 	 * If strtoul() did the right thing, *p will point at the first '-'
396*d9be5d44SMatt Barden 	 * after the identifier authority.
397*d9be5d44SMatt Barden 	 * The IdentifierAuthority can be up to 2^48, but all known ones
398*d9be5d44SMatt Barden 	 * currently fit into a uint8_t.
399*d9be5d44SMatt Barden 	 * TODO: support IdentifierAuthorities > 255 (those over UINT32_MAX are
400*d9be5d44SMatt Barden 	 * hex-formatted).
401*d9be5d44SMatt Barden 	 */
402*d9be5d44SMatt Barden 	if (sua > UINT8_MAX || (*p != '-' && *p != '\0'))
4036537f381Sas200622 		return (NULL);
4046537f381Sas200622 
405*d9be5d44SMatt Barden 	size = sizeof (smb_sid_t) + (NT_SID_SUBAUTH_MAX * sizeof (uint32_t));
4066537f381Sas200622 
407*d9be5d44SMatt Barden 	if ((sid = calloc(size, 1)) == NULL)
408*d9be5d44SMatt Barden 		return (NULL);
409*d9be5d44SMatt Barden 
410*d9be5d44SMatt Barden 	sid->sid_revision = NT_SID_REVISION;
411*d9be5d44SMatt Barden 	sid->sid_authority[5] = (uint8_t)sua;
412*d9be5d44SMatt Barden 
413*d9be5d44SMatt Barden 	for (i = 0; i < NT_SID_SUBAUTH_MAX && *p; ++i) {
414*d9be5d44SMatt Barden 		while (*p == '-')
4156537f381Sas200622 			++p;
4166537f381Sas200622 
4176537f381Sas200622 		if (*p < '0' || *p > '9') {
4186537f381Sas200622 			free(sid);
4196537f381Sas200622 			return (NULL);
420da6c28aaSamw 		}
421da6c28aaSamw 
422*d9be5d44SMatt Barden 		sid->sid_subauth[i] = strtoul(p, (char **)&p, 10);
423*d9be5d44SMatt Barden 		if (*p != '\0' && *p != '-') {
424*d9be5d44SMatt Barden 			free(sid);
425*d9be5d44SMatt Barden 			return (NULL);
426*d9be5d44SMatt Barden 		}
4276537f381Sas200622 	}
4286537f381Sas200622 
4296537f381Sas200622 	sid->sid_subauthcnt = i;
4306537f381Sas200622 	return (sid);
4316537f381Sas200622 }
4326537f381Sas200622 #endif /* _KERNEL */
433da6c28aaSamw 
434da6c28aaSamw /*
4356537f381Sas200622  * smb_sid_type2str
436da6c28aaSamw  *
437da6c28aaSamw  * Returns the text name for a SID_NAME_USE value. The SID_NAME_USE
438da6c28aaSamw  * provides the context for a SID, i.e. the type of resource to which
439da6c28aaSamw  * it refers.
440da6c28aaSamw  */
441da6c28aaSamw char *
smb_sid_type2str(uint16_t snu_id)4426537f381Sas200622 smb_sid_type2str(uint16_t snu_id)
443da6c28aaSamw {
444da6c28aaSamw 	static char *snu_name[] = {
445da6c28aaSamw 		"SidTypeSidPrefix",
446da6c28aaSamw 		"SidTypeUser",
447da6c28aaSamw 		"SidTypeGroup",
448da6c28aaSamw 		"SidTypeDomain",
449da6c28aaSamw 		"SidTypeAlias",
450da6c28aaSamw 		"SidTypeWellKnownGroup",
451da6c28aaSamw 		"SidTypeDeletedAccount",
452da6c28aaSamw 		"SidTypeInvalid",
453fe1c642dSBill Krier 		"SidTypeUnknown",
454fe1c642dSBill Krier 		"SidTypeComputer",
455fe1c642dSBill Krier 		"SidTypeLabel"
456da6c28aaSamw 	};
457da6c28aaSamw 
458da6c28aaSamw 	if (snu_id < ((sizeof (snu_name)/sizeof (snu_name[0]))))
459da6c28aaSamw 		return (snu_name[snu_id]);
4606537f381Sas200622 
461da6c28aaSamw 	return (snu_name[SidTypeUnknown]);
462da6c28aaSamw }
4636537f381Sas200622 
4646537f381Sas200622 static smb_sid_t *
smb_sid_alloc(size_t size)4656537f381Sas200622 smb_sid_alloc(size_t size)
4666537f381Sas200622 {
4676537f381Sas200622 	smb_sid_t *sid;
468b819cea2SGordon Ross #if defined(_KERNEL) || defined(_FAKE_KERNEL)
4696537f381Sas200622 	sid = kmem_alloc(size, KM_SLEEP);
4706537f381Sas200622 #else
4716537f381Sas200622 	sid = malloc(size);
4726537f381Sas200622 #endif
4736537f381Sas200622 	return (sid);
474da6c28aaSamw }
475da6c28aaSamw 
4766537f381Sas200622 void
smb_sid_free(smb_sid_t * sid)4776537f381Sas200622 smb_sid_free(smb_sid_t *sid)
478da6c28aaSamw {
479b819cea2SGordon Ross #if defined(_KERNEL) || defined(_FAKE_KERNEL)
4806537f381Sas200622 	if (sid == NULL)
4816537f381Sas200622 		return;
482da6c28aaSamw 
4836537f381Sas200622 	kmem_free(sid, smb_sid_len(sid));
4846537f381Sas200622 #else
4856537f381Sas200622 	free(sid);
4866537f381Sas200622 #endif
487da6c28aaSamw }
488