from twisted.trial import unittest
-from allmydata import check_requirement, cross_check, check_openssl_version, parse_build_date, PackagingError
+from allmydata import check_requirement, cross_check, PackagingError
+from allmydata.util.check_pyopenssl import check_openssl_version, check_resistant_to_heartbleed, OpenSSLVersionError
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 __init__(self, version, is_vulnerable=False):
+ self.is_vulnerable = is_vulnerable
+ self.opts = { self.SSLEAY_VERSION: version }
def SSLeay_version(self, which):
return self.opts[which]
self.failUnlessIn("but version '2.0'", res[0])
def test_check_openssl_version(self):
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL(""))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("NotOpenSSL"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL a.b.c"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 1.1.x"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 0.9"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 0.9.0"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 0.9.8"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 0.9.8", True))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 0.9.8x"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 1.0.0"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 1.0.0", True))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 1.0.0k"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 1.0.1"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 1.0.1", True))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 1.0.1c", True))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 1.0.1e 11 Feb 2013"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 1.0.1e 5 Apr 2014"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 1.0.1e 7 Abc 2014"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 1.0.1e invalid_date"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 1.0.1e 7 Apr"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 1.0.2-beta1"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 0.10"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 0.10.0"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 1.0.0"))
- self.failUnlessRaises(PackagingError, check_openssl_version, MockSSL("OpenSSL 1.0.0 1 Jan 2000"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL(""))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("NotOpenSSL"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL a.b.c"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 1.1.x"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 0.9"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 0.9.0"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 0.9.8"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 0.9.8x"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 1.0.0"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 1.0.0k"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 1.0.1", True))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 1.0.1c", True))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 1.0.1e 11 Feb 2013"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 1.0.1e 5 Apr 2014"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 1.0.1e 7 Abc 2014"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 1.0.1e invalid_date"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 1.0.1e 7 Apr"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 1.0.2-beta1"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 0.10"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 0.10.0"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 1.0.0"))
+ self.failUnlessRaises(OpenSSLVersionError, check_openssl_version, MockSSL("OpenSSL 1.0.0 1 Jan 2000"))
check_openssl_version(MockSSL("OpenSSL 0.9.8y"))
check_openssl_version(MockSSL("OpenSSL 0.9.8z"))
check_openssl_version(MockSSL("OpenSSL 2.0.0 31 Dec 2020"))
check_openssl_version(MockSSL("OpenSSL 10.0.0 31 Dec 2099"))
- self.failUnlessEqual(parse_build_date(['1', 'Jan', '2000']), (2000, 1, 1))
- self.failUnlessEqual(parse_build_date(['5', 'Apr', '2014']), (2014, 4, 5))
- self.failUnlessEqual(parse_build_date(['7', 'Apr', '2014']), (2014, 4, 7))
- self.failUnlessRaises(Exception, parse_build_date, [])
- self.failUnlessRaises(Exception, parse_build_date, ['1', 'Abc' '2000'])
-
# based on https://bitbucket.org/tarek/distutilsversion/src/17df9a7d96ef/test_verlib.py
import re
-class OpenSSLVersionError(EnvironmentError):
+class UnsafeOpenSSLError(EnvironmentError):
pass
split_version = openssl_version.split(' ')
if len(split_version) < 2 or split_version[0] != 'OpenSSL':
- raise OpenSSLVersionError("could not understand OpenSSL version string %s" % (openssl_version,))
+ raise UnsafeOpenSSLError("could not understand OpenSSL version string %s" % (openssl_version,))
try:
components = split_version[1].split('.')
(numeric_components == [1, 0, 2] and not components[2].startswith('2-beta')) or
(numeric_components >= [1, 0, 3])):
return
- except Exception, e:
- #import traceback
- #traceback.print_exc()
- pass
- else:
- if numeric_components == [1, 0, 1] and components[2] >= '1d':
- # Unfortunately, Debian and Ubuntu patched the Heartbleed bug without bumping
- # the version number or providing any other way to detect the patch status.
- # (BAD! STOP DOING THIS!)
-
- # Allow versions 1.0.1d through 1.0.1f if compiled with -DOPENSSL_NO_HEARTBEATS:
- try:
- openssl_cflags = SSL.SSLeay_version(SSL.SSLEAY_CFLAGS)
- except Exception, e:
- raise OpenSSLVersionError("refusing to use %s which may be vulnerable to security bugs.\n"
- "Unable to check compilation flags due to %s: %s\n"
- "Please upgrade to OpenSSL 1.0.1g or later."
- % (openssl_version, e.__class__.__name__, e))
- else:
- if '-DOPENSSL_NO_HEARTBEATS' in openssl_cflags.split(' '):
- return
if numeric_components == [1, 0, 1]:
# Also allow versions 1.0.1 through 1.0.1f if a Heartbleed vulnerability test passes.
# We assume that a library patched for Heartbleed is also patched for previous
# security bugs that affected 1.0.1 through 1.0.1c.
#
- # We do this check only if the version and compiler flag checks are inconclusive, to
- # minimize the chance for the test to break or give the wrong result somehow.
- if not is_vulnerable(SSL):
- return
+ # We do this check only if the version check above is inconclusive, to minimize the
+ # chance for the test to break or give the wrong result somehow.
+ check_resistant_to_heartbleed(SSL)
+
+ except Exception, e:
+ #import traceback
+ #traceback.print_exc()
+ pass
- raise OpenSSLVersionError("refusing to use %s which may be vulnerable to security bugs.\n"
- "Please upgrade to OpenSSL 1.0.1g or later." % (openssl_version,))
+ raise UnsafeOpenSSLError("refusing to use %s which may be vulnerable to security bugs.\n"
+ "Please upgrade to OpenSSL 1.0.1g or later." % (openssl_version,))
# As simple as possible, but no simpler.
'\x00\x01' # payload length (0 bytes)
) + '\x00'*33
-def is_vulnerable(SSL):
+def check_resistant_to_heartbleed(SSL):
def verify_callback(connection, x509, errnum, errdepth, ok):
return ok
if __name__ == '__main__':
from OpenSSL import SSL
#check_openssl_version(SSL)
- #print "Not vulnerable."
- print is_vulnerable(SSL)
+ check_resistant_to_heartbleed(SSL)
+ print "Not vulnerable."