X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fschemaparse.c;h=6f00e93eef2fa297d1cbfed1887fd8d11004caca;hb=517fa54bb0f764968ca56e7931a09adac4f33af6;hp=8f72136abbc2711209d36b66d69ab713c32d4fcc;hpb=2a869f5a99f537b246ba8640502e2a86117cb6e8;p=openldap diff --git a/servers/slapd/schemaparse.c b/servers/slapd/schemaparse.c index 8f72136abb..6f00e93eef 100644 --- a/servers/slapd/schemaparse.c +++ b/servers/slapd/schemaparse.c @@ -1,82 +1,325 @@ /* schemaparse.c - routines to parse config file objectclass definitions */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #include "portable.h" #include +#include #include #include #include "slap.h" +#include "ldap_schema.h" -extern char **str2charray(); -extern void charray_merge(); +int global_schemacheck = 1; /* schemacheck on is default */ -struct objclass *global_oc; -int global_schemacheck; +static void oc_usage(void) LDAP_GCCATTR((noreturn)); +static void at_usage(void) LDAP_GCCATTR((noreturn)); -static void oc_usage(); +static char *const err2text[] = { + "Success", + "Out of memory", + "ObjectClass not found", + "AttributeType not found", + "Duplicate objectClass", + "Duplicate attributeType", + "Duplicate ldapSyntax", + "Duplicate matchingRule", + "OID or name required", + "SYNTAX or SUPerior required", + "MatchingRule not found", + "Syntax not found", + "Syntax required" +}; + +char * +scherr2str(int code) +{ + if ( code < 0 || code >= (sizeof(err2text)/sizeof(char *)) ) { + return "Unknown error"; + } else { + return err2text[code]; + } +} + + +/* OID Macros */ + +/* String compare with delimiter check. Return 0 if not + * matched, otherwise return length matched. + */ +int +dscompare(const char *s1, const char *s2, char delim) +{ + const char *orig = s1; + while (*s1++ == *s2++) + if (!s1[-1]) break; + --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; + } + + for (om = om_list; om; om=om->som_next) { + char **names = om->som_names; + + if( names == NULL ) { + continue; + } + + 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; + } + } + } + return NULL; +} void -parse_oc( - Backend *be, - char *fname, +parse_oidm( + 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 \n"); + exit( EXIT_FAILURE ); + } + + oid = find_oidm( argv[1] ); + if( oid != NULL ) { + fprintf( stderr, + "%s: line %d: " + "ObjectIdentifier \"%s\" previously defined \"%s\"", + fname, lineno, argv[1], oid ); + exit( EXIT_FAILURE ); + } + + 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; +} + +void +parse_oc( + const char *fname, + int lineno, + char *line, char **argv ) { - int i; - char last; - struct objclass *oc; - struct objclass **ocp; - - oc = (struct objclass *) ch_calloc( 1, sizeof(struct objclass) ); - oc->oc_name = strdup( argv[1] ); - for ( i = 2; i < argc; i++ ) { - /* required attributes */ - if ( strcasecmp( argv[i], "requires" ) == 0 ) { - do { - i++; - if ( i < argc ) { - last = argv[i][strlen( argv[i] ) - 1]; - charray_merge( &oc->oc_required, - str2charray( argv[i], "," ) ); - } - } while ( i < argc && last == ',' ); - - /* optional attributes */ - } else if ( strcasecmp( argv[i], "allows" ) == 0 ) { - do { - i++; - if ( i < argc ) { - last = argv[i][strlen( argv[i] ) - 1]; - charray_merge( &oc->oc_allowed, - str2charray( argv[i], "," ) ); - } - } while ( i < argc && last == ',' ); + LDAP_OBJECT_CLASS *oc; + int code; + const char *err; + char *oid = NULL; - } else { - fprintf( stderr, - "%s: line %d: expecting \"requires\" or \"allows\" got \"%s\"\n", - fname, lineno, argv[i] ); - oc_usage(); + oc = ldap_str2objectclass(line,&code,&err,LDAP_SCHEMA_ALLOW_ALL); + if ( !oc ) { + fprintf( stderr, "%s: line %d: %s before %s\n", + fname, lineno, ldap_scherr2str(code), err ); + oc_usage(); + } + if ( oc->oc_oid ) { + 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); + exit( EXIT_FAILURE ); + } + if ( oid != oc->oc_oid ) { + ldap_memfree( oc->oc_oid ); + oc->oc_oid = oid; + } } } - - ocp = &global_oc; - while ( *ocp != NULL ) { - ocp = &(*ocp)->oc_next; + /* oc->oc_oid == NULL will be an error someday */ + code = oc_add(oc,&err); + if ( code ) { + fprintf( stderr, "%s: line %d: %s: \"%s\"\n", + fname, lineno, scherr2str(code), err); + exit( EXIT_FAILURE ); } - *ocp = oc; + ldap_memfree(oc); } static void -oc_usage() +oc_usage( void ) { - fprintf( stderr, " ::= objectclass \n" ); - fprintf( stderr, " [ requires ]\n" ); - fprintf( stderr, " [ allows ]\n" ); - exit( 1 ); + fprintf( stderr, + "ObjectClassDescription = \"(\" whsp\n" + " numericoid whsp ; ObjectClass identifier\n" + " [ \"NAME\" qdescrs ]\n" + " [ \"DESC\" qdstring ]\n" + " [ \"OBSOLETE\" whsp ]\n" + " [ \"SUP\" oids ] ; Superior ObjectClasses\n" + " [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n" + " ; default structural\n" + " [ \"MUST\" oids ] ; AttributeTypes\n" + " [ \"MAY\" oids ] ; AttributeTypes\n" + " whsp \")\"\n" ); + exit( EXIT_FAILURE ); } + +static void +at_usage( void ) +{ + fprintf( stderr, + "AttributeTypeDescription = \"(\" whsp\n" + " numericoid whsp ; AttributeType identifier\n" + " [ \"NAME\" qdescrs ] ; name used in AttributeType\n" + " [ \"DESC\" qdstring ] ; description\n" + " [ \"OBSOLETE\" whsp ]\n" + " [ \"SUP\" woid ] ; derived from this other\n" + " ; AttributeType\n" + " [ \"EQUALITY\" woid ] ; Matching Rule name\n" + " [ \"ORDERING\" woid ] ; Matching Rule name\n" + " [ \"SUBSTR\" woid ] ; Matching Rule name\n" + " [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n" + " [ \"SINGLE-VALUE\" whsp ] ; default multi-valued\n" + " [ \"COLLECTIVE\" whsp ] ; default not collective\n" + " [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n" + " [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n" + " ; userApplications\n" + " ; directoryOperation\n" + " ; distributedOperation\n" + " ; dSAOperation\n" + " whsp \")\"\n"); + exit( EXIT_FAILURE ); +} + +void +parse_at( + const char *fname, + int lineno, + char *line, + char **argv +) +{ + LDAP_ATTRIBUTE_TYPE *at; + int code; + const char *err; + char *oid = NULL; + char *soid = NULL; + + /* Kludge for OIDmacros for syntaxes. If the syntax field starts + * nonnumeric, look for and expand a macro. The macro's place in + * the input line will be replaced with a field of '0's to keep + * ldap_str2attributetype happy. The actual oid will be swapped + * into place afterwards. + */ + for (; argv[3]; argv++) + { + if (!strcasecmp(argv[3], "syntax") && + !OID_LEADCHAR(*argv[4])) + { + int slen; + Syntax *syn; + syn = syn_find_desc(argv[4], &slen); + if (!syn) + { + fprintf(stderr, "%s: line %d: OID %s not found\n", + fname, lineno, argv[4]); + exit( EXIT_FAILURE ); + } + memset(strstr(line, argv[4]), '0', slen); + soid = ch_strdup(syn->ssyn_syn.syn_oid ); + break; + } + } + at = ldap_str2attributetype(line,&code,&err,LDAP_SCHEMA_ALLOW_ALL); + if ( !at ) { + fprintf( stderr, "%s: line %d: %s before %s\n", + fname, lineno, ldap_scherr2str(code), err ); + at_usage(); + } + if ( at->at_oid ) { + 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); + exit( EXIT_FAILURE ); + } + if ( oid != at->at_oid ) { + ldap_memfree( at->at_oid ); + at->at_oid = oid; + } + } + } + /* at->at_oid == NULL will be an error someday */ + if (soid) { + ldap_memfree(at->at_syntax_oid); + at->at_syntax_oid = soid; + } + code = at_add(at,&err); + if ( code ) { + fprintf( stderr, "%s: line %d: %s: \"%s\"\n", + fname, lineno, scherr2str(code), err); + exit( EXIT_FAILURE ); + } + ldap_memfree(at); +}