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];
60 #ifdef SLAPD_SCHEMA_COMPAT
63 LDAP_OBJECT_CLASS *oc;
68 oc = (LDAP_OBJECT_CLASS *) ch_calloc( 1, sizeof(LDAP_OBJECT_CLASS) );
69 oc->oc_names = ch_calloc( 2, sizeof(char *) );
70 oc->oc_names[0] = ch_strdup( argv[1] );
71 oc->oc_names[1] = NULL;
73 if ( strcasecmp( oc->oc_names[0], "top" ) ) {
75 * no way to distinguish "auxiliary" from "structural"
76 * This may lead to future problems.
78 oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
80 for ( i = 2; i < argc; i++ ) {
81 /* required attributes */
82 if ( strcasecmp( argv[i], "requires" ) == 0 ) {
86 char **s = str2charray( argv[i], "," );
87 last = argv[i][strlen( argv[i] ) - 1];
88 charray_merge( &oc->oc_at_oids_must, s );
91 } while ( i < argc && last == ',' );
93 /* optional attributes */
94 } else if ( strcasecmp( argv[i], "allows" ) == 0 ) {
98 char **s = str2charray( argv[i], "," );
99 last = argv[i][strlen( argv[i] ) - 1];
101 charray_merge( &oc->oc_at_oids_may, s );
104 } while ( i < argc && last == ',' );
108 "%s: line %d: expecting \"requires\" or \"allows\" got \"%s\"\n",
109 fname, lineno, argv[i] );
115 * There was no requirement in the old schema that all attributes
116 * types were defined before use and they would just default to
117 * SYNTAX_CIS. To support this, we need to make attribute types
120 if ( oc->oc_at_oids_must ) {
121 for( namep = oc->oc_at_oids_must; *namep ; namep++ ) {
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 );
130 if ( oc->oc_at_oids_may ) {
131 for( namep = oc->oc_at_oids_may; *namep; namep++ ) {
132 code = at_fake_if_needed( *namep );
134 fprintf( stderr, "%s: line %d: %s %s\n",
135 fname, lineno, scherr2str(code), *namep);
136 exit( EXIT_FAILURE );
141 code = oc_add(oc,&err);
143 fprintf( stderr, "%s: line %d: %s %s\n",
144 fname, lineno, scherr2str(code), err);
145 exit( EXIT_FAILURE );
150 fprintf( stderr, "%s: line %d: %s %s\n",
151 fname, lineno, "not built with -DSLAPD_SCHEMA_COMPAT\n");
152 exit( EXIT_FAILURE );
158 /* String compare with delimiter check. Return 0 if not
159 * matched, otherwise return length matched.
162 dscompare(const char *s1, const char *s2, char delim)
164 const char *orig = s1;
165 while (*s1++ == *s2++)
169 if (!*s1 && (!*s2 || *s2 == delim))
174 static OidMacro *om_list = NULL;
176 /* Replace an OID Macro invocation with its full numeric OID.
177 * If the macro is used with "macroname:suffix" append ".suffix"
187 /* OID macros must start alpha */
188 if ( !isdigit( *oid ) )
190 for (om = om_list; om; om=om->som_next)
192 if ((pos = dscompare(om->som_name, oid, ':')))
194 suflen = strlen(oid + pos);
195 new = ch_calloc(1, om->som_oidlen + suflen + 1);
196 strcpy(new, om->som_oid);
199 suflen = om->som_oidlen;
201 strcpy(new+suflen, oid+pos+1);
222 usage: fprintf( stderr, "ObjectIdentifier <name> <oid>\n");
223 exit( EXIT_FAILURE );
226 om = (OidMacro *) ch_malloc( sizeof(OidMacro) );
227 om->som_name = ch_strdup( argv[1] );
228 om->som_oid = find_oidm( argv[2] );
231 fprintf( stderr, "%s: line %d: OID %s not recognized\n",
232 fname, lineno, argv[2] );
236 if (om->som_oid == argv[2]) {
237 om->som_oid = ch_strdup( argv[2] );
240 om->som_oidlen = strlen( om->som_oid );
241 om->som_next = om_list;
253 LDAP_OBJECT_CLASS *oc;
258 oc = ldap_str2objectclass(line,&code,&err);
260 fprintf( stderr, "%s: line %d: %s before %s\n",
261 fname, lineno, ldap_scherr2str(code), err );
265 if ( !isdigit( oc->oc_oid[0] )) {
266 /* Expand OID macros */
267 oid = find_oidm( oc->oc_oid );
270 "%s: line %d: OID %s not recognized\n",
271 fname, lineno, oc->oc_oid);
272 exit( EXIT_FAILURE );
274 if ( oid != oc->oc_oid ) {
275 ldap_memfree( oc->oc_oid );
280 /* oc->oc_oid == NULL will be an error someday */
281 code = oc_add(oc,&err);
283 fprintf( stderr, "%s: line %d: %s %s\n",
284 fname, lineno, scherr2str(code), err);
285 exit( EXIT_FAILURE );
293 fprintf( stderr, "ObjectClassDescription = \"(\" whsp\n");
294 fprintf( stderr, " numericoid whsp ; ObjectClass identifier\n");
295 fprintf( stderr, " [ \"NAME\" qdescrs ]\n");
296 fprintf( stderr, " [ \"DESC\" qdstring ]\n");
297 fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
298 fprintf( stderr, " [ \"SUP\" oids ] ; Superior ObjectClasses\n");
299 fprintf( stderr, " [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n");
300 fprintf( stderr, " ; default structural\n");
301 fprintf( stderr, " [ \"MUST\" oids ] ; AttributeTypes\n");
302 fprintf( stderr, " [ \"MAY\" oids ] ; AttributeTypes\n");
303 fprintf( stderr, "whsp \")\"\n");
304 exit( EXIT_FAILURE );
310 fprintf( stderr, "<oc clause> ::= objectclass <ocname>\n" );
311 fprintf( stderr, " [ requires <attrlist> ]\n" );
312 fprintf( stderr, " [ allows <attrlist> ]\n" );
313 exit( EXIT_FAILURE );
319 fprintf( stderr, "AttributeTypeDescription = \"(\" whsp\n");
320 fprintf( stderr, " numericoid whsp ; AttributeType identifier\n");
321 fprintf( stderr, " [ \"NAME\" qdescrs ] ; name used in AttributeType\n");
322 fprintf( stderr, " [ \"DESC\" qdstring ] ; description\n");
323 fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
324 fprintf( stderr, " [ \"SUP\" woid ] ; derived from this other\n");
325 fprintf( stderr, " ; AttributeType\n");
326 fprintf( stderr, " [ \"EQUALITY\" woid ] ; Matching Rule name\n");
327 fprintf( stderr, " [ \"ORDERING\" woid ] ; Matching Rule name\n");
328 fprintf( stderr, " [ \"SUBSTR\" woid ] ; Matching Rule name\n");
329 fprintf( stderr, " [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n");
330 fprintf( stderr, " [ \"SINGLE-VALUE\" whsp ] ; default multi-valued\n");
331 fprintf( stderr, " [ \"COLLECTIVE\" whsp ] ; default not collective\n");
332 fprintf( stderr, " [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n");
333 fprintf( stderr, " [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n");
334 fprintf( stderr, " ; userApplications\n");
335 fprintf( stderr, " ; directoryOperation\n");
336 fprintf( stderr, " ; distributedOperation\n");
337 fprintf( stderr, " ; dSAOperation\n");
338 fprintf( stderr, "whsp \")\"\n");
339 exit( EXIT_FAILURE );
350 LDAP_ATTRIBUTE_TYPE *at;
356 /* Kludge for OIDmacros for syntaxes. If the syntax field starts
357 * nonnumeric, look for and expand a macro. The macro's place in
358 * the input line will be replaced with a field of '0's to keep
359 * ldap_str2attributetype happy. The actual oid will be swapped
360 * into place afterwards.
362 for (; argv[3]; argv++)
364 if (!strcasecmp(argv[3], "syntax") &&
369 syn = syn_find_desc(argv[4], &slen);
372 fprintf(stderr, "%s: line %d: OID %s not found\n",
373 fname, lineno, argv[4]);
374 exit( EXIT_FAILURE );
376 memset(strstr(line, argv[4]), '0', slen);
377 soid = ch_strdup(syn->ssyn_syn.syn_oid );
381 at = ldap_str2attributetype(line,&code,&err);
383 fprintf( stderr, "%s: line %d: %s before %s\n",
384 fname, lineno, ldap_scherr2str(code), err );
388 if ( !isdigit( at->at_oid[0] )) {
389 /* Expand OID macros */
390 oid = find_oidm( at->at_oid );
393 "%s: line %d: OID %s not recognized\n",
394 fname, lineno, at->at_oid);
395 exit( EXIT_FAILURE );
397 if ( oid != at->at_oid ) {
398 ldap_memfree( at->at_oid );
403 /* at->at_oid == NULL will be an error someday */
406 ldap_memfree(at->at_syntax_oid);
407 at->at_syntax_oid = soid;
409 code = at_add(at,&err);
411 fprintf( stderr, "%s: line %d: %s %s\n",
412 fname, lineno, scherr2str(code), err);
413 exit( EXIT_FAILURE );