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