]> git.sur5r.net Git - openldap/blob - servers/slapd/mr.c
Add validation.
[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
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
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                 ldap_matchingrule_free((LDAPMatchingRule *)m);
81         }
82 }
83
84 static int
85 mr_insert(
86     MatchingRule        *smr,
87     const char          **err
88 )
89 {
90         MatchingRule            **mrp;
91         struct mindexrec        *mir;
92         char                    **names;
93
94         mrp = &mr_list;
95         while ( *mrp != NULL ) {
96                 mrp = &(*mrp)->smr_next;
97         }
98         *mrp = smr;
99
100         if ( smr->smr_oid ) {
101                 mir = (struct mindexrec *)
102                         ch_calloc( 1, sizeof(struct mindexrec) );
103                 mir->mir_name.bv_val = smr->smr_oid;
104                 mir->mir_name.bv_len = strlen( smr->smr_oid );
105                 mir->mir_mr = smr;
106                 if ( avl_insert( &mr_index, (caddr_t) mir,
107                                  (AVL_CMP) mr_index_cmp,
108                                  (AVL_DUP) avl_dup_error ) ) {
109                         *err = smr->smr_oid;
110                         ldap_memfree(mir);
111                         return SLAP_SCHERR_DUP_RULE;
112                 }
113                 /* FIX: temporal consistency check */
114                 mr_bvfind(&mir->mir_name);
115         }
116         if ( (names = smr->smr_names) ) {
117                 while ( *names ) {
118                         mir = (struct mindexrec *)
119                                 ch_calloc( 1, sizeof(struct mindexrec) );
120                         mir->mir_name.bv_val = *names;
121                         mir->mir_name.bv_len = strlen( *names );
122                         mir->mir_mr = smr;
123                         if ( avl_insert( &mr_index, (caddr_t) mir,
124                                          (AVL_CMP) mr_index_cmp,
125                                          (AVL_DUP) avl_dup_error ) ) {
126                                 *err = *names;
127                                 ldap_memfree(mir);
128                                 return SLAP_SCHERR_DUP_RULE;
129                         }
130                         /* FIX: temporal consistency check */
131                         mr_bvfind(&mir->mir_name);
132                         names++;
133                 }
134         }
135         return 0;
136 }
137
138 int
139 mr_add(
140     LDAPMatchingRule            *mr,
141         unsigned usage,
142         slap_mr_convert_func *convert,
143         slap_mr_normalize_func *normalize,
144     slap_mr_match_func  *match,
145         slap_mr_indexer_func *indexer,
146     slap_mr_filter_func *filter,
147         MatchingRule    *amr,
148     const char          **err
149 )
150 {
151         MatchingRule    *smr;
152         Syntax          *syn;
153         int             code;
154
155         smr = (MatchingRule *) ch_calloc( 1, sizeof(MatchingRule) );
156         AC_MEMCPY( &smr->smr_mrule, mr, sizeof(LDAPMatchingRule));
157
158         smr->smr_oidlen = strlen( mr->mr_oid );
159         smr->smr_usage = usage;
160         smr->smr_convert = convert;
161         smr->smr_normalize = normalize;
162         smr->smr_match = match;
163         smr->smr_indexer = indexer;
164         smr->smr_filter = filter;
165         smr->smr_associated = amr;
166
167         if ( smr->smr_syntax_oid ) {
168                 if ( (syn = syn_find(smr->smr_syntax_oid)) ) {
169                         smr->smr_syntax = syn;
170                 } else {
171                         *err = smr->smr_syntax_oid;
172                         return SLAP_SCHERR_SYN_NOT_FOUND;
173                 }
174         } else {
175                 *err = "";
176                 return SLAP_SCHERR_MR_INCOMPLETE;
177         }
178         code = mr_insert(smr,err);
179         return code;
180 }
181
182
183 int
184 register_matching_rule(
185         const char * desc,
186         unsigned usage,
187         slap_mr_convert_func *convert,
188         slap_mr_normalize_func *normalize,
189         slap_mr_match_func *match,
190         slap_mr_indexer_func *indexer,
191         slap_mr_filter_func *filter,
192         const char* associated )
193 {
194         LDAPMatchingRule *mr;
195         MatchingRule *amr = NULL;
196         int             code;
197         const char      *err;
198
199         if( usage == SLAP_MR_NONE ) {
200 #ifdef NEW_LOGGING
201                 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
202                            "register_matching_rule: %s not usable\n", desc ));
203 #else
204                 Debug( LDAP_DEBUG_ANY, "register_matching_rule: not usable %s\n",
205                     desc, 0, 0 );
206 #endif
207
208                 return -1;
209         }
210
211         if( associated != NULL ) {
212                 amr = mr_find( associated );
213
214 #if 0
215                 /* ignore for now */
216
217                 if( amr == NULL ) {
218 #ifdef NEW_LOGGING
219                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
220                                    "register_matching_rule: could not locate associated matching rule %s for %s\n",
221                                    associated, desc ));
222 #else
223                         Debug( LDAP_DEBUG_ANY, "register_matching_rule: could not locate "
224                                 "associated matching rule %s for %s\n",
225                                 associated, desc, 0 );
226 #endif
227
228                         return -1;
229                 }
230 #endif
231
232         }
233
234         mr = ldap_str2matchingrule( desc, &code, &err, LDAP_SCHEMA_ALLOW_ALL);
235         if ( !mr ) {
236 #ifdef NEW_LOGGING
237                 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
238                            "register_matching_rule: %s before %s in %s.\n",
239                            ldap_scherr2str(code), err, desc ));
240 #else
241                 Debug( LDAP_DEBUG_ANY, "Error in register_matching_rule: %s before %s in %s\n",
242                     ldap_scherr2str(code), err, desc );
243 #endif
244
245                 return( -1 );
246         }
247
248         code = mr_add( mr, usage,
249                 convert, normalize, match, indexer, filter, amr,
250                 &err );
251
252         ldap_memfree( mr );
253
254         if ( code ) {
255 #ifdef NEW_LOGGING
256                 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
257                            "register_matching_rule: %s for %s in %s.\n",
258                            scherr2str(code), err, desc ));
259 #else
260                 Debug( LDAP_DEBUG_ANY, "Error in register_matching_rule: %s for %s in %s\n",
261                     scherr2str(code), err, desc );
262 #endif
263
264                 return( -1 );
265         }
266
267         return( 0 );
268 }
269
270
271 #if defined( SLAPD_SCHEMA_DN )
272
273 int mr_schema_info( Entry *e )
274 {
275         struct berval   vals[2];
276         MatchingRule    *mr;
277
278         AttributeDescription *ad_matchingRules = slap_schema.si_ad_matchingRules;
279
280         vals[1].bv_val = NULL;
281
282         for ( mr = mr_list; mr; mr = mr->smr_next ) {
283                 if ( mr->smr_usage & SLAP_MR_HIDE ) {
284                         /* skip hidden rules */
285                         continue;
286                 }
287
288                 if ( ! mr->smr_match ) {
289                         /* skip rules without matching functions */
290                         continue;
291                 }
292
293                 if ( ldap_matchingrule2bv( &mr->smr_mrule, vals ) == NULL ) {
294                         return -1;
295                 }
296 #if 0
297                 Debug( LDAP_DEBUG_TRACE, "Merging mr [%ld] %s\n",
298                (long) vals[0].bv_len, vals[0].bv_val, 0 );
299 #endif
300                 attr_merge( e, ad_matchingRules, vals );
301                 ldap_memfree( vals[0].bv_val );
302         }
303         return 0;
304 }
305
306 #endif