mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-01-08 08:02:16 -05:00
uniformly exploit rootdn bind; add support for rootdn bind to backends that didn't have it (ITS#4962)
This commit is contained in:
parent
15545731bc
commit
27428ac00e
14 changed files with 158 additions and 62 deletions
|
|
@ -40,10 +40,14 @@ bdb_bind( Operation *op, SlapReply *rs )
|
|||
op->o_req_dn.bv_val, 0, 0);
|
||||
|
||||
/* allow noauth binds */
|
||||
if ( op->oq_bind.rb_method == LDAP_AUTH_SIMPLE && be_isroot_pw( op )) {
|
||||
ber_dupbv( &op->oq_bind.rb_edn, be_root_dn( op->o_bd ) );
|
||||
/* front end will send result */
|
||||
return LDAP_SUCCESS;
|
||||
switch ( be_rootdn_bind( op, rs ) ) {
|
||||
case SLAP_CB_CONTINUE:
|
||||
break;
|
||||
|
||||
default:
|
||||
/* in case of success, frontend will send result;
|
||||
* otherwise, be_rootdn_bind() did */
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
rs->sr_err = LOCK_ID(bdb->bi_dbenv, &locker);
|
||||
|
|
|
|||
|
|
@ -32,30 +32,42 @@
|
|||
|
||||
int
|
||||
dnssrv_back_bind(
|
||||
Operation *op,
|
||||
SlapReply *rs )
|
||||
Operation *op,
|
||||
SlapReply *rs )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE, "DNSSRV: bind %s (%d)\n",
|
||||
op->o_req_dn.bv_val == NULL ? "" : op->o_req_dn.bv_val,
|
||||
op->oq_bind.rb_method, NULL );
|
||||
|
||||
if ( op->oq_bind.rb_method == LDAP_AUTH_SIMPLE &&
|
||||
!BER_BVISNULL( &op->oq_bind.rb_cred ) &&
|
||||
!BER_BVISEMPTY( &op->oq_bind.rb_cred ) )
|
||||
Debug( LDAP_DEBUG_TRACE, "DNSSRV: bind dn=\"%s\" (%d)\n",
|
||||
BER_BVISNULL( &op->o_req_dn ) ? "" : op->o_req_dn.bv_val,
|
||||
op->orb_method, 0 );
|
||||
|
||||
/* allow rootdn as a means to auth without the need to actually
|
||||
* contact the proxied DSA */
|
||||
switch ( be_rootdn_bind( op, NULL ) ) {
|
||||
case LDAP_SUCCESS:
|
||||
/* frontend will send result */
|
||||
return rs->sr_err;
|
||||
|
||||
default:
|
||||
/* treat failure and like any other bind, otherwise
|
||||
* it could reveal the DN of the rootdn */
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &op->orb_cred ) &&
|
||||
!BER_BVISEMPTY( &op->orb_cred ) )
|
||||
{
|
||||
/* simple bind */
|
||||
Statslog( LDAP_DEBUG_STATS,
|
||||
"%s DNSSRV BIND dn=\"%s\" provided passwd\n",
|
||||
"%s DNSSRV BIND dn=\"%s\" provided cleartext passwd\n",
|
||||
op->o_log_prefix,
|
||||
BER_BVISNULL( &op->o_req_dn ) ? "" : op->o_req_dn.bv_val , 0, 0, 0 );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"DNSSRV: BIND dn=\"%s\" provided cleartext password\n",
|
||||
BER_BVISNULL( &op->o_req_dn ) ? "" : op->o_req_dn.bv_val, 0, 0 );
|
||||
|
||||
send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
|
||||
"you shouldn't send strangers your password" );
|
||||
|
||||
} else {
|
||||
/* unauthenticated bind */
|
||||
/* NOTE: we're not going to get here anyway:
|
||||
* unauthenticated bind is dealt with by the frontend */
|
||||
Debug( LDAP_DEBUG_TRACE, "DNSSRV: BIND dn=\"%s\"\n",
|
||||
BER_BVISNULL( &op->o_req_dn ) ? "" : op->o_req_dn.bv_val, 0, 0 );
|
||||
|
||||
|
|
|
|||
|
|
@ -177,6 +177,16 @@ ldap_back_bind( Operation *op, SlapReply *rs )
|
|||
ber_int_t msgid;
|
||||
ldap_back_send_t retrying = LDAP_BACK_RETRYING;
|
||||
|
||||
/* allow rootdn as a means to auth without the need to actually
|
||||
* contact the proxied DSA */
|
||||
switch ( be_rootdn_bind( op, rs ) ) {
|
||||
case SLAP_CB_CONTINUE:
|
||||
break;
|
||||
|
||||
default:
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
lc = ldap_back_getconn( op, rs, LDAP_BACK_BIND_SERR, NULL, NULL );
|
||||
if ( !lc ) {
|
||||
return rs->sr_err;
|
||||
|
|
|
|||
|
|
@ -773,17 +773,23 @@ ldif_back_bind( Operation *op, SlapReply *rs )
|
|||
int return_val = 0;
|
||||
Entry * entry = NULL;
|
||||
|
||||
switch ( be_rootdn_bind( op, rs ) ) {
|
||||
case SLAP_CB_CONTINUE:
|
||||
break;
|
||||
|
||||
default:
|
||||
/* in case of success, front end will send result;
|
||||
* otherwise, be_rootdn_bind() did */
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
li = (struct ldif_info *) op->o_bd->be_private;
|
||||
ldap_pvt_thread_rdwr_rlock(&li->li_rdwr);
|
||||
entry = get_entry(op, &li->li_base_path);
|
||||
|
||||
/* no object is found for them */
|
||||
if(entry == NULL) {
|
||||
if(be_isroot_pw(op)) {
|
||||
rs->sr_err = return_val = LDAP_SUCCESS;
|
||||
} else {
|
||||
rs->sr_err = return_val = LDAP_INVALID_CREDENTIALS;
|
||||
}
|
||||
rs->sr_err = return_val = LDAP_INVALID_CREDENTIALS;
|
||||
goto return_result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,24 +72,22 @@ meta_back_bind( Operation *op, SlapReply *rs )
|
|||
op->o_log_prefix, op->o_req_dn.bv_val, 0 );
|
||||
|
||||
/* the test on the bind method should be superfluous */
|
||||
if ( op->orb_method == LDAP_AUTH_SIMPLE
|
||||
&& be_isroot_dn( op->o_bd, &op->o_req_ndn ) )
|
||||
{
|
||||
if ( !be_isroot_pw( op ) ) {
|
||||
rs->sr_err = LDAP_INVALID_CREDENTIALS;
|
||||
rs->sr_text = NULL;
|
||||
send_ldap_result( op, rs );
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
switch ( be_rootdn_bind( op, rs ) ) {
|
||||
case LDAP_SUCCESS:
|
||||
if ( META_BACK_DEFER_ROOTDN_BIND( mi ) ) {
|
||||
rs->sr_err = LDAP_SUCCESS;
|
||||
rs->sr_text = NULL;
|
||||
/* frontend will return success */
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
isroot = 1;
|
||||
/* fallthru */
|
||||
|
||||
case SLAP_CB_CONTINUE:
|
||||
break;
|
||||
|
||||
default:
|
||||
/* be_rootdn_bind() sent result */
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
/* we need meta_back_getconn() not send result even on error,
|
||||
|
|
|
|||
|
|
@ -35,11 +35,8 @@ monitor_back_bind( Operation *op, SlapReply *rs )
|
|||
{
|
||||
Debug(LDAP_DEBUG_ARGS, "==> monitor_back_bind: dn: %s\n",
|
||||
op->o_req_dn.bv_val, 0, 0 );
|
||||
|
||||
if ( op->oq_bind.rb_method == LDAP_AUTH_SIMPLE
|
||||
&& be_isroot_pw( op ) )
|
||||
{
|
||||
ber_dupbv( &op->oq_bind.rb_edn, be_root_dn( op->o_bd ) );
|
||||
|
||||
if ( be_isroot_pw( op ) ) {
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,16 @@ perl_back_bind(
|
|||
|
||||
PerlBackend *perl_back = (PerlBackend *) op->o_bd->be_private;
|
||||
|
||||
/* allow rootdn as a means to auth without the need to actually
|
||||
* contact the proxied DSA */
|
||||
switch ( be_rootdn_bind( op, rs ) ) {
|
||||
case SLAP_CB_CONTINUE:
|
||||
break;
|
||||
|
||||
default:
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
#if defined(HAVE_WIN32_ASPERL) || defined(USE_ITHREADS)
|
||||
PERL_SET_CONTEXT( PERL_INTERPRETER );
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -111,6 +111,16 @@ relay_back_op_bind( Operation *op, SlapReply *rs )
|
|||
BackendDB *bd;
|
||||
int rc = 1;
|
||||
|
||||
/* allow rootdn as a means to auth without the need to actually
|
||||
* contact the proxied DSA */
|
||||
switch ( be_rootdn_bind( op, rs ) ) {
|
||||
case SLAP_CB_CONTINUE:
|
||||
break;
|
||||
|
||||
default:
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
bd = relay_back_select_backend( op, rs, LDAP_INVALID_CREDENTIALS, 1 );
|
||||
if ( bd == NULL ) {
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -49,6 +49,16 @@ shell_back_bind(
|
|||
FILE *rfp, *wfp;
|
||||
int rc;
|
||||
|
||||
/* allow rootdn as a means to auth without the need to actually
|
||||
* contact the proxied DSA */
|
||||
switch ( be_rootdn_bind( op, rs ) ) {
|
||||
case SLAP_CB_CONTINUE:
|
||||
break;
|
||||
|
||||
default:
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
if ( si->si_bind == NULL ) {
|
||||
send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
|
||||
"bind not implemented" );
|
||||
|
|
|
|||
|
|
@ -40,25 +40,18 @@ backsql_bind( Operation *op, SlapReply *rs )
|
|||
|
||||
Debug( LDAP_DEBUG_TRACE, "==>backsql_bind()\n", 0, 0, 0 );
|
||||
|
||||
if ( be_isroot_pw( op ) ) {
|
||||
ber_dupbv( &op->oq_bind.rb_edn, be_root_dn( op->o_bd ) );
|
||||
Debug( LDAP_DEBUG_TRACE, "<==backsql_bind() root bind\n",
|
||||
0, 0, 0 );
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
switch ( be_rootdn_bind( op, rs ) ) {
|
||||
case SLAP_CB_CONTINUE:
|
||||
break;
|
||||
|
||||
ber_dupbv( &op->oq_bind.rb_edn, &op->o_req_ndn );
|
||||
|
||||
if ( op->oq_bind.rb_method != LDAP_AUTH_SIMPLE ) {
|
||||
rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED;
|
||||
rs->sr_text = "authentication method not supported";
|
||||
send_ldap_result( op, rs );
|
||||
default:
|
||||
/* in case of success, front end will send result;
|
||||
* otherwise, be_rootdn_bind() did */
|
||||
Debug( LDAP_DEBUG_TRACE, "<==backsql_bind(%d)\n",
|
||||
rs->sr_err, 0, 0 );
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
/*
|
||||
* method = LDAP_AUTH_SIMPLE
|
||||
*/
|
||||
rs->sr_err = backsql_get_db_conn( op, &dbh );
|
||||
if ( !dbh ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "backsql_bind(): "
|
||||
|
|
|
|||
|
|
@ -765,14 +765,40 @@ be_isroot( Operation *op )
|
|||
int
|
||||
be_isroot_pw( Operation *op )
|
||||
{
|
||||
int result;
|
||||
return be_rootdn_bind( op, NULL ) == LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
if ( ! be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) {
|
||||
return 0;
|
||||
/*
|
||||
* checks if binding as rootdn
|
||||
*
|
||||
* return value:
|
||||
* SLAP_CB_CONTINUE if not the rootdn
|
||||
* LDAP_SUCCESS if rootdn & rootpw
|
||||
* LDAP_INVALID_CREDENTIALS if rootdn & !rootpw
|
||||
*
|
||||
* if rs != NULL
|
||||
* if LDAP_SUCCESS, op->orb_edn is set
|
||||
* if LDAP_INVALID_CREDENTIALS, response is sent to client
|
||||
*/
|
||||
int
|
||||
be_rootdn_bind( Operation *op, SlapReply *rs )
|
||||
{
|
||||
int rc;
|
||||
|
||||
assert( op->o_tag == LDAP_REQ_BIND );
|
||||
assert( op->orb_method == LDAP_AUTH_SIMPLE );
|
||||
|
||||
if ( !be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) {
|
||||
return SLAP_CB_CONTINUE;
|
||||
}
|
||||
|
||||
if ( BER_BVISEMPTY( &op->o_bd->be_rootpw ) ) {
|
||||
return 0;
|
||||
rc = LDAP_INVALID_CREDENTIALS;
|
||||
if ( rs ) {
|
||||
goto send_result;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef SLAPD_SPASSWD
|
||||
|
|
@ -780,13 +806,31 @@ be_isroot_pw( Operation *op )
|
|||
op->o_conn->c_sasl_authctx, NULL );
|
||||
#endif
|
||||
|
||||
result = lutil_passwd( &op->o_bd->be_rootpw, &op->orb_cred, NULL, NULL );
|
||||
rc = lutil_passwd( &op->o_bd->be_rootpw, &op->orb_cred, NULL, NULL );
|
||||
|
||||
#ifdef SLAPD_SPASSWD
|
||||
ldap_pvt_thread_pool_setkey( op->o_threadctx, slap_sasl_bind, NULL, NULL );
|
||||
#endif
|
||||
|
||||
return result == 0;
|
||||
rc = ( rc == 0 ? LDAP_SUCCESS : LDAP_INVALID_CREDENTIALS );
|
||||
if ( rs ) {
|
||||
send_result:;
|
||||
rs->sr_err = rc;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "%s: rootdn=\"%s\" bind%s\n",
|
||||
op->o_log_prefix, op->o_bd->be_rootdn.bv_val,
|
||||
rc == LDAP_SUCCESS ? " succeeded" : " failed" );
|
||||
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
/* Set to the pretty rootdn */
|
||||
ber_dupbv( &op->orb_edn, &op->o_bd->be_rootdn );
|
||||
|
||||
} else {
|
||||
send_ldap_result( op, rs );
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
|||
|
|
@ -3306,7 +3306,7 @@ done:
|
|||
static int
|
||||
config_back_bind( Operation *op, SlapReply *rs )
|
||||
{
|
||||
if ( op->orb_method == LDAP_AUTH_SIMPLE && be_isroot_pw( op )) {
|
||||
if ( be_isroot_pw( op ) ) {
|
||||
ber_dupbv( &op->orb_edn, be_root_dn( op->o_bd ));
|
||||
/* frontend sends result */
|
||||
return LDAP_SUCCESS;
|
||||
|
|
|
|||
|
|
@ -305,6 +305,7 @@ retcode_op_func( Operation *op, SlapReply *rs )
|
|||
|
||||
case LDAP_REQ_BIND:
|
||||
/* skip if rootdn */
|
||||
/* FIXME: better give the db a chance? */
|
||||
if ( be_isroot_pw( op ) ) {
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -345,6 +345,7 @@ LDAP_SLAPD_F (int) be_issubordinate LDAP_P(( Backend *be,
|
|||
LDAP_SLAPD_F (int) be_isroot LDAP_P(( Operation *op ));
|
||||
LDAP_SLAPD_F (int) be_isroot_dn LDAP_P(( Backend *be, struct berval *ndn ));
|
||||
LDAP_SLAPD_F (int) be_isroot_pw LDAP_P(( Operation *op ));
|
||||
LDAP_SLAPD_F (int) be_rootdn_bind LDAP_P(( Operation *op, SlapReply *rs ));
|
||||
LDAP_SLAPD_F (int) be_slurp_update LDAP_P(( Operation *op ));
|
||||
#define be_isupdate( op ) be_slurp_update( (op) )
|
||||
LDAP_SLAPD_F (int) be_shadow_update LDAP_P(( Operation *op ));
|
||||
|
|
|
|||
Loading…
Reference in a new issue