diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a5d5de7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/ndg_httpsclient.egg-info/ +/dist/ +*.pyc +.eggs/ +build/ diff --git a/.pydevproject b/.pydevproject index b26aeb6..85f561e 100644 --- a/.pydevproject +++ b/.pydevproject @@ -1,8 +1,14 @@ -ndg-https-client-py3.4 -python 3.0 - -/ndg_httpsclient - + + Default + + python 3.6 + + + + /ndg_httpsclient + + + diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..f0f7398 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,13 @@ +language: python +python: + - 2.7 + - 3.6 + - 3.7 + - 3.8 + - 3.9 + - nightly +script: + - python setup.py install +jobs: + allow_failures: + - python: nightly diff --git a/README.md b/README.md index d587439..7193452 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,56 @@ -A HTTPS client implementation for httplib and urllib2 based on -PyOpenSSL. PyOpenSSL provides a more fully featured SSL implementation over the -default provided with Python and importantly enables full verification of the -SSL peer. +A HTTPS client implementation for + * ``httplib`` (Python 2), ``http.client`` (Python 3) and + * ``urllib2`` (Python 2) and ``urllib`` (Python 3) + +... based on PyOpenSSL. PyOpenSSL provides a more fully featured SSL implementation +over the default provided with Python and importantly enables full verification +of the SSL peer using ``pyasn1``. Releases ======== +0.5.1 +----- + * Clean up handling for description file - pull in content from this file into setup() + * Allows the nightly build to fail + * Add Trove version classifiers to make it explicit what is supported + * Add python_requires to help pip + * Drop support for EOL Python 2.6 and 3.3 + +Thanks to @hugovk for contributions + +0.5.0 +----- + * Fix to Subject Alternative Name handling to allow for certificates with + more than 64 names (max now 1024). Thanks to Matt Pegler + * Fix to subjectAltName string to use byte type for correct matching + * Updated SSL Context objects to default to TLS 1.2 + +0.4.4 +----- + * Updated test certificates + +0.4.3 +----- + * Fix to ``ndg`` namespace package warning issue (https://github.com/cedadev/ndg_httpsclient/issues/3). + ``__init__.py`` file now included in ``ndg`` directory so that there are no longer warnings with imports + when using Python 2.x. Thanks to Max Mauntner for fix. + * Minor fix for installation: set minimum release for ``pyasn1`` to avoid conflicts with Ubuntu + install - see https://github.com/cedadev/ndg_httpsclient/issues/5 and + https://github.com/cedadev/ndg_httpsclient/pull/10. ``pyasn1`` also becomes mandatory rather + than optional package for install. - It required by ``cryptography`` anyway which is a + dependency for ``pyOpenSSL`` from version 0.14. + +0.4.2 +----- + * Fix to bug in ``ndg.httpsclient.utils.open_url`` - duplicate open call. + Nb. This bug and the fix DO NOT affect the ``httplib``and ``urllib2`` + interfaces that this package provides. + +0.4.1 +----- + * Added explicit ref to Python 3 in classifier text for Python 3 checking tools. + * Moved LICENSE file into package + 0.4.0 ----- * Made dual compatible with Python 2 / 3. @@ -26,13 +72,13 @@ Releases 0.3.1 ----- - * extended utils functions to support keyword for passing additional urllib2 + * extended utils functions to support keyword for passing additional ``urllib2`` handlers. 0.3.0 ----- - * Added ndg.httpsclient.utils.fetch_stream_from_url function and added - parameter for data to post in open_url and fetch_* methods. + * Added ``ndg.httpsclient.utils.fetch_stream_from_url`` function and added + parameter for data to post in ``open_url`` and ``fetch_*`` methods. * fix to ndg.httpsclient.utils module _should_use_proxy and open_url functions 0.2.0 @@ -46,14 +92,14 @@ Initial release Prerequisites ============= -This has been developed and tested for Python 2.6 and 2.7 with pyOpenSSL 0.13 and 0.14. -Version 0.4.0 tested with pyOpenSSL 0.15.1 and Python 2.7 and 3.4. Note that proxy support -is only available from Python 2.6.2 onwards. pyasn1 is required for correct SSL -verification with subjectAltNames. +This has been developed and tested for Python 2.7 with pyOpenSSL 0.13 +and 0.14. Version 0.4.0 tested with ``pyOpenSSL`` 0.15.1 and Python 2.7 and +3.4. +``pyasn1`` is required for correct SSL verification with ``subjectAltNames``. Installation ============ -Installation can be performed using easy_install or pip. +Installation can be performed using ``easy_install`` or ``pip``. Running ndg_httpclient ====================== diff --git a/ndg/__init__.py b/ndg/__init__.py index 3b01e15..69e3be5 100644 --- a/ndg/__init__.py +++ b/ndg/__init__.py @@ -1,19 +1 @@ -"""ndg_httpsclient - PyOpenSSL utility to make a httplib-like interface suitable -for use with urllib2 - -This is a setuptools namespace_package. DO NOT place any other -code in this file! There is no guarantee that it will be installed -with easy_install. See: - -http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages - -... for details. -""" -__author__ = "P J Kershaw" -__date__ = "06/01/12" -__copyright__ = "(C) 2012 Science and Technology Facilities Council" -__license__ = "BSD - see LICENSE file in top-level directory" -__contact__ = "Philip.Kershaw@stfc.ac.uk" -__revision__ = '$Id$' - -__import__('pkg_resources').declare_namespace(__name__) \ No newline at end of file +__path__ = __import__('pkgutil').extend_path(__path__, __name__) diff --git a/LICENSE b/ndg/httpsclient/LICENSE similarity index 100% rename from LICENSE rename to ndg/httpsclient/LICENSE diff --git a/ndg/httpsclient/https.py b/ndg/httpsclient/https.py index 41ad1c6..aaa0bb3 100644 --- a/ndg/httpsclient/https.py +++ b/ndg/httpsclient/https.py @@ -48,7 +48,7 @@ class HTTPSConnection(HTTPConnection): @type default_ssl_method: int """ default_port = HTTPS_PORT - default_ssl_method = SSL.SSLv23_METHOD + default_ssl_method = SSL.TLSv1_2_METHOD def __init__(self, host, port=None, strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, ssl_context=None): @@ -78,7 +78,7 @@ def connect(self): sock = socket.create_connection((self.host, self.port), self.timeout) - # Tunnel if using a proxy - ONLY available for Python 2.6.2 and above + # Tunnel if using a proxy - ONLY available for Python 2.6.2 and above if getattr(self, '_tunnel_host', None): self.sock = sock self._tunnel() @@ -100,6 +100,8 @@ class HTTPSContextHandler(AbstractHTTPHandler): ''' https_request = AbstractHTTPHandler.do_request_ + SSL_METHOD = SSL.TLSv1_2_METHOD + def __init__(self, ssl_context, debuglevel=0): """ @param ssl_context:SSL context @@ -116,7 +118,7 @@ def __init__(self, ssl_context, debuglevel=0): ssl_context) self.ssl_context = ssl_context else: - self.ssl_context = SSL.Context(SSL.TLSv1_METHOD) + self.ssl_context = SSL.Context(self.__class__.SSL_METHOD) def https_open(self, req): """Opens HTTPS request diff --git a/ndg/httpsclient/ssl_context_util.py b/ndg/httpsclient/ssl_context_util.py index 0ed1d32..810e3c8 100644 --- a/ndg/httpsclient/ssl_context_util.py +++ b/ndg/httpsclient/ssl_context_util.py @@ -41,7 +41,7 @@ def make_ssl_context_from_config(ssl_config=False, url=None): def make_ssl_context(key_file=None, cert_file=None, pem_file=None, ca_dir=None, - verify_peer=False, url=None, method=SSL.TLSv1_METHOD, + verify_peer=False, url=None, method=SSL.TLSv1_2_METHOD, key_file_passphrase=None): """ Creates SSL context containing certificate and key file locations. @@ -64,6 +64,8 @@ def make_ssl_context(key_file=None, cert_file=None, pem_file=None, ca_dir=None, if pem_file or ca_dir: ssl_context.load_verify_locations(pem_file, ca_dir) + else: + ssl_context.set_default_verify_paths() # Use OS CA bundle def _callback(conn, x509, errnum, errdepth, preverify_ok): """Default certification verification callback. diff --git a/ndg/httpsclient/ssl_peer_verification.py b/ndg/httpsclient/ssl_peer_verification.py index 5e82dae..b02b6f8 100644 --- a/ndg/httpsclient/ssl_peer_verification.py +++ b/ndg/httpsclient/ssl_peer_verification.py @@ -40,8 +40,9 @@ class ServerSSLCertVerification(object): 'domainComponent': 'DC', 'userid': 'UID' } - SUBJ_ALT_NAME_EXT_NAME = 'subjectAltName' - PARSER_RE_STR = '/(%s)=' % '|'.join(list(DN_LUT.keys()) + list(DN_LUT.values())) + SUBJ_ALT_NAME_EXT_NAME = b'subjectAltName' + PARSER_RE_STR = '/(%s)=' % '|'.join(list(DN_LUT.keys()) + \ + list(DN_LUT.values())) PARSER_RE = re.compile(PARSER_RE_STR) __slots__ = ('__hostname', '__certDN', '__subj_alt_name_match') diff --git a/ndg/httpsclient/subj_alt_name.py b/ndg/httpsclient/subj_alt_name.py index b2c1918..7c195aa 100644 --- a/ndg/httpsclient/subj_alt_name.py +++ b/ndg/httpsclient/subj_alt_name.py @@ -25,7 +25,7 @@ class Pyasn1ImportError(ImportError): raise Pyasn1ImportError(import_error_msg) -MAX = 64 +MAX = 1024 class DirectoryString(univ.Choice): @@ -69,7 +69,7 @@ class AttributeTypeAndValue(univ.Sequence): class RelativeDistinguishedName(univ.SetOf): - '''ASN.1 Realtive distinguished name''' + '''ASN.1 Relative distinguished name''' componentType = AttributeTypeAndValue() class RDNSequence(univ.SequenceOf): diff --git a/ndg/httpsclient/test/__init__.py b/ndg/httpsclient/test/__init__.py index 4e8196a..6d4ee88 100644 --- a/ndg/httpsclient/test/__init__.py +++ b/ndg/httpsclient/test/__init__.py @@ -16,11 +16,13 @@ class Constants(object): '''Convenience base class from which other unit tests can extend. Its sets the generic data directory path''' PORT = 4443 +# PORT = 443 PORT2 = 4444 HOSTNAME = 'localhost' +# HOSTNAME = 'files.pythonhosted.org' TEST_URI = 'https://%s:%d' % (HOSTNAME, PORT) TEST_URI2 = 'https://%s:%d' % (HOSTNAME, PORT2) - + UNITTEST_DIR = os.path.dirname(os.path.abspath(__file__)) CACERT_DIR = os.path.join(UNITTEST_DIR, 'pki', 'ca') SSL_CERT_FILENAME = 'localhost.crt' diff --git a/ndg/httpsclient/test/docker/Dockerfile b/ndg/httpsclient/test/docker/Dockerfile new file mode 100644 index 0000000..9ba08a2 --- /dev/null +++ b/ndg/httpsclient/test/docker/Dockerfile @@ -0,0 +1,6 @@ +FROM ubuntu:14.04 +RUN apt-get -yqq update && apt-get -yqq install python-pip python-dev libffi-dev libxmlsec1-openssl libssl-dev +WORKDIR /app/ +ADD . /app/ +RUN pip install -e . +CMD ["python", "setup.py", "test"] diff --git a/ndg/httpsclient/test/pki/ca/08bd99c7.0 b/ndg/httpsclient/test/pki/ca/08bd99c7.0 deleted file mode 100644 index 63ef7c3..0000000 --- a/ndg/httpsclient/test/pki/ca/08bd99c7.0 +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDLjCCAhagAwIBAgIBATANBgkqhkiG9w0BAQUFADA3MREwDwYDVQQLDAhTZWN1 -cml0eTEUMBIGA1UEAwwLTkRHIFRlc3QgQ0ExDDAKBgNVBAoMA05ERzAeFw0xNTAx -MjExNDMzMThaFw0yMDAxMjAxNDMzMThaMDcxETAPBgNVBAsMCFNlY3VyaXR5MRQw -EgYDVQQDDAtOREcgVGVzdCBDQTEMMAoGA1UECgwDTkRHMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEArq4QKUTRq45nCDR/p+OlHIIN8+ugUbiCfteazbTG -rX8vIQ9HxSuz/xvxTw+E0KgA4YSK2SJJP4QiCjlMKYS3Rt8o361GNtnRmeo5qyBu -GMSv73XL1uuqumggUZyrhhksckR7gyNFnKVXzZjAQPepsT0xBjs5uEAEqXJzAf+r -24AnT3MZRh7gsyEe3sZjd75kZVwcrWhrocyKlMCR77yEr+uP4pg+dEMhDMKKxlaF -C5RPMotOpWm/7AToHrGia34WSmcxvuOwxOkI4xEW6mxWMaVTBCXUh6Wb/0m/x8Nv -9VvS2UBC4sCp4MqlDpySxQpT1RgrhMTEmtUOh50l4eEhdwIDAQABo0UwQzASBgNV -HRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUkEvQjGOP -Oj5DZEvsm96AdiiFXWgwDQYJKoZIhvcNAQEFBQADggEBAGD0kQASmNzvtYL+JUGf -gTPyJhADl9Ai9GvZJsY/wX0IRTxRl5y08Dqlg3qyGG3GzL918cr1sVCYnLepNQES -T0MIz50DCKGryNSc74JHPDxpYaSV6whmNH5iwh8fy6tmJwF3FWbGXD2ddc+ofJqP -WPPJtzqxuuJ6iXQIFqD9mEn3iXVcvFuSzpdpH9paORTKB0j4gya9zctB8LP0ZXIE -//wREc+4msnmoTn+qkFAOPBg9WnvoipfyCXPgbTagxlofVjZ7gAgYIefqhXBTQdd -5tnYdyQQBRcUXQS2bBX03q8ftcxOjc3SvXI4MvrqofuFPwu4GnrspnC0KQYlXwEI -7ds= ------END CERTIFICATE----- diff --git a/ndg/httpsclient/test/pki/ca/7e15277f.0 b/ndg/httpsclient/test/pki/ca/7e15277f.0 new file mode 100644 index 0000000..9a4ab56 --- /dev/null +++ b/ndg/httpsclient/test/pki/ca/7e15277f.0 @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFLjCCAxagAwIBAgIBATANBgkqhkiG9w0BAQsFADA3MRQwEgYDVQQDDAtOREcg +VGVzdCBDQTEMMAoGA1UECgwDTkRHMREwDwYDVQQLDAhTZWN1cml0eTAeFw0yMDAy +MjcxMDM4MDhaFw0yNTAyMjUxMDM4MDhaMDcxFDASBgNVBAMMC05ERyBUZXN0IENB +MQwwCgYDVQQKDANOREcxETAPBgNVBAsMCFNlY3VyaXR5MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAoLeKc7StJLjyWuPBc+0pg8y5QJ4VQFzOc1jXbhqo +GugSvV/BpTqAPPCbd5hkET8nMIHkZ6EkXWNlxvYvrqKOKnrTvw3WUjEmsdoHkaXA +hq+v1IHbPbCQbB+RCCObuxlZ9Y72llUrODATb7dc9Odc4LCLPR/9+FjncB1d5b4x +Qt74VolID0dCd5dmMqy+lUYjsyLSycItmWcamdMEEPCop6AXlkAq3Q3eQDxaHtly +IOmyrYv2EWnFH5FRevhJdTnb48FdUTDya3T+BWpRqzF/Rh3NmI05JTbmSutCOs8m +SgSyi0JTNgaOaLlbtYVBLEkETUHPWABWwrXghIMIHaw3BZas2a9nlKE6zQSBxjsC +M/jJopgCDjLIxCw/SZ/Koovye/yvhMKYo71YnQCIv+1pIaL7GMrxMQZzrJiUVlpY +XtCyjx+5uiD4WuKCq6/aEKUd3o6ZdmNhkG8R0uBmivwxAmuMoMssCZC2GG7dBG+a +FlAG0OW+qzez4njjVwT7ePaO/ggRm6yJRNo7s3+SlEppV/orKLH4+O7FJm2HwTIB +Z3HSObrOJtjlcjM5pzhAFC4M0ul9vnCcnaFmhzB7bH7h8X7RaqECuHIhhfWTUiEP +f+riC5C962eGMqJH3zzPaXCKFVgyYXtphRZJYzf3oU4bGn69uumPl47McLd9lseR +uLkCAwEAAaNFMEMwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFIYdooV3qYYhM6aq0LTBYQWA9j1BMA0GCSqGSIb3DQEBCwUAA4IC +AQAzqykz00ztLxbAEVc8QbfxMYVa5QYp4Ljdl7Wb4IPb4WY6fDkkJ1wRNg/KWZov +CkTsiFvQSG5eHEVDLPUjW4WJ+eJI3uPeNjUTB+9i88pjbLqP1VBeiNdpTcOAu4w8 +cosK1wk6K3LNHATXZArD+8mHEFAHinuqlYwkBekIPBgMgbKr/WlaowV7fkIAUpxm +K2W7oLt3ZvWmFrsFcywLsyXmA8EC3d5svQ01YLHE7xJUcjatKSJyc+0dnMNy+ZZN +6NTPCefHwi5ShWWmkwtmvCChzePpYP/tBqkAIHLB7js2nHLZYtJYT1CqOGHdy3bL +DWHYU527Dj949K03/ZE8jkBqzQje5uAw9bqluydXXkAtMO8rMktIsEjZuMsyzD1b +Z8qdeHvwHQjnA1fvMuAO2QDTb8zGc8Mcn2/Jbj9ZD61cej75GWPIDolwSmMIA7fT +HyyD8NiOnqM1tGQZQWGTlwZidH6Z7jUASZd+J/+pVKyFmA6ecgo54/w/wTQSv/6S +ZWGp4ZYdjdpZ/coX2kbulej+Z3m0m4WB66LbvKD8zCYymRu5ULtS59QElliDKERS +U41awYtdgP/R/cz/SBoYxPvY/n1sOWT0mQp1+ctehDf+tDMirjOst71eq6n/85CR +NuP+k4yntJuzOjuxZ2MI8iuGDrqi/rFx2AhXXNCkCFDArw== +-----END CERTIFICATE----- diff --git a/ndg/httpsclient/test/pki/ca/ade0138a.0 b/ndg/httpsclient/test/pki/ca/ade0138a.0 deleted file mode 100644 index 63ef7c3..0000000 --- a/ndg/httpsclient/test/pki/ca/ade0138a.0 +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDLjCCAhagAwIBAgIBATANBgkqhkiG9w0BAQUFADA3MREwDwYDVQQLDAhTZWN1 -cml0eTEUMBIGA1UEAwwLTkRHIFRlc3QgQ0ExDDAKBgNVBAoMA05ERzAeFw0xNTAx -MjExNDMzMThaFw0yMDAxMjAxNDMzMThaMDcxETAPBgNVBAsMCFNlY3VyaXR5MRQw -EgYDVQQDDAtOREcgVGVzdCBDQTEMMAoGA1UECgwDTkRHMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEArq4QKUTRq45nCDR/p+OlHIIN8+ugUbiCfteazbTG -rX8vIQ9HxSuz/xvxTw+E0KgA4YSK2SJJP4QiCjlMKYS3Rt8o361GNtnRmeo5qyBu -GMSv73XL1uuqumggUZyrhhksckR7gyNFnKVXzZjAQPepsT0xBjs5uEAEqXJzAf+r -24AnT3MZRh7gsyEe3sZjd75kZVwcrWhrocyKlMCR77yEr+uP4pg+dEMhDMKKxlaF -C5RPMotOpWm/7AToHrGia34WSmcxvuOwxOkI4xEW6mxWMaVTBCXUh6Wb/0m/x8Nv -9VvS2UBC4sCp4MqlDpySxQpT1RgrhMTEmtUOh50l4eEhdwIDAQABo0UwQzASBgNV -HRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUkEvQjGOP -Oj5DZEvsm96AdiiFXWgwDQYJKoZIhvcNAQEFBQADggEBAGD0kQASmNzvtYL+JUGf -gTPyJhADl9Ai9GvZJsY/wX0IRTxRl5y08Dqlg3qyGG3GzL918cr1sVCYnLepNQES -T0MIz50DCKGryNSc74JHPDxpYaSV6whmNH5iwh8fy6tmJwF3FWbGXD2ddc+ofJqP -WPPJtzqxuuJ6iXQIFqD9mEn3iXVcvFuSzpdpH9paORTKB0j4gya9zctB8LP0ZXIE -//wREc+4msnmoTn+qkFAOPBg9WnvoipfyCXPgbTagxlofVjZ7gAgYIefqhXBTQdd -5tnYdyQQBRcUXQS2bBX03q8ftcxOjc3SvXI4MvrqofuFPwu4GnrspnC0KQYlXwEI -7ds= ------END CERTIFICATE----- diff --git a/ndg/httpsclient/test/pki/ca/ca.key b/ndg/httpsclient/test/pki/ca/ca.key new file mode 100644 index 0000000..4e79919 --- /dev/null +++ b/ndg/httpsclient/test/pki/ca/ca.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +ep2Pg4lXDl4+iO5SDobGse4Ka/Pkkw== +-----END PRIVATE KEY----- diff --git a/ndg/httpsclient/test/pki/ca/ndg-test-ca.jks b/ndg/httpsclient/test/pki/ca/ndg-test-ca.jks deleted file mode 100644 index 28cdbb2..0000000 Binary files a/ndg/httpsclient/test/pki/ca/ndg-test-ca.jks and /dev/null differ diff --git a/ndg/httpsclient/test/pki/gen-csr.sh b/ndg/httpsclient/test/pki/gen-csr.sh new file mode 100755 index 0000000..c008668 --- /dev/null +++ b/ndg/httpsclient/test/pki/gen-csr.sh @@ -0,0 +1,3 @@ +#!/bin/bash +openssl genrsa -out localhost.key 4096 +openssl req -new -out localhost.csr -subj '/O=NDG/OU=Security/CN=localhost' -key localhost.key diff --git a/ndg/httpsclient/test/pki/localhost.crt b/ndg/httpsclient/test/pki/localhost.crt index 953c7ef..74a393a 100644 --- a/ndg/httpsclient/test/pki/localhost.crt +++ b/ndg/httpsclient/test/pki/localhost.crt @@ -1,82 +1,30 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 1 (0x1) - Signature Algorithm: sha1WithRSAEncryption - Issuer: OU=Security, CN=NDG Test CA, O=NDG - Validity - Not Before: Jan 21 14:45:01 2015 GMT - Not After : Jan 20 14:45:01 2018 GMT - Subject: O=NDG, OU=Security, CN=localhost - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - RSA Public Key: (2048 bit) - Modulus (2048 bit): - 00:e3:29:45:fc:56:2d:a2:21:b6:49:c6:6a:ef:b3: - ed:d3:32:47:77:d9:85:ef:e5:6a:db:70:8b:5d:41: - 4d:b5:76:f5:96:42:5a:f7:82:a5:bb:b3:e1:f9:ac: - c6:b7:71:61:f4:4d:dd:28:f6:b1:ef:65:dc:5a:8c: - 47:b1:17:38:e1:8a:5f:40:b0:bb:a0:87:61:a7:72: - f8:c1:a1:5f:3b:f7:94:b5:cb:c3:50:84:ef:a8:13: - d4:92:ff:af:3a:d1:31:42:90:4b:58:4c:84:47:a6: - 3a:a3:3d:c1:9a:43:3c:10:f6:8a:b5:97:11:b7:74: - ab:32:92:be:9a:fc:ef:5e:45:78:30:61:67:10:63: - 09:ef:61:b7:1c:47:cc:69:c9:e7:27:8f:4d:97:33: - 59:33:b8:47:89:86:4c:cd:a4:38:7c:d0:60:ee:52: - c8:e1:2a:f1:3b:9b:e9:7c:d5:af:88:33:91:9c:10: - 63:89:01:03:fb:26:5e:3f:61:c3:b4:f0:fb:1f:ad: - e8:d2:49:8e:2f:16:81:bb:9c:d6:a5:48:91:58:7d: - ac:ac:2c:02:8a:f2:f4:22:80:1f:8c:32:5b:b5:77: - d0:36:e9:27:9a:9f:31:67:d5:4e:32:8d:cf:ce:73: - ef:88:86:e9:3c:53:e6:09:55:02:2b:86:7d:91:8d: - fb:53 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE - Netscape Comment: - OpenSSL Generated Certificate - X509v3 Subject Key Identifier: - A3:77:23:B5:1C:98:85:C8:6D:31:40:1C:2F:20:57:CD:C9:36:74:1B - X509v3 Authority Key Identifier: - keyid:90:4B:D0:8C:63:8F:3A:3E:43:64:4B:EC:9B:DE:80:76:28:85:5D:68 - - X509v3 Subject Alternative Name: - DNS:localhost - Signature Algorithm: sha1WithRSAEncryption - 33:b4:87:0e:2c:71:88:6d:ab:cc:14:c8:3f:1e:8d:e5:ed:26: - 6b:b8:76:93:29:b1:0b:c5:e7:41:6f:14:62:8f:e1:81:bb:02: - 13:5c:b2:34:b7:94:f2:7d:1e:fe:e7:89:0b:2e:56:30:58:eb: - 90:d4:05:5b:18:d9:c5:68:61:c0:f6:f7:1a:0f:14:d8:89:8e: - ee:ec:59:b8:48:96:58:33:2e:98:95:56:c3:02:e9:93:cd:3f: - 4c:0d:b5:b5:b6:6e:6f:95:5f:65:eb:1a:ce:56:20:e2:72:d4: - f7:58:5f:c0:7b:49:5f:ac:6b:01:7b:c8:f0:13:19:03:dd:4e: - 05:55:f9:31:52:ea:45:eb:54:b9:4b:a2:3f:22:c7:11:47:8a: - 94:b4:e9:9e:c0:09:96:72:66:ba:01:d3:f3:00:6e:24:ca:a9: - 6d:8e:7f:0b:a0:fd:f9:c9:4f:3a:36:07:c7:4a:c7:c7:1f:c7: - e0:2d:c3:21:d0:44:68:81:38:af:ce:cb:38:be:db:02:3d:ba: - 62:00:43:94:22:c8:d7:43:cd:db:73:23:9d:28:aa:d6:4c:08: - 45:8f:b5:1d:04:c7:2b:8e:22:12:e6:af:cd:9c:13:db:c9:76: - f4:0c:10:25:fa:5c:46:77:7d:e5:ee:16:b4:f1:24:94:22:06: - 85:40:0c:5f -----BEGIN CERTIFICATE----- -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 +qg== -----END CERTIFICATE----- diff --git a/ndg/httpsclient/test/pki/localhost.csr b/ndg/httpsclient/test/pki/localhost.csr new file mode 100644 index 0000000..a3c5181 --- /dev/null +++ b/ndg/httpsclient/test/pki/localhost.csr @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIEejCCAmICAQAwNTEMMAoGA1UECgwDTkRHMREwDwYDVQQLDAhTZWN1cml0eTES +MBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC +AgEAsBzYsKRp63t5l049CBJFzPZ7WYlDerAypPUF0yf4Ab/1kwicJ+1eYkEelvlY +p4DiFyUI/6wVR9rG3ZNwnus2w9fquQ3kkXAwAgMzONqrwOvVliN6dO8iedvq1Ygr +Yo/2dV0lHFIJcch03Sm8lB3KL7cs6dMfJ8cogf2VMEt/YdhjW2kYUNYv/LAduHuS +tSQh8Le9LHrFlcE2BK0gfiCOk/YPEp+4+ZLDUpp7a84pxEnb0/AH8fVNo+vRW9BM +035wELag56Fekf9BFtTw3J7u6rjP+WUoPksxkA4l7tVRTkDPFQfsMTbvzbgKZLXL +B3km57J52eyexOOW0RrJBye8Cb84Qivqs7RoNWZkfjSL9bX412JaAbG3c6u+NTvU +FACVqSeyG/bEPH1Q2wutD6I6kN2xjGkPzizhlrRX6qerUnlAJIPuhpAuLhIb2c8s +L7CkSEwJUYIe0KV8vU1VIFhXJxs+nWItA/fEKLBX3TnxdU9Pamwj49o8t5enVk2k +SRGX79TIB0MqpvcLqcTW2o1tNRGG4v8QIUUeIfWTiaUZl8afZgv3RE6ooWbph1gT +fnu8+t2MNujDfYKq3zAmpMTeYhrFkf68uopF7NtTx+aj7uDIQx4+wJNbDTJc/Kiu +KgsBsVkE7nnXaxrT0JcsaZ5NouzTbXnNorzUecCAzAVZP70CAwEAAaAAMA0GCSqG +SIb3DQEBCwUAA4ICAQBQ+niVozKfjJP1VCTDb88/mAGEpEOGF+BXwN7EdQKAwZva +vAxQSpqt8h0EYyToPCV6P5GNzFQ/rRW2OYgWwXEHk3ptiQzcJzIF/F9CbE9vgYO5 +Xvosxy3uyJr15sAoS+qL4jEXg7dDni+LesYYR5qx6l/5nYG/6ql0Z/K9+Z/1xrci +00Ml6+xq/oT1kc0JQYuUKnMXgQb6Mishyt+ESoRDFt6oFqlza7TNhC/Q3YxuOjqw +Hr3rc1T9L8ArYFMhwjCBSitJS9ojqtPyXTkE4ZrQoaAAl/jdwbiHQ81/PQErgrk4 +3RkyokdrOkeK2CssJ402s8ybnbYzaI+wg4K7r4APsiOXAacfVObmPYzQLamqCNkE +hcGD6Yp9JpSgVWH+cTHa47slz3RjLxMW0EMfffYOlsWlxnlY+LHTMrphfd7otSlD +c3lSbUgURW6babKQBxOULR0AooaJK/uHgarb+6xNQoPTA7RSDfemfBGu+xAxIeE8 +xPRXH6DYjhzwiHB8tFKcfdXX+MZCQ+QUHsbeVLVl+0kkw3J5bRTo5lS6menuzbPA +osnOO2IMBrhctgspj6MJg6lyFyWUDYzWn0JU6+rF/NHmnrlFgJ5in1eg1u783bXJ +0jKPpw1QAOz+gI2MHKx2Tpbu43UtAb/35GtW711e6lhm3gZUxjVQj7qhfW1pcw== +-----END CERTIFICATE REQUEST----- diff --git a/ndg/httpsclient/test/pki/localhost.key b/ndg/httpsclient/test/pki/localhost.key index 6a11b49..4be01f3 100644 --- a/ndg/httpsclient/test/pki/localhost.key +++ b/ndg/httpsclient/test/pki/localhost.key @@ -1,27 +1,51 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- diff --git a/ndg/httpsclient/test/test_https.py b/ndg/httpsclient/test/test_https.py index 86e0c51..415a6bc 100644 --- a/ndg/httpsclient/test/test_https.py +++ b/ndg/httpsclient/test/test_https.py @@ -38,7 +38,7 @@ def test02_open_fails(self): self.assertRaises(socket.error, conn.connect) def test03_ssl_verification_of_peer_fails(self): - ctx = SSL.Context(SSL.TLSv1_METHOD) + ctx = SSL.Context(SSL.TLSv1_2_METHOD) def verify_callback(conn, x509, errnum, errdepth, preverify_ok): log.debug('SSL peer certificate verification failed for %r', @@ -57,7 +57,7 @@ def verify_callback(conn, x509, errnum, errdepth, preverify_ok): self.assertRaises(SSL.Error, conn.request, 'GET', '/') def test03_ssl_verification_of_peer_succeeds(self): - ctx = SSL.Context(SSL.TLSv1_METHOD) + ctx = SSL.Context(SSL.TLSv1_2_METHOD) verify_callback = lambda conn, x509, errnum, errdepth, preverify_ok: \ preverify_ok @@ -76,7 +76,7 @@ def test03_ssl_verification_of_peer_succeeds(self): print('Response = %s' % resp.read()) def test04_ssl_verification_with_subj_alt_name(self): - ctx = SSL.Context(SSL.TLSv1_METHOD) + ctx = SSL.Context(SSL.TLSv1_2_METHOD) verification = ServerSSLCertVerification(hostname='localhost') verify_callback = verification.get_verify_server_cert_func() @@ -95,7 +95,7 @@ def test04_ssl_verification_with_subj_alt_name(self): print('Response = %s' % resp.read()) def test04_ssl_verification_with_subj_common_name(self): - ctx = SSL.Context(SSL.TLSv1_METHOD) + ctx = SSL.Context(SSL.TLSv1_2_METHOD) # Explicitly set verification of peer hostname using peer certificate # subject common name diff --git a/ndg/httpsclient/test/test_urllib2.py b/ndg/httpsclient/test/test_urllib2.py index 366c2ca..5262fe1 100644 --- a/ndg/httpsclient/test/test_urllib2.py +++ b/ndg/httpsclient/test/test_urllib2.py @@ -12,15 +12,16 @@ import sys if sys.version_info[0] > 2: - from urllib.error import URLError as URLError_ + from urllib.error import URLError as URLError else: - from urllib2 import URLError as URLError_ + from urllib2 import URLError as URLError import unittest from OpenSSL import SSL from ndg.httpsclient.test import Constants from ndg.httpsclient.urllib2_build_opener import build_opener +from ndg.httpsclient.ssl_peer_verification import ServerSSLCertVerification class Urllib2TestCase(unittest.TestCase): @@ -36,13 +37,15 @@ def test02_open(self): self.assertTrue(res) print("res = %s" % res.read()) + # Skip this test for remote service as it can take a long time to timeout + @unittest.skipIf(Constants.HOSTNAME != 'localhost', 'Skip non-local host') def test03_open_fails_unknown_loc(self): opener = build_opener() - self.assertRaises(URLError_, opener.open, Constants.TEST_URI2) + self.assertRaises(URLError, opener.open, Constants.TEST_URI2) def test04_open_peer_cert_verification_fails(self): # Explicitly set empty CA directory to make verification fail - ctx = SSL.Context(SSL.TLSv1_METHOD) + ctx = SSL.Context(SSL.TLSv1_2_METHOD) verify_callback = lambda conn, x509, errnum, errdepth, preverify_ok: \ preverify_ok @@ -50,7 +53,37 @@ def test04_open_peer_cert_verification_fails(self): ctx.load_verify_locations(None, './') opener = build_opener(ssl_context=ctx) self.assertRaises(SSL.Error, opener.open, Constants.TEST_URI) + + def test05_open_with_subj_alt_names_verification(self): + ctx = SSL.Context(SSL.TLSv1_2_METHOD) + + # Set wildcard hostname for subject alternative name matching - + # setting a minimum of two name components for hostname + split_hostname = Constants.HOSTNAME.split('.', 1) + if len(split_hostname) > 1: + _hostname = '*.' + split_hostname[-1] + else: + _hostname = Constants.HOSTNAME + + server_ssl_verify = ServerSSLCertVerification(hostname=_hostname) + verify_callback_ = server_ssl_verify.get_verify_server_cert_func() + ctx.set_verify(SSL.VERIFY_PEER, verify_callback_) + + # Set default verify paths if testing with peer that has corresponding + # CA cert in bundle provided with the OS. In this case, load verify + # locations is not needed. + #ctx.set_default_verify_paths() + ctx.set_verify_depth(9) + + # Set correct location for CA certs to verify with + ctx.load_verify_locations(None, Constants.CACERT_DIR) + + opener = build_opener(ssl_context=ctx) + res = opener.open(Constants.TEST_URI) + self.assertTrue(res) + print("res = %s" % res.read()) + if __name__ == "__main__": unittest.main() diff --git a/ndg/httpsclient/test/test_utils.py b/ndg/httpsclient/test/test_utils.py index 44382d0..a91045d 100644 --- a/ndg/httpsclient/test/test_utils.py +++ b/ndg/httpsclient/test/test_utils.py @@ -23,17 +23,17 @@ class TestUtilsModule(unittest.TestCase): '''Test ndg.httpsclient.utils module''' def test01_configuration(self): - config = Configuration(SSL.Context(SSL.TLSv1_METHOD), True) + config = Configuration(SSL.Context(SSL.TLSv1_2_METHOD), True) self.assertTrue(config.ssl_context) self.assertEqual(config.debug, True) def test02_fetch_from_url(self): - config = Configuration(SSL.Context(SSL.TLSv1_METHOD), True) + config = Configuration(SSL.Context(SSL.TLSv1_2_METHOD), True) res = fetch_from_url(Constants.TEST_URI, config) self.assertTrue(res) def test03_open_url(self): - config = Configuration(SSL.Context(SSL.TLSv1_METHOD), True) + config = Configuration(SSL.Context(SSL.TLSv1_2_METHOD), True) res = open_url(Constants.TEST_URI, config) self.assertEqual(res[0], 200, 'open_url for %r failed' % Constants.TEST_URI) diff --git a/ndg/httpsclient/utils.py b/ndg/httpsclient/utils.py index a2b0ed3..7e43a73 100644 --- a/ndg/httpsclient/utils.py +++ b/ndg/httpsclient/utils.py @@ -188,8 +188,8 @@ def open_url(url, config, data=None, handlers=None): # currently only supports http basic auth auth_handler = HTTPBasicAuthHandler_(HTTPPasswordMgrWithDefaultRealm_()) auth_handler.add_password(realm=None, uri=url, - user=config.httpauth[0], - passwd=config.httpauth[1]) + user=config.http_basicauth[0], + passwd=config.http_basicauth[1]) handlers.append(auth_handler) @@ -217,9 +217,6 @@ def open_url(url, config, data=None, handlers=None): return_message = '' response = None - # FIXME - response = opener.open(request) - try: response = opener.open(request) return_message = response.msg diff --git a/setup.py b/setup.py index d566d50..90ab546 100644 --- a/setup.py +++ b/setup.py @@ -5,126 +5,36 @@ use_setuptools() from setuptools import setup, find_packages -_long_description = ''' -This is a HTTPS client implementation for httplib and urllib2 based on -PyOpenSSL. PyOpenSSL provides a more fully featured SSL implementation over the -default provided with Python and importantly enables full verification of the -SSL peer. +NAMESPACE_PKGS = ['ndg'] -Releases -======== -0.4.0 ------ - * Made dual compatible with Python 2 / 3. - -0.3.3 ------ - * Fix to add in AnotherName for ``subjectAltNames`` field - added for support for CACert issued - certs (thanks to Gu1). - * Fix to HTTP Basic Auth option for ``ndg.httpsclient.utils.main`` - * Fix to ``ServerSSLCertVerification`` so that it can pass a function-based callback instead of using ``__call__``. In newer versions of OpenSSL (>= 0.14) the latter failed because of a request for ``__name__`` attribute. +with open('README.md') as f: + _long_description = f.read() -0.3.2 ------ - * Fix to SubjectAltNames support check - should only be enabled if pyasn1 is - installed. - * Fix to open_url: HTTP Request object was being created inside if headers is - None block - now corrected to create regardless. - * Added http basic auth support to script. (Thanks to Willem van Engen) - -0.3.1 ------ - * extended utils functions to support keyword for passing additional urllib2 - handlers. - -0.3.0 ------ - * Added ndg.httpsclient.utils.fetch_stream_from_url function and added - parameter for data to post in open_url and fetch_* methods. - * fix to ndg.httpsclient.utils module _should_use_proxy and open_url functions - -0.2.0 ------ - * added support for SSL verification with subjectAltNames using pyasn1 - * fixed minor bug - SSL cert DN prefix matching - -0.1.0 ------ -Initial release - -Prerequisites -============= -This has been developed and tested for Python 2.6 and 2.7 with pyOpenSSL 0.13 and 0.14. -Version 0.4.0 tested with pyOpenSSL 0.15.1 and Python 2.7 and 3.4. Note that proxy support -is only available from Python 2.6.2 onwards. pyasn1 is required for correct SSL -verification with subjectAltNames. - -Installation -============ -Installation can be performed using easy_install or pip. - -Running ndg_httpclient -====================== -A simple script for fetching data using HTTP or HTTPS GET from a specified URL. - -Parameter: - -``url`` - The URL of the resource to be fetched - -Options: - -``-h, --help`` - Show help message and exit. - -``-c FILE, --certificate=FILE`` - Certificate file - defaults to ``$HOME/credentials.pem`` - -``-k FILE, --private-key=FILE`` - Private key file - defaults to the certificate file - -``-t DIR, --ca-certificate-dir=DIR`` - Trusted CA certificate file directory. - -``-d, --debug`` - Print debug information - this may be useful in solving problems with HTTP or - HTTPS access to a server. - -``-p FILE, --post-data-file=FILE`` - POST data file - -``-f FILE, --fetch=FILE`` - Output file - -``-n, --no-verify-peer`` - Skip verification of peer certificate. -''' - setup( name='ndg_httpsclient', - version="0.4.0", + version="0.5.1", description='Provides enhanced HTTPS support for httplib and urllib2 using ' 'PyOpenSSL', author='Richard Wilkinson and Philip Kershaw', author_email='Philip.Kershaw@stfc.ac.uk', url='https://github.com/cedadev/ndg_httpsclient/', long_description=_long_description, - license='BSD - See LICENCE file for details', - namespace_packages=['ndg'], + long_description_content_type='text/markdown', + license='BSD - See ndg/httpsclient/LICENCE file for details', packages=find_packages(), - package_dir={'ndg.httpsclient': 'ndg/httpsclient'}, package_data={ 'ndg.httpsclient': [ - 'test/README', + 'LICENSE', + 'test/README', 'test/scripts/*.sh', 'test/pki/localhost.*', 'test/pki/ca/*.0' ], }, - install_requires = ['PyOpenSSL'], - extras_require = {'subjectAltName_support': 'pyasn1'}, - classifiers = [ - 'Development Status :: 3 - Alpha', + install_requires=['PyOpenSSL', 'pyasn1>=0.1.1'], + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', + classifiers=[ + 'Development Status :: 5 - Production/Stable', 'Environment :: Console', 'Environment :: Web Environment', 'Intended Audience :: End Users/Desktop', @@ -136,6 +46,12 @@ 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', 'Topic :: Security', 'Topic :: Internet', 'Topic :: Scientific/Engineering', @@ -143,8 +59,8 @@ 'Topic :: System :: Systems Administration :: Authentication/Directory', 'Topic :: Software Development :: Libraries :: Python Modules' ], - zip_safe = False, - entry_points = { + zip_safe=False, + entry_points={ 'console_scripts': ['ndg_httpclient = ndg.httpsclient.utils:main', ], }