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