Подтвердить что ты не робот

Есть ли API для предварительного получения списка доверенных корневых сертификатов в Windows?

Я использую Python и OpenSSL для подключения к сайту с использованием TLS (в некоторых кросс-платформенных программах, поэтому было бы слишком много работать, чтобы переключиться на CryptoAPI для всего); Однако я не хочу распространять (и обновлять) собственный список сертификатов. Я хочу получить их с платформы. В OS X и Linux это довольно просто, но Windows поставляется с неполным списком доверенных корневых центров сертификации для TLS; в основном только собственные сертификаты Microsoft, а затем динамически добавляет доверительные корни в хранилище, когда материал TLS высокого уровня (например, загрузка веб-страницы в Internet Explorer поверх HTTPS) должен проверять корневой трафик, который он ранее не видел. (Этот процесс объясняется здесь.) Это означает, что я могу перечислить корень Windows хранилище сертификатов с wincertstore, но это бесполезно, потому что на машинах с более поздними установленными ОС этот магазин будет почти пустым.

Microsoft предоставляет подробные инструкции для администраторов для предварительного извлечения этого списка, чтобы иметь возможность управлять машинами с жестко контролируемым доступом к сети; однако я не могу найти ссылку на API, который сделает то же самое, и просто загрузит все доверенные корневые сертификаты из Microsoft. (Честно говоря, в эпоху еженедельных обновлений для нескольких мегабайт, я не понимаю, почему предварительная загрузка этих файлов является такой большой проблемой, если это просто кеш, а для бонусных очков объясните, почему это должно произойти вообще.)

Итак: существует ли API, который позволит мне сообщить системе только предварительно кэшировать доверенные корневые сертификаты в соответствии с любыми правилами, которые он использует? В противном случае, если это действительно невозможно (т.е. Если CryptoAPI может загружать только один доверительный root за раз и только если вы подаете ему сертификат, подписанный этим корнем), есть ли способ подключить проверку сертификата OpenSSL в хранилище доверия CryptoAPI, чтобы проверка будет загружать и кэшировать доверительные корни, как и родное TLS-соединение?

4b9b3361

Ответ 1

Это не идеальный подход, но он должен сделать это, и это может дать вам возможность начать. Этот код примет файл .sst, сгенерированный с помощью certutil -generateSSTFromWU, и добавит все сертификаты в корневой магазин:

#include <Windows.h>

#include <WinCrypt.h>

#pragma comment(lib, "crypt32.lib")

#include <stdio.h>

void process_cert(PCCERT_CONTEXT cert)
{
    PCCERT_CHAIN_CONTEXT ccc;
    CERT_CHAIN_PARA ccp = {sizeof(CERT_CHAIN_PARA)};
    DWORD flags;
    char certname[256];

    CertGetNameStringA(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, certname, _countof(certname));

    flags = 0;

    if (!CertGetCertificateChain(HCCE_LOCAL_MACHINE, cert, NULL, NULL, &ccp, flags, NULL, &ccc))
    {
        printf("Certificate %s CertGetCertificateChain: %u\n", certname, GetLastError());
    }
    else
    {
        printf("Certificate %s : %x (%x)\n", certname, ccc->TrustStatus.dwErrorStatus, ccc->TrustStatus.dwInfoStatus);
    }
}

void mainfn(void)
{
    HCERTSTORE sst;
    PCCERT_CONTEXT cert;
    DWORD count;

    sst = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, (HCRYPTPROV)NULL, CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L"c:\\downloads\\roots.sst");

    if (sst == NULL)
    {
        printf("CertOpenStore: %x\n", GetLastError());
        return;
    }

    for (cert = NULL, count = 0; cert = CertEnumCertificatesInStore(sst, cert); count++) process_cert(cert);

    {
        DWORD err = GetLastError();
        if (err != CRYPT_E_NOT_FOUND)
        {
            printf("CertEnumCertificate: %u\n", err);
            return;
        }
    }
}

int main(int argc, char ** argv)
{
    mainfn();
    return 0;
}

Кроме того, в вашем контексте вы можете использовать корневые сертификаты в файле .sst напрямую, не добавляя их в корневой магазин. (В этом случае вам следует, вероятно, перечислить корневой магазин, а также файл .sst, чтобы включить любые локально добавленные сертификаты.)