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 /*
23c5866007SKeyur Desai * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
241fcced4cSJordan Brown */
251fcced4cSJordan Brown
261fcced4cSJordan Brown /*
271fcced4cSJordan Brown * Some helper routines for directory lookup. These offer functions that
281fcced4cSJordan Brown * you could implement yourself on top of the generic routines, but since
291fcced4cSJordan Brown * they're a common request we implement them here. (Well, OK, we cheat a bit
301fcced4cSJordan Brown * and call an internal routine to do the dirty work to reduce code
311fcced4cSJordan Brown * duplication, but you could still implement them using the generic routines.)
321fcced4cSJordan Brown */
331fcced4cSJordan Brown
341fcced4cSJordan Brown #include <stdio.h>
351fcced4cSJordan Brown #include <string.h>
36*cb174861Sjoyce mcintosh #include <libuutil.h>
371fcced4cSJordan Brown #include <rpcsvc/idmap_prot.h>
381fcced4cSJordan Brown #include "directory.h"
391fcced4cSJordan Brown #include "directory_private.h"
401fcced4cSJordan Brown #include "directory_library_impl.h"
411fcced4cSJordan Brown #include "sidutil.h"
421fcced4cSJordan Brown
431fcced4cSJordan Brown /*
441fcced4cSJordan Brown * Given a username, return a text-form SID.
451fcced4cSJordan Brown *
461fcced4cSJordan Brown * The SID must be free()ed by the caller.
471fcced4cSJordan Brown *
481fcced4cSJordan Brown * d, if non-NULL, specifies an existing directory-search context.
491fcced4cSJordan Brown * If NULL, a temporary one will be created.
501fcced4cSJordan Brown */
511fcced4cSJordan Brown directory_error_t
directory_sid_from_name_common(directory_t d,char * name,char * type,char ** sid,uint64_t * classes)521fcced4cSJordan Brown directory_sid_from_name_common(
531fcced4cSJordan Brown directory_t d,
541fcced4cSJordan Brown char *name,
551fcced4cSJordan Brown char *type,
561fcced4cSJordan Brown char **sid,
571fcced4cSJordan Brown uint64_t *classes)
581fcced4cSJordan Brown {
591fcced4cSJordan Brown directory_t d1 = NULL;
601fcced4cSJordan Brown static char *attrs[] = {
611fcced4cSJordan Brown "objectSid",
621fcced4cSJordan Brown "objectClass",
631fcced4cSJordan Brown NULL,
641fcced4cSJordan Brown };
651fcced4cSJordan Brown directory_entry_t *ret_list = NULL;
661fcced4cSJordan Brown directory_error_t de;
671fcced4cSJordan Brown struct ret_sid {
681fcced4cSJordan Brown sid_t **objectSid;
691fcced4cSJordan Brown char **objectClass;
701fcced4cSJordan Brown } *ret_sid;
711fcced4cSJordan Brown
721fcced4cSJordan Brown /* Prep for error cases. */
731fcced4cSJordan Brown *sid = NULL;
741fcced4cSJordan Brown if (classes != NULL)
751fcced4cSJordan Brown *classes = 0;
761fcced4cSJordan Brown
771fcced4cSJordan Brown if (d == NULL) {
781fcced4cSJordan Brown de = directory_open(&d1);
791fcced4cSJordan Brown if (de != NULL)
801fcced4cSJordan Brown goto out;
811fcced4cSJordan Brown } else {
821fcced4cSJordan Brown d1 = d;
831fcced4cSJordan Brown }
841fcced4cSJordan Brown
851fcced4cSJordan Brown de = directory_get_v(d1, &ret_list, &name, 1, type, attrs);
861fcced4cSJordan Brown if (de != NULL)
871fcced4cSJordan Brown goto out;
881fcced4cSJordan Brown if (ret_list[0].err != NULL) {
891fcced4cSJordan Brown de = ret_list[0].err;
901fcced4cSJordan Brown ret_list[0].err = NULL;
911fcced4cSJordan Brown goto out;
921fcced4cSJordan Brown }
931fcced4cSJordan Brown
941fcced4cSJordan Brown ret_sid = (struct ret_sid *)ret_list[0].attrs;
951fcced4cSJordan Brown if (ret_sid == NULL)
961fcced4cSJordan Brown goto out;
971fcced4cSJordan Brown
981fcced4cSJordan Brown if (ret_sid->objectSid != NULL &&
991fcced4cSJordan Brown ret_sid->objectSid[0] != NULL) {
1001fcced4cSJordan Brown char text_sid[SID_STRSZ+1];
1011fcced4cSJordan Brown sid_from_le(ret_sid->objectSid[0]);
1021fcced4cSJordan Brown sid_tostr(ret_sid->objectSid[0], text_sid);
1031fcced4cSJordan Brown *sid = strdup(text_sid);
1041fcced4cSJordan Brown if (*sid == NULL)
1051fcced4cSJordan Brown goto nomem;
1061fcced4cSJordan Brown }
1071fcced4cSJordan Brown
1081fcced4cSJordan Brown if (ret_sid->objectClass != NULL &&
1091fcced4cSJordan Brown classes != NULL)
1101fcced4cSJordan Brown *classes = class_bitmap(ret_sid->objectClass);
1111fcced4cSJordan Brown
1121fcced4cSJordan Brown goto out;
1131fcced4cSJordan Brown
1141fcced4cSJordan Brown nomem:
1151fcced4cSJordan Brown de = directory_error("ENOMEM.directory_sid_from_name_common",
1161fcced4cSJordan Brown "Insufficient memory retrieving data about SID", NULL);
1171fcced4cSJordan Brown
1181fcced4cSJordan Brown out:
1191fcced4cSJordan Brown directory_free(ret_list);
1201fcced4cSJordan Brown if (d == NULL)
1211fcced4cSJordan Brown directory_close(d1);
1221fcced4cSJordan Brown return (de);
1231fcced4cSJordan Brown }
1241fcced4cSJordan Brown
1251fcced4cSJordan Brown directory_error_t
directory_sid_from_name(directory_t d,char * name,char ** sid,uint64_t * classes)1261fcced4cSJordan Brown directory_sid_from_name(
1271fcced4cSJordan Brown directory_t d,
1281fcced4cSJordan Brown char *name,
1291fcced4cSJordan Brown char **sid,
1301fcced4cSJordan Brown uint64_t *classes)
1311fcced4cSJordan Brown {
1321fcced4cSJordan Brown return (directory_sid_from_name_common(d, name, DIRECTORY_ID_NAME, sid,
1331fcced4cSJordan Brown classes));
1341fcced4cSJordan Brown }
1351fcced4cSJordan Brown
1361fcced4cSJordan Brown directory_error_t
directory_sid_from_user_name(directory_t d,char * name,char ** sid)1371fcced4cSJordan Brown directory_sid_from_user_name(directory_t d, char *name, char **sid)
1381fcced4cSJordan Brown {
1391fcced4cSJordan Brown return (directory_sid_from_name_common(d, name, DIRECTORY_ID_USER, sid,
1401fcced4cSJordan Brown NULL));
1411fcced4cSJordan Brown }
1421fcced4cSJordan Brown
1431fcced4cSJordan Brown directory_error_t
directory_sid_from_group_name(directory_t d,char * name,char ** sid)1441fcced4cSJordan Brown directory_sid_from_group_name(directory_t d, char *name, char **sid)
1451fcced4cSJordan Brown {
1461fcced4cSJordan Brown return (directory_sid_from_name_common(d, name, DIRECTORY_ID_GROUP, sid,
1471fcced4cSJordan Brown NULL));
1481fcced4cSJordan Brown }
1491fcced4cSJordan Brown
1501fcced4cSJordan Brown /*
1511fcced4cSJordan Brown * Given a name or text-format SID, return a user@domain.
1521fcced4cSJordan Brown *
1531fcced4cSJordan Brown * The user@domain returned must be free()ed by the caller.
1541fcced4cSJordan Brown *
1551fcced4cSJordan Brown * Returns NULL and sets *name to NULL if no error occurred but the specified
1561fcced4cSJordan Brown * entity does not exist.
1571fcced4cSJordan Brown *
1581fcced4cSJordan Brown * d, if non-NULL, specifies an existing directory-search context.
1591fcced4cSJordan Brown * If NULL, a temporary one will be created.
1601fcced4cSJordan Brown */
1611fcced4cSJordan Brown static
1621fcced4cSJordan Brown directory_error_t
directory_canon_common(directory_t d,char * id,char * id_type,char ** canon,uint64_t * classes)1631fcced4cSJordan Brown directory_canon_common(
1641fcced4cSJordan Brown directory_t d,
1651fcced4cSJordan Brown char *id,
1661fcced4cSJordan Brown char *id_type,
1671fcced4cSJordan Brown char **canon,
1681fcced4cSJordan Brown uint64_t *classes)
1691fcced4cSJordan Brown {
1701fcced4cSJordan Brown directory_t d1 = NULL;
1711fcced4cSJordan Brown directory_entry_t *ret_list = NULL;
1721fcced4cSJordan Brown directory_error_t de;
1731fcced4cSJordan Brown /*
1741fcced4cSJordan Brown * Attributes required to generate a canonical name, in named-list and
1751fcced4cSJordan Brown * structure form.
1761fcced4cSJordan Brown */
1771fcced4cSJordan Brown static char *attrs[] = {
1781fcced4cSJordan Brown "x-sun-canonicalName",
1791fcced4cSJordan Brown "objectClass",
1801fcced4cSJordan Brown NULL,
1811fcced4cSJordan Brown };
1821fcced4cSJordan Brown
1831fcced4cSJordan Brown struct canon_name_ret {
1841fcced4cSJordan Brown char **x_sun_canonicalName;
1851fcced4cSJordan Brown char **objectClass;
1861fcced4cSJordan Brown } *ret_name;
1871fcced4cSJordan Brown
1881fcced4cSJordan Brown /* Prep for error cases. */
1891fcced4cSJordan Brown *canon = NULL;
1901fcced4cSJordan Brown if (classes != NULL)
1911fcced4cSJordan Brown *classes = 0;
1921fcced4cSJordan Brown
1931fcced4cSJordan Brown if (d == NULL) {
1941fcced4cSJordan Brown de = directory_open(&d1);
1951fcced4cSJordan Brown if (de != NULL)
1961fcced4cSJordan Brown goto out;
1971fcced4cSJordan Brown } else {
1981fcced4cSJordan Brown d1 = d;
1991fcced4cSJordan Brown }
2001fcced4cSJordan Brown
2011fcced4cSJordan Brown de = directory_get_v(d1, &ret_list, &id, 1, id_type, attrs);
2021fcced4cSJordan Brown if (de != NULL)
2031fcced4cSJordan Brown goto out;
2041fcced4cSJordan Brown if (ret_list[0].err != NULL) {
2051fcced4cSJordan Brown de = ret_list[0].err;
2061fcced4cSJordan Brown ret_list[0].err = NULL;
2071fcced4cSJordan Brown goto out;
2081fcced4cSJordan Brown }
2091fcced4cSJordan Brown
2101fcced4cSJordan Brown ret_name = (struct canon_name_ret *)ret_list[0].attrs;
2111fcced4cSJordan Brown if (ret_name == NULL)
2121fcced4cSJordan Brown goto out;
2131fcced4cSJordan Brown
2141fcced4cSJordan Brown if (ret_name->x_sun_canonicalName != NULL &&
2151fcced4cSJordan Brown ret_name->x_sun_canonicalName[0] != NULL) {
2161fcced4cSJordan Brown *canon = strdup(ret_name->x_sun_canonicalName[0]);
2171fcced4cSJordan Brown if (*canon == NULL)
2181fcced4cSJordan Brown goto nomem;
2191fcced4cSJordan Brown }
2201fcced4cSJordan Brown
2211fcced4cSJordan Brown if (ret_name->objectClass != NULL &&
2221fcced4cSJordan Brown classes != NULL)
2231fcced4cSJordan Brown *classes = class_bitmap(ret_name->objectClass);
2241fcced4cSJordan Brown
2251fcced4cSJordan Brown goto out;
2261fcced4cSJordan Brown
2271fcced4cSJordan Brown nomem:
2281fcced4cSJordan Brown de = directory_error("ENOMEM.directory_canon_common",
2291fcced4cSJordan Brown "Insufficient memory retrieving data about name", NULL);
2301fcced4cSJordan Brown
2311fcced4cSJordan Brown out:
2321fcced4cSJordan Brown directory_free(ret_list);
2331fcced4cSJordan Brown if (d == NULL)
2341fcced4cSJordan Brown directory_close(d1);
2351fcced4cSJordan Brown return (de);
2361fcced4cSJordan Brown }
2371fcced4cSJordan Brown
2381fcced4cSJordan Brown directory_error_t
directory_name_from_sid(directory_t d,char * sid,char ** canon,uint64_t * classes)2391fcced4cSJordan Brown directory_name_from_sid(
2401fcced4cSJordan Brown directory_t d,
2411fcced4cSJordan Brown char *sid,
2421fcced4cSJordan Brown char **canon,
2431fcced4cSJordan Brown uint64_t *classes)
2441fcced4cSJordan Brown {
2451fcced4cSJordan Brown return (directory_canon_common(d, sid, DIRECTORY_ID_SID, canon,
2461fcced4cSJordan Brown classes));
2471fcced4cSJordan Brown }
2481fcced4cSJordan Brown
2491fcced4cSJordan Brown directory_error_t
directory_canon_from_name(directory_t d,char * name,char ** canon,uint64_t * classes)2501fcced4cSJordan Brown directory_canon_from_name(
2511fcced4cSJordan Brown directory_t d,
2521fcced4cSJordan Brown char *name,
2531fcced4cSJordan Brown char **canon,
2541fcced4cSJordan Brown uint64_t *classes)
2551fcced4cSJordan Brown {
2561fcced4cSJordan Brown return (directory_canon_common(d, name, DIRECTORY_ID_NAME, canon,
2571fcced4cSJordan Brown classes));
2581fcced4cSJordan Brown }
2591fcced4cSJordan Brown
2601fcced4cSJordan Brown directory_error_t
directory_canon_from_user_name(directory_t d,char * name,char ** canon)2611fcced4cSJordan Brown directory_canon_from_user_name(directory_t d, char *name, char **canon)
2621fcced4cSJordan Brown {
2631fcced4cSJordan Brown return (
2641fcced4cSJordan Brown directory_canon_common(d, name, DIRECTORY_ID_USER, canon, NULL));
2651fcced4cSJordan Brown }
2661fcced4cSJordan Brown
2671fcced4cSJordan Brown directory_error_t
directory_canon_from_group_name(directory_t d,char * name,char ** canon)2681fcced4cSJordan Brown directory_canon_from_group_name(directory_t d, char *name, char **canon)
2691fcced4cSJordan Brown {
2701fcced4cSJordan Brown return (
2711fcced4cSJordan Brown directory_canon_common(d, name, DIRECTORY_ID_GROUP, canon, NULL));
2721fcced4cSJordan Brown }
2731fcced4cSJordan Brown
2741fcced4cSJordan Brown boolean_t
is_in_list(char ** list,char * val)2751fcced4cSJordan Brown is_in_list(char **list, char *val)
2761fcced4cSJordan Brown {
2771fcced4cSJordan Brown for (; *list != NULL; list++) {
278*cb174861Sjoyce mcintosh if (uu_strcaseeq(*list, val))
2791fcced4cSJordan Brown return (B_TRUE);
2801fcced4cSJordan Brown }
2811fcced4cSJordan Brown return (B_FALSE);
2821fcced4cSJordan Brown }
2831fcced4cSJordan Brown
2841fcced4cSJordan Brown uint64_t
class_bitmap(char ** objectClass)2851fcced4cSJordan Brown class_bitmap(char **objectClass)
2861fcced4cSJordan Brown {
2871fcced4cSJordan Brown uint64_t ret = 0;
2881fcced4cSJordan Brown
2891fcced4cSJordan Brown for (; *objectClass != NULL; objectClass++) {
290*cb174861Sjoyce mcintosh if (uu_strcaseeq(*objectClass, "user") ||
291*cb174861Sjoyce mcintosh uu_strcaseeq(*objectClass, "posixAccount"))
2921fcced4cSJordan Brown ret |= DIRECTORY_CLASS_USER;
2931fcced4cSJordan Brown
294*cb174861Sjoyce mcintosh if (uu_strcaseeq(*objectClass, "group") ||
295*cb174861Sjoyce mcintosh uu_strcaseeq(*objectClass, "posixGroup"))
2961fcced4cSJordan Brown ret |= DIRECTORY_CLASS_GROUP;
2971fcced4cSJordan Brown }
2981fcced4cSJordan Brown
2991fcced4cSJordan Brown return (ret);
3001fcced4cSJordan Brown }
301