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->next)
192 if ((pos = dscompare(om->name, oid, ':')))
194 suflen = strlen(oid + pos);
195 new = ch_calloc(1, om->oidlen + suflen + 1);
196 strcpy(new, om->oid);
201 strcpy(new+suflen, oid+pos+1);
223 usage: fprintf( stderr, "ObjectIdentifier <name> <oid>\n");
224 exit( EXIT_FAILURE );
226 om = (OidMacro *) ch_malloc( sizeof(OidMacro) );
227 om->name = ch_strdup( argv[1] );
228 om->oid = find_oidm( argv[2] );
231 fprintf( stderr, "%s: line %d: OID %s not recognized\n",
232 fname, lineno, argv[2] );
235 if (om->oid == argv[2])
236 om->oid = ch_strdup( argv[2] );
237 om->oidlen = strlen( om->oid );
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 );
307 fprintf( stderr, "<oc clause> ::= objectclass <ocname>\n" );
308 fprintf( stderr, " [ requires <attrlist> ]\n" );
309 fprintf( stderr, " [ allows <attrlist> ]\n" );
310 exit( EXIT_FAILURE );
316 fprintf( stderr, "AttributeTypeDescription = \"(\" whsp\n");
317 fprintf( stderr, " numericoid whsp ; AttributeType identifier\n");
318 fprintf( stderr, " [ \"NAME\" qdescrs ] ; name used in AttributeType\n");
319 fprintf( stderr, " [ \"DESC\" qdstring ] ; description\n");
320 fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
321 fprintf( stderr, " [ \"SUP\" woid ] ; derived from this other\n");
322 fprintf( stderr, " ; AttributeType\n");
323 fprintf( stderr, " [ \"EQUALITY\" woid ] ; Matching Rule name\n");
324 fprintf( stderr, " [ \"ORDERING\" woid ] ; Matching Rule name\n");
325 fprintf( stderr, " [ \"SUBSTR\" woid ] ; Matching Rule name\n");
326 fprintf( stderr, " [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n");
327 fprintf( stderr, " [ \"SINGLE-VALUE\" whsp ] ; default multi-valued\n");
328 fprintf( stderr, " [ \"COLLECTIVE\" whsp ] ; default not collective\n");
329 fprintf( stderr, " [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n");
330 fprintf( stderr, " [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n");
331 fprintf( stderr, " ; userApplications\n");
332 fprintf( stderr, " ; directoryOperation\n");
333 fprintf( stderr, " ; distributedOperation\n");
334 fprintf( stderr, " ; dSAOperation\n");
335 fprintf( stderr, "whsp \")\"\n");
336 exit( EXIT_FAILURE );
347 LDAP_ATTRIBUTE_TYPE *at;
353 /* Kludge for OIDmacros for syntaxes. If the syntax field starts
354 * nonnumeric, look for and expand a macro. The macro's place in
355 * the input line will be replaced with a field of '0's to keep
356 * ldap_str2attributetype happy. The actual oid will be swapped
357 * into place afterwards.
359 for (; argv[3]; argv++)
361 if (!strcasecmp(argv[3], "syntax") &&
366 syn = syn_find_desc(argv[4], &slen);
369 fprintf(stderr, "%s: line %d: OID %s not found\n",
370 fname, lineno, argv[4]);
371 exit( EXIT_FAILURE );
373 memset(strstr(line, argv[4]), '0', slen);
374 soid = ch_strdup(syn->ssyn_syn.syn_oid );
378 at = ldap_str2attributetype(line,&code,&err);
380 fprintf( stderr, "%s: line %d: %s before %s\n",
381 fname, lineno, ldap_scherr2str(code), err );
385 if ( !isdigit( at->at_oid[0] )) {
386 /* Expand OID macros */
387 oid = find_oidm( at->at_oid );
390 "%s: line %d: OID %s not recognized\n",
391 fname, lineno, at->at_oid);
392 exit( EXIT_FAILURE );
394 if ( oid != at->at_oid ) {
395 ldap_memfree( at->at_oid );
400 /* at->at_oid == NULL will be an error someday */
403 ldap_memfree(at->at_syntax_oid);
404 at->at_syntax_oid = soid;
406 code = at_add(at,&err);
408 fprintf( stderr, "%s: line %d: %s %s\n",
409 fname, lineno, scherr2str(code), err);
410 exit( EXIT_FAILURE );