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];
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 oc = ldap_str2objectclass(line,&code,&err);
249 fprintf( stderr, "%s: line %d: %s before %s\n",
250 fname, lineno, ldap_scherr2str(code), err );
254 if ( !isdigit( oc->oc_oid[0] )) {
255 /* Expand OID macros */
256 oid = find_oidm( oc->oc_oid );
259 "%s: line %d: OID %s not recognized\n",
260 fname, lineno, oc->oc_oid);
261 exit( EXIT_FAILURE );
263 if ( oid != oc->oc_oid ) {
264 ldap_memfree( oc->oc_oid );
269 /* oc->oc_oid == NULL will be an error someday */
270 code = oc_add(oc,&err);
272 fprintf( stderr, "%s: line %d: %s %s\n",
273 fname, lineno, scherr2str(code), err);
274 exit( EXIT_FAILURE );
282 fprintf( stderr, "ObjectClassDescription = \"(\" whsp\n");
283 fprintf( stderr, " numericoid whsp ; ObjectClass identifier\n");
284 fprintf( stderr, " [ \"NAME\" qdescrs ]\n");
285 fprintf( stderr, " [ \"DESC\" qdstring ]\n");
286 fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
287 fprintf( stderr, " [ \"SUP\" oids ] ; Superior ObjectClasses\n");
288 fprintf( stderr, " [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n");
289 fprintf( stderr, " ; default structural\n");
290 fprintf( stderr, " [ \"MUST\" oids ] ; AttributeTypes\n");
291 fprintf( stderr, " [ \"MAY\" oids ] ; AttributeTypes\n");
292 fprintf( stderr, "whsp \")\"\n");
293 exit( EXIT_FAILURE );
299 fprintf( stderr, "<oc clause> ::= objectclass <ocname>\n" );
300 fprintf( stderr, " [ requires <attrlist> ]\n" );
301 fprintf( stderr, " [ allows <attrlist> ]\n" );
302 exit( EXIT_FAILURE );
308 fprintf( stderr, "AttributeTypeDescription = \"(\" whsp\n");
309 fprintf( stderr, " numericoid whsp ; AttributeType identifier\n");
310 fprintf( stderr, " [ \"NAME\" qdescrs ] ; name used in AttributeType\n");
311 fprintf( stderr, " [ \"DESC\" qdstring ] ; description\n");
312 fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
313 fprintf( stderr, " [ \"SUP\" woid ] ; derived from this other\n");
314 fprintf( stderr, " ; AttributeType\n");
315 fprintf( stderr, " [ \"EQUALITY\" woid ] ; Matching Rule name\n");
316 fprintf( stderr, " [ \"ORDERING\" woid ] ; Matching Rule name\n");
317 fprintf( stderr, " [ \"SUBSTR\" woid ] ; Matching Rule name\n");
318 fprintf( stderr, " [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n");
319 fprintf( stderr, " [ \"SINGLE-VALUE\" whsp ] ; default multi-valued\n");
320 fprintf( stderr, " [ \"COLLECTIVE\" whsp ] ; default not collective\n");
321 fprintf( stderr, " [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n");
322 fprintf( stderr, " [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n");
323 fprintf( stderr, " ; userApplications\n");
324 fprintf( stderr, " ; directoryOperation\n");
325 fprintf( stderr, " ; distributedOperation\n");
326 fprintf( stderr, " ; dSAOperation\n");
327 fprintf( stderr, "whsp \")\"\n");
328 exit( EXIT_FAILURE );
339 LDAP_ATTRIBUTE_TYPE *at;
345 /* Kludge for OIDmacros for syntaxes. If the syntax field starts
346 * nonnumeric, look for and expand a macro. The macro's place in
347 * the input line will be replaced with a field of '0's to keep
348 * ldap_str2attributetype happy. The actual oid will be swapped
349 * into place afterwards.
351 for (; argv[3]; argv++)
353 if (!strcasecmp(argv[3], "syntax") &&
358 syn = syn_find_desc(argv[4], &slen);
361 fprintf(stderr, "%s: line %d: OID %s not found\n",
362 fname, lineno, argv[4]);
363 exit( EXIT_FAILURE );
365 memset(strstr(line, argv[4]), '0', slen);
366 soid = ch_strdup(syn->ssyn_syn.syn_oid );
370 at = ldap_str2attributetype(line,&code,&err);
372 fprintf( stderr, "%s: line %d: %s before %s\n",
373 fname, lineno, ldap_scherr2str(code), err );
377 if ( !isdigit( at->at_oid[0] )) {
378 /* Expand OID macros */
379 oid = find_oidm( at->at_oid );
382 "%s: line %d: OID %s not recognized\n",
383 fname, lineno, at->at_oid);
384 exit( EXIT_FAILURE );
386 if ( oid != at->at_oid ) {
387 ldap_memfree( at->at_oid );
392 /* at->at_oid == NULL will be an error someday */
395 ldap_memfree(at->at_syntax_oid);
396 at->at_syntax_oid = soid;
398 code = at_add(at,&err);
400 fprintf( stderr, "%s: line %d: %s %s\n",
401 fname, lineno, scherr2str(code), err);
402 exit( EXIT_FAILURE );