]> git.sur5r.net Git - openldap/blob - servers/slapd/schemaparse.c
93aa7da6ebb188a19b1976c46105f4fdc0cfa26b
[openldap] / servers / slapd / schemaparse.c
1 /* schemaparse.c - routines to parse config file objectclass definitions */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2007 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16
17 #include "portable.h"
18
19 #include <stdio.h>
20
21 #include <ac/ctype.h>
22 #include <ac/string.h>
23 #include <ac/socket.h>
24
25 #include "slap.h"
26 #include "ldap_schema.h"
27 #include "config.h"
28
29 static void             oc_usage(void); 
30 static void             at_usage(void);
31
32 static char *const err2text[] = {
33         "Success",
34         "Out of memory",
35         "ObjectClass not found",
36         "user-defined ObjectClass includes operational attributes",
37         "user-defined ObjectClass has inappropriate SUPerior",
38         "Duplicate objectClass",
39         "Inconsistent duplicate objectClass",
40         "AttributeType not found",
41         "AttributeType inappropriate matching rule",
42         "AttributeType inappropriate USAGE",
43         "AttributeType inappropriate SUPerior",
44         "AttributeType SYNTAX or SUPerior required",
45         "Duplicate attributeType",
46         "Inconsistent duplicate attributeType",
47         "MatchingRule not found",
48         "MatchingRule incomplete",
49         "Duplicate matchingRule",
50         "Syntax not found",
51         "Duplicate ldapSyntax",
52         "Superior syntax not found",
53         "OID or name required",
54         "Qualifier not supported",
55         "Invalid NAME",
56         "OID could not be expanded",
57         "Duplicate Content Rule",
58         "Content Rule not for STRUCTURAL object class",
59         "Content Rule AUX contains inappropriate object class",
60         "Content Rule attribute type list contains duplicate",
61         NULL
62 };
63
64 char *
65 scherr2str(int code)
66 {
67         if ( code < 0 || SLAP_SCHERR_LAST <= code ) {
68                 return "Unknown error";
69         } else {
70                 return err2text[code];
71         }
72 }
73
74 /* check schema descr validity */
75 int slap_valid_descr( const char *descr )
76 {
77         int i=0;
78
79         if( !DESC_LEADCHAR( descr[i] ) ) {
80                 return 0;
81         }
82
83         while( descr[++i] ) {
84                 if( !DESC_CHAR( descr[i] ) ) {
85                         return 0;
86                 }
87         }
88
89         return 1;
90 }
91
92
93 /* OID Macros */
94
95 /* String compare with delimiter check. Return 0 if not
96  * matched, otherwise return length matched.
97  */
98 int
99 dscompare(const char *s1, const char *s2, char delim)
100 {
101         const char *orig = s1;
102         while (*s1++ == *s2++)
103                 if (!s1[-1]) break;
104         --s1;
105         --s2;
106         if (!*s1 && (!*s2 || *s2 == delim))
107                 return s1 - orig;
108         return 0;
109 }
110
111 static void
112 cr_usage( void )
113 {
114         fprintf( stderr,
115                 "DITContentRuleDescription = \"(\" whsp\n"
116                 "  numericoid whsp       ; StructuralObjectClass identifier\n"
117                 "  [ \"NAME\" qdescrs ]\n"
118                 "  [ \"DESC\" qdstring ]\n"
119                 "  [ \"OBSOLETE\" whsp ]\n"
120                 "  [ \"AUX\" oids ]      ; Auxiliary ObjectClasses\n"
121                 "  [ \"MUST\" oids ]     ; AttributeTypes\n"
122                 "  [ \"MAY\" oids ]      ; AttributeTypes\n"
123                 "  [ \"NOT\" oids ]      ; AttributeTypes\n"
124                 "  whsp \")\"\n" );
125 }
126
127 int
128 parse_cr(
129         struct config_args_s *c,
130         ContentRule     **scr )
131 {
132         LDAPContentRule *cr;
133         int             code;
134         const char      *err;
135         char *line = strchr( c->line, '(' );
136
137         cr = ldap_str2contentrule( line, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
138         if ( !cr ) {
139                 snprintf( c->msg, sizeof( c->msg ), "%s: %s before %s",
140                         c->argv[0], ldap_scherr2str( code ), err );
141                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
142                         "%s %s\n", c->log, c->msg, 0 );
143                 cr_usage();
144                 return 1;
145         }
146
147         if ( cr->cr_oid == NULL ) {
148                 snprintf( c->msg, sizeof( c->msg ), "%s: OID is missing",
149                         c->argv[0] );
150                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
151                         "%s %s\n", c->log, c->msg, 0 );
152                 cr_usage();
153                 code = 1;
154                 goto done;
155         }
156
157         code = cr_add( cr, 1, scr, &err );
158         if ( code ) {
159                 snprintf( c->msg, sizeof( c->msg ), "%s: %s: \"%s\"",
160                         c->argv[0], scherr2str(code), err);
161                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
162                         "%s %s\n", c->log, c->msg, 0 );
163                 code = 1;
164                 goto done;
165         }
166
167 done:;
168         if ( code ) {
169                 ldap_contentrule_free( cr );
170
171         } else {
172                 ldap_memfree( cr );
173         }
174
175         return code;
176 }
177
178 int
179 parse_oc(
180         struct config_args_s *c,
181         ObjectClass     **soc,
182         ObjectClass *prev )
183 {
184         LDAPObjectClass *oc;
185         int             code;
186         const char      *err;
187         char *line = strchr( c->line, '(' );
188
189         oc = ldap_str2objectclass(line, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
190         if ( !oc ) {
191                 snprintf( c->msg, sizeof( c->msg ), "%s: %s before %s",
192                         c->argv[0], ldap_scherr2str( code ), err );
193                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
194                         "%s %s\n", c->log, c->msg, 0 );
195                 oc_usage();
196                 return 1;
197         }
198
199         if ( oc->oc_oid == NULL ) {
200                 snprintf( c->msg, sizeof( c->msg ), "%s: OID is missing",
201                         c->argv[0] );
202                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
203                         "%s %s\n", c->log, c->msg, 0 );
204                 oc_usage();
205                 code = 1;
206                 goto done;
207         }
208
209         code = oc_add( oc, 1, soc, prev, &err );
210         if ( code ) {
211                 snprintf( c->msg, sizeof( c->msg ), "%s: %s: \"%s\"",
212                         c->argv[0], scherr2str(code), err);
213                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
214                         "%s %s\n", c->log, c->msg, 0 );
215                 code = 1;
216                 goto done;
217         }
218
219 done:;
220         if ( code ) {
221                 ldap_objectclass_free( oc );
222
223         } else {
224                 ldap_memfree( oc );
225         }
226
227         return code;
228 }
229
230 static void
231 oc_usage( void )
232 {
233         fprintf( stderr,
234                 "ObjectClassDescription = \"(\" whsp\n"
235                 "  numericoid whsp                 ; ObjectClass identifier\n"
236                 "  [ \"NAME\" qdescrs ]\n"
237                 "  [ \"DESC\" qdstring ]\n"
238                 "  [ \"OBSOLETE\" whsp ]\n"
239                 "  [ \"SUP\" oids ]                ; Superior ObjectClasses\n"
240                 "  [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n"
241                 "                                  ; default structural\n"
242                 "  [ \"MUST\" oids ]               ; AttributeTypes\n"
243                 "  [ \"MAY\" oids ]                ; AttributeTypes\n"
244                 "  whsp \")\"\n" );
245 }
246
247 static void
248 at_usage( void )
249 {
250         fprintf( stderr, "%s%s%s",
251                 "AttributeTypeDescription = \"(\" whsp\n"
252                 "  numericoid whsp      ; AttributeType identifier\n"
253                 "  [ \"NAME\" qdescrs ]             ; name used in AttributeType\n"
254                 "  [ \"DESC\" qdstring ]            ; description\n"
255                 "  [ \"OBSOLETE\" whsp ]\n"
256                 "  [ \"SUP\" woid ]                 ; derived from this other\n"
257                 "                                   ; AttributeType\n",
258                 "  [ \"EQUALITY\" woid ]            ; Matching Rule name\n"
259                 "  [ \"ORDERING\" woid ]            ; Matching Rule name\n"
260                 "  [ \"SUBSTR\" woid ]              ; Matching Rule name\n"
261                 "  [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n"
262                 "  [ \"SINGLE-VALUE\" whsp ]        ; default multi-valued\n"
263                 "  [ \"COLLECTIVE\" whsp ]          ; default not collective\n",
264                 "  [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n"
265                 "  [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n"
266                 "                                   ; userApplications\n"
267                 "                                   ; directoryOperation\n"
268                 "                                   ; distributedOperation\n"
269                 "                                   ; dSAOperation\n"
270                 "  whsp \")\"\n");
271 }
272
273 int
274 parse_at(
275         struct config_args_s *c,
276         AttributeType   **sat,
277         AttributeType   *prev )
278 {
279         LDAPAttributeType *at;
280         int             code;
281         const char      *err;
282         char *line = strchr( c->line, '(' );
283
284         at = ldap_str2attributetype( line, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
285         if ( !at ) {
286                 snprintf( c->msg, sizeof( c->msg ), "%s: %s before %s",
287                         c->argv[0], ldap_scherr2str(code), err );
288                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
289                         "%s %s\n", c->log, c->msg, 0 );
290                 at_usage();
291                 return 1;
292         }
293
294         if ( at->at_oid == NULL ) {
295                 snprintf( c->msg, sizeof( c->msg ), "%s: OID is missing",
296                         c->argv[0] );
297                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
298                         "%s %s\n", c->log, c->msg, 0 );
299                 at_usage();
300                 code = 1;
301                 goto done;
302         }
303
304         /* operational attributes should be defined internally */
305         if ( at->at_usage ) {
306                 snprintf( c->msg, sizeof( c->msg ), "%s: \"%s\" is operational",
307                         c->argv[0], at->at_oid );
308                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
309                         "%s %s\n", c->log, c->msg, 0 );
310                 code = 1;
311                 goto done;
312         }
313
314         code = at_add( at, 1, sat, prev, &err);
315         if ( code ) {
316                 snprintf( c->msg, sizeof( c->msg ), "%s: %s: \"%s\"",
317                         c->argv[0], scherr2str(code), err);
318                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
319                         "%s %s\n", c->log, c->msg, 0 );
320                 code = 1;
321                 goto done;
322         }
323
324 done:;
325         if ( code ) {
326                 ldap_attributetype_free( at );
327
328         } else {
329                 ldap_memfree( at );
330         }
331
332         return code;
333 }