]> git.sur5r.net Git - openldap/blob - servers/slapd/mr.c
46d4c54f49da0bcf80e97ed65598d6e855cd6b36
[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 #include "../../libraries/libldap/ldap-int.h"
19
20 struct mindexrec {
21         struct berval   mir_name;
22         MatchingRule    *mir_mr;
23 };
24
25 static Avlnode  *mr_index = NULL;
26 static MatchingRule *mr_list = NULL;
27 static MatchingRuleUse *mru_list = NULL;
28
29 static int
30 mr_index_cmp(
31     struct mindexrec    *mir1,
32     struct mindexrec    *mir2
33 )
34 {
35         int i = mir1->mir_name.bv_len - mir2->mir_name.bv_len;
36         if (i) return i;
37         return (strcmp( mir1->mir_name.bv_val, mir2->mir_name.bv_val ));
38 }
39
40 static int
41 mr_index_name_cmp(
42     struct berval       *name,
43     struct mindexrec    *mir
44 )
45 {
46         int i = name->bv_len - mir->mir_name.bv_len;
47         if (i) return i;
48         return (strncmp( name->bv_val, mir->mir_name.bv_val, name->bv_len ));
49 }
50
51 MatchingRule *
52 mr_find( const char *mrname )
53 {
54         struct berval bv;
55
56         bv.bv_val = (char *)mrname;
57         bv.bv_len = strlen( mrname );
58         return mr_bvfind( &bv );
59 }
60
61 MatchingRule *
62 mr_bvfind( struct berval *mrname )
63 {
64         struct mindexrec        *mir = NULL;
65
66         if ( (mir = (struct mindexrec *) avl_find( mr_index, mrname,
67             (AVL_CMP) mr_index_name_cmp )) != NULL ) {
68                 return( mir->mir_mr );
69         }
70         return( NULL );
71 }
72
73 void
74 mr_destroy( void )
75 {
76         MatchingRule *m, *n;
77
78         avl_free(mr_index, ldap_memfree);
79         for (m=mr_list; m; m=n) {
80                 n = m->smr_next;
81                 ch_free( m->smr_str.bv_val );
82                 ldap_matchingrule_free((LDAPMatchingRule *)m);
83         }
84 }
85
86 static int
87 mr_insert(
88     MatchingRule        *smr,
89     const char          **err
90 )
91 {
92         MatchingRule            **mrp;
93         struct mindexrec        *mir;
94         char                    **names;
95
96         mrp = &mr_list;
97         while ( *mrp != NULL ) {
98                 mrp = &(*mrp)->smr_next;
99         }
100         *mrp = smr;
101
102         if ( smr->smr_oid ) {
103                 mir = (struct mindexrec *)
104                         ch_calloc( 1, sizeof(struct mindexrec) );
105                 mir->mir_name.bv_val = smr->smr_oid;
106                 mir->mir_name.bv_len = strlen( smr->smr_oid );
107                 mir->mir_mr = smr;
108                 if ( avl_insert( &mr_index, (caddr_t) mir,
109                                  (AVL_CMP) mr_index_cmp,
110                                  (AVL_DUP) avl_dup_error ) ) {
111                         *err = smr->smr_oid;
112                         ldap_memfree(mir);
113                         return SLAP_SCHERR_MR_DUP;
114                 }
115                 /* FIX: temporal consistency check */
116                 mr_bvfind(&mir->mir_name);
117         }
118         if ( (names = smr->smr_names) ) {
119                 while ( *names ) {
120                         mir = (struct mindexrec *)
121                                 ch_calloc( 1, sizeof(struct mindexrec) );
122                         mir->mir_name.bv_val = *names;
123                         mir->mir_name.bv_len = strlen( *names );
124                         mir->mir_mr = smr;
125                         if ( avl_insert( &mr_index, (caddr_t) mir,
126                                          (AVL_CMP) mr_index_cmp,
127                                          (AVL_DUP) avl_dup_error ) ) {
128                                 *err = *names;
129                                 ldap_memfree(mir);
130                                 return SLAP_SCHERR_MR_DUP;
131                         }
132                         /* FIX: temporal consistency check */
133                         mr_bvfind(&mir->mir_name);
134                         names++;
135                 }
136         }
137         return 0;
138 }
139
140 int
141 mr_add(
142     LDAPMatchingRule            *mr,
143     slap_mrule_defs_rec *def,
144         MatchingRule    *amr,
145     const char          **err
146 )
147 {
148         MatchingRule    *smr;
149         Syntax          *syn;
150         int             code;
151
152         smr = (MatchingRule *) ch_calloc( 1, sizeof(MatchingRule) );
153         AC_MEMCPY( &smr->smr_mrule, mr, sizeof(LDAPMatchingRule));
154
155         /*
156          * note: smr_bvoid uses the same memory of smr_mrule.mr_oid;
157          * smr_oidlen is #defined as smr_bvoid.bv_len
158          */
159         smr->smr_bvoid.bv_val = smr->smr_mrule.mr_oid;
160         smr->smr_oidlen = strlen( mr->mr_oid );
161         smr->smr_usage = def->mrd_usage;
162         smr->smr_convert = def->mrd_convert;
163         smr->smr_normalize = def->mrd_normalize;
164         smr->smr_match = def->mrd_match;
165         smr->smr_indexer = def->mrd_indexer;
166         smr->smr_filter = def->mrd_filter;
167         smr->smr_associated = amr;
168
169         if ( smr->smr_syntax_oid ) {
170                 if ( (syn = syn_find(smr->smr_syntax_oid)) ) {
171                         smr->smr_syntax = syn;
172                 } else {
173                         *err = smr->smr_syntax_oid;
174                         return SLAP_SCHERR_SYN_NOT_FOUND;
175                 }
176         } else {
177                 *err = "";
178                 return SLAP_SCHERR_MR_INCOMPLETE;
179         }
180         code = mr_insert(smr,err);
181         return code;
182 }
183
184 int
185 register_matching_rule(
186         slap_mrule_defs_rec *def )
187 {
188         LDAPMatchingRule *mr;
189         MatchingRule *amr = NULL;
190         int             code;
191         const char      *err;
192
193         if( def->mrd_usage == SLAP_MR_NONE ) {
194 #ifdef NEW_LOGGING
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 #endif
201
202                 return -1;
203         }
204
205         if( def->mrd_associated != NULL ) {
206                 amr = mr_find( def->mrd_associated );
207
208 #if 0
209                 /* ignore for now */
210
211                 if( amr == NULL ) {
212 #ifdef NEW_LOGGING
213                         LDAP_LOG( OPERATION, ERR,
214                            "register_matching_rule: could not locate associated "
215                            "matching rule %s for %s\n",  def->mrd_associated, def->mrd_desc, 0 );
216 #else
217                         Debug( LDAP_DEBUG_ANY, "register_matching_rule: could not locate "
218                                 "associated matching rule %s for %s\n",
219                                 def->mrd_associated, def->mrd_desc, 0 );
220 #endif
221
222                         return -1;
223                 }
224 #endif
225
226         }
227
228         mr = ldap_str2matchingrule( def->mrd_desc, &code, &err, LDAP_SCHEMA_ALLOW_ALL);
229         if ( !mr ) {
230 #ifdef NEW_LOGGING
231                 LDAP_LOG( OPERATION, ERR, 
232                         "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 #endif
238
239                 return( -1 );
240         }
241
242         code = mr_add( mr, def, amr, &err );
243
244         ldap_memfree( mr );
245
246         if ( code ) {
247 #ifdef NEW_LOGGING
248                 LDAP_LOG( OPERATION, ERR, 
249                         "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 #endif
255
256                 return( -1 );
257         }
258
259         return( 0 );
260 }
261
262 void
263 mru_destroy( void )
264 {
265         MatchingRuleUse *m, *n;
266
267         for (m=mru_list; m; m=n) {
268                 n = m->smru_next;
269                 if ( m->smru_str.bv_val ) {
270                         ch_free( m->smru_str.bv_val );
271                 }
272                 /* memory borrowed from m->smru_mr */
273                 m->smru_oid = NULL;
274                 m->smru_names = NULL;
275                 m->smru_desc = NULL;
276
277                 /* free what's left (basically 
278                  * smru_mruleuse.mru_applies_oids) */
279                 ldap_matchingruleuse_free((LDAPMatchingRuleUse *)m);
280         }
281 }
282
283 /*
284  * Appends a string to an array of char *,
285  * and returns the newly allocated char **.
286  * Maybe we can find a substitute, or borrow
287  * a helper from somewhere else
288  */
289 static char **
290 ch_append( char **array, char *value )
291 {
292         int     cnt;
293         char    **tmp;
294
295         if ( array == NULL ) {
296                 cnt = 0;
297         } else {
298                 for ( cnt = 0; array[ cnt ]; cnt++ )
299                         /* NO OP */ ;
300         }
301
302         tmp = LDAP_REALLOC( array, ( cnt + 2 ) * sizeof( char * ) );
303
304         tmp[ cnt++ ] = ch_strdup( value );
305         tmp[ cnt ] = NULL;
306
307         return tmp;
308 }
309
310 int
311 matching_rule_use_init( void )
312 {
313         MatchingRule    *mr;
314         MatchingRuleUse **mru_ptr = &mru_list;
315
316 #define MR_TYPE_MASK            ( SLAP_MR_TYPE_MASK & ~SLAP_MR_EXT )
317 #define MR_TYPE_SUBTYPE_MASK    ( MR_TYPE_MASK | SLAP_MR_SUBTYPE_MASK ) 
318 #if 0   /* all types regardless of EXT */
319 #define MR_TYPE(x)              ( (x) & MR_TYPE_MASK )
320 #define MR_TYPE_SUBTYPE(x)      ( (x) & MR_TYPE_SUBTYPE_MASK )
321 #else   /* only those marked as EXT (as per RFC 2252) */
322 #define MR_TYPE(x)              ( ( (x) & SLAP_MR_EXT ) ? ( (x) & MR_TYPE_MASK ) : SLAP_MR_NONE )
323 #define MR_TYPE_SUBTYPE(x)      ( ( (x) & SLAP_MR_EXT ) ? ( (x) & MR_TYPE_SUBTYPE_MASK ) : SLAP_MR_NONE )
324 #endif
325
326 #ifdef NEW_LOGGING
327         LDAP_LOG( OPERATION, INFO, "matching_rule_use_init\n", 0, 0, 0 );
328 #else
329         Debug( LDAP_DEBUG_TRACE, "matching_rule_use_init\n", 0, 0, 0 );
330 #endif
331
332         for ( mr = mr_list; mr; mr = mr->smr_next ) {
333                 slap_mask_t     um = MR_TYPE( mr->smr_usage );
334                 slap_mask_t     usm = MR_TYPE_SUBTYPE( mr->smr_usage );
335
336                 AttributeType   *at;
337                 MatchingRuleUse _mru, *mru = &_mru;
338
339                 mr->smr_mru = NULL;
340
341                 /* hide rules marked as HIDE */
342                 if ( mr->smr_usage & SLAP_MR_HIDE ) {
343                         continue;
344                 }
345
346                 /* hide rules with no type */
347                 if ( um == SLAP_MR_NONE ) {
348                         continue;
349                 }
350
351                 memset( mru, 0, sizeof( MatchingRuleUse ) );
352
353                 /*
354                  * Note: we're using the same values of the corresponding 
355                  * MatchingRule structure; maybe we'd copy them ...
356                  */
357                 mru->smru_mr = mr;
358                 mru->smru_obsolete = mr->smr_obsolete;
359                 mru->smru_applies_oids = NULL;
360                 mru->smru_next = NULL;
361                 mru->smru_oid = mr->smr_oid;
362                 mru->smru_names = mr->smr_names;
363                 mru->smru_desc = mr->smr_desc;
364
365 #ifdef NEW_LOGGING
366                 LDAP_LOG( OPERATION, INFO, "    %s (%s): ", 
367                                 mru->smru_oid, 
368                                 mru->smru_names ? mru->smru_names[ 0 ] : "", 0 );
369 #else
370                 Debug( LDAP_DEBUG_TRACE, "    %s (%s): ", 
371                                 mru->smru_oid, 
372                                 mru->smru_names ? mru->smru_names[ 0 ] : "", 0 );
373 #endif
374
375                 switch ( um ) {
376                 case SLAP_MR_EQUALITY:
377                         at = NULL;
378                         if ( usm == SLAP_MR_EQUALITY_APPROX ) {
379 #ifdef NEW_LOGGING
380                                 LDAP_LOG( OPERATION, INFO, "APPROX%s\n",
381                                                 ( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
382                                                 0, 0 );
383 #else
384                                 Debug( LDAP_DEBUG_TRACE, "APPROX%s\n",
385                                                 ( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
386                                                 0, 0 );
387 #endif
388
389                                 for ( at_start( &at ); at; at_next( &at ) ) {
390                                         if ( mr == at->sat_approx ) {
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                                                 mru->smru_applies_oids
401                                                         = ch_append( mru->smru_applies_oids, at->sat_oid );
402                                         }
403                                 }
404
405                         } else {
406 #ifdef NEW_LOGGING
407                                 LDAP_LOG( OPERATION, INFO, "EQUALITY%s\n",
408                                                 ( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
409                                                 0, 0 );
410 #else
411                                 Debug( LDAP_DEBUG_TRACE, "EQUALITY%s\n",
412                                                 ( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
413                                                 0, 0 );
414 #endif
415                                 for ( at_start( &at ); at; at_next( &at ) ) {
416                                         if ( mr == at->sat_equality ) {
417 #ifdef NEW_LOGGING
418                                                 LDAP_LOG( OPERATION, INFO, "        %s (%s)\n",
419                                                                 at->sat_oid,
420                                                                 at->sat_cname.bv_val, 0 );
421 #else
422                                                 Debug( LDAP_DEBUG_TRACE, "        %s (%s)\n",
423                                                                 at->sat_oid,
424                                                                 at->sat_cname.bv_val, 0 );
425 #endif
426                                                 mru->smru_applies_oids
427                                                         = ch_append( mru->smru_applies_oids, at->sat_oid );
428                                         }
429                                 }
430                         }
431                         break;
432
433                 case SLAP_MR_ORDERING:
434 #ifdef NEW_LOGGING
435                         LDAP_LOG( OPERATION, INFO, "ORDERING%s\n",
436                                         ( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
437                                         0, 0 );
438 #else
439                         Debug( LDAP_DEBUG_TRACE, "ORDERING%s\n",
440                                         ( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
441                                         0, 0 );
442 #endif
443                         at = NULL;
444                         for ( at_start( &at ); at; at_next( &at ) ) {
445                                 if ( mr == at->sat_ordering ) {
446 #ifdef NEW_LOGGING
447                                         LDAP_LOG( OPERATION, INFO, "        %s (%s)\n",
448                                                         at->sat_oid,
449                                                         at->sat_cname.bv_val, 0 );
450 #else
451                                         Debug( LDAP_DEBUG_TRACE, "        %s (%s)\n",
452                                                         at->sat_oid,
453                                                         at->sat_cname.bv_val, 0 );
454 #endif
455                                         mru->smru_applies_oids
456                                                 = ch_append( mru->smru_applies_oids, at->sat_oid );
457                                 }
458                         }
459                         break;
460
461                 case SLAP_MR_SUBSTR:
462 #ifdef NEW_LOGGING
463                         LDAP_LOG( OPERATION, INFO, "SUBSTR%s\n",
464                                         ( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
465                                         0, 0 );
466 #else
467                         Debug( LDAP_DEBUG_TRACE, "SUBSTR%s\n",
468                                         ( mr->smr_usage & SLAP_MR_EXT ) ? " (EXT)" : "",
469                                         0, 0 );
470 #endif
471                         at = NULL;
472                         for ( at_start( &at ); at; at_next( &at ) ) {
473                                 if ( mr == at->sat_substr ) {
474 #ifdef NEW_LOGGING
475                                         LDAP_LOG( OPERATION, INFO, "        %s (%s)\n",
476                                                         at->sat_oid,
477                                                         at->sat_cname.bv_val, 0 );
478 #else
479                                         Debug( LDAP_DEBUG_TRACE, "        %s (%s)\n",
480                                                         at->sat_oid,
481                                                         at->sat_cname.bv_val, 0 );
482 #endif
483                                         mru->smru_applies_oids
484                                                 = ch_append( mru->smru_applies_oids, at->sat_oid );
485                                 }
486                         }
487                         break;
488
489                 default:
490 #ifdef NEW_LOGGING
491                         LDAP_LOG( OPERATION, ERR, "        unknown matching rule type "
492                                         "(type mask %d, subtype mask %d%s)\n", um, usm,
493                                         ( mr->smr_usage & SLAP_MR_EXT ) ? ", EXT" : "" );
494 #else
495                         Debug( LDAP_DEBUG_ANY, "        unknown matching rule type "
496                                         "(type mask %d, subtype mask %d%s)\n", um, usm,
497                                         ( mr->smr_usage & SLAP_MR_EXT ) ? ", EXT" : "" );
498 #endif
499                         fprintf ( stderr, "    %d (%d)\n", um, usm );
500                         assert( 0 );
501                 }
502
503                 /*
504                  * Note: the matchingRules that are not used
505                  * by any attributeType are not listed as
506                  * matchingRuleUse
507                  */
508                 if ( mru->smru_applies_oids != NULL ) {
509 #ifdef NEW_LOGGING
510                         {
511                                 char    *str = ldap_matchingruleuse2str( &mru->smru_mruleuse );
512                                 LDAP_LOG( OPERATION, INFO, "matchingRuleUse: %s\n", str, 0, 0 );
513                                 ldap_memfree( str );
514                         }
515 #else
516                         {
517                                 char    *str = ldap_matchingruleuse2str( &mru->smru_mruleuse );
518                                 Debug( LDAP_DEBUG_TRACE, "matchingRuleUse: %s\n", str, 0, 0 );
519                                 ldap_memfree( str );
520                         }
521 #endif
522
523                         mru = (MatchingRuleUse *)LDAP_MALLOC( sizeof( MatchingRuleUse ) );
524                         mr->smr_mru = mru;
525                         *mru = _mru;
526                         *mru_ptr = mru;
527                         mru_ptr = &mru->smru_next;
528                 }
529         }
530
531         return( 0 );
532 }
533
534
535 #if defined( SLAPD_SCHEMA_DN )
536
537 int mr_schema_info( Entry *e )
538 {
539         MatchingRule    *mr;
540
541         AttributeDescription *ad_matchingRules = slap_schema.si_ad_matchingRules;
542
543         for ( mr = mr_list; mr; mr = mr->smr_next ) {
544                 if ( mr->smr_usage & SLAP_MR_HIDE ) {
545                         /* skip hidden rules */
546                         continue;
547                 }
548
549                 if ( ! mr->smr_match ) {
550                         /* skip rules without matching functions */
551                         continue;
552                 }
553
554                 if ( mr->smr_str.bv_val == NULL ) {
555                         if ( ldap_matchingrule2bv( &mr->smr_mrule, &mr->smr_str ) == NULL ) {
556                                 return -1;
557                         }
558                 }
559 #if 0
560                 Debug( LDAP_DEBUG_TRACE, "Merging mr [%lu] %s\n",
561                         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         return 0;
566 }
567
568 int mru_schema_info( Entry *e )
569 {
570         MatchingRuleUse *mru;
571
572         AttributeDescription *ad_matchingRuleUse 
573                 = slap_schema.si_ad_matchingRuleUse;
574
575         for ( mru = mru_list; mru; mru = mru->smru_next ) {
576
577                 assert( !( mru->smru_usage & SLAP_MR_HIDE ) );
578
579                 if ( mru->smru_str.bv_val == NULL ) {
580                         if ( ldap_matchingruleuse2bv( &mru->smru_mruleuse, &mru->smru_str )
581                                         == NULL ) {
582                                 return -1;
583                         }
584                 }
585
586 #if 0
587                 Debug( LDAP_DEBUG_TRACE, "Merging mru [%lu] %s\n",
588                         mru->smru_str.bv_len, mru->smru_str.bv_val, 0 );
589 #endif
590                 attr_merge_one( e, ad_matchingRuleUse, &mru->smru_str );
591         }
592         return 0;
593 }
594
595 #endif