2012-02-01 227 views
15

我正在編寫一個需要在客戶端瀏覽器中安裝證書的應用程序。我在PyOpenSSL文檔中爲「Context」對象找到了這一點,但我無法看到有關回調應如何驗證證書的任何內容,只是它應該以某種方式進行驗證。驗證PyOpenSSL中的客戶端證書

 
    set_verify(mode, callback) 
     Set the verification flags for this Context object to mode and 
     specify that callback should be used for verification callbacks. 
     mode should be one of VERIFY_NONE and VERIFY_PEER. If 
     VERIFY_PEER is used, mode can be OR:ed with 
     VERIFY_FAIL_IF_NO_PEER_CERT and VERIFY_CLIENT_ONCE to further 
     control the behaviour. callback should take five arguments: A 
     Connection object, an X509 object, and three integer variables, 
     which are in turn potential error number, error depth and return 
     code. callback should return true if verification passes and 
     false otherwise. 

我告訴我的地方(自簽名)上下文對象鍵(見下文),所以我想我不明白爲什麼這還不夠的庫,以檢查是否由客戶端提供的證書是一個有效的。這個回調函數應該做什麼?

class SecureAJAXServer(PlainAJAXServer): 
    def __init__(self, server_address, HandlerClass): 
     BaseServer.__init__(self, server_address, HandlerClass) 
     ctx = SSL.Context(SSL.SSLv23_METHOD) 
     ctx.use_privatekey_file ('keys/server.key') 
     ctx.use_certificate_file('keys/server.crt') 
     ctx.set_session_id("My_experimental_AJAX_Server") 
     ctx.set_verify(SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT | SSL.VERIFY_CLIENT_ONCE, callback_func) 
     self.socket = SSL.Connection(ctx, socket.socket(self.address_family, self.socket_type)) 
     self.server_bind() 
     self.server_activate() 

警告:編碼樂趣在這裏,高清不是一個職業,所以如果我的Q揭示我總跛行,天真和/或缺乏基本的瞭解,當涉及到SSL,請不要太粗糙了!

謝謝:)

羅傑

回答

6

OpenSSL documentationset_verify(),您所關心的關鍵是返回代碼

回調應該採取五個參數:一個連接對象,X509 對象和三個整數變量,這些變量又是潛在的錯誤 號碼,錯誤深度和返回碼。如果驗證通過,回調應該返回true 否則返回false。

有一個全方位的工作的例子,顯示更多或更少,你想要做什麼:When are client certificates verified?

基本上可以忽略第4個參數,只是檢查像第五個參數的返回碼的值所以:

from OpenSSL.SSL import Context, Connection, SSLv23_METHOD 
from OpenSSL.SSL import VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE 

class SecureAJAXServer(BaseServer): 
    def verify_callback(connection, x509, errnum, errdepth, ok): 
     if not ok: 
      print "Bad Certs" 
     else: 
      print "Certs are fine" 
     return ok 

    def __init__(self, server_address, HandlerClass): 
     BaseServer.__init__(self, server_address, HandlerClass) 
     ctx = Context(SSLv23_METHOD) 
     ctx.use_privatekey_file ('keys/server.key') 
     ctx.use_certificate_file('keys/server.crt') 
     ctx.set_session_id("My_experimental_AJAX_Server") 
     ctx.set_verify(VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE, verify_callback) 
     self.socket = Connection(ctx, socket.socket(self.address_family, self.socket_type)) 
     self.server_bind() 
     self.server_activate() 

注:我做了一個其他變化,這是from OpenSSL.SSL import ...簡化代碼一點,而我是測試它,這樣你就不必在每個導入符號前面的SSL.前綴。