Merge pull request #897 from awakecoding/master
Schannel Improvements + RemoteFX Fix
This commit is contained in:
commit
912d9e8f26
@ -520,7 +520,7 @@ void wf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
|
||||
wf_invalidate_region(wfi, surface_bits_command->destLeft, surface_bits_command->destTop,
|
||||
surface_bits_command->width, surface_bits_command->height);
|
||||
}
|
||||
else if (surface_bits_command->codecID == CODEC_ID_NONE)
|
||||
else if (surface_bits_command->codecID == RDP_CODEC_ID_NONE)
|
||||
{
|
||||
ZeroMemory(&bitmap_info, sizeof(bitmap_info));
|
||||
bitmap_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
|
@ -230,7 +230,7 @@ static BOOL fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, UINT32
|
||||
break;
|
||||
|
||||
case FASTPATH_UPDATETYPE_SURFCMDS:
|
||||
if (!update_recv_surfcmds(update, size, s))
|
||||
if (update_recv_surfcmds(update, size, s) < 0)
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
|
@ -119,7 +119,7 @@ int rpc_client_on_fragment_received_event(rdpRpc* rpc)
|
||||
{
|
||||
if (rpc->VirtualConnection->State >= VIRTUAL_CONNECTION_STATE_OPENED)
|
||||
{
|
||||
printf("Receiving Out-of-Sequence RTS PDU\n");
|
||||
//printf("Receiving Out-of-Sequence RTS PDU\n");
|
||||
rts_recv_out_of_sequence_pdu(rpc, buffer, header->common.frag_length);
|
||||
|
||||
rpc_client_fragment_pool_return(rpc, fragment);
|
||||
|
@ -841,9 +841,11 @@ int rts_recv_flow_control_ack_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
|
||||
offset += rts_flow_control_ack_command_read(rpc, &buffer[offset], length - offset,
|
||||
&BytesReceived, &AvailableWindow, (BYTE*) &ChannelCookie) + 4;
|
||||
|
||||
#if 0
|
||||
printf("BytesReceived: %d AvailableWindow: %d\n",
|
||||
BytesReceived, AvailableWindow);
|
||||
printf("ChannelCookie: " RPC_UUID_FORMAT_STRING "\n", RPC_UUID_FORMAT_ARGUMENTS(ChannelCookie));
|
||||
#endif
|
||||
|
||||
rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
|
||||
AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
|
||||
@ -880,9 +882,11 @@ int rts_recv_flow_control_ack_with_destination_pdu(rdpRpc* rpc, BYTE* buffer, UI
|
||||
offset += rts_flow_control_ack_command_read(rpc, &buffer[offset], length - offset,
|
||||
&BytesReceived, &AvailableWindow, (BYTE*) &ChannelCookie) + 4;
|
||||
|
||||
#if 0
|
||||
printf("Destination: %d BytesReceived: %d AvailableWindow: %d\n",
|
||||
Destination, BytesReceived, AvailableWindow);
|
||||
printf("ChannelCookie: " RPC_UUID_FORMAT_STRING "\n", RPC_UUID_FORMAT_ARGUMENTS(ChannelCookie));
|
||||
#endif
|
||||
|
||||
rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
|
||||
AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
|
||||
@ -999,7 +1003,6 @@ int rts_recv_out_of_sequence_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
|
||||
rts = (rpcconn_rts_hdr_t*) buffer;
|
||||
|
||||
rts_extract_pdu_signature(rpc, &signature, rts);
|
||||
rts_print_pdu_signature(rpc, &signature);
|
||||
SignatureId = rts_identify_pdu_signature(rpc, &signature, NULL);
|
||||
|
||||
if (SignatureId == RTS_PDU_FLOW_CONTROL_ACK)
|
||||
@ -1017,6 +1020,7 @@ int rts_recv_out_of_sequence_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
|
||||
else
|
||||
{
|
||||
printf("Unimplemented signature id: 0x%08X\n", SignatureId);
|
||||
rts_print_pdu_signature(rpc, &signature);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -181,8 +181,11 @@ BOOL TsProxyCreateTunnelWriteRequest(rdpTsg* tsg)
|
||||
*
|
||||
* Using reduced capabilities appears to trigger
|
||||
* TSG_PACKET_TYPE_QUARENC_RESPONSE instead of TSG_PACKET_TYPE_CAPS_RESPONSE
|
||||
*
|
||||
* However, reduced capabilities may break connectivity with servers enforcing features, such as
|
||||
* "Only allow connections from Remote Desktop Services clients that support RD Gateway messaging"
|
||||
*/
|
||||
NapCapabilities = TSG_NAP_CAPABILITY_IDLE_TIMEOUT;
|
||||
//NapCapabilities = TSG_NAP_CAPABILITY_IDLE_TIMEOUT;
|
||||
|
||||
*((UINT32*) &buffer[44]) = NapCapabilities; /* capabilities */
|
||||
|
||||
|
@ -85,7 +85,7 @@ BOOL nego_connect(rdpNego* nego)
|
||||
nego->state = NEGO_STATE_FAIL;
|
||||
}
|
||||
|
||||
if (!nego->NegotiateSecurityLayer_enabled)
|
||||
if (!nego->NegotiateSecurityLayer)
|
||||
{
|
||||
DEBUG_NEGO("Security Layer Negotiation is disabled");
|
||||
/* attempt only the highest enabled protocol (see nego_attempt_*) */
|
||||
@ -222,7 +222,7 @@ BOOL nego_transport_connect(rdpNego* nego)
|
||||
{
|
||||
nego_tcp_connect(nego);
|
||||
|
||||
if (nego->tcp_connected && !nego->NegotiateSecurityLayer_enabled)
|
||||
if (nego->tcp_connected && !nego->NegotiateSecurityLayer)
|
||||
return nego_security_connect(nego);
|
||||
|
||||
return nego->tcp_connected;
|
||||
@ -947,10 +947,10 @@ void nego_set_target(rdpNego* nego, char* hostname, int port)
|
||||
* @param enable_rdp whether to enable security layer negotiation (TRUE for enabled, FALSE for disabled)
|
||||
*/
|
||||
|
||||
void nego_set_negotiation_enabled(rdpNego* nego, BOOL NegotiateSecurityLayer_enabled)
|
||||
void nego_set_negotiation_enabled(rdpNego* nego, BOOL NegotiateSecurityLayer)
|
||||
{
|
||||
DEBUG_NEGO("Enabling security layer negotiation: %s", NegotiateSecurityLayer_enabled ? "TRUE" : "FALSE");
|
||||
nego->NegotiateSecurityLayer_enabled = NegotiateSecurityLayer_enabled;
|
||||
DEBUG_NEGO("Enabling security layer negotiation: %s", NegotiateSecurityLayer ? "TRUE" : "FALSE");
|
||||
nego->NegotiateSecurityLayer = NegotiateSecurityLayer;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,7 +100,7 @@ struct rdp_nego
|
||||
|
||||
UINT32 selected_protocol;
|
||||
UINT32 requested_protocols;
|
||||
BOOL NegotiateSecurityLayer_enabled;
|
||||
BOOL NegotiateSecurityLayer;
|
||||
BYTE enabled_protocols[16];
|
||||
|
||||
rdpTransport* transport;
|
||||
|
@ -153,8 +153,8 @@ BOOL transport_connect_nla(rdpTransport* transport)
|
||||
|
||||
if (credssp_authenticate(transport->credssp) < 0)
|
||||
{
|
||||
if (!connectErrorCode)
|
||||
connectErrorCode = AUTHENTICATIONERROR;
|
||||
if (!connectErrorCode)
|
||||
connectErrorCode = AUTHENTICATIONERROR;
|
||||
|
||||
printf("Authentication failure, check credentials.\n"
|
||||
"If credentials are valid, the NTLMSSP implementation may be to blame.\n");
|
||||
|
@ -59,50 +59,6 @@ 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)
|
||||
|
@ -30,5 +30,20 @@ typedef struct _LSA_UNICODE_STRING
|
||||
PWSTR Buffer;
|
||||
} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;
|
||||
|
||||
/**
|
||||
* Windows Integrity Mechanism Design:
|
||||
* http://msdn.microsoft.com/en-us/library/bb625963.aspx
|
||||
*/
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#define SECURITY_MANDATORY_UNTRUSTED_RID 0x0000
|
||||
#define SECURITY_MANDATORY_LOW_RID 0x1000
|
||||
#define SECURITY_MANDATORY_MEDIUM_RID 0x2000
|
||||
#define SECURITY_MANDATORY_HIGH_RID 0x3000
|
||||
#define SECURITY_MANDATORY_SYSTEM_RID 0x4000
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* WINPR_SECURITY_H */
|
||||
|
||||
|
@ -112,6 +112,7 @@ NTLM_CONTEXT* ntlm_ContextNew()
|
||||
context->NTLMv2 = TRUE;
|
||||
context->UseMIC = FALSE;
|
||||
context->SendVersionInfo = TRUE;
|
||||
context->SendSingleHostData = FALSE;
|
||||
|
||||
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\WinPR\\NTLM"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
|
||||
|
||||
@ -126,6 +127,9 @@ NTLM_CONTEXT* ntlm_ContextNew()
|
||||
if (RegQueryValueEx(hKey, _T("SendVersionInfo"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
|
||||
context->SendVersionInfo = dwValue ? 1 : 0;
|
||||
|
||||
if (RegQueryValueEx(hKey, _T("SendSingleHostData"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
|
||||
context->SendSingleHostData = dwValue ? 1 : 0;
|
||||
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
@ -337,9 +341,9 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, P
|
||||
if (pInput->cBuffers < 1)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
input_buffer = &pInput->pBuffers[0];
|
||||
input_buffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
|
||||
|
||||
if (input_buffer->BufferType != SECBUFFER_TOKEN)
|
||||
if (!input_buffer)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
if (input_buffer->cbBuffer < 1)
|
||||
@ -355,9 +359,9 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, P
|
||||
if (pOutput->cBuffers < 1)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
output_buffer = &pOutput->pBuffers[0];
|
||||
output_buffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
|
||||
|
||||
if (output_buffer->BufferType != SECBUFFER_TOKEN)
|
||||
if (!output_buffer->BufferType)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
if (output_buffer->cbBuffer < 1)
|
||||
@ -376,9 +380,9 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, P
|
||||
if (pInput->cBuffers < 1)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
input_buffer = &pInput->pBuffers[0];
|
||||
input_buffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
|
||||
|
||||
if (input_buffer->BufferType != SECBUFFER_TOKEN)
|
||||
if (!input_buffer)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
if (input_buffer->cbBuffer < 1)
|
||||
@ -450,9 +454,9 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti
|
||||
if (pOutput->cBuffers < 1)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
output_buffer = &pOutput->pBuffers[0];
|
||||
output_buffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
|
||||
|
||||
if (output_buffer->BufferType != SECBUFFER_TOKEN)
|
||||
if (!output_buffer)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
if (output_buffer->cbBuffer < 1)
|
||||
@ -471,19 +475,15 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti
|
||||
if (pInput->cBuffers < 1)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
input_buffer = &pInput->pBuffers[0];
|
||||
input_buffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
|
||||
|
||||
if (input_buffer->BufferType != SECBUFFER_TOKEN)
|
||||
if (!input_buffer)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
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];
|
||||
}
|
||||
channel_bindings = sspi_FindSecBuffer(pInput, SECBUFFER_CHANNEL_BINDINGS);
|
||||
|
||||
if (channel_bindings)
|
||||
{
|
||||
@ -501,9 +501,9 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti
|
||||
if (pOutput->cBuffers < 1)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
output_buffer = &pOutput->pBuffers[0];
|
||||
output_buffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
|
||||
|
||||
if (output_buffer->BufferType != SECBUFFER_TOKEN)
|
||||
if (!output_buffer)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
if (output_buffer->cbBuffer < 1)
|
||||
|
@ -92,7 +92,7 @@ enum _NTLM_AV_ID
|
||||
MsvAvDnsTreeName,
|
||||
MsvAvFlags,
|
||||
MsvAvTimestamp,
|
||||
MsvAvRestrictions,
|
||||
MsvAvSingleHost,
|
||||
MsvAvTargetName,
|
||||
MsvChannelBindings
|
||||
};
|
||||
@ -126,15 +126,15 @@ struct _NTLM_VERSION_INFO
|
||||
};
|
||||
typedef struct _NTLM_VERSION_INFO NTLM_VERSION_INFO;
|
||||
|
||||
struct _NTLM_RESTRICTION_ENCODING
|
||||
struct _NTLM_SINGLE_HOST_DATA
|
||||
{
|
||||
UINT32 Size;
|
||||
UINT32 Z4;
|
||||
UINT32 IntegrityLevel;
|
||||
UINT32 SubjectIntegrityLevel;
|
||||
UINT32 DataPresent;
|
||||
UINT32 CustomData;
|
||||
BYTE MachineID[32];
|
||||
};
|
||||
typedef struct _NTLM_RESTRICTION_ENCODING NTLM_RESTRICTION_ENCODING;
|
||||
typedef struct _NTLM_SINGLE_HOST_DATA NTLM_SINGLE_HOST_DATA;
|
||||
|
||||
struct _NTLM_RESPONSE
|
||||
{
|
||||
@ -244,6 +244,8 @@ struct _NTLM_CONTEXT
|
||||
BYTE* ChannelBindingToken;
|
||||
BYTE ChannelBindingsHash[16];
|
||||
SecPkgContext_Bindings Bindings;
|
||||
BOOL SendSingleHostData;
|
||||
NTLM_SINGLE_HOST_DATA SingleHostData;
|
||||
SecBuffer NegotiateMessage;
|
||||
SecBuffer ChallengeMessage;
|
||||
SecBuffer AuthenticateMessage;
|
||||
|
@ -279,6 +279,24 @@ void ntlm_compute_channel_bindings(NTLM_CONTEXT* context)
|
||||
MD5_Final(context->ChannelBindingsHash, &md5);
|
||||
}
|
||||
|
||||
void ntlm_compute_single_host_data(NTLM_CONTEXT* context)
|
||||
{
|
||||
/**
|
||||
* The Single_Host_Data structure allows a client to send machine-specific information
|
||||
* within an authentication exchange to services on the same machine. The client can
|
||||
* produce additional information to be processed in an implementation-specific way when
|
||||
* the client and server are on the same host. If the server and client platforms are
|
||||
* different or if they are on different hosts, then the information MUST be ignored.
|
||||
* Any fields after the MachineID field MUST be ignored on receipt.
|
||||
*/
|
||||
|
||||
context->SingleHostData.Size = 48;
|
||||
context->SingleHostData.Z4 = 0;
|
||||
context->SingleHostData.DataPresent = 1;
|
||||
context->SingleHostData.CustomData = SECURITY_MANDATORY_MEDIUM_RID;
|
||||
FillMemory(context->SingleHostData.MachineID, 32, 0xAA);
|
||||
}
|
||||
|
||||
void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
|
||||
{
|
||||
int length;
|
||||
@ -390,8 +408,12 @@ void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
|
||||
AvPairsValueLength += 4;
|
||||
}
|
||||
|
||||
//AvPairsCount++; /* MsvAvRestrictions */
|
||||
//AvPairsValueLength += 48;
|
||||
if (context->SendSingleHostData)
|
||||
{
|
||||
AvPairsCount++; /* MsvAvSingleHost */
|
||||
ntlm_compute_single_host_data(context);
|
||||
AvPairsValueLength += context->SingleHostData.Size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extended Protection for Authentication:
|
||||
@ -450,6 +472,12 @@ void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
|
||||
ntlm_av_pair_add(AuthenticateTargetInfo, MsvAvFlags, (PBYTE) &flags, 4);
|
||||
}
|
||||
|
||||
if (context->SendSingleHostData)
|
||||
{
|
||||
ntlm_av_pair_add(AuthenticateTargetInfo, MsvAvSingleHost,
|
||||
(PBYTE) &context->SingleHostData, context->SingleHostData.Size);
|
||||
}
|
||||
|
||||
if (!context->SuppressExtendedProtection)
|
||||
{
|
||||
ntlm_av_pair_add(AuthenticateTargetInfo, MsvChannelBindings, context->ChannelBindingsHash, 16);
|
||||
|
@ -228,13 +228,11 @@ SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextW(PCredHandle phCred
|
||||
sspi_SecureHandleSetUpperPointer(phNewContext, (void*) SCHANNEL_PACKAGE_NAME);
|
||||
|
||||
schannel_openssl_client_init(context->openssl);
|
||||
|
||||
status = schannel_openssl_client_process_tokens(context->openssl, pInput, pOutput);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
return SEC_E_OK;
|
||||
status = schannel_openssl_client_process_tokens(context->openssl, pInput, pOutput);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext,
|
||||
@ -267,6 +265,7 @@ SECURITY_STATUS SEC_ENTRY schannel_AcceptSecurityContext(PCredHandle phCredentia
|
||||
SCHANNEL_CONTEXT* context;
|
||||
SCHANNEL_CREDENTIALS* credentials;
|
||||
|
||||
status = SEC_E_OK;
|
||||
context = (SCHANNEL_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
|
||||
|
||||
if (!context)
|
||||
@ -284,13 +283,11 @@ SECURITY_STATUS SEC_ENTRY schannel_AcceptSecurityContext(PCredHandle phCredentia
|
||||
sspi_SecureHandleSetUpperPointer(phNewContext, (void*) SCHANNEL_PACKAGE_NAME);
|
||||
|
||||
schannel_openssl_server_init(context->openssl);
|
||||
|
||||
status = schannel_openssl_server_process_tokens(context->openssl, pInput, pOutput);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
return SEC_E_OK;
|
||||
status = schannel_openssl_server_process_tokens(context->openssl, pInput, pOutput);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SECURITY_STATUS SEC_ENTRY schannel_DeleteSecurityContext(PCtxtHandle phContext)
|
||||
@ -342,12 +339,22 @@ SECURITY_STATUS SEC_ENTRY schannel_VerifySignature(PCtxtHandle phContext, PSecBu
|
||||
|
||||
SECURITY_STATUS SEC_ENTRY schannel_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
|
||||
{
|
||||
return SEC_E_OK;
|
||||
SECURITY_STATUS status;
|
||||
SCHANNEL_CONTEXT* context;
|
||||
|
||||
context = (SCHANNEL_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
|
||||
|
||||
if (!context)
|
||||
return SEC_E_INVALID_HANDLE;
|
||||
|
||||
status = schannel_openssl_encrypt_message(context->openssl, pMessage);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SECURITY_STATUS SEC_ENTRY schannel_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP)
|
||||
{
|
||||
return SEC_E_OK;
|
||||
return SEC_E_UNSUPPORTED_FUNCTION;
|
||||
}
|
||||
|
||||
const SecurityFunctionTableA SCHANNEL_SecurityFunctionTableA =
|
||||
|
@ -138,7 +138,8 @@ int schannel_openssl_server_init(SCHANNEL_OPENSSL* context)
|
||||
int status;
|
||||
long options = 0;
|
||||
|
||||
context->ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
//context->ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
context->ctx = SSL_CTX_new(TLSv1_server_method());
|
||||
|
||||
if (!context->ctx)
|
||||
{
|
||||
@ -185,6 +186,12 @@ int schannel_openssl_server_init(SCHANNEL_OPENSSL* context)
|
||||
|
||||
SSL_CTX_set_options(context->ctx, options);
|
||||
|
||||
if (SSL_CTX_use_RSAPrivateKey_file(context->ctx, "/tmp/localhost.key", SSL_FILETYPE_PEM) <= 0)
|
||||
{
|
||||
printf("SSL_CTX_use_RSAPrivateKey_file failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
context->ssl = SSL_new(context->ctx);
|
||||
|
||||
if (!context->ssl)
|
||||
@ -193,12 +200,6 @@ int schannel_openssl_server_init(SCHANNEL_OPENSSL* context)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SSL_CTX_use_RSAPrivateKey_file(context->ctx, "/tmp/localhost.key", SSL_FILETYPE_PEM) <= 0)
|
||||
{
|
||||
printf("SSL_CTX_use_RSAPrivateKey_file failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SSL_use_certificate_file(context->ssl, "/tmp/localhost.crt", SSL_FILETYPE_PEM) <= 0)
|
||||
{
|
||||
printf("SSL_use_certificate_file failed\n");
|
||||
@ -248,9 +249,9 @@ SECURITY_STATUS schannel_openssl_client_process_tokens(SCHANNEL_OPENSSL* context
|
||||
if (pInput->cBuffers < 1)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
pBuffer = &pInput->pBuffers[0];
|
||||
pBuffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
|
||||
|
||||
if (pBuffer->BufferType != SECBUFFER_TOKEN)
|
||||
if (!pBuffer)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
status = BIO_write(context->bioRead, pBuffer->pvBuffer, pBuffer->cbBuffer);
|
||||
@ -266,26 +267,29 @@ SECURITY_STATUS schannel_openssl_client_process_tokens(SCHANNEL_OPENSSL* context
|
||||
|
||||
status = BIO_read(context->bioWrite, context->ReadBuffer, SCHANNEL_CB_MAX_TOKEN);
|
||||
|
||||
if (status >= 0)
|
||||
{
|
||||
winpr_HexDump(context->ReadBuffer, status);
|
||||
}
|
||||
|
||||
if (pOutput->cBuffers < 1)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
pBuffer = &pOutput->pBuffers[0];
|
||||
pBuffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
|
||||
|
||||
if (pBuffer->BufferType != SECBUFFER_TOKEN)
|
||||
if (!pBuffer)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
if (pBuffer->cbBuffer < status)
|
||||
return SEC_E_INSUFFICIENT_MEMORY;
|
||||
if (status > 0)
|
||||
{
|
||||
if (pBuffer->cbBuffer < status)
|
||||
return SEC_E_INSUFFICIENT_MEMORY;
|
||||
|
||||
CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status);
|
||||
pBuffer->cbBuffer = status;
|
||||
CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status);
|
||||
pBuffer->cbBuffer = status;
|
||||
|
||||
return SEC_I_CONTINUE_NEEDED;
|
||||
return SEC_I_CONTINUE_NEEDED;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBuffer->cbBuffer = 0;
|
||||
return SEC_E_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return SEC_E_OK;
|
||||
@ -302,12 +306,11 @@ SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context
|
||||
if (pInput->cBuffers < 1)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
pBuffer = &pInput->pBuffers[0];
|
||||
pBuffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
|
||||
|
||||
if (pBuffer->BufferType != SECBUFFER_TOKEN)
|
||||
if (!pBuffer)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
printf("Server input: %ld\n", pBuffer->cbBuffer);
|
||||
status = BIO_write(context->bioRead, pBuffer->pvBuffer, pBuffer->cbBuffer);
|
||||
|
||||
status = SSL_accept(context->ssl);
|
||||
@ -320,31 +323,76 @@ SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context
|
||||
|
||||
status = BIO_read(context->bioWrite, context->ReadBuffer, SCHANNEL_CB_MAX_TOKEN);
|
||||
|
||||
if (status >= 0)
|
||||
{
|
||||
winpr_HexDump(context->ReadBuffer, status);
|
||||
}
|
||||
|
||||
if (pOutput->cBuffers < 1)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
pBuffer = &pOutput->pBuffers[0];
|
||||
pBuffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
|
||||
|
||||
if (pBuffer->BufferType != SECBUFFER_TOKEN)
|
||||
if (!pBuffer)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
if (pBuffer->cbBuffer < status)
|
||||
return SEC_E_INSUFFICIENT_MEMORY;
|
||||
if (status > 0)
|
||||
{
|
||||
if (pBuffer->cbBuffer < status)
|
||||
return SEC_E_INSUFFICIENT_MEMORY;
|
||||
|
||||
CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status);
|
||||
pBuffer->cbBuffer = status;
|
||||
CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status);
|
||||
pBuffer->cbBuffer = status;
|
||||
|
||||
return SEC_I_CONTINUE_NEEDED;
|
||||
return SEC_I_CONTINUE_NEEDED;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBuffer->cbBuffer = 0;
|
||||
return SEC_E_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return SEC_E_OK;
|
||||
}
|
||||
|
||||
SECURITY_STATUS schannel_openssl_encrypt_message(SCHANNEL_OPENSSL* context, PSecBufferDesc pMessage)
|
||||
{
|
||||
int status;
|
||||
int ssl_error;
|
||||
PSecBuffer pStreamBodyBuffer;
|
||||
PSecBuffer pStreamHeaderBuffer;
|
||||
PSecBuffer pStreamTrailerBuffer;
|
||||
|
||||
pStreamHeaderBuffer = sspi_FindSecBuffer(pMessage, SECBUFFER_STREAM_HEADER);
|
||||
pStreamBodyBuffer = sspi_FindSecBuffer(pMessage, SECBUFFER_DATA);
|
||||
pStreamTrailerBuffer = sspi_FindSecBuffer(pMessage, SECBUFFER_STREAM_TRAILER);
|
||||
|
||||
if ((!pStreamHeaderBuffer) || (!pStreamBodyBuffer) || (!pStreamTrailerBuffer))
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
status = SSL_write(context->ssl, pStreamBodyBuffer->pvBuffer, pStreamBodyBuffer->cbBuffer);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
ssl_error = SSL_get_error(context->ssl, status);
|
||||
printf("SSL_write: %s\n", openssl_get_ssl_error_string(ssl_error));
|
||||
}
|
||||
|
||||
status = BIO_read(context->bioWrite, context->ReadBuffer, SCHANNEL_CB_MAX_TOKEN);
|
||||
|
||||
return SEC_E_UNSUPPORTED_FUNCTION;
|
||||
}
|
||||
|
||||
SECURITY_STATUS schannel_openssl_decrypt_message(SCHANNEL_OPENSSL* context, PSecBufferDesc pMessage)
|
||||
{
|
||||
//int status;
|
||||
//int ssl_error;
|
||||
PSecBuffer pBuffer;
|
||||
|
||||
pBuffer = sspi_FindSecBuffer(pMessage, SECBUFFER_DATA);
|
||||
|
||||
if (!pBuffer)
|
||||
return SEC_E_INVALID_TOKEN;
|
||||
|
||||
return SEC_E_UNSUPPORTED_FUNCTION;
|
||||
}
|
||||
|
||||
SCHANNEL_OPENSSL* schannel_openssl_new()
|
||||
{
|
||||
SCHANNEL_OPENSSL* context;
|
||||
|
@ -49,6 +49,9 @@ int schannel_openssl_server_init(SCHANNEL_OPENSSL* context);
|
||||
SECURITY_STATUS schannel_openssl_client_process_tokens(SCHANNEL_OPENSSL* context, PSecBufferDesc pInput, PSecBufferDesc pOutput);
|
||||
SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context, PSecBufferDesc pInput, PSecBufferDesc pOutput);
|
||||
|
||||
SECURITY_STATUS schannel_openssl_encrypt_message(SCHANNEL_OPENSSL* context, PSecBufferDesc pMessage);
|
||||
SECURITY_STATUS schannel_openssl_decrypt_message(SCHANNEL_OPENSSL* context, PSecBufferDesc pMessage);
|
||||
|
||||
SCHANNEL_OPENSSL* schannel_openssl_new();
|
||||
void schannel_openssl_free(SCHANNEL_OPENSSL* context);
|
||||
|
||||
|
@ -371,6 +371,23 @@ void sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDE
|
||||
}
|
||||
}
|
||||
|
||||
PSecBuffer sspi_FindSecBuffer(PSecBufferDesc pMessage, ULONG BufferType)
|
||||
{
|
||||
int index;
|
||||
PSecBuffer pSecBuffer = NULL;
|
||||
|
||||
for (index = 0; index < pMessage->cBuffers; index++)
|
||||
{
|
||||
if (pMessage->pBuffers[index].BufferType == BufferType)
|
||||
{
|
||||
pSecBuffer = &pMessage->pBuffers[index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pSecBuffer;
|
||||
}
|
||||
|
||||
static BOOL sspi_initialized = FALSE;
|
||||
|
||||
void sspi_GlobalInit()
|
||||
|
@ -33,6 +33,8 @@ typedef struct _CREDENTIALS CREDENTIALS;
|
||||
CREDENTIALS* sspi_CredentialsNew();
|
||||
void sspi_CredentialsFree(CREDENTIALS* credentials);
|
||||
|
||||
PSecBuffer sspi_FindSecBuffer(PSecBufferDesc pMessage, ULONG BufferType);
|
||||
|
||||
SecHandle* sspi_SecureHandleAlloc();
|
||||
void sspi_SecureHandleInit(SecHandle* handle);
|
||||
void sspi_SecureHandleInvalidate(SecHandle* handle);
|
||||
|
@ -10,8 +10,6 @@
|
||||
#include <winpr/crypto.h>
|
||||
#include <winpr/schannel.h>
|
||||
|
||||
HANDLE g_ClientEvent = NULL;
|
||||
HANDLE g_ServerEvent = NULL;
|
||||
BOOL g_ClientWait = FALSE;
|
||||
BOOL g_ServerWait = FALSE;
|
||||
|
||||
@ -20,6 +18,145 @@ HANDLE g_ClientWritePipe = NULL;
|
||||
HANDLE g_ServerReadPipe = NULL;
|
||||
HANDLE g_ServerWritePipe = NULL;
|
||||
|
||||
BYTE test_DummyMessage[64] =
|
||||
{
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
|
||||
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD
|
||||
};
|
||||
|
||||
int schannel_send(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phContext, BYTE* buffer, UINT32 length)
|
||||
{
|
||||
BYTE* ioBuffer;
|
||||
UINT32 ioBufferLength;
|
||||
BYTE* pMessageBuffer;
|
||||
SecBuffer Buffers[4];
|
||||
SecBufferDesc Message;
|
||||
SECURITY_STATUS status;
|
||||
DWORD NumberOfBytesWritten;
|
||||
SecPkgContext_StreamSizes StreamSizes;
|
||||
|
||||
ZeroMemory(&StreamSizes, sizeof(SecPkgContext_StreamSizes));
|
||||
status = table->QueryContextAttributes(phContext, SECPKG_ATTR_STREAM_SIZES, &StreamSizes);
|
||||
|
||||
ioBufferLength = StreamSizes.cbHeader + StreamSizes.cbMaximumMessage + StreamSizes.cbTrailer;
|
||||
ioBuffer = (BYTE*) malloc(ioBufferLength);
|
||||
ZeroMemory(ioBuffer, ioBufferLength);
|
||||
|
||||
pMessageBuffer = ioBuffer + StreamSizes.cbHeader;
|
||||
CopyMemory(pMessageBuffer, buffer, length);
|
||||
|
||||
Buffers[0].pvBuffer = ioBuffer;
|
||||
Buffers[0].cbBuffer = StreamSizes.cbHeader;
|
||||
Buffers[0].BufferType = SECBUFFER_STREAM_HEADER;
|
||||
|
||||
Buffers[1].pvBuffer = pMessageBuffer;
|
||||
Buffers[1].cbBuffer = length;
|
||||
Buffers[1].BufferType = SECBUFFER_DATA;
|
||||
|
||||
Buffers[2].pvBuffer = pMessageBuffer + length;
|
||||
Buffers[2].cbBuffer = StreamSizes.cbTrailer;
|
||||
Buffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
|
||||
|
||||
Buffers[3].pvBuffer = NULL;
|
||||
Buffers[3].cbBuffer = 0;
|
||||
Buffers[3].BufferType = SECBUFFER_EMPTY;
|
||||
|
||||
Message.ulVersion = SECBUFFER_VERSION;
|
||||
Message.cBuffers = 4;
|
||||
Message.pBuffers = Buffers;
|
||||
|
||||
ioBufferLength = Message.pBuffers[0].cbBuffer + Message.pBuffers[1].cbBuffer + Message.pBuffers[2].cbBuffer;
|
||||
|
||||
status = table->EncryptMessage(phContext, 0, &Message, 0);
|
||||
|
||||
printf("EncryptMessage status: 0x%08X\n", status);
|
||||
|
||||
printf("EncryptMessage output: cBuffers: %d [0]: %d / %d [1]: %d / %d [2]: %d / %d [3]: %d / %d\n", Message.cBuffers,
|
||||
Message.pBuffers[0].cbBuffer, Message.pBuffers[0].BufferType,
|
||||
Message.pBuffers[1].cbBuffer, Message.pBuffers[1].BufferType,
|
||||
Message.pBuffers[2].cbBuffer, Message.pBuffers[2].BufferType,
|
||||
Message.pBuffers[3].cbBuffer, Message.pBuffers[3].BufferType);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
return -1;
|
||||
|
||||
printf("Client > Server (%d)\n", ioBufferLength);
|
||||
winpr_HexDump(ioBuffer, ioBufferLength);
|
||||
|
||||
if (!WriteFile(hPipe, ioBuffer, ioBufferLength, &NumberOfBytesWritten, NULL))
|
||||
{
|
||||
printf("schannel_send: failed to write to pipe\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int schannel_recv(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phContext)
|
||||
{
|
||||
BYTE* ioBuffer;
|
||||
UINT32 ioBufferLength;
|
||||
BYTE* pMessageBuffer;
|
||||
SecBuffer Buffers[4];
|
||||
SecBufferDesc Message;
|
||||
SECURITY_STATUS status;
|
||||
DWORD NumberOfBytesRead;
|
||||
SecPkgContext_StreamSizes StreamSizes;
|
||||
|
||||
ZeroMemory(&StreamSizes, sizeof(SecPkgContext_StreamSizes));
|
||||
status = table->QueryContextAttributes(phContext, SECPKG_ATTR_STREAM_SIZES, &StreamSizes);
|
||||
|
||||
ioBufferLength = StreamSizes.cbHeader + StreamSizes.cbMaximumMessage + StreamSizes.cbTrailer;
|
||||
ioBuffer = (BYTE*) malloc(ioBufferLength);
|
||||
ZeroMemory(ioBuffer, ioBufferLength);
|
||||
|
||||
if (!ReadFile(hPipe, ioBuffer, ioBufferLength, &NumberOfBytesRead, NULL))
|
||||
{
|
||||
printf("schannel_recv: failed to read from pipe\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Buffers[0].pvBuffer = ioBuffer;
|
||||
Buffers[0].cbBuffer = NumberOfBytesRead;
|
||||
Buffers[0].BufferType = SECBUFFER_DATA;
|
||||
|
||||
Buffers[1].pvBuffer = NULL;
|
||||
Buffers[1].cbBuffer = 0;
|
||||
Buffers[1].BufferType = SECBUFFER_EMPTY;
|
||||
|
||||
Buffers[2].pvBuffer = NULL;
|
||||
Buffers[2].cbBuffer = 0;
|
||||
Buffers[2].BufferType = SECBUFFER_EMPTY;
|
||||
|
||||
Buffers[3].pvBuffer = NULL;
|
||||
Buffers[3].cbBuffer = 0;
|
||||
Buffers[3].BufferType = SECBUFFER_EMPTY;
|
||||
|
||||
Message.ulVersion = SECBUFFER_VERSION;
|
||||
Message.cBuffers = 4;
|
||||
Message.pBuffers = Buffers;
|
||||
|
||||
status = table->DecryptMessage(phContext, &Message, 0, NULL);
|
||||
|
||||
printf("DecryptMessage status: 0x%08X\n", status);
|
||||
|
||||
printf("DecryptMessage output: cBuffers: %d [0]: %d / %d [1]: %d / %d [2]: %d / %d [3]: %d / %d\n", Message.cBuffers,
|
||||
Message.pBuffers[0].cbBuffer, Message.pBuffers[0].BufferType,
|
||||
Message.pBuffers[1].cbBuffer, Message.pBuffers[1].BufferType,
|
||||
Message.pBuffers[2].cbBuffer, Message.pBuffers[2].BufferType,
|
||||
Message.pBuffers[3].cbBuffer, Message.pBuffers[3].BufferType);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
return -1;
|
||||
|
||||
printf("Decrypted Message (%d)\n", Message.pBuffers[1].cbBuffer);
|
||||
winpr_HexDump((BYTE*) Message.pBuffers[1].pvBuffer, Message.pBuffers[1].cbBuffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void* schannel_test_server_thread(void* arg)
|
||||
{
|
||||
BOOL extraData;
|
||||
@ -72,7 +209,11 @@ static void* schannel_test_server_thread(void* arg)
|
||||
//return NULL;
|
||||
}
|
||||
|
||||
#ifdef CERT_FIND_HAS_PRIVATE_KEY
|
||||
pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_HAS_PRIVATE_KEY, NULL, NULL);
|
||||
#else
|
||||
pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL);
|
||||
#endif
|
||||
|
||||
if (!pCertContext)
|
||||
{
|
||||
@ -110,6 +251,8 @@ static void* schannel_test_server_thread(void* arg)
|
||||
}
|
||||
|
||||
extraData = FALSE;
|
||||
g_ServerWait = TRUE;
|
||||
|
||||
lpTokenIn = (BYTE*) malloc(cbMaxToken);
|
||||
lpTokenOut = (BYTE*) malloc(cbMaxToken);
|
||||
|
||||
@ -121,9 +264,6 @@ static void* schannel_test_server_thread(void* arg)
|
||||
{
|
||||
if (!extraData)
|
||||
{
|
||||
WaitForSingleObject(g_ServerEvent, INFINITE);
|
||||
ResetEvent(g_ServerEvent);
|
||||
|
||||
if (g_ServerWait)
|
||||
{
|
||||
if (!ReadFile(g_ServerReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL))
|
||||
@ -137,10 +277,9 @@ static void* schannel_test_server_thread(void* arg)
|
||||
NumberOfBytesRead = 0;
|
||||
}
|
||||
}
|
||||
extraData = FALSE;
|
||||
|
||||
printf("Server Received %d bytes:\n", NumberOfBytesRead);
|
||||
winpr_HexDump(lpTokenIn, NumberOfBytesRead);
|
||||
extraData = FALSE;
|
||||
g_ServerWait = TRUE;
|
||||
|
||||
SecBuffer_in[0].BufferType = SECBUFFER_TOKEN;
|
||||
SecBuffer_in[0].pvBuffer = lpTokenIn;
|
||||
@ -165,13 +304,7 @@ static void* schannel_test_server_thread(void* arg)
|
||||
status = table->AcceptSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL,
|
||||
&SecBufferDesc_in, fContextReq, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry);
|
||||
|
||||
if (status == SEC_E_OK)
|
||||
{
|
||||
printf("AcceptSecurityContext SEC_E_OK, TLS connection complete\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status != SEC_I_CONTINUE_NEEDED) && (status != SEC_E_INCOMPLETE_MESSAGE))
|
||||
if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED) && (status != SEC_E_INCOMPLETE_MESSAGE))
|
||||
{
|
||||
printf("AcceptSecurityContext unexpected status: 0x%08X\n", status);
|
||||
return NULL;
|
||||
@ -179,7 +312,9 @@ static void* schannel_test_server_thread(void* arg)
|
||||
|
||||
NumberOfBytesWritten = 0;
|
||||
|
||||
if (status == SEC_I_CONTINUE_NEEDED)
|
||||
if (status == SEC_E_OK)
|
||||
printf("AcceptSecurityContext status: SEC_E_OK\n");
|
||||
else if (status == SEC_I_CONTINUE_NEEDED)
|
||||
printf("AcceptSecurityContext status: SEC_I_CONTINUE_NEEDED\n");
|
||||
else if (status == SEC_E_INCOMPLETE_MESSAGE)
|
||||
printf("AcceptSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n");
|
||||
@ -201,27 +336,35 @@ static void* schannel_test_server_thread(void* arg)
|
||||
if (status != SEC_E_INCOMPLETE_MESSAGE)
|
||||
{
|
||||
pSecBuffer = &SecBufferDesc_out.pBuffers[0];
|
||||
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
|
||||
|
||||
g_ClientWait = TRUE;
|
||||
SetEvent(g_ClientEvent);
|
||||
|
||||
if (!WriteFile(g_ClientWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL))
|
||||
if (pSecBuffer->cbBuffer > 0)
|
||||
{
|
||||
printf("failed to write to client pipe\n");
|
||||
return NULL;
|
||||
printf("Server > Client (%d)\n", pSecBuffer->cbBuffer);
|
||||
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
|
||||
|
||||
if (!WriteFile(g_ClientWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL))
|
||||
{
|
||||
printf("failed to write to client pipe\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_ClientWait = FALSE;
|
||||
SetEvent(g_ClientEvent);
|
||||
}
|
||||
|
||||
printf("Server wrote %d bytes\n", NumberOfBytesWritten);
|
||||
if (status == SEC_E_OK)
|
||||
{
|
||||
printf("Server Handshake Complete\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (1);
|
||||
|
||||
do
|
||||
{
|
||||
if (schannel_recv(table, g_ServerReadPipe, &context) < 0)
|
||||
break;
|
||||
}
|
||||
while(1);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -255,9 +398,6 @@ int TestSchannel(int argc, char* argv[])
|
||||
|
||||
sspi_GlobalInit();
|
||||
|
||||
g_ClientEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
g_ServerEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
SecInvalidateHandle(&context);
|
||||
SecInvalidateHandle(&credentials);
|
||||
|
||||
@ -377,13 +517,9 @@ int TestSchannel(int argc, char* argv[])
|
||||
ZeroMemory(&SecBufferDesc_out, sizeof(SecBufferDesc));
|
||||
|
||||
g_ClientWait = FALSE;
|
||||
SetEvent(g_ClientEvent);
|
||||
|
||||
do
|
||||
{
|
||||
WaitForSingleObject(g_ClientEvent, INFINITE);
|
||||
ResetEvent(g_ClientEvent);
|
||||
|
||||
if (g_ClientWait)
|
||||
{
|
||||
if (!ReadFile(g_ClientReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL))
|
||||
@ -397,6 +533,7 @@ int TestSchannel(int argc, char* argv[])
|
||||
NumberOfBytesRead = 0;
|
||||
}
|
||||
|
||||
g_ClientWait = TRUE;
|
||||
printf("NumberOfBytesRead: %d\n", NumberOfBytesRead);
|
||||
|
||||
SecBuffer_in[0].BufferType = SECBUFFER_TOKEN;
|
||||
@ -422,7 +559,7 @@ int TestSchannel(int argc, char* argv[])
|
||||
status = table->InitializeSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL, _T("localhost"),
|
||||
fContextReq, 0, 0, &SecBufferDesc_in, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry);
|
||||
|
||||
if ((status != SEC_I_CONTINUE_NEEDED) && (status != SEC_E_INCOMPLETE_MESSAGE))
|
||||
if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED) && (status != SEC_E_INCOMPLETE_MESSAGE))
|
||||
{
|
||||
printf("InitializeSecurityContext unexpected status: 0x%08X\n", status);
|
||||
return -1;
|
||||
@ -430,7 +567,9 @@ int TestSchannel(int argc, char* argv[])
|
||||
|
||||
NumberOfBytesWritten = 0;
|
||||
|
||||
if (status == SEC_I_CONTINUE_NEEDED)
|
||||
if (status == SEC_E_OK)
|
||||
printf("InitializeSecurityContext status: SEC_E_OK\n");
|
||||
else if (status == SEC_I_CONTINUE_NEEDED)
|
||||
printf("InitializeSecurityContext status: SEC_I_CONTINUE_NEEDED\n");
|
||||
else if (status == SEC_E_INCOMPLETE_MESSAGE)
|
||||
printf("InitializeSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n");
|
||||
@ -443,24 +582,51 @@ int TestSchannel(int argc, char* argv[])
|
||||
if (status != SEC_E_INCOMPLETE_MESSAGE)
|
||||
{
|
||||
pSecBuffer = &SecBufferDesc_out.pBuffers[0];
|
||||
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
|
||||
|
||||
g_ServerWait = TRUE;
|
||||
SetEvent(g_ServerEvent);
|
||||
|
||||
if (!WriteFile(g_ServerWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL))
|
||||
if (pSecBuffer->cbBuffer > 0)
|
||||
{
|
||||
printf("failed to write to server pipe\n");
|
||||
return -1;
|
||||
printf("Client > Server (%d)\n", pSecBuffer->cbBuffer);
|
||||
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
|
||||
|
||||
if (!WriteFile(g_ServerWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL))
|
||||
{
|
||||
printf("failed to write to server pipe\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (status == SEC_E_OK)
|
||||
{
|
||||
g_ServerWait = FALSE;
|
||||
SetEvent(g_ServerEvent);
|
||||
printf("Client Handshake Complete\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(1);
|
||||
|
||||
do
|
||||
{
|
||||
if (schannel_send(table, g_ServerWritePipe, &context, test_DummyMessage, sizeof(test_DummyMessage)) < 0)
|
||||
break;
|
||||
|
||||
for (index = 0; index < sizeof(test_DummyMessage); index++)
|
||||
{
|
||||
BYTE b, ln, hn;
|
||||
|
||||
b = test_DummyMessage[index];
|
||||
|
||||
ln = (b & 0x0F);
|
||||
hn = ((b & 0xF0) >> 4);
|
||||
|
||||
ln = (ln + 1) % 0xF;
|
||||
hn = (ln + 1) % 0xF;
|
||||
|
||||
b = (ln | (hn << 4));
|
||||
|
||||
test_DummyMessage[index] = b;
|
||||
}
|
||||
|
||||
printf("Client wrote %d bytes\n", NumberOfBytesWritten);
|
||||
Sleep(1000 * 10);
|
||||
}
|
||||
while(1);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user