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