Beispiel #1
0
def addsig(ctx, field, name, reason, location, certify, existing_only,
           timestamp_url, use_pades, with_validation_info, validation_context,
           trust_replace, trust, other_certs, style_name, stamp_url):
    ctx.obj[Ctx.EXISTING_ONLY] = existing_only or field is None
    ctx.obj[Ctx.TIMESTAMP_URL] = timestamp_url

    if use_pades:
        subfilter = fields.SigSeedSubFilter.PADES
    else:
        subfilter = fields.SigSeedSubFilter.ADOBE_PKCS7_DETACHED

    if with_validation_info:
        vc_kwargs = _build_vc_kwargs(ctx,
                                     validation_context,
                                     trust,
                                     trust_replace,
                                     other_certs,
                                     allow_fetching=True)
        vc = ValidationContext(**vc_kwargs)
    else:
        vc = None
    field_name, new_field_spec = parse_field_location_spec(
        field, require_full_spec=False)
    ctx.obj[Ctx.SIG_META] = signers.PdfSignatureMetadata(
        field_name=field_name,
        location=location,
        reason=reason,
        name=name,
        certify=certify,
        subfilter=subfilter,
        embed_validation_info=with_validation_info,
        validation_context=vc)
    ctx.obj[Ctx.NEW_FIELD_SPEC] = new_field_spec
    ctx.obj[Ctx.STAMP_STYLE] = _select_style(ctx, style_name, stamp_url)
    ctx.obj[Ctx.STAMP_URL] = stamp_url
Beispiel #2
0
    def _check_certificate(self, certificate):

        _, _, certificate_bytes = pem.unarmor(
            certificate.encode(), multiple=False)
        certificate = x509.Certificate.load(certificate_bytes)

        trust_roots = []
        with open(self.ca_crt, 'rb') as f:
            for _, _, der_bytes in pem.unarmor(f.read(), multiple=True):
                trust_roots.append(der_bytes)

        crls = []
        with open(settings.CA_CRL, 'rb') as f:
            crls.append(f.read())

        context = ValidationContext(crls=crls,
                                    trust_roots=trust_roots)

        try:
            validator = CertificateValidator(
                certificate, validation_context=context)
            result = validator.validate_usage(
                set(['digital_signature'])
            )
            dev = True
        except errors.PathValidationError as e:
            logger.debug("SimpleCA: validate PathValidationError %r" % (e))
            dev = False
        except errors.PathBuildingError as e:
            logger.debug("SimpleCA: validate PathBuildingError %r" % (e))
            dev = False
        logger.info("SimpleCA: validate cert %r == %r" %
                    (certificate.serial_number, dev))
        return dev
Beispiel #3
0
 def get_validation_context(self, name=None, as_dict=False):
     name = name or self.default_validation_context
     try:
         vc_config = self.validation_contexts[name]
     except KeyError:
         raise ConfigurationError(
             f"There is no validation context named '{name}'.")
     vc_kwargs = parse_trust_config(vc_config, self.time_tolerance)
     return vc_kwargs if as_dict else ValidationContext(**vc_kwargs)
Beispiel #4
0
def lta_update(ctx, infile, validation_context, trust, trust_replace,
               other_certs, timestamp_url):
    with pyhanko_exception_manager():
        vc_kwargs = _build_vc_kwargs(ctx, validation_context, trust,
                                     trust_replace, other_certs)
        timestamper = HTTPTimeStamper(timestamp_url)
        r = PdfFileReader(infile)
        signers.PdfTimeStamper(timestamper).update_archival_timestamp_chain(
            r, ValidationContext(**vc_kwargs))
Beispiel #5
0
 def test_crl_without_update_field(self):
     cert = self._load_cert_object('microsoft_armored.crt')
     root_certificates = self._load_trust_roots(
         os.path.join(fixtures_dir, 'root_certs'))
     moment = datetime(2009, 1, 1, 0, 0, 0, tzinfo=timezone.utc)
     context = ValidationContext(trust_roots=root_certificates,
                                 moment=moment,
                                 allow_fetching=True)
     validator = CertificateValidator(cert, validation_context=context)
     validator.validate_usage(set(['digital_signature']),
                              set(['code_signing']), False)
Beispiel #6
0
    def test_basic_certificate_validator_tls_invalid_key_usage(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, 'for the purpose'):
            validator.validate_usage(set(['crl_sign']))
Beispiel #7
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')
Beispiel #8
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))
Beispiel #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))
Beispiel #10
0
    def test_basic_certificate_validator_tls_invalid_key_usage(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, 'for the purpose'):
            validator.validate_usage(set(['crl_sign']))
Beispiel #11
0
    def verify(self, certificate):
        """Verifies the certificate, and its chain.

        :param Certificate certificate: The certificate to verify
        :return: A valid certificate chain for this certificate.
        :rtype: Iterable[Certificate]
        :raises AuthenticodeVerificationError: When the certificate could not be verified.
        """

        # we keep track of our asn1 objects to make sure we return Certificate objects when we're done
        to_check_asn1cert = certificate.to_asn1crypto
        all_certs = {to_check_asn1cert: certificate}

        # we need to get lists of our intermediates and trusted certificates
        intermediates, trust_roots = [], []
        for store in self.stores:
            for cert in store:
                asn1cert = cert.to_asn1crypto
                # we short-circuit the check here to ensure we do not check too much possibilities
                (trust_roots
                 if store.trusted else intermediates).append(asn1cert)
                all_certs[asn1cert] = cert

        # construct the context and validator for certvalidator
        timestamp = self.timestamp
        context = ValidationContext(
            trust_roots=list(trust_roots),
            moment=timestamp,
            weak_hash_algos=set() if self.allow_legacy else None,
            revocation_mode=self.revocation_mode,
            allow_fetching=self.allow_fetching,
            crl_fetch_params={'timeout': self.fetch_timeout},
            ocsp_fetch_params={'timeout': self.fetch_timeout},
            crls=self.crls,
            ocsps=self.ocsps)
        validator = CertificateValidator(
            end_entity_cert=to_check_asn1cert,
            intermediate_certs=list(intermediates),
            validation_context=context)

        # verify the chain
        try:
            chain = validator.validate_usage(
                key_usage=set(self.key_usages) if self.key_usages else set(),
                extended_key_usage=set(self.extended_key_usages)
                if self.extended_key_usages else set(),
                extended_optional=self.optional_eku)
        except Exception as e:
            raise VerificationError("Chain verification from %s failed: %s" %
                                    (certificate, e))

        signify_chain = [all_certs[x] for x in chain]
        self.verify_trust(signify_chain[0])
        return signify_chain
Beispiel #12
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')
Beispiel #13
0
    def validate_certificate(self, ca_certs: List[bytes]) -> bool:

        if not ca_certs:
            raise ValueError("ca_certs should be set.")
        if not self._cert:
            return False

        ctx = ValidationContext(trust_roots=ca_certs)
        try:
            validator = CertificateValidator(self._cert, self._intermediates, validation_context=ctx)
            validator.validate_usage(set(["digital_signature"]), extended_optional=True)
        except Exception as err:
            raise VerifyError("Failed to validate the certificate bound to the key.") from err
        return True
Beispiel #14
0
 def __init__(
     self,
     expected_measurement=None,
     accept_debug=False,
     accept_configuration_needed=False,
     accept_group_out_of_date=False,
 ):
     self.expected_measurement = expected_measurement
     self.accept_debug = accept_debug
     self.accept_configuration_needed = accept_configuration_needed
     self.accept_group_out_of_date = accept_group_out_of_date
     trust_roots = []
     for _, _, der_bytes in pem.unarmor(intel_sgx_root_ca, multiple=True):
         trust_roots.append(der_bytes)
     self.context = ValidationContext(trust_roots=trust_roots)
Beispiel #15
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']))
Beispiel #16
0
 def test_crl_without_update_field_hard_fail(self):
     cert = self._load_cert_object('microsoft_armored.crt')
     root_certificates = self._load_trust_roots(
         os.path.join(fixtures_dir, 'root_certs'))
     moment = datetime(2009, 1, 1, 0, 0, 0, tzinfo=timezone.utc)
     context = ValidationContext(trust_roots=root_certificates,
                                 moment=moment,
                                 allow_fetching=True,
                                 revocation_mode='hard-fail')
     validator = CertificateValidator(cert, validation_context=context)
     with self.assertRaisesRegexp(
             PathValidationError,
             'nextUpdate field is expected to be present in CRL'):
         validator.validate_usage(set(['digital_signature']),
                                  set(['code_signing']), False)
Beispiel #17
0
    def initialiser(self):
        # Charger le contexte de validation
        with open(self._contexte.configuration.mq_cafile, 'rb') as fichier:
            self.__cert_millegrille = fichier.read()
        self.__validation_context = ValidationContext(
            trust_roots=[self.__cert_millegrille])

        self._charger_cle_privee()
        self._charger_certificat()

        self._enveloppe = EnveloppeCertificat(
            certificat_pem='\n'.join(self._chaine))

        # Verifier que le certificat peut bien etre utilise pour signer des transactions
        # Valide aussi la chaine et les dates d'expiration
        self.valider_x509_enveloppe(self._enveloppe)
Beispiel #18
0
    def verify(self, certificate):
        """Verifies the certificate, and its chain.

        :param Certificate certificate: The certificate to verify
        :return: A valid certificate chain for this certificate.
        :rtype: Iterable[Certificate]
        :raises AuthenticodeVerificationError: When the certificate could not be verified.
        """

        # we keep track of our asn1 objects to make sure we return Certificate objects when we're done
        to_check_asn1cert = certificate.to_asn1crypto
        all_certs = {to_check_asn1cert: certificate}

        # we need to get lists of our intermediates and trusted certificates
        intermediates, trust_roots = [], []
        for store in self.stores:
            for cert in store:
                asn1cert = cert.to_asn1crypto
                (trust_roots
                 if store.trusted else intermediates).append(asn1cert)
                all_certs[asn1cert] = cert

        # construct the context and validator for certvalidator
        context = ValidationContext(
            trust_roots=list(trust_roots),
            moment=self.timestamp,
            weak_hash_algos=set() if self.allow_legacy else None)
        validator = CertificateValidator(
            end_entity_cert=to_check_asn1cert,
            intermediate_certs=list(intermediates),
            validation_context=context)

        # verify the chain
        try:
            chain = validator.validate_usage(
                key_usage=set(self.key_usages) if self.key_usages else set(),
                extended_key_usage=set(self.extended_key_usages)
                if self.extended_key_usages else set(),
                extended_optional=self.optional_eku)
        except Exception as e:
            raise VerificationError("Chain verification from %s failed: %s" %
                                    (certificate, e))
        else:
            return [all_certs[x] for x in chain]
Beispiel #19
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']))
Beispiel #20
0
def verify_chain(certificate: Union[str, x509.Certificate], ca: str):
    if isinstance(certificate, x509.Certificate):
        pem = certificate.public_bytes(serialization.Encoding.PEM)
    else:
        if certificate.startswith("-----BEGIN CERTIFICATE-----"):
            pem = certificate.encode()
        else:
            with open(certificate, "rb") as my_file:
                pem = my_file.read()
        # cert = x509.load_pem_x509_certificate(pem, default_backend())

    with open(ca, "rb") as my_file:
        pem_ca = my_file.read()
    # ca = x509.load_pem_x509_certificate(pem_ca, default_backend())

    trust_roots = [pem_ca]
    context = ValidationContext(trust_roots=trust_roots)

    validator = CertificateValidator(pem, validation_context=context)
    return validator.validate_usage({"digital_signature"})
Beispiel #21
0
def _signature_status(ltv_profile, ltv_obsessive, pretty_print, vc_kwargs,
                      executive_summary, embedded_sig):
    try:
        if ltv_profile is None:
            vc = ValidationContext(**vc_kwargs)
            status = validation.validate_pdf_signature(
                embedded_sig, signer_validation_context=vc)
        else:
            status = validation.validate_pdf_ltv_signature(
                embedded_sig,
                ltv_profile,
                force_revinfo=ltv_obsessive,
                validation_context_kwargs=vc_kwargs)
        if executive_summary and not pretty_print:
            return 'VALID' if status.bottom_line else 'INVALID'
        elif pretty_print:
            return status.pretty_print_details()
        else:
            return status.summary()
    except validation.ValidationInfoReadingError as e:
        msg = ('An error occurred while parsing the revocation information '
               'for this signature: ' + str(e))
        logger.error(msg, exc_info=e)
        if pretty_print:
            return msg
        else:
            return 'REVINFO_FAILURE'
    except SignatureValidationError as e:
        msg = 'An error occurred while validating this signature: ' + str(e)
        logger.error(msg, exc_info=e)
        if pretty_print:
            return msg
        else:
            return 'INVALID'
    except Exception as e:
        msg = 'Generic processing error: ' + str(e)
        logger.error(msg, exc_info=e)
        if pretty_print:
            return msg
        else:
            return 'MALFORMED'
Beispiel #22
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
Beispiel #23
0
    def validate(self, root_ca: CaSecret, with_openssl: bool = False):
        '''
        Validate that the cert and its certchain are anchored to the root cert.
        This function does not check certificate recovation or OCSP

        :param Secret root_ca: the self-signed root CA to validate against
        :param with_openssl: also use the openssl binary to validate the cert
        :returns: (none)
        :raises: ValueError if the certchain is invalid
        '''

        pem_signed_cert = self.cert_as_pem()
        pem_cert_chain = [
            x.public_bytes(serialization.Encoding.PEM) for x in self.cert_chain
        ]
        context = ValidationContext(trust_roots=[root_ca.cert_as_pem()])
        validator = CertificateValidator(pem_signed_cert,
                                         pem_cert_chain,
                                         validation_context=context)
        try:
            validator.validate_usage(set())
        except (ValidationError, PathBuildingError) as exc:
            raise ValueError(f'Certchain failed validation: {exc}') from exc

        if not with_openssl:
            return

        tmpdir = tempfile.TemporaryDirectory()
        rootfile = tmpdir.name + '/rootca.pem'
        with open(rootfile, 'w') as file_desc:
            file_desc.write(root_ca.cert_as_pem().decode('utf-8'))

        certfile = tmpdir.name + '/cert.pem'
        with open(certfile, 'w') as file_desc:
            file_desc.write(self.cert_as_pem().decode('utf-8'))

        cmd = [
            'openssl',
            'verify',
            '-CAfile',
            rootfile,
        ]

        if self.cert_chain:
            chainfile = tmpdir.name + '/chain.pem'
            with open(chainfile, 'w') as file_desc:
                for cert in self.cert_chain:
                    file_desc.write(
                        cert.public_bytes(
                            serialization.Encoding.PEM).decode('utf-8'))
            cmd.extend(['-untrusted', chainfile])

        cmd.append(certfile)
        result = subprocess.run(cmd)

        if result.returncode != 0:
            raise ValueError(
                f'Certificate validation with command {" ".join(cmd)} '
                f'failed: {result.returncode} for cert {certfile} and '
                f'root CA {rootfile}')

        tmpdir.cleanup()

        _LOGGER.debug('Successfully validated certchain using OpenSSL for '
                      f'cert {certfile} and root CA {rootfile}')
Beispiel #24
0
    def valider_x509_enveloppe(self,
                               enveloppe: EnveloppeCertificat,
                               date_reference: datetime.datetime = None):
        """
        Valide une enveloppe
        :param enveloppe:
        :param date_reference:
        :param ignorer_date: Charger le certificat en utilisation date courante ou fin de periode de validite
        :return: Resultat de validation (toujours valide)
        :raises certvalidator.errors.PathBuildingError: Si le path est invalide
        """
        cert_pem = enveloppe.certificat_pem.encode('utf-8')
        inter_list = list()

        # self._logger.debug("CERT PEM :\n%s" % enveloppe.certificat_pem)
        for pem in enveloppe.reste_chaine_pem:
            # self._logger.debug("Chaine PEM :\n%s" % pem.strip())
            inter_list.append(pem.strip().encode('utf-8'))

        if date_reference is not None:
            # batir un contexte avec la date
            validation_context = ValidationContext(
                moment=date_reference, trust_roots=[self.__cert_millegrille])
        else:
            validation_context = self.__validation_context

        # Verifier le certificat - noter qu'une exception est lancee en cas de probleme
        try:
            validator = CertificateValidator(
                cert_pem,
                intermediate_certs=inter_list,
                validation_context=validation_context)
            resultat = validator.validate_usage({'digital_signature'})
            enveloppe.set_est_verifie(True)
        except PathValidationError as pve:
            msg = pve.args[0]
            if 'expired' in msg:
                self._logger.info(
                    "Un des certificats est expire, verifier en fonction de la date de reference"
                )
                # Le certificat est expire, on fait la validation pour la fin de la periode de validite
                date_reference = pytz.UTC.localize(enveloppe.not_valid_after)
                validation_context = ValidationContext(
                    moment=date_reference,
                    trust_roots=[self.__cert_millegrille])
                validator = CertificateValidator(
                    cert_pem,
                    intermediate_certs=inter_list,
                    validation_context=validation_context)
                try:
                    resultat = validator.validate_usage({'digital_signature'})
                    enveloppe.set_est_verifie(True)
                    raise CertificatExpire(
                    )  # La chaine est valide pour une date anterieure
                except PathValidationError as pve:
                    if self._logger.isEnabledFor(logging.DEBUG):
                        self._logger.exception(
                            "Erreur validation path certificat")
                    else:
                        self._logger.info(
                            "Erreur validation path certificat : %s", str(pve))
            else:
                if self._logger.isEnabledFor(logging.DEBUG):
                    self._logger.exception("Erreur validation path certificat")
                else:
                    self._logger.info("Erreur validation path certificat : %s",
                                      str(pve))
                raise pve

        except PathBuildingError as pbe:
            # Verifier si on a une millegrille tierce
            dernier_cert_pem = inter_list[-1]
            dernier_cert = EnveloppeCertificat(certificat_pem=dernier_cert_pem)
            if dernier_cert.is_rootCA:
                idmg = dernier_cert.idmg
                # Verifier si le idmg est dans la liste des idmg autorises
                autorisation = self.__autorisations_idmg.get(idmg)
                if autorisation is None:
                    # Pas autorise, lancer l'exception
                    raise pbe
                elif autorisation.get('domaines_permis'):
                    # Valider la chaine en fonction de la racine fournie
                    if date_reference is not None:
                        # batir un contexte avec la date
                        validation_context = ValidationContext(
                            moment=date_reference,
                            trust_roots=[
                                self.__cert_millegrille, dernier_cert_pem
                            ])
                    else:
                        validation_context = ValidationContext(trust_roots=[
                            self.__cert_millegrille, dernier_cert_pem
                        ])

                    validator = CertificateValidator(
                        cert_pem,
                        intermediate_certs=inter_list,
                        validation_context=validation_context)

                    validator.validate_usage({'digital_signature'})

                    # Valide, on lance une exception pour indiquer la condition de validite (business rule)
                    raise AutorisationConditionnelleDomaine(
                        autorisation['domaines_permis'], idmg, enveloppe)

        return resultat
Beispiel #25
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
Beispiel #26
0
    def verify_bib(self, ctr, bib):
        addl_protected = b''
        addl_unprotected = {}
        aad_scope = 0x7
        for param in bib.payload.parameters:
            if param.type_code == 3:
                addl_protected = bytes(param.value)
            elif param.type_code == 4:
                addl_unprotected = dict(param.value)
            elif param.type_code == 5:
                aad_scope = int(param.value)

        addl_protected_map = cbor2.loads(
            addl_protected) if addl_protected else {}
        dupe_keys = set(addl_protected_map.keys()).intersection(
            set(addl_unprotected.keys()))
        if dupe_keys:
            LOGGER.warning('Duplicate keys in additional headers: %s',
                           dupe_keys)
            return StatusReport.ReasonCode.FAILED_SEC
        addl_headers = dict(addl_protected_map)
        addl_headers.update(addl_unprotected)

        bundle_at = DtnTimeField.dtntime_to_datetime(
            ctr.bundle.primary.create_ts.getfieldval('dtntime'))
        val_ctx = ValidationContext(
            trust_roots=[
                cert.public_bytes(serialization.Encoding.DER)
                for cert in self._ca_certs
            ],
            other_certs=[
                cert.public_bytes(serialization.Encoding.DER)
                for cert in self._cert_chain
            ],
            moment=bundle_at,
        )
        LOGGER.debug('Validating certificates at time %s', bundle_at)

        failure = None
        for (ix, blk_num) in enumerate(bib.payload.targets):
            target_blk = ctr.block_num(blk_num)
            for result in bib.payload.results[ix].results:
                msg_cls = CoseMessage._COSE_MSG_ID[result.type_code]

                # replace detached payload
                msg_enc = bytes(result.getfieldval('value'))
                msg_dec = cbor2.loads(msg_enc)
                LOGGER.debug('Received COSE message\n%s',
                             encode_diagnostic(msg_dec))
                msg_dec[2] = target_blk.getfieldval('btsd')

                msg_obj = msg_cls.from_cose_obj(msg_dec)
                msg_obj.external_aad = CoseContext.get_bpsec_cose_aad(
                    ctr, target_blk, bib, aad_scope, addl_protected)
                # use additional headers as defaults
                for (key, val) in msg_cls._parse_header(addl_headers).items():
                    msg_obj.uhdr.setdefault(key, val)
                LOGGER.info('full uhdr %s', msg_obj.uhdr)

                x5t_item = msg_obj.get_attr(headers.X5t)
                x5t = X5T.decode(x5t_item) if x5t_item else None

                x5chain_item = msg_obj.get_attr(headers.X5chain)
                if isinstance(x5chain_item, bytes):
                    x5chain = [x5chain_item]
                else:
                    x5chain = x5chain_item
                LOGGER.info('Validating X5t %s and X5chain length %d',
                            x5t.encode() if x5t else None,
                            len(x5chain) if x5chain else 0)

                if x5t is None and x5chain:
                    # Only one possible end-entity cert
                    LOGGER.warning('No X5T in header, assuming single chain')
                    found_chain = x5chain
                else:
                    try:
                        found_chain = x5chain if x5t.matches(
                            x5chain[0]) else None
                        if not found_chain:
                            raise RuntimeError(
                                'No chain matcing end-entity cert for {}'.
                                format(x5t.encode()))
                        LOGGER.debug(
                            'Found chain matcing end-entity cert for %s',
                            x5t.encode())
                    except Exception as err:
                        LOGGER.error(
                            'Failed to find cert chain for block num %d: %s',
                            blk_num, err)
                        failure = StatusReport.ReasonCode.FAILED_SEC
                        continue

                LOGGER.debug('Validating chain with %d certs against %d CAs',
                             len(found_chain), len(self._ca_certs))
                try:
                    val = CertificateValidator(
                        end_entity_cert=found_chain[0],
                        intermediate_certs=found_chain[1:],
                        validation_context=val_ctx)
                    val.validate_usage(
                        key_usage={'digital_signature'},
                        extended_key_usage={'1.3.6.1.5.5.7.3.35'},
                        extended_optional=True)
                except Exception as err:
                    LOGGER.error('Failed to verify chain on block num %d: %s',
                                 blk_num, err)
                    failure = StatusReport.ReasonCode.FAILED_SEC
                    continue

                peer_nodeid = bib.payload.source
                end_cert = x509.load_der_x509_certificate(
                    found_chain[0], default_backend())
                authn_nodeid = tcpcl.session.match_id(
                    peer_nodeid, end_cert, x509.UniformResourceIdentifier,
                    LOGGER, 'NODE-ID')
                if not authn_nodeid:
                    LOGGER.error(
                        'Failed to authenticate peer "%s" on block num %d',
                        peer_nodeid, blk_num)
                    failure = StatusReport.ReasonCode.FAILED_SEC
                    # Continue on to verification

                try:
                    msg_obj.key = self.extract_cose_key(end_cert.public_key())
                    msg_obj.verify_signature()
                    LOGGER.info('Verified signature on block num %d', blk_num)
                except Exception as err:
                    LOGGER.error(
                        'Failed to verify signature on block num %d: %s',
                        blk_num, err)
                    failure = StatusReport.ReasonCode.FAILED_SEC

        return failure