xref: /titanic_50/usr/src/common/smbsrv/smb_sid.c (revision da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0)
1*da6c28aaSamw /*
2*da6c28aaSamw  * CDDL HEADER START
3*da6c28aaSamw  *
4*da6c28aaSamw  * The contents of this file are subject to the terms of the
5*da6c28aaSamw  * Common Development and Distribution License (the "License").
6*da6c28aaSamw  * You may not use this file except in compliance with the License.
7*da6c28aaSamw  *
8*da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10*da6c28aaSamw  * See the License for the specific language governing permissions
11*da6c28aaSamw  * and limitations under the License.
12*da6c28aaSamw  *
13*da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14*da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16*da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17*da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18*da6c28aaSamw  *
19*da6c28aaSamw  * CDDL HEADER END
20*da6c28aaSamw  */
21*da6c28aaSamw /*
22*da6c28aaSamw  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*da6c28aaSamw  * Use is subject to license terms.
24*da6c28aaSamw  */
25*da6c28aaSamw 
26*da6c28aaSamw #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*da6c28aaSamw 
28*da6c28aaSamw /*
29*da6c28aaSamw  * NT Security Identifier (SID) library functions.
30*da6c28aaSamw  */
31*da6c28aaSamw 
32*da6c28aaSamw #ifndef _KERNEL
33*da6c28aaSamw #include <stdio.h>
34*da6c28aaSamw #include <strings.h>
35*da6c28aaSamw #include <stdlib.h>
36*da6c28aaSamw #include <syslog.h>
37*da6c28aaSamw #include <smbsrv/libsmb.h>
38*da6c28aaSamw #else /* _KERNEL */
39*da6c28aaSamw #include <sys/types.h>
40*da6c28aaSamw #include <sys/sunddi.h>
41*da6c28aaSamw #endif /* _KERNEL */
42*da6c28aaSamw 
43*da6c28aaSamw #include <smbsrv/alloc.h>
44*da6c28aaSamw #include <smbsrv/ntsid.h>
45*da6c28aaSamw #include <smbsrv/ntstatus.h>
46*da6c28aaSamw #include <smbsrv/smbinfo.h>
47*da6c28aaSamw 
48*da6c28aaSamw 
49*da6c28aaSamw /*
50*da6c28aaSamw  * nt_sid_is_valid
51*da6c28aaSamw  *
52*da6c28aaSamw  * Check that a sid is valid. The checking is minimal: check the pointer
53*da6c28aaSamw  * is valid and that the revision and sub-authority count is legal.
54*da6c28aaSamw  * Returns 1 if the sid appears to be valid. Otherwise 0.
55*da6c28aaSamw  */
56*da6c28aaSamw int
57*da6c28aaSamw nt_sid_is_valid(nt_sid_t *sid)
58*da6c28aaSamw {
59*da6c28aaSamw 	if (sid == 0)
60*da6c28aaSamw 		return (0);
61*da6c28aaSamw 
62*da6c28aaSamw 	return (sid->Revision == NT_SID_REVISION &&
63*da6c28aaSamw 	    sid->SubAuthCount < NT_SID_SUBAUTH_MAX) ? 1 : 0;
64*da6c28aaSamw }
65*da6c28aaSamw 
66*da6c28aaSamw 
67*da6c28aaSamw /*
68*da6c28aaSamw  * nt_sid_length
69*da6c28aaSamw  *
70*da6c28aaSamw  * Returns the number of bytes required to hold the sid.
71*da6c28aaSamw  */
72*da6c28aaSamw int
73*da6c28aaSamw nt_sid_length(nt_sid_t *sid)
74*da6c28aaSamw {
75*da6c28aaSamw 	if (sid == 0)
76*da6c28aaSamw 		return (0);
77*da6c28aaSamw 
78*da6c28aaSamw 	return (sizeof (nt_sid_t) - sizeof (DWORD)
79*da6c28aaSamw 	    + (sid->SubAuthCount * sizeof (DWORD)));
80*da6c28aaSamw }
81*da6c28aaSamw 
82*da6c28aaSamw 
83*da6c28aaSamw /*
84*da6c28aaSamw  * nt_sid_dup
85*da6c28aaSamw  *
86*da6c28aaSamw  * Make a duplicate of the specified sid. The memory for the new sid is
87*da6c28aaSamw  * allocated using malloc so the caller should call free when it is no
88*da6c28aaSamw  * longer required. A pointer to the new sid is returned.
89*da6c28aaSamw  */
90*da6c28aaSamw nt_sid_t *
91*da6c28aaSamw nt_sid_dup(nt_sid_t *sid)
92*da6c28aaSamw {
93*da6c28aaSamw 	nt_sid_t *new_sid;
94*da6c28aaSamw 	int size;
95*da6c28aaSamw 	int i;
96*da6c28aaSamw 
97*da6c28aaSamw 	if (sid == 0)
98*da6c28aaSamw 		return (0);
99*da6c28aaSamw 
100*da6c28aaSamw 	size = sizeof (nt_sid_t)
101*da6c28aaSamw 	    + (sid->SubAuthCount * sizeof (DWORD))
102*da6c28aaSamw 	    + sizeof (DWORD);
103*da6c28aaSamw 
104*da6c28aaSamw 	if ((new_sid = MEM_MALLOC("libnt", size)) == 0)
105*da6c28aaSamw 		return (0);
106*da6c28aaSamw 
107*da6c28aaSamw 	(void) memcpy(new_sid, sid, sizeof (nt_sid_t));
108*da6c28aaSamw 
109*da6c28aaSamw 	for (i = 0; i < sid->SubAuthCount && i < NT_SID_SUBAUTH_MAX; ++i)
110*da6c28aaSamw 		new_sid->SubAuthority[i] = sid->SubAuthority[i];
111*da6c28aaSamw 
112*da6c28aaSamw 	return (new_sid);
113*da6c28aaSamw }
114*da6c28aaSamw 
115*da6c28aaSamw 
116*da6c28aaSamw /*
117*da6c28aaSamw  * nt_sid_splice
118*da6c28aaSamw  *
119*da6c28aaSamw  * Make a full user sid from the domain sid and the user relative id
120*da6c28aaSamw  * (rid). The memory for the new sid is allocated using malloc so the
121*da6c28aaSamw  * caller should call free when it is no longer required. A pointer
122*da6c28aaSamw  * to the new sid is returned.
123*da6c28aaSamw  */
124*da6c28aaSamw nt_sid_t *
125*da6c28aaSamw nt_sid_splice(nt_sid_t *domain_sid, DWORD rid)
126*da6c28aaSamw {
127*da6c28aaSamw 	nt_sid_t *sid;
128*da6c28aaSamw 	int size;
129*da6c28aaSamw 	int i;
130*da6c28aaSamw 
131*da6c28aaSamw 	if (domain_sid == 0)
132*da6c28aaSamw 		return (0);
133*da6c28aaSamw 
134*da6c28aaSamw 	size = sizeof (nt_sid_t)
135*da6c28aaSamw 	    + (domain_sid->SubAuthCount * sizeof (DWORD))
136*da6c28aaSamw 	    + sizeof (DWORD);
137*da6c28aaSamw 
138*da6c28aaSamw 	if ((sid = MEM_MALLOC("libnt", size)) == 0)
139*da6c28aaSamw 		return (0);
140*da6c28aaSamw 
141*da6c28aaSamw 	(void) memcpy(sid, domain_sid, sizeof (nt_sid_t));
142*da6c28aaSamw 
143*da6c28aaSamw 	for (i = 0; i < sid->SubAuthCount && i < NT_SID_SUBAUTH_MAX; ++i)
144*da6c28aaSamw 		sid->SubAuthority[i] = domain_sid->SubAuthority[i];
145*da6c28aaSamw 
146*da6c28aaSamw 	sid->SubAuthority[i] = rid;
147*da6c28aaSamw 	++sid->SubAuthCount;
148*da6c28aaSamw 	return (sid);
149*da6c28aaSamw }
150*da6c28aaSamw 
151*da6c28aaSamw 
152*da6c28aaSamw /*
153*da6c28aaSamw  * nt_sid_get_rid
154*da6c28aaSamw  *
155*da6c28aaSamw  * Return the Relative Id (RID) from the specified SID. It is the
156*da6c28aaSamw  * caller's responsibility to ensure that this is an appropriate SID.
157*da6c28aaSamw  * All we do here is return the last sub-authority from the SID.
158*da6c28aaSamw  */
159*da6c28aaSamw int
160*da6c28aaSamw nt_sid_get_rid(nt_sid_t *sid, DWORD *rid)
161*da6c28aaSamw {
162*da6c28aaSamw 	if (!nt_sid_is_valid(sid))
163*da6c28aaSamw 		return (-1);
164*da6c28aaSamw 
165*da6c28aaSamw 	if (sid->SubAuthCount == 0) {
166*da6c28aaSamw 		return (-1);
167*da6c28aaSamw 	}
168*da6c28aaSamw 
169*da6c28aaSamw 	if (rid)
170*da6c28aaSamw 		*rid = sid->SubAuthority[sid->SubAuthCount - 1];
171*da6c28aaSamw 	return (0);
172*da6c28aaSamw }
173*da6c28aaSamw 
174*da6c28aaSamw 
175*da6c28aaSamw /*
176*da6c28aaSamw  * nt_sid_split
177*da6c28aaSamw  *
178*da6c28aaSamw  * Take a full user sid and split it into the domain sid and the user
179*da6c28aaSamw  * relative id (rid). The original sid is modified in place - use
180*da6c28aaSamw  * nt_sid_dup before calling this function to preserve the original SID.
181*da6c28aaSamw  */
182*da6c28aaSamw int
183*da6c28aaSamw nt_sid_split(nt_sid_t *sid, DWORD *rid)
184*da6c28aaSamw {
185*da6c28aaSamw 	if (!nt_sid_is_valid(sid)) {
186*da6c28aaSamw 		return (-1);
187*da6c28aaSamw 	}
188*da6c28aaSamw 
189*da6c28aaSamw 	if (sid->SubAuthCount == 0) {
190*da6c28aaSamw 		return (-1);
191*da6c28aaSamw 	}
192*da6c28aaSamw 
193*da6c28aaSamw 	--sid->SubAuthCount;
194*da6c28aaSamw 	if (rid)
195*da6c28aaSamw 		*rid = sid->SubAuthority[sid->SubAuthCount];
196*da6c28aaSamw 	return (0);
197*da6c28aaSamw }
198*da6c28aaSamw 
199*da6c28aaSamw 
200*da6c28aaSamw /*
201*da6c28aaSamw  * nt_sid_gen_null_sid
202*da6c28aaSamw  *
203*da6c28aaSamw  * This function allocates a SID structure and initializes it as the
204*da6c28aaSamw  * well-known Null SID (S-1-0-0). A pointer to the SID is returned.
205*da6c28aaSamw  * As the memory for this structure is obtained via malloc, it is the
206*da6c28aaSamw  * caller's responsibility to free the memory when it is no longer
207*da6c28aaSamw  * required. If malloc fails, a null pointer is returned.
208*da6c28aaSamw  */
209*da6c28aaSamw nt_sid_t *
210*da6c28aaSamw nt_sid_gen_null_sid(void)
211*da6c28aaSamw {
212*da6c28aaSamw 	nt_sid_t *sid;
213*da6c28aaSamw 	int size;
214*da6c28aaSamw 
215*da6c28aaSamw 	size = sizeof (nt_sid_t) + sizeof (DWORD);
216*da6c28aaSamw 
217*da6c28aaSamw 	if ((sid = MEM_MALLOC("libnt", size)) == 0) {
218*da6c28aaSamw 		return (0);
219*da6c28aaSamw 	}
220*da6c28aaSamw 
221*da6c28aaSamw 	sid->Revision = 1;
222*da6c28aaSamw 	sid->SubAuthCount = 1;
223*da6c28aaSamw 	return (sid);
224*da6c28aaSamw }
225*da6c28aaSamw 
226*da6c28aaSamw 
227*da6c28aaSamw /*
228*da6c28aaSamw  * nt_sid_is_equal
229*da6c28aaSamw  *
230*da6c28aaSamw  * Compare two SIDs and return a boolean result. The checks are ordered
231*da6c28aaSamw  * such that components that are more likely to differ are checked
232*da6c28aaSamw  * first. For example, after checking that the SIDs contain the same
233*da6c28aaSamw  * SubAuthCount, we check the sub-authorities in reverse order because
234*da6c28aaSamw  * the RID is the most likely differentiator between two SIDs, i.e.
235*da6c28aaSamw  * they are probably going to be in the same domain.
236*da6c28aaSamw  *
237*da6c28aaSamw  * Returns 1 if the SIDs are equal. Otherwise returns 0.
238*da6c28aaSamw  */
239*da6c28aaSamw int
240*da6c28aaSamw nt_sid_is_equal(nt_sid_t *sid1, nt_sid_t *sid2)
241*da6c28aaSamw {
242*da6c28aaSamw 	int i;
243*da6c28aaSamw 
244*da6c28aaSamw 	if (sid1 == 0 || sid2 == 0)
245*da6c28aaSamw 		return (0);
246*da6c28aaSamw 
247*da6c28aaSamw 	if (sid1->SubAuthCount != sid2->SubAuthCount ||
248*da6c28aaSamw 	    sid1->Revision != sid2->Revision)
249*da6c28aaSamw 		return (0);
250*da6c28aaSamw 
251*da6c28aaSamw 	for (i = sid1->SubAuthCount - 1; i >= 0; --i)
252*da6c28aaSamw 		if (sid1->SubAuthority[i] != sid2->SubAuthority[i])
253*da6c28aaSamw 			return (0);
254*da6c28aaSamw 
255*da6c28aaSamw 	if (bcmp(&sid1->Authority, &sid2->Authority, NT_SID_AUTH_MAX))
256*da6c28aaSamw 		return (0);
257*da6c28aaSamw 
258*da6c28aaSamw 	return (1);
259*da6c28aaSamw }
260*da6c28aaSamw 
261*da6c28aaSamw /*
262*da6c28aaSamw  * nt_sid_is_indomain
263*da6c28aaSamw  *
264*da6c28aaSamw  * Check if given SID is in given domain.
265*da6c28aaSamw  * Returns 1 on success. Otherwise returns 0.
266*da6c28aaSamw  */
267*da6c28aaSamw int
268*da6c28aaSamw nt_sid_is_indomain(nt_sid_t *domain_sid, nt_sid_t *sid)
269*da6c28aaSamw {
270*da6c28aaSamw 	int i;
271*da6c28aaSamw 
272*da6c28aaSamw 	if (sid == 0 || domain_sid == 0) {
273*da6c28aaSamw 		return (0);
274*da6c28aaSamw 	}
275*da6c28aaSamw 
276*da6c28aaSamw 	if (domain_sid->Revision != sid->Revision ||
277*da6c28aaSamw 	    sid->SubAuthCount < domain_sid->SubAuthCount)
278*da6c28aaSamw 		return (0);
279*da6c28aaSamw 
280*da6c28aaSamw 	for (i = domain_sid->SubAuthCount - 1; i >= 0; --i)
281*da6c28aaSamw 		if (domain_sid->SubAuthority[i] != sid->SubAuthority[i])
282*da6c28aaSamw 			return (0);
283*da6c28aaSamw 
284*da6c28aaSamw 	if (bcmp(&domain_sid->Authority, &sid->Authority, NT_SID_AUTH_MAX))
285*da6c28aaSamw 		return (0);
286*da6c28aaSamw 
287*da6c28aaSamw 	return (1);
288*da6c28aaSamw }
289*da6c28aaSamw 
290*da6c28aaSamw #ifndef _KERNEL
291*da6c28aaSamw /*
292*da6c28aaSamw  * nt_sid_is_local
293*da6c28aaSamw  *
294*da6c28aaSamw  * Check a SID to see if it belongs to the local domain. This is almost
295*da6c28aaSamw  * the same as checking that two SIDs are equal except that we don't
296*da6c28aaSamw  * care if the specified SID contains extra sub-authorities. We're only
297*da6c28aaSamw  * interested in the domain part.
298*da6c28aaSamw  *
299*da6c28aaSamw  * Returns 1 if the SIDs are equal. Otherwise returns 0.
300*da6c28aaSamw  */
301*da6c28aaSamw int
302*da6c28aaSamw nt_sid_is_local(nt_sid_t *sid)
303*da6c28aaSamw {
304*da6c28aaSamw 	nt_sid_t *local_sid;
305*da6c28aaSamw 
306*da6c28aaSamw 	local_sid = nt_domain_local_sid();
307*da6c28aaSamw 	return (nt_sid_is_indomain(local_sid, sid));
308*da6c28aaSamw }
309*da6c28aaSamw 
310*da6c28aaSamw /*
311*da6c28aaSamw  * nt_sid_is_builtin
312*da6c28aaSamw  *
313*da6c28aaSamw  * Check a SID to see if it belongs to the builtin domain.
314*da6c28aaSamw  * Returns 1 if the SID is a builtin SID. Otherwise returns 0.
315*da6c28aaSamw  */
316*da6c28aaSamw int
317*da6c28aaSamw nt_sid_is_builtin(nt_sid_t *sid)
318*da6c28aaSamw {
319*da6c28aaSamw 	nt_domain_t *domain;
320*da6c28aaSamw 
321*da6c28aaSamw 	domain = nt_domain_lookupbytype(NT_DOMAIN_BUILTIN);
322*da6c28aaSamw 	if (domain == 0)
323*da6c28aaSamw 		return (0);
324*da6c28aaSamw 	return (nt_sid_is_indomain(domain->sid, sid));
325*da6c28aaSamw }
326*da6c28aaSamw #endif /* _KERNEL */
327*da6c28aaSamw 
328*da6c28aaSamw /*
329*da6c28aaSamw  * nt_sid_is_domain_equal
330*da6c28aaSamw  *
331*da6c28aaSamw  * Compare two SIDs's domain and return a boolean result.
332*da6c28aaSamw  *
333*da6c28aaSamw  * Returns 1 if the domain SID are the same. Otherwise returns 0.
334*da6c28aaSamw  */
335*da6c28aaSamw int
336*da6c28aaSamw nt_sid_is_domain_equal(nt_sid_t *pSid1, nt_sid_t *pSid2)
337*da6c28aaSamw {
338*da6c28aaSamw 	int		i, n;
339*da6c28aaSamw 
340*da6c28aaSamw 	if (pSid1->Revision != pSid2->Revision)
341*da6c28aaSamw 		return (0);
342*da6c28aaSamw 
343*da6c28aaSamw 	if (pSid1->SubAuthCount != pSid2->SubAuthCount)
344*da6c28aaSamw 		return (0);
345*da6c28aaSamw 
346*da6c28aaSamw 	if (bcmp(pSid1->Authority, pSid2->Authority, NT_SID_AUTH_MAX) != 0)
347*da6c28aaSamw 		return (0);
348*da6c28aaSamw 
349*da6c28aaSamw 	n = pSid1->SubAuthCount;
350*da6c28aaSamw 
351*da6c28aaSamw 	n -= 1;		/* don't compare last SubAuthority[] (aka RID) */
352*da6c28aaSamw 
353*da6c28aaSamw 	for (i = 0; i < n; i++)
354*da6c28aaSamw 		if (pSid1->SubAuthority[i] != pSid2->SubAuthority[i])
355*da6c28aaSamw 			return (0);
356*da6c28aaSamw 
357*da6c28aaSamw 	return (1);
358*da6c28aaSamw }
359*da6c28aaSamw 
360*da6c28aaSamw /*
361*da6c28aaSamw  * nt_sid_logf
362*da6c28aaSamw  *
363*da6c28aaSamw  * Format a sid and write it to the system log. See nt_sid_format
364*da6c28aaSamw  * for format information.
365*da6c28aaSamw  */
366*da6c28aaSamw void
367*da6c28aaSamw nt_sid_logf(nt_sid_t *sid)
368*da6c28aaSamw {
369*da6c28aaSamw 	char *s;
370*da6c28aaSamw 
371*da6c28aaSamw 	if ((s = nt_sid_format(sid)) == 0)
372*da6c28aaSamw 		return;
373*da6c28aaSamw 
374*da6c28aaSamw 	MEM_FREE("libnt", s);
375*da6c28aaSamw }
376*da6c28aaSamw 
377*da6c28aaSamw 
378*da6c28aaSamw /*
379*da6c28aaSamw  * nt_sid_format
380*da6c28aaSamw  *
381*da6c28aaSamw  * Format a sid and return it as a string. The memory for the string is
382*da6c28aaSamw  * allocated using malloc so the caller should call free when it is no
383*da6c28aaSamw  * longer required. A pointer to the string is returned.
384*da6c28aaSamw  */
385*da6c28aaSamw char *
386*da6c28aaSamw nt_sid_format(nt_sid_t *sid)
387*da6c28aaSamw {
388*da6c28aaSamw 	int i;
389*da6c28aaSamw 	char *fmtbuf;
390*da6c28aaSamw 	char *p;
391*da6c28aaSamw 
392*da6c28aaSamw 	if (sid == 0)
393*da6c28aaSamw 		return (0);
394*da6c28aaSamw 
395*da6c28aaSamw 	if ((fmtbuf = MEM_MALLOC("libnt", NT_SID_FMTBUF_SIZE)) == 0)
396*da6c28aaSamw 		return (0);
397*da6c28aaSamw 
398*da6c28aaSamw 	p = fmtbuf;
399*da6c28aaSamw 	(void) sprintf(p, "S-%d-", sid->Revision);
400*da6c28aaSamw 	while (*p)
401*da6c28aaSamw 		++p;
402*da6c28aaSamw 
403*da6c28aaSamw 	for (i = 0; i < NT_SID_AUTH_MAX; ++i) {
404*da6c28aaSamw 		if (sid->Authority[i] != 0 || i == NT_SID_AUTH_MAX - 1)	{
405*da6c28aaSamw 			(void) sprintf(p, "%d", sid->Authority[i]);
406*da6c28aaSamw 			while (*p)
407*da6c28aaSamw 				++p;
408*da6c28aaSamw 		}
409*da6c28aaSamw 	}
410*da6c28aaSamw 
411*da6c28aaSamw 	for (i = 0; i < sid->SubAuthCount && i < NT_SID_SUBAUTH_MAX; ++i) {
412*da6c28aaSamw 		(void) sprintf(p, "-%u", sid->SubAuthority[i]);
413*da6c28aaSamw 		while (*p)
414*da6c28aaSamw 			++p;
415*da6c28aaSamw 	}
416*da6c28aaSamw 
417*da6c28aaSamw 	return (fmtbuf);
418*da6c28aaSamw }
419*da6c28aaSamw 
420*da6c28aaSamw /*
421*da6c28aaSamw  * nt_sid_format2
422*da6c28aaSamw  *
423*da6c28aaSamw  * Format a sid and return it in the passed buffer.
424*da6c28aaSamw  */
425*da6c28aaSamw void
426*da6c28aaSamw nt_sid_format2(nt_sid_t *sid, char *fmtbuf)
427*da6c28aaSamw {
428*da6c28aaSamw 	int i;
429*da6c28aaSamw 	char *p;
430*da6c28aaSamw 
431*da6c28aaSamw 	if (sid == 0 || fmtbuf == 0)
432*da6c28aaSamw 		return;
433*da6c28aaSamw 
434*da6c28aaSamw 	p = fmtbuf;
435*da6c28aaSamw 	(void) sprintf(p, "S-%d-", sid->Revision);
436*da6c28aaSamw 	while (*p)
437*da6c28aaSamw 		++p;
438*da6c28aaSamw 
439*da6c28aaSamw 	for (i = 0; i < NT_SID_AUTH_MAX; ++i) {
440*da6c28aaSamw 		if (sid->Authority[i] != 0 || i == NT_SID_AUTH_MAX - 1) {
441*da6c28aaSamw 			(void) sprintf(p, "%d", sid->Authority[i]);
442*da6c28aaSamw 			while (*p)
443*da6c28aaSamw 				++p;
444*da6c28aaSamw 		}
445*da6c28aaSamw 	}
446*da6c28aaSamw 
447*da6c28aaSamw 	for (i = 0; i < sid->SubAuthCount && i < NT_SID_SUBAUTH_MAX; ++i) {
448*da6c28aaSamw 		(void) sprintf(p, "-%u", sid->SubAuthority[i]);
449*da6c28aaSamw 		while (*p)
450*da6c28aaSamw 			++p;
451*da6c28aaSamw 	}
452*da6c28aaSamw }
453*da6c28aaSamw 
454*da6c28aaSamw /*
455*da6c28aaSamw  * nt_sid_strtosid
456*da6c28aaSamw  *
457*da6c28aaSamw  * Converts a SID in string form to a SID structure. There are lots of
458*da6c28aaSamw  * simplifying assumptions in here. The memory for the SID is allocated
459*da6c28aaSamw  * as if it was the largest possible SID; the caller is responsible for
460*da6c28aaSamw  * freeing the memory when it is no longer required. We assume that the
461*da6c28aaSamw  * string starts with "S-1-" and that the authority is held in the last
462*da6c28aaSamw  * byte, which should be okay for most situations. It also assumes the
463*da6c28aaSamw  * sub-authorities are in decimal format.
464*da6c28aaSamw  *
465*da6c28aaSamw  * On success, a pointer to a SID is returned. Otherwise a null pointer
466*da6c28aaSamw  * is returned.
467*da6c28aaSamw  *
468*da6c28aaSamw  * XXX this function may have endian issues
469*da6c28aaSamw  */
470*da6c28aaSamw nt_sid_t *
471*da6c28aaSamw nt_sid_strtosid(char *sidstr)
472*da6c28aaSamw {
473*da6c28aaSamw 	nt_sid_t *sid;
474*da6c28aaSamw 	char *p;
475*da6c28aaSamw 	int size;
476*da6c28aaSamw 	BYTE i;
477*da6c28aaSamw #ifdef _KERNEL
478*da6c28aaSamw 	long sua;
479*da6c28aaSamw #endif /* _KERNEL */
480*da6c28aaSamw 
481*da6c28aaSamw 	if (sidstr == 0) {
482*da6c28aaSamw 		return (0);
483*da6c28aaSamw 	}
484*da6c28aaSamw 
485*da6c28aaSamw 	if (strncmp(sidstr, "S-1-", 4) != 0) {
486*da6c28aaSamw 		return (0);
487*da6c28aaSamw 	}
488*da6c28aaSamw 
489*da6c28aaSamw 	size = sizeof (nt_sid_t) + (NT_SID_SUBAUTH_MAX * sizeof (DWORD));
490*da6c28aaSamw 
491*da6c28aaSamw 	if ((sid = MEM_MALLOC("libnt", size)) == 0) {
492*da6c28aaSamw 		return (0);
493*da6c28aaSamw 	}
494*da6c28aaSamw 
495*da6c28aaSamw 	bzero(sid, size);
496*da6c28aaSamw 	sid->Revision = NT_SID_REVISION;
497*da6c28aaSamw #ifndef _KERNEL
498*da6c28aaSamw 	sid->Authority[5] = atoi(&sidstr[4]);
499*da6c28aaSamw #else /* _KERNEL */
500*da6c28aaSamw 	sua = 0;
501*da6c28aaSamw 	/* XXX Why are we treating sua as a long/unsigned long? */
502*da6c28aaSamw 	(void) ddi_strtoul(&sidstr[4], 0, 10, (unsigned long *)&sua);
503*da6c28aaSamw 	sid->Authority[5] = (BYTE)sua;
504*da6c28aaSamw #endif /* _KERNEL */
505*da6c28aaSamw 
506*da6c28aaSamw 	for (i = 0, p = &sidstr[5]; i < NT_SID_SUBAUTH_MAX && *p; ++i) {
507*da6c28aaSamw 		while (*p && *p == '-')
508*da6c28aaSamw 			++p;
509*da6c28aaSamw 
510*da6c28aaSamw 		if (*p < '0' || *p > '9') {
511*da6c28aaSamw 			MEM_FREE("libnt", sid);
512*da6c28aaSamw 			return (0);
513*da6c28aaSamw 		}
514*da6c28aaSamw 
515*da6c28aaSamw #ifndef _KERNEL
516*da6c28aaSamw 		sid->SubAuthority[i] = strtoul(p, 0, 10);
517*da6c28aaSamw #else /* _KERNEL */
518*da6c28aaSamw 		sua = 0;
519*da6c28aaSamw 		(void) ddi_strtoul(p, 0, 10, (unsigned long *)&sua);
520*da6c28aaSamw 		sid->SubAuthority[i] = (DWORD)sua;
521*da6c28aaSamw #endif /* _KERNEL */
522*da6c28aaSamw 
523*da6c28aaSamw 		while (*p && *p != '-')
524*da6c28aaSamw 			++p;
525*da6c28aaSamw 	}
526*da6c28aaSamw 
527*da6c28aaSamw 	sid->SubAuthCount = i;
528*da6c28aaSamw 	return (sid);
529*da6c28aaSamw }
530*da6c28aaSamw 
531*da6c28aaSamw 
532*da6c28aaSamw /*
533*da6c28aaSamw  * nt_sid_name_use
534*da6c28aaSamw  *
535*da6c28aaSamw  * Returns the text name for a SID_NAME_USE value. The SID_NAME_USE
536*da6c28aaSamw  * provides the context for a SID, i.e. the type of resource to which
537*da6c28aaSamw  * it refers.
538*da6c28aaSamw  */
539*da6c28aaSamw char *
540*da6c28aaSamw nt_sid_name_use(unsigned int snu_id)
541*da6c28aaSamw {
542*da6c28aaSamw 	static char *snu_name[] = {
543*da6c28aaSamw 		"SidTypeSidPrefix",
544*da6c28aaSamw 		"SidTypeUser",
545*da6c28aaSamw 		"SidTypeGroup",
546*da6c28aaSamw 		"SidTypeDomain",
547*da6c28aaSamw 		"SidTypeAlias",
548*da6c28aaSamw 		"SidTypeWellKnownGroup",
549*da6c28aaSamw 		"SidTypeDeletedAccount",
550*da6c28aaSamw 		"SidTypeInvalid",
551*da6c28aaSamw 		"SidTypeUnknown"
552*da6c28aaSamw 	};
553*da6c28aaSamw 
554*da6c28aaSamw 	if (snu_id < ((sizeof (snu_name)/sizeof (snu_name[0]))))
555*da6c28aaSamw 		return (snu_name[snu_id]);
556*da6c28aaSamw 	else {
557*da6c28aaSamw 		return (snu_name[SidTypeUnknown]);
558*da6c28aaSamw 	}
559*da6c28aaSamw }
560*da6c28aaSamw 
561*da6c28aaSamw 
562*da6c28aaSamw /*
563*da6c28aaSamw  * nt_sid_copy
564*da6c28aaSamw  *
565*da6c28aaSamw  * Copy information of srcsid to dessid. The buffer should be allocated
566*da6c28aaSamw  * for dessid before passing to this function. The size of buffer for
567*da6c28aaSamw  * dessid should be specified in the buflen.
568*da6c28aaSamw  *
569*da6c28aaSamw  * Returns total bytes of information copied. If there is an error, 0
570*da6c28aaSamw  * will be returned.
571*da6c28aaSamw  */
572*da6c28aaSamw int
573*da6c28aaSamw nt_sid_copy(nt_sid_t *dessid, nt_sid_t *srcsid, unsigned buflen)
574*da6c28aaSamw {
575*da6c28aaSamw 	unsigned		n_bytes;
576*da6c28aaSamw 
577*da6c28aaSamw 	if (!dessid || !srcsid)
578*da6c28aaSamw 		return (0);
579*da6c28aaSamw 
580*da6c28aaSamw 	n_bytes = nt_sid_length(srcsid);
581*da6c28aaSamw 	if (n_bytes > buflen)
582*da6c28aaSamw 		return (0);
583*da6c28aaSamw 
584*da6c28aaSamw 	bcopy((char *)srcsid, (char *)dessid, n_bytes);
585*da6c28aaSamw 
586*da6c28aaSamw 	return (n_bytes);
587*da6c28aaSamw }
588