]> git.sur5r.net Git - openldap/blob - servers/slapd/schemaparse.c
e969e9b39066abf64198656555f04247edb8460f
[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 == NULL ) {
207                 fprintf( stderr,
208                         "%s: line %d: objectclass has no OID\n",
209                         fname, lineno );
210                 oc_usage();
211                 return 1;
212         }
213
214         if ( !OID_LEADCHAR( oc->oc_oid[0] )) {
215                 /* Expand OID macros */
216                 oid = find_oidm( oc->oc_oid );
217                 if ( !oid ) {
218                         fprintf( stderr,
219                                 "%s: line %d: OID %s not recognized\n",
220                                 fname, lineno, oc->oc_oid);
221                         return 1;
222                 }
223                 if ( oid != oc->oc_oid ) {
224                         ldap_memfree( oc->oc_oid );
225                         oc->oc_oid = oid;
226                 }
227         }
228
229         code = oc_add(oc,&err);
230         if ( code ) {
231                 fprintf( stderr, "%s: line %d: %s: \"%s\"\n",
232                          fname, lineno, scherr2str(code), err);
233                 return 1;
234         }
235
236         ldap_memfree(oc);
237         return 0;
238 }
239
240 static void
241 oc_usage( void )
242 {
243         fprintf( stderr,
244                 "ObjectClassDescription = \"(\" whsp\n"
245                 "  numericoid whsp                 ; ObjectClass identifier\n"
246                 "  [ \"NAME\" qdescrs ]\n"
247                 "  [ \"DESC\" qdstring ]\n"
248                 "  [ \"OBSOLETE\" whsp ]\n"
249                 "  [ \"SUP\" oids ]                ; Superior ObjectClasses\n"
250                 "  [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n"
251                 "                                  ; default structural\n"
252                 "  [ \"MUST\" oids ]               ; AttributeTypes\n"
253                 "  [ \"MAY\" oids ]                ; AttributeTypes\n"
254                 "  whsp \")\"\n" );
255 }
256
257
258 static void
259 at_usage( void )
260 {
261         fprintf( stderr,
262                 "AttributeTypeDescription = \"(\" whsp\n"
263                 "  numericoid whsp      ; AttributeType identifier\n"
264                 "  [ \"NAME\" qdescrs ]             ; name used in AttributeType\n"
265                 "  [ \"DESC\" qdstring ]            ; description\n"
266                 "  [ \"OBSOLETE\" whsp ]\n"
267                 "  [ \"SUP\" woid ]                 ; derived from this other\n"
268                 "                                   ; AttributeType\n"
269                 "  [ \"EQUALITY\" woid ]            ; Matching Rule name\n"
270                 "  [ \"ORDERING\" woid ]            ; Matching Rule name\n"
271                 "  [ \"SUBSTR\" woid ]              ; Matching Rule name\n"
272                 "  [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n"
273                 "  [ \"SINGLE-VALUE\" whsp ]        ; default multi-valued\n"
274                 "  [ \"COLLECTIVE\" whsp ]          ; default not collective\n"
275                 "  [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n"
276                 "  [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n"
277                 "                                   ; userApplications\n"
278                 "                                   ; directoryOperation\n"
279                 "                                   ; distributedOperation\n"
280                 "                                   ; dSAOperation\n"
281                 "  whsp \")\"\n");
282 }
283
284 int
285 parse_at(
286     const char  *fname,
287     int         lineno,
288     char        *line,
289     char        **argv
290 )
291 {
292         LDAPAttributeType *at;
293         int             code;
294         const char      *err;
295         char            *oid = NULL;
296
297         at = ldap_str2attributetype(line,&code,&err,LDAP_SCHEMA_ALLOW_ALL);
298         if ( !at ) {
299                 fprintf( stderr, "%s: line %d: %s before %s\n",
300                          fname, lineno, ldap_scherr2str(code), err );
301                 at_usage();
302                 return 1;
303         }
304
305         if ( at->at_oid == NULL ) {
306                 fprintf( stderr,
307                         "%s: line %d: attributeType has no OID\n",
308                         fname, lineno );
309                 at_usage();
310                 return 1;
311         }
312
313         if ( !OID_LEADCHAR( at->at_oid[0] )) {
314                 /* Expand OID macros */
315                 oid = find_oidm( at->at_oid );
316                 if ( !oid ) {
317                         fprintf( stderr,
318                                 "%s: line %d: OID %s not recognized\n",
319                                 fname, lineno, at->at_oid);
320                         return 1;
321                 }
322                 if ( oid != at->at_oid ) {
323                         ldap_memfree( at->at_oid );
324                         at->at_oid = oid;
325                 }
326         }
327
328         if ( at->at_syntax_oid && !OID_LEADCHAR( at->at_syntax_oid[0] )) {
329                 /* Expand OID macros */
330                 oid = find_oidm( at->at_syntax_oid );
331                 if ( !oid ) {
332                         fprintf(stderr,
333                                 "%s: line %d: OID %s not recognized\n",
334                                 fname, lineno, at->at_syntax_oid);
335                         return 1;
336                 }
337                 if ( oid != at->at_syntax_oid ) {
338                         ldap_memfree( at->at_syntax_oid );
339                         at->at_syntax_oid = oid;
340                 }
341
342         }
343         code = at_add(at,&err);
344         if ( code ) {
345                 fprintf( stderr, "%s: line %d: %s: \"%s\"\n",
346                          fname, lineno, scherr2str(code), err);
347                 return 1;
348         }
349         ldap_memfree(at);
350         return 0;
351 }