File python-bugzilla-0.6.2-CVE-2013-2191-ssl-validate.patch of Package python-bugzilla
Index: python-bugzilla-0.6.2/bugzilla/base.py
===================================================================
--- python-bugzilla-0.6.2.orig/bugzilla/base.py 2013-06-28 12:36:49.861947869 +0200
+++ python-bugzilla-0.6.2/bugzilla/base.py 2013-06-28 13:18:08.508875654 +0200
@@ -10,6 +10,7 @@
# the full text of the license.
import xmlrpclib, urllib2
+import httplib, socket, ssl
try:
import cookielib
except ImportError:
@@ -102,7 +103,8 @@
cookies persistently.
'''
def __init__(self, url=None, user=None, password=None,
- cookiefile=os.path.expanduser('~/.bugzillacookies')):
+ cookiefile=os.path.expanduser('~/.bugzillacookies'),
+ sslverify=True):
# Settings the user might want to tweak
self.user = user or ''
self.password = password or ''
@@ -115,6 +117,7 @@
else:
self._cookiefile = True
self.cookiefile = cookiefile
+ self._sslverify = bool(sslverify)
self.user_agent = user_agent
self.logged_in = False
@@ -253,6 +256,11 @@
If 'user' and 'password' are both set, we'll run login(). Otherwise
you'll have to login() yourself before some methods will work.
'''
+
+ # init ssl verification
+ if self._sslverify:
+ httplib.HTTPSConnection = VerifiedHTTPSConnection
+
# Set up the transport
if url.startswith('https'):
self._transport = SafeCookieTransport()
@@ -1050,6 +1058,44 @@
else:
request = request_with_cookies # python 2.6 and earlier
+
+class SSLVerifyError(Exception):
+ pass
+
+class VerifiedHTTPSConnection(httplib.HTTPSConnection):
+
+ def _get_valid_hosts(self, cert):
+ if 'subjectAltName' in cert:
+ return [x[1] for x in cert['subjectAltName']
+ if x[0].lower() == 'dns']
+ else:
+ return [x[0][1] for x in cert['subject']
+ if x[0][0].lower() == 'commonname']
+
+ def validate_hosts(self):
+ cert = self.sock.getpeercert()
+ hosts = self._get_valid_hosts(cert)
+ import re
+ for host in hosts:
+ host_re = host.replace('.', '\.').replace('*', '[^.]*')
+ if re.search('^%s$' % (host_re,), self.host, re.I):
+ return
+ raise SSLVerifyError("hostnames in certificate don't match request")
+
+ def connect(self):
+ # overrides the version in httplib so that we do
+ # certificate verification
+ sock = socket.create_connection((self.host, self.port),
+ self.timeout)
+ if self._tunnel_host:
+ self.sock = sock
+ self._tunnel()
+ # wrap the socket using verification with the root
+ # certs in trusted_root_certs
+ self.sock = ssl.wrap_socket(sock, cert_reqs=ssl.CERT_REQUIRED, ca_certs='/etc/ssl/certs')
+ self.validate_hosts()
+
+
class BasicAuthTransport(xmlrpclib.SafeTransport):
"""A subclass of xmlrpclib.SafeTransport that allows setting HTTP Basic Auth
without exposing it as part of URL in backtraces."""
Index: python-bugzilla-0.6.2/bin/bugzilla
===================================================================
--- python-bugzilla-0.6.2.orig/bin/bugzilla 2013-06-28 12:36:49.839947240 +0200
+++ python-bugzilla-0.6.2/bin/bugzilla 2013-06-28 13:16:52.103689280 +0200
@@ -55,6 +55,8 @@
p.add_option('--bztype',default='auto',
help="Bugzilla type. Autodetected if not set. "
"Available types: %s" % " ".join(bugzilla.classlist))
+ p.add_option('--nosslverify', dest='sslverify', action='store_false', default=True,
+ help="don't error on invalid bugzilla SSL certificate")
p.add_option('--user',
help="username")
p.add_option('--password',
@@ -363,7 +365,7 @@
bzclass = getattr(bugzilla,global_opt.bztype)
else:
parser.error("bztype must be one of: %s" % str(bugzilla.classlist))
- bz=bzclass(url=global_opt.bugzilla)
+ bz=bzclass(url=global_opt.bugzilla, sslverify=global_opt.sslverify)
# Handle 'login' action
if action == 'login':