libwinpr-sspi: add support for NTLMv2 Channel Binding Token (CBT)
This commit is contained in:
parent
d8949f5d8f
commit
1d893ed268
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user