def test_basic_certificate_validator_tls_expired(self):
        cert = self._load_cert_object('codex.crt')
        other_certs = [self._load_cert_object('GeoTrust_EV_SSL_CA_-_G4.crt')]

        validator = CertificateValidator(cert, other_certs)

        with self.assertRaisesRegexp(PathValidationError, 'expired'):
            validator.validate_tls('codexns.io')
예제 #2
0
    def test_basic_certificate_validator_tls_expired(self):
        cert = self._load_cert_object('codex.crt')
        other_certs = [self._load_cert_object('GeoTrust_EV_SSL_CA_-_G4.crt')]

        validator = CertificateValidator(cert, other_certs)

        with self.assertRaisesRegexp(PathValidationError, 'expired'):
            validator.validate_tls('codexns.io')
    def test_basic_certificate_validator_tls_invalid_hostname(self):
        cert = self._load_cert_object('codex.crt')
        other_certs = [self._load_cert_object('GeoTrust_EV_SSL_CA_-_G4.crt')]

        moment = datetime(2015, 1, 1, 0, 0, 0, tzinfo=timezone.utc)

        context = ValidationContext(moment=moment)
        validator = CertificateValidator(cert, other_certs, context)

        with self.assertRaisesRegexp(PathValidationError, 'not valid'):
            validator.validate_tls('google.com')
예제 #4
0
    def test_basic_certificate_validator_tls_invalid_hostname(self):
        cert = self._load_cert_object('codex.crt')
        other_certs = [self._load_cert_object('GeoTrust_EV_SSL_CA_-_G4.crt')]

        moment = datetime(2015, 1, 1, 0, 0, 0, tzinfo=timezone.utc)

        context = ValidationContext(moment=moment)
        validator = CertificateValidator(cert, other_certs, context)

        with self.assertRaisesRegexp(PathValidationError, 'not valid'):
            validator.validate_tls('google.com')
예제 #5
0
    def test_basic_certificate_validator_tls_invalid_hostname(self):
        cert = self._load_cert_object('mozilla.org.crt')
        other_certs = [self._load_cert_object('digicert-sha2-secure-server-ca.crt')]

        moment = datetime(2019, 1, 1, 0, 0, 0, tzinfo=timezone.utc)

        context = ValidationContext(moment=moment)
        validator = CertificateValidator(cert, other_certs, context)

        with self.assertRaisesRegex(PathValidationError, 'not valid'):
            validator.validate_tls('google.com')
    def test_basic_certificate_validator_tls_whitelist(self):
        cert = self._load_cert_object('codex.crt')
        other_certs = [self._load_cert_object('GeoTrust_EV_SSL_CA_-_G4.crt')]

        context = ValidationContext(whitelisted_certs=[cert.sha1_fingerprint])
        validator = CertificateValidator(cert, other_certs, context)

        # If whitelist does not work, this will raise exception for expiration
        validator.validate_tls('codexns.io')

        # If whitelist does not work, this will raise exception for hostname
        validator.validate_tls('google.com')

        # If whitelist does not work, this will raise exception for key usage
        validator.validate_usage(set(['crl_sign']))
예제 #7
0
    def test_basic_certificate_validator_tls_whitelist(self):
        cert = self._load_cert_object('codex.crt')
        other_certs = [self._load_cert_object('GeoTrust_EV_SSL_CA_-_G4.crt')]

        context = ValidationContext(whitelisted_certs=[cert.sha1_fingerprint])
        validator = CertificateValidator(cert, other_certs, context)

        # If whitelist does not work, this will raise exception for expiration
        validator.validate_tls('codexns.io')

        # If whitelist does not work, this will raise exception for hostname
        validator.validate_tls('google.com')

        # If whitelist does not work, this will raise exception for key usage
        validator.validate_usage(set(['crl_sign']))
    def test_basic_certificate_validator_tls(self):
        cert = self._load_cert_object('codex.crt')
        other_certs = [self._load_cert_object('GeoTrust_EV_SSL_CA_-_G4.crt')]

        moment = datetime(2015, 1, 1, 0, 0, 0, tzinfo=timezone.utc)

        context = ValidationContext(moment=moment)
        validator = CertificateValidator(cert, other_certs, context)

        path = validator.validate_tls('codexns.io')
        self.assertEqual(3, len(path))
예제 #9
0
    def test_basic_certificate_validator_tls(self):
        cert = self._load_cert_object('codex.crt')
        other_certs = [self._load_cert_object('GeoTrust_EV_SSL_CA_-_G4.crt')]

        moment = datetime(2015, 1, 1, 0, 0, 0, tzinfo=timezone.utc)

        context = ValidationContext(moment=moment)
        validator = CertificateValidator(cert, other_certs, context)

        path = validator.validate_tls('codexns.io')
        self.assertEqual(3, len(path))
예제 #10
0
    def test_basic_certificate_validator_tls_whitelist(self):
        cert = self._load_cert_object('mozilla.org.crt')
        other_certs = [self._load_cert_object('digicert-sha2-secure-server-ca.crt')]

        moment = datetime(2020, 1, 1, 0, 0, 0, tzinfo=timezone.utc)

        context = ValidationContext(
            whitelisted_certs=[cert.sha1_fingerprint],
            moment=moment
        )
        validator = CertificateValidator(cert, other_certs, context)

        # If whitelist does not work, this will raise exception for expiration
        validator.validate_tls('www.mozilla.org')

        # If whitelist does not work, this will raise exception for hostname
        validator.validate_tls('google.com')

        # If whitelist does not work, this will raise exception for key usage
        validator.validate_usage(set(['crl_sign']))
예제 #11
0
    def test_basic_certificate_validator_tls(self):
        cert = self._load_cert_object('mozilla.org.crt')
        other_certs = [self._load_cert_object('digicert-sha2-secure-server-ca.crt')]

        moment = datetime(2019, 1, 1, 0, 0, 0, tzinfo=timezone.utc)

        context = ValidationContext(moment=moment)
        validator = CertificateValidator(cert, other_certs, context)

        path = validator.validate_tls('www.mozilla.org')
        self.assertEqual(3, len(path))
예제 #12
0
    def _validate_chain_certvalidator(self, tlslite_connection):
        """Validate server certificate chain using 3rd party certvalidator library which uses oscrypt/libcrypto
        Note: oscrypt uses ctypes find_library() which does not work in certain distributions such as alpine.
        (e.g. see https://github.com/docker-library/python/issues/111)
        On such systems, users will have to rely on other server cert validation approaches such as using openssl
        or turning it off completely.
        """
        try:
            from certvalidator import CertificateValidator
            from certvalidator import ValidationContext
            from asn1crypto import x509, pem

            # validate server certificate chain
            session = tlslite_connection.sock.session
            assert type(session.serverCertChain.x509List) == list

            # get the end-entity cert
            file_bytes = session.serverCertChain.x509List[0].bytes
            end_entity_cert = x509.Certificate.load(str(file_bytes))

            def cert_files_exist(path, file_names):
                file_names = [os.path.join(path, f) for f in file_names]
                for f in file_names:
                    if not os.path.isfile(f):
                        return False
                return True

            def get_cert_bytes(cert_dir, file_names):
                file_names = [os.path.join(cert_dir, f) for f in file_names]
                result = []
                for fname in file_names:
                    arr = open(fname, "rb").read()
                    cert_bytes = pem.unarmor(arr)[2]
                    result.append(cert_bytes)
                return result

            intermediate_cert_names = [
                "comodo_ca_intermediate.pem",
                "sectigo_ca_intermediate.pem",
            ]

            extra_trust_names = [
                "scalyr_agent_ca_root.pem",
                "addtrust_external_ca_root.pem",
            ]

            # Determine the directory containing the certs.
            # First check the directory containing the _ca_file
            # but if we don't find the intermediate/extra certs there
            # then look in the relative `certs` directory.  The latter
            # will typically be required if running directly from source
            all_cert_names = intermediate_cert_names + extra_trust_names
            cert_dir = os.path.dirname(self._ca_file)
            if not cert_files_exist(cert_dir, all_cert_names):
                path = os.path.dirname(os.path.abspath(__file__))
                path = os.path.abspath(path + "../../certs")
                if cert_files_exist(path, all_cert_names):
                    cert_dir = path

            trust_roots = None
            intermediate_certs = get_cert_bytes(cert_dir, intermediate_cert_names)
            extra_trust_roots = get_cert_bytes(cert_dir, extra_trust_names)

            if trust_roots:
                context = ValidationContext(
                    trust_roots=trust_roots,
                    extra_trust_roots=extra_trust_roots,
                    other_certs=intermediate_certs,
                    # whitelisted_certs=[end_entity_cert.sha1_fingerprint],
                )
            else:
                context = ValidationContext(
                    extra_trust_roots=extra_trust_roots,
                    other_certs=intermediate_certs,
                    # whitelisted_certs=[end_entity_cert.sha1_fingerprint],
                )
            validator = CertificateValidator(
                end_entity_cert, validation_context=context
            )
            validator.validate_tls(six.text_type(self._host))
            log.info(
                "Scalyr server cert chain successfully validated via certvalidator library"
            )
        except Exception as ce:
            log.exception("Error validating server certificate chain: %s" % ce)
            raise
예제 #13
0
def run():
    """
    Runs through TLS hosts in the Alexa top 1000 to test TLS functionality

    :return:
        A bool - if the test succeeded without any socket errors
    """

    task_start = time.time()
    success = 0
    tls_errors = 0
    socket_errors = 0
    mismatch_info = []

    context = ValidationContext(allow_fetching=True)

    with open(os.path.join(fixtures_dir, 'alexa_top_1000.csv'), 'rb') as f:
        for line in f:
            domain = line.decode('utf-8').rstrip()
            os_result = None
            cv_result = None
            os_message = None
            cv_message = None

            try:
                os_start = time.time()
                con = tls.TLSSocket(domain, 443, timeout=3)
                con.close()
                success += 1
                os_result = 'OK'
                os_message = 'Success'
                _color('green', 'OK', domain, os_start)
            except (TLSVerificationError) as e:
                tls_errors += 1
                os_result = 'TLS'
                os_message = str_cls(e)
                _color('yellow', 'TLS', domain, os_start, str_cls(e))
            except (socket.error) as e:
                socket_errors += 1
                os_result = 'SOCK'
                os_message = str_cls(e)
                _color('red', 'SOCK', domain, os_start, str_cls(e))

            try:
                cv_start = time.time()
                session = tls.TLSSession(manual_validation=True)
                con = tls.TLSSocket(domain, 443, timeout=3, session=session)
                validator = CertificateValidator(con.certificate,
                                                 con.intermediates, context)
                validator.validate_tls(domain)
                con.close()
                success += 1
                cv_result = 'OK'
                cv_message = 'Success'
                _color('green', 'OK', domain, cv_start)
            except (PathValidationError, PathBuildingError) as e:
                tls_errors += 1
                cv_result = 'TLS'
                cv_message = str_cls(e)
                _color('yellow', 'TLS', domain, cv_start, str_cls(e))
            except (socket.error) as e:
                socket_errors += 1
                cv_result = 'SOCK'
                cv_message = str_cls(e)
                _color('red', 'SOCK', domain, cv_start, str_cls(e))

            if os_result != cv_result:
                mismatch_info.append(
                    [domain, os_result, os_message, cv_result, cv_message])

    total_time = time.time() - task_start
    total_domains = success + tls_errors + socket_errors

    stats = []
    if success > 0:
        stats.append('%d [%sOK%s]' % (success, Fore.GREEN, Fore.RESET))
    if tls_errors > 0:
        stats.append('%d [%sTLS%s]' % (tls_errors, Fore.YELLOW, Fore.RESET))
    if socket_errors > 0:
        stats.append('%d [%sSOCK%s]' % (socket_errors, Fore.RED, Fore.RESET))
    print('')
    print('Checked %d domains in %.3f seconds - %s' %
          (total_domains, total_time, ' '.join(stats)))

    if mismatch_info:
        print('')
        for info in mismatch_info:
            os_result = '[%s] %s' % (info[1], info[2])
            cv_result = '[%s] %s' % (info[3], info[4])
            _color(
                'red', 'DIFF',
                'oscrypto and certvalidator results for %s are different' %
                info[0], None, os_result, cv_result)

    return socket_errors == 0
예제 #14
0
def run():
    """
    Runs through TLS hosts in the Alexa top 1000 to test TLS functionality

    :return:
        A bool - if the test succeeded without any socket errors
    """

    task_start = time.time()
    success = 0
    tls_errors = 0
    socket_errors = 0
    mismatch_info = []

    context = ValidationContext(allow_fetching=True)

    with open(os.path.join(fixtures_dir, 'alexa_top_1000.csv'), 'rb') as f:
        for line in f:
            domain = line.decode('utf-8').rstrip()
            os_result = None
            cv_result = None
            os_message = None
            cv_message = None

            try:
                os_start = time.time()
                con = tls.TLSSocket(domain, 443, timeout=3)
                con.close()
                success += 1
                os_result = 'OK'
                os_message = 'Success'
                _color('green', 'OK', domain, os_start)
            except (TLSVerificationError) as e:
                tls_errors += 1
                os_result = 'TLS'
                os_message = str_cls(e)
                _color('yellow', 'TLS', domain, os_start, str_cls(e))
            except (socket.error) as e:
                socket_errors += 1
                os_result = 'SOCK'
                os_message = str_cls(e)
                _color('red', 'SOCK', domain, os_start, str_cls(e))

            try:
                cv_start = time.time()
                session = tls.TLSSession(manual_validation=True)
                con = tls.TLSSocket(domain, 443, timeout=3, session=session)
                validator = CertificateValidator(con.certificate, con.intermediates, context)
                validator.validate_tls(domain)
                con.close()
                success += 1
                cv_result = 'OK'
                cv_message = 'Success'
                _color('green', 'OK', domain, cv_start)
            except (PathValidationError, PathBuildingError) as e:
                tls_errors += 1
                cv_result = 'TLS'
                cv_message = str_cls(e)
                _color('yellow', 'TLS', domain, cv_start, str_cls(e))
            except (socket.error) as e:
                socket_errors += 1
                cv_result = 'SOCK'
                cv_message = str_cls(e)
                _color('red', 'SOCK', domain, cv_start, str_cls(e))

            if os_result != cv_result:
                mismatch_info.append([
                    domain,
                    os_result,
                    os_message,
                    cv_result,
                    cv_message
                ])

    total_time = time.time() - task_start
    total_domains = success + tls_errors + socket_errors

    stats = []
    if success > 0:
        stats.append('%d [%sOK%s]' % (success, Fore.GREEN, Fore.RESET))
    if tls_errors > 0:
        stats.append('%d [%sTLS%s]' % (tls_errors, Fore.YELLOW, Fore.RESET))
    if socket_errors > 0:
        stats.append('%d [%sSOCK%s]' % (socket_errors, Fore.RED, Fore.RESET))
    print('')
    print('Checked %d domains in %.3f seconds - %s' % (total_domains, total_time, ' '.join(stats)))

    if mismatch_info:
        print('')
        for info in mismatch_info:
            os_result = '[%s] %s' % (info[1], info[2])
            cv_result = '[%s] %s' % (info[3], info[4])
            _color(
                'red',
                'DIFF',
                'oscrypto and certvalidator results for %s are different' % info[0],
                None,
                os_result,
                cv_result
            )

    return socket_errors == 0
예제 #15
0
 def _verify_certificates(self, hostname):
     validator = CertificateValidator(self.certificates[0], self.certificates[1:])
     validator.validate_tls(hostname)