]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/schema_init.c
liberally accept many LDAPv2/LDAPv3 stuff in DN (quoted parts, ';' as rdn separator...
[openldap] / servers / slapd / schema_init.c
index c3d0fd50ee6c660872665ef925bf55fb95dcbc5e..8437777e12722ed44d77784a3079b37862fca325 100644 (file)
 #define berValidate                                            blobValidate
 
 /* unimplemented pretters */
+#define integerPretty                                  NULL
 #ifndef USE_LDAP_DN_PARSING
-#define dnPretty                                               NULL
+#      define dnPretty                                         NULL
+#else
+#      define SLAP_LDAPDN_PRETTY 0x1
 #endif /* !USE_LDAP_DN_PARSING */
-#define integerPretty                                  NULL
 
 /* recycled matching routines */
 #define bitStringMatch                                 octetStringMatch
@@ -233,7 +235,11 @@ dnValidate(
                return( LDAP_SUCCESS );
        }
 
-       rc = ldap_str2dn( in->bv_val, &dn, LDAP_DN_FORMAT_LDAPV3 );
+       rc = ldap_str2dn( in->bv_val, &dn, LDAP_DN_FORMAT_LDAP );
+
+       /*
+        * Fixme: should we also validate each DN component?
+        */
        ldapava_free_dn( dn );
        
        if ( rc != LDAP_SUCCESS ) {
@@ -243,6 +249,143 @@ dnValidate(
        return( LDAP_SUCCESS );
 }
 
+static void
+AVA_Sort( LDAPRDN *rdn, int iAVA )
+{
+       int             i;
+       LDAPAVA         *ava_in = rdn[ iAVA ][ 0 ];
+       
+       for ( i = 0; i < iAVA; i++ ) {
+               LDAPAVA         *ava = rdn[ i ][ 0 ];
+               int             a, j;
+
+               a = strcmp( ava_in->la_attr->bv_val, ava->la_attr->bv_val );
+
+               if ( a > 0 ) {
+                       break;
+               }
+
+               while ( a == 0 ) {
+                       int             v, d;
+
+                       d = ava_in->la_value->bv_len - ava->la_value->bv_len;
+
+                       v = memcmp( ava_in->la_value->bv_val, 
+                                       ava->la_value->bv_val,
+                                       d <= 0 ? ava_in->la_value->bv_len 
+                                               : ava->la_value->bv_len );
+
+                       if ( v == 0 && d != 0 ) {
+                               v = d;
+                       }
+
+                       if ( v <= 0 ) {
+                               /* 
+                                * got it!
+                                */
+                               break;
+                       }
+
+                       if ( ++i == iAVA ) {
+                               /*
+                                * already sorted
+                                */
+                               return;
+                       }
+
+                       ava = rdn[ i ][ 0 ];
+                       a = strcmp( ava_in->la_value->bv_val, 
+                                       ava->la_value->bv_val );
+               }
+
+               /*
+                * move ahead
+                */
+               for ( j = iAVA; j > i; j-- ) {
+                       rdn[ j ][ 0 ] = rdn[ j - 1 ][ 0 ];
+               }
+               rdn[ i ][ 0 ] = ava_in;
+
+               return;
+       }
+}
+
+/*
+ * In-place, schema-aware normalization / "pretty"ing of the
+ * structural representation of a distinguished name.
+ */
+static int
+LDAPDN_rewrite( LDAPDN *dn, unsigned flags )
+{
+       int             iRDN;
+       int             rc;
+
+       assert( dn );
+
+       for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
+               LDAPRDN         *rdn = dn[ iRDN ][ 0 ];
+               int             iAVA;
+
+               for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
+                       LDAPAVA                 *ava = rdn[ iAVA ][ 0 ];
+                       AttributeDescription    *ad = NULL;
+                       const char              *text = NULL;
+                       slap_syntax_transform_func *transf = NULL;
+                       MatchingRule *mr;
+                       struct berval           *bv = NULL;
+
+                       rc = slap_bv2ad( ava->la_attr, &ad, &text );
+                       if ( rc != LDAP_SUCCESS ) {
+                               return LDAP_INVALID_SYNTAX;
+                       }
+
+                       /* 
+                        * Replace attr oid/name with the canonical name
+                        */
+                       ber_bvfree( ava->la_attr );
+                       ava->la_attr = ber_bvdup( &ad->ad_cname );
+
+                       if( flags & SLAP_LDAPDN_PRETTY ) {
+                               transf = ad->ad_type->sat_syntax->ssyn_pretty;
+                               mr = NULL;
+                       } else {
+                               transf = ad->ad_type->sat_syntax->ssyn_normalize;
+                               mr = ad->ad_type->sat_equality;
+                       }
+
+                       if ( transf ) {
+                               /*
+                                * transform value by normalize/pretty function
+                                */
+                               rc = ( *transf )( ad->ad_type->sat_syntax,
+                                       ava->la_value, &bv );
+                       
+                               if ( rc != LDAP_SUCCESS ) {
+                                       return LDAP_INVALID_SYNTAX;
+                               }
+                       }
+
+                       if( mr && ( mr->smr_usage & SLAP_MR_DN_FOLD ) ) {
+                               struct berval *s = bv;
+
+                               bv = ber_bvstr( UTF8normalize( bv ? bv : ava->la_value, 
+                                       UTF8_CASEFOLD ) );
+
+                               ber_bvfree( s );
+                       }
+
+                       if( bv ) {
+                               ber_bvfree( ava->la_value );
+                               ava->la_value = bv;
+                       }
+
+                       AVA_Sort( rdn, iAVA );
+               }
+       }
+
+       return LDAP_SUCCESS;
+}
+
 int
 dnNormalize(
        Syntax *syntax,
@@ -251,21 +394,38 @@ dnNormalize(
 {
        struct berval *out = NULL;
 
+       Debug( LDAP_DEBUG_TRACE, ">>> dnNormalize: <%s>\n", val->bv_val, 0, 0 );
+
        if ( val->bv_len != 0 ) {
                LDAPDN          *dn = NULL;
                char            *dn_out = NULL;
                int             rc;
 
-               rc = ldap_str2dn( val->bv_val, &dn, LDAP_DN_FORMAT_LDAPV3 );
+               /*
+                * Go to structural representation
+                */
+               rc = ldap_str2dn( val->bv_val, &dn, LDAP_DN_FORMAT_LDAP );
                if ( rc != LDAP_SUCCESS ) {
-                       return( LDAP_INVALID_SYNTAX );
+                       return LDAP_INVALID_SYNTAX;
+               }
+
+               /*
+                * Schema-aware rewrite
+                */
+               if ( LDAPDN_rewrite( dn, 0 ) != LDAP_SUCCESS ) {
+                       ldapava_free_dn( dn );
+                       return LDAP_INVALID_SYNTAX;
                }
 
+               /*
+                * Back to string representation
+                */
                rc = ldap_dn2str( dn, &dn_out, LDAP_DN_FORMAT_LDAPV3 );
+
                ldapava_free_dn( dn );
 
                if ( rc != LDAP_SUCCESS ) {
-                       return( LDAP_INVALID_SYNTAX );
+                       return LDAP_INVALID_SYNTAX;
                }
 
                out = ber_bvstr( dn_out );
@@ -274,37 +434,50 @@ dnNormalize(
                out = ber_bvdup( val );
        }
 
+       Debug( LDAP_DEBUG_TRACE, "<<< dnNormalize: <%s>\n", out->bv_val, 0, 0 );
+
        *normalized = out;
 
-       return( LDAP_SUCCESS );
+       return LDAP_SUCCESS;
 }
 
 int
 dnPretty(
        Syntax *syntax,
        struct berval *val,
-       struct berval **normalized)
+       struct berval **pretty)
 {
        struct berval *out = NULL;
 
+       Debug( LDAP_DEBUG_TRACE, ">>> dnPretty: <%s>\n", val->bv_val, 0, 0 );
+
        if ( val->bv_len != 0 ) {
                LDAPDN          *dn = NULL;
                char            *dn_out = NULL;
-               unsigned        flags = LDAP_DN_FORMAT_LDAPV3;
                int             rc;
 
-               rc = ldap_str2dn( val->bv_val, &dn, flags );
+               /* FIXME: should be liberal in what we accept */
+               rc = ldap_str2dn( val->bv_val, &dn, LDAP_DN_FORMAT_LDAP );
                if ( rc != LDAP_SUCCESS ) {
-                       return( LDAP_INVALID_SYNTAX );
+                       return LDAP_INVALID_SYNTAX;
                }
 
-               flags |= LDAP_DN_PRETTY;
+               /*
+                * Schema-aware rewrite
+                */
+               if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY ) != LDAP_SUCCESS ) {
+                       ldapava_free_dn( dn );
+                       return LDAP_INVALID_SYNTAX;
+               }
+
+               /* FIXME: not sure why the default isn't pretty */
+               rc = ldap_dn2str( dn, &dn_out,
+                       LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY );
 
-               rc = ldap_dn2str( dn, &dn_out, flags );
                ldapava_free_dn( dn );
 
                if ( rc != LDAP_SUCCESS ) {
-                       return( LDAP_INVALID_SYNTAX );
+                       return LDAP_INVALID_SYNTAX;
                }
 
                out = ber_bvstr( dn_out );
@@ -313,9 +486,11 @@ dnPretty(
                out = ber_bvdup( val );
        }
 
-       *normalized = out;
+       Debug( LDAP_DEBUG_TRACE, "<<< dnPretty: <%s>\n", out->bv_val, 0, 0 );
 
-       return( LDAP_SUCCESS );
+       *pretty = out;
+
+       return LDAP_SUCCESS;
 }
 
 int
@@ -333,13 +508,7 @@ dnMatch(
        match = value->bv_len - asserted->bv_len;
 
        if ( match == 0 ) {
-#ifdef USE_DN_NORMALIZE
                match = strcmp( value->bv_val, asserted->bv_val );
-               fprintf(stderr, "USE_DN_NORMALIZE :(\n");
-#else
-               match = strcasecmp( value->bv_val, asserted->bv_val );
-               fprintf(stderr, "!USE_DN_NORMALIZE :)\n");
-#endif
        }
 
 #ifdef NEW_LOGGING
@@ -4621,7 +4790,7 @@ struct mrule_defs_rec mrule_defs[] = {
 
        {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
-               SLAP_MR_EQUALITY | SLAP_MR_EXT,
+               SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
                NULL, NULL,
                caseIgnoreMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
                directoryStringApproxMatchOID },
@@ -4667,7 +4836,7 @@ struct mrule_defs_rec mrule_defs[] = {
 
        {"( 2.5.13.8 NAME 'numericStringMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
-               SLAP_MR_EQUALITY | SLAP_MR_EXT,
+               SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
                NULL, NULL,
                caseIgnoreIA5Match,
                caseIgnoreIA5Indexer,
@@ -4685,7 +4854,7 @@ struct mrule_defs_rec mrule_defs[] = {
 
        {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
-               SLAP_MR_EQUALITY | SLAP_MR_EXT,
+               SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
                NULL, NULL,
                caseIgnoreListMatch, NULL, NULL,
                NULL},
@@ -4727,7 +4896,7 @@ struct mrule_defs_rec mrule_defs[] = {
 
        {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
-               SLAP_MR_EQUALITY | SLAP_MR_EXT,
+               SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
                NULL, NULL,
                telephoneNumberMatch,
                telephoneNumberIndexer,
@@ -4811,7 +4980,7 @@ struct mrule_defs_rec mrule_defs[] = {
 
        {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
-               SLAP_MR_EQUALITY | SLAP_MR_EXT,
+               SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
                NULL, NULL,
                caseIgnoreIA5Match, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
                IA5StringApproxMatchOID },