mr.c 11.3 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
323
324
325
326
327
328
329
330
331
332
333
334
335
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;

336
337
		char		**applies_oids = NULL;

338
339
340
341
342
343
344
		mr->smr_mru = NULL;

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

345
346
347
348
349
350
351
352
		/* 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).
		 */

353
354
355
		if (!( ( mr->smr_usage & SLAP_MR_EXT )
			|| mr->smr_compat_syntaxes ) )
		{
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
			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

383
384
		at = NULL;
		for ( at_start( &at ); at; at_next( &at ) ) {
385
			if( at->sat_flags & SLAP_AT_HIDE ) continue;
386
387
			if( mr->smr_usage & SLAP_MR_EXT && ( 
				mr->smr_syntax == at->sat_syntax ||
388
				mr == at->sat_equality ||
389
				mr == at->sat_approx ) )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
390
			{
391
				ldap_charray_add( &applies_oids, at->sat_cname.bv_val );
392
393
394
395
396
397
398
399
400

			} else 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] ) {
						ldap_charray_add( &applies_oids, at->sat_cname.bv_val );
						break;
					}
				}
401
402
403
404
405
406
407
408
			}
		}

		/*
		 * Note: the matchingRules that are not used
		 * by any attributeType are not listed as
		 * matchingRuleUse
		 */
409
410
		if ( applies_oids != NULL ) {
			mru->smru_applies_oids = applies_oids;
411
412
#ifdef NEW_LOGGING
			{
413
				char *str = ldap_matchingruleuse2str( &mru->smru_mruleuse );
414
415
416
417
418
				LDAP_LOG( OPERATION, INFO, "matchingRuleUse: %s\n", str, 0, 0 );
				ldap_memfree( str );
			}
#else
			{
419
				char *str = ldap_matchingruleuse2str( &mru->smru_mruleuse );
420
421
422
423
424
				Debug( LDAP_DEBUG_TRACE, "matchingRuleUse: %s\n", str, 0, 0 );
				ldap_memfree( str );
			}
#endif

425
426
			mru = (MatchingRuleUse *)ber_memalloc( sizeof( MatchingRuleUse ) );
			/* call-forward from MatchingRule to MatchingRuleUse */
427
			mr->smr_mru = mru;
428
			/* copy static data to newly allocated struct */
429
			*mru = _mru;
430
			/* append the struct pointer to the end of the list */
431
			*mru_ptr = mru;
432
			/* update the list head pointer */
433
434
435
436
437
438
439
			mru_ptr = &mru->smru_next;
		}
	}

	return( 0 );
}

440
441
442
443
444
445
446

#if defined( SLAPD_SCHEMA_DN )

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

447
448
	AttributeDescription *ad_matchingRules = slap_schema.si_ad_matchingRules;

449
	for ( mr = mr_list; mr; mr = mr->smr_next ) {
450
451
452
453
454
		if ( mr->smr_usage & SLAP_MR_HIDE ) {
			/* skip hidden rules */
			continue;
		}

455
456
457
458
459
		if ( ! mr->smr_match ) {
			/* skip rules without matching functions */
			continue;
		}

460
461
462
463
		if ( mr->smr_str.bv_val == NULL ) {
			if ( ldap_matchingrule2bv( &mr->smr_mrule, &mr->smr_str ) == NULL ) {
				return -1;
			}
464
		}
465
#if 0
466
467
		Debug( LDAP_DEBUG_TRACE, "Merging mr [%lu] %s\n",
			mr->smr_str.bv_len, mr->smr_str.bv_val, 0 );
468
#endif
469
		attr_merge_one( e, ad_matchingRules, &mr->smr_str );
470
471
472
473
	}
	return 0;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
474
475
int mru_schema_info( Entry *e )
{
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
	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
498
499
500
	return 0;
}

501
#endif