VYPR
Critical severityNVD Advisory· Published Feb 18, 2014· Updated Apr 29, 2026

CVE-2013-6396

CVE-2013-6396

Description

The OpenStack Python client library for Swift (python-swiftclient) 1.0 through 1.9.0 does not verify X.509 certificates from SSL servers, which allows man-in-the-middle attackers to spoof servers and obtain sensitive information via a crafted certificate.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
python-swiftclientPyPI
>= 1.0, < 2.02.0

Affected products

34
  • OpenStack/Swift34 versions
    cpe:2.3:a:openstack:swift:1.0.0:*:*:*:*:*:*:*+ 33 more
    • cpe:2.3:a:openstack:swift:1.0.0:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.0.1:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.0.2:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.1.0:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.10.0:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.1.0:rc1:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.1.0:rc2:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.11.0:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.2.0:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.2.0:gamma1:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.2.0:rc1:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.3.0:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.3.0:gamma1:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.3.0:rc1:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.4.0:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.4.1:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.4.2:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.4.3:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.4.4:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.4.5:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.4.6:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.4.7:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.4.8:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.5.0:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.6.0:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.7.0:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.7.2:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.7.4:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.7.5:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.7.6:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.8.0:*:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.8.0:rc1:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.8.0:rc2:*:*:*:*:*:*
    • cpe:2.3:a:openstack:swift:1.9.0:*:*:*:*:*:*:*

Patches

1
b182112719ab

Port to python-requests

https://github.com/openstack/python-swiftclientTristan CacquerayJan 24, 2014via ghsa
8 files changed · +150 339
  • bin/swift+7 7 modified
    @@ -32,7 +32,7 @@ try:
     except ImportError:
         import json
     
    -from swiftclient import Connection, HTTPException
    +from swiftclient import Connection, RequestException
     from swiftclient import command_helpers
     from swiftclient.utils import config_true_value, prt_bytes
     from swiftclient.multithreading import MultiThreadingManager
    @@ -1388,16 +1388,16 @@ 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 '
    +                           'having to verify the SSL certificate. '
                                'Defaults to env[SWIFTCLIENT_INSECURE] '
                                '(set to \'true\' to enable).')
         parser.add_option('--no-ssl-compression',
                           action='store_false', dest='ssl_compression',
                           default=True,
    -                      help='Disable SSL compression when using https. '
    -                           'This may increase performance.')
    +                      help='This option is deprecated and not used anymore. '
    +                           'SSL compression should be disabled by default '
    +                           'by the system SSL library')
         parser.disable_interspersed_args()
         (options, args) = parse_args(parser, argv[1:], enforce_requires=False)
         parser.enable_interspersed_args()
    @@ -1425,7 +1425,7 @@ Examples:
             parser.usage = globals()['st_%s_help' % args[0]]
             try:
                 globals()['st_%s' % args[0]](parser, argv[1:], thread_manager)
    -        except (ClientException, HTTPException, socket.error) as err:
    +        except (ClientException, RequestException, socket.error) as err:
                 thread_manager.error(str(err))
     
             had_error = thread_manager.error_count
    
  • requirements.txt+1 0 modified
    @@ -1 +1,2 @@
    +requests>=1.1
     simplejson>=2.0.9
    
  • swiftclient/client.py+114 90 modified
    @@ -18,24 +18,18 @@
     """
     
     import socket
    +import requests
     import sys
     import logging
     import warnings
    -from functools import wraps
     
    +from distutils.version import StrictVersion
    +from requests.exceptions import RequestException, SSLError
     from urllib import quote as _quote
     from urlparse import urlparse, urlunparse
    -from httplib import HTTPException, HTTPConnection, HTTPSConnection
     from time import sleep, time
     
     from swiftclient.exceptions import ClientException, InvalidHeadersException
    -from swiftclient.utils import get_environ_proxies
    -
    -try:
    -    from swiftclient.https_connection import HTTPSConnectionNoSSLComp
    -except ImportError:
    -    HTTPSConnectionNoSSLComp = HTTPSConnection
    -
     
     try:
         from logging import NullHandler
    @@ -50,6 +44,18 @@ def emit(self, record):
             def createLock(self):
                 self.lock = None
     
    +# requests version 1.2.3 try to encode headers in ascii, preventing
    +# utf-8 encoded header to be 'prepared'
    +if StrictVersion(requests.__version__) < StrictVersion('2.0.0'):
    +    from requests.structures import CaseInsensitiveDict
    +
    +    def prepare_unicode_headers(self, headers):
    +        if headers:
    +            self.headers = CaseInsensitiveDict(headers)
    +        else:
    +            self.headers = CaseInsensitiveDict()
    +    requests.models.PreparedRequest.prepare_headers = prepare_unicode_headers
    +
     logger = logging.getLogger("swiftclient")
     logger.addHandler(NullHandler())
     
    @@ -124,68 +130,93 @@ def encode_utf8(value):
         from json import loads as json_loads
     
     
    -def http_connection(url, proxy=None, ssl_compression=True):
    -    """
    -    Make an HTTPConnection or HTTPSConnection
    +class HTTPConnection:
    +    def __init__(self, url, proxy=None, cacert=None, insecure=False,
    +                 ssl_compression=False):
    +        """
    +        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 cacert: A CA bundle file to use in verifying a TLS server
    +                       certificate.
    +        :param insecure: Allow to access servers without checking SSL certs.
    +                         The server's certificate will not be verified.
    +        :param ssl_compression: SSL compression should be disabled by default
    +                                and this setting is not usable as of now. The
    +                                parameter is kept for backward compatibility.
    +        :raises ClientException: Unable to handle protocol scheme
    +        """
    +        self.url = url
    +        self.parsed_url = urlparse(url)
    +        self.host = self.parsed_url.netloc
    +        self.port = self.parsed_url.port
    +        self.requests_args = {}
    +        if self.parsed_url.scheme not in ('http', 'https'):
    +            raise ClientException("Unsupported scheme")
    +        self.requests_args['verify'] = not insecure
    +        if cacert:
    +            # verify requests parameter is used to pass the CA_BUNDLE file
    +            # see: http://docs.python-requests.org/en/latest/user/advanced/
    +            self.requests_args['verify'] = cacert
    +        if proxy:
    +            proxy_parsed = urlparse(proxy)
    +            if not proxy_parsed.scheme:
    +                raise ClientException("Proxy's missing scheme")
    +            self.requests_args['proxies'] = {
    +                proxy_parsed.scheme: '%s://%s' % (
    +                    proxy_parsed.scheme, proxy_parsed.netloc
    +                )
    +            }
    +        self.requests_args['stream'] = True
    +
    +    def _request(self, *arg, **kwarg):
    +        """ Final wrapper before requests call, to be patched in tests """
    +        return requests.request(*arg, **kwarg)
    +
    +    def request(self, method, full_path, data=None, headers={}, files=None):
    +        """ Encode url and header, then call requests.request """
    +        headers = dict((encode_utf8(x), encode_utf8(y)) for x, y in
    +                       headers.iteritems())
    +        url = encode_utf8("%s://%s%s" % (
    +            self.parsed_url.scheme,
    +            self.parsed_url.netloc,
    +            full_path))
    +        self.resp = self._request(method, url, headers=headers, data=data,
    +                                  files=files, **self.requests_args)
    +        return self.resp
    +
    +    def putrequest(self, full_path, data=None, headers={}, files=None):
    +        """
    +        Use python-requests files upload
     
    -    :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 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
    -                            will be made. This may provide a performance
    -                            increase for https upload/download operations.
    -    :returns: tuple of (parsed url, connection object)
    -    :raises ClientException: Unable to handle protocol scheme
    -    """
    -    url = encode_utf8(url)
    -    parsed = urlparse(url)
    -    if proxy:
    -        proxy_parsed = urlparse(proxy)
    -    else:
    -        proxies = get_environ_proxies(parsed.netloc)
    -        proxy = proxies.get(parsed.scheme, None)
    -        proxy_parsed = urlparse(proxy) if proxy else None
    -    host = proxy_parsed.netloc if proxy else parsed.netloc
    -    if parsed.scheme == 'http':
    -        conn = HTTPConnection(host)
    -    elif parsed.scheme == 'https':
    -        if ssl_compression is True:
    -            conn = HTTPSConnection(host)
    -        else:
    -            conn = HTTPSConnectionNoSSLComp(host)
    -    else:
    -        raise ClientException('Cannot handle protocol scheme %s for url %s' %
    -                              (parsed.scheme, repr(url)))
    -
    -    def putheader_wrapper(func):
    -
    -        @wraps(func)
    -        def putheader_escaped(key, value):
    -            func(encode_utf8(key), encode_utf8(value))
    -        return putheader_escaped
    -    conn.putheader = putheader_wrapper(conn.putheader)
    -
    -    def request_wrapper(func):
    -
    -        @wraps(func)
    -        def request_escaped(method, url, body=None, headers=None):
    -            validate_headers(headers)
    -            url = encode_utf8(url)
    -            if body:
    -                body = encode_utf8(body)
    -            func(method, url, body=body, headers=headers or {})
    -        return request_escaped
    -    conn.request = request_wrapper(conn.request)
    -    if proxy:
    -        try:
    -            # python 2.6 method
    -            conn._set_tunnel(parsed.hostname, parsed.port)
    -        except AttributeError:
    -            # python 2.7 method
    -            conn.set_tunnel(parsed.hostname, parsed.port)
    -    return parsed, conn
    +        :param data: Use data generator for chunked-transfer
    +        :param files: Use files for default transfer
    +        """
    +        return self.request('PUT', full_path, data, headers, files)
    +
    +    def getresponse(self):
    +        """ Adapt requests response to httplib interface """
    +        self.resp.status = self.resp.status_code
    +        old_getheader = self.resp.raw.getheader
    +
    +        def getheaders():
    +            return self.resp.headers.items()
    +
    +        def getheader(k, v=None):
    +            return old_getheader(k.lower(), v)
    +
    +        self.resp.getheaders = getheaders
    +        self.resp.getheader = getheader
    +        self.resp.read = self.resp.raw.read
    +        return self.resp
    +
    +
    +def http_connection(*arg, **kwarg):
    +    """ :returns: tuple of (parsed url, connection object) """
    +    conn = HTTPConnection(*arg, **kwarg)
    +    return conn.parsed_url, conn
     
     
     def get_auth_1_0(url, user, key, snet):
    @@ -890,27 +921,16 @@ def put_object(url, token=None, container=None, name=None, contents=None,
         if hasattr(contents, 'read'):
             if chunk_size is None:
                 chunk_size = 65536
    -        conn.putrequest('PUT', path)
    -        for header, value in headers.iteritems():
    -            conn.putheader(header, value)
             if content_length is None:
    -            conn.putheader('Transfer-Encoding', 'chunked')
    -            conn.endheaders()
    -            chunk = contents.read(chunk_size)
    -            while chunk:
    -                conn.send('%x\r\n%s\r\n' % (len(chunk), chunk))
    -                chunk = contents.read(chunk_size)
    -            conn.send('0\r\n\r\n')
    +            def chunk_reader():
    +                while True:
    +                    data = contents.read(chunk_size)
    +                    if not data:
    +                        break
    +                    yield data
    +            conn.putrequest(path, headers=headers, data=chunk_reader())
             else:
    -            conn.endheaders()
    -            left = content_length
    -            while left > 0:
    -                size = chunk_size
    -                if size > left:
    -                    size = left
    -                chunk = contents.read(size)
    -                conn.send(chunk)
    -                left -= len(chunk)
    +            conn.putrequest(path, headers=headers, files={"file": contents})
         else:
             if chunk_size is not None:
                 warn_msg = '%s object has no \"read\" method, ignoring chunk_size'\
    @@ -1129,6 +1149,8 @@ def get_auth(self):
     
         def http_connection(self):
             return http_connection(self.url,
    +                               cacert=self.cacert,
    +                               insecure=self.insecure,
                                    ssl_compression=self.ssl_compression)
     
         def _add_response_dict(self, target_dict, kwargs):
    @@ -1160,7 +1182,9 @@ def _retry(self, reset_func, func, *args, **kwargs):
                     rv = func(self.url, self.token, *args, **kwargs)
                     self._add_response_dict(caller_response_dict, kwargs)
                     return rv
    -            except (socket.error, HTTPException) as e:
    +            except SSLError:
    +                raise
    +            except (socket.error, RequestException) as e:
                     self._add_response_dict(caller_response_dict, kwargs)
                     if self.attempts > self.retries:
                         logger.exception(e)
    
  • swiftclient/https_connection.py+0 95 removed
    @@ -1,95 +0,0 @@
    -# Copyright (c) 2013 OpenStack, LLC.
    -#
    -# 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.
    -
    -"""
    -HTTPS/SSL related functionality
    -"""
    -
    -import socket
    -
    -from httplib import 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 HTTPSConnectionNoSSLComp(HTTPSConnection):
    -    """
    -    Extended HTTPSConnection which uses the OpenSSL library
    -    for disabling SSL compression.
    -    Note: This functionality can eventually be replaced
    -          with native Python 3.3 code.
    -    """
    -    def __init__(self, host):
    -        HTTPSConnection.__init__(self, host)
    -        self.setcontext()
    -
    -    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
    -
    -    def connect(self):
    -        """
    -        Connect to an SSL port using the OpenSSL library and apply
    -        per-connection parameters.
    -        """
    -        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    -        self.sock = OpenSSLConnectionDelegator(self.context, sock)
    -        self.sock.connect((self.host, self.port))
    -
    -
    -class OpenSSLConnectionDelegator(object):
    -    """
    -    An OpenSSL.SSL.Connection delegator.
    -
    -    Supplies an additional 'makefile' method which httplib requires
    -    and is not present in OpenSSL.SSL.Connection.
    -
    -    Note: Since it is not possible to inherit from OpenSSL.SSL.Connection
    -    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)
    -
    -    def __getattr__(self, name):
    -        return getattr(self.connection, name)
    -
    -    def makefile(self, *args, **kwargs):
    -        return socket._fileobject(self.connection, *args, **kwargs)
    
  • swiftclient/utils.py+0 50 modified
    @@ -14,23 +14,6 @@
     # limitations under the License.
     """Miscellaneous utility functions for use with Swift."""
     
    -import sys
    -import os
    -
    -_ver = sys.version_info
    -
    -#: Python 2.x?
    -is_py2 = (_ver[0] == 2)
    -
    -#: Python 3.x?
    -is_py3 = (_ver[0] == 3)
    -
    -if is_py2:
    -    from urllib import getproxies, proxy_bypass
    -elif is_py3:
    -    from urllib.request import getproxies, proxy_bypass
    -
    -
     TRUE_VALUES = set(('true', '1', 'yes', 'on', 't', 'y'))
     
     
    @@ -72,36 +55,3 @@ def prt_bytes(bytes, human_flag):
             bytes = '%12s' % bytes
     
         return(bytes)
    -
    -
    -# get_environ_proxies function, borrowed from python Requests
    -# (www.python-requests.org)
    -def get_environ_proxies(netloc):
    -    """Return a dict of environment proxies."""
    -
    -    get_proxy = lambda k: os.environ.get(k) or os.environ.get(k.upper())
    -
    -    # First check whether no_proxy is defined. If it is, check that the URL
    -    # we're getting isn't in the no_proxy list.
    -    no_proxy = get_proxy('no_proxy')
    -
    -    if no_proxy:
    -        # We need to check whether we match here. We need to see if we match
    -        # the end of the netloc, both with and without the port.
    -        no_proxy = no_proxy.replace(' ', '').split(',')
    -
    -        for host in no_proxy:
    -            if netloc.endswith(host) or netloc.split(':')[0].endswith(host):
    -                # The URL does match something in no_proxy, so we don't want
    -                # to apply the proxies on this URL.
    -                return {}
    -
    -    # If the system proxy settings indicate that this URL should be bypassed,
    -    # don't proxy.
    -    if proxy_bypass(netloc):
    -        return {}
    -
    -    # If we get here, we either didn't have no_proxy set or we're not going
    -    # anywhere that no_proxy applies to, and the system settings don't require
    -    # bypassing the proxy for the current URL.
    -    return getproxies()
    
  • tests/test_swiftclient.py+25 14 modified
    @@ -15,7 +15,6 @@
     
     # TODO: More tests
     import mock
    -import httplib
     import logging
     import socket
     import StringIO
    @@ -107,7 +106,8 @@ def fake_http_connection(*args, **kwargs):
                 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, cacert=None, insecure=False,
    +                        ssl_compression=True):
                     if storage_url:
                         self.assertEqual(storage_url, url)
     
    @@ -138,11 +138,17 @@ def tearDown(self):
     
     
     class MockHttpResponse():
    -    def __init__(self):
    -        self.status = 200
    +    def __init__(self, status=0):
    +        self.status = status
    +        self.status_code = status
             self.reason = "OK"
             self.buffer = []
     
    +        class Raw:
    +            def read():
    +                pass
    +        self.raw = Raw()
    +
         def read(self):
             return ""
     
    @@ -153,10 +159,15 @@ def getheaders(self):
             return {"key1": "value1", "key2": "value2"}
     
         def fake_response(self):
    -        return MockHttpResponse()
    +        return MockHttpResponse(self.status)
     
    -    def fake_send(self, msg):
    -        self.buffer.append(msg)
    +    def _fake_request(self, *arg, **kwarg):
    +        self.status = 200
    +        # This simulate previous httplib implementation that would do a
    +        # putrequest() and then use putheader() to send header.
    +        for k, v in kwarg['headers'].iteritems():
    +            self.buffer.append('%s: %s' % (k, v))
    +        return self.fake_response()
     
     
     class TestHttpHelpers(MockHttpTest):
    @@ -173,8 +184,7 @@ def test_http_connection(self):
             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))
    +        self.assertTrue(isinstance(conn, c.HTTPConnection))
             url = 'ftp://www.test.com'
             self.assertRaises(c.ClientException, c.http_connection, url)
     
    @@ -560,7 +570,7 @@ def test_unicode_ok(self):
     
             resp = MockHttpResponse()
             conn[1].getresponse = resp.fake_response
    -        conn[1].send = resp.fake_send
    +        conn[1]._request = resp._fake_request
             value = c.put_object(*args, headers=headers, http_conn=conn)
             self.assertTrue(isinstance(value, basestring))
             # Test for RFC-2616 encoded symbols
    @@ -573,7 +583,7 @@ def test_chunk_warning(self):
             args = ('asdf', 'asdf', 'asdf', 'asdf', mock_file)
             resp = MockHttpResponse()
             conn[1].getresponse = resp.fake_response
    -        conn[1].send = resp.fake_send
    +        conn[1]._request = resp._fake_request
             with warnings.catch_warnings(record=True) as w:
                 c.put_object(*args, chunk_size=20, headers={}, http_conn=conn)
                 self.assertEqual(len(w), 0)
    @@ -621,7 +631,7 @@ def test_unicode_ok(self):
     
             resp = MockHttpResponse()
             conn[1].getresponse = resp.fake_response
    -        conn[1].send = resp.fake_send
    +        conn[1]._request = resp._fake_request
             c.post_object(*args, headers=headers, http_conn=conn)
             # Test for RFC-2616 encoded symbols
             self.assertTrue("a-b: .x:yz mn:kl:qr" in resp.buffer[0],
    @@ -853,7 +863,7 @@ def __init__(self, parsed_url=None):
                         self.port = parsed_url.netloc
     
                 def putrequest(self, *args, **kwargs):
    -                return
    +                self.send()
     
                 def putheader(self, *args, **kwargs):
                     return
    @@ -880,7 +890,8 @@ def getheaders(self):
                 def read(self, *args, **kwargs):
                     return ''
     
    -        def local_http_connection(url, proxy=None, ssl_compression=True):
    +        def local_http_connection(url, proxy=None, cacert=None,
    +                                  insecure=False, ssl_compression=True):
                 parsed = urlparse(url)
                 return parsed, LocalConnection()
     
    
  • tests/test_utils.py+0 80 modified
    @@ -14,7 +14,6 @@
     # limitations under the License.
     
     import testtools
    -import os
     
     from swiftclient import utils as u
     
    @@ -118,82 +117,3 @@ def test_a_yotta(self):
         def test_overflow(self):
             bytes_ = 2 ** 90
             self.assertEqual('1024Y', u.prt_bytes(bytes_, True).lstrip())
    -
    -
    -class TestGetEnvironProxy(testtools.TestCase):
    -
    -    ENV_VARS = ('http_proxy', 'https_proxy', 'no_proxy',
    -                'HTTP_PROXY', 'HTTPS_PROXY', 'NO_PROXY')
    -
    -    def setUp(self):
    -        self.proxy_dict = {}
    -        super(TestGetEnvironProxy, self).setUp()
    -        for proxy_s in TestGetEnvironProxy.ENV_VARS:
    -            # Save old env value
    -            self.proxy_dict[proxy_s] = os.environ.get(proxy_s, None)
    -
    -    def tearDown(self):
    -        super(TestGetEnvironProxy, self).tearDown()
    -        for proxy_s in TestGetEnvironProxy.ENV_VARS:
    -            if self.proxy_dict[proxy_s]:
    -                os.environ[proxy_s] = self.proxy_dict[proxy_s]
    -            elif os.environ.get(proxy_s):
    -                del os.environ[proxy_s]
    -
    -    def setup_env(self, new_env={}):
    -        for proxy_s in TestGetEnvironProxy.ENV_VARS:
    -            # Set new env value
    -            if new_env.get(proxy_s):
    -                os.environ[proxy_s] = new_env.get(proxy_s)
    -            elif os.environ.get(proxy_s):
    -                del os.environ[proxy_s]
    -
    -    def test_http_proxy(self):
    -        self.setup_env({'http_proxy': 'http://proxy.tests.com:8080'})
    -        proxy_dict = u.get_environ_proxies('www.tests.com:81')
    -        self.assertEqual(proxy_dict['http'], 'http://proxy.tests.com:8080')
    -        self.assertEqual(proxy_dict.get('https'), None)
    -        self.assertEqual(len(proxy_dict), 1)
    -        self.setup_env({'HTTP_PROXY': 'http://proxy.tests.com:8080'})
    -        proxy_dict = u.get_environ_proxies('www.tests.com:81')
    -        self.assertEqual(proxy_dict['http'], 'http://proxy.tests.com:8080')
    -        self.assertEqual(proxy_dict.get('https'), None)
    -        self.assertEqual(len(proxy_dict), 1)
    -
    -    def test_https_proxy(self):
    -        self.setup_env({'https_proxy': 'http://proxy.tests.com:8080'})
    -        proxy_dict = u.get_environ_proxies('www.tests.com:81')
    -        self.assertEqual(proxy_dict['https'], 'http://proxy.tests.com:8080')
    -        self.assertEqual(proxy_dict.get('http'), None)
    -        self.assertEqual(len(proxy_dict), 1)
    -        self.setup_env({'HTTPS_PROXY': 'http://proxy.tests.com:8080'})
    -        proxy_dict = u.get_environ_proxies('www.tests.com:81')
    -        self.assertEqual(proxy_dict['https'], 'http://proxy.tests.com:8080')
    -        self.assertEqual(proxy_dict.get('http'), None)
    -        self.assertEqual(len(proxy_dict), 1)
    -
    -    def test_http_https_proxy(self):
    -        self.setup_env({'http_proxy': 'http://proxy1.tests.com:8081',
    -                        'https_proxy': 'http://proxy2.tests.com:8082'})
    -        proxy_dict = u.get_environ_proxies('www.tests.com:81')
    -        self.assertEqual(proxy_dict['http'], 'http://proxy1.tests.com:8081')
    -        self.assertEqual(proxy_dict['https'], 'http://proxy2.tests.com:8082')
    -        self.assertEqual(len(proxy_dict), 2)
    -        self.setup_env({'http_proxy': 'http://proxy1.tests.com:8081',
    -                        'HTTPS_PROXY': 'http://proxy2.tests.com:8082'})
    -        proxy_dict = u.get_environ_proxies('www.tests.com:81')
    -        self.assertEqual(proxy_dict['http'], 'http://proxy1.tests.com:8081')
    -        self.assertEqual(proxy_dict['https'], 'http://proxy2.tests.com:8082')
    -        self.assertEqual(len(proxy_dict), 2)
    -
    -    def test_proxy_exclusion(self):
    -        self.setup_env({'http_proxy': 'http://proxy1.tests.com:8081',
    -                        'https_proxy': 'http://proxy2.tests.com:8082',
    -                        'no_proxy': 'www.tests.com'})
    -        proxy_dict = u.get_environ_proxies('www.tests.com:81')
    -        self.assertEqual(len(proxy_dict), 0)
    -        self.setup_env({'http_proxy': 'http://proxy1.tests.com:8081',
    -                        'HTTPS_PROXY': 'http://proxy2.tests.com:8082',
    -                        'NO_PROXY': 'www.tests.com'})
    -        proxy_dict = u.get_environ_proxies('www.tests.com:81')
    -        self.assertEqual(len(proxy_dict), 0)
    
  • tests/utils.py+3 3 modified
    @@ -12,7 +12,7 @@
     # implied.
     # See the License for the specific language governing permissions and
     # limitations under the License.
    -from httplib import HTTPException
    +from requests import RequestException
     from time import sleep
     
     
    @@ -74,7 +74,7 @@ def getresponse(self):
     
             def getexpect(self):
                 if self.status == -2:
    -                raise HTTPException()
    +                raise RequestException()
                 if self.status == -3:
                     return FakeConn(507)
                 return FakeConn(100)
    @@ -141,7 +141,7 @@ def connect(*args, **ckwargs):
             etag = etag_iter.next()
             timestamp = timestamps_iter.next()
             if status <= 0:
    -            raise HTTPException()
    +            raise RequestException()
             fake_conn = FakeConn(status, etag, body=kwargs.get('body', ''),
                                  timestamp=timestamp)
             fake_conn.connect()
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.