]> git.sur5r.net Git - openldap/blob - servers/slapd/schemaparse.c
7009c265a91a443629ec3999170262ba9eff4940
[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         "Success",
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 < 0 || code >= (sizeof(err2text)/sizeof(char *)) ) {
44                 return "Unknown error";
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 ( OID_LEADCHAR( *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         LDAPObjectClass *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 ( !OID_LEADCHAR( 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,
210                 "ObjectClassDescription = \"(\" whsp\n"
211                 "  numericoid whsp                 ; ObjectClass identifier\n"
212                 "  [ \"NAME\" qdescrs ]\n"
213                 "  [ \"DESC\" qdstring ]\n"
214                 "  [ \"OBSOLETE\" whsp ]\n"
215                 "  [ \"SUP\" oids ]                ; Superior ObjectClasses\n"
216                 "  [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n"
217                 "                                  ; default structural\n"
218                 "  [ \"MUST\" oids ]               ; AttributeTypes\n"
219                 "  [ \"MAY\" oids ]                ; AttributeTypes\n"
220                 "  whsp \")\"\n" );
221         exit( EXIT_FAILURE );
222 }
223
224
225 static void
226 at_usage( void )
227 {
228         fprintf( stderr,
229                 "AttributeTypeDescription = \"(\" whsp\n"
230                 "  numericoid whsp      ; AttributeType identifier\n"
231                 "  [ \"NAME\" qdescrs ]             ; name used in AttributeType\n"
232                 "  [ \"DESC\" qdstring ]            ; description\n"
233                 "  [ \"OBSOLETE\" whsp ]\n"
234                 "  [ \"SUP\" woid ]                 ; derived from this other\n"
235                 "                                   ; AttributeType\n"
236                 "  [ \"EQUALITY\" woid ]            ; Matching Rule name\n"
237                 "  [ \"ORDERING\" woid ]            ; Matching Rule name\n"
238                 "  [ \"SUBSTR\" woid ]              ; Matching Rule name\n"
239                 "  [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n"
240                 "  [ \"SINGLE-VALUE\" whsp ]        ; default multi-valued\n"
241                 "  [ \"COLLECTIVE\" whsp ]          ; default not collective\n"
242                 "  [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n"
243                 "  [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n"
244                 "                                   ; userApplications\n"
245                 "                                   ; directoryOperation\n"
246                 "                                   ; distributedOperation\n"
247                 "                                   ; dSAOperation\n"
248                 "  whsp \")\"\n");
249         exit( EXIT_FAILURE );
250 }
251
252 void
253 parse_at(
254     const char  *fname,
255     int         lineno,
256     char        *line,
257     char        **argv
258 )
259 {
260         LDAPAttributeType *at;
261         int             code;
262         const char      *err;
263         char            *oid = NULL;
264         char            *soid = NULL;
265
266         /* Kludge for OIDmacros for syntaxes. If the syntax field starts
267          * nonnumeric, look for and expand a macro. The macro's place in
268          * the input line will be replaced with a field of '0's to keep
269          * ldap_str2attributetype happy. The actual oid will be swapped
270          * into place afterwards.
271          */
272         for (; argv[3]; argv++)
273         {
274                 if (!strcasecmp(argv[3], "syntax") &&
275                     !OID_LEADCHAR(*argv[4]))
276                 {
277                         int slen;
278                         Syntax *syn;
279                         syn = syn_find_desc(argv[4], &slen);
280                         if (!syn)
281                         {
282                             fprintf(stderr, "%s: line %d: OID %s not found\n",
283                                 fname, lineno, argv[4]);
284                             exit( EXIT_FAILURE );
285                         }
286                         memset(strstr(line, argv[4]), '0', slen);
287                         soid = ch_strdup(syn->ssyn_syn.syn_oid );
288                         break;
289                 }
290         }
291         at = ldap_str2attributetype(line,&code,&err,LDAP_SCHEMA_ALLOW_ALL);
292         if ( !at ) {
293                 fprintf( stderr, "%s: line %d: %s before %s\n",
294                          fname, lineno, ldap_scherr2str(code), err );
295                 at_usage();
296         }
297         if ( at->at_oid ) {
298                 if ( !OID_LEADCHAR( at->at_oid[0] )) {
299                         /* Expand OID macros */
300                         oid = find_oidm( at->at_oid );
301                         if ( !oid ) {
302                                 fprintf(stderr,
303                                         "%s: line %d: OID %s not recognized\n",
304                                         fname, lineno, at->at_oid);
305                                 exit( EXIT_FAILURE );
306                         }
307                         if ( oid != at->at_oid ) {
308                                 ldap_memfree( at->at_oid );
309                                 at->at_oid = oid;
310                         }
311                 }
312         }
313         /* at->at_oid == NULL will be an error someday */
314         if (soid) {
315                 ldap_memfree(at->at_syntax_oid);
316                 at->at_syntax_oid = soid;
317         }
318         code = at_add(at,&err);
319         if ( code ) {
320                 fprintf( stderr, "%s: line %d: %s: \"%s\"\n",
321                          fname, lineno, scherr2str(code), err);
322                 exit( EXIT_FAILURE );
323         }
324         ldap_memfree(at);
325 }