diff options
-rw-r--r-- | source4/auth/credentials/credentials.c | 14 | ||||
-rw-r--r-- | source4/auth/credentials/credentials.h | 7 | ||||
-rw-r--r-- | source4/auth/credentials/credentials_krb5.c | 55 |
3 files changed, 70 insertions, 6 deletions
diff --git a/source4/auth/credentials/credentials.c b/source4/auth/credentials/credentials.c index 39b22df729..951c523b64 100644 --- a/source4/auth/credentials/credentials.c +++ b/source4/auth/credentials/credentials.c @@ -53,6 +53,9 @@ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) cred->keytab_obtained = CRED_UNINITIALISED; cred->principal_obtained = CRED_UNINITIALISED; + cred->ccache_threshold = CRED_UNINITIALISED; + cred->client_gss_creds_threshold = CRED_UNINITIALISED; + cred->old_password = NULL; cred->smb_krb5_context = NULL; cred->salt_principal = NULL; @@ -125,6 +128,7 @@ const char *cli_credentials_get_username(struct cli_credentials *cred) cred->username = cred->username_cb(cred); cred->callback_running = False; cred->username_obtained = CRED_SPECIFIED; + cli_credentials_invalidate_ccache(cred, cred->username_obtained); } return cred->username; @@ -136,6 +140,7 @@ BOOL cli_credentials_set_username(struct cli_credentials *cred, if (obtained >= cred->username_obtained) { cred->username = talloc_strdup(cred, val); cred->username_obtained = obtained; + cli_credentials_invalidate_ccache(cred, cred->username_obtained); return True; } @@ -191,6 +196,7 @@ const char *cli_credentials_get_principal(struct cli_credentials *cred, TALLOC_C cred->principal = cred->principal_cb(cred); cred->callback_running = False; cred->principal_obtained = CRED_SPECIFIED; + cli_credentials_invalidate_ccache(cred, cred->principal_obtained); } if (cred->principal_obtained < cred->username_obtained) { @@ -214,6 +220,7 @@ BOOL cli_credentials_set_principal(struct cli_credentials *cred, if (obtained >= cred->principal_obtained) { cred->principal = talloc_strdup(cred, val); cred->principal_obtained = obtained; + cli_credentials_invalidate_ccache(cred, cred->principal_obtained); return True; } @@ -280,6 +287,7 @@ const char *cli_credentials_get_password(struct cli_credentials *cred) cred->password = cred->password_cb(cred); cred->callback_running = False; cred->password_obtained = CRED_CALLBACK_RESULT; + cli_credentials_invalidate_ccache(cred, cred->password_obtained); } return cred->password; @@ -295,6 +303,7 @@ BOOL cli_credentials_set_password(struct cli_credentials *cred, if (obtained >= cred->password_obtained) { cred->password = talloc_strdup(cred, val); cred->password_obtained = obtained; + cli_credentials_invalidate_ccache(cred, cred->password_obtained); cred->nt_hash = NULL; return True; @@ -309,6 +318,7 @@ BOOL cli_credentials_set_password_callback(struct cli_credentials *cred, if (cred->password_obtained < CRED_CALLBACK) { cred->password_cb = password_cb; cred->password_obtained = CRED_CALLBACK; + cli_credentials_invalidate_ccache(cred, cred->password_obtained); return True; } @@ -401,6 +411,7 @@ const char *cli_credentials_get_domain(struct cli_credentials *cred) cred->domain = cred->domain_cb(cred); cred->callback_running = False; cred->domain_obtained = CRED_SPECIFIED; + cli_credentials_invalidate_ccache(cred, cred->domain_obtained); } return cred->domain; @@ -417,6 +428,7 @@ BOOL cli_credentials_set_domain(struct cli_credentials *cred, * calculations */ cred->domain = strupper_talloc(cred, val); cred->domain_obtained = obtained; + cli_credentials_invalidate_ccache(cred, cred->domain_obtained); return True; } @@ -453,6 +465,7 @@ const char *cli_credentials_get_realm(struct cli_credentials *cred) cred->realm = cred->realm_cb(cred); cred->callback_running = False; cred->realm_obtained = CRED_SPECIFIED; + cli_credentials_invalidate_ccache(cred, cred->realm_obtained); } return cred->realm; @@ -469,6 +482,7 @@ BOOL cli_credentials_set_realm(struct cli_credentials *cred, if (obtained >= cred->realm_obtained) { cred->realm = strupper_talloc(cred, val); cred->realm_obtained = obtained; + cli_credentials_invalidate_ccache(cred, cred->realm_obtained); return True; } diff --git a/source4/auth/credentials/credentials.h b/source4/auth/credentials/credentials.h index e20c6015e9..2715e03c1c 100644 --- a/source4/auth/credentials/credentials.h +++ b/source4/auth/credentials/credentials.h @@ -61,6 +61,13 @@ struct cli_credentials { enum credentials_obtained keytab_obtained; enum credentials_obtained server_gss_creds_obtained; + /* Threshold values (essentially a MAX() over a number of the + * above) for the ccache and GSS credentials, to ensure we + * regenerate/pick correctly */ + + enum credentials_obtained ccache_threshold; + enum credentials_obtained client_gss_creds_threshold; + const char *workstation; const char *username; const char *password; diff --git a/source4/auth/credentials/credentials_krb5.c b/source4/auth/credentials/credentials_krb5.c index 2188bf6ad8..2f0ca35d76 100644 --- a/source4/auth/credentials/credentials_krb5.c +++ b/source4/auth/credentials/credentials_krb5.c @@ -101,7 +101,9 @@ int cli_credentials_set_from_ccache(struct cli_credentials *cred, krb5_free_principal(cred->ccache->smb_krb5_context->krb5_context, princ); + /* set the ccache_obtained here, as it just got set to UNINITIALISED by the calls above */ cred->ccache_obtained = obtained; + cli_credentials_invalidate_client_gss_creds(cred, cred->ccache_obtained); return 0; } @@ -262,9 +264,7 @@ int cli_credentials_get_ccache(struct cli_credentials *cred, cli_credentials_set_machine_account(cred); } - if (cred->ccache_obtained >=(MAX(MAX(cred->principal_obtained, - cred->username_obtained), - cred->password_obtained))) { + if (cred->ccache_obtained >= cred->ccache_threshold) { *ccc = cred->ccache; return 0; } @@ -289,6 +289,49 @@ int cli_credentials_get_ccache(struct cli_credentials *cred, return ret; } +void cli_credentials_invalidate_client_gss_creds(struct cli_credentials *cred, + enum credentials_obtained obtained) +{ + /* If the caller just changed the username/password etc, then + * any cached credentials are now invalid */ + if (obtained >= cred->client_gss_creds_obtained) { + if (cred->client_gss_creds_obtained > CRED_UNINITIALISED) { + talloc_free(cred->client_gss_creds); + } + cred->client_gss_creds_obtained = CRED_UNINITIALISED; + } + /* Now that we know that the data is 'this specified', then + * don't allow something less 'known' to be returned as a + * ccache. Ie, if the username is on the commmand line, we + * don't want to later guess to use a file-based ccache */ + if (obtained > cred->client_gss_creds_threshold) { + cred->client_gss_creds_threshold = obtained; + } +} + +void cli_credentials_invalidate_ccache(struct cli_credentials *cred, + enum credentials_obtained obtained) +{ + /* If the caller just changed the username/password etc, then + * any cached credentials are now invalid */ + if (obtained >= cred->ccache_obtained) { + if (cred->ccache_obtained > CRED_UNINITIALISED) { + talloc_free(cred->ccache); + } + cred->ccache_obtained = CRED_UNINITIALISED; + } + /* Now that we know that the data is 'this specified', then + * don't allow something less 'known' to be returned as a + * ccache. Ie, if the username is on the commmand line, we + * don't want to later guess to use a file-based ccache */ + if (obtained > cred->ccache_threshold) { + cred->ccache_threshold = obtained; + } + + cli_credentials_invalidate_client_gss_creds(cred, + obtained); +} + static int free_gssapi_creds(struct gssapi_creds_container *gcc) { OM_uint32 min_stat, maj_stat; @@ -303,9 +346,7 @@ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred, OM_uint32 maj_stat, min_stat; struct gssapi_creds_container *gcc; struct ccache_container *ccache; - if (cred->client_gss_creds_obtained >= (MAX(cred->ccache_obtained, - MAX(cred->principal_obtained, - cred->username_obtained)))) { + if (cred->client_gss_creds_obtained >= cred->client_gss_creds_threshold) { *_gcc = cred->client_gss_creds; return 0; } @@ -389,6 +430,8 @@ int cli_credentials_set_client_gss_creds(struct cli_credentials *cred, gcc->creds = gssapi_cred; talloc_set_destructor(gcc, free_gssapi_creds); + /* set the clinet_gss_creds_obtained here, as it just + got set to UNINITIALISED by the calls above */ cred->client_gss_creds_obtained = obtained; cred->client_gss_creds = gcc; } |