xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/schemaparse.c (revision 274254cdae52594c1aa480a736aef78313d15c9c)
1 /* schemaparse.c - routines to parse config file objectclass definitions */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/schemaparse.c,v 1.80.2.4 2008/02/11 23:26:44 kurt Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2008 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->cr_msg, sizeof( c->cr_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->cr_msg, 0 );
143 		cr_usage();
144 		return 1;
145 	}
146 
147 	if ( cr->cr_oid == NULL ) {
148 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing",
149 			c->argv[0] );
150 		Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
151 			"%s %s\n", c->log, c->cr_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->cr_msg, sizeof( c->cr_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->cr_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->cr_msg, sizeof( c->cr_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->cr_msg, 0 );
195 		oc_usage();
196 		return 1;
197 	}
198 
199 	if ( oc->oc_oid == NULL ) {
200 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing",
201 			c->argv[0] );
202 		Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
203 			"%s %s\n", c->log, c->cr_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->cr_msg, sizeof( c->cr_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->cr_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->cr_msg, sizeof( c->cr_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->cr_msg, 0 );
290 		at_usage();
291 		return 1;
292 	}
293 
294 	if ( at->at_oid == NULL ) {
295 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing",
296 			c->argv[0] );
297 		Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
298 			"%s %s\n", c->log, c->cr_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->cr_msg, sizeof( c->cr_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->cr_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->cr_msg, sizeof( c->cr_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->cr_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 }
334