port identity assertion to back-meta; share as much code as possible with back-ldap; misc cleanup

This commit is contained in:
Pierangelo Masarati 2006-06-15 23:12:38 +00:00
parent 3f9201e95b
commit 3ebb40c4dd
24 changed files with 1000 additions and 363 deletions

View 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;

View 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;

View 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,14 +1725,15 @@ 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;
int i = 0;
slap_idassert_mode_t mode;
struct berval assertedID,
ndn;
@ -1759,7 +1742,7 @@ ldap_back_proxy_authz_ctrl(
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;

View 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;

View 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:

View 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;

View 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;

View 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;

View 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;

View 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;

View 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

View 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;
}

View 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 );
}
}

View 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,

View File

@ -34,6 +34,16 @@
#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 ) {
@ -669,6 +679,7 @@ 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 );
}

View File

@ -214,10 +214,8 @@ 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 ] );
}
}
return 0;
}

View 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 );

View 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 ) {

View 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 {
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 );
}
}

View 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 );
}
}

View 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 );

View 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 );
}
}

View 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 );
}
}

View 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 );
/* 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_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 );
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,