Upgrade httplib2 to 10/13/16 HEAD for a few fixes

This commit is contained in:
Jay Lee
2016-10-13 15:19:35 -04:00
parent dabb3362c8
commit 801078e618
8 changed files with 445 additions and 182 deletions

View File

@@ -20,7 +20,8 @@ __contributors__ = ["Thomas Broyer (t.broyer@ltgt.net)",
"Jonathan Feinberg",
"Blair Zajac",
"Sam Ruby",
"Louis Nyffenegger"]
"Louis Nyffenegger",
"Alex Yu"]
__license__ = "MIT"
__version__ = "0.9.2"
@@ -67,21 +68,32 @@ except ImportError:
try:
import ssl # python 2.6
ssl_SSLError = ssl.SSLError
def _ssl_wrap_socket(sock, key_file, cert_file,
disable_validation, ca_certs):
def _ssl_wrap_socket(sock, key_file, cert_file, disable_validation,
ca_certs, ssl_version, hostname):
if disable_validation:
cert_reqs = ssl.CERT_NONE
else:
cert_reqs = ssl.CERT_REQUIRED
# We should be specifying SSL version 3 or TLS v1, but the ssl module
# doesn't expose the necessary knobs. So we need to go with the default
# of SSLv23.
return ssl.wrap_socket(sock, keyfile=key_file, certfile=cert_file,
cert_reqs=cert_reqs, ca_certs=ca_certs)
if ssl_version is None:
ssl_version = ssl.PROTOCOL_SSLv23
if hasattr(ssl, 'SSLContext'): # Python 2.7.9
context = ssl.SSLContext(ssl_version)
context.verify_mode = cert_reqs
context.check_hostname = (cert_reqs != ssl.CERT_NONE)
if cert_file:
context.load_cert_chain(cert_file, key_file)
if ca_certs:
context.load_verify_locations(ca_certs)
return context.wrap_socket(sock, server_hostname=hostname)
else:
return ssl.wrap_socket(sock, keyfile=key_file, certfile=cert_file,
cert_reqs=cert_reqs, ca_certs=ca_certs,
ssl_version=ssl_version)
except (AttributeError, ImportError):
ssl_SSLError = None
def _ssl_wrap_socket(sock, key_file, cert_file,
disable_validation, ca_certs):
def _ssl_wrap_socket(sock, key_file, cert_file, disable_validation,
ca_certs, ssl_version, hostname):
if not disable_validation:
raise CertificateValidationUnsupported(
"SSL certificate validation is not supported without "
@@ -162,6 +174,8 @@ class CertificateHostnameMismatch(SSLHandshakeError):
self.host = host
self.cert = cert
class NotRunningAppEngineEnvironment(HttpLib2Error): pass
# Open Items:
# -----------
# Proxy support
@@ -749,7 +763,7 @@ class ProxyInfo(object):
bypass_hosts = ()
def __init__(self, proxy_type, proxy_host, proxy_port,
proxy_rdns=True, proxy_user=None, proxy_pass=None):
proxy_rdns=True, proxy_user=None, proxy_pass=None, proxy_headers=None):
"""
Args:
proxy_type: The type of proxy server. This must be set to one of
@@ -770,6 +784,8 @@ class ProxyInfo(object):
proxy_user: The username used to authenticate with the proxy server.
proxy_pass: The password used to authenticate with the proxy server.
proxy_headers: Additional or modified headers for the proxy connect request.
"""
self.proxy_type = proxy_type
self.proxy_host = proxy_host
@@ -777,10 +793,11 @@ class ProxyInfo(object):
self.proxy_rdns = proxy_rdns
self.proxy_user = proxy_user
self.proxy_pass = proxy_pass
self.proxy_headers = proxy_headers
def astuple(self):
return (self.proxy_type, self.proxy_host, self.proxy_port,
self.proxy_rdns, self.proxy_user, self.proxy_pass)
self.proxy_rdns, self.proxy_user, self.proxy_pass, self.proxy_headers)
def isgood(self):
return (self.proxy_host != None) and (self.proxy_port != None)
@@ -858,6 +875,7 @@ def proxy_info_from_url(url, method='http'):
proxy_port = port,
proxy_user = username or None,
proxy_pass = password or None,
proxy_headers = None,
)
@@ -885,7 +903,7 @@ class HTTPConnectionWithTimeout(httplib.HTTPConnection):
msg = "getaddrinfo returns an empty list"
if self.proxy_info and self.proxy_info.isgood():
use_proxy = True
proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass = self.proxy_info.astuple()
proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass, proxy_headers = self.proxy_info.astuple()
host = proxy_host
port = proxy_port
@@ -900,7 +918,7 @@ class HTTPConnectionWithTimeout(httplib.HTTPConnection):
try:
if use_proxy:
self.sock = socks.socksocket(af, socktype, proto)
self.sock.setproxy(proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass)
self.sock.setproxy(proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass, proxy_headers)
else:
self.sock = socket.socket(af, socktype, proto)
self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
@@ -911,14 +929,14 @@ class HTTPConnectionWithTimeout(httplib.HTTPConnection):
if self.debuglevel > 0:
print "connect: (%s, %s) ************" % (self.host, self.port)
if use_proxy:
print "proxy: %s ************" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass))
print "proxy: %s ************" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass, proxy_headers))
self.sock.connect((self.host, self.port) + sa[2:])
except socket.error, msg:
if self.debuglevel > 0:
print "connect fail: (%s, %s)" % (self.host, self.port)
if use_proxy:
print "proxy: %s" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass))
print "proxy: %s" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass, proxy_headers))
if self.sock:
self.sock.close()
self.sock = None
@@ -938,7 +956,8 @@ class HTTPSConnectionWithTimeout(httplib.HTTPSConnection):
"""
def __init__(self, host, port=None, key_file=None, cert_file=None,
strict=None, timeout=None, proxy_info=None,
ca_certs=None, disable_ssl_certificate_validation=False):
ca_certs=None, disable_ssl_certificate_validation=False,
ssl_version=None):
httplib.HTTPSConnection.__init__(self, host, port=port,
key_file=key_file,
cert_file=cert_file, strict=strict)
@@ -949,6 +968,7 @@ class HTTPSConnectionWithTimeout(httplib.HTTPSConnection):
self.ca_certs = ca_certs
self.disable_ssl_certificate_validation = \
disable_ssl_certificate_validation
self.ssl_version = ssl_version
# The following two methods were adapted from https_wrapper.py, released
# with the Google Appengine SDK at
@@ -1007,7 +1027,7 @@ class HTTPSConnectionWithTimeout(httplib.HTTPSConnection):
msg = "getaddrinfo returns an empty list"
if self.proxy_info and self.proxy_info.isgood():
use_proxy = True
proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass = self.proxy_info.astuple()
proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass, proxy_headers = self.proxy_info.astuple()
host = proxy_host
port = proxy_port
@@ -1023,7 +1043,7 @@ class HTTPSConnectionWithTimeout(httplib.HTTPSConnection):
if use_proxy:
sock = socks.socksocket(family, socktype, proto)
sock.setproxy(proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass)
sock.setproxy(proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass, proxy_headers)
else:
sock = socket.socket(family, socktype, proto)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
@@ -1033,11 +1053,12 @@ class HTTPSConnectionWithTimeout(httplib.HTTPSConnection):
sock.connect((self.host, self.port))
self.sock =_ssl_wrap_socket(
sock, self.key_file, self.cert_file,
self.disable_ssl_certificate_validation, self.ca_certs)
self.disable_ssl_certificate_validation, self.ca_certs,
self.ssl_version, self.host)
if self.debuglevel > 0:
print "connect: (%s, %s)" % (self.host, self.port)
if use_proxy:
print "proxy: %s" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass))
print "proxy: %s" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass, proxy_headers))
if not self.disable_ssl_certificate_validation:
cert = self.sock.getpeercert()
hostname = self.host.split(':', 0)[0]
@@ -1065,7 +1086,7 @@ class HTTPSConnectionWithTimeout(httplib.HTTPSConnection):
if self.debuglevel > 0:
print "connect fail: (%s, %s)" % (self.host, self.port)
if use_proxy:
print "proxy: %s" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass))
print "proxy: %s" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass, proxy_headers))
if self.sock:
self.sock.close()
self.sock = None
@@ -1079,8 +1100,61 @@ SCHEME_TO_CONNECTION = {
'https': HTTPSConnectionWithTimeout
}
def _new_fixed_fetch(validate_certificate):
def fixed_fetch(url, payload=None, method="GET", headers={},
allow_truncated=False, follow_redirects=True,
deadline=None):
if deadline is None:
deadline = socket.getdefaulttimeout()
return fetch(url, payload=payload, method=method, headers=headers,
allow_truncated=allow_truncated,
follow_redirects=follow_redirects, deadline=deadline,
validate_certificate=validate_certificate)
return fixed_fetch
class AppEngineHttpConnection(httplib.HTTPConnection):
"""Use httplib on App Engine, but compensate for its weirdness.
The parameters key_file, cert_file, proxy_info, ca_certs,
disable_ssl_certificate_validation, and ssl_version are all dropped on
the ground.
"""
def __init__(self, host, port=None, key_file=None, cert_file=None,
strict=None, timeout=None, proxy_info=None, ca_certs=None,
disable_ssl_certificate_validation=False,
ssl_version=None):
httplib.HTTPConnection.__init__(self, host, port=port,
strict=strict, timeout=timeout)
class AppEngineHttpsConnection(httplib.HTTPSConnection):
"""Same as AppEngineHttpConnection, but for HTTPS URIs.
The parameters proxy_info, ca_certs, disable_ssl_certificate_validation,
and ssl_version are all dropped on the ground.
"""
def __init__(self, host, port=None, key_file=None, cert_file=None,
strict=None, timeout=None, proxy_info=None, ca_certs=None,
disable_ssl_certificate_validation=False,
ssl_version=None):
httplib.HTTPSConnection.__init__(self, host, port=port,
key_file=key_file,
cert_file=cert_file, strict=strict,
timeout=timeout)
self._fetch = _new_fixed_fetch(
not disable_ssl_certificate_validation)
# Use a different connection object for Google App Engine
try:
server_software = os.environ.get('SERVER_SOFTWARE')
if not server_software:
raise NotRunningAppEngineEnvironment()
elif not (server_software.startswith('Google App Engine/') or
server_software.startswith('Development/')):
raise NotRunningAppEngineEnvironment()
try:
from google.appengine.api import apiproxy_stub_map
if apiproxy_stub_map.apiproxy.GetStub('urlfetch') is None:
@@ -1094,48 +1168,12 @@ try:
from google3.apphosting.api.urlfetch import fetch
from google3.apphosting.api.urlfetch import InvalidURLError
def _new_fixed_fetch(validate_certificate):
def fixed_fetch(url, payload=None, method="GET", headers={},
allow_truncated=False, follow_redirects=True,
deadline=None):
if deadline is None:
deadline = socket.getdefaulttimeout() or 5
return fetch(url, payload=payload, method=method, headers=headers,
allow_truncated=allow_truncated,
follow_redirects=follow_redirects, deadline=deadline,
validate_certificate=validate_certificate)
return fixed_fetch
class AppEngineHttpConnection(httplib.HTTPConnection):
"""Use httplib on App Engine, but compensate for its weirdness.
The parameters key_file, cert_file, proxy_info, ca_certs, and
disable_ssl_certificate_validation are all dropped on the ground.
"""
def __init__(self, host, port=None, key_file=None, cert_file=None,
strict=None, timeout=None, proxy_info=None, ca_certs=None,
disable_ssl_certificate_validation=False):
httplib.HTTPConnection.__init__(self, host, port=port,
strict=strict, timeout=timeout)
class AppEngineHttpsConnection(httplib.HTTPSConnection):
"""Same as AppEngineHttpConnection, but for HTTPS URIs."""
def __init__(self, host, port=None, key_file=None, cert_file=None,
strict=None, timeout=None, proxy_info=None, ca_certs=None,
disable_ssl_certificate_validation=False):
httplib.HTTPSConnection.__init__(self, host, port=port,
key_file=key_file,
cert_file=cert_file, strict=strict,
timeout=timeout)
self._fetch = _new_fixed_fetch(
not disable_ssl_certificate_validation)
# Update the connection classes to use the Googel App Engine specific ones.
SCHEME_TO_CONNECTION = {
'http': AppEngineHttpConnection,
'https': AppEngineHttpsConnection
}
except (ImportError, AttributeError):
except (ImportError, AttributeError, NotRunningAppEngineEnvironment):
pass
@@ -1155,7 +1193,8 @@ class Http(object):
"""
def __init__(self, cache=None, timeout=None,
proxy_info=proxy_info_from_environment,
ca_certs=None, disable_ssl_certificate_validation=False):
ca_certs=None, disable_ssl_certificate_validation=False,
ssl_version=None):
"""If 'cache' is a string then it is used as a directory name for
a disk cache. Otherwise it must be an object that supports the
same interface as FileCache.
@@ -1178,11 +1217,14 @@ class Http(object):
If disable_ssl_certificate_validation is true, SSL cert validation will
not be performed.
By default, ssl.PROTOCOL_SSLv23 will be used for the ssl version.
"""
self.proxy_info = proxy_info
self.ca_certs = ca_certs
self.disable_ssl_certificate_validation = \
disable_ssl_certificate_validation
self.ssl_version = ssl_version
# Map domain name to an httplib connection
self.connections = {}
@@ -1285,9 +1327,10 @@ class Http(object):
err = getattr(e, 'args')[0]
else:
err = e.errno
if err == errno.ECONNREFUSED: # Connection refused
raise
if err in (errno.ENETUNREACH, errno.EADDRNOTAVAIL) and i < RETRIES:
continue # retry on potentially transient socket errors
raise
except httplib.HTTPException:
# Just because the server closed the connection doesn't apparently mean
# that the server didn't send a response.
@@ -1477,14 +1520,16 @@ class Http(object):
proxy_info=proxy_info,
ca_certs=self.ca_certs,
disable_ssl_certificate_validation=
self.disable_ssl_certificate_validation)
self.disable_ssl_certificate_validation,
ssl_version=self.ssl_version)
else:
conn = self.connections[conn_key] = connection_type(
authority, timeout=self.timeout,
proxy_info=proxy_info,
ca_certs=self.ca_certs,
disable_ssl_certificate_validation=
self.disable_ssl_certificate_validation)
self.disable_ssl_certificate_validation,
ssl_version=self.ssl_version)
else:
conn = self.connections[conn_key] = connection_type(
authority, timeout=self.timeout,

View File

@@ -102,28 +102,6 @@ A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
-----END CERTIFICATE-----
# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority
# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority
# Label: "Verisign Class 3 Public Primary Certification Authority"
# Serial: 149843929435818692848040365716851702463
# MD5 Fingerprint: 10:fc:63:5d:f6:26:3e:0d:f3:25:be:5f:79:cd:67:67
# SHA1 Fingerprint: 74:2c:31:92:e6:07:e4:24:eb:45:49:54:2b:e1:bb:c5:3e:61:74:e2
# SHA256 Fingerprint: e7:68:56:34:ef:ac:f6:9a:ce:93:9a:6b:25:5b:7b:4f:ab:ef:42:93:5b:50:a2:65:ac:b5:cb:60:27:e4:4e:70
-----BEGIN CERTIFICATE-----
MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do
lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc
AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k
-----END CERTIFICATE-----
# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority - G2/(c) 1998 VeriSign, Inc. - For authorized use only/VeriSign Trust Network
# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority - G2/(c) 1998 VeriSign, Inc. - For authorized use only/VeriSign Trust Network
# Label: "Verisign Class 3 Public Primary Certification Authority - G2"
@@ -1800,28 +1778,6 @@ kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC
FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
-----END CERTIFICATE-----
# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority
# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority
# Label: "Verisign Class 3 Public Primary Certification Authority"
# Serial: 80507572722862485515306429940691309246
# MD5 Fingerprint: ef:5a:f1:33:ef:f1:cd:bb:51:02:ee:12:14:4b:96:c4
# SHA1 Fingerprint: a1:db:63:93:91:6f:17:e4:18:55:09:40:04:15:c7:02:40:b0:ae:6b
# SHA256 Fingerprint: a4:b6:b3:99:6f:c2:f3:06:b3:fd:86:81:bd:63:41:3d:8c:50:09:cc:4f:a3:29:c2:cc:f0:e2:fa:1b:14:03:05
-----BEGIN CERTIFICATE-----
MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i
2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ
2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ
-----END CERTIFICATE-----
# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
# Label: "GlobalSign Root CA - R3"
@@ -2181,3 +2137,31 @@ IxKVCCIcl85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoo
hdVddLHRDiBYmxOlsGOm7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulr
so8uBtjRkcfGEvRM/TAXw8HaOFvjqermobp573PYtlNXLfbQ4ddI
-----END CERTIFICATE-----
# Issuer: O=Digital Signature Trust Co., CN=DST Root CA X3
# Subject: O=Digital Signature Trust Co., CN=DST Root CA X3
# Label: "IdenTrust DST Root CA X3"
# Serial: 44AFB080D6A327BA893039862EF8406B
# MD5 Fingerprint: 41:03:52:DC:0F:F7:50:1B:16:F0:02:8E:BA:6F:45:C5
# SHA1 Fingerprint: DA:C9:02:4F:54:D8:F6:DF:94:93:5F:B1:73:26:38:CA:6A:D7:7C:13
# SHA256 Fingerprint: 06:87:26:03:31:A7:24:03:D9:09:F1:05:E6:9B:CF:0D:32:E1:BD:24:93:FF:C6:D9:20:6D:11:BC:D6:77:07:39
-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
-----END CERTIFICATE-----

View File

@@ -177,7 +177,7 @@ class socksocket(socket.socket):
auth = self.__proxy[4] + ":" + self.__proxy[5]
return "Proxy-Authorization: Basic " + base64.b64encode(auth)
def setproxy(self, proxytype=None, addr=None, port=None, rdns=True, username=None, password=None):
def setproxy(self, proxytype=None, addr=None, port=None, rdns=True, username=None, password=None, headers=None):
"""setproxy(proxytype, addr[, port[, rdns[, username[, password]]]])
Sets the proxy to be used.
proxytype - The type of the proxy to be used. Three types
@@ -193,8 +193,9 @@ class socksocket(socket.socket):
The default is no authentication.
password - Password to authenticate with to the server.
Only relevant when username is also provided.
headers - Additional or modified headers for the proxy connect request.
"""
self.__proxy = (proxytype, addr, port, rdns, username, password)
self.__proxy = (proxytype, addr, port, rdns, username, password, headers)
def __negotiatesocks5(self, destaddr, destport):
"""__negotiatesocks5(self,destaddr,destport)
@@ -365,8 +366,17 @@ class socksocket(socket.socket):
else:
addr = destaddr
headers = ["CONNECT ", addr, ":", str(destport), " HTTP/1.1\r\n"]
headers += ["Host: ", destaddr, "\r\n"]
if (self.__proxy[4] != None and self.__proxy[5] != None):
wrote_host_header = False
wrote_auth_header = False
if self.__proxy[6] != None:
for key, val in self.__proxy[6].iteritems():
headers += [key, ": ", val, "\r\n"]
wrote_host_header = (key.lower() == "host")
wrote_auth_header = (key.lower() == "proxy-authorization")
if not wrote_host_header:
headers += ["Host: ", destaddr, "\r\n"]
if not wrote_auth_header:
if (self.__proxy[4] != None and self.__proxy[5] != None):
headers += [self.__getauthheader(), "\r\n"]
headers.append("\r\n")
self.sendall("".join(headers).encode())

View File

@@ -2,6 +2,7 @@ import logging
import os
import select
import SimpleHTTPServer
import socket
import SocketServer
import threading
@@ -27,11 +28,23 @@ class ShutdownServer(SocketServer.TCPServer):
BaseServer supports the shutdown method directly.
"""
def __init__(self, *args, **kwargs):
def __init__(self, use_tls, *args, **kwargs):
self.__use_tls = use_tls
SocketServer.TCPServer.__init__(self, *args, **kwargs)
self.__is_shut_down = threading.Event()
self.__serving = False
def server_bind(self):
SocketServer.TCPServer.server_bind(self)
if self.__use_tls:
import ssl
self.socket = ssl.wrap_socket(self.socket,
os.path.join(os.path.dirname(__file__), 'server.key'),
os.path.join(os.path.dirname(__file__), 'server.pem'),
True
)
def serve_forever(self, poll_interval=0.1):
"""Handle one request at a time until shutdown.
@@ -93,8 +106,8 @@ class ShutdownServer(SocketServer.TCPServer):
self.close_request(request)
def start_server(handler):
httpd = ShutdownServer(("", 0), handler)
def start_server(handler, use_tls=False):
httpd = ShutdownServer(use_tls, ("", 0), handler)
threading.Thread(target=httpd.serve_forever).start()
_, port = httpd.socket.getsockname()
return httpd, port

View File

@@ -1,70 +1,19 @@
# Certifcate Authority certificates for validating SSL connections.
#
# This file contains PEM format certificates generated from
# http://mxr.mozilla.org/seamonkey/source/security/nss/lib/ckfw/builtins/certdata.txt
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape security libraries.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1994-2000
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
Comodo CA Limited, CN=Trusted Certificate Services
==================================================
-----BEGIN CERTIFICATE-----
MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb
MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0
aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla
MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD
VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW
fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt
TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL
fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW
1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7
kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G
A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD
VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v
ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo
dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu
Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/
HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32
pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS
jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+
xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn
dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi
MIIDBzCCAe+gAwIBAgIJAIw94zvO7fk1MA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNV
BAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNjA2MDQwMjMxMTRaFw0yNjA2MDIwMjMx
MTRaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAK3YNcDIwK/wlTa0/iBARvDFOncQ6Jkk+Ymql1HXny7v
mWPFWeLXEW+Zw1NrQEx/SIUGvxpRA+QyhTOhu2Gcwvtqilix/dHgaKgqWEcRYu8m
L70uVDPVgB/kfNI8bpXM1Mz8Crjo0tHw5oUSD3wny8SyT6CYlXVmF923L8c2zdN9
n9blFgYwxBq2+q+mqOiDErMFbwHES8FNBSWGBXdE1xjBdITtlfeHezmJhj/ylPW1
7v8HInsv/WqU9DcJYlFxSnK0SZCLFBM/31Ez8O1gCfMlDUFvJoo59GyFqukUjuO1
uB85wpu27gtcLm/J9X1Md71IxbDupV7a0dDoTvbhO4kCAwEAAaNQME4wHQYDVR0O
BBYEFIHgAmwppZSKLz2peyFSO2kwVobNMB8GA1UdIwQYMBaAFIHgAmwppZSKLz2p
eyFSO2kwVobNMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJxz+AU/
Iq8fMEStJ0BgPP1N86W9Jpb7aPMFCYTEZ+nd8hFPhPs4//55J0yIve+1I43MNFFz
yflwwCzrIIhZdkvbsyea6CmlTo4jBc4+ihaDGobYnoNzFhavC47n5kYqJ8Ikyb2W
OMrmNRiaTeSBl0wQmftnnQCbonenjmE1LDuJtE6bCwfFjfLbMxwdWtp/ymOlXsb5
80XcWwcqc12UHWexYwHFzEJmDfncak/8tjHBsLWMJg5p2sVTY9kVt7TYgSIl+mFb
4WVGrqZd2uTlJkRQQ4pCl+D+PKwadHuV6YI7oxkeajjcHCgbK/ANwW28MXYho6t6
aWVIN4bWHrZ38kE=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,146 @@
Private TLS server key file used for HTTPS-related unit tests
-------------------------------------------------------------
Public Key Info:
Public Key Algorithm: RSA
Key Security Level: Medium (2048 bits)
modulus:
00:cc:fb:f1:c5:de:29:29:40:3f:c4:9f:af:da:f6:be
27:f4:6a:00:ae:5a:f2:99:c3:5f:7a:e6:9b:cf:d9:08
34:01:9b:ea:fb:da:b5:d0:b5:b2:4e:60:b4:0d:8d:05
57:e4:2e:04:d4:57:1a:58:3c:0b:3a:ed:67:a3:13:31
58:0a:c2:eb:fd:d6:27:ee:07:95:30:35:b5:98:91:c7
a5:9b:be:a9:7e:ae:fd:73:c3:6b:21:bc:52:f8:ef:71
db:d3:b1:cd:51:df:b3:37:b3:fd:7d:ae:7e:02:38:be
8e:6f:45:55:e5:6d:8a:02:cb:36:c4:17:7a:ea:24:9a
72:8d:1e:75:03:3a:6f:c4:cb:a0:3a:50:56:32:bb:4c
e2:ea:74:f0:96:31:74:b2:c1:03:e8:c3:d4:a3:59:fc
7a:cc:68:35:c4:97:eb:aa:46:fa:64:c3:f9:55:59:22
b5:2b:3c:96:84:c6:d2:7d:b4:9f:b9:9c:af:d1:20:30
7c:e8:60:4e:ee:0a:60:a0:9d:4e:8a:d8:34:74:bd:f2
40:bc:d7:c2:b3:1a:b2:bb:d7:a5:4a:4c:65:94:43:82
16:9a:8f:76:2a:05:b0:9e:3d:a7:fb:e2:c7:78:25:f7
df:ca:08:ee:ec:4f:cd:1a:3c:03:41:ec:91:c5:50:70
4b:
public exponent:
01:00:01:
private exponent:
00:ad:01:83:b8:7d:dd:fd:ab:f5:66:2d:64:ce:08:ec
cb:6a:15:41:87:e6:c8:d5:10:39:78:d0:43:f7:73:f4
e1:77:ee:31:b0:e9:92:04:9a:25:e8:d2:e3:84:80:5e
5f:24:fd:d6:23:a5:74:5d:be:27:b8:4f:80:e5:f9:1f
ef:6f:fd:be:12:1a:7a:cf:02:65:5f:30:25:99:a4:88
7d:74:ea:c1:c1:63:4e:15:33:7d:2b:16:f8:6c:94:23
63:e6:d3:2d:38:89:f6:87:f0:08:e5:d7:ad:10:90:f5
fb:df:5c:04:b8:43:f0:74:95:31:1e:e5:b6:5f:02:0f
bb:55:cb:e1:b5:48:9f:1f:d3:1b:55:a7:bc:39:2b:8e
6d:14:64:3b:bf:e8:ca:6b:af:a9:f3:13:9a:c6:df:15
ef:6d:17:4e:8e:67:6c:41:20:dc:6b:08:0d:b9:14:cd
83:10:62:15:e6:b0:89:5d:37:fb:f6:fd:f0:bf:3b:9c
0b:e9:fd:b8:de:e4:64:90:bf:81:d5:59:2c:30:43:07
b9:60:8c:d0:ac:4f:95:87:aa:38:62:bd:c7:06:a7:c4
2d:08:c1:3c:86:10:c7:8e:1e:df:58:bf:95:ad:39:84
a0:2b:13:e2:18:e6:4a:80:f0:bc:04:50:bd:7d:cf:23
a1:
prime1:
00:f0:8f:ad:2f:c9:64:f3:0d:2c:aa:06:17:05:8f:2f
d5:cb:92:22:90:05:66:3c:78:75:9d:7b:4c:6a:af:a9
1e:d6:28:4f:13:0e:3a:e7:31:49:3d:87:ef:2c:17:70
be:69:b3:42:82:6d:9c:b4:13:0a:e4:bc:8c:0f:1a:bd
04:b6:a0:be:ba:12:15:bf:04:db:91:1c:26:91:d6:d7
f2:ff:2f:0e:5f:96:a1:7c:4b:90:a8:2f:07:2a:cb:dc
40:a0:0b:1d:2a:1d:48:98:bd:4a:6b:9d:5c:69:b0:2b
6e:9b:2c:b2:a9:cb:28:fe:fa:7f:93:eb:20:c8:59:d0
11:
prime2:
00:da:23:c0:3e:82:4c:88:7c:d4:fb:de:24:45:eb:9c
ae:2c:80:2d:52:a6:95:05:33:b9:d8:c1:7b:52:01:62
11:e6:b6:c6:0d:56:a3:68:39:26:9a:90:08:95:12:a9
1c:59:f6:0b:1d:af:6d:c0:c6:9b:2e:7a:62:98:21:36
e1:15:4c:e6:6d:a4:08:ac:90:af:57:86:71:78:2e:0e
cf:59:0f:35:79:cb:6a:a2:e2:30:2a:a8:f2:84:68:bc
8a:f2:48:3b:07:d5:a5:34:f3:d3:ec:25:61:38:f1:0a
07:f7:7e:29:61:e4:15:01:80:e3:7b:bd:63:9c:2e:16
9b:
coefficient:
00:cb:b4:d2:9f:b4:04:db:8c:54:e6:ae:a9:28:a0:c9
70:ad:7a:94:72:5e:86:33:91:d9:43:61:2b:4d:55:e8
b7:25:d2:cd:db:1e:c4:56:95:68:85:e2:9b:4f:31:24
3a:40:06:41:1c:aa:7a:31:13:fa:07:e0:a6:59:c3:d1
d2:c5:2c:6a:82:98:bb:a1:59:c0:6f:ad:d7:2e:ed:5a
64:5f:e6:ea:4a:ee:45:29:d9:0f:96:b3:39:f7:ab:57
97:aa:c9:f7:b6:9c:c0:51:5d:9f:01:2c:ec:58:8d:06
6a:19:d0:33:74:11:6a:25:7c:8f:b7:31:d2:97:05:02
6f:
exp1:
00:87:60:43:95:1d:e0:0a:8b:82:74:18:43:42:64:a7
05:c8:ae:ef:76:5f:23:7e:aa:47:7e:1d:52:0e:c3:d6
07:bd:7b:27:ac:d0:98:43:5c:d0:1b:a9:70:e6:3e:36
bb:61:5e:78:f2:4f:5f:1d:53:8e:10:d5:2e:78:9d:92
7b:a1:8e:ea:66:6a:21:04:c3:66:10:ce:67:c2:30:c6
8c:40:21:2a:14:8e:ff:47:a4:7a:be:ba:e0:6c:ac:16
c1:e3:8e:fd:95:a2:af:25:0d:79:61:00:48:6e:4d:ae
d3:6a:ce:07:a9:57:e4:35:41:a1:24:0b:f1:01:ee:d1
11:
exp2:
00:ca:ca:bd:a7:de:fe:43:4c:b9:bb:c4:d2:37:e6:47
ec:6c:16:65:0c:17:2d:26:7e:e5:e1:2a:4d:f8:f8:ac
31:34:28:ea:89:ef:e7:4d:b7:03:ba:60:f8:79:8d:b5
85:53:e4:b6:84:cc:57:de:05:44:b2:ba:b7:f9:f1:b6
d1:1d:3a:36:65:eb:3e:dd:1e:4c:c3:b3:8a:bd:4d:24
1b:83:11:ee:86:e1:a2:aa:f6:58:0c:f0:af:34:85:21
f2:92:36:b0:1a:22:75:c9:7a:7b:a3:67:44:b0:e8:f4
88:5f:7e:fb:fd:b3:4a:0b:f1:c4:89:7e:91:a1:d9:fe
cd:
Public Key ID: 92:D5:B4:2A:B6:A8:64:67:2C:2A:08:DB:51:B8:97:86:5E:44:CD:6C
Public key's random art:
+--[ RSA 2048]----+
| + . |
| . E o . |
| o . . o |
| . o o . |
| = .= S |
|. +.=o + |
|o++== . |
|++o= |
|o . |
+-----------------+
-----BEGIN RSA PRIVATE KEY-----
MIIEpgIBAAKCAQEAzPvxxd4pKUA/xJ+v2va+J/RqAK5a8pnDX3rmm8/ZCDQBm+r7
2rXQtbJOYLQNjQVX5C4E1FcaWDwLOu1noxMxWArC6/3WJ+4HlTA1tZiRx6Wbvql+
rv1zw2shvFL473Hb07HNUd+zN7P9fa5+Aji+jm9FVeVtigLLNsQXeuokmnKNHnUD
Om/Ey6A6UFYyu0zi6nTwljF0ssED6MPUo1n8esxoNcSX66pG+mTD+VVZIrUrPJaE
xtJ9tJ+5nK/RIDB86GBO7gpgoJ1Oitg0dL3yQLzXwrMasrvXpUpMZZRDghaaj3Yq
BbCePaf74sd4Jfffygju7E/NGjwDQeyRxVBwSwIDAQABAoIBAQCtAYO4fd39q/Vm
LWTOCOzLahVBh+bI1RA5eNBD93P04XfuMbDpkgSaJejS44SAXl8k/dYjpXRdvie4
T4Dl+R/vb/2+Ehp6zwJlXzAlmaSIfXTqwcFjThUzfSsW+GyUI2Pm0y04ifaH8Ajl
160QkPX731wEuEPwdJUxHuW2XwIPu1XL4bVInx/TG1WnvDkrjm0UZDu/6Mprr6nz
E5rG3xXvbRdOjmdsQSDcawgNuRTNgxBiFeawiV03+/b98L87nAvp/bje5GSQv4HV
WSwwQwe5YIzQrE+Vh6o4Yr3HBqfELQjBPIYQx44e31i/la05hKArE+IY5kqA8LwE
UL19zyOhAoGBAPCPrS/JZPMNLKoGFwWPL9XLkiKQBWY8eHWde0xqr6ke1ihPEw46
5zFJPYfvLBdwvmmzQoJtnLQTCuS8jA8avQS2oL66EhW/BNuRHCaR1tfy/y8OX5ah
fEuQqC8HKsvcQKALHSodSJi9SmudXGmwK26bLLKpyyj++n+T6yDIWdARAoGBANoj
wD6CTIh81PveJEXrnK4sgC1SppUFM7nYwXtSAWIR5rbGDVajaDkmmpAIlRKpHFn2
Cx2vbcDGmy56YpghNuEVTOZtpAiskK9XhnF4Lg7PWQ81ectqouIwKqjyhGi8ivJI
OwfVpTTz0+wlYTjxCgf3filh5BUBgON7vWOcLhabAoGBAIdgQ5Ud4AqLgnQYQ0Jk
pwXIru92XyN+qkd+HVIOw9YHvXsnrNCYQ1zQG6lw5j42u2FeePJPXx1TjhDVLnid
knuhjupmaiEEw2YQzmfCMMaMQCEqFI7/R6R6vrrgbKwWweOO/ZWiryUNeWEASG5N
rtNqzgepV+Q1QaEkC/EB7tERAoGBAMrKvafe/kNMubvE0jfmR+xsFmUMFy0mfuXh
Kk34+KwxNCjqie/nTbcDumD4eY21hVPktoTMV94FRLK6t/nxttEdOjZl6z7dHkzD
s4q9TSQbgxHuhuGiqvZYDPCvNIUh8pI2sBoidcl6e6NnRLDo9Ihffvv9s0oL8cSJ
fpGh2f7NAoGBAMu00p+0BNuMVOauqSigyXCtepRyXoYzkdlDYStNVei3JdLN2x7E
VpVoheKbTzEkOkAGQRyqejET+gfgplnD0dLFLGqCmLuhWcBvrdcu7VpkX+bqSu5F
KdkPlrM596tXl6rJ97acwFFdnwEs7FiNBmoZ0DN0EWolfI+3MdKXBQJv
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,50 @@
Public, self-signed TLS server key file used for HTTPS-related unit tests
-------------------------------------------------------------------------
Public Key Information:
Public Key Algorithm: RSA
Algorithm Security Level: Medium (2048 bits)
Modulus (bits 2048):
00:cc:fb:f1:c5:de:29:29:40:3f:c4:9f:af:da:f6:be
27:f4:6a:00:ae:5a:f2:99:c3:5f:7a:e6:9b:cf:d9:08
34:01:9b:ea:fb:da:b5:d0:b5:b2:4e:60:b4:0d:8d:05
57:e4:2e:04:d4:57:1a:58:3c:0b:3a:ed:67:a3:13:31
58:0a:c2:eb:fd:d6:27:ee:07:95:30:35:b5:98:91:c7
a5:9b:be:a9:7e:ae:fd:73:c3:6b:21:bc:52:f8:ef:71
db:d3:b1:cd:51:df:b3:37:b3:fd:7d:ae:7e:02:38:be
8e:6f:45:55:e5:6d:8a:02:cb:36:c4:17:7a:ea:24:9a
72:8d:1e:75:03:3a:6f:c4:cb:a0:3a:50:56:32:bb:4c
e2:ea:74:f0:96:31:74:b2:c1:03:e8:c3:d4:a3:59:fc
7a:cc:68:35:c4:97:eb:aa:46:fa:64:c3:f9:55:59:22
b5:2b:3c:96:84:c6:d2:7d:b4:9f:b9:9c:af:d1:20:30
7c:e8:60:4e:ee:0a:60:a0:9d:4e:8a:d8:34:74:bd:f2
40:bc:d7:c2:b3:1a:b2:bb:d7:a5:4a:4c:65:94:43:82
16:9a:8f:76:2a:05:b0:9e:3d:a7:fb:e2:c7:78:25:f7
df:ca:08:ee:ec:4f:cd:1a:3c:03:41:ec:91:c5:50:70
4b
Exponent (bits 24):
01:00:01
Public Key Usage:
Public Key ID: 92d5b42ab6a864672c2a08db51b897865e44cd6c
-----BEGIN CERTIFICATE-----
MIIC+zCCAeOgAwIBAgIJAISbkoXpX75CMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV
BAMMCWxvY2FsaG9zdDAeFw0xNjA2MTcxNDA1NTlaFw0yNjA2MTUxNDA1NTlaMBQx
EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAMz78cXeKSlAP8Sfr9r2vif0agCuWvKZw1965pvP2Qg0AZvq+9q10LWyTmC0
DY0FV+QuBNRXGlg8CzrtZ6MTMVgKwuv91ifuB5UwNbWYkcelm76pfq79c8NrIbxS
+O9x29OxzVHfszez/X2ufgI4vo5vRVXlbYoCyzbEF3rqJJpyjR51AzpvxMugOlBW
MrtM4up08JYxdLLBA+jD1KNZ/HrMaDXEl+uqRvpkw/lVWSK1KzyWhMbSfbSfuZyv
0SAwfOhgTu4KYKCdTorYNHS98kC818KzGrK716VKTGWUQ4IWmo92KgWwnj2n++LH
eCX338oI7uxPzRo8A0HskcVQcEsCAwEAAaNQME4wHQYDVR0OBBYEFFdXD8Z8k0et
ZNyM4e4WypNnGlcCMB8GA1UdIwQYMBaAFFdXD8Z8k0etZNyM4e4WypNnGlcCMAwG
A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAC4FsnK1Ph/JpdoqSRTCJiVM
MPFaaavKEEyYdAKPk/Acmb9vf07sqsT+OZg/0obsZG9LxJb7x0iAnhfM3aS+CmO9
Ym2lXeFDaJ2bHooB9MsG2C3+n8lJUMwxm7Cqpff/lpCK6Z+6MGPx3GRs6HUEl34k
BB5pue2vqhtFQ03UdHMpAK0M7n3TloAWbFb1a/JmqzTbsQ0oaMHGoECQEAbaBl+a
/up6vA3iZHq+ZPYS1KIx+xuT/SapLcyUtjfhmq1bROVZP4+6EHMsBMnhJBYKxxHy
0qKvqJL9X3NQLMgMKKUKzX+BuG2u5aRRyVIqewT/ORjaUr9Y8lU7WlXPf7Ljm6s=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,66 @@
#!/usr/bin/python2
import BaseHTTPServer
import logging
import os.path
import unittest
import sys
import httplib2
from httplib2.test import miniserver
logger = logging.getLogger(__name__)
class KeepAliveHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"""
Request handler that keeps the HTTP connection open, so that the test can
inspect the resulting SSL connection object
"""
def do_GET(self):
self.send_response(200)
self.send_header("Content-Length", "0")
self.send_header("Connection", "keep-alive")
self.end_headers()
self.close_connection = 0
def log_message(self, s, *args):
# output via logging so nose can catch it
logger.info(s, *args)
class HttpsContextTest(unittest.TestCase):
def setUp(self):
if sys.version_info < (2, 7, 9):
return
self.httpd, self.port = miniserver.start_server(
KeepAliveHandler, True)
def tearDown(self):
self.httpd.shutdown()
def testHttpsContext(self):
if sys.version_info < (2, 7, 9):
if hasattr(unittest, "skipTest"):
self.skipTest("SSLContext requires Python 2.7.9")# Python 2.7.0
else:
return
import ssl
client = httplib2.Http(
ca_certs=os.path.join(os.path.dirname(__file__), 'server.pem'))
# Establish connection to local server
client.request('https://localhost:%d/' % (self.port))
# Verify that connection uses a TLS context with the correct hostname
conn = client.connections['https:localhost:%d' % self.port]
self.assertIsInstance(conn.sock, ssl.SSLSocket)
self.assertTrue(hasattr(conn.sock, 'context'))
self.assertIsInstance(conn.sock.context, ssl.SSLContext)
self.assertTrue(conn.sock.context.check_hostname)
self.assertEqual(conn.sock.server_hostname, 'localhost')
self.assertEqual(conn.sock.context.check_hostname, True)
self.assertEqual(conn.sock.context.verify_mode, ssl.CERT_REQUIRED)
self.assertEqual(conn.sock.context.protocol, ssl.PROTOCOL_SSLv23)