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