mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-02-03 20:40:05 -05:00
StartTLS (ITS#3507) + chain overlay fixes and improvements
This commit is contained in:
parent
ad2a19d8eb
commit
c6b6d2a5ec
21 changed files with 459 additions and 275 deletions
|
|
@ -46,14 +46,14 @@ ldap_back_add(
|
|||
int isupdate;
|
||||
int do_retry = 1;
|
||||
LDAPControl **ctrls = NULL;
|
||||
int rc = LDAP_SUCCESS;
|
||||
|
||||
rs->sr_err = LDAP_SUCCESS;
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, "==> ldap_back_add(\"%s\")\n",
|
||||
op->o_req_dn.bv_val, 0, 0 );
|
||||
|
||||
lc = ldap_back_getconn( op, rs );
|
||||
if ( !lc || !ldap_back_dobind( lc, op, rs ) ) {
|
||||
rc = -1;
|
||||
lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
|
||||
if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
|
@ -89,20 +89,19 @@ ldap_back_add(
|
|||
attrs[ i ] = NULL;
|
||||
|
||||
ctrls = op->o_ctrls;
|
||||
rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
rs->sr_err = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
|
||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||
send_ldap_result( op, rs );
|
||||
rc = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
retry:
|
||||
rs->sr_err = ldap_add_ext( lc->lc_ld, op->o_req_dn.bv_val, attrs,
|
||||
ctrls, NULL, &msgid );
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, 1 );
|
||||
rs->sr_err = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT );
|
||||
if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
|
||||
do_retry = 0;
|
||||
if ( ldap_back_retry( lc, op, rs ) ) {
|
||||
if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) {
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
|
@ -118,8 +117,8 @@ cleanup:
|
|||
}
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, "<== ldap_back_add(\"%s\"): %d\n",
|
||||
op->o_req_dn.bv_val, rc, 0 );
|
||||
op->o_req_dn.bv_val, rs->sr_err, 0 );
|
||||
|
||||
return rc;
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,12 +90,23 @@ struct ldapinfo {
|
|||
/* end of ID assert stuff */
|
||||
|
||||
ldap_pvt_thread_mutex_t conn_mutex;
|
||||
int savecred;
|
||||
unsigned flags;
|
||||
#define LDAP_BACK_F_NONE 0x00U
|
||||
#define LDAP_BACK_F_SAVECRED 0x01U
|
||||
#define LDAP_BACK_F_USE_TLS 0x02U
|
||||
#define LDAP_BACK_F_TLS_CRITICAL ( 0x04U | LDAP_BACK_F_USE_TLS )
|
||||
Avlnode *conntree;
|
||||
|
||||
int rwm_started;
|
||||
};
|
||||
|
||||
typedef enum ldap_back_send_t {
|
||||
LDAP_BACK_DONTSEND = 0x00,
|
||||
LDAP_BACK_SENDOK = 0x01,
|
||||
LDAP_BACK_SENDERR = 0x02,
|
||||
LDAP_BACK_SENDRESULT = (LDAP_BACK_SENDOK|LDAP_BACK_SENDERR)
|
||||
} ldap_back_send_t;
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
#include "proto-ldap.h"
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
* <http://www.OpenLDAP.org/license.html>.
|
||||
*/
|
||||
/* ACKNOWLEDGEMENTS:
|
||||
* This work was initially developed by the Howard Chu for inclusion
|
||||
* This work was initially developed by Howard Chu for inclusion
|
||||
* in OpenLDAP Software and subsequently enhanced by Pierangelo
|
||||
* Masarati.
|
||||
*/
|
||||
|
|
@ -41,6 +41,9 @@ static LDAP_REBIND_PROC ldap_back_rebind;
|
|||
static int
|
||||
ldap_back_proxy_authz_bind( struct ldapconn *lc, Operation *op, SlapReply *rs );
|
||||
|
||||
static int
|
||||
ldap_back_prepare_conn( struct ldapconn **lcp, Operation *op, SlapReply *rs, ldap_back_send_t sendok );
|
||||
|
||||
int
|
||||
ldap_back_bind( Operation *op, SlapReply *rs )
|
||||
{
|
||||
|
|
@ -50,9 +53,9 @@ ldap_back_bind( Operation *op, SlapReply *rs )
|
|||
int rc = 0;
|
||||
ber_int_t msgid;
|
||||
|
||||
lc = ldap_back_getconn( op, rs );
|
||||
lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
|
||||
if ( !lc ) {
|
||||
return( -1 );
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &lc->lc_bound_ndn ) ) {
|
||||
|
|
@ -65,7 +68,7 @@ ldap_back_bind( Operation *op, SlapReply *rs )
|
|||
rs->sr_err = ldap_sasl_bind( lc->lc_ld, op->o_req_dn.bv_val,
|
||||
LDAP_SASL_SIMPLE,
|
||||
&op->orb_cred, op->o_ctrls, NULL, &msgid );
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, 1 );
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT );
|
||||
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
/* If defined, proxyAuthz will be used also when
|
||||
|
|
@ -84,7 +87,7 @@ ldap_back_bind( Operation *op, SlapReply *rs )
|
|||
lc->lc_bound = 1;
|
||||
ber_dupbv( &lc->lc_bound_ndn, &op->o_req_ndn );
|
||||
|
||||
if ( li->savecred ) {
|
||||
if ( li->flags & LDAP_BACK_F_SAVECRED ) {
|
||||
if ( !BER_BVISNULL( &lc->lc_cred ) ) {
|
||||
memset( lc->lc_cred.bv_val, 0,
|
||||
lc->lc_cred.bv_len );
|
||||
|
|
@ -219,12 +222,76 @@ ldap_back_freeconn( Operation *op, struct ldapconn *lc )
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ldap_back_prepare_conn( struct ldapconn **lcp, Operation *op, SlapReply *rs, ldap_back_send_t sendok )
|
||||
{
|
||||
struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
|
||||
int vers = op->o_protocol;
|
||||
LDAP *ld = NULL;
|
||||
|
||||
assert( lcp != NULL );
|
||||
|
||||
rs->sr_err = ldap_initialize( &ld, li->url );
|
||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
/* Set LDAP version. This will always succeed: If the client
|
||||
* bound with a particular version, then so can we.
|
||||
*/
|
||||
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, (const void *)&vers );
|
||||
|
||||
/* Set LDAP version. This will always succeed: If the client
|
||||
* bound with a particular version, then so can we.
|
||||
*/
|
||||
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION,
|
||||
(const void *)&vers );
|
||||
|
||||
/* FIXME: configurable? */
|
||||
ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON );
|
||||
|
||||
if ( ( li->flags & LDAP_BACK_F_USE_TLS )
|
||||
&& !ldap_is_ldaps_url( li->url )
|
||||
&& ( rs->sr_err = ldap_start_tls_s( ld, NULL, NULL ) ) != LDAP_SUCCESS )
|
||||
{
|
||||
/* if StartTLS is requested, only attempt it if the URL
|
||||
* is not "ldaps://"; this may occur not only in case
|
||||
* of misconfiguration, but also when used in the chain
|
||||
* overlay, where the "uri" can be parsed out of a referral */
|
||||
if ( rs->sr_err == LDAP_SERVER_DOWN
|
||||
|| ( li->flags & LDAP_BACK_F_TLS_CRITICAL ) )
|
||||
{
|
||||
ldap_unbind_ext_s( ld, NULL, NULL );
|
||||
goto error_return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( *lcp == NULL ) {
|
||||
*lcp = (struct ldapconn *)ch_malloc( sizeof( struct ldapconn ) );
|
||||
memset( *lcp, 0, sizeof( struct ldapconn ) );
|
||||
}
|
||||
(*lcp)->lc_ld = ld;
|
||||
|
||||
error_return:;
|
||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||
rs->sr_err = slap_map_api2result( rs );
|
||||
if ( sendok & LDAP_BACK_SENDERR ) {
|
||||
if ( rs->sr_text == NULL ) {
|
||||
rs->sr_text = "ldap_initialize() failed";
|
||||
}
|
||||
send_ldap_result( op, rs );
|
||||
rs->sr_text = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
struct ldapconn *
|
||||
ldap_back_getconn( Operation *op, SlapReply *rs )
|
||||
ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
|
||||
{
|
||||
struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
|
||||
struct ldapconn *lc, lc_curr;
|
||||
LDAP *ld;
|
||||
int is_priv = 0;
|
||||
|
||||
/* Searches for a ldapconn in the avl tree */
|
||||
|
|
@ -258,31 +325,12 @@ ldap_back_getconn( Operation *op, SlapReply *rs )
|
|||
|
||||
/* Looks like we didn't get a bind. Open a new session... */
|
||||
if ( !lc ) {
|
||||
int vers = op->o_protocol;
|
||||
rs->sr_err = ldap_initialize( &ld, li->url );
|
||||
|
||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||
rs->sr_err = slap_map_api2result( rs );
|
||||
if ( rs->sr_text == NULL ) {
|
||||
rs->sr_text = "ldap_initialize() failed";
|
||||
}
|
||||
if ( op->o_conn ) {
|
||||
send_ldap_result( op, rs );
|
||||
}
|
||||
rs->sr_text = NULL;
|
||||
return( NULL );
|
||||
/* lc here must be NULL */
|
||||
if ( ldap_back_prepare_conn( &lc, op, rs, sendok ) != LDAP_SUCCESS ) {
|
||||
return NULL;
|
||||
}
|
||||
/* Set LDAP version. This will always succeed: If the client
|
||||
* bound with a particular version, then so can we.
|
||||
*/
|
||||
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION,
|
||||
(const void *)&vers );
|
||||
/* FIXME: configurable? */
|
||||
ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON );
|
||||
|
||||
lc = (struct ldapconn *)ch_malloc( sizeof( struct ldapconn ) );
|
||||
lc->lc_conn = lc_curr.lc_conn;
|
||||
lc->lc_ld = ld;
|
||||
ber_dupbv( &lc->lc_local_ndn, &lc_curr.lc_local_ndn );
|
||||
|
||||
ldap_pvt_thread_mutex_init( &lc->lc_mutex );
|
||||
|
|
@ -320,18 +368,18 @@ ldap_back_getconn( Operation *op, SlapReply *rs )
|
|||
/* Err could be -1 in case a duplicate ldapconn is inserted */
|
||||
if ( rs->sr_err != 0 ) {
|
||||
ldap_back_conn_free( lc );
|
||||
if ( op->o_conn ) {
|
||||
if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) {
|
||||
send_ldap_error( op, rs, LDAP_OTHER,
|
||||
"internal server error" );
|
||||
}
|
||||
return( NULL );
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"=>ldap_back_getconn: conn %p fetched\n", (void *) lc, 0, 0 );
|
||||
}
|
||||
|
||||
return( lc );
|
||||
return lc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -341,12 +389,19 @@ ldap_back_getconn( Operation *op, SlapReply *rs )
|
|||
* it from all the callers, and I made the function return the flag, so
|
||||
* it can be used to simplify the check.
|
||||
*/
|
||||
int
|
||||
ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs )
|
||||
static int
|
||||
ldap_back_dobind_int(
|
||||
struct ldapconn *lc,
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
ldap_back_send_t sendok,
|
||||
int retries )
|
||||
{
|
||||
int rc;
|
||||
ber_int_t msgid;
|
||||
|
||||
assert( retries >= 0 );
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &lc->lc_mutex );
|
||||
if ( !lc->lc_bound ) {
|
||||
/*
|
||||
|
|
@ -373,12 +428,33 @@ ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs )
|
|||
goto done;
|
||||
}
|
||||
|
||||
retry:;
|
||||
rs->sr_err = ldap_sasl_bind( lc->lc_ld,
|
||||
lc->lc_bound_ndn.bv_val,
|
||||
LDAP_SASL_SIMPLE, &lc->lc_cred,
|
||||
NULL, NULL, &msgid );
|
||||
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, 0 );
|
||||
|
||||
if ( rs->sr_err == LDAP_SERVER_DOWN ) {
|
||||
if ( retries > 0 ) {
|
||||
ldap_unbind_ext_s( lc->lc_ld, NULL, NULL );
|
||||
lc->lc_ld = NULL;
|
||||
|
||||
/* lc here must be the regular lc, reset and ready for init */
|
||||
if ( ldap_back_prepare_conn( &lc, op, rs, sendok ) != LDAP_SUCCESS ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
retries--;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
ldap_back_freeconn( op, lc );
|
||||
rs->sr_err = slap_map_api2result( rs );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, sendok );
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
lc->lc_bound = 1;
|
||||
}
|
||||
|
|
@ -390,6 +466,12 @@ done:;
|
|||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok )
|
||||
{
|
||||
return ldap_back_dobind_int( lc, op, rs, sendok, 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* ldap_back_rebind
|
||||
*
|
||||
|
|
@ -400,7 +482,9 @@ static int
|
|||
ldap_back_rebind( LDAP *ld, LDAP_CONST char *url, ber_tag_t request,
|
||||
ber_int_t msgid, void *params )
|
||||
{
|
||||
struct ldapconn *lc = params;
|
||||
struct ldapconn *lc = (struct ldapconn *)params;
|
||||
|
||||
/* FIXME: add checks on the URL/identity? */
|
||||
|
||||
return ldap_sasl_bind_s( ld, lc->lc_bound_ndn.bv_val,
|
||||
LDAP_SASL_SIMPLE, &lc->lc_cred, NULL, NULL, NULL );
|
||||
|
|
@ -408,11 +492,11 @@ ldap_back_rebind( LDAP *ld, LDAP_CONST char *url, ber_tag_t request,
|
|||
|
||||
int
|
||||
ldap_back_op_result(
|
||||
struct ldapconn *lc,
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
ber_int_t msgid,
|
||||
int sendok )
|
||||
struct ldapconn *lc,
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
ber_int_t msgid,
|
||||
ldap_back_send_t sendok )
|
||||
{
|
||||
char *match = NULL;
|
||||
LDAPMessage *res = NULL;
|
||||
|
|
@ -474,7 +558,10 @@ retry:;
|
|||
rs->sr_matched = match;
|
||||
}
|
||||
}
|
||||
if ( op->o_conn && ( sendok || rs->sr_err != LDAP_SUCCESS ) ) {
|
||||
if ( op->o_conn &&
|
||||
( ( sendok & LDAP_BACK_SENDOK )
|
||||
|| ( ( sendok & LDAP_BACK_SENDERR ) && rs->sr_err != LDAP_SUCCESS ) ) )
|
||||
{
|
||||
send_ldap_result( op, rs );
|
||||
}
|
||||
if ( match ) {
|
||||
|
|
@ -493,37 +580,20 @@ retry:;
|
|||
|
||||
/* return true if bound, false if failed */
|
||||
int
|
||||
ldap_back_retry( struct ldapconn *lc, Operation *op, SlapReply *rs )
|
||||
ldap_back_retry( struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok )
|
||||
{
|
||||
struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
|
||||
int vers = op->o_protocol;
|
||||
LDAP *ld;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &lc->lc_mutex );
|
||||
ldap_unbind_ext_s( lc->lc_ld, NULL, NULL );
|
||||
lc->lc_ld = NULL;
|
||||
lc->lc_bound = 0;
|
||||
rs->sr_err = ldap_initialize( &ld, li->url );
|
||||
|
||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||
rs->sr_err = slap_map_api2result( rs );
|
||||
if ( rs->sr_text == NULL ) {
|
||||
rs->sr_text = "ldap_initialize() failed";
|
||||
}
|
||||
if ( op->o_conn ) {
|
||||
send_ldap_result( op, rs );
|
||||
}
|
||||
rs->sr_text = NULL;
|
||||
|
||||
/* lc here must be the regular lc, reset and ready for init */
|
||||
if ( ldap_back_prepare_conn( &lc, op, rs, sendok ) != LDAP_SUCCESS ) {
|
||||
return 0;
|
||||
}
|
||||
/* Set LDAP version. This will always succeed: If the client
|
||||
* bound with a particular version, then so can we.
|
||||
*/
|
||||
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, (const void *)&vers );
|
||||
/* FIXME: configurable? */
|
||||
ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON );
|
||||
lc->lc_ld = ld;
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &lc->lc_mutex );
|
||||
return ldap_back_dobind( lc, op, rs );
|
||||
return ldap_back_dobind_int( lc, op, rs, sendok, 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -695,7 +765,7 @@ ldap_back_proxy_authz_bind( struct ldapconn *lc, Operation *op, SlapReply *rs )
|
|||
goto done;
|
||||
}
|
||||
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, 0 );
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDERR );
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
lc->lc_bound = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,18 +31,11 @@
|
|||
|
||||
static BackendInfo *lback;
|
||||
|
||||
#if 0
|
||||
static int
|
||||
ldap_chain_chk_referrals( Operation *op, SlapReply *rs )
|
||||
{
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
ldap_chain_operational( Operation *op, SlapReply *rs )
|
||||
{
|
||||
/* trap entries generated by back-ldap.
|
||||
/* Trap entries generated by back-ldap.
|
||||
*
|
||||
* FIXME: we need a better way to recognize them; a cleaner
|
||||
* solution would be to be able to intercept the response
|
||||
* of be_operational(), so that we can divert only those
|
||||
|
|
@ -57,8 +50,11 @@ ldap_chain_operational( Operation *op, SlapReply *rs )
|
|||
return SLAP_CB_CONTINUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search specific response that strips entryDN from entries
|
||||
*/
|
||||
static int
|
||||
ldap_chain_cb_response( Operation *op, SlapReply *rs )
|
||||
ldap_chain_cb_search_response( Operation *op, SlapReply *rs )
|
||||
{
|
||||
assert( op->o_tag == LDAP_REQ_SEARCH );
|
||||
|
||||
|
|
@ -82,83 +78,159 @@ ldap_chain_cb_response( Operation *op, SlapReply *rs )
|
|||
}
|
||||
|
||||
return SLAP_CB_CONTINUE;
|
||||
|
||||
} else if ( rs->sr_type == REP_RESULT ) {
|
||||
/* back-ldap tried to send result */
|
||||
op->o_callback->sc_private = (void *)(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dummy response that simply traces if back-ldap tried to send
|
||||
* anything to the client
|
||||
*/
|
||||
static int
|
||||
ldap_chain_cb_response( Operation *op, SlapReply *rs )
|
||||
{
|
||||
if ( rs->sr_type == REP_RESULT ) {
|
||||
op->o_callback->sc_private = (void *)(1);
|
||||
|
||||
} else if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH )
|
||||
{
|
||||
/* strip the entryDN attribute, but keep returning results */
|
||||
(void)ldap_chain_cb_search_response( op, rs );
|
||||
}
|
||||
|
||||
return SLAP_CB_CONTINUE;
|
||||
}
|
||||
|
||||
static int
|
||||
ldap_chain_op(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
int ( *op_f )( Operation *op, SlapReply *rs ),
|
||||
BerVarray ref )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
|
||||
struct ldapinfo li, *lip = (struct ldapinfo *)on->on_bi.bi_private;
|
||||
int rc;
|
||||
|
||||
if ( lip->url != NULL ) {
|
||||
op->o_bd->be_private = on->on_bi.bi_private;
|
||||
return ( *op_f )( op, rs );
|
||||
}
|
||||
|
||||
li = *lip;
|
||||
op->o_bd->be_private = &li;
|
||||
|
||||
/* if we parse the URI then by no means
|
||||
* we can cache stuff or reuse connections,
|
||||
* because in back-ldap there's no caching
|
||||
* based on the URI value, which is supposed
|
||||
* to be set once for all (correct?) */
|
||||
op->o_do_not_cache = 1;
|
||||
|
||||
for ( ; !BER_BVISNULL( ref ); ref++ ) {
|
||||
LDAPURLDesc *srv;
|
||||
char *save_dn;
|
||||
|
||||
/* We're setting the URI of the first referral;
|
||||
* what if there are more?
|
||||
|
||||
Document: draft-ietf-ldapbis-protocol-27.txt
|
||||
|
||||
4.1.10. Referral
|
||||
...
|
||||
If the client wishes to progress the operation, it MUST follow the
|
||||
referral by contacting one of the supported services. If multiple
|
||||
URIs are present, the client assumes that any supported URI may be
|
||||
used to progress the operation.
|
||||
|
||||
* so we actually need to follow exactly one,
|
||||
* and we can assume any is fine.
|
||||
*/
|
||||
|
||||
/* parse reference and use
|
||||
* proto://[host][:port]/ only */
|
||||
rc = ldap_url_parse_ext( ref->bv_val, &srv );
|
||||
if ( rc != LDAP_URL_SUCCESS ) {
|
||||
/* try next */
|
||||
rc = LDAP_OTHER;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* remove DN essentially because later on
|
||||
* ldap_initialize() will parse the URL
|
||||
* as a comma-separated URL list */
|
||||
save_dn = srv->lud_dn;
|
||||
srv->lud_dn = "";
|
||||
srv->lud_scope = LDAP_SCOPE_DEFAULT;
|
||||
li.url = ldap_url_desc2str( srv );
|
||||
srv->lud_dn = save_dn;
|
||||
ldap_free_urldesc( srv );
|
||||
|
||||
if ( li.url == NULL ) {
|
||||
/* try next */
|
||||
rc = LDAP_OTHER;
|
||||
continue;
|
||||
}
|
||||
|
||||
rc = ( *op_f )( op, rs );
|
||||
|
||||
ldap_memfree( li.url );
|
||||
li.url = NULL;
|
||||
|
||||
if ( rc == LDAP_SUCCESS && rs->sr_err == LDAP_SUCCESS ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
ldap_chain_response( Operation *op, SlapReply *rs )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
|
||||
void *private = op->o_bd->be_private;
|
||||
slap_callback *sc = op->o_callback;
|
||||
slap_callback *sc = op->o_callback,
|
||||
sc2 = { 0 };
|
||||
int rc = 0;
|
||||
int cache = op->o_do_not_cache;
|
||||
char *authzid = NULL;
|
||||
BerVarray ref;
|
||||
struct berval ndn = op->o_ndn;
|
||||
|
||||
struct ldapinfo li, *lip = (struct ldapinfo *)on->on_bi.bi_private;
|
||||
|
||||
if ( rs->sr_err != LDAP_REFERRAL && rs->sr_type != REP_SEARCHREF )
|
||||
if ( rs->sr_err != LDAP_REFERRAL && rs->sr_type != REP_SEARCHREF ) {
|
||||
return SLAP_CB_CONTINUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: add checks on who/when chain operations; e.g.:
|
||||
* a) what identities are authorized
|
||||
* b) what request DN (e.g. only chain requests rooted at <DN>)
|
||||
* c) what referral URIs
|
||||
* d) what protocol scheme (e.g. only ldaps://)
|
||||
* e) what ssf
|
||||
*/
|
||||
|
||||
ref = rs->sr_ref;
|
||||
rs->sr_ref = NULL;
|
||||
|
||||
op->o_callback = NULL;
|
||||
|
||||
if ( lip->url == NULL ) {
|
||||
/* if we parse the URI then by no means
|
||||
* we can cache stuff or reuse connections,
|
||||
* because in back-ldap there's no caching
|
||||
* based on the URI value, which is supposed
|
||||
* to be set once for all (correct?) */
|
||||
op->o_do_not_cache = 1;
|
||||
|
||||
/* FIXME: we're setting the URI of the first referral;
|
||||
* what if there are more? Is this something we should
|
||||
* worry about? */
|
||||
li = *lip;
|
||||
op->o_bd->be_private = &li;
|
||||
|
||||
if ( rs->sr_type != REP_SEARCHREF ) {
|
||||
LDAPURLDesc *srv;
|
||||
char *save_dn;
|
||||
|
||||
/* parse reference and use
|
||||
* proto://[host][:port]/ only */
|
||||
rc = ldap_url_parse_ext( ref[0].bv_val, &srv );
|
||||
if ( rc != LDAP_URL_SUCCESS ) {
|
||||
/* error */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* remove DN essentially because later on
|
||||
* ldap_initialize() will parse the URL
|
||||
* as a comma-separated URL list */
|
||||
save_dn = srv->lud_dn;
|
||||
srv->lud_dn = "";
|
||||
srv->lud_scope = LDAP_SCOPE_DEFAULT;
|
||||
li.url = ldap_url_desc2str( srv );
|
||||
srv->lud_dn = save_dn;
|
||||
ldap_free_urldesc( srv );
|
||||
|
||||
if ( li.url == NULL ) {
|
||||
/* error */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
op->o_bd->be_private = on->on_bi.bi_private;
|
||||
}
|
||||
/* we need this to know if back-ldap returned any result */
|
||||
sc2.sc_response = ldap_chain_cb_response;
|
||||
op->o_callback = &sc2;
|
||||
|
||||
/* Chaining can be performed by a privileged user on behalf
|
||||
* of normal users, using the ProxyAuthz control, by exploiting
|
||||
* the identity assertion feature of back-ldap; see idassert-*
|
||||
* directives in slapd-ldap(5).
|
||||
*
|
||||
* FIXME: the idassert-authcDN is one, will it be fine regardless
|
||||
* of the URI we obtain from the referral?
|
||||
*/
|
||||
|
||||
switch ( op->o_tag ) {
|
||||
|
|
@ -166,10 +238,10 @@ ldap_chain_response( Operation *op, SlapReply *rs )
|
|||
struct berval rndn = op->o_req_ndn;
|
||||
Connection *conn = op->o_conn;
|
||||
|
||||
/* FIXME: can we really get a referral for binds? */
|
||||
op->o_req_ndn = slap_empty_bv;
|
||||
|
||||
op->o_conn = NULL;
|
||||
rc = lback->bi_op_bind( op, rs );
|
||||
rc = ldap_chain_op( op, rs, lback->bi_op_bind, ref );
|
||||
op->o_req_ndn = rndn;
|
||||
op->o_conn = conn;
|
||||
}
|
||||
|
|
@ -182,7 +254,7 @@ ldap_chain_response( Operation *op, SlapReply *rs )
|
|||
char textbuf[ SLAP_TEXT_BUFLEN ];
|
||||
size_t textlen = sizeof( textbuf );
|
||||
|
||||
/* global overlay; create entry */
|
||||
/* global overlay: create entry */
|
||||
/* NOTE: this is a hack to use the chain overlay
|
||||
* as global. I expect to be able to remove this
|
||||
* soon by using slap_mods2entry() earlier in
|
||||
|
|
@ -197,7 +269,7 @@ ldap_chain_response( Operation *op, SlapReply *rs )
|
|||
break;
|
||||
}
|
||||
}
|
||||
rc = lback->bi_op_add( op, rs );
|
||||
rc = ldap_chain_op( op, rs, lback->bi_op_add, ref );
|
||||
if ( cleanup_attrs ) {
|
||||
attrs_free( op->ora_e->e_attrs );
|
||||
op->ora_e->e_attrs = NULL;
|
||||
|
|
@ -205,32 +277,38 @@ ldap_chain_response( Operation *op, SlapReply *rs )
|
|||
break;
|
||||
}
|
||||
case LDAP_REQ_DELETE:
|
||||
rc = lback->bi_op_delete( op, rs );
|
||||
rc = ldap_chain_op( op, rs, lback->bi_op_delete, ref );
|
||||
break;
|
||||
case LDAP_REQ_MODRDN:
|
||||
rc = lback->bi_op_modrdn( op, rs );
|
||||
rc = ldap_chain_op( op, rs, lback->bi_op_modrdn, ref );
|
||||
break;
|
||||
case LDAP_REQ_MODIFY:
|
||||
rc = lback->bi_op_modify( op, rs );
|
||||
rc = ldap_chain_op( op, rs, lback->bi_op_modify, ref );
|
||||
break;
|
||||
case LDAP_REQ_COMPARE:
|
||||
rc = lback->bi_op_compare( op, rs );
|
||||
rc = ldap_chain_op( op, rs, lback->bi_op_compare, ref );
|
||||
break;
|
||||
case LDAP_REQ_SEARCH:
|
||||
if ( rs->sr_type == REP_SEARCHREF ) {
|
||||
struct berval *curr = ref,
|
||||
odn = op->o_req_dn,
|
||||
ondn = op->o_req_ndn;
|
||||
slap_callback sc2 = { 0 };
|
||||
int tmprc = 0;
|
||||
ber_len_t refcnt = 0;
|
||||
BerVarray newref = NULL;
|
||||
|
||||
sc2.sc_response = ldap_chain_cb_response;
|
||||
op->o_callback = &sc2;
|
||||
|
||||
rs->sr_type = REP_SEARCH;
|
||||
|
||||
sc2.sc_response = ldap_chain_cb_search_response;
|
||||
|
||||
li = *lip;
|
||||
li.url = NULL;
|
||||
op->o_bd->be_private = &li;
|
||||
|
||||
/* if we parse the URI then by no means
|
||||
* we can cache stuff or reuse connections,
|
||||
* because in back-ldap there's no caching
|
||||
* based on the URI value, which is supposed
|
||||
* to be set once for all (correct?) */
|
||||
op->o_do_not_cache = 1;
|
||||
|
||||
/* copy the private info because we need to modify it */
|
||||
for ( ; !BER_BVISNULL( &curr[0] ); curr++ ) {
|
||||
LDAPURLDesc *srv;
|
||||
|
|
@ -238,11 +316,11 @@ ldap_chain_response( Operation *op, SlapReply *rs )
|
|||
|
||||
/* parse reference and use
|
||||
* proto://[host][:port]/ only */
|
||||
tmprc = ldap_url_parse_ext( curr[0].bv_val, &srv );
|
||||
if ( tmprc != LDAP_URL_SUCCESS ) {
|
||||
/* error */
|
||||
rc = 1;
|
||||
goto end_of_searchref;
|
||||
rc = ldap_url_parse_ext( curr[0].bv_val, &srv );
|
||||
if ( rc != LDAP_URL_SUCCESS ) {
|
||||
/* try next */
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* remove DN essentially because later on
|
||||
|
|
@ -263,15 +341,15 @@ ldap_chain_response( Operation *op, SlapReply *rs )
|
|||
ldap_free_urldesc( srv );
|
||||
|
||||
if ( li.url == NULL ) {
|
||||
/* error */
|
||||
rc = 1;
|
||||
goto end_of_searchref;
|
||||
/* try next */
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: should we also copy filter and scope?
|
||||
* according to RFC3296, no */
|
||||
tmprc = lback->bi_op_search( op, rs );
|
||||
rc = lback->bi_op_search( op, rs );
|
||||
|
||||
ldap_memfree( li.url );
|
||||
li.url = NULL;
|
||||
|
|
@ -281,76 +359,51 @@ ldap_chain_response( Operation *op, SlapReply *rs )
|
|||
op->o_tmpfree( op->o_req_ndn.bv_val,
|
||||
op->o_tmpmemctx );
|
||||
|
||||
if ( tmprc ) {
|
||||
/* error */
|
||||
rc = 1;
|
||||
goto end_of_searchref;
|
||||
}
|
||||
|
||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||
/* if search was not successful,
|
||||
* at least return the referral! */
|
||||
/* FIXME: assumes referrals
|
||||
* are always created via
|
||||
* referral_rewrite() and freed via
|
||||
* ber_bvarray_free( rs->sr_ref ) */
|
||||
newref = ch_realloc( newref, sizeof( struct berval ) * (refcnt + 2) );
|
||||
ber_dupbv( &newref[ refcnt ], &curr[ 0 ] );
|
||||
refcnt++;
|
||||
BER_BVZERO( &newref[ refcnt ] );
|
||||
if ( rc == LDAP_SUCCESS && rs->sr_err == LDAP_SUCCESS ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
end_of_searchref:;
|
||||
op->o_req_dn = odn;
|
||||
op->o_req_ndn = ondn;
|
||||
rs->sr_type = REP_SEARCHREF;
|
||||
rs->sr_entry = NULL;
|
||||
|
||||
/* if the error was bad, it was already returned
|
||||
* by back-ldap; destroy the referrals left;
|
||||
* otherwise, let the frontend return them. */
|
||||
if ( newref ) {
|
||||
if ( rc == 0 ) {
|
||||
rc = SLAP_CB_CONTINUE;
|
||||
if ( ref != default_referral ) {
|
||||
ber_bvarray_free( ref );
|
||||
}
|
||||
ref = newref;
|
||||
|
||||
} else {
|
||||
ber_bvarray_free( newref );
|
||||
}
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
/* couldn't chase any of the referrals */
|
||||
rc = SLAP_CB_CONTINUE;
|
||||
}
|
||||
|
||||
} else {
|
||||
rc = lback->bi_op_search( op, rs );
|
||||
rc = ldap_chain_op( op, rs, lback->bi_op_search, ref );
|
||||
}
|
||||
break;
|
||||
case LDAP_REQ_EXTENDED:
|
||||
rc = lback->bi_extended( op, rs );
|
||||
rc = ldap_chain_op( op, rs, lback->bi_extended, ref );
|
||||
/* FIXME: ldap_back_extended() by design
|
||||
* doesn't send result; frontend is expected
|
||||
* to send it... */
|
||||
if ( rc != SLAPD_ABANDON ) {
|
||||
send_ldap_extended( op, rs );
|
||||
rc = LDAP_SUCCESS;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
rc = SLAP_CB_CONTINUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( sc2.sc_private == NULL ) {
|
||||
op->o_callback = NULL;
|
||||
rc = rs->sr_err = slap_map_api2result( rs );
|
||||
send_ldap_result( op, rs );
|
||||
}
|
||||
|
||||
op->o_do_not_cache = cache;
|
||||
op->o_bd->be_private = private;
|
||||
op->o_callback = sc;
|
||||
op->o_ndn = ndn;
|
||||
if ( authzid ) {
|
||||
op->o_tmpfree( authzid, op->o_tmpmemctx );
|
||||
}
|
||||
rs->sr_ref = ref;
|
||||
if ( lip->url == NULL && li.url != NULL ) {
|
||||
ldap_memfree( li.url );
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -388,9 +441,9 @@ ldap_chain_db_init(
|
|||
BackendDB *be
|
||||
)
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *) be->bd_info;
|
||||
void *private = be->be_private;
|
||||
int rc;
|
||||
slap_overinst *on = (slap_overinst *)be->bd_info;
|
||||
int rc;
|
||||
BackendDB bd = *be;
|
||||
|
||||
if ( lback == NULL ) {
|
||||
lback = backend_info( "ldap" );
|
||||
|
|
@ -400,10 +453,9 @@ ldap_chain_db_init(
|
|||
}
|
||||
}
|
||||
|
||||
be->be_private = NULL;
|
||||
rc = lback->bi_db_init( be );
|
||||
on->on_bi.bi_private = be->be_private;
|
||||
be->be_private = private;
|
||||
bd.be_private = NULL;
|
||||
rc = lback->bi_db_init( &bd );
|
||||
on->on_bi.bi_private = bd.be_private;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -447,10 +499,6 @@ chain_init( void )
|
|||
|
||||
ldapchain.on_response = ldap_chain_response;
|
||||
|
||||
#if 0
|
||||
ldapchain.on_bi.bi_chk_referrals = ldap_chain_chk_referrals;
|
||||
#endif
|
||||
|
||||
return overlay_register( &ldapchain );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,9 +42,8 @@ ldap_back_compare(
|
|||
LDAPControl **ctrls = NULL;
|
||||
int rc = LDAP_SUCCESS;
|
||||
|
||||
lc = ldap_back_getconn( op, rs );
|
||||
if (!lc || !ldap_back_dobind( lc, op, rs ) ) {
|
||||
rc = -1;
|
||||
lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
|
||||
if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
|
@ -52,7 +51,6 @@ ldap_back_compare(
|
|||
rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
send_ldap_result( op, rs );
|
||||
rc = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
|
@ -61,10 +59,10 @@ retry:
|
|||
op->orc_ava->aa_desc->ad_cname.bv_val,
|
||||
&op->orc_ava->aa_value,
|
||||
ctrls, NULL, &msgid );
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, 1 );
|
||||
if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT );
|
||||
if ( rc == LDAP_UNAVAILABLE && do_retry ) {
|
||||
do_retry = 0;
|
||||
if ( ldap_back_retry(lc, op, rs ) ) {
|
||||
if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) {
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
|
@ -72,5 +70,5 @@ retry:
|
|||
cleanup:
|
||||
(void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
|
||||
|
||||
return rc;
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -213,6 +213,27 @@ ldap_back_db_config(
|
|||
li->url = ch_strdup( argv[ 1 ] );
|
||||
#endif
|
||||
|
||||
/* start tls */
|
||||
} else if ( strcasecmp( argv[0], "start-tls" ) == 0 ) {
|
||||
if ( argc != 1 ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: start-tls takes no arguments\n",
|
||||
fname, lineno );
|
||||
return( 1 );
|
||||
}
|
||||
li->flags |= LDAP_BACK_F_TLS_CRITICAL;
|
||||
|
||||
/* try start tls */
|
||||
} else if ( strcasecmp( argv[0], "try-start-tls" ) == 0 ) {
|
||||
if ( argc != 1 ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: try-start-tls takes no arguments\n",
|
||||
fname, lineno );
|
||||
return( 1 );
|
||||
}
|
||||
li->flags &= ~LDAP_BACK_F_TLS_CRITICAL;
|
||||
li->flags |= LDAP_BACK_F_USE_TLS;
|
||||
|
||||
/* name to use for ldap_back_group */
|
||||
} else if ( strcasecmp( argv[0], "acl-authcdn" ) == 0
|
||||
|| strcasecmp( argv[0], "binddn" ) == 0 )
|
||||
|
|
@ -272,7 +293,7 @@ ldap_back_db_config(
|
|||
fname, lineno );
|
||||
return( 1 );
|
||||
}
|
||||
li->savecred = 1;
|
||||
li->flags |= LDAP_BACK_F_SAVECRED;
|
||||
|
||||
/* intercept exop_who_am_i? */
|
||||
} else if ( strcasecmp( argv[0], "proxy-whoami" ) == 0 ) {
|
||||
|
|
@ -360,8 +381,8 @@ ldap_back_exop_whoami(
|
|||
|
||||
ctrls[0] = &c;
|
||||
op2.o_ndn = op->o_conn->c_ndn;
|
||||
lc = ldap_back_getconn(&op2, rs);
|
||||
if (!lc || !ldap_back_dobind( lc, op, rs )) {
|
||||
lc = ldap_back_getconn(&op2, rs, LDAP_BACK_SENDERR);
|
||||
if (!lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR )) {
|
||||
return -1;
|
||||
}
|
||||
c.ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
|
||||
|
|
@ -379,7 +400,7 @@ retry:
|
|||
&rs->sr_err);
|
||||
if ( rs->sr_err == LDAP_SERVER_DOWN && do_retry ) {
|
||||
do_retry = 0;
|
||||
if ( ldap_back_retry( lc, op, rs ) )
|
||||
if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) )
|
||||
goto retry;
|
||||
}
|
||||
ldap_back_freeconn( op, lc );
|
||||
|
|
|
|||
|
|
@ -42,9 +42,9 @@ ldap_back_delete(
|
|||
int do_retry = 1;
|
||||
int rc = LDAP_SUCCESS;
|
||||
|
||||
lc = ldap_back_getconn( op, rs );
|
||||
lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
|
||||
|
||||
if ( !lc || !ldap_back_dobind( lc, op, rs ) ) {
|
||||
if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
|
||||
rc = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
@ -60,10 +60,10 @@ ldap_back_delete(
|
|||
retry:
|
||||
rs->sr_err = ldap_delete_ext( lc->lc_ld, op->o_req_ndn.bv_val,
|
||||
ctrls, NULL, &msgid );
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, 1 );
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT );
|
||||
if ( rs->sr_err == LDAP_SERVER_DOWN && do_retry ) {
|
||||
do_retry = 0;
|
||||
if ( ldap_back_retry (lc, op, rs ) ) {
|
||||
if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) {
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ ldap_back_extended(
|
|||
* called twice; maybe we could avoid the
|
||||
* ldap_back_dobind() call inside each extended()
|
||||
* call ... */
|
||||
lc = ldap_back_getconn( op, rs );
|
||||
if ( !lc || !ldap_back_dobind( lc, op, rs ) ) {
|
||||
lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
|
||||
if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -99,8 +99,8 @@ ldap_back_exop_passwd(
|
|||
int rc, isproxy;
|
||||
int do_retry = 1;
|
||||
|
||||
lc = ldap_back_getconn( op, rs );
|
||||
if ( !lc || !ldap_back_dobind( lc, op, rs ) ) {
|
||||
lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
|
||||
if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -154,7 +154,7 @@ retry:
|
|||
rs->sr_err = slap_map_api2result( rs );
|
||||
if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
|
||||
do_retry = 0;
|
||||
if ( ldap_back_retry(lc, op, rs ) ) {
|
||||
if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) {
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,10 +144,10 @@ ldap_back_db_open( BackendDB *be )
|
|||
/* FIXME: disabled because namingContexts doesn't have
|
||||
* a matching rule, and using an MRA filter doesn't work
|
||||
* because the normalized assertion is compared to the
|
||||
* non-normalized value, which in general differ.
|
||||
* See ITS#3406 */
|
||||
* non-normalized value, which in general differs from
|
||||
* the normalized one. See ITS#3406 */
|
||||
struct berval filter,
|
||||
base = BER_BVC( "cn=Databases,cn=Monitor" );
|
||||
base = BER_BVC( "cn=Databases," SLAPD_MONITOR );
|
||||
struct berval vals[ 2 ];
|
||||
Attribute a = { 0 };
|
||||
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ ldap_back_modify(
|
|||
int do_retry = 1;
|
||||
LDAPControl **ctrls = NULL;
|
||||
|
||||
lc = ldap_back_getconn( op, rs );
|
||||
if ( !lc || !ldap_back_dobind( lc, op, rs ) ) {
|
||||
lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
|
||||
if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -106,10 +106,10 @@ ldap_back_modify(
|
|||
retry:
|
||||
rs->sr_err = ldap_modify_ext( lc->lc_ld, op->o_req_ndn.bv_val, modv,
|
||||
ctrls, NULL, &msgid );
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, 1 );
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT );
|
||||
if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
|
||||
do_retry = 0;
|
||||
if ( ldap_back_retry(lc, op, rs ) ) {
|
||||
if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) {
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ ldap_back_modrdn(
|
|||
int rc = LDAP_SUCCESS;
|
||||
char *newSup = NULL;
|
||||
|
||||
lc = ldap_back_getconn( op, rs );
|
||||
if ( !lc || !ldap_back_dobind( lc, op, rs ) ) {
|
||||
lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
|
||||
if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
|
|
@ -67,10 +67,10 @@ retry:
|
|||
rs->sr_err = ldap_rename( lc->lc_ld, op->o_req_ndn.bv_val,
|
||||
op->orr_newrdn.bv_val, newSup,
|
||||
op->orr_deleteoldrdn, ctrls, NULL, &msgid );
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, 1 );
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT );
|
||||
if ( rs->sr_err == LDAP_SERVER_DOWN && do_retry ) {
|
||||
do_retry = 0;
|
||||
if ( ldap_back_retry( lc, op, rs ) ) {
|
||||
if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) {
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,12 +49,12 @@ extern BI_connection_destroy ldap_back_conn_destroy;
|
|||
extern BI_entry_get_rw ldap_back_entry_get;
|
||||
|
||||
int ldap_back_freeconn( Operation *op, struct ldapconn *lc );
|
||||
struct ldapconn *ldap_back_getconn(struct slap_op *op, struct slap_rep *rs);
|
||||
int ldap_back_dobind(struct ldapconn *lc, Operation *op, SlapReply *rs);
|
||||
int ldap_back_retry(struct ldapconn *lc, Operation *op, SlapReply *rs);
|
||||
struct ldapconn *ldap_back_getconn(struct slap_op *op, struct slap_rep *rs, ldap_back_send_t sendok);
|
||||
int ldap_back_dobind(struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok);
|
||||
int ldap_back_retry(struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok);
|
||||
int ldap_back_map_result(SlapReply *rs);
|
||||
int ldap_back_op_result(struct ldapconn *lc, Operation *op, SlapReply *rs,
|
||||
ber_int_t msgid, int sendok);
|
||||
ber_int_t msgid, ldap_back_send_t sendok);
|
||||
int back_ldap_LTX_init_module(int argc, char *argv[]);
|
||||
|
||||
extern int ldap_back_conn_cmp( const void *c1, const void *c2);
|
||||
|
|
|
|||
|
|
@ -60,17 +60,17 @@ ldap_back_search(
|
|||
int do_retry = 1;
|
||||
LDAPControl **ctrls = NULL;
|
||||
|
||||
lc = ldap_back_getconn( op, rs );
|
||||
lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
|
||||
if ( !lc ) {
|
||||
return -1;
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: in case of values return filter, we might want
|
||||
* to map attrs and maybe rewrite value
|
||||
*/
|
||||
if ( !ldap_back_dobind( lc, op, rs ) ) {
|
||||
return -1;
|
||||
if ( !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
/* should we check return values? */
|
||||
|
|
@ -120,7 +120,7 @@ retry:
|
|||
|
||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||
fail:;
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, 0 );
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDERR );
|
||||
if ( freeconn ) {
|
||||
ldap_back_freeconn( op, lc );
|
||||
lc = NULL;
|
||||
|
|
@ -249,7 +249,7 @@ fail:;
|
|||
if ( rc == -1 ) {
|
||||
if ( do_retry ) {
|
||||
do_retry = 0;
|
||||
if ( ldap_back_retry( lc, op, rs ) ) {
|
||||
if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) {
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
|
@ -500,7 +500,6 @@ ldap_back_entry_get(
|
|||
*e = NULL;
|
||||
char *gattr[3];
|
||||
char *filter = NULL;
|
||||
Connection *oconn;
|
||||
SlapReply rs;
|
||||
int do_retry = 1;
|
||||
LDAPControl **ctrls = NULL;
|
||||
|
|
@ -508,16 +507,12 @@ ldap_back_entry_get(
|
|||
/* Tell getconn this is a privileged op */
|
||||
do_not_cache = op->o_do_not_cache;
|
||||
op->o_do_not_cache = 1;
|
||||
lc = ldap_back_getconn( op, &rs );
|
||||
oconn = op->o_conn;
|
||||
op->o_conn = NULL;
|
||||
if ( !lc || !ldap_back_dobind( lc, op, &rs ) ) {
|
||||
lc = ldap_back_getconn( op, &rs, LDAP_BACK_DONTSEND );
|
||||
if ( !lc || !ldap_back_dobind( lc, op, &rs, LDAP_BACK_DONTSEND ) ) {
|
||||
op->o_do_not_cache = do_not_cache;
|
||||
op->o_conn = oconn;
|
||||
return 1;
|
||||
return rs.sr_err;
|
||||
}
|
||||
op->o_do_not_cache = do_not_cache;
|
||||
op->o_conn = oconn;
|
||||
|
||||
if ( at ) {
|
||||
if ( oc && at != slap_schema.si_ad_objectClass ) {
|
||||
|
|
@ -555,7 +550,7 @@ retry:
|
|||
if ( rc != LDAP_SUCCESS ) {
|
||||
if ( rc == LDAP_SERVER_DOWN && do_retry ) {
|
||||
do_retry = 0;
|
||||
if ( ldap_back_retry( lc, op, &rs ) ) {
|
||||
if ( ldap_back_retry( lc, op, &rs, LDAP_BACK_DONTSEND ) ) {
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,15 +85,6 @@ typedef struct dncookie {
|
|||
#define META_BIND_NRETRIES 3
|
||||
#define META_BIND_TIMEOUT 1000
|
||||
|
||||
int ldap_back_freeconn( Operation *op, struct ldapconn *lc );
|
||||
struct ldapconn *ldap_back_getconn(struct slap_op *op, struct slap_rep *rs);
|
||||
int ldap_back_dobind(struct ldapconn *lc, Operation *op, SlapReply *rs);
|
||||
int ldap_back_retry(struct ldapconn *lc, Operation *op, SlapReply *rs);
|
||||
int ldap_back_map_result(SlapReply *rs);
|
||||
int ldap_back_op_result(struct ldapconn *lc, Operation *op, SlapReply *rs,
|
||||
ber_int_t msgid, int sendok);
|
||||
int back_ldap_LTX_init_module(int argc, char *argv[]);
|
||||
|
||||
int ldap_back_dn_massage(dncookie *dc, struct berval *dn,
|
||||
struct berval *res);
|
||||
|
||||
|
|
|
|||
|
|
@ -386,6 +386,10 @@ pager: +1 313 555 7671
|
|||
facsimileTelephoneNumber: +1 313 555 7762
|
||||
telephoneNumber: +1 313 555 4177
|
||||
|
||||
dn: ou=Other,dc=example,dc=com
|
||||
objectClass: organizationalUnit
|
||||
ou: Other
|
||||
|
||||
dn: ou=People,dc=example,dc=com
|
||||
objectClass: organizationalUnit
|
||||
objectClass: extensibleObject
|
||||
|
|
|
|||
|
|
@ -365,6 +365,10 @@ pager: +1 313 555 7671
|
|||
facsimileTelephoneNumber: +1 313 555 7762
|
||||
telephoneNumber: +1 313 555 4177
|
||||
|
||||
dn: ou=Other,dc=example,dc=com
|
||||
objectClass: organizationalUnit
|
||||
ou: Other
|
||||
|
||||
dn: ou=People,dc=example,dc=com
|
||||
objectClass: organizationalUnit
|
||||
objectClass: extensibleObject
|
||||
|
|
|
|||
4
tests/data/chainref.out
Normal file
4
tests/data/chainref.out
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
dn: ou=Other,dc=example,dc=com
|
||||
objectClass: organizationalUnit
|
||||
ou: Other
|
||||
|
||||
|
|
@ -29,6 +29,14 @@ objectclass: extensibleobject
|
|||
ou: Groups
|
||||
ref: @URI2@ou=Groups,dc=example,dc=com
|
||||
|
||||
dn: ou=Other,dc=example,dc=com
|
||||
objectclass: referral
|
||||
objectclass: extensibleobject
|
||||
ou: Other
|
||||
# invalid URI first to test failover capabilities (search only)
|
||||
ref: @URI3@ou=Other,dc=example,dc=com
|
||||
ref: @URI2@ou=Other,dc=example,dc=com
|
||||
|
||||
dn: ou=Alumni Association,ou=People,dc=example,dc=com
|
||||
objectclass: organizationalUnit
|
||||
ou: Alumni Association
|
||||
|
|
|
|||
|
|
@ -81,3 +81,8 @@ cn: Dir Man
|
|||
sn: Manager
|
||||
description: Manager of the directory
|
||||
userpassword:: c2VjcmV0
|
||||
|
||||
dn: ou=Other,dc=example,dc=com
|
||||
objectclass: organizationalUnit
|
||||
ou: Other
|
||||
|
||||
|
|
|
|||
|
|
@ -235,6 +235,7 @@ LDAPGLUEOUT=$DATADIR/ldapglue.out
|
|||
LDAPGLUEANONYMOUSOUT=$DATADIR/ldapglueanonymous.out
|
||||
RELAYOUT=$DATADIR/relay.out
|
||||
CHAINOUT=$DATADIR/chain.out
|
||||
CHAINREFOUT=$DATADIR/chainref.out
|
||||
CHAINMODOUT=$DATADIR/chainmod.out
|
||||
SQLREAD=$DATADIR/sql-read.out
|
||||
SQLWRITE=$DATADIR/sql-write.out
|
||||
|
|
|
|||
|
|
@ -110,6 +110,31 @@ for P in $PORT1 $PORT2 ; do
|
|||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Reading the referral entry "ou=Other,$BASEDN" as anonymous on port $P..."
|
||||
$LDAPSEARCH -h $LOCALHOST -p $P -b "ou=Other,$BASEDN" -S "" \
|
||||
> $SEARCHOUT 2>&1
|
||||
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapsearch failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
echo "Filtering ldapsearch results..."
|
||||
. $LDIFFILTER < $SEARCHOUT > $SEARCHFLT
|
||||
echo "Filtering original ldif used to create database..."
|
||||
. $LDIFFILTER < $CHAINREFOUT > $LDIFFLT
|
||||
echo "Comparing filter output..."
|
||||
$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
|
||||
|
||||
if test $? != 0 ; then
|
||||
echo "comparison failed - chained search didn't succeed"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit 1
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
#
|
||||
|
|
|
|||
Loading…
Reference in a new issue