1 /* schemaparse.c - routines to parse config file objectclass definitions */
3 * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
12 #include <ac/string.h>
13 #include <ac/socket.h>
16 #include "ldap_schema.h"
18 static Avlnode *object_classes = NULL;
20 int global_schemacheck = 1; /* schemacheck on is default */
22 static void oc_usage_old(void) LDAP_GCCATTR((noreturn));
23 static void oc_usage(void) LDAP_GCCATTR((noreturn));
24 static void at_usage(void) LDAP_GCCATTR((noreturn));
26 static char *err2text[] = {
29 "Objectclass not found",
30 "Attribute type not found",
31 "Duplicate objectclass",
32 "Duplicate attributetype",
34 "Duplicate matchingrule",
35 "OID or name required",
36 "Syntax or superior required",
37 "Matchingrule not found",
45 if ( code < 1 || code >= (sizeof(err2text)/sizeof(char *)) ) {
46 return "Unknown error";
48 return err2text[code];
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;
72 if ( strcasecmp( oc->oc_names[0], "top" ) ) {
73 oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
75 for ( i = 2; i < argc; i++ ) {
76 /* required attributes */
77 if ( strcasecmp( argv[i], "requires" ) == 0 ) {
81 char **s = str2charray( argv[i], "," );
82 last = argv[i][strlen( argv[i] ) - 1];
83 charray_merge( &oc->oc_at_oids_must, s );
86 } while ( i < argc && last == ',' );
88 /* optional attributes */
89 } else if ( strcasecmp( argv[i], "allows" ) == 0 ) {
93 char **s = str2charray( argv[i], "," );
94 last = argv[i][strlen( argv[i] ) - 1];
96 charray_merge( &oc->oc_at_oids_may, s );
99 } while ( i < argc && last == ',' );
103 "%s: line %d: expecting \"requires\" or \"allows\" got \"%s\"\n",
104 fname, lineno, argv[i] );
110 * There was no requirement in the old schema that all attributes
111 * types were defined before use and they would just default to
112 * SYNTAX_CIS. To support this, we need to make attribute types
115 if ( oc->oc_at_oids_must ) {
116 namep = oc->oc_at_oids_must;
118 code = at_fake_if_needed( *namep );
120 fprintf( stderr, "%s: line %d: %s %s\n",
121 fname, lineno, scherr2str(code), *namep);
122 exit( EXIT_FAILURE );
127 if ( oc->oc_at_oids_may ) {
128 namep = oc->oc_at_oids_may;
130 code = at_fake_if_needed( *namep );
132 fprintf( stderr, "%s: line %d: %s %s\n",
133 fname, lineno, scherr2str(code), *namep);
134 exit( EXIT_FAILURE );
140 code = oc_add(oc,&err);
142 fprintf( stderr, "%s: line %d: %s %s\n",
143 fname, lineno, scherr2str(code), err);
144 exit( EXIT_FAILURE );
151 /* String compare with delimiter check. Return 0 if not
152 * matched, otherwise return length matched.
155 dscompare(const char *s1, const char *s2, char delim)
157 const char *orig = s1;
158 while (*s1++ == *s2++)
162 if (!*s1 && (!*s2 || *s2 == delim))
167 static OidMacro *om_list = NULL;
169 /* Replace an OID Macro invocation with its full numeric OID.
170 * If the macro is used with "macroname:suffix" append ".suffix"
180 /* OID macros must start alpha */
181 if ( !isdigit( *oid ) )
183 for (om = om_list; om; om=om->next)
185 if ((pos = dscompare(om->name, oid, ':')))
187 suflen = strlen(oid + pos);
188 new = ch_calloc(1, om->oidlen + suflen + 1);
189 strcpy(new, om->oid);
194 strcpy(new+suflen, oid+pos+1);
216 usage: fprintf( stderr, "ObjectIdentifier <name> <oid>\n");
217 exit( EXIT_FAILURE );
219 om = (OidMacro *) ch_malloc( sizeof(OidMacro) );
220 om->name = ch_strdup( argv[1] );
221 om->oid = find_oidm( argv[2] );
224 fprintf( stderr, "%s: line %d: OID %s not recognized\n",
225 fname, lineno, argv[2] );
228 if (om->oid == argv[2])
229 om->oid = ch_strdup( argv[2] );
230 om->oidlen = strlen( om->oid );
243 LDAP_OBJECT_CLASS *oc;
248 /* Kludge for OIDmacros. If the numericOid field starts nonnumeric
249 * look for and expand a macro. The macro's place in the input line
250 * will be replaced with a field of '0's to keep ldap_str2objectclass
251 * happy. The actual oid will be swapped into place afterward.
253 if ( !isdigit( *argv[2] ))
255 oid = find_oidm(argv[2]);
258 fprintf(stderr, "%s: line %d: OID %s not recognized\n",
259 fname, lineno, argv[2]);
260 exit( EXIT_FAILURE );
263 memset(strstr(line, argv[2]), '0', strlen(argv[2]));
267 oc = ldap_str2objectclass(line,&code,&err);
269 fprintf( stderr, "%s: line %d: %s before %s\n",
270 fname, lineno, ldap_scherr2str(code), err );
275 ldap_memfree(oc->oc_oid);
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. If the numericOid field starts nonnumeric
354 * look for and expand a macro. The macro's place in the input line
355 * will be replaced with a field of '0's to keep ldap_str2attr
356 * happy. The actual oid will be swapped into place afterward.
358 if ( !isdigit( *argv[2] ))
360 oid = find_oidm(argv[2]);
363 fprintf(stderr, "%s: line %d: OID %s not recognized\n",
364 fname, lineno, argv[2]);
365 exit( EXIT_FAILURE );
368 memset(strstr(line, argv[2]), '0', strlen(argv[2]));
372 for (; argv[3]; argv++)
374 if (!strcasecmp(argv[3], "syntax") &&
379 syn = syn_find_desc(argv[4], &slen);
382 fprintf(stderr, "%s: line %d: OID %s not found\n",
383 fname, lineno, argv[4]);
384 exit( EXIT_FAILURE );
386 memset(strstr(line, argv[4]), '0', slen);
387 soid = ch_strdup(syn->ssyn_syn.syn_oid );
391 at = ldap_str2attributetype(line,&code,&err);
393 fprintf( stderr, "%s: line %d: %s before %s\n",
394 fname, lineno, ldap_scherr2str(code), err );
399 ldap_memfree(at->at_oid);
404 ldap_memfree(at->at_syntax_oid);
405 at->at_syntax_oid = soid;
407 code = at_add(at,&err);
409 fprintf( stderr, "%s: line %d: %s %s\n",
410 fname, lineno, scherr2str(code), err);
411 exit( EXIT_FAILURE );