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 /*
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * Information about well-known (builtin) names, and functions to retrieve
28 * information about them.
29 */
30
31 #include <assert.h>
32 #include <string.h>
33 #include <libuutil.h>
34 #include "idmapd.h"
35
36 /*
37 * Table for well-known SIDs.
38 *
39 * Background:
40 *
41 * Some of the well-known principals are stored under:
42 * cn=WellKnown Security Principals, cn=Configuration, dc=<forestRootDomain>
43 * They belong to objectClass "foreignSecurityPrincipal". They don't have
44 * "samAccountName" nor "userPrincipalName" attributes. Their names are
45 * available in "cn" and "name" attributes. Some of these principals have a
46 * second entry under CN=ForeignSecurityPrincipals,dc=<forestRootDomain> and
47 * these duplicate entries have the stringified SID in the "name" and "cn"
48 * attributes instead of the actual name.
49 *
50 * Those of the form S-1-5-32-X are Builtin groups and are stored in the
51 * cn=builtin container (except, Power Users which is not stored in AD)
52 *
53 * These principals are and will remain constant. Therefore doing AD lookups
54 * provides no benefit. Also, using hard-coded table (and thus avoiding AD
55 * lookup) improves performance and avoids additional complexity in the
56 * adutils.c code. Moreover these SIDs can be used when no Active Directory
57 * is available (such as the CIFS server's "workgroup" mode).
58 *
59 * Notes:
60 * 1. Currently we don't support localization of well-known SID names,
61 * unlike Windows.
62 *
63 * 2. Other well-known SIDs i.e. S-1-5-<domain>-<w-k RID> are not stored
64 * here. AD does have normal user/group objects for these objects and
65 * can be looked up using the existing AD lookup code.
66 *
67 * 3. See comments above lookup_wksids_sid2pid() for more information
68 * on how we lookup the wksids table.
69 *
70 * 4. If this table contains two entries for a particular Windows name,
71 * so as to offer both UID and GID mappings, the preferred mapping (the
72 * one that matches Windows usage) must be listed first. That is the
73 * entry that will be used when the caller specifies IDMAP_POSIXID
74 * ("don't care") as the target.
75 *
76 * Entries here come from KB243330, MS-LSAT, and
77 * http://technet.microsoft.com/en-us/library/cc755854.aspx
78 * http://technet.microsoft.com/en-us/library/cc755925.aspx
79 * http://msdn.microsoft.com/en-us/library/cc980032(PROT.10).aspx
80 */
81 static wksids_table_t wksids[] = {
82 /* S-1-0 Null Authority */
83 {"S-1-0", 0, "", "Nobody", 1, IDMAP_SENTINEL_PID, -1, 1},
84
85 /* S-1-1 World Authority */
86 {"S-1-1", 0, "", "Everyone", 0, IDMAP_SENTINEL_PID, -1, -1},
87
88 /* S-1-2 Local Authority */
89 {"S-1-2", 0, "", "Local", 0, IDMAP_SENTINEL_PID, -1, -1},
90 {"S-1-2", 1, "", "Console Logon", 0, IDMAP_SENTINEL_PID, -1, -1},
91
92 /* S-1-3 Creator Authority */
93 {"S-1-3", 0, "", "Creator Owner", 1, IDMAP_WK_CREATOR_OWNER_UID, 1, 0},
94 {"S-1-3", 1, "", "Creator Group", 0, IDMAP_WK_CREATOR_GROUP_GID, 0, 0},
95 {"S-1-3", 2, "", "Creator Owner Server", 1, IDMAP_SENTINEL_PID, -1, -1},
96 {"S-1-3", 3, "", "Creator Group Server", 0, IDMAP_SENTINEL_PID, -1, 1},
97 {"S-1-3", 4, "", "Owner Rights", 0, IDMAP_SENTINEL_PID, -1, -1},
98
99 /* S-1-4 Non-unique Authority */
100
101 /* S-1-5 NT Authority */
102 {"S-1-5", 1, "", "Dialup", 0, IDMAP_SENTINEL_PID, -1, -1},
103 {"S-1-5", 2, "", "Network", 0, IDMAP_SENTINEL_PID, -1, -1},
104 {"S-1-5", 3, "", "Batch", 0, IDMAP_SENTINEL_PID, -1, -1},
105 {"S-1-5", 4, "", "Interactive", 0, IDMAP_SENTINEL_PID, -1, -1},
106 /* S-1-5-5-X-Y Logon Session */
107 {"S-1-5", 6, "", "Service", 0, IDMAP_SENTINEL_PID, -1, -1},
108 {"S-1-5", 7, "", "Anonymous Logon", 0, GID_NOBODY, 0, 0},
109 {"S-1-5", 7, "", "Anonymous Logon", 0, UID_NOBODY, 1, 0},
110 {"S-1-5", 8, "", "Proxy", 0, IDMAP_SENTINEL_PID, -1, -1},
111 {"S-1-5", 9, "", "Enterprise Domain Controllers", 0,
112 IDMAP_SENTINEL_PID, -1, -1},
113 {"S-1-5", 10, "", "Self", 0, IDMAP_SENTINEL_PID, -1, -1},
114 {"S-1-5", 11, "", "Authenticated Users", 0, IDMAP_SENTINEL_PID, -1, -1},
115 {"S-1-5", 12, "", "Restricted", 0, IDMAP_SENTINEL_PID, -1, -1},
116 {"S-1-5", 13, "", "Terminal Server Users", 0,
117 IDMAP_SENTINEL_PID, -1, -1},
118 {"S-1-5", 14, "", "Remote Interactive Logon", 0,
119 IDMAP_SENTINEL_PID, -1, -1},
120 {"S-1-5", 15, "", "This Organization", 0, IDMAP_SENTINEL_PID, -1, -1},
121 {"S-1-5", 17, "", "IUSR", 0, IDMAP_SENTINEL_PID, -1, -1},
122 {"S-1-5", 18, "", "Local System", 0, IDMAP_WK_LOCAL_SYSTEM_GID, 0, 0},
123 {"S-1-5", 19, "", "Local Service", 0, IDMAP_SENTINEL_PID, -1, -1},
124 {"S-1-5", 20, "", "Network Service", 0, IDMAP_SENTINEL_PID, -1, -1},
125
126 /* S-1-5-21-<domain> Machine-local definitions */
127 {NULL, 498, NULL, "Enterprise Read-only Domain Controllers", 0,
128 IDMAP_SENTINEL_PID, -1, -1},
129 {NULL, 500, NULL, "Administrator", 1, IDMAP_SENTINEL_PID, 1, -1},
130 {NULL, 501, NULL, "Guest", 1, IDMAP_SENTINEL_PID, 1, -1},
131 {NULL, 502, NULL, "KRBTGT", 1, IDMAP_SENTINEL_PID, 1, -1},
132 {NULL, 512, NULL, "Domain Admins", 0, IDMAP_SENTINEL_PID, -1, -1},
133 {NULL, 513, NULL, "Domain Users", 0, IDMAP_SENTINEL_PID, -1, -1},
134 {NULL, 514, NULL, "Domain Guests", 0, IDMAP_SENTINEL_PID, -1, -1},
135 {NULL, 515, NULL, "Domain Computers", 0, IDMAP_SENTINEL_PID, -1, -1},
136 {NULL, 516, NULL, "Domain Controllers", 0, IDMAP_SENTINEL_PID, -1, -1},
137 {NULL, 517, NULL, "Cert Publishers", 0, IDMAP_SENTINEL_PID, -1, -1},
138 {NULL, 518, NULL, "Schema Admins", 0, IDMAP_SENTINEL_PID, -1, -1},
139 {NULL, 519, NULL, "Enterprise Admins", 0, IDMAP_SENTINEL_PID, -1, -1},
140 {NULL, 520, NULL, "Global Policy Creator Owners", 0,
141 IDMAP_SENTINEL_PID, -1, -1},
142 {NULL, 533, NULL, "RAS and IAS Servers", 0, IDMAP_SENTINEL_PID, -1, -1},
143
144 /* S-1-5-32 BUILTIN */
145 {"S-1-5-32", 544, "BUILTIN", "Administrators", 0,
146 IDMAP_SENTINEL_PID, -1, -1},
147 {"S-1-5-32", 545, "BUILTIN", "Users", 0, IDMAP_SENTINEL_PID, -1, -1},
148 {"S-1-5-32", 546, "BUILTIN", "Guests", 0, IDMAP_SENTINEL_PID, -1, -1},
149 {"S-1-5-32", 547, "BUILTIN", "Power Users", 0,
150 IDMAP_SENTINEL_PID, -1, -1},
151 {"S-1-5-32", 548, "BUILTIN", "Account Operators", 0,
152 IDMAP_SENTINEL_PID, -1, -1},
153 {"S-1-5-32", 549, "BUILTIN", "Server Operators", 0,
154 IDMAP_SENTINEL_PID, -1, -1},
155 {"S-1-5-32", 550, "BUILTIN", "Print Operators", 0,
156 IDMAP_SENTINEL_PID, -1, -1},
157 {"S-1-5-32", 551, "BUILTIN", "Backup Operators", 0,
158 IDMAP_SENTINEL_PID, -1, -1},
159 {"S-1-5-32", 552, "BUILTIN", "Replicator", 0,
160 IDMAP_SENTINEL_PID, -1, -1},
161 {"S-1-5-32", 554, "BUILTIN", "Pre-Windows 2000 Compatible Access", 0,
162 IDMAP_SENTINEL_PID, -1, -1},
163 {"S-1-5-32", 555, "BUILTIN", "Remote Desktop Users", 0,
164 IDMAP_SENTINEL_PID, -1, -1},
165 {"S-1-5-32", 556, "BUILTIN", "Network Configuration Operators", 0,
166 IDMAP_SENTINEL_PID, -1, -1},
167 {"S-1-5-32", 557, "BUILTIN", "Incoming Forest Trust Builders", 0,
168 IDMAP_SENTINEL_PID, -1, -1},
169 {"S-1-5-32", 558, "BUILTIN", "Performance Monitor Users", 0,
170 IDMAP_SENTINEL_PID, -1, -1},
171 {"S-1-5-32", 559, "BUILTIN", "Performance Log Users", 0,
172 IDMAP_SENTINEL_PID, -1, -1},
173 {"S-1-5-32", 560, "BUILTIN", "Windows Authorization Access Group", 0,
174 IDMAP_SENTINEL_PID, -1, -1},
175 {"S-1-5-32", 561, "BUILTIN", "Terminal Server License Servers", 0,
176 IDMAP_SENTINEL_PID, -1, -1},
177 {"S-1-5-32", 562, "BUILTIN", "Distributed COM Users", 0,
178 IDMAP_SENTINEL_PID, -1, -1},
179 {"S-1-5-32", 568, "BUILTIN", "IIS_IUSRS", 0,
180 IDMAP_SENTINEL_PID, -1, -1},
181 {"S-1-5-32", 569, "BUILTIN", "Cryptographic Operators", 0,
182 IDMAP_SENTINEL_PID, -1, -1},
183 {"S-1-5-32", 573, "BUILTIN", "Event Log Readers", 0,
184 IDMAP_SENTINEL_PID, -1, -1},
185 {"S-1-5-32", 574, "BUILTIN", "Certificate Service DCOM Access", 0,
186 IDMAP_SENTINEL_PID, -1, -1},
187
188 {"S-1-5", 33, "", "Write Restricted", 0, IDMAP_SENTINEL_PID, -1, -1},
189
190 /* S-1-5-64 NT Authority */
191 {"S-1-5-64", 10, "", "NTLM Authentication", 0,
192 IDMAP_SENTINEL_PID, -1, -1},
193 {"S-1-5-64", 14, "", "SChannel Authentication", 0,
194 IDMAP_SENTINEL_PID, -1, -1},
195 {"S-1-5-64", 21, "", "Digest Authentication", 0,
196 IDMAP_SENTINEL_PID, -1, -1},
197
198 /* S-1-5-80-a-b-c-d NT Service */
199
200 {"S-1-5", 1000, "", "Other Organization", 0,
201 IDMAP_SENTINEL_PID, -1, -1},
202
203 /* S-1-7 Internet$ */
204
205 /*
206 * S-1-16 Mandatory Label
207 * S-1-16-0 Untrusted Mandatory Level
208 * S-1-16-4096 Low Mandatory Level
209 * S-1-16-8192 Medium Mandatory Level
210 * S-1-16-8448 Medium Plus Mandatory Level
211 * S-1-16-12288 High Mandatory Level
212 * S-1-16-16384 System Mandatory Level
213 * S-1-16-20480 Protected Process Mandatory Level
214 */
215 };
216
217 /*
218 * Find a wksid entry for the specified Windows name and domain, of the
219 * specified type.
220 *
221 * Ignore entries intended only for U2W use.
222 */
223 const
224 wksids_table_t *
find_wksid_by_name(const char * name,const char * domain,idmap_id_type type)225 find_wksid_by_name(const char *name, const char *domain, idmap_id_type type)
226 {
227 int i;
228
229 RDLOCK_CONFIG();
230 int len = strlen(_idmapdstate.hostname);
231 char my_host_name[len + 1];
232 (void) strcpy(my_host_name, _idmapdstate.hostname);
233 UNLOCK_CONFIG();
234
235 for (i = 0; i < UU_NELEM(wksids); i++) {
236 /* Check to see if this entry yields the desired type */
237 switch (type) {
238 case IDMAP_UID:
239 if (wksids[i].is_user == 0)
240 continue;
241 break;
242 case IDMAP_GID:
243 if (wksids[i].is_user == 1)
244 continue;
245 break;
246 case IDMAP_POSIXID:
247 break;
248 default:
249 assert(FALSE);
250 }
251
252 if (strcasecmp(wksids[i].winname, name) != 0)
253 continue;
254
255 if (!EMPTY_STRING(domain)) {
256 const char *dom;
257
258 if (wksids[i].domain != NULL) {
259 dom = wksids[i].domain;
260 } else {
261 dom = my_host_name;
262 }
263 if (strcasecmp(dom, domain) != 0)
264 continue;
265 }
266
267 /*
268 * We have a Windows name, so ignore entries that are only
269 * usable for mapping UNIX->Windows. (Note: the current
270 * table does not have any such entries.)
271 */
272 if (wksids[i].direction == IDMAP_DIRECTION_U2W)
273 continue;
274
275 return (&wksids[i]);
276 }
277
278 return (NULL);
279 }
280
281 /*
282 * Find a wksid entry for the specified SID, of the specified type.
283 *
284 * Ignore entries intended only for U2W use.
285 */
286 const
287 wksids_table_t *
find_wksid_by_sid(const char * sid,int rid,idmap_id_type type)288 find_wksid_by_sid(const char *sid, int rid, idmap_id_type type)
289 {
290 int i;
291
292 RDLOCK_CONFIG();
293 int len = strlen(_idmapdstate.cfg->pgcfg.machine_sid);
294 char my_machine_sid[len + 1];
295 (void) strcpy(my_machine_sid, _idmapdstate.cfg->pgcfg.machine_sid);
296 UNLOCK_CONFIG();
297
298 for (i = 0; i < UU_NELEM(wksids); i++) {
299 int sidcmp;
300
301 /* Check to see if this entry yields the desired type */
302 switch (type) {
303 case IDMAP_UID:
304 if (wksids[i].is_user == 0)
305 continue;
306 break;
307 case IDMAP_GID:
308 if (wksids[i].is_user == 1)
309 continue;
310 break;
311 case IDMAP_POSIXID:
312 break;
313 default:
314 assert(FALSE);
315 }
316
317 if (wksids[i].sidprefix != NULL) {
318 sidcmp = strcasecmp(wksids[i].sidprefix, sid);
319 } else {
320 sidcmp = strcasecmp(my_machine_sid, sid);
321 }
322
323 if (sidcmp != 0)
324 continue;
325 if (wksids[i].rid != rid)
326 continue;
327
328 /*
329 * We have a SID, so ignore entries that are only usable
330 * for mapping UNIX->Windows. (Note: the current table
331 * does not have any such entries.)
332 */
333 if (wksids[i].direction == IDMAP_DIRECTION_U2W)
334 continue;
335
336 return (&wksids[i]);
337 }
338
339 return (NULL);
340 }
341
342 /*
343 * Find a wksid entry for the specified pid, of the specified type.
344 * Ignore entries that do not specify U2W mappings.
345 */
346 const
347 wksids_table_t *
find_wksid_by_pid(uid_t pid,int is_user)348 find_wksid_by_pid(uid_t pid, int is_user)
349 {
350 int i;
351
352 if (pid == IDMAP_SENTINEL_PID)
353 return (NULL);
354
355 for (i = 0; i < UU_NELEM(wksids); i++) {
356 if (wksids[i].pid == pid &&
357 wksids[i].is_user == is_user &&
358 (wksids[i].direction == IDMAP_DIRECTION_BI ||
359 wksids[i].direction == IDMAP_DIRECTION_U2W)) {
360 return (&wksids[i]);
361 }
362 }
363 return (NULL);
364 }
365
366 /*
367 * It is probably a bug that both this and find_wksid_by_sid exist,
368 * but for now the distinction is primarily that one takes {machinesid,rid}
369 * and the other takes a full SID.
370 */
371 const
372 wksids_table_t *
find_wk_by_sid(char * sid)373 find_wk_by_sid(char *sid)
374 {
375 int i;
376
377 RDLOCK_CONFIG();
378 int len = strlen(_idmapdstate.cfg->pgcfg.machine_sid);
379 char my_machine_sid[len + 1];
380 (void) strcpy(my_machine_sid, _idmapdstate.cfg->pgcfg.machine_sid);
381 UNLOCK_CONFIG();
382
383 for (i = 0; i < UU_NELEM(wksids); i++) {
384 int len;
385 const char *prefix;
386 char *p;
387 unsigned long rid;
388
389 if (wksids[i].sidprefix == NULL)
390 prefix = my_machine_sid;
391 else
392 prefix = wksids[i].sidprefix;
393
394 len = strlen(prefix);
395
396 /*
397 * Check to see whether the SID we're looking for starts
398 * with this prefix, then a -, then a single RID, and it's
399 * the right RID.
400 */
401 if (strncasecmp(sid, prefix, len) != 0)
402 continue;
403 if (sid[len] != '-')
404 continue;
405 rid = strtoul(sid + len + 1, &p, 10);
406 if (*p != '\0')
407 continue;
408
409 if (rid != wksids[i].rid)
410 continue;
411
412 return (&wksids[i]);
413 }
414 return (NULL);
415 }
416