r23063: Make sure to invalidate the ccache when we set a
authorAndrew Bartlett <abartlet@samba.org>
Tue, 22 May 2007 05:21:59 +0000 (05:21 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:52:46 +0000 (14:52 -0500)
username/password/realm/etc from the command line.

Also make sure it can't 'come back' from a later call to
cli_credentials_guess(), buy setting a threshold.

This should fix the issues with the build farm...

Andrew Bartlett
(This used to be commit 3b1dfb9306beb9f40d85d38cf6786ef161ec63f1)

source4/auth/credentials/credentials.c
source4/auth/credentials/credentials.h
source4/auth/credentials/credentials_krb5.c

index 39b22df729a0ccfb109dc6792d1dd2f782ea9465..951c523b64571b95770fb3e917e52255d70bf52b 100644 (file)
@@ -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;
        }
 
index e20c6015e953b0392ba3694f3f3af31e534ffc54..2715e03c1c0bc3e6a9810cdfd5055402c57d78b1 100644 (file)
@@ -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;
index 2188bf6ad89334ee6b90c6acebbfa5a14c0fdfee..2f0ca35d76733fc03ab36148fdf4e8f00e894848 100644 (file)
@@ -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;
        }