]> git.sur5r.net Git - openldap/commitdiff
add administrative bind and proxyAuthz control to enable bound operations in distribu...
authorPierangelo Masarati <ando@openldap.org>
Mon, 1 Dec 2003 08:04:51 +0000 (08:04 +0000)
committerPierangelo Masarati <ando@openldap.org>
Mon, 1 Dec 2003 08:04:51 +0000 (08:04 +0000)
servers/slapd/back-ldap/add.c
servers/slapd/back-ldap/back-ldap.h
servers/slapd/back-ldap/bind.c
servers/slapd/back-ldap/compare.c
servers/slapd/back-ldap/delete.c
servers/slapd/back-ldap/extended.c
servers/slapd/back-ldap/modify.c
servers/slapd/back-ldap/modrdn.c
servers/slapd/back-ldap/search.c

index c3ab9f3d2c0ea56550e59371b284666ebe5d8d53..cdb33521aa0ee880ef65062ca6c58f5ab59f414a 100644 (file)
@@ -73,6 +73,10 @@ ldap_back_add(
        struct berval mdn = { 0, NULL };
        ber_int_t msgid;
        dncookie dc;
+#ifdef LDAP_BACK_PROXY_AUTHZ 
+       LDAPControl **ctrls = NULL;
+       int rc = LDAP_SUCCESS;
+#endif /* LDAP_BACK_PROXY_AUTHZ */
 
 #ifdef NEW_LOGGING
        LDAP_LOG( BACK_LDAP, ENTRY, "ldap_back_add: %s\n", op->o_req_dn.bv_val, 0, 0 );
@@ -149,8 +153,29 @@ ldap_back_add(
        }
        attrs[i] = NULL;
 
+#ifdef LDAP_BACK_PROXY_AUTHZ
+       rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
+       if ( rc != LDAP_SUCCESS ) {
+               goto cleanup;
+       }
+#endif /* LDAP_BACK_PROXY_AUTHZ */
+
        rs->sr_err = ldap_add_ext(lc->ld, mdn.bv_val, attrs,
-                       op->o_ctrls, NULL, &msgid);
+#ifdef LDAP_BACK_PROXY_AUTHZ
+                       ctrls,
+#else /* ! LDAP_BACK_PROXY_AUTHZ */
+                       op->o_ctrls,
+#endif /* ! LDAP_BACK_PROXY_AUTHZ */
+                       NULL, &msgid);
+
+#ifdef LDAP_BACK_PROXY_AUTHZ
+cleanup:
+       if ( ctrls && ctrls != op->o_ctrls ) {
+               free( ctrls[ 0 ] );
+               free( ctrls );
+       } 
+#endif /* LDAP_BACK_PROXY_AUTHZ */
+
        for (--i; i>= 0; --i) {
                ch_free(attrs[i]->mod_vals.modv_bvals);
                ch_free(attrs[i]);
@@ -159,7 +184,12 @@ ldap_back_add(
        if ( mdn.bv_val != op->o_req_dn.bv_val ) {
                free( mdn.bv_val );
        }
-       
+#ifdef LDAP_BACK_PROXY_AUTHZ
+       if ( rc != LDAP_SUCCESS ) {
+               send_ldap_result( op, rs );
+               return -1;
+       }
+#endif /* LDAP_BACK_PROXY_AUTHZ */
        return ldap_back_op_result( lc, op, rs, msgid, 1 ) != LDAP_SUCCESS;
 }
 
index d7ded8a64b2d89f3ed8300a4a9122411c3631814..cc6f2ecbdec4441114586a056399b531e2225386 100644 (file)
@@ -210,6 +210,15 @@ extern int ldap_dnattr_result_rewrite( dncookie *dc, BerVarray a_vals );
 
 extern int ldap_chain_setup();
 
+#ifdef LDAP_BACK_PROXY_AUTHZ
+extern int
+ldap_back_proxy_authz_ctrl(
+               struct ldapconn *lc,
+               Operation       *op,
+               SlapReply       *rs,
+               LDAPControl     ***pctrls );
+#endif /* LDAP_BACK_PROXY_AUTHZ */
+
 LDAP_END_DECL
 
 #endif /* SLAPD_LDAP_H */
index 91f5be651cd2251f91043af7d62d484c41a420fd..483f0771f5132dcec6c2b88fc128292fce88bbe0 100644 (file)
@@ -404,13 +404,52 @@ ldap_back_getconn(Operation *op, SlapReply *rs)
 int
 ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs )
 {      
+       struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
        int rc;
        ber_int_t msgid;
 
        ldap_pvt_thread_mutex_lock( &lc->lc_mutex );
        if ( !lc->bound ) {
-               rs->sr_err = ldap_sasl_bind(lc->ld, lc->bound_dn.bv_val,
-                       LDAP_SASL_SIMPLE, &lc->cred, NULL, NULL, &msgid);
+#ifdef LDAP_BACK_PROXY_AUTHZ
+               int     gotit = 0;
+#if 0
+               int     i;
+
+               /*
+                * FIXME: we need to let clients use proxyAuthz
+                * otherwise we cannot do symmetric pools of servers;
+                * we have to live with the fact that a user can
+                * authorize itself as any ID that is allowed
+                * by the saslAuthzTo directive of the "binddn".
+                */
+               for ( i = 0; op->o_ctrls && op->o_ctrls[ i ]; i++ ) {
+                       if ( strcmp( op->o_ctrls[i]->ldctl_oid, LDAP_CONTROL_PROXY_AUTHZ ) == 0 ) {
+                               gotit = 1;
+                               break;
+                       }
+               }
+#endif
+
+               /*
+                * if no bind took place yet, but the connection is bound
+                * and the binddn is set, then bind with binddn and 
+                * explicitly add proxyAuthz control to every operation
+                * with the dn bound to the connection as control value.
+                */
+               if ( ( lc->bound_dn.bv_val == NULL || lc->bound_dn.bv_len == 0 )
+                               && ( op->o_conn && op->o_conn->c_dn.bv_val != NULL && op->o_conn->c_dn.bv_len != 0 )
+                               && ( li->binddn.bv_val != NULL && li->binddn.bv_len != 0 ) 
+                               && ! gotit ) {
+                       rs->sr_err = ldap_sasl_bind(lc->ld, li->binddn.bv_val,
+                               LDAP_SASL_SIMPLE, &li->bindpw, NULL, NULL, &msgid);
+
+               } else
+#endif /* LDAP_BACK_PROXY_AUTHZ */
+               {
+                       rs->sr_err = ldap_sasl_bind(lc->ld, lc->bound_dn.bv_val,
+                               LDAP_SASL_SIMPLE, &lc->cred, NULL, NULL, &msgid);
+               }
+               
                rc = ldap_back_op_result( lc, op, rs, msgid, 0 );
                if (rc == LDAP_SUCCESS) {
                        lc->bound = 1;
@@ -550,3 +589,98 @@ ldap_back_op_result(struct ldapconn *lc, Operation *op, SlapReply *rs,
        return( (rs->sr_err == LDAP_SUCCESS) ? 0 : -1 );
 }
 
+#ifdef LDAP_BACK_PROXY_AUTHZ
+/*
+ * ldap_back_proxy_authz_ctrl() prepends a proxyAuthz control
+ * to existing server-side controls if required; if not,
+ * the existing server-side controls are placed in *pctrls.
+ * The caller, after using the controls in client API 
+ * operations, if ( *pctrls != op->o_ctrls ), should
+ * free( (*pctrls)[ 0 ] ) and free( *pctrls ).
+ * The function returns success if the control could
+ * be added if required, or if it did nothing; in the future,
+ * it might return some error if it failed.
+ * 
+ * if no bind took place yet, but the connection is bound
+ * and the binddn is set, then bind with binddn and 
+ * explicitly add proxyAuthz control to every operation
+ * with the dn bound to the connection as control value.
+ *
+ * If no server-side controls are defined for the operation,
+ * simply add the proxyAuthz control; otherwise, if the
+ * proxyAuthz control is not already set, add it as
+ * the first one (FIXME: is controls order significant
+ * for security?).
+ */
+int
+ldap_back_proxy_authz_ctrl(
+               struct ldapconn *lc,
+               Operation       *op,
+               SlapReply       *rs,
+               LDAPControl     ***pctrls )
+{
+       struct ldapinfo *li = (struct ldapinfo *) op->o_bd->be_private;
+       LDAPControl     **ctrls = NULL;
+
+       *pctrls = NULL;
+
+       if ( ( lc->bound_dn.bv_val == NULL || lc->bound_dn.bv_len == 0 )
+                       && ( op->o_conn && op->o_conn->c_dn.bv_val != NULL && op->o_conn->c_dn.bv_len != 0 )
+                       && ( li->binddn.bv_val != NULL && li->binddn.bv_len != 0 ) ) {
+               int     i = 0, gotit = 0;
+               
+               if ( op->o_ctrls ) {
+                       for ( i = 0; op->o_ctrls[i]; i++ ) {
+                               if ( strcmp( op->o_ctrls[i]->ldctl_oid, LDAP_CONTROL_PROXY_AUTHZ ) == 0 ) {
+                                       gotit = 1;
+                                       break;
+                               }
+                       }
+               }
+
+               if ( ! gotit ) {
+                       ctrls = ch_malloc( sizeof( LDAPControl * ) * (i + 2) );
+                       ctrls[ 0 ] = ch_malloc( sizeof( LDAPControl ) );
+                       
+                       ctrls[ 0 ]->ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
+                       ctrls[ 0 ]->ldctl_iscritical = 1;
+                       ctrls[ 0 ]->ldctl_value.bv_len = op->o_conn->c_dn.bv_len + 3;
+                       ctrls[ 0 ]->ldctl_value.bv_val = ch_malloc( ctrls[ 0 ]->ldctl_value.bv_len + 1 );
+                       AC_MEMCPY( ctrls[ 0 ]->ldctl_value.bv_val, "dn:", sizeof( "dn:" ) - 1 );
+                       AC_MEMCPY( ctrls[ 0 ]->ldctl_value.bv_val + sizeof( "dn:") - 1,
+                                       op->o_conn->c_dn.bv_val, op->o_conn->c_dn.bv_len + 1 );
+
+                       if ( op->o_ctrls ) {
+                               for ( i = 0; op->o_ctrls[ i ]; i++ ) {
+                                       ctrls[ i + 1 ] = op->o_ctrls[ i ];
+                               }
+                       }
+                       ctrls[ i + 1 ] = NULL;
+
+               } else {
+                       /*
+                        * FIXME: we do not want to perform proxyAuthz
+                        * on behalf of the client, because this would
+                        * be performed with "binddn" privileges.
+                        *
+                        * This might actually be too strict, since
+                        * the "binddn" saslAuthzTo, and each entry's
+                        * saslAuthzFrom attributes may be crafted
+                        * to avoid unwanted proxyAuthz to take place.
+                        */
+#if 0
+                       rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+                       rs->sr_text = "proxyAuthz not allowed within namingContext";
+#endif
+               }
+       }
+
+       if ( ctrls == NULL ) {
+               ctrls = op->o_ctrls;
+       }
+
+       *pctrls = ctrls;
+       
+       return rs->sr_err;
+}
+#endif /* LDAP_BACK_PROXY_AUTHZ */
index 9ca34771c7fc774b158bd249802112e43baf4a11..8a6f8396b1f2c41dd6a72e813f41738c32785420 100644 (file)
@@ -66,11 +66,15 @@ ldap_back_compare(
 {
        struct ldapinfo *li = (struct ldapinfo *) op->o_bd->be_private;
        struct ldapconn *lc;
-       struct berval mapped_at, mapped_val;
+       struct berval mapped_at = { 0, NULL }, mapped_val = { 0, NULL };
        struct berval mdn = { 0, NULL };
        ber_int_t msgid;
        int freeval = 0;
        dncookie dc;
+#ifdef LDAP_BACK_PROXY_AUTHZ 
+       LDAPControl **ctrls = NULL;
+       int rc = LDAP_SUCCESS;
+#endif /* LDAP_BACK_PROXY_AUTHZ */
 
        lc = ldap_back_getconn(op, rs);
        if (!lc || !ldap_back_dobind( lc, op, rs ) ) {
@@ -119,18 +123,47 @@ ldap_back_compare(
                        } else if (mapped_val.bv_val != op->orc_ava->aa_value.bv_val) {
                                freeval = 1;
                        }
+               } else {
+                       mapped_val = op->orc_ava->aa_value;
                }
        }
 
-       rs->sr_err = ldap_compare_ext( lc->ld, mdn.bv_val, mapped_at.bv_val,
-               &mapped_val, op->o_ctrls, NULL, &msgid );
+#ifdef LDAP_BACK_PROXY_AUTHZ
+       rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
+       if ( rc != LDAP_SUCCESS ) {
+               goto cleanup;
+       }
+#endif /* LDAP_BACK_PROXY_AUTHZ */
+
+       rs->sr_err = ldap_compare_ext( lc->ld, mdn.bv_val,
+                       mapped_at.bv_val, &mapped_val, 
+#ifdef LDAP_BACK_PROXY_AUTHZ
+                       ctrls,
+#else /* ! LDAP_BACK_PROXY_AUTHZ */
+                       op->o_ctrls,
+#endif /* ! LDAP_BACK_PROXY_AUTHZ */
+                       NULL, &msgid );
 
+#ifdef LDAP_BACK_PROXY_AUTHZ
+cleanup:
+       if ( ctrls && ctrls != op->o_ctrls ) {
+               free( ctrls[ 0 ] );
+               free( ctrls );
+       }
+#endif /* LDAP_BACK_PROXY_AUTHZ */
+       
        if ( mdn.bv_val != op->o_req_dn.bv_val ) {
                free( mdn.bv_val );
        }
        if ( freeval ) {
                free( mapped_val.bv_val );
        }
-       
+
+#ifdef LDAP_BACK_PROXY_AUTHZ
+       if ( rc != LDAP_SUCCESS ) {
+               send_ldap_result( op, rs );
+               return -1;
+       }
+#endif /* LDAP_BACK_PROXY_AUTHZ */
        return( ldap_back_op_result( lc, op, rs, msgid, 1 ) );
 }
index 6db914ffd9b192fbcf221134e7461a89114b382a..a624eeae23c392c5c0638d9bbc0486928af361e6 100644 (file)
@@ -68,6 +68,10 @@ ldap_back_delete(
        struct ldapconn *lc;
        ber_int_t msgid;
        dncookie dc;
+#ifdef LDAP_BACK_PROXY_AUTHZ 
+       LDAPControl **ctrls = NULL;
+       int rc = LDAP_SUCCESS;
+#endif /* LDAP_BACK_PROXY_AUTHZ */
 
        struct berval mdn = { 0, NULL };
 
@@ -93,13 +97,40 @@ ldap_back_delete(
                send_ldap_result( op, rs );
                return -1;
        }
-       
-       rs->sr_err = ldap_delete_ext( lc->ld, mdn.bv_val, op->o_ctrls,
+
+#ifdef LDAP_BACK_PROXY_AUTHZ
+       rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
+       if ( rc != LDAP_SUCCESS ) {
+               goto cleanup;
+       }
+#endif /* LDAP_BACK_PROXY_AUTHZ */
+
+       rs->sr_err = ldap_delete_ext( lc->ld, mdn.bv_val,
+#ifdef LDAP_BACK_PROXY_AUTHZ
+                       ctrls,
+#else /* ! LDAP_BACK_PROXY_AUTHZ */
+                       op->o_ctrls,
+#endif /* ! LDAP_BACK_PROXY_AUTHZ */
                        NULL, &msgid );
 
+#ifdef LDAP_BACK_PROXY_AUTHZ
+cleanup:
+       if ( ctrls && ctrls != op->o_ctrls ) {
+               free( ctrls[ 0 ] );
+               free( ctrls );
+       }
+#endif /* LDAP_BACK_PROXY_AUTHZ */
+
        if ( mdn.bv_val != op->o_req_dn.bv_val ) {
                free( mdn.bv_val );
        }
-       
+
+#ifdef LDAP_BACK_PROXY_AUTHZ
+       if ( rc != LDAP_SUCCESS ) {
+               send_ldap_result( op, rs );
+               return -1;
+       }
+#endif /* LDAP_BACK_PROXY_AUTHZ */
+
        return( ldap_back_op_result( lc, op, rs, msgid, 1 ) );
 }
index caac505823872870fbc238d4d696794cc47e2283..364d8905f9dfe5a348fb04aa1a43cb130a7dc75c 100644 (file)
@@ -48,7 +48,40 @@ ldap_back_extended(
 
        for( i=0; exop_table[i].extended != NULL; i++ ) {
                if( ber_bvcmp( exop_table[i].oid, &op->oq_extended.rs_reqoid ) == 0 ) {
+#ifdef LDAP_BACK_PROXY_AUTHZ 
+                       struct ldapconn *lc;
+                       LDAPControl **oldctrls = NULL;
+                       int rc;
+
+                       /* FIXME: this needs to be called here, so it is
+                        * called twice; maybe we could avoid the 
+                        * ldap_back_dobind() call inside each extended()
+                        * call ... */
+                       lc = ldap_back_getconn(op, rs);
+                       if (!lc || !ldap_back_dobind(lc, op, rs) ) {
+                               return -1;
+                       }
+
+                       oldctrls = op->o_ctrls;
+                       if ( ldap_back_proxy_authz_ctrl( lc, op, rs, &op->o_ctrls ) ) {
+                               op->o_ctrls = oldctrls;
+                               send_ldap_result( op, rs );
+                               rs->sr_text = NULL;
+                               return rs->sr_err;
+                       }
+
+                       rc = (exop_table[i].extended)( op, rs );
+
+                       if ( op->o_ctrls && op->o_ctrls != oldctrls ) {
+                               free( op->o_ctrls[ 0 ] );
+                               free( op->o_ctrls );
+                       }
+                       op->o_ctrls = oldctrls;
+
+                       return rc;
+#else /* ! LDAP_BACK_PROXY_AUTHZ */
                        return (exop_table[i].extended)( op, rs );
+#endif /* ! LDAP_BACK_PROXY_AUTHZ */
                }
        }
 
index fa1b8625e00771e748b55549be3bec1cd707db46..c6a45a8e9856ee0e4d7c5932b7615bfedbf39d0d 100644 (file)
@@ -74,6 +74,9 @@ ldap_back_modify(
        struct berval mdn = { 0, NULL };
        ber_int_t msgid;
        dncookie dc;
+#ifdef LDAP_BACK_PROXY_AUTHZ 
+       LDAPControl **ctrls = NULL;
+#endif /* LDAP_BACK_PROXY_AUTHZ */
 
        lc = ldap_back_getconn(op, rs);
        if ( !lc || !ldap_back_dobind( lc, op, rs ) ) {
@@ -181,10 +184,29 @@ ldap_back_modify(
        }
        modv[i] = 0;
 
+#ifdef LDAP_BACK_PROXY_AUTHZ
+       rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
+       if ( rc != LDAP_SUCCESS ) {
+               goto cleanup;
+       }
+#endif /* LDAP_BACK_PROXY_AUTHZ */
+
        rs->sr_err = ldap_modify_ext( lc->ld, mdn.bv_val, modv,
-                       op->o_ctrls, NULL, &msgid );
+#ifdef LDAP_BACK_PROXY_AUTHZ
+                       ctrls,
+#else /* ! LDAP_BACK_PROXY_AUTHZ */
+                       op->o_ctrls,
+#endif /* ! LDAP_BACK_PROXY_AUTHZ */
+                       NULL, &msgid );
 
 cleanup:;
+#ifdef LDAP_BACK_PROXY_AUTHZ
+       if ( ctrls && ctrls != op->o_ctrls ) {
+               free( ctrls[ 0 ] );
+               free( ctrls );
+       }
+#endif /* LDAP_BACK_PROXY_AUTHZ */
+
        if ( mdn.bv_val != op->o_req_dn.bv_val ) {
                free( mdn.bv_val );
        }
@@ -194,6 +216,13 @@ cleanup:;
        ch_free( mods );
        ch_free( modv );
 
+#ifdef LDAP_BACK_PROXY_AUTHZ
+       if ( rc != LDAP_SUCCESS ) {
+               send_ldap_result( op, rs );
+               return -1;
+       }
+#endif /* LDAP_BACK_PROXY_AUTHZ */
+
        return ldap_back_op_result( lc, op, rs, msgid, 1 );
 }
 
index 6039c919ada7962896528e41dc991d9c622a7a5c..cf5154560f4df01e1b45be5f563cb70c816410f6 100644 (file)
@@ -68,6 +68,10 @@ ldap_back_modrdn(
        struct ldapconn *lc;
        ber_int_t msgid;
        dncookie dc;
+#ifdef LDAP_BACK_PROXY_AUTHZ 
+       LDAPControl **ctrls = NULL;
+       int rc = LDAP_SUCCESS;
+#endif /* LDAP_BACK_PROXY_AUTHZ */
 
        struct berval mdn = { 0, NULL }, mnewSuperior = { 0, NULL };
 
@@ -112,11 +116,31 @@ ldap_back_modrdn(
                return -1;
        }
 
+#ifdef LDAP_BACK_PROXY_AUTHZ
+       rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
+       if ( rc != LDAP_SUCCESS ) {
+               goto cleanup;
+       }
+#endif /* LDAP_BACK_PROXY_AUTHZ */
+
        rs->sr_err = ldap_rename( lc->ld, mdn.bv_val,
                        op->orr_newrdn.bv_val, mnewSuperior.bv_val,
-                       op->orr_deleteoldrdn, op->o_ctrls,
+                       op->orr_deleteoldrdn,
+#ifdef LDAP_BACK_PROXY_AUTHZ
+                       ctrls,
+#else /* ! LDAP_BACK_PROXY_AUTHZ */
+                       op->o_ctrls,
+#endif /* ! LDAP_BACK_PROXY_AUTHZ */
                        NULL, &msgid );
 
+#ifdef LDAP_BACK_PROXY_AUTHZ
+cleanup:
+       if ( ctrls && ctrls != op->o_ctrls ) {
+               free( ctrls[ 0 ] );
+               free( ctrls );
+       }
+#endif /* LDAP_BACK_PROXY_AUTHZ */
+
        if ( mdn.bv_val != op->o_req_dn.bv_val ) {
                free( mdn.bv_val );
        }
@@ -124,7 +148,14 @@ ldap_back_modrdn(
                && mnewSuperior.bv_val != op->oq_modrdn.rs_newSup->bv_val ) {
                free( mnewSuperior.bv_val );
        }
-       
+
+#ifdef LDAP_BACK_PROXY_AUTHZ
+       if ( rc != LDAP_SUCCESS ) {
+               send_ldap_result( op, rs );
+               return -1;
+       }
+#endif /* LDAP_BACK_PROXY_AUTHZ */
+
        return( ldap_back_op_result( lc, op, rs, msgid, 1 ) );
 }
 
index d1a68fcff4703b96190d14b2f65624b925a0dedf..53bd63dd5d392959c60d4484edcd16851db8752f 100644 (file)
@@ -88,7 +88,11 @@ ldap_back_search(
        struct berval mfilter = { 0, NULL };
        struct slap_limits_set *limit = NULL;
        int isroot = 0;
+       int dontfreetext = 0;
        dncookie dc;
+#ifdef LDAP_BACK_PROXY_AUTHZ
+       LDAPControl **ctrls = NULL;
+#endif /* LDAP_BACK_PROXY_AUTHZ */
 
        lc = ldap_back_getconn(op, rs);
        if ( !lc ) {
@@ -181,6 +185,7 @@ ldap_back_search(
        if ( rc ) {
                rs->sr_err = LDAP_OTHER;
                rs->sr_text = "Rewrite error";
+               dontfreetext = 1;
                rc = -1;
                goto finish;
        }
@@ -193,27 +198,26 @@ ldap_back_search(
                goto finish;
        }
 
-#if 0
-       if ( mapped_attrs == NULL && op->oq_search.rs_attrs) {
-               int count;
-
-               /* this can happen only if ch_calloc() fails
-                * in ldap_back_map_attrs() */
-               for (count=0; op->oq_search.rs_attrs[count].an_name.bv_val; count++);
-               mapped_attrs = ch_malloc( (count+1) * sizeof(char *));
-               for (count=0; op->oq_search.rs_attrs[count].an_name.bv_val; count++) {
-                       mapped_attrs[count] = op->oq_search.rs_attrs[count].an_name.bv_val;
-               }
-               mapped_attrs[count] = NULL;
+#ifdef LDAP_BACK_PROXY_AUTHZ
+       rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
+       if ( rc != LDAP_SUCCESS ) {
+               dontfreetext = 1;
+               goto finish;
        }
-#endif
-
+#endif /* LDAP_BACK_PROXY_AUTHZ */
+       
        rs->sr_err = ldap_search_ext(lc->ld, mbase.bv_val,
                        op->oq_search.rs_scope, mfilter.bv_val,
                        mapped_attrs, op->oq_search.rs_attrsonly,
-                       op->o_ctrls, NULL,
+#ifdef LDAP_BACK_PROXY_AUTHZ
+                       ctrls,
+#else /* ! LDAP_BACK_PROXY_AUTHZ */
+                       op->o_ctrls,
+#endif /* ! LDAP_BACK_PROXY_AUTHZ */
+                       NULL,
                        tv.tv_sec ? &tv : NULL, op->oq_search.rs_slimit,
-                       &msgid);
+                       &msgid );
+
        if ( rs->sr_err != LDAP_SUCCESS ) {
 fail:;
                rc = ldap_back_op_result(lc, op, rs, msgid, 0);
@@ -347,6 +351,13 @@ fail:;
 finish:;
        send_ldap_result( op, rs );
 
+#ifdef LDAP_BACK_PROXY_AUTHZ
+       if ( ctrls && ctrls != op->o_ctrls ) {
+               free( ctrls[ 0 ] );
+               free( ctrls );
+       }
+#endif /* LDAP_BACK_PROXY_AUTHZ */
+
        if ( match.bv_val ) {
                if ( rs->sr_matched != match.bv_val ) {
                        free( (char *)rs->sr_matched );
@@ -355,7 +366,9 @@ finish:;
                LDAP_FREE( match.bv_val );
        }
        if ( rs->sr_text ) {
-               LDAP_FREE( (char *)rs->sr_text );
+               if ( !dontfreetext ) {
+                       LDAP_FREE( (char *)rs->sr_text );
+               }
                rs->sr_text = NULL;
        }
        if ( mapped_attrs ) {
@@ -536,7 +549,6 @@ ldap_build_entry(
                } else if ( attr->a_desc->ad_type->sat_syntax ==
                                slap_schema.si_syn_distinguishedName ) {
                        ldap_dnattr_result_rewrite( &dc, attr->a_vals );
-
                }
 
                if ( normalize && last && attr->a_desc->ad_type->sat_equality &&
@@ -560,6 +572,7 @@ ldap_build_entry(
                *attrp = attr;
                attrp = &attr->a_next;
        }
+
        /* make sure it's free'able */
        if (!private && ent->e_name.bv_val == bdn->bv_val)
                ber_dupbv( &ent->e_name, bdn );
@@ -646,7 +659,7 @@ ldap_back_entry_get(
                *ptr++ = ')';
                *ptr++ = '\0';
        }
-               
+
        if (ldap_search_ext_s(lc->ld, mdn.bv_val, LDAP_SCOPE_BASE, filter,
                                gattr, 0, NULL, NULL, LDAP_NO_LIMIT,
                                LDAP_NO_LIMIT, &result) != LDAP_SUCCESS)