]> git.sur5r.net Git - openldap/blob - servers/slapd/schemaparse.c
Happy New Year
[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-2018 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         "Substitute syntax not specified",
54         "Substitute syntax not found",
55         "OID or name required",
56         "Qualifier not supported",
57         "Invalid NAME",
58         "OID could not be expanded",
59         "Duplicate Content Rule",
60         "Content Rule not for STRUCTURAL object class",
61         "Content Rule AUX contains inappropriate object class",
62         "Content Rule attribute type list contains duplicate",
63         NULL
64 };
65
66 char *
67 scherr2str(int code)
68 {
69         if ( code < 0 || SLAP_SCHERR_LAST <= code ) {
70                 return "Unknown error";
71         } else {
72                 return err2text[code];
73         }
74 }
75
76 /* check schema descr validity */
77 int slap_valid_descr( const char *descr )
78 {
79         int i=0;
80
81         if( !DESC_LEADCHAR( descr[i] ) ) {
82                 return 0;
83         }
84
85         while( descr[++i] ) {
86                 if( !DESC_CHAR( descr[i] ) ) {
87                         return 0;
88                 }
89         }
90
91         return 1;
92 }
93
94
95 /* OID Macros */
96
97 /* String compare with delimiter check. Return 0 if not
98  * matched, otherwise return length matched.
99  */
100 int
101 dscompare(const char *s1, const char *s2, char delim)
102 {
103         const char *orig = s1;
104         while (*s1++ == *s2++)
105                 if (!s1[-1]) break;
106         --s1;
107         --s2;
108         if (!*s1 && (!*s2 || *s2 == delim))
109                 return s1 - orig;
110         return 0;
111 }
112
113 static void
114 cr_usage( void )
115 {
116         fprintf( stderr,
117                 "DITContentRuleDescription = \"(\" whsp\n"
118                 "  numericoid whsp       ; StructuralObjectClass identifier\n"
119                 "  [ \"NAME\" qdescrs ]\n"
120                 "  [ \"DESC\" qdstring ]\n"
121                 "  [ \"OBSOLETE\" whsp ]\n"
122                 "  [ \"AUX\" oids ]      ; Auxiliary ObjectClasses\n"
123                 "  [ \"MUST\" oids ]     ; AttributeTypes\n"
124                 "  [ \"MAY\" oids ]      ; AttributeTypes\n"
125                 "  [ \"NOT\" oids ]      ; AttributeTypes\n"
126                 "  whsp \")\"\n" );
127 }
128
129 int
130 parse_cr(
131         struct config_args_s *c,
132         ContentRule     **scr )
133 {
134         LDAPContentRule *cr;
135         int             code;
136         const char      *err;
137         char *line = strchr( c->line, '(' );
138
139         cr = ldap_str2contentrule( line, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
140         if ( !cr ) {
141                 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s before %s",
142                         c->argv[0], ldap_scherr2str( code ), err );
143                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
144                         "%s %s\n", c->log, c->cr_msg, 0 );
145                 cr_usage();
146                 return 1;
147         }
148
149         if ( cr->cr_oid == NULL ) {
150                 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing",
151                         c->argv[0] );
152                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
153                         "%s %s\n", c->log, c->cr_msg, 0 );
154                 cr_usage();
155                 code = 1;
156                 goto done;
157         }
158
159         code = cr_add( cr, 1, scr, &err );
160         if ( code ) {
161                 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s: \"%s\"",
162                         c->argv[0], scherr2str(code), err);
163                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
164                         "%s %s\n", c->log, c->cr_msg, 0 );
165                 code = 1;
166                 goto done;
167         }
168
169 done:;
170         if ( code ) {
171                 ldap_contentrule_free( cr );
172
173         } else {
174                 ldap_memfree( cr );
175         }
176
177         return code;
178 }
179
180 int
181 parse_oc(
182         struct config_args_s *c,
183         ObjectClass     **soc,
184         ObjectClass *prev )
185 {
186         LDAPObjectClass *oc;
187         int             code;
188         const char      *err;
189         char *line = strchr( c->line, '(' );
190
191         oc = ldap_str2objectclass(line, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
192         if ( !oc ) {
193                 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s before %s",
194                         c->argv[0], ldap_scherr2str( code ), err );
195                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
196                         "%s %s\n", c->log, c->cr_msg, 0 );
197                 oc_usage();
198                 return 1;
199         }
200
201         if ( oc->oc_oid == NULL ) {
202                 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing",
203                         c->argv[0] );
204                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
205                         "%s %s\n", c->log, c->cr_msg, 0 );
206                 oc_usage();
207                 code = 1;
208                 goto done;
209         }
210
211         code = oc_add( oc, 1, soc, prev, &err );
212         if ( code ) {
213                 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s: \"%s\"",
214                         c->argv[0], scherr2str(code), err);
215                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
216                         "%s %s\n", c->log, c->cr_msg, 0 );
217                 code = 1;
218                 goto done;
219         }
220
221 done:;
222         if ( code ) {
223                 ldap_objectclass_free( oc );
224
225         } else {
226                 ldap_memfree( oc );
227         }
228
229         return code;
230 }
231
232 static void
233 oc_usage( void )
234 {
235         fprintf( stderr,
236                 "ObjectClassDescription = \"(\" whsp\n"
237                 "  numericoid whsp                 ; ObjectClass identifier\n"
238                 "  [ \"NAME\" qdescrs ]\n"
239                 "  [ \"DESC\" qdstring ]\n"
240                 "  [ \"OBSOLETE\" whsp ]\n"
241                 "  [ \"SUP\" oids ]                ; Superior ObjectClasses\n"
242                 "  [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n"
243                 "                                  ; default structural\n"
244                 "  [ \"MUST\" oids ]               ; AttributeTypes\n"
245                 "  [ \"MAY\" oids ]                ; AttributeTypes\n"
246                 "  whsp \")\"\n" );
247 }
248
249 static void
250 at_usage( void )
251 {
252         fprintf( stderr, "%s%s%s",
253                 "AttributeTypeDescription = \"(\" whsp\n"
254                 "  numericoid whsp      ; AttributeType identifier\n"
255                 "  [ \"NAME\" qdescrs ]             ; name used in AttributeType\n"
256                 "  [ \"DESC\" qdstring ]            ; description\n"
257                 "  [ \"OBSOLETE\" whsp ]\n"
258                 "  [ \"SUP\" woid ]                 ; derived from this other\n"
259                 "                                   ; AttributeType\n",
260                 "  [ \"EQUALITY\" woid ]            ; Matching Rule name\n"
261                 "  [ \"ORDERING\" woid ]            ; Matching Rule name\n"
262                 "  [ \"SUBSTR\" woid ]              ; Matching Rule name\n"
263                 "  [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n"
264                 "  [ \"SINGLE-VALUE\" whsp ]        ; default multi-valued\n"
265                 "  [ \"COLLECTIVE\" whsp ]          ; default not collective\n",
266                 "  [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n"
267                 "  [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n"
268                 "                                   ; userApplications\n"
269                 "                                   ; directoryOperation\n"
270                 "                                   ; distributedOperation\n"
271                 "                                   ; dSAOperation\n"
272                 "  whsp \")\"\n");
273 }
274
275 int
276 parse_at(
277         struct config_args_s *c,
278         AttributeType   **sat,
279         AttributeType   *prev )
280 {
281         LDAPAttributeType *at;
282         int             code;
283         const char      *err;
284         char *line = strchr( c->line, '(' );
285
286         at = ldap_str2attributetype( line, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
287         if ( !at ) {
288                 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s before %s",
289                         c->argv[0], ldap_scherr2str(code), err );
290                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
291                         "%s %s\n", c->log, c->cr_msg, 0 );
292                 at_usage();
293                 return 1;
294         }
295
296         if ( at->at_oid == NULL ) {
297                 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing",
298                         c->argv[0] );
299                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
300                         "%s %s\n", c->log, c->cr_msg, 0 );
301                 at_usage();
302                 code = 1;
303                 goto done;
304         }
305
306         /* operational attributes should be defined internally */
307         if ( at->at_usage ) {
308                 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: \"%s\" is operational",
309                         c->argv[0], at->at_oid );
310                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
311                         "%s %s\n", c->log, c->cr_msg, 0 );
312                 code = 1;
313                 goto done;
314         }
315
316         code = at_add( at, 1, sat, prev, &err);
317         if ( code ) {
318                 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s: \"%s\"",
319                         c->argv[0], scherr2str(code), err);
320                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
321                         "%s %s\n", c->log, c->cr_msg, 0 );
322                 code = 1;
323                 goto done;
324         }
325
326 done:;
327         if ( code ) {
328                 ldap_attributetype_free( at );
329
330         } else {
331                 ldap_memfree( at );
332         }
333
334         return code;
335 }
336
337 static void
338 syn_usage( void )
339 {
340         fprintf( stderr, "%s",
341                 "SyntaxDescription = \"(\" whsp\n"
342                 "  numericoid whsp                  ; object identifier\n"
343                 "  [ whsp \"DESC\" whsp qdstring ]  ; description\n"
344                 "  extensions whsp \")\"            ; extensions\n"
345                 "  whsp \")\"\n");
346 }
347
348 int
349 parse_syn(
350         struct config_args_s *c,
351         Syntax **ssyn,
352         Syntax *prev )
353 {
354         LDAPSyntax              *syn;
355         slap_syntax_defs_rec    def = { 0 };
356         int                     code;
357         const char              *err;
358         char                    *line = strchr( c->line, '(' );
359
360         syn = ldap_str2syntax( line, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
361         if ( !syn ) {
362                 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s before %s",
363                         c->argv[0], ldap_scherr2str(code), err );
364                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
365                         "%s %s\n", c->log, c->cr_msg, 0 );
366                 syn_usage();
367                 return 1;
368         }
369
370         if ( syn->syn_oid == NULL ) {
371                 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing",
372                         c->argv[0] );
373                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
374                         "%s %s\n", c->log, c->cr_msg, 0 );
375                 syn_usage();
376                 code = 1;
377                 goto done;
378         }
379
380         code = syn_add( syn, 1, &def, ssyn, prev, &err );
381         if ( code ) {
382                 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s: \"%s\"",
383                         c->argv[0], scherr2str(code), err);
384                 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
385                         "%s %s\n", c->log, c->cr_msg, 0 );
386                 code = 1;
387                 goto done;
388         }
389
390 done:;
391         if ( code ) {
392                 ldap_syntax_free( syn );
393
394         } else {
395                 ldap_memfree( syn );
396         }
397
398         return code;
399 }
400