DCERPC and krb5

Stefan (metze) Metzmacher metze at samba.org
Tue Dec 21 12:44:19 GMT 2004


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi Andrew,

here's my current DCERPC and krb5 patch, this sometimes works and sometimes not( so it has bugs)...



- --
metze

Stefan Metzmacher <metze at samba.org> www.samba.org
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3-nr1 (Windows XP)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFByBqjm70gjA5TCD8RAudHAJ0XKW6H6Ke4JAwPbe4eRwwVj16mswCeK2l8
7QXAZCIAlGbx0ekpJf+6azw=
=tqZt
-----END PGP SIGNATURE-----
-------------- next part --------------
Index: libcli/auth/kerberos_verify.c
===================================================================
--- libcli/auth/kerberos_verify.c	(revision 4312)
+++ libcli/auth/kerberos_verify.c	(working copy)
@@ -244,6 +244,40 @@
 	return ret;
 }
 
+static krb5_error_code gssapi_krb5_8003_checksum_flags(krb5_context context, const Checksum *cksum, uint32_t *_flags)
+{
+	krb5_error_code ret = 0;
+	uint8_t *p;
+	uint32_t hash_length;
+	uint8_t hash[16];
+	uint32_t flags;
+
+	if(cksum->cksumtype != 0x8003 || cksum->checksum.length < 24) {
+		return GSS_S_BAD_BINDINGS;
+	}
+
+	p = cksum->checksum.data;
+
+	hash_length = IVAL(p, 0);
+	p += 4;
+
+	if (hash_length != sizeof(hash)) {
+		return GSS_S_BAD_BINDINGS;
+	}
+
+	/* TODO: check hash! */
+
+	p += sizeof(hash);
+
+	flags = IVAL(p, 0);
+
+DEBUG(0,("gss_flags: 0x%08X\n", flags));
+
+	*_flags = flags;
+
+	return ret;
+}
+
 /**********************************************************************************
  Verify an incoming ticket and parse out the principal name and 
  authorization_data if available.
@@ -261,7 +295,9 @@
 	krb5_data packet;
 	krb5_ticket *tkt = NULL;
 	krb5_rcache rcache = NULL;
+	krb5_authenticator authenticator;
 	int ret;
+	uint32 flags = 0;
 
 	krb5_principal host_princ = NULL;
 	char *host_princ_s = NULL;
@@ -332,17 +368,36 @@
 		goto out;
 	}
 
-	ret = krb5_mk_rep(context, auth_context, &packet);
+	ret = krb5_auth_con_getauthenticator(context, auth_context, &authenticator);
 	if (ret) {
-		DEBUG(3,("ads_verify_ticket: Failed to generate mutual authentication reply (%s)\n",
+		DEBUG(3,("ads_verify_ticket: Failed to get authenticator (%s)\n",
 			error_message(ret)));
 		goto out;
 	}
 
-	*ap_rep = data_blob_talloc(mem_ctx, packet.data, packet.length);
-	SAFE_FREE(packet.data);
-	packet.length = 0;
+	ret = gssapi_krb5_8003_checksum_flags(context, authenticator->cksum, &flags);
+	if (ret) {
+		DEBUG(3,("ads_verify_ticket: Failed to get authenticator (%s)\n",
+			error_message(ret)));
+		goto out;
+	}
 
+	if (flags & GSS_C_MUTUAL_FLAG) {
+		ret = krb5_mk_rep(context, auth_context, &packet);
+		if (ret) {
+			DEBUG(3,("ads_verify_ticket: Failed to generate mutual authentication reply (%s)\n",
+				error_message(ret)));
+			goto out;
+		}
+
+		*ap_rep = data_blob_talloc(mem_ctx, packet.data, packet.length);
+		SAFE_FREE(packet.data);
+		packet.length = 0;
+	} else {
+		DEBUG(3,("no mutal: 0x%08X & 0x%08X\n", flags, GSS_C_MUTUAL_FLAG));
+		*ap_rep = data_blob(NULL, 0);
+	}
+
 #if 0
 	file_save("/tmp/ticket.dat", ticket->data, ticket->length);
 #endif
@@ -375,7 +430,14 @@
 		goto out;
 	}
 
-	sret = NT_STATUS_OK;
+#ifndef GSS_C_DCE_STYLE_FLAG
+#define GSS_C_DCE_STYLE_FLAG 0x1000
+#endif
+	if (flags & GSS_C_DCE_STYLE_FLAG) {
+		sret = NT_STATUS_MORE_PROCESSING_REQUIRED;
+	} else {
+		sret = NT_STATUS_OK;
+	}
 
  out:
 
@@ -383,11 +445,8 @@
 		release_server_mutex();
 	}
 
-	if (!NT_STATUS_IS_OK(sret)) {
+	if (!NT_STATUS_EQUAL(sret, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(sret)) {
 		data_blob_free(auth_data);
-	}
-
-	if (!NT_STATUS_IS_OK(sret)) {
 		data_blob_free(ap_rep);
 	}
 
@@ -404,4 +463,29 @@
 	return sret;
 }
 
+
+ NTSTATUS ads_krb5_rd_rep(TALLOC_CTX *mem_ctx, 
+			   krb5_context context,
+			   krb5_auth_context auth_context,
+			   const DATA_BLOB *ap_rep_in)
+{
+	krb5_data packet;
+	krb5_ap_rep_enc_part *ap_rep = NULL;
+	int ret;
+
+	ZERO_STRUCT(packet);
+
+	packet.length = ap_rep_in->length;
+	packet.data = (krb5_pointer)ap_rep_in->data;
+
+	ret = krb5_rd_rep(context, auth_context, &packet, &ap_rep);
+	if (ret) {
+		DEBUG(3,("ads_krb5_rd_rep: Failed to handle ap_rep (%s)\n",
+			error_message(ret)));
+		return NT_STATUS_LOGON_FAILURE;
+	}
+
+	return NT_STATUS_OK;
+}
+
 #endif /* HAVE_KRB5 */
Index: libcli/auth/kerberos.h
===================================================================
--- libcli/auth/kerberos.h	(revision 4312)
+++ libcli/auth/kerberos.h	(working copy)
@@ -81,6 +81,10 @@
 			   char **principal, DATA_BLOB *auth_data,
 			   DATA_BLOB *ap_rep,
 			   krb5_keyblock *keyblock);
+NTSTATUS ads_krb5_rd_rep(TALLOC_CTX *mem_ctx, 
+			   krb5_context context,
+			   krb5_auth_context auth_context,
+			   const DATA_BLOB *ap_rep_in);
 int kerberos_kinit_password_cc(krb5_context ctx, krb5_ccache cc, const char *principal, const char *password, time_t *expire_time, time_t *kdc_time);
 #endif /* HAVE_KRB5 */
 
Index: libcli/auth/gensec_krb5.c
===================================================================
--- libcli/auth/gensec_krb5.c	(revision 4312)
+++ libcli/auth/gensec_krb5.c	(working copy)
@@ -35,6 +35,7 @@
 
 enum GENSEC_KRB5_STATE {
 	GENSEC_KRB5_SERVER_START,
+	GENSEC_KRB5_SERVER_DCE_STYLE,
 	GENSEC_KRB5_CLIENT_START,
 	GENSEC_KRB5_CLIENT_MUTUAL_AUTH,
 	GENSEC_KRB5_DONE
@@ -50,6 +51,7 @@
 	krb5_data ticket;
 	krb5_keyblock krb5_keyblock;
 	char *peer_principal;
+	BOOL wrap;
 };
 
 #ifdef KRB5_DO_VERIFY_PAC
@@ -521,6 +523,7 @@
 
 		/* Parse the GSSAPI wrapping, if it's there... (win2k3 allows it to be omited) */
 		if (!gensec_gssapi_parse_krb5_wrap(out_mem_ctx, &in, &unwrapped_in, tok_id)) {
+			gensec_krb5_state->wrap = False;
 			nt_status = ads_verify_ticket(out_mem_ctx, 
 						      gensec_krb5_state->krb5_context, 
 						      gensec_krb5_state->krb5_auth_context, 
@@ -528,6 +531,7 @@
 						      &principal, &pac, &unwrapped_out,
 						      &gensec_krb5_state->krb5_keyblock);
 		} else {
+			gensec_krb5_state->wrap = True;
 			/* TODO: check the tok_id */
 			nt_status = ads_verify_ticket(out_mem_ctx, 
 						      gensec_krb5_state->krb5_context, 
@@ -537,7 +541,7 @@
 						      &gensec_krb5_state->krb5_keyblock);
 		}
 
-		if (!NT_STATUS_IS_OK(nt_status)) {
+		if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(nt_status)) {
 			return nt_status;
 		}
 
@@ -545,16 +549,50 @@
 			gensec_krb5_state->pac = data_blob_talloc_reference(gensec_krb5_state, &pac);
 		}
 
+		/* wrap that up in a nice GSS-API wrapping */
+		if (gensec_krb5_state->wrap) {
+			*out = gensec_gssapi_gen_krb5_wrap(out_mem_ctx, &unwrapped_out, TOK_ID_KRB_AP_REP);
+		} else {
+			*out = unwrapped_out;
+		}
+
+		gensec_krb5_state->peer_principal = talloc_steal(gensec_krb5_state, principal);
 		if (NT_STATUS_IS_OK(nt_status)) {
 			gensec_krb5_state->state_position = GENSEC_KRB5_DONE;
-			/* wrap that up in a nice GSS-API wrapping */
-#ifndef GENSEC_SEND_UNWRAPPED_KRB5
-			*out = gensec_gssapi_gen_krb5_wrap(out_mem_ctx, &unwrapped_out, TOK_ID_KRB_AP_REP);
-#else
+		} else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+			gensec_krb5_state->state_position = GENSEC_KRB5_SERVER_DCE_STYLE;
+		}
+		return nt_status;
+	}
+	case GENSEC_KRB5_SERVER_DCE_STYLE: {
+		DATA_BLOB unwrapped_in;
+		DATA_BLOB unwrapped_out = data_blob(NULL, 0);
+		uint8 tok_id[2];
+
+		if (!in.data) {
 			*out = unwrapped_out;
-#endif
-			gensec_krb5_state->peer_principal = talloc_steal(gensec_krb5_state, principal);
+			return NT_STATUS_MORE_PROCESSING_REQUIRED;
+		}	
+
+		/* Parse the GSSAPI wrapping, if it's there... (win2k3 allows it to be omited) */
+		if (!gensec_gssapi_parse_krb5_wrap(out_mem_ctx, &in, &unwrapped_in, tok_id)) {
+			gensec_krb5_state->wrap = False;
+			nt_status = ads_krb5_rd_rep(out_mem_ctx, 
+						      gensec_krb5_state->krb5_context, 
+						      gensec_krb5_state->krb5_auth_context, 
+						      &in);
+		} else {
+			gensec_krb5_state->wrap = True;
+			/* TODO: check the tok_id */
+			nt_status = ads_krb5_rd_rep(out_mem_ctx, 
+						      gensec_krb5_state->krb5_context, 
+						      gensec_krb5_state->krb5_auth_context, 
+						      &unwrapped_in);
 		}
+		if (!NT_STATUS_IS_OK(nt_status)) {
+			return nt_status;
+		}
+		gensec_krb5_state->state_position = GENSEC_KRB5_DONE;
 		return nt_status;
 	}
 	case GENSEC_KRB5_DONE:


More information about the samba-technical mailing list