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 if ( op->o_abandon ) {
140 /* check time limit */
141 if ( slap_get_time() > stoptime ) {
142 send_ldap_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
143 NULL, NULL, NULL, NULL );
148 if ( !(e = pw2entry( be, pw, &text )) ) {
149 err = LDAP_OPERATIONS_ERROR;
154 if ( test_filter( be, conn, op, e, filter ) == LDAP_COMPARE_TRUE ) {
155 /* check size limit */
156 if ( --slimit == -1 ) {
157 send_ldap_result( conn, op, LDAP_SIZELIMIT_EXCEEDED,
158 NULL, NULL, NULL, NULL );
163 send_search_entry( be, conn, op,
164 e, attrs, attrsonly, NULL );
174 if (! be_issuffix( be, nbase ) ) {
175 dnParent( nbase, &parent );
178 /* This backend is only one layer deep. Don't answer requests for
179 * anything deeper than that.
181 if( !be_issuffix( be, &parent ) ) {
183 for( i=0; be->be_nsuffix[i] != NULL; i++ ) {
184 if( dnIsSuffix( nbase, be->be_nsuffix[i] ) ) {
185 matched = be->be_suffix[i]->bv_val;
189 err = LDAP_NO_SUCH_OBJECT;
193 if( scope == LDAP_SCOPE_ONELEVEL ) {
197 if ( ldap_bv2rdn( base, &rdn, (char **)&text,
198 LDAP_DN_FORMAT_LDAP ))
200 err = LDAP_OPERATIONS_ERROR;
204 if ( (pw = getpwnam( rdn[0][0]->la_value.bv_val )) == NULL ) {
205 matched = parent.bv_val;
206 err = LDAP_NO_SUCH_OBJECT;
210 if ( !(e = pw2entry( be, pw, &text )) ) {
211 err = LDAP_OPERATIONS_ERROR;
215 if ( test_filter( be, conn, op, e, filter ) == LDAP_COMPARE_TRUE ) {
216 send_search_entry( be, conn, op,
217 e, attrs, attrsonly, NULL );
225 send_ldap_result( conn, op,
226 err, err == LDAP_NO_SUCH_OBJECT ? matched : NULL, text,
229 if( rdn != NULL ) ldap_rdnfree( rdn );
235 pw2entry( Backend *be, struct passwd *pw, const char **text )
239 struct berval vals[2];
244 AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass;
245 AttributeDescription *ad_cn = NULL;
246 AttributeDescription *ad_sn = NULL;
247 AttributeDescription *ad_uid = NULL;
248 AttributeDescription *ad_description = NULL;
250 rc = slap_str2ad( "cn", &ad_cn, text );
251 if(rc != LDAP_SUCCESS) return NULL;
252 rc = slap_str2ad( "sn", &ad_sn, text );
253 if(rc != LDAP_SUCCESS) return NULL;
254 rc = slap_str2ad( "uid", &ad_uid, text );
255 if(rc != LDAP_SUCCESS) return NULL;
256 rc = slap_str2ad( "description", &ad_description, text );
257 if(rc != LDAP_SUCCESS) return NULL;
260 * from pw we get pw_name and make it cn
261 * give it an objectclass of person.
264 pwlen = strlen( pw->pw_name );
265 vals[0].bv_len = (sizeof("uid=,")-1) + ( pwlen + be->be_suffix[0]->bv_len );
266 vals[0].bv_val = ch_malloc( vals[0].bv_len + 1 );
268 /* rdn attribute type should be a configuratable item */
269 sprintf( vals[0].bv_val, "uid=%s,%s",
270 pw->pw_name, be->be_suffix[0]->bv_val );
272 rc = dnNormalize2( NULL, vals, &bv );
273 if( rc != LDAP_SUCCESS ) {
274 free( vals[0].bv_val );
278 e = (Entry *) ch_calloc( 1, sizeof(Entry) );
284 vals[1].bv_val = NULL;
286 /* objectclasses should be configurable items */
287 vals[0].bv_val = "top";
288 vals[0].bv_len = sizeof("top")-1;
289 attr_merge( e, ad_objectClass, vals );
291 vals[0].bv_val = "person";
292 vals[0].bv_len = sizeof("person")-1;
293 attr_merge( e, ad_objectClass, vals );
295 vals[0].bv_val = "uidObject";
296 vals[0].bv_len = sizeof("uidObject")-1;
297 attr_merge( e, ad_objectClass, vals );
299 vals[0].bv_val = pw->pw_name;
300 vals[0].bv_len = pwlen;
301 attr_merge( e, ad_uid, vals ); /* required by uidObject */
302 attr_merge( e, ad_cn, vals ); /* required by person */
303 attr_merge( e, ad_sn, vals ); /* required by person */
307 * if gecos is present, add it as a cn. first process it
308 * according to standard BSD usage. If the processed cn has
309 * a space, use the tail as the surname.
311 if (pw->pw_gecos[0]) {
314 vals[0].bv_val = pw->pw_gecos;
315 vals[0].bv_len = strlen(vals[0].bv_val);
316 attr_merge(e, ad_description, vals);
318 s = strchr(vals[0].bv_val, ',');
321 s = strchr(vals[0].bv_val, '&');
324 int i = s - vals[0].bv_val;
325 strncpy(buf, vals[0].bv_val, i);
327 strcpy(s, pw->pw_name);
328 *s = TOUPPER((unsigned char)*s);
329 strcat(s, vals[0].bv_val+i+1);
330 vals[0].bv_val = buf;
332 vals[0].bv_len = strlen(vals[0].bv_val);
333 if ( strcmp( vals[0].bv_val, pw->pw_name ))
334 attr_merge( e, ad_cn, vals );
335 if ( (s=strrchr(vals[0].bv_val, ' '))) {
336 vals[0].bv_val = s + 1;
337 vals[0].bv_len = strlen(vals[0].bv_val);
338 attr_merge(e, ad_sn, vals);