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