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