1 /* schemaparse.c - routines to parse config file objectclass definitions */
4 * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
13 #include <ac/string.h>
14 #include <ac/socket.h>
17 #include "ldap_schema.h"
19 int global_schemacheck = 1; /* schemacheck on is default */
21 #ifndef SLAPD_SCHEMA_NOT_COMPAT
22 static void oc_usage_old(void) LDAP_GCCATTR((noreturn));
24 static void oc_usage(void) LDAP_GCCATTR((noreturn));
25 static void at_usage(void) LDAP_GCCATTR((noreturn));
27 static char *const err2text[] = {
30 "Objectclass not found",
31 "Attribute type not found",
32 "Duplicate objectclass",
33 "Duplicate attributetype",
35 "Duplicate matchingrule",
36 "OID or name required",
37 "Syntax or superior required",
38 "Matchingrule not found",
46 if ( code < 1 || code >= (sizeof(err2text)/sizeof(char *)) ) {
47 return "Unknown error";
49 return err2text[code];
53 #ifndef SLAPD_SCHEMA_NOT_COMPAT
65 LDAP_OBJECT_CLASS *oc;
70 oc = (LDAP_OBJECT_CLASS *) ch_calloc( 1, sizeof(LDAP_OBJECT_CLASS) );
71 oc->oc_names = ch_calloc( 2, sizeof(char *) );
72 oc->oc_names[0] = ch_strdup( argv[1] );
73 oc->oc_names[1] = NULL;
75 if ( strcasecmp( oc->oc_names[0], "top" ) ) {
77 * no way to distinguish "auxiliary" from "structural"
78 * This may lead to future problems.
80 oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
82 for ( i = 2; i < argc; i++ ) {
83 /* required attributes */
84 if ( strcasecmp( argv[i], "requires" ) == 0 ) {
88 char **s = str2charray( argv[i], "," );
89 last = argv[i][strlen( argv[i] ) - 1];
90 charray_merge( &oc->oc_at_oids_must, s );
93 } while ( i < argc && last == ',' );
95 /* optional attributes */
96 } else if ( strcasecmp( argv[i], "allows" ) == 0 ) {
100 char **s = str2charray( argv[i], "," );
101 last = argv[i][strlen( argv[i] ) - 1];
103 charray_merge( &oc->oc_at_oids_may, s );
106 } while ( i < argc && last == ',' );
110 "%s: line %d: expecting \"requires\" or \"allows\" got \"%s\"\n",
111 fname, lineno, argv[i] );
117 * There was no requirement in the old schema that all attributes
118 * types were defined before use and they would just default to
119 * SYNTAX_CIS. To support this, we need to make attribute types
122 if ( oc->oc_at_oids_must ) {
123 for( namep = oc->oc_at_oids_must; *namep ; namep++ ) {
124 code = at_fake_if_needed( *namep );
126 fprintf( stderr, "%s: line %d: %s %s\n",
127 fname, lineno, scherr2str(code), *namep);
128 exit( EXIT_FAILURE );
132 if ( oc->oc_at_oids_may ) {
133 for( namep = oc->oc_at_oids_may; *namep; namep++ ) {
134 code = at_fake_if_needed( *namep );
136 fprintf( stderr, "%s: line %d: %s %s\n",
137 fname, lineno, scherr2str(code), *namep);
138 exit( EXIT_FAILURE );
143 code = oc_add(oc,&err);
145 fprintf( stderr, "%s: line %d: %s %s\n",
146 fname, lineno, scherr2str(code), err);
147 exit( EXIT_FAILURE );
155 /* String compare with delimiter check. Return 0 if not
156 * matched, otherwise return length matched.
159 dscompare(const char *s1, const char *s2, char delim)
161 const char *orig = s1;
162 while (*s1++ == *s2++)
166 if (!*s1 && (!*s2 || *s2 == delim))
171 static OidMacro *om_list = NULL;
173 /* Replace an OID Macro invocation with its full numeric OID.
174 * If the macro is used with "macroname:suffix" append ".suffix"
184 /* OID macros must start alpha */
185 if ( !isdigit( *oid ) )
187 for (om = om_list; om; om=om->som_next)
189 if ((pos = dscompare(om->som_name, oid, ':')))
191 suflen = strlen(oid + pos);
192 new = ch_calloc(1, om->som_oid.bv_len + suflen + 1);
193 strcpy(new, om->som_oid.bv_val);
196 suflen = om->som_oid.bv_len;
198 strcpy(new+suflen, oid+pos+1);
219 usage: fprintf( stderr, "ObjectIdentifier <name> <oid>\n");
220 exit( EXIT_FAILURE );
223 om = (OidMacro *) ch_malloc( sizeof(OidMacro) );
224 om->som_name = ch_strdup( argv[1] );
225 om->som_oid.bv_val = find_oidm( argv[2] );
227 if (!om->som_oid.bv_val) {
228 fprintf( stderr, "%s: line %d: OID %s not recognized\n",
229 fname, lineno, argv[2] );
233 if (om->som_oid.bv_val == argv[2]) {
234 om->som_oid.bv_val = ch_strdup( argv[2] );
237 om->som_oid.bv_len = strlen( om->som_oid.bv_val );
238 om->som_next = om_list;
250 LDAP_OBJECT_CLASS *oc;
255 oc = ldap_str2objectclass(line,&code,&err);
257 fprintf( stderr, "%s: line %d: %s before %s\n",
258 fname, lineno, ldap_scherr2str(code), err );
262 if ( !isdigit( oc->oc_oid[0] )) {
263 /* Expand OID macros */
264 oid = find_oidm( oc->oc_oid );
267 "%s: line %d: OID %s not recognized\n",
268 fname, lineno, oc->oc_oid);
269 exit( EXIT_FAILURE );
271 if ( oid != oc->oc_oid ) {
272 ldap_memfree( oc->oc_oid );
277 /* oc->oc_oid == NULL will be an error someday */
278 code = oc_add(oc,&err);
280 fprintf( stderr, "%s: line %d: %s %s\n",
281 fname, lineno, scherr2str(code), err);
282 exit( EXIT_FAILURE );
290 fprintf( stderr, "ObjectClassDescription = \"(\" whsp\n");
291 fprintf( stderr, " numericoid whsp ; ObjectClass identifier\n");
292 fprintf( stderr, " [ \"NAME\" qdescrs ]\n");
293 fprintf( stderr, " [ \"DESC\" qdstring ]\n");
294 fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
295 fprintf( stderr, " [ \"SUP\" oids ] ; Superior ObjectClasses\n");
296 fprintf( stderr, " [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n");
297 fprintf( stderr, " ; default structural\n");
298 fprintf( stderr, " [ \"MUST\" oids ] ; AttributeTypes\n");
299 fprintf( stderr, " [ \"MAY\" oids ] ; AttributeTypes\n");
300 fprintf( stderr, "whsp \")\"\n");
301 exit( EXIT_FAILURE );
304 #ifndef SLAPD_SCHEMA_NOT_COMPAT
308 fprintf( stderr, "<oc clause> ::= objectclass <ocname>\n" );
309 fprintf( stderr, " [ requires <attrlist> ]\n" );
310 fprintf( stderr, " [ allows <attrlist> ]\n" );
311 exit( EXIT_FAILURE );
318 fprintf( stderr, "AttributeTypeDescription = \"(\" whsp\n");
319 fprintf( stderr, " numericoid whsp ; AttributeType identifier\n");
320 fprintf( stderr, " [ \"NAME\" qdescrs ] ; name used in AttributeType\n");
321 fprintf( stderr, " [ \"DESC\" qdstring ] ; description\n");
322 fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
323 fprintf( stderr, " [ \"SUP\" woid ] ; derived from this other\n");
324 fprintf( stderr, " ; AttributeType\n");
325 fprintf( stderr, " [ \"EQUALITY\" woid ] ; Matching Rule name\n");
326 fprintf( stderr, " [ \"ORDERING\" woid ] ; Matching Rule name\n");
327 fprintf( stderr, " [ \"SUBSTR\" woid ] ; Matching Rule name\n");
328 fprintf( stderr, " [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n");
329 fprintf( stderr, " [ \"SINGLE-VALUE\" whsp ] ; default multi-valued\n");
330 fprintf( stderr, " [ \"COLLECTIVE\" whsp ] ; default not collective\n");
331 fprintf( stderr, " [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n");
332 fprintf( stderr, " [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n");
333 fprintf( stderr, " ; userApplications\n");
334 fprintf( stderr, " ; directoryOperation\n");
335 fprintf( stderr, " ; distributedOperation\n");
336 fprintf( stderr, " ; dSAOperation\n");
337 fprintf( stderr, "whsp \")\"\n");
338 exit( EXIT_FAILURE );
349 LDAP_ATTRIBUTE_TYPE *at;
355 /* Kludge for OIDmacros for syntaxes. If the syntax field starts
356 * nonnumeric, look for and expand a macro. The macro's place in
357 * the input line will be replaced with a field of '0's to keep
358 * ldap_str2attributetype happy. The actual oid will be swapped
359 * into place afterwards.
361 for (; argv[3]; argv++)
363 if (!strcasecmp(argv[3], "syntax") &&
368 syn = syn_find_desc(argv[4], &slen);
371 fprintf(stderr, "%s: line %d: OID %s not found\n",
372 fname, lineno, argv[4]);
373 exit( EXIT_FAILURE );
375 memset(strstr(line, argv[4]), '0', slen);
376 soid = ch_strdup(syn->ssyn_syn.syn_oid );
380 at = ldap_str2attributetype(line,&code,&err);
382 fprintf( stderr, "%s: line %d: %s before %s\n",
383 fname, lineno, ldap_scherr2str(code), err );
387 if ( !isdigit( at->at_oid[0] )) {
388 /* Expand OID macros */
389 oid = find_oidm( at->at_oid );
392 "%s: line %d: OID %s not recognized\n",
393 fname, lineno, at->at_oid);
394 exit( EXIT_FAILURE );
396 if ( oid != at->at_oid ) {
397 ldap_memfree( at->at_oid );
402 /* at->at_oid == NULL will be an error someday */
405 ldap_memfree(at->at_syntax_oid);
406 at->at_syntax_oid = soid;
408 code = at_add(at,&err);
410 fprintf( stderr, "%s: line %d: %s %s\n",
411 fname, lineno, scherr2str(code), err);
412 exit( EXIT_FAILURE );