]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/commitdiff
Add OpenSSL version check and tests. refs ticket:2215
authorDaira Hopwood <daira@jacaranda.org>
Tue, 2 Jun 2015 17:07:20 +0000 (18:07 +0100)
committerDaira Hopwood <daira@jacaranda.org>
Tue, 2 Jun 2015 17:07:20 +0000 (18:07 +0100)
Signed-off-by: Daira Hopwood <daira@jacaranda.org>
src/allmydata/__init__.py
src/allmydata/_auto_deps.py
src/allmydata/test/test_version.py

index 44f971f8634fd86b8f9bf53678acdb29875d3be4..5f6cd8c11f2f948d77bde72539125ca26a29c5dc 100644 (file)
@@ -152,6 +152,28 @@ def normalized_version(verstr, what=None):
         raise PackagingError, ("could not parse %s due to %s: %s"
                                % (what or repr(verstr), cls.__name__, value)), trace
 
+def get_openssl_version():
+    try:
+        from OpenSSL import SSL
+        return extract_openssl_version(SSL)
+    except Exception:
+        return ("unknown", None, None)
+
+def extract_openssl_version(ssl_module):
+    openssl_version = ssl_module.SSLeay_version(ssl_module.SSLEAY_VERSION)
+    if openssl_version.startswith('OpenSSL '):
+        openssl_version = openssl_version[8 :]
+
+    (version, _, comment) = openssl_version.partition(' ')
+
+    try:
+        openssl_cflags = ssl_module.SSLeay_version(ssl_module.SSLEAY_CFLAGS)
+        if '-DOPENSSL_NO_HEARTBEATS' in openssl_cflags.split(' '):
+            comment += ", no heartbeats"
+    except Exception:
+        pass
+
+    return (version, None, comment if comment else None)
 
 def get_package_versions_and_locations():
     import warnings
@@ -221,6 +243,8 @@ def get_package_versions_and_locations():
             packages.append( (pkgname, (platform.python_version(), sys.executable, None)) )
         elif pkgname == 'platform':
             packages.append( (pkgname, (get_platform(), None, None)) )
+        elif pkgname == 'OpenSSL':
+            packages.append( (pkgname, get_openssl_version()) )
 
     return packages
 
@@ -297,7 +321,7 @@ def cross_check(pkg_resources_vers_and_locs, imported_vers_and_locs_list):
     from _auto_deps import not_import_versionable, ignorable
 
     errors = []
-    not_pkg_resourceable = ['python', 'platform', __appname__.lower()]
+    not_pkg_resourceable = ['python', 'platform', __appname__.lower(), 'openssl']
 
     for name, (imp_ver, imp_loc, imp_comment) in imported_vers_and_locs_list:
         name = name.lower()
index 69a6081586960e71207de1e96297bfbe4d6e8a1f..18faacc1ad1788817607a26dd8ebe41d07cb2b71 100644 (file)
@@ -69,6 +69,7 @@ package_imports = [
     ('python',           None),
     ('platform',         None),
     ('pyOpenSSL',        'OpenSSL'),
+    ('OpenSSL',          None),
     ('simplejson',       'simplejson'),
     ('pycrypto',         'Crypto'),
     ('pyasn1',           'pyasn1'),
@@ -169,7 +170,8 @@ else:
 #   not *directly* depend on pyOpenSSL.
 #
 # * pyOpenSSL >= 0.13 is needed in order to avoid
-#   <https://tahoe-lafs.org/trac/tahoe-lafs/ticket/2005>.
+#   <https://tahoe-lafs.org/trac/tahoe-lafs/ticket/2005>, and also to check the
+#   version of OpenSSL that pyOpenSSL is using.
 #
 # * pyOpenSSL >= 0.14 is built on the 'cryptography' package which depends
 #   on 'cffi' (and indirectly several other packages). Unfortunately cffi
index fc64277724c0d3ae258feddfd3149169c9dcdb9e..9433e36598538a40550b07ddd1be8a385a85a977 100644 (file)
@@ -3,12 +3,27 @@ from pkg_resources import Requirement
 
 from twisted.trial import unittest
 
-from allmydata import check_requirement, cross_check, PackagingError
+from allmydata import check_requirement, cross_check, extract_openssl_version, PackagingError
 from allmydata.util.verlib import NormalizedVersion as V, \
                                   IrrationalVersionError, \
                                   suggest_normalized_version as suggest
 
 
+class MockSSL(object):
+    SSLEAY_VERSION = 0
+    SSLEAY_CFLAGS = 2
+
+    def __init__(self, version, compiled_without_heartbeats=False):
+        self.opts = {
+            self.SSLEAY_VERSION: version,
+            self.SSLEAY_CFLAGS: compiled_without_heartbeats and 'compiler: gcc -DOPENSSL_NO_HEARTBEATS'
+                                                             or 'compiler: gcc',
+        }
+
+    def SSLeay_version(self, which):
+        return self.opts[which]
+
+
 class CheckRequirement(unittest.TestCase):
     def test_check_requirement(self):
         self._check_success("setuptools >= 0.6c6", {"setuptools": ("0.6", "", None)})
@@ -118,6 +133,18 @@ class CheckRequirement(unittest.TestCase):
         self.failUnlessEqual(len(res), 1)
         self.failUnlessIn("but version '2.0'", res[0])
 
+    def test_extract_openssl_version(self):
+        self.failUnlessEqual(extract_openssl_version(MockSSL("")),
+                                                     ("", None, None))
+        self.failUnlessEqual(extract_openssl_version(MockSSL("NotOpenSSL a.b.c foo")),
+                                                     ("NotOpenSSL", None, "a.b.c foo"))
+        self.failUnlessEqual(extract_openssl_version(MockSSL("OpenSSL a.b.c")),
+                                                     ("a.b.c", None, None))
+        self.failUnlessEqual(extract_openssl_version(MockSSL("OpenSSL 1.0.1e 11 Feb 2013")),
+                                                     ("1.0.1e", None, "11 Feb 2013"))
+        self.failUnlessEqual(extract_openssl_version(MockSSL("OpenSSL 1.0.1e 11 Feb 2013", compiled_without_heartbeats=True)),
+                                                     ("1.0.1e", None, "11 Feb 2013, no heartbeats"))
+
 
 # based on https://bitbucket.org/tarek/distutilsversion/src/17df9a7d96ef/test_verlib.py