libwinpr-sspi: add support for NTLMv2 Channel Binding Token (CBT)

This commit is contained in:
Marc-André Moreau 2013-01-09 00:20:08 -05:00
parent d8949f5d8f
commit 1d893ed268
9 changed files with 173 additions and 156 deletions

View File

@ -23,6 +23,9 @@
#include "crypto.h"
#include "certificate.h"
#include <winpr/crt.h>
#include <winpr/sspi.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
@ -40,6 +43,7 @@ struct rdp_tls
BYTE* PublicKey;
DWORD PublicKeyLength;
rdpSettings* settings;
SecPkgContext_Bindings* Bindings;
rdpCertificateStore* certificate_store;
};

View File

@ -80,7 +80,7 @@ int rpc_ncacn_http_send_in_channel_request(rdpRpc* rpc)
content_length = (continue_needed) ? 0 : 0x40000000;
s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer, content_length, TSG_CHANNEL_IN);
s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer[0], content_length, TSG_CHANNEL_IN);
DEBUG_RPC("\n%s", Stream_Buffer(s));
rpc_in_write(rpc, Stream_Buffer(s), Stream_Length(s));
@ -102,8 +102,8 @@ int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc)
crypto_base64_decode((BYTE*) http_response->AuthParam, strlen(http_response->AuthParam),
&ntlm_token_data, &ntlm_token_length);
ntlm->inputBuffer.pvBuffer = ntlm_token_data;
ntlm->inputBuffer.cbBuffer = ntlm_token_length;
ntlm->inputBuffer[0].pvBuffer = ntlm_token_data;
ntlm->inputBuffer[0].cbBuffer = ntlm_token_length;
http_response_free(http_response);
@ -123,7 +123,8 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel)
ntlm = rpc->NtlmHttpOut->ntlm;
ntlm_client_init(ntlm, TRUE, settings->GatewayUsername,
settings->GatewayDomain, settings->GatewayPassword);
settings->GatewayDomain, settings->GatewayPassword,
rpc->TlsIn->Bindings);
//ntlm_client_make_spn(ntlm, NULL, settings->GatewayHostname);
ntlm_client_make_spn(ntlm, _T("HTTP"), settings->GatewayHostname);
@ -168,7 +169,7 @@ int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc)
content_length = (continue_needed) ? 0 : 76;
s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer, content_length, TSG_CHANNEL_OUT);
s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer[0], content_length, TSG_CHANNEL_OUT);
DEBUG_RPC("\n%s", Stream_Buffer(s));
rpc_out_write(rpc, Stream_Buffer(s), Stream_Length(s));
@ -190,8 +191,8 @@ int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc)
crypto_base64_decode((BYTE*) http_response->AuthParam, strlen(http_response->AuthParam),
&ntlm_token_data, &ntlm_token_length);
ntlm->inputBuffer.pvBuffer = ntlm_token_data;
ntlm->inputBuffer.cbBuffer = ntlm_token_length;
ntlm->inputBuffer[0].pvBuffer = ntlm_token_data;
ntlm->inputBuffer[0].cbBuffer = ntlm_token_length;
http_response_free(http_response);

View File

@ -37,12 +37,15 @@
#include "ntlm.h"
BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char* password)
BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char* password, SecPkgContext_Bindings* Bindings)
{
SECURITY_STATUS status;
sspi_GlobalInit();
ntlm->http = http;
ntlm->Bindings = Bindings;
#ifdef WITH_NATIVE_SSPI
{
HMODULE hSSPI;
@ -91,7 +94,7 @@ BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char*
ntlm->fContextReq = 0;
if (http)
if (ntlm->http)
{
/* flags for HTTP authentication */
ntlm->fContextReq |= ISC_REQ_CONFIDENTIALITY;
@ -195,25 +198,33 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm)
{
SECURITY_STATUS status;
if (ntlm->outputBuffer.pvBuffer)
if (ntlm->outputBuffer[0].pvBuffer)
{
free(ntlm->outputBuffer.pvBuffer);
ntlm->outputBuffer.pvBuffer = NULL;
free(ntlm->outputBuffer[0].pvBuffer);
ntlm->outputBuffer[0].pvBuffer = NULL;
}
ntlm->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
ntlm->outputBufferDesc.cBuffers = 1;
ntlm->outputBufferDesc.pBuffers = &ntlm->outputBuffer;
ntlm->outputBuffer.BufferType = SECBUFFER_TOKEN;
ntlm->outputBuffer.cbBuffer = ntlm->cbMaxToken;
ntlm->outputBuffer.pvBuffer = malloc(ntlm->outputBuffer.cbBuffer);
ntlm->outputBufferDesc.pBuffers = ntlm->outputBuffer;
ntlm->outputBuffer[0].BufferType = SECBUFFER_TOKEN;
ntlm->outputBuffer[0].cbBuffer = ntlm->cbMaxToken;
ntlm->outputBuffer[0].pvBuffer = malloc(ntlm->outputBuffer[0].cbBuffer);
if (ntlm->haveInputBuffer)
{
ntlm->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
ntlm->inputBufferDesc.cBuffers = 1;
ntlm->inputBufferDesc.pBuffers = &ntlm->inputBuffer;
ntlm->inputBuffer.BufferType = SECBUFFER_TOKEN;
ntlm->inputBufferDesc.pBuffers = ntlm->inputBuffer;
ntlm->inputBuffer[0].BufferType = SECBUFFER_TOKEN;
if (ntlm->Bindings)
{
ntlm->inputBufferDesc.cBuffers++;
ntlm->inputBuffer[1].BufferType = SECBUFFER_CHANNEL_BINDINGS;
ntlm->inputBuffer[1].cbBuffer = ntlm->Bindings->BindingsLength;
ntlm->inputBuffer[1].pvBuffer = (void*) ntlm->Bindings->Bindings;
}
}
status = ntlm->table->InitializeSecurityContext(&ntlm->credentials,
@ -243,7 +254,7 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm)
if (ntlm->haveInputBuffer)
{
free(ntlm->inputBuffer.pvBuffer);
free(ntlm->inputBuffer[0].pvBuffer);
}
ntlm->haveInputBuffer = TRUE;

View File

@ -43,14 +43,15 @@ typedef struct rdp_ntlm_http rdpNtlmHttp;
struct rdp_ntlm
{
BOOL http;
CtxtHandle context;
ULONG cbMaxToken;
ULONG fContextReq;
ULONG pfContextAttr;
TimeStamp expiration;
PSecBuffer pBuffer;
SecBuffer inputBuffer;
SecBuffer outputBuffer;
SecBuffer inputBuffer[2];
SecBuffer outputBuffer[2];
BOOL haveContext;
BOOL haveInputBuffer;
LPTSTR ServicePrincipalName;
@ -62,6 +63,7 @@ struct rdp_ntlm
SecurityFunctionTable* table;
SEC_WINNT_AUTH_IDENTITY identity;
SecPkgContext_Sizes ContextSizes;
SecPkgContext_Bindings* Bindings;
};
struct rdp_ntlm_http
@ -72,7 +74,8 @@ struct rdp_ntlm_http
BOOL ntlm_authenticate(rdpNtlm* ntlm);
BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL confidentiality, char* user, char* domain, char* password);
BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL confidentiality, char* user,
char* domain, char* password, SecPkgContext_Bindings* Bindings);
void ntlm_client_uninit(rdpNtlm* ntlm);
BOOL ntlm_client_make_spn(rdpNtlm* ntlm, LPCTSTR ServiceClass, char* hostname);

View File

@ -102,7 +102,7 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
rpc->ntlm = ntlm_new();
ntlm_client_init(rpc->ntlm, FALSE, settings->GatewayUsername, settings->GatewayDomain, settings->GatewayPassword);
ntlm_client_init(rpc->ntlm, FALSE, settings->GatewayUsername, settings->GatewayDomain, settings->GatewayPassword, NULL);
ntlm_client_make_spn(rpc->ntlm, NULL, settings->GatewayHostname);
ntlm_authenticate(rpc->ntlm);
@ -112,8 +112,8 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
rpc_pdu_header_init(rpc, (rpcconn_hdr_t*) bind_pdu);
bind_pdu->auth_length = rpc->ntlm->outputBuffer.cbBuffer;
bind_pdu->auth_verifier.auth_value = rpc->ntlm->outputBuffer.pvBuffer;
bind_pdu->auth_length = rpc->ntlm->outputBuffer[0].cbBuffer;
bind_pdu->auth_verifier.auth_value = rpc->ntlm->outputBuffer[0].pvBuffer;
bind_pdu->ptype = PTYPE_BIND;
bind_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_SUPPORT_HEADER_SIGN | PFC_CONC_MPX;
@ -228,11 +228,11 @@ int rpc_recv_bind_ack_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
rpc->max_recv_frag = header->bind_ack.max_xmit_frag;
rpc->max_xmit_frag = header->bind_ack.max_recv_frag;
rpc->ntlm->inputBuffer.cbBuffer = header->common.auth_length;
rpc->ntlm->inputBuffer.pvBuffer = malloc(header->common.auth_length);
rpc->ntlm->inputBuffer[0].cbBuffer = header->common.auth_length;
rpc->ntlm->inputBuffer[0].pvBuffer = malloc(header->common.auth_length);
auth_data = buffer + (header->common.frag_length - header->common.auth_length);
CopyMemory(rpc->ntlm->inputBuffer.pvBuffer, auth_data, header->common.auth_length);
CopyMemory(rpc->ntlm->inputBuffer[0].pvBuffer, auth_data, header->common.auth_length);
ntlm_authenticate(rpc->ntlm);
@ -261,8 +261,8 @@ int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
rpc_pdu_header_init(rpc, (rpcconn_hdr_t*) auth_3_pdu);
auth_3_pdu->auth_length = rpc->ntlm->outputBuffer.cbBuffer;
auth_3_pdu->auth_verifier.auth_value = rpc->ntlm->outputBuffer.pvBuffer;
auth_3_pdu->auth_length = rpc->ntlm->outputBuffer[0].cbBuffer;
auth_3_pdu->auth_verifier.auth_value = rpc->ntlm->outputBuffer[0].pvBuffer;
auth_3_pdu->ptype = PTYPE_RPC_AUTH_3;
auth_3_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_CONC_MPX;

View File

@ -22,6 +22,7 @@
#endif
#include <winpr/crt.h>
#include <winpr/sspi.h>
#include <freerdp/utils/stream.h>
#include <freerdp/utils/tcp.h>
@ -58,6 +59,86 @@ static void tls_free_certificate(CryptoCert cert)
free(cert);
}
static void tls_md5_update_uint32_be(MD5_CTX* md5, UINT32 num)
{
BYTE be32[4];
be32[0] = (num >> 0) & 0xFF;
be32[1] = (num >> 8) & 0xFF;
be32[2] = (num >> 16) & 0xFF;
be32[3] = (num >> 24) & 0xFF;
MD5_Update(md5, be32, 4);
}
BYTE* tls_get_channel_bindings_hash(SecPkgContext_Bindings* Bindings)
{
MD5_CTX md5;
BYTE* ChannelBindingToken;
UINT32 ChannelBindingTokenLength;
BYTE* ChannelBindingsHash;
UINT32 ChannelBindingsHashLength;
SEC_CHANNEL_BINDINGS* ChannelBindings;
ChannelBindings = Bindings->Bindings;
ChannelBindingTokenLength = Bindings->BindingsLength - sizeof(SEC_CHANNEL_BINDINGS);
ChannelBindingToken = &((BYTE*) ChannelBindings)[ChannelBindings->dwApplicationDataOffset];
ChannelBindingsHashLength = 16;
ChannelBindingsHash = (BYTE*) malloc(ChannelBindingsHashLength);
ZeroMemory(ChannelBindingsHash, ChannelBindingsHashLength);
MD5_Init(&md5);
tls_md5_update_uint32_be(&md5, ChannelBindings->dwInitiatorAddrType);
tls_md5_update_uint32_be(&md5, ChannelBindings->cbInitiatorLength);
tls_md5_update_uint32_be(&md5, ChannelBindings->dwAcceptorAddrType);
tls_md5_update_uint32_be(&md5, ChannelBindings->cbAcceptorLength);
tls_md5_update_uint32_be(&md5, ChannelBindings->cbApplicationDataLength);
MD5_Update(&md5, (void*) ChannelBindingToken, ChannelBindingTokenLength);
MD5_Final(ChannelBindingsHash, &md5);
return ChannelBindingsHash;
}
#define TLS_SERVER_END_POINT "tls-server-end-point:"
SecPkgContext_Bindings* tls_get_channel_bindings(X509* cert)
{
int PrefixLength;
BYTE CertificateHash[32];
UINT32 CertificateHashLength;
BYTE* ChannelBindingToken;
UINT32 ChannelBindingTokenLength;
SEC_CHANNEL_BINDINGS* ChannelBindings;
SecPkgContext_Bindings* ContextBindings;
ZeroMemory(CertificateHash, sizeof(CertificateHash));
X509_digest(cert, EVP_sha256(), CertificateHash, &CertificateHashLength);
PrefixLength = strlen(TLS_SERVER_END_POINT);
ChannelBindingTokenLength = PrefixLength + CertificateHashLength;
ContextBindings = (SecPkgContext_Bindings*) malloc(sizeof(SecPkgContext_Bindings));
ZeroMemory(ContextBindings, sizeof(SecPkgContext_Bindings));
ContextBindings->BindingsLength = sizeof(SEC_CHANNEL_BINDINGS) + ChannelBindingTokenLength;
ChannelBindings = (SEC_CHANNEL_BINDINGS*) malloc(ContextBindings->BindingsLength);
ZeroMemory(ChannelBindings, ContextBindings->BindingsLength);
ContextBindings->Bindings = ChannelBindings;
ChannelBindings->cbApplicationDataLength = ChannelBindingTokenLength;
ChannelBindings->dwApplicationDataOffset = sizeof(SEC_CHANNEL_BINDINGS);
ChannelBindingToken = &((BYTE*) ChannelBindings)[ChannelBindings->dwApplicationDataOffset];
strcpy((char*) ChannelBindingToken, TLS_SERVER_END_POINT);
CopyMemory(&ChannelBindingToken[PrefixLength], CertificateHash, CertificateHashLength);
return ContextBindings;
}
BOOL tls_connect(rdpTls* tls)
{
CryptoCert cert;
@ -135,6 +216,8 @@ BOOL tls_connect(rdpTls* tls)
return FALSE;
}
tls->Bindings = tls_get_channel_bindings(cert->px509);
if (!crypto_cert_get_public_key(cert, &tls->PublicKey, &tls->PublicKeyLength))
{
printf("tls_connect: crypto_cert_get_public_key failed to return the server public key.\n");

View File

@ -416,8 +416,9 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti
NTLM_CONTEXT* context;
SECURITY_STATUS status;
CREDENTIALS* credentials;
PSecBuffer input_buffer;
PSecBuffer output_buffer;
PSecBuffer input_buffer = NULL;
PSecBuffer output_buffer = NULL;
PSecBuffer channel_bindings = NULL;
context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
@ -478,6 +479,18 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti
if (input_buffer->cbBuffer < 1)
return SEC_E_INVALID_TOKEN;
if (pInput->cBuffers > 1)
{
if (pInput->pBuffers[1].BufferType == SECBUFFER_CHANNEL_BINDINGS)
channel_bindings = &pInput->pBuffers[1];
}
if (channel_bindings)
{
context->Bindings.BindingsLength = channel_bindings->cbBuffer;
context->Bindings.Bindings = (SEC_CHANNEL_BINDINGS*) channel_bindings->pvBuffer;
}
if (context->state == NTLM_STATE_CHALLENGE)
{
status = ntlm_read_ChallengeMessage(context, input_buffer);

View File

@ -243,7 +243,7 @@ struct _NTLM_CONTEXT
SEC_WINNT_AUTH_IDENTITY identity;
BYTE* ChannelBindingToken;
BYTE ChannelBindingsHash[16];
SecPkgContext_Bindings EndpointBindings;
SecPkgContext_Bindings Bindings;
SecBuffer NegotiateMessage;
SecBuffer ChallengeMessage;
SecBuffer AuthenticateMessage;

View File

@ -228,66 +228,6 @@ void ntlm_free_unicode_string(PUNICODE_STRING string)
* https://raw.github.com/mozilla/mozilla-central/master/extensions/auth/nsAuthSSPI.cpp
*/
/* Certificate */
BYTE test_Certificate[525] =
"\x30\x82\x02\x09\x30\x82\x01\x76\xa0\x03\x02\x01\x02\x02\x10\xcb"
"\x69\x79\xcd\x51\x75\xc5\xb7\x4b\x67\x30\x83\x6c\x78\x44\x27\x30"
"\x09\x06\x05\x2b\x0e\x03\x02\x1d\x05\x00\x30\x16\x31\x14\x30\x12"
"\x06\x03\x55\x04\x03\x13\x0b\x44\x43\x2d\x57\x53\x32\x30\x30\x38"
"\x52\x32\x30\x1e\x17\x0d\x31\x32\x31\x31\x31\x37\x30\x30\x35\x39"
"\x32\x31\x5a\x17\x0d\x33\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35"
"\x39\x5a\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0b\x44"
"\x43\x2d\x57\x53\x32\x30\x30\x38\x52\x32\x30\x81\x9f\x30\x0d\x06"
"\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00"
"\x30\x81\x89\x02\x81\x81\x00\x9b\x00\xf8\x1a\x2d\x37\xc6\x8d\xa1"
"\x39\x91\x46\xf3\x6a\x1b\xf9\x60\x6c\xb3\x6c\xa0\xac\xed\x85\xe0"
"\x3f\xdc\x92\x86\x36\xbd\x64\xbf\x36\x51\xdb\x57\x3a\x8a\x82\x6b"
"\xd8\x94\x17\x7b\xd3\x91\x11\x98\xef\x19\x06\x52\x30\x03\x73\x67"
"\xc8\xed\x8e\xfa\x0b\x3d\x4c\xc9\x10\x63\x9f\xcf\xb4\xcf\x39\xd8"
"\xfe\x99\xeb\x5b\x11\xf2\xfc\xfa\x86\x24\xd9\xff\xd9\x19\xf5\x69"
"\xb4\xdf\x5a\x5a\xc4\x94\xb4\xb0\x07\x25\x97\x13\xad\x7e\x38\x14"
"\xfb\xd6\x33\x65\x6f\xe6\xf7\x48\x4b\x2d\xb3\x51\x2e\x6d\xc7\xea"
"\x11\x76\x9a\x2b\xf0\x00\x4d\x02\x03\x01\x00\x01\xa3\x60\x30\x5e"
"\x30\x13\x06\x03\x55\x1d\x25\x04\x0c\x30\x0a\x06\x08\x2b\x06\x01"
"\x05\x05\x07\x03\x01\x30\x47\x06\x03\x55\x1d\x01\x04\x40\x30\x3e"
"\x80\x10\xeb\x65\x26\x03\x95\x4b\xd6\xc0\x54\x75\x78\x7c\xb6\x2a"
"\xa1\xbb\xa1\x18\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13"
"\x0b\x44\x43\x2d\x57\x53\x32\x30\x30\x38\x52\x32\x82\x10\xcb\x69"
"\x79\xcd\x51\x75\xc5\xb7\x4b\x67\x30\x83\x6c\x78\x44\x27\x30\x09"
"\x06\x05\x2b\x0e\x03\x02\x1d\x05\x00\x03\x81\x81\x00\x7b\xfa\xfe"
"\xee\x74\x05\xac\xbb\x79\xe9\xda\xca\x00\x44\x96\x94\x71\x92\xb1"
"\xdb\xc9\x9b\x71\x29\xc0\xe4\x28\x5e\x6a\x50\x99\xcd\xa8\x17\xe4"
"\x56\xb9\xef\x7f\x02\x7d\x96\xa3\x48\x14\x72\x75\x2f\xb0\xb5\x87"
"\xee\x55\xe9\x6a\x6d\x28\x3c\xc1\xfd\x00\xe4\x76\xe3\x80\x88\x78"
"\x26\x0d\x6c\x8c\xb8\x64\x61\x63\xb7\x13\x3a\xab\xc7\xdd\x1d\x0a"
"\xd7\x15\x45\xa1\xd6\xd9\x34\xc7\x21\x48\xfb\x43\x87\x38\xda\x1f"
"\x50\x47\xb1\xa5\x5c\x47\xed\x04\x44\x97\xd3\xac\x74\x2d\xeb\x09"
"\x77\x59\xbf\xa3\x54\x5b\xde\x42\xd5\x23\x5a\x71\x9f";
BYTE test_CertificateHash_SHA256[] =
"\xea\x05\xfe\xfe\xcc\x6b\x0b\xd5\x71\xdb\xbc\x5b\xaa\x3e\xd4\x53"
"\x86\xd0\x44\x68\x35\xf7\xb7\x4c\x85\x62\x1b\x99\x83\x47\x5f\x95";
BYTE test_ChannelBindingsHash[] =
"\x65\x86\xE9\x9D\x81\xC2\xFC\x98\x4E\x47\x17\x2F\xD4\xDD\x03\x10";
/*
* Channel Bindings Data:
*
* tls-server-end-point:<binary hash>
*/
char TlsServerEndPointPrefix[] = "tls-server-end-point:";
void ntlm_uint32_to_big_endian(UINT32 num, BYTE be32[4])
{
be32[0] = (num >> 0) & 0xFF;
be32[1] = (num >> 8) & 0xFF;
be32[2] = (num >> 16) & 0xFF;
be32[3] = (num >> 24) & 0xFF;
}
/*
typedef struct gss_channel_bindings_struct {
OM_uint32 initiator_addrtype;
@ -298,83 +238,45 @@ typedef struct gss_channel_bindings_struct {
} *gss_channel_bindings_t;
*/
static void ntlm_md5_update_uint32_be(MD5_CTX* md5, UINT32 num)
{
BYTE be32[4];
be32[0] = (num >> 0) & 0xFF;
be32[1] = (num >> 8) & 0xFF;
be32[2] = (num >> 16) & 0xFF;
be32[3] = (num >> 24) & 0xFF;
MD5_Update(md5, be32, 4);
}
void ntlm_compute_channel_bindings(NTLM_CONTEXT* context)
{
#if 0
MD5_CTX md5;
BYTE be32[4];
int PrefixLength;
SHA256_CTX sha256;
BYTE* CertificateHash;
int CertificateHashLength;
BYTE* pChannelBindingToken;
int ChannelBindingTokenLength;
BYTE* ChannelBindingToken;
UINT32 ChannelBindingTokenLength;
SEC_CHANNEL_BINDINGS* ChannelBindings;
ZeroMemory(context->ChannelBindingsHash, 16);
ChannelBindings = context->Bindings.Bindings;
CertificateHashLength = 32;
CertificateHash = (BYTE*) malloc(CertificateHashLength);
ZeroMemory(CertificateHash, CertificateHashLength);
if (!ChannelBindings)
return;
SHA256_Init(&sha256);
SHA256_Update(&sha256, test_Certificate, sizeof(test_Certificate));
SHA256_Final(CertificateHash, &sha256);
printf("Certificate SHA256 Hash:\n");
winpr_HexDump(CertificateHash, CertificateHashLength);
PrefixLength = strlen(TlsServerEndPointPrefix);
ChannelBindingTokenLength = PrefixLength + CertificateHashLength;
context->ChannelBindingToken = (BYTE*) malloc(ChannelBindingTokenLength + 1);
strcpy((char*) context->ChannelBindingToken, TlsServerEndPointPrefix);
CopyMemory(&context->ChannelBindingToken[PrefixLength], CertificateHash, CertificateHashLength);
printf("ChannelBindingToken:\n");
winpr_HexDump(context->ChannelBindingToken, ChannelBindingTokenLength);
context->EndpointBindings.BindingsLength = sizeof(SEC_CHANNEL_BINDINGS) + ChannelBindingTokenLength;
context->EndpointBindings.Bindings = (SEC_CHANNEL_BINDINGS*) malloc(context->EndpointBindings.BindingsLength);
ZeroMemory(context->EndpointBindings.Bindings, context->EndpointBindings.BindingsLength);
ChannelBindings = context->EndpointBindings.Bindings;
ChannelBindings->cbApplicationDataLength = ChannelBindingTokenLength;
ChannelBindings->dwApplicationDataOffset = sizeof(SEC_CHANNEL_BINDINGS);
pChannelBindingToken = &((BYTE*) ChannelBindings)[ChannelBindings->dwApplicationDataOffset];
CopyMemory(pChannelBindingToken, context->ChannelBindingToken, ChannelBindingTokenLength);
printf("ChannelBindings\n");
winpr_HexDump((BYTE*) ChannelBindings, context->EndpointBindings.BindingsLength);
ChannelBindingTokenLength = context->Bindings.BindingsLength - sizeof(SEC_CHANNEL_BINDINGS);
ChannelBindingToken = &((BYTE*) ChannelBindings)[ChannelBindings->dwApplicationDataOffset];
MD5_Init(&md5);
ntlm_uint32_to_big_endian(ChannelBindings->dwInitiatorAddrType, be32);
MD5_Update(&md5, be32, 4);
ntlm_md5_update_uint32_be(&md5, ChannelBindings->dwInitiatorAddrType);
ntlm_md5_update_uint32_be(&md5, ChannelBindings->cbInitiatorLength);
ntlm_md5_update_uint32_be(&md5, ChannelBindings->dwAcceptorAddrType);
ntlm_md5_update_uint32_be(&md5, ChannelBindings->cbAcceptorLength);
ntlm_md5_update_uint32_be(&md5, ChannelBindings->cbApplicationDataLength);
ntlm_uint32_to_big_endian(ChannelBindings->cbInitiatorLength, be32);
MD5_Update(&md5, be32, 4);
ntlm_uint32_to_big_endian(ChannelBindings->dwAcceptorAddrType, be32);
MD5_Update(&md5, be32, 4);
ntlm_uint32_to_big_endian(ChannelBindings->cbAcceptorLength, be32);
MD5_Update(&md5, be32, 4);
ntlm_uint32_to_big_endian(ChannelBindings->cbApplicationDataLength, be32);
MD5_Update(&md5, be32, 4);
MD5_Update(&md5, (void*) pChannelBindingToken, ChannelBindingTokenLength);
MD5_Update(&md5, (void*) ChannelBindingToken, ChannelBindingTokenLength);
MD5_Final(context->ChannelBindingsHash, &md5);
printf("ChannelBindingsHash:\n");
winpr_HexDump(context->ChannelBindingsHash, 16);
free(CertificateHash);
printf("\n\n");
#endif
}
void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)