How to do mutual certificate authentication with httplib2

家住魔仙堡 提交于 2019-12-09 05:47:15

问题


I'm using httplib2 to make a request from my server to another web service. We want to use mutual certificate authentication. I see how to use a certificate for the outgoing connection (h.set_certificate), but how do I check the certificate used by the answering server?

This ticket seems to indicate that httplib2 doesn't do it itself, and has only vague suggestions about where to look.

Is it possible? Am I going to have to hack at a lower level?


回答1:


Here's the code my co-worker Dave St. Germain wrote to solve the problem:

import ssl
import socket
from httplib2 import has_timeout
import httplib2
import socks


class CertificateValidationError(httplib2.HttpLib2Error):
    pass


def validating_sever_factory(ca_cert_file):
    # we need to define a closure here because we don't control
    # the arguments this class is instantiated with
    class ValidatingHTTPSConnection(httplib2.HTTPSConnectionWithTimeout):

        def connect(self):
            # begin copypasta from HTTPSConnectionWithTimeout
            "Connect to a host on a given (SSL) port."

            if self.proxy_info and self.proxy_info.isgood():
                sock = socks.socksocket(socket.AF_INET, socket.SOCK_STREAM)
                sock.setproxy(*self.proxy_info.astuple())
            else:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

            if has_timeout(self.timeout):
                sock.settimeout(self.timeout)
            sock.connect((self.host, self.port))
            # end copypasta


            try:
                self.sock = ssl.wrap_socket(sock,
                            self.key_file,
                            self.cert_file,
                            cert_reqs=ssl.CERT_REQUIRED,
                            ca_certs=ca_cert_file
                            )
            except ssl.SSLError:
                # we have to capture the exception here and raise later because 
                # httplib2 tries to ignore exceptions on connect
                import sys
                self._exc_info = sys.exc_info()
                raise
            else:
                self._exc_info = None

                # this might be redundant
                server_cert = self.sock.getpeercert()
                if not server_cert:
                    raise CertificateValidationError(repr(server_cert))

        def getresponse(self):
            if not self._exc_info:
                return httplib2.HTTPSConnectionWithTimeout.getresponse(self)
            else:
                raise self._exc_info[1], None, self._exc_info[2]
    return ValidatingHTTPSConnection


def do_request(url,
        method='GET',
        body=None,
        headers=None,
        keyfile=None,
        certfile=None,
        ca_certs=None,
        proxy_info=None,
        timeout=30):
    """
    makes an http/https request, with optional client certificate and server
    certificate verification.
    returns response, content
    """
    kwargs = {}
    h = httplib2.Http(proxy_info=proxy_info, timeout=timeout)
    is_ssl = url.startswith('https')
    if is_ssl and ca_certs:
        kwargs['connection_type'] = validating_sever_factory(ca_certs)

    if is_ssl and keyfile and certfile:
        h.add_certificate(keyfile, certfile, '')
    return h.request(url, method=method, body=body, headers=headers, **kwargs)



回答2:


perhaps things have changed since your question, I am able to do mutual authentication with httplib2 v0.7, as below:

import httplib2

h=httplib2.Http(ca_certs='ca.crt')
h.add_certificate(key='client_private_key.pem', cert='cert_client.pem', domain='')
try: resp, cont = h.request('https://mytest.com/cgi-bin/test.cgi')
except Exception as e: print e

Note the domain='' argument, this is the only way I could make it work



来源:https://stackoverflow.com/questions/2363105/how-to-do-mutual-certificate-authentication-with-httplib2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!