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