]> git.sur5r.net Git - openldap/blob - servers/slapd/schemaparse.c
Add error handling to BDB_INDEX code
[openldap] / servers / slapd / schemaparse.c
1 /* schemaparse.c - routines to parse config file objectclass definitions */
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_schema.h"
18
19 int     global_schemacheck = 1; /* schemacheck on is default */
20
21 static void             oc_usage(void); 
22 static void             at_usage(void);
23
24 static char *const err2text[] = {
25         "Success",
26         "Out of memory",
27         "ObjectClass not found",
28         "ObjectClass inappropriate SUPerior",
29         "AttributeType not found",
30         "AttributeType inappropriate USAGE",
31         "Duplicate objectClass",
32         "Duplicate attributeType",
33         "Duplicate ldapSyntax",
34         "Duplicate matchingRule",
35         "OID or name required",
36         "SYNTAX or SUPerior required",
37         "MatchingRule not found",
38         "Syntax not found",
39         "Syntax required",
40         "Qualifier not supported",
41         "Invalid NAME"
42 };
43
44 char *
45 scherr2str(int code)
46 {
47         if ( code < 0 || code >= (sizeof(err2text)/sizeof(char *)) ) {
48                 return "Unknown error";
49         } else {
50                 return err2text[code];
51         }
52 }
53
54 /* check schema descr validity */
55 int slap_valid_descr( const char *descr )
56 {
57         int i=0;
58
59         if( !DESC_LEADCHAR( descr[i] ) ) {
60                 return 0;
61         }
62
63         while( descr[++i] ) {
64                 if( !DESC_CHAR( descr[i] ) ) {
65                         return 0;
66                 }
67         }
68
69         return 1;
70 }
71
72
73 /* OID Macros */
74
75 /* String compare with delimiter check. Return 0 if not
76  * matched, otherwise return length matched.
77  */
78 int
79 dscompare(const char *s1, const char *s2, char delim)
80 {
81         const char *orig = s1;
82         while (*s1++ == *s2++)
83                 if (!s1[-1]) break;
84         --s1;
85         --s2;
86         if (!*s1 && (!*s2 || *s2 == delim))
87                 return s1 - orig;
88         return 0;
89 }
90
91 static OidMacro *om_list = NULL;
92
93 /* Replace an OID Macro invocation with its full numeric OID.
94  * If the macro is used with "macroname:suffix" append ".suffix"
95  * to the expansion.
96  */
97 static char *
98 find_oidm(char *oid)
99 {
100         OidMacro *om;
101
102         /* OID macros must start alpha */
103         if ( OID_LEADCHAR( *oid ) )     {
104                 return oid;
105         }
106
107     for (om = om_list; om; om=om->som_next) {
108                 char **names = om->som_names;
109
110                 if( names == NULL ) {
111                         continue;
112                 }
113
114                 for( ; *names != NULL ; names++ ) {
115                         int pos = dscompare(*names, oid, ':');
116
117                         if( pos ) {
118                                 int suflen = strlen(oid + pos);
119                                 char *new = ch_calloc(1,
120                                         om->som_oid.bv_len + suflen + 1);
121                                 strcpy(new, om->som_oid.bv_val);
122
123                                 if( suflen ) {
124                                         suflen = om->som_oid.bv_len;
125                                         new[suflen++] = '.';
126                                         strcpy(new+suflen, oid+pos+1);
127                                 }
128                                 return new;
129                         }
130                 }
131         }
132         return NULL;
133 }
134
135 int
136 parse_oidm(
137     const char  *fname,
138     int         lineno,
139     int         argc,
140     char        **argv
141 )
142 {
143         char *oid;
144         OidMacro *om;
145
146         if (argc != 3) {
147                 fprintf( stderr, "%s: line %d: too many arguments\n",
148                         fname, lineno );
149 usage:  fprintf( stderr, "\tObjectIdentifier <name> <oid>\n");
150                 return 1;
151         }
152
153         oid = find_oidm( argv[1] );
154         if( oid != NULL ) {
155                 fprintf( stderr,
156                         "%s: line %d: "
157                         "ObjectIdentifier \"%s\" previously defined \"%s\"",
158                         fname, lineno, argv[1], oid );
159                 return 1;
160         }
161
162         om = (OidMacro *) ch_malloc( sizeof(OidMacro) );
163
164         om->som_names = NULL;
165         charray_add( &om->som_names, argv[1] );
166         om->som_oid.bv_val = find_oidm( argv[2] );
167
168         if (!om->som_oid.bv_val) {
169                 fprintf( stderr, "%s: line %d: OID %s not recognized\n",
170                         fname, lineno, argv[2] );
171                 goto usage;
172         }
173
174         if (om->som_oid.bv_val == argv[2]) {
175                 om->som_oid.bv_val = ch_strdup( argv[2] );
176         }
177
178         om->som_oid.bv_len = strlen( om->som_oid.bv_val );
179         om->som_next = om_list;
180         om_list = om;
181
182         return 0;
183 }
184
185 int
186 parse_oc(
187     const char  *fname,
188     int         lineno,
189     char        *line,
190     char        **argv
191 )
192 {
193         LDAPObjectClass *oc;
194         int             code;
195         const char      *err;
196         char            *oid = NULL;
197
198         oc = ldap_str2objectclass(line,&code,&err,LDAP_SCHEMA_ALLOW_ALL);
199         if ( !oc ) {
200                 fprintf( stderr, "%s: line %d: %s before %s\n",
201                          fname, lineno, ldap_scherr2str(code), err );
202                 oc_usage();
203                 return 1;
204         }
205
206         if ( oc->oc_oid ) {
207                 if ( !OID_LEADCHAR( oc->oc_oid[0] )) {
208                         /* Expand OID macros */
209                         oid = find_oidm( oc->oc_oid );
210                         if ( !oid ) {
211                                 fprintf(stderr,
212                                         "%s: line %d: OID %s not recognized\n",
213                                         fname, lineno, oc->oc_oid);
214                                 return 1;
215                         }
216                         if ( oid != oc->oc_oid ) {
217                                 ldap_memfree( oc->oc_oid );
218                                 oc->oc_oid = oid;
219                         }
220                 }
221         }
222
223         /* oc->oc_oid == NULL will be an error someday */
224         code = oc_add(oc,&err);
225         if ( code ) {
226                 fprintf( stderr, "%s: line %d: %s: \"%s\"\n",
227                          fname, lineno, scherr2str(code), err);
228                 return 1;
229         }
230
231         ldap_memfree(oc);
232         return 0;
233 }
234
235 static void
236 oc_usage( void )
237 {
238         fprintf( stderr,
239                 "ObjectClassDescription = \"(\" whsp\n"
240                 "  numericoid whsp                 ; ObjectClass identifier\n"
241                 "  [ \"NAME\" qdescrs ]\n"
242                 "  [ \"DESC\" qdstring ]\n"
243                 "  [ \"OBSOLETE\" whsp ]\n"
244                 "  [ \"SUP\" oids ]                ; Superior ObjectClasses\n"
245                 "  [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n"
246                 "                                  ; default structural\n"
247                 "  [ \"MUST\" oids ]               ; AttributeTypes\n"
248                 "  [ \"MAY\" oids ]                ; AttributeTypes\n"
249                 "  whsp \")\"\n" );
250 }
251
252
253 static void
254 at_usage( void )
255 {
256         fprintf( stderr,
257                 "AttributeTypeDescription = \"(\" whsp\n"
258                 "  numericoid whsp      ; AttributeType identifier\n"
259                 "  [ \"NAME\" qdescrs ]             ; name used in AttributeType\n"
260                 "  [ \"DESC\" qdstring ]            ; description\n"
261                 "  [ \"OBSOLETE\" whsp ]\n"
262                 "  [ \"SUP\" woid ]                 ; derived from this other\n"
263                 "                                   ; AttributeType\n"
264                 "  [ \"EQUALITY\" woid ]            ; Matching Rule name\n"
265                 "  [ \"ORDERING\" woid ]            ; Matching Rule name\n"
266                 "  [ \"SUBSTR\" woid ]              ; Matching Rule name\n"
267                 "  [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n"
268                 "  [ \"SINGLE-VALUE\" whsp ]        ; default multi-valued\n"
269                 "  [ \"COLLECTIVE\" whsp ]          ; default not collective\n"
270                 "  [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n"
271                 "  [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n"
272                 "                                   ; userApplications\n"
273                 "                                   ; directoryOperation\n"
274                 "                                   ; distributedOperation\n"
275                 "                                   ; dSAOperation\n"
276                 "  whsp \")\"\n");
277 }
278
279 int
280 parse_at(
281     const char  *fname,
282     int         lineno,
283     char        *line,
284     char        **argv
285 )
286 {
287         LDAPAttributeType *at;
288         int             code;
289         const char      *err;
290         char            *oid = NULL;
291         char            *soid = NULL;
292
293         at = ldap_str2attributetype(line,&code,&err,LDAP_SCHEMA_ALLOW_ALL);
294         if ( !at ) {
295                 fprintf( stderr, "%s: line %d: %s before %s\n",
296                          fname, lineno, ldap_scherr2str(code), err );
297                 at_usage();
298                 return 1;
299         }
300         if ( at->at_oid ) {
301                 if ( !OID_LEADCHAR( at->at_oid[0] )) {
302                         /* Expand OID macros */
303                         oid = find_oidm( at->at_oid );
304                         if ( !oid ) {
305                                 fprintf(stderr,
306                                         "%s: line %d: OID %s not recognized\n",
307                                         fname, lineno, at->at_oid);
308                                 return 1;
309                         }
310                         if ( oid != at->at_oid ) {
311                                 ldap_memfree( at->at_oid );
312                                 at->at_oid = oid;
313                         }
314                 }
315         }
316         /* at->at_oid == NULL will be an error someday */
317         if ( at->at_syntax_oid && !OID_LEADCHAR( at->at_syntax_oid[0] )) {
318                 /* Expand OID macros */
319                 oid = find_oidm( at->at_syntax_oid );
320                 if ( !oid ) {
321                         fprintf(stderr,
322                                 "%s: line %d: OID %s not recognized\n",
323                                 fname, lineno, at->at_syntax_oid);
324                         return 1;
325                 }
326                 if ( oid != at->at_syntax_oid ) {
327                         ldap_memfree( at->at_syntax_oid );
328                         at->at_syntax_oid = oid;
329                 }
330
331         }
332         code = at_add(at,&err);
333         if ( code ) {
334                 fprintf( stderr, "%s: line %d: %s: \"%s\"\n",
335                          fname, lineno, scherr2str(code), err);
336                 return 1;
337         }
338         ldap_memfree(at);
339         return 0;
340 }