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;
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->bv_val ) ) {
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_str2rdn( base->bv_val, &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 parent = dn_parent( be, nbase->bv_val );
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] != 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_str2rdn( base->bv_val, &rdn, (char **)&text,
199 LDAP_DN_FORMAT_LDAP ))
201 err = LDAP_OPERATIONS_ERROR;
205 if ( (pw = getpwnam( rdn[0][0]->la_value.bv_val )) == NULL ) {
207 err = LDAP_NO_SUCH_OBJECT;
211 if ( !(e = pw2entry( be, pw, &text )) ) {
212 err = LDAP_OPERATIONS_ERROR;
216 if ( test_filter( be, conn, op, e, filter ) == LDAP_COMPARE_TRUE ) {
217 send_search_entry( be, conn, op,
218 e, attrs, attrsonly, NULL );
226 send_ldap_result( conn, op,
227 err, err == LDAP_NO_SUCH_OBJECT ? matched : NULL, text,
230 if( rdn != NULL ) ldap_rdnfree( rdn );
236 pw2entry( Backend *be, struct passwd *pw, const char **text )
240 struct berval vals[2];
245 AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass;
246 AttributeDescription *ad_cn = NULL;
247 AttributeDescription *ad_sn = NULL;
248 AttributeDescription *ad_uid = NULL;
249 AttributeDescription *ad_description = NULL;
251 rc = slap_str2ad( "cn", &ad_cn, text );
252 if(rc != LDAP_SUCCESS) return NULL;
253 rc = slap_str2ad( "sn", &ad_sn, text );
254 if(rc != LDAP_SUCCESS) return NULL;
255 rc = slap_str2ad( "uid", &ad_uid, text );
256 if(rc != LDAP_SUCCESS) return NULL;
257 rc = slap_str2ad( "description", &ad_description, text );
258 if(rc != LDAP_SUCCESS) return NULL;
261 * from pw we get pw_name and make it cn
262 * give it an objectclass of person.
265 pwlen = strlen( pw->pw_name );
266 vals[0].bv_len = (sizeof("uid=,")-1) + ( pwlen + be->be_suffix[0]->bv_len );
267 vals[0].bv_val = ch_malloc( vals[0].bv_len + 1 );
269 /* rdn attribute type should be a configuratable item */
270 sprintf( vals[0].bv_val, "uid=%s,%s",
271 pw->pw_name, be->be_suffix[0]->bv_val );
273 rc = dnNormalize2( NULL, vals, &bv );
274 if( rc != LDAP_SUCCESS ) {
275 free( vals[0].bv_val );
279 e = (Entry *) ch_calloc( 1, sizeof(Entry) );
285 vals[1].bv_val = NULL;
287 /* objectclasses should be configurable items */
288 vals[0].bv_val = "top";
289 vals[0].bv_len = sizeof("top")-1;
290 attr_merge( e, ad_objectClass, vals );
292 vals[0].bv_val = "person";
293 vals[0].bv_len = sizeof("person")-1;
294 attr_merge( e, ad_objectClass, vals );
296 vals[0].bv_val = "uidObject";
297 vals[0].bv_len = sizeof("uidObject")-1;
298 attr_merge( e, ad_objectClass, vals );
300 vals[0].bv_val = pw->pw_name;
301 vals[0].bv_len = pwlen;
302 attr_merge( e, ad_uid, vals ); /* required by uidObject */
303 attr_merge( e, ad_cn, vals ); /* required by person */
304 attr_merge( e, ad_sn, vals ); /* required by person */
308 * if gecos is present, add it as a cn. first process it
309 * according to standard BSD usage. If the processed cn has
310 * a space, use the tail as the surname.
312 if (pw->pw_gecos[0]) {
315 vals[0].bv_val = pw->pw_gecos;
316 vals[0].bv_len = strlen(vals[0].bv_val);
317 attr_merge(e, ad_description, vals);
319 s = strchr(vals[0].bv_val, ',');
322 s = strchr(vals[0].bv_val, '&');
325 int i = s - vals[0].bv_val;
326 strncpy(buf, vals[0].bv_val, i);
328 strcpy(s, pw->pw_name);
330 strcat(s, vals[0].bv_val+i+1);
331 vals[0].bv_val = buf;
333 vals[0].bv_len = strlen(vals[0].bv_val);
334 if ( strcmp( vals[0].bv_val, pw->pw_name ))
335 attr_merge( e, ad_cn, vals );
336 if ( (s=strrchr(vals[0].bv_val, ' '))) {
337 vals[0].bv_val = s + 1;
338 vals[0].bv_len = strlen(vals[0].bv_val);
339 attr_merge(e, ad_sn, vals);