xref: /illumos-gate/usr/src/lib/smbsrv/libsmb/common/smb_wksids.c (revision 7800901e60d340b6af88e94a2149805dcfcaaf56)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * This module provides the interface to builtin domain information.
30  * These are the predefined groups and aliases in the NT AUTHORITY or
31  * BUILTIN domains, and some other miscellaneous bits.
32  */
33 
34 #include <string.h>
35 #include <synch.h>
36 #include <smbsrv/ntsid.h>
37 #include <smbsrv/string.h>
38 #include <smbsrv/alloc.h>
39 
40 /*
41  * This table should contain all of the NT builtin domain names.
42  */
43 static char *domain[] = {
44 	"LOCAL",
45 	"BUILTIN",
46 	"NT AUTHORITY",
47 	"UNKNOWN"
48 };
49 
50 static int wk_init = 0;
51 static rwlock_t wk_rwlock;
52 
53 /*
54  * This table should contain all of the builtin domains, groups and
55  * aliases. The order is important because we do string compares on
56  * the SIDs. For each domain, ensure that the domain SID appears
57  * before any aliases in that domain.
58  */
59 static well_known_account_t wkt[] = {
60 	{ SidTypeWellKnownGroup, 0, "S-1-0-0",		"Null",
61 	    LGF_HIDDEN, 0, NULL},
62 	{ SidTypeWellKnownGroup, 1, "S-1-1-0",		"Everyone",
63 	    LGF_HIDDEN, 0, NULL},
64 	{ SidTypeWellKnownGroup, 1, "S-1-2-0",		"LOCAL",
65 	    LGF_HIDDEN, 0, NULL},
66 	{ SidTypeWellKnownGroup, 1, "S-1-3-0",		"CREATOR OWNER",
67 	    LGF_HIDDEN, 0, NULL},
68 	{ SidTypeWellKnownGroup, 1, "S-1-3-1",		"CREATOR GROUP",
69 	    LGF_HIDDEN, 0, NULL},
70 	{ SidTypeWellKnownGroup, 1, "S-1-3-2",		"CREATOR OWNER SERVER",
71 	    LGF_HIDDEN, 0, NULL},
72 	{ SidTypeWellKnownGroup, 1, "S-1-3-3",		"CREATOR GROUP SERVER",
73 	    LGF_HIDDEN, 0, NULL},
74 	{ SidTypeDomain, 1, "S-1-4",			"NON UNIQUE",
75 	    LGF_HIDDEN, 0, NULL},
76 	{ SidTypeDomain, 2, "S-1-5",		"NT AUTHORITY",
77 	    LGF_HIDDEN, 0, NULL},
78 	{ SidTypeWellKnownGroup, 2, "S-1-5-1",		"DIALUP",
79 	    LGF_HIDDEN, 0, NULL},
80 	{ SidTypeWellKnownGroup, 2, "S-1-5-2",		"NETWORK",
81 	    LGF_HIDDEN, 0, NULL},
82 	{ SidTypeWellKnownGroup, 2, "S-1-5-3",		"BATCH",
83 	    LGF_HIDDEN, 0, NULL},
84 	{ SidTypeWellKnownGroup, 2, "S-1-5-4",		"INTERACTIVE",
85 	    LGF_HIDDEN, 0, NULL},
86 	{ SidTypeWellKnownGroup, 2, "S-1-5-6",		"SERVICE",
87 	    LGF_HIDDEN, 0, NULL},
88 	{ SidTypeWellKnownGroup, 2, "S-1-5-7",		"ANONYMOUS",
89 	    LGF_HIDDEN, 0, NULL},
90 	{ SidTypeWellKnownGroup, 2, "S-1-5-8",		"PROXY",
91 	    LGF_HIDDEN, 0, NULL},
92 	{ SidTypeWellKnownGroup, 2, "S-1-5-9",		"SERVER",
93 	    LGF_HIDDEN, 0, NULL},
94 	{ SidTypeWellKnownGroup, 2, "S-1-5-10",		"SELF",
95 	    LGF_HIDDEN, 0, NULL},
96 	{ SidTypeWellKnownGroup, 2, "S-1-5-11",		"Authenticated Users",
97 	    LGF_HIDDEN, 0, NULL},
98 	{ SidTypeWellKnownGroup, 2, "S-1-5-12",		"RESTRICTED",
99 	    LGF_HIDDEN, 0, NULL},
100 	{ SidTypeWellKnownGroup, 2, "S-1-5-18",		"SYSTEM",
101 	    LGF_HIDDEN, 0, NULL},
102 	{ SidTypeWellKnownGroup, 2, "S-1-5-21",		"NON_UNIQUE",
103 	    LGF_HIDDEN, 0, NULL},
104 	{ SidTypeDomain, 2, "S-1-5-32",			"BUILTIN",
105 	    LGF_HIDDEN, 0, NULL},
106 	{ SidTypeAlias, 1, "S-1-5-32-544",		"Administrators",
107 	    0, "Members can fully administer the computer/domain", NULL },
108 	{ SidTypeAlias, 1, "S-1-5-32-545",		"Users",
109 	    LGF_HIDDEN, 0, NULL},
110 	{ SidTypeAlias, 1, "S-1-5-32-546",		"Guests",
111 	    LGF_HIDDEN, 0, NULL},
112 	{ SidTypeAlias, 1, "S-1-5-32-547",		"Power Users",
113 	    0, "Members can share directories", NULL },
114 	{ SidTypeAlias, 1, "S-1-5-32-548",		"Account Operators",
115 	    LGF_HIDDEN, 0, NULL},
116 	{ SidTypeAlias, 1, "S-1-5-32-549",		"Server Operators",
117 	    LGF_HIDDEN, 0, NULL},
118 	{ SidTypeAlias, 1, "S-1-5-32-550",		"Print Operators",
119 	    LGF_HIDDEN, 0, NULL},
120 	{ SidTypeAlias, 1, "S-1-5-32-551",		"Backup Operators",
121 	    0, "Members can bypass file security to back up files", NULL },
122 	{ SidTypeAlias, 1, "S-1-5-32-552",		"Replicator",
123 	    LGF_HIDDEN, 0, NULL}
124 };
125 
126 
127 /*
128  * nt_builtin_lookup_sid
129  *
130  * Search the wkt looking for a match on the specified SID. If the
131  * SID matches a builtin entry, the associated name is returned.
132  * Otherwise a null pointer is returned.
133  */
134 char *
135 nt_builtin_lookup_sid(nt_sid_t *sid, WORD *sid_name_use)
136 {
137 	well_known_account_t *entry;
138 	char *sidbuf;
139 	int sidlen;
140 	int i;
141 
142 	if ((sidbuf = nt_sid_format(sid)) == 0)	{
143 		return (0);
144 	}
145 
146 	sidlen = strlen(sidbuf);
147 
148 	for (i = 0; i < sizeof (wkt)/sizeof (wkt[0]); ++i) {
149 		entry = &wkt[i];
150 
151 		if (strncmp(sidbuf, entry->sid, sidlen) == 0) {
152 			if (sid_name_use)
153 				*sid_name_use = entry->sid_name_use;
154 			free(sidbuf);
155 			return (entry->name);
156 		}
157 	}
158 
159 	free(sidbuf);
160 	return (0);
161 }
162 
163 
164 /*
165  * nt_builtin_lookup_name
166  *
167  * Search the wkt looking for a match on the specified name. If the
168  * name matches a builtin entry, the associated SID (which is in
169  * malloc'd memory) is returned. Otherwise a null pointer is returned.
170  */
171 nt_sid_t *
172 nt_builtin_lookup_name(char *name, WORD *sid_name_use)
173 {
174 	well_known_account_t *entry;
175 	int i;
176 
177 	for (i = 0; i < sizeof (wkt)/sizeof (wkt[0]); ++i) {
178 		entry = &wkt[i];
179 
180 		if (!utf8_strcasecmp(name, entry->name)) {
181 			if (sid_name_use)
182 				*sid_name_use = entry->sid_name_use;
183 			return (nt_sid_strtosid(entry->sid));
184 		}
185 	}
186 
187 	return (0);
188 }
189 
190 /*
191  * nt_builtin_lookup
192  *
193  * Search the wkt looking for a match on the specified name. If the
194  * name matches a builtin entry then pointer to that entry will be
195  * returned. Otherwise 0 is returned.
196  */
197 well_known_account_t *
198 nt_builtin_lookup(char *name)
199 {
200 	well_known_account_t *entry;
201 	int i;
202 
203 	(void) rw_rdlock(&wk_rwlock);
204 	for (i = 0; i < sizeof (wkt)/sizeof (wkt[0]); ++i) {
205 		entry = &wkt[i];
206 
207 		if (!utf8_strcasecmp(name, entry->name)) {
208 			(void) rw_unlock(&wk_rwlock);
209 			return (entry);
210 		}
211 	}
212 
213 	(void) rw_unlock(&wk_rwlock);
214 	return (0);
215 }
216 
217 
218 /*
219  * nt_builtin_is_wellknown
220  *
221  * Search the wkt looking for a match on the specified name. If the
222  * name matches a builtin entry returns 1. Otherwise returns 0.
223  */
224 int
225 nt_builtin_is_wellknown(char *name)
226 {
227 	well_known_account_t *entry;
228 	int i;
229 
230 	for (i = 0; i < sizeof (wkt)/sizeof (wkt[0]); ++i) {
231 		entry = &wkt[i];
232 
233 		if (!utf8_strcasecmp(name, entry->name)) {
234 			return (1);
235 		}
236 	}
237 
238 	return (0);
239 }
240 
241 /*
242  * nt_builtin_lookup_domain
243  *
244  * Return the builtin domain name for the specified alias or group name.
245  */
246 char *
247 nt_builtin_lookup_domain(char *name)
248 {
249 	well_known_account_t *entry;
250 	char *domain_name;
251 	int i;
252 
253 	for (i = 0; i < sizeof (wkt)/sizeof (wkt[0]); ++i) {
254 		entry = &wkt[i];
255 
256 		if (!utf8_strcasecmp(name, entry->name)) {
257 			domain_name = domain[entry->domain_ix];
258 			return (domain_name);
259 		}
260 	}
261 
262 	return (0);
263 }
264 
265 /*
266  * nt_builtin_findfirst
267  *
268  * Returns pointer to the first entry of well known sids table.
269  */
270 well_known_account_t *
271 nt_builtin_findfirst(DWORD *iterator)
272 {
273 	*iterator = 1;
274 	return (&wkt[0]);
275 }
276 
277 /*
278  * nt_builtin_findnext
279  *
280  * Returns pointer to the entry of well known sids table specified
281  * by the iterator. Increments iterator to point to the next entry.
282  */
283 well_known_account_t *
284 nt_builtin_findnext(DWORD *iterator)
285 {
286 	if (*iterator < sizeof (wkt)/sizeof (wkt[0]))
287 		return (&wkt[(*iterator)++]);
288 
289 	return (0);
290 }
291 
292 /*
293  * nt_builtin_init
294  *
295  * Generate binary SIDs from the string SIDs in the table
296  * and set the proper field.
297  *
298  * Caller MUST not store the binary SID pointer anywhere that
299  * could lead to freeing it.
300  *
301  * This function should only be called once.
302  */
303 int
304 nt_builtin_init()
305 {
306 	well_known_account_t *entry;
307 	int i;
308 
309 	(void) rw_wrlock(&wk_rwlock);
310 	if (wk_init) {
311 		(void) rw_unlock(&wk_rwlock);
312 		return (1);
313 	}
314 
315 	for (i = 0; i < sizeof (wkt)/sizeof (wkt[0]); ++i) {
316 		entry = &wkt[i];
317 		entry->binsid = nt_sid_strtosid(entry->sid);
318 		if (entry->binsid == NULL) {
319 			(void) rw_unlock(&wk_rwlock);
320 			nt_builtin_fini();
321 			return (0);
322 		}
323 	}
324 
325 	wk_init = 1;
326 	(void) rw_unlock(&wk_rwlock);
327 	return (1);
328 }
329 
330 void
331 nt_builtin_fini()
332 {
333 	int i;
334 
335 	(void) rw_wrlock(&wk_rwlock);
336 	if (wk_init == 0) {
337 		(void) rw_unlock(&wk_rwlock);
338 		return;
339 	}
340 
341 	for (i = 0; i < sizeof (wkt)/sizeof (wkt[0]); ++i) {
342 		if (wkt[i].binsid) {
343 			free(wkt[i].binsid);
344 			wkt[i].binsid = NULL;
345 		}
346 	}
347 
348 	wk_init = 0;
349 	(void) rw_unlock(&wk_rwlock);
350 }
351