mr.c 10.7 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
    const char		**err
)
{
	MatchingRule	*smr;
	Syntax		*syn;
149
	Syntax		**compat_syn = NULL;
150
151
	int		code;

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
	if( def->mrd_compat_syntaxes ) {
		int i;
		for( i=0; def->mrd_compat_syntaxes[i]; i++ ) {
			/* just count em */
		}

		compat_syn = ch_malloc( sizeof(Syntax *) * (i+1) );

		for( i=0; def->mrd_compat_syntaxes[i]; i++ ) {
			compat_syn[i] = syn_find( def->mrd_compat_syntaxes[i] );
			if( compat_syn[i] == NULL ) {
				return SLAP_SCHERR_SYN_NOT_FOUND;
			}
		}

		compat_syn[i] = NULL;
	}

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

173
174
175
176
177
	/*
	 * 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;
178
	smr->smr_oidlen = strlen( mr->mr_oid );
179
	smr->smr_usage = def->mrd_usage;
180
	smr->smr_compat_syntaxes = compat_syn;
181
182
183
184
185
	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;
186
	smr->smr_associated = amr;
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204

	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(
205
	slap_mrule_defs_rec *def )
206
{
207
	LDAPMatchingRule *mr;
208
	MatchingRule *amr = NULL;
209
210
211
	int		code;
	const char	*err;

212
213
214
	if( def->mrd_usage == SLAP_MR_NONE &&
		def->mrd_compat_syntaxes == NULL )
	{
215
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
216
		LDAP_LOG( OPERATION, ERR, 
217
			"register_matching_rule: %s not usable\n", def->mrd_desc, 0, 0 );
218
#else
219
		Debug( LDAP_DEBUG_ANY, "register_matching_rule: not usable %s\n",
220
		    def->mrd_desc, 0, 0 );
221
222
#endif

223
224
225
		return -1;
	}

226
227
	if( def->mrd_associated != NULL ) {
		amr = mr_find( def->mrd_associated );
228

229
230
231
232
#if 0
		/* ignore for now */

		if( amr == NULL ) {
233
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
234
235
			LDAP_LOG( OPERATION, ERR,
			   "register_matching_rule: could not locate associated "
236
237
			   "matching rule %s for %s\n",
				def->mrd_associated, def->mrd_desc, 0 );
238
#else
239
240
			Debug( LDAP_DEBUG_ANY, "register_matching_rule: could not locate "
				"associated matching rule %s for %s\n",
241
				def->mrd_associated, def->mrd_desc, 0 );
242
243
#endif

244
245
246
			return -1;
		}
#endif
247
248
	}

249
250
	mr = ldap_str2matchingrule( def->mrd_desc, &code, &err,
		LDAP_SCHEMA_ALLOW_ALL );
251
	if ( !mr ) {
252
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
253
254
		LDAP_LOG( OPERATION, ERR, 
			"register_matching_rule: %s before %s in %s.\n",
255
			ldap_scherr2str(code), err, def->mrd_desc );
256
#else
257
258
		Debug( LDAP_DEBUG_ANY,
			"Error in register_matching_rule: %s before %s in %s\n",
259
		    ldap_scherr2str(code), err, def->mrd_desc );
260
261
#endif

262
263
264
		return( -1 );
	}

265
	code = mr_add( mr, def, amr, &err );
266

267
268
	ldap_memfree( mr );

269
	if ( code ) {
270
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
271
272
		LDAP_LOG( OPERATION, ERR, 
			"register_matching_rule: %s for %s in %s.\n",
273
			scherr2str(code), err, def->mrd_desc );
274
#else
275
276
		Debug( LDAP_DEBUG_ANY,
			"Error in register_matching_rule: %s for %s in %s\n",
277
		    scherr2str(code), err, def->mrd_desc );
278
279
#endif

280
281
		return( -1 );
	}
282

283
284
285
	return( 0 );
}

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
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;

#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 ) {
		AttributeType	*at;
		MatchingRuleUse	_mru, *mru = &_mru;

323
324
		char		**applies_oids = NULL;

325
326
327
328
329
330
331
		mr->smr_mru = NULL;

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

332
333
334
335
336
337
338
339
		/* hide rules not marked as designed for extensibility */
		/* MR_EXT means can be used any attribute type whose
		 * syntax is same as the assertion syntax.
		 * Another mechanism is needed where rule can be used
		 * with attribute of other syntaxes.
		 * Framework doesn't support this (yet).
		 */

340
341
342
		if (!( ( mr->smr_usage & SLAP_MR_EXT )
			|| mr->smr_compat_syntaxes ) )
		{
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
			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

370
371
		at = NULL;
		for ( at_start( &at ); at; at_next( &at ) ) {
372
			if( at->sat_flags & SLAP_AT_HIDE ) continue;
373

374
375
			if( mr_usable_with_at( mr, at )) {
				ldap_charray_add( &applies_oids, at->sat_cname.bv_val );
376
377
378
379
380
381
382
383
			}
		}

		/*
		 * Note: the matchingRules that are not used
		 * by any attributeType are not listed as
		 * matchingRuleUse
		 */
384
385
		if ( applies_oids != NULL ) {
			mru->smru_applies_oids = applies_oids;
386
387
#ifdef NEW_LOGGING
			{
388
				char *str = ldap_matchingruleuse2str( &mru->smru_mruleuse );
389
390
391
392
393
				LDAP_LOG( OPERATION, INFO, "matchingRuleUse: %s\n", str, 0, 0 );
				ldap_memfree( str );
			}
#else
			{
394
				char *str = ldap_matchingruleuse2str( &mru->smru_mruleuse );
395
396
397
398
399
				Debug( LDAP_DEBUG_TRACE, "matchingRuleUse: %s\n", str, 0, 0 );
				ldap_memfree( str );
			}
#endif

400
401
			mru = (MatchingRuleUse *)ber_memalloc( sizeof( MatchingRuleUse ) );
			/* call-forward from MatchingRule to MatchingRuleUse */
402
			mr->smr_mru = mru;
403
			/* copy static data to newly allocated struct */
404
			*mru = _mru;
405
			/* append the struct pointer to the end of the list */
406
			*mru_ptr = mru;
407
			/* update the list head pointer */
408
409
410
411
412
413
414
			mru_ptr = &mru->smru_next;
		}
	}

	return( 0 );
}

415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
int mr_usable_with_at(
	MatchingRule *mr,
	AttributeType *at )
{
	if( mr->smr_usage & SLAP_MR_EXT && ( 
		mr->smr_syntax == at->sat_syntax ||
		mr == at->sat_equality || mr == at->sat_approx ) )
	{
		return 1;
	}

	if ( mr->smr_compat_syntaxes ) {
		int i;
		for( i=0; mr->smr_compat_syntaxes[i]; i++ ) {
			if( at->sat_syntax == mr->smr_compat_syntaxes[i] ) {
				return 1;
			}
		}
	}
	return 0;
}
436
437
438
439
440

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

441
442
	AttributeDescription *ad_matchingRules = slap_schema.si_ad_matchingRules;

443
	for ( mr = mr_list; mr; mr = mr->smr_next ) {
444
445
446
447
448
		if ( mr->smr_usage & SLAP_MR_HIDE ) {
			/* skip hidden rules */
			continue;
		}

449
450
451
452
453
		if ( ! mr->smr_match ) {
			/* skip rules without matching functions */
			continue;
		}

454
455
456
457
		if ( mr->smr_str.bv_val == NULL ) {
			if ( ldap_matchingrule2bv( &mr->smr_mrule, &mr->smr_str ) == NULL ) {
				return -1;
			}
458
		}
459
#if 0
460
461
		Debug( LDAP_DEBUG_TRACE, "Merging mr [%lu] %s\n",
			mr->smr_str.bv_len, mr->smr_str.bv_val, 0 );
462
#endif
Julius Enarusai's avatar
   
Julius Enarusai committed
463
464
		if( attr_merge_one( e, ad_matchingRules, &mr->smr_str ) )
			return -1;
465
466
467
468
	}
	return 0;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
469
470
int mru_schema_info( Entry *e )
{
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
	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
Julius Enarusai's avatar
   
Julius Enarusai committed
491
492
		if( attr_merge_one( e, ad_matchingRuleUse, &mru->smru_str ) )
			return -1;
493
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
494
495
	return 0;
}