xref: /illumos-gate/usr/src/cmd/idmap/idmapd/wksids.c (revision e0f1c0afa46cc84d4b1e40124032a9a87310386e)
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 *
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 *
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 *
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 *
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