mr.c 13.2 KB
Newer Older
1
2
3
/* mr.c - routines to manage matching rule definitions */
/* $OpenLDAP$ */
/*
Kurt Zeilenga's avatar
Kurt Zeilenga committed
4
 * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
 */

#include "portable.h"

#include <stdio.h>

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

#include "slap.h"
#include "ldap_pvt.h"

struct mindexrec {
Howard Chu's avatar
Howard Chu committed
20
	struct berval	mir_name;
21
22
23
24
25
	MatchingRule	*mir_mr;
};

static Avlnode	*mr_index = NULL;
static MatchingRule *mr_list = NULL;
26
static MatchingRuleUse *mru_list = NULL;
27
28
29
30
31
32
33

static int
mr_index_cmp(
    struct mindexrec	*mir1,
    struct mindexrec	*mir2
)
{
Howard Chu's avatar
Howard Chu committed
34
35
36
	int i = mir1->mir_name.bv_len - mir2->mir_name.bv_len;
	if (i) return i;
	return (strcmp( mir1->mir_name.bv_val, mir2->mir_name.bv_val ));
37
38
39
40
}

static int
mr_index_name_cmp(
Howard Chu's avatar
Howard Chu committed
41
    struct berval	*name,
42
43
44
    struct mindexrec	*mir
)
{
Howard Chu's avatar
Howard Chu committed
45
46
47
	int i = name->bv_len - mir->mir_name.bv_len;
	if (i) return i;
	return (strncmp( name->bv_val, mir->mir_name.bv_val, name->bv_len ));
48
49
50
51
}

MatchingRule *
mr_find( const char *mrname )
Howard Chu's avatar
Howard Chu committed
52
53
54
{
	struct berval bv;

Howard Chu's avatar
Howard Chu committed
55
	bv.bv_val = (char *)mrname;
Howard Chu's avatar
Howard Chu committed
56
57
58
59
60
61
	bv.bv_len = strlen( mrname );
	return mr_bvfind( &bv );
}

MatchingRule *
mr_bvfind( struct berval *mrname )
62
63
64
65
{
	struct mindexrec	*mir = NULL;

	if ( (mir = (struct mindexrec *) avl_find( mr_index, mrname,
Gary Williams's avatar
Gary Williams committed
66
	    (AVL_CMP) mr_index_name_cmp )) != NULL ) {
67
68
69
70
71
		return( mir->mir_mr );
	}
	return( NULL );
}

72
73
74
75
76
77
78
79
void
mr_destroy( void )
{
	MatchingRule *m, *n;

	avl_free(mr_index, ldap_memfree);
	for (m=mr_list; m; m=n) {
		n = m->smr_next;
80
		ch_free( m->smr_str.bv_val );
81
82
83
84
		ldap_matchingrule_free((LDAPMatchingRule *)m);
	}
}

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
static int
mr_insert(
    MatchingRule	*smr,
    const char		**err
)
{
	MatchingRule		**mrp;
	struct mindexrec	*mir;
	char			**names;

	mrp = &mr_list;
	while ( *mrp != NULL ) {
		mrp = &(*mrp)->smr_next;
	}
	*mrp = smr;

	if ( smr->smr_oid ) {
		mir = (struct mindexrec *)
			ch_calloc( 1, sizeof(struct mindexrec) );
Howard Chu's avatar
Howard Chu committed
104
105
		mir->mir_name.bv_val = smr->smr_oid;
		mir->mir_name.bv_len = strlen( smr->smr_oid );
106
107
108
109
110
111
		mir->mir_mr = smr;
		if ( avl_insert( &mr_index, (caddr_t) mir,
				 (AVL_CMP) mr_index_cmp,
				 (AVL_DUP) avl_dup_error ) ) {
			*err = smr->smr_oid;
			ldap_memfree(mir);
112
			return SLAP_SCHERR_MR_DUP;
113
114
		}
		/* FIX: temporal consistency check */
Howard Chu's avatar
Howard Chu committed
115
		mr_bvfind(&mir->mir_name);
116
117
118
119
120
	}
	if ( (names = smr->smr_names) ) {
		while ( *names ) {
			mir = (struct mindexrec *)
				ch_calloc( 1, sizeof(struct mindexrec) );
Howard Chu's avatar
Howard Chu committed
121
122
			mir->mir_name.bv_val = *names;
			mir->mir_name.bv_len = strlen( *names );
123
124
125
126
127
128
			mir->mir_mr = smr;
			if ( avl_insert( &mr_index, (caddr_t) mir,
					 (AVL_CMP) mr_index_cmp,
					 (AVL_DUP) avl_dup_error ) ) {
				*err = *names;
				ldap_memfree(mir);
129
				return SLAP_SCHERR_MR_DUP;
130
131
			}
			/* FIX: temporal consistency check */
Howard Chu's avatar
Howard Chu committed
132
			mr_bvfind(&mir->mir_name);
133
134
135
136
137
138
139
140
			names++;
		}
	}
	return 0;
}

int
mr_add(
141
    LDAPMatchingRule		*mr,
142
    slap_mrule_defs_rec	*def,
143
	MatchingRule	*amr,
144
145
146
147
148
149
150
151
    const char		**err
)
{
	MatchingRule	*smr;
	Syntax		*syn;
	int		code;

	smr = (MatchingRule *) ch_calloc( 1, sizeof(MatchingRule) );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
152
	AC_MEMCPY( &smr->smr_mrule, mr, sizeof(LDAPMatchingRule));
153

154
155
156
157
158
	/*
	 * note: smr_bvoid uses the same memory of smr_mrule.mr_oid;
	 * smr_oidlen is #defined as smr_bvoid.bv_len
	 */
	smr->smr_bvoid.bv_val = smr->smr_mrule.mr_oid;
159
	smr->smr_oidlen = strlen( mr->mr_oid );
160
161
162
163
164
165
	smr->smr_usage = def->mrd_usage;
	smr->smr_convert = def->mrd_convert;
	smr->smr_normalize = def->mrd_normalize;
	smr->smr_match = def->mrd_match;
	smr->smr_indexer = def->mrd_indexer;
	smr->smr_filter = def->mrd_filter;
166
	smr->smr_associated = amr;
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

	if ( smr->smr_syntax_oid ) {
		if ( (syn = syn_find(smr->smr_syntax_oid)) ) {
			smr->smr_syntax = syn;
		} else {
			*err = smr->smr_syntax_oid;
			return SLAP_SCHERR_SYN_NOT_FOUND;
		}
	} else {
		*err = "";
		return SLAP_SCHERR_MR_INCOMPLETE;
	}
	code = mr_insert(smr,err);
	return code;
}

int
register_matching_rule(
185
	slap_mrule_defs_rec *def )
186
{
187
	LDAPMatchingRule *mr;
188
	MatchingRule *amr = NULL;
189
190
191
	int		code;
	const char	*err;

192
	if( def->mrd_usage == SLAP_MR_NONE ) {
193
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
194
		LDAP_LOG( OPERATION, ERR, 
195
			"register_matching_rule: %s not usable\n", def->mrd_desc, 0, 0 );
196
#else
197
		Debug( LDAP_DEBUG_ANY, "register_matching_rule: not usable %s\n",
198
		    def->mrd_desc, 0, 0 );
199
200
#endif

201
202
203
		return -1;
	}

204
205
	if( def->mrd_associated != NULL ) {
		amr = mr_find( def->mrd_associated );
206

207
208
209
210
#if 0
		/* ignore for now */

		if( amr == NULL ) {
211
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
212
213
			LDAP_LOG( OPERATION, ERR,
			   "register_matching_rule: could not locate associated "
214
			   "matching rule %s for %s\n",  def->mrd_associated, def->mrd_desc, 0 );
215
#else
216
217
			Debug( LDAP_DEBUG_ANY, "register_matching_rule: could not locate "
				"associated matching rule %s for %s\n",
218
				def->mrd_associated, def->mrd_desc, 0 );
219
220
#endif

221
222
223
			return -1;
		}
#endif
224
225
226

	}

227
	mr = ldap_str2matchingrule( def->mrd_desc, &code, &err, LDAP_SCHEMA_ALLOW_ALL);
228
	if ( !mr ) {
229
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
230
231
		LDAP_LOG( OPERATION, ERR, 
			"register_matching_rule: %s before %s in %s.\n",
232
			ldap_scherr2str(code), err, def->mrd_desc );
233
#else
234
		Debug( LDAP_DEBUG_ANY, "Error in register_matching_rule: %s before %s in %s\n",
235
		    ldap_scherr2str(code), err, def->mrd_desc );
236
237
#endif

238
239
240
		return( -1 );
	}

241
	code = mr_add( mr, def, amr, &err );
242

243
244
	ldap_memfree( mr );

245
	if ( code ) {
246
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
247
248
		LDAP_LOG( OPERATION, ERR, 
			"register_matching_rule: %s for %s in %s.\n",
249
			scherr2str(code), err, def->mrd_desc );
250
#else
251
		Debug( LDAP_DEBUG_ANY, "Error in register_matching_rule: %s for %s in %s\n",
252
		    scherr2str(code), err, def->mrd_desc );
253
254
#endif

255
256
		return( -1 );
	}
257

258
259
260
	return( 0 );
}

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
void
mru_destroy( void )
{
	MatchingRuleUse *m, *n;

	for (m=mru_list; m; m=n) {
		n = m->smru_next;
		if ( m->smru_str.bv_val ) {
			ch_free( m->smru_str.bv_val );
		}
		/* memory borrowed from m->smru_mr */
		m->smru_oid = NULL;
		m->smru_names = NULL;
		m->smru_desc = NULL;

		/* free what's left (basically 
		 * smru_mruleuse.mru_applies_oids) */
		ldap_matchingruleuse_free((LDAPMatchingRuleUse *)m);
	}
}

int
matching_rule_use_init( void )
{
	MatchingRule	*mr;
	MatchingRuleUse	**mru_ptr = &mru_list;

#define MR_TYPE_MASK		( SLAP_MR_TYPE_MASK & ~SLAP_MR_EXT )
#define MR_TYPE_SUBTYPE_MASK	( MR_TYPE_MASK | SLAP_MR_SUBTYPE_MASK ) 
#if 0	/* all types regardless of EXT */
#define MR_TYPE(x)		( (x) & MR_TYPE_MASK )
#define MR_TYPE_SUBTYPE(x)	( (x) & MR_TYPE_SUBTYPE_MASK )
#else	/* only those marked as EXT (as per RFC 2252) */
#define MR_TYPE(x)		( ( (x) & SLAP_MR_EXT ) ? ( (x) & MR_TYPE_MASK ) : SLAP_MR_NONE )
#define MR_TYPE_SUBTYPE(x)	( ( (x) & SLAP_MR_EXT ) ? ( (x) & MR_TYPE_SUBTYPE_MASK ) : SLAP_MR_NONE )
#endif

#ifdef NEW_LOGGING
	LDAP_LOG( OPERATION, INFO, "matching_rule_use_init\n", 0, 0, 0 );
#else
	Debug( LDAP_DEBUG_TRACE, "matching_rule_use_init\n", 0, 0, 0 );
#endif

	for ( mr = mr_list; mr; mr = mr->smr_next ) {
		slap_mask_t	um = MR_TYPE( mr->smr_usage );
		slap_mask_t	usm = MR_TYPE_SUBTYPE( mr->smr_usage );

		AttributeType	*at;
		MatchingRuleUse	_mru, *mru = &_mru;

311
312
		char		**applies_oids = NULL;

313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
		mr->smr_mru = NULL;

		/* hide rules marked as HIDE */
		if ( mr->smr_usage & SLAP_MR_HIDE ) {
			continue;
		}

		/* hide rules with no type */
		if ( um == SLAP_MR_NONE ) {
			continue;
		}

		memset( mru, 0, sizeof( MatchingRuleUse ) );

		/*
		 * Note: we're using the same values of the corresponding 
		 * MatchingRule structure; maybe we'd copy them ...
		 */
		mru->smru_mr = mr;
		mru->smru_obsolete = mr->smr_obsolete;
		mru->smru_applies_oids = NULL;
		mru->smru_next = NULL;
		mru->smru_oid = mr->smr_oid;
		mru->smru_names = mr->smr_names;
		mru->smru_desc = mr->smr_desc;

#ifdef NEW_LOGGING
		LDAP_LOG( OPERATION, INFO, "    %s (%s): ", 
				mru->smru_oid, 
				mru->smru_names ? mru->smru_names[ 0 ] : "", 0 );
#else
		Debug( LDAP_DEBUG_TRACE, "    %s (%s): ", 
				mru->smru_oid, 
				mru->smru_names ? mru->smru_names[ 0 ] : "", 0 );
#endif

		switch ( um ) {
		case SLAP_MR_EQUALITY:
			at = NULL;
			if ( usm == SLAP_MR_EQUALITY_APPROX ) {
#ifdef NEW_LOGGING
				LDAP_LOG( OPERATION, INFO, "APPROX%s\n",
						( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
						0, 0 );
#else
				Debug( LDAP_DEBUG_TRACE, "APPROX%s\n",
						( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
						0, 0 );
#endif

				for ( at_start( &at ); at; at_next( &at ) ) {
					if ( mr == at->sat_approx ) {
#ifdef NEW_LOGGING
						LDAP_LOG( OPERATION, INFO, "        %s (%s)\n",
								at->sat_oid,
								at->sat_cname.bv_val, 0 );
#else
						Debug( LDAP_DEBUG_TRACE, "        %s (%s)\n",
								at->sat_oid,
								at->sat_cname.bv_val, 0 );
#endif
374
375
						ldap_charray_add( &applies_oids,
								at->sat_oid );
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
					}
				}

			} else {
#ifdef NEW_LOGGING
				LDAP_LOG( OPERATION, INFO, "EQUALITY%s\n",
						( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
						0, 0 );
#else
				Debug( LDAP_DEBUG_TRACE, "EQUALITY%s\n",
						( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
						0, 0 );
#endif
				for ( at_start( &at ); at; at_next( &at ) ) {
					if ( mr == at->sat_equality ) {
#ifdef NEW_LOGGING
						LDAP_LOG( OPERATION, INFO, "        %s (%s)\n",
								at->sat_oid,
								at->sat_cname.bv_val, 0 );
#else
						Debug( LDAP_DEBUG_TRACE, "        %s (%s)\n",
								at->sat_oid,
								at->sat_cname.bv_val, 0 );
#endif
400
						ldap_charray_add( &applies_oids,
401
								at->sat_cname.bv_val );
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
					}
				}
			}
			break;

		case SLAP_MR_ORDERING:
#ifdef NEW_LOGGING
			LDAP_LOG( OPERATION, INFO, "ORDERING%s\n",
					( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
					0, 0 );
#else
			Debug( LDAP_DEBUG_TRACE, "ORDERING%s\n",
					( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
					0, 0 );
#endif
			at = NULL;
			for ( at_start( &at ); at; at_next( &at ) ) {
				if ( mr == at->sat_ordering ) {
#ifdef NEW_LOGGING
					LDAP_LOG( OPERATION, INFO, "        %s (%s)\n",
							at->sat_oid,
							at->sat_cname.bv_val, 0 );
#else
					Debug( LDAP_DEBUG_TRACE, "        %s (%s)\n",
							at->sat_oid,
							at->sat_cname.bv_val, 0 );
#endif
429
					ldap_charray_add( &applies_oids,
430
							at->sat_cname.bv_val );
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
				}
			}
			break;

		case SLAP_MR_SUBSTR:
#ifdef NEW_LOGGING
			LDAP_LOG( OPERATION, INFO, "SUBSTR%s\n",
					( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
					0, 0 );
#else
			Debug( LDAP_DEBUG_TRACE, "SUBSTR%s\n",
					( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
					0, 0 );
#endif
			at = NULL;
			for ( at_start( &at ); at; at_next( &at ) ) {
				if ( mr == at->sat_substr ) {
#ifdef NEW_LOGGING
					LDAP_LOG( OPERATION, INFO, "        %s (%s)\n",
							at->sat_oid,
							at->sat_cname.bv_val, 0 );
#else
					Debug( LDAP_DEBUG_TRACE, "        %s (%s)\n",
							at->sat_oid,
							at->sat_cname.bv_val, 0 );
#endif
457
					ldap_charray_add( &applies_oids,
458
							at->sat_cname.bv_val );
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
				}
			}
			break;

		default:
#ifdef NEW_LOGGING
			LDAP_LOG( OPERATION, ERR, "        unknown matching rule type "
					"(type mask %d, subtype mask %d%s)\n", um, usm,
					( mr->smr_usage & SLAP_MR_EXT ) ? ", EXT" : "" );
#else
			Debug( LDAP_DEBUG_ANY, "        unknown matching rule type "
					"(type mask %d, subtype mask %d%s)\n", um, usm,
					( mr->smr_usage & SLAP_MR_EXT ) ? ", EXT" : "" );
#endif
			fprintf ( stderr, "    %d (%d)\n", um, usm );
			assert( 0 );
		}

		/*
		 * Note: the matchingRules that are not used
		 * by any attributeType are not listed as
		 * matchingRuleUse
		 */
482
483
		if ( applies_oids != NULL ) {
			mru->smru_applies_oids = applies_oids;
484
485
486
487
488
489
490
491
492
493
494
495
496
497
#ifdef NEW_LOGGING
			{
				char	*str = ldap_matchingruleuse2str( &mru->smru_mruleuse );
				LDAP_LOG( OPERATION, INFO, "matchingRuleUse: %s\n", str, 0, 0 );
				ldap_memfree( str );
			}
#else
			{
				char	*str = ldap_matchingruleuse2str( &mru->smru_mruleuse );
				Debug( LDAP_DEBUG_TRACE, "matchingRuleUse: %s\n", str, 0, 0 );
				ldap_memfree( str );
			}
#endif

498
499
			mru = (MatchingRuleUse *)ber_memalloc( sizeof( MatchingRuleUse ) );
			/* call-forward from MatchingRule to MatchingRuleUse */
500
			mr->smr_mru = mru;
501
			/* copy static data to newly allocated struct */
502
			*mru = _mru;
503
			/* append the struct pointer to the end of the list */
504
			*mru_ptr = mru;
505
			/* update the list head pointer */
506
507
508
509
510
511
512
			mru_ptr = &mru->smru_next;
		}
	}

	return( 0 );
}

513
514
515
516
517
518
519

#if defined( SLAPD_SCHEMA_DN )

int mr_schema_info( Entry *e )
{
	MatchingRule	*mr;

520
521
	AttributeDescription *ad_matchingRules = slap_schema.si_ad_matchingRules;

522
	for ( mr = mr_list; mr; mr = mr->smr_next ) {
523
524
525
526
527
		if ( mr->smr_usage & SLAP_MR_HIDE ) {
			/* skip hidden rules */
			continue;
		}

528
529
530
531
532
		if ( ! mr->smr_match ) {
			/* skip rules without matching functions */
			continue;
		}

533
534
535
536
		if ( mr->smr_str.bv_val == NULL ) {
			if ( ldap_matchingrule2bv( &mr->smr_mrule, &mr->smr_str ) == NULL ) {
				return -1;
			}
537
		}
538
#if 0
539
540
		Debug( LDAP_DEBUG_TRACE, "Merging mr [%lu] %s\n",
			mr->smr_str.bv_len, mr->smr_str.bv_val, 0 );
541
#endif
542
		attr_merge_one( e, ad_matchingRules, &mr->smr_str );
543
544
545
546
	}
	return 0;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
547
548
int mru_schema_info( Entry *e )
{
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
	MatchingRuleUse	*mru;

	AttributeDescription *ad_matchingRuleUse 
		= slap_schema.si_ad_matchingRuleUse;

	for ( mru = mru_list; mru; mru = mru->smru_next ) {

		assert( !( mru->smru_usage & SLAP_MR_HIDE ) );

		if ( mru->smru_str.bv_val == NULL ) {
			if ( ldap_matchingruleuse2bv( &mru->smru_mruleuse, &mru->smru_str )
					== NULL ) {
				return -1;
			}
		}

#if 0
		Debug( LDAP_DEBUG_TRACE, "Merging mru [%lu] %s\n",
			mru->smru_str.bv_len, mru->smru_str.bv_val, 0 );
#endif
		attr_merge_one( e, ad_matchingRuleUse, &mru->smru_str );
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
571
572
573
	return 0;
}

574
#endif