xref: /onnv-gate/usr/src/lib/libidmap/common/directory_helper.c (revision 12890:16985853e3aa)
110122SJordan.Brown@Sun.COM /*
210122SJordan.Brown@Sun.COM  * CDDL HEADER START
310122SJordan.Brown@Sun.COM  *
410122SJordan.Brown@Sun.COM  * The contents of this file are subject to the terms of the
510122SJordan.Brown@Sun.COM  * Common Development and Distribution License (the "License").
610122SJordan.Brown@Sun.COM  * You may not use this file except in compliance with the License.
710122SJordan.Brown@Sun.COM  *
810122SJordan.Brown@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910122SJordan.Brown@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1010122SJordan.Brown@Sun.COM  * See the License for the specific language governing permissions
1110122SJordan.Brown@Sun.COM  * and limitations under the License.
1210122SJordan.Brown@Sun.COM  *
1310122SJordan.Brown@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1410122SJordan.Brown@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510122SJordan.Brown@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1610122SJordan.Brown@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1710122SJordan.Brown@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1810122SJordan.Brown@Sun.COM  *
1910122SJordan.Brown@Sun.COM  * CDDL HEADER END
2010122SJordan.Brown@Sun.COM  */
2110122SJordan.Brown@Sun.COM 
2210122SJordan.Brown@Sun.COM /*
2312065SKeyur.Desai@Sun.COM  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2410122SJordan.Brown@Sun.COM  */
2510122SJordan.Brown@Sun.COM 
2610122SJordan.Brown@Sun.COM /*
2710122SJordan.Brown@Sun.COM  * Some helper routines for directory lookup.  These offer functions that
2810122SJordan.Brown@Sun.COM  * you could implement yourself on top of the generic routines, but since
2910122SJordan.Brown@Sun.COM  * they're a common request we implement them here.  (Well, OK, we cheat a bit
3010122SJordan.Brown@Sun.COM  * and call an internal routine to do the dirty work to reduce code
3110122SJordan.Brown@Sun.COM  * duplication, but you could still implement them using the generic routines.)
3210122SJordan.Brown@Sun.COM  */
3310122SJordan.Brown@Sun.COM 
3410122SJordan.Brown@Sun.COM #include <stdio.h>
3510122SJordan.Brown@Sun.COM #include <string.h>
36*12890SJoyce.McIntosh@Sun.COM #include <libuutil.h>
3710122SJordan.Brown@Sun.COM #include <rpcsvc/idmap_prot.h>
3810122SJordan.Brown@Sun.COM #include "directory.h"
3910122SJordan.Brown@Sun.COM #include "directory_private.h"
4010122SJordan.Brown@Sun.COM #include "directory_library_impl.h"
4110122SJordan.Brown@Sun.COM #include "sidutil.h"
4210122SJordan.Brown@Sun.COM 
4310122SJordan.Brown@Sun.COM /*
4410122SJordan.Brown@Sun.COM  * Given a username, return a text-form SID.
4510122SJordan.Brown@Sun.COM  *
4610122SJordan.Brown@Sun.COM  * The SID must be free()ed by the caller.
4710122SJordan.Brown@Sun.COM  *
4810122SJordan.Brown@Sun.COM  * d, if non-NULL, specifies an existing directory-search context.
4910122SJordan.Brown@Sun.COM  * If NULL, a temporary one will be created.
5010122SJordan.Brown@Sun.COM  */
5110122SJordan.Brown@Sun.COM directory_error_t
directory_sid_from_name_common(directory_t d,char * name,char * type,char ** sid,uint64_t * classes)5210122SJordan.Brown@Sun.COM directory_sid_from_name_common(
5310122SJordan.Brown@Sun.COM     directory_t d,
5410122SJordan.Brown@Sun.COM     char *name,
5510122SJordan.Brown@Sun.COM     char *type,
5610122SJordan.Brown@Sun.COM     char **sid,
5710122SJordan.Brown@Sun.COM     uint64_t *classes)
5810122SJordan.Brown@Sun.COM {
5910122SJordan.Brown@Sun.COM 	directory_t d1 = NULL;
6010122SJordan.Brown@Sun.COM 	static char *attrs[] = {
6110122SJordan.Brown@Sun.COM 		"objectSid",
6210122SJordan.Brown@Sun.COM 		"objectClass",
6310122SJordan.Brown@Sun.COM 		NULL,
6410122SJordan.Brown@Sun.COM 	};
6510122SJordan.Brown@Sun.COM 	directory_entry_t *ret_list = NULL;
6610122SJordan.Brown@Sun.COM 	directory_error_t de;
6710122SJordan.Brown@Sun.COM 	struct ret_sid {
6810122SJordan.Brown@Sun.COM 		sid_t **objectSid;
6910122SJordan.Brown@Sun.COM 		char **objectClass;
7010122SJordan.Brown@Sun.COM 	} *ret_sid;
7110122SJordan.Brown@Sun.COM 
7210122SJordan.Brown@Sun.COM 	/* Prep for error cases. */
7310122SJordan.Brown@Sun.COM 	*sid = NULL;
7410122SJordan.Brown@Sun.COM 	if (classes != NULL)
7510122SJordan.Brown@Sun.COM 		*classes = 0;
7610122SJordan.Brown@Sun.COM 
7710122SJordan.Brown@Sun.COM 	if (d == NULL) {
7810122SJordan.Brown@Sun.COM 		de = directory_open(&d1);
7910122SJordan.Brown@Sun.COM 		if (de != NULL)
8010122SJordan.Brown@Sun.COM 			goto out;
8110122SJordan.Brown@Sun.COM 	} else {
8210122SJordan.Brown@Sun.COM 		d1 = d;
8310122SJordan.Brown@Sun.COM 	}
8410122SJordan.Brown@Sun.COM 
8510122SJordan.Brown@Sun.COM 	de = directory_get_v(d1, &ret_list, &name, 1, type, attrs);
8610122SJordan.Brown@Sun.COM 	if (de != NULL)
8710122SJordan.Brown@Sun.COM 		goto out;
8810122SJordan.Brown@Sun.COM 	if (ret_list[0].err != NULL) {
8910122SJordan.Brown@Sun.COM 		de = ret_list[0].err;
9010122SJordan.Brown@Sun.COM 		ret_list[0].err = NULL;
9110122SJordan.Brown@Sun.COM 		goto out;
9210122SJordan.Brown@Sun.COM 	}
9310122SJordan.Brown@Sun.COM 
9410122SJordan.Brown@Sun.COM 	ret_sid = (struct ret_sid *)ret_list[0].attrs;
9510122SJordan.Brown@Sun.COM 	if (ret_sid == NULL)
9610122SJordan.Brown@Sun.COM 		goto out;
9710122SJordan.Brown@Sun.COM 
9810122SJordan.Brown@Sun.COM 	if (ret_sid->objectSid != NULL &&
9910122SJordan.Brown@Sun.COM 	    ret_sid->objectSid[0] != NULL) {
10010122SJordan.Brown@Sun.COM 		char text_sid[SID_STRSZ+1];
10110122SJordan.Brown@Sun.COM 		sid_from_le(ret_sid->objectSid[0]);
10210122SJordan.Brown@Sun.COM 		sid_tostr(ret_sid->objectSid[0], text_sid);
10310122SJordan.Brown@Sun.COM 		*sid = strdup(text_sid);
10410122SJordan.Brown@Sun.COM 		if (*sid == NULL)
10510122SJordan.Brown@Sun.COM 			goto nomem;
10610122SJordan.Brown@Sun.COM 	}
10710122SJordan.Brown@Sun.COM 
10810122SJordan.Brown@Sun.COM 	if (ret_sid->objectClass != NULL &&
10910122SJordan.Brown@Sun.COM 	    classes != NULL)
11010122SJordan.Brown@Sun.COM 		*classes = class_bitmap(ret_sid->objectClass);
11110122SJordan.Brown@Sun.COM 
11210122SJordan.Brown@Sun.COM 	goto out;
11310122SJordan.Brown@Sun.COM 
11410122SJordan.Brown@Sun.COM nomem:
11510122SJordan.Brown@Sun.COM 	de = directory_error("ENOMEM.directory_sid_from_name_common",
11610122SJordan.Brown@Sun.COM 	    "Insufficient memory retrieving data about SID", NULL);
11710122SJordan.Brown@Sun.COM 
11810122SJordan.Brown@Sun.COM out:
11910122SJordan.Brown@Sun.COM 	directory_free(ret_list);
12010122SJordan.Brown@Sun.COM 	if (d == NULL)
12110122SJordan.Brown@Sun.COM 		directory_close(d1);
12210122SJordan.Brown@Sun.COM 	return (de);
12310122SJordan.Brown@Sun.COM }
12410122SJordan.Brown@Sun.COM 
12510122SJordan.Brown@Sun.COM directory_error_t
directory_sid_from_name(directory_t d,char * name,char ** sid,uint64_t * classes)12610122SJordan.Brown@Sun.COM directory_sid_from_name(
12710122SJordan.Brown@Sun.COM     directory_t d,
12810122SJordan.Brown@Sun.COM     char *name,
12910122SJordan.Brown@Sun.COM     char **sid,
13010122SJordan.Brown@Sun.COM     uint64_t *classes)
13110122SJordan.Brown@Sun.COM {
13210122SJordan.Brown@Sun.COM 	return (directory_sid_from_name_common(d, name, DIRECTORY_ID_NAME, sid,
13310122SJordan.Brown@Sun.COM 	    classes));
13410122SJordan.Brown@Sun.COM }
13510122SJordan.Brown@Sun.COM 
13610122SJordan.Brown@Sun.COM directory_error_t
directory_sid_from_user_name(directory_t d,char * name,char ** sid)13710122SJordan.Brown@Sun.COM directory_sid_from_user_name(directory_t d, char *name, char **sid)
13810122SJordan.Brown@Sun.COM {
13910122SJordan.Brown@Sun.COM 	return (directory_sid_from_name_common(d, name, DIRECTORY_ID_USER, sid,
14010122SJordan.Brown@Sun.COM 	    NULL));
14110122SJordan.Brown@Sun.COM }
14210122SJordan.Brown@Sun.COM 
14310122SJordan.Brown@Sun.COM directory_error_t
directory_sid_from_group_name(directory_t d,char * name,char ** sid)14410122SJordan.Brown@Sun.COM directory_sid_from_group_name(directory_t d, char *name, char **sid)
14510122SJordan.Brown@Sun.COM {
14610122SJordan.Brown@Sun.COM 	return (directory_sid_from_name_common(d, name, DIRECTORY_ID_GROUP, sid,
14710122SJordan.Brown@Sun.COM 	    NULL));
14810122SJordan.Brown@Sun.COM }
14910122SJordan.Brown@Sun.COM 
15010122SJordan.Brown@Sun.COM /*
15110122SJordan.Brown@Sun.COM  * Given a name or text-format SID, return a user@domain.
15210122SJordan.Brown@Sun.COM  *
15310122SJordan.Brown@Sun.COM  * The user@domain returned must be free()ed by the caller.
15410122SJordan.Brown@Sun.COM  *
15510122SJordan.Brown@Sun.COM  * Returns NULL and sets *name to NULL if no error occurred but the specified
15610122SJordan.Brown@Sun.COM  * entity does not exist.
15710122SJordan.Brown@Sun.COM  *
15810122SJordan.Brown@Sun.COM  * d, if non-NULL, specifies an existing directory-search context.
15910122SJordan.Brown@Sun.COM  * If NULL, a temporary one will be created.
16010122SJordan.Brown@Sun.COM  */
16110122SJordan.Brown@Sun.COM static
16210122SJordan.Brown@Sun.COM directory_error_t
directory_canon_common(directory_t d,char * id,char * id_type,char ** canon,uint64_t * classes)16310122SJordan.Brown@Sun.COM directory_canon_common(
16410122SJordan.Brown@Sun.COM     directory_t d,
16510122SJordan.Brown@Sun.COM     char *id,
16610122SJordan.Brown@Sun.COM     char *id_type,
16710122SJordan.Brown@Sun.COM     char **canon,
16810122SJordan.Brown@Sun.COM     uint64_t *classes)
16910122SJordan.Brown@Sun.COM {
17010122SJordan.Brown@Sun.COM 	directory_t d1 = NULL;
17110122SJordan.Brown@Sun.COM 	directory_entry_t *ret_list = NULL;
17210122SJordan.Brown@Sun.COM 	directory_error_t de;
17310122SJordan.Brown@Sun.COM 	/*
17410122SJordan.Brown@Sun.COM 	 * Attributes required to generate a canonical name, in named-list and
17510122SJordan.Brown@Sun.COM 	 * structure form.
17610122SJordan.Brown@Sun.COM 	 */
17710122SJordan.Brown@Sun.COM 	static char *attrs[] = {
17810122SJordan.Brown@Sun.COM 		"x-sun-canonicalName",
17910122SJordan.Brown@Sun.COM 		"objectClass",
18010122SJordan.Brown@Sun.COM 		NULL,
18110122SJordan.Brown@Sun.COM 	};
18210122SJordan.Brown@Sun.COM 
18310122SJordan.Brown@Sun.COM 	struct canon_name_ret {
18410122SJordan.Brown@Sun.COM 		char **x_sun_canonicalName;
18510122SJordan.Brown@Sun.COM 		char **objectClass;
18610122SJordan.Brown@Sun.COM 	} *ret_name;
18710122SJordan.Brown@Sun.COM 
18810122SJordan.Brown@Sun.COM 	/* Prep for error cases. */
18910122SJordan.Brown@Sun.COM 	*canon = NULL;
19010122SJordan.Brown@Sun.COM 	if (classes != NULL)
19110122SJordan.Brown@Sun.COM 		*classes = 0;
19210122SJordan.Brown@Sun.COM 
19310122SJordan.Brown@Sun.COM 	if (d == NULL) {
19410122SJordan.Brown@Sun.COM 		de = directory_open(&d1);
19510122SJordan.Brown@Sun.COM 		if (de != NULL)
19610122SJordan.Brown@Sun.COM 			goto out;
19710122SJordan.Brown@Sun.COM 	} else {
19810122SJordan.Brown@Sun.COM 		d1 = d;
19910122SJordan.Brown@Sun.COM 	}
20010122SJordan.Brown@Sun.COM 
20110122SJordan.Brown@Sun.COM 	de = directory_get_v(d1, &ret_list, &id, 1, id_type, attrs);
20210122SJordan.Brown@Sun.COM 	if (de != NULL)
20310122SJordan.Brown@Sun.COM 		goto out;
20410122SJordan.Brown@Sun.COM 	if (ret_list[0].err != NULL) {
20510122SJordan.Brown@Sun.COM 		de = ret_list[0].err;
20610122SJordan.Brown@Sun.COM 		ret_list[0].err = NULL;
20710122SJordan.Brown@Sun.COM 		goto out;
20810122SJordan.Brown@Sun.COM 	}
20910122SJordan.Brown@Sun.COM 
21010122SJordan.Brown@Sun.COM 	ret_name = (struct canon_name_ret *)ret_list[0].attrs;
21110122SJordan.Brown@Sun.COM 	if (ret_name == NULL)
21210122SJordan.Brown@Sun.COM 		goto out;
21310122SJordan.Brown@Sun.COM 
21410122SJordan.Brown@Sun.COM 	if (ret_name->x_sun_canonicalName != NULL &&
21510122SJordan.Brown@Sun.COM 	    ret_name->x_sun_canonicalName[0] != NULL) {
21610122SJordan.Brown@Sun.COM 		*canon = strdup(ret_name->x_sun_canonicalName[0]);
21710122SJordan.Brown@Sun.COM 		if (*canon == NULL)
21810122SJordan.Brown@Sun.COM 			goto nomem;
21910122SJordan.Brown@Sun.COM 	}
22010122SJordan.Brown@Sun.COM 
22110122SJordan.Brown@Sun.COM 	if (ret_name->objectClass != NULL &&
22210122SJordan.Brown@Sun.COM 	    classes != NULL)
22310122SJordan.Brown@Sun.COM 		*classes = class_bitmap(ret_name->objectClass);
22410122SJordan.Brown@Sun.COM 
22510122SJordan.Brown@Sun.COM 	goto out;
22610122SJordan.Brown@Sun.COM 
22710122SJordan.Brown@Sun.COM nomem:
22810122SJordan.Brown@Sun.COM 	de = directory_error("ENOMEM.directory_canon_common",
22910122SJordan.Brown@Sun.COM 	    "Insufficient memory retrieving data about name", NULL);
23010122SJordan.Brown@Sun.COM 
23110122SJordan.Brown@Sun.COM out:
23210122SJordan.Brown@Sun.COM 	directory_free(ret_list);
23310122SJordan.Brown@Sun.COM 	if (d == NULL)
23410122SJordan.Brown@Sun.COM 		directory_close(d1);
23510122SJordan.Brown@Sun.COM 	return (de);
23610122SJordan.Brown@Sun.COM }
23710122SJordan.Brown@Sun.COM 
23810122SJordan.Brown@Sun.COM directory_error_t
directory_name_from_sid(directory_t d,char * sid,char ** canon,uint64_t * classes)23910122SJordan.Brown@Sun.COM directory_name_from_sid(
24010122SJordan.Brown@Sun.COM     directory_t d,
24110122SJordan.Brown@Sun.COM     char *sid,
24210122SJordan.Brown@Sun.COM     char **canon,
24310122SJordan.Brown@Sun.COM     uint64_t *classes)
24410122SJordan.Brown@Sun.COM {
24510122SJordan.Brown@Sun.COM 	return (directory_canon_common(d, sid, DIRECTORY_ID_SID, canon,
24610122SJordan.Brown@Sun.COM 	    classes));
24710122SJordan.Brown@Sun.COM }
24810122SJordan.Brown@Sun.COM 
24910122SJordan.Brown@Sun.COM directory_error_t
directory_canon_from_name(directory_t d,char * name,char ** canon,uint64_t * classes)25010122SJordan.Brown@Sun.COM directory_canon_from_name(
25110122SJordan.Brown@Sun.COM     directory_t d,
25210122SJordan.Brown@Sun.COM     char *name,
25310122SJordan.Brown@Sun.COM     char **canon,
25410122SJordan.Brown@Sun.COM     uint64_t *classes)
25510122SJordan.Brown@Sun.COM {
25610122SJordan.Brown@Sun.COM 	return (directory_canon_common(d, name, DIRECTORY_ID_NAME, canon,
25710122SJordan.Brown@Sun.COM 	    classes));
25810122SJordan.Brown@Sun.COM }
25910122SJordan.Brown@Sun.COM 
26010122SJordan.Brown@Sun.COM directory_error_t
directory_canon_from_user_name(directory_t d,char * name,char ** canon)26110122SJordan.Brown@Sun.COM directory_canon_from_user_name(directory_t d, char *name, char **canon)
26210122SJordan.Brown@Sun.COM {
26310122SJordan.Brown@Sun.COM 	return (
26410122SJordan.Brown@Sun.COM 	    directory_canon_common(d, name, DIRECTORY_ID_USER, canon, NULL));
26510122SJordan.Brown@Sun.COM }
26610122SJordan.Brown@Sun.COM 
26710122SJordan.Brown@Sun.COM directory_error_t
directory_canon_from_group_name(directory_t d,char * name,char ** canon)26810122SJordan.Brown@Sun.COM directory_canon_from_group_name(directory_t d, char *name, char **canon)
26910122SJordan.Brown@Sun.COM {
27010122SJordan.Brown@Sun.COM 	return (
27110122SJordan.Brown@Sun.COM 	    directory_canon_common(d, name, DIRECTORY_ID_GROUP, canon, NULL));
27210122SJordan.Brown@Sun.COM }
27310122SJordan.Brown@Sun.COM 
27410122SJordan.Brown@Sun.COM boolean_t
is_in_list(char ** list,char * val)27510122SJordan.Brown@Sun.COM is_in_list(char **list, char *val)
27610122SJordan.Brown@Sun.COM {
27710122SJordan.Brown@Sun.COM 	for (; *list != NULL; list++) {
278*12890SJoyce.McIntosh@Sun.COM 		if (uu_strcaseeq(*list, val))
27910122SJordan.Brown@Sun.COM 			return (B_TRUE);
28010122SJordan.Brown@Sun.COM 	}
28110122SJordan.Brown@Sun.COM 	return (B_FALSE);
28210122SJordan.Brown@Sun.COM }
28310122SJordan.Brown@Sun.COM 
28410122SJordan.Brown@Sun.COM uint64_t
class_bitmap(char ** objectClass)28510122SJordan.Brown@Sun.COM class_bitmap(char **objectClass)
28610122SJordan.Brown@Sun.COM {
28710122SJordan.Brown@Sun.COM 	uint64_t ret = 0;
28810122SJordan.Brown@Sun.COM 
28910122SJordan.Brown@Sun.COM 	for (; *objectClass != NULL; objectClass++) {
290*12890SJoyce.McIntosh@Sun.COM 		if (uu_strcaseeq(*objectClass, "user") ||
291*12890SJoyce.McIntosh@Sun.COM 		    uu_strcaseeq(*objectClass, "posixAccount"))
29210122SJordan.Brown@Sun.COM 			ret |= DIRECTORY_CLASS_USER;
29310122SJordan.Brown@Sun.COM 
294*12890SJoyce.McIntosh@Sun.COM 		if (uu_strcaseeq(*objectClass, "group") ||
295*12890SJoyce.McIntosh@Sun.COM 		    uu_strcaseeq(*objectClass, "posixGroup"))
29610122SJordan.Brown@Sun.COM 			ret |= DIRECTORY_CLASS_GROUP;
29710122SJordan.Brown@Sun.COM 	}
29810122SJordan.Brown@Sun.COM 
29910122SJordan.Brown@Sun.COM 	return (ret);
30010122SJordan.Brown@Sun.COM }
301