]> git.sur5r.net Git - openldap/blob - servers/slapd/mr.c
605dbe8f84a6969619586bc7b29c9597489889ec
[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         int             code;
150
151         smr = (MatchingRule *) ch_calloc( 1, sizeof(MatchingRule) );
152         AC_MEMCPY( &smr->smr_mrule, mr, sizeof(LDAPMatchingRule));
153
154         /*
155          * note: smr_bvoid uses the same memory of smr_mrule.mr_oid;
156          * smr_oidlen is #defined as smr_bvoid.bv_len
157          */
158         smr->smr_bvoid.bv_val = smr->smr_mrule.mr_oid;
159         smr->smr_oidlen = strlen( mr->mr_oid );
160         smr->smr_usage = def->mrd_usage;
161         smr->smr_convert = def->mrd_convert;
162         smr->smr_normalize = def->mrd_normalize;
163         smr->smr_match = def->mrd_match;
164         smr->smr_indexer = def->mrd_indexer;
165         smr->smr_filter = def->mrd_filter;
166         smr->smr_associated = amr;
167
168         if ( smr->smr_syntax_oid ) {
169                 if ( (syn = syn_find(smr->smr_syntax_oid)) ) {
170                         smr->smr_syntax = syn;
171                 } else {
172                         *err = smr->smr_syntax_oid;
173                         return SLAP_SCHERR_SYN_NOT_FOUND;
174                 }
175         } else {
176                 *err = "";
177                 return SLAP_SCHERR_MR_INCOMPLETE;
178         }
179         code = mr_insert(smr,err);
180         return code;
181 }
182
183 int
184 register_matching_rule(
185         slap_mrule_defs_rec *def )
186 {
187         LDAPMatchingRule *mr;
188         MatchingRule *amr = NULL;
189         int             code;
190         const char      *err;
191
192         if( def->mrd_usage == SLAP_MR_NONE ) {
193 #ifdef NEW_LOGGING
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 #endif
200
201                 return -1;
202         }
203
204         if( def->mrd_associated != NULL ) {
205                 amr = mr_find( def->mrd_associated );
206
207 #if 0
208                 /* ignore for now */
209
210                 if( amr == NULL ) {
211 #ifdef NEW_LOGGING
212                         LDAP_LOG( OPERATION, ERR,
213                            "register_matching_rule: could not locate associated "
214                            "matching rule %s for %s\n",  def->mrd_associated, def->mrd_desc, 0 );
215 #else
216                         Debug( LDAP_DEBUG_ANY, "register_matching_rule: could not locate "
217                                 "associated matching rule %s for %s\n",
218                                 def->mrd_associated, def->mrd_desc, 0 );
219 #endif
220
221                         return -1;
222                 }
223 #endif
224
225         }
226
227         mr = ldap_str2matchingrule( def->mrd_desc, &code, &err, LDAP_SCHEMA_ALLOW_ALL);
228         if ( !mr ) {
229 #ifdef NEW_LOGGING
230                 LDAP_LOG( OPERATION, ERR, 
231                         "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 #endif
237
238                 return( -1 );
239         }
240
241         code = mr_add( mr, def, amr, &err );
242
243         ldap_memfree( mr );
244
245         if ( code ) {
246 #ifdef NEW_LOGGING
247                 LDAP_LOG( OPERATION, ERR, 
248                         "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 #endif
254
255                 return( -1 );
256         }
257
258         return( 0 );
259 }
260
261 void
262 mru_destroy( void )
263 {
264         MatchingRuleUse *m, *n;
265
266         for (m=mru_list; m; m=n) {
267                 n = m->smru_next;
268                 if ( m->smru_str.bv_val ) {
269                         ch_free( m->smru_str.bv_val );
270                 }
271                 /* memory borrowed from m->smru_mr */
272                 m->smru_oid = NULL;
273                 m->smru_names = NULL;
274                 m->smru_desc = NULL;
275
276                 /* free what's left (basically 
277                  * smru_mruleuse.mru_applies_oids) */
278                 ldap_matchingruleuse_free((LDAPMatchingRuleUse *)m);
279         }
280 }
281
282 int
283 matching_rule_use_init( void )
284 {
285         MatchingRule    *mr;
286         MatchingRuleUse **mru_ptr = &mru_list;
287
288 #define MR_TYPE_MASK            ( SLAP_MR_TYPE_MASK & ~SLAP_MR_EXT )
289 #define MR_TYPE_SUBTYPE_MASK    ( MR_TYPE_MASK | SLAP_MR_SUBTYPE_MASK ) 
290 #if 0   /* all types regardless of EXT */
291 #define MR_TYPE(x)              ( (x) & MR_TYPE_MASK )
292 #define MR_TYPE_SUBTYPE(x)      ( (x) & MR_TYPE_SUBTYPE_MASK )
293 #else   /* only those marked as EXT (as per RFC 2252) */
294 #define MR_TYPE(x)              ( ( (x) & SLAP_MR_EXT ) ? ( (x) & MR_TYPE_MASK ) : SLAP_MR_NONE )
295 #define MR_TYPE_SUBTYPE(x)      ( ( (x) & SLAP_MR_EXT ) ? ( (x) & MR_TYPE_SUBTYPE_MASK ) : SLAP_MR_NONE )
296 #endif
297
298 #ifdef NEW_LOGGING
299         LDAP_LOG( OPERATION, INFO, "matching_rule_use_init\n", 0, 0, 0 );
300 #else
301         Debug( LDAP_DEBUG_TRACE, "matching_rule_use_init\n", 0, 0, 0 );
302 #endif
303
304         for ( mr = mr_list; mr; mr = mr->smr_next ) {
305                 slap_mask_t     um = MR_TYPE( mr->smr_usage );
306                 slap_mask_t     usm = MR_TYPE_SUBTYPE( mr->smr_usage );
307
308                 AttributeType   *at;
309                 MatchingRuleUse _mru, *mru = &_mru;
310
311                 char            **applies_oids = NULL;
312
313                 mr->smr_mru = NULL;
314
315                 /* hide rules marked as HIDE */
316                 if ( mr->smr_usage & SLAP_MR_HIDE ) {
317                         continue;
318                 }
319
320                 /* hide rules with no type */
321                 if ( um == SLAP_MR_NONE ) {
322                         continue;
323                 }
324
325                 memset( mru, 0, sizeof( MatchingRuleUse ) );
326
327                 /*
328                  * Note: we're using the same values of the corresponding 
329                  * MatchingRule structure; maybe we'd copy them ...
330                  */
331                 mru->smru_mr = mr;
332                 mru->smru_obsolete = mr->smr_obsolete;
333                 mru->smru_applies_oids = NULL;
334                 mru->smru_next = NULL;
335                 mru->smru_oid = mr->smr_oid;
336                 mru->smru_names = mr->smr_names;
337                 mru->smru_desc = mr->smr_desc;
338
339 #ifdef NEW_LOGGING
340                 LDAP_LOG( OPERATION, INFO, "    %s (%s): ", 
341                                 mru->smru_oid, 
342                                 mru->smru_names ? mru->smru_names[ 0 ] : "", 0 );
343 #else
344                 Debug( LDAP_DEBUG_TRACE, "    %s (%s): ", 
345                                 mru->smru_oid, 
346                                 mru->smru_names ? mru->smru_names[ 0 ] : "", 0 );
347 #endif
348
349                 switch ( um ) {
350                 case SLAP_MR_EQUALITY:
351                         at = NULL;
352                         if ( usm == SLAP_MR_EQUALITY_APPROX ) {
353 #ifdef NEW_LOGGING
354                                 LDAP_LOG( OPERATION, INFO, "APPROX%s\n",
355                                                 ( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
356                                                 0, 0 );
357 #else
358                                 Debug( LDAP_DEBUG_TRACE, "APPROX%s\n",
359                                                 ( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
360                                                 0, 0 );
361 #endif
362
363                                 for ( at_start( &at ); at; at_next( &at ) ) {
364                                         if ( mr == at->sat_approx ) {
365 #ifdef NEW_LOGGING
366                                                 LDAP_LOG( OPERATION, INFO, "        %s (%s)\n",
367                                                                 at->sat_oid,
368                                                                 at->sat_cname.bv_val, 0 );
369 #else
370                                                 Debug( LDAP_DEBUG_TRACE, "        %s (%s)\n",
371                                                                 at->sat_oid,
372                                                                 at->sat_cname.bv_val, 0 );
373 #endif
374                                                 ldap_charray_add( &applies_oids,
375                                                                 at->sat_oid );
376                                         }
377                                 }
378
379                         } else {
380 #ifdef NEW_LOGGING
381                                 LDAP_LOG( OPERATION, INFO, "EQUALITY%s\n",
382                                                 ( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
383                                                 0, 0 );
384 #else
385                                 Debug( LDAP_DEBUG_TRACE, "EQUALITY%s\n",
386                                                 ( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
387                                                 0, 0 );
388 #endif
389                                 for ( at_start( &at ); at; at_next( &at ) ) {
390                                         if ( mr == at->sat_equality ) {
391 #ifdef NEW_LOGGING
392                                                 LDAP_LOG( OPERATION, INFO, "        %s (%s)\n",
393                                                                 at->sat_oid,
394                                                                 at->sat_cname.bv_val, 0 );
395 #else
396                                                 Debug( LDAP_DEBUG_TRACE, "        %s (%s)\n",
397                                                                 at->sat_oid,
398                                                                 at->sat_cname.bv_val, 0 );
399 #endif
400                                                 ldap_charray_add( &applies_oids,
401                                                                 at->sat_oid );
402                                         }
403                                 }
404                         }
405                         break;
406
407                 case SLAP_MR_ORDERING:
408 #ifdef NEW_LOGGING
409                         LDAP_LOG( OPERATION, INFO, "ORDERING%s\n",
410                                         ( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
411                                         0, 0 );
412 #else
413                         Debug( LDAP_DEBUG_TRACE, "ORDERING%s\n",
414                                         ( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
415                                         0, 0 );
416 #endif
417                         at = NULL;
418                         for ( at_start( &at ); at; at_next( &at ) ) {
419                                 if ( mr == at->sat_ordering ) {
420 #ifdef NEW_LOGGING
421                                         LDAP_LOG( OPERATION, INFO, "        %s (%s)\n",
422                                                         at->sat_oid,
423                                                         at->sat_cname.bv_val, 0 );
424 #else
425                                         Debug( LDAP_DEBUG_TRACE, "        %s (%s)\n",
426                                                         at->sat_oid,
427                                                         at->sat_cname.bv_val, 0 );
428 #endif
429                                         ldap_charray_add( &applies_oids,
430                                                         at->sat_oid );
431                                 }
432                         }
433                         break;
434
435                 case SLAP_MR_SUBSTR:
436 #ifdef NEW_LOGGING
437                         LDAP_LOG( OPERATION, INFO, "SUBSTR%s\n",
438                                         ( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
439                                         0, 0 );
440 #else
441                         Debug( LDAP_DEBUG_TRACE, "SUBSTR%s\n",
442                                         ( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
443                                         0, 0 );
444 #endif
445                         at = NULL;
446                         for ( at_start( &at ); at; at_next( &at ) ) {
447                                 if ( mr == at->sat_substr ) {
448 #ifdef NEW_LOGGING
449                                         LDAP_LOG( OPERATION, INFO, "        %s (%s)\n",
450                                                         at->sat_oid,
451                                                         at->sat_cname.bv_val, 0 );
452 #else
453                                         Debug( LDAP_DEBUG_TRACE, "        %s (%s)\n",
454                                                         at->sat_oid,
455                                                         at->sat_cname.bv_val, 0 );
456 #endif
457                                         ldap_charray_add( &applies_oids,
458                                                         at->sat_oid );
459                                 }
460                         }
461                         break;
462
463                 default:
464 #ifdef NEW_LOGGING
465                         LDAP_LOG( OPERATION, ERR, "        unknown matching rule type "
466                                         "(type mask %d, subtype mask %d%s)\n", um, usm,
467                                         ( mr->smr_usage & SLAP_MR_EXT ) ? ", EXT" : "" );
468 #else
469                         Debug( LDAP_DEBUG_ANY, "        unknown matching rule type "
470                                         "(type mask %d, subtype mask %d%s)\n", um, usm,
471                                         ( mr->smr_usage & SLAP_MR_EXT ) ? ", EXT" : "" );
472 #endif
473                         fprintf ( stderr, "    %d (%d)\n", um, usm );
474                         assert( 0 );
475                 }
476
477                 /*
478                  * Note: the matchingRules that are not used
479                  * by any attributeType are not listed as
480                  * matchingRuleUse
481                  */
482                 if ( applies_oids != NULL ) {
483                         mru->smru_applies_oids = applies_oids;
484 #ifdef NEW_LOGGING
485                         {
486                                 char    *str = ldap_matchingruleuse2str( &mru->smru_mruleuse );
487                                 LDAP_LOG( OPERATION, INFO, "matchingRuleUse: %s\n", str, 0, 0 );
488                                 ldap_memfree( str );
489                         }
490 #else
491                         {
492                                 char    *str = ldap_matchingruleuse2str( &mru->smru_mruleuse );
493                                 Debug( LDAP_DEBUG_TRACE, "matchingRuleUse: %s\n", str, 0, 0 );
494                                 ldap_memfree( str );
495                         }
496 #endif
497
498                         mru = (MatchingRuleUse *)ber_memalloc( sizeof( MatchingRuleUse ) );
499                         /* call-forward from MatchingRule to MatchingRuleUse */
500                         mr->smr_mru = mru;
501                         /* copy static data to newly allocated struct */
502                         *mru = _mru;
503                         /* append the struct pointer to the end of the list */
504                         *mru_ptr = mru;
505                         /* update the list head pointer */
506                         mru_ptr = &mru->smru_next;
507                 }
508         }
509
510         return( 0 );
511 }
512
513
514 #if defined( SLAPD_SCHEMA_DN )
515
516 int mr_schema_info( Entry *e )
517 {
518         MatchingRule    *mr;
519
520         AttributeDescription *ad_matchingRules = slap_schema.si_ad_matchingRules;
521
522         for ( mr = mr_list; mr; mr = mr->smr_next ) {
523                 if ( mr->smr_usage & SLAP_MR_HIDE ) {
524                         /* skip hidden rules */
525                         continue;
526                 }
527
528                 if ( ! mr->smr_match ) {
529                         /* skip rules without matching functions */
530                         continue;
531                 }
532
533                 if ( mr->smr_str.bv_val == NULL ) {
534                         if ( ldap_matchingrule2bv( &mr->smr_mrule, &mr->smr_str ) == NULL ) {
535                                 return -1;
536                         }
537                 }
538 #if 0
539                 Debug( LDAP_DEBUG_TRACE, "Merging mr [%lu] %s\n",
540                         mr->smr_str.bv_len, mr->smr_str.bv_val, 0 );
541 #endif
542                 attr_merge_one( e, ad_matchingRules, &mr->smr_str );
543         }
544         return 0;
545 }
546
547 int mru_schema_info( Entry *e )
548 {
549         MatchingRuleUse *mru;
550
551         AttributeDescription *ad_matchingRuleUse 
552                 = slap_schema.si_ad_matchingRuleUse;
553
554         for ( mru = mru_list; mru; mru = mru->smru_next ) {
555
556                 assert( !( mru->smru_usage & SLAP_MR_HIDE ) );
557
558                 if ( mru->smru_str.bv_val == NULL ) {
559                         if ( ldap_matchingruleuse2bv( &mru->smru_mruleuse, &mru->smru_str )
560                                         == NULL ) {
561                                 return -1;
562                         }
563                 }
564
565 #if 0
566                 Debug( LDAP_DEBUG_TRACE, "Merging mru [%lu] %s\n",
567                         mru->smru_str.bv_len, mru->smru_str.bv_val, 0 );
568 #endif
569                 attr_merge_one( e, ad_matchingRuleUse, &mru->smru_str );
570         }
571         return 0;
572 }
573
574 #endif