xref: /illumos-gate/usr/src/lib/smbsrv/libsmb/common/smb_wksids.c (revision 2dea4eed7ad1c66ae4770263aa2911815a8b86eb)
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 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <stdlib.h>
27 #include <string.h>
28 #include <synch.h>
29 
30 #include <smbsrv/libsmb.h>
31 
32 static int wk_init = 0;
33 static rwlock_t wk_rwlock;
34 
35 static char *wka_nbdomain[] = {
36 	"",
37 	"NT Pseudo Domain",
38 	"NT Authority",
39 	"Builtin",
40 	"Internet$"
41 };
42 
43 /*
44  * Predefined well known accounts table
45  */
46 static smb_wka_t wka_tbl[] = {
47 	{ 0, "S-1-0-0",		"Null",
48 		SidTypeWellKnownGroup, 0, NULL, NULL },
49 	{ 0, "S-1-1-0",		"Everyone",
50 		SidTypeWellKnownGroup, 0, NULL, NULL },
51 	{ 0, "S-1-2-0",		"Local",
52 		SidTypeWellKnownGroup, 0, NULL, NULL },
53 	{ 0, "S-1-3-0",		"Creator Owner",
54 		SidTypeWellKnownGroup, 0, NULL, NULL },
55 	{ 0, "S-1-3-1",		"Creator Group",
56 		SidTypeWellKnownGroup, 0, NULL, NULL },
57 	{ 0, "S-1-3-2",		"Creator Owner Server",
58 		SidTypeWellKnownGroup, 0, NULL, NULL },
59 	{ 0, "S-1-3-3",		"Creator Group Server",
60 		SidTypeWellKnownGroup, 0, NULL, NULL },
61 	{ 0, "S-1-3-4",		"Owner Rights",
62 		SidTypeWellKnownGroup, 0, NULL, NULL },
63 	{ 0, "S-1-3-5",		"Group Rights",
64 		SidTypeWellKnownGroup, 0, NULL, NULL },
65 	{ 1, "S-1-5",		"NT Pseudo Domain",
66 		SidTypeDomain, 0, NULL, NULL },
67 	{ 2, "S-1-5-1",		"Dialup",
68 		SidTypeWellKnownGroup, 0, NULL, NULL },
69 	{ 2, "S-1-5-2",		"Network",
70 		SidTypeWellKnownGroup, 0, NULL, NULL },
71 	{ 2, "S-1-5-3",		"Batch",
72 		SidTypeWellKnownGroup, 0, NULL, NULL },
73 	{ 2, "S-1-5-4",		"Interactive",
74 		SidTypeWellKnownGroup, 0, NULL, NULL },
75 	{ 2, "S-1-5-6",		"Service",
76 		SidTypeWellKnownGroup, 0, NULL, NULL },
77 	{ 2, "S-1-5-7",		"Anonymous",
78 		SidTypeWellKnownGroup, 0, NULL, NULL },
79 	{ 2, "S-1-5-8",		"Proxy",
80 		SidTypeWellKnownGroup, 0, NULL, NULL },
81 	{ 2, "S-1-5-9",		"Enterprise Domain Controllers",
82 		SidTypeWellKnownGroup, 0, NULL, NULL },
83 	{ 2, "S-1-5-10",	"Self",
84 		SidTypeWellKnownGroup, 0, NULL, NULL },
85 	{ 2, "S-1-5-11",	"Authenticated Users",
86 		SidTypeWellKnownGroup, 0, NULL, NULL },
87 	{ 2, "S-1-5-12",	"Restricted",
88 		SidTypeWellKnownGroup, 0, NULL, NULL },
89 	{ 2, "S-1-5-13",	"Terminal Server User",
90 		SidTypeWellKnownGroup, 0, NULL, NULL },
91 	{ 2, "S-1-5-14",	"Remote Interactive Logon",
92 		SidTypeWellKnownGroup, 0, NULL, NULL },
93 	{ 2, "S-1-5-15",	"This Organization",
94 		SidTypeWellKnownGroup, 0, NULL, NULL },
95 	{ 2, "S-1-5-18",	"System",
96 		SidTypeWellKnownGroup, 0, NULL, NULL },
97 	{ 2, "S-1-5-19",	"Local Service",
98 		SidTypeWellKnownGroup, 0, NULL, NULL },
99 	{ 2, "S-1-5-20",	"Network Service",
100 		SidTypeWellKnownGroup, 0, NULL, NULL },
101 	{ 2, "S-1-5-33",	"Write Restricted",
102 		SidTypeWellKnownGroup, 0, NULL, NULL },
103 	{ 2, "S-1-5-1000",	"Other Organization",
104 		SidTypeWellKnownGroup, 0, NULL, NULL },
105 	{ 3, "S-1-5-32",	"Builtin",
106 		SidTypeDomain, 0, NULL, NULL },
107 	{ 4, "S-1-7",		"Internet$",
108 		SidTypeDomain, 0, NULL, NULL },
109 
110 	{ 3, "S-1-5-32-544",	"Administrators", SidTypeAlias,
111 	    SMB_WKAFLG_LGRP_ENABLE,
112 	    "Members can fully administer the computer/domain", NULL },
113 	{ 3, "S-1-5-32-545",	"Users",
114 		SidTypeAlias, 0, NULL, NULL },
115 	{ 3, "S-1-5-32-546",	"Guests",
116 		SidTypeAlias, 0, NULL, NULL },
117 	{ 3, "S-1-5-32-547",	"Power Users", SidTypeAlias,
118 	    SMB_WKAFLG_LGRP_ENABLE, "Members can share directories", NULL },
119 	{ 3, "S-1-5-32-548",	"Account Operators",
120 		SidTypeAlias, 0, NULL, NULL },
121 	{ 3, "S-1-5-32-549",	"Server Operators",
122 		SidTypeAlias, 0, NULL, NULL },
123 	{ 3, "S-1-5-32-550",	"Print Operators",
124 		SidTypeAlias, 0, NULL, NULL },
125 	{ 3, "S-1-5-32-551",	"Backup Operators", SidTypeAlias,
126 	    SMB_WKAFLG_LGRP_ENABLE,
127 	    "Members can bypass file security to back up files", NULL },
128 	{ 3, "S-1-5-32-552",	"Replicator",
129 		SidTypeAlias, 0, NULL, NULL },
130 	{ 3, "S-1-5-32-766",	"Current Owner",
131 		SidTypeAlias, 0, NULL, NULL },
132 	{ 3, "S-1-5-32-767",	"Current Group",
133 		SidTypeAlias, 0, NULL, NULL },
134 };
135 
136 #define	SMB_WKA_NUM	(sizeof (wka_tbl)/sizeof (wka_tbl[0]))
137 
138 /*
139  * Looks up well known accounts table for the given SID.
140  * Upon success returns a pointer to the account entry in
141  * the table, otherwise returns NULL.
142  */
143 smb_wka_t *
144 smb_wka_lookup_sid(smb_sid_t *sid)
145 {
146 	smb_wka_t *entry;
147 	int i;
148 
149 	(void) rw_rdlock(&wk_rwlock);
150 
151 	for (i = 0; i < SMB_WKA_NUM; ++i) {
152 		entry = &wka_tbl[i];
153 		if (smb_sid_cmp(sid, entry->wka_binsid)) {
154 			(void) rw_unlock(&wk_rwlock);
155 			return (entry);
156 		}
157 	}
158 
159 	(void) rw_unlock(&wk_rwlock);
160 	return (NULL);
161 }
162 
163 
164 /*
165  * Looks up well known accounts table for the given name.
166  * Upon success returns a pointer to the binary SID of the
167  * entry, otherwise returns NULL.
168  */
169 smb_sid_t *
170 smb_wka_get_sid(const char *name)
171 {
172 	smb_wka_t *entry;
173 	smb_sid_t *sid = NULL;
174 
175 	if ((entry = smb_wka_lookup_name(name)) != NULL)
176 		sid = entry->wka_binsid;
177 
178 	return (sid);
179 }
180 
181 /*
182  * Looks up well known accounts table for the given name.
183  * Upon success returns a pointer to the account entry in
184  * the table, otherwise returns NULL.
185  */
186 smb_wka_t *
187 smb_wka_lookup_name(const char *name)
188 {
189 	smb_wka_t *entry;
190 	int i;
191 
192 	(void) rw_rdlock(&wk_rwlock);
193 	for (i = 0; i < SMB_WKA_NUM; ++i) {
194 		entry = &wka_tbl[i];
195 		if (!smb_strcasecmp(name, entry->wka_name, 0)) {
196 			(void) rw_unlock(&wk_rwlock);
197 			return (entry);
198 		}
199 	}
200 
201 	(void) rw_unlock(&wk_rwlock);
202 	return (NULL);
203 }
204 
205 /*
206  * Lookup a name in the BUILTIN domain.
207  */
208 smb_wka_t *
209 smb_wka_lookup_builtin(const char *name)
210 {
211 	smb_wka_t	*entry;
212 	int		i;
213 
214 	(void) rw_rdlock(&wk_rwlock);
215 	for (i = 0; i < SMB_WKA_NUM; ++i) {
216 		entry = &wka_tbl[i];
217 
218 		if (entry->wka_domidx != 3)
219 			continue;
220 
221 		if (!smb_strcasecmp(name, entry->wka_name, 0)) {
222 			(void) rw_unlock(&wk_rwlock);
223 			return (entry);
224 		}
225 	}
226 
227 	(void) rw_unlock(&wk_rwlock);
228 	return (NULL);
229 }
230 
231 /*
232  * Returns the Netbios domain name for the given index
233  */
234 char *
235 smb_wka_get_domain(int idx)
236 {
237 	if ((idx >= 0) && (idx < SMB_WKA_NUM))
238 		return (wka_nbdomain[idx]);
239 
240 	return (NULL);
241 }
242 
243 /*
244  * This function adds well known groups to groups in a user's
245  * access token (gids).
246  *
247  * "Network" SID is added for all users connecting over CIFS.
248  *
249  * "Authenticated Users" SID is added for all users except Guest
250  * and Anonymous.
251  *
252  * "Guests" SID is added for guest users and Administrators SID
253  * is added for admin users.
254  */
255 uint32_t
256 smb_wka_token_groups(uint32_t flags, smb_ids_t *gids)
257 {
258 	smb_id_t *id;
259 	int total_cnt;
260 
261 	total_cnt = gids->i_cnt + 3;
262 
263 	gids->i_ids = realloc(gids->i_ids, total_cnt * sizeof (smb_id_t));
264 	if (gids->i_ids == NULL)
265 		return (NT_STATUS_NO_MEMORY);
266 
267 	id = gids->i_ids + gids->i_cnt;
268 	id->i_sid = smb_sid_dup(smb_wka_get_sid("Network"));
269 	id->i_attrs = 0x7;
270 	if (id->i_sid == NULL)
271 		return (NT_STATUS_NO_MEMORY);
272 	id++;
273 	gids->i_cnt++;
274 
275 	if ((flags & SMB_ATF_ANON) == 0) {
276 		if (flags & SMB_ATF_GUEST)
277 			id->i_sid = smb_sid_dup(smb_wka_get_sid("Guests"));
278 		else
279 			id->i_sid =
280 			    smb_sid_dup(smb_wka_get_sid("Authenticated Users"));
281 		id->i_attrs = 0x7;
282 		if (id->i_sid == NULL)
283 			return (NT_STATUS_NO_MEMORY);
284 		id++;
285 		gids->i_cnt++;
286 	}
287 
288 	if (flags & SMB_ATF_ADMIN) {
289 		id->i_sid = smb_sid_dup(smb_wka_get_sid("Administrators"));
290 		id->i_attrs = 0x7;
291 		if (id->i_sid == NULL)
292 			return (NT_STATUS_NO_MEMORY);
293 		gids->i_cnt++;
294 	}
295 
296 	return (NT_STATUS_SUCCESS);
297 }
298 
299 /*
300  * smb_wka_init
301  *
302  * Generate binary SIDs from the string SIDs in the table
303  * and set the proper field.
304  *
305  * Caller MUST not store the binary SID pointer anywhere that
306  * could lead to freeing it.
307  *
308  * This function should only be called once.
309  */
310 int
311 smb_wka_init(void)
312 {
313 	smb_wka_t *entry;
314 	int i;
315 
316 	(void) rw_wrlock(&wk_rwlock);
317 	if (wk_init) {
318 		(void) rw_unlock(&wk_rwlock);
319 		return (1);
320 	}
321 
322 	for (i = 0; i < SMB_WKA_NUM; ++i) {
323 		entry = &wka_tbl[i];
324 		entry->wka_binsid = smb_sid_fromstr(entry->wka_sid);
325 		if (entry->wka_binsid == NULL) {
326 			(void) rw_unlock(&wk_rwlock);
327 			smb_wka_fini();
328 			return (0);
329 		}
330 	}
331 
332 	wk_init = 1;
333 	(void) rw_unlock(&wk_rwlock);
334 	return (1);
335 }
336 
337 void
338 smb_wka_fini(void)
339 {
340 	int i;
341 
342 	(void) rw_wrlock(&wk_rwlock);
343 	if (wk_init == 0) {
344 		(void) rw_unlock(&wk_rwlock);
345 		return;
346 	}
347 
348 	for (i = 0; i < SMB_WKA_NUM; ++i) {
349 		if (wka_tbl[i].wka_binsid) {
350 			free(wka_tbl[i].wka_binsid);
351 			wka_tbl[i].wka_binsid = NULL;
352 		}
353 	}
354 
355 	wk_init = 0;
356 	(void) rw_unlock(&wk_rwlock);
357 }
358