2016-01-11 29 views
10

TLSを使用してサイトに接続するためにPythonとOpenSSLを使用しています(一部のクロスプラットフォームソフトウェアでは、すべてのCryptoAPIに切り替えるにはあまりにも多くの作業が必要になります)。しかし、私は証明書のカスタムリストを配布(および更新)したくありません。私はプラットフォームからそれらを取得したい。 OS XとLinuxでは、これはかなり簡単ですが、WindowsにはTLS用の信頼できるルート証明機関の不完全なリストが付属しています。基本的にはMicrosoft自身の証明書だけを使用して、高レベルのTLSの処理(HTTPS経由のInternet ExplorerでWebページを読み込むなど)が以前には見られなかった信頼ルートを確認する必要があるときに、 (This process is explained here.)これは私がenumerate the Windows root certificate store with wincertstoreを意味することができることを意味しますが、最近インストールされたOSが搭載されているマシンでは、そのストアはほとんど空になるため、役に立たなくなります。Windows上で信頼できるルート証明書のリストを事前に取得するためのAPIはありますか?

Microsoftは厳密に制御されたネットワークアクセスを持つコンピュータを操作できるように、この一覧を事前に取得するようにdetailed instructions for administratorsを提供しています。しかし、私は同じことをするAPIへの参照を見つけることができず、Microsoftからすべての信頼できるルート証明書をダウンロードするだけです。 (正直なところ、毎週のマルチメガバイトのシステムアップデート時代には、キャッシュをダウンロードするだけで、これをダウンロードするのは大したことではありません。なぜボーナスポイントが必要なのか説明してください)

したがって、使用するルールに応じて信頼できるルート証明書をプリキャッシュするようにシステムに指示するAPIはありますか?それが本当に不可能な場合(つまり、CryptoAPIが一度に1つの信頼ルートしかダウンロードできない場合、そのルートによって署名された証明書を送る場合のみ)、OpenSSL証明書検証をCryptoAPIの信頼ストアに接続する方法があります。ネイティブTLS接続と同様に、検証でダウンロードして信頼ルートをキャッシュしますか?

+0

興味深い。私は彼らがほとんどの時間中断し続けるので、私は私のVM上でこれを見ていないと思いますか? – Glyph

+0

@HarryJohnston - おそらく、このコマンドを実行することは、プログラムでこれを行う正しい答えです。しかし、私たちがサブプロセスを必要としないように呼び出すAPIを知っていることは理想的です。 – Glyph

+0

したがって、 'certutil -syncWithWU'は証明書をディレクトリに置くだけです。 '' ROOT ''ストアには保存されません。どこにいても構いません。 – Glyph

答えて

1

これは理想的な方法ではありませんが、ピンチで行う必要があります。なし、

#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ファイル内のルート証明書を使用することを好むかもしれません:このコードはcertutil -generateSSTFromWUによって生成された.sstファイルを取得し、ルートストアにすべての証明書を追加しますそれらをルートストアに追加することもできます。 (その場合は、ルートストアと.sstファイルを列挙し、ローカルに追加された証明書を含めるようにしてください)

+0

これは*ルートストアからすべての証明書を削除しますか?私はWUが正常に行うことを正確にしたい。ユーザーが証明書を信頼できない場合、私はそれを再信用したくありません。彼らがカスタム証明書を追加した場合、その証明書を尊重したいと思います。 – Glyph

+0

これで証明書が削除されることはなく、既にストア内に存在する証明書には影響しません。すべての証明書が有効であることをWindowsに確認することだけです。これとInternet Explorerの機能との唯一の違いは、ルート証明書につながる証明書チェーンについて尋ねるのではなく、Windowsにルート証明書について直接問い合わせることです。 –

+0

(OpenSSLがあなた自身でサイト証明書を検証するオプションを提供する場合、それはより良いオプションかもしれません。)CertGetCertificateChainと友人が検証を行う場合、あなたのプログラムはInternet Explorerのように*特定のサイトが実際に店舗に必要とする証明書) –

関連する問題