1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-28 01:58:17 +03:00

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>
This commit is contained in:
Andrew Tridgell 2012-10-31 17:58:20 +11:00
parent ffb608b54d
commit 994696c5c4
2 changed files with 64 additions and 0 deletions

View File

@ -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);

View File

@ -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,