]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-ldap/chain.c
allow proxies to filter out search references (ITS#5593)
[openldap] / servers / slapd / back-ldap / chain.c
index b81de4fb8750a6ce31d1e958fef727b55264f273..32783ed0a9765a66baea47b8f39e484290920a43 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2003-2006 The OpenLDAP Foundation.
+ * Copyright 2003-2008 The OpenLDAP Foundation.
  * Portions Copyright 2003 Howard Chu.
  * All rights reserved.
  *
@@ -112,7 +112,7 @@ static int ldap_chain_db_init_common( BackendDB     *be );
 static int ldap_chain_db_init_one( BackendDB *be );
 static int ldap_chain_db_open_one( BackendDB *be );
 #define        ldap_chain_db_close_one(be)     (0)
-#define        ldap_chain_db_destroy_one(be)   (lback)->bi_db_destroy( (be) )
+#define        ldap_chain_db_destroy_one(be, rs)       (lback)->bi_db_destroy( (be), (rs) )
 
 typedef struct ldap_chain_cb_t {
        ldap_chain_status_t     lb_status;
@@ -414,14 +414,19 @@ ldap_chain_op(
        li.li_bvuri = bvuri;
        first_rc = -1;
        for ( ; !BER_BVISNULL( ref ); ref++ ) {
-               LDAPURLDesc     *srv;
-               char            *save_dn;
+               SlapReply       rs2 = { 0 };
+               LDAPURLDesc     *srv = NULL;
+               struct berval   save_req_dn = op->o_req_dn,
+                               save_req_ndn = op->o_req_ndn,
+                               dn = BER_BVNULL,
+                               pdn = BER_BVNULL,
+                               ndn = BER_BVNULL;
                int             temporary = 0;
                        
                /* We're setting the URI of the first referral;
                 * what if there are more?
 
-Document: draft-ietf-ldapbis-protocol-27.txt
+Document: RFC 4511
 
 4.1.10. Referral 
    ...
@@ -443,22 +448,42 @@ Document: draft-ietf-ldapbis-protocol-27.txt
                        continue;
                }
 
-               /* remove DN essentially because later on 
-                * ldap_initialize() will parse the URL 
-                * as a comma-separated URL list */
-               save_dn = srv->lud_dn;
-               srv->lud_dn = "";
+               /* normalize DN */
+               rc = LDAP_SUCCESS;
                srv->lud_scope = LDAP_SCOPE_DEFAULT;
+               if ( srv->lud_dn != NULL ) {
+                       ber_str2bv( srv->lud_dn, 0, 0, &dn );
+                       rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, op->o_tmpmemctx );
+                       if ( rc == LDAP_SUCCESS ) {
+                               /* remove DN essentially because later on 
+                                * ldap_initialize() will parse the URL 
+                                * as a comma-separated URL list */
+                               srv->lud_dn = "";
+                       }
+
+               } else {
+                       srv->lud_dn = "";
+               }
+
                li.li_uri = ldap_url_desc2str( srv );
-               srv->lud_dn = save_dn;
+               srv->lud_dn = dn.bv_val;
                ldap_free_urldesc( srv );
 
-               if ( li.li_uri == NULL ) {
+               if ( rc != LDAP_SUCCESS ) {
                        /* try next */
                        rc = LDAP_OTHER;
                        continue;
                }
 
+               if ( li.li_uri == NULL ) {
+                       /* try next */
+                       rc = LDAP_OTHER;
+                       goto further_cleanup;
+               }
+
+               op->o_req_dn = pdn;
+               op->o_req_ndn = ndn;
+
                ber_str2bv( li.li_uri, 0, 0, &li.li_bvuri[ 0 ] );
 
                /* Searches for a ldapinfo in the avl tree */
@@ -482,7 +507,7 @@ Document: draft-ietf-ldapbis-protocol-27.txt
                        if ( rc != 0 ) {
                                lip->li_uri = NULL;
                                lip->li_bvuri = NULL;
-                               (void)ldap_chain_db_destroy_one( op->o_bd );
+                               (void)ldap_chain_db_destroy_one( op->o_bd, NULL);
                                goto cleanup;
                        }
 
@@ -506,7 +531,7 @@ Document: draft-ietf-ldapbis-protocol-27.txt
                lb->lb_op_f = op_f;
                lb->lb_depth = depth + 1;
 
-               rc = op_f( op, rs );
+               rc = op_f( op, &rs2 );
 
                /* note the first error */
                if ( first_rc == -1 ) {
@@ -521,12 +546,26 @@ cleanup:;
                        lip->li_uri = NULL;
                        lip->li_bvuri = NULL;
                        (void)ldap_chain_db_close_one( op->o_bd );
-                       (void)ldap_chain_db_destroy_one( op->o_bd );
+                       (void)ldap_chain_db_destroy_one( op->o_bd, NULL );
+               }
+
+further_cleanup:;
+               if ( !BER_BVISNULL( &pdn ) ) {
+                       op->o_tmpfree( pdn.bv_val, op->o_tmpmemctx );
+               }
+               op->o_req_dn = save_req_dn;
+
+               if ( !BER_BVISNULL( &ndn ) ) {
+                       op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx );
                }
+               op->o_req_ndn = save_req_ndn;
                
-               if ( rc == LDAP_SUCCESS && rs->sr_err == LDAP_SUCCESS ) {
+               if ( rc == LDAP_SUCCESS && rs2.sr_err == LDAP_SUCCESS ) {
+                       *rs = rs2;
                        break;
                }
+
+               rc = rs2.sr_err;
        }
 
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
@@ -578,8 +617,13 @@ ldap_chain_search(
         * to be set once for all (correct?) */
        li.li_bvuri = bvuri;
        for ( ; !BER_BVISNULL( &ref[0] ); ref++ ) {
+               SlapReply       rs2 = { 0 };
                LDAPURLDesc     *srv;
-               char            *save_dn;
+               struct berval   save_req_dn = op->o_req_dn,
+                               save_req_ndn = op->o_req_ndn,
+                               dn,
+                               pdn = BER_BVNULL,
+                               ndn = BER_BVNULL;
                int             temporary = 0;
 
                /* parse reference and use
@@ -591,29 +635,38 @@ ldap_chain_search(
                        continue;
                }
 
-               /* remove DN essentially because later on 
-                * ldap_initialize() will parse the URL 
-                * as a comma-separated URL list */
-               save_dn = srv->lud_dn;
-               srv->lud_dn = "";
-               srv->lud_scope = LDAP_SCOPE_DEFAULT;
-               li.li_uri = ldap_url_desc2str( srv );
-               if ( li.li_uri != NULL ) {
-                       ber_str2bv_x( save_dn, 0, 1, &op->o_req_dn,
-                                       op->o_tmpmemctx );
-                       ber_dupbv_x( &op->o_req_ndn, &op->o_req_dn,
-                                       op->o_tmpmemctx );
+               /* normalize DN */
+               rc = LDAP_INVALID_SYNTAX;
+               if ( srv->lud_dn != NULL ) {
+                       ber_str2bv( srv->lud_dn, 0, 0, &dn );
+                       rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, op->o_tmpmemctx );
+                       if ( rc == LDAP_SUCCESS ) {
+                               /* remove DN essentially because later on 
+                                * ldap_initialize() will parse the URL 
+                                * as a comma-separated URL list */
+                               srv->lud_dn = "";
+                               srv->lud_scope = LDAP_SCOPE_DEFAULT;
+                               li.li_uri = ldap_url_desc2str( srv );
+                               srv->lud_dn = dn.bv_val;
+                       }
                }
-
-               srv->lud_dn = save_dn;
                ldap_free_urldesc( srv );
 
-               if ( li.li_uri == NULL ) {
+               if ( rc != LDAP_SUCCESS ) {
                        /* try next */
-                       rs->sr_err = LDAP_OTHER;
+                       rc = LDAP_OTHER;
                        continue;
                }
 
+               if ( li.li_uri == NULL ) {
+                       /* try next */
+                       rc = LDAP_OTHER;
+                       goto further_cleanup;
+               }
+
+               op->o_req_dn = pdn;
+               op->o_req_ndn = ndn;
+
                ber_str2bv( li.li_uri, 0, 0, &li.li_bvuri[ 0 ] );
 
                /* Searches for a ldapinfo in the avl tree */
@@ -638,7 +691,7 @@ ldap_chain_search(
                        if ( rc != 0 ) {
                                lip->li_uri = NULL;
                                lip->li_bvuri = NULL;
-                               (void)ldap_chain_db_destroy_one( op->o_bd );
+                               (void)ldap_chain_db_destroy_one( op->o_bd, NULL );
                                goto cleanup;
                        }
 
@@ -664,7 +717,7 @@ ldap_chain_search(
 
                /* FIXME: should we also copy filter and scope?
                 * according to RFC3296, no */
-               rc = lback->bi_op_search( op, rs );
+               rc = lback->bi_op_search( op, &rs2 );
                if ( first_rc == -1 ) {
                        first_rc = rc;
                }
@@ -673,21 +726,30 @@ cleanup:;
                ldap_memfree( li.li_uri );
                li.li_uri = NULL;
 
-               op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
-               op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
-
                if ( temporary ) {
                        lip->li_uri = NULL;
                        lip->li_bvuri = NULL;
                        (void)ldap_chain_db_close_one( op->o_bd );
-                       (void)ldap_chain_db_destroy_one( op->o_bd );
+                       (void)ldap_chain_db_destroy_one( op->o_bd, NULL );
                }
                
-               if ( rc == LDAP_SUCCESS && rs->sr_err == LDAP_SUCCESS ) {
+further_cleanup:;
+               if ( !BER_BVISNULL( &pdn ) ) {
+                       op->o_tmpfree( pdn.bv_val, op->o_tmpmemctx );
+               }
+               op->o_req_dn = save_req_dn;
+
+               if ( !BER_BVISNULL( &ndn ) ) {
+                       op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx );
+               }
+               op->o_req_ndn = save_req_ndn;
+               
+               if ( rc == LDAP_SUCCESS && rs2.sr_err == LDAP_SUCCESS ) {
+                       *rs = rs2;
                        break;
                }
 
-               rc = rs->sr_err;
+               rc = rs2.sr_err;
        }
 
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
@@ -723,6 +785,7 @@ ldap_chain_response( Operation *op, SlapReply *rs )
        slap_callback   *sc = op->o_callback,
                        sc2 = { 0 };
        int             rc = 0;
+       const char      *text = NULL;
        const char      *matched;
        BerVarray       ref;
        struct berval   ndn = op->o_ndn;
@@ -778,6 +841,8 @@ ldap_chain_response( Operation *op, SlapReply *rs )
        SLAP_DBFLAGS( &db ) &= ~SLAP_DBFLAG_MONITORING;
        op->o_bd = &db;
 
+       text = rs->sr_text;
+       rs->sr_text = NULL;
        matched = rs->sr_matched;
        rs->sr_matched = NULL;
        ref = rs->sr_ref;
@@ -860,6 +925,7 @@ ldap_chain_response( Operation *op, SlapReply *rs )
                 * to send it... */
                /* FIXME: what about chaining? */
                if ( rc != SLAPD_ABANDON ) {
+                       rs->sr_err = rc;
                        send_ldap_extended( op, rs );
                        rc = LDAP_SUCCESS;
                }
@@ -911,6 +977,7 @@ cannot_chain:;
                                rc = SLAP_CB_CONTINUE;
                                rs->sr_err = sr_err;
                                rs->sr_type = sr_type;
+                               rs->sr_text = text;
                                rs->sr_matched = matched;
                                rs->sr_ref = ref;
                        }
@@ -929,6 +996,7 @@ cannot_chain:;
 dont_chain:;
        rs->sr_err = sr_err;
        rs->sr_type = sr_type;
+       rs->sr_text = text;
        rs->sr_matched = matched;
        rs->sr_ref = ref;
        op->o_bd = bd;
@@ -1121,7 +1189,7 @@ chain_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
 
 done:;
        if ( rc != LDAP_SUCCESS ) {
-               (void)ldap_chain_db_destroy_one( ca->be );
+               (void)ldap_chain_db_destroy_one( ca->be, NULL );
                ch_free( ca->be );
                ca->be = NULL;
        }
@@ -1146,9 +1214,9 @@ ldap_chain_cfadd_apply( void *datum, void *arg )
        struct berval                   bv;
 
        /* FIXME: should not hardcode "olcDatabase" here */
-       bv.bv_len = snprintf( lca->ca->msg, sizeof( lca->ca->msg ),
+       bv.bv_len = snprintf( lca->ca->cr_msg, sizeof( lca->ca->cr_msg ),
                "olcDatabase={%d}%s", lca->count, lback->bi_type );
-       bv.bv_val = lca->ca->msg;
+       bv.bv_val = lca->ca->cr_msg;
 
        lca->ca->be->be_private = (void *)li;
        config_build_entry( lca->op, lca->rs, lca->p->e_private, lca->ca,
@@ -1408,11 +1476,11 @@ chain_cf_gen( ConfigArgs *c )
 
        case CH_MAX_DEPTH:
                if ( c->value_int < 0 ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                "<%s> invalid max referral depth %d",
                                c->argv[0], c->value_int );
                        Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
-                               c->log, c->msg, 0 );
+                               c->log, c->cr_msg, 0 );
                        rc = 1;
                        break;
                }
@@ -1435,7 +1503,8 @@ chain_cf_gen( ConfigArgs *c )
 
 static int
 ldap_chain_db_init(
-       BackendDB *be )
+       BackendDB *be,
+       ConfigReply *cr )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
        ldap_chain_t    *lc = NULL;
@@ -1566,7 +1635,7 @@ private_destroy:;
 
                                db.bd_info = lback;
                                db.be_private = (void *)lc->lc_cfg_li;
-                               ldap_chain_db_destroy_one( &db );
+                               ldap_chain_db_destroy_one( &db, NULL );
                                lc->lc_cfg_li = NULL;
 
                        } else {
@@ -1619,7 +1688,7 @@ ldap_chain_db_apply( void *datum, void *arg )
 
        lca->be->be_private = (void *)li;
 
-       return lca->func( lca->be );
+       return lca->func( lca->be, NULL );
 }
 
 static int
@@ -1642,7 +1711,7 @@ ldap_chain_db_func(
                        db.bd_info = lback;
                        db.be_private = lc->lc_common_li;
 
-                       rc = func( &db );
+                       rc = func( &db, NULL );
 
                        if ( rc != 0 ) {
                                return rc;
@@ -1666,7 +1735,8 @@ ldap_chain_db_func(
 
 static int
 ldap_chain_db_open(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        slap_overinst   *on = (slap_overinst *) be->bd_info;
        ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
@@ -1698,14 +1768,16 @@ ldap_chain_db_open(
 
 static int
 ldap_chain_db_close(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        return ldap_chain_db_func( be, db_close );
 }
 
 static int
 ldap_chain_db_destroy(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        slap_overinst   *on = (slap_overinst *) be->bd_info;
        ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
@@ -1737,7 +1809,7 @@ ldap_chain_db_init_common(
 
        be->bd_info = lback;
        be->be_private = NULL;
-       rc = lback->bi_db_init( be );
+       rc = lback->bi_db_init( be, NULL );
        if ( rc != 0 ) {
                return rc;
        }
@@ -1772,7 +1844,7 @@ ldap_chain_db_init_one(
 
        be->bd_info = lback;
        be->be_private = NULL;
-       t = lback->bi_db_init( be );
+       t = lback->bi_db_init( be, NULL );
        if ( t != 0 ) {
                return t;
        }
@@ -1816,7 +1888,7 @@ ldap_chain_db_open_one(
                }
        }
 
-       return lback->bi_db_open( be );
+       return lback->bi_db_open( be, NULL );
 }
 
 typedef struct ldap_chain_conn_apply_t {