[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Sat May 1 15:06:31 MDT 2010


The branch, master has been updated
       via  44e7ea6... s4:credentials Make the CCACHE in credentials depend on the things that built it
      from  485def3... talloc: Documentation fix for talloc

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 44e7ea692708c1c956fc9bd20ed9a6d5de9479a4
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Sat May 1 10:33:08 2010 +1000

    s4:credentials Make the CCACHE in credentials depend on the things that built it
    
    This means that we consider the ccache only as reliable as the least
    specified of the inputs we used.
    
    This means that we will regenerate the ccache if any of the inputs change.
    
    Andrew Bartlett

-----------------------------------------------------------------------

Summary of changes:
 source4/auth/credentials/credentials.c             |   20 +++++-
 source4/auth/credentials/credentials_krb5.c        |   75 +++++++++++++++-----
 source4/auth/credentials/credentials_krb5.h        |    6 ++
 source4/auth/gensec/gensec_gssapi.c                |    4 +
 source4/auth/gensec/gensec_krb5.c                  |    9 ++-
 source4/auth/kerberos/kerberos.h                   |   15 ----
 .../auth/kerberos/kerberos_credentials.h           |   18 +++---
 source4/auth/kerberos/kerberos_util.c              |   16 +++--
 8 files changed, 113 insertions(+), 50 deletions(-)
 copy libcli/smb/smb_common.h => source4/auth/kerberos/kerberos_credentials.h (66%)


Changeset truncated at 500 lines:

diff --git a/source4/auth/credentials/credentials.c b/source4/auth/credentials/credentials.c
index 5f2658d..6f7630a 100644
--- a/source4/auth/credentials/credentials.c
+++ b/source4/auth/credentials/credentials.c
@@ -222,7 +222,7 @@ _PUBLIC_ const char *cli_credentials_get_bind_dn(struct cli_credentials *cred)
  * @retval The username set on this context.
  * @note Return value will never be NULL except by programmer error.
  */
-_PUBLIC_ const char *cli_credentials_get_principal(struct cli_credentials *cred, TALLOC_CTX *mem_ctx)
+const char *cli_credentials_get_principal_and_obtained(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, enum credentials_obtained *obtained)
 {
 	if (cred->machine_account_pending) {
 		cli_credentials_set_machine_account(cred,
@@ -238,20 +238,36 @@ _PUBLIC_ const char *cli_credentials_get_principal(struct cli_credentials *cred,
 		cli_credentials_invalidate_ccache(cred, cred->principal_obtained);
 	}
 
-	if (cred->principal_obtained < cred->username_obtained) {
+	if (cred->principal_obtained < cred->username_obtained
+	    || cred->principal_obtained < MAX(cred->domain_obtained, cred->realm_obtained)) {
 		if (cred->domain_obtained > cred->realm_obtained) {
+			*obtained = MIN(cred->domain_obtained, cred->username_obtained);
 			return talloc_asprintf(mem_ctx, "%s@%s", 
 					       cli_credentials_get_username(cred),
 					       cli_credentials_get_domain(cred));
 		} else {
+			*obtained = MIN(cred->domain_obtained, cred->username_obtained);
 			return talloc_asprintf(mem_ctx, "%s@%s", 
 					       cli_credentials_get_username(cred),
 					       cli_credentials_get_realm(cred));
 		}
 	}
+	*obtained = cred->principal_obtained;
 	return talloc_reference(mem_ctx, cred->principal);
 }
 
+/**
+ * Obtain the client principal for this credentials context.
+ * @param cred credentials context
+ * @retval The username set on this context.
+ * @note Return value will never be NULL except by programmer error.
+ */
+_PUBLIC_ const char *cli_credentials_get_principal(struct cli_credentials *cred, TALLOC_CTX *mem_ctx)
+{
+	enum credentials_obtained obtained;
+	return cli_credentials_get_principal_and_obtained(cred, mem_ctx, &obtained);
+}
+
 bool cli_credentials_set_principal(struct cli_credentials *cred, 
 				   const char *val, 
 				   enum credentials_obtained obtained)
diff --git a/source4/auth/credentials/credentials_krb5.c b/source4/auth/credentials/credentials_krb5.c
index d760730..12bf610 100644
--- a/source4/auth/credentials/credentials_krb5.c
+++ b/source4/auth/credentials/credentials_krb5.c
@@ -27,6 +27,7 @@
 #include "auth/credentials/credentials.h"
 #include "auth/credentials/credentials_proto.h"
 #include "auth/credentials/credentials_krb5.h"
+#include "auth/kerberos/kerberos_credentials.h"
 #include "param/param.h"
 
 _PUBLIC_ int cli_credentials_get_krb5_context(struct cli_credentials *cred, 
@@ -282,6 +283,7 @@ _PUBLIC_ int cli_credentials_get_named_ccache(struct cli_credentials *cred,
 					      const char **error_string)
 {
 	krb5_error_code ret;
+	enum credentials_obtained obtained;
 	
 	if (cred->machine_account_pending) {
 		cli_credentials_set_machine_account(cred, lp_ctx);
@@ -302,15 +304,13 @@ _PUBLIC_ int cli_credentials_get_named_ccache(struct cli_credentials *cred,
 		return ret;
 	}
 
-	ret = kinit_to_ccache(cred, cred, (*ccc)->smb_krb5_context, (*ccc)->ccache, error_string);
+	ret = kinit_to_ccache(cred, cred, (*ccc)->smb_krb5_context, (*ccc)->ccache, &obtained, error_string);
 	if (ret) {
 		return ret;
 	}
 
 	ret = cli_credentials_set_from_ccache(cred, *ccc, 
-					      (MAX(MAX(cred->principal_obtained, 
-						       cred->username_obtained), 
-						   cred->password_obtained)), error_string);
+					      obtained, error_string);
 	
 	cred->ccache = *ccc;
 	cred->ccache_obtained = cred->principal_obtained;
@@ -330,6 +330,16 @@ _PUBLIC_ int cli_credentials_get_ccache(struct cli_credentials *cred,
 	return cli_credentials_get_named_ccache(cred, event_ctx, lp_ctx, NULL, ccc, error_string);
 }
 
+/* We have good reason to think the ccache in these credentials is invalid - blow it away */
+static void cli_credentials_unconditionally_invalidate_client_gss_creds(struct cli_credentials *cred)
+{
+	if (cred->client_gss_creds_obtained > CRED_UNINITIALISED) {
+		talloc_unlink(cred, cred->client_gss_creds);
+		cred->client_gss_creds = NULL;
+	}
+	cred->client_gss_creds_obtained = CRED_UNINITIALISED;
+}
+
 void cli_credentials_invalidate_client_gss_creds(struct cli_credentials *cred, 
 						 enum credentials_obtained obtained)
 {
@@ -351,6 +361,18 @@ void cli_credentials_invalidate_client_gss_creds(struct cli_credentials *cred,
 	}
 }
 
+/* We have good reason to think this CCACHE is invalid.  Blow it away */
+static void cli_credentials_unconditionally_invalidate_ccache(struct cli_credentials *cred)
+{
+	if (cred->ccache_obtained > CRED_UNINITIALISED) {
+		talloc_unlink(cred, cred->ccache);
+		cred->ccache = NULL;
+	}
+	cred->ccache_obtained = CRED_UNINITIALISED;
+
+	cli_credentials_unconditionally_invalidate_client_gss_creds(cred);
+}
+
 _PUBLIC_ void cli_credentials_invalidate_ccache(struct cli_credentials *cred, 
 				       enum credentials_obtained obtained)
 {
@@ -416,6 +438,23 @@ _PUBLIC_ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
 
 	maj_stat = gss_krb5_import_cred(&min_stat, ccache->ccache, NULL, NULL, 
 					&gcc->creds);
+	if ((maj_stat == GSS_S_FAILURE) && (min_stat == (OM_uint32)KRB5_CC_END || min_stat == (OM_uint32) KRB5_CC_NOTFOUND)) {
+		/* This CCACHE is no good.  Ensure we don't use it again */
+		cli_credentials_unconditionally_invalidate_ccache(cred);
+
+		/* Now try again to get a ccache */
+		ret = cli_credentials_get_ccache(cred, event_ctx, lp_ctx,
+						 &ccache, error_string);
+		if (ret) {
+			DEBUG(1, ("Failed to re-get CCACHE for GSSAPI client: %s\n", error_message(ret)));
+			return ret;
+		}
+
+		maj_stat = gss_krb5_import_cred(&min_stat, ccache->ccache, NULL, NULL,
+						&gcc->creds);
+
+	}
+
 	if (maj_stat) {
 		talloc_free(gcc);
 		if (min_stat) {
@@ -698,12 +737,11 @@ _PUBLIC_ int cli_credentials_get_server_gss_creds(struct cli_credentials *cred,
 	TALLOC_CTX *mem_ctx;
 	krb5_principal princ;
 	const char *error_string;
+	enum credentials_obtained obtained;
 
-	if (cred->server_gss_creds_obtained >= (MAX(cred->keytab_obtained, 
-						    MAX(cred->principal_obtained, 
-							cred->username_obtained)))) {
-		*_gcc = cred->server_gss_creds;
-		return 0;
+	mem_ctx = talloc_new(cred);
+	if (!mem_ctx) {
+		return ENOMEM;
 	}
 
 	ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx, &smb_krb5_context);
@@ -711,22 +749,23 @@ _PUBLIC_ int cli_credentials_get_server_gss_creds(struct cli_credentials *cred,
 		return ret;
 	}
 
-	ret = cli_credentials_get_keytab(cred, event_ctx, lp_ctx, &ktc);
+	ret = principal_from_credentials(mem_ctx, cred, smb_krb5_context, &princ, &obtained, &error_string);
 	if (ret) {
-		DEBUG(1, ("Failed to get keytab for GSSAPI server: %s\n", error_message(ret)));
+		DEBUG(1,("cli_credentials_get_server_gss_creds: makeing krb5 principal failed (%s)\n",
+			 error_string));
+		talloc_free(mem_ctx);
 		return ret;
 	}
 
-	mem_ctx = talloc_new(cred);
-	if (!mem_ctx) {
-		return ENOMEM;
+	if (cred->server_gss_creds_obtained >= (MAX(cred->keytab_obtained, obtained))) {
+		talloc_free(mem_ctx);
+		*_gcc = cred->server_gss_creds;
+		return 0;
 	}
 
-	ret = principal_from_credentials(mem_ctx, cred, smb_krb5_context, &princ, &error_string);
+	ret = cli_credentials_get_keytab(cred, event_ctx, lp_ctx, &ktc);
 	if (ret) {
-		DEBUG(1,("cli_credentials_get_server_gss_creds: makeing krb5 principal failed (%s)\n",
-			 error_string));
-		talloc_free(mem_ctx);
+		DEBUG(1, ("Failed to get keytab for GSSAPI server: %s\n", error_message(ret)));
 		return ret;
 	}
 
diff --git a/source4/auth/credentials/credentials_krb5.h b/source4/auth/credentials/credentials_krb5.h
index 72a4373..3a614ff 100644
--- a/source4/auth/credentials/credentials_krb5.h
+++ b/source4/auth/credentials/credentials_krb5.h
@@ -44,6 +44,12 @@ krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx,
 					   struct cli_credentials *credentials, 
 					   struct smb_krb5_context *smb_krb5_context,
 					   krb5_principal *princ,
+					   enum credentials_obtained *obtained,
 					   const char **error_string);
+krb5_error_code impersonate_principal_from_credentials(TALLOC_CTX *parent_ctx,
+						       struct cli_credentials *credentials,
+						       struct smb_krb5_context *smb_krb5_context,
+						       krb5_principal *princ,
+						       const char **error_string);
 	
 #endif /* __CREDENTIALS_KRB5_H__ */
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c
index 9e974cb..c6901a7 100644
--- a/source4/auth/gensec/gensec_gssapi.c
+++ b/source4/auth/gensec/gensec_gssapi.c
@@ -379,6 +379,10 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
 	case KRB5_KDC_UNREACH:
 		DEBUG(3, ("Cannot reach a KDC we require to contact %s : %s\n", principal, error_string));
 		return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
+	case KRB5_CC_NOTFOUND:
+	case KRB5_CC_END:
+		DEBUG(3, ("Error preparing credentials we require to contact %s : %s\n", principal, error_string));
+		return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
 	default:
 		DEBUG(1, ("Aquiring initiator credentials failed: %s\n", error_string));
 		return NT_STATUS_UNSUCCESSFUL;
diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c
index bb9ace7..c2f96d7 100644
--- a/source4/auth/gensec/gensec_krb5.c
+++ b/source4/auth/gensec/gensec_krb5.c
@@ -31,6 +31,8 @@
 #include "lib/tsocket/tsocket.h"
 #include "librpc/rpc/dcerpc.h"
 #include "auth/credentials/credentials.h"
+#include "auth/credentials/credentials_krb5.h"
+#include "auth/kerberos/kerberos_credentials.h"
 #include "auth/gensec/gensec.h"
 #include "auth/gensec/gensec_proto.h"
 #include "param/param.h"
@@ -287,6 +289,10 @@ static NTSTATUS gensec_krb5_common_client_start(struct gensec_security *gensec_s
 	case KRB5_KDC_UNREACH:
 		DEBUG(3, ("Cannot reach a KDC we require to contact %s: %s\n", principal, error_string));
 		return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
+	case KRB5_CC_NOTFOUND:
+	case KRB5_CC_END:
+		DEBUG(3, ("Error preparing credentials we require to contact %s : %s\n", principal, error_string));
+		return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
 	default:
 		DEBUG(1, ("gensec_krb5_start: Aquiring initiator credentials failed: %s\n", error_string));
 		return NT_STATUS_UNSUCCESSFUL;
@@ -474,6 +480,7 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security,
 		struct keytab_container *keytab;
 		krb5_principal server_in_keytab;
 		const char *error_string;
+		enum credentials_obtained obtained;
 
 		if (!in.data) {
 			return NT_STATUS_INVALID_PARAMETER;
@@ -490,7 +497,7 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security,
 		/* This ensures we lookup the correct entry in that keytab */
 		ret = principal_from_credentials(out_mem_ctx, gensec_get_credentials(gensec_security), 
 						 gensec_krb5_state->smb_krb5_context, 
-						 &server_in_keytab, &error_string);
+						 &server_in_keytab, &obtained, &error_string);
 
 		if (ret) {
 			DEBUG(2,("Failed to make credentials from principal: %s\n", error_string));
diff --git a/source4/auth/kerberos/kerberos.h b/source4/auth/kerberos/kerberos.h
index 992b509..1990343 100644
--- a/source4/auth/kerberos/kerberos.h
+++ b/source4/auth/kerberos/kerberos.h
@@ -104,21 +104,6 @@ bool kerberos_compatible_enctypes(krb5_context context, krb5_enctype enctype1, k
 void kerberos_free_data_contents(krb5_context context, krb5_data *pdata);
 krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry);
 char *smb_get_krb5_error_message(krb5_context context, krb5_error_code code, TALLOC_CTX *mem_ctx);
- krb5_error_code kinit_to_ccache(TALLOC_CTX *parent_ctx,
-				 struct cli_credentials *credentials,
-				 struct smb_krb5_context *smb_krb5_context,
-				 krb5_ccache ccache,
-				 const char **error_string);
-krb5_error_code impersonate_principal_from_credentials(TALLOC_CTX *parent_ctx,
-						       struct cli_credentials *credentials,
-						       struct smb_krb5_context *smb_krb5_context,
-						       krb5_principal *princ,
-						       const char **error_string);
-krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx, 
-					   struct cli_credentials *credentials, 
-					   struct smb_krb5_context *smb_krb5_context,
-					   krb5_principal *princ,
-					   const char **error_string);
 NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
 			     struct smb_iconv_convenience *iconv_convenience,
 			     struct PAC_DATA **pac_data_out,
diff --git a/libcli/smb/smb_common.h b/source4/auth/kerberos/kerberos_credentials.h
similarity index 66%
copy from libcli/smb/smb_common.h
copy to source4/auth/kerberos/kerberos_credentials.h
index d6186ab..5522775 100644
--- a/libcli/smb/smb_common.h
+++ b/source4/auth/kerberos/kerberos_credentials.h
@@ -1,9 +1,9 @@
 /*
    Unix SMB/CIFS implementation.
 
-   SMB and SMB2 common header
+   Kerberos utility functions for GENSEC
 
-   Copyright (C) Stefan Metzmacher 2009
+   Copyright (C) Andrew Bartlett <abartlet at samba.org> 2004-2010
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -15,14 +15,14 @@
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#ifndef __LIBCLI_SMB_SMB_COMMON_H__
-#define __LIBCLI_SMB_SMB_COMMON_H__
-
-#include "../libcli/smb/smb2_constants.h"
-#include "../libcli/smb/smb2_create_blob.h"
-
-#endif
+krb5_error_code kinit_to_ccache(TALLOC_CTX *parent_ctx,
+				 struct cli_credentials *credentials,
+				 struct smb_krb5_context *smb_krb5_context,
+				 krb5_ccache ccache,
+				 enum credentials_obtained *obtained,
+				 const char **error_string);
diff --git a/source4/auth/kerberos/kerberos_util.c b/source4/auth/kerberos/kerberos_util.c
index 44d97b7..2b35851 100644
--- a/source4/auth/kerberos/kerberos_util.c
+++ b/source4/auth/kerberos/kerberos_util.c
@@ -26,6 +26,7 @@
 #include "auth/credentials/credentials.h"
 #include "auth/credentials/credentials_proto.h"
 #include "auth/credentials/credentials_krb5.h"
+#include "auth/kerberos/kerberos_credentials.h"
 
 struct principal_container {
 	struct smb_krb5_context *smb_krb5_context;
@@ -143,6 +144,7 @@ static krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx,
 					    struct cli_credentials *credentials, 
 					    struct smb_krb5_context *smb_krb5_context,
 					    krb5_principal *princ,
+					    enum credentials_obtained *obtained,
 					    const char **error_string)
 {
 	krb5_error_code ret;
@@ -152,7 +154,7 @@ static krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx,
 		(*error_string) = error_message(ENOMEM);
 		return ENOMEM;
 	}
-	princ_string = cli_credentials_get_principal(credentials, mem_ctx);
+	princ_string = cli_credentials_get_principal_and_obtained(credentials, mem_ctx, obtained);
 	if (!princ_string) {
 		(*error_string) = error_message(ENOMEM);
 		return ENOMEM;
@@ -188,6 +190,7 @@ static krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx,
 				 struct cli_credentials *credentials,
 				 struct smb_krb5_context *smb_krb5_context,
 				 krb5_ccache ccache,
+				 enum credentials_obtained *obtained,
 				 const char **error_string)
 {
 	krb5_error_code ret;
@@ -203,7 +206,7 @@ static krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx,
 		return ENOMEM;
 	}
 
-	ret = principal_from_credentials(mem_ctx, credentials, smb_krb5_context, &princ, error_string);
+	ret = principal_from_credentials(mem_ctx, credentials, smb_krb5_context, &princ, obtained, error_string);
 	if (ret) {
 		talloc_free(mem_ctx);
 		return ret;
@@ -285,7 +288,8 @@ static krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx,
 		ret = kinit_to_ccache(parent_ctx,
 				      credentials,
 				      smb_krb5_context,
-				      ccache, error_string);
+				      ccache, obtained,
+				      error_string);
 	}
 	if (ret) {
 		(*error_string) = talloc_asprintf(credentials, "kinit for %s failed (%s)\n",
@@ -410,6 +414,7 @@ static krb5_error_code create_keytab(TALLOC_CTX *parent_ctx,
 	krb5_principal princ;
 	const char *princ_string;
 	const char *error_string;
+	enum credentials_obtained obtained;
 
 	TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
 	if (!mem_ctx) {
@@ -418,7 +423,7 @@ static krb5_error_code create_keytab(TALLOC_CTX *parent_ctx,
 
 	princ_string = cli_credentials_get_principal(machine_account, mem_ctx);
 	/* Get the principal we will store the new keytab entries under */
-	ret = principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, &princ, &error_string);
+	ret = principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, &princ, &obtained, &error_string);
 	if (ret) {
 		DEBUG(1,("create_keytab: makeing krb5 principal failed (%s)\n", error_string));
 		talloc_free(mem_ctx);
@@ -549,6 +554,7 @@ static krb5_error_code remove_old_entries(TALLOC_CTX *parent_ctx,
 	TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
 	const char *princ_string;
 	const char *error_string;
+	enum credentials_obtained obtained;
 
 	if (!mem_ctx) {
 		return ENOMEM;
@@ -558,7 +564,7 @@ static krb5_error_code remove_old_entries(TALLOC_CTX *parent_ctx,
 	princ_string = cli_credentials_get_principal(machine_account, mem_ctx);
 
 	/* Get the principal we will store the new keytab entries under */
-	ret = principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, &princ, &error_string);
+	ret = principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, &princ, &obtained, &error_string);
 	if (ret) {
 		DEBUG(1,("update_keytab: makeing krb5 principal failed (%s)\n", error_string));
 		talloc_free(mem_ctx);


-- 
Samba Shared Repository


More information about the samba-cvs mailing list