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