]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/schema_prep.c
More system schema checks
[openldap] / servers / slapd / schema_prep.c
index 143d167498fb2d33c5a6412344451460cf20608a..2c41c0d368954ddbf59dc7bbaf839fa8424bd7f2 100644 (file)
@@ -115,6 +115,12 @@ structuralObjectClassMatch(
        return LDAP_SUCCESS;
 }
 
+static ObjectClassSchemaCheckFN rootDseObjectClass;
+static ObjectClassSchemaCheckFN aliasObjectClass;
+static ObjectClassSchemaCheckFN referralObjectClass;
+static ObjectClassSchemaCheckFN subentryObjectClass;
+static ObjectClassSchemaCheckFN dynamicObjectClass;
+
 static struct slap_schema_oc_map {
        char *ssom_name;
        char *ssom_defn;
@@ -134,38 +140,51 @@ static struct slap_schema_oc_map {
                        "DESC 'RFC2256: an alias' "
                        "SUP top STRUCTURAL "
                        "MUST aliasedObjectName )",
-               0, offsetof(struct slap_internal_schema, si_oc_alias) },
+               aliasObjectClass,
+               offsetof(struct slap_internal_schema, si_oc_alias) },
        { "referral", "( 2.16.840.1.113730.3.2.6 NAME 'referral' "
                        "DESC 'namedref: named subordinate referral' "
                        "SUP top STRUCTURAL MUST ref )",
-               0, offsetof(struct slap_internal_schema, si_oc_referral) },
+               referralObjectClass,
+               offsetof(struct slap_internal_schema, si_oc_referral) },
        { "LDAProotDSE", "( 1.3.6.1.4.1.4203.1.4.1 "
                        "NAME ( 'OpenLDAProotDSE' 'LDAProotDSE' ) "
                        "DESC 'OpenLDAP Root DSE object' "
                        "SUP top STRUCTURAL MAY cn )",
-               0, offsetof(struct slap_internal_schema, si_oc_rootdse) },
+               rootDseObjectClass,
+               offsetof(struct slap_internal_schema, si_oc_rootdse) },
        { "subentry", "( 2.5.20.0 NAME 'subentry' "
                        "SUP top STRUCTURAL "
                        "MUST ( cn $ subtreeSpecification ) )",
-               0, offsetof(struct slap_internal_schema, si_oc_subentry) },
+               subentryObjectClass,
+               offsetof(struct slap_internal_schema, si_oc_subentry) },
        { "subschema", "( 2.5.20.1 NAME 'subschema' "
                "DESC 'RFC2252: controlling subschema (sub)entry' "
-               "AUXILIARY"
+               "AUXILIARY "
                "MAY ( dITStructureRules $ nameForms $ ditContentRules $ "
                        "objectClasses $ attributeTypes $ matchingRules $ "
                        "matchingRuleUse ) )",
-               0, offsetof(struct slap_internal_schema, si_oc_subschema) },
+               subentryObjectClass,
+               offsetof(struct slap_internal_schema, si_oc_subschema) },
        { "collectiveAttributes", "( 2.5.20.2 "
                        "NAME 'collectiveAttributes' "
                        "AUXILIARY )",
-               0,
+               subentryObjectClass,
                offsetof(struct slap_internal_schema, si_oc_collectiveAttributes) },
+       { "dynamicObject", "( 1.3.6.1.4.1.1466.101.119.2 "
+                       "NAME 'dynamicObject' "
+                       "DESC 'RFC2589: Dynamic Object' "
+                       "SUP top AUXILIARY )",
+               dynamicObjectClass,
+               offsetof(struct slap_internal_schema, si_oc_dynamicObject) },
        { NULL, 0 }
 };
 
 static AttributeTypeSchemaCheckFN rootDseAttribute;
-static AttributeTypeSchemaCheckFN subentryAttribute;
+static AttributeTypeSchemaCheckFN aliasAttribute;
 static AttributeTypeSchemaCheckFN referralAttribute;
+static AttributeTypeSchemaCheckFN subentryAttribute;
+static AttributeTypeSchemaCheckFN dynamicAttribute;
 
 static struct slap_schema_ad_map {
        char *ssam_name;
@@ -399,7 +418,7 @@ static struct slap_schema_ad_map {
                        "DESC 'RFC2256: name of aliased object' "
                        "EQUALITY distinguishedNameMatch "
                        "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )",
-               NULL, NULL, NULL, NULL,
+               aliasAttribute, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_aliasedObjectName) },
        { "ref", "( 2.16.840.1.113730.3.1.34 NAME 'ref' "
                        "DESC 'namedref: subordinate referral URL' "
@@ -439,7 +458,7 @@ static struct slap_schema_ad_map {
                        "DESC 'RFC2589: entry time-to-live' "
                        "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE "
                        "NO-USER-MODIFICATION USAGE dSAOperation )",
-               NULL, NULL, NULL, NULL,
+               dynamicAttribute, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_entryTtl) },
        { "dynamicSubtrees", "( 1.3.6.1.4.1.1466.101.119.4 "
                        "NAME 'dynamicSubtrees' "
@@ -449,7 +468,7 @@ static struct slap_schema_ad_map {
                rootDseAttribute, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_dynamicSubtrees) },
 
-       /* userApplication attributes */
+       /* userApplication attributes (which system schema depends upon) */
        { "distinguishedName", "( 2.5.4.49 NAME 'distinguishedName' "
                        "DESC 'RFC2256: common supertype of DN attributes' "
                        "EQUALITY distinguishedNameMatch "
@@ -468,7 +487,6 @@ static struct slap_schema_ad_map {
                        "SUP name )",
                NULL, NULL, NULL, NULL,
                offsetof(struct slap_internal_schema, si_ad_cn) },
-
        { "userPassword", "( 2.5.4.35 NAME 'userPassword' "
                        "DESC 'RFC2256/2307: password of user' "
                        "EQUALITY octetStringMatch "
@@ -577,36 +595,37 @@ slap_schema_load( void )
        }
 
        for( i=0; oc_map[i].ssom_name; i++ ) {
-               LDAPObjectClass *oc;
-               int             code;
-               const char      *err;
-
-               oc = ldap_str2objectclass( oc_map[i].ssom_defn, &code, &err,
-                       LDAP_SCHEMA_ALLOW_ALL );
-               if ( !oc ) {
-                       fprintf( stderr, "slap_schema_load: "
-                               "%s: %s before %s\n",
-                                oc_map[i].ssom_name, ldap_scherr2str(code), err );
-                       return code;
-               }
+               if( oc_map[i].ssom_defn != NULL ) {
+                       LDAPObjectClass *oc;
+                       int             code;
+                       const char      *err;
 
-               if ( oc->oc_oid == NULL ) {
-                       fprintf( stderr, "slap_schema_load: "
-                               "%s: objectclass has no OID\n",
-                               oc_map[i].ssom_name );
-                       return LDAP_OTHER;
-               }
+                       oc = ldap_str2objectclass( oc_map[i].ssom_defn, &code, &err,
+                               LDAP_SCHEMA_ALLOW_ALL );
+                       if ( !oc ) {
+                               fprintf( stderr, "slap_schema_load: "
+                                       "%s: %s before %s\n",
+                                       oc_map[i].ssom_name, ldap_scherr2str(code), err );
+                               return code;
+                       }
 
-               code = oc_add(oc,&err);
-               if ( code ) {
-                       fprintf( stderr, "slap_schema_load: "
-                               "%s: %s: \"%s\"\n",
-                                oc_map[i].ssom_name, scherr2str(code), err);
-                       return code;
-               }
+                       if ( oc->oc_oid == NULL ) {
+                               fprintf( stderr, "slap_schema_load: "
+                                       "%s: objectclass has no OID\n",
+                                       oc_map[i].ssom_name );
+                               return LDAP_OTHER;
+                       }
 
-               ldap_memfree(oc);
-               return 0;
+                       code = oc_add(oc,&err);
+                       if ( code ) {
+                               fprintf( stderr, "slap_schema_load: "
+                                       "%s: %s: \"%s\"\n",
+                                       oc_map[i].ssom_name, scherr2str(code), err);
+                               return code;
+                       }
+
+                       ldap_memfree(oc);
+               }
        }
 
        return LDAP_SUCCESS;
@@ -703,16 +722,122 @@ slap_schema_check( void )
        return LDAP_SUCCESS;
 }
 
+static int rootDseObjectClass (
+       Backend *be,
+       Entry *e,
+       ObjectClass *oc,
+       const char** text,
+       char *textbuf, size_t textlen )
+{
+       *text = textbuf;
+
+       if( e->e_nname.bv_len ) {
+               snprintf( textbuf, textlen,
+                       "objectClass \"%s\" only allowed in the root DSE",
+                       oc->soc_oid );
+               return LDAP_OBJECT_CLASS_VIOLATION;
+       }
+
+       /* we should not be called for the root DSE */
+       assert( 0 );
+       return LDAP_SUCCESS;
+}
+
+static int aliasObjectClass (
+       Backend *be,
+       Entry *e,
+       ObjectClass *oc,
+       const char** text,
+       char *textbuf, size_t textlen )
+{
+       *text = textbuf;
+
+       if( !SLAP_ALIASES(be) ) {
+               snprintf( textbuf, textlen,
+                       "objectClass \"%s\" not supported in context",
+                       oc->soc_oid );
+               return LDAP_OBJECT_CLASS_VIOLATION;
+       }
+
+       return LDAP_SUCCESS;
+}
+
+static int referralObjectClass (
+       Backend *be,
+       Entry *e,
+       ObjectClass *oc,
+       const char** text,
+       char *textbuf, size_t textlen )
+{
+       *text = textbuf;
+
+       if( !SLAP_REFERRALS(be) ) {
+               snprintf( textbuf, textlen,
+                       "objectClass \"%s\" not supported in context",
+                       oc->soc_oid );
+               return LDAP_OBJECT_CLASS_VIOLATION;
+       }
+
+       return LDAP_SUCCESS;
+}
+
+static int subentryObjectClass (
+       Backend *be,
+       Entry *e,
+       ObjectClass *oc,
+       const char** text,
+       char *textbuf, size_t textlen )
+{
+       *text = textbuf;
+
+       if( !SLAP_SUBENTRIES(be) ) {
+               snprintf( textbuf, textlen,
+                       "objectClass \"%s\" not supported in context",
+                       oc->soc_oid );
+               return LDAP_OBJECT_CLASS_VIOLATION;
+       }
+
+       if( oc != slap_schema.si_oc_subentry && !is_entry_subentry( e ) ) {
+               snprintf( textbuf, textlen,
+                       "objectClass \"%s\" only allowed in subentries",
+                       oc->soc_oid );
+               return LDAP_OBJECT_CLASS_VIOLATION;
+       }
+
+       return LDAP_SUCCESS;
+}
+
+static int dynamicObjectClass (
+       Backend *be,
+       Entry *e,
+       ObjectClass *oc,
+       const char** text,
+       char *textbuf, size_t textlen )
+{
+       *text = textbuf;
+
+       if( !SLAP_DYNAMIC(be) ) {
+               snprintf( textbuf, textlen,
+                       "objectClass \"%s\" not supported in context",
+                       oc->soc_oid );
+               return LDAP_OBJECT_CLASS_VIOLATION;
+       }
+
+       return LDAP_SUCCESS;
+}
+
 static int rootDseAttribute (
+       Backend *be,
        Entry *e,
        Attribute *attr,
        const char** text,
        char *textbuf, size_t textlen )
 {
        *text = textbuf;
+
        if( e->e_nname.bv_len ) {
                snprintf( textbuf, textlen,
-                       "attribute \"%s\"only allowed in the root DSE",
+                       "attribute \"%s\" only allowed in the root DSE",
                        attr->a_desc->ad_cname.bv_val );
                return LDAP_OBJECT_CLASS_VIOLATION;
        }
@@ -722,16 +847,25 @@ static int rootDseAttribute (
        return LDAP_SUCCESS;
 }
 
-static int subentryAttribute (
+static int aliasAttribute (
+       Backend *be,
        Entry *e,
        Attribute *attr,
        const char** text,
        char *textbuf, size_t textlen )
 {
        *text = textbuf;
-       if( !is_entry_subentry( e ) ) {
+
+       if( !SLAP_ALIASES(be) ) {
+               snprintf( textbuf, textlen,
+                       "attribute \"%s\" not supported in context",
+                       attr->a_desc->ad_cname.bv_val );
+               return LDAP_OBJECT_CLASS_VIOLATION;
+       }
+
+       if( !is_entry_alias( e ) ) {
                snprintf( textbuf, textlen,
-                       "attribute \"%s\"only allowed in the subentry",
+                       "attribute \"%s\" only allowed in the alias",
                        attr->a_desc->ad_cname.bv_val );
                return LDAP_OBJECT_CLASS_VIOLATION;
        }
@@ -740,15 +874,76 @@ static int subentryAttribute (
 }
 
 static int referralAttribute (
+       Backend *be,
        Entry *e,
        Attribute *attr,
        const char** text,
        char *textbuf, size_t textlen )
 {
        *text = textbuf;
+
+       if( !SLAP_REFERRALS(be) ) {
+               snprintf( textbuf, textlen,
+                       "attribute \"%s\" not supported in context",
+                       attr->a_desc->ad_cname.bv_val );
+               return LDAP_OBJECT_CLASS_VIOLATION;
+       }
+
        if( !is_entry_referral( e ) ) {
                snprintf( textbuf, textlen,
-                       "attribute \"%s\"only allowed in the referral",
+                       "attribute \"%s\" only allowed in the referral",
+                       attr->a_desc->ad_cname.bv_val );
+               return LDAP_OBJECT_CLASS_VIOLATION;
+       }
+
+       return LDAP_SUCCESS;
+}
+
+static int subentryAttribute (
+       Backend *be,
+       Entry *e,
+       Attribute *attr,
+       const char** text,
+       char *textbuf, size_t textlen )
+{
+       *text = textbuf;
+
+       if( !SLAP_SUBENTRIES(be) ) {
+               snprintf( textbuf, textlen,
+                       "attribute \"%s\" not supported in context",
+                       attr->a_desc->ad_cname.bv_val );
+               return LDAP_OBJECT_CLASS_VIOLATION;
+       }
+
+       if( !is_entry_subentry( e ) ) {
+               snprintf( textbuf, textlen,
+                       "attribute \"%s\" only allowed in the subentry",
+                       attr->a_desc->ad_cname.bv_val );
+               return LDAP_OBJECT_CLASS_VIOLATION;
+       }
+
+       return LDAP_SUCCESS;
+}
+
+static int dynamicAttribute (
+       Backend *be,
+       Entry *e,
+       Attribute *attr,
+       const char** text,
+       char *textbuf, size_t textlen )
+{
+       *text = textbuf;
+
+       if( !SLAP_DYNAMIC(be) ) {
+               snprintf( textbuf, textlen,
+                       "attribute \"%s\" not supported in context",
+                       attr->a_desc->ad_cname.bv_val );
+               return LDAP_OBJECT_CLASS_VIOLATION;
+       }
+
+       if( !is_entry_dynamicObject( e ) ) {
+               snprintf( textbuf, textlen,
+                       "attribute \"%s\" only allowed in dynamic object",
                        attr->a_desc->ad_cname.bv_val );
                return LDAP_OBJECT_CLASS_VIOLATION;
        }