Exemple #1
0
    def get_ocsp_response(self, data):
        try:
            ocsp_request = asn1crypto.ocsp.OCSPRequest.load(data)

            tbs_request = ocsp_request['tbs_request']
            request_list = tbs_request['request_list']
            if len(request_list) != 1:
                log.error('Received OCSP request with multiple sub requests')
                raise NotImplemented('Combined requests not yet supported')
            single_request = request_list[0]  # TODO: Support more than one request
            req_cert = single_request['req_cert']
            serial = serial_from_int(req_cert['serial_number'].native)
        except Exception as e:
            log.exception('Error parsing OCSP request: %s', e)
            return self.fail('malformed_request')

        ca = CertificateAuthority.objects.get(serial=self.ca_serial)

        try:
            cert = Certificate.objects.filter(ca=ca).get(serial=serial)
        except Certificate.DoesNotExist:
            log.warn('OCSP request for unknown cert received.')
            return self.fail('internal_error')  # TODO: return a 'unkown' response instead

        builder = OCSPResponseBuilder(
            response_status='successful',  # ResponseStatus.successful.value,
            certificate=load_certificate(force_bytes(cert.pub)),
            certificate_status=cert.ocsp_status,
            revocation_date=cert.revoked_date,
        )

        # Parse extensions
        for extension in tbs_request['request_extensions']:
            extn_id = extension['extn_id'].native
            critical = extension['critical'].native
            value = extension['extn_value'].parsed

            # This variable tracks whether any unknown extensions were encountered
            unknown = False

            # Handle nonce extension
            if extn_id == 'nonce':
                builder.nonce = value.native

            # That's all we know
            else:
                unknown = True

            # If an unknown critical extension is encountered (which should not
            # usually happen, according to RFC 6960 4.1.2), we should throw our
            # hands up in despair and run.
            if unknown is True and critical is True:
                log.warning('Could not parse unknown critical extension: %r',
                        dict(extension.native))
                return self._fail('internal_error')

            # If it's an unknown non-critical extension, we can safely ignore it.
            elif unknown is True:
                log.info('Ignored unknown non-critical extension: %r', dict(extension.native))

        builder.certificate_issuer = load_certificate(force_bytes(ca.pub))
        builder.next_update = timezone.now() + timedelta(days=1)

        responder_cert = self.get_responder_cert()

        return builder.build(self.responder_key, responder_cert)
Exemple #2
0
    def _build_ocsp_response(self, ocsp_request: OCSPRequest) -> OCSPResponse:
        """
        Create and return an OCSP response from an OCSP request.
        """
        # Get the certificate serial
        tbs_request = ocsp_request['tbs_request']
        request_list = tbs_request['request_list']
        if len(request_list) != 1:
            logger.warning('Received OCSP request with multiple sub requests')
            raise NotImplemented('Combined requests not yet supported')
        single_request = request_list[0]  # TODO: Support more than one request
        req_cert = single_request['req_cert']
        serial = req_cert['serial_number'].native

        # Check certificate status
        try:
            certificate_status, revocation_date = self._validate(serial)
        except Exception as e:
            logger.exception('Could not determine certificate status: %s', e)
            return self._fail(ResponseStatus.internal_error)

        # Retrieve certificate
        try:
            subject_cert_contents = self._cert_retrieve(serial)
        except Exception as e:
            logger.exception('Could not retrieve certificate with serial %s: %s', serial, e)
            return self._fail(ResponseStatus.internal_error)

        # Parse certificate
        try:
            subject_cert = asymmetric.load_certificate(subject_cert_contents.encode('utf8'))
        except Exception as e:
            logger.exception('Returned certificate with serial %s is invalid: %s', serial, e)
            return self._fail(ResponseStatus.internal_error)

        # Build the response
        builder = OCSPResponseBuilder(**{
            'response_status': ResponseStatus.successful.value,
            'certificate': subject_cert,
            'certificate_status': certificate_status.value,
            'revocation_date': revocation_date,
        })

        # Parse extensions
        for extension in tbs_request['request_extensions']:
            extn_id = extension['extn_id'].native
            critical = extension['critical'].native
            value = extension['extn_value'].parsed

            # This variable tracks whether any unknown extensions were encountered
            unknown = False

            # Handle nonce extension
            if extn_id == 'nonce':
                builder.nonce = value.native

            # That's all we know
            else:
                unknown = True

            # If an unknown critical extension is encountered (which should not
            # usually happen, according to RFC 6960 4.1.2), we should throw our
            # hands up in despair and run.
            if unknown is True and critical is True:
                logger.warning('Could not parse unknown critical extension: %r',
                        dict(extension.native))
                return self._fail(ResponseStatus.internal_error)

            # If it's an unknown non-critical extension, we can safely ignore it.
            elif unknown is True:
                logger.info('Ignored unknown non-critical extension: %r', dict(extension.native))

        # Set certificate issuer
        builder.certificate_issuer = self._issuer_cert

        # Set next update date
        builder.next_update = datetime.now(timezone.utc) + timedelta(days=self._next_update_days)

        return builder.build(self._responder_key, self._responder_cert)
Exemple #3
0
    def get_ocsp_response(self, data):
        try:
            ocsp_request = asn1crypto.ocsp.OCSPRequest.load(data)

            tbs_request = ocsp_request['tbs_request']
            request_list = tbs_request['request_list']
            if len(request_list) != 1:
                log.error('Received OCSP request with multiple sub requests')
                raise NotImplemented('Combined requests not yet supported')
            single_request = request_list[
                0]  # TODO: Support more than one request
            req_cert = single_request['req_cert']
            serial = serial_from_int(req_cert['serial_number'].native)
        except Exception as e:
            log.exception('Error parsing OCSP request: %s', e)
            return self.fail(u'malformed_request')

        # Get CA and certificate
        ca = CertificateAuthority.objects.get(serial=self.ca)
        try:
            cert = Certificate.objects.filter(ca=ca).get(serial=serial)
        except Certificate.DoesNotExist:
            log.warn('OCSP request for unknown cert received.')
            return self.fail(u'internal_error')

        # load ca cert and responder key/cert
        ca_cert = load_certificate(force_bytes(ca.pub))
        responder_key = load_private_key(self.responder_key)
        responder_cert = load_certificate(self.responder_cert)

        builder = OCSPResponseBuilder(
            response_status=u'successful',  # ResponseStatus.successful.value,
            certificate=load_certificate(force_bytes(cert.pub)),
            certificate_status=force_text(cert.ocsp_status),
            revocation_date=cert.revoked_date,
        )

        # Parse extensions
        for extension in tbs_request['request_extensions']:
            extn_id = extension['extn_id'].native
            critical = extension['critical'].native
            value = extension['extn_value'].parsed

            # This variable tracks whether any unknown extensions were encountered
            unknown = False

            # Handle nonce extension
            if extn_id == 'nonce':
                builder.nonce = value.native

            # That's all we know
            else:  # pragma: no cover
                unknown = True

            # If an unknown critical extension is encountered (which should not
            # usually happen, according to RFC 6960 4.1.2), we should throw our
            # hands up in despair and run.
            if unknown is True and critical is True:  # pragma: no cover
                log.warning('Could not parse unknown critical extension: %r',
                            dict(extension.native))
                return self._fail('internal_error')

            # If it's an unknown non-critical extension, we can safely ignore it.
            elif unknown is True:  # pragma: no cover
                log.info('Ignored unknown non-critical extension: %r',
                         dict(extension.native))

        builder.certificate_issuer = ca_cert
        builder.next_update = datetime.utcnow() + timedelta(
            seconds=self.expires)
        return builder.build(responder_key, responder_cert)
    def build_ocsp_response(self, ocsp_request: OCSPRequest) -> OCSPResponse:
        """
        Create and return an OCSP response from an OCSP request.
        """
        # Get the certificate serial
        req_cert_id = _get_req_cert_id(ocsp_request)
        #serial = req_cert_id['serial_number'].native
        #issuer_key_hash = req_cert_id['issuer_key_hash'].native
        #issuer_name_hash = req_cert_id['issuer_name_hash'].native
        #hash_algorithm = req_cert_id['hash_algorithm']
        #hash_algo_name = hash_algorithm['algorithm'].native
        #hash_algo_params = hash_algorithm['parameters'].native

        # Check certificate status
        try:
            certificate_status, revocation_date = self._validate(req_cert_id, self.issuer_cert)
        except Exception as e:
            logger.exception('Could not determine certificate status: %s', e)
            return _fail(ResponseStatus.internal_error)

        # Retrieve certificate
        try:
            subject_cert_contents = self._cert_retrieve(req_cert_id, self.issuer_cert)
        except Exception as e:
            logger.exception('Could not retrieve certificate with serial %s: %s', serial, e)
            return _fail(ResponseStatus.internal_error)

        # Parse certificate if needed
        if isinstance(subject_cert_contents, x509.Certificate):
            subject_cert = subject_cert_contents
        elif isinstance(subject_cert_contents, asymmetric.Certificate):
            subject_cert = subject_cert_contents.asn1
        else:
            try:
                subject_cert = asymmetric.load_certificate(subject_cert_contents.encode('utf8'))
            except Exception as e:
                logger.exception('Returned certificate with serial %s is invalid: %s', serial, e)
                return _fail(ResponseStatus.internal_error)

        # Build the response
        builder = OCSPResponseBuilder(**{
            'response_status': ResponseStatus.successful.value,
            'certificate': subject_cert,
            'certificate_status': certificate_status.value,
            'revocation_date': revocation_date,
        })

        # Parse extensions
        tbs_request = ocsp_request['tbs_request']
        for extension in tbs_request['request_extensions']:
            extn_id = extension['extn_id'].native
            critical = extension['critical'].native
            value = extension['extn_value'].parsed

            # This variable tracks whether any unknown extensions were encountered
            unknown = False

            # Handle nonce extension
            if extn_id == 'nonce':
                builder.nonce = value.native

            # That's all we know
            else:
                unknown = True

            # If an unknown critical extension is encountered (which should not
            # usually happen, according to RFC 6960 4.1.2), we should throw our
            # hands up in despair and run.
            if unknown is True and critical is True:
                logger.warning('Could not parse unknown critical extension: %r',
                        dict(extension.native))
                return _fail(ResponseStatus.internal_error)

            # If it's an unknown non-critical extension, we can safely ignore it.
            elif unknown is True:
                logger.info('Ignored unknown non-critical extension: %r', dict(extension.native))

        # Set certificate issuer
        builder.certificate_issuer = self._issuer_cert

        # Set next update date
        builder.next_update = datetime.now(timezone.utc) + timedelta(days=self._next_update_days)

        return builder.build(self._responder_key, self._responder_cert)