]> git.sur5r.net Git - openldap/blob - servers/slapd/schemaparse.c
22cb966ecea279c9fb1afd51ab9da3309ebf6465
[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         char            *soid = NULL;
297
298         at = ldap_str2attributetype(line,&code,&err,LDAP_SCHEMA_ALLOW_ALL);
299         if ( !at ) {
300                 fprintf( stderr, "%s: line %d: %s before %s\n",
301                          fname, lineno, ldap_scherr2str(code), err );
302                 at_usage();
303                 return 1;
304         }
305
306         if ( at->at_oid == NULL ) {
307                 fprintf( stderr,
308                         "%s: line %d: attributeType has no OID\n",
309                         fname, lineno );
310                 at_usage();
311                 return 1;
312         }
313
314         if ( !OID_LEADCHAR( at->at_oid[0] )) {
315                 /* Expand OID macros */
316                 oid = find_oidm( at->at_oid );
317                 if ( !oid ) {
318                         fprintf( stderr,
319                                 "%s: line %d: OID %s not recognized\n",
320                                 fname, lineno, at->at_oid);
321                         return 1;
322                 }
323                 if ( oid != at->at_oid ) {
324                         ldap_memfree( at->at_oid );
325                         at->at_oid = oid;
326                 }
327         }
328
329         if ( at->at_syntax_oid && !OID_LEADCHAR( at->at_syntax_oid[0] )) {
330                 /* Expand OID macros */
331                 oid = find_oidm( at->at_syntax_oid );
332                 if ( !oid ) {
333                         fprintf(stderr,
334                                 "%s: line %d: OID %s not recognized\n",
335                                 fname, lineno, at->at_syntax_oid);
336                         return 1;
337                 }
338                 if ( oid != at->at_syntax_oid ) {
339                         ldap_memfree( at->at_syntax_oid );
340                         at->at_syntax_oid = oid;
341                 }
342
343         }
344         code = at_add(at,&err);
345         if ( code ) {
346                 fprintf( stderr, "%s: line %d: %s: \"%s\"\n",
347                          fname, lineno, scherr2str(code), err);
348                 return 1;
349         }
350         ldap_memfree(at);
351         return 0;
352 }