rwmmap.c 29.4 KB
Newer Older
1
2
3
4
/* rwmmap.c - rewrite/mapping routines */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
5
 * Copyright 1999-2021 The OpenLDAP Foundation.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
6
7
 * Portions Copyright 1999-2003 Howard Chu.
 * Portions Copyright 2000-2003 Pierangelo Masarati.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */
/* ACKNOWLEDGEMENTS:
 * This work was initially developed by the Howard Chu for inclusion
 * in OpenLDAP Software and subsequently enhanced by Pierangelo
 * Masarati.
 */

#include "portable.h"

26
27
#ifdef SLAPD_OVER_RWM

28
29
30
31
32
33
34
35
36
37
38
39
#include <stdio.h>

#include <ac/string.h>
#include <ac/socket.h>

#include "slap.h"
#include "rwm.h"

#undef ldap_debug	/* silence a warning in ldap-int.h */
#include "../../../libraries/libldap/ldap-int.h"

int
40
rwm_mapping_cmp( const void *c1, const void *c2 )
41
42
43
{
	struct ldapmapping *map1 = (struct ldapmapping *)c1;
	struct ldapmapping *map2 = (struct ldapmapping *)c2;
44
	int rc = map1->m_src.bv_len - map2->m_src.bv_len;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
45
	
46
47
48
	if ( rc ) {
		return rc;
	}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
49

50
	return strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val );
51
52
53
}

int
54
rwm_mapping_dup( void *c1, void *c2 )
55
56
57
{
	struct ldapmapping *map1 = (struct ldapmapping *)c1;
	struct ldapmapping *map2 = (struct ldapmapping *)c2;
58
59
60
61
62
	int rc = map1->m_src.bv_len - map2->m_src.bv_len;

	if ( rc ) {
		return 0;
	}
63

64
	return ( ( strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val ) == 0 ) ? -1 : 0 );
65
66
}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
67
int
68
rwm_map_init( struct ldapmap *lm, struct ldapmapping **m )
69
{
Pierangelo Masarati's avatar
Pierangelo Masarati committed
70
71
72
	struct ldapmapping	*mapping;
	const char		*text;
	int			rc;
73

74
	assert( m != NULL );
75
76
77
78
79
80

	*m = NULL;
	
	mapping = (struct ldapmapping *)ch_calloc( 2, 
			sizeof( struct ldapmapping ) );
	if ( mapping == NULL ) {
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
81
		return LDAP_NO_MEMORY;
82
83
	}

84
85
86
	/* NOTE: this is needed to make sure that
	 *	rwm-map attribute *
	 * does not  filter out all attributes including objectClass */
87
	rc = slap_str2ad( "objectClass", &mapping[0].m_src_ad, &text );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
88
	if ( rc != LDAP_SUCCESS ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
89
		ch_free( mapping );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
90
91
92
		return rc;
	}

93
94
95
	mapping[0].m_dst_ad = mapping[0].m_src_ad;
	ber_dupbv( &mapping[0].m_src, &mapping[0].m_src_ad->ad_cname );
	ber_dupbv( &mapping[0].m_dst, &mapping[0].m_src );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
96

97
98
99
100
	mapping[1].m_src = mapping[0].m_src;
	mapping[1].m_dst = mapping[0].m_dst;
	mapping[1].m_src_ad = mapping[0].m_src_ad;
	mapping[1].m_dst_ad = mapping[1].m_src_ad;
101

102
	avl_insert( &lm->map, (caddr_t)&mapping[0], 
103
			rwm_mapping_cmp, rwm_mapping_dup );
104
	avl_insert( &lm->remap, (caddr_t)&mapping[1], 
105
			rwm_mapping_cmp, rwm_mapping_dup );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
106

107
	*m = mapping;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
108
109

	return rc;
110
111
}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
112
113
int
rwm_mapping( struct ldapmap *map, struct berval *s, struct ldapmapping **m, int remap )
114
115
{
	Avlnode *tree;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
116
	struct ldapmapping fmapping;
117

Pierangelo Masarati's avatar
Pierangelo Masarati committed
118
119
120
121
	if ( map == NULL ) {
		return 0;
	}

122
	assert( m != NULL );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
123

124
125
126
127
128
129
130
131
132
	/* let special attrnames slip through (ITS#5760) */
	if ( bvmatch( s, slap_bv_no_attrs )
		|| bvmatch( s, slap_bv_all_user_attrs )
		|| bvmatch( s, slap_bv_all_operational_attrs ) )
	{
		*m = NULL;
		return 0;
	}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
133
	if ( remap == RWM_REMAP ) {
134
		tree = map->remap;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
135

136
	} else {
137
		tree = map->map;
138
	}
139

140
	fmapping.m_src = *s;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
141
	*m = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping,
142
			rwm_mapping_cmp );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
143
144
145
146
147
148
149
150
151
152
153
154
155

	if ( *m == NULL ) {
		return map->drop_missing;
	}

	return 0;
}

void
rwm_map( struct ldapmap *map, struct berval *s, struct berval *bv, int remap )
{
	struct ldapmapping *mapping;

156
157
158
159
160
161
162
	/* map->map may be NULL when mapping is configured,
	 * but map->remap can't */
	if ( map->remap == NULL ) {
		*bv = *s;
		return;
	}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
163
	BER_BVZERO( bv );
164
	( void )rwm_mapping( map, s, &mapping, remap );
165
	if ( mapping != NULL ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
166
		if ( !BER_BVISNULL( &mapping->m_dst ) ) {
167
168
			*bv = mapping->m_dst;
		}
169
170
171
		return;
	}

172
	if ( !map->drop_missing ) {
173
		*bv = *s;
174
	}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
175
176
177
178
179
180
181
}

/*
 * Map attribute names in place
 */
int
rwm_map_attrnames(
182
	Operation	*op,
Pierangelo Masarati's avatar
Pierangelo Masarati committed
183
184
185
186
187
	struct ldapmap	*at_map,
	struct ldapmap	*oc_map,
	AttributeName	*an,
	AttributeName	**anp,
	int		remap )
Pierangelo Masarati's avatar
Pierangelo Masarati committed
188
{
189
	int		i, j, x;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
190

191
	assert( anp != NULL );
192
193
194

	*anp = NULL;

195
	if ( an == NULL && op->o_bd->be_extra_anlist == NULL ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
196
197
198
		return LDAP_SUCCESS;
	}

199
200
201
202
203
204
205
206
207
208
209
210
211
	i = 0;
	if ( an != NULL ) {
		for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ )
			/* just count */ ;
	}

	x = 0;
	if ( op->o_bd->be_extra_anlist ) {
		for ( ; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ )
			/* just count */ ;
	}

	assert( i > 0 || x > 0 );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
212
	*anp = op->o_tmpcalloc( ( i + x + 1 ), sizeof( AttributeName ),
213
		op->o_tmpmemctx );
214
215
216
	if ( *anp == NULL ) {
		return LDAP_NO_MEMORY;
	}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
217

Howard Chu's avatar
Howard Chu committed
218
	j = 0;
Howard Chu's avatar
Howard Chu committed
219
	if ( an != NULL ) {
Howard Chu's avatar
Howard Chu committed
220
	for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
		struct ldapmapping	*m;
		int			at_drop_missing = 0,
					oc_drop_missing = 0;

		if ( an[i].an_desc ) {
			if ( !at_map ) {
				/* FIXME: better leave as is? */
				continue;
			}
				
			at_drop_missing = rwm_mapping( at_map, &an[i].an_name, &m, remap );
			if ( at_drop_missing || ( m && BER_BVISNULL( &m->m_dst ) ) ) {
				continue;
			}

			if ( !m ) {
				(*anp)[j] = an[i];
				j++;
				continue;
			}

			(*anp)[j] = an[i];
			if ( remap == RWM_MAP ) {
				(*anp)[j].an_name = m->m_dst;
				(*anp)[j].an_desc = m->m_dst_ad;
			} else {
				(*anp)[j].an_name = m->m_src;
				(*anp)[j].an_desc = m->m_src_ad;

			}

			j++;
			continue;

		} else if ( an[i].an_oc ) {
			if ( !oc_map ) {
				/* FIXME: better leave as is? */
				continue;
			}

			oc_drop_missing = rwm_mapping( oc_map, &an[i].an_name, &m, remap );

			if ( oc_drop_missing || ( m && BER_BVISNULL( &m->m_dst ) ) ) {
				continue;
			}

			if ( !m ) {
				(*anp)[j] = an[i];
				j++;
				continue;
			}

			(*anp)[j] = an[i];
			if ( remap == RWM_MAP ) {
				(*anp)[j].an_name = m->m_dst;
				(*anp)[j].an_oc = m->m_dst_oc;
			} else {
				(*anp)[j].an_name = m->m_src;
				(*anp)[j].an_oc = m->m_src_oc;
			}

		} else {
			at_drop_missing = rwm_mapping( at_map, &an[i].an_name, &m, remap );
		
			if ( at_drop_missing || !m ) {
				oc_drop_missing = rwm_mapping( oc_map, &an[i].an_name, &m, remap );

				/* if both at_map and oc_map required to drop missing,
				 * then do it */
				if ( oc_drop_missing && at_drop_missing ) {
					continue;
				}

				/* if no oc_map mapping was found and at_map required
				 * to drop missing, then do it; otherwise, at_map wins
				 * and an is considered an attr and is left unchanged */
				if ( !m ) {
					if ( at_drop_missing ) {
						continue;
					}
					(*anp)[j] = an[i];
					j++;
					continue;
				}
	
				if ( BER_BVISNULL( &m->m_dst ) ) {
					continue;
				}

				(*anp)[j] = an[i];
				if ( remap == RWM_MAP ) {
					(*anp)[j].an_name = m->m_dst;
					(*anp)[j].an_oc = m->m_dst_oc;
				} else {
					(*anp)[j].an_name = m->m_src;
					(*anp)[j].an_oc = m->m_src_oc;
				}
				j++;
				continue;
			}

			if ( !BER_BVISNULL( &m->m_dst ) ) {
				(*anp)[j] = an[i];
				if ( remap == RWM_MAP ) {
					(*anp)[j].an_name = m->m_dst;
					(*anp)[j].an_desc = m->m_dst_ad;
				} else {
					(*anp)[j].an_name = m->m_src;
					(*anp)[j].an_desc = m->m_src_ad;
				}
				j++;
				continue;
			}
		}
	}
Howard Chu's avatar
Howard Chu committed
336
	}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
337

338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
	if ( op->o_bd->be_extra_anlist != NULL ) {
		/* we assume be_extra_anlist are already mapped */
		for ( x = 0; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ ) {
			BER_BVZERO( &(*anp)[j].an_name );
			if ( op->o_bd->be_extra_anlist[x].an_desc &&
				ad_inlist( op->o_bd->be_extra_anlist[x].an_desc, *anp ) )
			{
				continue;
			}

			(*anp)[j] = op->o_bd->be_extra_anlist[x];
			j++;
		}
	}

	if ( j == 0 && ( i != 0 || x != 0 ) ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
354
		memset( &(*anp)[0], 0, sizeof( AttributeName ) );
355
		(*anp)[0].an_name = *slap_bv_no_attrs;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
356
		j = 1;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
357
358
	}
	memset( &(*anp)[j], 0, sizeof( AttributeName ) );
359

Pierangelo Masarati's avatar
Pierangelo Masarati committed
360
	return LDAP_SUCCESS;
361
362
}

363
#if 0 /* unused! */
364
365
int
rwm_map_attrs(
Pierangelo Masarati's avatar
Pierangelo Masarati committed
366
367
368
369
	struct ldapmap	*at_map,
	AttributeName	*an,
	int		remap,
	char		***mapped_attrs )
370
371
372
373
{
	int i, j;
	char **na;

374
	if ( an == NULL ) {
375
376
377
378
		*mapped_attrs = NULL;
		return LDAP_SUCCESS;
	}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
379
380
	for ( i = 0; !BER_BVISNULL( &an[ i ].an_name ); i++ )
		/* count'em */ ;
381

382
	na = (char **)ch_calloc( i + 1, sizeof( char * ) );
383
	if ( na == NULL ) {
384
385
386
387
		*mapped_attrs = NULL;
		return LDAP_NO_MEMORY;
	}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
388
	for ( i = j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
389
		struct ldapmapping	*mapping;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
390
		
391
		if ( rwm_mapping( at_map, &an[i].an_name, &mapping, remap ) ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
392
393
394
			continue;
		}

395
396
397
398
399
		if ( !mapping ) {
			na[ j++ ] = an[ i ].an_name.bv_val;
			
		} else if ( !BER_BVISNULL( &mapping->m_dst ) ) {
			na[ j++ ] = mapping->m_dst.bv_val;
400
		}
401
	}
402

403
	if ( j == 0 && i != 0 ) {
404
		na[ j++ ] = LDAP_NO_ATTRS;
405
	}
406
407

	na[ j ] = NULL;
408
409

	*mapped_attrs = na;
410

411
412
	return LDAP_SUCCESS;
}
413
#endif
414

415
static int
416
map_attr_value(
Pierangelo Masarati's avatar
Pierangelo Masarati committed
417
418
419
420
421
	dncookie		*dc,
	AttributeDescription 	**adp,
	struct berval		*mapped_attr,
	struct berval		*value,
	struct berval		*mapped_value,
422
423
	int			remap,
	void			*memctx )
424
{
425
	struct berval		vtmp = BER_BVNULL;
426
	int			freeval = 0;
427
428
	AttributeDescription	*ad = *adp;
	struct ldapmapping	*mapping = NULL;
429

430
431
432
433
	rwm_mapping( &dc->rwmap->rwm_at, &ad->ad_cname, &mapping, remap );
	if ( mapping == NULL ) {
		if ( dc->rwmap->rwm_at.drop_missing ) {
			return -1;
434
435
		}

436
437
438
439
		*mapped_attr = ad->ad_cname;

	} else {
		*mapped_attr = mapping->m_dst;
440
441
	}

442
443
444
	if ( value != NULL ) {
		assert( mapped_value != NULL );

445
446
		if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
				|| ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
447
448
449
		{
			dncookie 	fdc = *dc;
			int		rc;
450

451
			fdc.ctx = "searchFilterAttrDN";
452

453
454
455
456
457
458
459
460
			vtmp = *value;
			rc = rwm_dn_massage_normalize( &fdc, value, &vtmp );
			switch ( rc ) {
			case LDAP_SUCCESS:
				if ( vtmp.bv_val != value->bv_val ) {
					freeval = 1;
				}
				break;
461
		
462
463
464
465
466
			case LDAP_UNWILLING_TO_PERFORM:
			case LDAP_OTHER:
			default:
				return -1;
			}
467

468
469
470
		} else if ( ad->ad_type->sat_equality &&
			( ad->ad_type->sat_equality->smr_usage & SLAP_MR_MUTATION_NORMALIZER ) )
		{
471
472
			if ( ad->ad_type->sat_equality->smr_normalize(
				(SLAP_MR_DENORMALIZE|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX),
473
				NULL, NULL, value, &vtmp, memctx ) )
474
			{
475
476
				return -1;
			}
477
			freeval = 2;
478

479
480
481
482
483
484
485
486
487
		} else if ( ad == slap_schema.si_ad_objectClass
				|| ad == slap_schema.si_ad_structuralObjectClass )
		{
			rwm_map( &dc->rwmap->rwm_oc, value, &vtmp, remap );
			if ( BER_BVISNULL( &vtmp ) || BER_BVISEMPTY( &vtmp ) ) {
				vtmp = *value;
			}
		
		} else {
488
489
490
			vtmp = *value;
		}

491
		filter_escape_value_x( &vtmp, mapped_value, memctx );
492

493
494
		switch ( freeval ) {
		case 1:
495
			ch_free( vtmp.bv_val );
496
497
498
499
500
			break;

		case 2:
			ber_memfree_x( vtmp.bv_val, memctx );
			break;
501
		}
502
503
	}
	
504
505
506
507
508
	if ( mapping != NULL ) {
		assert( mapping->m_dst_ad != NULL );
		*adp = mapping->m_dst_ad;
	}

509
510
511
	return 0;
}

512
513
static int
rwm_int_filter_map_rewrite(
Pierangelo Masarati's avatar
Pierangelo Masarati committed
514
515
516
517
	Operation		*op,
	dncookie		*dc,
	Filter			*f,
	struct berval		*fstr )
518
519
{
	int		i;
520
	Filter		*p, ftmp;
521
	AttributeDescription *ad;
522
523
	struct berval	atmp,
			vtmp,
Pierangelo Masarati's avatar
Pierangelo Masarati committed
524
			*tmp;
525
	static struct berval
526
527
528
529
530
531
			/* better than nothing... */
			ber_bvfalse = BER_BVC( "(!(objectClass=*))" ),
			ber_bvtf_false = BER_BVC( "(|)" ),
			/* better than nothing... */
			ber_bvtrue = BER_BVC( "(objectClass=*)" ),
			ber_bvtf_true = BER_BVC( "(&)" ),
Pierangelo Masarati's avatar
Pierangelo Masarati committed
532
533
#if 0
			/* no longer needed; preserved for completeness */
534
			ber_bvundefined = BER_BVC( "(?=undefined)" ),
Pierangelo Masarati's avatar
Pierangelo Masarati committed
535
#endif
536
537
538
			ber_bverror = BER_BVC( "(?=error)" ),
			ber_bvunknown = BER_BVC( "(?=unknown)" ),
			ber_bvnone = BER_BVC( "(?=none)" );
539
540
	ber_len_t	len;

Pierangelo Masarati's avatar
Pierangelo Masarati committed
541
542
543
	assert( fstr != NULL );
	BER_BVZERO( fstr );

544
	if ( f == NULL ) {
545
		ber_dupbv_x( fstr, &ber_bvnone, op->o_tmpmemctx );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
546
		return LDAP_OTHER;
547
548
	}

549
550
#if 0
	/* ITS#6814: give the caller a chance to use undefined filters */
551
552
553
	if ( f->f_choice & SLAPD_FILTER_UNDEFINED ) {
		goto computed;
	}
554
#endif
555

556
	switch ( f->f_choice & SLAPD_FILTER_MASK ) {
557
	case LDAP_FILTER_EQUALITY:
558
559
		ad = f->f_av_desc;
		if ( map_attr_value( dc, &ad, &atmp,
560
			&f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
561
		{
562
			goto computed;
563
564
		}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
565
		fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(=)" );
566
		fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
567
568

		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
569
			atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
570

571
		op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
572
573
574
		break;

	case LDAP_FILTER_GE:
575
576
		ad = f->f_av_desc;
		if ( map_attr_value( dc, &ad, &atmp,
577
			&f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
578
		{
579
			goto computed;
580
581
		}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
582
		fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(>=)" );
583
		fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
584
585

		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
586
			atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
587

588
		op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
589
590
591
		break;

	case LDAP_FILTER_LE:
592
593
		ad = f->f_av_desc;
		if ( map_attr_value( dc, &ad, &atmp,
594
			&f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
595
		{
596
			goto computed;
597
598
		}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
599
		fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(<=)" );
600
		fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
601
602

		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
603
			atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
604

605
		op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
606
607
608
		break;

	case LDAP_FILTER_APPROX:
609
610
		ad = f->f_av_desc;
		if ( map_attr_value( dc, &ad, &atmp,
611
			&f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
612
		{
613
			goto computed;
614
615
		}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
616
		fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(~=)" );
617
		fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
618
619

		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
620
			atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
621

622
		op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
623
624
625
		break;

	case LDAP_FILTER_SUBSTRINGS:
626
627
		ad = f->f_sub_desc;
		if ( map_attr_value( dc, &ad, &atmp,
628
			NULL, NULL, RWM_MAP, op->o_tmpmemctx ) )
629
		{
630
			goto computed;
631
632
633
634
		}

		/* cannot be a DN ... */

Pierangelo Masarati's avatar
Pierangelo Masarati committed
635
		fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" );
636
		fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
637
638
639
640

		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
			atmp.bv_val );

Pierangelo Masarati's avatar
Pierangelo Masarati committed
641
		if ( !BER_BVISNULL( &f->f_sub_initial ) ) {
642
643
			len = fstr->bv_len;

644
			filter_escape_value_x( &f->f_sub_initial, &vtmp, op->o_tmpmemctx );
645
646

			fstr->bv_len += vtmp.bv_len;
647
648
			fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
				op->o_tmpmemctx );
649
650
651

			snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
				/* "(attr=" */ "%s*)",
652
				vtmp.bv_len ? vtmp.bv_val : "" );
653

654
			op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
655
656
657
		}

		if ( f->f_sub_any != NULL ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
658
			for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ ) {
659
				len = fstr->bv_len;
660
661
				filter_escape_value_x( &f->f_sub_any[i], &vtmp,
					op->o_tmpmemctx );
662
663

				fstr->bv_len += vtmp.bv_len + 1;
664
665
				fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
					op->o_tmpmemctx );
666
667
668

				snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
					/* "(attr=[init]*[any*]" */ "%s*)",
669
					vtmp.bv_len ? vtmp.bv_val : "" );
670
				op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
671
672
673
			}
		}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
674
		if ( !BER_BVISNULL( &f->f_sub_final ) ) {
675
676
			len = fstr->bv_len;

677
			filter_escape_value_x( &f->f_sub_final, &vtmp, op->o_tmpmemctx );
678
679

			fstr->bv_len += vtmp.bv_len;
680
681
			fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
				op->o_tmpmemctx );
682
683
684

			snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
				/* "(attr=[init*][any*]" */ "%s)",
685
				vtmp.bv_len ? vtmp.bv_val : "" );
686

687
			op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
688
689
690
691
692
		}

		break;

	case LDAP_FILTER_PRESENT:
693
694
		ad = f->f_desc;
		if ( map_attr_value( dc, &ad, &atmp,
695
			NULL, NULL, RWM_MAP, op->o_tmpmemctx ) )
696
		{
697
			goto computed;
698
699
		}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
700
		fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" );
701
		fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
702
703
704
705
706
707
708
709

		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
			atmp.bv_val );
		break;

	case LDAP_FILTER_AND:
	case LDAP_FILTER_OR:
	case LDAP_FILTER_NOT:
Pierangelo Masarati's avatar
Pierangelo Masarati committed
710
		fstr->bv_len = STRLENOF( "(%)" );
711
		fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
712
713
714
715
716
717

		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
			f->f_choice == LDAP_FILTER_AND ? '&' :
			f->f_choice == LDAP_FILTER_OR ? '|' : '!' );

		for ( p = f->f_list; p != NULL; p = p->f_next ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
718
719
			int	rc;

720
721
			len = fstr->bv_len;

Pierangelo Masarati's avatar
Pierangelo Masarati committed
722
723
724
			rc = rwm_int_filter_map_rewrite( op, dc, p, &vtmp );
			if ( rc != LDAP_SUCCESS ) {
				return rc;
725
726
727
			}
			
			fstr->bv_len += vtmp.bv_len;
728
729
			fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
				op->o_tmpmemctx );
730
731

			snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2, 
732
				/*"("*/ "%s)", vtmp.bv_len ? vtmp.bv_val : "" );
733

734
			op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
735
736
737
738
739
740
		}

		break;

	case LDAP_FILTER_EXT: {
		if ( f->f_mr_desc ) {
741
742
			ad = f->f_mr_desc;
			if ( map_attr_value( dc, &ad, &atmp,
743
				&f->f_mr_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
744
			{
745
				goto computed;
746
747
748
			}

		} else {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
749
			BER_BVSTR( &atmp, "" );
750
			filter_escape_value_x( &f->f_mr_value, &vtmp, op->o_tmpmemctx );
751
752
753
754
		}
			

		fstr->bv_len = atmp.bv_len +
Pierangelo Masarati's avatar
Pierangelo Masarati committed
755
			( f->f_mr_dnattrs ? STRLENOF( ":dn" ) : 0 ) +
756
			( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len + 1 : 0 ) +
Pierangelo Masarati's avatar
Pierangelo Masarati committed
757
			vtmp.bv_len + STRLENOF( "(:=)" );
758
		fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
759
760
761
762

		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
			atmp.bv_val,
			f->f_mr_dnattrs ? ":dn" : "",
Pierangelo Masarati's avatar
Pierangelo Masarati committed
763
764
			!BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "",
			!BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "",
765
			vtmp.bv_len ? vtmp.bv_val : "" );
766
		op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
767
768
		break;
	}
769

770
	case -1:
771
computed:;
772
		f = &ftmp;
773
774
775
776
		f->f_choice = SLAPD_FILTER_COMPUTED;
		f->f_result = SLAPD_COMPARE_UNDEFINED;
		/* fallthru */

777
	case SLAPD_FILTER_COMPUTED:
778
779
		switch ( f->f_result ) {
		case LDAP_COMPARE_FALSE:
780
		/* FIXME: treat UNDEFINED as FALSE */
781
		case SLAPD_COMPARE_UNDEFINED:
782
			if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
783
				tmp = &ber_bvtf_false;
784
				break;
785
			}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
786
			tmp = &ber_bvfalse;
787
			break;
788

789
		case LDAP_COMPARE_TRUE:
790
			if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
791
				tmp = &ber_bvtf_true;
792
				break;
793
			}
794
			tmp = &ber_bvtrue;
795
796
797
			break;
			
		default:
Pierangelo Masarati's avatar
Pierangelo Masarati committed
798
			tmp = &ber_bverror;
799
800
801
			break;
		}

802
		ber_dupbv_x( fstr, tmp, op->o_tmpmemctx );
803
804
		break;
		
805
	default:
806
		ber_dupbv_x( fstr, &ber_bvunknown, op->o_tmpmemctx );
807
808
809
		break;
	}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
810
	return LDAP_SUCCESS;
811
812
}

813
814
int
rwm_filter_map_rewrite(
Pierangelo Masarati's avatar
Pierangelo Masarati committed
815
816
817
818
	Operation		*op,
	dncookie		*dc,
	Filter			*f,
	struct berval		*fstr )
819
820
821
822
823
{
	int		rc;
	dncookie 	fdc;
	struct berval	ftmp;

824
	rc = rwm_int_filter_map_rewrite( op, dc, f, fstr );
825

Pierangelo Masarati's avatar
Pierangelo Masarati committed
826
	if ( rc != 0 ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
827
		return rc;
828
829
830
831
832
833
834
835
	}

	fdc = *dc;
	ftmp = *fstr;

	fdc.ctx = "searchFilter";

	switch ( rewrite_session( fdc.rwmap->rwm_rw, fdc.ctx, 
Pierangelo Masarati's avatar
Pierangelo Masarati committed
836
				( !BER_BVISEMPTY( &ftmp ) ? ftmp.bv_val : "" ), 
837
838
				fdc.conn, &fstr->bv_val ) )
	{
839
	case REWRITE_REGEXEC_OK:
Pierangelo Masarati's avatar
Pierangelo Masarati committed
840
		if ( !BER_BVISNULL( fstr ) ) {
841
			fstr->bv_len = strlen( fstr->bv_val );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
842

843
844
845
846
847
848
		} else {
			*fstr = ftmp;
		}

		Debug( LDAP_DEBUG_ARGS,
			"[rw] %s: \"%s\" -> \"%s\"\n",
849
			fdc.ctx, ftmp.bv_val, fstr->bv_val );		
Pierangelo Masarati's avatar
Pierangelo Masarati committed
850
		if ( fstr->bv_val != ftmp.bv_val ) {
851
852
853
			ber_bvreplace_x( &ftmp, fstr, op->o_tmpmemctx );
			ch_free( fstr->bv_val );
			*fstr = ftmp;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
854
		}
855
856
857
858
859
860
861
862
		rc = LDAP_SUCCESS;
		break;
 		
 	case REWRITE_REGEXEC_UNWILLING:
		if ( fdc.rs ) {
			fdc.rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
			fdc.rs->sr_text = "Operation not allowed";
		}
863
		op->o_tmpfree( ftmp.bv_val, op->o_tmpmemctx );
864
865
866
867
868
869
870
871
		rc = LDAP_UNWILLING_TO_PERFORM;
		break;
	       	
	case REWRITE_REGEXEC_ERR:
		if ( fdc.rs ) {
			fdc.rs->sr_err = LDAP_OTHER;
			fdc.rs->sr_text = "Rewrite error";
		}
872
		op->o_tmpfree( ftmp.bv_val, op->o_tmpmemctx );
873
874
875
		rc = LDAP_OTHER;
		break;
	}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
876

877
878
879
	return rc;
}

880
881
882
883
884
885
886
887
/*
 * I don't like this much, but we need two different
 * functions because different heap managers may be
 * in use in back-ldap/meta to reduce the amount of
 * calls to malloc routines, and some of the free()
 * routines may be macros with args
 */
int
888
rwm_referral_rewrite(
889
890
891
	Operation		*op,
	SlapReply		*rs,
	void			*cookie,
Pierangelo Masarati's avatar
Pierangelo Masarati committed
892
893
	BerVarray		a_vals,
	BerVarray		*pa_nvals )
894
{
895
896
897
898
899
900
901
	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
	struct ldaprwmap	*rwmap = 
			(struct ldaprwmap *)on->on_bi.bi_private;

	int			i, last;

	dncookie		dc;
902
903
	struct berval		dn = BER_BVNULL,
				ndn = BER_BVNULL;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
904

905
	assert( a_vals != NULL );
906
907

	/*
908
	 * Rewrite the dn if needed
909
910
911
912
913
	 */
	dc.rwmap = rwmap;
	dc.conn = op->o_conn;
	dc.rs = rs;
	dc.ctx = (char *)cookie;
914

915
916
917
918
	for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ )
		;
	last--;
	
Pierangelo Masarati's avatar
Pierangelo Masarati committed
919
920
	if ( pa_nvals != NULL ) {
		if ( *pa_nvals == NULL ) {
921
922
			*pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) );
			memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
923
924
		}
	}
925

Pierangelo Masarati's avatar
Pierangelo Masarati committed
926
	for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
927
928
		struct berval	olddn = BER_BVNULL,
				oldval;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
929
		int		rc;
930
931
932
933
934
935
936
937
938
939
940
		LDAPURLDesc	*ludp;

		oldval = a_vals[i];
		rc = ldap_url_parse( oldval.bv_val, &ludp );
		if ( rc != LDAP_URL_SUCCESS ) {
			/* leave attr untouched if massage failed */
			if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
				ber_dupbv( &(*pa_nvals)[i], &oldval );
			}
			continue;
		}
941
942
943
944
945
946
947
948
949

		/* FIXME: URLs like "ldap:///dc=suffix" if passed
		 * thru ldap_url_parse() and ldap_url_desc2str() 
		 * get rewritten as "ldap:///dc=suffix??base";
		 * we don't want this to occur... */
		if ( ludp->lud_scope == LDAP_SCOPE_BASE ) {
			ludp->lud_scope = LDAP_SCOPE_DEFAULT;
		}

950
		ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
951

952
953
954
955
956
957
958
959
960
		dn = olddn;
		if ( pa_nvals ) {
			ndn = olddn;
			rc = rwm_dn_massage_pretty_normalize( &dc, &olddn,
					&dn, &ndn );
		} else {
			rc = rwm_dn_massage_pretty( &dc, &olddn, &dn );
		}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
961
		switch ( rc ) {
962
963
964
965
966
967
968
969
970
		case LDAP_UNWILLING_TO_PERFORM:
			/*
			 * FIXME: need to check if it may be considered 
			 * legal to trim values when adding/modifying;
			 * it should be when searching (e.g. ACLs).
			 */
			ch_free( a_vals[i].bv_val );
			if (last > i ) {
				a_vals[i] = a_vals[last];
Pierangelo Masarati's avatar
Pierangelo Masarati committed
971
972
973
974
975
976
977
				if ( pa_nvals ) {
					(*pa_nvals)[i] = (*pa_nvals)[last];
				}
			}
			BER_BVZERO( &a_vals[last] );
			if ( pa_nvals ) {
				BER_BVZERO( &(*pa_nvals)[last] );
978
979
980
			}
			last--;
			break;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
981
982
		
		case LDAP_SUCCESS:
983
984
985
986
987
			if ( !BER_BVISNULL( &dn ) && dn.bv_val != olddn.bv_val ) {
				char	*newurl;

				ludp->lud_dn = dn.bv_val;
				newurl = ldap_url_desc2str( ludp );
988
989
				ludp->lud_dn = olddn.bv_val;
				ch_free( dn.bv_val );
990
991
				if ( newurl == NULL ) {
					/* FIXME: leave attr untouched
992
993
					 * even if ldap_url_desc2str failed...
					 */
994
995
996
997
					break;
				}

				ber_str2bv( newurl, 0, 1, &a_vals[i] );
998
				ber_memfree( newurl );
999

Pierangelo Masarati's avatar
Pierangelo Masarati committed
1000
				if ( pa_nvals ) {
1001
1002
					ludp->lud_dn = ndn.bv_val;
					newurl = ldap_url_desc2str( ludp );
1003
1004
					ludp->lud_dn = olddn.bv_val;
					ch_free( ndn.bv_val );
1005
1006
					if ( newurl == NULL ) {
						/* FIXME: leave attr untouched
1007
1008
						 * even if ldap_url_desc2str failed...
						 */
1009
1010
1011
1012
1013
						ch_free( a_vals[i].bv_val );
						a_vals[i] = oldval;
						break;
					}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
1014
1015
1016
					if ( !BER_BVISNULL( &(*pa_nvals)[i] ) ) {
						ch_free( (*pa_nvals)[i].bv_val );
					}
1017
					ber_str2bv( newurl, 0, 1, &(*pa_nvals)[i] );
1018
					ber_memfree( newurl );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
1019
				}
1020
1021
1022

				ch_free( oldval.bv_val );
				ludp->lud_dn = olddn.bv_val;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
1023
1024
			}
			break;
1025
1026
1027

		default:
			/* leave attr untouched if massage failed */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
1028
			if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050