Created
March 5, 2013 19:50
-
-
Save thom-nic/5093603 to your computer and use it in GitHub Desktop.
Handler for authenticating HTTPS connections with urllib2. (Python 2.x) Note that the 'ciphers' option in ssl.wrap_socket is python 2.7 only.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging, urllib2 | |
import https | |
client_cert_key = None # file path | |
client_cert_pem = None #file path | |
ca_certs = None # file path | |
handlers = [] | |
handlers.append( HTTPSClientAuthHandler( | |
key = client_cert_key, | |
cert = client_cert_pem, | |
ca_certs = ca_certs, | |
ssl_version = ssl.PROTOCOL_TLSv1, | |
ciphers = 'TLS_RSA_WITH_AES_256_CBC_SHA' ) ) | |
http = urllib2.build_opener(*handlers) | |
# do it! | |
resp = http.open('https://something.com') | |
data = resp.read() | |
resp.close() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import urllib2, httplib, ssl, socket | |
DEFAULT_HTTP_TIMEOUT = 10 #seconds | |
# http://code.activestate.com/recipes/577548-https-httplib-client-connection-with-certificate-v/ | |
# http://stackoverflow.com/questions/1875052/using-paired-certificates-with-urllib2 | |
class HTTPSClientAuthHandler(urllib2.HTTPSHandler): | |
''' | |
Allows sending a client certificate with the HTTPS connection. | |
This version also validates the peer (server) certificate since, well... | |
WTF IS THE POINT OF SSL IF YOU DON"T AUTHENTICATE THE PERSON YOU"RE TALKING TO!??! | |
''' | |
def __init__(self, key=None, cert=None, ca_certs=None, ssl_version=None, ciphers=None): | |
urllib2.HTTPSHandler.__init__(self) | |
self.key = key | |
self.cert = cert | |
self.ca_certs = ca_certs | |
self.ssl_version = ssl_version | |
self.ciphers = ciphers | |
def https_open(self, req): | |
# Rather than pass in a reference to a connection class, we pass in | |
# a reference to a function which, for all intents and purposes, | |
# will behave as a constructor | |
return self.do_open(self.get_connection, req) | |
def get_connection(self, host, timeout=DEFAULT_HTTP_TIMEOUT): | |
return HTTPSConnection( host, | |
key_file = self.key, | |
cert_file = self.cert, | |
timeout = timeout, | |
ciphers = self.ciphers, | |
ca_certs = self.ca_certs, | |
ssl_version = self.ssl_version ) | |
class HTTPSConnection(httplib.HTTPSConnection): | |
''' | |
Overridden to allow peer certificate validation, configuration | |
of SSL/ TLS version and cipher selection. See: | |
http://hg.python.org/cpython/file/c1c45755397b/Lib/httplib.py#l1144 | |
and `ssl.wrap_socket()` | |
''' | |
def __init__(self, host, **kwargs): | |
self.ciphers = kwargs.pop('ciphers',None) | |
self.ca_certs = kwargs.pop('ca_certs',None) | |
self.ssl_version = kwargs.pop('ssl_version',ssl.PROTOCOL_SSLv23) | |
httplib.HTTPSConnection.__init__(self,host,**kwargs) | |
def connect(self): | |
sock = socket.create_connection( (self.host, self.port), self.timeout ) | |
if self._tunnel_host: | |
self.sock = sock | |
self._tunnel() | |
# with open(self.ca_certs,'r') as test: | |
# logging.info('+++++++++++++++ CA CERTS: %s ++++++++++++++', self.ca_certs) | |
self.sock = ssl.wrap_socket( sock, | |
keyfile = self.key_file, | |
certfile = self.cert_file, | |
ca_certs = self.ca_certs, | |
# ciphers = self.ciphers, # DOH! This is Python 2.7-only! | |
cert_reqs = ssl.CERT_REQUIRED if self.ca_certs else ssl.CERT_NONE, | |
ssl_version = self.ssl_version ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment