1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * This is an extract from usr/src/common/smbsrv/smb_sid.c,
28  * with functions renamed as part of a tentative plan for convergence.
29  */
30 #ifndef _KERNEL
31 #include <stdio.h>
32 #include <strings.h>
33 #include <stdlib.h>
34 #include <syslog.h>
35 #else /* _KERNEL */
36 #include <sys/types.h>
37 #include <sys/sunddi.h>
38 #endif /* _KERNEL */
39 
40 #include <sidutil.h>
41 
42 /*
43  * sid_len
44  *
45  * Returns the number of bytes required to hold the sid.
46  */
47 int
sid_len(sid_t * sid)48 sid_len(sid_t *sid)
49 {
50 	if (sid == NULL)
51 		return (0);
52 
53 	return (sizeof (sid_t) - sizeof (uint32_t)
54 	    + (sid->sid_subauthcnt * sizeof (uint32_t)));
55 }
56 
57 /*
58  * sid_tostr
59  *
60  * Fill in the passed buffer with the string form of the given
61  * binary sid.
62  */
63 void
sid_tostr(sid_t * sid,char * strsid)64 sid_tostr(sid_t *sid, char *strsid)
65 {
66 	char *p = strsid;
67 	int i;
68 
69 	if (sid == NULL || strsid == NULL)
70 		return;
71 
72 	(void) sprintf(p, "S-%d-", sid->sid_revision);
73 	while (*p)
74 		p++;
75 
76 	for (i = 0; i < NT_SID_AUTH_MAX; ++i) {
77 		if (sid->sid_authority[i] != 0 || i == NT_SID_AUTH_MAX - 1) {
78 			(void) sprintf(p, "%d", sid->sid_authority[i]);
79 			while (*p)
80 				p++;
81 		}
82 	}
83 
84 	for (i = 0; i < sid->sid_subauthcnt && i < NT_SID_SUBAUTH_MAX; ++i) {
85 		(void) sprintf(p, "-%u", sid->sid_subauth[i]);
86 		while (*p)
87 			p++;
88 	}
89 }
90 
91 /*
92  * sid_fromstr
93  *
94  * Converts a SID in string form to a SID structure. There are lots of
95  * simplifying assumptions in here. The memory for the SID is allocated
96  * as if it was the largest possible SID; the caller is responsible for
97  * freeing the memory when it is no longer required. We assume that the
98  * string starts with "S-1-" and that the authority is held in the last
99  * byte, which should be okay for most situations. It also assumes the
100  * sub-authorities are in decimal format.
101  *
102  * On success, a pointer to a SID is returned. Otherwise a null pointer
103  * is returned.
104  */
105 sid_t *
sid_fromstr(char * sidstr)106 sid_fromstr(char *sidstr)
107 {
108 	sid_t *sid;
109 	char *p;
110 	int size;
111 	uint8_t i;
112 
113 	if (sidstr == NULL)
114 		return (NULL);
115 
116 	if (strncmp(sidstr, "S-1-", 4) != 0)
117 		return (NULL);
118 
119 	size = sizeof (sid_t) + (NT_SID_SUBAUTH_MAX * sizeof (uint32_t));
120 
121 	if ((sid = malloc(size)) == NULL)
122 		return (NULL);
123 
124 	bzero(sid, size);
125 	sid->sid_revision = NT_SID_REVISION;
126 	sid->sid_authority[5] = atoi(&sidstr[4]);
127 
128 	for (i = 0, p = &sidstr[5]; i < NT_SID_SUBAUTH_MAX && *p; ++i) {
129 		while (*p && *p == '-')
130 			++p;
131 
132 		if (*p < '0' || *p > '9') {
133 			free(sid);
134 			return (NULL);
135 		}
136 
137 		sid->sid_subauth[i] = strtoul(p, NULL, 10);
138 
139 		while (*p && *p != '-')
140 			++p;
141 	}
142 
143 	sid->sid_subauthcnt = i;
144 	return (sid);
145 }
146 
147 void
sid_free(sid_t * sid)148 sid_free(sid_t *sid)
149 {
150 #ifdef _KERNEL
151 	if (sid == NULL)
152 		return;
153 
154 	kmem_free(sid, sid_len(sid));
155 #else
156 	free(sid);
157 #endif
158 }
159 
160 void
sid_to_le(sid_t * sid)161 sid_to_le(sid_t *sid)
162 {
163 	int i;
164 
165 	for (i = 0; i < sid->sid_subauthcnt && i < NT_SID_SUBAUTH_MAX; ++i) {
166 		uint32_t v = sid->sid_subauth[i];
167 		uint8_t *p = (uint8_t *)&sid->sid_subauth[i];
168 
169 		p[0] = v & 0xff;
170 		p[1] = (v >> 8) & 0xff;
171 		p[2] = (v >> 16) & 0xff;
172 		p[3] = (v >> 24) & 0xff;
173 	}
174 }
175 
176 void
sid_from_le(sid_t * sid)177 sid_from_le(sid_t *sid)
178 {
179 	int i;
180 
181 	for (i = 0; i < sid->sid_subauthcnt && i < NT_SID_SUBAUTH_MAX; ++i) {
182 		uint32_t v;
183 		uint8_t *p = (uint8_t *)&sid->sid_subauth[i];
184 
185 		v = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
186 
187 		sid->sid_subauth[i] = v;
188 	}
189 }
190