]> git.sur5r.net Git - openldap/blob - servers/slapd/schemaparse.c
4517b78647ed41e3aa2bb062e0fb7f57f397d511
[openldap] / servers / slapd / schemaparse.c
1 /* schemaparse.c - routines to parse config file objectclass 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_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 *tmp = ch_malloc( om->som_oid.bv_len
120                                         + suflen + 1);
121                                 strcpy(tmp, om->som_oid.bv_val);
122                                 if( suflen ) {
123                                         suflen = om->som_oid.bv_len;
124                                         tmp[suflen++] = '.';
125                                         strcpy(tmp+suflen, oid+pos+1);
126                                 }
127                                 return tmp;
128                         }
129                 }
130         }
131         return NULL;
132 }
133
134 void
135 oidm_destroy()
136 {
137         OidMacro *om, *n;
138
139         for (om = om_list; om; om = n) {
140                 n = om->som_next;
141                 charray_free(om->som_names);
142                 free(om->som_oid.bv_val);
143                 free(om);
144         }
145 }
146
147 int
148 parse_oidm(
149     const char  *fname,
150     int         lineno,
151     int         argc,
152     char        **argv
153 )
154 {
155         char *oid;
156         OidMacro *om;
157
158         if (argc != 3) {
159                 fprintf( stderr, "%s: line %d: too many arguments\n",
160                         fname, lineno );
161 usage:  fprintf( stderr, "\tObjectIdentifier <name> <oid>\n");
162                 return 1;
163         }
164
165         oid = find_oidm( argv[1] );
166         if( oid != NULL ) {
167                 fprintf( stderr,
168                         "%s: line %d: "
169                         "ObjectIdentifier \"%s\" previously defined \"%s\"",
170                         fname, lineno, argv[1], oid );
171                 return 1;
172         }
173
174         om = (OidMacro *) ch_malloc( sizeof(OidMacro) );
175
176         om->som_names = NULL;
177         charray_add( &om->som_names, argv[1] );
178         om->som_oid.bv_val = find_oidm( argv[2] );
179
180         if (!om->som_oid.bv_val) {
181                 fprintf( stderr, "%s: line %d: OID %s not recognized\n",
182                         fname, lineno, argv[2] );
183                 goto usage;
184         }
185
186         if (om->som_oid.bv_val == argv[2]) {
187                 om->som_oid.bv_val = ch_strdup( argv[2] );
188         }
189
190         om->som_oid.bv_len = strlen( om->som_oid.bv_val );
191         om->som_next = om_list;
192         om_list = om;
193
194         return 0;
195 }
196
197 int
198 parse_oc(
199     const char  *fname,
200     int         lineno,
201     char        *line,
202     char        **argv
203 )
204 {
205         LDAPObjectClass *oc;
206         int             code;
207         const char      *err;
208         char            *oid = NULL;
209
210         oc = ldap_str2objectclass(line,&code,&err,LDAP_SCHEMA_ALLOW_ALL);
211         if ( !oc ) {
212                 fprintf( stderr, "%s: line %d: %s before %s\n",
213                          fname, lineno, ldap_scherr2str(code), err );
214                 oc_usage();
215                 return 1;
216         }
217
218         if ( oc->oc_oid == NULL ) {
219                 fprintf( stderr,
220                         "%s: line %d: objectclass has no OID\n",
221                         fname, lineno );
222                 oc_usage();
223                 return 1;
224         }
225
226         if ( !OID_LEADCHAR( oc->oc_oid[0] )) {
227                 /* Expand OID macros */
228                 oid = find_oidm( oc->oc_oid );
229                 if ( !oid ) {
230                         fprintf( stderr,
231                                 "%s: line %d: OID %s not recognized\n",
232                                 fname, lineno, oc->oc_oid);
233                         return 1;
234                 }
235                 if ( oid != oc->oc_oid ) {
236                         ldap_memfree( oc->oc_oid );
237                         oc->oc_oid = oid;
238                 }
239         }
240
241         code = oc_add(oc,&err);
242         if ( code ) {
243                 fprintf( stderr, "%s: line %d: %s: \"%s\"\n",
244                          fname, lineno, scherr2str(code), err);
245                 return 1;
246         }
247
248         ldap_memfree(oc);
249         return 0;
250 }
251
252 static void
253 oc_usage( void )
254 {
255         fprintf( stderr,
256                 "ObjectClassDescription = \"(\" whsp\n"
257                 "  numericoid whsp                 ; ObjectClass identifier\n"
258                 "  [ \"NAME\" qdescrs ]\n"
259                 "  [ \"DESC\" qdstring ]\n"
260                 "  [ \"OBSOLETE\" whsp ]\n"
261                 "  [ \"SUP\" oids ]                ; Superior ObjectClasses\n"
262                 "  [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n"
263                 "                                  ; default structural\n"
264                 "  [ \"MUST\" oids ]               ; AttributeTypes\n"
265                 "  [ \"MAY\" oids ]                ; AttributeTypes\n"
266                 "  whsp \")\"\n" );
267 }
268
269
270 static void
271 at_usage( void )
272 {
273         fprintf( stderr,
274                 "AttributeTypeDescription = \"(\" whsp\n"
275                 "  numericoid whsp      ; AttributeType identifier\n"
276                 "  [ \"NAME\" qdescrs ]             ; name used in AttributeType\n"
277                 "  [ \"DESC\" qdstring ]            ; description\n"
278                 "  [ \"OBSOLETE\" whsp ]\n"
279                 "  [ \"SUP\" woid ]                 ; derived from this other\n"
280                 "                                   ; AttributeType\n"
281                 "  [ \"EQUALITY\" woid ]            ; Matching Rule name\n"
282                 "  [ \"ORDERING\" woid ]            ; Matching Rule name\n"
283                 "  [ \"SUBSTR\" woid ]              ; Matching Rule name\n"
284                 "  [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n"
285                 "  [ \"SINGLE-VALUE\" whsp ]        ; default multi-valued\n"
286                 "  [ \"COLLECTIVE\" whsp ]          ; default not collective\n"
287                 "  [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n"
288                 "  [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n"
289                 "                                   ; userApplications\n"
290                 "                                   ; directoryOperation\n"
291                 "                                   ; distributedOperation\n"
292                 "                                   ; dSAOperation\n"
293                 "  whsp \")\"\n");
294 }
295
296 int
297 parse_at(
298     const char  *fname,
299     int         lineno,
300     char        *line,
301     char        **argv
302 )
303 {
304         LDAPAttributeType *at;
305         int             code;
306         const char      *err;
307         char            *oid = NULL;
308
309         at = ldap_str2attributetype(line,&code,&err,LDAP_SCHEMA_ALLOW_ALL);
310         if ( !at ) {
311                 fprintf( stderr, "%s: line %d: %s before %s\n",
312                          fname, lineno, ldap_scherr2str(code), err );
313                 at_usage();
314                 return 1;
315         }
316
317         if ( at->at_oid == NULL ) {
318                 fprintf( stderr,
319                         "%s: line %d: attributeType has no OID\n",
320                         fname, lineno );
321                 at_usage();
322                 return 1;
323         }
324
325 #if 0
326         /* operational attributes should be defined internally */
327         if ( at->at_usage ) {
328                 fprintf( stderr, "%s: line %d: attribute type \"%s\" is operational\n",
329                          fname, lineno, at->at_oid );
330                 return 1;
331         }
332 #endif
333
334         if ( !OID_LEADCHAR( at->at_oid[0] )) {
335                 /* Expand OID macros */
336                 oid = find_oidm( at->at_oid );
337                 if ( !oid ) {
338                         fprintf( stderr,
339                                 "%s: line %d: OID %s not recognized\n",
340                                 fname, lineno, at->at_oid);
341                         return 1;
342                 }
343                 if ( oid != at->at_oid ) {
344                         ldap_memfree( at->at_oid );
345                         at->at_oid = oid;
346                 }
347         }
348
349         if ( at->at_syntax_oid && !OID_LEADCHAR( at->at_syntax_oid[0] )) {
350                 /* Expand OID macros */
351                 oid = find_oidm( at->at_syntax_oid );
352                 if ( !oid ) {
353                         fprintf(stderr,
354                                 "%s: line %d: OID %s not recognized\n",
355                                 fname, lineno, at->at_syntax_oid);
356                         return 1;
357                 }
358                 if ( oid != at->at_syntax_oid ) {
359                         ldap_memfree( at->at_syntax_oid );
360                         at->at_syntax_oid = oid;
361                 }
362
363         }
364
365         code = at_add(at,&err);
366         if ( code ) {
367                 fprintf( stderr, "%s: line %d: %s: \"%s\"\n",
368                          fname, lineno, scherr2str(code), err);
369                 return 1;
370         }
371         ldap_memfree(at);
372         return 0;
373 }