summaryrefslogtreecommitdiff
path: root/auth
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2012-10-31 17:58:20 +1100
committerAndrew Tridgell <tridge@samba.org>2012-11-01 15:40:40 +1100
commit994696c5c4638b0665021eac1c55b4c6ea9fd55f (patch)
tree257b6a23f448d5778a0c24a7cc3cd245867a62ee /auth
parentffb608b54d452e2c96222840f1bd48759f32d0b5 (diff)
downloadsamba-994696c5c4638b0665021eac1c55b4c6ea9fd55f.tar.gz
samba-994696c5c4638b0665021eac1c55b4c6ea9fd55f.tar.bz2
samba-994696c5c4638b0665021eac1c55b4c6ea9fd55f.zip
auth: added cli_credentials_failed_kerberos_login()
this is used to support retrying kerberos connections after removing a ccache entry, to cope with a server being re-built while our client still has a valid service ticket Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'auth')
-rw-r--r--auth/credentials/credentials.h3
-rw-r--r--auth/credentials/credentials_krb5.c61
2 files changed, 64 insertions, 0 deletions
diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h
index 0bcfd61264..dbc014fd08 100644
--- a/auth/credentials/credentials.h
+++ b/auth/credentials/credentials.h
@@ -182,6 +182,9 @@ int cli_credentials_get_named_ccache(struct cli_credentials *cred,
struct loadparm_context *lp_ctx,
char *ccache_name,
struct ccache_container **ccc, const char **error_string);
+bool cli_credentials_failed_kerberos_login(struct cli_credentials *cred,
+ const char *principal,
+ unsigned int *count);
int cli_credentials_get_keytab(struct cli_credentials *cred,
struct loadparm_context *lp_ctx,
struct keytab_container **_ktc);
diff --git a/auth/credentials/credentials_krb5.c b/auth/credentials/credentials_krb5.c
index 459e9487f4..cc51f56d79 100644
--- a/auth/credentials/credentials_krb5.c
+++ b/auth/credentials/credentials_krb5.c
@@ -212,6 +212,67 @@ _PUBLIC_ int cli_credentials_set_ccache(struct cli_credentials *cred,
return 0;
}
+/*
+ * Indicate the we failed to log in to this service/host with these
+ * credentials. The caller passes an unsigned int which they
+ * initialise to the number of times they would like to retry.
+ *
+ * This method is used to support re-trying with freshly fetched
+ * credentials in case a server is rebuilt while clients have
+ * non-expired tickets. When the client code gets a logon failure they
+ * throw away the existing credentials for the server and retry.
+ */
+_PUBLIC_ bool cli_credentials_failed_kerberos_login(struct cli_credentials *cred,
+ const char *principal,
+ unsigned int *count)
+{
+ struct ccache_container *ccc;
+ krb5_creds creds, creds2;
+ int ret;
+
+ if (principal == NULL) {
+ /* no way to delete if we don't know the principal */
+ return false;
+ }
+
+ ccc = cred->ccache;
+ if (ccc == NULL) {
+ /* not a kerberos connection */
+ return false;
+ }
+
+ if (*count > 0) {
+ /* We have already tried discarding the credentials */
+ return false;
+ }
+ (*count)++;
+
+ ZERO_STRUCT(creds);
+ ret = krb5_parse_name(ccc->smb_krb5_context->krb5_context, principal, &creds.server);
+ if (ret != 0) {
+ return false;
+ }
+
+ ret = krb5_cc_retrieve_cred(ccc->smb_krb5_context->krb5_context, ccc->ccache, KRB5_TC_MATCH_SRV_NAMEONLY, &creds, &creds2);
+ if (ret != 0) {
+ /* don't retry - we didn't find these credentials to remove */
+ return false;
+ }
+
+ ret = krb5_cc_remove_cred(ccc->smb_krb5_context->krb5_context, ccc->ccache, KRB5_TC_MATCH_SRV_NAMEONLY, &creds);
+ krb5_free_cred_contents(ccc->smb_krb5_context->krb5_context, &creds2);
+ if (ret != 0) {
+ /* don't retry - we didn't find these credentials to
+ * remove. Note that with the current backend this
+ * never happens, as it always returns 0 even if the
+ * creds don't exist, which is why we do a separate
+ * krb5_cc_retrieve_cred() above.
+ */
+ return false;
+ }
+ return true;
+}
+
static int cli_credentials_new_ccache(struct cli_credentials *cred,
struct loadparm_context *lp_ctx,