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