mr.c 10.8 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-2003 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

static int
mr_index_cmp(
30
31
    const void	*v_mir1,
    const void	*v_mir2
32
33
)
{
34
35
	const struct mindexrec	*mir1 = v_mir1;
	const struct mindexrec	*mir2 = v_mir2;
Howard Chu's avatar
Howard Chu committed
36
37
38
	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 ));
39
40
41
42
}

static int
mr_index_name_cmp(
43
44
    const void	*v_name,
    const void	*v_mir
45
46
)
{
47
48
	const struct berval    *name = v_name;
	const struct mindexrec *mir  = v_mir;
Howard Chu's avatar
Howard Chu committed
49
50
51
	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 ));
52
53
54
55
}

MatchingRule *
mr_find( const char *mrname )
Howard Chu's avatar
Howard Chu committed
56
57
58
{
	struct berval bv;

Howard Chu's avatar
Howard Chu committed
59
	bv.bv_val = (char *)mrname;
Howard Chu's avatar
Howard Chu committed
60
61
62
63
64
65
	bv.bv_len = strlen( mrname );
	return mr_bvfind( &bv );
}

MatchingRule *
mr_bvfind( struct berval *mrname )
66
67
68
{
	struct mindexrec	*mir = NULL;

69
	if ( (mir = avl_find( mr_index, mrname, mr_index_name_cmp )) != NULL ) {
70
71
72
73
74
		return( mir->mir_mr );
	}
	return( NULL );
}

75
76
77
78
79
80
81
82
void
mr_destroy( void )
{
	MatchingRule *m, *n;

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

88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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
107
108
		mir->mir_name.bv_val = smr->smr_oid;
		mir->mir_name.bv_len = strlen( smr->smr_oid );
109
110
		mir->mir_mr = smr;
		if ( avl_insert( &mr_index, (caddr_t) mir,
111
		                 mr_index_cmp, avl_dup_error ) ) {
112
113
			*err = smr->smr_oid;
			ldap_memfree(mir);
114
			return SLAP_SCHERR_MR_DUP;
115
116
		}
		/* FIX: temporal consistency check */
Howard Chu's avatar
Howard Chu committed
117
		mr_bvfind(&mir->mir_name);
118
119
120
121
122
	}
	if ( (names = smr->smr_names) ) {
		while ( *names ) {
			mir = (struct mindexrec *)
				ch_calloc( 1, sizeof(struct mindexrec) );
Howard Chu's avatar
Howard Chu committed
123
124
			mir->mir_name.bv_val = *names;
			mir->mir_name.bv_len = strlen( *names );
125
126
			mir->mir_mr = smr;
			if ( avl_insert( &mr_index, (caddr_t) mir,
127
			                 mr_index_cmp, avl_dup_error ) ) {
128
129
				*err = *names;
				ldap_memfree(mir);
130
				return SLAP_SCHERR_MR_DUP;
131
132
			}
			/* FIX: temporal consistency check */
Howard Chu's avatar
Howard Chu committed
133
			mr_bvfind(&mir->mir_name);
134
135
136
137
138
139
140
141
			names++;
		}
	}
	return 0;
}

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

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
	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;
	}

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

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

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

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

224
225
226
		return -1;
	}

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

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

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

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

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

263
264
265
		return( -1 );
	}

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

268
269
	ldap_memfree( mr );

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

281
282
		return( -1 );
	}
283

284
285
286
	return( 0 );
}

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

324
325
		char		**applies_oids = NULL;

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

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

333
334
335
336
337
338
339
340
		/* 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).
		 */

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

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

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

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

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

	return( 0 );
}

416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
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;
}
437
438
439
440
441

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

442
443
	AttributeDescription *ad_matchingRules = slap_schema.si_ad_matchingRules;

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

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

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

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