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 standard UNIX users/groups. 281fcced4cSJordan Brown * (NB: not just from files, but all nsswitch sources.) 291fcced4cSJordan Brown */ 301fcced4cSJordan Brown 311fcced4cSJordan Brown #include <pwd.h> 321fcced4cSJordan Brown #include <grp.h> 331fcced4cSJordan Brown #include <malloc.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 <errno.h> 401fcced4cSJordan Brown #include "idmapd.h" 411fcced4cSJordan Brown #include "directory.h" 421fcced4cSJordan Brown #include "directory_private.h" 431fcced4cSJordan Brown #include <rpcsvc/idmap_prot.h> 441fcced4cSJordan Brown #include "directory_server_impl.h" 451fcced4cSJordan Brown #include "sidutil.h" 461fcced4cSJordan Brown 471fcced4cSJordan Brown static directory_error_t machine_sid_dav(directory_values_rpc *lvals, 481fcced4cSJordan Brown unsigned int rid); 491fcced4cSJordan Brown static directory_error_t directory_provider_nsswitch_populate( 501fcced4cSJordan Brown directory_entry_rpc *pent, struct passwd *pwd, struct group *grp, 511fcced4cSJordan Brown idmap_utf8str_list *attrs); 521fcced4cSJordan Brown 531fcced4cSJordan Brown /* 541fcced4cSJordan Brown * Retrieve information by name. 551fcced4cSJordan Brown * Called indirectly through the directory_provider_static structure. 561fcced4cSJordan Brown */ 571fcced4cSJordan Brown static 581fcced4cSJordan Brown directory_error_t 591fcced4cSJordan Brown directory_provider_nsswitch_get( 601fcced4cSJordan Brown directory_entry_rpc *del, 611fcced4cSJordan Brown idmap_utf8str_list *ids, 621fcced4cSJordan Brown idmap_utf8str types, 631fcced4cSJordan Brown idmap_utf8str_list *attrs) 641fcced4cSJordan Brown { 651fcced4cSJordan Brown int i; 661fcced4cSJordan Brown 671fcced4cSJordan Brown RDLOCK_CONFIG(); 681fcced4cSJordan Brown 691fcced4cSJordan Brown /* 6835280 spurious lint error if the strlen is in the declaration */ 701fcced4cSJordan Brown int host_name_len = strlen(_idmapdstate.hostname); 711fcced4cSJordan Brown char my_host_name[host_name_len + 1]; 721fcced4cSJordan Brown (void) strcpy(my_host_name, _idmapdstate.hostname); 731fcced4cSJordan Brown 741fcced4cSJordan Brown /* We use len later, so this is not merely a workaround for 6835280 */ 751fcced4cSJordan Brown int machine_sid_len = strlen(_idmapdstate.cfg->pgcfg.machine_sid); 761fcced4cSJordan Brown char my_machine_sid[machine_sid_len + 1]; 771fcced4cSJordan Brown (void) strcpy(my_machine_sid, _idmapdstate.cfg->pgcfg.machine_sid); 781fcced4cSJordan Brown 791fcced4cSJordan Brown UNLOCK_CONFIG(); 801fcced4cSJordan Brown 811fcced4cSJordan Brown for (i = 0; i < ids->idmap_utf8str_list_len; i++) { 821fcced4cSJordan Brown struct passwd *pwd = NULL; 831fcced4cSJordan Brown struct group *grp = NULL; 841fcced4cSJordan Brown directory_error_t de; 851fcced4cSJordan Brown int type; 861fcced4cSJordan Brown 871fcced4cSJordan Brown /* 881fcced4cSJordan Brown * Extract the type for this particular ID. 891fcced4cSJordan Brown * Advance to the next type, if it's there, else keep 901fcced4cSJordan Brown * using this type until we run out of IDs. 911fcced4cSJordan Brown */ 921fcced4cSJordan Brown type = *types; 931fcced4cSJordan Brown if (*(types+1) != '\0') 941fcced4cSJordan Brown types++; 951fcced4cSJordan Brown 961fcced4cSJordan Brown /* 971fcced4cSJordan Brown * If this entry has already been handled, one way or another, 981fcced4cSJordan Brown * skip it. 991fcced4cSJordan Brown */ 1001fcced4cSJordan Brown if (del[i].status != DIRECTORY_NOT_FOUND) 1011fcced4cSJordan Brown continue; 1021fcced4cSJordan Brown 1031fcced4cSJordan Brown char *id = ids->idmap_utf8str_list_val[i]; 1041fcced4cSJordan Brown 1051fcced4cSJordan Brown if (type == DIRECTORY_ID_SID[0]) { 1061fcced4cSJordan Brown /* 1071fcced4cSJordan Brown * Is it our SID? 1081fcced4cSJordan Brown * Check whether the first part matches, then a "-", 1091fcced4cSJordan Brown * then a single RID. 1101fcced4cSJordan Brown */ 1111fcced4cSJordan Brown if (strncasecmp(id, my_machine_sid, machine_sid_len) != 1121fcced4cSJordan Brown 0) 1131fcced4cSJordan Brown continue; 1141fcced4cSJordan Brown if (id[machine_sid_len] != '-') 1151fcced4cSJordan Brown continue; 1161fcced4cSJordan Brown char *p; 1171fcced4cSJordan Brown uint32_t rid = 1181fcced4cSJordan Brown strtoul(id + machine_sid_len + 1, &p, 10); 1191fcced4cSJordan Brown if (*p != '\0') 1201fcced4cSJordan Brown continue; 1211fcced4cSJordan Brown 1221fcced4cSJordan Brown if (rid < LOCALRID_UID_MIN) { 1231fcced4cSJordan Brown /* Builtin, not handled here */ 1241fcced4cSJordan Brown continue; 1251fcced4cSJordan Brown } 1261fcced4cSJordan Brown 1271fcced4cSJordan Brown if (rid <= LOCALRID_UID_MAX) { 1281fcced4cSJordan Brown /* User */ 1291fcced4cSJordan Brown errno = 0; 1301fcced4cSJordan Brown pwd = getpwuid(rid - LOCALRID_UID_MIN); 1311fcced4cSJordan Brown if (pwd == NULL) { 1321fcced4cSJordan Brown if (errno == 0) /* Not found */ 1331fcced4cSJordan Brown continue; 1341fcced4cSJordan Brown char buf[40]; 1351fcced4cSJordan Brown int err = errno; 1361fcced4cSJordan Brown (void) snprintf(buf, sizeof (buf), 1371fcced4cSJordan Brown "%d", err); 1381fcced4cSJordan Brown directory_entry_set_error(&del[i], 1391fcced4cSJordan Brown directory_error("errno.getpwuid", 1401fcced4cSJordan Brown "getpwuid: %2 (%1)", 1411fcced4cSJordan Brown buf, strerror(err), NULL)); 1421fcced4cSJordan Brown continue; 1431fcced4cSJordan Brown } 1441fcced4cSJordan Brown } else if (rid >= LOCALRID_GID_MIN && 1451fcced4cSJordan Brown rid <= LOCALRID_GID_MAX) { 1461fcced4cSJordan Brown /* Group */ 1471fcced4cSJordan Brown errno = 0; 1481fcced4cSJordan Brown grp = getgrgid(rid - LOCALRID_GID_MIN); 1491fcced4cSJordan Brown if (grp == NULL) { 1501fcced4cSJordan Brown if (errno == 0) /* Not found */ 1511fcced4cSJordan Brown continue; 1521fcced4cSJordan Brown char buf[40]; 1531fcced4cSJordan Brown int err = errno; 1541fcced4cSJordan Brown (void) snprintf(buf, sizeof (buf), 1551fcced4cSJordan Brown "%d", err); 1561fcced4cSJordan Brown directory_entry_set_error(&del[i], 1571fcced4cSJordan Brown directory_error("errno.getgrgid", 1581fcced4cSJordan Brown "getgrgid: %2 (%1)", 1591fcced4cSJordan Brown buf, strerror(err), NULL)); 1601fcced4cSJordan Brown continue; 1611fcced4cSJordan Brown } 1621fcced4cSJordan Brown } else 1631fcced4cSJordan Brown continue; 1641fcced4cSJordan Brown 1651fcced4cSJordan Brown } else { 1661fcced4cSJordan Brown int id_len = strlen(id); 1671fcced4cSJordan Brown char name[id_len + 1]; 1681fcced4cSJordan Brown char domain[id_len + 1]; 1691fcced4cSJordan Brown 1701fcced4cSJordan Brown split_name(name, domain, id); 1711fcced4cSJordan Brown 1721fcced4cSJordan Brown if (domain[0] != '\0') { 1731fcced4cSJordan Brown if (!domain_eq(domain, my_host_name)) 1741fcced4cSJordan Brown continue; 1751fcced4cSJordan Brown } 1761fcced4cSJordan Brown 1771fcced4cSJordan Brown /* 1781fcced4cSJordan Brown * If the caller has requested user or group 1791fcced4cSJordan Brown * information specifically, we only set one of 1801fcced4cSJordan Brown * pwd or grp. 1811fcced4cSJordan Brown * If the caller has requested either type, we try 1821fcced4cSJordan Brown * both in the hopes of getting one. 1831fcced4cSJordan Brown * Note that directory_provider_nsswitch_populate 1841fcced4cSJordan Brown * considers it to be an error if both are set. 1851fcced4cSJordan Brown */ 1861fcced4cSJordan Brown if (type != DIRECTORY_ID_GROUP[0]) { 1871fcced4cSJordan Brown /* prep for not found / error case */ 1881fcced4cSJordan Brown errno = 0; 1891fcced4cSJordan Brown 1901fcced4cSJordan Brown pwd = getpwnam(name); 1911fcced4cSJordan Brown if (pwd == NULL && errno != 0) { 1921fcced4cSJordan Brown char buf[40]; 1931fcced4cSJordan Brown int err = errno; 1941fcced4cSJordan Brown (void) snprintf(buf, sizeof (buf), 1951fcced4cSJordan Brown "%d", err); 1961fcced4cSJordan Brown directory_entry_set_error(&del[i], 1971fcced4cSJordan Brown directory_error("errno.getpwnam", 1981fcced4cSJordan Brown "getpwnam: %2 (%1)", 1991fcced4cSJordan Brown buf, strerror(err), NULL)); 2001fcced4cSJordan Brown continue; 2011fcced4cSJordan Brown } 2021fcced4cSJordan Brown } 2031fcced4cSJordan Brown 2041fcced4cSJordan Brown if (type != DIRECTORY_ID_USER[0]) { 2051fcced4cSJordan Brown /* prep for not found / error case */ 2061fcced4cSJordan Brown errno = 0; 2071fcced4cSJordan Brown 2081fcced4cSJordan Brown grp = getgrnam(name); 2091fcced4cSJordan Brown if (grp == NULL && errno != 0) { 2101fcced4cSJordan Brown char buf[40]; 2111fcced4cSJordan Brown int err = errno; 2121fcced4cSJordan Brown (void) snprintf(buf, sizeof (buf), 2131fcced4cSJordan Brown "%d", err); 2141fcced4cSJordan Brown directory_entry_set_error(&del[i], 2151fcced4cSJordan Brown directory_error("errno.getgrnam", 2161fcced4cSJordan Brown "getgrnam: %2 (%1)", 2171fcced4cSJordan Brown buf, strerror(err), NULL)); 2181fcced4cSJordan Brown continue; 2191fcced4cSJordan Brown } 2201fcced4cSJordan Brown } 2211fcced4cSJordan Brown } 2221fcced4cSJordan Brown 2231fcced4cSJordan Brown /* 2241fcced4cSJordan Brown * Didn't find it, don't populate the structure. 2251fcced4cSJordan Brown * Another provider might populate it. 2261fcced4cSJordan Brown */ 2271fcced4cSJordan Brown if (pwd == NULL && grp == NULL) 2281fcced4cSJordan Brown continue; 2291fcced4cSJordan Brown 2301fcced4cSJordan Brown de = directory_provider_nsswitch_populate(&del[i], pwd, grp, 2311fcced4cSJordan Brown attrs); 2321fcced4cSJordan Brown if (de != NULL) { 2331fcced4cSJordan Brown directory_entry_set_error(&del[i], de); 2341fcced4cSJordan Brown de = NULL; 2351fcced4cSJordan Brown continue; 2361fcced4cSJordan Brown } 2371fcced4cSJordan Brown } 2381fcced4cSJordan Brown 2391fcced4cSJordan Brown return (NULL); 2401fcced4cSJordan Brown } 2411fcced4cSJordan Brown 2421fcced4cSJordan Brown /* 2431fcced4cSJordan Brown * Given a pwd structure or a grp structure, and a list of attributes that 2441fcced4cSJordan Brown * were requested, populate the structure to return to the caller. 2451fcced4cSJordan Brown */ 2461fcced4cSJordan Brown static 2471fcced4cSJordan Brown directory_error_t 2481fcced4cSJordan Brown directory_provider_nsswitch_populate( 2491fcced4cSJordan Brown directory_entry_rpc *pent, 2501fcced4cSJordan Brown struct passwd *pwd, 2511fcced4cSJordan Brown struct group *grp, 2521fcced4cSJordan Brown idmap_utf8str_list *attrs) 2531fcced4cSJordan Brown { 2541fcced4cSJordan Brown int j; 2551fcced4cSJordan Brown directory_values_rpc *llvals; 2561fcced4cSJordan Brown int nattrs; 2571fcced4cSJordan Brown 2581fcced4cSJordan Brown /* 2591fcced4cSJordan Brown * If it wasn't for this case, everything would be a lot simpler. 2601fcced4cSJordan Brown * UNIX allows users and groups with the same name. Windows doesn't. 2611fcced4cSJordan Brown */ 2621fcced4cSJordan Brown if (pwd != NULL && grp != NULL) { 2631fcced4cSJordan Brown return directory_error("Ambiguous.Name", 2641fcced4cSJordan Brown "Ambiguous name, is both a user and a group", 2651fcced4cSJordan Brown NULL); 2661fcced4cSJordan Brown } 2671fcced4cSJordan Brown 2681fcced4cSJordan Brown nattrs = attrs->idmap_utf8str_list_len; 2691fcced4cSJordan Brown 2701fcced4cSJordan Brown llvals = calloc(nattrs, sizeof (directory_values_rpc)); 2711fcced4cSJordan Brown if (llvals == NULL) 2721fcced4cSJordan Brown goto nomem; 2731fcced4cSJordan Brown 2741fcced4cSJordan Brown pent->directory_entry_rpc_u.attrs.attrs_val = llvals; 2751fcced4cSJordan Brown pent->directory_entry_rpc_u.attrs.attrs_len = nattrs; 2761fcced4cSJordan Brown pent->status = DIRECTORY_FOUND; 2771fcced4cSJordan Brown 2781fcced4cSJordan Brown for (j = 0; j < nattrs; j++) { 2791fcced4cSJordan Brown directory_values_rpc *val; 2801fcced4cSJordan Brown char *a; 2811fcced4cSJordan Brown directory_error_t de; 2821fcced4cSJordan Brown 2831fcced4cSJordan Brown /* 2841fcced4cSJordan Brown * We're going to refer to these a lot, so make a shorthand 2851fcced4cSJordan Brown * copy. 2861fcced4cSJordan Brown */ 2871fcced4cSJordan Brown a = attrs->idmap_utf8str_list_val[j]; 2881fcced4cSJordan Brown val = &llvals[j]; 2891fcced4cSJordan Brown 2901fcced4cSJordan Brown /* 2911fcced4cSJordan Brown * Start by assuming no errors and that we don't have 2921fcced4cSJordan Brown * the information 2931fcced4cSJordan Brown */ 2941fcced4cSJordan Brown val->found = FALSE; 2951fcced4cSJordan Brown de = NULL; 2961fcced4cSJordan Brown 2971fcced4cSJordan Brown if (pwd != NULL) { 2981fcced4cSJordan Brown /* 2991fcced4cSJordan Brown * Handle attributes for user entries. 3001fcced4cSJordan Brown */ 301*cb174861Sjoyce mcintosh if (uu_strcaseeq(a, "cn")) { 3021fcced4cSJordan Brown const char *p = pwd->pw_name; 3031fcced4cSJordan Brown de = str_list_dav(val, &p, 1); 304*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "objectClass")) { 3051fcced4cSJordan Brown static const char *objectClasses[] = { 3061fcced4cSJordan Brown "top", 3071fcced4cSJordan Brown "posixAccount", 3081fcced4cSJordan Brown }; 3091fcced4cSJordan Brown de = str_list_dav(val, objectClasses, 310*cb174861Sjoyce mcintosh UU_NELEM(objectClasses)); 311*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "gidNumber")) { 3121fcced4cSJordan Brown de = uint_list_dav(val, &pwd->pw_gid, 1); 313*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "objectSid")) { 3141fcced4cSJordan Brown de = machine_sid_dav(val, 3151fcced4cSJordan Brown pwd->pw_uid + LOCALRID_UID_MIN); 316*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "displayName")) { 3171fcced4cSJordan Brown const char *p = pwd->pw_gecos; 3181fcced4cSJordan Brown de = str_list_dav(val, &p, 1); 319*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "distinguishedName")) { 3201fcced4cSJordan Brown char *dn; 3211fcced4cSJordan Brown RDLOCK_CONFIG(); 3221fcced4cSJordan Brown (void) asprintf(&dn, 3231fcced4cSJordan Brown "uid=%s,ou=people,dc=%s", 3241fcced4cSJordan Brown pwd->pw_name, _idmapdstate.hostname); 3251fcced4cSJordan Brown UNLOCK_CONFIG(); 3261fcced4cSJordan Brown if (dn == NULL) 3271fcced4cSJordan Brown goto nomem; 3281fcced4cSJordan Brown const char *cdn = dn; 3291fcced4cSJordan Brown de = str_list_dav(val, &cdn, 1); 3301fcced4cSJordan Brown free(dn); 331*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "uid")) { 3321fcced4cSJordan Brown const char *p = pwd->pw_name; 3331fcced4cSJordan Brown de = str_list_dav(val, &p, 1); 334*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "uidNumber")) { 3351fcced4cSJordan Brown de = uint_list_dav(val, &pwd->pw_uid, 1); 336*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "gecos")) { 3371fcced4cSJordan Brown const char *p = pwd->pw_gecos; 3381fcced4cSJordan Brown de = str_list_dav(val, &p, 1); 339*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "homeDirectory")) { 3401fcced4cSJordan Brown const char *p = pwd->pw_dir; 3411fcced4cSJordan Brown de = str_list_dav(val, &p, 1); 342*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "loginShell")) { 3431fcced4cSJordan Brown const char *p = pwd->pw_shell; 3441fcced4cSJordan Brown de = str_list_dav(val, &p, 1); 345*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "x-sun-canonicalName")) { 3461fcced4cSJordan Brown char *canon; 3471fcced4cSJordan Brown RDLOCK_CONFIG(); 3481fcced4cSJordan Brown (void) asprintf(&canon, "%s@%s", 3491fcced4cSJordan Brown pwd->pw_name, _idmapdstate.hostname); 3501fcced4cSJordan Brown UNLOCK_CONFIG(); 3511fcced4cSJordan Brown if (canon == NULL) 3521fcced4cSJordan Brown goto nomem; 3531fcced4cSJordan Brown const char *ccanon = canon; 3541fcced4cSJordan Brown de = str_list_dav(val, &ccanon, 1); 3551fcced4cSJordan Brown free(canon); 356*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "x-sun-provider")) { 3571fcced4cSJordan Brown const char *provider = "UNIX-passwd"; 3581fcced4cSJordan Brown de = str_list_dav(val, &provider, 1); 3591fcced4cSJordan Brown } 3601fcced4cSJordan Brown } else if (grp != NULL) { 3611fcced4cSJordan Brown /* 3621fcced4cSJordan Brown * Handle attributes for group entries. 3631fcced4cSJordan Brown */ 364*cb174861Sjoyce mcintosh if (uu_strcaseeq(a, "cn")) { 3651fcced4cSJordan Brown const char *p = grp->gr_name; 3661fcced4cSJordan Brown de = str_list_dav(val, &p, 1); 367*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "objectClass")) { 3681fcced4cSJordan Brown static const char *objectClasses[] = { 3691fcced4cSJordan Brown "top", 3701fcced4cSJordan Brown "posixGroup", 3711fcced4cSJordan Brown }; 3721fcced4cSJordan Brown de = str_list_dav(val, objectClasses, 373*cb174861Sjoyce mcintosh UU_NELEM(objectClasses)); 374*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "gidNumber")) { 3751fcced4cSJordan Brown de = uint_list_dav(val, &grp->gr_gid, 1); 376*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "objectSid")) { 3771fcced4cSJordan Brown de = machine_sid_dav(val, 3781fcced4cSJordan Brown grp->gr_gid + LOCALRID_GID_MIN); 379*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "displayName")) { 3801fcced4cSJordan Brown const char *p = grp->gr_name; 3811fcced4cSJordan Brown de = str_list_dav(val, &p, 1); 382*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "distinguishedName")) { 3831fcced4cSJordan Brown char *dn; 3841fcced4cSJordan Brown RDLOCK_CONFIG(); 3851fcced4cSJordan Brown (void) asprintf(&dn, 3861fcced4cSJordan Brown "cn=%s,ou=group,dc=%s", 3871fcced4cSJordan Brown grp->gr_name, _idmapdstate.hostname); 3881fcced4cSJordan Brown UNLOCK_CONFIG(); 3891fcced4cSJordan Brown if (dn == NULL) 3901fcced4cSJordan Brown goto nomem; 3911fcced4cSJordan Brown const char *cdn = dn; 3921fcced4cSJordan Brown de = str_list_dav(val, &cdn, 1); 3931fcced4cSJordan Brown free(dn); 394*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "memberUid")) { 3951fcced4cSJordan Brown /* 3961fcced4cSJordan Brown * NEEDSWORK: There is probably a non-cast 3971fcced4cSJordan Brown * way to do this, but I don't immediately 3981fcced4cSJordan Brown * see it. 3991fcced4cSJordan Brown */ 4001fcced4cSJordan Brown const char * const *members = 4011fcced4cSJordan Brown (const char * const *)grp->gr_mem; 4021fcced4cSJordan Brown de = str_list_dav(val, members, 0); 403*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "x-sun-canonicalName")) { 4041fcced4cSJordan Brown char *canon; 4051fcced4cSJordan Brown RDLOCK_CONFIG(); 4061fcced4cSJordan Brown (void) asprintf(&canon, "%s@%s", 4071fcced4cSJordan Brown grp->gr_name, _idmapdstate.hostname); 4081fcced4cSJordan Brown UNLOCK_CONFIG(); 4091fcced4cSJordan Brown if (canon == NULL) 4101fcced4cSJordan Brown goto nomem; 4111fcced4cSJordan Brown const char *ccanon = canon; 4121fcced4cSJordan Brown de = str_list_dav(val, &ccanon, 1); 4131fcced4cSJordan Brown free(canon); 414*cb174861Sjoyce mcintosh } else if (uu_strcaseeq(a, "x-sun-provider")) { 4151fcced4cSJordan Brown const char *provider = "UNIX-group"; 4161fcced4cSJordan Brown de = str_list_dav(val, &provider, 1); 4171fcced4cSJordan Brown } 4181fcced4cSJordan Brown } 4191fcced4cSJordan Brown 4201fcced4cSJordan Brown if (de != NULL) 4211fcced4cSJordan Brown return (de); 4221fcced4cSJordan Brown } 4231fcced4cSJordan Brown 4241fcced4cSJordan Brown return (NULL); 4251fcced4cSJordan Brown 4261fcced4cSJordan Brown nomem: 4271fcced4cSJordan Brown return (directory_error("ENOMEM.users", 4281fcced4cSJordan Brown "No memory allocating return value for user lookup", NULL)); 4291fcced4cSJordan Brown } 4301fcced4cSJordan Brown 4311fcced4cSJordan Brown /* 4321fcced4cSJordan Brown * Populate a directory attribute value with a SID based on our machine SID 4331fcced4cSJordan Brown * and the specified RID. 4341fcced4cSJordan Brown * 4351fcced4cSJordan Brown * It's a bit perverse that we must take a text-format SID and turn it into 4361fcced4cSJordan Brown * a binary-format SID, only to have the caller probably turn it back into 4371fcced4cSJordan Brown * text format, but SIDs are carried across LDAP in binary format. 4381fcced4cSJordan Brown */ 4391fcced4cSJordan Brown static 4401fcced4cSJordan Brown directory_error_t 4411fcced4cSJordan Brown machine_sid_dav(directory_values_rpc *lvals, unsigned int rid) 4421fcced4cSJordan Brown { 4431fcced4cSJordan Brown sid_t *sid; 4441fcced4cSJordan Brown directory_error_t de; 4451fcced4cSJordan Brown 4461fcced4cSJordan Brown RDLOCK_CONFIG(); 4471fcced4cSJordan Brown int len = strlen(_idmapdstate.cfg->pgcfg.machine_sid); 4481fcced4cSJordan Brown char buf[len + 100]; /* 100 is enough space for any RID */ 4491fcced4cSJordan Brown (void) snprintf(buf, sizeof (buf), "%s-%u", 4501fcced4cSJordan Brown _idmapdstate.cfg->pgcfg.machine_sid, rid); 4511fcced4cSJordan Brown UNLOCK_CONFIG(); 4521fcced4cSJordan Brown 4531fcced4cSJordan Brown sid = sid_fromstr(buf); 4541fcced4cSJordan Brown if (sid == NULL) 4551fcced4cSJordan Brown goto nomem; 4561fcced4cSJordan Brown 4571fcced4cSJordan Brown sid_to_le(sid); 4581fcced4cSJordan Brown 4591fcced4cSJordan Brown de = bin_list_dav(lvals, sid, 1, sid_len(sid)); 4601fcced4cSJordan Brown sid_free(sid); 4611fcced4cSJordan Brown return (de); 4621fcced4cSJordan Brown 4631fcced4cSJordan Brown nomem: 4641fcced4cSJordan Brown return (directory_error("ENOMEM.machine_sid_dav", 4651fcced4cSJordan Brown "Out of memory allocating return value for lookup", NULL)); 4661fcced4cSJordan Brown } 4671fcced4cSJordan Brown 4681fcced4cSJordan Brown struct directory_provider_static directory_provider_nsswitch = { 4691fcced4cSJordan Brown "files", 4701fcced4cSJordan Brown directory_provider_nsswitch_get, 4711fcced4cSJordan Brown }; 472