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]
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
27 * Server-side support for directory information lookup functions.
34 #include <sys/types.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.
68 directory_get_common_1_svc(
69 idmap_utf8str_list ids
,
71 idmap_utf8str_list attrs
,
72 directory_results_rpc
*result
,
77 directory_entry_rpc
*entries
;
81 nids
= ids
.idmap_utf8str_list_len
;
83 entries
= (directory_entry_rpc
*)
84 calloc(nids
, sizeof (directory_entry_rpc
));
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
]) >
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
,
110 de
= directory_error("ENOMEM.get_common",
111 "Insufficient memory retrieving directory data", NULL
);
114 xdr_free(xdr_directory_results_rpc
, (char *)result
);
115 result
->failed
= TRUE
;
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.
126 split_name(char *name
, char *domain
, char *id
)
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);
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.
156 str_list_dav(directory_values_rpc
*lvals
, const char * const *str_list
, int n
)
158 directory_value_rpc
*dav
;
162 for (n
= 0; str_list
[n
] != NULL
; n
++)
166 dav
= calloc(n
, sizeof (directory_value_rpc
));
170 lvals
->directory_values_rpc_u
.values
.values_val
= dav
;
171 lvals
->directory_values_rpc_u
.values
.values_len
= n
;
174 for (i
= 0; i
< n
; i
++) {
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
)
181 dav
[i
].directory_value_rpc_len
= len
;
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
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.
206 uint_list_dav(directory_values_rpc
*lvals
, const unsigned int *array
, int n
)
208 directory_value_rpc
*dav
;
211 dav
= calloc(n
, sizeof (directory_value_rpc
));
215 lvals
->directory_values_rpc_u
.values
.values_val
= dav
;
216 lvals
->directory_values_rpc_u
.values
.values_len
= n
;
219 for (i
= 0; i
< n
; i
++) {
220 char buf
[100]; /* larger than any integer */
223 (void) snprintf(buf
, sizeof (buf
), "%u", array
[i
]);
226 dav
[i
].directory_value_rpc_val
= uu_memdup(buf
, len
);
227 if (dav
[i
].directory_value_rpc_val
== NULL
)
229 dav
[i
].directory_value_rpc_len
= len
;
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.
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
;
256 dav
= calloc(n
, sizeof (directory_value_rpc
));
260 lvals
->directory_values_rpc_u
.values
.values_val
= dav
;
261 lvals
->directory_values_rpc_u
.values
.values_len
= n
;
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
)
268 dav
[i
].directory_value_rpc_len
= sz
;
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
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
);