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