]> git.sur5r.net Git - openldap/blob - servers/slapd/mr.c
64d02b30581fd51d806e7289d3eaceafc7c67aae
[openldap] / servers / slapd / mr.c
1 /* mr.c - routines to manage matching rule definitions */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/ctype.h>
13 #include <ac/string.h>
14 #include <ac/socket.h>
15
16 #include "slap.h"
17 #include "ldap_pvt.h"
18
19 struct mindexrec {
20         struct berval   mir_name;
21         MatchingRule    *mir_mr;
22 };
23
24 static Avlnode  *mr_index = NULL;
25 static MatchingRule *mr_list = NULL;
26 static MatchingRuleUse *mru_list = NULL;
27
28 static int
29 mr_index_cmp(
30     struct mindexrec    *mir1,
31     struct mindexrec    *mir2
32 )
33 {
34         int i = mir1->mir_name.bv_len - mir2->mir_name.bv_len;
35         if (i) return i;
36         return (strcmp( mir1->mir_name.bv_val, mir2->mir_name.bv_val ));
37 }
38
39 static int
40 mr_index_name_cmp(
41     struct berval       *name,
42     struct mindexrec    *mir
43 )
44 {
45         int i = name->bv_len - mir->mir_name.bv_len;
46         if (i) return i;
47         return (strncmp( name->bv_val, mir->mir_name.bv_val, name->bv_len ));
48 }
49
50 MatchingRule *
51 mr_find( const char *mrname )
52 {
53         struct berval bv;
54
55         bv.bv_val = (char *)mrname;
56         bv.bv_len = strlen( mrname );
57         return mr_bvfind( &bv );
58 }
59
60 MatchingRule *
61 mr_bvfind( struct berval *mrname )
62 {
63         struct mindexrec        *mir = NULL;
64
65         if ( (mir = (struct mindexrec *) avl_find( mr_index, mrname,
66             (AVL_CMP) mr_index_name_cmp )) != NULL ) {
67                 return( mir->mir_mr );
68         }
69         return( NULL );
70 }
71
72 void
73 mr_destroy( void )
74 {
75         MatchingRule *m, *n;
76
77         avl_free(mr_index, ldap_memfree);
78         for (m=mr_list; m; m=n) {
79                 n = m->smr_next;
80                 ch_free( m->smr_str.bv_val );
81                 ldap_matchingrule_free((LDAPMatchingRule *)m);
82         }
83 }
84
85 static int
86 mr_insert(
87     MatchingRule        *smr,
88     const char          **err
89 )
90 {
91         MatchingRule            **mrp;
92         struct mindexrec        *mir;
93         char                    **names;
94
95         mrp = &mr_list;
96         while ( *mrp != NULL ) {
97                 mrp = &(*mrp)->smr_next;
98         }
99         *mrp = smr;
100
101         if ( smr->smr_oid ) {
102                 mir = (struct mindexrec *)
103                         ch_calloc( 1, sizeof(struct mindexrec) );
104                 mir->mir_name.bv_val = smr->smr_oid;
105                 mir->mir_name.bv_len = strlen( smr->smr_oid );
106                 mir->mir_mr = smr;
107                 if ( avl_insert( &mr_index, (caddr_t) mir,
108                                  (AVL_CMP) mr_index_cmp,
109                                  (AVL_DUP) avl_dup_error ) ) {
110                         *err = smr->smr_oid;
111                         ldap_memfree(mir);
112                         return SLAP_SCHERR_MR_DUP;
113                 }
114                 /* FIX: temporal consistency check */
115                 mr_bvfind(&mir->mir_name);
116         }
117         if ( (names = smr->smr_names) ) {
118                 while ( *names ) {
119                         mir = (struct mindexrec *)
120                                 ch_calloc( 1, sizeof(struct mindexrec) );
121                         mir->mir_name.bv_val = *names;
122                         mir->mir_name.bv_len = strlen( *names );
123                         mir->mir_mr = smr;
124                         if ( avl_insert( &mr_index, (caddr_t) mir,
125                                          (AVL_CMP) mr_index_cmp,
126                                          (AVL_DUP) avl_dup_error ) ) {
127                                 *err = *names;
128                                 ldap_memfree(mir);
129                                 return SLAP_SCHERR_MR_DUP;
130                         }
131                         /* FIX: temporal consistency check */
132                         mr_bvfind(&mir->mir_name);
133                         names++;
134                 }
135         }
136         return 0;
137 }
138
139 int
140 mr_add(
141     LDAPMatchingRule            *mr,
142     slap_mrule_defs_rec *def,
143         MatchingRule    *amr,
144     const char          **err
145 )
146 {
147         MatchingRule    *smr;
148         Syntax          *syn;
149         Syntax          **compat_syn = NULL;
150         int             code;
151
152         if( def->mrd_compat_syntaxes ) {
153                 int i;
154                 for( i=0; def->mrd_compat_syntaxes[i]; i++ ) {
155                         /* just count em */
156                 }
157
158                 compat_syn = ch_malloc( sizeof(Syntax *) * (i+1) );
159
160                 for( i=0; def->mrd_compat_syntaxes[i]; i++ ) {
161                         compat_syn[i] = syn_find( def->mrd_compat_syntaxes[i] );
162                         if( compat_syn[i] == NULL ) {
163                                 return SLAP_SCHERR_SYN_NOT_FOUND;
164                         }
165                 }
166
167                 compat_syn[i] = NULL;
168         }
169
170         smr = (MatchingRule *) ch_calloc( 1, sizeof(MatchingRule) );
171         AC_MEMCPY( &smr->smr_mrule, mr, sizeof(LDAPMatchingRule));
172
173         /*
174          * note: smr_bvoid uses the same memory of smr_mrule.mr_oid;
175          * smr_oidlen is #defined as smr_bvoid.bv_len
176          */
177         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         smr->smr_convert = def->mrd_convert;
182         smr->smr_normalize = def->mrd_normalize;
183         smr->smr_match = def->mrd_match;
184         smr->smr_indexer = def->mrd_indexer;
185         smr->smr_filter = def->mrd_filter;
186         smr->smr_associated = amr;
187
188         if ( smr->smr_syntax_oid ) {
189                 if ( (syn = syn_find(smr->smr_syntax_oid)) ) {
190                         smr->smr_syntax = syn;
191                 } else {
192                         *err = smr->smr_syntax_oid;
193                         return SLAP_SCHERR_SYN_NOT_FOUND;
194                 }
195         } else {
196                 *err = "";
197                 return SLAP_SCHERR_MR_INCOMPLETE;
198         }
199         code = mr_insert(smr,err);
200         return code;
201 }
202
203 int
204 register_matching_rule(
205         slap_mrule_defs_rec *def )
206 {
207         LDAPMatchingRule *mr;
208         MatchingRule *amr = NULL;
209         int             code;
210         const char      *err;
211
212         if( def->mrd_usage == SLAP_MR_NONE &&
213                 def->mrd_compat_syntaxes == NULL )
214         {
215 #ifdef NEW_LOGGING
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 #endif
222
223                 return -1;
224         }
225
226         if( def->mrd_associated != NULL ) {
227                 amr = mr_find( def->mrd_associated );
228
229 #if 0
230                 /* ignore for now */
231
232                 if( amr == NULL ) {
233 #ifdef NEW_LOGGING
234                         LDAP_LOG( OPERATION, ERR,
235                            "register_matching_rule: could not locate associated "
236                            "matching rule %s for %s\n",
237                                 def->mrd_associated, def->mrd_desc, 0 );
238 #else
239                         Debug( LDAP_DEBUG_ANY, "register_matching_rule: could not locate "
240                                 "associated matching rule %s for %s\n",
241                                 def->mrd_associated, def->mrd_desc, 0 );
242 #endif
243
244                         return -1;
245                 }
246 #endif
247         }
248
249         mr = ldap_str2matchingrule( def->mrd_desc, &code, &err,
250                 LDAP_SCHEMA_ALLOW_ALL );
251         if ( !mr ) {
252 #ifdef NEW_LOGGING
253                 LDAP_LOG( OPERATION, ERR, 
254                         "register_matching_rule: %s before %s in %s.\n",
255                         ldap_scherr2str(code), err, def->mrd_desc );
256 #else
257                 Debug( LDAP_DEBUG_ANY,
258                         "Error in register_matching_rule: %s before %s in %s\n",
259                     ldap_scherr2str(code), err, def->mrd_desc );
260 #endif
261
262                 return( -1 );
263         }
264
265         code = mr_add( mr, def, amr, &err );
266
267         ldap_memfree( mr );
268
269         if ( code ) {
270 #ifdef NEW_LOGGING
271                 LDAP_LOG( OPERATION, ERR, 
272                         "register_matching_rule: %s for %s in %s.\n",
273                         scherr2str(code), err, def->mrd_desc );
274 #else
275                 Debug( LDAP_DEBUG_ANY,
276                         "Error in register_matching_rule: %s for %s in %s\n",
277                     scherr2str(code), err, def->mrd_desc );
278 #endif
279
280                 return( -1 );
281         }
282
283         return( 0 );
284 }
285
286 void
287 mru_destroy( void )
288 {
289         MatchingRuleUse *m, *n;
290
291         for (m=mru_list; m; m=n) {
292                 n = m->smru_next;
293                 if ( m->smru_str.bv_val ) {
294                         ch_free( m->smru_str.bv_val );
295                 }
296                 /* memory borrowed from m->smru_mr */
297                 m->smru_oid = NULL;
298                 m->smru_names = NULL;
299                 m->smru_desc = NULL;
300
301                 /* free what's left (basically 
302                  * smru_mruleuse.mru_applies_oids) */
303                 ldap_matchingruleuse_free((LDAPMatchingRuleUse *)m);
304         }
305 }
306
307 int
308 matching_rule_use_init( void )
309 {
310         MatchingRule    *mr;
311         MatchingRuleUse **mru_ptr = &mru_list;
312
313 #define MR_TYPE_MASK            ( SLAP_MR_TYPE_MASK & ~SLAP_MR_EXT )
314 #define MR_TYPE_SUBTYPE_MASK    ( MR_TYPE_MASK | SLAP_MR_SUBTYPE_MASK ) 
315 #if 0   /* all types regardless of EXT */
316 #define MR_TYPE(x)              ( (x) & MR_TYPE_MASK )
317 #define MR_TYPE_SUBTYPE(x)      ( (x) & MR_TYPE_SUBTYPE_MASK )
318 #else   /* only those marked as EXT (as per RFC 2252) */
319 #define MR_TYPE(x)              ( ( (x) & SLAP_MR_EXT ) ? ( (x) & MR_TYPE_MASK ) : SLAP_MR_NONE )
320 #define MR_TYPE_SUBTYPE(x)      ( ( (x) & SLAP_MR_EXT ) ? ( (x) & MR_TYPE_SUBTYPE_MASK ) : SLAP_MR_NONE )
321 #endif
322
323 #ifdef NEW_LOGGING
324         LDAP_LOG( OPERATION, INFO, "matching_rule_use_init\n", 0, 0, 0 );
325 #else
326         Debug( LDAP_DEBUG_TRACE, "matching_rule_use_init\n", 0, 0, 0 );
327 #endif
328
329         for ( mr = mr_list; mr; mr = mr->smr_next ) {
330                 slap_mask_t     um = MR_TYPE( mr->smr_usage );
331                 slap_mask_t     usm = MR_TYPE_SUBTYPE( mr->smr_usage );
332
333                 AttributeType   *at;
334                 MatchingRuleUse _mru, *mru = &_mru;
335
336                 char            **applies_oids = NULL;
337
338                 mr->smr_mru = NULL;
339
340                 /* hide rules marked as HIDE */
341                 if ( mr->smr_usage & SLAP_MR_HIDE ) {
342                         continue;
343                 }
344
345                 /* hide rules not marked as designed for extensibility */
346                 /* MR_EXT means can be used any attribute type whose
347                  * syntax is same as the assertion syntax.
348                  * Another mechanism is needed where rule can be used
349                  * with attribute of other syntaxes.
350                  * Framework doesn't support this (yet).
351                  */
352
353                 if (!( ( mr->smr_usage & SLAP_MR_EXT )
354                         || mr->smr_compat_syntaxes ) )
355                 {
356                         continue;
357                 }
358
359                 memset( mru, 0, sizeof( MatchingRuleUse ) );
360
361                 /*
362                  * Note: we're using the same values of the corresponding 
363                  * MatchingRule structure; maybe we'd copy them ...
364                  */
365                 mru->smru_mr = mr;
366                 mru->smru_obsolete = mr->smr_obsolete;
367                 mru->smru_applies_oids = NULL;
368                 mru->smru_next = NULL;
369                 mru->smru_oid = mr->smr_oid;
370                 mru->smru_names = mr->smr_names;
371                 mru->smru_desc = mr->smr_desc;
372
373 #ifdef NEW_LOGGING
374                 LDAP_LOG( OPERATION, INFO, "    %s (%s): ", 
375                                 mru->smru_oid, 
376                                 mru->smru_names ? mru->smru_names[ 0 ] : "", 0 );
377 #else
378                 Debug( LDAP_DEBUG_TRACE, "    %s (%s): ", 
379                                 mru->smru_oid, 
380                                 mru->smru_names ? mru->smru_names[ 0 ] : "", 0 );
381 #endif
382
383                 at = NULL;
384                 for ( at_start( &at ); at; at_next( &at ) ) {
385                         if( at->sat_flags & SLAP_AT_HIDE ) continue;
386
387                         if( mr_usable_with_at( mr, at )) {
388                                 ldap_charray_add( &applies_oids, at->sat_cname.bv_val );
389                         }
390                 }
391
392                 /*
393                  * Note: the matchingRules that are not used
394                  * by any attributeType are not listed as
395                  * matchingRuleUse
396                  */
397                 if ( applies_oids != NULL ) {
398                         mru->smru_applies_oids = applies_oids;
399 #ifdef NEW_LOGGING
400                         {
401                                 char *str = ldap_matchingruleuse2str( &mru->smru_mruleuse );
402                                 LDAP_LOG( OPERATION, INFO, "matchingRuleUse: %s\n", str, 0, 0 );
403                                 ldap_memfree( str );
404                         }
405 #else
406                         {
407                                 char *str = ldap_matchingruleuse2str( &mru->smru_mruleuse );
408                                 Debug( LDAP_DEBUG_TRACE, "matchingRuleUse: %s\n", str, 0, 0 );
409                                 ldap_memfree( str );
410                         }
411 #endif
412
413                         mru = (MatchingRuleUse *)ber_memalloc( sizeof( MatchingRuleUse ) );
414                         /* call-forward from MatchingRule to MatchingRuleUse */
415                         mr->smr_mru = mru;
416                         /* copy static data to newly allocated struct */
417                         *mru = _mru;
418                         /* append the struct pointer to the end of the list */
419                         *mru_ptr = mru;
420                         /* update the list head pointer */
421                         mru_ptr = &mru->smru_next;
422                 }
423         }
424
425         return( 0 );
426 }
427
428 int mr_usable_with_at(
429         MatchingRule *mr,
430         AttributeType *at )
431 {
432         if( mr->smr_usage & SLAP_MR_EXT && ( 
433                 mr->smr_syntax == at->sat_syntax ||
434                 mr == at->sat_equality || mr == at->sat_approx ) )
435         {
436                 return 1;
437         }
438
439         if ( mr->smr_compat_syntaxes ) {
440                 int i;
441                 for( i=0; mr->smr_compat_syntaxes[i]; i++ ) {
442                         if( at->sat_syntax == mr->smr_compat_syntaxes[i] ) {
443                                 return 1;
444                         }
445                 }
446         }
447         return 0;
448 }
449
450 int mr_schema_info( Entry *e )
451 {
452         MatchingRule    *mr;
453
454         AttributeDescription *ad_matchingRules = slap_schema.si_ad_matchingRules;
455
456         for ( mr = mr_list; mr; mr = mr->smr_next ) {
457                 if ( mr->smr_usage & SLAP_MR_HIDE ) {
458                         /* skip hidden rules */
459                         continue;
460                 }
461
462                 if ( ! mr->smr_match ) {
463                         /* skip rules without matching functions */
464                         continue;
465                 }
466
467                 if ( mr->smr_str.bv_val == NULL ) {
468                         if ( ldap_matchingrule2bv( &mr->smr_mrule, &mr->smr_str ) == NULL ) {
469                                 return -1;
470                         }
471                 }
472 #if 0
473                 Debug( LDAP_DEBUG_TRACE, "Merging mr [%lu] %s\n",
474                         mr->smr_str.bv_len, mr->smr_str.bv_val, 0 );
475 #endif
476                 if( attr_merge_one( e, ad_matchingRules, &mr->smr_str ) )
477                         return -1;
478         }
479         return 0;
480 }
481
482 int mru_schema_info( Entry *e )
483 {
484         MatchingRuleUse *mru;
485
486         AttributeDescription *ad_matchingRuleUse 
487                 = slap_schema.si_ad_matchingRuleUse;
488
489         for ( mru = mru_list; mru; mru = mru->smru_next ) {
490
491                 assert( !( mru->smru_usage & SLAP_MR_HIDE ) );
492
493                 if ( mru->smru_str.bv_val == NULL ) {
494                         if ( ldap_matchingruleuse2bv( &mru->smru_mruleuse, &mru->smru_str )
495                                         == NULL ) {
496                                 return -1;
497                         }
498                 }
499
500 #if 0
501                 Debug( LDAP_DEBUG_TRACE, "Merging mru [%lu] %s\n",
502                         mru->smru_str.bv_len, mru->smru_str.bv_val, 0 );
503 #endif
504                 if( attr_merge_one( e, ad_matchingRuleUse, &mru->smru_str ) )
505                         return -1;
506         }
507         return 0;
508 }