2010-02-13 183 views
9

我正在寫一個OpenSSL庫的小程序,該程序假設與SSLv3服務器建立連接。此服務器分配一個自簽名證書,導致握手失敗,並顯示以下消息:「sslv3警報握手失敗,證書鏈中的自簽名證書」。OpenSSL忽略自簽名證書錯誤

有沒有辦法強制連接進行?我已經打過電話SSL_CTX_set_verify像這樣:

SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); 

但它似乎並沒有改變任何東西。

有什麼建議嗎?

+0

'SSL_VERIFY_NONE'完全禁用證書驗證。你可能不想這樣做,因爲這會讓你容易受到MITM攻擊。正確的做法是將自簽名證書添加到可信證書列表中。 (請參閱SSL_CTX_load_verify_locations()。) – 2017-02-03 10:52:43

+0

順便說一句,錯誤消息並不意味着服務器的證書是自簽名的。這意味着您不信任根CA的證書: ** X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ** _證書鏈中存在自簽名證書。可以使用不受信任的證書構建證書鏈,但無法在本地找到根CA. 根CA證書始終是自簽名的。 – 2017-02-03 11:15:02

回答

4

默認情況下OpenSSL的走證書鏈,並嘗試來驗證每一個步驟,SSL_set_verify()不改變這種狀況,看塔人頁。引用它:執行

實際驗證程序或者使用 內置驗證過程或使用另一應用程序提供 驗證函數SSL_CTX_set_cert_verify_callback(3)設置。

因此,解決方案是創建一個簡單的回調,並設置一個,這樣就覆蓋所有證書鏈行走:

static int always_true_callback(X509_STORE_CTX *ctx, void *arg) 
{ 
    return 1; 
} 

SSL_CTX_set_cert_verify_callback(CTX, always_true_callback); 
+2

只需引用文本下面幾段:'如果未指定verify_callback,則將使用默認回調。它的返回值與preverify_ok相同,因此,如果設置了SSL_VERIFY_PEER,則任何驗證失敗都將導致終止TLS/SSL握手併發出警報消息。「 您的答案不正確,將驗證模式設置爲SSL_VERIFY_NONE應該足夠了。 – Spidey 2015-01-15 15:24:10

+1

@Spidey你看過這個問題嗎?它被認爲SSL_VERIFY_NONE *不夠*。你自己嘗試過嗎?僅供參考,您所引用的手冊適用於'SSL_CTX_set_verify()'。但即使* set_verify *回調總是成功,驗證失敗的方式還有很多,這就是爲什麼您必須使用'SSL_CTX_set_cert_verify_callback()'設置更通用的回調。 – jimis 2015-01-19 10:05:31

+0

總是返回'1'完全禁用證書驗證。這與設置'SSL_VERIFY_NONE'相同。 (即@Spidey是對的。)你可能不想這樣做,因爲這會讓你容易受到MITM攻擊。正確的做法是將自簽名證書添加到可信證書列表中。 (請參閱SSL_CTX_load_verify_locations()。) – 2017-02-03 10:54:51

0

您是否嘗試過設置SSL_set_verify?

SSL_set_verify(s, SSL_VERIFY_NONE, NULL); 
+0

試過,沒有變化 – Ramsey 2010-02-13 09:24:17

+0

更多的代碼在這一點上會很好。 – Xorlev 2010-02-13 09:37:49

+0

感謝您的回覆。我嘗試了所有的建議,但仍然沒有運氣。我在這裏粘貼了程序的關鍵部分: http://pastebin.com/m78497bf3 – Ramsey 2010-02-13 17:32:14

2

您是否嘗試過給你的應用程序服務器的CA證書,以便您的應用程序可以驗證證書鏈?

+0

正確,但在此情況下,簽名證書,OP必須讓他的應用信任的不是CA證書,而是服務器的證書。 – 2017-02-03 11:02:11

+0

我的不好,OP是錯的。服務器證書不是自簽名的。問題中包含的錯誤消息顯示錯誤是'X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN',這意味着所提到的自簽名證書不是服務器證書,而是根CA證書。 – 2017-02-03 11:11:06

0

您可以嘗試將自己的回調傳遞給SSL_set_verify(),然後進行自己的驗證。這並不理想,因爲我認爲你需要完成所有的驗證,然後讓自簽名錯誤被忽略,但是你應該能夠計算出標準驗證代碼從OpenSSL源代碼所做的事情,然後簡單地將它拉出來到你自己的驗證回調,並允許特定的錯誤代碼......

+0

如果您打算接受自簽名證書,那麼其餘的驗證步驟無論如何都毫無意義。 – caf 2010-03-02 08:43:10

+0

caf - 可能,是... – 2010-03-02 16:09:02

2

檢查這些OpenSSL的例子:http://www.rtfm.com/openssl-examples/

wclient.c連接到任何HTTPS網頁,例如:

wclient -h www.yahoo.com -p 443 

如果你使用默認安裝運行它,你會得到一個證書錯誤(你可以使用-i標誌繞過證書檢查)。

驗證證書,你需要下載CA證書(威瑞信,Thawte的,Equifax公司等),因此谷歌這個文件cacert.pem,下載並重新命名爲root.pem和你將能夠連接到Web服務器並驗證其證書。

+0

另外,如果要打印證書,請在check_cert(ssl,host)之後插入以下行(在wclient.c中):X509_print_fp(stdout,SSL_get_peer_certificate(ssl)); – 2010-02-18 20:08:24

+0

正確,儘管在這種情況下服務器使用自簽名證書,但OP必須使其應用信任的內容不是CA證書,而是服務器的證書。 – 2017-02-03 11:02:05

+0

我的不好,OP是錯的。服務器證書不是自簽名的。問題中包含的錯誤消息顯示錯誤是'X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN',這意味着所提到的自簽名證書不是服務器證書,而是根CA證書。 – 2017-02-03 11:10:52

0

我的示例客戶端代碼(link)可以正常使用自簽名服務器證書。我所以SSL_connect後,下面的代碼,並有超過自簽名的證書,接受的完全控制在我的客戶

SSL_CTX* ctx = SSL_CTX_new(SSLv3_method()); 

// TCP connection and SSL handshake ... 

/* Check the certificate */ 

rc = SSL_get_verify_result(ssl); 
if(rc != X509_V_OK) { 
    if (rc == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || rc == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) { 
    fprintf(stderr, "self signed certificate\n"); 
    } 
    else { 
    fprintf(stderr, "Certificate verification error: %ld\n", SSL_get_verify_result(ssl)); 
    SSL_CTX_free(ctx); 
    return 0; 
    } 
} 
+0

這會讓你容易受到MITM攻擊!如果你這樣做,任何自簽證書都會被接受。如果證書是可信的,則不會引發您忽略的錯誤。正確的做法是將自簽名證書添加到可信證書列表中。 (請參閱SSL_CTX_load_verify_locations()。) – 2017-02-03 10:59:30

相關問題