Package: s3cmd
Version: 1.5.0~rc1-2
Severity: important
Tags: patch upstream

When running on a bucket like "foo.luke.wf", s3cmd will print an error like 
this:

WARNING: Retrying failed request: /?prefix=ops/ (hostname 
'foo.luke.wf.s3.amazonaws.com' doesn't match either of '*.s3.amazonaws.com', 
's3.amazonaws.com')

Fixed upstream in 
https://github.com/s3tools/s3cmd/commit/ecee692cbc355f775508b7d769493a3b56f12656

-- System Information:
Debian Release: 8.0
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: amd64 (x86_64)

Kernel: Linux 3.19.0-10-generic (SMP w/8 CPU cores)
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)
Shell: /bin/sh linked to /bin/dash
Init: unable to detect

Versions of packages s3cmd depends on:
ii  python-dateutil  2.2-2
pn  python:any       <none>

Versions of packages s3cmd recommends:
ii  python-magic  1:5.22+15-2

s3cmd suggests no packages.

-- no debconf information
>From ecee692cbc355f775508b7d769493a3b56f12656 Mon Sep 17 00:00:00 2001
From: Matt Domsch <[email protected]>
Date: Thu, 15 Jan 2015 10:42:42 -0600
Subject: [PATCH] fix S3 wildcard certificate checking

First, the implementation had a bug, and did not actually disable the
ssl.match_hostname() check like we originally believed, because the
change to the context.check_hostname=False flag occurred too late.

Second, we want to do the hostname checking ourselves, so we can
continue when presented with an S3 wildcard certificate.  We invoke
the SSLContext.match_hostname() function for all connections, and if
it fails, we check if we're actually looking at an S3 wildcard
certificate and communicating with an S3 host. If so, this is
permissible.  If not, we fail the connection immediately.

This should resolve the concern over disabling SSL certificate
hostname checking.

This patch was backported from upstream to apply on the packaged version
by Luke Faraone <[email protected]>.
---
 S3/ConnMan.py | 31 +++++++++++++++++++++++++++----
 1 file changed, 27 insertions(+), 4 deletions(-)

--- a/S3/ConnMan.py
+++ b/S3/ConnMan.py
@@ -8,6 +8,7 @@
 from urlparse import urlparse
 from threading import Semaphore
 from logging import debug, info, warning, error
+import ssl as ssllib
 
 from Config import Config
 from Exceptions import ParameterError
@@ -25,7 +26,36 @@
         elif not ssl:
             self.c = httplib.HTTPConnection(hostname)
         else:
-            self.c = httplib.HTTPSConnection(hostname)
+            context = ssllib.create_default_context()
+            # S3's wildcart certificate doesn't work with DNS-style named buckets.
+            if hostname.endswith('.amazonaws.com') and context:
+                # this merely delays running the hostname check until
+                # after the connection is made and we get control
+                # back.  We then run the same check, relaxed for S3's
+                # wildcard certificates.
+                context.check_hostname = False
+            self.c = httplib.HTTPSConnection(hostname, context=context)
+
+
+
+    @staticmethod
+    def match_hostname_aws(cert, hostname, e):
+        san = cert.get('subjectAltName', ())
+        for key, value in san:
+            if key == 'DNS':
+                if value.startswith('*.s3') and value.endswith('.amazonaws.com') and hostname.endswith('.amazonaws.com'):
+                    return
+        raise e
+
+    @staticmethod
+    def match_hostname(conn):
+        cert = conn.c.sock.getpeercert()
+        hostname = conn.c.sock.server_hostname
+        try:
+            ssllib.match_hostname(cert, hostname)
+        except ssllib.CertificateError, e:
+            http_connection.match_hostname_aws(cert, hostname, e)
+
 
 class ConnMan(object):
     conn_pool_sem = Semaphore()
@@ -55,6 +85,8 @@
             debug("ConnMan.get(): creating new connection: %s" % conn_id)
             conn = http_connection(conn_id, hostname, ssl, cfg)
             conn.c.connect()
+            if conn.ssl:
+                http_connection.match_hostname(conn)
         conn.counter += 1
         return conn
 

Reply via email to