Home | History | Annotate | Download | only in idmapd
      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 2009 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, SENTINEL_PID, -1, 1},
     85 
     86 	/* S-1-1	World Authority */
     87 	{"S-1-1", 0, "", "Everyone", 0, SENTINEL_PID, -1, -1},
     88 
     89 	/* S-1-2	Local Authority */
     90 	{"S-1-2", 0, "", "Local", 0, SENTINEL_PID, -1, -1},
     91 	{"S-1-2", 1, "", "Console Logon", 0, 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, SENTINEL_PID, -1, -1},
     97 	{"S-1-3", 3, "", "Creator Group Server", 0, SENTINEL_PID, -1, 1},
     98 	{"S-1-3", 4, "", "Owner Rights", 0, 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, SENTINEL_PID, -1, -1},
    104 	{"S-1-5", 2, "", "Network", 0, SENTINEL_PID, -1, -1},
    105 	{"S-1-5", 3, "", "Batch", 0, SENTINEL_PID, -1, -1},
    106 	{"S-1-5", 4, "", "Interactive", 0, SENTINEL_PID, -1, -1},
    107 	/* S-1-5-5-X-Y	Logon Session */
    108 	{"S-1-5", 6, "", "Service", 0, 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, SENTINEL_PID, -1, -1},
    112 	{"S-1-5", 9, "", "Enterprise Domain Controllers", 0,
    113 	    SENTINEL_PID, -1, -1},
    114 	{"S-1-5", 10, "", "Self", 0, SENTINEL_PID, -1, -1},
    115 	{"S-1-5", 11, "", "Authenticated Users", 0, SENTINEL_PID, -1, -1},
    116 	{"S-1-5", 12, "", "Restricted", 0, SENTINEL_PID, -1, -1},
    117 	{"S-1-5", 13, "", "Terminal Server Users", 0, SENTINEL_PID, -1, -1},
    118 	{"S-1-5", 14, "", "Remote Interactive Logon", 0, SENTINEL_PID, -1, -1},
    119 	{"S-1-5", 15, "", "This Organization", 0, SENTINEL_PID, -1, -1},
    120 	{"S-1-5", 17, "", "IUSR", 0, SENTINEL_PID, -1, -1},
    121 	{"S-1-5", 18, "", "Local System", 0, IDMAP_WK_LOCAL_SYSTEM_GID, 0, 0},
    122 	{"S-1-5", 19, "", "Local Service", 0, SENTINEL_PID, -1, -1},
    123 	{"S-1-5", 20, "", "Network Service", 0, SENTINEL_PID, -1, -1},
    124 
    125 	/* S-1-5-21-<domain>	Machine-local definitions */
    126 	{NULL, 498, NULL, "Enterprise Read-only Domain Controllers", 0,
    127 	    SENTINEL_PID, -1, -1},
    128 	{NULL, 500, NULL, "Administrator", 1, SENTINEL_PID, 1, -1},
    129 	{NULL, 501, NULL, "Guest", 1, SENTINEL_PID, 1, -1},
    130 	{NULL, 502, NULL, "KRBTGT", 1, SENTINEL_PID, 1, -1},
    131 	{NULL, 512, NULL, "Domain Admins", 0, SENTINEL_PID, -1, -1},
    132 	{NULL, 513, NULL, "Domain Users", 0, SENTINEL_PID, -1, -1},
    133 	{NULL, 514, NULL, "Domain Guests", 0, SENTINEL_PID, -1, -1},
    134 	{NULL, 515, NULL, "Domain Computers", 0, SENTINEL_PID, -1, -1},
    135 	{NULL, 516, NULL, "Domain Controllers", 0, SENTINEL_PID, -1, -1},
    136 	{NULL, 517, NULL, "Cert Publishers", 0, SENTINEL_PID, -1, -1},
    137 	{NULL, 518, NULL, "Schema Admins", 0, SENTINEL_PID, -1, -1},
    138 	{NULL, 519, NULL, "Enterprise Admins", 0, SENTINEL_PID, -1, -1},
    139 	{NULL, 520, NULL, "Global Policy Creator Owners", 0,
    140 	    SENTINEL_PID, -1, -1},
    141 	{NULL, 533, NULL, "RAS and IAS Servers", 0, SENTINEL_PID, -1, -1},
    142 
    143 	/* S-1-5-32	BUILTIN */
    144 	{"S-1-5-32", 544, "BUILTIN", "Administrators", 0, SENTINEL_PID, -1, -1},
    145 	{"S-1-5-32", 545, "BUILTIN", "Users", 0, SENTINEL_PID, -1, -1},
    146 	{"S-1-5-32", 546, "BUILTIN", "Guests", 0, SENTINEL_PID, -1, -1},
    147 	{"S-1-5-32", 547, "BUILTIN", "Power Users", 0, SENTINEL_PID, -1, -1},
    148 	{"S-1-5-32", 548, "BUILTIN", "Account Operators", 0,
    149 	    SENTINEL_PID, -1, -1},
    150 	{"S-1-5-32", 549, "BUILTIN", "Server Operators", 0,
    151 	    SENTINEL_PID, -1, -1},
    152 	{"S-1-5-32", 550, "BUILTIN", "Print Operators", 0,
    153 	    SENTINEL_PID, -1, -1},
    154 	{"S-1-5-32", 551, "BUILTIN", "Backup Operators", 0,
    155 	    SENTINEL_PID, -1, -1},
    156 	{"S-1-5-32", 552, "BUILTIN", "Replicator", 0, SENTINEL_PID, -1, -1},
    157 	{"S-1-5-32", 554, "BUILTIN", "Pre-Windows 2000 Compatible Access", 0,
    158 	    SENTINEL_PID, -1, -1},
    159 	{"S-1-5-32", 555, "BUILTIN", "Remote Desktop Users", 0,
    160 	    SENTINEL_PID, -1, -1},
    161 	{"S-1-5-32", 556, "BUILTIN", "Network Configuration Operators", 0,
    162 	    SENTINEL_PID, -1, -1},
    163 	{"S-1-5-32", 557, "BUILTIN", "Incoming Forest Trust Builders", 0,
    164 	    SENTINEL_PID, -1, -1},
    165 	{"S-1-5-32", 558, "BUILTIN", "Performance Monitor Users", 0,
    166 	    SENTINEL_PID, -1, -1},
    167 	{"S-1-5-32", 559, "BUILTIN", "Performance Log Users", 0,
    168 	    SENTINEL_PID, -1, -1},
    169 	{"S-1-5-32", 560, "BUILTIN", "Windows Authorization Access Group", 0,
    170 	    SENTINEL_PID, -1, -1},
    171 	{"S-1-5-32", 561, "BUILTIN", "Terminal Server License Servers", 0,
    172 	    SENTINEL_PID, -1, -1},
    173 	{"S-1-5-32", 562, "BUILTIN", "Distributed COM Users", 0,
    174 	    SENTINEL_PID, -1, -1},
    175 	{"S-1-5-32", 568, "BUILTIN", "IIS_IUSRS", 0, SENTINEL_PID, -1, -1},
    176 	{"S-1-5-32", 569, "BUILTIN", "Cryptographic Operators", 0,
    177 	    SENTINEL_PID, -1, -1},
    178 	{"S-1-5-32", 573, "BUILTIN", "Event Log Readers", 0,
    179 	    SENTINEL_PID, -1, -1},
    180 	{"S-1-5-32", 574, "BUILTIN", "Certificate Service DCOM Access", 0,
    181 	    SENTINEL_PID, -1, -1},
    182 
    183 	{"S-1-5", 33, "", "Write Restricted", 0, SENTINEL_PID, -1, -1},
    184 
    185 	/* S-1-5-64	NT Authority */
    186 	{"S-1-5-64", 10, "", "NTLM Authentication", 0, SENTINEL_PID, -1, -1},
    187 	{"S-1-5-64", 14, "", "SChannel Authentication", 0,
    188 	    SENTINEL_PID, -1, -1},
    189 	{"S-1-5-64", 21, "", "Digest Authentication", 0, SENTINEL_PID, -1, -1},
    190 
    191 	/* S-1-5-80-a-b-c-d NT Service */
    192 
    193 	{"S-1-5", 1000, "", "Other Organization", 0, SENTINEL_PID, -1, -1},
    194 
    195 	/* S-1-7 Internet$ */
    196 
    197 	/*
    198 	 * S-1-16	Mandatory Label
    199 	 * S-1-16-0	Untrusted Mandatory Level
    200 	 * S-1-16-4096	Low Mandatory Level
    201 	 * S-1-16-8192	Medium Mandatory Level
    202 	 * S-1-16-8448	Medium Plus Mandatory Level
    203 	 * S-1-16-12288	High Mandatory Level
    204 	 * S-1-16-16384	System Mandatory Level
    205 	 * S-1-16-20480	Protected Process Mandatory Level
    206 	 */
    207 };
    208 
    209 /*
    210  * Find a wksid entry for the specified Windows name and domain, of the
    211  * specified type.
    212  *
    213  * Ignore entries intended only for U2W use.
    214  */
    215 const
    216 wksids_table_t *
    217 find_wksid_by_name(const char *name, const char *domain, int type)
    218 {
    219 	int i;
    220 
    221 	RDLOCK_CONFIG();
    222 	int len = strlen(_idmapdstate.hostname);
    223 	char my_host_name[len + 1];
    224 	(void) strcpy(my_host_name, _idmapdstate.hostname);
    225 	UNLOCK_CONFIG();
    226 
    227 	for (i = 0; i < NELEM(wksids); i++) {
    228 		/* Check to see if this entry yields the desired type */
    229 		switch (type) {
    230 		case IDMAP_UID:
    231 			if (wksids[i].is_user == 0)
    232 				continue;
    233 			break;
    234 		case IDMAP_GID:
    235 			if (wksids[i].is_user == 1)
    236 				continue;
    237 			break;
    238 		case IDMAP_POSIXID:
    239 			break;
    240 		default:
    241 			assert(FALSE);
    242 		}
    243 
    244 		if (strcasecmp(wksids[i].winname, name) != 0)
    245 			continue;
    246 
    247 		if (!EMPTY_STRING(domain)) {
    248 			const char *dom;
    249 
    250 			if (wksids[i].domain != NULL) {
    251 				dom = wksids[i].domain;
    252 			} else {
    253 				dom = my_host_name;
    254 			}
    255 			if (strcasecmp(dom, domain) != 0)
    256 				continue;
    257 		}
    258 
    259 		/*
    260 		 * We have a Windows name, so ignore entries that are only
    261 		 * usable for mapping UNIX->Windows.  (Note:  the current
    262 		 * table does not have any such entries.)
    263 		 */
    264 		if (wksids[i].direction == IDMAP_DIRECTION_U2W)
    265 			continue;
    266 
    267 		return (&wksids[i]);
    268 	}
    269 
    270 	return (NULL);
    271 }
    272 
    273 /*
    274  * Find a wksid entry for the specified SID, of the specified type.
    275  *
    276  * Ignore entries intended only for U2W use.
    277  */
    278 const
    279 wksids_table_t *
    280 find_wksid_by_sid(const char *sid, int rid, int type)
    281 {
    282 	int i;
    283 
    284 	RDLOCK_CONFIG();
    285 	int len = strlen(_idmapdstate.cfg->pgcfg.machine_sid);
    286 	char my_machine_sid[len + 1];
    287 	(void) strcpy(my_machine_sid, _idmapdstate.cfg->pgcfg.machine_sid);
    288 	UNLOCK_CONFIG();
    289 
    290 	for (i = 0; i < NELEM(wksids); i++) {
    291 		int sidcmp;
    292 
    293 		/* Check to see if this entry yields the desired type */
    294 		switch (type) {
    295 		case IDMAP_UID:
    296 			if (wksids[i].is_user == 0)
    297 				continue;
    298 			break;
    299 		case IDMAP_GID:
    300 			if (wksids[i].is_user == 1)
    301 				continue;
    302 			break;
    303 		case IDMAP_POSIXID:
    304 			break;
    305 		default:
    306 			assert(FALSE);
    307 		}
    308 
    309 		if (wksids[i].sidprefix != NULL) {
    310 			sidcmp = strcasecmp(wksids[i].sidprefix, sid);
    311 		} else {
    312 			sidcmp = strcasecmp(my_machine_sid, sid);
    313 		}
    314 
    315 		if (sidcmp != 0)
    316 			continue;
    317 		if (wksids[i].rid != rid)
    318 			continue;
    319 
    320 		/*
    321 		 * We have a SID, so ignore entries that are only usable
    322 		 * for mapping UNIX->Windows.  (Note:  the current table
    323 		 * does not have any such entries.)
    324 		 */
    325 		if (wksids[i].direction == IDMAP_DIRECTION_U2W)
    326 			continue;
    327 
    328 		return (&wksids[i]);
    329 	}
    330 
    331 	return (NULL);
    332 }
    333 
    334 /*
    335  * Find a wksid entry for the specified pid, of the specified type.
    336  * Ignore entries that do not specify U2W mappings.
    337  */
    338 const
    339 wksids_table_t *
    340 find_wksid_by_pid(uid_t pid, int is_user)
    341 {
    342 	int i;
    343 
    344 	if (pid == SENTINEL_PID)
    345 		return (NULL);
    346 
    347 	for (i = 0; i < NELEM(wksids); i++) {
    348 		if (wksids[i].pid == pid &&
    349 		    wksids[i].is_user == is_user &&
    350 		    (wksids[i].direction == IDMAP_DIRECTION_BI ||
    351 		    wksids[i].direction == IDMAP_DIRECTION_U2W)) {
    352 			return (&wksids[i]);
    353 		}
    354 	}
    355 	return (NULL);
    356 }
    357 
    358 /*
    359  * It is probably a bug that both this and find_wksid_by_sid exist,
    360  * but for now the distinction is primarily that one takes {machinesid,rid}
    361  * and the other takes a full SID.
    362  */
    363 const
    364 wksids_table_t *
    365 find_wk_by_sid(char *sid)
    366 {
    367 	int i;
    368 
    369 	RDLOCK_CONFIG();
    370 	int len = strlen(_idmapdstate.cfg->pgcfg.machine_sid);
    371 	char my_machine_sid[len + 1];
    372 	(void) strcpy(my_machine_sid, _idmapdstate.cfg->pgcfg.machine_sid);
    373 	UNLOCK_CONFIG();
    374 
    375 	for (i = 0; i < NELEM(wksids); i++) {
    376 		int len;
    377 		const char *prefix;
    378 		char *p;
    379 		unsigned long rid;
    380 
    381 		if (wksids[i].sidprefix == NULL)
    382 			prefix = my_machine_sid;
    383 		else
    384 			prefix = wksids[i].sidprefix;
    385 
    386 		len = strlen(prefix);
    387 
    388 		/*
    389 		 * Check to see whether the SID we're looking for starts
    390 		 * with this prefix, then a -, then a single RID, and it's
    391 		 * the right RID.
    392 		 */
    393 		if (strncasecmp(sid, prefix, len) != 0)
    394 			continue;
    395 		if (sid[len] != '-')
    396 			continue;
    397 		rid = strtoul(sid + len + 1, &p, 10);
    398 		if (*p != '\0')
    399 			continue;
    400 
    401 		if (rid != wksids[i].rid)
    402 			continue;
    403 
    404 		return (&wksids[i]);
    405 	}
    406 	return (NULL);
    407 }
    408