Merge pull request #885 from awakecoding/master

SSPI NTLMv2 Fixes and Improvements
This commit is contained in:
Marc-André Moreau 2013-01-09 06:35:23 -08:00
commit 4c31e4efaf
44 changed files with 2769 additions and 315 deletions

View File

@ -96,6 +96,9 @@ COMMAND_LINE_ARGUMENT_A args[] =
{ "sec-ext", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "nla extended protocol security" },
{ "cert-name", COMMAND_LINE_VALUE_REQUIRED, "<name>", NULL, NULL, -1, NULL, "certificate name" },
{ "cert-ignore", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "ignore certificate" },
{ "pcb", COMMAND_LINE_VALUE_REQUIRED, "<blob>", NULL, NULL, -1, NULL, "Preconnection Blob" },
{ "pcid", COMMAND_LINE_VALUE_REQUIRED, "<id>", NULL, NULL, -1, NULL, "Preconnection Id" },
{ "vmconnect", COMMAND_LINE_VALUE_OPTIONAL, "<vmid>", NULL, NULL, -1, NULL, "Hyper-V console (use port 2179, disable negotiation)" },
{ "authentication", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "authentication (hack!)" },
{ "encryption", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "encryption (hack!)" },
{ "grab-keyboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "grab keyboard" },
@ -189,6 +192,7 @@ int freerdp_client_print_command_line_help(int argc, char** argv)
printf(" xfreerdp connection.rdp /p:Pwd123! /f\n");
printf(" xfreerdp /u:CONTOSO\\JohnDoe /p:Pwd123! /v:rdp.contoso.com\n");
printf(" xfreerdp /u:JohnDoe /p:Pwd123! /w:1366 /h:768 /v:192.168.1.100:4489\n");
printf(" xfreerdp /u:JohnDoe /p:Pwd123! /vmconnect:C824F53E-95D2-46C6-9A18-23A5BB403532 /v:192.168.1.100\n");
printf("\n");
printf("Clipboard Redirection: +clipboard\n");
@ -832,6 +836,17 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
settings->ServerHostname = _strdup(arg->Value);
}
}
CommandLineSwitchCase(arg, "vmconnect")
{
settings->ServerPort = 2179;
settings->NegotiateSecurityLayer = FALSE;
if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
{
settings->SendPreconnectionPdu = TRUE;
settings->PreconnectionBlob = _strdup(arg->Value);
}
}
CommandLineSwitchCase(arg, "port")
{
settings->ServerPort = atoi(arg->Value);
@ -1161,16 +1176,16 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
{
settings->NegotiateSecurityLayer = arg->Value ? TRUE : FALSE;
}
CommandLineSwitchCase(arg, "pcid")
{
settings->SendPreconnectionPdu = TRUE;
settings->PreconnectionId = atoi(arg->Value);
}
CommandLineSwitchCase(arg, "pcb")
{
settings->SendPreconnectionPdu = TRUE;
settings->PreconnectionBlob = _strdup(arg->Value);
}
CommandLineSwitchCase(arg, "pcid")
{
settings->SendPreconnectionPdu = TRUE;
settings->PreconnectionId = atoi(arg->Value);
}
CommandLineSwitchCase(arg, "sec")
{
if (strcmp("rdp", arg->Value) == 0) /* Standard RDP */

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

@ -22,6 +22,11 @@
typedef struct rdp_update rdpUpdate;
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/collections.h>
#include <freerdp/rail.h>
#include <freerdp/types.h>
#include <freerdp/freerdp.h>
@ -191,6 +196,9 @@ struct rdp_update
SURFACE_BITS_COMMAND surface_bits_command;
SURFACE_FRAME_MARKER surface_frame_marker;
HANDLE thread;
wQueue* queue;
};
#endif /* FREERDP_UPDATE_H */

View File

@ -340,7 +340,7 @@ static BOOL fastpath_recv_update_data(rdpFastPath* fastpath, STREAM* s)
return TRUE;
}
BOOL fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s)
int fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s)
{
rdpUpdate* update = fastpath->rdp->update;
@ -349,15 +349,12 @@ BOOL fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s)
while (stream_get_left(s) >= 3)
{
if (!fastpath_recv_update_data(fastpath, s))
{
/* XXX: Do we need to call EndPaint? */
return FALSE;
}
return -1;
}
IFCALL(update->EndPaint, update->context);
return TRUE;
return 0;
}
static BOOL fastpath_read_input_event_header(STREAM* s, BYTE* eventFlags, BYTE* eventCode)
@ -506,7 +503,7 @@ static BOOL fastpath_recv_input_event(rdpFastPath* fastpath, STREAM* s)
return TRUE;
}
BOOL fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s)
int fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s)
{
BYTE i;
@ -518,7 +515,7 @@ BOOL fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s)
*/
if (stream_get_left(s) < 1)
return FALSE;
return -1;
stream_read_BYTE(s, fastpath->numberEvents); /* eventHeader (1 byte) */
}
@ -526,10 +523,10 @@ BOOL fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s)
for (i = 0; i < fastpath->numberEvents; i++)
{
if (!fastpath_recv_input_event(fastpath, s))
return FALSE;
return -1;
}
return TRUE;
return 0;
}
static UINT32 fastpath_get_sec_bytes(rdpRdp* rdp)

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

@ -465,9 +465,9 @@ BOOL nego_recv_response(rdpNego* nego)
STREAM* s = transport_recv_stream_init(nego->transport, 1024);
if (transport_read(nego->transport, s) < 0)
return FALSE;
return -1;
return nego_recv(nego->transport, s, nego);
return ((nego_recv(nego->transport, s, nego) < 0) ? FALSE : TRUE);
}
/**
@ -478,7 +478,7 @@ BOOL nego_recv_response(rdpNego* nego)
* @param extra nego pointer
*/
BOOL nego_recv(rdpTransport* transport, STREAM* s, void* extra)
int nego_recv(rdpTransport* transport, STREAM* s, void* extra)
{
BYTE li;
BYTE type;
@ -488,7 +488,7 @@ BOOL nego_recv(rdpTransport* transport, STREAM* s, void* extra)
length = tpkt_read_header(s);
if (length == 0)
return FALSE;
return -1;
li = tpdu_read_connection_confirm(s);
@ -546,7 +546,7 @@ BOOL nego_recv(rdpTransport* transport, STREAM* s, void* extra)
nego->state = NEGO_STATE_FAIL;
}
return TRUE;
return 0;
}
/**

View File

@ -117,7 +117,7 @@ void nego_attempt_tls(rdpNego* nego);
void nego_attempt_rdp(rdpNego* nego);
void nego_send(rdpNego* nego);
BOOL nego_recv(rdpTransport* transport, STREAM* s, void* extra);
int nego_recv(rdpTransport* transport, STREAM* s, void* extra);
BOOL nego_recv_response(rdpNego* nego);
BOOL nego_read_request(rdpNego* nego, STREAM* s);

View File

@ -156,7 +156,7 @@ static BOOL peer_recv_data_pdu(freerdp_peer* client, STREAM* s)
return TRUE;
}
static BOOL peer_recv_tpkt_pdu(freerdp_peer* client, STREAM* s)
static int peer_recv_tpkt_pdu(freerdp_peer* client, STREAM* s)
{
rdpRdp* rdp;
UINT16 length;
@ -171,7 +171,7 @@ static BOOL peer_recv_tpkt_pdu(freerdp_peer* client, STREAM* s)
if (!rdp_read_header(rdp, s, &length, &channelId))
{
printf("Incorrect RDP header.\n");
return FALSE;
return -1;
}
if (rdp->settings->DisableEncryption)
@ -183,7 +183,7 @@ static BOOL peer_recv_tpkt_pdu(freerdp_peer* client, STREAM* s)
if (!rdp_decrypt(rdp, s, length - 4, securityFlags))
{
printf("rdp_decrypt failed\n");
return FALSE;
return -1;
}
}
}
@ -195,7 +195,7 @@ static BOOL peer_recv_tpkt_pdu(freerdp_peer* client, STREAM* s)
else
{
if (!rdp_read_share_control_header(s, &pduLength, &pduType, &pduSource))
return FALSE;
return -1;
client->settings->PduSource = pduSource;
@ -203,19 +203,19 @@ static BOOL peer_recv_tpkt_pdu(freerdp_peer* client, STREAM* s)
{
case PDU_TYPE_DATA:
if (!peer_recv_data_pdu(client, s))
return FALSE;
return -1;
break;
default:
printf("Client sent pduType %d\n", pduType);
return FALSE;
return -1;
}
}
return TRUE;
return 0;
}
static BOOL peer_recv_fastpath_pdu(freerdp_peer* client, STREAM* s)
static int peer_recv_fastpath_pdu(freerdp_peer* client, STREAM* s)
{
rdpRdp* rdp;
UINT16 length;
@ -225,10 +225,10 @@ static BOOL peer_recv_fastpath_pdu(freerdp_peer* client, STREAM* s)
fastpath = rdp->fastpath;
length = fastpath_read_header_rdp(fastpath, s);
if (length == 0 || length > stream_get_left(s))
if ((length == 0) || (length > stream_get_left(s)))
{
printf("incorrect FastPath PDU header length %d\n", length);
return FALSE;
return -1;
}
if (fastpath->encryptionFlags & FASTPATH_OUTPUT_ENCRYPTED)
@ -239,7 +239,7 @@ static BOOL peer_recv_fastpath_pdu(freerdp_peer* client, STREAM* s)
return fastpath_recv_inputs(fastpath, s);
}
static BOOL peer_recv_pdu(freerdp_peer* client, STREAM* s)
static int peer_recv_pdu(freerdp_peer* client, STREAM* s)
{
if (tpkt_verify_header(s))
return peer_recv_tpkt_pdu(client, s);
@ -256,7 +256,7 @@ static BOOL peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra)
{
case CONNECTION_STATE_INITIAL:
if (!rdp_server_accept_nego(rdp, s))
return FALSE;
return -1;
if (rdp->nego->selected_protocol & PROTOCOL_NLA)
{
@ -273,29 +273,29 @@ static BOOL peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra)
case CONNECTION_STATE_NEGO:
if (!rdp_server_accept_mcs_connect_initial(rdp, s))
return FALSE;
return -1;
break;
case CONNECTION_STATE_MCS_CONNECT:
if (!rdp_server_accept_mcs_erect_domain_request(rdp, s))
return FALSE;
return -1;
break;
case CONNECTION_STATE_MCS_ERECT_DOMAIN:
if (!rdp_server_accept_mcs_attach_user_request(rdp, s))
return FALSE;
return -1;
break;
case CONNECTION_STATE_MCS_ATTACH_USER:
if (!rdp_server_accept_mcs_channel_join_request(rdp, s))
return FALSE;
return -1;
break;
case CONNECTION_STATE_MCS_CHANNEL_JOIN:
if (rdp->settings->DisableEncryption)
{
if (!rdp_server_accept_client_keys(rdp, s))
return FALSE;
return -1;
break;
}
rdp->state = CONNECTION_STATE_ESTABLISH_KEYS;
@ -303,12 +303,12 @@ static BOOL peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra)
case CONNECTION_STATE_ESTABLISH_KEYS:
if (!rdp_server_accept_client_info(rdp, s))
return FALSE;
return -1;
IFCALL(client->Capabilities, client);
if (!rdp_send_demand_active(rdp))
return FALSE;
return -1;
break;
case CONNECTION_STATE_LICENSE:
@ -325,15 +325,15 @@ static BOOL peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra)
case CONNECTION_STATE_ACTIVE:
if (!peer_recv_pdu(client, s))
return FALSE;
return -1;
break;
default:
printf("Invalid state %d\n", rdp->state);
return FALSE;
return -1;
}
return TRUE;
return 0;
}
static BOOL freerdp_peer_close(freerdp_peer* client)

View File

@ -480,7 +480,7 @@ void rdp_recv_set_error_info_data_pdu(rdpRdp* rdp, STREAM* s)
rdp_print_errinfo(rdp->errorInfo);
}
BOOL rdp_recv_data_pdu(rdpRdp* rdp, STREAM* s)
int rdp_recv_data_pdu(rdpRdp* rdp, STREAM* s)
{
BYTE type;
UINT16 length;
@ -507,7 +507,7 @@ BOOL rdp_recv_data_pdu(rdpRdp* rdp, STREAM* s)
else
{
printf("decompress_rdp() failed\n");
return FALSE;
return -1;
}
stream_seek(s, compressed_len - 18);
}
@ -522,7 +522,7 @@ BOOL rdp_recv_data_pdu(rdpRdp* rdp, STREAM* s)
{
case DATA_PDU_TYPE_UPDATE:
if (!update_recv(rdp->update, comp_stream))
return FALSE;
return -1;
break;
case DATA_PDU_TYPE_CONTROL:
@ -611,7 +611,7 @@ BOOL rdp_recv_data_pdu(rdpRdp* rdp, STREAM* s)
stream_free(comp_stream);
}
return TRUE;
return 0;
}
BOOL rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, STREAM* s)
@ -624,7 +624,7 @@ BOOL rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, STREAM* s)
if (type == PDU_TYPE_DATA)
{
return rdp_recv_data_pdu(rdp, s);
return (rdp_recv_data_pdu(rdp, s) < 0) ? FALSE : TRUE;
}
else if (type == PDU_TYPE_SERVER_REDIRECTION)
{
@ -712,7 +712,7 @@ BOOL rdp_decrypt(rdpRdp* rdp, STREAM* s, int length, UINT16 securityFlags)
* @param s stream
*/
static BOOL rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s)
static int rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s)
{
UINT16 length;
UINT16 pduType;
@ -725,7 +725,7 @@ static BOOL rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s)
if (!rdp_read_header(rdp, s, &length, &channelId))
{
printf("Incorrect RDP header.\n");
return FALSE;
return -1;
}
if (rdp->settings->DisableEncryption)
@ -737,7 +737,7 @@ static BOOL rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s)
if (!rdp_decrypt(rdp, s, length - 4, securityFlags))
{
printf("rdp_decrypt failed\n");
return FALSE;
return -1;
}
}
@ -749,7 +749,7 @@ static BOOL rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s)
*/
s->p -= 2;
rdp_recv_enhanced_security_redirection_packet(rdp, s);
return TRUE;
return -1;
}
}
@ -770,16 +770,16 @@ static BOOL rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s)
switch (pduType)
{
case PDU_TYPE_DATA:
if (!rdp_recv_data_pdu(rdp, s))
if (rdp_recv_data_pdu(rdp, s) < 0)
{
printf("rdp_recv_data_pdu failed\n");
return FALSE;
return -1;
}
break;
case PDU_TYPE_DEACTIVATE_ALL:
if (!rdp_recv_deactivate_all(rdp, s))
return FALSE;
return -1;
break;
case PDU_TYPE_SERVER_REDIRECTION:
@ -794,10 +794,10 @@ static BOOL rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s)
}
}
return TRUE;
return 0;
}
static BOOL rdp_recv_fastpath_pdu(rdpRdp* rdp, STREAM* s)
static int rdp_recv_fastpath_pdu(rdpRdp* rdp, STREAM* s)
{
UINT16 length;
rdpFastPath* fastpath;
@ -808,7 +808,7 @@ static BOOL rdp_recv_fastpath_pdu(rdpRdp* rdp, STREAM* s)
if ((length == 0) || (length > stream_get_left(s)))
{
printf("incorrect FastPath PDU header length %d\n", length);
return FALSE;
return -1;
}
if (fastpath->encryptionFlags & FASTPATH_OUTPUT_ENCRYPTED)
@ -819,7 +819,7 @@ static BOOL rdp_recv_fastpath_pdu(rdpRdp* rdp, STREAM* s)
return fastpath_recv_updates(rdp->fastpath, s);
}
static BOOL rdp_recv_pdu(rdpRdp* rdp, STREAM* s)
static int rdp_recv_pdu(rdpRdp* rdp, STREAM* s)
{
if (tpkt_verify_header(s))
return rdp_recv_tpkt_pdu(rdp, s);
@ -842,58 +842,58 @@ void rdp_recv(rdpRdp* rdp)
rdp_recv_pdu(rdp, s);
}
static BOOL rdp_recv_callback(rdpTransport* transport, STREAM* s, void* extra)
static int rdp_recv_callback(rdpTransport* transport, STREAM* s, void* extra)
{
int status = 0;
rdpRdp* rdp = (rdpRdp*) extra;
switch (rdp->state)
{
case CONNECTION_STATE_NEGO:
if (!rdp_client_connect_mcs_connect_response(rdp, s))
return FALSE;
status = -1;
break;
case CONNECTION_STATE_MCS_ATTACH_USER:
if (!rdp_client_connect_mcs_attach_user_confirm(rdp, s))
return FALSE;
status = -1;
break;
case CONNECTION_STATE_MCS_CHANNEL_JOIN:
if (!rdp_client_connect_mcs_channel_join_confirm(rdp, s))
return FALSE;
status = -1;
break;
case CONNECTION_STATE_LICENSE:
if (!rdp_client_connect_license(rdp, s))
return FALSE;
status = -1;
break;
case CONNECTION_STATE_CAPABILITY:
if (!rdp_client_connect_demand_active(rdp, s))
{
printf("rdp_client_connect_demand_active failed\n");
return FALSE;
status = -1;
}
break;
case CONNECTION_STATE_FINALIZATION:
if (!rdp_recv_pdu(rdp, s))
return FALSE;
if (rdp->finalize_sc_pdus == FINALIZE_SC_COMPLETE)
status = rdp_recv_pdu(rdp, s);
if ((status >= 0) && (rdp->finalize_sc_pdus == FINALIZE_SC_COMPLETE))
rdp->state = CONNECTION_STATE_ACTIVE;
break;
case CONNECTION_STATE_ACTIVE:
if (!rdp_recv_pdu(rdp, s))
return FALSE;
status = rdp_recv_pdu(rdp, s);
break;
default:
printf("Invalid state %d\n", rdp->state);
return FALSE;
status = -1;
break;
}
return TRUE;
return status;
}
int rdp_send_channel_data(rdpRdp* rdp, int channel_id, BYTE* data, int size)

View File

@ -76,7 +76,7 @@ static int update_recv_surfcmd_frame_marker(rdpUpdate* update, STREAM* s)
return 6;
}
BOOL update_recv_surfcmds(rdpUpdate* update, UINT32 size, STREAM* s)
int update_recv_surfcmds(rdpUpdate* update, UINT32 size, STREAM* s)
{
BYTE* mark;
UINT16 cmdType;
@ -102,7 +102,7 @@ BOOL update_recv_surfcmds(rdpUpdate* update, UINT32 size, STREAM* s)
default:
DEBUG_WARN("unknown cmdType 0x%X", cmdType);
return FALSE;
return -1;
}
size -= cmdLength;
@ -113,7 +113,8 @@ BOOL update_recv_surfcmds(rdpUpdate* update, UINT32 size, STREAM* s)
pcap_flush(update->pcap_rfx);
}
}
return TRUE;
return 0;
}
void update_write_surfcmd_surface_bits_header(STREAM* s, SURFACE_BITS_COMMAND* cmd)

View File

@ -33,7 +33,7 @@ enum SURFCMD_CMDTYPE
CMDTYPE_STREAM_SURFACE_BITS = 0x0006
};
BOOL update_recv_surfcmds(rdpUpdate* update, UINT32 size, STREAM* s);
int update_recv_surfcmds(rdpUpdate* update, UINT32 size, STREAM* s);
void update_write_surfcmd_surface_bits_header(STREAM* s, SURFACE_BITS_COMMAND* cmd);
void update_write_surfcmd_frame_marker(STREAM* s, UINT16 frameAction, UINT32 frameId);

View File

@ -589,6 +589,7 @@ int transport_check_fds(rdpTransport** ptransport)
int pos;
int status;
UINT16 length;
int recv_status;
STREAM* received;
rdpTransport* transport = *ptransport;
@ -684,10 +685,21 @@ int transport_check_fds(rdpTransport** ptransport)
stream_seal(received);
stream_set_pos(received, 0);
if (transport->ReceiveCallback(transport, received, transport->ReceiveExtra) == FALSE)
/**
* ReceiveCallback return values:
*
* -1: synchronous failure
* 0: synchronous success
* 1: asynchronous return
*/
recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra);
if (recv_status < 0)
status = -1;
transport_receive_pool_return(transport, received);
if (recv_status == 0)
transport_receive_pool_return(transport, received);
if (status < 0)
return status;

View File

@ -22,6 +22,7 @@
#endif
#include <winpr/crt.h>
#include <winpr/thread.h>
#include "update.h"
#include "surface.h"
@ -620,6 +621,20 @@ void update_register_client_callbacks(rdpUpdate* update)
update->SuppressOutput = update_send_suppress_output;
}
static void* update_thread(void* arg)
{
rdpUpdate* update;
update = (rdpUpdate*) arg;
while (WaitForSingleObject(Queue_Event(update->queue), INFINITE) == WAIT_OBJECT_0)
{
}
return NULL;
}
rdpUpdate* update_new(rdpRdp* rdp)
{
rdpUpdate* update;
@ -657,6 +672,10 @@ rdpUpdate* update_new(rdpRdp* rdp)
deleteList->cIndices = 0;
update->SuppressOutput = update_send_suppress_output;
update->queue = Queue_New(TRUE, -1, -1);
update->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) update_thread, update, 0, NULL);
}
return update;
@ -679,7 +698,9 @@ void update_free(rdpUpdate* update)
free(update->secondary);
free(update->altsec);
free(update->window);
CloseHandle(update->thread);
free(update);
}
}

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

@ -54,7 +54,6 @@ if(WITH_WIN8)
endif()
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} dsound)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-server)
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS

View File

@ -24,7 +24,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <winpr\windows.h>
#include <winpr/windows.h>
#define INITGUID
#include <initguid.h>
#include <objbase.h>
#define CINTERFACE
#include <mmsystem.h>
#include <dsound.h>
@ -38,7 +43,7 @@
* Here are some temp things that shall be moved
*
*/
IDirectSoundCapture8 * cap;
IDirectSoundCapture8* cap;
IDirectSoundCaptureBuffer8* capBuf;
DSCBUFFERDESC dscbd;
DWORD capturePos;

View File

@ -0,0 +1,387 @@
/**
* WinPR: Windows Portable Runtime
* Cryptography API (CryptoAPI)
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_CRYPTO_H
#define WINPR_CRYPTO_H
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#ifdef _WIN32
#include <wincrypt.h>
#else
#define GET_ALG_CLASS(x) (x & (7 << 13))
#define GET_ALG_TYPE(x) (x & (15 << 9))
#define GET_ALG_SID(x) (x & (511))
#define ALG_CLASS_ANY (0)
#define ALG_CLASS_SIGNATURE (1 << 13)
#define ALG_CLASS_MSG_ENCRYPT (2 << 13)
#define ALG_CLASS_DATA_ENCRYPT (3 << 13)
#define ALG_CLASS_HASH (4 << 13)
#define ALG_CLASS_KEY_EXCHANGE (5 << 13)
#define ALG_CLASS_ALL (7 << 13)
#define ALG_TYPE_ANY (0)
#define ALG_TYPE_DSS (1 << 9)
#define ALG_TYPE_RSA (2 << 9)
#define ALG_TYPE_BLOCK (3 << 9)
#define ALG_TYPE_STREAM (4 << 9)
#define ALG_TYPE_DH (5 << 9)
#define ALG_TYPE_SECURECHANNEL (6 << 9)
#define ALG_TYPE_RESERVED7 (7 << 9)
#define ALG_SID_ANY (0)
#define ALG_SID_RSA_ANY 0
#define ALG_SID_RSA_PKCS 1
#define ALG_SID_RSA_MSATWORK 2
#define ALG_SID_RSA_ENTRUST 3
#define ALG_SID_RSA_PGP 4
#define ALG_SID_DSS_ANY 0
#define ALG_SID_DSS_PKCS 1
#define ALG_SID_DSS_DMS 2
#define ALG_SID_ECDSA 3
#define ALG_SID_DES 1
#define ALG_SID_3DES 3
#define ALG_SID_DESX 4
#define ALG_SID_IDEA 5
#define ALG_SID_CAST 6
#define ALG_SID_SAFERSK64 7
#define ALG_SID_SAFERSK128 8
#define ALG_SID_3DES_112 9
#define ALG_SID_CYLINK_MEK 12
#define ALG_SID_RC5 13
#define ALG_SID_AES_128 14
#define ALG_SID_AES_192 15
#define ALG_SID_AES_256 16
#define ALG_SID_AES 17
#define ALG_SID_SKIPJACK 10
#define ALG_SID_TEK 11
#define CRYPT_MODE_CBCI 6
#define CRYPT_MODE_CFBP 7
#define CRYPT_MODE_OFBP 8
#define CRYPT_MODE_CBCOFM 9
#define CRYPT_MODE_CBCOFMI 10
#define ALG_SID_RC2 2
#define ALG_SID_RC4 1
#define ALG_SID_SEAL 2
#define ALG_SID_DH_SANDF 1
#define ALG_SID_DH_EPHEM 2
#define ALG_SID_AGREED_KEY_ANY 3
#define ALG_SID_KEA 4
#define ALG_SID_ECDH 5
#define ALG_SID_MD2 1
#define ALG_SID_MD4 2
#define ALG_SID_MD5 3
#define ALG_SID_SHA 4
#define ALG_SID_SHA1 4
#define ALG_SID_MAC 5
#define ALG_SID_RIPEMD 6
#define ALG_SID_RIPEMD160 7
#define ALG_SID_SSL3SHAMD5 8
#define ALG_SID_HMAC 9
#define ALG_SID_TLS1PRF 10
#define ALG_SID_HASH_REPLACE_OWF 11
#define ALG_SID_SHA_256 12
#define ALG_SID_SHA_384 13
#define ALG_SID_SHA_512 14
#define ALG_SID_SSL3_MASTER 1
#define ALG_SID_SCHANNEL_MASTER_HASH 2
#define ALG_SID_SCHANNEL_MAC_KEY 3
#define ALG_SID_PCT1_MASTER 4
#define ALG_SID_SSL2_MASTER 5
#define ALG_SID_TLS1_MASTER 6
#define ALG_SID_SCHANNEL_ENC_KEY 7
#define ALG_SID_ECMQV 1
#define CALG_MD2 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD2)
#define CALG_MD4 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD4)
#define CALG_MD5 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD5)
#define CALG_SHA (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA)
#define CALG_SHA1 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA1)
#define CALG_MAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MAC)
#define CALG_RSA_SIGN (ALG_CLASS_SIGNATURE | ALG_TYPE_RSA | ALG_SID_RSA_ANY)
#define CALG_DSS_SIGN (ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | ALG_SID_DSS_ANY)
#define CALG_NO_SIGN (ALG_CLASS_SIGNATURE | ALG_TYPE_ANY | ALG_SID_ANY)
#define CALG_RSA_KEYX (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_RSA | ALG_SID_RSA_ANY)
#define CALG_DES (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_DES)
#define CALG_3DES_112 (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_3DES_112)
#define CALG_3DES (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_3DES)
#define CALG_DESX (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_DESX)
#define CALG_RC2 (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_RC2)
#define CALG_RC4 (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_STREAM | ALG_SID_RC4)
#define CALG_SEAL (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_STREAM | ALG_SID_SEAL)
#define CALG_DH_SF (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_DH_SANDF)
#define CALG_DH_EPHEM (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_DH_EPHEM)
#define CALG_AGREEDKEY_ANY (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_AGREED_KEY_ANY)
#define CALG_KEA_KEYX (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_KEA)
#define CALG_HUGHES_MD5 (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_ANY | ALG_SID_MD5)
#define CALG_SKIPJACK (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_SKIPJACK)
#define CALG_TEK (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_TEK)
#define CALG_CYLINK_MEK (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_CYLINK_MEK)
#define CALG_SSL3_SHAMD5 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SSL3SHAMD5)
#define CALG_SSL3_MASTER (ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_SSL3_MASTER)
#define CALG_SCHANNEL_MASTER_HASH (ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_SCHANNEL_MASTER_HASH)
#define CALG_SCHANNEL_MAC_KEY (ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_SCHANNEL_MAC_KEY)
#define CALG_SCHANNEL_ENC_KEY (ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_SCHANNEL_ENC_KEY)
#define CALG_PCT1_MASTER (ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_PCT1_MASTER)
#define CALG_SSL2_MASTER (ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_SSL2_MASTER)
#define CALG_TLS1_MASTER (ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_TLS1_MASTER)
#define CALG_RC5 (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_RC5)
#define CALG_HMAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC)
#define CALG_TLS1PRF (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_TLS1PRF)
#define CALG_HASH_REPLACE_OWF (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HASH_REPLACE_OWF)
#define CALG_AES_128 (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_AES_128)
#define CALG_AES_192 (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_AES_192)
#define CALG_AES_256 (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_AES_256)
#define CALG_AES (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_AES)
#define CALG_SHA_256 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256)
#define CALG_SHA_384 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_384)
#define CALG_SHA_512 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_512)
#define CALG_ECDH (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_ECDH)
#define CALG_ECMQV (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_ANY | ALG_SID_ECMQV)
#define CALG_ECDSA (ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | ALG_SID_ECDSA)
typedef struct _CRYPTOAPI_BLOB
{
DWORD cbData;
BYTE* pbData;
} CRYPT_INTEGER_BLOB, *PCRYPT_INTEGER_BLOB,
CRYPT_UINT_BLOB, *PCRYPT_UINT_BLOB,
CRYPT_OBJID_BLOB, *PCRYPT_OBJID_BLOB,
CERT_NAME_BLOB, *PCERT_NAME_BLOB,
CERT_RDN_VALUE_BLOB, *PCERT_RDN_VALUE_BLOB,
CERT_BLOB, *PCERT_BLOB,
CRL_BLOB, *PCRL_BLOB,
DATA_BLOB, *PDATA_BLOB,
CRYPT_DATA_BLOB, *PCRYPT_DATA_BLOB,
CRYPT_HASH_BLOB, *PCRYPT_HASH_BLOB,
CRYPT_DIGEST_BLOB, *PCRYPT_DIGEST_BLOB,
CRYPT_DER_BLOB, *PCRYPT_DER_BLOB,
CRYPT_ATTR_BLOB, *PCRYPT_ATTR_BLOB;
typedef struct _CRYPT_ALGORITHM_IDENTIFIER
{
LPSTR pszObjId;
CRYPT_OBJID_BLOB Parameters;
} CRYPT_ALGORITHM_IDENTIFIER, *PCRYPT_ALGORITHM_IDENTIFIER;
typedef struct _CRYPT_BIT_BLOB
{
DWORD cbData;
BYTE* pbData;
DWORD cUnusedBits;
} CRYPT_BIT_BLOB, *PCRYPT_BIT_BLOB;
typedef struct _CERT_PUBLIC_KEY_INFO
{
CRYPT_ALGORITHM_IDENTIFIER Algorithm;
CRYPT_BIT_BLOB PublicKey;
} CERT_PUBLIC_KEY_INFO, *PCERT_PUBLIC_KEY_INFO;
typedef struct _CERT_EXTENSION
{
LPSTR pszObjId;
BOOL fCritical;
CRYPT_OBJID_BLOB Value;
} CERT_EXTENSION, *PCERT_EXTENSION;
typedef const CERT_EXTENSION* PCCERT_EXTENSION;
typedef struct _CERT_INFO
{
DWORD dwVersion;
CRYPT_INTEGER_BLOB SerialNumber;
CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
CERT_NAME_BLOB Issuer;
FILETIME NotBefore;
FILETIME NotAfter;
CERT_NAME_BLOB Subject;
CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo;
CRYPT_BIT_BLOB IssuerUniqueId;
CRYPT_BIT_BLOB SubjectUniqueId;
DWORD cExtension;
PCERT_EXTENSION rgExtension;
} CERT_INFO, *PCERT_INFO;
typedef void *HCERTSTORE;
typedef ULONG_PTR HCRYPTPROV;
typedef ULONG_PTR HCRYPTPROV_LEGACY;
typedef struct _CERT_CONTEXT
{
DWORD dwCertEncodingType;
BYTE* pbCertEncoded;
DWORD cbCertEncoded;
PCERT_INFO pCertInfo;
HCERTSTORE hCertStore;
} CERT_CONTEXT, *PCERT_CONTEXT;
typedef const CERT_CONTEXT *PCCERT_CONTEXT;
#define CERT_ENCODING_TYPE_MASK 0x0000FFFF
#define CMSG_ENCODING_TYPE_MASK 0xFFFF0000
#define GET_CERT_ENCODING_TYPE(x) (x & CERT_ENCODING_TYPE_MASK)
#define GET_CMSG_ENCODING_TYPE(x) (x & CMSG_ENCODING_TYPE_MASK)
#define CRYPT_ASN_ENCODING 0x00000001
#define CRYPT_NDR_ENCODING 0x00000002
#define X509_ASN_ENCODING 0x00000001
#define X509_NDR_ENCODING 0x00000002
#define PKCS_7_ASN_ENCODING 0x00010000
#define PKCS_7_NDR_ENCODING 0x00020000
#define CERT_COMPARE_MASK 0xFFFF
#define CERT_COMPARE_SHIFT 16
#define CERT_COMPARE_ANY 0
#define CERT_COMPARE_SHA1_HASH 1
#define CERT_COMPARE_NAME 2
#define CERT_COMPARE_ATTR 3
#define CERT_COMPARE_MD5_HASH 4
#define CERT_COMPARE_PROPERTY 5
#define CERT_COMPARE_PUBLIC_KEY 6
#define CERT_COMPARE_HASH CERT_COMPARE_SHA1_HASH
#define CERT_COMPARE_NAME_STR_A 7
#define CERT_COMPARE_NAME_STR_W 8
#define CERT_COMPARE_KEY_SPEC 9
#define CERT_COMPARE_ENHKEY_USAGE 10
#define CERT_COMPARE_CTL_USAGE CERT_COMPARE_ENHKEY_USAGE
#define CERT_COMPARE_SUBJECT_CERT 11
#define CERT_COMPARE_ISSUER_OF 12
#define CERT_COMPARE_EXISTING 13
#define CERT_COMPARE_SIGNATURE_HASH 14
#define CERT_COMPARE_KEY_IDENTIFIER 15
#define CERT_COMPARE_CERT_ID 16
#define CERT_COMPARE_CROSS_CERT_DIST_POINTS 17
#define CERT_COMPARE_PUBKEY_MD5_HASH 18
#define CERT_COMPARE_SUBJECT_INFO_ACCESS 19
#define CERT_COMPARE_HASH_STR 20
#define CERT_COMPARE_HAS_PRIVATE_KEY 21
#define CERT_FIND_ANY (CERT_COMPARE_ANY << CERT_COMPARE_SHIFT)
#define CERT_FIND_SHA1_HASH (CERT_COMPARE_SHA1_HASH << CERT_COMPARE_SHIFT)
#define CERT_FIND_MD5_HASH (CERT_COMPARE_MD5_HASH << CERT_COMPARE_SHIFT)
#define CERT_FIND_SIGNATURE_HASH (CERT_COMPARE_SIGNATURE_HASH << CERT_COMPARE_SHIFT)
#define CERT_FIND_KEY_IDENTIFIER (CERT_COMPARE_KEY_IDENTIFIER << CERT_COMPARE_SHIFT)
#define CERT_FIND_HASH CERT_FIND_SHA1_HASH
#define CERT_FIND_PROPERTY (CERT_COMPARE_PROPERTY << CERT_COMPARE_SHIFT)
#define CERT_FIND_PUBLIC_KEY (CERT_COMPARE_PUBLIC_KEY << CERT_COMPARE_SHIFT)
#define CERT_FIND_SUBJECT_NAME (CERT_COMPARE_NAME << CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
#define CERT_FIND_SUBJECT_ATTR (CERT_COMPARE_ATTR << CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
#define CERT_FIND_ISSUER_NAME (CERT_COMPARE_NAME << CERT_COMPARE_SHIFT | CERT_INFO_ISSUER_FLAG)
#define CERT_FIND_ISSUER_ATTR (CERT_COMPARE_ATTR << CERT_COMPARE_SHIFT | CERT_INFO_ISSUER_FLAG)
#define CERT_FIND_SUBJECT_STR_A (CERT_COMPARE_NAME_STR_A << CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
#define CERT_FIND_SUBJECT_STR_W (CERT_COMPARE_NAME_STR_W << CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
#define CERT_FIND_SUBJECT_STR CERT_FIND_SUBJECT_STR_W
#define CERT_FIND_ISSUER_STR_A (CERT_COMPARE_NAME_STR_A << CERT_COMPARE_SHIFT | CERT_INFO_ISSUER_FLAG)
#define CERT_FIND_ISSUER_STR_W (CERT_COMPARE_NAME_STR_W << CERT_COMPARE_SHIFT | CERT_INFO_ISSUER_FLAG)
#define CERT_FIND_ISSUER_STR CERT_FIND_ISSUER_STR_W
#define CERT_FIND_KEY_SPEC (CERT_COMPARE_KEY_SPEC << CERT_COMPARE_SHIFT)
#define CERT_FIND_ENHKEY_USAGE (CERT_COMPARE_ENHKEY_USAGE << CERT_COMPARE_SHIFT)
#define CERT_FIND_CTL_USAGE CERT_FIND_ENHKEY_USAGE
#define CERT_FIND_SUBJECT_CERT (CERT_COMPARE_SUBJECT_CERT << CERT_COMPARE_SHIFT)
#define CERT_FIND_ISSUER_OF (CERT_COMPARE_ISSUER_OF << CERT_COMPARE_SHIFT)
#define CERT_FIND_EXISTING (CERT_COMPARE_EXISTING << CERT_COMPARE_SHIFT)
#define CERT_FIND_CERT_ID (CERT_COMPARE_CERT_ID << CERT_COMPARE_SHIFT)
#define CERT_FIND_CROSS_CERT_DIST_POINTS (CERT_COMPARE_CROSS_CERT_DIST_POINTS << CERT_COMPARE_SHIFT)
#define CERT_FIND_PUBKEY_MD5_HASH (CERT_COMPARE_PUBKEY_MD5_HASH << CERT_COMPARE_SHIFT)
#define CERT_FIND_SUBJECT_INFO_ACCESS (CERT_COMPARE_SUBJECT_INFO_ACCESS << CERT_COMPARE_SHIFT)
#define CERT_FIND_HASH_STR (CERT_COMPARE_HASH_STR << CERT_COMPARE_SHIFT)
#define CERT_FIND_HAS_PRIVATE_KEY (CERT_COMPARE_HAS_PRIVATE_KEY << CERT_COMPARE_SHIFT)
#define CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG 0x1
#define CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG 0x2
#define CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG 0x4
#define CERT_FIND_NO_ENHKEY_USAGE_FLAG 0x8
#define CERT_FIND_OR_ENHKEY_USAGE_FLAG 0x10
#define CERT_FIND_VALID_ENHKEY_USAGE_FLAG 0x20
#define CERT_FIND_OPTIONAL_CTL_USAGE_FLAG CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG
#define CERT_FIND_EXT_ONLY_CTL_USAGE_FLAG CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
#define CERT_FIND_PROP_ONLY_CTL_USAGE_FLAG CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
#define CERT_FIND_NO_CTL_USAGE_FLAG CERT_FIND_NO_ENHKEY_USAGE_FLAG
#define CERT_FIND_OR_CTL_USAGE_FLAG CERT_FIND_OR_ENHKEY_USAGE_FLAG
#define CERT_FIND_VALID_CTL_USAGE_FLAG CERT_FIND_VALID_ENHKEY_USAGE_FLAG
#define CERT_NAME_EMAIL_TYPE 1
#define CERT_NAME_RDN_TYPE 2
#define CERT_NAME_ATTR_TYPE 3
#define CERT_NAME_SIMPLE_DISPLAY_TYPE 4
#define CERT_NAME_FRIENDLY_DISPLAY_TYPE 5
#define CERT_NAME_DNS_TYPE 6
#define CERT_NAME_URL_TYPE 7
#define CERT_NAME_UPN_TYPE 8
#define CERT_NAME_ISSUER_FLAG 0x1
#define CERT_NAME_DISABLE_IE4_UTF8_FLAG 0x00010000
#define CERT_NAME_SEARCH_ALL_NAMES_FLAG 0x2
WINPR_API HCERTSTORE CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv, LPCWSTR szSubsystemProtocol);
WINPR_API HCERTSTORE CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv, LPCSTR szSubsystemProtocol);
WINPR_API BOOL CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags);
#ifdef UNICODE
#define CertOpenSystemStore CertOpenSystemStoreW
#else
#define CertOpenSystemStore CertOpenSystemStoreA
#endif
WINPR_API PCCERT_CONTEXT CertFindCertificateInStore(HCERTSTORE hCertStore, DWORD dwCertEncodingType,
DWORD dwFindFlags, DWORD dwFindType, const void* pvFindPara, PCCERT_CONTEXT pPrevCertContext);
WINPR_API PCCERT_CONTEXT CertEnumCertificatesInStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrevCertContext);
DWORD CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType,
DWORD dwFlags, void* pvTypePara, LPWSTR pszNameString, DWORD cchNameString);
DWORD CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType,
DWORD dwFlags, void* pvTypePara, LPSTR pszNameString, DWORD cchNameString);
#ifdef UNICODE
#define CertGetNameString CertGetNameStringW
#else
#define CertGetNameString CertGetNameStringA
#endif
#endif
#endif /* WINPR_CRYPTO_H */

View File

@ -0,0 +1,287 @@
/**
* WinPR: Windows Portable Runtime
* Schannel Security Package
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_SSPI_SCHANNEL_H
#define WINPR_SSPI_SCHANNEL_H
#include <winpr/sspi.h>
#include <winpr/crypto.h>
#ifdef _WIN32
#include <schannel.h>
#else
#define SCHANNEL_NAME_A "Schannel"
#define SCHANNEL_NAME_W L"Schannel"
#ifdef _UNICODE
#define SCHANNEL_NAME SCHANNEL_NAME_W
#else
#define SCHANNEL_NAME SCHANNEL_NAME_A
#endif
#define SECPKG_ATTR_SUPPORTED_ALGS 86
#define SECPKG_ATTR_CIPHER_STRENGTHS 87
#define SECPKG_ATTR_SUPPORTED_PROTOCOLS 88
typedef struct _SecPkgCred_SupportedAlgs
{
DWORD cSupportedAlgs;
ALG_ID* palgSupportedAlgs;
} SecPkgCred_SupportedAlgs, *PSecPkgCred_SupportedAlgs;
typedef struct _SecPkgCred_CipherStrengths
{
DWORD dwMinimumCipherStrength;
DWORD dwMaximumCipherStrength;
} SecPkgCred_CipherStrengths, *PSecPkgCred_CipherStrengths;
typedef struct _SecPkgCred_SupportedProtocols
{
DWORD grbitProtocol;
} SecPkgCred_SupportedProtocols, *PSecPkgCred_SupportedProtocols;
enum eTlsSignatureAlgorithm
{
TlsSignatureAlgorithm_Anonymous = 0,
TlsSignatureAlgorithm_Rsa = 1,
TlsSignatureAlgorithm_Dsa = 2,
TlsSignatureAlgorithm_Ecdsa = 3
};
enum eTlsHashAlgorithm
{
TlsHashAlgorithm_None = 0,
TlsHashAlgorithm_Md5 = 1,
TlsHashAlgorithm_Sha1 = 2,
TlsHashAlgorithm_Sha224 = 3,
TlsHashAlgorithm_Sha256 = 4,
TlsHashAlgorithm_Sha384 = 5,
TlsHashAlgorithm_Sha512 = 6
};
#define SCH_CRED_V1 0x00000001
#define SCH_CRED_V2 0x00000002
#define SCH_CRED_VERSION 0x00000002
#define SCH_CRED_V3 0x00000003
#define SCHANNEL_CRED_VERSION 0x00000004
struct _HMAPPER;
typedef struct _SCHANNEL_CRED
{
DWORD dwVersion;
DWORD cCreds;
PCCERT_CONTEXT* paCred;
HCERTSTORE hRootStore;
DWORD cMappers;
struct _HMAPPER **aphMappers;
DWORD cSupportedAlgs;
ALG_ID* palgSupportedAlgs;
DWORD grbitEnabledProtocols;
DWORD dwMinimumCipherStrength;
DWORD dwMaximumCipherStrength;
DWORD dwSessionLifespan;
DWORD dwFlags;
DWORD dwCredFormat;
} SCHANNEL_CRED, *PSCHANNEL_CRED;
#define SCH_CRED_FORMAT_CERT_CONTEXT 0x00000000
#define SCH_CRED_FORMAT_CERT_HASH 0x00000001
#define SCH_CRED_FORMAT_CERT_HASH_STORE 0x00000002
#define SCH_CRED_MAX_STORE_NAME_SIZE 128
#define SCH_CRED_MAX_SUPPORTED_ALGS 256
#define SCH_CRED_MAX_SUPPORTED_CERTS 100
typedef struct _SCHANNEL_CERT_HASH
{
DWORD dwLength;
DWORD dwFlags;
HCRYPTPROV hProv;
BYTE ShaHash[20];
} SCHANNEL_CERT_HASH, *PSCHANNEL_CERT_HASH;
typedef struct _SCHANNEL_CERT_HASH_STORE
{
DWORD dwLength;
DWORD dwFlags;
HCRYPTPROV hProv;
BYTE ShaHash[20];
WCHAR pwszStoreName[SCH_CRED_MAX_STORE_NAME_SIZE];
} SCHANNEL_CERT_HASH_STORE, *PSCHANNEL_CERT_HASH_STORE;
#define SCH_MACHINE_CERT_HASH 0x00000001
#define SCH_CRED_NO_SYSTEM_MAPPER 0x00000002
#define SCH_CRED_NO_SERVERNAME_CHECK 0x00000004
#define SCH_CRED_MANUAL_CRED_VALIDATION 0x00000008
#define SCH_CRED_NO_DEFAULT_CREDS 0x00000010
#define SCH_CRED_AUTO_CRED_VALIDATION 0x00000020
#define SCH_CRED_USE_DEFAULT_CREDS 0x00000040
#define SCH_CRED_DISABLE_RECONNECTS 0x00000080
#define SCH_CRED_REVOCATION_CHECK_END_CERT 0x00000100
#define SCH_CRED_REVOCATION_CHECK_CHAIN 0x00000200
#define SCH_CRED_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT 0x00000400
#define SCH_CRED_IGNORE_NO_REVOCATION_CHECK 0x00000800
#define SCH_CRED_IGNORE_REVOCATION_OFFLINE 0x00001000
#define SCH_CRED_RESTRICTED_ROOTS 0x00002000
#define SCH_CRED_REVOCATION_CHECK_CACHE_ONLY 0x00004000
#define SCH_CRED_CACHE_ONLY_URL_RETRIEVAL 0x00008000
#define SCH_CRED_MEMORY_STORE_CERT 0x00010000
#define SCH_CRED_CACHE_ONLY_URL_RETRIEVAL_ON_CREATE 0x00020000
#define SCH_SEND_ROOT_CERT 0x00040000
#define SCH_CRED_SNI_CREDENTIAL 0x00080000
#define SCH_CRED_SNI_ENABLE_OCSP 0x00100000
#define SCH_SEND_AUX_RECORD 0x00200000
#define SCHANNEL_RENEGOTIATE 0
#define SCHANNEL_SHUTDOWN 1
#define SCHANNEL_ALERT 2
#define SCHANNEL_SESSION 3
typedef struct _SCHANNEL_ALERT_TOKEN
{
DWORD dwTokenType;
DWORD dwAlertType;
DWORD dwAlertNumber;
} SCHANNEL_ALERT_TOKEN;
#define TLS1_ALERT_WARNING 1
#define TLS1_ALERT_FATAL 2
#define TLS1_ALERT_CLOSE_NOTIFY 0
#define TLS1_ALERT_UNEXPECTED_MESSAGE 10
#define TLS1_ALERT_BAD_RECORD_MAC 20
#define TLS1_ALERT_DECRYPTION_FAILED 21
#define TLS1_ALERT_RECORD_OVERFLOW 22
#define TLS1_ALERT_DECOMPRESSION_FAIL 30
#define TLS1_ALERT_HANDSHAKE_FAILURE 40
#define TLS1_ALERT_BAD_CERTIFICATE 42
#define TLS1_ALERT_UNSUPPORTED_CERT 43
#define TLS1_ALERT_CERTIFICATE_REVOKED 44
#define TLS1_ALERT_CERTIFICATE_EXPIRED 45
#define TLS1_ALERT_CERTIFICATE_UNKNOWN 46
#define TLS1_ALERT_ILLEGAL_PARAMETER 47
#define TLS1_ALERT_UNKNOWN_CA 48
#define TLS1_ALERT_ACCESS_DENIED 49
#define TLS1_ALERT_DECODE_ERROR 50
#define TLS1_ALERT_DECRYPT_ERROR 51
#define TLS1_ALERT_EXPORT_RESTRICTION 60
#define TLS1_ALERT_PROTOCOL_VERSION 70
#define TLS1_ALERT_INSUFFIENT_SECURITY 71
#define TLS1_ALERT_INTERNAL_ERROR 80
#define TLS1_ALERT_USER_CANCELED 90
#define TLS1_ALERT_NO_RENEGOTIATION 100
#define TLS1_ALERT_UNSUPPORTED_EXT 110
#define SSL_SESSION_ENABLE_RECONNECTS 1
#define SSL_SESSION_DISABLE_RECONNECTS 2
typedef struct _SCHANNEL_SESSION_TOKEN
{
DWORD dwTokenType;
DWORD dwFlags;
} SCHANNEL_SESSION_TOKEN;
typedef struct _SCHANNEL_CLIENT_SIGNATURE
{
DWORD cbLength;
ALG_ID aiHash;
DWORD cbHash;
BYTE HashValue[36];
BYTE CertThumbprint[20];
} SCHANNEL_CLIENT_SIGNATURE, *PSCHANNEL_CLIENT_SIGNATURE;
#define SP_PROT_SSL3_SERVER 0x00000010
#define SP_PROT_SSL3_CLIENT 0x00000020
#define SP_PROT_SSL3 (SP_PROT_SSL3_SERVER | SP_PROT_SSL3_CLIENT)
#define SP_PROT_TLS1_SERVER 0x00000040
#define SP_PROT_TLS1_CLIENT 0x00000080
#define SP_PROT_TLS1 (SP_PROT_TLS1_SERVER | SP_PROT_TLS1_CLIENT)
#define SP_PROT_SSL3TLS1_CLIENTS (SP_PROT_TLS1_CLIENT | SP_PROT_SSL3_CLIENT)
#define SP_PROT_SSL3TLS1_SERVERS (SP_PROT_TLS1_SERVER | SP_PROT_SSL3_SERVER)
#define SP_PROT_SSL3TLS1 (SP_PROT_SSL3 | SP_PROT_TLS1)
#define SP_PROT_UNI_SERVER 0x40000000
#define SP_PROT_UNI_CLIENT 0x80000000
#define SP_PROT_UNI (SP_PROT_UNI_SERVER | SP_PROT_UNI_CLIENT)
#define SP_PROT_ALL 0xFFFFFFFF
#define SP_PROT_NONE 0
#define SP_PROT_CLIENTS (SP_PROT_SSL3_CLIENT | SP_PROT_UNI_CLIENT | SP_PROT_TLS1_CLIENT)
#define SP_PROT_SERVERS (SP_PROT_SSL3_SERVER | SP_PROT_UNI_SERVER | SP_PROT_TLS1_SERVER)
#define SP_PROT_TLS1_0_SERVER SP_PROT_TLS1_SERVER
#define SP_PROT_TLS1_0_CLIENT SP_PROT_TLS1_CLIENT
#define SP_PROT_TLS1_0 (SP_PROT_TLS1_0_SERVER | SP_PROT_TLS1_0_CLIENT)
#define SP_PROT_TLS1_1_SERVER 0x00000100
#define SP_PROT_TLS1_1_CLIENT 0x00000200
#define SP_PROT_TLS1_1 (SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_1_CLIENT)
#define SP_PROT_TLS1_2_SERVER 0x00000400
#define SP_PROT_TLS1_2_CLIENT 0x00000800
#define SP_PROT_TLS1_2 (SP_PROT_TLS1_2_SERVER | SP_PROT_TLS1_2_CLIENT)
#define SP_PROT_DTLS_SERVER 0x00010000
#define SP_PROT_DTLS_CLIENT 0x00020000
#define SP_PROT_DTLS (SP_PROT_DTLS_SERVER | SP_PROT_DTLS_CLIENT)
#define SP_PROT_DTLS1_0_SERVER SP_PROT_DTLS_SERVER
#define SP_PROT_DTLS1_0_CLIENT SP_PROT_DTLS_CLIENT
#define SP_PROT_DTLS1_0 (SP_PROT_DTLS1_0_SERVER | SP_PROT_DTLS1_0_CLIENT)
#define SP_PROT_DTLS1_X_SERVER SP_PROT_DTLS1_0_SERVER
#define SP_PROT_DTLS1_X_CLIENT SP_PROT_DTLS1_0_CLIENT
#define SP_PROT_DTLS1_X (SP_PROT_DTLS1_X_SERVER | SP_PROT_DTLS1_X_CLIENT)
#define SP_PROT_TLS1_1PLUS_SERVER (SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_2_SERVER)
#define SP_PROT_TLS1_1PLUS_CLIENT (SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT)
#define SP_PROT_TLS1_1PLUS (SP_PROT_TLS1_1PLUS_SERVER | SP_PROT_TLS1_1PLUS_CLIENT)
#define SP_PROT_TLS1_X_SERVER (SP_PROT_TLS1_0_SERVER | SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_2_SERVER)
#define SP_PROT_TLS1_X_CLIENT (SP_PROT_TLS1_0_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT)
#define SP_PROT_TLS1_X (SP_PROT_TLS1_X_SERVER | SP_PROT_TLS1_X_CLIENT)
#define SP_PROT_SSL3TLS1_X_CLIENTS (SP_PROT_TLS1_X_CLIENT | SP_PROT_SSL3_CLIENT)
#define SP_PROT_SSL3TLS1_X_SERVERS (SP_PROT_TLS1_X_SERVER | SP_PROT_SSL3_SERVER)
#define SP_PROT_SSL3TLS1_X (SP_PROT_SSL3 | SP_PROT_TLS1_X)
#define SP_PROT_X_CLIENTS (SP_PROT_CLIENTS | SP_PROT_TLS1_X_CLIENT | SP_PROT_DTLS1_X_CLIENT)
#define SP_PROT_X_SERVERS (SP_PROT_SERVERS | SP_PROT_TLS1_X_SERVER | SP_PROT_DTLS1_X_SERVER )
#endif
#endif /* WINPR_SSPI_SCHANNEL_H */

View File

@ -635,12 +635,20 @@ struct _SecHandle
ULONG_PTR dwUpper;
};
typedef struct _SecHandle SecHandle;
typedef SecHandle* PSecHandle;
typedef SecHandle CredHandle;
typedef CredHandle* PCredHandle;
typedef SecHandle CtxtHandle;
typedef CtxtHandle* PCtxtHandle;
#define SecInvalidateHandle(x) \
((PSecHandle)(x))->dwLower = ((PSecHandle)(x))->dwUpper = ((ULONG_PTR)((INT_PTR) - 1));
#define SecIsValidHandle(x) \
((((PSecHandle)(x))->dwLower != ((ULONG_PTR)((INT_PTR) - 1))) && \
(((PSecHandle) (x))->dwUpper != ((ULONG_PTR)((INT_PTR) - 1))))
#endif
#define SECBUFFER_VERSION 0

View File

@ -0,0 +1,49 @@
# WinPR: Windows Portable Runtime
# libwinpr-crypto cmake build script
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set(MODULE_NAME "winpr-crypto")
set(MODULE_PREFIX "WINPR_CRYPTO")
set(${MODULE_PREFIX}_SRCS
crypto.c
cert.c)
if(MSVC AND (NOT MONOLITHIC_BUILD))
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def)
endif()
add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT"
MONOLITHIC ${MONOLITHIC_BUILD}
SOURCES ${${MODULE_PREFIX}_SRCS})
set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SOVERSION ${WINPR_VERSION} PREFIX "lib")
if(WIN32)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} crypt32)
endif()
if(MONOLITHIC_BUILD)
else()
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR")
if(BUILD_TESTING)
add_subdirectory(test)
endif()

View File

@ -0,0 +1,9 @@
set(MINWIN_LAYER "1")
set(MINWIN_GROUP "core")
set(MINWIN_MAJOR_VERSION "1")
set(MINWIN_MINOR_VERSION "0")
set(MINWIN_SHORT_NAME "crypto")
set(MINWIN_LONG_NAME "Cryptography API (CryptoAPI)")
set(MODULE_LIBRARY_NAME "crypt32")

View File

@ -0,0 +1,194 @@
/**
* WinPR: Windows Portable Runtime
* Cryptography API (CryptoAPI)
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crypto.h>
/**
* CertOpenStore
* CertCloseStore
* CertControlStore
* CertDuplicateStore
* CertSaveStore
* CertRegisterPhysicalStore
* CertRegisterSystemStore
* CertAddStoreToCollection
* CertRemoveStoreFromCollection
* CertOpenSystemStoreA
* CertOpenSystemStoreW
* CertEnumPhysicalStore
* CertEnumSystemStore
* CertEnumSystemStoreLocation
* CertSetStoreProperty
* CertUnregisterPhysicalStore
* CertUnregisterSystemStore
*
* CertAddCertificateContextToStore
* CertAddCertificateLinkToStore
* CertAddCRLContextToStore
* CertAddCRLLinkToStore
* CertAddCTLContextToStore
* CertAddCTLLinkToStore
* CertAddEncodedCertificateToStore
* CertAddEncodedCertificateToSystemStoreA
* CertAddEncodedCertificateToSystemStoreW
* CertAddEncodedCRLToStore
* CertAddEncodedCTLToStore
* CertAddSerializedElementToStore
* CertDeleteCertificateFromStore
* CertDeleteCRLFromStore
* CertDeleteCTLFromStore
* CertGetCRLFromStore
* CertEnumCertificatesInStore
* CertEnumCRLsInStore
* CertEnumCTLsInStore
* CertFindCertificateInStore
* CertFindChainInStore
* CertFindCRLInStore
* CertFindCTLInStore
* CertGetIssuerCertificateFromStore
* CertGetStoreProperty
* CertGetSubjectCertificateFromStore
* CertSerializeCertificateStoreElement
* CertSerializeCRLStoreElement
* CertSerializeCTLStoreElement
*
* CertAddEnhancedKeyUsageIdentifier
* CertAddRefServerOcspResponse
* CertAddRefServerOcspResponseContext
* CertAlgIdToOID
* CertCloseServerOcspResponse
* CertCompareCertificate
* CertCompareCertificateName
* CertCompareIntegerBlob
* CertComparePublicKeyInfo
* CertCreateCertificateChainEngine
* CertCreateCertificateContext
* CertCreateContext
* CertCreateCRLContext
* CertCreateCTLContext
* CertCreateCTLEntryFromCertificateContextProperties
* CertCreateSelfSignCertificate
* CertDuplicateCertificateChain
* CertDuplicateCertificateContext
* CertDuplicateCRLContext
* CertDuplicateCTLContext
* CertEnumCertificateContextProperties
* CertEnumCRLContextProperties
* CertEnumCTLContextProperties
* CertEnumSubjectInSortedCTL
* CertFindAttribute
* CertFindCertificateInCRL
* CertFindExtension
* CertFindRDNAttr
* CertFindSubjectInCTL
* CertFindSubjectInSortedCTL
* CertFreeCertificateChain
* CertFreeCertificateChainEngine
* CertFreeCertificateChainList
* CertFreeCertificateContext
* CertFreeCRLContext
* CertFreeCTLContext
* CertFreeServerOcspResponseContext
* CertGetCertificateChain
* CertGetCertificateContextProperty
* CertGetCRLContextProperty
* CertGetCTLContextProperty
* CertGetEnhancedKeyUsage
* CertGetIntendedKeyUsage
* CertGetNameStringA
* CertGetNameStringW
* CertGetPublicKeyLength
* CertGetServerOcspResponseContext
* CertGetValidUsages
* CertIsRDNAttrsInCertificateName
* CertIsStrongHashToSign
* CertIsValidCRLForCertificate
* CertNameToStrA
* CertNameToStrW
* CertOIDToAlgId
* CertOpenServerOcspResponse
* CertRDNValueToStrA
* CertRDNValueToStrW
* CertRemoveEnhancedKeyUsageIdentifier
* CertResyncCertificateChainEngine
* CertRetrieveLogoOrBiometricInfo
* CertSelectCertificateChains
* CertSetCertificateContextPropertiesFromCTLEntry
* CertSetCertificateContextProperty
* CertSetCRLContextProperty
* CertSetCTLContextProperty
* CertSetEnhancedKeyUsage
* CertStrToNameA
* CertStrToNameW
* CertVerifyCertificateChainPolicy
* CertVerifyCRLRevocation
* CertVerifyCRLTimeValidity
* CertVerifyCTLUsage
* CertVerifyRevocation
* CertVerifySubjectCertificateContext
* CertVerifyTimeValidity
* CertVerifyValidityNesting
*/
#ifndef _WIN32
HCERTSTORE CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv, LPCWSTR szSubsystemProtocol)
{
return (HCERTSTORE) 1;
}
HCERTSTORE CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv, LPCSTR szSubsystemProtocol)
{
return CertOpenSystemStoreW(hProv, NULL);
}
BOOL CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
{
return TRUE;
}
PCCERT_CONTEXT CertFindCertificateInStore(HCERTSTORE hCertStore, DWORD dwCertEncodingType,
DWORD dwFindFlags, DWORD dwFindType, const void* pvFindPara, PCCERT_CONTEXT pPrevCertContext)
{
return (PCCERT_CONTEXT) 1;
}
PCCERT_CONTEXT CertEnumCertificatesInStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrevCertContext)
{
return (PCCERT_CONTEXT) NULL;
}
DWORD CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType,
DWORD dwFlags, void* pvTypePara, LPWSTR pszNameString, DWORD cchNameString)
{
return 0;
}
DWORD CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType,
DWORD dwFlags, void* pvTypePara, LPSTR pszNameString, DWORD cchNameString)
{
return 0;
}
#endif

View File

@ -0,0 +1,149 @@
/**
* WinPR: Windows Portable Runtime
* Cryptography API (CryptoAPI)
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crypto.h>
/**
* CryptAcquireCertificatePrivateKey
* CryptBinaryToStringA
* CryptBinaryToStringW
* CryptCloseAsyncHandle
* CryptCreateAsyncHandle
* CryptCreateKeyIdentifierFromCSP
* CryptDecodeMessage
* CryptDecodeObject
* CryptDecodeObjectEx
* CryptDecryptAndVerifyMessageSignature
* CryptDecryptMessage
* CryptEncodeObject
* CryptEncodeObjectEx
* CryptEncryptMessage
* CryptEnumKeyIdentifierProperties
* CryptEnumOIDFunction
* CryptEnumOIDInfo
* CryptExportPKCS8
* CryptExportPublicKeyInfo
* CryptExportPublicKeyInfoEx
* CryptExportPublicKeyInfoFromBCryptKeyHandle
* CryptFindCertificateKeyProvInfo
* CryptFindLocalizedName
* CryptFindOIDInfo
* CryptFormatObject
* CryptFreeOIDFunctionAddress
* CryptGetAsyncParam
* CryptGetDefaultOIDDllList
* CryptGetDefaultOIDFunctionAddress
* CryptGetKeyIdentifierProperty
* CryptGetMessageCertificates
* CryptGetMessageSignerCount
* CryptGetOIDFunctionAddress
* CryptGetOIDFunctionValue
* CryptHashCertificate
* CryptHashCertificate2
* CryptHashMessage
* CryptHashPublicKeyInfo
* CryptHashToBeSigned
* CryptImportPKCS8
* CryptImportPublicKeyInfo
* CryptImportPublicKeyInfoEx
* CryptImportPublicKeyInfoEx2
* CryptInitOIDFunctionSet
* CryptInstallDefaultContext
* CryptInstallOIDFunctionAddress
* CryptLoadSip
* CryptMemAlloc
* CryptMemFree
* CryptMemRealloc
* CryptMsgCalculateEncodedLength
* CryptMsgClose
* CryptMsgControl
* CryptMsgCountersign
* CryptMsgCountersignEncoded
* CryptMsgDuplicate
* CryptMsgEncodeAndSignCTL
* CryptMsgGetAndVerifySigner
* CryptMsgGetParam
* CryptMsgOpenToDecode
* CryptMsgOpenToEncode
* CryptMsgSignCTL
* CryptMsgUpdate
* CryptMsgVerifyCountersignatureEncoded
* CryptMsgVerifyCountersignatureEncodedEx
* CryptProtectData
* CryptProtectMemory
* CryptQueryObject
* CryptRegisterDefaultOIDFunction
* CryptRegisterOIDFunction
* CryptRegisterOIDInfo
* CryptRetrieveTimeStamp
* CryptSetAsyncParam
* CryptSetKeyIdentifierProperty
* CryptSetOIDFunctionValue
* CryptSignAndEncodeCertificate
* CryptSignAndEncryptMessage
* CryptSignCertificate
* CryptSignMessage
* CryptSignMessageWithKey
* CryptSIPAddProvider
* CryptSIPCreateIndirectData
* CryptSIPGetCaps
* CryptSIPGetSignedDataMsg
* CryptSIPLoad
* CryptSIPPutSignedDataMsg
* CryptSIPRemoveProvider
* CryptSIPRemoveSignedDataMsg
* CryptSIPRetrieveSubjectGuid
* CryptSIPRetrieveSubjectGuidForCatalogFile
* CryptSIPVerifyIndirectData
* CryptStringToBinaryA
* CryptStringToBinaryW
* CryptUninstallDefaultContext
* CryptUnprotectData
* CryptUnprotectMemory
* CryptUnregisterDefaultOIDFunction
* CryptUnregisterOIDFunction
* CryptUnregisterOIDInfo
* CryptUpdateProtectedState
* CryptVerifyCertificateSignature
* CryptVerifyCertificateSignatureEx
* CryptVerifyDetachedMessageHash
* CryptVerifyDetachedMessageSignature
* CryptVerifyMessageHash
* CryptVerifyMessageSignature
* CryptVerifyMessageSignatureWithKey
* CryptVerifyTimeStampSignature
* DbgInitOSS
* DbgPrintf
* PFXExportCertStore
* PFXExportCertStore2
* PFXExportCertStoreEx
* PFXImportCertStore
* PFXIsPFXBlob
* PFXVerifyPassword
*/
#ifndef _WIN32
#endif

View File

@ -0,0 +1,3 @@
LIBRARY "libwinpr-crypto"
EXPORTS

3
winpr/libwinpr/crypto/test/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
TestCrypto
TestCrypto.c

View File

@ -0,0 +1,35 @@
set(MODULE_NAME "TestCrypto")
set(MODULE_PREFIX "TEST_CRYPTO")
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
set(${MODULE_PREFIX}_TESTS
TestCertEnumCertificatesInStore.c)
create_test_sourcelist(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_DRIVER}
${${MODULE_PREFIX}_TESTS})
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
if(WIN32)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} secur32 crypt32 cryptui)
endif()
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE winpr
MODULES winpr-crt winpr-crypto winpr-utils)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
foreach(test ${${MODULE_PREFIX}_TESTS})
get_filename_component(TestName ${test} NAME_WE)
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
endforeach()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")

View File

@ -0,0 +1,66 @@
#include <winpr/crt.h>
#include <winpr/tchar.h>
#include <winpr/crypto.h>
#ifdef _WIN32
//#define WITH_CRYPTUI 1
#endif
#ifdef WITH_CRYPTUI
#include <cryptuiapi.h>
#endif
int TestCertEnumCertificatesInStore(int argc, char* argv[])
{
int index;
DWORD status;
LPTSTR pszNameString;
HCERTSTORE hCertStore = NULL;
PCCERT_CONTEXT pCertContext = NULL;
/**
* System Store Locations:
* http://msdn.microsoft.com/en-us/library/windows/desktop/aa388136/
*/
/**
* Requires elevated rights:
* hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, (HCRYPTPROV_LEGACY) NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE, _T("Remote Desktop"));
*/
hCertStore = CertOpenSystemStore((HCRYPTPROV_LEGACY) NULL, _T("MY"));
// hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, (HCRYPTPROV_LEGACY) NULL, CERT_SYSTEM_STORE_CURRENT_USER, _T("MY"));
if (!hCertStore)
{
printf("Failed to open system store\n");
return -1;
}
index = 0;
while ((pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext)))
{
status = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0);
pszNameString = (LPTSTR) malloc(status * sizeof(TCHAR));
status = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, status);
_tprintf(_T("Certificate #%d: %s\n"), index++, pszNameString);
#ifdef WITH_CRYPTUI
CryptUIDlgViewContext(CERT_STORE_CERTIFICATE_CONTEXT, pCertContext, NULL, NULL, 0, NULL);
#endif
}
if (!CertCloseStore(hCertStore, 0))
{
printf("Failed to close system store\n");
return -1;
}
return 0;
}

View File

@ -1,5 +1,5 @@
# WinPR: Windows Portable Runtime
# libwinpr-thread cmake build script
# libwinpr-pool cmake build script
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
#

View File

@ -33,6 +33,8 @@ set(${MODULE_PREFIX}_NEGOTIATE_SRCS
Negotiate/negotiate.h)
set(${MODULE_PREFIX}_SCHANNEL_SRCS
Schannel/schannel_openssl.c
Schannel/schannel_openssl.h
Schannel/schannel.c
Schannel/schannel.h)
@ -79,7 +81,7 @@ endif()
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL
MODULE winpr
MODULES winpr-crt winpr-sysinfo winpr-registry winpr-utils)
MODULES winpr-crt winpr-sysinfo winpr-registry winpr-crypto winpr-utils)
if(MONOLITHIC_BUILD)
set(WINPR_LIBS ${WINPR_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE)

View File

@ -133,7 +133,7 @@ NTLM_CONTEXT* ntlm_ContextNew()
* Extended Protection is enabled by default in Windows 7,
* but enabling it in WinPR breaks TS Gateway at this point
*/
context->SuppressExtendedProtection = TRUE;
context->SuppressExtendedProtection = FALSE;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Control\\LSA"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
@ -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

@ -27,6 +27,7 @@
#include <openssl/des.h>
#include <openssl/md4.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/rc4.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
@ -242,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,124 +228,55 @@ void ntlm_free_unicode_string(PUNICODE_STRING string)
* https://raw.github.com/mozilla/mozilla-central/master/extensions/auth/nsAuthSSPI.cpp
*/
/* Certificate (TBSCertificate) */
BYTE test_Certificate[] =
"\x30\x82\x02\xfa\xa0\x03\x02\x01\x02\x02\x10\x33\x1d\x91\x3b\x2b"
"\x0a\xc8\x90\x4a\x19\x35\xed\x79\x65\xb8\xe3\x30\x09\x06\x05\x2b"
"\x0e\x03\x02\x1d\x05\x00\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04"
"\x03\x13\x0b\x4c\x41\x42\x33\x2d\x57\x32\x4b\x38\x52\x32\x30\x1e"
"\x17\x0d\x31\x32\x31\x32\x31\x37\x31\x37\x33\x33\x31\x32\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\x4c\x41\x42\x33\x2d"
"\x57\x32\x4b\x38\x52\x32\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86"
"\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82"
"\x02\x0a\x02\x82\x02\x01\x00\xbf\x99\x68\x59\x41\x06\x5a\xd0\x3a"
"\x38\x7a\xca\x7a\x1e\x85\xee\x21\x7e\xa3\x01\xca\xf5\xdd\x2f\xbc"
"\xf7\x05\x87\x12\x89\x22\xd7\x37\xc1\xe1\x5d\x41\x02\xd8\x60\xc5"
"\x07\xec\x26\x6f\x13\x48\xe1\xf3\xc3\x42\x1e\x71\x5d\x31\x8e\x83"
"\x74\xac\x23\x84\x88\x02\xf4\xa2\x0a\xa8\x41\xfd\x16\x27\x31\x9c"
"\xb6\x78\x08\x84\xfe\x5f\xa1\x9f\x9b\x5c\xe4\x41\xf0\x7f\xb2\x41"
"\xe8\xd7\xf1\xcc\xb5\xd4\x38\x38\x5c\x0b\x64\x4b\x10\x6a\x62\x55"
"\xc1\x4f\xa3\x22\x58\x01\x92\x1c\x09\x68\xec\xe4\xf1\x01\xda\xe3"
"\x6d\x4b\xec\xc2\x9e\xc4\x8e\xc0\x00\x0f\x6e\x07\x7b\xec\x87\x0e"
"\x17\x46\xc7\x84\x78\x78\xd0\x9b\xeb\x86\xca\xd4\x30\x09\xe4\xd5"
"\xb7\x54\xab\xc0\x86\x2c\x7f\x0e\x8f\x00\xda\xd9\xdf\xb3\x56\xbe"
"\xce\xd5\x65\x1b\xe0\xe2\x55\x5a\xd1\xef\xfc\xe6\x20\x3f\x22\xc0"
"\xa6\x88\x63\x00\xa7\x0a\xcb\x73\xf1\x0d\x73\xba\x79\x39\x45\x8d"
"\xa8\x1f\x32\x58\xb1\xb5\x23\xe7\x68\x7d\xc4\x3a\x8f\x44\xa8\x36"
"\xc1\x5d\x0d\xcf\x4a\x21\x0f\x33\x8c\xb4\x57\x9a\x9f\xcb\xc6\xcb"
"\x04\x25\x74\x3a\x91\xaf\xd6\xb5\x35\x94\xa5\xe3\xe1\xa4\x92\x87"
"\xb5\xc7\xd9\x23\x07\xe2\x37\xf3\xb9\x6d\x01\x55\xa2\x39\x65\x8e"
"\xee\xcc\x53\x29\xcb\x1f\x1c\x7e\x7d\x4e\xd6\xfc\xe7\x02\x0a\xba"
"\xdb\xa9\x2d\x74\x9a\xeb\xe0\x95\x50\x23\xcd\xff\xe7\xc4\x47\xc2"
"\x55\x08\xdb\x1b\x0f\xb8\xd4\x4d\x4f\xd7\xd7\x13\x4c\x66\xed\x0f"
"\x78\x7d\x9a\xd5\xb5\xc0\x9e\xf3\xff\xe6\xef\xb7\xea\xd1\xff\xd4"
"\xf7\x09\x92\x15\x3e\x44\xb4\x3e\x01\x29\x06\xf1\x73\xa3\x61\xe8"
"\x84\x7b\x3e\x0d\x12\x44\x73\x4a\x29\x4b\x82\xe3\xac\x64\x81\xa5"
"\xa5\x1d\xa6\xb5\xd6\xc2\xe5\x6f\x98\x3b\x7c\x70\x82\xda\xf9\xf1"
"\xde\x46\x7b\xe8\x9e\x03\xbf\xc7\xb2\xe6\x26\x24\x21\x6c\xb3\x67"
"\xde\xe0\x8c\x17\x93\xf2\x32\xe5\xae\x5e\xfd\x4f\x77\x40\x3e\x25"
"\xfe\xfe\xc0\xd5\xc9\xcd\xff\x8b\xa2\x4e\xae\x89\x12\x0f\x05\xdb"
"\xc5\xba\xc2\x02\x6f\x60\xf8\x91\x23\x99\x29\xb4\x22\x5e\x62\x43"
"\x5e\xde\xb3\x56\x02\x3c\xa2\xf8\x2a\xbf\x82\xf7\x7a\xcc\x2c\x26"
"\x96\x88\x0e\x8d\x65\xb6\x7f\xda\x3c\x52\x6a\x25\xc1\xb2\x89\x5e"
"\x3d\x30\x39\x5f\x11\x74\x3c\x00\xa2\xef\x2c\xff\x3e\xaa\x04\x34"
"\x93\xbd\x55\xc2\x8b\x98\x5b\x66\x9c\x53\x8b\x27\x7c\x4c\x87\x0b"
"\x5b\x24\x72\x08\x06\xf9\x11\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\x8c\x90\xe6\x16\x1e\x1e\xa9\xf3\xbf\x03\x93\x22\xe1\x0c"
"\x3b\xfe\xa1\x18\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13"
"\x0b\x4c\x41\x42\x33\x2d\x57\x32\x4b\x38\x52\x32\x82\x10\x33\x1d"
"\x91\x3b\x2b\x0a\xc8\x90\x4a\x19\x35\xed\x79\x65\xb8\xe3";
/* 544D5750776A7533334736516B4D76694762777548516B41 (MD5 hash of SEC_CHANNEL_BINDINGS) */
BYTE test_ChannelBindingsHash[] = "\x54\x4D\x57\x50\x77\x6A\x75\x33\x33\x47\x36\x51\x6B\x4D\x76\x69\x47\x62\x77\x75\x48\x51\x6B\x41";
/* 63d3533695bf1bd0de203fee9691a2515e2e7bfe75bb8ab09da08911e157847c (SHA-256 hash of Certificate, length = 32) */
BYTE test_CertificateHash_SHA256[] = "\x63\xd3\x53\x36\x95\xbf\x1b\xd0\xde\x20\x3f\xee\x96\x91\xa2\x51\x5e\x2e\x7b\xfe\x75\xbb\x8a\xb0\x9d\xa0\x89\x11\xe1\x57\x84\x7c";
/* c0ef35911b5ba641c4b67f4b32c7efc4c1d82e2b (SHA1 hash of Certificate, length = 20) */
BYTE test_CertificateHash_SHA1[] = "\xc0\xef\x35\x91\x1b\x5b\xa6\x41\xc4\xb6\x7f\x4b\x32\xc7\xef\xc4\xc1\xd8\x2e\x2b";
/* d2b4df88a54faf95590cd336987a97a5 (MD5 hash of Certificate, length = 16) */
BYTE test_CertificateHash_MD5[] = "\xd2\xb4\xdf\x88\xa5\x4f\xaf\x95\x59\x0c\xd3\x36\x98\x7a\x97\xa5";
BYTE* test_CertificateHash = test_CertificateHash_SHA256;
int test_CertificateHashLength = 32;
/*
* Channel Bindings Data:
*
* tls-server-end-point:<binary hash>
typedef struct gss_channel_bindings_struct {
OM_uint32 initiator_addrtype;
gss_buffer_desc initiator_address;
OM_uint32 acceptor_addrtype;
gss_buffer_desc acceptor_address;
gss_buffer_desc application_data;
} *gss_channel_bindings_t;
*/
char TlsServerEndPointPrefix[] = "tls-server-end-point:";
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;
int HashLength;
int PrefixLength;
BYTE* pChannelBindingToken;
int ChannelBindingTokenLength;
BYTE* ChannelBindingToken;
UINT32 ChannelBindingTokenLength;
SEC_CHANNEL_BINDINGS* ChannelBindings;
ZeroMemory(context->ChannelBindingsHash, 16);
ChannelBindings = context->Bindings.Bindings;
HashLength = test_CertificateHashLength;
PrefixLength = strlen(TlsServerEndPointPrefix);
ChannelBindingTokenLength = PrefixLength + HashLength;
context->ChannelBindingToken = (BYTE*) malloc(ChannelBindingTokenLength + 1);
strcpy((char*) context->ChannelBindingToken, TlsServerEndPointPrefix);
CopyMemory(&context->ChannelBindingToken[PrefixLength], test_CertificateHash, HashLength);
if (!ChannelBindings)
return;
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);
MD5_Update(&md5, (void*) context->EndpointBindings.Bindings, context->EndpointBindings.BindingsLength);
MD5_Final(context->ChannelBindingsHash, &md5);
printf("ChannelBindingsHash:\n");
winpr_HexDump(context->ChannelBindingsHash, 16);
#endif
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);
MD5_Update(&md5, (void*) ChannelBindingToken, ChannelBindingTokenLength);
MD5_Final(context->ChannelBindingsHash, &md5);
}
void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)

View File

@ -30,47 +30,17 @@
char* SCHANNEL_PACKAGE_NAME = "Schannel";
SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext,
SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{
return SEC_E_OK;
}
SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext,
SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{
SCHANNEL_CONTEXT* context;
CREDENTIALS* credentials;
context = sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
{
context = schannel_ContextNew();
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
sspi_SecureHandleSetLowerPointer(phNewContext, context);
sspi_SecureHandleSetUpperPointer(phNewContext, (void*) SCHANNEL_PACKAGE_NAME);
}
return SEC_E_OK;
}
SCHANNEL_CONTEXT* schannel_ContextNew()
{
SCHANNEL_CONTEXT* context;
context = (SCHANNEL_CONTEXT*) calloc(1, sizeof(SCHANNEL_CONTEXT));
context = (SCHANNEL_CONTEXT*) malloc(sizeof(SCHANNEL_CONTEXT));
if (context != NULL)
{
ZeroMemory(context, sizeof(SCHANNEL_CONTEXT));
context->openssl = schannel_openssl_new();
}
return context;
@ -81,40 +51,109 @@ void schannel_ContextFree(SCHANNEL_CONTEXT* context)
if (!context)
return;
schannel_openssl_free(context->openssl);
free(context);
}
SECURITY_STATUS SEC_ENTRY schannel_QueryContextAttributes(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
SCHANNEL_CREDENTIALS* schannel_CredentialsNew()
{
if (!phContext)
return SEC_E_INVALID_HANDLE;
SCHANNEL_CREDENTIALS* credentials;
if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY;
credentials = (SCHANNEL_CREDENTIALS*) malloc(sizeof(SCHANNEL_CREDENTIALS));
if (credentials != NULL)
{
ZeroMemory(credentials, sizeof(SCHANNEL_CREDENTIALS));
}
return credentials;
}
void schannel_CredentialsFree(SCHANNEL_CREDENTIALS* credentials)
{
if (!credentials)
return;
free(credentials);
}
static ALG_ID schannel_SupportedAlgs[] =
{
CALG_AES_128, CALG_AES_256, CALG_RC4, CALG_DES, CALG_3DES,
CALG_MD5, CALG_SHA1, CALG_SHA_256, CALG_SHA_384, CALG_SHA_512,
CALG_RSA_SIGN, CALG_DH_EPHEM,
(ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_RESERVED7 | 6), /* what is this? */
CALG_DSS_SIGN, CALG_ECDSA
};
SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
{
if (ulAttribute == SECPKG_ATTR_SUPPORTED_ALGS)
{
PSecPkgCred_SupportedAlgs SupportedAlgs = (PSecPkgCred_SupportedAlgs) pBuffer;
SupportedAlgs->cSupportedAlgs = sizeof(schannel_SupportedAlgs) / sizeof(ALG_ID);
SupportedAlgs->palgSupportedAlgs = (ALG_ID*) schannel_SupportedAlgs;
return SEC_E_OK;
}
else if (ulAttribute == SECPKG_ATTR_CIPHER_STRENGTHS)
{
PSecPkgCred_CipherStrengths CipherStrengths = (PSecPkgCred_CipherStrengths) pBuffer;
CipherStrengths->dwMinimumCipherStrength = 40;
CipherStrengths->dwMaximumCipherStrength = 256;
return SEC_E_OK;
}
else if (ulAttribute == SECPKG_ATTR_SUPPORTED_PROTOCOLS)
{
PSecPkgCred_SupportedProtocols SupportedProtocols = (PSecPkgCred_SupportedProtocols) pBuffer;
/* Observed SupportedProtocols: 0x208A0 */
SupportedProtocols->grbitProtocol = (SP_PROT_CLIENTS | SP_PROT_SERVERS);
return SEC_E_OK;
}
return SEC_E_UNSUPPORTED_FUNCTION;
}
SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
{
return schannel_QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
}
SECURITY_STATUS SEC_ENTRY schannel_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{
return SEC_E_OK;
}
SECURITY_STATUS SEC_ENTRY schannel_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{
CREDENTIALS* credentials;
SEC_WINNT_AUTH_IDENTITY* identity;
SCHANNEL_CREDENTIALS* credentials;
if (fCredentialUse == SECPKG_CRED_OUTBOUND)
{
credentials = sspi_CredentialsNew();
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
SCHANNEL_CRED* cred;
//CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY));
credentials = schannel_CredentialsNew();
credentials->fCredentialUse = fCredentialUse;
cred = (SCHANNEL_CRED*) pAuthData;
if (cred)
{
CopyMemory(&credentials->cred, cred, sizeof(SCHANNEL_CRED));
}
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) SCHANNEL_PACKAGE_NAME);
return SEC_E_OK;
}
else if (fCredentialUse == SECPKG_CRED_INBOUND)
{
credentials = schannel_CredentialsNew();
credentials->fCredentialUse = fCredentialUse;
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) SCHANNEL_PACKAGE_NAME);
@ -125,18 +164,165 @@ SECURITY_STATUS SEC_ENTRY schannel_AcquireCredentialsHandleA(SEC_CHAR* pszPrinci
return SEC_E_OK;
}
SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
SECURITY_STATUS SEC_ENTRY schannel_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{
SECURITY_STATUS status;
SEC_WCHAR* pszPrincipalW = NULL;
SEC_WCHAR* pszPackageW = NULL;
ConvertToUnicode(CP_UTF8, 0, pszPrincipal, -1, &pszPrincipalW, 0);
ConvertToUnicode(CP_UTF8, 0, pszPackage, -1, &pszPackageW, 0);
status = schannel_AcquireCredentialsHandleW(pszPrincipalW, pszPackageW, fCredentialUse, pvLogonID,
pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry);
free(pszPrincipalW);
free(pszPackageW);
return SEC_E_OK;
}
SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
SECURITY_STATUS SEC_ENTRY schannel_FreeCredentialsHandle(PCredHandle phCredential)
{
if (ulAttribute == SECPKG_CRED_ATTR_NAMES)
{
CREDENTIALS* credentials;
SCHANNEL_CREDENTIALS* credentials;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
if (!phCredential)
return SEC_E_INVALID_HANDLE;
credentials = (SCHANNEL_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
if (!credentials)
return SEC_E_INVALID_HANDLE;
schannel_CredentialsFree(credentials);
return SEC_E_OK;
}
SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext,
SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{
SECURITY_STATUS status;
SCHANNEL_CONTEXT* context;
SCHANNEL_CREDENTIALS* credentials;
context = sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
{
context = schannel_ContextNew();
if (!context)
return SEC_E_INSUFFICIENT_MEMORY;
credentials = (SCHANNEL_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
context->server = FALSE;
CopyMemory(&context->cred, &credentials->cred, sizeof(SCHANNEL_CRED));
sspi_SecureHandleSetLowerPointer(phNewContext, context);
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;
}
SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext,
SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{
SECURITY_STATUS status;
SEC_WCHAR* pszTargetNameW = NULL;
if (pszTargetName != NULL)
{
ConvertToUnicode(CP_UTF8, 0, pszTargetName, -1, &pszTargetNameW, 0);
}
status = schannel_InitializeSecurityContextW(phCredential, phContext, pszTargetNameW, fContextReq,
Reserved1, TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
if (pszTargetNameW != NULL)
free(pszTargetNameW);
return status;
}
SECURITY_STATUS SEC_ENTRY schannel_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext,
PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp)
{
SECURITY_STATUS status;
SCHANNEL_CONTEXT* context;
SCHANNEL_CREDENTIALS* credentials;
context = (SCHANNEL_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
{
context = schannel_ContextNew();
if (!context)
return SEC_E_INSUFFICIENT_MEMORY;
credentials = (SCHANNEL_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
context->server = TRUE;
sspi_SecureHandleSetLowerPointer(phNewContext, context);
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;
}
SECURITY_STATUS SEC_ENTRY schannel_DeleteSecurityContext(PCtxtHandle phContext)
{
SCHANNEL_CONTEXT* context;
context = (SCHANNEL_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
return SEC_E_INVALID_HANDLE;
schannel_ContextFree(context);
return SEC_E_OK;
}
SECURITY_STATUS SEC_ENTRY schannel_QueryContextAttributes(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
{
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY;
if (ulAttribute == SECPKG_ATTR_SIZES)
{
SecPkgContext_Sizes* ContextSizes = (SecPkgContext_Sizes*) pBuffer;
ContextSizes->cbMaxToken = 0x6000;
ContextSizes->cbMaxSignature = 16;
ContextSizes->cbBlockSize = 0;
ContextSizes->cbSecurityTrailer = 16;
return SEC_E_OK;
}
@ -144,20 +330,13 @@ SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesA(PCredHandle phCre
return SEC_E_UNSUPPORTED_FUNCTION;
}
SECURITY_STATUS SEC_ENTRY schannel_FreeCredentialsHandle(PCredHandle phCredential)
SECURITY_STATUS SEC_ENTRY schannel_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
{
CREDENTIALS* credentials;
if (!phCredential)
return SEC_E_INVALID_HANDLE;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
if (!credentials)
return SEC_E_INVALID_HANDLE;
sspi_CredentialsFree(credentials);
return SEC_E_OK;
}
SECURITY_STATUS SEC_ENTRY schannel_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP)
{
return SEC_E_OK;
}
@ -171,16 +350,6 @@ SECURITY_STATUS SEC_ENTRY schannel_DecryptMessage(PCtxtHandle phContext, PSecBuf
return SEC_E_OK;
}
SECURITY_STATUS SEC_ENTRY schannel_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
{
return SEC_E_OK;
}
SECURITY_STATUS SEC_ENTRY schannel_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP)
{
return SEC_E_OK;
}
const SecurityFunctionTableA SCHANNEL_SecurityFunctionTableA =
{
1, /* dwVersion */
@ -190,9 +359,9 @@ const SecurityFunctionTableA SCHANNEL_SecurityFunctionTableA =
schannel_FreeCredentialsHandle, /* FreeCredentialsHandle */
NULL, /* Reserved2 */
schannel_InitializeSecurityContextA, /* InitializeSecurityContext */
NULL, /* AcceptSecurityContext */
schannel_AcceptSecurityContext, /* AcceptSecurityContext */
NULL, /* CompleteAuthToken */
NULL, /* DeleteSecurityContext */
schannel_DeleteSecurityContext, /* DeleteSecurityContext */
NULL, /* ApplyControlToken */
schannel_QueryContextAttributes, /* QueryContextAttributes */
NULL, /* ImpersonateSecurityContext */
@ -222,9 +391,9 @@ const SecurityFunctionTableW SCHANNEL_SecurityFunctionTableW =
schannel_FreeCredentialsHandle, /* FreeCredentialsHandle */
NULL, /* Reserved2 */
schannel_InitializeSecurityContextW, /* InitializeSecurityContext */
NULL, /* AcceptSecurityContext */
schannel_AcceptSecurityContext, /* AcceptSecurityContext */
NULL, /* CompleteAuthToken */
NULL, /* DeleteSecurityContext */
schannel_DeleteSecurityContext, /* DeleteSecurityContext */
NULL, /* ApplyControlToken */
schannel_QueryContextAttributes, /* QueryContextAttributes */
NULL, /* ImpersonateSecurityContext */
@ -250,7 +419,7 @@ const SecPkgInfoA SCHANNEL_SecPkgInfoA =
0x000107B3, /* fCapabilities */
1, /* wVersion */
0x000E, /* wRPCID */
0x00006000, /* cbMaxToken */
SCHANNEL_CB_MAX_TOKEN, /* cbMaxToken */
"Schannel", /* Name */
"Schannel Security Package" /* Comment */
};
@ -269,7 +438,7 @@ const SecPkgInfoW SCHANNEL_SecPkgInfoW =
0x000107B3, /* fCapabilities */
1, /* wVersion */
0x000E, /* wRPCID */
0x00006000, /* cbMaxToken */
SCHANNEL_CB_MAX_TOKEN, /* cbMaxToken */
SCHANNEL_SecPkgInfoW_Name, /* Name */
SCHANNEL_SecPkgInfoW_Comment /* Comment */
};

View File

@ -21,12 +21,24 @@
#define WINPR_SSPI_SCHANNEL_PRIVATE_H
#include <winpr/sspi.h>
#include <winpr/schannel.h>
#include "../sspi.h"
#include "schannel_openssl.h"
struct _SCHANNEL_CREDENTIALS
{
SCHANNEL_CRED cred;
ULONG fCredentialUse;
};
typedef struct _SCHANNEL_CREDENTIALS SCHANNEL_CREDENTIALS;
struct _SCHANNEL_CONTEXT
{
BOOL server;
SCHANNEL_CRED cred;
SCHANNEL_OPENSSL* openssl;
};
typedef struct _SCHANNEL_CONTEXT SCHANNEL_CONTEXT;

View File

@ -0,0 +1,376 @@
/**
* WinPR: Windows Portable Runtime
* Schannel Security Package (OpenSSL)
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/sspi.h>
#include <winpr/print.h>
#include "schannel_openssl.h"
char* openssl_get_ssl_error_string(int ssl_error)
{
switch (ssl_error)
{
case SSL_ERROR_ZERO_RETURN:
return "SSL_ERROR_ZERO_RETURN";
case SSL_ERROR_WANT_READ:
return "SSL_ERROR_WANT_READ";
case SSL_ERROR_WANT_WRITE:
return "SSL_ERROR_WANT_WRITE";
case SSL_ERROR_SYSCALL:
return "SSL_ERROR_SYSCALL";
case SSL_ERROR_SSL:
ERR_print_errors_fp(stdout);
return "SSL_ERROR_SSL";
}
return "SSL_ERROR_UNKNOWN";
}
int schannel_openssl_client_init(SCHANNEL_OPENSSL* context)
{
int status;
long options = 0;
context->ctx = SSL_CTX_new(TLSv1_client_method());
if (!context->ctx)
{
printf("SSL_CTX_new failed\n");
return -1;
}
/**
* SSL_OP_NO_COMPRESSION:
*
* The Microsoft RDP server does not advertise support
* for TLS compression, but alternative servers may support it.
* This was observed between early versions of the FreeRDP server
* and the FreeRDP client, and caused major performance issues,
* which is why we're disabling it.
*/
#ifdef SSL_OP_NO_COMPRESSION
options |= SSL_OP_NO_COMPRESSION;
#endif
/**
* SSL_OP_TLS_BLOCK_PADDING_BUG:
*
* The Microsoft RDP server does *not* support TLS padding.
* It absolutely needs to be disabled otherwise it won't work.
*/
options |= SSL_OP_TLS_BLOCK_PADDING_BUG;
/**
* SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS:
*
* Just like TLS padding, the Microsoft RDP server does not
* support empty fragments. This needs to be disabled.
*/
options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
SSL_CTX_set_options(context->ctx, options);
context->ssl = SSL_new(context->ctx);
if (!context->ssl)
{
printf("SSL_new failed\n");
return -1;
}
context->bioRead = BIO_new(BIO_s_mem());
if (!context->bioRead)
{
printf("BIO_new failed\n");
return -1;
}
status = BIO_set_write_buf_size(context->bioRead, SCHANNEL_CB_MAX_TOKEN);
context->bioWrite = BIO_new(BIO_s_mem());
if (!context->bioWrite)
{
printf("BIO_new failed\n");
return -1;
}
status = BIO_set_write_buf_size(context->bioWrite, SCHANNEL_CB_MAX_TOKEN);
status = BIO_make_bio_pair(context->bioRead, context->bioWrite);
SSL_set_bio(context->ssl, context->bioRead, context->bioWrite);
context->ReadBuffer = (BYTE*) malloc(SCHANNEL_CB_MAX_TOKEN);
context->WriteBuffer = (BYTE*) malloc(SCHANNEL_CB_MAX_TOKEN);
return 0;
}
int schannel_openssl_server_init(SCHANNEL_OPENSSL* context)
{
int status;
long options = 0;
context->ctx = SSL_CTX_new(SSLv23_server_method());
if (!context->ctx)
{
printf("SSL_CTX_new failed\n");
return -1;
}
/*
* SSL_OP_NO_SSLv2:
*
* We only want SSLv3 and TLSv1, so disable SSLv2.
* SSLv3 is used by, eg. Microsoft RDC for Mac OS X.
*/
options |= SSL_OP_NO_SSLv2;
/**
* SSL_OP_NO_COMPRESSION:
*
* The Microsoft RDP server does not advertise support
* for TLS compression, but alternative servers may support it.
* This was observed between early versions of the FreeRDP server
* and the FreeRDP client, and caused major performance issues,
* which is why we're disabling it.
*/
#ifdef SSL_OP_NO_COMPRESSION
options |= SSL_OP_NO_COMPRESSION;
#endif
/**
* SSL_OP_TLS_BLOCK_PADDING_BUG:
*
* The Microsoft RDP server does *not* support TLS padding.
* It absolutely needs to be disabled otherwise it won't work.
*/
options |= SSL_OP_TLS_BLOCK_PADDING_BUG;
/**
* SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS:
*
* Just like TLS padding, the Microsoft RDP server does not
* support empty fragments. This needs to be disabled.
*/
options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
SSL_CTX_set_options(context->ctx, options);
context->ssl = SSL_new(context->ctx);
if (!context->ssl)
{
printf("SSL_new failed\n");
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");
return -1;
}
context->bioRead = BIO_new(BIO_s_mem());
if (!context->bioRead)
{
printf("BIO_new failed\n");
return -1;
}
status = BIO_set_write_buf_size(context->bioRead, SCHANNEL_CB_MAX_TOKEN);
context->bioWrite = BIO_new(BIO_s_mem());
if (!context->bioWrite)
{
printf("BIO_new failed\n");
return -1;
}
status = BIO_set_write_buf_size(context->bioWrite, SCHANNEL_CB_MAX_TOKEN);
status = BIO_make_bio_pair(context->bioRead, context->bioWrite);
SSL_set_bio(context->ssl, context->bioRead, context->bioWrite);
context->ReadBuffer = (BYTE*) malloc(SCHANNEL_CB_MAX_TOKEN);
context->WriteBuffer = (BYTE*) malloc(SCHANNEL_CB_MAX_TOKEN);
return 0;
}
SECURITY_STATUS schannel_openssl_client_process_tokens(SCHANNEL_OPENSSL* context, PSecBufferDesc pInput, PSecBufferDesc pOutput)
{
int status;
int ssl_error;
PSecBuffer pBuffer;
if (!context->connected)
{
if (pInput)
{
if (pInput->cBuffers < 1)
return SEC_E_INVALID_TOKEN;
pBuffer = &pInput->pBuffers[0];
if (pBuffer->BufferType != SECBUFFER_TOKEN)
return SEC_E_INVALID_TOKEN;
status = BIO_write(context->bioRead, pBuffer->pvBuffer, pBuffer->cbBuffer);
}
status = SSL_connect(context->ssl);
if (status < 0)
{
ssl_error = SSL_get_error(context->ssl, status);
printf("SSL_connect error: %s\n", openssl_get_ssl_error_string(ssl_error));
}
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];
if (pBuffer->BufferType != SECBUFFER_TOKEN)
return SEC_E_INVALID_TOKEN;
if (pBuffer->cbBuffer < status)
return SEC_E_INSUFFICIENT_MEMORY;
CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status);
pBuffer->cbBuffer = status;
return SEC_I_CONTINUE_NEEDED;
}
return SEC_E_OK;
}
SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context, PSecBufferDesc pInput, PSecBufferDesc pOutput)
{
int status;
int ssl_error;
PSecBuffer pBuffer;
if (!context->connected)
{
if (pInput->cBuffers < 1)
return SEC_E_INVALID_TOKEN;
pBuffer = &pInput->pBuffers[0];
if (pBuffer->BufferType != SECBUFFER_TOKEN)
return SEC_E_INVALID_TOKEN;
printf("Server input: %d\n", pBuffer->cbBuffer);
status = BIO_write(context->bioRead, pBuffer->pvBuffer, pBuffer->cbBuffer);
status = SSL_accept(context->ssl);
if (status < 0)
{
ssl_error = SSL_get_error(context->ssl, status);
printf("SSL_accept error: %s\n", openssl_get_ssl_error_string(ssl_error));
}
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];
if (pBuffer->BufferType != SECBUFFER_TOKEN)
return SEC_E_INVALID_TOKEN;
if (pBuffer->cbBuffer < status)
return SEC_E_INSUFFICIENT_MEMORY;
CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status);
pBuffer->cbBuffer = status;
return SEC_I_CONTINUE_NEEDED;
}
return SEC_E_OK;
}
SCHANNEL_OPENSSL* schannel_openssl_new()
{
SCHANNEL_OPENSSL* context;
context = (SCHANNEL_OPENSSL*) malloc(sizeof(SCHANNEL_OPENSSL));
if (context != NULL)
{
ZeroMemory(context, sizeof(SCHANNEL_OPENSSL));
SSL_load_error_strings();
SSL_library_init();
context->connected = FALSE;
}
return context;
}
void schannel_openssl_free(SCHANNEL_OPENSSL* context)
{
if (context)
{
free(context->ReadBuffer);
free(context->WriteBuffer);
free(context);
}
}

View File

@ -0,0 +1,55 @@
/**
* WinPR: Windows Portable Runtime
* Schannel Security Package (OpenSSL)
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_SSPI_SCHANNEL_OPENSSL_H
#define WINPR_SSPI_SCHANNEL_OPENSSL_H
#include <winpr/sspi.h>
#include "../sspi.h"
/* OpenSSL includes windows.h */
#include <winpr/windows.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/bio.h>
struct _SCHANNEL_OPENSSL
{
SSL* ssl;
SSL_CTX* ctx;
BOOL connected;
BIO* bioRead;
BIO* bioWrite;
BYTE* ReadBuffer;
BYTE* WriteBuffer;
};
typedef struct _SCHANNEL_OPENSSL SCHANNEL_OPENSSL;
int schannel_openssl_client_init(SCHANNEL_OPENSSL* context);
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);
SCHANNEL_OPENSSL* schannel_openssl_new();
void schannel_openssl_free(SCHANNEL_OPENSSL* context);
#endif /* WINPR_SSPI_SCHANNEL_OPENSSL_H */

View File

@ -40,24 +40,31 @@
extern const SecPkgInfoA NTLM_SecPkgInfoA;
extern const SecPkgInfoW NTLM_SecPkgInfoW;
extern const SecPkgInfoA CREDSSP_SecPkgInfoA;
extern const SecPkgInfoW CREDSSP_SecPkgInfoW;
extern const SecurityFunctionTableA NTLM_SecurityFunctionTableA;
extern const SecurityFunctionTableW NTLM_SecurityFunctionTableW;
extern const SecPkgInfoA CREDSSP_SecPkgInfoA;
extern const SecPkgInfoW CREDSSP_SecPkgInfoW;
extern const SecurityFunctionTableA CREDSSP_SecurityFunctionTableA;
extern const SecurityFunctionTableW CREDSSP_SecurityFunctionTableW;
extern const SecPkgInfoA SCHANNEL_SecPkgInfoA;
extern const SecPkgInfoW SCHANNEL_SecPkgInfoW;
extern const SecurityFunctionTableA SCHANNEL_SecurityFunctionTableA;
extern const SecurityFunctionTableW SCHANNEL_SecurityFunctionTableW;
const SecPkgInfoA* SecPkgInfoA_LIST[] =
{
&NTLM_SecPkgInfoA,
&CREDSSP_SecPkgInfoA
&CREDSSP_SecPkgInfoA,
&SCHANNEL_SecPkgInfoA
};
const SecPkgInfoW* SecPkgInfoW_LIST[] =
{
&NTLM_SecPkgInfoW,
&CREDSSP_SecPkgInfoW
&CREDSSP_SecPkgInfoW,
&SCHANNEL_SecPkgInfoW
};
SecurityFunctionTableA SSPI_SecurityFunctionTableA;
@ -80,16 +87,19 @@ typedef struct _SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME;
const SecurityFunctionTableA_NAME SecurityFunctionTableA_NAME_LIST[] =
{
{ "NTLM", &NTLM_SecurityFunctionTableA },
{ "CREDSSP", &CREDSSP_SecurityFunctionTableA }
{ "CREDSSP", &CREDSSP_SecurityFunctionTableA },
{ "Schannel", &SCHANNEL_SecurityFunctionTableA }
};
WCHAR NTLM_NAME_W[] = { 'N','T','L','M','\0' };
WCHAR CREDSSP_NAME_W[] = { 'C','r','e','d','S','S','P','\0' };
WCHAR SCHANNEL_NAME_W[] = { 'S','c','h','a','n','n','e','l','\0' };
const SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME_LIST[] =
{
{ NTLM_NAME_W, &NTLM_SecurityFunctionTableW },
{ CREDSSP_NAME_W, &CREDSSP_SecurityFunctionTableW }
{ CREDSSP_NAME_W, &CREDSSP_SecurityFunctionTableW },
{ SCHANNEL_NAME_W, &SCHANNEL_SecurityFunctionTableW }
};
#endif

View File

@ -22,6 +22,8 @@
#include <winpr/sspi.h>
#define SCHANNEL_CB_MAX_TOKEN 0x00006000
struct _CREDENTIALS
{
SEC_WINNT_AUTH_IDENTITY identity;

View File

@ -8,7 +8,9 @@ set(${MODULE_PREFIX}_TESTS
TestQuerySecurityPackageInfo.c
TestEnumerateSecurityPackages.c
TestInitializeSecurityContext.c
TestAcquireCredentialsHandle.c)
TestAcquireCredentialsHandle.c
TestSchannel.c
TestNTLM.c)
create_test_sourcelist(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_DRIVER}
@ -17,13 +19,13 @@ create_test_sourcelist(${MODULE_PREFIX}_SRCS
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
if(WIN32)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} secur32)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} secur32 crypt32)
endif()
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE winpr
MODULES winpr-sspi)
MODULES winpr-sspi winpr-thread winpr-pipe winpr-file winpr-crypto winpr-utils)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})

View File

@ -0,0 +1,59 @@
#include <winpr/crt.h>
#include <winpr/sspi.h>
BYTE test_Certificate[] =
"\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_Certificate_SHA256Hash[] =
"\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_ChannelBindings_MD5Hash[] =
"\x65\x86\xE9\x9D\x81\xC2\xFC\x98\x4E\x47\x17\x2F\xD4\xDD\x03\x10";
int test_ntlm_channel_binding_token()
{
return 0;
}
int TestNTLM(int argc, char* argv[])
{
if (test_ntlm_channel_binding_token() < 0)
return -1;
return 0;
}

View File

@ -0,0 +1,472 @@
#include <winpr/crt.h>
#include <winpr/sspi.h>
#include <winpr/file.h>
#include <winpr/pipe.h>
#include <winpr/tchar.h>
#include <winpr/print.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/crypto.h>
#include <winpr/schannel.h>
HANDLE g_ClientEvent = NULL;
HANDLE g_ServerEvent = NULL;
BOOL g_ClientWait = FALSE;
BOOL g_ServerWait = FALSE;
HANDLE g_ClientReadPipe = NULL;
HANDLE g_ClientWritePipe = NULL;
HANDLE g_ServerReadPipe = NULL;
HANDLE g_ServerWritePipe = NULL;
static void* schannel_test_server_thread(void* arg)
{
BOOL extraData;
BYTE* lpTokenIn;
BYTE* lpTokenOut;
TimeStamp expiry;
UINT32 cbMaxToken;
UINT32 fContextReq;
ULONG fContextAttr;
SCHANNEL_CRED cred;
CtxtHandle context;
CredHandle credentials;
DWORD cchNameString;
LPTSTR pszNameString;
HCERTSTORE hCertStore;
PCCERT_CONTEXT pCertContext;
PSecBuffer pSecBuffer;
SecBuffer SecBuffer_in[2];
SecBuffer SecBuffer_out[2];
SecBufferDesc SecBufferDesc_in;
SecBufferDesc SecBufferDesc_out;
DWORD NumberOfBytesRead;
SECURITY_STATUS status;
PSecPkgInfo pPackageInfo;
PSecurityFunctionTable table;
DWORD NumberOfBytesWritten;
printf("Starting Server\n");
SecInvalidateHandle(&context);
SecInvalidateHandle(&credentials);
table = InitSecurityInterface();
status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo);
if (status != SEC_E_OK)
{
printf("QuerySecurityPackageInfo failure: 0x%08X\n", status);
return NULL;
}
cbMaxToken = pPackageInfo->cbMaxToken;
hCertStore = CertOpenSystemStore(0, _T("MY"));
if (!hCertStore)
{
printf("Error opening system store\n");
//return NULL;
}
pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL);
if (!pCertContext)
{
printf("Error finding certificate in store\n");
//return NULL;
}
cchNameString = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0);
pszNameString = (LPTSTR) malloc(status * sizeof(TCHAR));
cchNameString = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, cchNameString);
_tprintf(_T("Certificate Name: %s\n"), pszNameString);
ZeroMemory(&cred, sizeof(SCHANNEL_CRED));
cred.dwVersion = SCHANNEL_CRED_VERSION;
cred.cCreds = 1;
cred.paCred = &pCertContext;
cred.cSupportedAlgs = 0;
cred.palgSupportedAlgs = NULL;
cred.grbitEnabledProtocols = SP_PROT_TLS1_SERVER;
cred.dwFlags = SCH_CRED_NO_SYSTEM_MAPPER;
status = table->AcquireCredentialsHandle(NULL, SCHANNEL_NAME,
SECPKG_CRED_INBOUND, NULL, &cred, NULL, NULL, &credentials, NULL);
if (status != SEC_E_OK)
{
printf("AcquireCredentialsHandle failure: 0x%08X\n", status);
return NULL;
}
extraData = FALSE;
lpTokenIn = (BYTE*) malloc(cbMaxToken);
lpTokenOut = (BYTE*) malloc(cbMaxToken);
fContextReq = ASC_REQ_STREAM |
ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT |
ASC_REQ_CONFIDENTIALITY | ASC_REQ_EXTENDED_ERROR;
do
{
if (!extraData)
{
WaitForSingleObject(g_ServerEvent, INFINITE);
ResetEvent(g_ServerEvent);
if (g_ServerWait)
{
if (!ReadFile(g_ServerReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL))
{
printf("Failed to read from server pipe\n");
return NULL;
}
}
else
{
NumberOfBytesRead = 0;
}
}
extraData = FALSE;
printf("Server Received %d bytes:\n", NumberOfBytesRead);
winpr_HexDump(lpTokenIn, NumberOfBytesRead);
SecBuffer_in[0].BufferType = SECBUFFER_TOKEN;
SecBuffer_in[0].pvBuffer = lpTokenIn;
SecBuffer_in[0].cbBuffer = NumberOfBytesRead;
SecBuffer_in[1].BufferType = SECBUFFER_EMPTY;
SecBuffer_in[1].pvBuffer = NULL;
SecBuffer_in[1].cbBuffer = 0;
SecBufferDesc_in.ulVersion = SECBUFFER_VERSION;
SecBufferDesc_in.cBuffers = 2;
SecBufferDesc_in.pBuffers = SecBuffer_in;
SecBuffer_out[0].BufferType = SECBUFFER_TOKEN;
SecBuffer_out[0].pvBuffer = lpTokenOut;
SecBuffer_out[0].cbBuffer = cbMaxToken;
SecBufferDesc_out.ulVersion = SECBUFFER_VERSION;
SecBufferDesc_out.cBuffers = 1;
SecBufferDesc_out.pBuffers = SecBuffer_out;
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))
{
printf("AcceptSecurityContext unexpected status: 0x%08X\n", status);
return NULL;
}
NumberOfBytesWritten = 0;
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");
printf("Server cBuffers: %d pBuffers[0]: %d type: %d\n",
SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType);
printf("Server Input cBuffers: %d pBuffers[1]: %d type: %d\n",
SecBufferDesc_in.cBuffers, SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType);
if (SecBufferDesc_in.pBuffers[1].BufferType == SECBUFFER_EXTRA)
{
printf("AcceptSecurityContext SECBUFFER_EXTRA\n");
pSecBuffer = &SecBufferDesc_in.pBuffers[1];
CopyMemory(lpTokenIn, &lpTokenIn[NumberOfBytesRead - pSecBuffer->cbBuffer], pSecBuffer->cbBuffer);
NumberOfBytesRead = pSecBuffer->cbBuffer;
continue;
}
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))
{
printf("failed to write to client pipe\n");
return NULL;
}
}
else
{
g_ClientWait = FALSE;
SetEvent(g_ClientEvent);
}
printf("Server wrote %d bytes\n", NumberOfBytesWritten);
}
while (1);
return NULL;
}
int TestSchannel(int argc, char* argv[])
{
int index;
ALG_ID algId;
HANDLE thread;
BYTE* lpTokenIn;
BYTE* lpTokenOut;
TimeStamp expiry;
UINT32 cbMaxToken;
SCHANNEL_CRED cred;
UINT32 fContextReq;
ULONG fContextAttr;
CtxtHandle context;
CredHandle credentials;
SECURITY_STATUS status;
PSecPkgInfo pPackageInfo;
PSecBuffer pSecBuffer;
SecBuffer SecBuffer_in[2];
SecBuffer SecBuffer_out[1];
SecBufferDesc SecBufferDesc_in;
SecBufferDesc SecBufferDesc_out;
PSecurityFunctionTable table;
DWORD NumberOfBytesRead;
DWORD NumberOfBytesWritten;
SecPkgCred_SupportedAlgs SupportedAlgs;
SecPkgCred_CipherStrengths CipherStrengths;
SecPkgCred_SupportedProtocols SupportedProtocols;
sspi_GlobalInit();
g_ClientEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
g_ServerEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
SecInvalidateHandle(&context);
SecInvalidateHandle(&credentials);
if (!CreatePipe(&g_ClientReadPipe, &g_ClientWritePipe, NULL, 0))
{
printf("Failed to create client pipe\n");
return -1;
}
if (!CreatePipe(&g_ServerReadPipe, &g_ServerWritePipe, NULL, 0))
{
printf("Failed to create server pipe\n");
return -1;
}
thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) schannel_test_server_thread, NULL, 0, NULL);
table = InitSecurityInterface();
status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo);
if (status != SEC_E_OK)
{
printf("QuerySecurityPackageInfo failure: 0x%08X\n", status);
return -1;
}
cbMaxToken = pPackageInfo->cbMaxToken;
ZeroMemory(&cred, sizeof(SCHANNEL_CRED));
cred.dwVersion = SCHANNEL_CRED_VERSION;
cred.cCreds = 0;
cred.paCred = NULL;
cred.cSupportedAlgs = 0;
cred.palgSupportedAlgs = NULL;
cred.grbitEnabledProtocols = SP_PROT_SSL3TLS1_CLIENTS;
cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS;
cred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
status = table->AcquireCredentialsHandle(NULL, SCHANNEL_NAME,
SECPKG_CRED_OUTBOUND, NULL, &cred, NULL, NULL, &credentials, NULL);
if (status != SEC_E_OK)
{
printf("AcquireCredentialsHandle failure: 0x%08X\n", status);
return -1;
}
ZeroMemory(&SupportedAlgs, sizeof(SecPkgCred_SupportedAlgs));
status = table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_SUPPORTED_ALGS, &SupportedAlgs);
if (status != SEC_E_OK)
{
printf("QueryCredentialsAttributes SECPKG_ATTR_SUPPORTED_ALGS failure: 0x%08X\n", status);
return -1;
}
/**
* SupportedAlgs: 15
* 0x660E 0x6610 0x6801 0x6603 0x6601 0x8003 0x8004
* 0x800C 0x800D 0x800E 0x2400 0xAA02 0xAE06 0x2200 0x2203
*/
printf("SupportedAlgs: %d\n", SupportedAlgs.cSupportedAlgs);
for (index = 0; index < SupportedAlgs.cSupportedAlgs; index++)
{
algId = SupportedAlgs.palgSupportedAlgs[index];
printf("\t0x%04X CLASS: %d TYPE: %d SID: %d\n", algId,
((GET_ALG_CLASS(algId)) >> 13), ((GET_ALG_TYPE(algId)) >> 9), GET_ALG_SID(algId));
}
printf("\n");
ZeroMemory(&CipherStrengths, sizeof(SecPkgCred_CipherStrengths));
status = table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_CIPHER_STRENGTHS, &CipherStrengths);
if (status != SEC_E_OK)
{
printf("QueryCredentialsAttributes SECPKG_ATTR_CIPHER_STRENGTHS failure: 0x%08X\n", status);
return -1;
}
/* CipherStrengths: Minimum: 40 Maximum: 256 */
printf("CipherStrengths: Minimum: %d Maximum: %d\n",
CipherStrengths.dwMinimumCipherStrength, CipherStrengths.dwMaximumCipherStrength);
ZeroMemory(&SupportedProtocols, sizeof(SecPkgCred_SupportedProtocols));
status = table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_SUPPORTED_PROTOCOLS, &SupportedProtocols);
if (status != SEC_E_OK)
{
printf("QueryCredentialsAttributes SECPKG_ATTR_SUPPORTED_PROTOCOLS failure: 0x%08X\n", status);
return -1;
}
/* SupportedProtocols: 0x208A0 */
printf("SupportedProtocols: 0x%04X\n", SupportedProtocols.grbitProtocol);
fContextReq = ISC_REQ_STREAM |
ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR |
ISC_REQ_MANUAL_CRED_VALIDATION | ISC_REQ_INTEGRITY;
lpTokenIn = (BYTE*) malloc(cbMaxToken);
lpTokenOut = (BYTE*) malloc(cbMaxToken);
ZeroMemory(&SecBuffer_in, sizeof(SecBuffer_in));
ZeroMemory(&SecBuffer_out, sizeof(SecBuffer_out));
ZeroMemory(&SecBufferDesc_in, sizeof(SecBufferDesc));
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))
{
printf("failed to read from server pipe\n");
return -1;
}
}
else
{
NumberOfBytesRead = 0;
}
printf("NumberOfBytesRead: %d\n", NumberOfBytesRead);
SecBuffer_in[0].BufferType = SECBUFFER_TOKEN;
SecBuffer_in[0].pvBuffer = lpTokenIn;
SecBuffer_in[0].cbBuffer = NumberOfBytesRead;
SecBuffer_in[1].pvBuffer = NULL;
SecBuffer_in[1].cbBuffer = 0;
SecBuffer_in[1].BufferType = SECBUFFER_EMPTY;
SecBufferDesc_in.ulVersion = SECBUFFER_VERSION;
SecBufferDesc_in.cBuffers = 2;
SecBufferDesc_in.pBuffers = SecBuffer_in;
SecBuffer_out[0].BufferType = SECBUFFER_TOKEN;
SecBuffer_out[0].pvBuffer = lpTokenOut;
SecBuffer_out[0].cbBuffer = cbMaxToken;
SecBufferDesc_out.ulVersion = SECBUFFER_VERSION;
SecBufferDesc_out.cBuffers = 1;
SecBufferDesc_out.pBuffers = SecBuffer_out;
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))
{
printf("InitializeSecurityContext unexpected status: 0x%08X\n", status);
return -1;
}
NumberOfBytesWritten = 0;
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");
printf("Client Output cBuffers: %d pBuffers[0]: %d type: %d\n",
SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType);
printf("Client Input cBuffers: %d pBuffers[1]: %d type: %d\n",
SecBufferDesc_in.cBuffers, SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType);
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))
{
printf("failed to write to server pipe\n");
return -1;
}
}
else
{
g_ServerWait = FALSE;
SetEvent(g_ServerEvent);
}
printf("Client wrote %d bytes\n", NumberOfBytesWritten);
}
while(1);
WaitForSingleObject(thread, INFINITE);
sspi_GlobalFinish();
return 0;
}