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