1 /* search.c - /etc/passwd backend search function */
10 #include <ac/string.h>
19 static Entry *pw2entry(
36 struct berval *filterstr,
47 int err = LDAP_SUCCESS;
50 struct berval parent = { 0, NULL };
52 const char *text = NULL;
54 AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass;
56 tlimit = (tlimit > be->be_timelimit || tlimit < 1) ? be->be_timelimit
58 stoptime = op->o_time + tlimit;
59 slimit = (slimit > be->be_sizelimit || slimit < 1) ? be->be_sizelimit
65 if ( be->be_private != NULL ) {
66 (void) setpwfile( (char *) be->be_private );
68 #endif /* HAVE_SETPWFILE */
70 /* Handle a query for the base of this backend */
71 if ( be_issuffix( be, nbase ) ) {
72 struct berval vals[2];
74 vals[1].bv_val = NULL;
76 matched = (char *) base;
78 if( scope != LDAP_SCOPE_ONELEVEL ) {
79 AttributeDescription *desc = NULL;
81 /* Create an entry corresponding to the base DN */
82 e = (Entry *) ch_calloc(1, sizeof(Entry));
83 e->e_name.bv_val = ch_strdup( base->bv_val );
84 e->e_name.bv_len = base->bv_len;
85 e->e_nname.bv_val = ch_strdup( nbase->bv_val );
86 e->e_nname.bv_len = nbase->bv_len;
90 /* Use the first attribute of the DN
91 * as an attribute within the entry itself.
93 if( ldap_bv2rdn( base, &rdn, (char **)&text,
94 LDAP_DN_FORMAT_LDAP ) )
96 err = LDAP_INVALID_DN_SYNTAX;
100 if( slap_bv2ad( &rdn[0][0]->la_attr, &desc, &text )) {
101 err = LDAP_NO_SUCH_OBJECT;
106 vals[0] = rdn[0][0]->la_value;
107 attr_merge( e, desc, vals );
112 /* Every entry needs an objectclass. We don't really
113 * know if our hardcoded choice here agrees with the
114 * DN that was configured for this backend, but it's
115 * better than nothing.
117 * should be a configuratable item
119 vals[0].bv_val = "organizationalUnit";
120 vals[0].bv_len = sizeof("organizationalUnit")-1;
121 attr_merge( e, ad_objectClass, vals );
123 if ( test_filter( be, conn, op, e, filter ) == LDAP_COMPARE_TRUE ) {
124 send_search_entry( be, conn, op,
125 e, attrs, attrsonly, NULL );
130 if ( scope != LDAP_SCOPE_BASE ) {
131 /* check all our "children" */
133 for ( pw = getpwent(); pw != NULL; pw = getpwent() ) {
134 /* check for abandon */
135 ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
136 if ( op->o_abandon ) {
137 ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
141 ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
143 /* check time limit */
144 if ( slap_get_time() > stoptime ) {
145 send_ldap_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
146 NULL, NULL, NULL, NULL );
151 if ( !(e = pw2entry( be, pw, &text )) ) {
152 err = LDAP_OPERATIONS_ERROR;
157 if ( test_filter( be, conn, op, e, filter ) == LDAP_COMPARE_TRUE ) {
158 /* check size limit */
159 if ( --slimit == -1 ) {
160 send_ldap_result( conn, op, LDAP_SIZELIMIT_EXCEEDED,
161 NULL, NULL, NULL, NULL );
166 send_search_entry( be, conn, op,
167 e, attrs, attrsonly, NULL );
177 if (! be_issuffix( be, nbase ) ) {
178 dnParent( nbase, &parent );
181 /* This backend is only one layer deep. Don't answer requests for
182 * anything deeper than that.
184 if( !be_issuffix( be, &parent ) ) {
186 for( i=0; be->be_nsuffix[i] != NULL; i++ ) {
187 if( dnIsSuffix( nbase, be->be_nsuffix[i] ) ) {
188 matched = be->be_suffix[i]->bv_val;
192 err = LDAP_NO_SUCH_OBJECT;
196 if( scope == LDAP_SCOPE_ONELEVEL ) {
200 if ( ldap_bv2rdn( base, &rdn, (char **)&text,
201 LDAP_DN_FORMAT_LDAP ))
203 err = LDAP_OPERATIONS_ERROR;
207 if ( (pw = getpwnam( rdn[0][0]->la_value.bv_val )) == NULL ) {
208 matched = parent.bv_val;
209 err = LDAP_NO_SUCH_OBJECT;
213 if ( !(e = pw2entry( be, pw, &text )) ) {
214 err = LDAP_OPERATIONS_ERROR;
218 if ( test_filter( be, conn, op, e, filter ) == LDAP_COMPARE_TRUE ) {
219 send_search_entry( be, conn, op,
220 e, attrs, attrsonly, NULL );
228 send_ldap_result( conn, op,
229 err, err == LDAP_NO_SUCH_OBJECT ? matched : NULL, text,
232 if( rdn != NULL ) ldap_rdnfree( rdn );
238 pw2entry( Backend *be, struct passwd *pw, const char **text )
242 struct berval vals[2];
247 AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass;
248 AttributeDescription *ad_cn = NULL;
249 AttributeDescription *ad_sn = NULL;
250 AttributeDescription *ad_uid = NULL;
251 AttributeDescription *ad_description = NULL;
253 rc = slap_str2ad( "cn", &ad_cn, text );
254 if(rc != LDAP_SUCCESS) return NULL;
255 rc = slap_str2ad( "sn", &ad_sn, text );
256 if(rc != LDAP_SUCCESS) return NULL;
257 rc = slap_str2ad( "uid", &ad_uid, text );
258 if(rc != LDAP_SUCCESS) return NULL;
259 rc = slap_str2ad( "description", &ad_description, text );
260 if(rc != LDAP_SUCCESS) return NULL;
263 * from pw we get pw_name and make it cn
264 * give it an objectclass of person.
267 pwlen = strlen( pw->pw_name );
268 vals[0].bv_len = (sizeof("uid=,")-1) + ( pwlen + be->be_suffix[0]->bv_len );
269 vals[0].bv_val = ch_malloc( vals[0].bv_len + 1 );
271 /* rdn attribute type should be a configuratable item */
272 sprintf( vals[0].bv_val, "uid=%s,%s",
273 pw->pw_name, be->be_suffix[0]->bv_val );
275 rc = dnNormalize2( NULL, vals, &bv );
276 if( rc != LDAP_SUCCESS ) {
277 free( vals[0].bv_val );
281 e = (Entry *) ch_calloc( 1, sizeof(Entry) );
287 vals[1].bv_val = NULL;
289 /* objectclasses should be configurable items */
290 vals[0].bv_val = "top";
291 vals[0].bv_len = sizeof("top")-1;
292 attr_merge( e, ad_objectClass, vals );
294 vals[0].bv_val = "person";
295 vals[0].bv_len = sizeof("person")-1;
296 attr_merge( e, ad_objectClass, vals );
298 vals[0].bv_val = "uidObject";
299 vals[0].bv_len = sizeof("uidObject")-1;
300 attr_merge( e, ad_objectClass, vals );
302 vals[0].bv_val = pw->pw_name;
303 vals[0].bv_len = pwlen;
304 attr_merge( e, ad_uid, vals ); /* required by uidObject */
305 attr_merge( e, ad_cn, vals ); /* required by person */
306 attr_merge( e, ad_sn, vals ); /* required by person */
310 * if gecos is present, add it as a cn. first process it
311 * according to standard BSD usage. If the processed cn has
312 * a space, use the tail as the surname.
314 if (pw->pw_gecos[0]) {
317 vals[0].bv_val = pw->pw_gecos;
318 vals[0].bv_len = strlen(vals[0].bv_val);
319 attr_merge(e, ad_description, vals);
321 s = strchr(vals[0].bv_val, ',');
324 s = strchr(vals[0].bv_val, '&');
327 int i = s - vals[0].bv_val;
328 strncpy(buf, vals[0].bv_val, i);
330 strcpy(s, pw->pw_name);
332 strcat(s, vals[0].bv_val+i+1);
333 vals[0].bv_val = buf;
335 vals[0].bv_len = strlen(vals[0].bv_val);
336 if ( strcmp( vals[0].bv_val, pw->pw_name ))
337 attr_merge( e, ad_cn, vals );
338 if ( (s=strrchr(vals[0].bv_val, ' '))) {
339 vals[0].bv_val = s + 1;
340 vals[0].bv_len = strlen(vals[0].bv_val);
341 attr_merge(e, ad_sn, vals);