xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-ldap/search.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: search.c,v 1.1.1.5 2014/05/28 09:58:49 tron Exp $	*/
2 
3 /* search.c - ldap backend search function */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 1999-2014 The OpenLDAP Foundation.
8  * Portions Copyright 1999-2003 Howard Chu.
9  * Portions Copyright 2000-2003 Pierangelo Masarati.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted only as authorized by the OpenLDAP
14  * Public License.
15  *
16  * A copy of this license is available in the file LICENSE in the
17  * top-level directory of the distribution or, alternatively, at
18  * <http://www.OpenLDAP.org/license.html>.
19  */
20 /* ACKNOWLEDGEMENTS:
21  * This work was initially developed by the Howard Chu for inclusion
22  * in OpenLDAP Software and subsequently enhanced by Pierangelo
23  * Masarati.
24  */
25 
26 #include "portable.h"
27 
28 #include <stdio.h>
29 
30 #include <ac/socket.h>
31 #include <ac/string.h>
32 #include <ac/time.h>
33 
34 #include "slap.h"
35 #include "back-ldap.h"
36 #include "../../../libraries/liblber/lber-int.h"
37 
38 #include "lutil.h"
39 
40 static int
41 ldap_build_entry( Operation *op, LDAPMessage *e, Entry *ent,
42 	 struct berval *bdn );
43 
44 /*
45  * replaces (&) with (objectClass=*) and (|) with (!(objectClass=*))
46  * as the best replacement for RFC 4526 absolute true/absolute false
47  * filters; the only difference (AFAIK) is that they require search
48  * access to objectClass.
49  *
50  * filter->bv_val may be alloc'd on the thread's slab, if equal to
51  * op->ors_filterstr.bv_val, or realloc'd on the thread's slab otherwise.
52  */
53 static int
54 ldap_back_munge_filter(
55 	Operation	*op,
56 	struct berval	*filter )
57 {
58 	char *ptr;
59 	int gotit = 0;
60 
61 	Debug( LDAP_DEBUG_ARGS, "=> ldap_back_munge_filter \"%s\"\n",
62 			filter->bv_val, 0, 0 );
63 
64 	for ( ptr = strchr( filter->bv_val, '(' );
65 			ptr;
66 			ptr = strchr( ptr, '(' ) )
67 	{
68 		static struct berval
69 			bv_t = BER_BVC( "(&)" ),
70 			bv_f = BER_BVC( "(|)" ),
71 			bv_T = BER_BVC( "(objectClass=*)" ),
72 			bv_F = BER_BVC( "(!(objectClass=*))" );
73 		struct berval *oldbv = NULL,
74 			*newbv = NULL,
75 			oldfilter = BER_BVNULL;
76 
77 		if ( ptr[2] != ')' ) {
78 			ptr++;
79 			continue;
80 		}
81 
82 		switch ( ptr[1] ) {
83 		case '&':
84 			oldbv = &bv_t;
85 			newbv = &bv_T;
86 			break;
87 
88 		case '|':
89 			oldbv = &bv_f;
90 			newbv = &bv_F;
91 			break;
92 
93 		default:
94 			/* should be an error */
95 			continue;
96 		}
97 
98 		oldfilter = *filter;
99 		filter->bv_len += newbv->bv_len - oldbv->bv_len;
100 		if ( filter->bv_val == op->ors_filterstr.bv_val ) {
101 			filter->bv_val = op->o_tmpalloc( filter->bv_len + 1,
102 					op->o_tmpmemctx );
103 
104 			AC_MEMCPY( filter->bv_val, op->ors_filterstr.bv_val,
105 					ptr - oldfilter.bv_val );
106 
107 		} else {
108 			filter->bv_val = op->o_tmprealloc( filter->bv_val,
109 					filter->bv_len + 1, op->o_tmpmemctx );
110 		}
111 
112 		ptr = filter->bv_val + ( ptr - oldfilter.bv_val );
113 
114 		AC_MEMCPY( &ptr[ newbv->bv_len ],
115 				&ptr[ oldbv->bv_len ],
116 				oldfilter.bv_len - ( ptr - filter->bv_val ) - oldbv->bv_len + 1 );
117 		AC_MEMCPY( ptr, newbv->bv_val, newbv->bv_len );
118 
119 		ptr += newbv->bv_len;
120 
121 		gotit++;
122 	}
123 
124 	Debug( LDAP_DEBUG_ARGS, "<= ldap_back_munge_filter \"%s\" (%d)\n",
125 			filter->bv_val, gotit, 0 );
126 
127 	return gotit;
128 }
129 
130 int
131 ldap_back_search(
132 		Operation	*op,
133 		SlapReply	*rs )
134 {
135 	ldapinfo_t	*li = (ldapinfo_t *) op->o_bd->be_private;
136 
137 	ldapconn_t	*lc = NULL;
138 	struct timeval	tv;
139 	time_t		stoptime = (time_t)(-1);
140 	LDAPMessage	*res,
141 			*e;
142 	int		rc = 0,
143 			msgid;
144 	struct berval	match = BER_BVNULL,
145 			filter = BER_BVNULL;
146 	int		i, x;
147 	char		**attrs = NULL;
148 	int		freetext = 0, filter_undef = 0;
149 	int		do_retry = 1, dont_retry = 0;
150 	LDAPControl	**ctrls = NULL;
151 	char		**references = NULL;
152 
153 	rs_assert_ready( rs );
154 	rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia, we can set rs = non-entry */
155 
156 	if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
157 		return rs->sr_err;
158 	}
159 
160 	/*
161 	 * FIXME: in case of values return filter, we might want
162 	 * to map attrs and maybe rewrite value
163 	 */
164 
165 	if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
166 		tv.tv_sec = op->ors_tlimit;
167 		tv.tv_usec = 0;
168 		stoptime = op->o_time + op->ors_tlimit;
169 
170 	} else {
171 		LDAP_BACK_TV_SET( &tv );
172 	}
173 
174 	i = 0;
175 	if ( op->ors_attrs ) {
176 		for ( ; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++ )
177 			/* just count attrs */ ;
178 	}
179 
180 	x = 0;
181 	if ( op->o_bd->be_extra_anlist ) {
182 		for ( ; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ )
183 			/* just count attrs */ ;
184 	}
185 
186 	if ( i > 0 || x > 0 ) {
187 		int j = 0;
188 
189 		attrs = op->o_tmpalloc( ( i + x + 1 )*sizeof( char * ),
190 			op->o_tmpmemctx );
191 		if ( attrs == NULL ) {
192 			rs->sr_err = LDAP_NO_MEMORY;
193 			rc = -1;
194 			goto finish;
195 		}
196 
197 		if ( i > 0 ) {
198 			for ( i = 0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++, j++ ) {
199 				attrs[ j ] = op->ors_attrs[i].an_name.bv_val;
200 			}
201 		}
202 
203 		if ( x > 0 ) {
204 			for ( x = 0; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++, j++ ) {
205 				if ( op->o_bd->be_extra_anlist[x].an_desc &&
206 					ad_inlist( op->o_bd->be_extra_anlist[x].an_desc, op->ors_attrs ) )
207 				{
208 					continue;
209 				}
210 
211 				attrs[ j ] = op->o_bd->be_extra_anlist[x].an_name.bv_val;
212 			}
213 		}
214 
215 		attrs[ j ] = NULL;
216 	}
217 
218 	ctrls = op->o_ctrls;
219 	rc = ldap_back_controls_add( op, rs, lc, &ctrls );
220 	if ( rc != LDAP_SUCCESS ) {
221 		goto finish;
222 	}
223 
224 	/* deal with <draft-zeilenga-ldap-t-f> filters */
225 	filter = op->ors_filterstr;
226 retry:
227 	/* this goes after retry because ldap_back_munge_filter()
228 	 * optionally replaces RFC 4526 T-F filters (&) (|)
229 	 * if already computed, they will be re-installed
230 	 * by filter2bv_undef_x() later */
231 	if ( !LDAP_BACK_T_F( li ) ) {
232 		ldap_back_munge_filter( op, &filter );
233 	}
234 
235 	rs->sr_err = ldap_pvt_search( lc->lc_ld, op->o_req_dn.bv_val,
236 			op->ors_scope, filter.bv_val,
237 			attrs, op->ors_attrsonly, ctrls, NULL,
238 			tv.tv_sec ? &tv : NULL,
239 			op->ors_slimit, op->ors_deref, &msgid );
240 
241 	ldap_pvt_thread_mutex_lock( &li->li_counter_mutex );
242 	ldap_pvt_mp_add( li->li_ops_completed[ SLAP_OP_SEARCH ], 1 );
243 	ldap_pvt_thread_mutex_unlock( &li->li_counter_mutex );
244 
245 	if ( rs->sr_err != LDAP_SUCCESS ) {
246 		switch ( rs->sr_err ) {
247 		case LDAP_SERVER_DOWN:
248 			if ( do_retry ) {
249 				do_retry = 0;
250 				if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_DONTSEND ) ) {
251 					goto retry;
252 				}
253 			}
254 
255 			if ( lc == NULL ) {
256 				/* reset by ldap_back_retry ... */
257 				rs->sr_err = slap_map_api2result( rs );
258 
259 			} else {
260 				rc = ldap_back_op_result( lc, op, rs, msgid, 0, LDAP_BACK_DONTSEND );
261 			}
262 
263 			goto finish;
264 
265 		case LDAP_FILTER_ERROR:
266 			/* first try? */
267 			if ( !filter_undef &&
268 				strstr( filter.bv_val, "(?" ) &&
269 				!LDAP_BACK_NOUNDEFFILTER( li ) )
270 			{
271 				BER_BVZERO( &filter );
272 				filter2bv_undef_x( op, op->ors_filter, 1, &filter );
273 				filter_undef = 1;
274 				goto retry;
275 			}
276 
277 			/* invalid filters return success with no data */
278 			rs->sr_err = LDAP_SUCCESS;
279 			rs->sr_text = NULL;
280 			goto finish;
281 
282 		default:
283 			rs->sr_err = slap_map_api2result( rs );
284 			rs->sr_text = NULL;
285 			goto finish;
286 		}
287 	}
288 
289 	/* if needed, initialize timeout */
290 	if ( li->li_timeout[ SLAP_OP_SEARCH ] ) {
291 		if ( tv.tv_sec == 0 || tv.tv_sec > li->li_timeout[ SLAP_OP_SEARCH ] ) {
292 			tv.tv_sec = li->li_timeout[ SLAP_OP_SEARCH ];
293 			tv.tv_usec = 0;
294 		}
295 	}
296 
297 	/* We pull apart the ber result, stuff it into a slapd entry, and
298 	 * let send_search_entry stuff it back into ber format. Slow & ugly,
299 	 * but this is necessary for version matching, and for ACL processing.
300 	 */
301 
302 	for ( rc = -2; rc != -1; rc = ldap_result( lc->lc_ld, msgid, LDAP_MSG_ONE, &tv, &res ) )
303 	{
304 		/* check for abandon */
305 		if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( lc ) ) {
306 			if ( rc > 0 ) {
307 				ldap_msgfree( res );
308 			}
309 			(void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
310 			rc = SLAPD_ABANDON;
311 			goto finish;
312 		}
313 
314 		if ( rc == 0 || rc == -2 ) {
315 			ldap_pvt_thread_yield();
316 
317 			/* check timeout */
318 			if ( li->li_timeout[ SLAP_OP_SEARCH ] ) {
319 				if ( rc == 0 ) {
320 					(void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
321 					rs->sr_text = "Operation timed out";
322 					rc = rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
323 						LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
324 					goto finish;
325 				}
326 
327 			} else {
328 				LDAP_BACK_TV_SET( &tv );
329 			}
330 
331 			/* check time limit */
332 			if ( op->ors_tlimit != SLAP_NO_LIMIT
333 					&& slap_get_time() > stoptime )
334 			{
335 				(void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
336 				rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
337 				goto finish;
338 			}
339 			continue;
340 
341 		} else {
342 			/* only touch when activity actually took place... */
343 			if ( li->li_idle_timeout && lc ) {
344 				lc->lc_time = op->o_time;
345 			}
346 
347 			/* don't retry any more */
348 			dont_retry = 1;
349 		}
350 
351 
352 		if ( rc == LDAP_RES_SEARCH_ENTRY ) {
353 			Entry		ent = { 0 };
354 			struct berval	bdn = BER_BVNULL;
355 
356 			do_retry = 0;
357 
358 			e = ldap_first_entry( lc->lc_ld, res );
359 			rc = ldap_build_entry( op, e, &ent, &bdn );
360 			if ( rc == LDAP_SUCCESS ) {
361 				ldap_get_entry_controls( lc->lc_ld, res, &rs->sr_ctrls );
362 				rs->sr_entry = &ent;
363 				rs->sr_attrs = op->ors_attrs;
364 				rs->sr_operational_attrs = NULL;
365 				rs->sr_flags = 0;
366 				rs->sr_err = LDAP_SUCCESS;
367 				rc = rs->sr_err = send_search_entry( op, rs );
368 				if ( rs->sr_ctrls ) {
369 					ldap_controls_free( rs->sr_ctrls );
370 					rs->sr_ctrls = NULL;
371 				}
372 				rs->sr_entry = NULL;
373 				rs->sr_flags = 0;
374 				if ( !BER_BVISNULL( &ent.e_name ) ) {
375 					assert( ent.e_name.bv_val != bdn.bv_val );
376 					op->o_tmpfree( ent.e_name.bv_val, op->o_tmpmemctx );
377 					BER_BVZERO( &ent.e_name );
378 				}
379 				if ( !BER_BVISNULL( &ent.e_nname ) ) {
380 					op->o_tmpfree( ent.e_nname.bv_val, op->o_tmpmemctx );
381 					BER_BVZERO( &ent.e_nname );
382 				}
383 				entry_clean( &ent );
384 			}
385 			ldap_msgfree( res );
386 			switch ( rc ) {
387 			case LDAP_SUCCESS:
388 			case LDAP_INSUFFICIENT_ACCESS:
389 				break;
390 
391 			default:
392 				if ( rc == LDAP_UNAVAILABLE ) {
393 					rc = rs->sr_err = LDAP_OTHER;
394 				} else {
395 					(void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
396 				}
397 				goto finish;
398 			}
399 
400 		} else if ( rc == LDAP_RES_SEARCH_REFERENCE ) {
401 			if ( LDAP_BACK_NOREFS( li ) ) {
402 				ldap_msgfree( res );
403 				continue;
404 			}
405 
406 			do_retry = 0;
407 			rc = ldap_parse_reference( lc->lc_ld, res,
408 					&references, &rs->sr_ctrls, 1 );
409 
410 			if ( rc != LDAP_SUCCESS ) {
411 				continue;
412 			}
413 
414 			/* FIXME: there MUST be at least one */
415 			if ( references && references[ 0 ] && references[ 0 ][ 0 ] ) {
416 				int		cnt;
417 
418 				for ( cnt = 0; references[ cnt ]; cnt++ )
419 					/* NO OP */ ;
420 
421 				/* FIXME: there MUST be at least one */
422 				rs->sr_ref = op->o_tmpalloc( ( cnt + 1 ) * sizeof( struct berval ),
423 					op->o_tmpmemctx );
424 
425 				for ( cnt = 0; references[ cnt ]; cnt++ ) {
426 					ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] );
427 				}
428 				BER_BVZERO( &rs->sr_ref[ cnt ] );
429 
430 				/* ignore return value by now */
431 				RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) );
432 				rs->sr_entry = NULL;
433 				( void )send_search_reference( op, rs );
434 
435 			} else {
436 				Debug( LDAP_DEBUG_ANY,
437 					"%s ldap_back_search: "
438 					"got SEARCH_REFERENCE "
439 					"with no referrals\n",
440 					op->o_log_prefix, 0, 0 );
441 			}
442 
443 			/* cleanup */
444 			if ( references ) {
445 				ber_memvfree( (void **)references );
446 				op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );
447 				rs->sr_ref = NULL;
448 				references = NULL;
449 			}
450 
451 			if ( rs->sr_ctrls ) {
452 				ldap_controls_free( rs->sr_ctrls );
453 				rs->sr_ctrls = NULL;
454 			}
455 
456 		} else if ( rc == LDAP_RES_INTERMEDIATE ) {
457 			/* FIXME: response controls
458 			 * are passed without checks */
459 			rc = ldap_parse_intermediate( lc->lc_ld,
460 				res,
461 				(char **)&rs->sr_rspoid,
462 				&rs->sr_rspdata,
463 				&rs->sr_ctrls,
464 				0 );
465 			if ( rc != LDAP_SUCCESS ) {
466 				continue;
467 			}
468 
469 			slap_send_ldap_intermediate( op, rs );
470 
471 			if ( rs->sr_rspoid != NULL ) {
472 				ber_memfree( (char *)rs->sr_rspoid );
473 				rs->sr_rspoid = NULL;
474 			}
475 
476 			if ( rs->sr_rspdata != NULL ) {
477 				ber_bvfree( rs->sr_rspdata );
478 				rs->sr_rspdata = NULL;
479 			}
480 
481 			if ( rs->sr_ctrls != NULL ) {
482 				ldap_controls_free( rs->sr_ctrls );
483 				rs->sr_ctrls = NULL;
484 			}
485 
486 		} else {
487 			char		*err = NULL;
488 
489 			rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err,
490 					&match.bv_val, &err,
491 					&references, &rs->sr_ctrls, 1 );
492 			if ( rc == LDAP_SUCCESS ) {
493 				if ( err ) {
494 					rs->sr_text = err;
495 					freetext = 1;
496 				}
497 			} else {
498 				rs->sr_err = rc;
499 			}
500 			rs->sr_err = slap_map_api2result( rs );
501 
502 			/* RFC 4511: referrals can only appear
503 			 * if result code is LDAP_REFERRAL */
504 			if ( references
505 				&& references[ 0 ]
506 				&& references[ 0 ][ 0 ] )
507 			{
508 				if ( rs->sr_err != LDAP_REFERRAL ) {
509 					Debug( LDAP_DEBUG_ANY,
510 						"%s ldap_back_search: "
511 						"got referrals with err=%d\n",
512 						op->o_log_prefix,
513 						rs->sr_err, 0 );
514 
515 				} else {
516 					int	cnt;
517 
518 					for ( cnt = 0; references[ cnt ]; cnt++ )
519 						/* NO OP */ ;
520 
521 					rs->sr_ref = op->o_tmpalloc( ( cnt + 1 ) * sizeof( struct berval ),
522 						op->o_tmpmemctx );
523 
524 					for ( cnt = 0; references[ cnt ]; cnt++ ) {
525 						/* duplicating ...*/
526 						ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] );
527 					}
528 					BER_BVZERO( &rs->sr_ref[ cnt ] );
529 				}
530 
531 			} else if ( rs->sr_err == LDAP_REFERRAL ) {
532 				Debug( LDAP_DEBUG_ANY,
533 					"%s ldap_back_search: "
534 					"got err=%d with null "
535 					"or empty referrals\n",
536 					op->o_log_prefix,
537 					rs->sr_err, 0 );
538 
539 				rs->sr_err = LDAP_NO_SUCH_OBJECT;
540 			}
541 
542 			if ( match.bv_val != NULL ) {
543 				match.bv_len = strlen( match.bv_val );
544 			}
545 
546 			rc = 0;
547 			break;
548 		}
549 
550 		/* if needed, restore timeout */
551 		if ( li->li_timeout[ SLAP_OP_SEARCH ] ) {
552 			if ( tv.tv_sec == 0 || tv.tv_sec > li->li_timeout[ SLAP_OP_SEARCH ] ) {
553 				tv.tv_sec = li->li_timeout[ SLAP_OP_SEARCH ];
554 				tv.tv_usec = 0;
555 			}
556 		}
557 	}
558 
559  	if ( rc == -1 ) {
560 		if ( dont_retry == 0 ) {
561 			if ( do_retry ) {
562 				do_retry = 0;
563 				if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_DONTSEND ) ) {
564 					goto retry;
565 				}
566 			}
567 
568 			rs->sr_err = LDAP_SERVER_DOWN;
569 			rs->sr_err = slap_map_api2result( rs );
570 			goto finish;
571 
572 		} else if ( LDAP_BACK_ONERR_STOP( li ) ) {
573 			/* if onerr == STOP */
574 			rs->sr_err = LDAP_SERVER_DOWN;
575 			rs->sr_err = slap_map_api2result( rs );
576 			goto finish;
577 		}
578 	}
579 
580 	/*
581 	 * Rewrite the matched portion of the search base, if required
582 	 */
583 	if ( !BER_BVISNULL( &match ) && !BER_BVISEMPTY( &match ) ) {
584 		struct berval	pmatch;
585 
586 		if ( dnPretty( NULL, &match, &pmatch, op->o_tmpmemctx ) != LDAP_SUCCESS ) {
587 			pmatch.bv_val = match.bv_val;
588 			match.bv_val = NULL;
589 		}
590 		rs->sr_matched = pmatch.bv_val;
591 		rs->sr_flags |= REP_MATCHED_MUSTBEFREED;
592 	}
593 
594 finish:;
595 	if ( !BER_BVISNULL( &match ) ) {
596 		ber_memfree( match.bv_val );
597 	}
598 
599 	if ( rs->sr_v2ref ) {
600 		rs->sr_err = LDAP_REFERRAL;
601 	}
602 
603 	if ( LDAP_BACK_QUARANTINE( li ) ) {
604 		ldap_back_quarantine( op, rs );
605 	}
606 
607 	if ( filter.bv_val != op->ors_filterstr.bv_val ) {
608 		op->o_tmpfree( filter.bv_val, op->o_tmpmemctx );
609 	}
610 
611 #if 0
612 	/* let send_ldap_result play cleanup handlers (ITS#4645) */
613 	if ( rc != SLAPD_ABANDON )
614 #endif
615 	{
616 		send_ldap_result( op, rs );
617 	}
618 
619 	(void)ldap_back_controls_free( op, rs, &ctrls );
620 
621 	if ( rs->sr_ctrls ) {
622 		ldap_controls_free( rs->sr_ctrls );
623 		rs->sr_ctrls = NULL;
624 	}
625 
626 	if ( rs->sr_text ) {
627 		if ( freetext ) {
628 			ber_memfree( (char *)rs->sr_text );
629 		}
630 		rs->sr_text = NULL;
631 	}
632 
633 	if ( rs->sr_ref ) {
634 		op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );
635 		rs->sr_ref = NULL;
636 	}
637 
638 	if ( references ) {
639 		ber_memvfree( (void **)references );
640 	}
641 
642 	if ( attrs ) {
643 		op->o_tmpfree( attrs, op->o_tmpmemctx );
644 	}
645 
646 	if ( lc != NULL ) {
647 		ldap_back_release_conn( li, lc );
648 	}
649 
650 	return rs->sr_err;
651 }
652 
653 static int
654 ldap_build_entry(
655 		Operation	*op,
656 		LDAPMessage	*e,
657 		Entry		*ent,
658 		struct berval	*bdn )
659 {
660 	struct berval	a;
661 	BerElement	ber = *ldap_get_message_ber( e );
662 	Attribute	*attr, **attrp;
663 	const char	*text;
664 	int		last;
665 	char *lastb;
666 	ber_len_t len;
667 
668 	/* safe assumptions ... */
669 	assert( ent != NULL );
670 	BER_BVZERO( &ent->e_bv );
671 
672 	if ( ber_scanf( &ber, "{m", bdn ) == LBER_ERROR ) {
673 		return LDAP_DECODING_ERROR;
674 	}
675 
676 	/*
677 	 * Note: this may fail if the target host(s) schema differs
678 	 * from the one known to the meta, and a DN with unknown
679 	 * attributes is returned.
680 	 *
681 	 * FIXME: should we log anything, or delegate to dnNormalize?
682 	 */
683 	/* Note: if the distinguished values or the naming attributes
684 	 * change, should we massage them as well?
685 	 */
686 	if ( dnPrettyNormal( NULL, bdn, &ent->e_name, &ent->e_nname,
687 		op->o_tmpmemctx ) != LDAP_SUCCESS )
688 	{
689 		return LDAP_INVALID_DN_SYNTAX;
690 	}
691 
692 	ent->e_attrs = NULL;
693 	if ( ber_first_element( &ber, &len, &lastb ) != LBER_SEQUENCE ) {
694 		return LDAP_SUCCESS;
695 	}
696 
697 	attrp = &ent->e_attrs;
698 	while ( ber_next_element( &ber, &len, lastb ) == LBER_SEQUENCE &&
699 		ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) {
700 		int				i;
701 		slap_syntax_validate_func	*validate;
702 		slap_syntax_transform_func	*pretty;
703 
704 		attr = attr_alloc( NULL );
705 		if ( attr == NULL ) {
706 			return LDAP_OTHER;
707 		}
708 		if ( slap_bv2ad( &a, &attr->a_desc, &text )
709 				!= LDAP_SUCCESS )
710 		{
711 			if ( slap_bv2undef_ad( &a, &attr->a_desc, &text,
712 				SLAP_AD_PROXIED ) != LDAP_SUCCESS )
713 			{
714 				Debug( LDAP_DEBUG_ANY,
715 					"%s ldap_build_entry: "
716 					"slap_bv2undef_ad(%s): %s\n",
717 					op->o_log_prefix, a.bv_val, text );
718 
719 				( void )ber_scanf( &ber, "x" /* [W] */ );
720 				attr_free( attr );
721 				continue;
722 			}
723 		}
724 
725 		/* no subschemaSubentry */
726 		if ( attr->a_desc == slap_schema.si_ad_subschemaSubentry
727 			|| attr->a_desc == slap_schema.si_ad_entryDN )
728 		{
729 
730 			/*
731 			 * We eat target's subschemaSubentry because
732 			 * a search for this value is likely not
733 			 * to resolve to the appropriate backend;
734 			 * later, the local subschemaSubentry is
735 			 * added.
736 			 *
737 			 * We also eat entryDN because the frontend
738 			 * will reattach it without checking if already
739 			 * present...
740 			 */
741 			( void )ber_scanf( &ber, "x" /* [W] */ );
742 			attr_free( attr );
743 			continue;
744 		}
745 
746 		if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR
747 				|| attr->a_vals == NULL )
748 		{
749 			/*
750 			 * Note: attr->a_vals can be null when using
751 			 * values result filter
752 			 */
753 			attr->a_vals = (struct berval *)&slap_dummy_bv;
754 		}
755 
756 		validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate;
757 		pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty;
758 
759 		if ( !validate && !pretty ) {
760 			attr->a_nvals = NULL;
761 			attr_free( attr );
762 			goto next_attr;
763 		}
764 
765 		for ( i = 0; !BER_BVISNULL( &attr->a_vals[i] ); i++ ) ;
766 		last = i;
767 
768 		/*
769 		 * check that each value is valid per syntax
770 		 * and pretty if appropriate
771 		 */
772 		for ( i = 0; i<last; i++ ) {
773 			struct berval	pval;
774 			int		rc;
775 
776 			if ( pretty ) {
777 				rc = ordered_value_pretty( attr->a_desc,
778 					&attr->a_vals[i], &pval, NULL );
779 
780 			} else {
781 				rc = ordered_value_validate( attr->a_desc,
782 					&attr->a_vals[i], 0 );
783 			}
784 
785 			if ( rc != LDAP_SUCCESS ) {
786 				ObjectClass *oc;
787 
788 				/* check if, by chance, it's an undefined objectClass */
789 				if ( attr->a_desc == slap_schema.si_ad_objectClass &&
790 						( oc = oc_bvfind_undef( &attr->a_vals[i] ) ) != NULL )
791 				{
792 					ber_dupbv( &pval, &oc->soc_cname );
793 					rc = LDAP_SUCCESS;
794 
795 				} else {
796 					ber_memfree( attr->a_vals[i].bv_val );
797 					if ( --last == i ) {
798 						BER_BVZERO( &attr->a_vals[i] );
799 						break;
800 					}
801 					attr->a_vals[i] = attr->a_vals[last];
802 					BER_BVZERO( &attr->a_vals[last] );
803 					i--;
804 				}
805 			}
806 
807 			if ( rc == LDAP_SUCCESS && pretty ) {
808 				ber_memfree( attr->a_vals[i].bv_val );
809 				attr->a_vals[i] = pval;
810 			}
811 		}
812 		attr->a_numvals = last = i;
813 		if ( last == 0 && attr->a_vals != &slap_dummy_bv ) {
814 			attr->a_nvals = NULL;
815 			attr_free( attr );
816 			goto next_attr;
817 		}
818 
819 		if ( last && attr->a_desc->ad_type->sat_equality &&
820 				attr->a_desc->ad_type->sat_equality->smr_normalize )
821 		{
822 			attr->a_nvals = ch_malloc( ( last + 1 )*sizeof( struct berval ) );
823 			for ( i = 0; i < last; i++ ) {
824 				int		rc;
825 
826 				rc = ordered_value_normalize(
827 					SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
828 					attr->a_desc,
829 					attr->a_desc->ad_type->sat_equality,
830 					&attr->a_vals[i], &attr->a_nvals[i],
831 					NULL );
832 
833 				if ( rc != LDAP_SUCCESS ) {
834 					ber_memfree( attr->a_vals[i].bv_val );
835 					if ( --last == i ) {
836 						BER_BVZERO( &attr->a_vals[i] );
837 						break;
838 					}
839 					attr->a_vals[i] = attr->a_vals[last];
840 					BER_BVZERO( &attr->a_vals[last] );
841 					i--;
842 				}
843 			}
844 			BER_BVZERO( &attr->a_nvals[i] );
845 			if ( last == 0 ) {
846 				attr_free( attr );
847 				goto next_attr;
848 			}
849 
850 		} else {
851 			attr->a_nvals = attr->a_vals;
852 		}
853 
854 		attr->a_numvals = last;
855 
856 		/* Handle sorted vals, strip dups but keep the attr */
857 		if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) {
858 			while ( attr->a_numvals > 1 ) {
859 				int rc = slap_sort_vals( (Modifications *)attr, &text, &i, op->o_tmpmemctx );
860 				if ( rc != LDAP_TYPE_OR_VALUE_EXISTS )
861 					break;
862 
863 				/* Strip duplicate values */
864 				if ( attr->a_nvals != attr->a_vals )
865 					ber_memfree( attr->a_nvals[i].bv_val );
866 				ber_memfree( attr->a_vals[i].bv_val );
867 				attr->a_numvals--;
868 
869 				assert( i >= 0 );
870 				if ( (unsigned)i < attr->a_numvals ) {
871 					attr->a_vals[i] = attr->a_vals[attr->a_numvals];
872 					if ( attr->a_nvals != attr->a_vals )
873 						attr->a_nvals[i] = attr->a_nvals[attr->a_numvals];
874 				}
875 				BER_BVZERO(&attr->a_vals[attr->a_numvals]);
876 				if ( attr->a_nvals != attr->a_vals )
877 					BER_BVZERO(&attr->a_nvals[attr->a_numvals]);
878 			}
879 			attr->a_flags |= SLAP_ATTR_SORTED_VALS;
880 		}
881 
882 		*attrp = attr;
883 		attrp = &attr->a_next;
884 
885 next_attr:;
886 	}
887 
888 	return LDAP_SUCCESS;
889 }
890 
891 /* return 0 IFF we can retrieve the entry with ndn
892  */
893 int
894 ldap_back_entry_get(
895 		Operation		*op,
896 		struct berval		*ndn,
897 		ObjectClass		*oc,
898 		AttributeDescription	*at,
899 		int			rw,
900 		Entry			**ent )
901 {
902 	ldapinfo_t	*li = (ldapinfo_t *) op->o_bd->be_private;
903 
904 	ldapconn_t	*lc = NULL;
905 	int		rc,
906 			do_not_cache;
907 	ber_tag_t	tag;
908 	struct berval	bdn;
909 	LDAPMessage	*result = NULL,
910 			*e = NULL;
911 	char		*attr[3], **attrp = NULL;
912 	char		*filter = NULL;
913 	SlapReply	rs;
914 	int		do_retry = 1;
915 	LDAPControl	**ctrls = NULL;
916 
917 	*ent = NULL;
918 
919 	/* Tell getconn this is a privileged op */
920 	do_not_cache = op->o_do_not_cache;
921 	tag = op->o_tag;
922 	/* do not cache */
923 	op->o_do_not_cache = 1;
924 	/* ldap_back_entry_get() is an entry lookup, so it does not need
925 	 * to know what the entry is being looked up for */
926 	op->o_tag = LDAP_REQ_SEARCH;
927 	rc = ldap_back_dobind( &lc, op, &rs, LDAP_BACK_DONTSEND );
928 	op->o_do_not_cache = do_not_cache;
929 	op->o_tag = tag;
930 	if ( !rc ) {
931 		return rs.sr_err;
932 	}
933 
934 	if ( at ) {
935 		attrp = attr;
936 		if ( oc && at != slap_schema.si_ad_objectClass ) {
937 			attr[0] = slap_schema.si_ad_objectClass->ad_cname.bv_val;
938 			attr[1] = at->ad_cname.bv_val;
939 			attr[2] = NULL;
940 
941 		} else {
942 			attr[0] = at->ad_cname.bv_val;
943 			attr[1] = NULL;
944 		}
945 	}
946 
947 	if ( oc ) {
948 		char	*ptr;
949 
950 		filter = op->o_tmpalloc( STRLENOF( "(objectClass=" ")" )
951 				+ oc->soc_cname.bv_len + 1, op->o_tmpmemctx );
952 		ptr = lutil_strcopy( filter, "(objectClass=" );
953 		ptr = lutil_strcopy( ptr, oc->soc_cname.bv_val );
954 		*ptr++ = ')';
955 		*ptr++ = '\0';
956 	}
957 
958 retry:
959 	ctrls = op->o_ctrls;
960 	rc = ldap_back_controls_add( op, &rs, lc, &ctrls );
961 	if ( rc != LDAP_SUCCESS ) {
962 		goto cleanup;
963 	}
964 
965 	/* TODO: timeout? */
966 	rc = ldap_pvt_search_s( lc->lc_ld, ndn->bv_val, LDAP_SCOPE_BASE, filter,
967 				attrp, LDAP_DEREF_NEVER, ctrls, NULL,
968 				NULL, LDAP_NO_LIMIT, 0, &result );
969 	if ( rc != LDAP_SUCCESS ) {
970 		if ( rc == LDAP_SERVER_DOWN && do_retry ) {
971 			do_retry = 0;
972 			if ( ldap_back_retry( &lc, op, &rs, LDAP_BACK_DONTSEND ) ) {
973 				/* if the identity changed, there might be need to re-authz */
974 				(void)ldap_back_controls_free( op, &rs, &ctrls );
975 				goto retry;
976 			}
977 		}
978 		goto cleanup;
979 	}
980 
981 	e = ldap_first_entry( lc->lc_ld, result );
982 	if ( e == NULL ) {
983 		/* the entry exists, but it doesn't match the filter? */
984 		goto cleanup;
985 	}
986 
987 	*ent = entry_alloc();
988 	if ( *ent == NULL ) {
989 		rc = LDAP_NO_MEMORY;
990 		goto cleanup;
991 	}
992 
993 	rc = ldap_build_entry( op, e, *ent, &bdn );
994 
995 	if ( rc != LDAP_SUCCESS ) {
996 		entry_free( *ent );
997 		*ent = NULL;
998 	}
999 
1000 cleanup:
1001 	(void)ldap_back_controls_free( op, &rs, &ctrls );
1002 
1003 	if ( result ) {
1004 		ldap_msgfree( result );
1005 	}
1006 
1007 	if ( filter ) {
1008 		op->o_tmpfree( filter, op->o_tmpmemctx );
1009 	}
1010 
1011 	if ( lc != NULL ) {
1012 		ldap_back_release_conn( li, lc );
1013 	}
1014 
1015 	return rc;
1016 }
1017