From: Pierangelo Masarati Date: Thu, 16 Aug 2007 09:38:15 +0000 (+0000) Subject: uniformly exploit rootdn bind; add support for rootdn bind to backends that didn... X-Git-Tag: OPENLDAP_REL_ENG_2_4_MP~209 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=27428ac00eaf1674abb515c7a7c4ba74c06b5db9;p=openldap uniformly exploit rootdn bind; add support for rootdn bind to backends that didn't have it (ITS#4962) --- diff --git a/servers/slapd/back-bdb/bind.c b/servers/slapd/back-bdb/bind.c index 84f3a38a0e..634d398b07 100644 --- a/servers/slapd/back-bdb/bind.c +++ b/servers/slapd/back-bdb/bind.c @@ -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); diff --git a/servers/slapd/back-dnssrv/bind.c b/servers/slapd/back-dnssrv/bind.c index 20fd959fc5..6bf68fda5d 100644 --- a/servers/slapd/back-dnssrv/bind.c +++ b/servers/slapd/back-dnssrv/bind.c @@ -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 ); diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c index 9d122e36a2..ebc51bdbd0 100644 --- a/servers/slapd/back-ldap/bind.c +++ b/servers/slapd/back-ldap/bind.c @@ -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; diff --git a/servers/slapd/back-ldif/ldif.c b/servers/slapd/back-ldif/ldif.c index 5bbd8fe4ff..6adee351ad 100644 --- a/servers/slapd/back-ldif/ldif.c +++ b/servers/slapd/back-ldif/ldif.c @@ -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; } diff --git a/servers/slapd/back-meta/bind.c b/servers/slapd/back-meta/bind.c index 1434112362..252e726441 100644 --- a/servers/slapd/back-meta/bind.c +++ b/servers/slapd/back-meta/bind.c @@ -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, diff --git a/servers/slapd/back-monitor/bind.c b/servers/slapd/back-monitor/bind.c index bc7dbc5298..984253479b 100644 --- a/servers/slapd/back-monitor/bind.c +++ b/servers/slapd/back-monitor/bind.c @@ -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; } diff --git a/servers/slapd/back-perl/bind.c b/servers/slapd/back-perl/bind.c index 2e19370f49..878c48dfb0 100644 --- a/servers/slapd/back-perl/bind.c +++ b/servers/slapd/back-perl/bind.c @@ -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 diff --git a/servers/slapd/back-relay/op.c b/servers/slapd/back-relay/op.c index e3a40db3a3..0616472458 100644 --- a/servers/slapd/back-relay/op.c +++ b/servers/slapd/back-relay/op.c @@ -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; diff --git a/servers/slapd/back-shell/bind.c b/servers/slapd/back-shell/bind.c index 32d8865e3d..dcbbcd4ba8 100644 --- a/servers/slapd/back-shell/bind.c +++ b/servers/slapd/back-shell/bind.c @@ -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" ); diff --git a/servers/slapd/back-sql/bind.c b/servers/slapd/back-sql/bind.c index 7db1ac8e5d..4c8f710c0b 100644 --- a/servers/slapd/back-sql/bind.c +++ b/servers/slapd/back-sql/bind.c @@ -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; - } - - 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 ); + 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 */ + 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(): " diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index ab0ccd1f95..ca1914fb2a 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -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 diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index c18d94333f..1829a74af8 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -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; diff --git a/servers/slapd/overlays/retcode.c b/servers/slapd/overlays/retcode.c index f5bca0ab1d..76b70d7be7 100644 --- a/servers/slapd/overlays/retcode.c +++ b/servers/slapd/overlays/retcode.c @@ -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; } diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 19b86837ec..2e796c08d4 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -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 ));