[python-swiftclient/el6-havana] Update to upstream 1.8.0

Jakub Ruzicka jruzicka at fedoraproject.org
Tue Dec 10 13:51:05 UTC 2013


commit 9b33617aabc336b2e1177e05f4b189a61d089fd7
Author: Jakub Ruzicka <jruzicka at redhat.com>
Date:   Tue Dec 10 14:44:51 2013 +0100

    Update to upstream 1.8.0
    
    Changelog:
    - Update to upstream 1.8.0
    - Add SSL certificate verification by default (CVE-2013-6396)
    - New runtime and build dependency: pyOpenSSL
    - New runtime dependency: python-keystoneclient
    - python-pbr has been removed from runtime by upstream

 .gitignore                                         |    1 +
 0001-Remove-builtin-requirements-handling.patch    |   45 ++
 0001-Remove-runtime-dependency-on-python-pbr.patch |   73 --
 ...d-SSL-certificate-verification-by-default.patch |  809 ++++++++++++++++++++
 python-swiftclient.spec                            |   21 +-
 sources                                            |    2 +-
 6 files changed, 871 insertions(+), 80 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 40ed193..fecfadd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@
 /python-swiftclient-1.5.0.tar.gz
 /python-swiftclient-1.6.0.tar.gz
 /python-swiftclient-1.7.0.tar.gz
+/python-swiftclient-1.8.0.tar.gz
diff --git a/0001-Remove-builtin-requirements-handling.patch b/0001-Remove-builtin-requirements-handling.patch
new file mode 100644
index 0000000..a28f2c5
--- /dev/null
+++ b/0001-Remove-builtin-requirements-handling.patch
@@ -0,0 +1,45 @@
+From 49f2f86b4852d4c4e7fcb1877f051cae490c0fc9 Mon Sep 17 00:00:00 2001
+From: Jakub Ruzicka <jruzicka at redhat.com>
+Date: Fri, 6 Dec 2013 17:36:12 +0100
+Subject: [PATCH] Remove builtin requirements handling
+
+---
+ requirements.txt      | 1 -
+ setup.py              | 1 -
+ test-requirements.txt | 9 ---------
+ 3 files changed, 11 deletions(-)
+ delete mode 100644 requirements.txt
+ delete mode 100644 test-requirements.txt
+
+diff --git a/requirements.txt b/requirements.txt
+deleted file mode 100644
+index 519b048..0000000
+--- a/requirements.txt
++++ /dev/null
+@@ -1 +0,0 @@
+-simplejson>=2.0.9
+diff --git a/setup.py b/setup.py
+index 70c2b3f..afab729 100644
+--- a/setup.py
++++ b/setup.py
+@@ -18,5 +18,4 @@
+ import setuptools
+ 
+ setuptools.setup(
+-    setup_requires=['pbr'],
+     pbr=True)
+diff --git a/test-requirements.txt b/test-requirements.txt
+deleted file mode 100644
+index 5b78b5f..0000000
+--- a/test-requirements.txt
++++ /dev/null
+@@ -1,9 +0,0 @@
+-hacking>=0.5.6,<0.8
+-
+-coverage>=3.6
+-discover
+-mock>=1.0
+-python-keystoneclient>=0.3.2
+-sphinx>=1.1.2
+-testrepository>=0.0.17
+-testtools>=0.9.32
diff --git a/0002-Add-SSL-certificate-verification-by-default.patch b/0002-Add-SSL-certificate-verification-by-default.patch
new file mode 100644
index 0000000..fd048d7
--- /dev/null
+++ b/0002-Add-SSL-certificate-verification-by-default.patch
@@ -0,0 +1,809 @@
+From a92005b5b92dde8e7269557a50fbc498762ab4b2 Mon Sep 17 00:00:00 2001
+From: Thomas Leaman <thomas.leaman at hp.com>
+Date: Mon, 24 Jun 2013 16:22:55 +0000
+Subject: [PATCH] Add SSL certificate verification by default
+
+Verifies the SSL certificates including matching CNAME.
+Can be turned off with --insecure
+
+Fixes bug 1199783
+
+Change-Id: I168dba604b32e0cb814333d64396926e2bccf242
+---
+ bin/swift                       |   5 +-
+ swiftclient/client.py           |  24 ++---
+ swiftclient/https_connection.py | 162 +++++++++++++++++++++++------
+ tests/test_ssl.py               | 225 ++++++++++++++++++++++++++++++++++++++++
+ tests/test_swiftclient.py       |  11 +-
+ tests/var/ca.crt                |  34 ++++++
+ tests/var/certificate.crt       |  66 ++++++++++++
+ tests/var/expired-cert.crt      |  35 +++++++
+ tests/var/privatekey.key        |  51 +++++++++
+ 9 files changed, 560 insertions(+), 53 deletions(-)
+ create mode 100644 tests/test_ssl.py
+ create mode 100644 tests/var/ca.crt
+ create mode 100644 tests/var/certificate.crt
+ create mode 100644 tests/var/expired-cert.crt
+ create mode 100644 tests/var/privatekey.key
+
+diff --git a/bin/swift b/bin/swift
+index 0de5fbe..e11e62b 100755
+--- a/bin/swift
++++ b/bin/swift
+@@ -1411,9 +1411,8 @@ Examples:
+     parser.add_option('--insecure',
+                       action="store_true", dest="insecure",
+                       default=default_val,
+-                      help='Allow swiftclient to access insecure keystone '
+-                           'server. The keystone\'s certificate will not '
+-                           'be verified. '
++                      help='Allow swiftclient to access servers without '
++                           'verifying the SSL certificate. '
+                            'Defaults to env[SWIFTCLIENT_INSECURE] '
+                            '(set to \'true\' to enable).')
+     parser.add_option('--no-ssl-compression',
+diff --git a/swiftclient/client.py b/swiftclient/client.py
+index a95ce70..5535a47 100644
+--- a/swiftclient/client.py
++++ b/swiftclient/client.py
+@@ -25,15 +25,11 @@ from functools import wraps
+ 
+ from urllib import quote as _quote
+ from urlparse import urlparse, urlunparse
+-from httplib import HTTPException, HTTPConnection, HTTPSConnection
++from httplib import HTTPException, HTTPConnection
+ from time import sleep
+ 
+ from swiftclient.exceptions import ClientException, InvalidHeadersException
+-
+-try:
+-    from swiftclient.https_connection import HTTPSConnectionNoSSLComp
+-except ImportError:
+-    HTTPSConnectionNoSSLComp = HTTPSConnection
++from swiftclient.https_connection import HTTPSConnection
+ 
+ 
+ try:
+@@ -119,13 +115,15 @@ except ImportError:
+     from json import loads as json_loads
+ 
+ 
+-def http_connection(url, proxy=None, ssl_compression=True):
++def http_connection(url, proxy=None, insecure=False, ssl_compression=True):
+     """
+     Make an HTTPConnection or HTTPSConnection
+ 
+     :param url: url to connect to
+     :param proxy: proxy to connect through, if any; None by default; str of the
+                   format 'http://127.0.0.1:8888' to set one
++    :param insecure: Allow to access servers without checking SSL certs.
++                     The server's certificate will not be verified.
+     :param ssl_compression: Whether to enable compression at the SSL layer.
+                             If set to 'False' and the pyOpenSSL library is
+                             present an attempt to disable SSL compression
+@@ -141,10 +139,9 @@ def http_connection(url, proxy=None, ssl_compression=True):
+     if parsed.scheme == 'http':
+         conn = HTTPConnection(host)
+     elif parsed.scheme == 'https':
+-        if ssl_compression is True:
+-            conn = HTTPSConnection(host)
+-        else:
+-            conn = HTTPSConnectionNoSSLComp(host)
++        conn = HTTPSConnection(host,
++                               insecure=insecure,
++                               ssl_compression=ssl_compression)
+     else:
+         raise ClientException('Cannot handle protocol scheme %s for url %s' %
+                               (parsed.scheme, repr(url)))
+@@ -1043,8 +1040,8 @@ class Connection(object):
+         :param os_options: The OpenStack options which can have tenant_id,
+                            auth_token, service_type, endpoint_type,
+                            tenant_name, object_storage_url, region_name
+-        :param insecure: Allow to access insecure keystone server.
+-                         The keystone's certificate will not be verified.
++        :param insecure: Allow to access servers without checking SSL certs.
++                         The server's certificate will not be verified.
+         :param ssl_compression: Whether to enable compression at the SSL layer.
+                                 If set to 'False' and the pyOpenSSL library is
+                                 present an attempt to disable SSL compression
+@@ -1080,6 +1077,7 @@ class Connection(object):
+ 
+     def http_connection(self):
+         return http_connection(self.url,
++                               insecure=self.insecure,
+                                ssl_compression=self.ssl_compression)
+ 
+     def _add_response_dict(self, target_dict, kwargs):
+diff --git a/swiftclient/https_connection.py b/swiftclient/https_connection.py
+index 2a2dc1f..a0cf511 100644
+--- a/swiftclient/https_connection.py
++++ b/swiftclient/https_connection.py
+@@ -18,45 +18,132 @@ HTTPS/SSL related functionality
+ """
+ 
+ import socket
++import struct
+ 
+-from httplib import HTTPSConnection
+-
++from httplib import HTTPSConnection as _HTTPSConnection
+ import OpenSSL
+ 
+-try:
+-    from eventlet.green.OpenSSL.SSL import GreenConnection
+-    from eventlet.greenio import GreenSocket
+-    from eventlet.patcher import is_monkey_patched
+ 
+-    def getsockopt(self, *args, **kwargs):
+-        return self.fd.getsockopt(*args, **kwargs)
+-    # The above is a workaround for an eventlet bug in getsockopt.
+-    # TODO(mclaren): Workaround can be removed when this fix lands:
+-    # https://bitbucket.org/eventlet/eventlet/commits/609f230
+-    GreenSocket.getsockopt = getsockopt
+-except ImportError:
+-    def is_monkey_patched(*args):
+-        return False
++class SSLCertificateError(BaseException):
++    pass
++
+ 
++class SSLConfigurationError(BaseException):
++    pass
+ 
+-class HTTPSConnectionNoSSLComp(HTTPSConnection):
++
++class HTTPSConnection(_HTTPSConnection):
+     """
+-    Extended HTTPSConnection which uses the OpenSSL library
+-    for disabling SSL compression.
+-    Note: This functionality can eventually be replaced
++    Extended HTTPSConnection which attempts to use the OpenSSL
++    library for enhanced SSL support
++    Note: Much of this functionality can eventually be replaced
+           with native Python 3.3 code.
+     """
+-    def __init__(self, host):
+-        HTTPSConnection.__init__(self, host)
++    def __init__(self, host, port=None, key_file=None, cert_file=None,
++                 cacert=None, timeout=None, insecure=False,
++                 ssl_compression=True):
++        _HTTPSConnection.__init__(self, host, port,
++                                  key_file=key_file,
++                                  cert_file=cert_file)
++        self.key_file = key_file
++        self.cert_file = cert_file
++        self.timeout = timeout
++        self.insecure = insecure
++        self.ssl_compression = ssl_compression
++        self.cacert = cacert
+         self.setcontext()
+ 
++    @staticmethod
++    def host_matches_cert(host, x509):
++        """
++        Verify that the the x509 certificate we have received
++        from 'host' correctly identifies the server we are
++        connecting to, ie that the certificate's Common Name
++        or a Subject Alternative Name matches 'host'.
++        """
++        # First see if we can match the CN
++        if x509.get_subject().commonName == host:
++            return True
++
++        # Also try Subject Alternative Names for a match
++        san_list = None
++        for i in xrange(x509.get_extension_count()):
++            ext = x509.get_extension(i)
++            if ext.get_short_name() == 'subjectAltName':
++                san_list = str(ext)
++                for san in ''.join(san_list.split()).split(','):
++                    if san == "DNS:%s" % host:
++                        return True
++
++        # Server certificate does not match host
++        msg = ('Host "%s" does not match x509 certificate contents: '
++               'CommonName "%s"' % (host, x509.get_subject().commonName))
++        if san_list is not None:
++            msg = msg + ', subjectAltName "%s"' % san_list
++        raise SSLCertificateError(msg)
++
++    def verify_callback(self, connection, x509, errnum,
++                        depth, preverify_ok):
++        # NOTE(leaman): preverify_ok may be a non-boolean type
++        preverify_ok = bool(preverify_ok)
++        if x509.has_expired():
++            msg = "SSL Certificate expired on '%s'" % x509.get_notAfter()
++            raise SSLCertificateError(msg)
++
++        if depth == 0 and preverify_ok:
++            # We verify that the host matches against the last
++            # certificate in the chain
++            return self.host_matches_cert(self.host, x509)
++        else:
++            # Pass through OpenSSL's default result
++            return preverify_ok
++
+     def setcontext(self):
+         """
+         Set up the OpenSSL context.
+         """
+         self.context = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD)
+-        # Disable SSL layer compression.
+-        self.context.set_options(0x20000)  # SSL_OP_NO_COMPRESSION
++
++        if self.ssl_compression is False:
++            self.context.set_options(0x20000)  # SSL_OP_NO_COMPRESSION
++
++        if self.insecure is not True:
++            self.context.set_verify(OpenSSL.SSL.VERIFY_PEER,
++                                    self.verify_callback)
++        else:
++            self.context.set_verify(OpenSSL.SSL.VERIFY_NONE,
++                                    lambda *args: True)
++
++        if self.cert_file:
++            try:
++                self.context.use_certificate_file(self.cert_file)
++            except Exception as e:
++                msg = 'Unable to load cert from "%s" %s' % (self.cert_file, e)
++                raise SSLConfigurationError(msg)
++            if self.key_file is None:
++                # We support having key and cert in same file
++                try:
++                    self.context.use_privatekey_file(self.cert_file)
++                except Exception as e:
++                    msg = ('No key file specified and unable to load key '
++                           'from "%s" %s' % (self.cert_file, e))
++                    raise SSLConfigurationError(msg)
++
++        if self.key_file:
++            try:
++                self.context.use_privatekey_file(self.key_file)
++            except Exception as e:
++                msg = 'Unable to load key from "%s" %s' % (self.key_file, e)
++                raise SSLConfigurationError(msg)
++
++        if self.cacert:
++            try:
++                self.context.load_verify_locations(self.cacert)
++            except Exception as e:
++                msg = 'Unable to load CA from "%s"' % (self.cacert, e)
++                raise SSLConfigurationError(msg)
++        else:
++            self.context.set_default_verify_paths()
+ 
+     def connect(self):
+         """
+@@ -64,9 +151,24 @@ class HTTPSConnectionNoSSLComp(HTTPSConnection):
+         per-connection parameters.
+         """
+         sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
++        if self.timeout is not None:
++            # '0' microseconds
++            sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO,
++                            struct.pack('fL', self.timeout, 0))
+         self.sock = OpenSSLConnectionDelegator(self.context, sock)
+         self.sock.connect((self.host, self.port))
+ 
++    def close(self):
++        if self.sock:
++            # Removing reference to socket but don't close it yet.
++            # Response close will close both socket and associated
++            # file. Closing socket too soon will cause response
++            # reads to fail with socket IO error 'Bad file descriptor'.
++            self.sock = None
++
++        # Calling close on HTTPSConnection to continue doing that cleanup.
++        HTTPSConnection.close(self)
++
+ 
+ class OpenSSLConnectionDelegator(object):
+     """
+@@ -79,17 +181,15 @@ class OpenSSLConnectionDelegator(object):
+     a delegator must be used.
+     """
+     def __init__(self, *args, **kwargs):
+-        if is_monkey_patched('socket'):
+-            # If we are running in a monkey patched environment
+-            # use eventlet's GreenConnection -- it handles eventlet's
+-            # non-blocking sockets correctly.
+-            Connection = GreenConnection
+-        else:
+-            Connection = OpenSSL.SSL.Connection
+-        self.connection = Connection(*args, **kwargs)
++        self.connection = OpenSSL.SSL.Connection(*args, **kwargs)
+ 
+     def __getattr__(self, name):
+         return getattr(self.connection, name)
+ 
+     def makefile(self, *args, **kwargs):
++        # Making sure socket is closed when this file is closed
++        # since we now avoid closing socket on connection close
++        # see new close method under VerifiedHTTPSConnection
++        kwargs['close'] = True
++
+         return socket._fileobject(self.connection, *args, **kwargs)
+diff --git a/tests/test_ssl.py b/tests/test_ssl.py
+new file mode 100644
+index 0000000..b17b8bb
+--- /dev/null
++++ b/tests/test_ssl.py
+@@ -0,0 +1,225 @@
++# Copyright 2013 OpenStack LLC.
++# All Rights Reserved.
++#
++#    Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
++#
++#    Unless required by applicable law or agreed to in writing, software
++#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
++#    License for the specific language governing permissions and limitations
++#    under the License.
++
++import os
++
++import testtools
++from OpenSSL import crypto
++
++from swiftclient import https_connection as h
++
++
++TEST_VAR_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__),
++                                            'var'))
++
++
++class TestHTTPSConnection(testtools.TestCase):
++    def test_ssl_init_ok(self):
++        """
++        Test HTTPSConnection class init
++        """
++        key_file = os.path.join(TEST_VAR_DIR, 'privatekey.key')
++        cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++        cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
++        try:
++            h.HTTPSConnection('127.0.0.1', 0,
++                              key_file=key_file,
++                              cert_file=cert_file,
++                              cacert=cacert)
++        except h.SSLConfigurationError:
++            self.fail('Failed to init HTTPSConnection.')
++
++    def test_ssl_init_cert_no_key(self):
++        """
++        Test HTTPSConnection: absense of SSL key file.
++        """
++        cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++        cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
++        try:
++            h.HTTPSConnection('127.0.0.1', 0,
++                              cert_file=cert_file,
++                              cacert=cacert)
++            self.fail('Failed to raise assertion.')
++        except h.SSLConfigurationError:
++            pass
++
++    def test_ssl_init_key_no_cert(self):
++        """
++        Test HTTPSConnection: absense of SSL cert file.
++        """
++        key_file = os.path.join(TEST_VAR_DIR, 'privatekey.key')
++        cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
++        try:
++            h.HTTPSConnection('127.0.0.1', 0,
++                              key_file=key_file,
++                              cacert=cacert)
++        except:
++            self.fail('Failed to init HTTPSConnection.')
++
++    def test_ssl_init_bad_key(self):
++        """
++        Test HTTPSConnection: bad key.
++        """
++        cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++        cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
++        try:
++            h.HTTPSConnection('127.0.0.1', 0,
++                              cert_file=cert_file,
++                              cacert=cacert)
++            self.fail('Failed to raise assertion.')
++        except h.SSLConfigurationError:
++            pass
++
++    def test_ssl_init_bad_cert(self):
++        """
++        Test HTTPSConnection: bad cert.
++        """
++        cert_file = os.path.join(TEST_VAR_DIR, 'badcert.crt')
++        cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
++        try:
++            h.HTTPSConnection('127.0.0.1', 0,
++                              cert_file=cert_file,
++                              cacert=cacert)
++            self.fail('Failed to raise assertion.')
++        except h.SSLConfigurationError:
++            pass
++
++    def test_ssl_init_bad_ca(self):
++        """
++        Test HTTPSConnection: bad CA.
++        """
++        cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++        cacert = os.path.join(TEST_VAR_DIR, 'badca.crt')
++        try:
++            h.HTTPSConnection('127.0.0.1', 0,
++                              cert_file=cert_file,
++                              cacert=cacert)
++            self.fail('Failed to raise assertion.')
++        except h.SSLConfigurationError:
++            pass
++
++    def test_ssl_cert_cname(self):
++        """
++        Test certificate: CN match
++        """
++        cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++        cert = crypto.load_certificate(crypto.FILETYPE_PEM,
++                                       file(cert_file).read())
++        # The expected cert should have CN=0.0.0.0
++        self.assertEqual(cert.get_subject().commonName, '0.0.0.0')
++        try:
++            conn = h.HTTPSConnection('0.0.0.0', 0)
++            conn.verify_callback(None, cert, 0, 0, 1)
++        except:
++            self.fail('Unexpected exception.')
++
++    def test_ssl_cert_subject_alt_name(self):
++        """
++        Test certificate: SAN match
++        """
++        cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++        cert = crypto.load_certificate(crypto.FILETYPE_PEM,
++                                       file(cert_file).read())
++        # The expected cert should have CN=0.0.0.0
++        self.assertEqual(cert.get_subject().commonName, '0.0.0.0')
++        try:
++            conn = h.HTTPSConnection('alt1.example.com', 0)
++            conn.verify_callback(None, cert, 0, 0, 1)
++        except:
++            self.fail('Unexpected exception.')
++
++        try:
++            conn = h.HTTPSConnection('alt2.example.com', 0)
++            conn.verify_callback(None, cert, 0, 0, 1)
++        except:
++            self.fail('Unexpected exception.')
++
++    def test_ssl_cert_mismatch(self):
++        """
++        Test certificate: bogus host
++        """
++        cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++        cert = crypto.load_certificate(crypto.FILETYPE_PEM,
++                                       file(cert_file).read())
++        # The expected cert should have CN=0.0.0.0
++        self.assertEqual(cert.get_subject().commonName, '0.0.0.0')
++        try:
++            conn = h.HTTPSConnection('mismatch.example.com', 0)
++        except:
++            self.fail('Failed to init HTTPSConnection.')
++
++        self.assertRaises(h.SSLCertificateError,
++                          conn.verify_callback, None, cert, 0, 0, 1)
++
++    def test_ssl_expired_cert(self):
++        """
++        Test certificate: out of date cert
++        """
++        cert_file = os.path.join(TEST_VAR_DIR, 'expired-cert.crt')
++        cert = crypto.load_certificate(crypto.FILETYPE_PEM,
++                                       file(cert_file).read())
++        # The expected expired cert has CN=openstack.example.com
++        self.assertEqual(cert.get_subject().commonName,
++                         'openstack.example.com')
++        try:
++            conn = h.HTTPSConnection('openstack.example.com', 0)
++        except:
++            self.fail('Failed to init HTTPSConnection.')
++
++        self.assertRaises(h.SSLCertificateError,
++                          conn.verify_callback, None, cert, 0, 0, 1)
++
++    def test_ssl_broken_key_file(self):
++        """
++        Test verify exception is raised.
++        """
++        cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++        cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
++        key_file = 'fake.key'
++        self.assertRaises(
++            h.SSLConfigurationError,
++            h.HTTPSConnection, '127.0.0.1',
++            0, key_file=key_file,
++            cert_file=cert_file, cacert=cacert)
++
++    def test_ssl_init_ok_with_insecure_true(self):
++        """
++        Test HTTPSConnection class init
++        """
++        key_file = os.path.join(TEST_VAR_DIR, 'privatekey.key')
++        cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++        cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
++        try:
++            h.HTTPSConnection('127.0.0.1', 0,
++                              key_file=key_file,
++                              cert_file=cert_file,
++                              cacert=cacert, insecure=True)
++        except h.SSLConfigurationError:
++            self.fail('Failed to init HTTPSConnection.')
++
++    def test_ssl_init_ok_with_ssl_compression_false(self):
++        """
++        Test HTTPSConnection class init
++        """
++        key_file = os.path.join(TEST_VAR_DIR, 'privatekey.key')
++        cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++        cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
++        try:
++            h.HTTPSConnection('127.0.0.1', 0,
++                              key_file=key_file,
++                              cert_file=cert_file,
++                              cacert=cacert, ssl_compression=False)
++        except h.SSLConfigurationError:
++            self.fail('Failed to init HTTPSConnection.')
+diff --git a/tests/test_swiftclient.py b/tests/test_swiftclient.py
+index 6cf3c11..10eecde 100644
+--- a/tests/test_swiftclient.py
++++ b/tests/test_swiftclient.py
+@@ -15,7 +15,6 @@
+ 
+ # TODO: More tests
+ import mock
+-import httplib
+ import socket
+ import StringIO
+ import testtools
+@@ -126,7 +125,7 @@ class MockHttpTest(testtools.TestCase):
+             query_string = kwargs.get('query_string')
+             storage_url = kwargs.get('storage_url')
+ 
+-            def wrapper(url, proxy=None, ssl_compression=True):
++            def wrapper(url, proxy=None, insecure=False, ssl_compression=True):
+                 if storage_url:
+                     self.assertEqual(storage_url, url)
+ 
+@@ -187,9 +186,8 @@ class TestHttpHelpers(MockHttpTest):
+         _junk, conn = c.http_connection(url)
+         self.assertTrue(isinstance(conn, c.HTTPConnection))
+         url = 'https://www.test.com'
+-        _junk, conn = c.http_connection(url)
+-        self.assertTrue(isinstance(conn, httplib.HTTPSConnection) or
+-                        isinstance(conn, c.HTTPSConnectionNoSSLComp))
++        _junk, conn = c.http_connection(url, insecure=True)
++        self.assertTrue(isinstance(conn, c.HTTPSConnection))
+         url = 'ftp://www.test.com'
+         self.assertRaises(c.ClientException, c.http_connection, url)
+ 
+@@ -841,7 +839,8 @@ class TestConnection(MockHttpTest):
+             def read(self, *args, **kwargs):
+                 return ''
+ 
+-        def local_http_connection(url, proxy=None, ssl_compression=True):
++        def local_http_connection(url, proxy=None, insecure=False,
++                                  ssl_compression=True):
+             parsed = urlparse(url)
+             return parsed, LocalConnection()
+ 
+diff --git a/tests/var/ca.crt b/tests/var/ca.crt
+new file mode 100644
+index 0000000..c149d8c
+--- /dev/null
++++ b/tests/var/ca.crt
+@@ -0,0 +1,34 @@
++-----BEGIN CERTIFICATE-----
++MIIF7jCCA9YCCQDbl9qx7iIeJDANBgkqhkiG9w0BAQUFADCBuDEZMBcGA1UEChMQ
++T3BlbnN0YWNrIENBIE9yZzEaMBgGA1UECxMRT3BlbnN0YWNrIFRlc3QgQ0ExIzAh
++BgkqhkiG9w0BCQEWFGFkbWluQGNhLmV4YW1wbGUuY29tMREwDwYDVQQHEwhTdGF0
++ZSBDQTELMAkGA1UECBMCQ0ExCzAJBgNVBAYTAkFVMS0wKwYDVQQDEyRPcGVuc3Rh
++Y2sgVGVzdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMTIxMTE2MTI1MDE2WhcN
++NDAwNDAzMTI1MDE2WjCBuDEZMBcGA1UEChMQT3BlbnN0YWNrIENBIE9yZzEaMBgG
++A1UECxMRT3BlbnN0YWNrIFRlc3QgQ0ExIzAhBgkqhkiG9w0BCQEWFGFkbWluQGNh
++LmV4YW1wbGUuY29tMREwDwYDVQQHEwhTdGF0ZSBDQTELMAkGA1UECBMCQ0ExCzAJ
++BgNVBAYTAkFVMS0wKwYDVQQDEyRPcGVuc3RhY2sgVGVzdCBDZXJ0aWZpY2F0ZSBB
++dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC94cpBjwj2
++MD0w5j1Jlcy8Ljmk3r7CRaoV5vhWUrAWpT7Thxr/Ti0qAfZZRSIVpvBM0RlseH0Q
++toUJixuYMoNRPUQ74r/TRoO8HfjQDJfnXtWg2L7DRP8p4Zgj3vByBUCU+rKsbI/H
++Nssl/AronADbZXCoL5hJRN8euMYZGrt/Gh1ZotKE5gQlEjylDFlA3s3pn+ABLgzf
++7L7iufwV3zLdPRHCb6Ve8YvUmKfI6gy+WwTRhNhLz4Nj0uBthnj6QhnRXtxkNT7A
++aAStqKH6TtYRnk2Owh8ITFbtLQ0/MSV8jHAxMXx9AloBhEKxv3cIpgLH6lOCnj//
++Ql+H6/QWtmTUHzP1kBfMhTQnWTfR92QTcgEMiZ7a07VyVtLh+kp/G5IUqpM6Pyz/
++O6QDs7FF69bTpws7Ce916PPrGFZ9Gqvo/P0jXge8kYqO+a8QnTRldAxdUzPJCK9+
++Dyi2LWeHf8nPFYdwW9Ov6Jw1CKDYxjJg6KIwnrMPa2eUdPB6/OKkqr9/KemOoKQu
++4KSaYadFZbaJwt7JPZaHy6TpkGxW7Af8RqGrW6a6nWEFcfO2POuHcAHWL5LiRmni
++unm60DBF3b3itDTqCvER3mZE9pN8dqtxdpB8SUX8eq0UJJK2K8mJQS+oE9crbqYb
++1kQbYjhhPLlvOQru+/m/abqZrC04u2OtYQIDAQABMA0GCSqGSIb3DQEBBQUAA4IC
++AQA8wGVBbzfpQ3eYpchiHyHF9N5LIhr6Bt4jYDKLz8DIbElLtoOlgH/v7hLGJ7wu
++R9OteonwQ1qr9umMmnp61bKXOEBJLBJbGKEt0MNLmmX89+M/h3rdMVZEz/Hht/xK
++Xm4di8pjkHfmdhqsbiFW81lAt9W1r74lnH7wQHr9ueALGKDx0hi8pAZ27itgQVHL
++eA1erhw0kjr9BqWpDIskVwePcD7pFoZ48GQlST0uIEq5U+1AWq7AbOABsqODygKi
++Ri5pmTasNFT7nEX3ti4VN214MNy0JnPzTRNWR2rD0I30AebM3KkzTprbLVfnGkm4
++7hOPV+Wc8EjgbbrUAIp2YpOfO/9nbgljTOUsqfjqxzvHx/09XOo2M6NIE5UiHqIq
++TXN7CeGIhBoYbvBAH2QvtveFXv41IYL4zFFXo4wTBSzCCOUGeDDv0U4hhsNaCkDQ
++G2TcubNA4g/FAtqLvPj/6VbIIgFE/1/6acsT+W0O+kkVAb7ej2dpI7J+jKXDXuiA
++PDCMn9dVQ7oAcaQvVdvvRphLdIZ9wHgqKhxKsMwzIMExuDKL0lWe/3sueFyol6nv
++xRCSgzr5MqSObbO3EnWgcUocBvlPyYLnTM2T8C5wh3BGnJXqJSRETggNn8PXBVIm
+++c5o+Ic0mYu4v8P1ZSozFdgf+HLriVPwzJU5dHvvTEu7sw==
++-----END CERTIFICATE-----
+diff --git a/tests/var/certificate.crt b/tests/var/certificate.crt
+new file mode 100644
+index 0000000..06c02ab
+--- /dev/null
++++ b/tests/var/certificate.crt
+@@ -0,0 +1,66 @@
++# Certificate:
++#    Data:
++#        Version: 3 (0x2)
++#        Serial Number: 1 (0x1)
++#        Signature Algorithm: sha1WithRSAEncryption
++#        Issuer: O=Openstack CA Org, OU=Openstack Test CA/emailAddress=admin at ca.example.com,
++#                L=State CA, ST=CA, C=AU, CN=Openstack Test Certificate Authority
++#        Validity
++#            Not Before: Nov 16 12:50:19 2012 GMT
++#            Not After : Apr  3 12:50:19 2040 GMT
++#        Subject: O=Openstack Test Org, OU=Openstack Test Unit/emailAddress=admin at example.com,
++#                 L=State1, ST=CA, C=US, CN=0.0.0.0
++#        Subject Public Key Info:
++#            Public Key Algorithm: rsaEncryption
++#            RSA Public Key: (4096 bit)
++#                Modulus (4096 bit):
++#                    00:d4:bb:3a:c4:a0:06:54:31:23:5d:b0:78:5a:be:
++#                    45:44:ae:a1:89:86:11:d8:ca:a8:33:b0:4f:f3:e1:
++#                    .
++#                    .
++#                    .
++#                Exponent: 65537 (0x10001)
++#        X509v3 extensions:
++#            X509v3 Subject Alternative Name:
++#                DNS:alt1.example.com, DNS:alt2.example.com
++#    Signature Algorithm: sha1WithRSAEncryption
++#        2c:fc:5c:87:24:bd:4a:fa:40:d2:2e:35:a4:2a:f3:1c:b3:67:
++#        b0:e4:8a:cd:67:6b:55:50:d4:cb:dd:2d:26:a5:15:62:90:a3:
++#        .
++#        .
++#        .
++-----BEGIN CERTIFICATE-----
++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
++tdc5rw==
++-----END CERTIFICATE-----
+diff --git a/tests/var/expired-cert.crt b/tests/var/expired-cert.crt
+new file mode 100644
+index 0000000..227d422
+--- /dev/null
++++ b/tests/var/expired-cert.crt
+@@ -0,0 +1,35 @@
++-----BEGIN CERTIFICATE-----
++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
++l3+dFHnWayuCdqcFwIl3m8i8FupFihz9+A==
++-----END CERTIFICATE-----
+diff --git a/tests/var/privatekey.key b/tests/var/privatekey.key
+new file mode 100644
+index 0000000..5b47d44
+--- /dev/null
++++ b/tests/var/privatekey.key
+@@ -0,0 +1,51 @@
++-----BEGIN RSA PRIVATE KEY-----
++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
++-----END RSA PRIVATE KEY-----
diff --git a/python-swiftclient.spec b/python-swiftclient.spec
index ed71fb8..e07f002 100644
--- a/python-swiftclient.spec
+++ b/python-swiftclient.spec
@@ -1,5 +1,5 @@
 Name:       python-swiftclient
-Version:    1.7.0
+Version:    1.8.0
 Release:    1%{?dist}
 Summary:    Client Library for OpenStack Object Storage API
 License:    ASL 2.0
@@ -7,12 +7,15 @@ URL:        http://pypi.python.org/pypi/%{name}
 Source0:    http://pypi.python.org/packages/source/p/%{name}/%{name}-%{version}.tar.gz
 
 #
-# patches_base=1.7.0
+# patches_base=1.8.0
 #
-Patch0001: 0001-Remove-runtime-dependency-on-python-pbr.patch
+Patch0001: 0001-Remove-builtin-requirements-handling.patch
+Patch0002: 0002-Add-SSL-certificate-verification-by-default.patch
 
 BuildArch:  noarch
 Requires:   python-simplejson
+Requires:   python-keystoneclient
+Requires:   pyOpenSSL >= 0.12
 # /usr/bin/swift collision with older swift-im rhbz#857900
 Conflicts:  swift < 2.0-0.3
 
@@ -20,6 +23,7 @@ BuildRequires: python2-devel
 BuildRequires: python-setuptools
 BuildRequires: python-d2to1
 BuildRequires: python-pbr
+BuildRequires: pyOpenSSL
 
 %description
 Client library and command line utility for interacting with Openstack
@@ -39,9 +43,7 @@ Object Storage API.
 %setup -q
 
 %patch0001 -p1
-
-# We provide version like this in order to remove runtime dep on pbr.
-sed -i s/REDHATSWIFTCLIENTVERSION/%{version}/ swiftclient/version.py
+%patch0002 -p1
 
 # Remove bundled egg-info
 rm -rf python_swiftclient.egg-info
@@ -73,6 +75,13 @@ rm -fr doc/build/html/.doctrees doc/build/html/.buildinfo
 %doc LICENSE doc/build/html
 
 %changelog
+* Tue Dec 10 2013 Jakub Ruzicka <jruzicka at redhat.com> 1.8.0-1
+- Update to upstream 1.8.0
+- Add SSL certificate verification by default (CVE-2013-6396)
+- New runtime and build dependency: pyOpenSSL
+- New runtime dependency: python-keystoneclient
+- python-pbr has been removed from runtime by upstream
+
 * Tue Oct 08 2013 Jakub Ruzicka <jruzicka at redhat.com> - 1.7.0-1
 - Update to upstream 1.7.0.
 
diff --git a/sources b/sources
index 415cac1..8c87381 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-6b31fa77d534d82a0053ed605dba01be  python-swiftclient-1.7.0.tar.gz
+1f7be5a72f3590d20cf2706d86486927  python-swiftclient-1.8.0.tar.gz


More information about the scm-commits mailing list