]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-ldap/bind.c
Partially revert prev commit, leave rs->sr_err == SLAPD_ABANDON
[openldap] / servers / slapd / back-ldap / bind.c
index 02485e8c1a6df05f3cf96284eaef41200fd23ee6..9691f11f6df9a1c60e2c1f802f4e47c693e4ff03 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1999-2007 The OpenLDAP Foundation.
+ * Copyright 1999-2009 The OpenLDAP Foundation.
  * Portions Copyright 2000-2003 Pierangelo Masarati.
  * Portions Copyright 1999-2003 Howard Chu.
  * All rights reserved.
@@ -1228,6 +1228,8 @@ ldap_back_dobind_cb(
 {
        ber_tag_t *tptr = op->o_callback->sc_private;
        op->o_tag = *tptr;
+       rs->sr_tag = slap_req2res( op->o_tag );
+
        return SLAP_CB_CONTINUE;
 }
 
@@ -1390,15 +1392,26 @@ retry_lock:;
 
                lutil_sasl_freedefs( defaults );
 
-               rs->sr_err = slap_map_api2result( rs );
-               if ( rs->sr_err != LDAP_SUCCESS ) {
+               switch ( rs->sr_err ) {
+               case LDAP_SUCCESS:
+                       LDAP_BACK_CONN_ISBOUND_SET( lc );
+                       break;
+
+               case LDAP_LOCAL_ERROR:
+                       /* list client API error codes that require
+                        * to taint the connection */
+                       /* FIXME: should actually retry? */
+                       LDAP_BACK_CONN_TAINTED_SET( lc );
+
+                       /* fallthru */
+
+               default:
                        LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
+                       rs->sr_err = slap_map_api2result( rs );
                        if ( sendok & LDAP_BACK_SENDERR ) {
                                send_ldap_result( op, rs );
                        }
-
-               } else {
-                       LDAP_BACK_CONN_ISBOUND_SET( lc );
+                       break;
                }
 
                if ( LDAP_BACK_QUARANTINE( li ) ) {
@@ -1462,12 +1475,12 @@ retry:;
                        if ( op->o_callback == &cb )
                                op->o_callback = cb.sc_next;
                        op->o_tag = o_tag;
-                       rs->sr_text = "Internal proxy bind failure";
+                       rs->sr_text = "Proxy can't contact remote server";
                        send_ldap_result( op, rs );
                }
 
                rc = 0;
-               goto leave;
+               goto func_leave;
        }
 
        rc = ldap_back_op_result( lc, op, rs, msgid,
@@ -1486,7 +1499,7 @@ done:;
                ldap_set_rebind_proc( lc->lc_ld, li->li_rebind_f, lc );
        }
 
-leave:;
+func_leave:;
        if ( op->o_callback == &cb )
                op->o_callback = cb.sc_next;
        op->o_tag = o_tag;
@@ -1624,8 +1637,6 @@ ldap_back_op_result(
        char            **refs = NULL;
        LDAPControl     **ctrls = NULL;
 
-#define        ERR_OK(err) ((err) == LDAP_SUCCESS || (err) == LDAP_COMPARE_FALSE || (err) == LDAP_COMPARE_TRUE)
-
        rs->sr_text = NULL;
        rs->sr_matched = NULL;
        rs->sr_ref = NULL;
@@ -1634,7 +1645,7 @@ ldap_back_op_result(
        /* if the error recorded in the reply corresponds
         * to a successful state, get the error from the
         * remote server response */
-       if ( ERR_OK( rs->sr_err ) ) {
+       if ( LDAP_ERR_OK( rs->sr_err ) ) {
                int             rc;
                struct timeval  tv;
                LDAPMessage     *res = NULL;
@@ -1787,7 +1798,7 @@ retry:;
        /* if the error in the reply structure is not
         * LDAP_SUCCESS, try to map it from client 
         * to server error */
-       if ( !ERR_OK( rs->sr_err ) ) {
+       if ( !LDAP_ERR_OK( rs->sr_err ) ) {
                rs->sr_err = slap_map_api2result( rs );
 
                /* internal ops ( op->o_conn == NULL ) 
@@ -1812,8 +1823,8 @@ retry:;
                }
 
        } else if ( op->o_conn &&
-               ( ( ( sendok & LDAP_BACK_SENDOK ) && ERR_OK( rs->sr_err ) )
-                       || ( ( sendok & LDAP_BACK_SENDERR ) && rs->sr_err != LDAP_SUCCESS ) ) )
+               ( ( ( sendok & LDAP_BACK_SENDOK ) && LDAP_ERR_OK( rs->sr_err ) )
+                       || ( ( sendok & LDAP_BACK_SENDERR ) && !LDAP_ERR_OK( rs->sr_err ) ) ) )
        {
                send_ldap_result( op, rs );
        }
@@ -1846,7 +1857,7 @@ retry:;
                rs->sr_ctrls = NULL;
        }
 
-       return( ERR_OK( rs->sr_err ) ? LDAP_SUCCESS : rs->sr_err );
+       return( LDAP_ERR_OK( rs->sr_err ) ? LDAP_SUCCESS : rs->sr_err );
 }
 
 /* return true if bound, false if failed */
@@ -2134,15 +2145,26 @@ ldap_back_proxy_authz_bind(
                                LDAP_SASL_QUIET, lutil_sasl_interact,
                                defaults );
 
-               rs->sr_err = slap_map_api2result( rs );
-               if ( rs->sr_err != LDAP_SUCCESS ) {
+               switch ( rs->sr_err ) {
+               case LDAP_SUCCESS:
+                       LDAP_BACK_CONN_ISBOUND_SET( lc );
+                       break;
+
+               case LDAP_LOCAL_ERROR:
+                       /* list client API error codes that require
+                        * to taint the connection */
+                       /* FIXME: should actually retry? */
+                       LDAP_BACK_CONN_TAINTED_SET( lc );
+
+                       /* fallthru */
+
+               default:
                        LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
+                       rs->sr_err = slap_map_api2result( rs );
                        if ( sendok & LDAP_BACK_SENDERR ) {
                                send_ldap_result( op, rs );
                        }
-
-               } else {
-                       LDAP_BACK_CONN_ISBOUND_SET( lc );
+                       break;
                }
 
                lutil_sasl_freedefs( defaults );
@@ -2184,7 +2206,9 @@ ldap_back_proxy_authz_bind(
                 * so that referral chasing is attempted using the right
                 * identity */
                LDAP_BACK_CONN_ISBOUND_SET( lc );
-               ber_bvreplace( &lc->lc_bound_ndn, binddn );
+               if ( !BER_BVISNULL( binddn ) ) {
+                       ber_bvreplace( &lc->lc_bound_ndn, binddn );
+               }
 
                if ( !BER_BVISNULL( &lc->lc_cred ) ) {
                        memset( lc->lc_cred.bv_val, 0,
@@ -2192,8 +2216,10 @@ ldap_back_proxy_authz_bind(
                }
 
                if ( LDAP_BACK_SAVECRED( li ) ) {
-                       ber_bvreplace( &lc->lc_cred, bindcred );
-                       ldap_set_rebind_proc( lc->lc_ld, li->li_rebind_f, lc );
+                       if ( !BER_BVISNULL( bindcred ) ) {
+                               ber_bvreplace( &lc->lc_cred, bindcred );
+                               ldap_set_rebind_proc( lc->lc_ld, li->li_rebind_f, lc );
+                       }
 
                } else {
                        lc->lc_cred.bv_len = 0;
@@ -2249,7 +2275,8 @@ ldap_back_proxy_authz_ctrl(
         * but if it is not set this test fails.  We need a different
         * means to detect if idassert is enabled */
        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 ) ) )
+               && ( BER_BVISNULL( &si->si_bc.sb_binddn ) || BER_BVISEMPTY( &si->si_bc.sb_binddn ) )
+               && BER_BVISNULL( &si->si_bc.sb_saslmech ) )
        {
                goto done;
        }
@@ -2517,8 +2544,8 @@ ldap_back_controls_add(
 
        LDAPControl     **ctrls = NULL;
        /* set to the maximum number of controls this backend can add */
-       LDAPControl     c[ 2 ] = { 0 };
-       int             i = 0, j = 0;
+       LDAPControl     c[ 2 ] = { { 0 } };
+       int             n = 0, i, j1 = 0, j2 = 0;
 
        *pctrls = NULL;
 
@@ -2539,30 +2566,38 @@ ldap_back_controls_add(
                goto done;
        }
 
+       /* put controls that go __before__ existing ones here */
+
        /* proxyAuthz for identity assertion */
        switch ( ldap_back_proxy_authz_ctrl( op, rs, &lc->lc_bound_ndn,
-               li->li_version, &li->li_idassert, &c[ j ] ) )
+               li->li_version, &li->li_idassert, &c[ j1 ] ) )
        {
        case SLAP_CB_CONTINUE:
                break;
 
        case LDAP_SUCCESS:
-               j++;
+               j1++;
                break;
 
        default:
                goto done;
        }
 
+       /* put controls that go __after__ existing ones here */
+
 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
+       /* FIXME: according to <draft-wahl-ldap-session>, 
+        * the server should check if the control can be added
+        * based on the identity of the client and so */
+
        /* session tracking */
        if ( LDAP_BACK_ST_REQUEST( li ) ) {
-               switch ( slap_ctrl_session_tracking_request_add( op, rs, &c[ j ] ) ) {
+               switch ( slap_ctrl_session_tracking_request_add( op, rs, &c[ j1 + j2 ] ) ) {
                case SLAP_CB_CONTINUE:
                        break;
 
                case LDAP_SUCCESS:
-                       j++;
+                       j2++;
                        break;
 
                default:
@@ -2575,31 +2610,47 @@ ldap_back_controls_add(
                rs->sr_err = LDAP_SUCCESS;
        }
 
-       if ( j == 0 ) {
+       /* if nothing to do, just bail out */
+       if ( j1 == 0 && j2 == 0 ) {
                goto done;
        }
 
+       assert( j1 + j2 <= (int) (sizeof( c )/sizeof( c[0] )) );
+
        if ( op->o_ctrls ) {
-               for ( i = 0; op->o_ctrls[ i ]; i++ )
+               for ( n = 0; op->o_ctrls[ n ]; n++ )
                        /* just count ctrls */ ;
        }
 
-       ctrls = op->o_tmpalloc( sizeof( LDAPControl * ) * (i + j + 1) + j * sizeof( LDAPControl ),
+       ctrls = op->o_tmpalloc( (n + j1 + j2 + 1) * sizeof( LDAPControl * ) + ( j1 + j2 ) * sizeof( LDAPControl ),
                        op->o_tmpmemctx );
-       ctrls[ 0 ] = (LDAPControl *)&ctrls[ i + j + 1 ];
-       *ctrls[ 0 ] = c[ 0 ];
-       for ( i = 1; i < j; i++ ) {
-               ctrls[ i ] = &ctrls[ 0 ][ i ];
-               *ctrls[ i ] = c[ i ];
+       if ( j1 ) {
+               ctrls[ 0 ] = (LDAPControl *)&ctrls[ n + j1 + j2 + 1 ];
+               *ctrls[ 0 ] = c[ 0 ];
+               for ( i = 1; i < j1; i++ ) {
+                       ctrls[ i ] = &ctrls[ 0 ][ i ];
+                       *ctrls[ i ] = c[ i ];
+               }
        }
 
        i = 0;
        if ( op->o_ctrls ) {
                for ( i = 0; op->o_ctrls[ i ]; i++ ) {
-                       ctrls[ i + j ] = op->o_ctrls[ i ];
+                       ctrls[ i + j1 ] = op->o_ctrls[ i ];
+               }
+       }
+
+       n += j1;
+       if ( j2 ) {
+               ctrls[ n ] = (LDAPControl *)&ctrls[ n + j2 + 1 ] + j1;
+               *ctrls[ n ] = c[ j1 ];
+               for ( i = 1; i < j2; i++ ) {
+                       ctrls[ n + i ] = &ctrls[ n ][ i ];
+                       *ctrls[ n + i ] = c[ i ];
                }
        }
-       ctrls[ i + j ] = NULL;
+
+       ctrls[ n + j2 ] = NULL;
 
 done:;
        if ( ctrls == NULL ) {
@@ -2619,13 +2670,27 @@ ldap_back_controls_free( Operation *op, SlapReply *rs, LDAPControl ***pctrls )
        /* we assume that the controls added by the proxy come first,
         * so as soon as we find op->o_ctrls[ 0 ] we can stop */
        if ( ctrls && ctrls != op->o_ctrls ) {
-               int     i;
+               int             i = 0, n = 0, n_added;
+               LDAPControl     *lower, *upper;
 
                assert( ctrls[ 0 ] != NULL );
 
+               for ( n = 0; ctrls[ n ] != NULL; n++ )
+                       /* count 'em */ ;
+
+               if ( op->o_ctrls ) {
+                       for ( i = 0; op->o_ctrls[ i ] != NULL; i++ )
+                               /* count 'em */ ;
+               }
+
+               n_added = n - i;
+               lower = (LDAPControl *)&ctrls[ n ];
+               upper = &lower[ n_added ];
+
                for ( i = 0; ctrls[ i ] != NULL; i++ ) {
-                       if ( op->o_ctrls && ctrls[ i ] == op->o_ctrls[ 0 ] ) {
-                               break;
+                       if ( ctrls[ i ] < lower || ctrls[ i ] >= upper ) {
+                               /* original; don't touch */
+                               continue;
                        }
 
                        if ( !BER_BVISNULL( &ctrls[ i ]->ldctl_value ) ) {