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 int global_schemacheck = 1; /* schemacheck on is default */
20 static void oc_usage_old(void) LDAP_GCCATTR((noreturn));
21 static void oc_usage(void) LDAP_GCCATTR((noreturn));
22 static void at_usage(void) LDAP_GCCATTR((noreturn));
24 static char *const err2text[] = {
27 "Objectclass not found",
28 "Attribute type not found",
29 "Duplicate objectclass",
30 "Duplicate attributetype",
32 "Duplicate matchingrule",
33 "OID or name required",
34 "Syntax or superior required",
35 "Matchingrule not found",
43 if ( code < 1 || code >= (sizeof(err2text)/sizeof(char *)) ) {
44 return "Unknown error";
46 return err2text[code];
61 LDAP_OBJECT_CLASS *oc;
66 oc = (LDAP_OBJECT_CLASS *) ch_calloc( 1, sizeof(LDAP_OBJECT_CLASS) );
67 oc->oc_names = ch_calloc( 2, sizeof(char *) );
68 oc->oc_names[0] = ch_strdup( argv[1] );
69 oc->oc_names[1] = NULL;
70 if ( strcasecmp( oc->oc_names[0], "top" ) ) {
71 oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
73 for ( i = 2; i < argc; i++ ) {
74 /* required attributes */
75 if ( strcasecmp( argv[i], "requires" ) == 0 ) {
79 char **s = str2charray( argv[i], "," );
80 last = argv[i][strlen( argv[i] ) - 1];
81 charray_merge( &oc->oc_at_oids_must, s );
84 } while ( i < argc && last == ',' );
86 /* optional attributes */
87 } else if ( strcasecmp( argv[i], "allows" ) == 0 ) {
91 char **s = str2charray( argv[i], "," );
92 last = argv[i][strlen( argv[i] ) - 1];
94 charray_merge( &oc->oc_at_oids_may, s );
97 } while ( i < argc && last == ',' );
101 "%s: line %d: expecting \"requires\" or \"allows\" got \"%s\"\n",
102 fname, lineno, argv[i] );
108 * There was no requirement in the old schema that all attributes
109 * types were defined before use and they would just default to
110 * SYNTAX_CIS. To support this, we need to make attribute types
113 if ( oc->oc_at_oids_must ) {
114 namep = oc->oc_at_oids_must;
116 code = at_fake_if_needed( *namep );
118 fprintf( stderr, "%s: line %d: %s %s\n",
119 fname, lineno, scherr2str(code), *namep);
120 exit( EXIT_FAILURE );
125 if ( oc->oc_at_oids_may ) {
126 namep = oc->oc_at_oids_may;
128 code = at_fake_if_needed( *namep );
130 fprintf( stderr, "%s: line %d: %s %s\n",
131 fname, lineno, scherr2str(code), *namep);
132 exit( EXIT_FAILURE );
138 code = oc_add(oc,&err);
140 fprintf( stderr, "%s: line %d: %s %s\n",
141 fname, lineno, scherr2str(code), err);
142 exit( EXIT_FAILURE );
149 /* String compare with delimiter check. Return 0 if not
150 * matched, otherwise return length matched.
153 dscompare(const char *s1, const char *s2, char delim)
155 const char *orig = s1;
156 while (*s1++ == *s2++)
160 if (!*s1 && (!*s2 || *s2 == delim))
165 static OidMacro *om_list = NULL;
167 /* Replace an OID Macro invocation with its full numeric OID.
168 * If the macro is used with "macroname:suffix" append ".suffix"
178 /* OID macros must start alpha */
179 if ( !isdigit( *oid ) )
181 for (om = om_list; om; om=om->next)
183 if ((pos = dscompare(om->name, oid, ':')))
185 suflen = strlen(oid + pos);
186 new = ch_calloc(1, om->oidlen + suflen + 1);
187 strcpy(new, om->oid);
192 strcpy(new+suflen, oid+pos+1);
214 usage: fprintf( stderr, "ObjectIdentifier <name> <oid>\n");
215 exit( EXIT_FAILURE );
217 om = (OidMacro *) ch_malloc( sizeof(OidMacro) );
218 om->name = ch_strdup( argv[1] );
219 om->oid = find_oidm( argv[2] );
222 fprintf( stderr, "%s: line %d: OID %s not recognized\n",
223 fname, lineno, argv[2] );
226 if (om->oid == argv[2])
227 om->oid = ch_strdup( argv[2] );
228 om->oidlen = strlen( om->oid );
241 LDAP_OBJECT_CLASS *oc;
246 /* Kludge for OIDmacros. If the numericOid field starts nonnumeric
247 * look for and expand a macro. The macro's place in the input line
248 * will be replaced with a field of '0's to keep ldap_str2objectclass
249 * happy. The actual oid will be swapped into place afterward.
251 if ( !isdigit( *argv[2] ))
253 oid = find_oidm(argv[2]);
256 fprintf(stderr, "%s: line %d: OID %s not recognized\n",
257 fname, lineno, argv[2]);
258 exit( EXIT_FAILURE );
261 memset(strstr(line, argv[2]), '0', strlen(argv[2]));
265 oc = ldap_str2objectclass(line,&code,&err);
267 fprintf( stderr, "%s: line %d: %s before %s\n",
268 fname, lineno, ldap_scherr2str(code), err );
273 ldap_memfree(oc->oc_oid);
276 code = oc_add(oc,&err);
278 fprintf( stderr, "%s: line %d: %s %s\n",
279 fname, lineno, scherr2str(code), err);
280 exit( EXIT_FAILURE );
288 fprintf( stderr, "ObjectClassDescription = \"(\" whsp\n");
289 fprintf( stderr, " numericoid whsp ; ObjectClass identifier\n");
290 fprintf( stderr, " [ \"NAME\" qdescrs ]\n");
291 fprintf( stderr, " [ \"DESC\" qdstring ]\n");
292 fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
293 fprintf( stderr, " [ \"SUP\" oids ] ; Superior ObjectClasses\n");
294 fprintf( stderr, " [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n");
295 fprintf( stderr, " ; default structural\n");
296 fprintf( stderr, " [ \"MUST\" oids ] ; AttributeTypes\n");
297 fprintf( stderr, " [ \"MAY\" oids ] ; AttributeTypes\n");
298 fprintf( stderr, "whsp \")\"\n");
299 exit( EXIT_FAILURE );
305 fprintf( stderr, "<oc clause> ::= objectclass <ocname>\n" );
306 fprintf( stderr, " [ requires <attrlist> ]\n" );
307 fprintf( stderr, " [ allows <attrlist> ]\n" );
308 exit( EXIT_FAILURE );
314 fprintf( stderr, "AttributeTypeDescription = \"(\" whsp\n");
315 fprintf( stderr, " numericoid whsp ; AttributeType identifier\n");
316 fprintf( stderr, " [ \"NAME\" qdescrs ] ; name used in AttributeType\n");
317 fprintf( stderr, " [ \"DESC\" qdstring ] ; description\n");
318 fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
319 fprintf( stderr, " [ \"SUP\" woid ] ; derived from this other\n");
320 fprintf( stderr, " ; AttributeType\n");
321 fprintf( stderr, " [ \"EQUALITY\" woid ] ; Matching Rule name\n");
322 fprintf( stderr, " [ \"ORDERING\" woid ] ; Matching Rule name\n");
323 fprintf( stderr, " [ \"SUBSTR\" woid ] ; Matching Rule name\n");
324 fprintf( stderr, " [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n");
325 fprintf( stderr, " [ \"SINGLE-VALUE\" whsp ] ; default multi-valued\n");
326 fprintf( stderr, " [ \"COLLECTIVE\" whsp ] ; default not collective\n");
327 fprintf( stderr, " [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n");
328 fprintf( stderr, " [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n");
329 fprintf( stderr, " ; userApplications\n");
330 fprintf( stderr, " ; directoryOperation\n");
331 fprintf( stderr, " ; distributedOperation\n");
332 fprintf( stderr, " ; dSAOperation\n");
333 fprintf( stderr, "whsp \")\"\n");
334 exit( EXIT_FAILURE );
345 LDAP_ATTRIBUTE_TYPE *at;
351 /* Kludge for OIDmacros. If the numericOid field starts nonnumeric
352 * look for and expand a macro. The macro's place in the input line
353 * will be replaced with a field of '0's to keep ldap_str2attr
354 * happy. The actual oid will be swapped into place afterward.
356 if ( !isdigit( *argv[2] ))
358 oid = find_oidm(argv[2]);
361 fprintf(stderr, "%s: line %d: OID %s not recognized\n",
362 fname, lineno, argv[2]);
363 exit( EXIT_FAILURE );
366 memset(strstr(line, argv[2]), '0', strlen(argv[2]));
370 for (; argv[3]; argv++)
372 if (!strcasecmp(argv[3], "syntax") &&
377 syn = syn_find_desc(argv[4], &slen);
380 fprintf(stderr, "%s: line %d: OID %s not found\n",
381 fname, lineno, argv[4]);
382 exit( EXIT_FAILURE );
384 memset(strstr(line, argv[4]), '0', slen);
385 soid = ch_strdup(syn->ssyn_syn.syn_oid );
389 at = ldap_str2attributetype(line,&code,&err);
391 fprintf( stderr, "%s: line %d: %s before %s\n",
392 fname, lineno, ldap_scherr2str(code), err );
397 ldap_memfree(at->at_oid);
402 ldap_memfree(at->at_syntax_oid);
403 at->at_syntax_oid = soid;
405 code = at_add(at,&err);
407 fprintf( stderr, "%s: line %d: %s %s\n",
408 fname, lineno, scherr2str(code), err);
409 exit( EXIT_FAILURE );