dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / idmap / idmapd / directory_server.c
blob3fcfa2b722be7e8fe5c1528ff153a730a03610c0
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
27 * Server-side support for directory information lookup functions.
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stdarg.h>
33 #include <malloc.h>
34 #include <sys/types.h>
35 #include <netdb.h>
36 #include <pthread.h>
37 #include <unistd.h>
38 #include <string.h>
39 #include <libuutil.h>
40 #include <note.h>
41 #include "idmapd.h"
42 #include "directory.h"
43 #include "directory_private.h"
44 #include <rpcsvc/idmap_prot.h>
45 #include "directory_library_impl.h"
46 #include "directory_server_impl.h"
47 #include "sized_array.h"
50 * Here's a list of all of the modules that provide directory
51 * information. In the fullness of time this should probably be
52 * a plugin-able switch mechanism.
53 * Note that the list is in precedence order.
55 extern struct directory_provider_static directory_provider_builtin;
56 extern struct directory_provider_static directory_provider_nsswitch;
57 extern struct directory_provider_static directory_provider_ad;
58 struct directory_provider_static *providers[] = {
59 &directory_provider_builtin,
60 &directory_provider_nsswitch,
61 &directory_provider_ad,
65 * This is the entry point for all directory lookup service requests.
67 bool_t
68 directory_get_common_1_svc(
69 idmap_utf8str_list ids,
70 idmap_utf8str types,
71 idmap_utf8str_list attrs,
72 directory_results_rpc *result,
73 struct svc_req *req)
75 NOTE(ARGUNUSED(req))
76 int nids;
77 directory_entry_rpc *entries;
78 directory_error_t de;
79 int i;
81 nids = ids.idmap_utf8str_list_len;
83 entries = (directory_entry_rpc *)
84 calloc(nids, sizeof (directory_entry_rpc));
85 if (entries == NULL)
86 goto nomem;
87 result->directory_results_rpc_u.entries.entries_val = entries;
88 result->directory_results_rpc_u.entries.entries_len = nids;
89 result->failed = FALSE;
91 for (i = 0; i < nids; i++) {
92 if (strlen(ids.idmap_utf8str_list_val[i]) >
93 IDMAP_MAX_NAME_LEN) {
94 directory_entry_set_error(&entries[i],
95 directory_error("invalid_arg.id.too_long",
96 "Identifier too long", NULL));
100 for (i = 0; i < UU_NELEM(providers); i++) {
101 de = providers[i]->get(entries, &ids, types,
102 &attrs);
103 if (de != NULL)
104 goto err;
107 return (TRUE);
109 nomem:
110 de = directory_error("ENOMEM.get_common",
111 "Insufficient memory retrieving directory data", NULL);
113 err:
114 xdr_free(xdr_directory_results_rpc, (char *)result);
115 result->failed = TRUE;
116 return (
117 directory_error_to_rpc(&result->directory_results_rpc_u.err, de));
121 * Split name into {domain, name}.
122 * Suggest allocating name and domain on the stack, same size as id,
123 * using variable length arrays.
125 void
126 split_name(char *name, char *domain, char *id)
128 char *p;
130 if ((p = strchr(id, '@')) != NULL) {
131 (void) strlcpy(name, id, p - id + 1);
132 (void) strcpy(domain, p + 1);
133 } else if ((p = strchr(id, '\\')) != NULL) {
134 (void) strcpy(name, p + 1);
135 (void) strlcpy(domain, id, p - id + 1);
136 } else {
137 (void) strcpy(name, id);
138 (void) strcpy(domain, "");
143 * Given a list of strings, return a set of directory attribute values.
145 * Mark that the attribute was found.
147 * Note that the terminating \0 is *not* included in the result, because
148 * that's the way that strings come from LDAP.
149 * (Note also that the client side stuff adds in a terminating \0.)
151 * Note that on error the array may have been partially populated and will
152 * need to be cleaned up by the caller. This is normally not a problem
153 * because the caller will need to clean up several such arrays.
155 directory_error_t
156 str_list_dav(directory_values_rpc *lvals, const char * const *str_list, int n)
158 directory_value_rpc *dav;
159 int i;
161 if (n == 0) {
162 for (n = 0; str_list[n] != NULL; n++)
163 /* LOOP */;
166 dav = calloc(n, sizeof (directory_value_rpc));
167 if (dav == NULL)
168 goto nomem;
170 lvals->directory_values_rpc_u.values.values_val = dav;
171 lvals->directory_values_rpc_u.values.values_len = n;
172 lvals->found = TRUE;
174 for (i = 0; i < n; i++) {
175 int len;
177 len = strlen(str_list[i]);
178 dav[i].directory_value_rpc_val = uu_memdup(str_list[i], len);
179 if (dav[i].directory_value_rpc_val == NULL)
180 goto nomem;
181 dav[i].directory_value_rpc_len = len;
184 return (NULL);
186 nomem:
187 return (directory_error("ENOMEM.str_list_dav",
188 "Insufficient memory copying values"));
192 * Given a list of unsigned integers, return a set of string directory
193 * attribute values.
195 * Mark that the attribute was found.
197 * Note that the terminating \0 is *not* included in the result, because
198 * that's the way that strings come from LDAP.
199 * (Note also that the client side stuff adds in a terminating \0.)
201 * Note that on error the array may have been partially populated and will
202 * need to be cleaned up by the caller. This is normally not a problem
203 * because the caller will need to clean up several such arrays.
205 directory_error_t
206 uint_list_dav(directory_values_rpc *lvals, const unsigned int *array, int n)
208 directory_value_rpc *dav;
209 int i;
211 dav = calloc(n, sizeof (directory_value_rpc));
212 if (dav == NULL)
213 goto nomem;
215 lvals->directory_values_rpc_u.values.values_val = dav;
216 lvals->directory_values_rpc_u.values.values_len = n;
217 lvals->found = TRUE;
219 for (i = 0; i < n; i++) {
220 char buf[100]; /* larger than any integer */
221 int len;
223 (void) snprintf(buf, sizeof (buf), "%u", array[i]);
225 len = strlen(buf);
226 dav[i].directory_value_rpc_val = uu_memdup(buf, len);
227 if (dav[i].directory_value_rpc_val == NULL)
228 goto nomem;
229 dav[i].directory_value_rpc_len = len;
232 return (NULL);
234 nomem:
235 return (directory_error("ENOMEM.uint_list_dav",
236 "Insufficient memory copying values"));
240 * Given a list of fixed-length binary chunks, return a set of binary
241 * directory attribute values.
243 * Mark that the attribute was found.
245 * Note that on error the array may have been partially populated and will
246 * need to be cleaned up by the caller. This is normally not a problem
247 * because the caller will need to clean up several such arrays.
249 directory_error_t
250 bin_list_dav(directory_values_rpc *lvals, const void *array, int n, size_t sz)
252 directory_value_rpc *dav;
253 char *inbuf = (char *)array;
254 int i;
256 dav = calloc(n, sizeof (directory_value_rpc));
257 if (dav == NULL)
258 goto nomem;
260 lvals->directory_values_rpc_u.values.values_val = dav;
261 lvals->directory_values_rpc_u.values.values_len = n;
262 lvals->found = TRUE;
264 for (i = 0; i < n; i++) {
265 dav[i].directory_value_rpc_val = uu_memdup(inbuf, sz);
266 if (dav[i].directory_value_rpc_val == NULL)
267 goto nomem;
268 dav[i].directory_value_rpc_len = sz;
269 inbuf += sz;
272 return (NULL);
274 nomem:
275 return (directory_error("ENOMEM.bin_list_dav",
276 "Insufficient memory copying values"));
280 * Set up to return an error on a particular directory entry.
281 * Note that the caller need not (and in fact must not) free
282 * the directory_error_t; it will be freed when the directory entry
283 * list is freed.
285 void
286 directory_entry_set_error(directory_entry_rpc *ent, directory_error_t de)
288 xdr_free(xdr_directory_entry_rpc, (char *)&ent);
289 ent->status = DIRECTORY_ERROR;
290 (void) directory_error_to_rpc(&ent->directory_entry_rpc_u.err, de);