11fcced4cSJordan Brown /* 21fcced4cSJordan Brown * CDDL HEADER START 31fcced4cSJordan Brown * 41fcced4cSJordan Brown * The contents of this file are subject to the terms of the 51fcced4cSJordan Brown * Common Development and Distribution License (the "License"). 61fcced4cSJordan Brown * You may not use this file except in compliance with the License. 71fcced4cSJordan Brown * 81fcced4cSJordan Brown * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91fcced4cSJordan Brown * or http://www.opensolaris.org/os/licensing. 101fcced4cSJordan Brown * See the License for the specific language governing permissions 111fcced4cSJordan Brown * and limitations under the License. 121fcced4cSJordan Brown * 131fcced4cSJordan Brown * When distributing Covered Code, include this CDDL HEADER in each 141fcced4cSJordan Brown * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151fcced4cSJordan Brown * If applicable, add the following below this CDDL HEADER, with the 161fcced4cSJordan Brown * fields enclosed by brackets "[]" replaced with your own identifying 171fcced4cSJordan Brown * information: Portions Copyright [yyyy] [name of copyright owner] 181fcced4cSJordan Brown * 191fcced4cSJordan Brown * CDDL HEADER END 201fcced4cSJordan Brown */ 211fcced4cSJordan Brown 221fcced4cSJordan Brown /* 23*cb174861Sjoyce mcintosh * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 241fcced4cSJordan Brown */ 251fcced4cSJordan Brown 261fcced4cSJordan Brown /* 271fcced4cSJordan Brown * Retrieve directory information for built-in users and groups 281fcced4cSJordan Brown */ 291fcced4cSJordan Brown 301fcced4cSJordan Brown #include <stdio.h> 311fcced4cSJordan Brown #include <limits.h> 321fcced4cSJordan Brown #include <sys/idmap.h> 331fcced4cSJordan Brown #include <sys/param.h> 341fcced4cSJordan Brown #include <string.h> 351fcced4cSJordan Brown #include <stdlib.h> 361fcced4cSJordan Brown #include <netdb.h> 37*cb174861Sjoyce mcintosh #include <libuutil.h> 381fcced4cSJordan Brown #include <note.h> 391fcced4cSJordan Brown #include "idmapd.h" 401fcced4cSJordan Brown #include "directory.h" 411fcced4cSJordan Brown #include "directory_private.h" 421fcced4cSJordan Brown #include <rpcsvc/idmap_prot.h> 431fcced4cSJordan Brown #include "directory_server_impl.h" 441fcced4cSJordan Brown #include "sidutil.h" 451fcced4cSJordan Brown 461fcced4cSJordan Brown static directory_error_t sid_dav(directory_values_rpc *lvals, 471fcced4cSJordan Brown const wksids_table_t *wksid); 481fcced4cSJordan Brown static directory_error_t directory_provider_builtin_populate( 491fcced4cSJordan Brown directory_entry_rpc *pent, const wksids_table_t *wksid, 501fcced4cSJordan Brown idmap_utf8str_list *attrs); 511fcced4cSJordan Brown 521fcced4cSJordan Brown /* 531fcced4cSJordan Brown * Retrieve information by name. 541fcced4cSJordan Brown * Called indirectly through the directory_provider_static structure. 551fcced4cSJordan Brown */ 561fcced4cSJordan Brown static 571fcced4cSJordan Brown directory_error_t 581fcced4cSJordan Brown directory_provider_builtin_get( 591fcced4cSJordan Brown directory_entry_rpc *del, 601fcced4cSJordan Brown idmap_utf8str_list *ids, 611fcced4cSJordan Brown idmap_utf8str types, 621fcced4cSJordan Brown idmap_utf8str_list *attrs) 631fcced4cSJordan Brown { 641fcced4cSJordan Brown int i; 651fcced4cSJordan Brown 661fcced4cSJordan Brown for (i = 0; i < ids->idmap_utf8str_list_len; i++) { 671fcced4cSJordan Brown const wksids_table_t *wksid; 681fcced4cSJordan Brown directory_error_t de; 691fcced4cSJordan Brown int type; 701fcced4cSJordan Brown 711fcced4cSJordan Brown /* 721fcced4cSJordan Brown * Extract the type for this particular ID. 731fcced4cSJordan Brown * Advance to the next type, if it's there, else keep 741fcced4cSJordan Brown * using this type until we run out of IDs. 751fcced4cSJordan Brown */ 761fcced4cSJordan Brown type = *types; 771fcced4cSJordan Brown if (*(types+1) != '\0') 781fcced4cSJordan Brown types++; 791fcced4cSJordan Brown 801fcced4cSJordan Brown /* 811fcced4cSJordan Brown * If this entry has already been handled, one way or another, 821fcced4cSJordan Brown * skip it. 831fcced4cSJordan Brown */ 841fcced4cSJordan Brown if (del[i].status != DIRECTORY_NOT_FOUND) 851fcced4cSJordan Brown continue; 861fcced4cSJordan Brown 871fcced4cSJordan Brown char *id = ids->idmap_utf8str_list_val[i]; 881fcced4cSJordan Brown 891fcced4cSJordan Brown /* 901fcced4cSJordan Brown * End-to-end error injection point. 911fcced4cSJordan Brown * NEEDSWORK: should probably eliminate this for production 921fcced4cSJordan Brown */ 93*cb174861Sjoyce mcintosh if (uu_streq(id, " DEBUG BUILTIN ERROR ")) { 941fcced4cSJordan Brown directory_entry_set_error(&del[i], 951fcced4cSJordan Brown directory_error("Directory_provider_builtin.debug", 961fcced4cSJordan Brown "Directory_provider_builtin: artificial error", 971fcced4cSJordan Brown NULL)); 981fcced4cSJordan Brown continue; 991fcced4cSJordan Brown } 1001fcced4cSJordan Brown 1011fcced4cSJordan Brown if (type == DIRECTORY_ID_SID[0]) 1021fcced4cSJordan Brown wksid = find_wk_by_sid(id); 1031fcced4cSJordan Brown else { 1041fcced4cSJordan Brown int idmap_id_type; 1051fcced4cSJordan Brown if (type == DIRECTORY_ID_NAME[0]) 1061fcced4cSJordan Brown idmap_id_type = IDMAP_POSIXID; 1071fcced4cSJordan Brown else if (type == DIRECTORY_ID_USER[0]) 1081fcced4cSJordan Brown idmap_id_type = IDMAP_UID; 1091fcced4cSJordan Brown else if (type == DIRECTORY_ID_GROUP[0]) 1101fcced4cSJordan Brown idmap_id_type = IDMAP_GID; 1111fcced4cSJordan Brown else { 1121fcced4cSJordan Brown directory_entry_set_error(&del[i], 1131fcced4cSJordan Brown directory_error("invalid_arg.id_type", 1141fcced4cSJordan Brown "Invalid ID type \"%1\"", 1151fcced4cSJordan Brown types, NULL)); 1161fcced4cSJordan Brown continue; 1171fcced4cSJordan Brown } 1181fcced4cSJordan Brown 1191fcced4cSJordan Brown int id_len = strlen(id); 1201fcced4cSJordan Brown char name[id_len + 1]; 1211fcced4cSJordan Brown char domain[id_len + 1]; 1221fcced4cSJordan Brown 1231fcced4cSJordan Brown split_name(name, domain, id); 1241fcced4cSJordan Brown 1251fcced4cSJordan Brown wksid = find_wksid_by_name(name, domain, idmap_id_type); 1261fcced4cSJordan Brown } 1271fcced4cSJordan Brown 1281fcced4cSJordan Brown if (wksid == NULL) 1291fcced4cSJordan Brown continue; 1301fcced4cSJordan Brown 1311fcced4cSJordan Brown de = directory_provider_builtin_populate(&del[i], wksid, attrs); 1321fcced4cSJordan Brown if (de != NULL) { 1331fcced4cSJordan Brown directory_entry_set_error(&del[i], de); 1341fcced4cSJordan Brown de = NULL; 1351fcced4cSJordan Brown } 1361fcced4cSJordan Brown } 1371fcced4cSJordan Brown 1381fcced4cSJordan Brown return (NULL); 1391fcced4cSJordan Brown } 1401fcced4cSJordan Brown 1411fcced4cSJordan Brown /* 1421fcced4cSJordan Brown * Given a well-known name entry and a list of attributes that were 1431fcced4cSJordan Brown * requested, populate the structure to return to the caller. 1441fcced4cSJordan Brown */ 1451fcced4cSJordan Brown static 1461fcced4cSJordan Brown directory_error_t 1471fcced4cSJordan Brown directory_provider_builtin_populate( 1481fcced4cSJordan Brown directory_entry_rpc *pent, 1491fcced4cSJordan Brown const wksids_table_t *wksid, 1501fcced4cSJordan Brown idmap_utf8str_list *attrs) 1511fcced4cSJordan Brown { 1521fcced4cSJordan Brown int j; 1531fcced4cSJordan Brown directory_values_rpc *llvals; 1541fcced4cSJordan Brown int nattrs; 1551fcced4cSJordan Brown 1561fcced4cSJordan Brown nattrs = attrs->idmap_utf8str_list_len; 1571fcced4cSJordan Brown 1581fcced4cSJordan Brown llvals = calloc(nattrs, sizeof (directory_values_rpc)); 1591fcced4cSJordan Brown if (llvals == NULL) 1601fcced4cSJordan Brown goto nomem; 1611fcced4cSJordan Brown 1621fcced4cSJordan Brown pent->status = DIRECTORY_FOUND; 1631fcced4cSJordan Brown pent->directory_entry_rpc_u.attrs.attrs_val = llvals; 1641fcced4cSJordan Brown pent->directory_entry_rpc_u.attrs.attrs_len = nattrs; 1651fcced4cSJordan Brown 1661fcced4cSJordan Brown for (j = 0; j < nattrs; j++) { 1671fcced4cSJordan Brown directory_values_rpc *val; 1681fcced4cSJordan Brown char *a; 1691fcced4cSJordan Brown directory_error_t de; 1701fcced4cSJordan Brown 1711fcced4cSJordan Brown /* 1721fcced4cSJordan Brown * We're going to refer to these a lot, so make a shorthand 1731fcced4cSJordan Brown * copy. 1741fcced4cSJordan Brown */ 1751fcced4cSJordan Brown a = attrs->idmap_utf8str_list_val[j]; 1761fcced4cSJordan Brown val = &llvals[j]; 1771fcced4cSJordan Brown 1781fcced4cSJordan Brown /* 1791fcced4cSJordan Brown * Start by assuming no errors and that we don't have 1801fcced4cSJordan Brown * the information. 1811fcced4cSJordan Brown */ 1821fcced4cSJordan Brown val->found = FALSE; 1831fcced4cSJordan Brown de = NULL; 1841fcced4cSJordan Brown 185*cb174861Sjoyce mcintosh if (uu_strcaseeq(a, "uid")) { 1861fcced4cSJordan Brown de = str_list_dav(val, &wksid->winname, 1); 187*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "uidNumber")) { 1889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (wksid->pid != IDMAP_SENTINEL_PID && 1899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States wksid->is_user) { 1901fcced4cSJordan Brown de = uint_list_dav(val, &wksid->pid, 1); 1911fcced4cSJordan Brown } 192*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "gidNumber")) { 1939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (wksid->pid != IDMAP_SENTINEL_PID && 1949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States !wksid->is_user) { 1951fcced4cSJordan Brown de = uint_list_dav(val, &wksid->pid, 1); 1961fcced4cSJordan Brown } 197*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "displayName") || 198*cb174861Sjoyce mcintosh uu_strcaseeq(a, "cn")) { 1991fcced4cSJordan Brown de = str_list_dav(val, &wksid->winname, 1); 200*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "distinguishedName")) { 2011fcced4cSJordan Brown char *container; 2021fcced4cSJordan Brown if (wksid->domain == NULL) { 2031fcced4cSJordan Brown container = "Users"; 2041fcced4cSJordan Brown } else { 2051fcced4cSJordan Brown container = "Builtin"; 2061fcced4cSJordan Brown } 2071fcced4cSJordan Brown RDLOCK_CONFIG(); 2081fcced4cSJordan Brown char *dn; 2091fcced4cSJordan Brown (void) asprintf(&dn, 2101fcced4cSJordan Brown "CN=%s,CN=%s,DC=%s", 2111fcced4cSJordan Brown wksid->winname, container, _idmapdstate.hostname); 2121fcced4cSJordan Brown UNLOCK_CONFIG(); 2131fcced4cSJordan Brown const char *cdn = dn; 2141fcced4cSJordan Brown de = str_list_dav(val, &cdn, 1); 2151fcced4cSJordan Brown free(dn); 216*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "objectClass")) { 2171fcced4cSJordan Brown if (wksid->is_wuser) { 2181fcced4cSJordan Brown static const char *objectClasses[] = { 2191fcced4cSJordan Brown "top", 2201fcced4cSJordan Brown "person", 2211fcced4cSJordan Brown "organizationalPerson", 2221fcced4cSJordan Brown "user", 2231fcced4cSJordan Brown }; 2241fcced4cSJordan Brown de = str_list_dav(val, objectClasses, 225*cb174861Sjoyce mcintosh UU_NELEM(objectClasses)); 2261fcced4cSJordan Brown } else { 2271fcced4cSJordan Brown static const char *objectClasses[] = { 2281fcced4cSJordan Brown "top", 2291fcced4cSJordan Brown "group", 2301fcced4cSJordan Brown }; 2311fcced4cSJordan Brown de = str_list_dav(val, objectClasses, 232*cb174861Sjoyce mcintosh UU_NELEM(objectClasses)); 2331fcced4cSJordan Brown } 234*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "objectSid")) { 2351fcced4cSJordan Brown de = sid_dav(val, wksid); 236*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "x-sun-canonicalName")) { 2371fcced4cSJordan Brown char *canon; 2381fcced4cSJordan Brown 2391fcced4cSJordan Brown if (wksid->domain == NULL) { 2401fcced4cSJordan Brown RDLOCK_CONFIG(); 2411fcced4cSJordan Brown (void) asprintf(&canon, "%s@%s", 2421fcced4cSJordan Brown wksid->winname, _idmapdstate.hostname); 2431fcced4cSJordan Brown UNLOCK_CONFIG(); 244*cb174861Sjoyce mcintosh } else if (uu_streq(wksid->domain, "")) { 2451fcced4cSJordan Brown canon = strdup(wksid->winname); 2461fcced4cSJordan Brown } else { 2471fcced4cSJordan Brown (void) asprintf(&canon, "%s@%s", 2481fcced4cSJordan Brown wksid->winname, wksid->domain); 2491fcced4cSJordan Brown } 2501fcced4cSJordan Brown 2511fcced4cSJordan Brown if (canon == NULL) 2521fcced4cSJordan Brown goto nomem; 2531fcced4cSJordan Brown const char *ccanon = canon; 2541fcced4cSJordan Brown de = str_list_dav(val, &ccanon, 1); 2551fcced4cSJordan Brown free(canon); 256*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "x-sun-provider")) { 2571fcced4cSJordan Brown const char *provider = "Builtin"; 2581fcced4cSJordan Brown de = str_list_dav(val, &provider, 1); 2591fcced4cSJordan Brown } 2601fcced4cSJordan Brown if (de != NULL) 2611fcced4cSJordan Brown return (de); 2621fcced4cSJordan Brown } 2631fcced4cSJordan Brown 2641fcced4cSJordan Brown return (NULL); 2651fcced4cSJordan Brown 2661fcced4cSJordan Brown nomem: 2671fcced4cSJordan Brown return (directory_error("ENOMEM.users", 2681fcced4cSJordan Brown "No memory allocating return value for user lookup", NULL)); 2691fcced4cSJordan Brown } 2701fcced4cSJordan Brown 2711fcced4cSJordan Brown /* 2721fcced4cSJordan Brown * Given a well-known name structure, generate a binary-format SID. 2731fcced4cSJordan Brown * It's a bit perverse that we must take a text-format SID and turn it into 2741fcced4cSJordan Brown * a binary-format SID, only to have the caller probably turn it back into 2751fcced4cSJordan Brown * text format, but SIDs are carried across LDAP in binary format. 2761fcced4cSJordan Brown */ 2771fcced4cSJordan Brown static 2781fcced4cSJordan Brown directory_error_t 2791fcced4cSJordan Brown sid_dav(directory_values_rpc *lvals, const wksids_table_t *wksid) 2801fcced4cSJordan Brown { 2811fcced4cSJordan Brown char *text_sid; 2821fcced4cSJordan Brown sid_t *sid; 2831fcced4cSJordan Brown directory_error_t de; 2841fcced4cSJordan Brown 2851fcced4cSJordan Brown if (wksid->sidprefix == NULL) { 2861fcced4cSJordan Brown RDLOCK_CONFIG(); 2871fcced4cSJordan Brown (void) asprintf(&text_sid, "%s-%d", 2881fcced4cSJordan Brown _idmapdstate.cfg->pgcfg.machine_sid, 2891fcced4cSJordan Brown wksid->rid); 2901fcced4cSJordan Brown UNLOCK_CONFIG(); 2911fcced4cSJordan Brown } else { 2921fcced4cSJordan Brown (void) asprintf(&text_sid, "%s-%d", 2931fcced4cSJordan Brown wksid->sidprefix, wksid->rid); 2941fcced4cSJordan Brown } 2951fcced4cSJordan Brown 2961fcced4cSJordan Brown if (text_sid == NULL) 2971fcced4cSJordan Brown goto nomem; 2981fcced4cSJordan Brown 2991fcced4cSJordan Brown sid = sid_fromstr(text_sid); 3001fcced4cSJordan Brown free(text_sid); 3011fcced4cSJordan Brown 3021fcced4cSJordan Brown if (sid == NULL) 3031fcced4cSJordan Brown goto nomem; 3041fcced4cSJordan Brown 3051fcced4cSJordan Brown sid_to_le(sid); 3061fcced4cSJordan Brown 3071fcced4cSJordan Brown de = bin_list_dav(lvals, sid, 1, sid_len(sid)); 3081fcced4cSJordan Brown 3091fcced4cSJordan Brown sid_free(sid); 3101fcced4cSJordan Brown 3111fcced4cSJordan Brown return (de); 3121fcced4cSJordan Brown 3131fcced4cSJordan Brown nomem: 3141fcced4cSJordan Brown return (directory_error("ENOMEM.sid_dav", 3151fcced4cSJordan Brown "No memory allocating SID for user lookup", NULL)); 3161fcced4cSJordan Brown } 3171fcced4cSJordan Brown 3181fcced4cSJordan Brown struct directory_provider_static directory_provider_builtin = { 3191fcced4cSJordan Brown "builtin", 3201fcced4cSJordan Brown directory_provider_builtin_get, 3211fcced4cSJordan Brown }; 322