You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-08 14:02:17 +03:00
Fix clang-tidy warnings.
simplify error handling in schannel_certs.c
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
*************************************************************************************/
|
*************************************************************************************/
|
||||||
#include "ma_schannel.h"
|
#include "ma_schannel.h"
|
||||||
#include "schannel_certs.h"
|
#include "schannel_certs.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#pragma comment (lib, "crypt32.lib")
|
#pragma comment (lib, "crypt32.lib")
|
||||||
#pragma comment (lib, "secur32.lib")
|
#pragma comment (lib, "secur32.lib")
|
||||||
@@ -201,7 +202,6 @@ static int ma_tls_set_client_certs(MARIADB_TLS *ctls,const CERT_CONTEXT **cert_c
|
|||||||
MYSQL *mysql= ctls->pvio->mysql;
|
MYSQL *mysql= ctls->pvio->mysql;
|
||||||
char *certfile= mysql->options.ssl_cert,
|
char *certfile= mysql->options.ssl_cert,
|
||||||
*keyfile= mysql->options.ssl_key;
|
*keyfile= mysql->options.ssl_key;
|
||||||
SC_CTX *sctx= (SC_CTX *)ctls->ssl;
|
|
||||||
MARIADB_PVIO *pvio= ctls->pvio;
|
MARIADB_PVIO *pvio= ctls->pvio;
|
||||||
char errmsg[256];
|
char errmsg[256];
|
||||||
|
|
||||||
@@ -295,7 +295,7 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
|
|||||||
size_t i;
|
size_t i;
|
||||||
DWORD protocol = 0;
|
DWORD protocol = 0;
|
||||||
int verify_certs;
|
int verify_certs;
|
||||||
CERT_CONTEXT* cert_context = NULL;
|
const CERT_CONTEXT* cert_context = NULL;
|
||||||
|
|
||||||
if (!ctls)
|
if (!ctls)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -319,10 +319,10 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
|
|||||||
*/
|
*/
|
||||||
for (i = 0; i < sizeof(tls_version) / sizeof(tls_version[0]); i++)
|
for (i = 0; i < sizeof(tls_version) / sizeof(tls_version[0]); i++)
|
||||||
{
|
{
|
||||||
if (!stricmp(mysql->options.ssl_cipher, tls_version[i].tls_version))
|
if (!_stricmp(mysql->options.ssl_cipher, tls_version[i].tls_version))
|
||||||
protocol |= tls_version[i].protocol;
|
protocol |= tls_version[i].protocol;
|
||||||
}
|
}
|
||||||
memset(AlgId, 0, MAX_ALG_ID * sizeof(ALG_ID));
|
memset(AlgId, 0, sizeof(AlgId));
|
||||||
Cred.cSupportedAlgs = (DWORD)set_cipher(mysql->options.ssl_cipher, protocol, AlgId, MAX_ALG_ID);
|
Cred.cSupportedAlgs = (DWORD)set_cipher(mysql->options.ssl_cipher, protocol, AlgId, MAX_ALG_ID);
|
||||||
if (Cred.cSupportedAlgs)
|
if (Cred.cSupportedAlgs)
|
||||||
{
|
{
|
||||||
|
@@ -62,6 +62,14 @@ static DWORD get_last_error()
|
|||||||
assert(0);
|
assert(0);
|
||||||
return ERROR_INTERNAL_ERROR;
|
return ERROR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define FAIL(fmt,...) \
|
||||||
|
{\
|
||||||
|
status = get_last_error();\
|
||||||
|
ma_format_win32_error(errmsg, errmsg_len, status, fmt, __VA_ARGS__);\
|
||||||
|
goto cleanup;\
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Load file into memory. Add null terminator at the end, so it will be a valid C string.
|
Load file into memory. Add null terminator at the end, so it will be a valid C string.
|
||||||
*/
|
*/
|
||||||
@@ -71,33 +79,31 @@ static char* pem_file_to_string(const char* file, char* errmsg, size_t errmsg_le
|
|||||||
size_t file_bufsize = 0;
|
size_t file_bufsize = 0;
|
||||||
size_t total_bytes_read = 0;
|
size_t total_bytes_read = 0;
|
||||||
char* file_buffer = NULL;
|
char* file_buffer = NULL;
|
||||||
|
SECURITY_STATUS status = SEC_E_OK;
|
||||||
|
|
||||||
HANDLE file_handle = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL,
|
HANDLE file_handle = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
if (file_handle == INVALID_HANDLE_VALUE)
|
if (file_handle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
ma_format_win32_error(errmsg, errmsg_len, GetLastError(), "failed to open file '%s'", file);
|
FAIL("failed to open file '%s'", file);
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GetFileSizeEx(file_handle, &file_size))
|
if (!GetFileSizeEx(file_handle, &file_size))
|
||||||
{
|
{
|
||||||
ma_format_win32_error(errmsg, errmsg_len, get_last_error(), "GetFileSizeEx failed on '%s'", file);
|
FAIL("GetFileSizeEx failed on '%s'", file);
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file_size.QuadPart > ULONG_MAX - 1)
|
if (file_size.QuadPart > ULONG_MAX - 1)
|
||||||
{
|
{
|
||||||
snprintf(errmsg, errmsg_len, "file '%s' too large", file);
|
SetLastError(SEC_E_INVALID_PARAMETER);
|
||||||
goto cleanup;
|
FAIL("file '%s' too large", file);
|
||||||
}
|
}
|
||||||
|
|
||||||
file_bufsize = (size_t)file_size.QuadPart;
|
file_bufsize = (size_t)file_size.QuadPart;
|
||||||
file_buffer = (char*)malloc(file_bufsize + 1);
|
file_buffer = (char*)LocalAlloc(0,file_bufsize + 1);
|
||||||
if (!file_buffer)
|
if (!file_buffer)
|
||||||
{
|
{
|
||||||
snprintf(errmsg, errmsg_len, "malloc(%zu) failed, out of memory", file_bufsize + 1);
|
FAIL("LocalAlloc(0,%zu) failed", file_bufsize + 1);
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (total_bytes_read < file_bufsize)
|
while (total_bytes_read < file_bufsize)
|
||||||
@@ -108,9 +114,7 @@ static char* pem_file_to_string(const char* file, char* errmsg, size_t errmsg_le
|
|||||||
if (!ReadFile(file_handle, file_buffer + total_bytes_read,
|
if (!ReadFile(file_handle, file_buffer + total_bytes_read,
|
||||||
bytes_to_read, &bytes_read, NULL))
|
bytes_to_read, &bytes_read, NULL))
|
||||||
{
|
{
|
||||||
ma_format_win32_error(errmsg, errmsg_len, GetLastError(),
|
FAIL("ReadFile() failed to read file '%s'", file);
|
||||||
"ReadFile() failed to read file '%s'", file);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
if (bytes_read == 0)
|
if (bytes_read == 0)
|
||||||
{
|
{
|
||||||
@@ -125,9 +129,18 @@ static char* pem_file_to_string(const char* file, char* errmsg, size_t errmsg_le
|
|||||||
|
|
||||||
/* Null terminate the buffer */
|
/* Null terminate the buffer */
|
||||||
file_buffer[file_bufsize] = '\0';
|
file_buffer[file_bufsize] = '\0';
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (file_handle != INVALID_HANDLE_VALUE)
|
if (file_handle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
CloseHandle(file_handle);
|
CloseHandle(file_handle);
|
||||||
|
}
|
||||||
|
if (status)
|
||||||
|
{
|
||||||
|
/* Some error happened. */
|
||||||
|
LocalFree(file_buffer);
|
||||||
|
file_buffer = NULL;
|
||||||
|
}
|
||||||
return file_buffer;
|
return file_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,7 +227,9 @@ static SECURITY_STATUS add_certs_to_store(
|
|||||||
{
|
{
|
||||||
char* file_buffer = NULL;
|
char* file_buffer = NULL;
|
||||||
char* cur = NULL;
|
char* cur = NULL;
|
||||||
SECURITY_STATUS status = SEC_E_INTERNAL_ERROR;
|
SECURITY_STATUS status = SEC_E_OK;
|
||||||
|
CRL_CONTEXT* crl_context = NULL;
|
||||||
|
CERT_CONTEXT* cert_context = NULL;
|
||||||
char* begin;
|
char* begin;
|
||||||
char* end;
|
char* end;
|
||||||
|
|
||||||
@@ -231,14 +246,12 @@ static SECURITY_STATUS add_certs_to_store(
|
|||||||
|
|
||||||
if (!end)
|
if (!end)
|
||||||
{
|
{
|
||||||
snprintf(errmsg, errmsg_len, "Invalid PEM file '%s',"
|
SetLastError(SEC_E_INVALID_PARAMETER);
|
||||||
"missing end marker corresponding to begin marker '%s' at offset %zu",
|
FAIL("Invalid PEM file '%s', missing end marker corresponding to begin marker '%s' at offset %zu",
|
||||||
file, pem_sections[type].begin_tag, (size_t)(begin - file_buffer));
|
file, pem_sections[type].begin_tag, (size_t)(begin - file_buffer));
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
CERT_BLOB cert_blob;
|
CERT_BLOB cert_blob;
|
||||||
void* context = NULL;
|
void* context = NULL;
|
||||||
int add_cert_result = FALSE;
|
|
||||||
DWORD actual_content_type = 0;
|
DWORD actual_content_type = 0;
|
||||||
|
|
||||||
cert_blob.pbData = (BYTE*)begin;
|
cert_blob.pbData = (BYTE*)begin;
|
||||||
@@ -249,58 +262,44 @@ static SECURITY_STATUS add_certs_to_store(
|
|||||||
CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, &actual_content_type,
|
CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, &actual_content_type,
|
||||||
NULL, NULL, NULL, (const void**)&context))
|
NULL, NULL, NULL, (const void**)&context))
|
||||||
{
|
{
|
||||||
ma_format_win32_error(errmsg, errmsg_len, GetLastError(),
|
FAIL("failed to extract certificate from PEM file '%s'",file);
|
||||||
"failed to extract certificate from PEM file '%s'",
|
|
||||||
file);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!context)
|
if (!context)
|
||||||
{
|
{
|
||||||
ma_format_win32_error(errmsg, errmsg_len, 0,
|
SetLastError(SEC_E_INTERNAL_ERROR);
|
||||||
"unexpected result from CryptQueryObject(),cert_context is NULL"
|
FAIL("unexpected result from CryptQueryObject(),cert_context is NULL"
|
||||||
" after successful completion, file '%s'",
|
" after successful completion, file '%s'",
|
||||||
file);
|
file);
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actual_content_type == CERT_QUERY_CONTENT_CERT)
|
if (actual_content_type == CERT_QUERY_CONTENT_CERT)
|
||||||
{
|
{
|
||||||
CERT_CONTEXT* cert_context = (CERT_CONTEXT*)context;
|
CERT_CONTEXT* cert_context = (CERT_CONTEXT*)context;
|
||||||
BOOL ok = CertAddCertificateContextToStore(
|
if (!CertAddCertificateContextToStore(
|
||||||
trust_store, cert_context,
|
trust_store, cert_context,
|
||||||
CERT_STORE_ADD_ALWAYS, NULL);
|
CERT_STORE_ADD_ALWAYS, NULL))
|
||||||
if (!ok)
|
|
||||||
status = get_last_error();
|
|
||||||
CertFreeCertificateContext(cert_context);
|
|
||||||
if (!ok)
|
|
||||||
{
|
{
|
||||||
status = get_last_error();
|
FAIL("CertAddCertificateContextToStore failed");
|
||||||
ma_format_win32_error(errmsg, errmsg_len, get_last_error(),
|
|
||||||
"CertAddCertificateContextToStore failed");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (actual_content_type == CERT_QUERY_CONTENT_CRL)
|
else if (actual_content_type == CERT_QUERY_CONTENT_CRL)
|
||||||
{
|
{
|
||||||
CRL_CONTEXT* crl_context = (CRL_CONTEXT*)context;
|
CRL_CONTEXT* crl_context = (CRL_CONTEXT*)context;
|
||||||
BOOL ok = CertAddCRLContextToStore(
|
if (!CertAddCRLContextToStore(
|
||||||
trust_store, crl_context,
|
trust_store, crl_context,
|
||||||
CERT_STORE_ADD_ALWAYS, NULL);
|
CERT_STORE_ADD_ALWAYS, NULL))
|
||||||
if (!ok)
|
|
||||||
status = get_last_error();
|
|
||||||
CertFreeCRLContext(crl_context);
|
|
||||||
if (!ok)
|
|
||||||
{
|
{
|
||||||
ma_format_win32_error(errmsg, errmsg_len, status, "CertAddCRLContextToStore() failed");
|
FAIL("CertAddCRLContextToStore() failed");
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
status = SEC_E_OK;
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
free(file_buffer);
|
LocalFree(file_buffer);
|
||||||
|
if (cert_context)
|
||||||
|
CertFreeCertificateContext(cert_context);
|
||||||
|
if (crl_context)
|
||||||
|
CertFreeCRLContext(crl_context);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,38 +316,41 @@ SECURITY_STATUS add_dir_to_store(HCERTSTORE trust_store, const char* dir,
|
|||||||
char path[MAX_PATH];
|
char path[MAX_PATH];
|
||||||
char pattern[MAX_PATH];
|
char pattern[MAX_PATH];
|
||||||
DWORD dwAttr;
|
DWORD dwAttr;
|
||||||
HANDLE hFind;
|
HANDLE hFind = INVALID_HANDLE_VALUE;
|
||||||
SECURITY_STATUS status = SEC_E_INTERNAL_ERROR;
|
SECURITY_STATUS status = SEC_E_OK;
|
||||||
|
|
||||||
if ((dwAttr = GetFileAttributes(dir)) == INVALID_FILE_ATTRIBUTES)
|
if ((dwAttr = GetFileAttributes(dir)) == INVALID_FILE_ATTRIBUTES)
|
||||||
{
|
{
|
||||||
ma_format_win32_error(errmsg, errmsg_len, 0, "invalid directory '%s'", dir);
|
SetLastError(SEC_E_INVALID_PARAMETER);
|
||||||
return status;
|
FAIL("directory '%s' does not exist", dir);
|
||||||
}
|
}
|
||||||
if (!(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
|
if (!(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
|
||||||
{
|
{
|
||||||
ma_format_win32_error(errmsg, errmsg_len, 0, "'%s' is not a directory", dir);
|
SetLastError(SEC_E_INVALID_PARAMETER);
|
||||||
return status;
|
FAIL("'%s' is not a directory", dir);
|
||||||
}
|
}
|
||||||
snprintf(pattern, sizeof(pattern), "%s\\*", dir);
|
sprintf_s(pattern, sizeof(pattern), "%s\\*", dir);
|
||||||
hFind = FindFirstFile(pattern, &ffd);
|
hFind = FindFirstFile(pattern, &ffd);
|
||||||
if (hFind == INVALID_HANDLE_VALUE)
|
if (hFind == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
ma_format_win32_error(errmsg, errmsg_len, GetLastError(), "FindFirstFile(%s) failed", pattern);
|
FAIL("FindFirstFile(%s) failed",pattern);
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
continue;
|
continue;
|
||||||
snprintf(path, sizeof(path), "%s\\%s", dir, ffd.cFileName);
|
sprintf_s(path, sizeof(path), "%s\\%s", dir, ffd.cFileName);
|
||||||
|
|
||||||
// ignore error from add_certs_to_store(), not all file
|
// ignore error from add_certs_to_store(), not all file
|
||||||
// maybe PEM.
|
// maybe PEM.
|
||||||
add_certs_to_store(trust_store, path, type, errmsg,
|
add_certs_to_store(trust_store, path, type, errmsg,
|
||||||
errmsg_len);
|
errmsg_len);
|
||||||
} while (FindNextFile(hFind, &ffd) != 0);
|
} while (FindNextFile(hFind, &ffd) != 0);
|
||||||
FindClose(hFind);
|
|
||||||
|
cleanup:
|
||||||
|
if (hFind != INVALID_HANDLE_VALUE)
|
||||||
|
FindClose(hFind);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,7 +360,7 @@ static int count_certificates(HCERTSTORE store)
|
|||||||
int num_certs = 0;
|
int num_certs = 0;
|
||||||
PCCERT_CONTEXT c = NULL;
|
PCCERT_CONTEXT c = NULL;
|
||||||
|
|
||||||
while (c = CertEnumCertificatesInStore(store, c))
|
while ((c = CertEnumCertificatesInStore(store, c)))
|
||||||
num_certs++;
|
num_certs++;
|
||||||
|
|
||||||
return num_certs;
|
return num_certs;
|
||||||
@@ -389,7 +391,7 @@ SECURITY_STATUS schannel_create_store(
|
|||||||
|
|
||||||
HCERTSTORE store = NULL;
|
HCERTSTORE store = NULL;
|
||||||
HCERTSTORE system_store = NULL;
|
HCERTSTORE system_store = NULL;
|
||||||
int status = SEC_E_INTERNAL_ERROR;
|
int status = SEC_E_OK;
|
||||||
|
|
||||||
*out_store = NULL;
|
*out_store = NULL;
|
||||||
if (!CAFile && !CAPath && !CRLFile && !CRLPath)
|
if (!CAFile && !CAPath && !CRLFile && !CRLPath)
|
||||||
@@ -405,9 +407,7 @@ SECURITY_STATUS schannel_create_store(
|
|||||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||||
if (!store)
|
if (!store)
|
||||||
{
|
{
|
||||||
status = get_last_error();
|
FAIL("CertOpenStore failed for memory store");
|
||||||
ma_format_win32_error(errmsg, errmsg_len, status, "failed to create certificate store");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (CRLFile || CRLPath)
|
else if (CRLFile || CRLPath)
|
||||||
@@ -419,19 +419,13 @@ SECURITY_STATUS schannel_create_store(
|
|||||||
CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
|
CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
|
||||||
if (!system_store)
|
if (!system_store)
|
||||||
{
|
{
|
||||||
status = get_last_error();
|
FAIL("CertOpenStore failed for system store");
|
||||||
ma_format_win32_error(errmsg, errmsg_len, status,
|
|
||||||
"failed to open system certificate store");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
store = CertDuplicateStore(system_store);
|
store = CertDuplicateStore(system_store);
|
||||||
if (!store)
|
if (!store)
|
||||||
{
|
{
|
||||||
status = get_last_error();
|
FAIL("CertDuplicateStore failed");
|
||||||
ma_format_win32_error(errmsg, errmsg_len, status,
|
|
||||||
"failed to duplicate system certificate store");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,10 +446,9 @@ SECURITY_STATUS schannel_create_store(
|
|||||||
|
|
||||||
if ((CAFile || CAPath) && store && !count_certificates(store))
|
if ((CAFile || CAPath) && store && !count_certificates(store))
|
||||||
{
|
{
|
||||||
snprintf(errmsg, errmsg_len,
|
SetLastError(SEC_E_INVALID_PARAMETER);
|
||||||
"no valid certificates were found, CAFile='%s', CAPath='%s'",
|
FAIL("no valid certificates were found, CAFile='%s', CAPath='%s'",
|
||||||
CAFile ? CAFile : "<not set>", CAPath ? CAPath : "<not set>");
|
CAFile ? CAFile : "<not set>", CAPath ? CAPath : "<not set>");
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CRLFile)
|
if (CRLFile)
|
||||||
@@ -468,7 +461,6 @@ SECURITY_STATUS schannel_create_store(
|
|||||||
status = add_dir_to_store(store, CRLPath, PEM_TYPE_X509_CRL,
|
status = add_dir_to_store(store, CRLPath, PEM_TYPE_X509_CRL,
|
||||||
errmsg, errmsg_len);
|
errmsg, errmsg_len);
|
||||||
}
|
}
|
||||||
status = SEC_E_OK;
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (system_store)
|
if (system_store)
|
||||||
@@ -496,8 +488,8 @@ static SECURITY_STATUS VerifyServerCertificate(
|
|||||||
LPWSTR pwszServerName,
|
LPWSTR pwszServerName,
|
||||||
DWORD dwRevocationCheckFlags,
|
DWORD dwRevocationCheckFlags,
|
||||||
DWORD dwVerifyFlags,
|
DWORD dwVerifyFlags,
|
||||||
LPSTR pErrMessage,
|
LPSTR errmsg,
|
||||||
size_t cbErrMessage)
|
size_t errmsg_len)
|
||||||
{
|
{
|
||||||
SSL_EXTRA_CERT_CHAIN_POLICY_PARA polExtra;
|
SSL_EXTRA_CERT_CHAIN_POLICY_PARA polExtra;
|
||||||
CERT_CHAIN_POLICY_PARA PolicyPara;
|
CERT_CHAIN_POLICY_PARA PolicyPara;
|
||||||
@@ -509,13 +501,12 @@ static SECURITY_STATUS VerifyServerCertificate(
|
|||||||
szOID_SERVER_GATED_CRYPTO,
|
szOID_SERVER_GATED_CRYPTO,
|
||||||
szOID_SGC_NETSCAPE };
|
szOID_SGC_NETSCAPE };
|
||||||
DWORD cUsages = sizeof(rgszUsages) / sizeof(LPSTR);
|
DWORD cUsages = sizeof(rgszUsages) / sizeof(LPSTR);
|
||||||
SECURITY_STATUS Status = SEC_E_INTERNAL_ERROR;
|
SECURITY_STATUS status = SEC_E_OK;
|
||||||
|
|
||||||
if (pServerCert == NULL)
|
if (pServerCert == NULL)
|
||||||
{
|
{
|
||||||
snprintf(pErrMessage, cbErrMessage, "Invalid parameter pServerCert passed to VerifyServerCertificate");
|
SetLastError(SEC_E_WRONG_PRINCIPAL);
|
||||||
Status = SEC_E_WRONG_PRINCIPAL;
|
FAIL("Invalid parameter pServerCert passed to VerifyServerCertificate");
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ZeroMemory(&ChainPara, sizeof(ChainPara));
|
ZeroMemory(&ChainPara, sizeof(ChainPara));
|
||||||
@@ -531,10 +522,7 @@ static SECURITY_STATUS VerifyServerCertificate(
|
|||||||
EngineConfig.hExclusiveRoot = hStore;
|
EngineConfig.hExclusiveRoot = hStore;
|
||||||
if (!CertCreateCertificateChainEngine(&EngineConfig, &hChainEngine))
|
if (!CertCreateCertificateChainEngine(&EngineConfig, &hChainEngine))
|
||||||
{
|
{
|
||||||
Status = get_last_error();
|
FAIL("CertCreateCertificateChainEngine failed");
|
||||||
ma_format_win32_error(pErrMessage, cbErrMessage, Status,
|
|
||||||
"CertCreateCertificateChainEngine failed");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -548,8 +536,7 @@ static SECURITY_STATUS VerifyServerCertificate(
|
|||||||
NULL,
|
NULL,
|
||||||
&pChainContext))
|
&pChainContext))
|
||||||
{
|
{
|
||||||
Status = get_last_error();
|
FAIL("CertGetCertificateChain failed");
|
||||||
ma_format_win32_error(pErrMessage, cbErrMessage, Status, "CertGetCertificateChain failed");
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,18 +560,14 @@ static SECURITY_STATUS VerifyServerCertificate(
|
|||||||
&PolicyPara,
|
&PolicyPara,
|
||||||
&PolicyStatus))
|
&PolicyStatus))
|
||||||
{
|
{
|
||||||
Status = get_last_error();
|
FAIL("CertVerifyCertificateChainPolicy failed");
|
||||||
ma_format_win32_error(pErrMessage, cbErrMessage, Status, "CertVerifyCertificateChainPolicy failed");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PolicyStatus.dwError)
|
if (PolicyStatus.dwError)
|
||||||
{
|
{
|
||||||
Status = PolicyStatus.dwError;
|
SetLastError(PolicyStatus.dwError);
|
||||||
ma_format_win32_error(pErrMessage, cbErrMessage, Status, "Server certificate validation failed");
|
FAIL("Server certificate validation failed");
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
Status = SEC_E_OK;
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (hChainEngine)
|
if (hChainEngine)
|
||||||
@@ -595,7 +578,7 @@ cleanup:
|
|||||||
{
|
{
|
||||||
CertFreeCertificateChain(pChainContext);
|
CertFreeCertificateChain(pChainContext);
|
||||||
}
|
}
|
||||||
return Status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -619,7 +602,7 @@ SECURITY_STATUS schannel_verify_server_certificate(
|
|||||||
char* errmsg,
|
char* errmsg,
|
||||||
size_t errmsg_len)
|
size_t errmsg_len)
|
||||||
{
|
{
|
||||||
SECURITY_STATUS status = SEC_E_INTERNAL_ERROR;
|
SECURITY_STATUS status = SEC_E_OK;
|
||||||
wchar_t* wserver_name = NULL;
|
wchar_t* wserver_name = NULL;
|
||||||
DWORD dwVerifyFlags;
|
DWORD dwVerifyFlags;
|
||||||
DWORD dwRevocationFlags;
|
DWORD dwRevocationFlags;
|
||||||
@@ -627,16 +610,14 @@ SECURITY_STATUS schannel_verify_server_certificate(
|
|||||||
if (check_server_name)
|
if (check_server_name)
|
||||||
{
|
{
|
||||||
int cchServerName = (int)strlen(server_name) + 1;
|
int cchServerName = (int)strlen(server_name) + 1;
|
||||||
wserver_name = (wchar_t*)malloc(sizeof(wchar_t) * cchServerName);
|
wserver_name = (wchar_t*)LocalAlloc(0,sizeof(wchar_t) * cchServerName);
|
||||||
if (!wserver_name)
|
if (!wserver_name)
|
||||||
{
|
{
|
||||||
ma_format_win32_error(errmsg, errmsg_len, ERROR_OUTOFMEMORY, "malloc() failed");
|
FAIL("LocalAlloc() failed");
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
if (MultiByteToWideChar(CP_UTF8, 0, server_name, cchServerName, wserver_name, cchServerName) < 0)
|
if (MultiByteToWideChar(CP_UTF8, 0, server_name, cchServerName, wserver_name, cchServerName) < 0)
|
||||||
{
|
{
|
||||||
ma_format_win32_error(errmsg, errmsg_len, GetLastError(), "MultiByteToWideChar() failed");
|
FAIL("MultiByteToWideChar() failed");
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,7 +632,7 @@ SECURITY_STATUS schannel_verify_server_certificate(
|
|||||||
dwRevocationFlags, dwVerifyFlags, errmsg, errmsg_len);
|
dwRevocationFlags, dwVerifyFlags, errmsg, errmsg_len);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
free(wserver_name);
|
LocalFree(wserver_name);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -668,21 +649,17 @@ static SECURITY_STATUS load_private_key(CERT_CONTEXT* cert, char* private_key_st
|
|||||||
CERT_KEY_CONTEXT cert_key_context = { 0 };
|
CERT_KEY_CONTEXT cert_key_context = { 0 };
|
||||||
PCRYPT_PRIVATE_KEY_INFO pki = NULL;
|
PCRYPT_PRIVATE_KEY_INFO pki = NULL;
|
||||||
DWORD pki_len = 0;
|
DWORD pki_len = 0;
|
||||||
SECURITY_STATUS status = SEC_E_INTERNAL_ERROR;
|
SECURITY_STATUS status = SEC_E_OK;
|
||||||
|
|
||||||
derbuf = LocalAlloc(0, derlen);
|
derbuf = LocalAlloc(0, derlen);
|
||||||
if (!derbuf)
|
if (!derbuf)
|
||||||
{
|
{
|
||||||
status = get_last_error();
|
FAIL("LocalAlloc failed")
|
||||||
ma_format_win32_error(errmsg, errmsg_len, status, "Memory allocation failed");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CryptStringToBinaryA(private_key_str, (DWORD)len, CRYPT_STRING_BASE64HEADER, derbuf, &derlen, NULL, NULL))
|
if (!CryptStringToBinaryA(private_key_str, (DWORD)len, CRYPT_STRING_BASE64HEADER, derbuf, &derlen, NULL, NULL))
|
||||||
{
|
{
|
||||||
status = get_last_error();
|
FAIL("Failed to convert BASE64 private key");
|
||||||
ma_format_win32_error(errmsg, errmsg_len, status, "Failed to convert BASE64 private key");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -706,10 +683,7 @@ static SECURITY_STATUS load_private_key(CERT_CONTEXT* cert, char* private_key_st
|
|||||||
CRYPT_DECODE_ALLOC_FLAG,
|
CRYPT_DECODE_ALLOC_FLAG,
|
||||||
NULL, &keyblob, &keyblob_len))
|
NULL, &keyblob, &keyblob_len))
|
||||||
{
|
{
|
||||||
status = get_last_error();
|
FAIL("Failed to parse private key");
|
||||||
ma_format_win32_error(errmsg, errmsg_len, status,
|
|
||||||
"Failed to parse private key");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!CryptDecodeObjectEx(
|
else if (!CryptDecodeObjectEx(
|
||||||
@@ -719,24 +693,17 @@ static SECURITY_STATUS load_private_key(CERT_CONTEXT* cert, char* private_key_st
|
|||||||
CRYPT_DECODE_ALLOC_FLAG, NULL,
|
CRYPT_DECODE_ALLOC_FLAG, NULL,
|
||||||
&keyblob, &keyblob_len))
|
&keyblob, &keyblob_len))
|
||||||
{
|
{
|
||||||
status = get_last_error();
|
FAIL("Failed to parse private key");
|
||||||
ma_format_win32_error(errmsg, errmsg_len, status,
|
|
||||||
"Failed to parse private key");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
if (!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
||||||
{
|
{
|
||||||
status = get_last_error();
|
FAIL("CryptAcquireContext failed");
|
||||||
ma_format_win32_error(errmsg, errmsg_len, status, "CryptAcquireContext failed");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CryptImportKey(hProv, keyblob, keyblob_len, 0, 0, (HCRYPTKEY*)&hKey))
|
if (!CryptImportKey(hProv, keyblob, keyblob_len, 0, 0, (HCRYPTKEY*)&hKey))
|
||||||
{
|
{
|
||||||
status = get_last_error();
|
FAIL("CryptImportKey failed");
|
||||||
ma_format_win32_error(errmsg, errmsg_len, status, "CryptImportKey failed");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
cert_key_context.hCryptProv = hProv;
|
cert_key_context.hCryptProv = hProv;
|
||||||
cert_key_context.dwKeySpec = AT_KEYEXCHANGE;
|
cert_key_context.dwKeySpec = AT_KEYEXCHANGE;
|
||||||
@@ -745,10 +712,8 @@ static SECURITY_STATUS load_private_key(CERT_CONTEXT* cert, char* private_key_st
|
|||||||
/* assign private key to certificate context */
|
/* assign private key to certificate context */
|
||||||
if (!CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0, &cert_key_context))
|
if (!CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0, &cert_key_context))
|
||||||
{
|
{
|
||||||
status = get_last_error();
|
FAIL("CertSetCertificateContextProperty failed");
|
||||||
ma_format_win32_error(errmsg, errmsg_len, get_last_error(), "Can't assign private key to certificate context");
|
|
||||||
}
|
}
|
||||||
status = SEC_E_OK;
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
LocalFree(derbuf);
|
LocalFree(derbuf);
|
||||||
@@ -779,7 +744,7 @@ static CERT_CONTEXT* create_client_certificate_mem(
|
|||||||
char* end;
|
char* end;
|
||||||
CERT_BLOB cert_blob;
|
CERT_BLOB cert_blob;
|
||||||
DWORD actual_content_type = 0;
|
DWORD actual_content_type = 0;
|
||||||
int ok = 0;
|
SECURITY_STATUS status = SEC_E_OK;
|
||||||
|
|
||||||
/* Parse certificate */
|
/* Parse certificate */
|
||||||
pem_locate(cert_file_content, PEM_TYPE_CERTIFICATE,
|
pem_locate(cert_file_content, PEM_TYPE_CERTIFICATE,
|
||||||
@@ -787,8 +752,8 @@ static CERT_CONTEXT* create_client_certificate_mem(
|
|||||||
|
|
||||||
if (!begin || !end)
|
if (!begin || !end)
|
||||||
{
|
{
|
||||||
snprintf(errmsg, errmsg_len, "Client certificate not found in PEM file");
|
SetLastError(SEC_E_INVALID_PARAMETER);
|
||||||
goto cleanup;
|
FAIL("Client certificate not found in PEM file");
|
||||||
}
|
}
|
||||||
|
|
||||||
cert_blob.pbData = (BYTE*)begin;
|
cert_blob.pbData = (BYTE*)begin;
|
||||||
@@ -799,9 +764,7 @@ static CERT_CONTEXT* create_client_certificate_mem(
|
|||||||
CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, &actual_content_type,
|
CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, &actual_content_type,
|
||||||
NULL, NULL, NULL, (const void**)&ctx))
|
NULL, NULL, NULL, (const void**)&ctx))
|
||||||
{
|
{
|
||||||
ma_format_win32_error(errmsg, errmsg_len, GetLastError(),
|
FAIL("Can't parse client certficate");
|
||||||
"Can't parse client certficate");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse key */
|
/* Parse key */
|
||||||
@@ -812,22 +775,22 @@ static CERT_CONTEXT* create_client_certificate_mem(
|
|||||||
if (begin && end)
|
if (begin && end)
|
||||||
{
|
{
|
||||||
/* Assign key to certificate.*/
|
/* Assign key to certificate.*/
|
||||||
ok = !load_private_key(ctx, begin, (end - begin), errmsg, errmsg_len);
|
status = load_private_key(ctx, begin, (end - begin), errmsg, errmsg_len);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!begin || !end)
|
if (!begin || !end)
|
||||||
snprintf(errmsg, errmsg_len, "Client private key not found in PEM");
|
{
|
||||||
|
SetLastError(SEC_E_INVALID_PARAMETER);
|
||||||
|
FAIL("Client private key not found in PEM");
|
||||||
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (!ok)
|
if (status && ctx)
|
||||||
{
|
{
|
||||||
if (ctx)
|
CertFreeCertificateContext(ctx);
|
||||||
{
|
ctx = NULL;
|
||||||
CertFreeCertificateContext(ctx);
|
|
||||||
ctx = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
@@ -859,9 +822,9 @@ CERT_CONTEXT* schannel_create_cert_context(char* cert_file, char* key_file, char
|
|||||||
ctx = create_client_certificate_mem(cert_file_content, key_file_content, errmsg, errmsg_len);
|
ctx = create_client_certificate_mem(cert_file_content, key_file_content, errmsg, errmsg_len);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
free(cert_file_content);
|
LocalFree(cert_file_content);
|
||||||
if (cert_file != key_file)
|
if (cert_file != key_file)
|
||||||
free(key_file_content);
|
LocalFree(key_file_content);
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
@@ -35,7 +35,7 @@ extern SECURITY_STATUS schannel_create_store(
|
|||||||
extern SECURITY_STATUS schannel_verify_server_certificate(
|
extern SECURITY_STATUS schannel_verify_server_certificate(
|
||||||
const CERT_CONTEXT* cert,
|
const CERT_CONTEXT* cert,
|
||||||
HCERTSTORE store,
|
HCERTSTORE store,
|
||||||
BOOL <EFBFBD>check_revocation,
|
BOOL check_revocation,
|
||||||
const char* server_name,
|
const char* server_name,
|
||||||
BOOL check_server_name,
|
BOOL check_server_name,
|
||||||
char* errmsg,
|
char* errmsg,
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Format Windows error, with optional text.
|
Format Windows error, with optional text.
|
||||||
@@ -40,7 +41,7 @@ void ma_format_win32_error(char* buf, size_t buflen, DWORD code, _Printf_format_
|
|||||||
{
|
{
|
||||||
va_list vargs;
|
va_list vargs;
|
||||||
va_start(vargs, fmt);
|
va_start(vargs, fmt);
|
||||||
cur += vsnprintf(cur, end - cur, fmt, vargs);
|
cur += vsnprintf_s(cur, end - cur, _TRUNCATE, fmt, vargs);
|
||||||
va_end(vargs);
|
va_end(vargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +97,7 @@ void ma_format_win32_error(char* buf, size_t buflen, DWORD code, _Printf_format_
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct map_entry* entry = NULL;
|
struct map_entry* entry = NULL;
|
||||||
strncpy(cur,". ",end-cur);
|
strncpy_s(cur,end-cur, ". ", _TRUNCATE);
|
||||||
cur += 2;
|
cur += 2;
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(map) / sizeof(map[0]); i++)
|
for (size_t i = 0; i < sizeof(map) / sizeof(map[0]); i++)
|
||||||
@@ -111,7 +112,7 @@ void ma_format_win32_error(char* buf, size_t buflen, DWORD code, _Printf_format_
|
|||||||
return;
|
return;
|
||||||
if (entry)
|
if (entry)
|
||||||
{
|
{
|
||||||
cur += snprintf(cur, end - cur, "%s. Error 0x%08lX(%s)", entry->msg, code, entry->sym);
|
sprintf_s(cur, end - cur, "%s. Error 0x%08lX(%s)", entry->msg, code, entry->sym);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -125,7 +126,7 @@ void ma_format_win32_error(char* buf, size_t buflen, DWORD code, _Printf_format_
|
|||||||
cur++;
|
cur++;
|
||||||
*cur = 0;
|
*cur = 0;
|
||||||
}
|
}
|
||||||
cur += snprintf(cur, end - cur, ". Error %lu/0x%08lX", code, code);
|
sprintf_s(cur, end - cur, ". Error %lu/0x%08lX", code, code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user