1
0
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:
Vladislav Vaintroub
2019-12-09 00:22:46 +01:00
parent 63df45ce3d
commit 2efc52b5b7
4 changed files with 113 additions and 149 deletions

View File

@@ -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)
{ {

View File

@@ -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;
} }

View File

@@ -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,

View File

@@ -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);
} }
} }