mr.c 10.4 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
		mr->smr_mru = NULL;

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

320
321
322
323
324
325
326
327
328
		/* 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).
		 */

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

356
357
		at = NULL;
		for ( at_start( &at ); at; at_next( &at ) ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
358
			if( mr->smr_syntax == at->sat_syntax ||
359
360
				mr == at->sat_equality ||
				mr == at->sat_approx )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
361
			{
362
				ldap_charray_add( &applies_oids, at->sat_cname.bv_val );
363
364
365
366
367
368
369
370
			}
		}

		/*
		 * Note: the matchingRules that are not used
		 * by any attributeType are not listed as
		 * matchingRuleUse
		 */
371
372
		if ( applies_oids != NULL ) {
			mru->smru_applies_oids = applies_oids;
373
374
375
376
377
378
379
380
381
382
383
384
385
386
#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

387
388
			mru = (MatchingRuleUse *)ber_memalloc( sizeof( MatchingRuleUse ) );
			/* call-forward from MatchingRule to MatchingRuleUse */
389
			mr->smr_mru = mru;
390
			/* copy static data to newly allocated struct */
391
			*mru = _mru;
392
			/* append the struct pointer to the end of the list */
393
			*mru_ptr = mru;
394
			/* update the list head pointer */
395
396
397
398
399
400
401
			mru_ptr = &mru->smru_next;
		}
	}

	return( 0 );
}

402
403
404
405
406
407
408

#if defined( SLAPD_SCHEMA_DN )

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

409
410
	AttributeDescription *ad_matchingRules = slap_schema.si_ad_matchingRules;

411
	for ( mr = mr_list; mr; mr = mr->smr_next ) {
412
413
414
415
416
		if ( mr->smr_usage & SLAP_MR_HIDE ) {
			/* skip hidden rules */
			continue;
		}

417
418
419
420
421
		if ( ! mr->smr_match ) {
			/* skip rules without matching functions */
			continue;
		}

422
423
424
425
		if ( mr->smr_str.bv_val == NULL ) {
			if ( ldap_matchingrule2bv( &mr->smr_mrule, &mr->smr_str ) == NULL ) {
				return -1;
			}
426
		}
427
#if 0
428
429
		Debug( LDAP_DEBUG_TRACE, "Merging mr [%lu] %s\n",
			mr->smr_str.bv_len, mr->smr_str.bv_val, 0 );
430
#endif
431
		attr_merge_one( e, ad_matchingRules, &mr->smr_str );
432
433
434
435
	}
	return 0;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
436
437
int mru_schema_info( Entry *e )
{
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
	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
460
461
462
	return 0;
}

463
#endif