]> git.sur5r.net Git - openldap/commitdiff
port identity assertion to back-meta; share as much code as possible with back-ldap...
authorPierangelo Masarati <ando@openldap.org>
Thu, 15 Jun 2006 23:12:38 +0000 (23:12 +0000)
committerPierangelo Masarati <ando@openldap.org>
Thu, 15 Jun 2006 23:12:38 +0000 (23:12 +0000)
24 files changed:
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/config.c
servers/slapd/back-ldap/delete.c
servers/slapd/back-ldap/extended.c
servers/slapd/back-ldap/init.c
servers/slapd/back-ldap/modify.c
servers/slapd/back-ldap/modrdn.c
servers/slapd/back-ldap/proto-ldap.h
servers/slapd/back-ldap/search.c
servers/slapd/back-meta/add.c
servers/slapd/back-meta/back-meta.h
servers/slapd/back-meta/bind.c
servers/slapd/back-meta/candidates.c
servers/slapd/back-meta/compare.c
servers/slapd/back-meta/config.c
servers/slapd/back-meta/conn.c
servers/slapd/back-meta/delete.c
servers/slapd/back-meta/init.c
servers/slapd/back-meta/modify.c
servers/slapd/back-meta/modrdn.c
servers/slapd/back-meta/search.c

index 260b57aea721b6c4cfbcd6211fcc64f0492ea29e..cb46b16f355bb85aec3e03634f3f7ab5c4c57e0a 100644 (file)
@@ -93,7 +93,8 @@ ldap_back_add(
        attrs[ i ] = NULL;
 
        ctrls = op->o_ctrls;
-       rs->sr_err = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn, op, rs, &ctrls );
+       rs->sr_err = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
+               li->li_version, &li->li_idassert, op, rs, &ctrls );
        if ( rs->sr_err != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
                goto cleanup;
index 3df8356d1519d52345509091bef00d5542a4a26b..26528bcd6da64a9a3b4793643f565561b865d25f 100644 (file)
@@ -44,18 +44,23 @@ typedef struct ldapconn_t {
        struct berval           lc_bound_ndn;
        struct berval           lc_local_ndn;
        unsigned                lc_lcflags;
-#define LDAP_BACK_CONN_ISSET(lc,f)     ((lc)->lc_lcflags & (f))
-#define        LDAP_BACK_CONN_SET(lc,f)        ((lc)->lc_lcflags |= (f))
-#define        LDAP_BACK_CONN_CLEAR(lc,f)      ((lc)->lc_lcflags &= ~(f))
-#define        LDAP_BACK_CONN_CPY(lc,f,mlc) \
+#define LDAP_BACK_CONN_ISSET_F(fp,f)   (*(fp) & (f))
+#define        LDAP_BACK_CONN_SET_F(fp,f)      (*(fp) |= (f))
+#define        LDAP_BACK_CONN_CLEAR_F(fp,f)    (*(fp) &= ~(f))
+#define        LDAP_BACK_CONN_CPY_F(fp,f,mfp) \
        do { \
-               if ( ((f) & (mlc)->lc_lcflags) == (f) ) { \
-                       (lc)->lc_lcflags |= (f); \
+               if ( ((f) & *(mfp)) == (f) ) { \
+                       *(fp) |= (f); \
                } else { \
-                       (lc)->lc_lcflags &= ~(f); \
+                       *(fp) &= ~(f); \
                } \
        } while ( 0 )
 
+#define LDAP_BACK_CONN_ISSET(lc,f)     LDAP_BACK_CONN_ISSET_F(&(lc)->lc_lcflags, (f))
+#define        LDAP_BACK_CONN_SET(lc,f)        LDAP_BACK_CONN_SET_F(&(lc)->lc_lcflags, (f))
+#define        LDAP_BACK_CONN_CLEAR(lc,f)      LDAP_BACK_CONN_CLEAR_F(&(lc)->lc_lcflags, (f))
+#define        LDAP_BACK_CONN_CPY(lc,f,mlc)    LDAP_BACK_CONN_CPY_F(&(lc)->lc_lcflags, (f), &(mlc)->lc_lcflags)
+
 #define        LDAP_BACK_FCONN_ISBOUND (0x00000001U)
 #define        LDAP_BACK_FCONN_ISANON  (0x00000002U)
 #define        LDAP_BACK_FCONN_ISBMASK (LDAP_BACK_FCONN_ISBOUND|LDAP_BACK_FCONN_ISANON)
@@ -96,18 +101,6 @@ typedef struct ldapconn_t {
        time_t                  lc_time;
 } ldapconn_t;
 
-/*
- * identity assertion modes
- */
-enum {
-       LDAP_BACK_IDASSERT_LEGACY = 1,
-       LDAP_BACK_IDASSERT_NOASSERT,
-       LDAP_BACK_IDASSERT_ANONYMOUS,
-       LDAP_BACK_IDASSERT_SELF,
-       LDAP_BACK_IDASSERT_OTHERDN,
-       LDAP_BACK_IDASSERT_OTHERID
-};
-
 /*
  * operation enumeration for timeouts
  */
@@ -137,6 +130,47 @@ typedef struct slap_retry_info_t {
 #define SLAP_RETRYNUM_FINITE(n)        ((n) > SLAP_RETRYNUM_FOREVER)   /* not forever */
 } slap_retry_info_t;
 
+/*
+ * identity assertion modes
+ */
+typedef enum {
+       LDAP_BACK_IDASSERT_LEGACY = 1,
+       LDAP_BACK_IDASSERT_NOASSERT,
+       LDAP_BACK_IDASSERT_ANONYMOUS,
+       LDAP_BACK_IDASSERT_SELF,
+       LDAP_BACK_IDASSERT_OTHERDN,
+       LDAP_BACK_IDASSERT_OTHERID
+} slap_idassert_mode_t;
+
+/* ID assert stuff */
+typedef struct slap_idassert_t {
+       slap_idassert_mode_t    si_mode;
+#define        li_idassert_mode        li_idassert.si_mode
+
+       slap_bindconf   si_bc;
+#define        li_idassert_authcID     li_idassert.si_bc.sb_authcId
+#define        li_idassert_authcDN     li_idassert.si_bc.sb_binddn
+#define        li_idassert_passwd      li_idassert.si_bc.sb_cred
+#define        li_idassert_authzID     li_idassert.si_bc.sb_authzId
+#define        li_idassert_authmethod  li_idassert.si_bc.sb_method
+#define        li_idassert_sasl_mech   li_idassert.si_bc.sb_saslmech
+#define        li_idassert_sasl_realm  li_idassert.si_bc.sb_realm
+#define        li_idassert_secprops    li_idassert.si_bc.sb_secprops
+#define        li_idassert_tls         li_idassert.si_bc.sb_tls
+
+       unsigned        si_flags;
+#define LDAP_BACK_AUTH_NONE                            0x00U
+#define        LDAP_BACK_AUTH_NATIVE_AUTHZ                     0x01U
+#define        LDAP_BACK_AUTH_OVERRIDE                         0x02U
+#define        LDAP_BACK_AUTH_PRESCRIPTIVE                     0x04U
+#define        LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ             0x08U
+#define        LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND     0x10U
+#define        li_idassert_flags       li_idassert.si_flags
+
+       BerVarray       si_authz;
+#define        li_idassert_authz       li_idassert.si_authz
+} slap_idassert_t;
+
 /*
  * Hook to allow mucking with ldapinfo_t when quarantine is over
  */
@@ -166,27 +200,7 @@ typedef struct ldapinfo_t {
 #define        li_acl_secprops li_acl.sb_secprops
 
        /* ID assert stuff */
-       int             li_idassert_mode;
-
-       slap_bindconf   li_idassert;
-#define        li_idassert_authcID     li_idassert.sb_authcId
-#define        li_idassert_authcDN     li_idassert.sb_binddn
-#define        li_idassert_passwd      li_idassert.sb_cred
-#define        li_idassert_authzID     li_idassert.sb_authzId
-#define        li_idassert_authmethod  li_idassert.sb_method
-#define        li_idassert_sasl_mech   li_idassert.sb_saslmech
-#define        li_idassert_sasl_realm  li_idassert.sb_realm
-#define        li_idassert_secprops    li_idassert.sb_secprops
-
-       unsigned        li_idassert_flags;
-#define LDAP_BACK_AUTH_NONE                            0x00U
-#define        LDAP_BACK_AUTH_NATIVE_AUTHZ                     0x01U
-#define        LDAP_BACK_AUTH_OVERRIDE                         0x02U
-#define        LDAP_BACK_AUTH_PRESCRIPTIVE                     0x04U
-#define        LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ             0x08U
-#define        LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND     0x10U
-
-       BerVarray       li_idassert_authz;
+       slap_idassert_t li_idassert;
        /* end of ID assert stuff */
 
        int             li_nretries;
index c05e0ee77713e960c92f6de7b3772cf33d4c8dec..bd33fd5dabb6b963561ca9a4853ca311e027b976 100644 (file)
@@ -971,24 +971,6 @@ retry_lock:;
                ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
        }
 
-#if 0
-       while ( lc->lc_refcnt > 1 ) {
-               ldap_pvt_thread_yield();
-               rc = LDAP_BACK_CONN_ISBOUND( lc );
-               if ( rc ) {
-                       return rc;
-               }
-       }
-
-       if ( dolock ) {
-               ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
-       }
-       LDAP_BACK_CONN_BINDING_SET( lc );
-       if ( dolock ) {
-               ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
-       }
-#endif
-
        /*
         * FIXME: we need to let clients use proxyAuthz
         * otherwise we cannot do symmetric pools of servers;
@@ -1743,23 +1725,24 @@ done:;
 int
 ldap_back_proxy_authz_ctrl(
                struct berval   *bound_ndn,
+               int             version,
+               slap_idassert_t *si,
                Operation       *op,
                SlapReply       *rs,
                LDAPControl     ***pctrls )
 {
-       ldapinfo_t      *li = (ldapinfo_t *) op->o_bd->be_private;
-       LDAPControl     **ctrls = NULL;
-       int             i = 0,
-                       mode;
-       struct berval   assertedID,
-                       ndn;
+       LDAPControl             **ctrls = NULL;
+       int                     i = 0;
+       slap_idassert_mode_t    mode;
+       struct berval           assertedID,
+                               ndn;
 
        *pctrls = NULL;
 
        rs->sr_err = LDAP_SUCCESS;
 
        /* don't proxyAuthz if protocol is not LDAPv3 */
-       switch ( li->li_version ) {
+       switch ( version ) {
        case LDAP_VERSION3:
                break;
 
@@ -1776,8 +1759,8 @@ ldap_back_proxy_authz_ctrl(
        /* FIXME: SASL/EXTERNAL over ldapi:// doesn't honor the authcID,
         * but if it is not set this test fails.  We need a different
         * means to detect if idassert is enabled */
-       if ( ( BER_BVISNULL( &li->li_idassert_authcID ) || BER_BVISEMPTY( &li->li_idassert_authcID ) )
-                       && ( BER_BVISNULL( &li->li_idassert_authcDN ) || BER_BVISEMPTY( &li->li_idassert_authcDN ) ) )
+       if ( ( BER_BVISNULL( &si->si_bc.sb_authcId ) || BER_BVISEMPTY( &si->si_bc.sb_authcId ) )
+                       && ( BER_BVISNULL( &si->si_bc.sb_binddn ) || BER_BVISEMPTY( &si->si_bc.sb_binddn ) ) )
        {
                goto done;
        }
@@ -1796,7 +1779,7 @@ ldap_back_proxy_authz_ctrl(
                ndn = op->o_ndn;
        }
 
-       if ( li->li_idassert_mode == LDAP_BACK_IDASSERT_LEGACY ) {
+       if ( si->si_mode == LDAP_BACK_IDASSERT_LEGACY ) {
                if ( op->o_proxy_authz ) {
                        /*
                         * FIXME: we do not want to perform proxyAuthz
@@ -1823,18 +1806,18 @@ ldap_back_proxy_authz_ctrl(
                        goto done;
                }
 
-               if ( BER_BVISNULL( &li->li_idassert_authcDN ) ) {
+               if ( BER_BVISNULL( &si->si_bc.sb_binddn ) ) {
                        goto done;
                }
 
-       } else if ( li->li_idassert_authmethod == LDAP_AUTH_SASL ) {
-               if ( ( li->li_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) )
+       } else if ( si->si_bc.sb_method == LDAP_AUTH_SASL ) {
+               if ( ( si->si_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) )
                {
                        /* already asserted in SASL via native authz */
                        goto done;
                }
 
-       } else if ( li->li_idassert_authz && !be_isroot( op ) ) {
+       } else if ( si->si_authz && !be_isroot( op ) ) {
                int             rc;
                struct berval authcDN;
 
@@ -1843,11 +1826,10 @@ ldap_back_proxy_authz_ctrl(
                } else {
                        authcDN = ndn;
                }
-               rc = slap_sasl_matches( op, li->li_idassert_authz,
+               rc = slap_sasl_matches( op, si->si_authz,
                                &authcDN, & authcDN );
                if ( rc != LDAP_SUCCESS ) {
-                       if ( li->li_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE )
-                       {
+                       if ( si->si_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
                                /* ndn is not authorized
                                 * to use idassert */
                                rs->sr_err = rc;
@@ -1882,7 +1864,7 @@ ldap_back_proxy_authz_ctrl(
                mode = LDAP_BACK_IDASSERT_NOASSERT;
 
        } else {
-               mode = li->li_idassert_mode;
+               mode = si->si_mode;
        }
 
        switch ( mode ) {
@@ -1915,7 +1897,7 @@ ldap_back_proxy_authz_ctrl(
        case LDAP_BACK_IDASSERT_OTHERID:
        case LDAP_BACK_IDASSERT_OTHERDN:
                /* assert idassert DN */
-               assertedID = li->li_idassert_authzID;
+               assertedID = si->si_bc.sb_authzId;
                break;
 
        default:
@@ -1943,7 +1925,7 @@ ldap_back_proxy_authz_ctrl(
        ctrls[ 0 ]->ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
        ctrls[ 0 ]->ldctl_iscritical = 1;
 
-       switch ( li->li_idassert_mode ) {
+       switch ( si->si_mode ) {
        /* already in u:ID or dn:DN form */
        case LDAP_BACK_IDASSERT_OTHERID:
        case LDAP_BACK_IDASSERT_OTHERDN:
@@ -1965,7 +1947,7 @@ ldap_back_proxy_authz_ctrl(
         * to encode the value of the authzID (and called it proxyDN);
         * this hack provides compatibility with those DSAs that
         * implement it this way */
-       if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
+       if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
                struct berval           authzID = ctrls[ 0 ]->ldctl_value;
                BerElementBuffer        berbuf;
                BerElement              *ber = (BerElement *)&berbuf;
@@ -1995,7 +1977,7 @@ free_ber:;
                        goto done;
                }
 
-       } else if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
+       } else if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
                struct berval           authzID = ctrls[ 0 ]->ldctl_value,
                                        tmp;
                BerElementBuffer        berbuf;
index e37e986bc39d5a588b1e46d82f98d87ffae6aada..b14de0d68def022aa59a8c375caa5548175f1803 100644 (file)
@@ -36,6 +36,8 @@ ldap_back_compare(
                Operation       *op,
                SlapReply       *rs )
 {
+       ldapinfo_t      *li = (ldapinfo_t *)op->o_bd->be_private;
+
        ldapconn_t      *lc;
        ber_int_t       msgid;
        int             do_retry = 1;
@@ -49,7 +51,8 @@ ldap_back_compare(
        }
 
        ctrls = op->o_ctrls;
-       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn, op, rs, &ctrls );
+       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
+               li->li_version, &li->li_idassert, op, rs, &ctrls );
        if ( rc != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
                goto cleanup;
index 14a44a51ed99627ab7e4d495fe752d3d52d3059a..05846e015e68518f27d82b42f1a87a684fcc3c13 100644 (file)
@@ -512,6 +512,181 @@ slap_retry_info_destroy(
        ri->ri_num = NULL;
 }
 
+static int
+slap_idassert_authzfrom_parse( ConfigArgs *c, slap_idassert_t *si )
+{
+       ldapinfo_t      *li = ( ldapinfo_t * )c->be->be_private;
+       struct berval   bv;
+       struct berval   in;
+       int             rc;
+
+       ber_str2bv( c->argv[ 1 ], 0, 0, &in );
+       rc = authzNormalize( 0, NULL, NULL, &in, &bv, NULL );
+       if ( rc != LDAP_SUCCESS ) {
+               snprintf( c->msg, sizeof( c->msg ),
+                       "\"idassert-authzFrom <authz>\": "
+                       "invalid syntax" );
+               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+               return 1;
+       }
+       ber_bvarray_add( &li->li_idassert_authz, &bv );
+
+       return 0;
+}
+
+static int
+slap_idassert_parse( ConfigArgs *c, slap_idassert_t *si )
+{
+       int             i;
+
+       for ( i = 1; i < c->argc; i++ ) {
+               if ( strncasecmp( c->argv[ i ], "mode=", STRLENOF( "mode=" ) ) == 0 ) {
+                       char    *argvi = c->argv[ i ] + STRLENOF( "mode=" );
+                       int     j;
+
+                       j = verb_to_mask( argvi, idassert_mode );
+                       if ( BER_BVISNULL( &idassert_mode[ j ].word ) ) {
+                               snprintf( c->msg, sizeof( c->msg ),
+                                       "\"idassert-bind <args>\": "
+                                       "unknown mode \"%s\"",
+                                       argvi );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               return 1;
+                       }
+
+                       si->si_mode = idassert_mode[ j ].mask;
+
+               } else if ( strncasecmp( c->argv[ i ], "authz=", STRLENOF( "authz=" ) ) == 0 ) {
+                       char    *argvi = c->argv[ i ] + STRLENOF( "authz=" );
+
+                       if ( strcasecmp( argvi, "native" ) == 0 ) {
+                               if ( si->si_bc.sb_method != LDAP_AUTH_SASL ) {
+                                       snprintf( c->msg, sizeof( c->msg ),
+                                               "\"idassert-bind <args>\": "
+                                               "authz=\"native\" incompatible "
+                                               "with auth method" );
+                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                                       return 1;
+                               }
+                               si->si_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ;
+
+                       } else if ( strcasecmp( argvi, "proxyAuthz" ) == 0 ) {
+                               si->si_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ;
+
+                       } else {
+                               snprintf( c->msg, sizeof( c->msg ),
+                                       "\"idassert-bind <args>\": "
+                                       "unknown authz \"%s\"",
+                                       argvi );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               return 1;
+                       }
+
+               } else if ( strncasecmp( c->argv[ i ], "flags=", STRLENOF( "flags=" ) ) == 0 ) {
+                       char    *argvi = c->argv[ i ] + STRLENOF( "flags=" );
+                       char    **flags = ldap_str2charray( argvi, "," );
+                       int     j, err = 0;
+
+                       if ( flags == NULL ) {
+                               snprintf( c->msg, sizeof( c->msg ),
+                                       "\"idassert-bind <args>\": "
+                                       "unable to parse flags \"%s\"",
+                                       argvi );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               return 1;
+                       }
+
+                       for ( j = 0; flags[ j ] != NULL; j++ ) {
+
+                               if ( strcasecmp( flags[ j ], "override" ) == 0 ) {
+                                       si->si_flags |= LDAP_BACK_AUTH_OVERRIDE;
+
+                               } else if ( strcasecmp( flags[ j ], "prescriptive" ) == 0 ) {
+                                       si->si_flags |= LDAP_BACK_AUTH_PRESCRIPTIVE;
+
+                               } else if ( strcasecmp( flags[ j ], "non-prescriptive" ) == 0 ) {
+                                       si->si_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE );
+
+                               } else if ( strcasecmp( flags[ j ], "obsolete-proxy-authz" ) == 0 ) {
+                                       if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
+                                               Debug( LDAP_DEBUG_ANY,
+                                                               "%s: \"obsolete-proxy-authz\" flag "
+                                                               "in \"idassert-mode <args>\" "
+                                                               "incompatible with previously issued \"obsolete-encoding-workaround\" flag.\n",
+                                                               c->log, 0, 0 );
+                                               err = 1;
+                                               break;
+
+                                       } else {
+                                               si->si_flags |= LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ;
+                                       }
+
+                               } else if ( strcasecmp( flags[ j ], "obsolete-encoding-workaround" ) == 0 ) {
+                                       if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
+                                               Debug( LDAP_DEBUG_ANY,
+                                                               "%s: \"obsolete-encoding-workaround\" flag "
+                                                               "in \"idassert-mode <args>\" "
+                                                               "incompatible with previously issued \"obsolete-proxy-authz\" flag.\n",
+                                                               c->log, 0, 0 );
+                                               err = 1;
+                                               break;
+
+                                       } else {
+                                               si->si_flags |= LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND;
+                                       }
+
+                               } else {
+                                       snprintf( c->msg, sizeof( c->msg ),
+                                               "\"idassert-bind <args>\": "
+                                               "unknown flag \"%s\"",
+                                               flags[ j ] );
+                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                                       err = 1;
+                                       break;
+                               }
+                       }
+
+                       ldap_charray_free( flags );
+                       if ( err ) {
+                               return 1;
+                       }
+
+               } else if ( bindconf_parse( c->argv[ i ], &si->si_bc ) ) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+/* NOTE: temporary, until back-meta is ported to back-config */
+int
+slap_idassert_authzfrom_parse_cf( const char *fname, int lineno, const char *arg, slap_idassert_t *si )
+{
+       ConfigArgs      c = { 0 };
+       char            *argv[ 2 ];
+
+       snprintf( c.log, sizeof( c.log ), "%s: line %d", fname, lineno );
+       c.argc = 2;
+       c.argv = argv;
+       argv[ 0 ] = arg;
+       argv[ 1 ] = NULL;
+
+       return slap_idassert_authzfrom_parse( &c, si );
+}
+
+int
+slap_idassert_parse_cf( const char *fname, int lineno, int argc, char *argv[], slap_idassert_t *si )
+{
+       ConfigArgs      c = { 0 };
+
+       snprintf( c.log, sizeof( c.log ), "%s: line %d", fname, lineno );
+       c.argc = argc;
+       c.argv = argv;
+
+       return slap_idassert_parse( &c, si );
+}
+
 static int
 ldap_back_cf_gen( ConfigArgs *c )
 {
@@ -689,7 +864,7 @@ ldap_back_cf_gen( ConfigArgs *c )
                                /* end-of-flags */
                        }
 
-                       bindconf_unparse( &li->li_idassert, &bc );
+                       bindconf_unparse( &li->li_idassert.si_bc, &bc );
 
                        if ( !BER_BVISNULL( &bv ) ) {
                                ber_len_t       len = bv.bv_len + bc.bv_len;
@@ -912,7 +1087,7 @@ ldap_back_cf_gen( ConfigArgs *c )
                        break;
 
                case LDAP_BACK_CFG_IDASSERT_BIND:
-                       bindconf_free( &li->li_idassert );
+                       bindconf_free( &li->li_idassert.si_bc );
                        break;
 
                case LDAP_BACK_CFG_REBIND:
@@ -1315,22 +1490,9 @@ done_url:;
                ber_str2bv( c->argv[ 1 ], 0, 1, &li->li_idassert_passwd );
                break;
 
-       case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: {
-               struct berval   bv;
-               struct berval   in;
-               int             rc;
-
-               ber_str2bv( c->argv[ 1 ], 0, 0, &in );
-               rc = authzNormalize( 0, NULL, NULL, &in, &bv, NULL );
-               if ( rc != LDAP_SUCCESS ) {
-                       snprintf( c->msg, sizeof( c->msg ),
-                               "\"idassert-authzFrom <authz>\": "
-                               "invalid syntax" );
-                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
-                       return 1;
-               }
-               ber_bvarray_add( &li->li_idassert_authz, &bv );
-               } break;
+       case LDAP_BACK_CFG_IDASSERT_AUTHZFROM:
+               rc = slap_idassert_authzfrom_parse( c, &li->li_idassert );
+               break;
 
        case LDAP_BACK_CFG_IDASSERT_METHOD:
                /* no longer supported */
@@ -1341,122 +1503,7 @@ done_url:;
                return 1;
 
        case LDAP_BACK_CFG_IDASSERT_BIND:
-               for ( i = 1; i < c->argc; i++ ) {
-                       if ( strncasecmp( c->argv[ i ], "mode=", STRLENOF( "mode=" ) ) == 0 ) {
-                               char    *argvi = c->argv[ i ] + STRLENOF( "mode=" );
-                               int     j;
-
-                               j = verb_to_mask( argvi, idassert_mode );
-                               if ( BER_BVISNULL( &idassert_mode[ j ].word ) ) {
-                                       snprintf( c->msg, sizeof( c->msg ),
-                                               "\"idassert-bind <args>\": "
-                                               "unknown mode \"%s\"",
-                                               argvi );
-                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
-                                       return 1;
-                               }
-
-                               li->li_idassert_mode = idassert_mode[ j ].mask;
-
-                       } else if ( strncasecmp( c->argv[ i ], "authz=", STRLENOF( "authz=" ) ) == 0 ) {
-                               char    *argvi = c->argv[ i ] + STRLENOF( "authz=" );
-
-                               if ( strcasecmp( argvi, "native" ) == 0 ) {
-                                       if ( li->li_idassert_authmethod != LDAP_AUTH_SASL ) {
-                                               snprintf( c->msg, sizeof( c->msg ),
-                                                       "\"idassert-bind <args>\": "
-                                                       "authz=\"native\" incompatible "
-                                                       "with auth method" );
-                                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
-                                               return 1;
-                                       }
-                                       li->li_idassert_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ;
-
-                               } else if ( strcasecmp( argvi, "proxyAuthz" ) == 0 ) {
-                                       li->li_idassert_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ;
-
-                               } else {
-                                       snprintf( c->msg, sizeof( c->msg ),
-                                               "\"idassert-bind <args>\": "
-                                               "unknown authz \"%s\"",
-                                               argvi );
-                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
-                                       return 1;
-                               }
-
-                       } else if ( strncasecmp( c->argv[ i ], "flags=", STRLENOF( "flags=" ) ) == 0 ) {
-                               char    *argvi = c->argv[ i ] + STRLENOF( "flags=" );
-                               char    **flags = ldap_str2charray( argvi, "," );
-                               int     j, err = 0;
-
-                               if ( flags == NULL ) {
-                                       snprintf( c->msg, sizeof( c->msg ),
-                                               "\"idassert-bind <args>\": "
-                                               "unable to parse flags \"%s\"",
-                                               argvi );
-                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
-                                       return 1;
-                               }
-
-                               for ( j = 0; flags[ j ] != NULL; j++ ) {
-
-                                       if ( strcasecmp( flags[ j ], "override" ) == 0 ) {
-                                               li->li_idassert_flags |= LDAP_BACK_AUTH_OVERRIDE;
-
-                                       } else if ( strcasecmp( flags[ j ], "prescriptive" ) == 0 ) {
-                                               li->li_idassert_flags |= LDAP_BACK_AUTH_PRESCRIPTIVE;
-
-                                       } else if ( strcasecmp( flags[ j ], "non-prescriptive" ) == 0 ) {
-                                               li->li_idassert_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE );
-
-                                       } else if ( strcasecmp( flags[ j ], "obsolete-proxy-authz" ) == 0 ) {
-                                               if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
-                                                       Debug( LDAP_DEBUG_ANY,
-                                                                       "%s: line %d: \"obsolete-proxy-authz\" flag "
-                                                                       "in \"idassert-mode <args>\" "
-                                                                       "incompatible with previously issued \"obsolete-encoding-workaround\" flag.\n",
-                                                                       c->fname, c->lineno, 0 );
-                                                       err = 1;
-                                                       break;
-
-                                               } else {
-                                                       li->li_idassert_flags |= LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ;
-                                               }
-
-                                       } else if ( strcasecmp( flags[ j ], "obsolete-encoding-workaround" ) == 0 ) {
-                                               if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
-                                                       Debug( LDAP_DEBUG_ANY,
-                                                                       "%s: line %d: \"obsolete-encoding-workaround\" flag "
-                                                               "in \"idassert-mode <args>\" "
-                                                               "incompatible with previously issued \"obsolete-proxy-authz\" flag.\n",
-                                                               c->fname, c->lineno, 0 );
-                                                       err = 1;
-                                                       break;
-
-                                               } else {
-                                                       li->li_idassert_flags |= LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND;
-                                               }
-
-                                       } else {
-                                               snprintf( c->msg, sizeof( c->msg ),
-                                                       "\"idassert-bind <args>\": "
-                                                       "unknown flag \"%s\"",
-                                                       flags[ j ] );
-                                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
-                                               err = 1;
-                                               break;
-                                       }
-                               }
-
-                               ldap_charray_free( flags );
-                               if ( err ) {
-                                       return 1;
-                               }
-
-                       } else if ( bindconf_parse( c->argv[ i ], &li->li_idassert ) ) {
-                               return 1;
-                       }
-               }
+               rc = slap_idassert_parse( c, &li->li_idassert );
                break;
 
        case LDAP_BACK_CFG_REBIND:
index 3394a5aeba6b0e1c96f16fcb86d14dfe6b7f39d2..43e88540b4b59b0a5bc31ef8209b0bc1144f1e70 100644 (file)
@@ -51,7 +51,8 @@ ldap_back_delete(
        }
 
        ctrls = op->o_ctrls;
-       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn, op, rs, &ctrls );
+       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
+               li->li_version, &li->li_idassert, op, rs, &ctrls );
        if ( rc != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
                rc = rs->sr_err;
index 2bf37c49e35ec4041ceaca4b67896dae7e7457c9..9af2738a8b5f5699da56297413de1e4469d9e448 100644 (file)
@@ -42,6 +42,8 @@ static struct exop {
 static int
 ldap_back_extended_one( Operation *op, SlapReply *rs, BI_op_extended exop )
 {
+       ldapinfo_t      *li = (ldapinfo_t *) op->o_bd->be_private;
+
        ldapconn_t      *lc;
        LDAPControl     **oldctrls = NULL;
        int             rc;
@@ -56,7 +58,9 @@ ldap_back_extended_one( Operation *op, SlapReply *rs, BI_op_extended exop )
        }
 
        oldctrls = op->o_ctrls;
-       if ( ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn, op, rs, &op->o_ctrls ) ) {
+       if ( ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
+               li->li_version, &li->li_idassert, op, rs, &op->o_ctrls ) )
+       {
                op->o_ctrls = oldctrls;
                send_ldap_extended( op, rs );
                rs->sr_text = NULL;
index 396eb912e55805794ff14c1f46ca0071161f5974..74ef0b6b44a45603b8479557c3e7a71e3a5164c5 100644 (file)
@@ -126,7 +126,7 @@ ldap_back_db_init( Backend *be )
 
        li->li_idassert_authmethod = LDAP_AUTH_NONE;
        BER_BVZERO( &li->li_idassert_sasl_mech );
-       li->li_idassert.sb_tls = SB_TLS_DEFAULT;
+       li->li_idassert_tls = SB_TLS_DEFAULT;
 
        /* by default, use proxyAuthz control on each operation */
        li->li_idassert_flags = LDAP_BACK_AUTH_PRESCRIPTIVE;
index e3ad3d5abaf5145f6b22ab4d133f18166258f116..60ccc5168738a29cc02c5805bd9775dc081bd387 100644 (file)
@@ -99,7 +99,8 @@ ldap_back_modify(
        modv[ i ] = 0;
 
        ctrls = op->o_ctrls;
-       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn, op, rs, &ctrls );
+       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
+               li->li_version, &li->li_idassert, op, rs, &ctrls );
        if ( rc != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
                rc = -1;
index 304482922f4e6dd970bf6af1adaf96a4b02e429a..2f92a0003d061fc1691f44f14b3ec0f207c2a061 100644 (file)
@@ -74,7 +74,8 @@ ldap_back_modrdn(
        }
 
        ctrls = op->o_ctrls;
-       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn, op, rs, &ctrls );
+       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
+               li->li_version, &li->li_idassert, op, rs, &ctrls );
        if ( rc != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
                rc = -1;
index 72dd5f359bad85236ae982ef5ba67beabbcc6992..10539d1d353f149700c064e2018bd1412cf80fbc 100644 (file)
@@ -68,6 +68,8 @@ extern void ldap_back_conn_free( void *c );
 extern int
 ldap_back_proxy_authz_ctrl(
                struct berval   *bound_ndn,
+               int             version,
+               slap_idassert_t *si,
                Operation       *op,
                SlapReply       *rs,
                LDAPControl     ***pctrls );
@@ -87,6 +89,8 @@ extern int slap_retry_info_parse( char *in, slap_retry_info_t *ri,
        char *buf, ber_len_t buflen );
 extern int slap_retry_info_unparse( slap_retry_info_t *ri, struct berval *bvout );
 
+extern int slap_idassert_authzfrom_parse_cf( const char *fname, int lineno, const char *arg, slap_idassert_t *si );
+extern int slap_idassert_parse_cf( const char *fname, int lineno, int argc, char *argv[], slap_idassert_t *si );
 
 extern int chain_initialize( void );
 #ifdef LDAP_DEVEL
index cc17bc06af189b91fac7c6e656585affcf9e750d..175341bc1ef0db60925a787d7095e7137546a81f 100644 (file)
@@ -203,7 +203,8 @@ ldap_back_search(
        }
 
        ctrls = op->o_ctrls;
-       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn, op, rs, &ctrls );
+       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
+               li->li_version, &li->li_idassert, op, rs, &ctrls );
        if ( rc != LDAP_SUCCESS ) {
                goto finish;
        }
@@ -708,9 +709,10 @@ ldap_back_entry_get(
                ObjectClass             *oc,
                AttributeDescription    *at,
                int                     rw,
-               Entry                   **ent
-)
+               Entry                   **ent )
 {
+       ldapinfo_t      *li = (ldapinfo_t *) op->o_bd->be_private;
+
        ldapconn_t      *lc;
        int             rc = 1,
                        do_not_cache;
@@ -760,7 +762,8 @@ ldap_back_entry_get(
        }
 
        ctrls = op->o_ctrls;
-       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn, op, &rs, &ctrls );
+       rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,
+               li->li_version, &li->li_idassert, op, &rs, &ctrls );
        if ( rc != LDAP_SUCCESS ) {
                goto cleanup;
        }
index af2663549f123e204b22c2b25a17f854f333fb49..1b56d7ed8c5d1ae8f99a364b3380c879a71496c2 100644 (file)
@@ -36,6 +36,7 @@ int
 meta_back_add( Operation *op, SlapReply *rs )
 {
        metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
+       metatarget_t    *mt;
        metaconn_t      *mc;
        int             i, candidate = -1;
        int             isupdate;
@@ -45,6 +46,7 @@ meta_back_add( Operation *op, SlapReply *rs )
        dncookie        dc;
        int             msgid;
        int             do_retry = 1;
+       LDAPControl     **ctrls = NULL;
        int             maperr = 1;
 
        Debug(LDAP_DEBUG_ARGS, "==> meta_back_add: %s\n",
@@ -63,7 +65,8 @@ meta_back_add( Operation *op, SlapReply *rs )
        /*
         * Rewrite the add dn, if needed
         */
-       dc.target = mi->mi_targets[ candidate ];
+       mt = mi->mi_targets[ candidate ];
+       dc.target = mt;
        dc.conn = op->o_conn;
        dc.rs = rs;
        dc.ctx = "addDN";
@@ -96,7 +99,7 @@ meta_back_add( Operation *op, SlapReply *rs )
                        mapped = a->a_desc->ad_cname;
 
                } else {
-                       ldap_back_map( &mi->mi_targets[ candidate ]->mt_rwmap.rwm_at,
+                       ldap_back_map( &mt->mt_rwmap.rwm_at,
                                        &a->a_desc->ad_cname, &mapped, BACKLDAP_MAP );
                        if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
                                continue;
@@ -121,11 +124,11 @@ meta_back_add( Operation *op, SlapReply *rs )
                        for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); ) {
                                struct ldapmapping      *mapping;
 
-                               ldap_back_mapping( &mi->mi_targets[ candidate ]->mt_rwmap.rwm_oc,
+                               ldap_back_mapping( &mt->mt_rwmap.rwm_oc,
                                                &a->a_vals[ j ], &mapping, BACKLDAP_MAP );
 
                                if ( mapping == NULL ) {
-                                       if ( mi->mi_targets[ candidate ]->mt_rwmap.rwm_oc.drop_missing ) {
+                                       if ( mt->mt_rwmap.rwm_oc.drop_missing ) {
                                                continue;
                                        }
                                        attrs[ i ]->mod_bvalues[ j ] = &a->a_vals[ j ];
@@ -165,9 +168,17 @@ meta_back_add( Operation *op, SlapReply *rs )
        }
        attrs[ i ] = NULL;
 
+       ctrls = op->o_ctrls;
+       if ( ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn,
+               mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) != LDAP_SUCCESS )
+       {
+               maperr = 0;
+               goto sendres;
+       }
+
 retry:;
        rs->sr_err = ldap_add_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
-                             attrs, op->o_ctrls, NULL, &msgid );
+                             attrs, ctrls, NULL, &msgid );
        if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
                do_retry = 0;
                if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
@@ -180,8 +191,8 @@ retry:;
                LDAPMessage     *res = NULL;
                int             rc;
 
-               if ( mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_ADD ] != 0 ) {
-                       tv.tv_sec = mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_ADD ];
+               if ( mt->mt_timeout[ LDAP_BACK_OP_ADD ] != 0 ) {
+                       tv.tv_sec = mt->mt_timeout[ LDAP_BACK_OP_ADD ];
                        tv.tv_usec = 0;
                        tvp = &tv;
                }
@@ -201,6 +212,7 @@ retry:;
                        break;
 
                case LDAP_RES_ADD:
+                       /* FIXME: matched? referrals? response controls? */
                        rc = ldap_parse_result( mc->mc_conns[ candidate ].msc_ld,
                                res, &rs->sr_err, NULL, NULL, NULL, NULL, 1 );
                        if ( rc != LDAP_SUCCESS ) {
@@ -215,13 +227,16 @@ retry:;
                }
        }
 
+sendres:;
+       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+
        if ( maperr ) {
                rs->sr_err = meta_back_op_result( mc, op, rs, candidate );
 
        } else {
                send_ldap_result( op, rs );
 
-               if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ candidate ] ) ) {
+               if ( META_BACK_TGT_QUARANTINE( mt ) ) {
                        meta_back_quarantine( op, rs, candidate );
                }
        }
index c5a4ee4c1ffb899eafbf09025085eabb9d07fe27..9d42fae474103bb9ef2d246ae4b94d46e9ac850e 100644 (file)
@@ -229,8 +229,19 @@ typedef struct metatarget_t {
        struct berval           mt_binddn;
        struct berval           mt_bindpw;
 
-       struct berval           mt_pseudorootdn;
-       struct berval           mt_pseudorootpw;
+       slap_idassert_t         mt_idassert;
+#define        mt_idassert_mode        mt_idassert.si_mode
+#define        mt_idassert_authcID     mt_idassert.si_bc.sb_authcId
+#define        mt_idassert_authcDN     mt_idassert.si_bc.sb_binddn
+#define        mt_idassert_passwd      mt_idassert.si_bc.sb_cred
+#define        mt_idassert_authzID     mt_idassert.si_bc.sb_authzId
+#define        mt_idassert_authmethod  mt_idassert.si_bc.sb_method
+#define        mt_idassert_sasl_mech   mt_idassert.si_bc.sb_saslmech
+#define        mt_idassert_sasl_realm  mt_idassert.si_bc.sb_realm
+#define        mt_idassert_secprops    mt_idassert.si_bc.sb_secprops
+#define        mt_idassert_tls         mt_idassert.si_bc.sb_tls
+#define        mt_idassert_flags       mt_idassert.si_flags
+#define        mt_idassert_authz       mt_idassert.si_authz
 
        int                     mt_nretries;
 #define META_RETRY_UNDEFINED   (-2)
@@ -400,6 +411,17 @@ meta_back_single_dobind(
        int                     retries,
        int                     dolock );
 
+extern int
+meta_back_proxy_authz_cred(
+       metaconn_t              *mc,
+       int                     candidate,
+       Operation               *op,
+       SlapReply               *rs,
+       ldap_back_send_t        sendok,
+       struct berval           *binddn,
+       struct berval           *bindcred,
+       int                     *method );
+
 extern int
 meta_back_cancel(
        metaconn_t              *mc,
index b5df2a52fd8976c5fc11880af76550db9070e6d6..9f5c009229198bd88b1ca7f6c3c5b6acf46abe07 100644 (file)
 #include "../back-ldap/back-ldap.h"
 #include "back-meta.h"
 
+#include "lutil_ldap.h"
+
+static int
+meta_back_proxy_authz_bind(
+       metaconn_t              *mc,
+       int                     candidate,
+       Operation               *op,
+       SlapReply               *rs,
+       ldap_back_send_t        sendok );
+
 int
 meta_back_bind( Operation *op, SlapReply *rs )
 {
@@ -140,7 +150,8 @@ meta_back_bind( Operation *op, SlapReply *rs )
                }
 
                if ( isroot ) {
-                       if ( BER_BVISNULL( &mt->mt_pseudorootdn ) )
+                       if ( mt->mt_idassert_authmethod == LDAP_AUTH_NONE
+                               || BER_BVISNULL( &mt->mt_idassert_authcDN ) )
                        {
                                metasingleconn_t        *msc = &mc->mc_conns[ i ];
 
@@ -163,9 +174,14 @@ meta_back_bind( Operation *op, SlapReply *rs )
                                continue;
                        }
 
-                       op2.o_req_dn = mt->mt_pseudorootdn;
-                       op2.o_req_ndn = mt->mt_pseudorootdn;
-                       op2.orb_cred = mt->mt_pseudorootpw;
+                       /* FIXME: if sb_method == LDAP_AUTH_SASL things differ a bit */
+                       if ( mt->mt_idassert_authmethod == LDAP_AUTH_SASL ) {
+                               /* ### */
+                       }
+
+                       op2.o_req_dn = mt->mt_idassert_authcDN;
+                       op2.o_req_ndn = mt->mt_idassert_authcDN;
+                       op2.orb_cred = mt->mt_idassert_passwd;
                        op2.orb_method = LDAP_AUTH_SIMPLE;
 
                        massage = 0;
@@ -233,7 +249,7 @@ retry_lock:;
                        }
 
                        ber_bvreplace( &mc->mc_local_ndn, &op->o_req_ndn );
-                       if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) {
+                       if ( isroot ) {
                                mc->mc_conn = LDAP_BACK_PCONN_SET( op );
                        }
                        lerr = avl_insert( &mi->mi_conninfo.lai_tree, (caddr_t)mc,
@@ -310,7 +326,7 @@ retry:;
                switch ( ldap_result( msc->msc_ld, msgid, LDAP_MSG_ALL, &tv, &res ) ) {
                case 0:
                        Debug( LDAP_DEBUG_ANY,
-                               "%s meta_back_single_bind[%d]: ldap_result=0 nretries=%d.\n",
+                               "%s meta_back_bind_op_result[%d]: ldap_result=0 nretries=%d.\n",
                                op->o_log_prefix, candidate, nretries );
 
                        if ( nretries != META_RETRY_NEVER ) {
@@ -334,11 +350,12 @@ retry:;
                                "err=%d (%s) nretries=%d",
                                rs->sr_err, ldap_err2string( rs->sr_err ), nretries );
                        Debug( LDAP_DEBUG_ANY,
-                               "### %s meta_back_single_bind[%d]: %s.\n",
+                               "### %s meta_back_bind_op_result[%d]: %s.\n",
                                op->o_log_prefix, candidate, buf );
                        break;
 
                default:
+                       /* FIXME: matched? referrals? response controls? */
                        rc = ldap_parse_result( msc->msc_ld, res, &rs->sr_err,
                                        NULL, NULL, NULL, NULL, 1 );
                        if ( rc != LDAP_SUCCESS ) {
@@ -416,7 +433,20 @@ meta_back_single_bind(
                goto return_results;
        }
 
-       ber_bvreplace( &msc->msc_bound_ndn, &op->o_req_dn );
+       /* If defined, proxyAuthz will be used also when
+        * back-ldap is the authorizing backend; for this
+        * purpose, a successful bind is followed by a
+        * bind with the configured identity assertion */
+       /* NOTE: use with care */
+       if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) {
+               meta_back_proxy_authz_bind( mc, candidate, op, rs, LDAP_BACK_SENDERR );
+               if ( !LDAP_BACK_CONN_ISBOUND( msc ) ) {
+                       goto return_results;
+               }
+               goto cache_refresh;
+       }
+
+       ber_bvreplace( &msc->msc_bound_ndn, &op->o_req_ndn );
        LDAP_BACK_CONN_ISBOUND_SET( msc );
        mc->mc_authz_target = candidate;
 
@@ -468,41 +498,18 @@ meta_back_single_dobind(
 
        assert( !LDAP_BACK_CONN_ISBOUND( msc ) );
 
-       /*
-        * meta_back_single_dobind() calls meta_back_single_bind()
-        * if required.
-        */
-       if ( be_isroot( op ) && !BER_BVISNULL( &mt->mt_pseudorootdn ) )
+       /* NOTE: this obsoletes pseudorootdn */
+       if ( op->o_conn != NULL &&
+               !op->o_do_not_cache &&
+               ( BER_BVISNULL( &msc->msc_bound_ndn ) ||
+                       BER_BVISEMPTY( &msc->msc_bound_ndn ) ||
+                       ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
        {
-               Operation       op2 = *op;
-
-               op2.o_tag = LDAP_REQ_BIND;
-               op2.o_req_dn = mt->mt_pseudorootdn;
-               op2.o_req_ndn = mt->mt_pseudorootdn;
-               op2.orb_cred = mt->mt_pseudorootpw;
-               op2.orb_method = LDAP_AUTH_SIMPLE;
-
-               rc = meta_back_single_bind( &op2, rs, *mcp, candidate, 0 );
+               (void)meta_back_proxy_authz_bind( mc, candidate, op, rs, sendok );
+               rc = rs->sr_err;
                goto done;
        }
 
-       /*
-        * Otherwise an anonymous bind is performed
-        * (note: if the target was already bound, the anonymous
-        * bind clears the previous bind).
-        */
-       if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
-               ber_memfree( msc->msc_bound_ndn.bv_val );
-               BER_BVZERO( &msc->msc_bound_ndn );
-       }
-               
-       if ( LDAP_BACK_SAVECRED( mi ) && !BER_BVISNULL( &msc->msc_cred ) ) {
-               /* destroy sensitive data */
-               memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
-               ber_memfree( msc->msc_cred.bv_val );
-               BER_BVZERO( &msc->msc_cred );
-       }
-
        /* FIXME: should we check if at least some of the op->o_ctrls
         * can/should be passed? */
        rs->sr_err = ldap_sasl_bind( msc->msc_ld, "", LDAP_SASL_SIMPLE, &cred,
@@ -576,7 +583,7 @@ meta_back_dobind(
        for ( i = 0; i < mi->mi_ntargets; i++ ) {
                metatarget_t            *mt = mi->mi_targets[ i ];
                metasingleconn_t        *msc = &mc->mc_conns[ i ];
-               int                     rc, do_retry = 1;
+               int                     rc;
 
                /*
                 * Not a candidate
@@ -593,7 +600,10 @@ meta_back_dobind(
 
 retry_binding:;
                ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
-               if ( LDAP_BACK_CONN_ISBOUND( msc ) || LDAP_BACK_CONN_ISANON( msc ) ) {
+               if ( LDAP_BACK_CONN_ISBOUND( msc )
+                       || ( LDAP_BACK_CONN_ISANON( msc )
+                               && mt->mt_idassert_authmethod == LDAP_AUTH_NONE ) )
+               {
                        ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
                        ++bound;
                        continue;
@@ -608,7 +618,6 @@ retry_binding:;
                LDAP_BACK_CONN_BINDING_SET( msc );
                ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
 
-retry:;
                rc = meta_back_single_dobind( op, rs, &mc, i,
                        LDAP_BACK_DONTSEND, mt->mt_nretries, 1 );
                /*
@@ -625,10 +634,11 @@ retry:;
                        }
 
 
-                       if ( rc == LDAP_UNAVAILABLE && do_retry ) {
-                               do_retry = 0;
+                       if ( rc == LDAP_UNAVAILABLE ) {
+                               /* FIXME: meta_back_retry() already calls
+                                * meta_back_single_dobind() */
                                if ( meta_back_retry( op, rs, &mc, i, sendok ) ) {
-                                       goto retry;
+                                       goto retry_ok;
                                }
 
                                if ( mc != NULL ) {
@@ -668,7 +678,8 @@ retry:;
 
                        continue;
                } /* else */
-               
+
+retry_ok:;
                Debug( LDAP_DEBUG_TRACE,
                        "%s meta_back_dobind[%d]: "
                        "(%s)\n",
@@ -983,3 +994,303 @@ meta_back_op_result(
        return ( ( rerr == LDAP_SUCCESS ) ? 0 : -1 );
 }
 
+/*
+ * meta_back_proxy_authz_cred()
+ *
+ * prepares credentials & method for meta_back_proxy_authz_bind();
+ * or, if method is SASL, performs the SASL bind directly.
+ */
+int
+meta_back_proxy_authz_cred(
+       metaconn_t              *mc,
+       int                     candidate,
+       Operation               *op,
+       SlapReply               *rs,
+       ldap_back_send_t        sendok,
+       struct berval           *binddn,
+       struct berval           *bindcred,
+       int                     *method )
+{
+       metainfo_t              *mi = (metainfo_t *)op->o_bd->be_private;
+       metatarget_t            *mt = mi->mi_targets[ candidate ];
+       metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
+       struct berval           ndn;
+       int                     dobind = 0;
+
+       /* don't proxyAuthz if protocol is not LDAPv3 */
+       switch ( mt->mt_version ) {
+       case LDAP_VERSION3:
+               break;
+
+       case 0:
+               if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) {
+                       break;
+               }
+               /* fall thru */
+
+       default:
+               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+               if ( sendok & LDAP_BACK_SENDERR ) {
+                       send_ldap_result( op, rs );
+               }
+               LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
+               goto done;
+       }
+
+       if ( op->o_tag == LDAP_REQ_BIND ) {
+               ndn = op->o_req_ndn;
+
+       } else if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) {
+               ndn = op->o_conn->c_ndn;
+
+       } else {
+               ndn = op->o_ndn;
+       }
+
+       /*
+        * 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 authzTo directive of the "proxyauthzdn".
+        */
+       /*
+        * NOTE: current Proxy Authorization specification
+        * and implementation do not allow proxy authorization
+        * control to be provided with Bind requests
+        */
+       /*
+        * if no bind took place yet, but the connection is bound
+        * and the "proxyauthzdn" is set, then bind as 
+        * "proxyauthzdn" and explicitly add the proxyAuthz 
+        * control to every operation with the dn bound 
+        * to the connection as control value.
+        */
+
+       /* bind as proxyauthzdn only if no idassert mode
+        * is requested, or if the client's identity
+        * is authorized */
+       switch ( mt->mt_idassert_mode ) {
+       case LDAP_BACK_IDASSERT_LEGACY:
+               if ( !BER_BVISNULL( &ndn ) && !BER_BVISEMPTY( &ndn ) ) {
+                       if ( !BER_BVISNULL( &mt->mt_idassert_authcDN ) && !BER_BVISEMPTY( &mt->mt_idassert_authcDN ) )
+                       {
+                               *binddn = mt->mt_idassert_authcDN;
+                               *bindcred = mt->mt_idassert_passwd;
+                               dobind = 1;
+                       }
+               }
+               break;
+
+       default:
+               /* NOTE: rootdn can always idassert */
+               if ( BER_BVISNULL( &ndn ) && mt->mt_idassert_authz == NULL ) {
+                       if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
+                               rs->sr_err = LDAP_INAPPROPRIATE_AUTH;
+                               if ( sendok & LDAP_BACK_SENDERR ) {
+                                       send_ldap_result( op, rs );
+                               }
+                               LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
+
+                       } else {
+                               rs->sr_err = LDAP_SUCCESS;
+                               *binddn = slap_empty_bv;
+                               *bindcred = slap_empty_bv;
+                               break;
+                       }
+
+                       goto done;
+
+               } else if ( mt->mt_idassert_authz && !be_isroot( op ) ) {
+                       struct berval authcDN;
+
+                       if ( BER_BVISNULL( &ndn ) ) {
+                               authcDN = slap_empty_bv;
+
+                       } else {
+                               authcDN = ndn;
+                       }       
+                       rs->sr_err = slap_sasl_matches( op, mt->mt_idassert_authz,
+                                       &authcDN, &authcDN );
+                       if ( rs->sr_err != LDAP_SUCCESS ) {
+                               if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
+                                       if ( sendok & LDAP_BACK_SENDERR ) {
+                                               send_ldap_result( op, rs );
+                                       }
+                                       LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
+
+                               } else {
+                                       rs->sr_err = LDAP_SUCCESS;
+                                       *binddn = slap_empty_bv;
+                                       *bindcred = slap_empty_bv;
+                                       break;
+                               }
+
+                               goto done;
+                       }
+               }
+
+               *binddn = mt->mt_idassert_authcDN;
+               *bindcred = mt->mt_idassert_passwd;
+               dobind = 1;
+               break;
+       }
+
+       if ( dobind && mt->mt_idassert_authmethod == LDAP_AUTH_SASL ) {
+#ifdef HAVE_CYRUS_SASL
+               void            *defaults = NULL;
+               struct berval   authzID = BER_BVNULL;
+               int             freeauthz = 0;
+
+               /* if SASL supports native authz, prepare for it */
+               if ( ( !op->o_do_not_cache || !op->o_is_auth_check ) &&
+                               ( mt->mt_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) )
+               {
+                       switch ( mt->mt_idassert_mode ) {
+                       case LDAP_BACK_IDASSERT_OTHERID:
+                       case LDAP_BACK_IDASSERT_OTHERDN:
+                               authzID = mt->mt_idassert_authzID;
+                               break;
+
+                       case LDAP_BACK_IDASSERT_ANONYMOUS:
+                               BER_BVSTR( &authzID, "dn:" );
+                               break;
+
+                       case LDAP_BACK_IDASSERT_SELF:
+                               if ( BER_BVISNULL( &ndn ) ) {
+                                       /* connection is not authc'd, so don't idassert */
+                                       BER_BVSTR( &authzID, "dn:" );
+                                       break;
+                               }
+                               authzID.bv_len = STRLENOF( "dn:" ) + ndn.bv_len;
+                               authzID.bv_val = slap_sl_malloc( authzID.bv_len + 1, op->o_tmpmemctx );
+                               AC_MEMCPY( authzID.bv_val, "dn:", STRLENOF( "dn:" ) );
+                               AC_MEMCPY( authzID.bv_val + STRLENOF( "dn:" ),
+                                               ndn.bv_val, ndn.bv_len + 1 );
+                               freeauthz = 1;
+                               break;
+
+                       default:
+                               break;
+                       }
+               }
+
+               if ( mt->mt_idassert_secprops != NULL ) {
+                       rs->sr_err = ldap_set_option( msc->msc_ld,
+                               LDAP_OPT_X_SASL_SECPROPS,
+                               (void *)mt->mt_idassert_secprops );
+
+                       if ( rs->sr_err != LDAP_OPT_SUCCESS ) {
+                               rs->sr_err = LDAP_OTHER;
+                               if ( sendok & LDAP_BACK_SENDERR ) {
+                                       send_ldap_result( op, rs );
+                               }
+                               LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
+                               goto done;
+                       }
+               }
+
+               defaults = lutil_sasl_defaults( msc->msc_ld,
+                               mt->mt_idassert_sasl_mech.bv_val,
+                               mt->mt_idassert_sasl_realm.bv_val,
+                               mt->mt_idassert_authcID.bv_val,
+                               mt->mt_idassert_passwd.bv_val,
+                               authzID.bv_val );
+
+               rs->sr_err = ldap_sasl_interactive_bind_s( msc->msc_ld, binddn->bv_val,
+                               mt->mt_idassert_sasl_mech.bv_val, NULL, NULL,
+                               LDAP_SASL_QUIET, lutil_sasl_interact,
+                               defaults );
+
+               rs->sr_err = slap_map_api2result( rs );
+               if ( rs->sr_err != LDAP_SUCCESS ) {
+                       LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
+                       if ( sendok & LDAP_BACK_SENDERR ) {
+                               send_ldap_result( op, rs );
+                       }
+
+               } else {
+                       LDAP_BACK_CONN_ISBOUND_SET( msc );
+               }
+
+               lutil_sasl_freedefs( defaults );
+               if ( freeauthz ) {
+                       slap_sl_free( authzID.bv_val, op->o_tmpmemctx );
+               }
+
+               goto done;
+#endif /* HAVE_CYRUS_SASL */
+       }
+
+       *method = mt->mt_idassert_authmethod;
+       switch ( mt->mt_idassert_authmethod ) {
+       case LDAP_AUTH_NONE:
+               BER_BVSTR( binddn, "" );
+               BER_BVSTR( bindcred, "" );
+               /* fallthru */
+
+       case LDAP_AUTH_SIMPLE:
+               break;
+
+       default:
+               /* unsupported! */
+               LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
+               rs->sr_err = LDAP_AUTH_METHOD_NOT_SUPPORTED;
+               if ( sendok & LDAP_BACK_SENDERR ) {
+                       send_ldap_result( op, rs );
+               }
+               break;
+       }
+
+done:;
+       return rs->sr_err;
+}
+
+static int
+meta_back_proxy_authz_bind( metaconn_t *mc, int candidate, Operation *op, SlapReply *rs, ldap_back_send_t sendok )
+{
+       metainfo_t              *mi = (metainfo_t *)op->o_bd->be_private;
+       metatarget_t            *mt = mi->mi_targets[ candidate ];
+       metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
+       struct berval           binddn = BER_BVC( "" ),
+                               cred = BER_BVC( "" );
+       int                     method = LDAP_AUTH_NONE,
+                               rc;
+
+       rc = meta_back_proxy_authz_cred( mc, candidate, op, rs, sendok, &binddn, &cred, &method );
+       if ( rc == LDAP_SUCCESS && !LDAP_BACK_CONN_ISBOUND( msc ) ) {
+               int     msgid;
+
+               switch ( method ) {
+               case LDAP_AUTH_NONE:
+               case LDAP_AUTH_SIMPLE:
+                       rs->sr_err = ldap_sasl_bind( msc->msc_ld,
+                                       binddn.bv_val, LDAP_SASL_SIMPLE,
+                                       &cred, NULL, NULL, &msgid );
+                       rc = meta_back_bind_op_result( op, rs, mc, candidate, msgid, sendok );
+                       if ( rc == LDAP_SUCCESS ) {
+                               /* set rebind stuff in case of successful proxyAuthz bind,
+                                * so that referral chasing is attempted using the right
+                                * identity */
+                               LDAP_BACK_CONN_ISBOUND_SET( msc );
+                               ber_bvreplace( &msc->msc_bound_ndn, &binddn );
+
+                               if ( LDAP_BACK_SAVECRED( mi ) ) {
+                                       if ( !BER_BVISNULL( &msc->msc_cred ) ) {
+                                               memset( msc->msc_cred.bv_val, 0,
+                                                       msc->msc_cred.bv_len );
+                                       }
+                                       ber_bvreplace( &msc->msc_cred, &cred );
+                                       ldap_set_rebind_proc( msc->msc_ld, mt->mt_rebind_f, msc );
+                               }
+                       }
+                       break;
+
+               default:
+                       assert( 0 );
+                       break;
+               }
+       }
+
+       return LDAP_BACK_CONN_ISBOUND( msc );
+}
index a3c3732c92631ecb71ee0bfbc0dee971f04cfdc2..64b56cc8ada7baad0059492bb2532136c8388d56 100644 (file)
@@ -214,9 +214,7 @@ meta_clear_candidates( Operation *op, metaconn_t *mc )
        int             c;
 
        for ( c = 0; c < mi->mi_ntargets; c++ ) {
-               if ( mc->mc_conns[ c ].msc_ld != NULL ) {
-                       meta_clear_one_candidate( &mc->mc_conns[ c ] );
-               }
+               meta_clear_one_candidate( &mc->mc_conns[ c ] );
        }
 
        return 0;
index 75272d674422edcbf83bca217206f43c565bd6d3..7b9ab0243034f68a87dff31c36fbf5db2960077a 100644 (file)
@@ -74,6 +74,8 @@ meta_back_compare( Operation *op, SlapReply *rs )
                struct berval           mdn = BER_BVNULL;
                struct berval           mapped_attr = op->orc_ava->aa_desc->ad_cname;
                struct berval           mapped_value = op->orc_ava->aa_value;
+               metatarget_t            *mt = mi->mi_targets[ i ];
+               LDAPControl             **ctrls = NULL;
 
                if ( ! META_IS_CANDIDATE( &candidates[ i ] ) ) {
                        msgid[ i ] = -1;
@@ -83,7 +85,7 @@ meta_back_compare( Operation *op, SlapReply *rs )
                /*
                 * Rewrite the compare dn, if needed
                 */
-               dc.target = mi->mi_targets[ i ];
+               dc.target = mt;
 
                switch ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
                case LDAP_UNWILLING_TO_PERFORM:
@@ -98,7 +100,7 @@ meta_back_compare( Operation *op, SlapReply *rs )
                 * if attr is objectClass, try to remap the value
                 */
                if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass ) {
-                       ldap_back_map( &mi->mi_targets[ i ]->mt_rwmap.rwm_oc,
+                       ldap_back_map( &mt->mt_rwmap.rwm_oc,
                                        &op->orc_ava->aa_value,
                                        &mapped_value, BACKLDAP_MAP );
 
@@ -109,7 +111,7 @@ meta_back_compare( Operation *op, SlapReply *rs )
                 * else try to remap the attribute
                 */
                } else {
-                       ldap_back_map( &mi->mi_targets[ i ]->mt_rwmap.rwm_at,
+                       ldap_back_map( &mt->mt_rwmap.rwm_at,
                                &op->orc_ava->aa_desc->ad_cname,
                                &mapped_attr, BACKLDAP_MAP );
                        if ( BER_BVISNULL( &mapped_attr ) || mapped_attr.bv_val[0] == '\0' ) {
@@ -132,6 +134,13 @@ meta_back_compare( Operation *op, SlapReply *rs )
                        }
                }
                
+               ctrls = op->o_ctrls;
+               if ( ldap_back_proxy_authz_ctrl( &mc->mc_conns[ i ].msc_bound_ndn,
+                       mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) != LDAP_SUCCESS )
+               {
+                       continue;
+               }
+
                /*
                 * the compare op is spawned across the targets and the first
                 * that returns determines the result; a constraint on unicity
@@ -139,7 +148,9 @@ meta_back_compare( Operation *op, SlapReply *rs )
                 */
                 rc = ldap_compare_ext( mc->mc_conns[ i ].msc_ld, mdn.bv_val,
                                mapped_attr.bv_val, &mapped_value,
-                               op->o_ctrls, NULL, &msgid[ i ] );
+                               ctrls, NULL, &msgid[ i ] );
+
+               (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
 
                if ( mdn.bv_val != op->o_req_dn.bv_val ) {
                        free( mdn.bv_val );
@@ -208,6 +219,7 @@ meta_back_compare( Operation *op, SlapReply *rs )
                                        goto finish;
                                }
 
+                               /* FIXME: matched? referrals? response controls? */
                                rc = ldap_parse_result( msc->msc_ld, res,
                                                &rs->sr_err,
                                                NULL, NULL, NULL, NULL, 1 );
index 555d51b7e63ffaeb59cf298b0abe1dd719f87939..e5230859e8a5ec33d08dee753a84f2312ba468c3 100644 (file)
@@ -781,10 +781,12 @@ meta_back_db_config(
                }
 
        /* bind-defer? */
-       } else if ( strcasecmp( argv[ 0 ], "pseudoroot-bind-defer" ) == 0 ) {
+       } else if ( strcasecmp( argv[ 0 ], "pseudoroot-bind-defer" ) == 0
+               || strcasecmp( argv[ 0 ], "root-bind-defer" ) == 0 )
+       {
                if ( argc != 2 ) {
                        Debug( LDAP_DEBUG_ANY,
-       "%s: line %d: \"pseudoroot-bind-defer {FALSE|true}\" takes 1 argument\n",
+       "%s: line %d: \"[pseudo]root-bind-defer {FALSE|true}\" takes 1 argument\n",
                                fname, lineno, 0 );
                        return( 1 );
                }
@@ -800,7 +802,7 @@ meta_back_db_config(
 
                default:
                        Debug( LDAP_DEBUG_ANY,
-       "%s: line %d: \"pseudoroot-bind-defer {FALSE|true}\": invalid arg \"%s\".\n",
+       "%s: line %d: \"[pseudo]root-bind-defer {FALSE|true}\": invalid arg \"%s\".\n",
                                fname, lineno, argv[ 1 ] );
                        return 1;
                }
@@ -956,15 +958,74 @@ meta_back_db_config(
                        return 1;
                }
 
-               dn.bv_val = argv[ 1 ];
-               dn.bv_len = strlen( argv[ 1 ] );
-               if ( dnNormalize( 0, NULL, NULL, &dn,
-                       &mi->mi_targets[ i ]->mt_pseudorootdn, NULL ) != LDAP_SUCCESS )
+               /*
+                * exact replacement:
+                *
+
+idassert-bind  bindmethod=simple
+               binddn=<pseudorootdn>
+               credentials=<pseudorootpw>
+               mode=none
+               flags=non-prescriptive
+idassert-authzFrom     "dn:<rootdn>"
+
+                * so that only when authc'd as <rootdn> the proxying occurs
+                * rebinding as the <pseudorootdn> without proxyAuthz.
+                */
+
+               Debug( LDAP_DEBUG_ANY,
+                       "%s: line %d: \"pseudorootdn\", \"pseudorootpw\" are no longer supported; "
+                       "use \"idassert-bind\" and \"idassert-authzFrom\" instead.\n",
+                       fname, lineno, 0 );
+
                {
-                       Debug( LDAP_DEBUG_ANY, "%s: line %d: "
-                                       "pseudoroot DN '%s' is invalid\n",
-                                       fname, lineno, argv[ 1 ] );
-                       return( 1 );
+                       char    binddn[ SLAP_TEXT_BUFLEN ];
+                       char    *cargv[] = {
+                               "idassert-bind",
+                               "bindmethod=simple",
+                               NULL,
+                               "mode=none",
+                               "flags=non-prescriptive",
+                               NULL
+                       };
+                       int     cargc = 5;
+                       int     rc;
+
+                       if ( BER_BVISNULL( &be->be_rootndn ) ) {
+                               Debug( LDAP_DEBUG_ANY, "%s: line %d: \"pseudorootpw\": \"rootdn\" must be defined first.\n",
+                                       fname, lineno, 0 );
+                               return 1;
+                       }
+
+                       if ( snprintf( binddn, sizeof( binddn ), "binddn=%s", argv[ 1 ] ) >= sizeof( binddn ) ) {
+                               Debug( LDAP_DEBUG_ANY, "%s: line %d: \"pseudorootdn\" too long.\n",
+                                       fname, lineno, 0 );
+                               return 1;
+                       }
+                       cargv[ 2 ] = binddn;
+
+                       rc = slap_idassert_parse_cf( fname, lineno, cargc, cargv, &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert );
+                       if ( rc == 0 ) {
+                               struct berval   bv;
+
+                               if ( mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert_authz != NULL ) {
+                                       Debug( LDAP_DEBUG_ANY, "%s: line %d: \"idassert-authzFrom\" already defined (discarded).\n",
+                                               fname, lineno, 0 );
+                                       ber_bvarray_free( mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert_authz );
+                                       mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert_authz = NULL;
+                               }
+
+                               assert( !BER_BVISNULL( &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert_authcDN ) );
+
+                               bv.bv_len = STRLENOF( "dn:" ) + be->be_rootndn.bv_len;
+                               bv.bv_val = ber_memalloc( bv.bv_len + 1 );
+                               AC_MEMCPY( bv.bv_val, "dn:", STRLENOF( "dn:" ) );
+                               AC_MEMCPY( &bv.bv_val[ STRLENOF( "dn:" ) ], be->be_rootndn.bv_val, be->be_rootndn.bv_len + 1 );
+
+                               ber_bvarray_add( &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert_authz, &bv );
+                       }
+
+                       return rc;
                }
 
        /* password to use as pseudo-root */
@@ -984,7 +1045,65 @@ meta_back_db_config(
                            fname, lineno, 0 );
                        return 1;
                }
-               ber_str2bv( argv[ 1 ], 0L, 1, &mi->mi_targets[ i ]->mt_pseudorootpw );
+
+               Debug( LDAP_DEBUG_ANY,
+                       "%s: line %d: \"pseudorootdn\", \"pseudorootpw\" are no longer supported; "
+                       "use \"idassert-bind\" and \"idassert-authzFrom\" instead.\n",
+                       fname, lineno, 0 );
+
+               if ( BER_BVISNULL( &mi->mi_targets[ i ]->mt_idassert_authcDN ) ) {
+                       Debug( LDAP_DEBUG_ANY, "%s: line %d: \"pseudorootpw\": \"pseudorootdn\" must be defined first.\n",
+                               fname, lineno, 0 );
+                       return 1;
+               }
+
+               if ( !BER_BVISNULL( &mi->mi_targets[ i ]->mt_idassert_passwd ) ) {
+                       memset( mi->mi_targets[ i ]->mt_idassert_passwd.bv_val, 0,
+                               mi->mi_targets[ i ]->mt_idassert_passwd.bv_len );
+                       ber_memfree( mi->mi_targets[ i ]->mt_idassert_passwd.bv_val );
+               }
+               ber_str2bv( argv[ 1 ], 0, 1, &mi->mi_targets[ i ]->mt_idassert_passwd );
+
+       /* idassert-bind */
+       } else if ( strcasecmp( argv[ 0 ], "idassert-bind" ) == 0 ) {
+               if ( mi->mi_ntargets == 0 ) {
+                       Debug( LDAP_DEBUG_ANY,
+                               "%s: line %d: \"idassert-bind\" "
+                               "must appear inside a target specification.\n",
+                               fname, lineno, 0 );
+                       return 1;
+               }
+
+               return slap_idassert_parse_cf( fname, lineno, argc, argv, &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert );
+
+       /* idassert-authzFrom */
+       } else if ( strcasecmp( argv[ 0 ], "idassert-authzFrom" ) == 0 ) {
+               if ( mi->mi_ntargets == 0 ) {
+                       Debug( LDAP_DEBUG_ANY,
+                               "%s: line %d: \"idassert-bind\" "
+                               "must appear inside a target specification.\n",
+                               fname, lineno, 0 );
+                       return 1;
+               }
+
+               switch ( argc ) {
+               case 2:
+                       break;
+
+               case 1:
+                       Debug( LDAP_DEBUG_ANY,
+                               "%s: line %d: missing <id> in \"idassert-authzFrom <id>\".\n",
+                               fname, lineno, 0 );
+                       return 1;
+
+               default:
+                       Debug( LDAP_DEBUG_ANY,
+                               "%s: line %d: extra cruft after <id> in \"idassert-authzFrom <id>\".\n",
+                               fname, lineno, 0 );
+                       return 1;
+               }
+
+               return slap_idassert_authzfrom_parse_cf( fname, lineno, argv[ 1 ], &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert );
 
        /* quarantine */
        } else if ( strcasecmp( argv[ 0 ], "quarantine" ) == 0 ) {
index 3be9cacb4047c967c9662857a9ec3c294026b6c9..82cb41b403ef687f0dc5a1ac02678266380c3524 100644 (file)
@@ -368,6 +368,7 @@ retry:;
                                if ( rs->sr_err == LDAP_SUCCESS ) {
                                        int             err;
 
+                                       /* FIXME: matched? referrals? response controls? */
                                        rs->sr_err = ldap_parse_result( msc->msc_ld, res,
                                                &err, NULL, NULL, NULL, NULL, 1 );
                                        res = NULL;
@@ -443,21 +444,28 @@ retry:;
         */
 
        if ( ispriv ) {
-               if ( !BER_BVISNULL( &mt->mt_pseudorootdn ) ) {
-                       ber_dupbv( &msc->msc_bound_ndn, &mt->mt_pseudorootdn );
-                       if ( !BER_BVISNULL( &mt->mt_pseudorootpw ) ) {
-                               ber_dupbv( &msc->msc_cred, &mt->mt_pseudorootpw );
+               if ( !BER_BVISNULL( &mt->mt_idassert_authcDN ) ) {
+                       ber_bvreplace( &msc->msc_bound_ndn, &mt->mt_idassert_authcDN );
+                       if ( !BER_BVISNULL( &mt->mt_idassert_passwd ) ) {
+                               ber_bvreplace( &msc->msc_cred, &mt->mt_idassert_passwd );
                        }
 
                } else {
-                       ber_str2bv( "", 0, 1, &msc->msc_bound_ndn );
+                       ber_bvreplace( &msc->msc_bound_ndn, &slap_empty_bv );
                }
 
                LDAP_BACK_CONN_ISPRIV_SET( msc );
 
        } else {
-               BER_BVZERO( &msc->msc_cred );
-               BER_BVZERO( &msc->msc_bound_ndn );
+               if ( !BER_BVISNULL( &msc->msc_cred ) ) {
+                       memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
+                       ber_memfree_x( msc->msc_cred.bv_val, NULL );
+                       BER_BVZERO( &msc->msc_cred );
+               }
+               if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
+                       ber_memfree_x( msc->msc_bound_ndn.bv_val, NULL );
+                       BER_BVZERO( &msc->msc_bound_ndn );
+               }
                if ( !BER_BVISEMPTY( &op->o_ndn )
                        && SLAP_IS_AUTHZ_BACKEND( op )
                        && isauthz )
@@ -484,7 +492,7 @@ retry:;
                        }
 
                } else {
-                       ber_str2bv( "", 0, 1, &msc->msc_bound_ndn );
+                       ber_dupbv( &msc->msc_bound_ndn, &slap_empty_bv );
                }
        }
 
index bb29bcb177156f764523dfbd91c701d2a703d003..dd105b0756c1ae1e77617b1f5e0e6acf842dfb5a 100644 (file)
@@ -35,6 +35,7 @@ int
 meta_back_delete( Operation *op, SlapReply *rs )
 {
        metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
+       metatarget_t    *mt;
        metaconn_t      *mc = NULL;
        int             candidate = -1;
        struct berval   mdn = BER_BVNULL;
@@ -42,6 +43,7 @@ meta_back_delete( Operation *op, SlapReply *rs )
        int             msgid;
        int             do_retry = 1;
        int             maperr = 1;
+       LDAPControl     **ctrls = NULL;
 
        mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
        if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
@@ -53,7 +55,8 @@ meta_back_delete( Operation *op, SlapReply *rs )
        /*
         * Rewrite the compare dn, if needed
         */
-       dc.target = mi->mi_targets[ candidate ];
+       mt = mi->mi_targets[ candidate ];
+       dc.target = mt;
        dc.conn = op->o_conn;
        dc.rs = rs;
        dc.ctx = "deleteDN";
@@ -63,9 +66,17 @@ meta_back_delete( Operation *op, SlapReply *rs )
                goto done;
        }
 
+       ctrls = op->o_ctrls;
+       if ( ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn,
+               mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) != LDAP_SUCCESS )
+       {
+               maperr = 0;
+               goto sendres;
+       }
+
 retry:;
        rs->sr_err = ldap_delete_ext( mc->mc_conns[ candidate ].msc_ld,
-                       mdn.bv_val, op->o_ctrls, NULL, &msgid );
+                       mdn.bv_val, ctrls, NULL, &msgid );
        if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
                do_retry = 0;
                if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
@@ -78,8 +89,8 @@ retry:;
                LDAPMessage     *res = NULL;
                int             rc;
 
-               if ( mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_DELETE ] != 0 ) {
-                       tv.tv_sec = mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_DELETE ];
+               if ( mt->mt_timeout[ LDAP_BACK_OP_DELETE ] != 0 ) {
+                       tv.tv_sec = mt->mt_timeout[ LDAP_BACK_OP_DELETE ];
                        tv.tv_usec = 0;
                        tvp = &tv;
                }
@@ -100,6 +111,7 @@ retry:;
                        break;
 
                case LDAP_RES_DELETE:
+                       /* FIXME: matched? referrals? response controls? */
                        rc = ldap_parse_result( mc->mc_conns[ candidate ].msc_ld,
                                res, &rs->sr_err, NULL, NULL, NULL, NULL, 1 );
                        if ( rc != LDAP_SUCCESS ) {
@@ -114,13 +126,16 @@ retry:;
                }
        }
 
+sendres:;
+       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+
        if ( maperr ) {
                rs->sr_err = meta_back_op_result( mc, op, rs, candidate );
 
        } else {
                send_ldap_result( op, rs );
 
-               if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ candidate ] ) ) {
+               if ( META_BACK_TGT_QUARANTINE( mt ) ) {
                        meta_back_quarantine( op, rs, candidate );
                }
        }
index c06fbd277bf8a51613fa95b024294d768d24a004..7fee4d1c3feb00f74efa5c7d8d65a91c9f64dfca 100644 (file)
@@ -230,11 +230,26 @@ target_free(
        if ( !BER_BVISNULL( &mt->mt_bindpw ) ) {
                free( mt->mt_bindpw.bv_val );
        }
-       if ( !BER_BVISNULL( &mt->mt_pseudorootdn ) ) {
-               free( mt->mt_pseudorootdn.bv_val );
+       if ( !BER_BVISNULL( &mt->mt_idassert_authcID ) ) {
+               ch_free( mt->mt_idassert_authcID.bv_val );
        }
-       if ( !BER_BVISNULL( &mt->mt_pseudorootpw ) ) {
-               free( mt->mt_pseudorootpw.bv_val );
+       if ( !BER_BVISNULL( &mt->mt_idassert_authcDN ) ) {
+               ch_free( mt->mt_idassert_authcDN.bv_val );
+       }
+       if ( !BER_BVISNULL( &mt->mt_idassert_passwd ) ) {
+               ch_free( mt->mt_idassert_passwd.bv_val );
+       }
+       if ( !BER_BVISNULL( &mt->mt_idassert_authzID ) ) {
+               ch_free( mt->mt_idassert_authzID.bv_val );
+       }
+       if ( !BER_BVISNULL( &mt->mt_idassert_sasl_mech ) ) {
+               ch_free( mt->mt_idassert_sasl_mech.bv_val );
+       }
+       if ( !BER_BVISNULL( &mt->mt_idassert_sasl_realm ) ) {
+               ch_free( mt->mt_idassert_sasl_realm.bv_val );
+       }
+       if ( mt->mt_idassert_authz != NULL ) {
+               ber_bvarray_free( mt->mt_idassert_authz );
        }
        if ( mt->mt_rwmap.rwm_rw ) {
                rewrite_info_delete( &mt->mt_rwmap.rwm_rw );
index 00c1d629770063a81e1b2ba59fa9063db08067e4..61796fe2d29f9addec99747e461568e8a3b1e193 100644 (file)
@@ -35,6 +35,7 @@ int
 meta_back_modify( Operation *op, SlapReply *rs )
 {
        metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
+       metatarget_t    *mt;
        metaconn_t      *mc;
        int             rc = 0;
        int             maperr = 1;
@@ -48,6 +49,7 @@ meta_back_modify( Operation *op, SlapReply *rs )
        dncookie        dc;
        int             msgid;
        int             do_retry = 1;
+       LDAPControl     **ctrls = NULL;
 
        mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
        if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
@@ -59,7 +61,8 @@ meta_back_modify( Operation *op, SlapReply *rs )
        /*
         * Rewrite the modify dn, if needed
         */
-       dc.target = mi->mi_targets[ candidate ];
+       mt = mi->mi_targets[ candidate ];
+       dc.target = mt;
        dc.conn = op->o_conn;
        dc.rs = rs;
        dc.ctx = "modifyDN";
@@ -102,7 +105,7 @@ meta_back_modify( Operation *op, SlapReply *rs )
                        mapped = ml->sml_desc->ad_cname;
 
                } else {
-                       ldap_back_map( &mi->mi_targets[ candidate ]->mt_rwmap.rwm_at,
+                       ldap_back_map( &mt->mt_rwmap.rwm_at,
                                        &ml->sml_desc->ad_cname, &mapped,
                                        BACKLDAP_MAP );
                        if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
@@ -129,11 +132,11 @@ meta_back_modify( Operation *op, SlapReply *rs )
                                for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); ) {
                                        struct ldapmapping      *mapping;
 
-                                       ldap_back_mapping( &mi->mi_targets[ candidate ]->mt_rwmap.rwm_oc,
+                                       ldap_back_mapping( &mt->mt_rwmap.rwm_oc,
                                                        &ml->sml_values[ j ], &mapping, BACKLDAP_MAP );
 
                                        if ( mapping == NULL ) {
-                                               if ( mi->mi_targets[ candidate ]->mt_rwmap.rwm_oc.drop_missing ) {
+                                               if ( mt->mt_rwmap.rwm_oc.drop_missing ) {
                                                        continue;
                                                }
                                                mods[ i ].mod_bvalues[ j ] = &ml->sml_values[ j ];
@@ -174,9 +177,17 @@ meta_back_modify( Operation *op, SlapReply *rs )
        }
        modv[ i ] = 0;
 
+       ctrls = op->o_ctrls;
+       rc = ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn,
+               mt->mt_version, &mt->mt_idassert, op, rs, &ctrls );
+       if ( rc != LDAP_SUCCESS ) {
+               maperr = 0;
+               goto cleanup;
+       }
+
 retry:;
        rs->sr_err = ldap_modify_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
-                       modv, op->o_ctrls, NULL, &msgid );
+                       modv, ctrls, NULL, &msgid );
        if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
                do_retry = 0;
                if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
@@ -188,8 +199,8 @@ retry:;
                struct timeval  tv, *tvp = NULL;
                LDAPMessage     *res = NULL;
 
-               if ( mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_MODIFY ] != 0 ) {
-                       tv.tv_sec = mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_MODIFY ];
+               if ( mt->mt_timeout[ LDAP_BACK_OP_MODIFY ] != 0 ) {
+                       tv.tv_sec = mt->mt_timeout[ LDAP_BACK_OP_MODIFY ];
                        tv.tv_usec = 0;
                        tvp = &tv;
                }
@@ -210,6 +221,7 @@ retry:;
                        break;
 
                case LDAP_RES_MODIFY:
+                       /* FIXME: matched? referrals? response controls? */
                        rc = ldap_parse_result( mc->mc_conns[ candidate ].msc_ld,
                                res, &rs->sr_err, NULL, NULL, NULL, NULL, 1 );
                        if ( rc != LDAP_SUCCESS ) {
@@ -226,13 +238,15 @@ retry:;
        }
 
 cleanup:;
+       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+
        if ( maperr ) {
                rc = meta_back_op_result( mc, op, rs, candidate );
 
        } else {
                send_ldap_result( op, rs );
 
-               if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ candidate ] ) ) {
+               if ( META_BACK_TGT_QUARANTINE( mt ) ) {
                        meta_back_quarantine( op, rs, candidate );
                }
        }
index 16a3f1320de88433485cf8eb51a15a0c86bb3ec3..d9db0df7717c11df395f14fd9a53a65200584ded 100644 (file)
@@ -35,6 +35,7 @@ int
 meta_back_modrdn( Operation *op, SlapReply *rs )
 {
        metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
+       metatarget_t    *mt;
        metaconn_t      *mc;
        int             candidate = -1;
        struct berval   mdn = BER_BVNULL,
@@ -43,6 +44,7 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
        int             msgid;
        int             do_retry = 1;
        int             maperr = 1;
+       LDAPControl     **ctrls = NULL;
 
        mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
        if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
@@ -51,6 +53,8 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
 
        assert( mc->mc_conns[ candidate ].msc_ld != NULL );
 
+       mt = mi->mi_targets[ candidate ];
+       dc.target = mt;
        dc.conn = op->o_conn;
        dc.rs = rs;
 
@@ -76,7 +80,7 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
                 */
 
                /* needs LDAPv3 */
-               switch ( mi->mi_targets[ candidate ]->mt_version ) {
+               switch ( mt->mt_version ) {
                case LDAP_VERSION3:
                        break;
 
@@ -97,7 +101,6 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
                /*
                 * Rewrite the new superior, if defined and required
                 */
-               dc.target = mi->mi_targets[ candidate ];
                dc.ctx = "newSuperiorDN";
                if ( ldap_back_dn_massage( &dc, op->orr_newSup, &mnewSuperior ) ) {
                        rs->sr_err = LDAP_OTHER;
@@ -109,7 +112,6 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
        /*
         * Rewrite the modrdn dn, if required
         */
-       dc.target = mi->mi_targets[ candidate ];
        dc.ctx = "modrDN";
        if ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
                rs->sr_err = LDAP_OTHER;
@@ -117,11 +119,19 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
                goto cleanup;
        }
 
+       ctrls = op->o_ctrls;
+       if ( ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn,
+               mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) != LDAP_SUCCESS )
+       {
+               maperr = 0;
+               goto cleanup;
+       }
+
 retry:;
        rs->sr_err = ldap_rename( mc->mc_conns[ candidate ].msc_ld,
                        mdn.bv_val, op->orr_newrdn.bv_val,
                        mnewSuperior.bv_val, op->orr_deleteoldrdn,
-                       op->o_ctrls, NULL, &msgid );
+                       ctrls, NULL, &msgid );
        if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
                do_retry = 0;
                if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
@@ -134,8 +144,8 @@ retry:;
                LDAPMessage     *res = NULL;
                int             rc;
 
-               if ( mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_MODRDN ] != 0 ) {
-                       tv.tv_sec = mi->mi_targets[ candidate ]->mt_timeout[ LDAP_BACK_OP_MODRDN ];
+               if ( mt->mt_timeout[ LDAP_BACK_OP_MODRDN ] != 0 ) {
+                       tv.tv_sec = mt->mt_timeout[ LDAP_BACK_OP_MODRDN ];
                        tv.tv_usec = 0;
                        tvp = &tv;
                }
@@ -155,6 +165,7 @@ retry:;
                        break;
 
                case LDAP_RES_RENAME:
+                       /* FIXME: matched? referrals? response controls? */
                        rc = ldap_parse_result( mc->mc_conns[ candidate ].msc_ld,
                                res, &rs->sr_err, NULL, NULL, NULL, NULL, 1 );
                        if ( rc != LDAP_SUCCESS ) {
@@ -170,13 +181,15 @@ retry:;
        }
 
 cleanup:;
+       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+
        if ( maperr ) {
                meta_back_op_result( mc, op, rs, candidate );
 
        } else {
                send_ldap_result( op, rs );
 
-               if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ candidate ] ) ) {
+               if ( META_BACK_TGT_QUARANTINE( mt ) ) {
                        meta_back_quarantine( op, rs, candidate );
                }
        }
index 17493f2391e2ea8f3940287f55b99d2324aa3246..554d921f113349e5caef3ebcea36e67a2c3de86e 100644 (file)
@@ -76,11 +76,11 @@ meta_search_dobind_init(
        metatarget_t            *mt = mi->mi_targets[ candidate ];
        metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
 
-       char                    *binddn = "";
-       struct berval           cred = BER_BVC( "" );
+       struct berval           binddn = BER_BVC( "" ),
+                               cred = BER_BVC( "" );
+       int                     method;
 
        int                     rc;
-       int                     nretries = 1;
 
        meta_search_candidate_t retcode;
 
@@ -108,42 +108,61 @@ meta_search_dobind_init(
        LDAP_BACK_CONN_BINDING_SET( msc );
        ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
 
-       if ( be_isroot( op ) && !BER_BVISNULL( &mt->mt_pseudorootdn ) ) {
-               binddn = mt->mt_pseudorootdn.bv_val;
-               cred = mt->mt_pseudorootpw;
-       }
+       /* NOTE: this obsoletes pseudorootdn */
+       if ( op->o_conn != NULL &&
+               !op->o_do_not_cache &&
+               ( BER_BVISNULL( &msc->msc_bound_ndn ) ||
+                       BER_BVISEMPTY( &msc->msc_bound_ndn ) ||
+                       ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
+       {
+               rc = meta_back_proxy_authz_cred( mc, candidate, op, rs, LDAP_BACK_DONTSEND, &binddn, &cred, &method );
+               if ( rc != LDAP_SUCCESS ) {
+                       goto down;
+               }
 
-       /*
-        * Otherwise an anonymous bind is performed
-        * (note: if the target was already bound, the anonymous
-        * bind clears the previous bind).
-        */
-       if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
-               ber_memfree( msc->msc_bound_ndn.bv_val );
-               BER_BVZERO( &msc->msc_bound_ndn );
-       }
-               
-       if ( LDAP_BACK_SAVECRED( mi ) && !BER_BVISNULL( &msc->msc_cred ) ) {
-               /* destroy sensitive data */
-               memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
-               ber_memfree( msc->msc_cred.bv_val );
-               BER_BVZERO( &msc->msc_cred );
+               /* NOTE: we copy things here, even if bind didn't succeed yet,
+                * because the connection is not shared until bind is over */
+               if ( !BER_BVISNULL( &binddn ) ) {
+                       ber_bvreplace( &msc->msc_bound_ndn, &binddn );
+                       if ( LDAP_BACK_SAVECRED( mi ) && !BER_BVISNULL( &cred ) ) {
+                               ber_dupbv( &msc->msc_cred, &cred );
+                       }
+               }
+
+               if ( LDAP_BACK_CONN_ISBOUND( msc ) ) {
+                       /* idassert ws configured with SASL bind */
+                       ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+                       LDAP_BACK_CONN_BINDING_CLEAR( msc );
+                       ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+                       return META_SEARCH_CANDIDATE;
+               }
+
+               /* paranoid */
+               switch ( method ) {
+               case LDAP_AUTH_NONE:
+               case LDAP_AUTH_SIMPLE:
+                       /* do a simple bind with binddn, cred */
+                       break;
+
+               default:
+                       assert( 0 );
+                       break;
+               }
        }
 
-retry:;
        assert( msc->msc_ld != NULL );
 
-       rc = ldap_sasl_bind( msc->msc_ld, binddn, LDAP_SASL_SIMPLE, &cred,
+       rc = ldap_sasl_bind( msc->msc_ld, binddn.bv_val, LDAP_SASL_SIMPLE, &cred,
                        NULL, NULL, &candidates[ candidate ].sr_msgid );
        switch ( rc ) {
        case LDAP_SUCCESS:
                META_BINDING_SET( &candidates[ candidate ] );
                return META_SEARCH_BINDING;
 
+down:;
        case LDAP_SERVER_DOWN:
-               if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
-                       nretries = 0;
-                       goto retry;
+               if ( meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
+                       return META_SEARCH_CANDIDATE;
                }
 
                if ( *mcp == NULL ) {
@@ -195,12 +214,14 @@ meta_search_dobind_result(
 
        assert( msc->msc_ld != NULL );
 
+       /* FIXME: matched? referrals? response controls? */
        rc = ldap_parse_result( msc->msc_ld, res,
                &candidates[ candidate ].sr_err,
                NULL, NULL, NULL, NULL, 1 );
-       if ( rc == LDAP_SUCCESS ) {
-               rc = slap_map_api2result( &candidates[ candidate ] );
+       if ( rc != LDAP_SUCCESS ) {
+               candidates[ candidate ].sr_err = rc;
        }
+       rc = slap_map_api2result( &candidates[ candidate ] );
 
        ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
        LDAP_BACK_CONN_BINDING_CLEAR( msc );
@@ -248,6 +269,7 @@ meta_back_search_start(
        meta_search_candidate_t retcode;
        struct timeval          tv, *tvp = NULL;
        int                     nretries = 1;
+       LDAPControl             **ctrls = NULL;
 
        /* this should not happen; just in case... */
        if ( msc->msc_ld == NULL ) {
@@ -402,6 +424,15 @@ meta_back_search_start(
                tvp = &tv;
        }
 
+       ctrls = op->o_ctrls;
+       if ( ldap_back_proxy_authz_ctrl( &msc->msc_bound_ndn,
+               mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) != LDAP_SUCCESS )
+       {
+               candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
+               retcode = META_SEARCH_NOT_CANDIDATE;
+               goto done;
+       }
+
        /*
         * Starts the search
         */
@@ -410,7 +441,7 @@ retry:;
        rc = ldap_search_ext( msc->msc_ld,
                        mbase.bv_val, realscope, mfilter.bv_val,
                        mapped_attrs, op->ors_attrsonly,
-                       op->o_ctrls, NULL, tvp, op->ors_slimit,
+                       ctrls, NULL, tvp, op->ors_slimit,
                        &candidates[ candidate ].sr_msgid ); 
        switch ( rc ) {
        case LDAP_SUCCESS:
@@ -435,6 +466,8 @@ retry:;
        }
 
 done:;
+       (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+
        if ( mapped_attrs ) {
                free( mapped_attrs );
        }
@@ -892,6 +925,7 @@ really_bad:;
                                 * back-meta would need to merge them
                                 * consistently (think of pagedResults...)
                                 */
+                               /* FIXME: response controls? */
                                rs->sr_err = ldap_parse_result( msc->msc_ld,
                                                        res,
                                                        &candidates[ i ].sr_err,