1 /* search.c - /etc/passwd backend search function */
10 #include <ac/string.h>
16 #include "back-passwd.h"
19 static void pw_start( Backend *be );
21 static Entry *pw2entry(
38 struct berval *filterstr,
49 int err = LDAP_SUCCESS;
52 struct berval parent = { 0, NULL };
54 const char *text = NULL;
56 AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass;
58 tlimit = (tlimit > be->be_timelimit || tlimit < 1) ? be->be_timelimit
60 stoptime = op->o_time + tlimit;
61 slimit = (slimit > be->be_sizelimit || slimit < 1) ? be->be_sizelimit
64 /* Handle a query for the base of this backend */
65 if ( be_issuffix( be, nbase ) ) {
66 struct berval vals[2];
68 vals[1].bv_val = NULL;
70 matched = (char *) base;
72 if( scope != LDAP_SCOPE_ONELEVEL ) {
73 AttributeDescription *desc = NULL;
75 /* Create an entry corresponding to the base DN */
76 e = (Entry *) ch_calloc(1, sizeof(Entry));
77 e->e_name.bv_val = ch_strdup( base->bv_val );
78 e->e_name.bv_len = base->bv_len;
79 e->e_nname.bv_val = ch_strdup( nbase->bv_val );
80 e->e_nname.bv_len = nbase->bv_len;
84 /* Use the first attribute of the DN
85 * as an attribute within the entry itself.
87 if( ldap_bv2rdn( base, &rdn, (char **)&text,
88 LDAP_DN_FORMAT_LDAP ) )
90 err = LDAP_INVALID_DN_SYNTAX;
94 if( slap_bv2ad( &rdn[0][0]->la_attr, &desc, &text )) {
95 err = LDAP_NO_SUCH_OBJECT;
100 vals[0] = rdn[0][0]->la_value;
101 attr_merge( e, desc, vals );
106 /* Every entry needs an objectclass. We don't really
107 * know if our hardcoded choice here agrees with the
108 * DN that was configured for this backend, but it's
109 * better than nothing.
111 * should be a configuratable item
113 vals[0].bv_val = "organizationalUnit";
114 vals[0].bv_len = sizeof("organizationalUnit")-1;
115 attr_merge( e, ad_objectClass, vals );
117 if ( test_filter( be, conn, op, e, filter ) == LDAP_COMPARE_TRUE ) {
118 send_search_entry( be, conn, op,
119 e, attrs, attrsonly, NULL );
124 if ( scope != LDAP_SCOPE_BASE ) {
125 /* check all our "children" */
127 ldap_pvt_thread_mutex_lock( &passwd_mutex );
129 for ( pw = getpwent(); pw != NULL; pw = getpwent() ) {
130 /* check for abandon */
131 if ( op->o_abandon ) {
133 ldap_pvt_thread_mutex_unlock( &passwd_mutex );
137 /* check time limit */
138 if ( slap_get_time() > stoptime ) {
139 send_ldap_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
140 NULL, NULL, NULL, NULL );
142 ldap_pvt_thread_mutex_unlock( &passwd_mutex );
146 if ( !(e = pw2entry( be, pw, &text )) ) {
149 ldap_pvt_thread_mutex_unlock( &passwd_mutex );
153 if ( test_filter( be, conn, op, e, filter ) == LDAP_COMPARE_TRUE ) {
154 /* check size limit */
155 if ( --slimit == -1 ) {
156 send_ldap_result( conn, op, LDAP_SIZELIMIT_EXCEEDED,
157 NULL, NULL, NULL, NULL );
159 ldap_pvt_thread_mutex_unlock( &passwd_mutex );
163 send_search_entry( be, conn, op,
164 e, attrs, attrsonly, NULL );
171 ldap_pvt_thread_mutex_unlock( &passwd_mutex );
175 if (! be_issuffix( be, nbase ) ) {
176 dnParent( nbase, &parent );
179 /* This backend is only one layer deep. Don't answer requests for
180 * anything deeper than that.
182 if( !be_issuffix( be, &parent ) ) {
184 for( i=0; be->be_nsuffix[i].bv_val != NULL; i++ ) {
185 if( dnIsSuffix( nbase, &be->be_nsuffix[i] ) ) {
186 matched = be->be_suffix[i].bv_val;
190 err = LDAP_NO_SUCH_OBJECT;
194 if( scope == LDAP_SCOPE_ONELEVEL ) {
198 if ( ldap_bv2rdn( base, &rdn, (char **)&text,
199 LDAP_DN_FORMAT_LDAP ))
205 ldap_pvt_thread_mutex_lock( &passwd_mutex );
207 if ( (pw = getpwnam( rdn[0][0]->la_value.bv_val )) == NULL ) {
208 matched = parent.bv_val;
209 err = LDAP_NO_SUCH_OBJECT;
210 ldap_pvt_thread_mutex_unlock( &passwd_mutex );
214 e = pw2entry( be, pw, &text );
215 ldap_pvt_thread_mutex_unlock( &passwd_mutex );
221 if ( test_filter( be, conn, op, e, filter ) == LDAP_COMPARE_TRUE ) {
222 send_search_entry( be, conn, op,
223 e, attrs, attrsonly, NULL );
231 send_ldap_result( conn, op,
232 err, err == LDAP_NO_SUCH_OBJECT ? matched : NULL, text,
235 if( rdn != NULL ) ldap_rdnfree( rdn );
247 #ifdef HAVE_SETPWFILE
248 if ( be->be_private != NULL ) {
249 (void) setpwfile( (char *) be->be_private );
251 #endif /* HAVE_SETPWFILE */
255 pw2entry( Backend *be, struct passwd *pw, const char **text )
259 struct berval vals[2];
264 AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass;
265 AttributeDescription *ad_cn = NULL;
266 AttributeDescription *ad_sn = NULL;
267 AttributeDescription *ad_uid = NULL;
268 AttributeDescription *ad_description = NULL;
270 rc = slap_str2ad( "cn", &ad_cn, text );
271 if(rc != LDAP_SUCCESS) return NULL;
272 rc = slap_str2ad( "sn", &ad_sn, text );
273 if(rc != LDAP_SUCCESS) return NULL;
274 rc = slap_str2ad( "uid", &ad_uid, text );
275 if(rc != LDAP_SUCCESS) return NULL;
276 rc = slap_str2ad( "description", &ad_description, text );
277 if(rc != LDAP_SUCCESS) return NULL;
280 * from pw we get pw_name and make it cn
281 * give it an objectclass of person.
284 pwlen = strlen( pw->pw_name );
285 vals[0].bv_len = (sizeof("uid=,")-1) + ( pwlen + be->be_suffix[0].bv_len );
286 vals[0].bv_val = ch_malloc( vals[0].bv_len + 1 );
288 /* rdn attribute type should be a configuratable item */
289 sprintf( vals[0].bv_val, "uid=%s,%s",
290 pw->pw_name, be->be_suffix[0].bv_val );
292 rc = dnNormalize2( NULL, vals, &bv );
293 if( rc != LDAP_SUCCESS ) {
294 free( vals[0].bv_val );
298 e = (Entry *) ch_calloc( 1, sizeof(Entry) );
304 vals[1].bv_val = NULL;
306 /* objectclasses should be configurable items */
307 vals[0].bv_val = "top";
308 vals[0].bv_len = sizeof("top")-1;
309 attr_merge( e, ad_objectClass, vals );
311 vals[0].bv_val = "person";
312 vals[0].bv_len = sizeof("person")-1;
313 attr_merge( e, ad_objectClass, vals );
315 vals[0].bv_val = "uidObject";
316 vals[0].bv_len = sizeof("uidObject")-1;
317 attr_merge( e, ad_objectClass, vals );
319 vals[0].bv_val = pw->pw_name;
320 vals[0].bv_len = pwlen;
321 attr_merge( e, ad_uid, vals ); /* required by uidObject */
322 attr_merge( e, ad_cn, vals ); /* required by person */
323 attr_merge( e, ad_sn, vals ); /* required by person */
327 * if gecos is present, add it as a cn. first process it
328 * according to standard BSD usage. If the processed cn has
329 * a space, use the tail as the surname.
331 if (pw->pw_gecos[0]) {
334 vals[0].bv_val = pw->pw_gecos;
335 vals[0].bv_len = strlen(vals[0].bv_val);
336 attr_merge(e, ad_description, vals);
338 s = strchr(vals[0].bv_val, ',');
341 s = strchr(vals[0].bv_val, '&');
345 if( vals[0].bv_len + pwlen < sizeof(buf) ) {
346 int i = s - vals[0].bv_val;
347 strncpy(buf, vals[0].bv_val, i);
349 strcpy(s, pw->pw_name);
350 *s = TOUPPER((unsigned char)*s);
351 strcat(s, vals[0].bv_val+i+1);
352 vals[0].bv_val = buf;
355 vals[0].bv_len = strlen(vals[0].bv_val);
357 if ( vals[0].bv_len && strcasecmp( vals[0].bv_val, pw->pw_name )) {
358 attr_merge( e, ad_cn, vals );
361 if ( (s=strrchr(vals[0].bv_val, ' '))) {
362 vals[0].bv_val = s + 1;
363 vals[0].bv_len = strlen(vals[0].bv_val);
364 attr_merge(e, ad_sn, vals);