mr.c 13.5 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
 * 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"
18
#include "../../libraries/libldap/ldap-int.h"
19
20

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

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

static int
mr_index_cmp(
    struct mindexrec	*mir1,
    struct mindexrec	*mir2
)
{
Howard Chu's avatar
Howard Chu committed
35
36
37
	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 ));
38
39
40
41
}

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

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

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

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

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

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

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

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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
105
106
		mir->mir_name.bv_val = smr->smr_oid;
		mir->mir_name.bv_len = strlen( smr->smr_oid );
107
108
109
110
111
112
		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);
113
			return SLAP_SCHERR_MR_DUP;
114
115
		}
		/* FIX: temporal consistency check */
Howard Chu's avatar
Howard Chu committed
116
		mr_bvfind(&mir->mir_name);
117
118
119
120
121
	}
	if ( (names = smr->smr_names) ) {
		while ( *names ) {
			mir = (struct mindexrec *)
				ch_calloc( 1, sizeof(struct mindexrec) );
Howard Chu's avatar
Howard Chu committed
122
123
			mir->mir_name.bv_val = *names;
			mir->mir_name.bv_len = strlen( *names );
124
125
126
127
128
129
			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);
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
150
151
152
    const char		**err
)
{
	MatchingRule	*smr;
	Syntax		*syn;
	int		code;

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

155
156
157
158
159
	/*
	 * 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;
160
	smr->smr_oidlen = strlen( mr->mr_oid );
161
162
163
164
165
166
	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;
167
	smr->smr_associated = amr;
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185

	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(
186
	slap_mrule_defs_rec *def )
187
{
188
	LDAPMatchingRule *mr;
189
	MatchingRule *amr = NULL;
190
191
192
	int		code;
	const char	*err;

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

202
203
204
		return -1;
	}

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

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

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

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

	}

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

239
240
241
		return( -1 );
	}

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

244
245
	ldap_memfree( mr );

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

256
257
		return( -1 );
	}
258

259
260
261
	return( 0 );
}

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
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
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
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
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
429
430
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
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
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);
	}
}

/*
 * Appends a string to an array of char *,
 * and returns the newly allocated char **.
 * Maybe we can find a substitute, or borrow
 * a helper from somewhere else
 */
static char **
ch_append( char **array, char *value )
{
	int	cnt;
	char	**tmp;

	if ( array == NULL ) {
		cnt = 0;
	} else {
		for ( cnt = 0; array[ cnt ]; cnt++ )
			/* NO OP */ ;
	}

	tmp = LDAP_REALLOC( array, ( cnt + 2 ) * sizeof( char * ) );

	tmp[ cnt++ ] = ch_strdup( value );
	tmp[ cnt ] = NULL;

	return tmp;
}

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;

		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
						mru->smru_applies_oids
							= ch_append( mru->smru_applies_oids, at->sat_oid );
					}
				}

			} 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
						mru->smru_applies_oids
							= ch_append( mru->smru_applies_oids, at->sat_oid );
					}
				}
			}
			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
					mru->smru_applies_oids
						= ch_append( mru->smru_applies_oids, at->sat_oid );
				}
			}
			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
					mru->smru_applies_oids
						= ch_append( mru->smru_applies_oids, at->sat_oid );
				}
			}
			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
		 */
		if ( mru->smru_applies_oids != NULL ) {
#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

			mru = (MatchingRuleUse *)LDAP_MALLOC( sizeof( MatchingRuleUse ) );
			mr->smr_mru = mru;
			*mru = _mru;
			*mru_ptr = mru;
			mru_ptr = &mru->smru_next;
		}
	}

	return( 0 );
}

534
535
536
537
538
539
540

#if defined( SLAPD_SCHEMA_DN )

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

541
542
	AttributeDescription *ad_matchingRules = slap_schema.si_ad_matchingRules;

543
	for ( mr = mr_list; mr; mr = mr->smr_next ) {
544
545
546
547
548
		if ( mr->smr_usage & SLAP_MR_HIDE ) {
			/* skip hidden rules */
			continue;
		}

549
550
551
552
553
		if ( ! mr->smr_match ) {
			/* skip rules without matching functions */
			continue;
		}

554
555
556
557
		if ( mr->smr_str.bv_val == NULL ) {
			if ( ldap_matchingrule2bv( &mr->smr_mrule, &mr->smr_str ) == NULL ) {
				return -1;
			}
558
		}
559
#if 0
560
561
		Debug( LDAP_DEBUG_TRACE, "Merging mr [%lu] %s\n",
			mr->smr_str.bv_len, mr->smr_str.bv_val, 0 );
562
#endif
563
		attr_merge_one( e, ad_matchingRules, &mr->smr_str );
564
565
566
567
	}
	return 0;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
568
569
int mru_schema_info( Entry *e )
{
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
	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
592
593
594
	return 0;
}

595
#endif