]> 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 c1cc2cfa267e144ffabcaccabee2704c2fae4aed..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,132 +249,235 @@ dnValidate(
        return( LDAP_SUCCESS );
 }
 
-int
-dnNormalize(
-       Syntax *syntax,
-       struct berval *val,
-       struct berval **normalized )
+static void
+AVA_Sort( LDAPRDN *rdn, int iAVA )
 {
-       struct berval *out = NULL;
+       int             i;
+       LDAPAVA         *ava_in = rdn[ iAVA ][ 0 ];
+       
+       for ( i = 0; i < iAVA; i++ ) {
+               LDAPAVA         *ava = rdn[ i ][ 0 ];
+               int             a, j;
 
-       if ( val->bv_len != 0 ) {
-               LDAPDN          *dn = NULL;
-               char            *dn_out = NULL;
-               int             rc, iRDN;
+               a = strcmp( ava_in->la_attr->bv_val, ava->la_attr->bv_val );
 
-               rc = ldap_str2dn( val->bv_val, &dn, LDAP_DN_FORMAT_LDAPV3 );
-               if ( rc != LDAP_SUCCESS ) {
-                       return( LDAP_INVALID_SYNTAX );
+               if ( a > 0 ) {
+                       break;
                }
 
-#if 0
-               /*
-                * Add schema-aware normalization stuff
-                */
-               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 *nf = NULL;
-                               struct berval           *bv = NULL;
-
-                               rc = slap_bv2ad( ava->la_attr, &ad, &text );
-                               if ( rc != LDAP_SUCCESS ) {
-                                       goto error_return;
-                               }
+               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 ) {
                                /* 
-                                * FIXME: is this required? 
+                                * got it!
                                 */
-                               if ( isalpha( ava->la_attr->bv_val[0] ) ) {
-                                       (void) ldap_pvt_str2upper( ava->la_attr->bv_val );
-                               }
-                               
+                               break;
+                       }
+
+                       if ( ++i == iAVA ) {
                                /*
-                                * FIXME: What is this intended for?
+                                * already sorted
                                 */
-                               nf = ad->ad_type->sat_syntax->ssyn_normalize;
-                               if ( !nf ) {
-                                       break;
-                               }
-                               
-                               rc = ( *nf )( ad->ad_type->sat_syntax,
-                                        ava->la_value, &bv );
-                               
-                               if ( rc != LDAP_SUCCESS ) {
-                                       goto error_return;
-                               }
+                               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 ) {
                                /*
-                                * FIXME: shouldn't this happen inside 
-                                * ssyn_normalize if the syntax is case 
-                                * insensitive?
+                                * transform value by normalize/pretty function
                                 */
-                               if ( !( ava->la_flags & LDAP_AVA_BINARY ) ) {
-                                       struct berval *s = bv;
-                                       
-                                       bv = ber_bvstr( UTF8normalize( bv, 
-                                                       UTF8_CASEFOLD ) );
-                                       ber_bvfree( s );
+                               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 );
                }
-#endif
+       }
 
-               rc = ldap_dn2str( dn, &dn_out, LDAP_DN_FORMAT_LDAPV3 );
+       return LDAP_SUCCESS;
+}
+
+int
+dnNormalize(
+       Syntax *syntax,
+       struct berval *val,
+       struct berval **normalized )
+{
+       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;
+
+               /*
+                * Go to structural representation
+                */
+               rc = ldap_str2dn( val->bv_val, &dn, LDAP_DN_FORMAT_LDAP );
                if ( rc != LDAP_SUCCESS ) {
-error_return:;
+                       return LDAP_INVALID_SYNTAX;
+               }
+
+               /*
+                * Schema-aware rewrite
+                */
+               if ( LDAPDN_rewrite( dn, 0 ) != LDAP_SUCCESS ) {
                        ldapava_free_dn( dn );
-                       return( LDAP_INVALID_SYNTAX );
+                       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;
+               }
+
                out = ber_bvstr( dn_out );
 
        } else {
                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 );
@@ -377,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
@@ -397,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
@@ -4685,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 },
@@ -4731,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,
@@ -4749,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},
@@ -4791,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,
@@ -4875,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 },