1 /* schemaparse.c - routines to parse config file objectclass definitions */
4 * Copyright 1998-2000 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 "AttributeType not found",
32 "Duplicate objectClass",
33 "Duplicate attributeType",
34 "Duplicate ldapSyntax",
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"
182 /* OID macros must start alpha */
183 if ( isdigit( *oid ) ) {
187 for (om = om_list; om; om=om->som_next) {
188 char **names = om->som_names;
190 if( names == NULL ) {
194 for( ; *names != NULL ; names++ ) {
195 int pos = dscompare(*names, oid, ':');
198 int suflen = strlen(oid + pos);
199 char *new = ch_calloc(1,
200 om->som_oid.bv_len + suflen + 1);
201 strcpy(new, om->som_oid.bv_val);
204 suflen = om->som_oid.bv_len;
206 strcpy(new+suflen, oid+pos+1);
227 fprintf( stderr, "%s: line %d: too many arguments\n",
229 usage: fprintf( stderr, "\tObjectIdentifier <name> <oid>\n");
230 exit( EXIT_FAILURE );
233 oid = find_oidm( argv[1] );
237 "ObjectIdentifier \"%s\" previously defined \"%s\"",
238 fname, lineno, argv[1], oid );
239 exit( EXIT_FAILURE );
242 om = (OidMacro *) ch_malloc( sizeof(OidMacro) );
244 om->som_names = NULL;
245 charray_add( &om->som_names, argv[1] );
246 om->som_oid.bv_val = find_oidm( argv[2] );
248 if (!om->som_oid.bv_val) {
249 fprintf( stderr, "%s: line %d: OID %s not recognized\n",
250 fname, lineno, argv[2] );
254 if (om->som_oid.bv_val == argv[2]) {
255 om->som_oid.bv_val = ch_strdup( argv[2] );
258 om->som_oid.bv_len = strlen( om->som_oid.bv_val );
259 om->som_next = om_list;
271 LDAP_OBJECT_CLASS *oc;
276 oc = ldap_str2objectclass(line,&code,&err);
278 fprintf( stderr, "%s: line %d: %s before %s\n",
279 fname, lineno, ldap_scherr2str(code), err );
283 if ( !isdigit( oc->oc_oid[0] )) {
284 /* Expand OID macros */
285 oid = find_oidm( oc->oc_oid );
288 "%s: line %d: OID %s not recognized\n",
289 fname, lineno, oc->oc_oid);
290 exit( EXIT_FAILURE );
292 if ( oid != oc->oc_oid ) {
293 ldap_memfree( oc->oc_oid );
298 /* oc->oc_oid == NULL will be an error someday */
299 code = oc_add(oc,&err);
301 fprintf( stderr, "%s: line %d: %s: \"%s\"\n",
302 fname, lineno, scherr2str(code), err);
303 exit( EXIT_FAILURE );
311 fprintf( stderr, "ObjectClassDescription = \"(\" whsp\n");
312 fprintf( stderr, " numericoid whsp ; ObjectClass identifier\n");
313 fprintf( stderr, " [ \"NAME\" qdescrs ]\n");
314 fprintf( stderr, " [ \"DESC\" qdstring ]\n");
315 fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
316 fprintf( stderr, " [ \"SUP\" oids ] ; Superior ObjectClasses\n");
317 fprintf( stderr, " [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n");
318 fprintf( stderr, " ; default structural\n");
319 fprintf( stderr, " [ \"MUST\" oids ] ; AttributeTypes\n");
320 fprintf( stderr, " [ \"MAY\" oids ] ; AttributeTypes\n");
321 fprintf( stderr, "whsp \")\"\n");
322 exit( EXIT_FAILURE );
325 #ifndef SLAPD_SCHEMA_NOT_COMPAT
329 fprintf( stderr, "<oc clause> ::= objectclass <ocname>\n" );
330 fprintf( stderr, " [ requires <attrlist> ]\n" );
331 fprintf( stderr, " [ allows <attrlist> ]\n" );
332 exit( EXIT_FAILURE );
339 fprintf( stderr, "AttributeTypeDescription = \"(\" whsp\n");
340 fprintf( stderr, " numericoid whsp ; AttributeType identifier\n");
341 fprintf( stderr, " [ \"NAME\" qdescrs ] ; name used in AttributeType\n");
342 fprintf( stderr, " [ \"DESC\" qdstring ] ; description\n");
343 fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
344 fprintf( stderr, " [ \"SUP\" woid ] ; derived from this other\n");
345 fprintf( stderr, " ; AttributeType\n");
346 fprintf( stderr, " [ \"EQUALITY\" woid ] ; Matching Rule name\n");
347 fprintf( stderr, " [ \"ORDERING\" woid ] ; Matching Rule name\n");
348 fprintf( stderr, " [ \"SUBSTR\" woid ] ; Matching Rule name\n");
349 fprintf( stderr, " [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n");
350 fprintf( stderr, " [ \"SINGLE-VALUE\" whsp ] ; default multi-valued\n");
351 fprintf( stderr, " [ \"COLLECTIVE\" whsp ] ; default not collective\n");
352 fprintf( stderr, " [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n");
353 fprintf( stderr, " [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n");
354 fprintf( stderr, " ; userApplications\n");
355 fprintf( stderr, " ; directoryOperation\n");
356 fprintf( stderr, " ; distributedOperation\n");
357 fprintf( stderr, " ; dSAOperation\n");
358 fprintf( stderr, "whsp \")\"\n");
359 exit( EXIT_FAILURE );
370 LDAP_ATTRIBUTE_TYPE *at;
376 /* Kludge for OIDmacros for syntaxes. If the syntax field starts
377 * nonnumeric, look for and expand a macro. The macro's place in
378 * the input line will be replaced with a field of '0's to keep
379 * ldap_str2attributetype happy. The actual oid will be swapped
380 * into place afterwards.
382 for (; argv[3]; argv++)
384 if (!strcasecmp(argv[3], "syntax") &&
389 syn = syn_find_desc(argv[4], &slen);
392 fprintf(stderr, "%s: line %d: OID %s not found\n",
393 fname, lineno, argv[4]);
394 exit( EXIT_FAILURE );
396 memset(strstr(line, argv[4]), '0', slen);
397 soid = ch_strdup(syn->ssyn_syn.syn_oid );
401 at = ldap_str2attributetype(line,&code,&err);
403 fprintf( stderr, "%s: line %d: %s before %s\n",
404 fname, lineno, ldap_scherr2str(code), err );
408 if ( !isdigit( at->at_oid[0] )) {
409 /* Expand OID macros */
410 oid = find_oidm( at->at_oid );
413 "%s: line %d: OID %s not recognized\n",
414 fname, lineno, at->at_oid);
415 exit( EXIT_FAILURE );
417 if ( oid != at->at_oid ) {
418 ldap_memfree( at->at_oid );
423 /* at->at_oid == NULL will be an error someday */
426 ldap_memfree(at->at_syntax_oid);
427 at->at_syntax_oid = soid;
429 code = at_add(at,&err);
431 fprintf( stderr, "%s: line %d: %s: \"%s\"\n",
432 fname, lineno, scherr2str(code), err);
433 exit( EXIT_FAILURE );