2016-09-29 92 views
1

我使用boost asio連接到我的有效證書(由根CA簽名)。我正在使用的代碼是ssl client example可從boost文檔中獲得。在Windows上獲取根CA證書的可靠方法

我加入的唯一路線是:

boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23_client); 
ctx.set_default_verify_paths(); <------------- Add default verification paths 
ctx.set_password_callback(&password_callback);  

client c(io_service, ctx, iterator); 

io_service.run(); 

的問題是:使用此代碼與本地安裝的OpenSSH副本(從MSI安裝程序安裝)時,路徑正確地找到和我的證書驗證。當我下載我自己的openSSH倉庫副本並編譯它時,這一行不再起作用,並且我沒有根CA證書來驗證我自己的(因此它失敗了)。

因爲我想最終將這些客戶端分佈到客戶機器上,所以我想避免設置像SSL_CERT_DIR之類的環境變量。如何可靠地找到具有boost asio的根CA證書,或者從源編譯中配置我的openSSH以查找它們?

回答

2

您可以從Windows CA存儲加載根CA.它已包含「默認」可信根CA證書,可通過certmgr進行管理。使用以下函數替換窗口下的set_default_verify_paths:

#include <boost/asio/ssl/context.hpp> 
#include <wincrypt.h> 

void add_windows_root_certs(boost::asio::ssl::context &ctx) 
{ 
    HCERTSTORE hStore = CertOpenSystemStore(0, "ROOT"); 
    if (hStore == NULL) { 
     return; 
    } 

    X509_STORE *store = X509_STORE_new(); 
    PCCERT_CONTEXT pContext = NULL; 
    while ((pContext = CertEnumCertificatesInStore(hStore, pContext)) != NULL) { 
     X509 *x509 = d2i_X509(NULL, 
           (const unsigned char **)&pContext->pbCertEncoded, 
           pContext->cbCertEncoded); 
     if(x509 != NULL) { 
      X509_STORE_add_cert(store, x509); 
      X509_free(x509); 
     } 
    } 

    CertFreeCertificateContext(pContext); 
    CertCloseStore(hStore, 0); 

    SSL_CTX_set_cert_store(ctx.native_handle(), store); 
} 

這將從windows ca store中加載證書。它使用d2i_X509將它們轉換爲內部OpenSSL格式並將它們添加到OpenSSL X509_STORE。然後,SSL_CTX_set_cert_store將該存儲附加到boost ssl上下文。你可以用它來建立你的SSL上下文:

namespace ssl = boost::asio::ssl; 
ssl::context ctx(ssl::context::tlsv12_client); 
ctx.set_options(ssl::context::default_workarounds 
          | ssl::context::no_sslv2 
          | ssl::context::no_sslv3 
          | ssl::context::tlsv12_client); 

#if BOOST_OS_WINDOWS 
add_windows_root_certs(ctx); 
#else 
ctx.set_default_verify_paths(); 
#endif 

ctx.set_password_callback(&password_callback); 

client c(io_service, ctx, iterator); 

io_service.run(); 

注意:您可能會需要crypt32添加到您的鏈接庫。

注2:BOOST_OS_WINDOWS需要Boost Predef