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