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 * Retrieve directory information for built-in users and groups
32 #include <sys/idmap.h>
33 #include <sys/param.h>
40 #include "directory.h"
41 #include "directory_private.h"
42 #include <rpcsvc/idmap_prot.h>
43 #include "directory_server_impl.h"
46 static directory_error_t
sid_dav(directory_values_rpc
*lvals
,
47 const wksids_table_t
*wksid
);
48 static directory_error_t
directory_provider_builtin_populate(
49 directory_entry_rpc
*pent
, const wksids_table_t
*wksid
,
50 idmap_utf8str_list
*attrs
);
53 * Retrieve information by name.
54 * Called indirectly through the directory_provider_static structure.
58 directory_provider_builtin_get(
59 directory_entry_rpc
*del
,
60 idmap_utf8str_list
*ids
,
62 idmap_utf8str_list
*attrs
)
66 for (i
= 0; i
< ids
->idmap_utf8str_list_len
; i
++) {
67 const wksids_table_t
*wksid
;
72 * Extract the type for this particular ID.
73 * Advance to the next type, if it's there, else keep
74 * using this type until we run out of IDs.
77 if (*(types
+1) != '\0')
81 * If this entry has already been handled, one way or another,
84 if (del
[i
].status
!= DIRECTORY_NOT_FOUND
)
87 char *id
= ids
->idmap_utf8str_list_val
[i
];
90 * End-to-end error injection point.
91 * NEEDSWORK: should probably eliminate this for production
93 if (uu_streq(id
, " DEBUG BUILTIN ERROR ")) {
94 directory_entry_set_error(&del
[i
],
95 directory_error("Directory_provider_builtin.debug",
96 "Directory_provider_builtin: artificial error",
101 if (type
== DIRECTORY_ID_SID
[0])
102 wksid
= find_wk_by_sid(id
);
105 if (type
== DIRECTORY_ID_NAME
[0])
106 idmap_id_type
= IDMAP_POSIXID
;
107 else if (type
== DIRECTORY_ID_USER
[0])
108 idmap_id_type
= IDMAP_UID
;
109 else if (type
== DIRECTORY_ID_GROUP
[0])
110 idmap_id_type
= IDMAP_GID
;
112 directory_entry_set_error(&del
[i
],
113 directory_error("invalid_arg.id_type",
114 "Invalid ID type \"%1\"",
119 int id_len
= strlen(id
);
120 char name
[id_len
+ 1];
121 char domain
[id_len
+ 1];
123 split_name(name
, domain
, id
);
125 wksid
= find_wksid_by_name(name
, domain
, idmap_id_type
);
131 de
= directory_provider_builtin_populate(&del
[i
], wksid
, attrs
);
133 directory_entry_set_error(&del
[i
], de
);
142 * Given a well-known name entry and a list of attributes that were
143 * requested, populate the structure to return to the caller.
147 directory_provider_builtin_populate(
148 directory_entry_rpc
*pent
,
149 const wksids_table_t
*wksid
,
150 idmap_utf8str_list
*attrs
)
153 directory_values_rpc
*llvals
;
156 nattrs
= attrs
->idmap_utf8str_list_len
;
158 llvals
= calloc(nattrs
, sizeof (directory_values_rpc
));
162 pent
->status
= DIRECTORY_FOUND
;
163 pent
->directory_entry_rpc_u
.attrs
.attrs_val
= llvals
;
164 pent
->directory_entry_rpc_u
.attrs
.attrs_len
= nattrs
;
166 for (j
= 0; j
< nattrs
; j
++) {
167 directory_values_rpc
*val
;
169 directory_error_t de
;
172 * We're going to refer to these a lot, so make a shorthand
175 a
= attrs
->idmap_utf8str_list_val
[j
];
179 * Start by assuming no errors and that we don't have
185 if (uu_strcaseeq(a
, "uid")) {
186 de
= str_list_dav(val
, &wksid
->winname
, 1);
187 } else if (uu_strcaseeq(a
, "uidNumber")) {
188 if (wksid
->pid
!= IDMAP_SENTINEL_PID
&&
190 de
= uint_list_dav(val
, &wksid
->pid
, 1);
192 } else if (uu_strcaseeq(a
, "gidNumber")) {
193 if (wksid
->pid
!= IDMAP_SENTINEL_PID
&&
195 de
= uint_list_dav(val
, &wksid
->pid
, 1);
197 } else if (uu_strcaseeq(a
, "displayName") ||
198 uu_strcaseeq(a
, "cn")) {
199 de
= str_list_dav(val
, &wksid
->winname
, 1);
200 } else if (uu_strcaseeq(a
, "distinguishedName")) {
202 if (wksid
->domain
== NULL
) {
205 container
= "Builtin";
211 wksid
->winname
, container
, _idmapdstate
.hostname
);
213 const char *cdn
= dn
;
214 de
= str_list_dav(val
, &cdn
, 1);
216 } else if (uu_strcaseeq(a
, "objectClass")) {
217 if (wksid
->is_wuser
) {
218 static const char *objectClasses
[] = {
221 "organizationalPerson",
224 de
= str_list_dav(val
, objectClasses
,
225 UU_NELEM(objectClasses
));
227 static const char *objectClasses
[] = {
231 de
= str_list_dav(val
, objectClasses
,
232 UU_NELEM(objectClasses
));
234 } else if (uu_strcaseeq(a
, "objectSid")) {
235 de
= sid_dav(val
, wksid
);
236 } else if (uu_strcaseeq(a
, "x-sun-canonicalName")) {
239 if (wksid
->domain
== NULL
) {
241 (void) asprintf(&canon
, "%s@%s",
242 wksid
->winname
, _idmapdstate
.hostname
);
244 } else if (uu_streq(wksid
->domain
, "")) {
245 canon
= strdup(wksid
->winname
);
247 (void) asprintf(&canon
, "%s@%s",
248 wksid
->winname
, wksid
->domain
);
253 const char *ccanon
= canon
;
254 de
= str_list_dav(val
, &ccanon
, 1);
256 } else if (uu_strcaseeq(a
, "x-sun-provider")) {
257 const char *provider
= "Builtin";
258 de
= str_list_dav(val
, &provider
, 1);
267 return (directory_error("ENOMEM.users",
268 "No memory allocating return value for user lookup", NULL
));
272 * Given a well-known name structure, generate a binary-format SID.
273 * It's a bit perverse that we must take a text-format SID and turn it into
274 * a binary-format SID, only to have the caller probably turn it back into
275 * text format, but SIDs are carried across LDAP in binary format.
279 sid_dav(directory_values_rpc
*lvals
, const wksids_table_t
*wksid
)
283 directory_error_t de
;
285 if (wksid
->sidprefix
== NULL
) {
287 (void) asprintf(&text_sid
, "%s-%d",
288 _idmapdstate
.cfg
->pgcfg
.machine_sid
,
292 (void) asprintf(&text_sid
, "%s-%d",
293 wksid
->sidprefix
, wksid
->rid
);
296 if (text_sid
== NULL
)
299 sid
= sid_fromstr(text_sid
);
307 de
= bin_list_dav(lvals
, sid
, 1, sid_len(sid
));
314 return (directory_error("ENOMEM.sid_dav",
315 "No memory allocating SID for user lookup", NULL
));
318 struct directory_provider_static directory_provider_builtin
= {
320 directory_provider_builtin_get
,