diff options
author | Andrew Tridgell <tridge@samba.org> | 2012-10-31 17:58:20 +1100 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2012-11-01 15:40:40 +1100 |
commit | 994696c5c4638b0665021eac1c55b4c6ea9fd55f (patch) | |
tree | 257b6a23f448d5778a0c24a7cc3cd245867a62ee /auth | |
parent | ffb608b54d452e2c96222840f1bd48759f32d0b5 (diff) | |
download | samba-994696c5c4638b0665021eac1c55b4c6ea9fd55f.tar.gz |
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.h | 3 | ||||
-rw-r--r-- | auth/credentials/credentials_krb5.c | 61 |
2 files changed, 64 insertions, 0 deletions
diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h index 0bcfd61264d..dbc014fd08c 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 459e9487f48..cc51f56d79b 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, |