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;
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)
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
*/
#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
*/
#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;
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;
int
ldap_back_proxy_authz_ctrl(
struct berval *bound_ndn,
+ int version,
+ slap_idassert_t *si,
Operation *op,
SlapReply *rs,
LDAPControl ***pctrls )
{
- ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private;
- LDAPControl **ctrls = NULL;
- int i = 0,
- mode;
- struct berval assertedID,
- ndn;
+ LDAPControl **ctrls = NULL;
+ int i = 0;
+ slap_idassert_mode_t mode;
+ struct berval assertedID,
+ ndn;
*pctrls = NULL;
rs->sr_err = LDAP_SUCCESS;
/* don't proxyAuthz if protocol is not LDAPv3 */
- switch ( li->li_version ) {
+ switch ( version ) {
case LDAP_VERSION3:
break;
/* 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;
}
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
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;
} 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;
mode = LDAP_BACK_IDASSERT_NOASSERT;
} else {
- mode = li->li_idassert_mode;
+ mode = si->si_mode;
}
switch ( mode ) {
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:
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:
* 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;
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;
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;
}
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;
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 )
{
/* 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;
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:
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 */
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:
}
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;
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;
}
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;
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;
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;
}
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;
extern int
ldap_back_proxy_authz_ctrl(
struct berval *bound_ndn,
+ int version,
+ slap_idassert_t *si,
Operation *op,
SlapReply *rs,
LDAPControl ***pctrls );
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
}
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;
}
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;
}
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;
}
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;
dncookie dc;
int msgid;
int do_retry = 1;
+ LDAPControl **ctrls = NULL;
int maperr = 1;
Debug(LDAP_DEBUG_ARGS, "==> meta_back_add: %s\n",
/*
* 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";
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;
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 ];
}
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 ) ) {
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;
}
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 ) {
}
}
+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 );
}
}
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)
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,
#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 )
{
}
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 ];
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;
}
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,
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 ) {
"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 ) {
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;
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,
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
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;
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 );
/*
}
- 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 ) {
continue;
} /* else */
-
+
+retry_ok:;
Debug( LDAP_DEBUG_TRACE,
"%s meta_back_dobind[%d]: "
"(%s)\n",
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 );
+}
int c;
for ( c = 0; c < mi->mi_ntargets; c++ ) {
- if ( mc->mc_conns[ c ].msc_ld != NULL ) {
- meta_clear_one_candidate( &mc->mc_conns[ c ] );
- }
+ meta_clear_one_candidate( &mc->mc_conns[ c ] );
}
return 0;
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;
/*
* 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:
* 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 );
* 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' ) {
}
}
+ 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
*/
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 );
goto finish;
}
+ /* FIXME: matched? referrals? response controls? */
rc = ldap_parse_result( msc->msc_ld, res,
&rs->sr_err,
NULL, NULL, NULL, NULL, 1 );
}
/* 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 );
}
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;
}
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 */
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 ) {
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;
*/
if ( ispriv ) {
- if ( !BER_BVISNULL( &mt->mt_pseudorootdn ) ) {
- ber_dupbv( &msc->msc_bound_ndn, &mt->mt_pseudorootdn );
- if ( !BER_BVISNULL( &mt->mt_pseudorootpw ) ) {
- ber_dupbv( &msc->msc_cred, &mt->mt_pseudorootpw );
+ if ( !BER_BVISNULL( &mt->mt_idassert_authcDN ) ) {
+ ber_bvreplace( &msc->msc_bound_ndn, &mt->mt_idassert_authcDN );
+ if ( !BER_BVISNULL( &mt->mt_idassert_passwd ) ) {
+ ber_bvreplace( &msc->msc_cred, &mt->mt_idassert_passwd );
}
} else {
- ber_str2bv( "", 0, 1, &msc->msc_bound_ndn );
+ ber_bvreplace( &msc->msc_bound_ndn, &slap_empty_bv );
}
LDAP_BACK_CONN_ISPRIV_SET( msc );
} else {
- BER_BVZERO( &msc->msc_cred );
- BER_BVZERO( &msc->msc_bound_ndn );
+ if ( !BER_BVISNULL( &msc->msc_cred ) ) {
+ memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
+ ber_memfree_x( msc->msc_cred.bv_val, NULL );
+ BER_BVZERO( &msc->msc_cred );
+ }
+ if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
+ ber_memfree_x( msc->msc_bound_ndn.bv_val, NULL );
+ BER_BVZERO( &msc->msc_bound_ndn );
+ }
if ( !BER_BVISEMPTY( &op->o_ndn )
&& SLAP_IS_AUTHZ_BACKEND( op )
&& isauthz )
}
} else {
- ber_str2bv( "", 0, 1, &msc->msc_bound_ndn );
+ ber_dupbv( &msc->msc_bound_ndn, &slap_empty_bv );
}
}
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;
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 ) ) {
/*
* 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";
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 ) ) {
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;
}
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 ) {
}
}
+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 );
}
}
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 );
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;
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 ) ) {
/*
* 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";
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 ) ) {
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 ];
}
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 ) ) {
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;
}
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 ) {
}
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 );
}
}
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,
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 ) ) {
assert( mc->mc_conns[ candidate ].msc_ld != NULL );
+ mt = mi->mi_targets[ candidate ];
+ dc.target = mt;
dc.conn = op->o_conn;
dc.rs = rs;
*/
/* needs LDAPv3 */
- switch ( mi->mi_targets[ candidate ]->mt_version ) {
+ switch ( mt->mt_version ) {
case LDAP_VERSION3:
break;
/*
* 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;
/*
* 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;
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 ) ) {
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;
}
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 ) {
}
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 );
}
}
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;
LDAP_BACK_CONN_BINDING_SET( msc );
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
- if ( be_isroot( op ) && !BER_BVISNULL( &mt->mt_pseudorootdn ) ) {
- binddn = mt->mt_pseudorootdn.bv_val;
- cred = mt->mt_pseudorootpw;
- }
+ /* NOTE: this obsoletes pseudorootdn */
+ if ( op->o_conn != NULL &&
+ !op->o_do_not_cache &&
+ ( BER_BVISNULL( &msc->msc_bound_ndn ) ||
+ BER_BVISEMPTY( &msc->msc_bound_ndn ) ||
+ ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
+ {
+ rc = meta_back_proxy_authz_cred( mc, candidate, op, rs, LDAP_BACK_DONTSEND, &binddn, &cred, &method );
+ if ( rc != LDAP_SUCCESS ) {
+ goto down;
+ }
- /*
- * Otherwise an anonymous bind is performed
- * (note: if the target was already bound, the anonymous
- * bind clears the previous bind).
- */
- if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
- ber_memfree( msc->msc_bound_ndn.bv_val );
- BER_BVZERO( &msc->msc_bound_ndn );
- }
-
- if ( LDAP_BACK_SAVECRED( mi ) && !BER_BVISNULL( &msc->msc_cred ) ) {
- /* destroy sensitive data */
- memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
- ber_memfree( msc->msc_cred.bv_val );
- BER_BVZERO( &msc->msc_cred );
+ /* NOTE: we copy things here, even if bind didn't succeed yet,
+ * because the connection is not shared until bind is over */
+ if ( !BER_BVISNULL( &binddn ) ) {
+ ber_bvreplace( &msc->msc_bound_ndn, &binddn );
+ if ( LDAP_BACK_SAVECRED( mi ) && !BER_BVISNULL( &cred ) ) {
+ ber_dupbv( &msc->msc_cred, &cred );
+ }
+ }
+
+ if ( LDAP_BACK_CONN_ISBOUND( msc ) ) {
+ /* idassert ws configured with SASL bind */
+ ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+ LDAP_BACK_CONN_BINDING_CLEAR( msc );
+ ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+ return META_SEARCH_CANDIDATE;
+ }
+
+ /* paranoid */
+ switch ( method ) {
+ case LDAP_AUTH_NONE:
+ case LDAP_AUTH_SIMPLE:
+ /* do a simple bind with binddn, cred */
+ break;
+
+ default:
+ assert( 0 );
+ break;
+ }
}
-retry:;
assert( msc->msc_ld != NULL );
- rc = ldap_sasl_bind( msc->msc_ld, binddn, LDAP_SASL_SIMPLE, &cred,
+ rc = ldap_sasl_bind( msc->msc_ld, binddn.bv_val, LDAP_SASL_SIMPLE, &cred,
NULL, NULL, &candidates[ candidate ].sr_msgid );
switch ( rc ) {
case LDAP_SUCCESS:
META_BINDING_SET( &candidates[ candidate ] );
return META_SEARCH_BINDING;
+down:;
case LDAP_SERVER_DOWN:
- if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
- nretries = 0;
- goto retry;
+ if ( meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
+ return META_SEARCH_CANDIDATE;
}
if ( *mcp == NULL ) {
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 );
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 ) {
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
*/
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:
}
done:;
+ (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
+
if ( mapped_attrs ) {
free( mapped_attrs );
}
* 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,