From ad83f20cbab205aa68c21ccae51c4ad86c33ad48 Mon Sep 17 00:00:00 2001 From: Mark Reynolds Date: Wed, 27 Jun 2012 10:35:08 -0400 Subject: [PATCH] Ticket 366 - Change DS to purge ticket from krb cache in case of authentication error Bug Description: Under certain circumstances, a replica can be removed, and readded, but the master replica still holds its old kerberos credentials in a cache(ccache). Until the mater replica is restarted, replication will not resume. Fix Description: If a sasl bind fails, ands it a GSSAPI, and the errror is 49, clear out the ccache. I also noticed that when this situation arises we report errors when trying to update the referrals in the repl agreement to this replica. The error is 20(type or value exists), and it will log at least one of these messages per update. The error should not be written to the error log, as it's not a problem that needs reporting. https://fedorahosted.org/389/ticket/366 reviewed by: ? --- ldap/servers/plugins/replication/replutil.c | 2 +- ldap/servers/slapd/ldaputil.c | 47 +++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletions(-) diff --git a/ldap/servers/plugins/replication/replutil.c b/ldap/servers/plugins/replication/replutil.c index b09bf53..5e8019c 100644 --- a/ldap/servers/plugins/replication/replutil.c +++ b/ldap/servers/plugins/replication/replutil.c @@ -788,7 +788,7 @@ repl_set_mtn_state_and_referrals( } } - if (rc != LDAP_SUCCESS) { + if (rc != LDAP_SUCCESS && rc != LDAP_TYPE_OR_VALUE_EXISTS) { slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "repl_set_mtn_referrals: could " "not set referrals for replica %s: %d\n", slapi_sdn_get_dn(repl_root_sdn), rc); diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c index 3990815..fd4e93f 100644 --- a/ldap/servers/slapd/ldaputil.c +++ b/ldap/servers/slapd/ldaputil.c @@ -126,6 +126,10 @@ static char **mozldap_ldap_explode( const char *dn, const int notypes, const int static char **mozldap_ldap_explode_dn( const char *dn, const int notypes ); static char **mozldap_ldap_explode_rdn( const char *rdn, const int notypes ); +#ifdef HAVE_KRB5 +static void clear_krb5_ccache(); +#endif + #ifdef MEMPOOL_EXPERIMENTAL void _free_wrapper(void *ptr) { @@ -1159,6 +1163,12 @@ slapi_ldap_bind( bindid ? bindid : "(anon)", mech, /* mech cannot be SIMPLE here */ rc, ldap_err2string(rc)); +#ifdef HAVE_KRB5 + if(mech && !strcmp(mech, "GSSAPI") && rc == 49){ + /* only on err 49 should we clear out the credential cache */ + clear_krb5_ccache(); + } +#endif } } @@ -2062,6 +2072,43 @@ cleanup: return; } +static void +clear_krb5_ccache() +{ + krb5_context ctx = NULL; + krb5_ccache cc = NULL; + int rc = 0; + + PR_Lock(krb5_lock); + + /* initialize the kerberos context */ + if ((rc = krb5_init_context(&ctx))) { + slapi_log_error(SLAPI_LOG_FATAL, "clear_krb5_ccache", "Could not initialize kerberos context: %d (%s)\n", + rc, error_message(rc)); + goto done; + } + /* get the default ccache */ + if ((rc = krb5_cc_default(ctx, &cc))) { + slapi_log_error(SLAPI_LOG_FATAL, "clear_krb5_ccache", "Could not get default kerberos ccache: %d (%s)\n", + rc, error_message(rc)); + goto done; + } + /* destroy the ccache */ + if((rc = krb5_cc_destroy(ctx, cc))){ + slapi_log_error(SLAPI_LOG_FATAL, "clear_krb5_ccache", "Could not destroy kerberos ccache: %d (%s)\n", + rc, error_message(rc)); + } else { + slapi_log_error(SLAPI_LOG_TRACE,"clear_krb5_ccache", "Successfully cleared kerberos ccache\n"); + } + +done: + if(ctx){ + krb5_free_context(ctx); + } + + PR_Unlock(krb5_lock); +} + #endif /* HAVE_KRB5 */ #define LDAP_DN 1 -- 1.7.1