]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/dn.c
patch for ITS#3173
[openldap] / servers / slapd / dn.c
index 647468d92bffc5ba5804596c44278e2870f6b271..6702e8dc18816938c6e106dfdc6ca184257aa2f2 100644 (file)
@@ -1,8 +1,27 @@
 /* dn.c - routines for dealing with distinguished names */
 /* $OpenLDAP$ */
-/*
- * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
- * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2004 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* Portions Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
  */
 
 #include "portable.h"
 #include <ac/string.h>
 #include <ac/time.h>
 
-#include "ldap_pvt.h"
-
 #include "slap.h"
-
+#include "ldap_pvt.h" /* must be after slap.h, to get ldap_bv2dn_x() & co */
 #include "lutil.h"
 
 /*
  * structural representation of a distinguished name.
  */
 static int
-LDAPDN_validate( LDAPDN *dn )
+LDAPDN_validate( LDAPDN dn )
 {
        int             iRDN;
        int             rc;
 
        assert( dn );
 
-       for ( iRDN = 0; dn[ 0 ][ iRDN ]; iRDN++ ) {
-               LDAPRDN         *rdn = dn[ 0 ][ iRDN ];
+       for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
+               LDAPRDN         rdn = dn[ iRDN ];
                int             iAVA;
 
                assert( rdn );
 
-               for ( iAVA = 0; rdn[ 0 ][ iAVA ]; iAVA++ ) {
-                       LDAPAVA                 *ava = rdn[ 0 ][ iAVA ];
+               for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
+                       LDAPAVA                 *ava = rdn[ iAVA ];
                        AttributeDescription    *ad;
                        slap_syntax_validate_func *validate = NULL;
 
@@ -106,7 +123,7 @@ dnValidate(
        struct berval *in )
 {
        int             rc;
-       LDAPDN          *dn = NULL;
+       LDAPDN          dn = NULL;
 
        assert( in );
 
@@ -152,16 +169,16 @@ dnValidate(
  * a RDN should be limited.
  */
 static void
-AVA_Sort( LDAPRDN *rdn, int iAVA )
+AVA_Sort( LDAPRDN rdn, int iAVA )
 {
        int             i;
-       LDAPAVA         *ava_in = rdn[ 0 ][ iAVA ];
+       LDAPAVA         *ava_in = rdn[ iAVA ];
 
        assert( rdn );
        assert( ava_in );
        
        for ( i = 0; i < iAVA; i++ ) {
-               LDAPAVA         *ava = rdn[ 0 ][ i ];
+               LDAPAVA         *ava = rdn[ i ];
                int             a, j;
 
                assert( ava );
@@ -200,7 +217,7 @@ AVA_Sort( LDAPRDN *rdn, int iAVA )
                                return;
                        }
 
-                       ava = rdn[ 0 ][ i ];
+                       ava = rdn[ i ];
                        a = strcmp( ava_in->la_attr.bv_val, 
                                        ava->la_attr.bv_val );
                }
@@ -209,9 +226,9 @@ AVA_Sort( LDAPRDN *rdn, int iAVA )
                 * move ahead
                 */
                for ( j = iAVA; j > i; j-- ) {
-                       rdn[ 0 ][ j ] = rdn[ 0 ][ j - 1 ];
+                       rdn[ j ] = rdn[ j - 1 ];
                }
-               rdn[ 0 ][ i ] = ava_in;
+               rdn[ i ] = ava_in;
 
                return;
        }
@@ -222,29 +239,27 @@ AVA_Sort( LDAPRDN *rdn, int iAVA )
  * structural representation of a distinguished name.
  */
 static int
-LDAPDN_rewrite( LDAPDN *dn, unsigned flags )
+LDAPDN_rewrite( LDAPDN dn, unsigned flags, void *ctx )
 {
        int             iRDN;
        int             rc;
 
        assert( dn );
 
-       for ( iRDN = 0; dn[ 0 ][ iRDN ]; iRDN++ ) {
-               LDAPRDN         *rdn = dn[ 0 ][ iRDN ];
+       for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
+               LDAPRDN         rdn = dn[ iRDN ];
                int             iAVA;
 
                assert( rdn );
 
-               for ( iAVA = 0; rdn[ 0 ][ iAVA ]; iAVA++ ) {
-                       LDAPAVA                 *ava = rdn[ 0 ][ iAVA ];
+               for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
+                       LDAPAVA                 *ava = rdn[ iAVA ];
                        AttributeDescription    *ad;
                        slap_syntax_validate_func *validf = NULL;
-#ifdef SLAP_NVALUES
                        slap_mr_normalize_func *normf = NULL;
-#endif
                        slap_syntax_transform_func *transf = NULL;
                        MatchingRule *mr = NULL;
-                       struct berval           bv = { 0, NULL };
+                       struct berval           bv = BER_BVNULL;
                        int                     do_sort = 0;
 
                        assert( ava );
@@ -267,6 +282,11 @@ LDAPDN_rewrite( LDAPDN *dn, unsigned flags )
                        ava->la_attr = ad->ad_cname;
 
                        if( ava->la_flags & LDAP_AVA_BINARY ) {
+                               if( ava->la_value.bv_len == 0 ) {
+                                       /* BER encoding is empty */
+                                       return LDAP_INVALID_SYNTAX;
+                               }
+
                                /* AVA is binary encoded, don't muck with it */
                        } else if( flags & SLAP_LDAPDN_PRETTY ) {
                                transf = ad->ad_type->sat_syntax->ssyn_pretty;
@@ -276,11 +296,7 @@ LDAPDN_rewrite( LDAPDN *dn, unsigned flags )
                        } else { /* normalization */
                                validf = ad->ad_type->sat_syntax->ssyn_validate;
                                mr = ad->ad_type->sat_equality;
-#ifdef SLAP_NVALUES
                                if( mr ) normf = mr->smr_normalize;
-#else
-                               transf = ad->ad_type->sat_syntax->ssyn_normalize;
-#endif
                        }
 
                        if ( validf ) {
@@ -297,59 +313,45 @@ LDAPDN_rewrite( LDAPDN *dn, unsigned flags )
 
                        if ( transf ) {
                                /*
-#ifdef SLAP_NVALUES
                                 * transform value by pretty function
-#else
-                                * transform value by normalize/pretty function
-#endif
                                 *      if value is empty, use empty_bv
                                 */
                                rc = ( *transf )( ad->ad_type->sat_syntax,
                                        ava->la_value.bv_len
                                                ? &ava->la_value
                                                : (struct berval *) &slap_empty_bv,
-                                       &bv );
+                                       &bv, ctx );
                        
                                if ( rc != LDAP_SUCCESS ) {
                                        return LDAP_INVALID_SYNTAX;
                                }
                        }
 
-#ifdef SLAP_NVALUES
                        if ( normf ) {
                                /*
                                 * normalize value
                                 *      if value is empty, use empty_bv
                                 */
                                rc = ( *normf )(
-                                       0,
+                                       SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
                                        ad->ad_type->sat_syntax,
                                        mr,
                                        ava->la_value.bv_len
                                                ? &ava->la_value
                                                : (struct berval *) &slap_empty_bv,
-                                       &bv );
+                                       &bv, ctx );
                        
                                if ( rc != LDAP_SUCCESS ) {
                                        return LDAP_INVALID_SYNTAX;
                                }
                        }
 
-#else
-                       if( mr && ( mr->smr_usage & SLAP_MR_DN_FOLD ) ) {
-                               char *s = bv.bv_val;
-
-                               if ( UTF8bvnormalize( &bv, &bv, 
-                                               LDAP_UTF8_CASEFOLD ) == NULL ) {
-                                       return LDAP_INVALID_SYNTAX;
-                               }
-                               free( s );
-                       }
-#endif
 
                        if( bv.bv_val ) {
-                               free( ava->la_value.bv_val );
+                               if ( ava->la_flags & LDAP_AVA_FREE_VALUE )
+                                       ber_memfree_x( ava->la_value.bv_val, ctx );
                                ava->la_value = bv;
+                               ava->la_flags |= LDAP_AVA_FREE_VALUE;
                        }
 
                        if( do_sort ) AVA_Sort( rdn, iAVA );
@@ -360,19 +362,13 @@ LDAPDN_rewrite( LDAPDN *dn, unsigned flags )
 }
 
 int
-#ifdef SLAP_NVALUES
 dnNormalize(
     slap_mask_t use,
     Syntax *syntax,
     MatchingRule *mr,
     struct berval *val,
-    struct berval *out )
-#else
-dnNormalize(
-    Syntax *syntax,
-    struct berval *val,
-    struct berval *out )
-#endif
+    struct berval *out,
+    void *ctx)
 {
        assert( val );
        assert( out );
@@ -380,13 +376,13 @@ dnNormalize(
        Debug( LDAP_DEBUG_TRACE, ">>> dnNormalize: <%s>\n", val->bv_val, 0, 0 );
 
        if ( val->bv_len != 0 ) {
-               LDAPDN          *dn = NULL;
+               LDAPDN          dn = NULL;
                int             rc;
 
                /*
                 * Go to structural representation
                 */
-               rc = ldap_bv2dn( val, &dn, LDAP_DN_FORMAT_LDAP );
+               rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
                if ( rc != LDAP_SUCCESS ) {
                        return LDAP_INVALID_SYNTAX;
                }
@@ -396,24 +392,24 @@ dnNormalize(
                /*
                 * Schema-aware rewrite
                 */
-               if ( LDAPDN_rewrite( dn, 0 ) != LDAP_SUCCESS ) {
-                       ldap_dnfree( dn );
+               if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) {
+                       ldap_dnfree_x( dn, ctx );
                        return LDAP_INVALID_SYNTAX;
                }
 
                /*
                 * Back to string representation
                 */
-               rc = ldap_dn2bv( dn, out,
-                       LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY );
+               rc = ldap_dn2bv_x( dn, out,
+                       LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
 
-               ldap_dnfree( dn );
+               ldap_dnfree_x( dn, ctx );
 
                if ( rc != LDAP_SUCCESS ) {
                        return LDAP_INVALID_SYNTAX;
                }
        } else {
-               ber_dupbv( out, val );
+               ber_dupbv_x( out, val, ctx );
        }
 
        Debug( LDAP_DEBUG_TRACE, "<<< dnNormalize: <%s>\n", out->bv_val, 0, 0 );
@@ -421,36 +417,12 @@ dnNormalize(
        return LDAP_SUCCESS;
 }
 
-#if 0
-/*
- * dn "pretty"ing routine
- */
 int
 dnPretty(
        Syntax *syntax,
        struct berval *val,
-       struct berval **pretty)
-{
-       struct berval *out;
-       int rc;
-
-       assert( pretty && *pretty == NULL );
-
-       out = ch_malloc( sizeof( struct berval ) );
-       rc = dnPretty2( syntax, val, out );
-       if ( rc != LDAP_SUCCESS )
-               free( out );
-       else
-               *pretty = out;
-       return rc;
-}
-#endif
-
-int
-dnPretty2(
-       Syntax *syntax,
-       struct berval *val,
-       struct berval *out)
+       struct berval *out,
+       void *ctx)
 {
        assert( val );
        assert( out );
@@ -462,17 +434,17 @@ dnPretty2(
 #endif
 
        if ( val->bv_len == 0 ) {
-               ber_dupbv( out, val );
+               ber_dupbv_x( out, val, ctx );
 
        } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
                return LDAP_INVALID_SYNTAX;
 
        } else {
-               LDAPDN          *dn = NULL;
+               LDAPDN          dn = NULL;
                int             rc;
 
                /* FIXME: should be liberal in what we accept */
-               rc = ldap_bv2dn( val, &dn, LDAP_DN_FORMAT_LDAP );
+               rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
                if ( rc != LDAP_SUCCESS ) {
                        return LDAP_INVALID_SYNTAX;
                }
@@ -482,8 +454,8 @@ dnPretty2(
                /*
                 * Schema-aware rewrite
                 */
-               if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY ) != LDAP_SUCCESS ) {
-                       ldap_dnfree( dn );
+               if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) {
+                       ldap_dnfree_x( dn, ctx );
                        return LDAP_INVALID_SYNTAX;
                }
 
@@ -491,17 +463,21 @@ dnPretty2(
                /* RE: the default is the form that is used as
                 * an internal representation; the pretty form
                 * is a variant */
-               rc = ldap_dn2bv( dn, out,
-                       LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY );
+               rc = ldap_dn2bv_x( dn, out,
+                       LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
 
-               ldap_dnfree( dn );
+               ldap_dnfree_x( dn, ctx );
 
                if ( rc != LDAP_SUCCESS ) {
                        return LDAP_INVALID_SYNTAX;
                }
        }
 
+#ifdef NEW_LOGGING
+       LDAP_LOG( OPERATION, ARGS, "<<< dnPretty: <%s>\n", out->bv_val, 0, 0 );
+#else
        Debug( LDAP_DEBUG_TRACE, "<<< dnPretty: <%s>\n", out->bv_val, 0, 0 );
+#endif
 
        return LDAP_SUCCESS;
 }
@@ -510,8 +486,9 @@ int
 dnPrettyNormalDN(
        Syntax *syntax,
        struct berval *val,
-       LDAPDN **dn,
-       int flags )
+       LDAPDN *dn,
+       int flags,
+       void *ctx )
 {
        assert( val );
        assert( dn );
@@ -536,7 +513,7 @@ dnPrettyNormalDN(
                int             rc;
 
                /* FIXME: should be liberal in what we accept */
-               rc = ldap_bv2dn( val, dn, LDAP_DN_FORMAT_LDAP );
+               rc = ldap_bv2dn_x( val, dn, LDAP_DN_FORMAT_LDAP, ctx );
                if ( rc != LDAP_SUCCESS ) {
                        return LDAP_INVALID_SYNTAX;
                }
@@ -546,8 +523,8 @@ dnPrettyNormalDN(
                /*
                 * Schema-aware rewrite
                 */
-               if ( LDAPDN_rewrite( *dn, flags ) != LDAP_SUCCESS ) {
-                       ldap_dnfree( *dn );
+               if ( LDAPDN_rewrite( *dn, flags, ctx ) != LDAP_SUCCESS ) {
+                       ldap_dnfree_x( *dn, ctx );
                        *dn = NULL;
                        return LDAP_INVALID_SYNTAX;
                }
@@ -568,7 +545,8 @@ dnPrettyNormal(
        Syntax *syntax,
        struct berval *val,
        struct berval *pretty,
-       struct berval *normal)
+       struct berval *normal,
+       void *ctx)
 {
 #ifdef NEW_LOGGING
        LDAP_LOG ( OPERATION, ENTRY, ">>> dnPrettyNormal: <%s>\n", val->bv_val, 0, 0 );
@@ -581,15 +559,15 @@ dnPrettyNormal(
        assert( normal );
 
        if ( val->bv_len == 0 ) {
-               ber_dupbv( pretty, val );
-               ber_dupbv( normal, val );
+               ber_dupbv_x( pretty, val, ctx );
+               ber_dupbv_x( normal, val, ctx );
 
        } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
                /* too big */
                return LDAP_INVALID_SYNTAX;
 
        } else {
-               LDAPDN          *dn = NULL;
+               LDAPDN          dn = NULL;
                int             rc;
 
                pretty->bv_val = NULL;
@@ -598,7 +576,7 @@ dnPrettyNormal(
                normal->bv_len = 0;
 
                /* FIXME: should be liberal in what we accept */
-               rc = ldap_bv2dn( val, &dn, LDAP_DN_FORMAT_LDAP );
+               rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
                if ( rc != LDAP_SUCCESS ) {
                        return LDAP_INVALID_SYNTAX;
                }
@@ -608,33 +586,33 @@ dnPrettyNormal(
                /*
                 * Schema-aware rewrite
                 */
-               if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY ) != LDAP_SUCCESS ) {
-                       ldap_dnfree( dn );
+               if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) {
+                       ldap_dnfree_x( dn, ctx );
                        return LDAP_INVALID_SYNTAX;
                }
 
-               rc = ldap_dn2bv( dn, pretty,
-                       LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY );
+               rc = ldap_dn2bv_x( dn, pretty,
+                       LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
 
                if ( rc != LDAP_SUCCESS ) {
-                       ldap_dnfree( dn );
+                       ldap_dnfree_x( dn, ctx );
                        return LDAP_INVALID_SYNTAX;
                }
 
-               if ( LDAPDN_rewrite( dn, 0 ) != LDAP_SUCCESS ) {
-                       ldap_dnfree( dn );
-                       free( pretty->bv_val );
+               if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) {
+                       ldap_dnfree_x( dn, ctx );
+                       ber_memfree_x( pretty->bv_val, ctx );
                        pretty->bv_val = NULL;
                        pretty->bv_len = 0;
                        return LDAP_INVALID_SYNTAX;
                }
 
-               rc = ldap_dn2bv( dn, normal,
-                       LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY );
+               rc = ldap_dn2bv_x( dn, normal,
+                       LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
 
-               ldap_dnfree( dn );
+               ldap_dnfree_x( dn, ctx );
                if ( rc != LDAP_SUCCESS ) {
-                       free( pretty->bv_val );
+                       ber_memfree_x( pretty->bv_val, ctx );
                        pretty->bv_val = NULL;
                        pretty->bv_len = 0;
                        return LDAP_INVALID_SYNTAX;
@@ -725,9 +703,10 @@ dnParent(
 int
 dnExtractRdn( 
        struct berval   *dn, 
-       struct berval   *rdn )
+       struct berval   *rdn,
+       void *ctx )
 {
-       LDAPRDN         *tmpRDN;
+       LDAPRDN         tmpRDN;
        const char      *p;
        int             rc;
 
@@ -738,14 +717,14 @@ dnExtractRdn(
                return LDAP_OTHER;
        }
 
-       rc = ldap_bv2rdn( dn, &tmpRDN, (char **)&p, LDAP_DN_FORMAT_LDAP );
+       rc = ldap_bv2rdn_x( dn, &tmpRDN, (char **)&p, LDAP_DN_FORMAT_LDAP, ctx );
        if ( rc != LDAP_SUCCESS ) {
                return rc;
        }
 
-       rc = ldap_rdn2bv( tmpRDN, rdn, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY );
+       rc = ldap_rdn2bv_x( tmpRDN, rdn, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
 
-       ldap_rdnfree( tmpRDN );
+       ldap_rdnfree_x( tmpRDN, ctx );
        if ( rc != LDAP_SUCCESS ) {
                return rc;
        }
@@ -859,17 +838,18 @@ rdnValidate( struct berval *rdn )
 void
 build_new_dn( struct berval * new_dn,
        struct berval * parent_dn,
-       struct berval * newrdn )
+       struct berval * newrdn,
+       void *memctx )
 {
        char *ptr;
 
-       if ( parent_dn == NULL ) {
+       if ( parent_dn == NULL || parent_dn->bv_len == 0 ) {
                ber_dupbv( new_dn, newrdn );
                return;
        }
 
        new_dn->bv_len = parent_dn->bv_len + newrdn->bv_len + 1;
-       new_dn->bv_val = (char *) ch_malloc( new_dn->bv_len + 1 );
+       new_dn->bv_val = (char *) slap_sl_malloc( new_dn->bv_len + 1, memctx );
 
        ptr = lutil_strcopy( new_dn->bv_val, newrdn->bv_val );
        *ptr++ = ',';
@@ -923,7 +903,12 @@ int
 dnX509normalize( void *x509_name, struct berval *out )
 {
        /* Invoke the LDAP library's converter with our schema-rewriter */
-       return ldap_X509dn2bv( x509_name, out, LDAPDN_rewrite, 0 );
+       int rc = ldap_X509dn2bv( x509_name, out, LDAPDN_rewrite, 0 );
+
+       Debug( LDAP_DEBUG_TRACE,
+               "dnX509Normalize: <%s>\n", out->bv_val, 0, 0 );
+
+       return rc;
 }
 
 /*