[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Fri Jul 23 11:56:14 MDT 2010


The branch, master has been updated
       via  5912206... Fix bug 7583 - Smbclient fails to kerberos connect to a Alfresco JLAN CIFS Server
      from  c75106f... s3: not use as-needed by default and auto use if enable-developer is active

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


- Log -----------------------------------------------------------------
commit 5912206606babc178aa1e3c1a3be853eba808323
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jul 23 10:54:46 2010 -0700

    Fix bug 7583 - Smbclient fails to kerberos connect to a Alfresco JLAN CIFS Server
    
    Correctly calculate the gssapi channel binding checkum.
    
    Jeremy
    
    Signed off by: simo <idra at samba.org>

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

Summary of changes:
 source3/libsmb/clikrb5.c |  303 +++++++++++++++++++++++-----------------------
 1 files changed, 151 insertions(+), 152 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c
index 68b45d8..fb2fdba 100644
--- a/source3/libsmb/clikrb5.c
+++ b/source3/libsmb/clikrb5.c
@@ -35,14 +35,16 @@
 
 #define GSSAPI_CHECKSUM      0x8003             /* Checksum type value for Kerberos */
 #define GSSAPI_BNDLENGTH     16                 /* Bind Length (rfc-1964 pg.3) */
-#define GSSAPI_CHECKSUM_SIZE (12+GSSAPI_BNDLENGTH)
-
-#if defined(TKT_FLG_OK_AS_DELEGATE ) && defined(HAVE_KRB5_FWD_TGT_CREDS) && defined(HAVE_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE) && defined(KRB5_AUTH_CONTEXT_USE_SUBKEY)
-static krb5_error_code ads_krb5_get_fwd_ticket( krb5_context context,
-                                         krb5_auth_context *auth_context,
-                                         krb5_creds *credsp,
-                                         krb5_ccache ccache,
-                                         krb5_data *authenticator);
+#define GSSAPI_CHECKSUM_SIZE (4+GSSAPI_BNDLENGTH+4) /* Length of bind length,
+							bind field, flags field. */
+
+/* MIT krb5 1.7beta3 (in Ubuntu Karmic) is missing the prototype,
+   but still has the symbol */
+#if !HAVE_DECL_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE
+krb5_error_code krb5_auth_con_set_req_cksumtype(  
+	krb5_context     context,
+	krb5_auth_context      auth_context,  
+	krb5_cksumtype     cksumtype);
 #endif
 
 /**************************************************************
@@ -652,6 +654,92 @@ static bool ads_cleanup_expired_creds(krb5_context context,
 	return True;
 }
 
+/* Allocate and setup the auth context into the state we need. */
+
+static krb5_error_code setup_auth_context(krb5_context context,
+			krb5_auth_context *auth_context)
+{
+	krb5_error_code retval;
+
+	retval = krb5_auth_con_init(context, auth_context );
+	if (retval) {
+		DEBUG(1,("krb5_auth_con_init failed (%s)\n",
+			error_message(retval)));
+		return retval;
+	}
+
+	/* Ensure this is an addressless ticket. */
+	retval = krb5_auth_con_setaddrs(context, *auth_context, NULL, NULL);
+	if (retval) {
+		DEBUG(1,("krb5_auth_con_setaddrs failed (%s)\n",
+			error_message(retval)));
+	}
+
+	return retval;
+}
+
+static krb5_error_code create_gss_checksum(krb5_data *in_data, /* [inout] */
+						uint32_t gss_flags)
+{
+	unsigned int orig_length = in_data->length;
+	unsigned int base_cksum_size = GSSAPI_CHECKSUM_SIZE;
+	char *gss_cksum = NULL;
+
+	if (orig_length) {
+		/* Extra length field for delgated ticket. */
+		base_cksum_size += 4;
+	}
+
+	if ((unsigned int)base_cksum_size + orig_length <
+			(unsigned int)base_cksum_size) {
+                return EINVAL;
+        }
+
+	gss_cksum = (char *)SMB_MALLOC(base_cksum_size + orig_length);
+	if (gss_cksum == NULL) {
+		return ENOMEM;
+        }
+
+	memset(gss_cksum, '\0', base_cksum_size + orig_length);
+	SIVAL(gss_cksum, 0, GSSAPI_BNDLENGTH);
+
+	/* Precalculated MD5sum of NULL channel bindings (20 bytes) */
+	/* Channel bindings are: (all ints encoded as little endian)
+
+		[4 bytes] initiator_addrtype (255 for null bindings)
+		[4 bytes] initiator_address length
+			[n bytes] .. initiator_address data - not present
+				     in null bindings.
+		[4 bytes] acceptor_addrtype (255 for null bindings)
+		[4 bytes] acceptor_address length
+			[n bytes] .. acceptor_address data - not present
+				     in null bindings.
+		[4 bytes] application_data length
+			[n bytes] .. application_ data - not present
+				     in null bindings.
+		MD5 of this is ""\x14\x8f\x0c\xf7\xb1u\xdey*J\x9a%\xdfV\xc5\x18"
+	*/
+
+	memcpy(&gss_cksum[4],
+		"\x14\x8f\x0c\xf7\xb1u\xdey*J\x9a%\xdfV\xc5\x18",
+		GSSAPI_BNDLENGTH);
+
+	SIVAL(gss_cksum, 20, gss_flags);
+
+	if (orig_length) {
+		SSVAL(gss_cksum, 24, 1); /* The Delegation Option identifier */
+		SSVAL(gss_cksum, 26, orig_length);
+		/* Copy the kerberos KRB_CRED data */
+		memcpy(gss_cksum + 28, in_data->data, orig_length);
+		free(in_data->data);
+		in_data->data = NULL;
+		in_data->length = 0;
+	}
+	in_data->data = gss_cksum;
+	in_data->length = base_cksum_size + orig_length;
+	return 0;
+}
+
 /*
   we can't use krb5_mk_req because w2k wants the service to be in a particular format
 */
@@ -672,7 +760,8 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context,
 	krb5_data in_data;
 	bool creds_ready = False;
 	int i = 0, maxtries = 3;
-	
+	uint32_t gss_flags = 0;
+
 	ZERO_STRUCT(in_data);
 
 	retval = smb_krb5_parse_name(context, principal, &server);
@@ -742,45 +831,51 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context,
 		*expire_time = (time_t)credsp->times.endtime;
 	}
 
-#if defined(TKT_FLG_OK_AS_DELEGATE ) && defined(HAVE_KRB5_FWD_TGT_CREDS) && defined(HAVE_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE) && defined(KRB5_AUTH_CONTEXT_USE_SUBKEY)
+	/* Allocate the auth_context. */
+	retval = setup_auth_context(context, auth_context);
+	if (retval) {
+		DEBUG(1,("setup_auth_context failed (%s)\n",
+			error_message(retval)));
+		goto cleanup_creds;
+	}
+
+#if defined(TKT_FLG_OK_AS_DELEGATE ) && defined(HAVE_KRB5_FWD_TGT_CREDS) && defined(HAVE_KRB5_AUTH_CON_SETUSERUSERKEY) && defined(KRB5_AUTH_CONTEXT_USE_SUBKEY)
 	if( credsp->ticket_flags & TKT_FLG_OK_AS_DELEGATE ) {
 		/* Fetch a forwarded TGT from the KDC so that we can hand off a 2nd ticket
 		 as part of the kerberos exchange. */
 
 		DEBUG( 3, ("ads_krb5_mk_req: server marked as OK to delegate to, building forwardable TGT\n")  );
 
-		if( *auth_context == NULL ) {
-			/* Allocate if it has not yet been allocated. */
-			retval = krb5_auth_con_init( context, auth_context );
-			if (retval) {
-				DEBUG(1,("ads_krb5_mk_req: krb5_auth_con_init failed (%s)\n",
-					error_message(retval)));
-				goto cleanup_creds;
-			}
-		}
-
-		retval = krb5_auth_con_setuseruserkey( context, *auth_context, &credsp->keyblock );
+		retval = krb5_auth_con_setuseruserkey(context,
+					*auth_context,
+					&credsp->keyblock );
 		if (retval) {
-			DEBUG(1,("ads_krb5_mk_req: krb5_auth_con_setuseruserkey failed (%s)\n",
+			DEBUG(1,("krb5_auth_con_setuseruserkey failed (%s)\n",
 				error_message(retval)));
 			goto cleanup_creds;
 		}
 
 		/* Must use a subkey for forwarded tickets. */
-		retval = krb5_auth_con_setflags( context, *auth_context, KRB5_AUTH_CONTEXT_USE_SUBKEY);
+		retval = krb5_auth_con_setflags(context,
+				*auth_context,
+				KRB5_AUTH_CONTEXT_USE_SUBKEY);
 		if (retval) {
-			DEBUG(1,("ads_krb5_mk_req: krb5_auth_con_setflags failed (%s)\n",
+			DEBUG(1,("krb5_auth_con_setflags failed (%s)\n",
 				error_message(retval)));
 			goto cleanup_creds;
 		}
 
-		retval = ads_krb5_get_fwd_ticket( context,
-						auth_context,
-						credsp,
-						ccache,
-						&in_data );
+		retval = krb5_fwd_tgt_creds(context,/* Krb5 context [in] */
+				*auth_context,  /* Authentication context [in] */
+				CONST_DISCARD(char *, KRB5_TGS_NAME),  /* Ticket service name ("krbtgt") [in] */
+				credsp->client, /* Client principal for the tgt [in] */
+				credsp->server, /* Server principal for the tgt [in] */
+				ccache,         /* Credential cache to use for storage [in] */
+				1,              /* Turn on for "Forwardable ticket" [in] */
+				&in_data );     /* Resulting response [out] */
+
 		if (retval) {
-			DEBUG( 3, ("ads_krb5_get_fwd_ticket failed (%s)\n",
+			DEBUG( 3, ("krb5_fwd_tgt_creds failed (%s)\n",
 				   error_message( retval ) ) );
 
 			/*
@@ -795,10 +890,35 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context,
 			}
 			krb5_auth_con_free(context, *auth_context);
 			*auth_context = NULL;
+			retval = setup_auth_context(context, auth_context);
+			if (retval) {
+				DEBUG(1,("setup_auth_context failed (%s)\n",
+					error_message(retval)));
+				goto cleanup_creds;
+			}
+		} else {
+			/* We got a delegated ticket. */
+			gss_flags |= GSS_C_DELEG_FLAG;
 		}
 	}
 #endif
 
+	/* Frees and reallocates in_data into a GSS checksum blob. */
+	retval = create_gss_checksum(&in_data, gss_flags);
+	if (retval) {
+		goto cleanup_data;
+	}
+
+#if defined(HAVE_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE)
+	/* We always want GSS-checksum types. */
+	retval = krb5_auth_con_set_req_cksumtype(context, *auth_context, GSSAPI_CHECKSUM );
+	if (retval) {
+		DEBUG(1,("krb5_auth_con_set_req_cksumtype failed (%s)\n",
+			error_message(retval)));
+		goto cleanup_data;
+	}
+#endif
+
 	retval = krb5_mk_req_extended(context, auth_context, ap_req_options, 
 				      &in_data, credsp, outbuf);
 	if (retval) {
@@ -806,6 +926,7 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context,
 			 error_message(retval)));
 	}
 
+cleanup_data:
 	if (in_data.data) {
 		free( in_data.data );
 		in_data.length = 0;
@@ -1864,128 +1985,6 @@ krb5_error_code smb_krb5_keytab_name(TALLOC_CTX *mem_ctx,
 	return ret;
 }
 
-#if defined(TKT_FLG_OK_AS_DELEGATE ) && defined(HAVE_KRB5_FWD_TGT_CREDS) && defined(HAVE_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE) && defined(KRB5_AUTH_CONTEXT_USE_SUBKEY)
-/**************************************************************
-Routine: ads_krb5_get_fwd_ticket
- Description:
-    When a service ticket is flagged as trusted
-    for delegation we should provide a forwardable
-    ticket so that the remote host can act on our
-    behalf.  This is done by taking the 2nd forwardable
-    TGT and storing it in the GSS-API authenticator
-    "checksum".  This routine will populate
-    the krb5_data authenticator with this TGT.
- Parameters:
-    krb5_context context: The kerberos context for this authentication.
-    krb5_auth_context:    The authentication context.
-    krb5_creds *credsp:   The ticket credentials (AS-REP).
-    krb5_ccache ccache:   The credentials cache.
-    krb5_data &authenticator: The checksum field that will store the TGT, and
-     authenticator.data must be freed by the caller.
-
- Returns:
-    krb5_error_code: 0 if no errors, otherwise set.
-**************************************************************/
-
-static krb5_error_code ads_krb5_get_fwd_ticket( krb5_context context,
-					 krb5_auth_context *auth_context,
-					 krb5_creds *credsp,
-					 krb5_ccache ccache,
-					 krb5_data *authenticator)
-{
-	krb5_data fwdData;
-	krb5_error_code retval = 0;
-	char *pChksum = NULL;
-	char *p = NULL;
-
-/* MIT krb5 1.7beta3 (in Ubuntu Karmic) is missing the prototype,
-   but still has the symbol */
-#if !HAVE_DECL_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE
-krb5_error_code krb5_auth_con_set_req_cksumtype(  
-	krb5_context     context,
-	krb5_auth_context      auth_context,  
-	krb5_cksumtype     cksumtype);
-#endif
-
-	ZERO_STRUCT(fwdData);
-	ZERO_STRUCTP(authenticator);
-
-	retval = krb5_fwd_tgt_creds(context,/* Krb5 context [in] */
-				*auth_context,  /* Authentication context [in] */
-				CONST_DISCARD(char *, KRB5_TGS_NAME),  /* Ticket service name ("krbtgt") [in] */
-				credsp->client, /* Client principal for the tgt [in] */
-				credsp->server, /* Server principal for the tgt [in] */
-				ccache,         /* Credential cache to use for storage [in] */
-				1,              /* Turn on for "Forwardable ticket" [in] */
-				&fwdData );     /* Resulting response [out] */
-
-
-	if (retval) {
-		DEBUG(1,("ads_krb5_get_fwd_ticket: krb5_fwd_tgt_creds failed (%s)\n", 
-			error_message(retval)));
-		goto out;
-	}
-
-	if ((unsigned int)GSSAPI_CHECKSUM_SIZE + (unsigned int)fwdData.length <
-		(unsigned int)GSSAPI_CHECKSUM_SIZE) {
-		retval = EINVAL;
-		goto out;
-	}
-
-	/* We're going to allocate a gssChecksum structure with a little
-	   extra data the length of the kerberos credentials length
-	   (APPLICATION 22) so that we can pack it on the end of the structure.
-	*/
-
-	pChksum	= (char *)SMB_MALLOC(GSSAPI_CHECKSUM_SIZE + fwdData.length );
-	if (!pChksum) {
-		retval = ENOMEM;
-		goto out;
-	}
-
-	p = pChksum;
-
-	SIVAL(p, 0, GSSAPI_BNDLENGTH);
-	p += 4;
-
-	/* Zero out the bindings fields */
-	memset(p, '\0', GSSAPI_BNDLENGTH );
-	p += GSSAPI_BNDLENGTH;
-
-	SIVAL(p, 0, GSS_C_DELEG_FLAG );
-	p += 4;
-	SSVAL(p, 0, 1 );
-	p += 2;
-	SSVAL(p, 0, fwdData.length );
-	p += 2;
-
-	/* Migrate the kerberos KRB_CRED data to the checksum delegation */
-	memcpy(p, fwdData.data, fwdData.length );
-	p += fwdData.length;
-
-	/* We need to do this in order to allow our GSS-API  */
-	retval = krb5_auth_con_set_req_cksumtype( context, *auth_context, GSSAPI_CHECKSUM );
-	if (retval) {
-		goto out;
-	}
-
-	/* We now have a service ticket, now turn it into an AP-REQ. */
-	authenticator->length = fwdData.length + GSSAPI_CHECKSUM_SIZE;
-
-	/* Caller should call free() when they're done with this. */
-	authenticator->data = (char *)pChksum;
-
-  out:
-
- 	/* Remove that input data, we never needed it anyway. */
-   	if (fwdData.length > 0) {
-  		krb5_free_data_contents( context, &fwdData );
-   	}
-
-	return retval;
-}
-#endif
-
 #if defined(HAVE_KRB5_GET_CREDS_OPT_SET_IMPERSONATE) && \
     defined(HAVE_KRB5_GET_CREDS_OPT_ALLOC) && \
     defined(HAVE_KRB5_GET_CREDS)


-- 
Samba Shared Repository


More information about the samba-cvs mailing list