r23132: Resolve an issue where we would use the ccache after we free()ed it.
authorAndrew Bartlett <abartlet@samba.org>
Fri, 25 May 2007 05:19:02 +0000 (05:19 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:52:53 +0000 (14:52 -0500)
The problem was, we would set the ccache, then invalidate it as we set
details from it (like the principal name from the ccache).

Instead, set the ccache onto the credentials structure after we are
done processing it.

Andrew Bartlett
(This used to be commit d285bd927c604d930fc44cc84ef3321aa4ce9d9a)

source4/auth/auth_util.c
source4/auth/credentials/credentials_krb5.c

index d4a2fa93e8a87047c9752db221cd334f4a26cf4e..649928ac9b36d239ade0bf0e5795452840c38db1 100644 (file)
@@ -581,8 +581,9 @@ struct auth_session_info *anonymous_session(TALLOC_CTX *mem_ctx)
        return session_info;
 }
 
-NTSTATUS auth_system_session_info(TALLOC_CTX *parent_ctx, 
-                                 struct auth_session_info **_session_info) 
+static NTSTATUS _auth_system_session_info(TALLOC_CTX *parent_ctx, 
+                                         BOOL anonymous_credentials, 
+                                         struct auth_session_info **_session_info) 
 {
        NTSTATUS nt_status;
        struct auth_serversupplied_info *server_info = NULL;
@@ -609,7 +610,7 @@ NTSTATUS auth_system_session_info(TALLOC_CTX *parent_ctx,
 
        cli_credentials_set_conf(session_info->credentials);
 
-       if (lp_parm_bool(-1,"system","anonymous", False)) {
+       if (anonymous_credentials) {
                cli_credentials_set_anonymous(session_info->credentials);
        } else {
                cli_credentials_set_machine_account_pending(session_info->credentials);
@@ -619,11 +620,36 @@ NTSTATUS auth_system_session_info(TALLOC_CTX *parent_ctx,
        return NT_STATUS_OK;
 }
 
+_PUBLIC_ NTSTATUS auth_system_session_info(TALLOC_CTX *parent_ctx, 
+                                          struct auth_session_info **_session_info) 
+{
+       return _auth_system_session_info(parent_ctx, lp_parm_bool(-1,"system","anonymous", False), 
+                                        _session_info);
+}
+
+/*
+  Create a system session, with machine account credentials
+*/
 _PUBLIC_ struct auth_session_info *system_session(TALLOC_CTX *mem_ctx) 
 {
        NTSTATUS nt_status;
        struct auth_session_info *session_info = NULL;
-       nt_status = auth_system_session_info(mem_ctx, &session_info);
+       nt_status = auth_system_session_info(mem_ctx,
+                                            &session_info);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               return NULL;
+       }
+       return session_info;
+}
+
+/*
+  Create a system session, but with anonymous credentials (so we do not need to open secrets.ldb)
+*/
+_PUBLIC_ struct auth_session_info *system_session_anon(TALLOC_CTX *mem_ctx) 
+{
+       NTSTATUS nt_status;
+       struct auth_session_info *session_info = NULL;
+       nt_status = _auth_system_session_info(mem_ctx, False, &session_info);
        if (!NT_STATUS_IS_OK(nt_status)) {
                return NULL;
        }
index 2f0ca35d76733fc03ab36148fdf4e8f00e894848..06308a09ff440e703a2c46096fe5b0a65b1f9a4e 100644 (file)
@@ -60,7 +60,8 @@ NTSTATUS cli_credentials_set_krb5_context(struct cli_credentials *cred,
        return NT_STATUS_OK;
 }
 
-int cli_credentials_set_from_ccache(struct cli_credentials *cred, 
+static int cli_credentials_set_from_ccache(struct cli_credentials *cred, 
+                                   struct ccache_container *ccache,
                                    enum credentials_obtained obtained)
 {
        
@@ -73,37 +74,37 @@ int cli_credentials_set_from_ccache(struct cli_credentials *cred,
                return 0;
        }
 
-       ret = krb5_cc_get_principal(cred->ccache->smb_krb5_context->krb5_context, 
-                                   cred->ccache->ccache, &princ);
+       ret = krb5_cc_get_principal(ccache->smb_krb5_context->krb5_context, 
+                                   ccache->ccache, &princ);
 
        if (ret) {
-               char *err_mess = smb_get_krb5_error_message(cred->ccache->smb_krb5_context->krb5_context, ret, cred);
+               char *err_mess = smb_get_krb5_error_message(ccache->smb_krb5_context->krb5_context, 
+                                                           ret, cred);
                DEBUG(1,("failed to get principal from ccache: %s\n", 
                         err_mess));
                talloc_free(err_mess);
                return ret;
        }
        
-       ret = krb5_unparse_name(cred->ccache->smb_krb5_context->krb5_context, princ, &name);
+       ret = krb5_unparse_name(ccache->smb_krb5_context->krb5_context, princ, &name);
        if (ret) {
-               char *err_mess = smb_get_krb5_error_message(cred->ccache->smb_krb5_context->krb5_context, ret, cred);
+               char *err_mess = smb_get_krb5_error_message(ccache->smb_krb5_context->krb5_context, ret, cred);
                DEBUG(1,("failed to unparse principal from ccache: %s\n", 
                         err_mess));
                talloc_free(err_mess);
                return ret;
        }
 
-       realm = krb5_princ_realm(cred->ccache->smb_krb5_context->krb5_context, princ);
+       realm = krb5_princ_realm(ccache->smb_krb5_context->krb5_context, princ);
 
        cli_credentials_set_principal(cred, name, obtained);
 
        free(name);
 
-       krb5_free_principal(cred->ccache->smb_krb5_context->krb5_context, princ);
+       krb5_free_principal(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;
 }
@@ -181,20 +182,22 @@ int cli_credentials_set_ccache(struct cli_credentials *cred,
 
        krb5_free_principal(ccc->smb_krb5_context->krb5_context, princ);
 
-       cred->ccache = ccc;
-       talloc_steal(cred, ccc);
-
-       ret = cli_credentials_set_from_ccache(cred, obtained);
+       ret = cli_credentials_set_from_ccache(cred, ccc, obtained);
 
        if (ret) {
                return ret;
        }
 
+       cred->ccache = ccc;
+       cred->ccache_obtained = obtained;
+       talloc_steal(cred, ccc);
+
+       cli_credentials_invalidate_client_gss_creds(cred, cred->ccache_obtained);
        return 0;
 }
 
 
-int cli_credentials_new_ccache(struct cli_credentials *cred, struct ccache_container **_ccc)
+static int cli_credentials_new_ccache(struct cli_credentials *cred, struct ccache_container **_ccc)
 {
        krb5_error_code ret;
        char *rand_string;
@@ -241,17 +244,10 @@ int cli_credentials_new_ccache(struct cli_credentials *cred, struct ccache_conta
 
        talloc_set_destructor(ccc, free_mccache);
 
-       cred->ccache = ccc;
-       talloc_steal(cred, ccc);
        talloc_free(ccache_name);
 
-       if (_ccc) {
-               *_ccc = ccc;
-       }
+       *_ccc = ccc;
 
-       cred->ccache_obtained = (MAX(MAX(cred->principal_obtained, 
-                                        cred->username_obtained), 
-                                    cred->password_obtained));
        return ret;
 }
 
@@ -272,20 +268,27 @@ int cli_credentials_get_ccache(struct cli_credentials *cred,
                return EINVAL;
        }
 
-       ret = cli_credentials_new_ccache(cred, NULL);
+       ret = cli_credentials_new_ccache(cred, ccc);
        if (ret) {
                return ret;
        }
-       ret = kinit_to_ccache(cred, cred, cred->ccache->smb_krb5_context, cred->ccache->ccache);
+
+       ret = kinit_to_ccache(cred, cred, (*ccc)->smb_krb5_context, (*ccc)->ccache);
        if (ret) {
                return ret;
        }
-       ret = cli_credentials_set_from_ccache(cred, cred->principal_obtained);
 
+       ret = cli_credentials_set_from_ccache(cred, *ccc, 
+                                             (MAX(MAX(cred->principal_obtained, 
+                                                      cred->username_obtained), 
+                                                  cred->password_obtained)));
+       
+       cred->ccache = *ccc;
+       cred->ccache_obtained = cred->principal_obtained;
        if (ret) {
                return ret;
        }
-       *ccc = cred->ccache;
+       cli_credentials_invalidate_client_gss_creds(cred, cred->ccache_obtained);
        return ret;
 }
 
@@ -297,6 +300,7 @@ void cli_credentials_invalidate_client_gss_creds(struct cli_credentials *cred,
        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 = NULL;
                }
                cred->client_gss_creds_obtained = CRED_UNINITIALISED;
        }
@@ -317,6 +321,7 @@ void cli_credentials_invalidate_ccache(struct cli_credentials *cred,
        if (obtained >= cred->ccache_obtained) {
                if (cred->ccache_obtained > CRED_UNINITIALISED) {
                        talloc_free(cred->ccache);
+                       cred->ccache = NULL;
                }
                cred->ccache_obtained = CRED_UNINITIALISED;
        }
@@ -424,8 +429,10 @@ int cli_credentials_set_client_gss_creds(struct cli_credentials *cred,
        }
 
        if (ret == 0) {
-               ret = cli_credentials_set_from_ccache(cred, obtained);
+               ret = cli_credentials_set_from_ccache(cred, ccc, obtained);
        }
+       cred->ccache = ccc;
+       cred->ccache_obtained = obtained;
        if (ret == 0) {
                gcc->creds = gssapi_cred;
                talloc_set_destructor(gcc, free_gssapi_creds);