SUPPORT-9524. Добавлен статус CERT_TRUST_IS_PARTIAL_CHAIN + вывод информации о сертификате в случае ошибки при проверке цепочки сертификатов
This commit is contained in:
parent
7dbcabb9ff
commit
cdef230819
4 changed files with 185 additions and 2 deletions
|
|
@ -120,6 +120,7 @@ $ /opt/cprocsp/bin/amd64/curl -v http://127.0.0.1/msg/verify_detached \
|
||||||
| `CERT_TRUST_REVOCATION_STATUS_UNKNOWN` | Неизвестен статус отзыва сертификата или одного из сертификатов в цепочке (проблема с CRL) |
|
| `CERT_TRUST_REVOCATION_STATUS_UNKNOWN` | Неизвестен статус отзыва сертификата или одного из сертификатов в цепочке (проблема с CRL) |
|
||||||
| `CERT_TRUST_IS_UNTRUSTED_ROOT` | Сертификат или цепочка сертификатов основана на ненадежном корневом сертификате |
|
| `CERT_TRUST_IS_UNTRUSTED_ROOT` | Сертификат или цепочка сертификатов основана на ненадежном корневом сертификате |
|
||||||
| `CERT_TRUST_IS_NOT_TIME_VALID` | Этот сертификат или один из сертификатов в цепочке сертификатов является недопустимым по времени |
|
| `CERT_TRUST_IS_NOT_TIME_VALID` | Этот сертификат или один из сертификатов в цепочке сертификатов является недопустимым по времени |
|
||||||
|
| `CERT_TRUST_IS_PARTIAL_CHAIN` | Цепочка сертификатов не полная |
|
||||||
|
|
||||||
## Сборка из исходников
|
## Сборка из исходников
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ capi_function_list_init(library_t *lib, capi_function_list_t *fl)
|
||||||
LIBRARY_RESOLVE(fl->CertFindExtension, lib, "CertFindExtension");
|
LIBRARY_RESOLVE(fl->CertFindExtension, lib, "CertFindExtension");
|
||||||
LIBRARY_RESOLVE(fl->CryptDecodeObjectEx, lib, "CryptDecodeObjectEx");
|
LIBRARY_RESOLVE(fl->CryptDecodeObjectEx, lib, "CryptDecodeObjectEx");
|
||||||
LIBRARY_RESOLVE(fl->LocalFree, lib, "LocalFree");
|
LIBRARY_RESOLVE(fl->LocalFree, lib, "LocalFree");
|
||||||
|
LIBRARY_RESOLVE(fl->FileTimeToSystemTime, lib, "FileTimeToSystemTime");
|
||||||
|
|
||||||
#ifdef UNICODE
|
#ifdef UNICODE
|
||||||
LIBRARY_RESOLVE(fl->CryptSignHash, lib, "CryptSignHashW");
|
LIBRARY_RESOLVE(fl->CryptSignHash, lib, "CryptSignHashW");
|
||||||
|
|
|
||||||
|
|
@ -266,6 +266,12 @@ DECLARE_FN(WINADVAPI,
|
||||||
LOCAL_FREE,
|
LOCAL_FREE,
|
||||||
(HLOCAL hMem));
|
(HLOCAL hMem));
|
||||||
|
|
||||||
|
DECLARE_FN(WINADVAPI,
|
||||||
|
BOOL,
|
||||||
|
FILE_TIME_TO_SYSTEM_TIME,
|
||||||
|
(CONST FILETIME *lpFileTime,
|
||||||
|
LPSYSTEMTIME lpSystemTime));
|
||||||
|
|
||||||
#ifdef UNICODE
|
#ifdef UNICODE
|
||||||
#define CRYPT_SIGN_HASH_FN CRYPT_SIGN_HASH_W_FN
|
#define CRYPT_SIGN_HASH_FN CRYPT_SIGN_HASH_W_FN
|
||||||
#define CRYPT_VERIFY_SIGNATURE_FN CRYPT_VERIFY_SIGNATURE_W_FN
|
#define CRYPT_VERIFY_SIGNATURE_FN CRYPT_VERIFY_SIGNATURE_W_FN
|
||||||
|
|
@ -308,6 +314,7 @@ typedef struct {
|
||||||
CERT_FIND_EXTENSION_FN CertFindExtension;
|
CERT_FIND_EXTENSION_FN CertFindExtension;
|
||||||
CRYPT_DECODE_OBJECT_EX_FN CryptDecodeObjectEx;
|
CRYPT_DECODE_OBJECT_EX_FN CryptDecodeObjectEx;
|
||||||
LOCAL_FREE_FN LocalFree;
|
LOCAL_FREE_FN LocalFree;
|
||||||
|
FILE_TIME_TO_SYSTEM_TIME_FN FileTimeToSystemTime;
|
||||||
|
|
||||||
} capi_function_list_t;
|
} capi_function_list_t;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,12 @@
|
||||||
#include "library.h"
|
#include "library.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
||||||
|
#define SHA1_SIZE 20
|
||||||
|
|
||||||
static const char* CERT_TRUST_IS_UNTRUSTED_ROOT_ERR_CODE = "CERT_TRUST_IS_UNTRUSTED_ROOT";
|
static const char* CERT_TRUST_IS_UNTRUSTED_ROOT_ERR_CODE = "CERT_TRUST_IS_UNTRUSTED_ROOT";
|
||||||
static const char* CERT_TRUST_REVOCATION_STATUS_UNKNOWN_ERR_CODE = "CERT_TRUST_REVOCATION_STATUS_UNKNOWN";
|
static const char* CERT_TRUST_REVOCATION_STATUS_UNKNOWN_ERR_CODE = "CERT_TRUST_REVOCATION_STATUS_UNKNOWN";
|
||||||
static const char* CERT_TRUST_IS_NOT_TIME_VALID_ERR_CODE = "CERT_TRUST_IS_NOT_TIME_VALID";
|
static const char* CERT_TRUST_IS_NOT_TIME_VALID_ERR_CODE = "CERT_TRUST_IS_NOT_TIME_VALID";
|
||||||
|
static const char* CERT_TRUST_IS_PARTIAL_CHAIN_ERR_CODE = "CERT_TRUST_IS_PARTIAL_CHAIN";
|
||||||
|
|
||||||
static capi_function_list_t cp_function_list;
|
static capi_function_list_t cp_function_list;
|
||||||
static library_t libcapi;
|
static library_t libcapi;
|
||||||
|
|
@ -24,6 +27,10 @@ static PCCERT_CONTEXT get_signer_cert(const cryptopro_context_t *ctx, HCERTSTORE
|
||||||
|
|
||||||
static int set_password(PCCERT_CONTEXT cert_ctx, const str_t *password);
|
static int set_password(PCCERT_CONTEXT cert_ctx, const str_t *password);
|
||||||
|
|
||||||
|
static bool get_subject_name(PCCERT_CONTEXT cert, /*out*/ char **subject_name);
|
||||||
|
|
||||||
|
static bool get_issuer_name(PCCERT_CONTEXT cert, /*out*/ char **issuer_name);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
cryptopro_init(const char* cp_file)
|
cryptopro_init(const char* cp_file)
|
||||||
{
|
{
|
||||||
|
|
@ -128,7 +135,7 @@ print_crl_urls_from_certificate(PCCERT_CONTEXT cert)
|
||||||
&crl_dist_points,
|
&crl_dist_points,
|
||||||
&info_size
|
&info_size
|
||||||
)) {
|
)) {
|
||||||
LOG_ERROR("CryptDecodeObjectEx failed. Desc: 0x%x", cp_function_list.GetLastError());
|
LOG_ERROR("CryptDecodeObjectEx failed. Error code: 0x%08x", cp_function_list.GetLastError());
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,6 +167,169 @@ error:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_crt_urls_from_certificate(PCCERT_CONTEXT cert)
|
||||||
|
{
|
||||||
|
LOG_TRACE("print_crt_urls_from_certificate enter");
|
||||||
|
|
||||||
|
PCERT_EXTENSION extension = cp_function_list.CertFindExtension(
|
||||||
|
szOID_AUTHORITY_INFO_ACCESS,
|
||||||
|
cert->pCertInfo->cExtension,
|
||||||
|
cert->pCertInfo->rgExtension
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!extension) {
|
||||||
|
LOG_WARN("Authority Info Access extension not found");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD info_size = 0;
|
||||||
|
PCERT_AUTHORITY_INFO_ACCESS info_access = NULL;
|
||||||
|
|
||||||
|
if (!cp_function_list.CryptDecodeObjectEx(
|
||||||
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
||||||
|
X509_AUTHORITY_INFO_ACCESS,
|
||||||
|
extension->Value.pbData,
|
||||||
|
extension->Value.cbData,
|
||||||
|
CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
|
||||||
|
NULL,
|
||||||
|
&info_access,
|
||||||
|
&info_size
|
||||||
|
)) {
|
||||||
|
LOG_ERROR("CryptDecodeObjectEx failed. Error code: 0x%08x", cp_function_list.GetLastError());
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info_access && info_access->cAccDescr > 0) {
|
||||||
|
for (DWORD i = 0; i < info_access->cAccDescr; i++) {
|
||||||
|
if (strcmp(info_access->rgAccDescr[i].pszAccessMethod, szOID_PKIX_CA_ISSUERS) == 0) {
|
||||||
|
if (info_access->rgAccDescr[i].AccessLocation.dwAltNameChoice == CERT_ALT_NAME_URL) {
|
||||||
|
LOG_INFO("CA Issuers URL: %ls", info_access->rgAccDescr[i].AccessLocation._empty_union_.pwszURL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info_access) {
|
||||||
|
cp_function_list.LocalFree(info_access);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_TRACE("print_crt_urls_from_certificate exit");
|
||||||
|
return;
|
||||||
|
|
||||||
|
error:
|
||||||
|
LOG_ERROR("print_crt_urls_from_certificate exit with error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char*
|
||||||
|
bin_to_hex(const BYTE *bytes, DWORD len)
|
||||||
|
{
|
||||||
|
char* hex = NULL;
|
||||||
|
|
||||||
|
hex = malloc(len * 2 + 1);
|
||||||
|
if (hex == NULL) {
|
||||||
|
LOG_ERROR("bin_to_hex exit with error: could not allocate memory for hex (%d bytes)", len * 2 + 1);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (DWORD i = 0; i < len; i++) {
|
||||||
|
sprintf(hex + i * 2, "%02x", bytes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
get_thumbprint(PCCERT_CONTEXT cert, /*out*/ char** thumbprint)
|
||||||
|
{
|
||||||
|
LOG_TRACE("get_thumbprint enter");
|
||||||
|
|
||||||
|
BYTE sha1_hash[SHA1_SIZE];
|
||||||
|
DWORD sha1_hash_size = sizeof(sha1_hash);
|
||||||
|
|
||||||
|
if (!cp_function_list.CertGetCertificateContextProperty(
|
||||||
|
cert,
|
||||||
|
CERT_SHA1_HASH_PROP_ID,
|
||||||
|
sha1_hash,
|
||||||
|
&sha1_hash_size)) {
|
||||||
|
LOG_ERROR("CertGetCertificateContextProperty(CERT_SHA1_HASH_PROP_ID) failed. Error code: 0x%08x",
|
||||||
|
cp_function_list.GetLastError());
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
*thumbprint = bin_to_hex(sha1_hash, sha1_hash_size);
|
||||||
|
if (*thumbprint == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG("thumbprint: '%s'", *thumbprint);
|
||||||
|
|
||||||
|
LOG_TRACE("get_thumbprint exit");
|
||||||
|
return true;
|
||||||
|
|
||||||
|
error:
|
||||||
|
LOG_ERROR("get_thumbprint exit with error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_cert_time_validity(PCCERT_CONTEXT cert)
|
||||||
|
{
|
||||||
|
SYSTEMTIME st;
|
||||||
|
|
||||||
|
LOG_TRACE("print_cert_time_validity enter");
|
||||||
|
|
||||||
|
if (cp_function_list.FileTimeToSystemTime(&cert->pCertInfo->NotBefore, &st)) {
|
||||||
|
LOG_INFO("Not valid before: %02d.%02d.%04d", st.wDay, st.wMonth, st.wYear);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cp_function_list.FileTimeToSystemTime(&cert->pCertInfo->NotAfter, &st)) {
|
||||||
|
LOG_INFO("Not valid after: %02d.%02d.%04d", st.wDay, st.wMonth, st.wYear);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_TRACE("print_cert_time_validity exit");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_common_cert_info(PCCERT_CONTEXT cert)
|
||||||
|
{
|
||||||
|
char* subject = NULL;
|
||||||
|
char* issuer = NULL;
|
||||||
|
char* thumbprint = NULL;
|
||||||
|
|
||||||
|
LOG_TRACE("print_common_cert_info enter");
|
||||||
|
|
||||||
|
if (get_thumbprint(cert, &thumbprint)) {
|
||||||
|
LOG_INFO("SHA1 Hash: %s", thumbprint);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_subject_name(cert, &subject)) {
|
||||||
|
LOG_INFO("Subject: %s", subject);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_issuer_name(cert, &issuer)) {
|
||||||
|
LOG_INFO("Issuer: %s", issuer);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(subject);
|
||||||
|
free(issuer);
|
||||||
|
free(thumbprint);
|
||||||
|
|
||||||
|
LOG_TRACE("print_common_cert_info exit");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_cert_info(PCCERT_CONTEXT cert)
|
||||||
|
{
|
||||||
|
LOG_INFO("=========== Certificate Info: ===========");
|
||||||
|
print_common_cert_info(cert);
|
||||||
|
print_cert_time_validity(cert);
|
||||||
|
print_crt_urls_from_certificate(cert);
|
||||||
|
print_crl_urls_from_certificate(cert);
|
||||||
|
LOG_INFO("=========================================");
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process_trust_status_error(PCCERT_CONTEXT cert, DWORD status, /*out*/ const char **error_code)
|
process_trust_status_error(PCCERT_CONTEXT cert, DWORD status, /*out*/ const char **error_code)
|
||||||
{
|
{
|
||||||
|
|
@ -168,7 +338,6 @@ process_trust_status_error(PCCERT_CONTEXT cert, DWORD status, /*out*/ const char
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case CERT_TRUST_REVOCATION_STATUS_UNKNOWN:
|
case CERT_TRUST_REVOCATION_STATUS_UNKNOWN:
|
||||||
*error_code = CERT_TRUST_REVOCATION_STATUS_UNKNOWN_ERR_CODE;
|
*error_code = CERT_TRUST_REVOCATION_STATUS_UNKNOWN_ERR_CODE;
|
||||||
print_crl_urls_from_certificate(cert);
|
|
||||||
break;
|
break;
|
||||||
case CERT_TRUST_IS_UNTRUSTED_ROOT:
|
case CERT_TRUST_IS_UNTRUSTED_ROOT:
|
||||||
*error_code = CERT_TRUST_IS_UNTRUSTED_ROOT_ERR_CODE;
|
*error_code = CERT_TRUST_IS_UNTRUSTED_ROOT_ERR_CODE;
|
||||||
|
|
@ -176,6 +345,9 @@ process_trust_status_error(PCCERT_CONTEXT cert, DWORD status, /*out*/ const char
|
||||||
case CERT_TRUST_IS_NOT_TIME_VALID:
|
case CERT_TRUST_IS_NOT_TIME_VALID:
|
||||||
*error_code = CERT_TRUST_IS_NOT_TIME_VALID_ERR_CODE;
|
*error_code = CERT_TRUST_IS_NOT_TIME_VALID_ERR_CODE;
|
||||||
break;
|
break;
|
||||||
|
case CERT_TRUST_IS_PARTIAL_CHAIN:
|
||||||
|
*error_code = CERT_TRUST_IS_PARTIAL_CHAIN_ERR_CODE;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
*error_code = NULL;
|
*error_code = NULL;
|
||||||
break;
|
break;
|
||||||
|
|
@ -188,6 +360,8 @@ process_trust_status_error(PCCERT_CONTEXT cert, DWORD status, /*out*/ const char
|
||||||
LOG_WARN("The certificate is not trusted. CERT_TRUST_STATUS: '0x%08x'", status);
|
LOG_WARN("The certificate is not trusted. CERT_TRUST_STATUS: '0x%08x'", status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print_cert_info(cert);
|
||||||
|
|
||||||
LOG_TRACE("process_trust_status_error exit");
|
LOG_TRACE("process_trust_status_error exit");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue