[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Tue Jun 7 20:20:02 MDT 2011


The branch, master has been updated
       via  c790213 s4-gensec bring GSS_S_CONTEXT_EXPIRED into it's own error handler
       via  9cf686f s4-credentials Don't use expired Kerberos or GSSAPI credentials
       via  8dbab93 s4-credentials Allow use of file-based credentials caches for debugging.
      from  5fb2781 Part 3 of bugfix for #8211 - "inherit owner = yes" doesn't interact correctly with "inherit permissions = yes" and POSIX ACLs

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


- Log -----------------------------------------------------------------
commit c79021382b3feda518440f7627a78959b96d0619
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Jun 8 08:55:19 2011 +1000

    s4-gensec bring GSS_S_CONTEXT_EXPIRED into it's own error handler
    
    This allows us to print much more debugging in this critical situation.
    
    Andrew Bartlett
    
    Autobuild-User: Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date: Wed Jun  8 04:19:58 CEST 2011 on sn-devel-104

commit 9cf686f56fa50932a67f80a455c36025ca3470db
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Jun 8 08:53:16 2011 +1000

    s4-credentials Don't use expired Kerberos or GSSAPI credentials
    
    In a long-lived credentials cache situation, we may need to refetch
    the ticket after (say) 10 hours.  This code should help that happen,
    by checking the lifetime before returning any credentials cache or
    GSSAPI credentials.
    
    Andrew Bartlett

commit 8dbab93f28d8ddbce8f44116f45a107a05a59a15
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Jun 8 08:51:56 2011 +1000

    s4-credentials Allow use of file-based credentials caches for debugging.
    
    This means that we will leave a slew of file based credentials caches
    in /tmp, which should give some clues to the administrator or
    developer via klist as to what has gone wrong.
    
    Andrew Bartlett

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

Summary of changes:
 source4/auth/credentials/credentials_krb5.c |   73 ++++++++++++++++++++++++---
 source4/auth/gensec/gensec_gssapi.c         |   59 +++++++++++++++++++++
 2 files changed, 125 insertions(+), 7 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/auth/credentials/credentials_krb5.c b/source4/auth/credentials/credentials_krb5.c
index bfba167..26fa809 100644
--- a/source4/auth/credentials/credentials_krb5.c
+++ b/source4/auth/credentials/credentials_krb5.c
@@ -235,9 +235,15 @@ static int cli_credentials_new_ccache(struct cli_credentials *cred,
 
 	if (!ccache_name) {
 		must_free_cc_name = true;
-		ccache_name = talloc_asprintf(ccc, "MEMORY:%p", 
-					      ccc);
-		
+
+		if (lpcfg_parm_bool(lp_ctx, NULL, "credentials", "krb5_cc_file", false)) {
+			ccache_name = talloc_asprintf(ccc, "FILE:/tmp/krb5_cc_samba_%u_%p", 
+						      (unsigned int)getpid(), ccc);
+		} else {
+			ccache_name = talloc_asprintf(ccc, "MEMORY:%p", 
+						      ccc);
+		}
+
 		if (!ccache_name) {
 			talloc_free(ccc);
 			(*error_string) = strerror(ENOMEM);
@@ -288,8 +294,38 @@ _PUBLIC_ int cli_credentials_get_named_ccache(struct cli_credentials *cred,
 
 	if (cred->ccache_obtained >= cred->ccache_threshold && 
 	    cred->ccache_obtained > CRED_UNINITIALISED) {
-		*ccc = cred->ccache;
-		return 0;
+		time_t lifetime;
+		bool expired = false;
+		ret = krb5_cc_get_lifetime(cred->ccache->smb_krb5_context->krb5_context, 
+					   cred->ccache->ccache, &lifetime);
+		if (ret == KRB5_CC_END) {
+			/* If we have a particular ccache set, without
+			 * an initial ticket, then assume there is a
+			 * good reason */
+		} else if (ret == 0) {
+			if (lifetime == 0) {
+				DEBUG(3, ("Ticket in credentials cache for %s expired, will refresh\n",
+					  cli_credentials_get_principal(cred, cred)));
+				expired = true;
+			} else if (lifetime < 300) {
+				DEBUG(3, ("Ticket in credentials cache for %s will shortly expire (%u secs), will refresh\n", 
+					  cli_credentials_get_principal(cred, cred), (unsigned int)lifetime));
+				expired = true;
+			}
+		} else {
+			(*error_string) = talloc_asprintf(cred, "failed to get ccache lifetime: %s\n",
+							  smb_get_krb5_error_message(cred->ccache->smb_krb5_context->krb5_context,
+										     ret, cred));
+			return ret;
+		}
+
+		DEBUG(5, ("Ticket in credentials cache for %s will expire in %u secs\n", 
+			  cli_credentials_get_principal(cred, cred), (unsigned int)lifetime));
+		
+		if (!expired) {
+			*ccc = cred->ccache;
+			return 0;
+		}
 	}
 	if (cli_credentials_is_anonymous(cred)) {
 		(*error_string) = "Cannot get anonymous kerberos credentials";
@@ -416,8 +452,31 @@ _PUBLIC_ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
 
 	if (cred->client_gss_creds_obtained >= cred->client_gss_creds_threshold && 
 	    cred->client_gss_creds_obtained > CRED_UNINITIALISED) {
-		*_gcc = cred->client_gss_creds;
-		return 0;
+		bool expired = false;
+		OM_uint32 lifetime = 0;
+		gss_cred_usage_t usage = 0;
+		maj_stat = gss_inquire_cred(&min_stat, cred->client_gss_creds->creds, 
+					    NULL, &lifetime, &usage, NULL);
+		if (maj_stat == GSS_S_CREDENTIALS_EXPIRED) {
+			DEBUG(3, ("Credentials for %s expired, must refresh credentials cache\n", cli_credentials_get_principal(cred, cred)));
+			expired = true;
+		} else if (maj_stat == GSS_S_COMPLETE && lifetime < 300) {
+			DEBUG(3, ("Credentials for %s will expire shortly (%u sec), must refresh credentials cache\n", cli_credentials_get_principal(cred, cred), lifetime));
+			expired = true;
+		} else if (maj_stat != GSS_S_COMPLETE) {
+			*error_string = talloc_asprintf(cred, "inquiry of credential lifefime via GSSAPI gss_inquire_cred failed: %s\n",
+							gssapi_error_string(cred, maj_stat, min_stat, NULL));
+			return EINVAL;
+		}
+		if (expired) {
+			cli_credentials_unconditionally_invalidate_client_gss_creds(cred);
+		} else {
+			DEBUG(5, ("GSSAPI credentials for %s will expire in %u secs\n", 
+				  cli_credentials_get_principal(cred, cred), (unsigned int)lifetime));
+		
+			*_gcc = cred->client_gss_creds;
+			return 0;
+		}
 	}
 
 	ret = cli_credentials_get_ccache(cred, event_ctx, lp_ctx,
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c
index 47f4774..72c6b3f 100644
--- a/source4/auth/gensec/gensec_gssapi.c
+++ b/source4/auth/gensec/gensec_gssapi.c
@@ -523,6 +523,65 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security,
 			gss_release_buffer(&min_stat2, &output_token);
 			
 			return NT_STATUS_MORE_PROCESSING_REQUIRED;
+		} else if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
+			gss_cred_id_t creds;
+			gss_name_t name;
+			gss_buffer_desc buffer;
+			OM_uint32 lifetime = 0;
+			gss_cred_usage_t usage;
+			const char *role = NULL;
+			DEBUG(0, ("GSS %s Update(krb5)(%d) Update failed, credentials expired during GSSAPI handshake!\n",
+				  role,
+				  gensec_gssapi_state->gss_exchange_count));
+
+			
+			switch (gensec_security->gensec_role) {
+			case GENSEC_CLIENT:
+				creds = gensec_gssapi_state->client_cred->creds;
+				role = "client";
+			case GENSEC_SERVER:
+				creds = gensec_gssapi_state->server_cred->creds;
+				role = "server";
+			}
+
+			maj_stat = gss_inquire_cred(&min_stat, 
+						    creds,
+						    &name, &lifetime, &usage, NULL);
+
+			if (maj_stat == GSS_S_COMPLETE) {
+				const char *usage_string;
+				switch (usage) {
+				case GSS_C_BOTH:
+					usage_string = "GSS_C_BOTH";
+					break;
+				case GSS_C_ACCEPT:
+					usage_string = "GSS_C_ACCEPT";
+					break;
+				case GSS_C_INITIATE:
+					usage_string = "GSS_C_INITIATE";
+					break;
+				}
+				maj_stat = gss_display_name(&min_stat, name, &buffer, NULL);
+				if (maj_stat) {
+					buffer.value = NULL;
+					buffer.length = 0;
+				}
+				if (lifetime > 0) {
+					DEBUG(0, ("GSSAPI gss_inquire_cred indicates expiry of %*.*s in %u sec for %s\n", 
+						  (int)buffer.length, (int)buffer.length, (char *)buffer.value, 
+						  lifetime, usage_string));
+				} else {
+					DEBUG(0, ("GSSAPI gss_inquire_cred indicates %*.*s has already expired for %s\n", 
+						  (int)buffer.length, (int)buffer.length, (char *)buffer.value, 
+						  usage_string));
+				}
+				gss_release_buffer(&min_stat, &buffer);
+				gss_release_name(&min_stat, &name);
+			} else if (maj_stat != GSS_S_COMPLETE) {
+				DEBUG(0, ("inquiry of credential lifefime via GSSAPI gss_inquire_cred failed: %s\n",
+					  gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
+			}
+			return NT_STATUS_INVALID_PARAMETER;
 		} else if (gss_oid_equal(gensec_gssapi_state->gss_oid, gss_mech_krb5)) {
 			switch (min_stat) {
 			case KRB5KRB_AP_ERR_TKT_NYV:


-- 
Samba Shared Repository


More information about the samba-cvs mailing list