version 1.12, 1999/06/15 10:28:54
|
version 1.12.8.14, 2002/01/04 20:38:31
|
Line 1
|
Line 1
|
/* schemaparse.c - routines to parse config file objectclass definitions */ |
/* schemaparse.c - routines to parse config file objectclass definitions */ |
|
/* $OpenLDAP: pkg/ldap/servers/slapd/schemaparse.c,v 1.12.8.13 2001/10/11 16:49:04 kurt Exp $ */ |
|
/* |
|
* Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. |
|
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file |
|
*/ |
|
|
#include "portable.h" |
#include "portable.h" |
|
|
#include <stdio.h> |
#include <stdio.h> |
|
|
|
#include <ac/ctype.h> |
#include <ac/string.h> |
#include <ac/string.h> |
#include <ac/socket.h> |
#include <ac/socket.h> |
|
|
#include "slap.h" |
#include "slap.h" |
#include "ldap_schema.h" |
#include "ldap_schema.h" |
|
|
static Avlnode *object_classes = NULL; |
|
|
|
int global_schemacheck = 1; /* schemacheck on is default */ |
int global_schemacheck = 1; /* schemacheck on is default */ |
|
|
static void oc_usage_old(void); |
static void oc_usage(void); |
static void oc_usage(void); |
static void at_usage(void); |
|
|
static char *err2text[] = { |
static char *const err2text[] = { |
"", |
"Success", |
"Out of memory", |
"Out of memory", |
"Objectclass not found", |
"ObjectClass not found", |
"Attribute type not found", |
"ObjectClass inappropriate SUPerior", |
"Duplicate objectclass", |
"AttributeType not found", |
"Duplicate attributetype", |
"AttributeType inappropriate USAGE", |
"Duplicate syntax", |
"Duplicate objectClass", |
"Duplicate matchingrule", |
"Duplicate attributeType", |
|
"Duplicate ldapSyntax", |
|
"Duplicate matchingRule", |
"OID or name required", |
"OID or name required", |
"Syntax or superior required", |
"SYNTAX or SUPerior required", |
"Matchingrule not found", |
"MatchingRule not found", |
"Syntax not found", |
"Syntax not found", |
"Syntax required" |
"Syntax required", |
|
"Qualifier not supported", |
|
"Invalid NAME" |
}; |
}; |
|
|
char * |
char * |
scherr2str(int code) |
scherr2str(int code) |
{ |
{ |
if ( code < 1 || code >= (sizeof(err2text)/sizeof(char *)) ) { |
if ( code < 0 || code >= (sizeof(err2text)/sizeof(char *)) ) { |
return "Unknown error"; |
return "Unknown error"; |
} else { |
} else { |
return err2text[code]; |
return err2text[code]; |
} |
} |
} |
} |
|
|
void |
/* check schema descr validity */ |
parse_oc_old( |
int slap_valid_descr( const char *descr ) |
Backend *be, |
|
char *fname, |
|
int lineno, |
|
int argc, |
|
char **argv |
|
) |
|
{ |
{ |
int i; |
int i=0; |
char last; |
|
LDAP_OBJECT_CLASS *oc; |
|
int code; |
|
const char *err; |
|
char **namep; |
|
|
|
oc = (LDAP_OBJECT_CLASS *) ch_calloc( 1, sizeof(LDAP_OBJECT_CLASS) ); |
if( !DESC_LEADCHAR( descr[i] ) ) { |
oc->oc_names = ch_calloc( 2, sizeof(char *) ); |
return 0; |
oc->oc_names[0] = ch_strdup( argv[1] ); |
} |
oc->oc_names[1] = NULL; |
|
if ( strcasecmp( oc->oc_names[0], "top" ) ) { |
|
oc->oc_kind = LDAP_SCHEMA_STRUCTURAL; |
|
} |
|
for ( i = 2; i < argc; i++ ) { |
|
/* required attributes */ |
|
if ( strcasecmp( argv[i], "requires" ) == 0 ) { |
|
do { |
|
i++; |
|
if ( i < argc ) { |
|
char **s = str2charray( argv[i], "," ); |
|
last = argv[i][strlen( argv[i] ) - 1]; |
|
charray_merge( &oc->oc_at_oids_must, s ); |
|
charray_free( s ); |
|
} |
|
} while ( i < argc && last == ',' ); |
|
|
|
/* optional attributes */ |
|
} else if ( strcasecmp( argv[i], "allows" ) == 0 ) { |
|
do { |
|
i++; |
|
if ( i < argc ) { |
|
char **s = str2charray( argv[i], "," ); |
|
last = argv[i][strlen( argv[i] ) - 1]; |
|
|
|
charray_merge( &oc->oc_at_oids_may, s ); |
|
charray_free( s ); |
|
} |
|
} while ( i < argc && last == ',' ); |
|
|
|
} else { |
while( descr[++i] ) { |
fprintf( stderr, |
if( !DESC_CHAR( descr[i] ) ) { |
"%s: line %d: expecting \"requires\" or \"allows\" got \"%s\"\n", |
return 0; |
fname, lineno, argv[i] ); |
|
oc_usage_old(); |
|
} |
} |
} |
} |
|
|
/* |
return 1; |
* There was no requirement in the old schema that all attributes |
} |
* types were defined before use and they would just default to |
|
* SYNTAX_CIS. To support this, we need to make attribute types |
|
* out of thin air. |
/* OID Macros */ |
*/ |
|
if ( oc->oc_at_oids_must ) { |
/* String compare with delimiter check. Return 0 if not |
namep = oc->oc_at_oids_must; |
* matched, otherwise return length matched. |
while ( *namep ) { |
*/ |
code = at_fake_if_needed( *namep ); |
int |
if ( code ) { |
dscompare(const char *s1, const char *s2, char delim) |
fprintf( stderr, "%s: line %d: %s %s\n", |
{ |
fname, lineno, scherr2str(code), *namep); |
const char *orig = s1; |
exit( 1 ); |
while (*s1++ == *s2++) |
} |
if (!s1[-1]) break; |
namep++; |
--s1; |
} |
--s2; |
|
if (!*s1 && (!*s2 || *s2 == delim)) |
|
return s1 - orig; |
|
return 0; |
|
} |
|
|
|
static OidMacro *om_list = NULL; |
|
|
|
/* Replace an OID Macro invocation with its full numeric OID. |
|
* If the macro is used with "macroname:suffix" append ".suffix" |
|
* to the expansion. |
|
*/ |
|
static char * |
|
find_oidm(char *oid) |
|
{ |
|
OidMacro *om; |
|
|
|
/* OID macros must start alpha */ |
|
if ( OID_LEADCHAR( *oid ) ) { |
|
return oid; |
} |
} |
if ( oc->oc_at_oids_may ) { |
|
namep = oc->oc_at_oids_may; |
for (om = om_list; om; om=om->som_next) { |
while ( *namep ) { |
char **names = om->som_names; |
code = at_fake_if_needed( *namep ); |
|
if ( code ) { |
if( names == NULL ) { |
fprintf( stderr, "%s: line %d: %s %s\n", |
continue; |
fname, lineno, scherr2str(code), *namep); |
} |
exit( 1 ); |
|
|
for( ; *names != NULL ; names++ ) { |
|
int pos = dscompare(*names, oid, ':'); |
|
|
|
if( pos ) { |
|
int suflen = strlen(oid + pos); |
|
char *new = ch_calloc(1, |
|
om->som_oid.bv_len + suflen + 1); |
|
strcpy(new, om->som_oid.bv_val); |
|
|
|
if( suflen ) { |
|
suflen = om->som_oid.bv_len; |
|
new[suflen++] = '.'; |
|
strcpy(new+suflen, oid+pos+1); |
|
} |
|
return new; |
} |
} |
namep++; |
|
} |
} |
} |
} |
|
return NULL; |
code = oc_add(oc,&err); |
} |
if ( code ) { |
|
fprintf( stderr, "%s: line %d: %s %s\n", |
int |
fname, lineno, scherr2str(code), err); |
parse_oidm( |
exit( 1 ); |
const char *fname, |
|
int lineno, |
|
int argc, |
|
char **argv |
|
) |
|
{ |
|
char *oid; |
|
OidMacro *om; |
|
|
|
if (argc != 3) { |
|
fprintf( stderr, "%s: line %d: too many arguments\n", |
|
fname, lineno ); |
|
usage: fprintf( stderr, "\tObjectIdentifier <name> <oid>\n"); |
|
return 1; |
} |
} |
ldap_memfree(oc); |
|
|
oid = find_oidm( argv[1] ); |
|
if( oid != NULL ) { |
|
fprintf( stderr, |
|
"%s: line %d: " |
|
"ObjectIdentifier \"%s\" previously defined \"%s\"", |
|
fname, lineno, argv[1], oid ); |
|
return 1; |
|
} |
|
|
|
om = (OidMacro *) ch_malloc( sizeof(OidMacro) ); |
|
|
|
om->som_names = NULL; |
|
charray_add( &om->som_names, argv[1] ); |
|
om->som_oid.bv_val = find_oidm( argv[2] ); |
|
|
|
if (!om->som_oid.bv_val) { |
|
fprintf( stderr, "%s: line %d: OID %s not recognized\n", |
|
fname, lineno, argv[2] ); |
|
goto usage; |
|
} |
|
|
|
if (om->som_oid.bv_val == argv[2]) { |
|
om->som_oid.bv_val = ch_strdup( argv[2] ); |
|
} |
|
|
|
om->som_oid.bv_len = strlen( om->som_oid.bv_val ); |
|
om->som_next = om_list; |
|
om_list = om; |
|
|
|
return 0; |
} |
} |
|
|
void |
int |
parse_oc( |
parse_oc( |
char *fname, |
const char *fname, |
int lineno, |
int lineno, |
char *line |
char *line, |
|
char **argv |
) |
) |
{ |
{ |
LDAP_OBJECT_CLASS *oc; |
LDAPObjectClass *oc; |
int code; |
int code; |
const char *err; |
const char *err; |
|
char *oid = NULL; |
|
|
oc = ldap_str2objectclass(line,&code,&err); |
oc = ldap_str2objectclass(line,&code,&err,LDAP_SCHEMA_ALLOW_ALL); |
if ( !oc ) { |
if ( !oc ) { |
fprintf( stderr, "%s: line %d: %s before %s\n", |
fprintf( stderr, "%s: line %d: %s before %s\n", |
fname, lineno, ldap_scherr2str(code), err ); |
fname, lineno, ldap_scherr2str(code), err ); |
oc_usage(); |
oc_usage(); |
|
return 1; |
|
} |
|
|
|
if ( oc->oc_oid == NULL ) { |
|
fprintf( stderr, |
|
"%s: line %d: objectclass has no OID\n", |
|
fname, lineno ); |
|
oc_usage(); |
|
return 1; |
|
} |
|
|
|
if ( !OID_LEADCHAR( oc->oc_oid[0] )) { |
|
/* Expand OID macros */ |
|
oid = find_oidm( oc->oc_oid ); |
|
if ( !oid ) { |
|
fprintf( stderr, |
|
"%s: line %d: OID %s not recognized\n", |
|
fname, lineno, oc->oc_oid); |
|
return 1; |
|
} |
|
if ( oid != oc->oc_oid ) { |
|
ldap_memfree( oc->oc_oid ); |
|
oc->oc_oid = oid; |
|
} |
} |
} |
|
|
code = oc_add(oc,&err); |
code = oc_add(oc,&err); |
if ( code ) { |
if ( code ) { |
fprintf( stderr, "%s: line %d: %s %s\n", |
fprintf( stderr, "%s: line %d: %s: \"%s\"\n", |
fname, lineno, scherr2str(code), err); |
fname, lineno, scherr2str(code), err); |
exit( 1 ); |
return 1; |
} |
} |
|
|
ldap_memfree(oc); |
ldap_memfree(oc); |
|
return 0; |
} |
} |
|
|
static void |
static void |
oc_usage( void ) |
oc_usage( void ) |
{ |
{ |
fprintf( stderr, "ObjectClassDescription = \"(\" whsp\n"); |
fprintf( stderr, |
fprintf( stderr, " numericoid whsp ; ObjectClass identifier\n"); |
"ObjectClassDescription = \"(\" whsp\n" |
fprintf( stderr, " [ \"NAME\" qdescrs ]\n"); |
" numericoid whsp ; ObjectClass identifier\n" |
fprintf( stderr, " [ \"DESC\" qdstring ]\n"); |
" [ \"NAME\" qdescrs ]\n" |
fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n"); |
" [ \"DESC\" qdstring ]\n" |
fprintf( stderr, " [ \"SUP\" oids ] ; Superior ObjectClasses\n"); |
" [ \"OBSOLETE\" whsp ]\n" |
fprintf( stderr, " [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n"); |
" [ \"SUP\" oids ] ; Superior ObjectClasses\n" |
fprintf( stderr, " ; default structural\n"); |
" [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n" |
fprintf( stderr, " [ \"MUST\" oids ] ; AttributeTypes\n"); |
" ; default structural\n" |
fprintf( stderr, " [ \"MAY\" oids ] ; AttributeTypes\n"); |
" [ \"MUST\" oids ] ; AttributeTypes\n" |
fprintf( stderr, "whsp \")\"\n"); |
" [ \"MAY\" oids ] ; AttributeTypes\n" |
exit( 1 ); |
" whsp \")\"\n" ); |
} |
} |
|
|
static void |
|
oc_usage_old( void ) |
|
{ |
|
fprintf( stderr, "<oc clause> ::= objectclass <ocname>\n" ); |
|
fprintf( stderr, " [ requires <attrlist> ]\n" ); |
|
fprintf( stderr, " [ allows <attrlist> ]\n" ); |
|
exit( 1 ); |
|
} |
|
|
|
static void |
static void |
at_usage( void ) |
at_usage( void ) |
{ |
{ |
fprintf( stderr, "AttributeTypeDescription = \"(\" whsp\n"); |
fprintf( stderr, |
fprintf( stderr, " numericoid whsp ; AttributeType identifier\n"); |
"AttributeTypeDescription = \"(\" whsp\n" |
fprintf( stderr, " [ \"NAME\" qdescrs ] ; name used in AttributeType\n"); |
" numericoid whsp ; AttributeType identifier\n" |
fprintf( stderr, " [ \"DESC\" qdstring ] ; description\n"); |
" [ \"NAME\" qdescrs ] ; name used in AttributeType\n" |
fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n"); |
" [ \"DESC\" qdstring ] ; description\n" |
fprintf( stderr, " [ \"SUP\" woid ] ; derived from this other\n"); |
" [ \"OBSOLETE\" whsp ]\n" |
fprintf( stderr, " ; AttributeType\n"); |
" [ \"SUP\" woid ] ; derived from this other\n" |
fprintf( stderr, " [ \"EQUALITY\" woid ] ; Matching Rule name\n"); |
" ; AttributeType\n" |
fprintf( stderr, " [ \"ORDERING\" woid ] ; Matching Rule name\n"); |
" [ \"EQUALITY\" woid ] ; Matching Rule name\n" |
fprintf( stderr, " [ \"SUBSTR\" woid ] ; Matching Rule name\n"); |
" [ \"ORDERING\" woid ] ; Matching Rule name\n" |
fprintf( stderr, " [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n"); |
" [ \"SUBSTR\" woid ] ; Matching Rule name\n" |
fprintf( stderr, " [ \"SINGLE-VALUE\" whsp ] ; default multi-valued\n"); |
" [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n" |
fprintf( stderr, " [ \"COLLECTIVE\" whsp ] ; default not collective\n"); |
" [ \"SINGLE-VALUE\" whsp ] ; default multi-valued\n" |
fprintf( stderr, " [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n"); |
" [ \"COLLECTIVE\" whsp ] ; default not collective\n" |
fprintf( stderr, " [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n"); |
" [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n" |
fprintf( stderr, " ; userApplications\n"); |
" [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n" |
fprintf( stderr, " ; directoryOperation\n"); |
" ; userApplications\n" |
fprintf( stderr, " ; distributedOperation\n"); |
" ; directoryOperation\n" |
fprintf( stderr, " ; dSAOperation\n"); |
" ; distributedOperation\n" |
fprintf( stderr, "whsp \")\"\n"); |
" ; dSAOperation\n" |
exit( 1 ); |
" whsp \")\"\n"); |
} |
} |
|
|
void |
int |
parse_at( |
parse_at( |
char *fname, |
const char *fname, |
int lineno, |
int lineno, |
char *line |
char *line, |
|
char **argv |
) |
) |
{ |
{ |
LDAP_ATTRIBUTE_TYPE *at; |
LDAPAttributeType *at; |
int code; |
int code; |
const char *err; |
const char *err; |
|
char *oid = NULL; |
|
char *soid = NULL; |
|
|
at = ldap_str2attributetype(line,&code,&err); |
at = ldap_str2attributetype(line,&code,&err,LDAP_SCHEMA_ALLOW_ALL); |
if ( !at ) { |
if ( !at ) { |
fprintf( stderr, "%s: line %d: %s before %s\n", |
fprintf( stderr, "%s: line %d: %s before %s\n", |
fname, lineno, ldap_scherr2str(code), err ); |
fname, lineno, ldap_scherr2str(code), err ); |
at_usage(); |
at_usage(); |
|
return 1; |
|
} |
|
|
|
if ( at->at_oid == NULL ) { |
|
fprintf( stderr, |
|
"%s: line %d: attributeType has no OID\n", |
|
fname, lineno ); |
|
at_usage(); |
|
return 1; |
|
} |
|
|
|
if ( !OID_LEADCHAR( at->at_oid[0] )) { |
|
/* Expand OID macros */ |
|
oid = find_oidm( at->at_oid ); |
|
if ( !oid ) { |
|
fprintf( stderr, |
|
"%s: line %d: OID %s not recognized\n", |
|
fname, lineno, at->at_oid); |
|
return 1; |
|
} |
|
if ( oid != at->at_oid ) { |
|
ldap_memfree( at->at_oid ); |
|
at->at_oid = oid; |
|
} |
|
} |
|
|
|
if ( at->at_syntax_oid && !OID_LEADCHAR( at->at_syntax_oid[0] )) { |
|
/* Expand OID macros */ |
|
oid = find_oidm( at->at_syntax_oid ); |
|
if ( !oid ) { |
|
fprintf(stderr, |
|
"%s: line %d: OID %s not recognized\n", |
|
fname, lineno, at->at_syntax_oid); |
|
return 1; |
|
} |
|
if ( oid != at->at_syntax_oid ) { |
|
ldap_memfree( at->at_syntax_oid ); |
|
at->at_syntax_oid = oid; |
|
} |
|
|
} |
} |
code = at_add(at,&err); |
code = at_add(at,&err); |
if ( code ) { |
if ( code ) { |
fprintf( stderr, "%s: line %d: %s %s\n", |
fprintf( stderr, "%s: line %d: %s: \"%s\"\n", |
fname, lineno, scherr2str(code), err); |
fname, lineno, scherr2str(code), err); |
exit( 1 ); |
return 1; |
} |
} |
ldap_memfree(at); |
ldap_memfree(at); |
|
return 0; |
} |
} |