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-2021 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 "slap-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 *
scherr2str(int code)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 */
slap_valid_descr(const char * descr)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
dscompare(const char * s1,const char * s2,char delim)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
cr_usage(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
parse_cr(struct config_args_s * c,ContentRule ** scr)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 );
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 );
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 );
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
parse_oc(struct config_args_s * c,ObjectClass ** soc,ObjectClass * prev)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 );
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 );
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 );
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
oc_usage(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
at_usage(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
parse_at(struct config_args_s * c,AttributeType ** sat,AttributeType * prev)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 );
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 );
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 );
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 );
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
syn_usage(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
parse_syn(struct config_args_s * c,Syntax ** ssyn,Syntax * prev)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 );
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 );
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 );
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
401