]> git.sur5r.net Git - openldap/blob - servers/slapd/schema_init.c
SLAPD_SCHEMA_NOT_COMPAT:
[openldap] / servers / slapd / schema_init.c
1 /* schema_init.c - init builtin schema */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 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 #define berValidate blobValidate
20 static int
21 blobValidate(
22         Syntax *syntax,
23         struct berval *in )
24 {
25         /* any value allowed */
26         return 0;
27 }
28
29 static int
30 UTF8StringValidate(
31         Syntax *syntax,
32         struct berval *in )
33 {
34         ber_len_t count;
35         int len;
36         unsigned char *u = in->bv_val;
37
38         for( count = in->bv_len; count > 0; count-=len, u+=len ) {
39                 /* get the length indicated by the first byte */
40                 len = LDAP_UTF8_CHARLEN( u );
41
42                 /* should not be zero */
43                 if( len == 0 ) return -1;
44
45                 /* make sure len corresponds with the offset
46                         to the next character */
47                 if( LDAP_UTF8_OFFSET( u ) != len ) return -1;
48         }
49
50         if( count != 0 ) return -1;
51
52         return 0;
53 }
54
55 static int
56 UTF8StringNormalize(
57         Syntax *syntax,
58         struct berval *val,
59         struct berval **normalized )
60 {
61         struct berval *newval;
62         char *p, *q, *s;
63
64         newval = ch_malloc( sizeof( struct berval ) );
65
66         p = val->bv_val;
67
68         /* Ignore initial whitespace */
69         while ( ldap_utf8_isspace( p ) ) {
70                 LDAP_UTF8_INCR( p );
71         }
72
73         if( *p ) {
74                 ch_free( newval );
75                 return 1;
76         }
77
78         newval->bv_val = ch_strdup( p );
79         p = q = newval->bv_val;
80         s = NULL;
81
82         while ( *p ) {
83                 int len;
84
85                 if ( ldap_utf8_isspace( p ) ) {
86                         len = LDAP_UTF8_COPY(q,p);
87                         s=q;
88                         p+=len;
89                         q+=len;
90
91                         /* Ignore the extra whitespace */
92                         while ( ldap_utf8_isspace( p ) ) {
93                                 LDAP_UTF8_INCR( p );
94                         }
95                 } else {
96                         len = LDAP_UTF8_COPY(q,p);
97                         s=NULL;
98                         p+=len;
99                         q+=len;
100                 }
101         }
102
103         assert( *newval->bv_val );
104         assert( newval->bv_val < p );
105         assert( p <= q );
106
107         /* cannot start with a space */
108         assert( !ldap_utf8_isspace(newval->bv_val) );
109
110         /*
111          * If the string ended in space, backup the pointer one
112          * position.  One is enough because the above loop collapsed
113          * all whitespace to a single space.
114          */
115
116         if ( s != NULL ) {
117                 q = s;
118         }
119
120         /* cannot end with a space */
121         assert( !ldap_utf8_isspace( LDAP_UTF8_PREV(q) ) );
122
123         /* null terminate */
124         *q = '\0';
125
126         newval->bv_len = q - newval->bv_val;
127         *normalized = newval;
128
129         return 0;
130 }
131
132 static int
133 oidValidate(
134         Syntax *syntax,
135         struct berval *val )
136 {
137         ber_len_t i;
138
139         if( val->bv_len == 0 ) return 0;
140
141         if( isdigit(val->bv_val[0]) ) {
142                 int dot = 0;
143                 for(i=1; i < val->bv_len; i++) {
144                         if( val->bv_val[i] == '.' ) {
145                                 if( dot++ ) return 1;
146                         } else if ( isdigit(val->bv_val[i]) ) {
147                                 dot = 0;
148                         } else {
149                                 return 1;
150                         }
151                 }
152
153                 return !dot ? 0 : 1;
154
155         } else if( isalpha(val->bv_val[0]) ) {
156                 for(i=1; i < val->bv_len; i++) {
157                         if( !isalpha(val->bv_val[i] ) ) {
158                                 return 1;
159                         }
160                 }
161
162                 return 0;
163         }
164         
165         return 1;
166 }
167
168 static int
169 integerValidate(
170         Syntax *syntax,
171         struct berval *val )
172 {
173         ber_len_t i;
174
175         for(i=0; i < val->bv_len; i++) {
176                 if( !isdigit(val->bv_val[i]) ) return -1;
177         }
178
179         return 0;
180 }
181
182 static int
183 printableStringValidate(
184         Syntax *syntax,
185         struct berval *val )
186 {
187         ber_len_t i;
188
189         for(i=0; i < val->bv_len; i++) {
190                 if( !isprint(val->bv_val[i]) ) return -1;
191         }
192
193         return 0;
194 }
195
196 static int
197 IA5StringValidate(
198         Syntax *syntax,
199         struct berval *val )
200 {
201         ber_len_t i;
202
203         for(i=0; i < val->bv_len; i++) {
204                 if( !isascii(val->bv_val[i]) ) return -1;
205         }
206
207         return 0;
208 }
209
210 static int
211 IA5StringConvert(
212         Syntax *syntax,
213         struct berval *in,
214         struct berval **out )
215 {
216         ldap_unicode_t *u;
217         ber_len_t i, len = in->bv_len;
218         struct berval *bv = ch_malloc( sizeof(struct berval) );
219
220         bv->bv_len = len * sizeof( ldap_unicode_t );
221         bv->bv_val = (char *) u = ch_malloc( bv->bv_len + sizeof( ldap_unicode_t ) );;
222
223         for(i=0; i < len; i++ ) {
224                 /*
225                  * IA5StringValidate should have been called to ensure
226                  * input is limited to IA5.
227                  */
228                 u[i] = in->bv_val[i];
229         }
230         u[i] = 0;
231
232         *out = bv;
233         return 0;
234 }
235
236 static int
237 IA5StringNormalize(
238         Syntax *syntax,
239         struct berval *val,
240         struct berval **normalized )
241 {
242         struct berval *newval;
243         char *p, *q;
244
245         newval = ch_malloc( sizeof( struct berval ) );
246
247         p = val->bv_val;
248
249         /* Ignore initial whitespace */
250         while ( isspace( *p++ ) ) {
251                 /* EMPTY */  ;
252         }
253
254         if( *p ) {
255                 ch_free( newval );
256                 return 1;
257         }
258
259         newval->bv_val = ch_strdup( p );
260         p = q = newval->bv_val;
261
262         while ( *p ) {
263                 if ( isspace( *p ) ) {
264                         *q++ = *p++;
265
266                         /* Ignore the extra whitespace */
267                         while ( isspace( *p++ ) ) {
268                                 /* EMPTY */  ;
269                         }
270                 } else {
271                         *q++ = *p++;
272                 }
273         }
274
275         assert( *newval->bv_val );
276         assert( newval->bv_val < p );
277         assert( p <= q );
278
279         /* cannot start with a space */
280         assert( !isspace(*newval->bv_val) );
281
282         /*
283          * If the string ended in space, backup the pointer one
284          * position.  One is enough because the above loop collapsed
285          * all whitespace to a single space.
286          */
287
288         if ( isspace( q[-1] ) ) {
289                 --q;
290         }
291
292         /* cannot end with a space */
293         assert( !isspace( q[-1] ) );
294
295         /* null terminate */
296         *q = '\0';
297
298         newval->bv_len = q - newval->bv_val;
299         *normalized = newval;
300
301         return 0;
302 }
303
304 static int
305 caseExactIA5Match(
306         int *match,
307         unsigned use,
308         Syntax *syntax,
309         MatchingRule *mr,
310         struct berval *value,
311         void *assertedValue )
312 {
313         *match = strcmp( value->bv_val,
314                 ((struct berval *) assertedValue)->bv_val );
315         return LDAP_SUCCESS;
316 }
317
318 static int
319 caseIgnoreIA5Match(
320         int *match,
321         unsigned use,
322         Syntax *syntax,
323         MatchingRule *mr,
324         struct berval *value,
325         void *assertedValue )
326 {
327         *match = strcasecmp( value->bv_val,
328                 ((struct berval *) assertedValue)->bv_val );
329         return LDAP_SUCCESS;
330 }
331
332 static int
333 objectClassMatch(
334         int *match,
335         unsigned use,
336         Syntax *syntax,
337         MatchingRule *mr,
338         struct berval *value,
339         void *assertedValue )
340 {
341         ObjectClass *oc = oc_find( value->bv_val );
342         ObjectClass *asserted = oc_find( ((struct berval *) assertedValue)->bv_val );
343
344         *match = ( oc == NULL || oc != asserted );
345         return LDAP_SUCCESS;
346 }
347
348 struct syntax_defs_rec {
349         char *sd_desc;
350         int sd_flags;
351         slap_syntax_validate_func *sd_validate;
352         slap_syntax_transform_func *sd_normalize;
353         slap_syntax_transform_func *sd_pretty;
354 #ifdef SLAPD_BINARY_CONVERSION
355         slap_syntax_transform_func *sd_ber2str;
356         slap_syntax_transform_func *sd_str2ber;
357 #endif
358 };
359
360 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
361 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
362
363 struct syntax_defs_rec syntax_defs[] = {
364         {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' " X_BINARY X_NOT_H_R ")",
365                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
366         {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
367                 0, NULL, NULL, NULL},
368         {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
369                 0, NULL, NULL, NULL},
370         {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' " X_NOT_H_R ")",
371                 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
372         {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' " X_BINARY X_NOT_H_R ")",
373                 SLAP_SYNTAX_BER, berValidate, NULL, NULL},
374         {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
375                 0, NULL, NULL, NULL},
376         {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
377                 0, NULL, NULL, NULL},
378         {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
379                 X_BINARY X_NOT_H_R ")",
380                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
381         {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
382                 X_BINARY X_NOT_H_R ")",
383                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
384         {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
385                 X_BINARY X_NOT_H_R ")",
386                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
387         {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
388                 0, NULL, NULL, NULL},
389         {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'DN' )",
390                 0, blobValidate, NULL, NULL},
391         {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
392                 0, NULL, NULL, NULL},
393         {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
394                 0, NULL, NULL, NULL},
395         {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
396                 0, UTF8StringValidate, UTF8StringNormalize, NULL},
397         {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
398                 0, NULL, NULL, NULL},
399         {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
400                 0, NULL, NULL, NULL},
401         {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
402                 0, NULL, NULL, NULL},
403         {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
404                 0, NULL, NULL, NULL},
405         {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
406                 0, NULL, NULL, NULL},
407         {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
408                 0, blobValidate, NULL, NULL},
409         {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
410                 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
411         {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
412                 0, NULL, NULL, NULL},
413         {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
414                 0, NULL, NULL, NULL},
415         {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
416                 0, IA5StringValidate, IA5StringNormalize, NULL},
417         {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
418                 0, integerValidate, NULL, NULL},
419         {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
420                 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
421         {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
422                 0, NULL, NULL, NULL},
423         {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
424                 0, NULL, NULL, NULL},
425         {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
426                 0, NULL, NULL, NULL},
427         {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
428                 0, NULL, NULL, NULL},
429         {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
430                 0, NULL, NULL, NULL},
431         {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
432                 0, NULL, NULL, NULL},
433         {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
434                 0, NULL, NULL, NULL},
435         {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
436                 0, NULL, NULL, NULL},
437         {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
438                 0, NULL, NULL, NULL},
439         {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
440                 0, oidValidate, NULL, NULL},
441         {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
442                 0, NULL, NULL, NULL},
443         {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
444                 0, blobValidate, NULL, NULL},
445         {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
446                 0, blobValidate, NULL, NULL},
447         {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
448                 0, NULL, NULL, NULL},
449         {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
450                 0, NULL, NULL, NULL},
451         {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
452                 0, printableStringValidate, NULL, NULL},
453         {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
454                 X_BINARY X_NOT_H_R ")",
455                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
456         {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
457                 0, blobValidate, NULL, NULL},
458         {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
459                 0, NULL, NULL, NULL},
460         {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
461                 0, NULL, NULL, NULL},
462         {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
463                 0, NULL, NULL, NULL},
464         {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
465                 0, NULL, NULL, NULL},
466         {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
467                 0, NULL, NULL, NULL},
468         {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
469                 0, NULL, NULL, NULL},
470         {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
471                 0, NULL, NULL, NULL},
472         {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
473                 0, NULL, NULL, NULL},
474
475         /* OpenLDAP Experimental Syntaxes */
476         {"( " SLAPD_OID_ACI_SYNTAX " DESC 'OpenLDAP Experimental ACI' )",
477                 0, NULL, NULL, NULL},
478
479         {NULL, 0, NULL, NULL, NULL}
480 };
481
482 struct mrule_defs_rec {
483         char *                                          mrd_desc;
484         unsigned                                        mrd_usage;
485         slap_mr_convert_func *          mrd_convert;
486         slap_mr_normalize_func *        mrd_normalize;
487         slap_mr_match_func *            mrd_match;
488         slap_mr_indexer_func *          mrd_indexer;
489         slap_mr_filter_func *           mrd_filter;
490 };
491
492 /*
493  * Other matching rules in X.520 that we do not use:
494  *
495  * 2.5.13.9             numericStringOrderingMatch
496  * 2.5.13.13    booleanMatch
497  * 2.5.13.15    integerOrderingMatch
498  * 2.5.13.18    octetStringOrderingMatch
499  * 2.5.13.19    octetStringSubstringsMatch
500  * 2.5.13.25    uTCTimeMatch
501  * 2.5.13.26    uTCTimeOrderingMatch
502  * 2.5.13.31    directoryStringFirstComponentMatch
503  * 2.5.13.32    wordMatch
504  * 2.5.13.33    keywordMatch
505  * 2.5.13.34    certificateExactMatch
506  * 2.5.13.35    certificateMatch
507  * 2.5.13.36    certificatePairExactMatch
508  * 2.5.13.37    certificatePairMatch
509  * 2.5.13.38    certificateListExactMatch
510  * 2.5.13.39    certificateListMatch
511  * 2.5.13.40    algorithmIdentifierMatch
512  * 2.5.13.41    storedPrefixMatch
513  * 2.5.13.42    attributeCertificateMatch
514  * 2.5.13.43    readerAndKeyIDMatch
515  * 2.5.13.44    attributeIntegrityMatch
516  */
517
518 /* recycled matching functions */
519 #define caseIgnoreMatch caseIgnoreIA5Match
520 #define caseExactMatch caseExactIA5Match
521
522 /* unimplemented matching functions */
523 #define objectIdentifierMatch NULL
524 #define distinguishedNameMatch NULL
525 #define caseIgnoreOrderingMatch NULL
526 #define caseIgnoreSubstringsMatch NULL
527 #define caseExactOrderingMatch NULL
528 #define caseExactSubstringsMatch NULL
529 #define numericStringMatch NULL
530 #define numericStringSubstringsMatch NULL
531 #define caseIgnoreListMatch NULL
532 #define caseIgnoreListSubstringsMatch NULL
533 #define integerMatch NULL
534 #define bitStringMatch NULL
535 #define octetStringMatch NULL
536 #define telephoneNumberMatch NULL
537 #define telephoneNumberSubstringsMatch NULL
538 #define presentationAddressMatch NULL
539 #define uniqueMemberMatch NULL
540 #define protocolInformationMatch NULL
541 #define generalizedTimeMatch NULL
542 #define generalizedTimeOrderingMatch NULL
543 #define integerFirstComponentMatch NULL
544 #define objectIdentifierFirstComponentMatch NULL
545 #define caseIgnoreIA5SubstringsMatch NULL
546
547 struct mrule_defs_rec mrule_defs[] = {
548         {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
549                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
550                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
551                 NULL, NULL, objectIdentifierMatch, NULL, NULL},
552
553         {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
554                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
555                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
556                 NULL, NULL, distinguishedNameMatch, NULL, NULL},
557
558         {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
559                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
560                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
561                 NULL, NULL, caseIgnoreMatch, NULL, NULL},
562
563         {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
564                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
565                 SLAP_MR_ORDERING,
566                 NULL, NULL, caseIgnoreOrderingMatch, NULL, NULL},
567
568         {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
569                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
570                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
571                 NULL, NULL, caseIgnoreSubstringsMatch, NULL, NULL},
572
573         /* Next three are not in the RFC's, but are needed for compatibility */
574         {"( 2.5.13.5 NAME 'caseExactMatch' "
575                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
576                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
577                 NULL, NULL, caseExactMatch, NULL, NULL},
578
579         {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
580                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
581                 SLAP_MR_ORDERING,
582                 NULL, NULL, caseExactOrderingMatch, NULL, NULL},
583
584         {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
585                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
586                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
587                 NULL, NULL, caseExactSubstringsMatch, NULL, NULL},
588
589         {"( 2.5.13.8 NAME 'numericStringMatch' "
590                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
591                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
592                 NULL, NULL, numericStringMatch, NULL, NULL},
593
594         {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
595                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
596                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
597                 NULL, NULL, numericStringSubstringsMatch, NULL, NULL},
598
599         {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
600                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
601                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
602                 NULL, NULL, caseIgnoreListMatch, NULL, NULL},
603
604         {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
605                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
606                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
607                 NULL, NULL, caseIgnoreListSubstringsMatch, NULL, NULL},
608
609         {"( 2.5.13.14 NAME 'integerMatch' "
610                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
611                 SLAP_MR_NONE | SLAP_MR_EXT,
612                 NULL, NULL, integerMatch, NULL, NULL},
613
614         {"( 2.5.13.16 NAME 'bitStringMatch' "
615                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
616                 SLAP_MR_NONE | SLAP_MR_EXT,
617                 NULL, NULL, bitStringMatch, NULL, NULL},
618
619         {"( 2.5.13.17 NAME 'octetStringMatch' "
620                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
621                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
622                 NULL, NULL, octetStringMatch, NULL, NULL},
623
624         {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
625                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
626                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
627                 NULL, NULL, telephoneNumberMatch, NULL, NULL},
628
629         {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
630                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
631                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
632                 NULL, NULL, telephoneNumberSubstringsMatch, NULL, NULL},
633
634         {"( 2.5.13.22 NAME 'presentationAddressMatch' "
635                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
636                 SLAP_MR_NONE | SLAP_MR_EXT,
637                 NULL, NULL, presentationAddressMatch, NULL, NULL},
638
639         {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
640                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
641                 SLAP_MR_NONE | SLAP_MR_EXT,
642                 NULL, NULL, uniqueMemberMatch, NULL, NULL},
643
644         {"( 2.5.13.24 NAME 'protocolInformationMatch' "
645                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
646                 SLAP_MR_NONE | SLAP_MR_EXT,
647                 NULL, NULL, protocolInformationMatch, NULL, NULL},
648
649         {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
650                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
651                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
652                 NULL, NULL, generalizedTimeMatch, NULL, NULL},
653
654         {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
655                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
656                 SLAP_MR_ORDERING,
657                 NULL, NULL, generalizedTimeOrderingMatch, NULL, NULL},
658
659         {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
660                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
661                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
662                 NULL, NULL, integerFirstComponentMatch, NULL, NULL},
663
664         {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
665                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
666                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
667                 NULL, NULL, objectIdentifierFirstComponentMatch, NULL, NULL},
668
669         {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
670                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
671                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
672                 NULL, NULL, caseExactIA5Match, NULL, NULL},
673
674         {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
675                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
676                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
677                 NULL, NULL, caseIgnoreIA5Match, NULL, NULL},
678
679         {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
680                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
681                 SLAP_MR_SUBSTR,
682                 NULL, NULL, caseIgnoreIA5SubstringsMatch, NULL, NULL},
683
684         {NULL, SLAP_MR_NONE, NULL, NULL, NULL}
685 };
686
687 static int schema_init_done = 0;
688
689 int
690 schema_init( void )
691 {
692         int             res;
693         int             i;
694
695         /* we should only be called once (from main) */
696         assert( schema_init_done == 0 );
697
698         for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
699                 res = register_syntax( syntax_defs[i].sd_desc,
700                     syntax_defs[i].sd_flags,
701                     syntax_defs[i].sd_validate,
702                     syntax_defs[i].sd_normalize,
703                         syntax_defs[i].sd_pretty
704 #ifdef SLAPD_BINARY_CONVERSION
705                         ,
706                     syntax_defs[i].sd_ber2str,
707                         syntax_defs[i].sd_str2ber
708 #endif
709                 );
710
711                 if ( res ) {
712                         fprintf( stderr, "schema_init: Error registering syntax %s\n",
713                                  syntax_defs[i].sd_desc );
714                         return -1;
715                 }
716         }
717
718         for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
719                 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE ) {
720                         fprintf( stderr,
721                                 "schema_init: Ingoring unusable matching rule %s\n",
722                                  mrule_defs[i].mrd_desc );
723                         continue;
724                 }
725
726                 res = register_matching_rule(
727                         mrule_defs[i].mrd_desc,
728                         mrule_defs[i].mrd_usage,
729                         mrule_defs[i].mrd_convert,
730                         mrule_defs[i].mrd_normalize,
731                     mrule_defs[i].mrd_match,
732                         mrule_defs[i].mrd_indexer,
733                         mrule_defs[i].mrd_filter );
734
735                 if ( res ) {
736                         fprintf( stderr,
737                                 "schema_init: Error registering matching rule %s\n",
738                                  mrule_defs[i].mrd_desc );
739                         return -1;
740                 }
741         }
742         schema_init_done = 1;
743         return( 0 );
744 }
745
746 #ifdef SLAPD_SCHEMA_NOT_COMPAT
747 struct slap_internal_schema slap_schema;
748
749 struct slap_schema_oc_map {
750         char *ssom_name;
751         size_t ssom_offset;
752 } oc_map[] = {
753         { "alias", offsetof(struct slap_internal_schema, si_oc_alias) },
754         { "referral", offsetof(struct slap_internal_schema, si_oc_referral) },
755         { NULL, 0 }
756 };
757
758 struct slap_schema_ad_map {
759         char *ssam_name;
760         slap_mr_match_func *ssam_match;
761         size_t ssam_offset;
762 } ad_map[] = {
763         { "objectClass", objectClassMatch,
764                 offsetof(struct slap_internal_schema, si_ad_objectClass) },
765
766         { "creatorsName", NULL,
767                 offsetof(struct slap_internal_schema, si_ad_creatorsName) },
768         { "createTimestamp", NULL,
769                 offsetof(struct slap_internal_schema, si_ad_createTimestamp) },
770         { "modifiersName", NULL,
771                 offsetof(struct slap_internal_schema, si_ad_modifiersName) },
772         { "modifyTimestamp", NULL,
773                 offsetof(struct slap_internal_schema, si_ad_modifyTimestamp) },
774
775         { "subschemaSubentry", NULL,
776                 offsetof(struct slap_internal_schema, si_ad_subschemaSubentry) },
777
778         { "namingContexts", NULL,
779                 offsetof(struct slap_internal_schema, si_ad_namingContexts) },
780         { "supportedControl", NULL,
781                 offsetof(struct slap_internal_schema, si_ad_supportedControl) },
782         { "supportedExtension", NULL,
783                 offsetof(struct slap_internal_schema, si_ad_supportedExtension) },
784         { "supportedLDAPVersion", NULL,
785                 offsetof(struct slap_internal_schema, si_ad_supportedLDAPVersion) },
786 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
787         { "supportedACIMechanisms", NULL,
788                 offsetof(struct slap_internal_schema, si_ad_supportedACIMechanisms) },
789
790 #endif
791         { "supportedSASLMechanisms", NULL,
792                 offsetof(struct slap_internal_schema, si_ad_supportedSASLMechanisms) },
793
794         { "attributeTypes", NULL,
795                 offsetof(struct slap_internal_schema, si_ad_attributeTypes) },
796         { "ldapSyntaxes", NULL,
797                 offsetof(struct slap_internal_schema, si_ad_ldapSyntaxes) },
798         { "matchingRules", NULL,
799                 offsetof(struct slap_internal_schema, si_ad_matchingRules) },
800         { "objectClasses", NULL,
801                 offsetof(struct slap_internal_schema, si_ad_objectClasses) },
802
803         { "ref", NULL,
804                 offsetof(struct slap_internal_schema, si_ad_ref) },
805
806         { "entry", NULL,
807                 offsetof(struct slap_internal_schema, si_ad_entry) },
808         { "children", NULL,
809                 offsetof(struct slap_internal_schema, si_ad_children) },
810
811         { "userPassword", NULL,
812                 offsetof(struct slap_internal_schema, si_ad_userPassword) },
813         { "authPassword", NULL,
814                 offsetof(struct slap_internal_schema, si_ad_authPassword) },
815 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
816         { "krbName", NULL,
817                 offsetof(struct slap_internal_schema, si_ad_krbName) },
818 #endif
819
820         { NULL, NULL, 0 }
821 };
822
823 #endif
824
825 int
826 schema_prep( void )
827 {
828 #ifdef SLAPD_SCHEMA_NOT_COMPAT
829         int i;
830 #endif
831         /* we should only be called once after schema_init() was called */
832         assert( schema_init_done == 1 );
833
834 #ifdef SLAPD_SCHEMA_NOT_COMPAT
835         for( i=0; oc_map[i].ssom_name; i++ ) {
836                 ObjectClass ** ocp = (ObjectClass **)
837                         &(((char *) &slap_schema)[oc_map[i].ssom_offset]);
838
839                 *ocp = oc_find( oc_map[i].ssom_name );
840
841                 if( *ocp == NULL ) {
842                         fprintf( stderr,
843                                 "No objectClass \"%s\" defined in schema\n",
844                                 oc_map[i].ssom_name );
845                         return LDAP_OBJECT_CLASS_VIOLATION;
846                 }
847         }
848
849         for( i=0; ad_map[i].ssam_name; i++ ) {
850                 int rc;
851                 const char *text;
852
853                 AttributeDescription ** adp = (AttributeDescription **)
854                         &(((char *) &slap_schema)[ad_map[i].ssam_offset]);
855
856                 *adp = NULL;
857
858                 rc = slap_str2ad( ad_map[i].ssam_name, adp, &text );
859
860                 if( rc != LDAP_SUCCESS ) {
861                         fprintf( stderr,
862                                 "No attribute \"%s\" defined in schema\n",
863                                 ad_map[i].ssam_name );
864                         return rc;
865                 }
866
867                 if( ad_map[i].ssam_match ) {
868                         /* install custom matching routine */
869                         (*adp)->ad_type->sat_equality->smr_match = ad_map[i].ssam_match;
870                 }
871         }
872 #endif
873
874         ++schema_init_done;
875         return 0;
876 }