Skip to content

Commit 0a48ec5

Browse files
committed
Updated certificate files.
1 parent 42bf75f commit 0a48ec5

26 files changed

+1925
-127
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ of the SSL peer using ``pyasn1``.
88

99
Releases
1010
========
11+
0.4.4
12+
-----
13+
* Updated test certificates
14+
1115
0.4.3
1216
-----
1317
* Fix to ``ndg`` namespace package warning issue (https://github.com/cedadev/ndg_httpsclient/issues/3).

build/lib/ndg/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__path__ = __import__('pkgutil').extend_path(__path__, __name__)

build/lib/ndg/httpsclient/LICENSE

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Copyright (c) 2012, Science & Technology Facilities Council (STFC)
2+
All rights reserved.
3+
4+
Redistribution and use in source and binary forms, with or without
5+
modification, are permitted provided that the following conditions are met:
6+
7+
* Redistributions of source code must retain the above copyright notice,
8+
this list of conditions and the following disclaimer.
9+
* Redistributions in binary form must reproduce the above copyright notice,
10+
this list of conditions and the following disclaimer in the documentation
11+
and/or other materials provided with the distribution.
12+
* Neither the name of the Science & Technology Facilities Council (STFC)
13+
nor the names of its contributors may be used to endorse or promote
14+
products derived from this software without specific prior written
15+
permission.
16+
17+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

build/lib/ndg/httpsclient/__init__.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"""ndg_httpsclient - PyOpenSSL utility to make a httplib-like interface suitable
2+
for use with urllib2
3+
"""
4+
__author__ = "P J Kershaw (STFC) and Richard Wilkinson (Tessella)"
5+
__date__ = "09/12/11"
6+
__copyright__ = "(C) 2011 Science and Technology Facilities Council"
7+
__license__ = "BSD - see LICENSE file in top-level directory"
8+
__contact__ = "[email protected]"
9+
__revision__ = '$Id$'

build/lib/ndg/httpsclient/https.py

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
"""ndg_httpsclient HTTPS module containing PyOpenSSL implementation of
2+
httplib.HTTPSConnection
3+
4+
PyOpenSSL utility to make a httplib-like interface suitable for use with
5+
urllib2
6+
"""
7+
__author__ = "P J Kershaw (STFC)"
8+
__date__ = "09/12/11"
9+
__copyright__ = "(C) 2012 Science and Technology Facilities Council"
10+
__license__ = "BSD - see LICENSE file in top-level directory"
11+
__contact__ = "[email protected]"
12+
__revision__ = '$Id$'
13+
import logging
14+
import socket
15+
import sys
16+
17+
if sys.version_info[0] > 2:
18+
from http.client import HTTPS_PORT
19+
from http.client import HTTPConnection
20+
21+
from urllib.request import AbstractHTTPHandler
22+
else:
23+
from httplib import HTTPS_PORT
24+
from httplib import HTTPConnection
25+
26+
from urllib2 import AbstractHTTPHandler
27+
28+
29+
from OpenSSL import SSL
30+
31+
from ndg.httpsclient.ssl_socket import SSLSocket
32+
33+
log = logging.getLogger(__name__)
34+
35+
36+
class HTTPSConnection(HTTPConnection):
37+
"""This class allows communication via SSL using PyOpenSSL.
38+
It is based on httplib.HTTPSConnection, modified to use PyOpenSSL.
39+
40+
Note: This uses the constructor inherited from HTTPConnection to allow it to
41+
be used with httplib and HTTPSContextHandler. To use the class directly with
42+
an SSL context set ssl_context after construction.
43+
44+
@cvar default_port: default port for this class (443)
45+
@type default_port: int
46+
@cvar default_ssl_method: default SSL method used if no SSL context is
47+
explicitly set - defaults to version 2/3.
48+
@type default_ssl_method: int
49+
"""
50+
default_port = HTTPS_PORT
51+
default_ssl_method = SSL.SSLv23_METHOD
52+
53+
def __init__(self, host, port=None, strict=None,
54+
timeout=socket._GLOBAL_DEFAULT_TIMEOUT, ssl_context=None):
55+
HTTPConnection.__init__(self, host, port, strict, timeout)
56+
if not hasattr(self, 'ssl_context'):
57+
self.ssl_context = None
58+
59+
if ssl_context is not None:
60+
if not isinstance(ssl_context, SSL.Context):
61+
raise TypeError('Expecting OpenSSL.SSL.Context type for "'
62+
'ssl_context" keyword; got %r instead' %
63+
ssl_context)
64+
65+
self.ssl_context = ssl_context
66+
67+
def connect(self):
68+
"""Create SSL socket and connect to peer
69+
"""
70+
if getattr(self, 'ssl_context', None):
71+
if not isinstance(self.ssl_context, SSL.Context):
72+
raise TypeError('Expecting OpenSSL.SSL.Context type for "'
73+
'ssl_context" attribute; got %r instead' %
74+
self.ssl_context)
75+
ssl_context = self.ssl_context
76+
else:
77+
ssl_context = SSL.Context(self.__class__.default_ssl_method)
78+
79+
sock = socket.create_connection((self.host, self.port), self.timeout)
80+
81+
# Tunnel if using a proxy - ONLY available for Python 2.6.2 and above
82+
if getattr(self, '_tunnel_host', None):
83+
self.sock = sock
84+
self._tunnel()
85+
86+
self.sock = SSLSocket(ssl_context, sock)
87+
88+
# Go to client mode.
89+
self.sock.set_connect_state()
90+
91+
def close(self):
92+
"""Close socket and shut down SSL connection"""
93+
if hasattr(self.sock, "close"):
94+
self.sock.close()
95+
96+
97+
class HTTPSContextHandler(AbstractHTTPHandler):
98+
'''HTTPS handler that allows a SSL context to be set for the SSL
99+
connections.
100+
'''
101+
https_request = AbstractHTTPHandler.do_request_
102+
103+
def __init__(self, ssl_context, debuglevel=0):
104+
"""
105+
@param ssl_context:SSL context
106+
@type ssl_context: OpenSSL.SSL.Context
107+
@param debuglevel: debug level for HTTPSHandler
108+
@type debuglevel: int
109+
"""
110+
AbstractHTTPHandler.__init__(self, debuglevel)
111+
112+
if ssl_context is not None:
113+
if not isinstance(ssl_context, SSL.Context):
114+
raise TypeError('Expecting OpenSSL.SSL.Context type for "'
115+
'ssl_context" keyword; got %r instead' %
116+
ssl_context)
117+
self.ssl_context = ssl_context
118+
else:
119+
self.ssl_context = SSL.Context(SSL.TLSv1_METHOD)
120+
121+
def https_open(self, req):
122+
"""Opens HTTPS request
123+
@param req: HTTP request
124+
@return: HTTP Response object
125+
"""
126+
# Make a custom class extending HTTPSConnection, with the SSL context
127+
# set as a class variable so that it is available to the connect method.
128+
customHTTPSContextConnection = type('CustomHTTPSContextConnection',
129+
(HTTPSConnection, object),
130+
{'ssl_context': self.ssl_context})
131+
return self.do_open(customHTTPSContextConnection, req)
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
"""ndg_httpsclient SSL Context utilities module containing convenience routines
2+
for setting SSL context configuration.
3+
4+
"""
5+
__author__ = "P J Kershaw (STFC)"
6+
__date__ = "09/12/11"
7+
__copyright__ = "(C) 2012 Science and Technology Facilities Council"
8+
__license__ = "BSD - see LICENSE file in top-level directory"
9+
__contact__ = "[email protected]"
10+
__revision__ = '$Id$'
11+
import sys
12+
13+
if sys.version_info[0] > 2:
14+
import urllib.parse as urlparse_
15+
else:
16+
import urlparse as urlparse_
17+
18+
from OpenSSL import SSL
19+
20+
from ndg.httpsclient.ssl_peer_verification import ServerSSLCertVerification
21+
22+
23+
class SSlContextConfig(object):
24+
"""
25+
Holds configuration options for creating a SSL context. This is used as a
26+
template to create the contexts with specific verification callbacks.
27+
"""
28+
def __init__(self, key_file=None, cert_file=None, pem_file=None, ca_dir=None,
29+
verify_peer=False):
30+
self.key_file = key_file
31+
self.cert_file = cert_file
32+
self.pem_file = pem_file
33+
self.ca_dir = ca_dir
34+
self.verify_peer = verify_peer
35+
36+
37+
def make_ssl_context_from_config(ssl_config=False, url=None):
38+
return make_ssl_context(ssl_config.key_file, ssl_config.cert_file,
39+
ssl_config.pem_file, ssl_config.ca_dir,
40+
ssl_config.verify_peer, url)
41+
42+
43+
def make_ssl_context(key_file=None, cert_file=None, pem_file=None, ca_dir=None,
44+
verify_peer=False, url=None, method=SSL.TLSv1_METHOD,
45+
key_file_passphrase=None):
46+
"""
47+
Creates SSL context containing certificate and key file locations.
48+
"""
49+
ssl_context = SSL.Context(method)
50+
51+
# Key file defaults to certificate file if present.
52+
if cert_file:
53+
ssl_context.use_certificate_file(cert_file)
54+
55+
if key_file_passphrase:
56+
passwd_cb = lambda max_passphrase_len, set_prompt, userdata: \
57+
key_file_passphrase
58+
ssl_context.set_passwd_cb(passwd_cb)
59+
60+
if key_file:
61+
ssl_context.use_privatekey_file(key_file)
62+
elif cert_file:
63+
ssl_context.use_privatekey_file(cert_file)
64+
65+
if pem_file or ca_dir:
66+
ssl_context.load_verify_locations(pem_file, ca_dir)
67+
68+
def _callback(conn, x509, errnum, errdepth, preverify_ok):
69+
"""Default certification verification callback.
70+
Performs no checks and returns the status passed in.
71+
"""
72+
return preverify_ok
73+
74+
verify_callback = _callback
75+
76+
if verify_peer:
77+
ssl_context.set_verify_depth(9)
78+
if url:
79+
set_peer_verification_for_url_hostname(ssl_context, url)
80+
else:
81+
ssl_context.set_verify(SSL.VERIFY_PEER, verify_callback)
82+
else:
83+
ssl_context.set_verify(SSL.VERIFY_NONE, verify_callback)
84+
85+
return ssl_context
86+
87+
88+
def set_peer_verification_for_url_hostname(ssl_context, url,
89+
if_verify_enabled=False):
90+
'''Convenience routine to set peer verification callback based on
91+
ServerSSLCertVerification class'''
92+
if not if_verify_enabled or (ssl_context.get_verify_mode() & SSL.VERIFY_PEER):
93+
urlObj = urlparse_.urlparse(url)
94+
hostname = urlObj.hostname
95+
server_ssl_cert_verif = ServerSSLCertVerification(hostname=hostname)
96+
verify_callback_ = server_ssl_cert_verif.get_verify_server_cert_func()
97+
ssl_context.set_verify(SSL.VERIFY_PEER, verify_callback_)
98+

0 commit comments

Comments
 (0)