]> git.sur5r.net Git - openldap/blob - servers/slapd/schemaparse.c
Per ITS#419, don't require SLAPD_RLOOKUPS when HAVE_TCPD
[openldap] / servers / slapd / schemaparse.c
1 /* schemaparse.c - routines to parse config file objectclass definitions */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-1999 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_old(void) LDAP_GCCATTR((noreturn));
22 static void             oc_usage(void)     LDAP_GCCATTR((noreturn));
23 static void             at_usage(void)     LDAP_GCCATTR((noreturn));
24
25 static char *const err2text[] = {
26         "",
27         "Out of memory",
28         "Objectclass not found",
29         "Attribute type not found",
30         "Duplicate objectclass",
31         "Duplicate attributetype",
32         "Duplicate syntax",
33         "Duplicate matchingrule",
34         "OID or name required",
35         "Syntax or superior required",
36         "Matchingrule not found",
37         "Syntax not found",
38         "Syntax required"
39 };
40
41 char *
42 scherr2str(int code)
43 {
44         if ( code < 1 || code >= (sizeof(err2text)/sizeof(char *)) ) {
45                 return "Unknown error";
46         } else {
47                 return err2text[code];
48         }
49 }
50
51 void
52 parse_oc_old(
53     Backend     *be,
54     const char  *fname,
55     int         lineno,
56     int         argc,
57     char        **argv
58 )
59 {
60         int             i;
61         char            last;
62         LDAP_OBJECT_CLASS       *oc;
63         int             code;
64         const char      *err;
65         char            **namep;
66
67         oc = (LDAP_OBJECT_CLASS *) ch_calloc( 1, sizeof(LDAP_OBJECT_CLASS) );
68         oc->oc_names = ch_calloc( 2, sizeof(char *) );
69         oc->oc_names[0] = ch_strdup( argv[1] );
70         oc->oc_names[1] = NULL;
71         if ( strcasecmp( oc->oc_names[0], "top" ) ) {
72                 oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
73         }
74         for ( i = 2; i < argc; i++ ) {
75                 /* required attributes */
76                 if ( strcasecmp( argv[i], "requires" ) == 0 ) {
77                         do {
78                                 i++;
79                                 if ( i < argc ) {
80                                         char **s = str2charray( argv[i], "," );
81                                         last = argv[i][strlen( argv[i] ) - 1];
82                                         charray_merge( &oc->oc_at_oids_must, s );
83                                         charray_free( s );
84                                 }
85                         } while ( i < argc && last == ',' );
86
87                 /* optional attributes */
88                 } else if ( strcasecmp( argv[i], "allows" ) == 0 ) {
89                         do {
90                                 i++;
91                                 if ( i < argc ) {
92                                         char **s = str2charray( argv[i], "," );
93                                         last = argv[i][strlen( argv[i] ) - 1];
94                                         
95                                         charray_merge( &oc->oc_at_oids_may, s );
96                                         charray_free( s );
97                                 }
98                         } while ( i < argc && last == ',' );
99
100                 } else {
101                         fprintf( stderr,
102             "%s: line %d: expecting \"requires\" or \"allows\" got \"%s\"\n",
103                             fname, lineno, argv[i] );
104                         oc_usage_old();
105                 }
106         }
107
108         /*
109          * There was no requirement in the old schema that all attributes
110          * types were defined before use and they would just default to
111          * SYNTAX_CIS.  To support this, we need to make attribute types
112          * out of thin air.
113          */
114         if ( oc->oc_at_oids_must ) {
115                 namep = oc->oc_at_oids_must;
116                 while ( *namep ) {
117                         code = at_fake_if_needed( *namep );
118                         if ( code ) {
119                                 fprintf( stderr, "%s: line %d: %s %s\n",
120                                          fname, lineno, scherr2str(code), *namep);
121                                 exit( EXIT_FAILURE );
122                         }
123                         namep++;
124                 }
125         }
126         if ( oc->oc_at_oids_may ) {
127                 namep = oc->oc_at_oids_may;
128                 while ( *namep ) {
129                         code = at_fake_if_needed( *namep );
130                         if ( code ) {
131                                 fprintf( stderr, "%s: line %d: %s %s\n",
132                                          fname, lineno, scherr2str(code), *namep);
133                                 exit( EXIT_FAILURE );
134                         }
135                         namep++;
136                 }
137         }
138         
139         code = oc_add(oc,&err);
140         if ( code ) {
141                 fprintf( stderr, "%s: line %d: %s %s\n",
142                          fname, lineno, scherr2str(code), err);
143                 exit( EXIT_FAILURE );
144         }
145         ldap_memfree(oc);
146 }
147
148 /* OID Macros */
149
150 /* String compare with delimiter check. Return 0 if not
151  * matched, otherwise return length matched.
152  */
153 int
154 dscompare(const char *s1, const char *s2, char delim)
155 {
156         const char *orig = s1;
157         while (*s1++ == *s2++)
158                 if (!s1[-1]) break;
159         --s1;
160         --s2;
161         if (!*s1 && (!*s2 || *s2 == delim))
162                 return s1 - orig;
163         return 0;
164 }
165
166 static OidMacro *om_list = NULL;
167
168 /* Replace an OID Macro invocation with its full numeric OID.
169  * If the macro is used with "macroname:suffix" append ".suffix"
170  * to the expansion.
171  */
172 static char *
173 find_oidm(char *oid)
174 {
175         OidMacro *om;
176         char *new;
177         int pos, suflen;
178
179         /* OID macros must start alpha */
180         if ( !isdigit( *oid ) )
181         {
182             for (om = om_list; om; om=om->next)
183             {
184                 if ((pos = dscompare(om->name, oid, ':')))
185                 {
186                         suflen = strlen(oid + pos);
187                         new = ch_calloc(1, om->oidlen + suflen + 1);
188                         strcpy(new, om->oid);
189                         if (suflen)
190                         {
191                                 suflen = om->oidlen;
192                                 new[suflen++] = '.';
193                                 strcpy(new+suflen, oid+pos+1);
194                         }
195                         return new;
196                 }
197             }
198             return NULL;
199         }
200         return oid;
201 }
202
203 void
204 parse_oidm(
205     const char  *fname,
206     int         lineno,
207     int         argc,
208     char        **argv
209 )
210 {
211         OidMacro *om;
212
213         if (argc != 3)
214         {
215 usage:          fprintf( stderr, "ObjectIdentifier <name> <oid>\n");
216                 exit( EXIT_FAILURE );
217         }
218         om = (OidMacro *) ch_malloc( sizeof(OidMacro) );
219         om->name = ch_strdup( argv[1] );
220         om->oid = find_oidm( argv[2] );
221         if (!om->oid)
222         {
223                 fprintf( stderr, "%s: line %d: OID %s not recognized\n",
224                         fname, lineno, argv[2] );
225                 goto usage;
226         }
227         if (om->oid == argv[2])
228                 om->oid = ch_strdup( argv[2] );
229         om->oidlen = strlen( om->oid );
230         om->next = om_list;
231         om_list = om;
232 }
233
234 void
235 parse_oc(
236     const char  *fname,
237     int         lineno,
238     char        *line,
239     char        **argv
240 )
241 {
242         LDAP_OBJECT_CLASS *oc;
243         int             code;
244         const char      *err;
245         char            *oid = NULL;
246
247         oc = ldap_str2objectclass(line,&code,&err);
248         if ( !oc ) {
249                 fprintf( stderr, "%s: line %d: %s before %s\n",
250                          fname, lineno, ldap_scherr2str(code), err );
251                 oc_usage();
252         }
253         if ( oc->oc_oid ) {
254                 if ( !isdigit( oc->oc_oid[0] )) {
255                         /* Expand OID macros */
256                         oid = find_oidm( oc->oc_oid );
257                         if ( !oid ) {
258                                 fprintf(stderr,
259                                         "%s: line %d: OID %s not recognized\n",
260                                         fname, lineno, oc->oc_oid);
261                                 exit( EXIT_FAILURE );
262                         }
263                         if ( oid != oc->oc_oid ) {
264                                 ldap_memfree( oc->oc_oid );
265                                 oc->oc_oid = oid;
266                         }
267                 }
268         }
269         /* oc->oc_oid == NULL will be an error someday */
270         code = oc_add(oc,&err);
271         if ( code ) {
272                 fprintf( stderr, "%s: line %d: %s %s\n",
273                          fname, lineno, scherr2str(code), err);
274                 exit( EXIT_FAILURE );
275         }
276         ldap_memfree(oc);
277 }
278
279 static void
280 oc_usage( void )
281 {
282         fprintf( stderr, "ObjectClassDescription = \"(\" whsp\n");
283         fprintf( stderr, "  numericoid whsp      ; ObjectClass identifier\n");
284         fprintf( stderr, "  [ \"NAME\" qdescrs ]\n");
285         fprintf( stderr, "  [ \"DESC\" qdstring ]\n");
286         fprintf( stderr, "  [ \"OBSOLETE\" whsp ]\n");
287         fprintf( stderr, "  [ \"SUP\" oids ]       ; Superior ObjectClasses\n");
288         fprintf( stderr, "  [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n");
289         fprintf( stderr, "                       ; default structural\n");
290         fprintf( stderr, "  [ \"MUST\" oids ]      ; AttributeTypes\n");
291         fprintf( stderr, "  [ \"MAY\" oids ]       ; AttributeTypes\n");
292         fprintf( stderr, "whsp \")\"\n");
293         exit( EXIT_FAILURE );
294 }
295
296 static void
297 oc_usage_old( void )
298 {
299         fprintf( stderr, "<oc clause> ::= objectclass <ocname>\n" );
300         fprintf( stderr, "                [ requires <attrlist> ]\n" );
301         fprintf( stderr, "                [ allows <attrlist> ]\n" );
302         exit( EXIT_FAILURE );
303 }
304
305 static void
306 at_usage( void )
307 {
308         fprintf( stderr, "AttributeTypeDescription = \"(\" whsp\n");
309         fprintf( stderr, "  numericoid whsp      ; AttributeType identifier\n");
310         fprintf( stderr, "  [ \"NAME\" qdescrs ]             ; name used in AttributeType\n");
311         fprintf( stderr, "  [ \"DESC\" qdstring ]            ; description\n");
312         fprintf( stderr, "  [ \"OBSOLETE\" whsp ]\n");
313         fprintf( stderr, "  [ \"SUP\" woid ]                 ; derived from this other\n");
314         fprintf( stderr, "                                 ; AttributeType\n");
315         fprintf( stderr, "  [ \"EQUALITY\" woid ]            ; Matching Rule name\n");
316         fprintf( stderr, "  [ \"ORDERING\" woid ]            ; Matching Rule name\n");
317         fprintf( stderr, "  [ \"SUBSTR\" woid ]              ; Matching Rule name\n");
318         fprintf( stderr, "  [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n");
319         fprintf( stderr, "  [ \"SINGLE-VALUE\" whsp ]        ; default multi-valued\n");
320         fprintf( stderr, "  [ \"COLLECTIVE\" whsp ]          ; default not collective\n");
321         fprintf( stderr, "  [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n");
322         fprintf( stderr, "  [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n");
323         fprintf( stderr, "                                 ; userApplications\n");
324         fprintf( stderr, "                                 ; directoryOperation\n");
325         fprintf( stderr, "                                 ; distributedOperation\n");
326         fprintf( stderr, "                                 ; dSAOperation\n");
327         fprintf( stderr, "whsp \")\"\n");
328         exit( EXIT_FAILURE );
329 }
330
331 void
332 parse_at(
333     const char  *fname,
334     int         lineno,
335     char        *line,
336     char        **argv
337 )
338 {
339         LDAP_ATTRIBUTE_TYPE *at;
340         int             code;
341         const char      *err;
342         char            *oid = NULL;
343         char            *soid = NULL;
344
345         /* Kludge for OIDmacros for syntaxes. If the syntax field starts
346          * nonnumeric, look for and expand a macro. The macro's place in
347          * the input line will be replaced with a field of '0's to keep
348          * ldap_str2attributetype happy. The actual oid will be swapped
349          * into place afterwards.
350          */
351         for (; argv[3]; argv++)
352         {
353                 if (!strcasecmp(argv[3], "syntax") &&
354                     !isdigit(*argv[4]))
355                 {
356                         int slen;
357                         Syntax *syn;
358                         syn = syn_find_desc(argv[4], &slen);
359                         if (!syn)
360                         {
361                             fprintf(stderr, "%s: line %d: OID %s not found\n",
362                                 fname, lineno, argv[4]);
363                             exit( EXIT_FAILURE );
364                         }
365                         memset(strstr(line, argv[4]), '0', slen);
366                         soid = ch_strdup(syn->ssyn_syn.syn_oid );
367                         break;
368                 }
369         }
370         at = ldap_str2attributetype(line,&code,&err);
371         if ( !at ) {
372                 fprintf( stderr, "%s: line %d: %s before %s\n",
373                          fname, lineno, ldap_scherr2str(code), err );
374                 at_usage();
375         }
376         if ( at->at_oid ) {
377                 if ( !isdigit( at->at_oid[0] )) {
378                         /* Expand OID macros */
379                         oid = find_oidm( at->at_oid );
380                         if ( !oid ) {
381                                 fprintf(stderr,
382                                         "%s: line %d: OID %s not recognized\n",
383                                         fname, lineno, at->at_oid);
384                                 exit( EXIT_FAILURE );
385                         }
386                         if ( oid != at->at_oid ) {
387                                 ldap_memfree( at->at_oid );
388                                 at->at_oid = oid;
389                         }
390                 }
391         }
392         /* at->at_oid == NULL will be an error someday */
393         if (soid)
394         {
395                 ldap_memfree(at->at_syntax_oid);
396                 at->at_syntax_oid = soid;
397         }
398         code = at_add(at,&err);
399         if ( code ) {
400                 fprintf( stderr, "%s: line %d: %s %s\n",
401                          fname, lineno, scherr2str(code), err);
402                 exit( EXIT_FAILURE );
403         }
404         ldap_memfree(at);
405 }