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);
23 static void oc_usage(void);
25 static char *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;
71 if ( strcasecmp( oc->oc_names[0], "top" ) ) {
72 oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
74 for ( i = 2; i < argc; i++ ) {
75 /* required attributes */
76 if ( strcasecmp( argv[i], "requires" ) == 0 ) {
80 char **s = str2charray( argv[i], "," );
81 last = argv[i][strlen( argv[i] ) - 1];
82 charray_merge( &oc->oc_at_oids_must, s );
85 } while ( i < argc && last == ',' );
87 /* optional attributes */
88 } else if ( strcasecmp( argv[i], "allows" ) == 0 ) {
92 char **s = str2charray( argv[i], "," );
93 last = argv[i][strlen( argv[i] ) - 1];
95 charray_merge( &oc->oc_at_oids_may, s );
98 } while ( i < argc && last == ',' );
102 "%s: line %d: expecting \"requires\" or \"allows\" got \"%s\"\n",
103 fname, lineno, argv[i] );
109 * There was no requirement in the old schema that all attributes
110 * types were defined before use and they would just default to
111 * SYNTAX_CIS. To support this, we need to make attribute types
114 if ( oc->oc_at_oids_must ) {
115 namep = oc->oc_at_oids_must;
117 code = at_fake_if_needed( *namep );
119 fprintf( stderr, "%s: line %d: %s %s\n",
120 fname, lineno, scherr2str(code), *namep);
121 exit( EXIT_FAILURE );
126 if ( oc->oc_at_oids_may ) {
127 namep = oc->oc_at_oids_may;
129 code = at_fake_if_needed( *namep );
131 fprintf( stderr, "%s: line %d: %s %s\n",
132 fname, lineno, scherr2str(code), *namep);
133 exit( EXIT_FAILURE );
139 code = oc_add(oc,&err);
141 fprintf( stderr, "%s: line %d: %s %s\n",
142 fname, lineno, scherr2str(code), err);
143 exit( EXIT_FAILURE );
150 /* String compare with delimiter check. Return 0 if not
151 * matched, otherwise return length matched.
154 dscompare(const char *s1, const char *s2, char delim)
156 const char *orig = s1;
157 while (*s1++ == *s2++)
161 if (!*s1 && (!*s2 || *s2 == delim))
166 static OidMacro *om_list = NULL;
168 /* Replace an OID Macro invocation with its full numeric OID.
169 * If the macro is used with "macroname:suffix" append ".suffix"
179 /* OID macros must start alpha */
180 if ( !isdigit( *oid ) )
182 for (om = om_list; om; om=om->next)
184 if ((pos = dscompare(om->name, oid, ':')))
186 suflen = strlen(oid + pos);
187 new = ch_calloc(1, om->oidlen + suflen + 1);
188 strcpy(new, om->oid);
193 strcpy(new+suflen, oid+pos+1);
215 usage: fprintf( stderr, "ObjectIdentifier <name> <oid>\n");
216 exit( EXIT_FAILURE );
218 om = (OidMacro *) ch_malloc( sizeof(OidMacro) );
219 om->name = ch_strdup( argv[1] );
220 om->oid = find_oidm( argv[2] );
223 fprintf( stderr, "%s: line %d: OID %s not recognized\n",
224 fname, lineno, argv[2] );
227 if (om->oid == argv[2])
228 om->oid = ch_strdup( argv[2] );
229 om->oidlen = strlen( om->oid );
242 LDAP_OBJECT_CLASS *oc;
247 /* Kludge for OIDmacros. If the numericOid field starts nonnumeric
248 * look for and expand a macro. The macro's place in the input line
249 * will be replaced with a field of '0's to keep ldap_str2objectclass
250 * happy. The actual oid will be swapped into place afterward.
252 if ( !isdigit( *argv[2] ))
254 oid = find_oidm(argv[2]);
257 fprintf(stderr, "%s: line %d: OID %s not recognized\n",
258 fname, lineno, argv[2]);
259 exit( EXIT_FAILURE );
262 memset(strstr(line, argv[2]), '0', strlen(argv[2]));
266 oc = ldap_str2objectclass(line,&code,&err);
268 fprintf( stderr, "%s: line %d: %s before %s\n",
269 fname, lineno, ldap_scherr2str(code), err );
274 ldap_memfree(oc->oc_oid);
277 code = oc_add(oc,&err);
279 fprintf( stderr, "%s: line %d: %s %s\n",
280 fname, lineno, scherr2str(code), err);
281 exit( EXIT_FAILURE );
289 fprintf( stderr, "ObjectClassDescription = \"(\" whsp\n");
290 fprintf( stderr, " numericoid whsp ; ObjectClass identifier\n");
291 fprintf( stderr, " [ \"NAME\" qdescrs ]\n");
292 fprintf( stderr, " [ \"DESC\" qdstring ]\n");
293 fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
294 fprintf( stderr, " [ \"SUP\" oids ] ; Superior ObjectClasses\n");
295 fprintf( stderr, " [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n");
296 fprintf( stderr, " ; default structural\n");
297 fprintf( stderr, " [ \"MUST\" oids ] ; AttributeTypes\n");
298 fprintf( stderr, " [ \"MAY\" oids ] ; AttributeTypes\n");
299 fprintf( stderr, "whsp \")\"\n");
300 exit( EXIT_FAILURE );
306 fprintf( stderr, "<oc clause> ::= objectclass <ocname>\n" );
307 fprintf( stderr, " [ requires <attrlist> ]\n" );
308 fprintf( stderr, " [ allows <attrlist> ]\n" );
309 exit( EXIT_FAILURE );
315 fprintf( stderr, "AttributeTypeDescription = \"(\" whsp\n");
316 fprintf( stderr, " numericoid whsp ; AttributeType identifier\n");
317 fprintf( stderr, " [ \"NAME\" qdescrs ] ; name used in AttributeType\n");
318 fprintf( stderr, " [ \"DESC\" qdstring ] ; description\n");
319 fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
320 fprintf( stderr, " [ \"SUP\" woid ] ; derived from this other\n");
321 fprintf( stderr, " ; AttributeType\n");
322 fprintf( stderr, " [ \"EQUALITY\" woid ] ; Matching Rule name\n");
323 fprintf( stderr, " [ \"ORDERING\" woid ] ; Matching Rule name\n");
324 fprintf( stderr, " [ \"SUBSTR\" woid ] ; Matching Rule name\n");
325 fprintf( stderr, " [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n");
326 fprintf( stderr, " [ \"SINGLE-VALUE\" whsp ] ; default multi-valued\n");
327 fprintf( stderr, " [ \"COLLECTIVE\" whsp ] ; default not collective\n");
328 fprintf( stderr, " [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n");
329 fprintf( stderr, " [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n");
330 fprintf( stderr, " ; userApplications\n");
331 fprintf( stderr, " ; directoryOperation\n");
332 fprintf( stderr, " ; distributedOperation\n");
333 fprintf( stderr, " ; dSAOperation\n");
334 fprintf( stderr, "whsp \")\"\n");
335 exit( EXIT_FAILURE );
346 LDAP_ATTRIBUTE_TYPE *at;
352 /* Kludge for OIDmacros. If the numericOid field starts nonnumeric
353 * look for and expand a macro. The macro's place in the input line
354 * will be replaced with a field of '0's to keep ldap_str2attr
355 * happy. The actual oid will be swapped into place afterward.
357 if ( !isdigit( *argv[2] ))
359 oid = find_oidm(argv[2]);
362 fprintf(stderr, "%s: line %d: OID %s not recognized\n",
363 fname, lineno, argv[2]);
364 exit( EXIT_FAILURE );
367 memset(strstr(line, argv[2]), '0', strlen(argv[2]));
371 for (; argv[3]; argv++)
373 if (!strcasecmp(argv[3], "syntax") &&
378 syn = syn_find_desc(argv[4], &slen);
381 fprintf(stderr, "%s: line %d: OID %s not found\n",
382 fname, lineno, argv[4]);
383 exit( EXIT_FAILURE );
385 memset(strstr(line, argv[4]), '0', slen);
386 soid = ch_strdup(syn->ssyn_syn.syn_oid );
390 at = ldap_str2attributetype(line,&code,&err);
392 fprintf( stderr, "%s: line %d: %s before %s\n",
393 fname, lineno, ldap_scherr2str(code), err );
398 ldap_memfree(at->at_oid);
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 );