Преглед изворни кода

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: richm(Thanks!)
(cherry picked from commit 14cb1d07ee1864de8ca54083ef6901d5b4627758)
Mark Reynolds пре 13 година
родитељ
комит
5b715ab9d5
2 измењених фајлова са 48 додато и 1 уклоњено
  1. 1 1
      ldap/servers/plugins/replication/replutil.c
  2. 47 0
      ldap/servers/slapd/ldaputil.c

+ 1 - 1
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);

+ 47 - 0
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)
 {
@@ -1155,6 +1159,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
 	}
     }
 
@@ -2058,6 +2068,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