]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-ldap/chain.c
pool privileged connections (ITS#4791)
[openldap] / servers / slapd / back-ldap / chain.c
index 6bf0deac50322b2d117d8f26e4ddf3735eb5eba1..f7b10782430777e9d9eba7e8a1571b5ed2d4f05a 100644 (file)
@@ -27,9 +27,9 @@
 #include <ac/string.h>
 #include <ac/socket.h>
 
+#include "lutil.h"
 #include "slap.h"
 #include "back-ldap.h"
-
 #include "config.h"
 
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
@@ -110,7 +110,7 @@ typedef struct ldap_chain_t {
 
 static int ldap_chain_db_init_common( BackendDB        *be );
 static int ldap_chain_db_init_one( BackendDB *be );
-#define        ldap_chain_db_open_one(be)      (lback)->bi_db_open( (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) )
 
@@ -136,6 +136,8 @@ ldap_chain_search(
        BerVarray       ref,
        int             depth );
 
+static slap_overinst ldapchain;
+
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
 static int
 chaining_control_add(
@@ -412,14 +414,18 @@ ldap_chain_op(
        li.li_bvuri = bvuri;
        first_rc = -1;
        for ( ; !BER_BVISNULL( ref ); ref++ ) {
-               LDAPURLDesc     *srv;
-               char            *save_dn;
+               LDAPURLDesc     *srv = NULL;
+               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;
                        
                /* 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 
    ...
@@ -441,22 +447,35 @@ 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 = "";
-               srv->lud_scope = LDAP_SCOPE_DEFAULT;
-               li.li_uri = ldap_url_desc2str( srv );
-               srv->lud_dn = save_dn;
+               /* normalize DN */
+               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;
+               }
                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 */
@@ -478,6 +497,8 @@ Document: draft-ietf-ldapbis-protocol-27.txt
                        lip->li_bvuri = bvuri;
                        rc = ldap_chain_db_open_one( op->o_bd );
                        if ( rc != 0 ) {
+                               lip->li_uri = NULL;
+                               lip->li_bvuri = NULL;
                                (void)ldap_chain_db_destroy_one( op->o_bd );
                                goto cleanup;
                        }
@@ -519,6 +540,17 @@ cleanup:;
                        (void)ldap_chain_db_close_one( op->o_bd );
                        (void)ldap_chain_db_destroy_one( op->o_bd );
                }
+
+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 ) {
                        break;
@@ -575,7 +607,11 @@ ldap_chain_search(
        li.li_bvuri = bvuri;
        for ( ; !BER_BVISNULL( &ref[0] ); ref++ ) {
                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
@@ -587,29 +623,35 @@ 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 */
+               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 */
@@ -632,6 +674,8 @@ ldap_chain_search(
                        lip->li_bvuri = bvuri;
                        rc = ldap_chain_db_open_one( op->o_bd );
                        if ( rc != 0 ) {
+                               lip->li_uri = NULL;
+                               lip->li_bvuri = NULL;
                                (void)ldap_chain_db_destroy_one( op->o_bd );
                                goto cleanup;
                        }
@@ -677,6 +721,17 @@ cleanup:;
                        (void)ldap_chain_db_destroy_one( op->o_bd );
                }
                
+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 ) {
                        break;
                }
@@ -712,7 +767,7 @@ ldap_chain_response( Operation *op, SlapReply *rs )
 {
        slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
        ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
-       void            *private = op->o_bd->be_private;
+       BackendDB       db, *bd = op->o_bd;
        ldap_chain_cb_t lb = { 0 };
        slap_callback   *sc = op->o_callback,
                        sc2 = { 0 };
@@ -768,6 +823,10 @@ ldap_chain_response( Operation *op, SlapReply *rs )
         *   e) what ssf
         */
 
+       db = *op->o_bd;
+       SLAP_DBFLAGS( &db ) &= ~SLAP_DBFLAG_MONITORING;
+       op->o_bd = &db;
+
        matched = rs->sr_matched;
        rs->sr_matched = NULL;
        ref = rs->sr_ref;
@@ -921,7 +980,7 @@ dont_chain:;
        rs->sr_type = sr_type;
        rs->sr_matched = matched;
        rs->sr_ref = ref;
-       op->o_bd->be_private = private;
+       op->o_bd = bd;
        op->o_callback = sc;
        op->o_ndn = ndn;
 
@@ -1095,14 +1154,18 @@ chain_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
        if ( lc->lc_common_li == NULL ) {
                lc->lc_common_li = li;
 
-       } else if ( avl_insert( &lc->lc_lai.lai_tree, (caddr_t)li,
-               ldap_chain_uri_cmp, ldap_chain_uri_dup ) )
-       {
-               Debug( LDAP_DEBUG_ANY, "slapd-chain: "
-                       "database \"%s\" insert failed.\n",
-                       e->e_name.bv_val, 0, 0 );
-               rc = LDAP_CONSTRAINT_VIOLATION;
-               goto done;
+       } else {
+               li->li_uri = ch_strdup( at->a_vals[ 0 ].bv_val );
+               value_add_one( &li->li_bvuri, &at->a_vals[ 0 ] );
+               if ( avl_insert( &lc->lc_lai.lai_tree, (caddr_t)li,
+                       ldap_chain_uri_cmp, ldap_chain_uri_dup ) )
+               {
+                       Debug( LDAP_DEBUG_ANY, "slapd-chain: "
+                               "database \"%s\" insert failed.\n",
+                               e->e_name.bv_val, 0, 0 );
+                       rc = LDAP_CONSTRAINT_VIOLATION;
+                       goto done;
+               }
        }
 
 done:;
@@ -1427,11 +1490,17 @@ ldap_chain_db_init(
        ldap_chain_t    *lc = NULL;
 
        if ( lback == NULL ) {
+               static BackendInfo      lback2;
+
                lback = backend_info( "ldap" );
 
                if ( lback == NULL ) {
                        return 1;
                }
+
+               lback2 = *lback;
+               lback2.bi_type = ldapchain.on_bi.bi_type;
+               lback = &lback2;
        }
 
        lc = ch_malloc( sizeof( ldap_chain_t ) );
@@ -1650,10 +1719,10 @@ ldap_chain_db_open(
 {
        slap_overinst   *on = (slap_overinst *) be->bd_info;
        ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
+       slap_mask_t     monitoring;
+       int             rc = 0;
 
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
-       int     rc = 0;
-
        rc = overlay_register_control( be, LDAP_CONTROL_X_CHAINING_BEHAVIOR );
        if ( rc != 0 ) {
                return rc;
@@ -1667,7 +1736,13 @@ ldap_chain_db_open(
                be->be_private = be_private;
        }
 
-       return ldap_chain_db_func( be, db_open );
+       /* filter out and restore monitoring */
+       monitoring = ( SLAP_DBFLAGS( be ) & SLAP_DBFLAG_MONITORING );
+       SLAP_DBFLAGS( be ) &= ~SLAP_DBFLAG_MONITORING;
+       rc = ldap_chain_db_func( be, db_open );
+       SLAP_DBFLAGS( be ) |= monitoring;
+
+       return rc;
 }
 
 static int
@@ -1707,17 +1782,18 @@ ldap_chain_db_init_common(
 {
        BackendInfo     *bi = be->bd_info;
        ldapinfo_t      *li;
-       int             t;
+       int             rc;
 
        be->bd_info = lback;
        be->be_private = NULL;
-       t = lback->bi_db_init( be );
-       if ( t != 0 ) {
-               return t;
+       rc = lback->bi_db_init( be );
+       if ( rc != 0 ) {
+               return rc;
        }
        li = (ldapinfo_t *)be->be_private;
        li->li_urllist_f = NULL;
        li->li_urllist_p = NULL;
+
        be->bd_info = bi;
 
        return 0;
@@ -1765,6 +1841,33 @@ ldap_chain_db_init_one(
        return 0;
 }
 
+static int
+ldap_chain_db_open_one(
+       BackendDB       *be )
+{
+       if ( SLAP_DBMONITORING( be ) ) {
+               ldapinfo_t      *li = (ldapinfo_t *)be->be_private;
+
+               if ( li->li_uri == NULL ) {
+                       ber_str2bv( "cn=Common Connections", 0, 1,
+                               &li->li_monitor_info.lmi_rdn );
+
+               } else {
+                       char            *ptr;
+
+                       li->li_monitor_info.lmi_rdn.bv_len
+                               = STRLENOF( "cn=" ) + strlen( li->li_uri );
+                       ptr = li->li_monitor_info.lmi_rdn.bv_val
+                               = ch_malloc( li->li_monitor_info.lmi_rdn.bv_len + 1 );
+                       ptr = lutil_strcopy( ptr, "cn=" );
+                       ptr = lutil_strcopy( ptr, li->li_uri );
+                       ptr[ 0 ] = '\0';
+               }
+       }
+
+       return lback->bi_db_open( be );
+}
+
 typedef struct ldap_chain_conn_apply_t {
        BackendDB       *be;
        Connection      *conn;
@@ -1933,8 +2036,6 @@ ldap_chain_parse_ctrl(
 }
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
 
-static slap_overinst ldapchain;
-
 int
 chain_initialize( void )
 {