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