http: windows - make https requests work in threads
parent
4f62e8235f
commit
cd625b04eb
|
@ -1,5 +1,6 @@
|
||||||
#include <vschannel.h>
|
#include <vschannel.h>
|
||||||
|
|
||||||
|
|
||||||
// Proxy
|
// Proxy
|
||||||
CHAR * psz_proxy_server = "proxy";
|
CHAR * psz_proxy_server = "proxy";
|
||||||
INT i_proxy_port = 80;
|
INT i_proxy_port = 80;
|
||||||
|
@ -26,14 +27,12 @@ struct TlsContext {
|
||||||
WSADATA wsa_data;
|
WSADATA wsa_data;
|
||||||
CredHandle h_client_creds;
|
CredHandle h_client_creds;
|
||||||
CtxtHandle h_context;
|
CtxtHandle h_context;
|
||||||
|
PCCERT_CONTEXT p_pemote_cert_context;
|
||||||
BOOL creds_initialized;
|
BOOL creds_initialized;
|
||||||
BOOL context_initialized;
|
BOOL context_initialized;
|
||||||
PCCERT_CONTEXT p_pemote_cert_context;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TlsContext tls_ctx;
|
TlsContext new_tls_context() {
|
||||||
|
|
||||||
struct TlsContext new_tls_context() {
|
|
||||||
return (struct TlsContext) {
|
return (struct TlsContext) {
|
||||||
.cert_store = NULL,
|
.cert_store = NULL,
|
||||||
.g_hsecurity = NULL,
|
.g_hsecurity = NULL,
|
||||||
|
@ -44,26 +43,26 @@ struct TlsContext new_tls_context() {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
BOOL load_security_library(void) {
|
BOOL load_security_library(TlsContext *tls_ctx) {
|
||||||
INIT_SECURITY_INTERFACE pInitSecurityInterface;
|
INIT_SECURITY_INTERFACE pInitSecurityInterface;
|
||||||
|
|
||||||
// Load Security DLL
|
// Load Security DLL
|
||||||
tls_ctx.g_hsecurity = LoadLibraryA("schannel.dll");
|
tls_ctx->g_hsecurity = LoadLibraryA("schannel.dll");
|
||||||
if(tls_ctx.g_hsecurity == NULL) {
|
if(tls_ctx->g_hsecurity == NULL) {
|
||||||
printf("Error 0x%x loading %s.\n", GetLastError(), "schannel.dll");
|
printf("Error 0x%x loading %s.\n", GetLastError(), "schannel.dll");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
pInitSecurityInterface = (INIT_SECURITY_INTERFACE)GetProcAddress(tls_ctx.g_hsecurity, "InitSecurityInterfaceA");
|
pInitSecurityInterface = (INIT_SECURITY_INTERFACE)GetProcAddress(tls_ctx->g_hsecurity, "InitSecurityInterfaceA");
|
||||||
|
|
||||||
if(pInitSecurityInterface == NULL) {
|
if(pInitSecurityInterface == NULL) {
|
||||||
printf("Error 0x%x reading InitSecurityInterface entry point.\n", GetLastError());
|
printf("Error 0x%x reading InitSecurityInterface entry point.\n", GetLastError());
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
tls_ctx.sspi = pInitSecurityInterface();
|
tls_ctx->sspi = pInitSecurityInterface();
|
||||||
|
|
||||||
if(tls_ctx.sspi == NULL) {
|
if(tls_ctx->sspi == NULL) {
|
||||||
printf("Error 0x%x reading security interface.\n",
|
printf("Error 0x%x reading security interface.\n",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -72,69 +71,67 @@ BOOL load_security_library(void) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unload_security_library(void) {
|
void unload_security_library(TlsContext *tls_ctx) {
|
||||||
FreeLibrary(tls_ctx.g_hsecurity);
|
FreeLibrary(tls_ctx->g_hsecurity);
|
||||||
tls_ctx.g_hsecurity = NULL;
|
tls_ctx->g_hsecurity = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vschannel_cleanup() {
|
void vschannel_cleanup(TlsContext *tls_ctx) {
|
||||||
// Free the server certificate context.
|
// Free the server certificate context.
|
||||||
if(tls_ctx.p_pemote_cert_context) {
|
if(tls_ctx->p_pemote_cert_context) {
|
||||||
CertFreeCertificateContext(tls_ctx.p_pemote_cert_context);
|
CertFreeCertificateContext(tls_ctx->p_pemote_cert_context);
|
||||||
tls_ctx.p_pemote_cert_context = NULL;
|
tls_ctx->p_pemote_cert_context = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free SSPI context handle.
|
// Free SSPI context handle.
|
||||||
if(tls_ctx.context_initialized) {
|
if(tls_ctx->context_initialized) {
|
||||||
tls_ctx.sspi->DeleteSecurityContext(&tls_ctx.h_context);
|
tls_ctx->sspi->DeleteSecurityContext(&tls_ctx->h_context);
|
||||||
tls_ctx.context_initialized = FALSE;
|
tls_ctx->context_initialized = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free SSPI credentials handle.
|
// Free SSPI credentials handle.
|
||||||
if(tls_ctx.creds_initialized) {
|
if(tls_ctx->creds_initialized) {
|
||||||
tls_ctx.sspi->FreeCredentialsHandle(&tls_ctx.h_client_creds);
|
tls_ctx->sspi->FreeCredentialsHandle(&tls_ctx->h_client_creds);
|
||||||
tls_ctx.creds_initialized = FALSE;
|
tls_ctx->creds_initialized = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close socket.
|
// Close socket.
|
||||||
if(tls_ctx.socket != INVALID_SOCKET) {
|
if(tls_ctx->socket != INVALID_SOCKET) {
|
||||||
closesocket(tls_ctx.socket);
|
closesocket(tls_ctx->socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown WinSock subsystem.
|
// Shutdown WinSock subsystem.
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
|
|
||||||
// Close "MY" certificate store.
|
// Close "MY" certificate store.
|
||||||
if(tls_ctx.cert_store) {
|
if(tls_ctx->cert_store) {
|
||||||
CertCloseStore(tls_ctx.cert_store, 0);
|
CertCloseStore(tls_ctx->cert_store, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
unload_security_library();
|
unload_security_library(tls_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vschannel_init() {
|
void vschannel_init(TlsContext *tls_ctx) {
|
||||||
tls_ctx = new_tls_context();
|
if(!load_security_library(tls_ctx)) {
|
||||||
|
|
||||||
if(!load_security_library()) {
|
|
||||||
printf("Error initializing the security library\n");
|
printf("Error initializing the security library\n");
|
||||||
vschannel_cleanup();
|
vschannel_cleanup(tls_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the WinSock subsystem.
|
// Initialize the WinSock subsystem.
|
||||||
if(WSAStartup(0x0101, &tls_ctx.wsa_data) == SOCKET_ERROR) {
|
if(WSAStartup(0x0101, &tls_ctx->wsa_data) == SOCKET_ERROR) {
|
||||||
printf("Error %d returned by WSAStartup\n", GetLastError());
|
printf("Error %d returned by WSAStartup\n", GetLastError());
|
||||||
vschannel_cleanup();
|
vschannel_cleanup(tls_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create credentials.
|
// Create credentials.
|
||||||
if(create_credentials()) {
|
if(create_credentials(tls_ctx)) {
|
||||||
printf("Error creating credentials\n");
|
printf("Error creating credentials\n");
|
||||||
vschannel_cleanup();
|
vschannel_cleanup(tls_ctx);
|
||||||
}
|
}
|
||||||
tls_ctx.creds_initialized = TRUE;
|
tls_ctx->creds_initialized = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
INT request(INT iport, CHAR *host, CHAR *req, CHAR **out)
|
INT request(TlsContext *tls_ctx, INT iport, CHAR *host, CHAR *req, CHAR **out)
|
||||||
{
|
{
|
||||||
SecBuffer ExtraData;
|
SecBuffer ExtraData;
|
||||||
SECURITY_STATUS Status;
|
SECURITY_STATUS Status;
|
||||||
|
@ -150,34 +147,34 @@ INT request(INT iport, CHAR *host, CHAR *req, CHAR **out)
|
||||||
port_number = iport;
|
port_number = iport;
|
||||||
|
|
||||||
// Connect to server.
|
// Connect to server.
|
||||||
if(connect_to_server(host, port_number)) {
|
if(connect_to_server(tls_ctx, host, port_number)) {
|
||||||
printf("Error connecting to server\n");
|
printf("Error connecting to server\n");
|
||||||
vschannel_cleanup();
|
vschannel_cleanup(tls_ctx);
|
||||||
return resp_length;
|
return resp_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform handshake
|
// Perform handshake
|
||||||
if(perform_client_handshake(host, &ExtraData)) {
|
if(perform_client_handshake(tls_ctx, host, &ExtraData)) {
|
||||||
printf("Error performing handshake\n");
|
printf("Error performing handshake\n");
|
||||||
vschannel_cleanup();
|
vschannel_cleanup(tls_ctx);
|
||||||
return resp_length;
|
return resp_length;
|
||||||
}
|
}
|
||||||
tls_ctx.context_initialized = TRUE;
|
tls_ctx->context_initialized = TRUE;
|
||||||
|
|
||||||
// Authenticate server's credentials.
|
// Authenticate server's credentials.
|
||||||
|
|
||||||
// Get server's certificate.
|
// Get server's certificate.
|
||||||
Status = tls_ctx.sspi->QueryContextAttributes(&tls_ctx.h_context,
|
Status = tls_ctx->sspi->QueryContextAttributes(&tls_ctx->h_context,
|
||||||
SECPKG_ATTR_REMOTE_CERT_CONTEXT,
|
SECPKG_ATTR_REMOTE_CERT_CONTEXT,
|
||||||
(PVOID)&tls_ctx.p_pemote_cert_context);
|
(PVOID)&tls_ctx->p_pemote_cert_context);
|
||||||
if(Status != SEC_E_OK) {
|
if(Status != SEC_E_OK) {
|
||||||
printf("Error 0x%x querying remote certificate\n", Status);
|
printf("Error 0x%x querying remote certificate\n", Status);
|
||||||
vschannel_cleanup();
|
vschannel_cleanup(tls_ctx);
|
||||||
return resp_length;
|
return resp_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to validate server certificate.
|
// Attempt to validate server certificate.
|
||||||
Status = verify_server_certificate(tls_ctx.p_pemote_cert_context, host,0);
|
Status = verify_server_certificate(tls_ctx->p_pemote_cert_context, host,0);
|
||||||
if(Status) {
|
if(Status) {
|
||||||
// The server certificate did not validate correctly. At this
|
// The server certificate did not validate correctly. At this
|
||||||
// point, we cannot tell if we are connecting to the correct
|
// point, we cannot tell if we are connecting to the correct
|
||||||
|
@ -187,35 +184,35 @@ INT request(INT iport, CHAR *host, CHAR *req, CHAR **out)
|
||||||
// It is therefore best if we abort the connection.
|
// It is therefore best if we abort the connection.
|
||||||
|
|
||||||
printf("Error 0x%x authenticating server credentials!\n", Status);
|
printf("Error 0x%x authenticating server credentials!\n", Status);
|
||||||
vschannel_cleanup();
|
vschannel_cleanup(tls_ctx);
|
||||||
return resp_length;
|
return resp_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free the server certificate context.
|
// Free the server certificate context.
|
||||||
CertFreeCertificateContext(tls_ctx.p_pemote_cert_context);
|
CertFreeCertificateContext(tls_ctx->p_pemote_cert_context);
|
||||||
tls_ctx.p_pemote_cert_context = NULL;
|
tls_ctx->p_pemote_cert_context = NULL;
|
||||||
|
|
||||||
// Request from server
|
// Request from server
|
||||||
if(https_make_request(req, out, &resp_length)) {
|
if(https_make_request(tls_ctx, req, out, &resp_length)) {
|
||||||
vschannel_cleanup();
|
vschannel_cleanup(tls_ctx);
|
||||||
return resp_length;
|
return resp_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send a close_notify alert to the server and
|
// Send a close_notify alert to the server and
|
||||||
// close down the connection.
|
// close down the connection.
|
||||||
if(disconnect_from_server()) {
|
if(disconnect_from_server(tls_ctx)) {
|
||||||
printf("Error disconnecting from server\n");
|
printf("Error disconnecting from server\n");
|
||||||
vschannel_cleanup();
|
vschannel_cleanup(tls_ctx);
|
||||||
return resp_length;
|
return resp_length;
|
||||||
}
|
}
|
||||||
tls_ctx.context_initialized = FALSE;
|
tls_ctx->context_initialized = FALSE;
|
||||||
tls_ctx.socket = INVALID_SOCKET;
|
tls_ctx->socket = INVALID_SOCKET;
|
||||||
|
|
||||||
return resp_length;
|
return resp_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static SECURITY_STATUS create_credentials() {
|
static SECURITY_STATUS create_credentials(TlsContext *tls_ctx) {
|
||||||
TimeStamp tsExpiry;
|
TimeStamp tsExpiry;
|
||||||
SECURITY_STATUS Status;
|
SECURITY_STATUS Status;
|
||||||
|
|
||||||
|
@ -226,10 +223,10 @@ static SECURITY_STATUS create_credentials() {
|
||||||
|
|
||||||
// Open the "MY" certificate store, which is where Internet Explorer
|
// Open the "MY" certificate store, which is where Internet Explorer
|
||||||
// stores its client certificates.
|
// stores its client certificates.
|
||||||
if(tls_ctx.cert_store == NULL) {
|
if(tls_ctx->cert_store == NULL) {
|
||||||
tls_ctx.cert_store = CertOpenSystemStore(0, "MY");
|
tls_ctx->cert_store = CertOpenSystemStore(0, "MY");
|
||||||
|
|
||||||
if(!tls_ctx.cert_store) {
|
if(!tls_ctx->cert_store) {
|
||||||
printf("Error 0x%x returned by CertOpenSystemStore\n",
|
printf("Error 0x%x returned by CertOpenSystemStore\n",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
return SEC_E_NO_CREDENTIALS;
|
return SEC_E_NO_CREDENTIALS;
|
||||||
|
@ -241,16 +238,16 @@ static SECURITY_STATUS create_credentials() {
|
||||||
// of course). Real applications may wish to specify other parameters
|
// of course). Real applications may wish to specify other parameters
|
||||||
// as well.
|
// as well.
|
||||||
|
|
||||||
ZeroMemory(&tls_ctx.schannel_cred, sizeof(tls_ctx.schannel_cred));
|
ZeroMemory(&tls_ctx->schannel_cred, sizeof(tls_ctx->schannel_cred));
|
||||||
|
|
||||||
tls_ctx.schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
|
tls_ctx->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
|
||||||
if(pCertContext)
|
if(pCertContext)
|
||||||
{
|
{
|
||||||
tls_ctx.schannel_cred.cCreds = 1;
|
tls_ctx->schannel_cred.cCreds = 1;
|
||||||
tls_ctx.schannel_cred.paCred = &pCertContext;
|
tls_ctx->schannel_cred.paCred = &pCertContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
tls_ctx.schannel_cred.grbitEnabledProtocols = protocol;
|
tls_ctx->schannel_cred.grbitEnabledProtocols = protocol;
|
||||||
|
|
||||||
if(aid_key_exch)
|
if(aid_key_exch)
|
||||||
{
|
{
|
||||||
|
@ -259,11 +256,11 @@ static SECURITY_STATUS create_credentials() {
|
||||||
|
|
||||||
if(cSupportedAlgs)
|
if(cSupportedAlgs)
|
||||||
{
|
{
|
||||||
tls_ctx.schannel_cred.cSupportedAlgs = cSupportedAlgs;
|
tls_ctx->schannel_cred.cSupportedAlgs = cSupportedAlgs;
|
||||||
tls_ctx.schannel_cred.palgSupportedAlgs = rgbSupportedAlgs;
|
tls_ctx->schannel_cred.palgSupportedAlgs = rgbSupportedAlgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
tls_ctx.schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
|
tls_ctx->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
|
||||||
|
|
||||||
// The SCH_CRED_MANUAL_CRED_VALIDATION flag is specified because
|
// The SCH_CRED_MANUAL_CRED_VALIDATION flag is specified because
|
||||||
// this sample verifies the server certificate manually.
|
// this sample verifies the server certificate manually.
|
||||||
|
@ -272,19 +269,19 @@ static SECURITY_STATUS create_credentials() {
|
||||||
// certificate. Applications running on newer versions of Windows can
|
// certificate. Applications running on newer versions of Windows can
|
||||||
// leave off this flag, in which case the InitializeSecurityContext
|
// leave off this flag, in which case the InitializeSecurityContext
|
||||||
// function will validate the server certificate automatically.
|
// function will validate the server certificate automatically.
|
||||||
// tls_ctx.schannel_cred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
|
// tls_ctx->schannel_cred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
|
||||||
|
|
||||||
// Create an SSPI credential.
|
// Create an SSPI credential.
|
||||||
|
|
||||||
Status = tls_ctx.sspi->AcquireCredentialsHandle(
|
Status = tls_ctx->sspi->AcquireCredentialsHandle(
|
||||||
NULL, // Name of principal
|
NULL, // Name of principal
|
||||||
UNISP_NAME_A, // Name of package
|
UNISP_NAME_A, // Name of package
|
||||||
SECPKG_CRED_OUTBOUND, // Flags indicating use
|
SECPKG_CRED_OUTBOUND, // Flags indicating use
|
||||||
NULL, // Pointer to logon ID
|
NULL, // Pointer to logon ID
|
||||||
&tls_ctx.schannel_cred, // Package specific data
|
&tls_ctx->schannel_cred, // Package specific data
|
||||||
NULL, // Pointer to GetKey() func
|
NULL, // Pointer to GetKey() func
|
||||||
NULL, // Value to pass to GetKey()
|
NULL, // Value to pass to GetKey()
|
||||||
&tls_ctx.h_client_creds, // (out) Cred Handle
|
&tls_ctx->h_client_creds, // (out) Cred Handle
|
||||||
&tsExpiry); // (out) Lifetime (optional)
|
&tsExpiry); // (out) Lifetime (optional)
|
||||||
if(Status != SEC_E_OK) {
|
if(Status != SEC_E_OK) {
|
||||||
printf("Error 0x%x returned by AcquireCredentialsHandle\n", Status);
|
printf("Error 0x%x returned by AcquireCredentialsHandle\n", Status);
|
||||||
|
@ -304,7 +301,7 @@ cleanup:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static INT connect_to_server(CHAR *host, INT port_number) {
|
static INT connect_to_server(TlsContext *tls_ctx, CHAR *host, INT port_number) {
|
||||||
SOCKET Socket;
|
SOCKET Socket;
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
struct hostent *hp;
|
struct hostent *hp;
|
||||||
|
@ -381,13 +378,13 @@ static INT connect_to_server(CHAR *host, INT port_number) {
|
||||||
// should continue to receive until CR LF CR LF is received
|
// should continue to receive until CR LF CR LF is received
|
||||||
}
|
}
|
||||||
|
|
||||||
tls_ctx.socket = Socket;
|
tls_ctx->socket = Socket;
|
||||||
|
|
||||||
return SEC_E_OK;
|
return SEC_E_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static LONG disconnect_from_server() {
|
static LONG disconnect_from_server(TlsContext *tls_ctx) {
|
||||||
DWORD dwType;
|
DWORD dwType;
|
||||||
PBYTE pbMessage;
|
PBYTE pbMessage;
|
||||||
DWORD cbMessage;
|
DWORD cbMessage;
|
||||||
|
@ -412,7 +409,7 @@ static LONG disconnect_from_server() {
|
||||||
OutBuffer.pBuffers = OutBuffers;
|
OutBuffer.pBuffers = OutBuffers;
|
||||||
OutBuffer.ulVersion = SECBUFFER_VERSION;
|
OutBuffer.ulVersion = SECBUFFER_VERSION;
|
||||||
|
|
||||||
Status = tls_ctx.sspi->ApplyControlToken(&tls_ctx.h_context, &OutBuffer);
|
Status = tls_ctx->sspi->ApplyControlToken(&tls_ctx->h_context, &OutBuffer);
|
||||||
|
|
||||||
if(FAILED(Status)) {
|
if(FAILED(Status)) {
|
||||||
printf("Error 0x%x returned by ApplyControlToken\n", Status);
|
printf("Error 0x%x returned by ApplyControlToken\n", Status);
|
||||||
|
@ -436,9 +433,9 @@ static LONG disconnect_from_server() {
|
||||||
OutBuffer.pBuffers = OutBuffers;
|
OutBuffer.pBuffers = OutBuffers;
|
||||||
OutBuffer.ulVersion = SECBUFFER_VERSION;
|
OutBuffer.ulVersion = SECBUFFER_VERSION;
|
||||||
|
|
||||||
Status = tls_ctx.sspi->InitializeSecurityContext(
|
Status = tls_ctx->sspi->InitializeSecurityContext(
|
||||||
&tls_ctx.h_client_creds, &tls_ctx.h_context, NULL, dwSSPIFlags, 0, SECURITY_NATIVE_DREP,
|
&tls_ctx->h_client_creds, &tls_ctx->h_context, NULL, dwSSPIFlags, 0, SECURITY_NATIVE_DREP,
|
||||||
NULL, 0, &tls_ctx.h_context, &OutBuffer, &dwSSPIOutFlags, &tsExpiry);
|
NULL, 0, &tls_ctx->h_context, &OutBuffer, &dwSSPIOutFlags, &tsExpiry);
|
||||||
|
|
||||||
if(FAILED(Status)) {
|
if(FAILED(Status)) {
|
||||||
printf("Error 0x%x returned by InitializeSecurityContext\n", Status);
|
printf("Error 0x%x returned by InitializeSecurityContext\n", Status);
|
||||||
|
@ -451,7 +448,7 @@ static LONG disconnect_from_server() {
|
||||||
// Send the close notify message to the server.
|
// Send the close notify message to the server.
|
||||||
|
|
||||||
if(pbMessage != NULL && cbMessage != 0) {
|
if(pbMessage != NULL && cbMessage != 0) {
|
||||||
cbData = send(tls_ctx.socket, pbMessage, cbMessage, 0);
|
cbData = send(tls_ctx->socket, pbMessage, cbMessage, 0);
|
||||||
if(cbData == SOCKET_ERROR || cbData == 0) {
|
if(cbData == SOCKET_ERROR || cbData == 0) {
|
||||||
Status = WSAGetLastError();
|
Status = WSAGetLastError();
|
||||||
printf("Error %d sending close notify\n", Status);
|
printf("Error %d sending close notify\n", Status);
|
||||||
|
@ -459,23 +456,23 @@ static LONG disconnect_from_server() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free output buffer.
|
// Free output buffer.
|
||||||
tls_ctx.sspi->FreeContextBuffer(pbMessage);
|
tls_ctx->sspi->FreeContextBuffer(pbMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|
||||||
// Free the security context.
|
// Free the security context.
|
||||||
tls_ctx.sspi->DeleteSecurityContext(&tls_ctx.h_context);
|
tls_ctx->sspi->DeleteSecurityContext(&tls_ctx->h_context);
|
||||||
|
|
||||||
// Close the socket.
|
// Close the socket.
|
||||||
closesocket(tls_ctx.socket);
|
closesocket(tls_ctx->socket);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static SECURITY_STATUS perform_client_handshake(CHAR *host, SecBuffer *pExtraData) {
|
static SECURITY_STATUS perform_client_handshake(TlsContext *tls_ctx, CHAR *host, SecBuffer *pExtraData) {
|
||||||
SecBufferDesc OutBuffer;
|
SecBufferDesc OutBuffer;
|
||||||
SecBuffer OutBuffers[1];
|
SecBuffer OutBuffers[1];
|
||||||
DWORD dwSSPIFlags;
|
DWORD dwSSPIFlags;
|
||||||
|
@ -503,8 +500,8 @@ static SECURITY_STATUS perform_client_handshake(CHAR *host, SecBuffer *pExtraDat
|
||||||
OutBuffer.pBuffers = OutBuffers;
|
OutBuffer.pBuffers = OutBuffers;
|
||||||
OutBuffer.ulVersion = SECBUFFER_VERSION;
|
OutBuffer.ulVersion = SECBUFFER_VERSION;
|
||||||
|
|
||||||
scRet = tls_ctx.sspi->InitializeSecurityContext(
|
scRet = tls_ctx->sspi->InitializeSecurityContext(
|
||||||
&tls_ctx.h_client_creds,
|
&tls_ctx->h_client_creds,
|
||||||
NULL,
|
NULL,
|
||||||
host,
|
host,
|
||||||
dwSSPIFlags,
|
dwSSPIFlags,
|
||||||
|
@ -512,7 +509,7 @@ static SECURITY_STATUS perform_client_handshake(CHAR *host, SecBuffer *pExtraDat
|
||||||
SECURITY_NATIVE_DREP,
|
SECURITY_NATIVE_DREP,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
&tls_ctx.h_context,
|
&tls_ctx->h_context,
|
||||||
&OutBuffer,
|
&OutBuffer,
|
||||||
&dwSSPIOutFlags,
|
&dwSSPIOutFlags,
|
||||||
&tsExpiry);
|
&tsExpiry);
|
||||||
|
@ -526,24 +523,24 @@ static SECURITY_STATUS perform_client_handshake(CHAR *host, SecBuffer *pExtraDat
|
||||||
// Send response to server if there is one.
|
// Send response to server if there is one.
|
||||||
if(OutBuffers[0].cbBuffer != 0 && OutBuffers[0].pvBuffer != NULL)
|
if(OutBuffers[0].cbBuffer != 0 && OutBuffers[0].pvBuffer != NULL)
|
||||||
{
|
{
|
||||||
cbData = send(tls_ctx.socket, OutBuffers[0].pvBuffer, OutBuffers[0].cbBuffer, 0);
|
cbData = send(tls_ctx->socket, OutBuffers[0].pvBuffer, OutBuffers[0].cbBuffer, 0);
|
||||||
if(cbData == SOCKET_ERROR || cbData == 0) {
|
if(cbData == SOCKET_ERROR || cbData == 0) {
|
||||||
printf("Error %d sending data to server (1)\n", WSAGetLastError());
|
printf("Error %d sending data to server (1)\n", WSAGetLastError());
|
||||||
tls_ctx.sspi->FreeContextBuffer(OutBuffers[0].pvBuffer);
|
tls_ctx->sspi->FreeContextBuffer(OutBuffers[0].pvBuffer);
|
||||||
tls_ctx.sspi->DeleteSecurityContext(&tls_ctx.h_context);
|
tls_ctx->sspi->DeleteSecurityContext(&tls_ctx->h_context);
|
||||||
return SEC_E_INTERNAL_ERROR;
|
return SEC_E_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free output buffer.
|
// Free output buffer.
|
||||||
tls_ctx.sspi->FreeContextBuffer(OutBuffers[0].pvBuffer);
|
tls_ctx->sspi->FreeContextBuffer(OutBuffers[0].pvBuffer);
|
||||||
OutBuffers[0].pvBuffer = NULL;
|
OutBuffers[0].pvBuffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return client_handshake_loop(TRUE, pExtraData);
|
return client_handshake_loop(tls_ctx, TRUE, pExtraData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static SECURITY_STATUS client_handshake_loop(BOOL fDoInitialRead, SecBuffer *pExtraData) {
|
static SECURITY_STATUS client_handshake_loop(TlsContext *tls_ctx, BOOL fDoInitialRead, SecBuffer *pExtraData) {
|
||||||
SecBufferDesc InBuffer;
|
SecBufferDesc InBuffer;
|
||||||
SecBuffer InBuffers[2];
|
SecBuffer InBuffers[2];
|
||||||
SecBufferDesc OutBuffer;
|
SecBufferDesc OutBuffer;
|
||||||
|
@ -594,7 +591,7 @@ static SECURITY_STATUS client_handshake_loop(BOOL fDoInitialRead, SecBuffer *pEx
|
||||||
// Read data from server.
|
// Read data from server.
|
||||||
if(0 == cbIoBuffer || scRet == SEC_E_INCOMPLETE_MESSAGE) {
|
if(0 == cbIoBuffer || scRet == SEC_E_INCOMPLETE_MESSAGE) {
|
||||||
if(fDoRead) {
|
if(fDoRead) {
|
||||||
cbData = recv(tls_ctx.socket,
|
cbData = recv(tls_ctx->socket,
|
||||||
IoBuffer + cbIoBuffer,
|
IoBuffer + cbIoBuffer,
|
||||||
IO_BUFFER_SIZE - cbIoBuffer,
|
IO_BUFFER_SIZE - cbIoBuffer,
|
||||||
0);
|
0);
|
||||||
|
@ -647,8 +644,8 @@ static SECURITY_STATUS client_handshake_loop(BOOL fDoInitialRead, SecBuffer *pEx
|
||||||
|
|
||||||
// Call InitializeSecurityContext.
|
// Call InitializeSecurityContext.
|
||||||
|
|
||||||
scRet = tls_ctx.sspi->InitializeSecurityContext(
|
scRet = tls_ctx->sspi->InitializeSecurityContext(
|
||||||
&tls_ctx.h_client_creds, &tls_ctx.h_context, NULL, dwSSPIFlags, 0, SECURITY_NATIVE_DREP,
|
&tls_ctx->h_client_creds, &tls_ctx->h_context, NULL, dwSSPIFlags, 0, SECURITY_NATIVE_DREP,
|
||||||
&InBuffer, 0, NULL, &OutBuffer, &dwSSPIOutFlags, &tsExpiry);
|
&InBuffer, 0, NULL, &OutBuffer, &dwSSPIOutFlags, &tsExpiry);
|
||||||
|
|
||||||
// If InitializeSecurityContext was successful (or if the error was
|
// If InitializeSecurityContext was successful (or if the error was
|
||||||
|
@ -659,20 +656,20 @@ static SECURITY_STATUS client_handshake_loop(BOOL fDoInitialRead, SecBuffer *pEx
|
||||||
scRet == SEC_I_CONTINUE_NEEDED ||
|
scRet == SEC_I_CONTINUE_NEEDED ||
|
||||||
FAILED(scRet) && (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR)) {
|
FAILED(scRet) && (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR)) {
|
||||||
if(OutBuffers[0].cbBuffer != 0 && OutBuffers[0].pvBuffer != NULL) {
|
if(OutBuffers[0].cbBuffer != 0 && OutBuffers[0].pvBuffer != NULL) {
|
||||||
cbData = send(tls_ctx.socket,
|
cbData = send(tls_ctx->socket,
|
||||||
OutBuffers[0].pvBuffer,
|
OutBuffers[0].pvBuffer,
|
||||||
OutBuffers[0].cbBuffer,
|
OutBuffers[0].cbBuffer,
|
||||||
0);
|
0);
|
||||||
if(cbData == SOCKET_ERROR || cbData == 0) {
|
if(cbData == SOCKET_ERROR || cbData == 0) {
|
||||||
printf("Error %d sending data to server (2)\n",
|
printf("Error %d sending data to server (2)\n",
|
||||||
WSAGetLastError());
|
WSAGetLastError());
|
||||||
tls_ctx.sspi->FreeContextBuffer(OutBuffers[0].pvBuffer);
|
tls_ctx->sspi->FreeContextBuffer(OutBuffers[0].pvBuffer);
|
||||||
tls_ctx.sspi->DeleteSecurityContext(&tls_ctx.h_context);
|
tls_ctx->sspi->DeleteSecurityContext(&tls_ctx->h_context);
|
||||||
return SEC_E_INTERNAL_ERROR;
|
return SEC_E_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free output buffer.
|
// Free output buffer.
|
||||||
tls_ctx.sspi->FreeContextBuffer(OutBuffers[0].pvBuffer);
|
tls_ctx->sspi->FreeContextBuffer(OutBuffers[0].pvBuffer);
|
||||||
OutBuffers[0].pvBuffer = NULL;
|
OutBuffers[0].pvBuffer = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -739,7 +736,7 @@ static SECURITY_STATUS client_handshake_loop(BOOL fDoInitialRead, SecBuffer *pEx
|
||||||
// we will attempt to connect anonymously (using our current
|
// we will attempt to connect anonymously (using our current
|
||||||
// credentials).
|
// credentials).
|
||||||
|
|
||||||
get_new_client_credentials();
|
get_new_client_credentials(tls_ctx);
|
||||||
|
|
||||||
// Go around again.
|
// Go around again.
|
||||||
fDoRead = FALSE;
|
fDoRead = FALSE;
|
||||||
|
@ -764,7 +761,7 @@ static SECURITY_STATUS client_handshake_loop(BOOL fDoInitialRead, SecBuffer *pEx
|
||||||
|
|
||||||
// Delete the security context in the case of a fatal error.
|
// Delete the security context in the case of a fatal error.
|
||||||
if(FAILED(scRet)) {
|
if(FAILED(scRet)) {
|
||||||
tls_ctx.sspi->DeleteSecurityContext(&tls_ctx.h_context);
|
tls_ctx->sspi->DeleteSecurityContext(&tls_ctx->h_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalFree(IoBuffer);
|
LocalFree(IoBuffer);
|
||||||
|
@ -773,7 +770,7 @@ static SECURITY_STATUS client_handshake_loop(BOOL fDoInitialRead, SecBuffer *pEx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static SECURITY_STATUS https_make_request(CHAR *req, CHAR **out, int *length) {
|
static SECURITY_STATUS https_make_request(TlsContext *tls_ctx, CHAR *req, CHAR **out, int *length) {
|
||||||
SecPkgContext_StreamSizes Sizes;
|
SecPkgContext_StreamSizes Sizes;
|
||||||
SECURITY_STATUS scRet;
|
SECURITY_STATUS scRet;
|
||||||
SecBufferDesc Message;
|
SecBufferDesc Message;
|
||||||
|
@ -793,7 +790,7 @@ static SECURITY_STATUS https_make_request(CHAR *req, CHAR **out, int *length) {
|
||||||
|
|
||||||
|
|
||||||
// Read stream encryption properties.
|
// Read stream encryption properties.
|
||||||
scRet = tls_ctx.sspi->QueryContextAttributes(&tls_ctx.h_context, SECPKG_ATTR_STREAM_SIZES, &Sizes);
|
scRet = tls_ctx->sspi->QueryContextAttributes(&tls_ctx->h_context, SECPKG_ATTR_STREAM_SIZES, &Sizes);
|
||||||
if(scRet != SEC_E_OK) {
|
if(scRet != SEC_E_OK) {
|
||||||
printf("Error 0x%x reading SECPKG_ATTR_STREAM_SIZES\n", scRet);
|
printf("Error 0x%x reading SECPKG_ATTR_STREAM_SIZES\n", scRet);
|
||||||
return scRet;
|
return scRet;
|
||||||
|
@ -843,7 +840,7 @@ static SECURITY_STATUS https_make_request(CHAR *req, CHAR **out, int *length) {
|
||||||
Message.cBuffers = 4;
|
Message.cBuffers = 4;
|
||||||
Message.pBuffers = Buffers;
|
Message.pBuffers = Buffers;
|
||||||
|
|
||||||
scRet = tls_ctx.sspi->EncryptMessage(&tls_ctx.h_context, 0, &Message, 0);
|
scRet = tls_ctx->sspi->EncryptMessage(&tls_ctx->h_context, 0, &Message, 0);
|
||||||
|
|
||||||
if(FAILED(scRet)) {
|
if(FAILED(scRet)) {
|
||||||
printf("Error 0x%x returned by EncryptMessage\n", scRet);
|
printf("Error 0x%x returned by EncryptMessage\n", scRet);
|
||||||
|
@ -851,10 +848,10 @@ static SECURITY_STATUS https_make_request(CHAR *req, CHAR **out, int *length) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the encrypted data to the server.
|
// Send the encrypted data to the server.
|
||||||
cbData = send(tls_ctx.socket, pbIoBuffer, Buffers[0].cbBuffer + Buffers[1].cbBuffer + Buffers[2].cbBuffer, 0);
|
cbData = send(tls_ctx->socket, pbIoBuffer, Buffers[0].cbBuffer + Buffers[1].cbBuffer + Buffers[2].cbBuffer, 0);
|
||||||
if(cbData == SOCKET_ERROR || cbData == 0) {
|
if(cbData == SOCKET_ERROR || cbData == 0) {
|
||||||
printf("Error %d sending data to server (3)\n", WSAGetLastError());
|
printf("Error %d sending data to server (3)\n", WSAGetLastError());
|
||||||
tls_ctx.sspi->DeleteSecurityContext(&tls_ctx.h_context);
|
tls_ctx->sspi->DeleteSecurityContext(&tls_ctx->h_context);
|
||||||
return SEC_E_INTERNAL_ERROR;
|
return SEC_E_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -864,7 +861,7 @@ static SECURITY_STATUS https_make_request(CHAR *req, CHAR **out, int *length) {
|
||||||
while(TRUE){
|
while(TRUE){
|
||||||
// Read some data.
|
// Read some data.
|
||||||
if(0 == cbIoBuffer || scRet == SEC_E_INCOMPLETE_MESSAGE) {
|
if(0 == cbIoBuffer || scRet == SEC_E_INCOMPLETE_MESSAGE) {
|
||||||
cbData = recv(tls_ctx.socket, pbIoBuffer + cbIoBuffer, cbIoBufferLength - cbIoBuffer, 0);
|
cbData = recv(tls_ctx->socket, pbIoBuffer + cbIoBuffer, cbIoBufferLength - cbIoBuffer, 0);
|
||||||
if(cbData == SOCKET_ERROR) {
|
if(cbData == SOCKET_ERROR) {
|
||||||
printf("Error %d reading data from server\n", WSAGetLastError());
|
printf("Error %d reading data from server\n", WSAGetLastError());
|
||||||
scRet = SEC_E_INTERNAL_ERROR;
|
scRet = SEC_E_INTERNAL_ERROR;
|
||||||
|
@ -899,7 +896,7 @@ static SECURITY_STATUS https_make_request(CHAR *req, CHAR **out, int *length) {
|
||||||
Message.cBuffers = 4;
|
Message.cBuffers = 4;
|
||||||
Message.pBuffers = Buffers;
|
Message.pBuffers = Buffers;
|
||||||
|
|
||||||
scRet = tls_ctx.sspi->DecryptMessage(&tls_ctx.h_context, &Message, 0, NULL);
|
scRet = tls_ctx->sspi->DecryptMessage(&tls_ctx->h_context, &Message, 0, NULL);
|
||||||
|
|
||||||
if(scRet == SEC_E_INCOMPLETE_MESSAGE) {
|
if(scRet == SEC_E_INCOMPLETE_MESSAGE) {
|
||||||
// The input buffer contains only a fragment of an
|
// The input buffer contains only a fragment of an
|
||||||
|
@ -963,7 +960,7 @@ static SECURITY_STATUS https_make_request(CHAR *req, CHAR **out, int *length) {
|
||||||
if(scRet == SEC_I_RENEGOTIATE)
|
if(scRet == SEC_I_RENEGOTIATE)
|
||||||
{
|
{
|
||||||
// The server wants to perform another handshake sequence.
|
// The server wants to perform another handshake sequence.
|
||||||
scRet = client_handshake_loop(FALSE, &ExtraBuffer);
|
scRet = client_handshake_loop(tls_ctx, FALSE, &ExtraBuffer);
|
||||||
if(scRet != SEC_E_OK) {
|
if(scRet != SEC_E_OK) {
|
||||||
return scRet;
|
return scRet;
|
||||||
}
|
}
|
||||||
|
@ -1079,7 +1076,7 @@ cleanup:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void get_new_client_credentials() {
|
static void get_new_client_credentials(TlsContext *tls_ctx) {
|
||||||
CredHandle hCreds;
|
CredHandle hCreds;
|
||||||
SecPkgContext_IssuerListInfoEx IssuerListInfo;
|
SecPkgContext_IssuerListInfoEx IssuerListInfo;
|
||||||
PCCERT_CHAIN_CONTEXT pChainContext;
|
PCCERT_CHAIN_CONTEXT pChainContext;
|
||||||
|
@ -1089,7 +1086,7 @@ static void get_new_client_credentials() {
|
||||||
SECURITY_STATUS Status;
|
SECURITY_STATUS Status;
|
||||||
|
|
||||||
// Read list of trusted issuers from schannel.
|
// Read list of trusted issuers from schannel.
|
||||||
Status = tls_ctx.sspi->QueryContextAttributes(&tls_ctx.h_context, SECPKG_ATTR_ISSUER_LIST_EX, (PVOID)&IssuerListInfo);
|
Status = tls_ctx->sspi->QueryContextAttributes(&tls_ctx->h_context, SECPKG_ATTR_ISSUER_LIST_EX, (PVOID)&IssuerListInfo);
|
||||||
if(Status != SEC_E_OK) {
|
if(Status != SEC_E_OK) {
|
||||||
printf("Error 0x%x querying issuer list info\n", Status);
|
printf("Error 0x%x querying issuer list info\n", Status);
|
||||||
return;
|
return;
|
||||||
|
@ -1109,7 +1106,7 @@ static void get_new_client_credentials() {
|
||||||
|
|
||||||
while(TRUE) {
|
while(TRUE) {
|
||||||
// Find a certificate chain.
|
// Find a certificate chain.
|
||||||
pChainContext = CertFindChainInStore(tls_ctx.cert_store,
|
pChainContext = CertFindChainInStore(tls_ctx->cert_store,
|
||||||
X509_ASN_ENCODING,
|
X509_ASN_ENCODING,
|
||||||
0,
|
0,
|
||||||
CERT_CHAIN_FIND_BY_ISSUER,
|
CERT_CHAIN_FIND_BY_ISSUER,
|
||||||
|
@ -1124,16 +1121,16 @@ static void get_new_client_credentials() {
|
||||||
pCertContext = pChainContext->rgpChain[0]->rgpElement[0]->pCertContext;
|
pCertContext = pChainContext->rgpChain[0]->rgpElement[0]->pCertContext;
|
||||||
|
|
||||||
// Create schannel credential.
|
// Create schannel credential.
|
||||||
tls_ctx.schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
|
tls_ctx->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
|
||||||
tls_ctx.schannel_cred.cCreds = 1;
|
tls_ctx->schannel_cred.cCreds = 1;
|
||||||
tls_ctx.schannel_cred.paCred = &pCertContext;
|
tls_ctx->schannel_cred.paCred = &pCertContext;
|
||||||
|
|
||||||
Status = tls_ctx.sspi->AcquireCredentialsHandle(
|
Status = tls_ctx->sspi->AcquireCredentialsHandle(
|
||||||
NULL, // Name of principal
|
NULL, // Name of principal
|
||||||
UNISP_NAME_A, // Name of package
|
UNISP_NAME_A, // Name of package
|
||||||
SECPKG_CRED_OUTBOUND, // Flags indicating use
|
SECPKG_CRED_OUTBOUND, // Flags indicating use
|
||||||
NULL, // Pointer to logon ID
|
NULL, // Pointer to logon ID
|
||||||
&tls_ctx.schannel_cred, // Package specific data
|
&tls_ctx->schannel_cred, // Package specific data
|
||||||
NULL, // Pointer to GetKey() func
|
NULL, // Pointer to GetKey() func
|
||||||
NULL, // Value to pass to GetKey()
|
NULL, // Value to pass to GetKey()
|
||||||
&hCreds, // (out) Cred Handle
|
&hCreds, // (out) Cred Handle
|
||||||
|
@ -1144,9 +1141,9 @@ static void get_new_client_credentials() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy the old credentials.
|
// Destroy the old credentials.
|
||||||
tls_ctx.sspi->FreeCredentialsHandle(&tls_ctx.h_client_creds);
|
tls_ctx->sspi->FreeCredentialsHandle(&tls_ctx->h_client_creds);
|
||||||
|
|
||||||
tls_ctx.h_client_creds = hCreds;
|
tls_ctx->h_client_creds = hCreds;
|
||||||
|
|
||||||
//
|
//
|
||||||
// As you can see, this sample code maintains a single credential
|
// As you can see, this sample code maintains a single credential
|
||||||
|
|
|
@ -20,31 +20,28 @@
|
||||||
// Define here to be sure
|
// Define here to be sure
|
||||||
#define SP_PROT_TLS1_2_CLIENT 0x00000800
|
#define SP_PROT_TLS1_2_CLIENT 0x00000800
|
||||||
|
|
||||||
|
typedef struct TlsContext TlsContext;
|
||||||
|
|
||||||
static struct TlsContext new_tls_context();
|
TlsContext new_tls_context();
|
||||||
|
|
||||||
static void vschannel_init();
|
static void vschannel_init(TlsContext *tls_ctx);
|
||||||
|
|
||||||
static void vschannel_cleanup();
|
static void vschannel_cleanup(TlsContext *tls_ctx);
|
||||||
|
|
||||||
static INT request(INT iport, CHAR *host, CHAR *req, CHAR **out);
|
static INT request(TlsContext *tls_ctx, INT iport, CHAR *host, CHAR *req, CHAR **out);
|
||||||
|
|
||||||
static SECURITY_STATUS https_make_request(
|
static SECURITY_STATUS https_make_request(TlsContext *tls_ctx, CHAR *req, CHAR **out, int *length);
|
||||||
CHAR *req, CHAR **out, int *length);
|
|
||||||
|
|
||||||
static INT connect_to_server(CHAR *host, INT port_number);
|
static INT connect_to_server(TlsContext *tls_ctx, CHAR *host, INT port_number);
|
||||||
|
|
||||||
static LONG disconnect_from_server();
|
static LONG disconnect_from_server(TlsContext *tls_ctx);
|
||||||
|
|
||||||
static SECURITY_STATUS perform_client_handshake(
|
static SECURITY_STATUS perform_client_handshake(TlsContext *tls_ctx, CHAR *host, SecBuffer *pExtraData);
|
||||||
CHAR *host, SecBuffer *pExtraData);
|
|
||||||
|
|
||||||
static SECURITY_STATUS client_handshake_loop(
|
static SECURITY_STATUS client_handshake_loop(TlsContext *tls_ctx, BOOL fDoInitialRead, SecBuffer *pExtraData);
|
||||||
BOOL fDoInitialRead, SecBuffer *pExtraData);
|
|
||||||
|
|
||||||
static DWORD verify_server_certificate(
|
static DWORD verify_server_certificate(PCCERT_CONTEXT pServerCert, PSTR host, DWORD dwCertFlags);
|
||||||
PCCERT_CONTEXT pServerCert, PSTR host, DWORD dwCertFlags);
|
|
||||||
|
|
||||||
static SECURITY_STATUS create_credentials();
|
static SECURITY_STATUS create_credentials(TlsContext *tls_ctx);
|
||||||
|
|
||||||
static void get_new_client_credentials();
|
static void get_new_client_credentials(TlsContext *tls_ctx);
|
|
@ -4,9 +4,6 @@
|
||||||
|
|
||||||
module http
|
module http
|
||||||
|
|
||||||
import strings
|
|
||||||
import net.urllib
|
|
||||||
|
|
||||||
|
|
||||||
#flag windows -I @VROOT/thirdparty/vschannel
|
#flag windows -I @VROOT/thirdparty/vschannel
|
||||||
#flag -l ws2_32
|
#flag -l ws2_32
|
||||||
|
@ -14,15 +11,19 @@ import net.urllib
|
||||||
|
|
||||||
#include "vschannel.c"
|
#include "vschannel.c"
|
||||||
|
|
||||||
|
fn C.new_tls_context() C.TlsContext
|
||||||
|
|
||||||
fn init_module() {}
|
fn init_module() {}
|
||||||
|
|
||||||
fn (req &Request) ssl_do(port int, method, host_name, path string) Response {
|
fn (req &Request) ssl_do(port int, method, host_name, path string) Response {
|
||||||
C.vschannel_init()
|
mut ctx := C.new_tls_context()
|
||||||
|
C.vschannel_init(&ctx)
|
||||||
|
|
||||||
mut buff := malloc(C.vsc_init_resp_buff_size)
|
mut buff := malloc(C.vsc_init_resp_buff_size)
|
||||||
addr := host_name
|
addr := host_name
|
||||||
sdata := req.build_request_headers(method, host_name, path)
|
sdata := req.build_request_headers(method, host_name, path)
|
||||||
length := int(C.request(port, addr.str, sdata.str, &buff))
|
length := int(C.request(&ctx, port, addr.str, sdata.str, &buff))
|
||||||
|
|
||||||
C.vschannel_cleanup()
|
C.vschannel_cleanup(&ctx)
|
||||||
return parse_response(string(buff, length))
|
return parse_response(string(buff, length))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue