vlib.http: schannel cleanup. use ctx struct instead of passing args everywhere
parent
68a4c125c5
commit
5a84a4e507
|
@ -1,9 +1,5 @@
|
|||
#include <vschannel.h>
|
||||
|
||||
|
||||
// TODO: joe-c
|
||||
// create context struct instead of using global
|
||||
|
||||
// Proxy
|
||||
CHAR * psz_proxy_server = "proxy";
|
||||
INT i_proxy_port = 80;
|
||||
|
@ -14,34 +10,36 @@ BOOL use_proxy = FALSE;
|
|||
DWORD protocol = 0;
|
||||
ALG_ID aid_key_exch = 0;
|
||||
|
||||
// Cred store
|
||||
HCERTSTORE cert_store = NULL;
|
||||
SCHANNEL_CRED schannel_cred;
|
||||
|
||||
// Loaded sec lib
|
||||
HMODULE g_hsecurity = NULL;
|
||||
|
||||
// SSPI
|
||||
PSecurityFunctionTable sspi;
|
||||
|
||||
struct TlsContext tls_ctx;
|
||||
|
||||
// TODO: joe-c
|
||||
// socket / tls ctx
|
||||
struct TlsContext {
|
||||
SOCKET Socket;
|
||||
WSADATA WsaData;
|
||||
CredHandle hClientCreds;
|
||||
CtxtHandle hContext;
|
||||
BOOL fCredsInitialized;
|
||||
BOOL fContextInitialized;
|
||||
PCCERT_CONTEXT pRemoteCertContext;
|
||||
// SSPI
|
||||
PSecurityFunctionTable sspi;
|
||||
// Cred store
|
||||
HCERTSTORE cert_store;
|
||||
SCHANNEL_CRED schannel_cred;
|
||||
// Loaded sec lib
|
||||
HMODULE g_hsecurity;
|
||||
// Socket
|
||||
SOCKET socket;
|
||||
WSADATA wsa_data;
|
||||
CredHandle h_client_creds;
|
||||
CtxtHandle h_context;
|
||||
BOOL creds_initialized;
|
||||
BOOL context_initialized;
|
||||
PCCERT_CONTEXT p_pemote_cert_context;
|
||||
};
|
||||
|
||||
struct TlsContext new_tls_context() {
|
||||
return (struct TlsContext) {
|
||||
.Socket = INVALID_SOCKET,
|
||||
.fCredsInitialized = FALSE,
|
||||
.fContextInitialized = FALSE,
|
||||
.pRemoteCertContext = NULL
|
||||
.cert_store = NULL,
|
||||
.g_hsecurity = NULL,
|
||||
.socket = INVALID_SOCKET,
|
||||
.creds_initialized = FALSE,
|
||||
.context_initialized = FALSE,
|
||||
.p_pemote_cert_context = NULL
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -49,22 +47,22 @@ BOOL load_security_library(void) {
|
|||
INIT_SECURITY_INTERFACE pInitSecurityInterface;
|
||||
|
||||
// Load Security DLL
|
||||
g_hsecurity = LoadLibraryA("schannel.dll");
|
||||
if(g_hsecurity == NULL) {
|
||||
tls_ctx.g_hsecurity = LoadLibraryA("schannel.dll");
|
||||
if(tls_ctx.g_hsecurity == NULL) {
|
||||
printf("Error 0x%x loading %s.\n", GetLastError(), "schannel.dll");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pInitSecurityInterface = (INIT_SECURITY_INTERFACE)GetProcAddress(g_hsecurity, "InitSecurityInterfaceA");
|
||||
pInitSecurityInterface = (INIT_SECURITY_INTERFACE)GetProcAddress(tls_ctx.g_hsecurity, "InitSecurityInterfaceA");
|
||||
|
||||
if(pInitSecurityInterface == NULL) {
|
||||
printf("Error 0x%x reading InitSecurityInterface entry point.\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
sspi = pInitSecurityInterface();
|
||||
tls_ctx.sspi = pInitSecurityInterface();
|
||||
|
||||
if(sspi == NULL) {
|
||||
if(tls_ctx.sspi == NULL) {
|
||||
printf("Error 0x%x reading security interface.\n",
|
||||
GetLastError());
|
||||
return FALSE;
|
||||
|
@ -74,40 +72,40 @@ BOOL load_security_library(void) {
|
|||
}
|
||||
|
||||
void unload_security_library(void) {
|
||||
FreeLibrary(g_hsecurity);
|
||||
g_hsecurity = NULL;
|
||||
FreeLibrary(tls_ctx.g_hsecurity);
|
||||
tls_ctx.g_hsecurity = NULL;
|
||||
}
|
||||
|
||||
void vschannel_cleanup() {
|
||||
// Free the server certificate context.
|
||||
if(tls_ctx.pRemoteCertContext) {
|
||||
CertFreeCertificateContext(tls_ctx.pRemoteCertContext);
|
||||
tls_ctx.pRemoteCertContext = NULL;
|
||||
if(tls_ctx.p_pemote_cert_context) {
|
||||
CertFreeCertificateContext(tls_ctx.p_pemote_cert_context);
|
||||
tls_ctx.p_pemote_cert_context = NULL;
|
||||
}
|
||||
|
||||
// Free SSPI context handle.
|
||||
if(tls_ctx.fContextInitialized) {
|
||||
sspi->DeleteSecurityContext(&tls_ctx.hContext);
|
||||
tls_ctx.fContextInitialized = FALSE;
|
||||
if(tls_ctx.context_initialized) {
|
||||
tls_ctx.sspi->DeleteSecurityContext(&tls_ctx.h_context);
|
||||
tls_ctx.context_initialized = FALSE;
|
||||
}
|
||||
|
||||
// Free SSPI credentials handle.
|
||||
if(tls_ctx.fCredsInitialized) {
|
||||
sspi->FreeCredentialsHandle(&tls_ctx.hClientCreds);
|
||||
tls_ctx.fCredsInitialized = FALSE;
|
||||
if(tls_ctx.creds_initialized) {
|
||||
tls_ctx.sspi->FreeCredentialsHandle(&tls_ctx.h_client_creds);
|
||||
tls_ctx.creds_initialized = FALSE;
|
||||
}
|
||||
|
||||
// Close socket.
|
||||
if(tls_ctx.Socket != INVALID_SOCKET) {
|
||||
closesocket(tls_ctx.Socket);
|
||||
if(tls_ctx.socket != INVALID_SOCKET) {
|
||||
closesocket(tls_ctx.socket);
|
||||
}
|
||||
|
||||
// Shutdown WinSock subsystem.
|
||||
WSACleanup();
|
||||
|
||||
// Close "MY" certificate store.
|
||||
if(cert_store) {
|
||||
CertCloseStore(cert_store, 0);
|
||||
if(tls_ctx.cert_store) {
|
||||
CertCloseStore(tls_ctx.cert_store, 0);
|
||||
}
|
||||
|
||||
unload_security_library();
|
||||
|
@ -122,17 +120,17 @@ void vschannel_init() {
|
|||
}
|
||||
|
||||
// Initialize the WinSock subsystem.
|
||||
if(WSAStartup(0x0101, &tls_ctx.WsaData) == SOCKET_ERROR) {
|
||||
if(WSAStartup(0x0101, &tls_ctx.wsa_data) == SOCKET_ERROR) {
|
||||
printf("Error %d returned by WSAStartup\n", GetLastError());
|
||||
vschannel_cleanup();
|
||||
}
|
||||
|
||||
// Create credentials.
|
||||
if(create_credentials(&tls_ctx.hClientCreds)) {
|
||||
if(create_credentials()) {
|
||||
printf("Error creating credentials\n");
|
||||
vschannel_cleanup();
|
||||
}
|
||||
tls_ctx.fCredsInitialized = TRUE;
|
||||
tls_ctx.creds_initialized = TRUE;
|
||||
}
|
||||
|
||||
INT request(CHAR *host, CHAR *req, CHAR *out)
|
||||
|
@ -149,26 +147,26 @@ INT request(CHAR *host, CHAR *req, CHAR *out)
|
|||
protocol = SP_PROT_TLS1_2_CLIENT;
|
||||
|
||||
// Connect to server.
|
||||
if(connect_to_server(host, port_number, &tls_ctx.Socket)) {
|
||||
if(connect_to_server(host, port_number)) {
|
||||
printf("Error connecting to server\n");
|
||||
vschannel_cleanup();
|
||||
return resp_length;
|
||||
}
|
||||
|
||||
// Perform handshake
|
||||
if(perform_client_handshake(tls_ctx.Socket, &tls_ctx.hClientCreds, host, &tls_ctx.hContext, &ExtraData)) {
|
||||
if(perform_client_handshake(host, &ExtraData)) {
|
||||
printf("Error performing handshake\n");
|
||||
vschannel_cleanup();
|
||||
return resp_length;
|
||||
}
|
||||
tls_ctx.fContextInitialized = TRUE;
|
||||
tls_ctx.context_initialized = TRUE;
|
||||
|
||||
// Authenticate server's credentials.
|
||||
|
||||
// Get server's certificate.
|
||||
Status = sspi->QueryContextAttributes(&tls_ctx.hContext,
|
||||
Status = tls_ctx.sspi->QueryContextAttributes(&tls_ctx.h_context,
|
||||
SECPKG_ATTR_REMOTE_CERT_CONTEXT,
|
||||
(PVOID)&tls_ctx.pRemoteCertContext);
|
||||
(PVOID)&tls_ctx.p_pemote_cert_context);
|
||||
if(Status != SEC_E_OK) {
|
||||
printf("Error 0x%x querying remote certificate\n", Status);
|
||||
vschannel_cleanup();
|
||||
|
@ -176,7 +174,7 @@ INT request(CHAR *host, CHAR *req, CHAR *out)
|
|||
}
|
||||
|
||||
// Attempt to validate server certificate.
|
||||
Status = verify_server_certificate(tls_ctx.pRemoteCertContext, host,0);
|
||||
Status = verify_server_certificate(tls_ctx.p_pemote_cert_context, host,0);
|
||||
if(Status) {
|
||||
// The server certificate did not validate correctly. At this
|
||||
// point, we cannot tell if we are connecting to the correct
|
||||
|
@ -191,11 +189,11 @@ INT request(CHAR *host, CHAR *req, CHAR *out)
|
|||
}
|
||||
|
||||
// Free the server certificate context.
|
||||
CertFreeCertificateContext(tls_ctx.pRemoteCertContext);
|
||||
tls_ctx.pRemoteCertContext = NULL;
|
||||
CertFreeCertificateContext(tls_ctx.p_pemote_cert_context);
|
||||
tls_ctx.p_pemote_cert_context = NULL;
|
||||
|
||||
// Request from server
|
||||
if(https_make_request(tls_ctx.Socket, &tls_ctx.hClientCreds, &tls_ctx.hContext, req, out, &resp_length)) {
|
||||
if(https_make_request(req, out, &resp_length)) {
|
||||
vschannel_cleanup();
|
||||
return resp_length;
|
||||
}
|
||||
|
@ -203,19 +201,19 @@ INT request(CHAR *host, CHAR *req, CHAR *out)
|
|||
|
||||
// Send a close_notify alert to the server and
|
||||
// close down the connection.
|
||||
if(disconnect_from_server(tls_ctx.Socket, &tls_ctx.hClientCreds, &tls_ctx.hContext)) {
|
||||
if(disconnect_from_server()) {
|
||||
printf("Error disconnecting from server\n");
|
||||
vschannel_cleanup();
|
||||
return resp_length;
|
||||
}
|
||||
tls_ctx.fContextInitialized = FALSE;
|
||||
tls_ctx.Socket = INVALID_SOCKET;
|
||||
tls_ctx.context_initialized = FALSE;
|
||||
tls_ctx.socket = INVALID_SOCKET;
|
||||
|
||||
return resp_length;
|
||||
}
|
||||
|
||||
|
||||
static SECURITY_STATUS create_credentials(PCredHandle phCreds) {
|
||||
static SECURITY_STATUS create_credentials() {
|
||||
TimeStamp tsExpiry;
|
||||
SECURITY_STATUS Status;
|
||||
|
||||
|
@ -226,10 +224,10 @@ static SECURITY_STATUS create_credentials(PCredHandle phCreds) {
|
|||
|
||||
// Open the "MY" certificate store, which is where Internet Explorer
|
||||
// stores its client certificates.
|
||||
if(cert_store == NULL) {
|
||||
cert_store = CertOpenSystemStore(0, "MY");
|
||||
if(tls_ctx.cert_store == NULL) {
|
||||
tls_ctx.cert_store = CertOpenSystemStore(0, "MY");
|
||||
|
||||
if(!cert_store) {
|
||||
if(!tls_ctx.cert_store) {
|
||||
printf("Error 0x%x returned by CertOpenSystemStore\n",
|
||||
GetLastError());
|
||||
return SEC_E_NO_CREDENTIALS;
|
||||
|
@ -241,16 +239,16 @@ static SECURITY_STATUS create_credentials(PCredHandle phCreds) {
|
|||
// of course). Real applications may wish to specify other parameters
|
||||
// as well.
|
||||
|
||||
ZeroMemory(&schannel_cred, sizeof(schannel_cred));
|
||||
ZeroMemory(&tls_ctx.schannel_cred, sizeof(tls_ctx.schannel_cred));
|
||||
|
||||
schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
|
||||
tls_ctx.schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
|
||||
if(pCertContext)
|
||||
{
|
||||
schannel_cred.cCreds = 1;
|
||||
schannel_cred.paCred = &pCertContext;
|
||||
tls_ctx.schannel_cred.cCreds = 1;
|
||||
tls_ctx.schannel_cred.paCred = &pCertContext;
|
||||
}
|
||||
|
||||
schannel_cred.grbitEnabledProtocols = protocol;
|
||||
tls_ctx.schannel_cred.grbitEnabledProtocols = protocol;
|
||||
|
||||
if(aid_key_exch)
|
||||
{
|
||||
|
@ -259,11 +257,11 @@ static SECURITY_STATUS create_credentials(PCredHandle phCreds) {
|
|||
|
||||
if(cSupportedAlgs)
|
||||
{
|
||||
schannel_cred.cSupportedAlgs = cSupportedAlgs;
|
||||
schannel_cred.palgSupportedAlgs = rgbSupportedAlgs;
|
||||
tls_ctx.schannel_cred.cSupportedAlgs = cSupportedAlgs;
|
||||
tls_ctx.schannel_cred.palgSupportedAlgs = rgbSupportedAlgs;
|
||||
}
|
||||
|
||||
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
|
||||
// this sample verifies the server certificate manually.
|
||||
|
@ -272,19 +270,19 @@ static SECURITY_STATUS create_credentials(PCredHandle phCreds) {
|
|||
// certificate. Applications running on newer versions of Windows can
|
||||
// leave off this flag, in which case the InitializeSecurityContext
|
||||
// function will validate the server certificate automatically.
|
||||
// schannel_cred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
|
||||
// tls_ctx.schannel_cred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
|
||||
|
||||
// Create an SSPI credential.
|
||||
|
||||
Status = sspi->AcquireCredentialsHandle(
|
||||
Status = tls_ctx.sspi->AcquireCredentialsHandle(
|
||||
NULL, // Name of principal
|
||||
UNISP_NAME_A, // Name of package
|
||||
SECPKG_CRED_OUTBOUND, // Flags indicating use
|
||||
NULL, // Pointer to logon ID
|
||||
&schannel_cred, // Package specific data
|
||||
&tls_ctx.schannel_cred, // Package specific data
|
||||
NULL, // Pointer to GetKey() func
|
||||
NULL, // Value to pass to GetKey()
|
||||
phCreds, // (out) Cred Handle
|
||||
&tls_ctx.h_client_creds, // (out) Cred Handle
|
||||
&tsExpiry); // (out) Lifetime (optional)
|
||||
if(Status != SEC_E_OK) {
|
||||
printf("Error 0x%x returned by AcquireCredentialsHandle\n", Status);
|
||||
|
@ -304,7 +302,7 @@ cleanup:
|
|||
}
|
||||
|
||||
|
||||
static INT connect_to_server( CHAR *host, INT port_number, SOCKET *pSocket) {
|
||||
static INT connect_to_server(CHAR *host, INT port_number) {
|
||||
SOCKET Socket;
|
||||
struct sockaddr_in sin;
|
||||
struct hostent *hp;
|
||||
|
@ -381,13 +379,13 @@ static INT connect_to_server( CHAR *host, INT port_number, SOCKET *pSocket) {
|
|||
// should continue to receive until CR LF CR LF is received
|
||||
}
|
||||
|
||||
*pSocket = Socket;
|
||||
tls_ctx.socket = Socket;
|
||||
|
||||
return SEC_E_OK;
|
||||
}
|
||||
|
||||
|
||||
static LONG disconnect_from_server(SOCKET Socket, PCredHandle phCreds, CtxtHandle *phContext) {
|
||||
static LONG disconnect_from_server() {
|
||||
DWORD dwType;
|
||||
PBYTE pbMessage;
|
||||
DWORD cbMessage;
|
||||
|
@ -412,7 +410,7 @@ static LONG disconnect_from_server(SOCKET Socket, PCredHandle phCreds, CtxtHandl
|
|||
OutBuffer.pBuffers = OutBuffers;
|
||||
OutBuffer.ulVersion = SECBUFFER_VERSION;
|
||||
|
||||
Status = sspi->ApplyControlToken(phContext, &OutBuffer);
|
||||
Status = tls_ctx.sspi->ApplyControlToken(&tls_ctx.h_context, &OutBuffer);
|
||||
|
||||
if(FAILED(Status)) {
|
||||
printf("Error 0x%x returned by ApplyControlToken\n", Status);
|
||||
|
@ -436,9 +434,9 @@ static LONG disconnect_from_server(SOCKET Socket, PCredHandle phCreds, CtxtHandl
|
|||
OutBuffer.pBuffers = OutBuffers;
|
||||
OutBuffer.ulVersion = SECBUFFER_VERSION;
|
||||
|
||||
Status = sspi->InitializeSecurityContext(
|
||||
phCreds, phContext, NULL, dwSSPIFlags, 0, SECURITY_NATIVE_DREP,
|
||||
NULL, 0, phContext, &OutBuffer, &dwSSPIOutFlags, &tsExpiry);
|
||||
Status = tls_ctx.sspi->InitializeSecurityContext(
|
||||
&tls_ctx.h_client_creds, &tls_ctx.h_context, NULL, dwSSPIFlags, 0, SECURITY_NATIVE_DREP,
|
||||
NULL, 0, &tls_ctx.h_context, &OutBuffer, &dwSSPIOutFlags, &tsExpiry);
|
||||
|
||||
if(FAILED(Status)) {
|
||||
printf("Error 0x%x returned by InitializeSecurityContext\n", Status);
|
||||
|
@ -451,7 +449,7 @@ static LONG disconnect_from_server(SOCKET Socket, PCredHandle phCreds, CtxtHandl
|
|||
// Send the close notify message to the server.
|
||||
|
||||
if(pbMessage != NULL && cbMessage != 0) {
|
||||
cbData = send(Socket, pbMessage, cbMessage, 0);
|
||||
cbData = send(tls_ctx.socket, pbMessage, cbMessage, 0);
|
||||
if(cbData == SOCKET_ERROR || cbData == 0) {
|
||||
Status = WSAGetLastError();
|
||||
printf("Error %d sending close notify\n", Status);
|
||||
|
@ -459,31 +457,23 @@ static LONG disconnect_from_server(SOCKET Socket, PCredHandle phCreds, CtxtHandl
|
|||
}
|
||||
|
||||
// Free output buffer.
|
||||
sspi->FreeContextBuffer(pbMessage);
|
||||
tls_ctx.sspi->FreeContextBuffer(pbMessage);
|
||||
}
|
||||
|
||||
|
||||
cleanup:
|
||||
|
||||
// Free the security context.
|
||||
sspi->DeleteSecurityContext(phContext);
|
||||
tls_ctx.sspi->DeleteSecurityContext(&tls_ctx.h_context);
|
||||
|
||||
// Close the socket.
|
||||
closesocket(Socket);
|
||||
closesocket(tls_ctx.socket);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
SECURITY_STATUS
|
||||
perform_client_handshake(
|
||||
SOCKET Socket, // in
|
||||
PCredHandle phCreds, // in
|
||||
CHAR * host, // in
|
||||
CtxtHandle * phContext, // out
|
||||
SecBuffer * pExtraData) // out
|
||||
{
|
||||
static SECURITY_STATUS perform_client_handshake(CHAR *host, SecBuffer *pExtraData) {
|
||||
SecBufferDesc OutBuffer;
|
||||
SecBuffer OutBuffers[1];
|
||||
DWORD dwSSPIFlags;
|
||||
|
@ -511,8 +501,8 @@ perform_client_handshake(
|
|||
OutBuffer.pBuffers = OutBuffers;
|
||||
OutBuffer.ulVersion = SECBUFFER_VERSION;
|
||||
|
||||
scRet = sspi->InitializeSecurityContext(
|
||||
phCreds,
|
||||
scRet = tls_ctx.sspi->InitializeSecurityContext(
|
||||
&tls_ctx.h_client_creds,
|
||||
NULL,
|
||||
host,
|
||||
dwSSPIFlags,
|
||||
|
@ -520,7 +510,7 @@ perform_client_handshake(
|
|||
SECURITY_NATIVE_DREP,
|
||||
NULL,
|
||||
0,
|
||||
phContext,
|
||||
&tls_ctx.h_context,
|
||||
&OutBuffer,
|
||||
&dwSSPIOutFlags,
|
||||
&tsExpiry);
|
||||
|
@ -534,30 +524,24 @@ perform_client_handshake(
|
|||
// Send response to server if there is one.
|
||||
if(OutBuffers[0].cbBuffer != 0 && OutBuffers[0].pvBuffer != NULL)
|
||||
{
|
||||
cbData = send(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) {
|
||||
printf("Error %d sending data to server (1)\n", WSAGetLastError());
|
||||
sspi->FreeContextBuffer(OutBuffers[0].pvBuffer);
|
||||
sspi->DeleteSecurityContext(phContext);
|
||||
tls_ctx.sspi->FreeContextBuffer(OutBuffers[0].pvBuffer);
|
||||
tls_ctx.sspi->DeleteSecurityContext(&tls_ctx.h_context);
|
||||
return SEC_E_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
// Free output buffer.
|
||||
sspi->FreeContextBuffer(OutBuffers[0].pvBuffer);
|
||||
tls_ctx.sspi->FreeContextBuffer(OutBuffers[0].pvBuffer);
|
||||
OutBuffers[0].pvBuffer = NULL;
|
||||
}
|
||||
|
||||
return client_handshake_loop(Socket, phCreds, phContext, TRUE, pExtraData);
|
||||
return client_handshake_loop(TRUE, pExtraData);
|
||||
}
|
||||
|
||||
|
||||
static SECURITY_STATUS client_handshake_loop(
|
||||
SOCKET Socket, // in
|
||||
PCredHandle phCreds, // in
|
||||
CtxtHandle * phContext, // in, out
|
||||
BOOL fDoInitialRead, // in
|
||||
SecBuffer * pExtraData) // out
|
||||
{
|
||||
static SECURITY_STATUS client_handshake_loop(BOOL fDoInitialRead, SecBuffer *pExtraData) {
|
||||
SecBufferDesc InBuffer;
|
||||
SecBuffer InBuffers[2];
|
||||
SecBufferDesc OutBuffer;
|
||||
|
@ -608,7 +592,7 @@ static SECURITY_STATUS client_handshake_loop(
|
|||
// Read data from server.
|
||||
if(0 == cbIoBuffer || scRet == SEC_E_INCOMPLETE_MESSAGE) {
|
||||
if(fDoRead) {
|
||||
cbData = recv(Socket,
|
||||
cbData = recv(tls_ctx.socket,
|
||||
IoBuffer + cbIoBuffer,
|
||||
IO_BUFFER_SIZE - cbIoBuffer,
|
||||
0);
|
||||
|
@ -661,8 +645,8 @@ static SECURITY_STATUS client_handshake_loop(
|
|||
|
||||
// Call InitializeSecurityContext.
|
||||
|
||||
scRet = sspi->InitializeSecurityContext(
|
||||
phCreds, phContext, NULL, dwSSPIFlags, 0, SECURITY_NATIVE_DREP,
|
||||
scRet = tls_ctx.sspi->InitializeSecurityContext(
|
||||
&tls_ctx.h_client_creds, &tls_ctx.h_context, NULL, dwSSPIFlags, 0, SECURITY_NATIVE_DREP,
|
||||
&InBuffer, 0, NULL, &OutBuffer, &dwSSPIOutFlags, &tsExpiry);
|
||||
|
||||
// If InitializeSecurityContext was successful (or if the error was
|
||||
|
@ -673,20 +657,20 @@ static SECURITY_STATUS client_handshake_loop(
|
|||
scRet == SEC_I_CONTINUE_NEEDED ||
|
||||
FAILED(scRet) && (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR)) {
|
||||
if(OutBuffers[0].cbBuffer != 0 && OutBuffers[0].pvBuffer != NULL) {
|
||||
cbData = send(Socket,
|
||||
cbData = send(tls_ctx.socket,
|
||||
OutBuffers[0].pvBuffer,
|
||||
OutBuffers[0].cbBuffer,
|
||||
0);
|
||||
if(cbData == SOCKET_ERROR || cbData == 0) {
|
||||
printf("Error %d sending data to server (2)\n",
|
||||
WSAGetLastError());
|
||||
sspi->FreeContextBuffer(OutBuffers[0].pvBuffer);
|
||||
sspi->DeleteSecurityContext(phContext);
|
||||
tls_ctx.sspi->FreeContextBuffer(OutBuffers[0].pvBuffer);
|
||||
tls_ctx.sspi->DeleteSecurityContext(&tls_ctx.h_context);
|
||||
return SEC_E_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
// Free output buffer.
|
||||
sspi->FreeContextBuffer(OutBuffers[0].pvBuffer);
|
||||
tls_ctx.sspi->FreeContextBuffer(OutBuffers[0].pvBuffer);
|
||||
OutBuffers[0].pvBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -753,7 +737,7 @@ static SECURITY_STATUS client_handshake_loop(
|
|||
// we will attempt to connect anonymously (using our current
|
||||
// credentials).
|
||||
|
||||
get_new_client_credentials(phCreds, phContext);
|
||||
get_new_client_credentials();
|
||||
|
||||
// Go around again.
|
||||
fDoRead = FALSE;
|
||||
|
@ -778,7 +762,7 @@ static SECURITY_STATUS client_handshake_loop(
|
|||
|
||||
// Delete the security context in the case of a fatal error.
|
||||
if(FAILED(scRet)) {
|
||||
sspi->DeleteSecurityContext(phContext);
|
||||
tls_ctx.sspi->DeleteSecurityContext(&tls_ctx.h_context);
|
||||
}
|
||||
|
||||
LocalFree(IoBuffer);
|
||||
|
@ -787,7 +771,7 @@ static SECURITY_STATUS client_handshake_loop(
|
|||
}
|
||||
|
||||
|
||||
static SECURITY_STATUS https_make_request(SOCKET Socket, PCredHandle phCreds, CtxtHandle *phContext, CHAR *req, CHAR *out, int *length) {
|
||||
static SECURITY_STATUS https_make_request(CHAR *req, CHAR *out, int *length) {
|
||||
SecPkgContext_StreamSizes Sizes;
|
||||
SECURITY_STATUS scRet;
|
||||
SecBufferDesc Message;
|
||||
|
@ -807,7 +791,7 @@ static SECURITY_STATUS https_make_request(SOCKET Socket, PCredHandle phCreds, Ct
|
|||
|
||||
|
||||
// Read stream encryption properties.
|
||||
scRet = sspi->QueryContextAttributes(phContext, SECPKG_ATTR_STREAM_SIZES, &Sizes);
|
||||
scRet = tls_ctx.sspi->QueryContextAttributes(&tls_ctx.h_context, SECPKG_ATTR_STREAM_SIZES, &Sizes);
|
||||
if(scRet != SEC_E_OK) {
|
||||
printf("Error 0x%x reading SECPKG_ATTR_STREAM_SIZES\n", scRet);
|
||||
return scRet;
|
||||
|
@ -857,7 +841,7 @@ static SECURITY_STATUS https_make_request(SOCKET Socket, PCredHandle phCreds, Ct
|
|||
Message.cBuffers = 4;
|
||||
Message.pBuffers = Buffers;
|
||||
|
||||
scRet = sspi->EncryptMessage(phContext, 0, &Message, 0);
|
||||
scRet = tls_ctx.sspi->EncryptMessage(&tls_ctx.h_context, 0, &Message, 0);
|
||||
|
||||
if(FAILED(scRet)) {
|
||||
printf("Error 0x%x returned by EncryptMessage\n", scRet);
|
||||
|
@ -865,10 +849,10 @@ static SECURITY_STATUS https_make_request(SOCKET Socket, PCredHandle phCreds, Ct
|
|||
}
|
||||
|
||||
// Send the encrypted data to the server.
|
||||
cbData = send(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) {
|
||||
printf("Error %d sending data to server (3)\n", WSAGetLastError());
|
||||
sspi->DeleteSecurityContext(phContext);
|
||||
tls_ctx.sspi->DeleteSecurityContext(&tls_ctx.h_context);
|
||||
return SEC_E_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
|
@ -877,7 +861,7 @@ static SECURITY_STATUS https_make_request(SOCKET Socket, PCredHandle phCreds, Ct
|
|||
while(TRUE){
|
||||
// Read some data.
|
||||
if(0 == cbIoBuffer || scRet == SEC_E_INCOMPLETE_MESSAGE) {
|
||||
cbData = recv(Socket, pbIoBuffer + cbIoBuffer, cbIoBufferLength - cbIoBuffer, 0);
|
||||
cbData = recv(tls_ctx.socket, pbIoBuffer + cbIoBuffer, cbIoBufferLength - cbIoBuffer, 0);
|
||||
if(cbData == SOCKET_ERROR) {
|
||||
printf("Error %d reading data from server\n", WSAGetLastError());
|
||||
scRet = SEC_E_INTERNAL_ERROR;
|
||||
|
@ -912,7 +896,7 @@ static SECURITY_STATUS https_make_request(SOCKET Socket, PCredHandle phCreds, Ct
|
|||
Message.cBuffers = 4;
|
||||
Message.pBuffers = Buffers;
|
||||
|
||||
scRet = sspi->DecryptMessage(phContext, &Message, 0, NULL);
|
||||
scRet = tls_ctx.sspi->DecryptMessage(&tls_ctx.h_context, &Message, 0, NULL);
|
||||
|
||||
if(scRet == SEC_E_INCOMPLETE_MESSAGE) {
|
||||
// The input buffer contains only a fragment of an
|
||||
|
@ -966,7 +950,7 @@ static SECURITY_STATUS https_make_request(SOCKET Socket, PCredHandle phCreds, Ct
|
|||
if(scRet == SEC_I_RENEGOTIATE)
|
||||
{
|
||||
// The server wants to perform another handshake sequence.
|
||||
scRet = client_handshake_loop(Socket, phCreds, phContext, FALSE, &ExtraBuffer);
|
||||
scRet = client_handshake_loop(FALSE, &ExtraBuffer);
|
||||
if(scRet != SEC_E_OK) {
|
||||
return scRet;
|
||||
}
|
||||
|
@ -1082,7 +1066,7 @@ cleanup:
|
|||
}
|
||||
|
||||
|
||||
static void get_new_client_credentials(CredHandle *phCreds, CtxtHandle *phContext) {
|
||||
static void get_new_client_credentials() {
|
||||
CredHandle hCreds;
|
||||
SecPkgContext_IssuerListInfoEx IssuerListInfo;
|
||||
PCCERT_CHAIN_CONTEXT pChainContext;
|
||||
|
@ -1092,7 +1076,7 @@ static void get_new_client_credentials(CredHandle *phCreds, CtxtHandle *phContex
|
|||
SECURITY_STATUS Status;
|
||||
|
||||
// Read list of trusted issuers from schannel.
|
||||
Status = sspi->QueryContextAttributes(phContext, 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) {
|
||||
printf("Error 0x%x querying issuer list info\n", Status);
|
||||
return;
|
||||
|
@ -1112,7 +1096,7 @@ static void get_new_client_credentials(CredHandle *phCreds, CtxtHandle *phContex
|
|||
|
||||
while(TRUE) {
|
||||
// Find a certificate chain.
|
||||
pChainContext = CertFindChainInStore(cert_store,
|
||||
pChainContext = CertFindChainInStore(tls_ctx.cert_store,
|
||||
X509_ASN_ENCODING,
|
||||
0,
|
||||
CERT_CHAIN_FIND_BY_ISSUER,
|
||||
|
@ -1127,16 +1111,16 @@ static void get_new_client_credentials(CredHandle *phCreds, CtxtHandle *phContex
|
|||
pCertContext = pChainContext->rgpChain[0]->rgpElement[0]->pCertContext;
|
||||
|
||||
// Create schannel credential.
|
||||
schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
|
||||
schannel_cred.cCreds = 1;
|
||||
schannel_cred.paCred = &pCertContext;
|
||||
tls_ctx.schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
|
||||
tls_ctx.schannel_cred.cCreds = 1;
|
||||
tls_ctx.schannel_cred.paCred = &pCertContext;
|
||||
|
||||
Status = sspi->AcquireCredentialsHandle(
|
||||
Status = tls_ctx.sspi->AcquireCredentialsHandle(
|
||||
NULL, // Name of principal
|
||||
UNISP_NAME_A, // Name of package
|
||||
SECPKG_CRED_OUTBOUND, // Flags indicating use
|
||||
NULL, // Pointer to logon ID
|
||||
&schannel_cred, // Package specific data
|
||||
&tls_ctx.schannel_cred, // Package specific data
|
||||
NULL, // Pointer to GetKey() func
|
||||
NULL, // Value to pass to GetKey()
|
||||
&hCreds, // (out) Cred Handle
|
||||
|
@ -1147,9 +1131,9 @@ static void get_new_client_credentials(CredHandle *phCreds, CtxtHandle *phContex
|
|||
}
|
||||
|
||||
// Destroy the old credentials.
|
||||
sspi->FreeCredentialsHandle(phCreds);
|
||||
tls_ctx.sspi->FreeCredentialsHandle(&tls_ctx.h_client_creds);
|
||||
|
||||
*phCreds = hCreds;
|
||||
tls_ctx.h_client_creds = hCreds;
|
||||
|
||||
//
|
||||
// As you can see, this sample code maintains a single credential
|
||||
|
|
|
@ -27,26 +27,22 @@ static void vschannel_cleanup();
|
|||
|
||||
static INT request(CHAR *host, CHAR *req, CHAR *out);
|
||||
|
||||
static SECURITY_STATUS create_credentials(PCredHandle phCreds);
|
||||
static SECURITY_STATUS https_make_request(
|
||||
CHAR *req, CHAR *out, int *length);
|
||||
|
||||
static INT connect_to_server(CHAR *host, INT port_number, SOCKET *pSocket);
|
||||
static INT connect_to_server(CHAR *host, INT port_number);
|
||||
|
||||
static LONG disconnect_from_server();
|
||||
|
||||
static SECURITY_STATUS perform_client_handshake(
|
||||
SOCKET Socket, PCredHandle phCreds, CHAR *host,
|
||||
CtxtHandle *phContext, SecBuffer *pExtraData);
|
||||
CHAR *host, SecBuffer *pExtraData);
|
||||
|
||||
static SECURITY_STATUS client_handshake_loop(
|
||||
SOCKET Socket, PCredHandle phCreds, CtxtHandle *phContext,
|
||||
BOOL fDoInitialRead, SecBuffer *pExtraData);
|
||||
|
||||
static SECURITY_STATUS https_make_request(
|
||||
SOCKET Socket, PCredHandle phCreds,
|
||||
CtxtHandle *phContext, CHAR *req, CHAR *out, int *length);
|
||||
|
||||
static DWORD verify_server_certificate(
|
||||
PCCERT_CONTEXT pServerCert, PSTR host, DWORD dwCertFlags);
|
||||
|
||||
static LONG disconnect_from_server(
|
||||
SOCKET Socket, PCredHandle phCreds, CtxtHandle *phContext);
|
||||
static SECURITY_STATUS create_credentials();
|
||||
|
||||
static void get_new_client_credentials(CredHandle *phCreds, CtxtHandle *phContext);
|
||||
static void get_new_client_credentials();
|
Loading…
Reference in New Issue