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