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 static void oc_usage_old(void) LDAP_GCCATTR((noreturn));
22 static void oc_usage(void) LDAP_GCCATTR((noreturn));
23 static void at_usage(void) LDAP_GCCATTR((noreturn));
25 static char *const err2text[] = {
28 "Objectclass not found",
29 "Attribute type not found",
30 "Duplicate objectclass",
31 "Duplicate attributetype",
33 "Duplicate matchingrule",
34 "OID or name required",
35 "Syntax or superior required",
36 "Matchingrule not found",
44 if ( code < 1 || code >= (sizeof(err2text)/sizeof(char *)) ) {
45 return "Unknown error";
47 return err2text[code];
62 LDAP_OBJECT_CLASS *oc;
67 oc = (LDAP_OBJECT_CLASS *) ch_calloc( 1, sizeof(LDAP_OBJECT_CLASS) );
68 oc->oc_names = ch_calloc( 2, sizeof(char *) );
69 oc->oc_names[0] = ch_strdup( argv[1] );
70 oc->oc_names[1] = NULL;
72 if ( strcasecmp( oc->oc_names[0], "top" ) ) {
74 * no way to distinguish "auxiliary" from "structural"
75 * This may lead to future problems.
77 oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
79 for ( i = 2; i < argc; i++ ) {
80 /* required attributes */
81 if ( strcasecmp( argv[i], "requires" ) == 0 ) {
85 char **s = str2charray( argv[i], "," );
86 last = argv[i][strlen( argv[i] ) - 1];
87 charray_merge( &oc->oc_at_oids_must, s );
90 } while ( i < argc && last == ',' );
92 /* optional attributes */
93 } else if ( strcasecmp( argv[i], "allows" ) == 0 ) {
97 char **s = str2charray( argv[i], "," );
98 last = argv[i][strlen( argv[i] ) - 1];
100 charray_merge( &oc->oc_at_oids_may, s );
103 } while ( i < argc && last == ',' );
107 "%s: line %d: expecting \"requires\" or \"allows\" got \"%s\"\n",
108 fname, lineno, argv[i] );
114 * There was no requirement in the old schema that all attributes
115 * types were defined before use and they would just default to
116 * SYNTAX_CIS. To support this, we need to make attribute types
119 if ( oc->oc_at_oids_must ) {
120 namep = oc->oc_at_oids_must;
122 code = at_fake_if_needed( *namep );
124 fprintf( stderr, "%s: line %d: %s %s\n",
125 fname, lineno, scherr2str(code), *namep);
126 exit( EXIT_FAILURE );
131 if ( oc->oc_at_oids_may ) {
132 namep = oc->oc_at_oids_may;
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 );
144 code = oc_add(oc,&err);
146 fprintf( stderr, "%s: line %d: %s %s\n",
147 fname, lineno, scherr2str(code), err);
148 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->next)
189 if ((pos = dscompare(om->name, oid, ':')))
191 suflen = strlen(oid + pos);
192 new = ch_calloc(1, om->oidlen + suflen + 1);
193 strcpy(new, om->oid);
198 strcpy(new+suflen, oid+pos+1);
220 usage: fprintf( stderr, "ObjectIdentifier <name> <oid>\n");
221 exit( EXIT_FAILURE );
223 om = (OidMacro *) ch_malloc( sizeof(OidMacro) );
224 om->name = ch_strdup( argv[1] );
225 om->oid = find_oidm( argv[2] );
228 fprintf( stderr, "%s: line %d: OID %s not recognized\n",
229 fname, lineno, argv[2] );
232 if (om->oid == argv[2])
233 om->oid = ch_strdup( argv[2] );
234 om->oidlen = strlen( om->oid );
247 LDAP_OBJECT_CLASS *oc;
252 oc = ldap_str2objectclass(line,&code,&err);
254 fprintf( stderr, "%s: line %d: %s before %s\n",
255 fname, lineno, ldap_scherr2str(code), err );
259 if ( !isdigit( oc->oc_oid[0] )) {
260 /* Expand OID macros */
261 oid = find_oidm( oc->oc_oid );
264 "%s: line %d: OID %s not recognized\n",
265 fname, lineno, oc->oc_oid);
266 exit( EXIT_FAILURE );
268 if ( oid != oc->oc_oid ) {
269 ldap_memfree( oc->oc_oid );
274 /* oc->oc_oid == NULL will be an error someday */
275 code = oc_add(oc,&err);
277 fprintf( stderr, "%s: line %d: %s %s\n",
278 fname, lineno, scherr2str(code), err);
279 exit( EXIT_FAILURE );
287 fprintf( stderr, "ObjectClassDescription = \"(\" whsp\n");
288 fprintf( stderr, " numericoid whsp ; ObjectClass identifier\n");
289 fprintf( stderr, " [ \"NAME\" qdescrs ]\n");
290 fprintf( stderr, " [ \"DESC\" qdstring ]\n");
291 fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
292 fprintf( stderr, " [ \"SUP\" oids ] ; Superior ObjectClasses\n");
293 fprintf( stderr, " [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n");
294 fprintf( stderr, " ; default structural\n");
295 fprintf( stderr, " [ \"MUST\" oids ] ; AttributeTypes\n");
296 fprintf( stderr, " [ \"MAY\" oids ] ; AttributeTypes\n");
297 fprintf( stderr, "whsp \")\"\n");
298 exit( EXIT_FAILURE );
304 fprintf( stderr, "<oc clause> ::= objectclass <ocname>\n" );
305 fprintf( stderr, " [ requires <attrlist> ]\n" );
306 fprintf( stderr, " [ allows <attrlist> ]\n" );
307 exit( EXIT_FAILURE );
313 fprintf( stderr, "AttributeTypeDescription = \"(\" whsp\n");
314 fprintf( stderr, " numericoid whsp ; AttributeType identifier\n");
315 fprintf( stderr, " [ \"NAME\" qdescrs ] ; name used in AttributeType\n");
316 fprintf( stderr, " [ \"DESC\" qdstring ] ; description\n");
317 fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
318 fprintf( stderr, " [ \"SUP\" woid ] ; derived from this other\n");
319 fprintf( stderr, " ; AttributeType\n");
320 fprintf( stderr, " [ \"EQUALITY\" woid ] ; Matching Rule name\n");
321 fprintf( stderr, " [ \"ORDERING\" woid ] ; Matching Rule name\n");
322 fprintf( stderr, " [ \"SUBSTR\" woid ] ; Matching Rule name\n");
323 fprintf( stderr, " [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n");
324 fprintf( stderr, " [ \"SINGLE-VALUE\" whsp ] ; default multi-valued\n");
325 fprintf( stderr, " [ \"COLLECTIVE\" whsp ] ; default not collective\n");
326 fprintf( stderr, " [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n");
327 fprintf( stderr, " [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n");
328 fprintf( stderr, " ; userApplications\n");
329 fprintf( stderr, " ; directoryOperation\n");
330 fprintf( stderr, " ; distributedOperation\n");
331 fprintf( stderr, " ; dSAOperation\n");
332 fprintf( stderr, "whsp \")\"\n");
333 exit( EXIT_FAILURE );
344 LDAP_ATTRIBUTE_TYPE *at;
350 /* Kludge for OIDmacros for syntaxes. If the syntax field starts
351 * nonnumeric, look for and expand a macro. The macro's place in
352 * the input line will be replaced with a field of '0's to keep
353 * ldap_str2attributetype happy. The actual oid will be swapped
354 * into place afterwards.
356 for (; argv[3]; argv++)
358 if (!strcasecmp(argv[3], "syntax") &&
363 syn = syn_find_desc(argv[4], &slen);
366 fprintf(stderr, "%s: line %d: OID %s not found\n",
367 fname, lineno, argv[4]);
368 exit( EXIT_FAILURE );
370 memset(strstr(line, argv[4]), '0', slen);
371 soid = ch_strdup(syn->ssyn_syn.syn_oid );
375 at = ldap_str2attributetype(line,&code,&err);
377 fprintf( stderr, "%s: line %d: %s before %s\n",
378 fname, lineno, ldap_scherr2str(code), err );
382 if ( !isdigit( at->at_oid[0] )) {
383 /* Expand OID macros */
384 oid = find_oidm( at->at_oid );
387 "%s: line %d: OID %s not recognized\n",
388 fname, lineno, at->at_oid);
389 exit( EXIT_FAILURE );
391 if ( oid != at->at_oid ) {
392 ldap_memfree( at->at_oid );
397 /* at->at_oid == NULL will be an error someday */
400 ldap_memfree(at->at_syntax_oid);
401 at->at_syntax_oid = soid;
403 code = at_add(at,&err);
405 fprintf( stderr, "%s: line %d: %s %s\n",
406 fname, lineno, scherr2str(code), err);
407 exit( EXIT_FAILURE );