2012-02-01 229 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.前缀。