Skip to content

Instantly share code, notes, and snippets.

@thom-nic
Created March 5, 2013 19:50
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save thom-nic/5093603 to your computer and use it in GitHub Desktop.
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.
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()
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