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