Example #1
0
def _decode_issuing_dist_point(backend, idp):
    idp = backend._ffi.cast("ISSUING_DIST_POINT *", idp)
    idp = backend._ffi.gc(idp, backend._lib.ISSUING_DIST_POINT_free)
    if idp.distpoint != backend._ffi.NULL:
        full_name, relative_name = _decode_distpoint(backend, idp.distpoint)
    else:
        full_name = None
        relative_name = None

    only_user = idp.onlyuser == 255
    only_ca = idp.onlyCA == 255
    indirect_crl = idp.indirectCRL == 255
    only_attr = idp.onlyattr == 255
    if idp.onlysomereasons != backend._ffi.NULL:
        only_some_reasons = _decode_reasons(backend, idp.onlysomereasons)
    else:
        only_some_reasons = None

    return x509.IssuingDistributionPoint(
        full_name,
        relative_name,
        only_user,
        only_ca,
        only_some_reasons,
        indirect_crl,
        only_attr,
    )
Example #2
0
 def get_idp(
     self,
     full_name: typing.Optional[typing.Iterable[x509.GeneralName]] = None,
     indirect_crl: bool = False,
     only_contains_attribute_certs: bool = False,
     only_contains_ca_certs: bool = False,
     only_contains_user_certs: bool = False,
     only_some_reasons: typing.Optional[typing.FrozenSet[
         x509.ReasonFlags]] = None,
     relative_name: typing.Optional[x509.RelativeDistinguishedName] = None,
 ) -> "x509.Extension[x509.IssuingDistributionPoint]":
     """Get an IssuingDistributionPoint extension."""
     return x509.Extension(
         oid=x509.oid.ExtensionOID.ISSUING_DISTRIBUTION_POINT,
         value=x509.IssuingDistributionPoint(
             full_name=full_name,
             indirect_crl=indirect_crl,
             only_contains_attribute_certs=only_contains_attribute_certs,
             only_contains_ca_certs=only_contains_ca_certs,
             only_contains_user_certs=only_contains_user_certs,
             only_some_reasons=only_some_reasons,
             relative_name=relative_name,
         ),
         critical=True,
     )
Example #3
0
 def get_idp(self, full_name=None, indirect_crl=False, only_contains_attribute_certs=False,
             only_contains_ca_certs=False, only_contains_user_certs=False, only_some_reasons=None,
             relative_name=None):
     if not ca_settings.CRYPTOGRAPHY_HAS_IDP:  # pragma: only cryptography<2.5
         return
     else:  # pragma: only cryptography>=2.5
         return x509.Extension(
             oid=ExtensionOID.ISSUING_DISTRIBUTION_POINT,
             value=x509.IssuingDistributionPoint(
                 full_name=full_name,
                 indirect_crl=indirect_crl,
                 only_contains_attribute_certs=only_contains_attribute_certs,
                 only_contains_ca_certs=only_contains_ca_certs,
                 only_contains_user_certs=only_contains_user_certs,
                 only_some_reasons=only_some_reasons,
                 relative_name=relative_name
             ), critical=True)
Example #4
0
 def get_idp(self,
             full_name=None,
             indirect_crl=False,
             only_contains_attribute_certs=False,
             only_contains_ca_certs=False,
             only_contains_user_certs=False,
             only_some_reasons=None,
             relative_name=None):
     return x509.Extension(
         oid=ExtensionOID.ISSUING_DISTRIBUTION_POINT,
         value=x509.IssuingDistributionPoint(
             full_name=full_name,
             indirect_crl=indirect_crl,
             only_contains_attribute_certs=only_contains_attribute_certs,
             only_contains_ca_certs=only_contains_ca_certs,
             only_contains_user_certs=only_contains_user_certs,
             only_some_reasons=only_some_reasons,
             relative_name=relative_name),
         critical=True)
Example #5
0
    def get_crl(self, expires=86400, encoding=None, algorithm=None, password=None, scope=None, counter=None,
                **kwargs):
        """Generate a Certificate Revocation List (CRL).

        The ``full_name`` and ``relative_name`` parameters describe how to retrieve the CRL and are used in
        the `Issuing Distribution Point extension <https://tools.ietf.org/html/rfc5280.html#section-5.2.5>`_.
        The former defaults to the ``crl_url`` field, pass ``None`` to not include the value. At most one of
        the two may be set.

        Parameters
        ----------

        expires : int
            The time in seconds when this CRL expires. Note that you should generate a new CRL until then.
        encoding : :py:class:`~cg:cryptography.hazmat.primitives.serialization.Encoding` or str, optional
            The encoding format for the CRL, passed to :py:func:`~django_ca.utils.parse_encoding`. The default
            value is ``"PEM"``.
        algorithm : :py:class:`~cg:cryptography.hazmat.primitives.hashes.Hash` or str, optional
            The hash algorithm to use, passed to :py:func:`~django_ca.utils.parse_hash_algorithm`. The default
            is to use :ref:`CA_DIGEST_ALGORITHM <settings-ca-digest-algorithm>`.
        password : bytes, optional
            Password used to load the private key of the certificate authority. If not passed, the private key
            is assumed to be unencrypted.
        scope : {None, 'ca', 'user', 'attribute'}, optional
            What to include in the CRL: Use ``"ca"`` to include only revoked certificate authorities and
            ``"user"`` to include only certificates or ``None`` (the default) to include both.
            ``"attribute"`` is reserved for future use and always produces an empty CRL.
        counter : str, optional
            Override the counter-variable for the CRL Number extension. Passing the same key to multiple
            invocations will yield a different sequence then what would ordinarily be returned. The default is
            to use the scope as the key.
        full_name : list of str or :py:class:`~cg:cryptography.x509.GeneralName`, optional
            List of general names to use in the Issuing Distribution Point extension. If not passed, use
            ``crl_url`` if set.
        relative_name : :py:class:`~cg:cryptography.x509.RelativeDistinguishedName`, optional
            Used in Issuing Distribution Point extension, retrieve the CRL relative to the issuer.

        Returns
        -------

        bytes
            The CRL in the requested format.
        """

        if scope is not None and scope not in ['ca', 'user', 'attribute']:
            raise ValueError('Scope must be either None, "ca", "user" or "attribute"')
        encoding = parse_encoding(encoding)

        now = now_builder = timezone.now()
        algorithm = parse_hash_algorithm(algorithm)

        if timezone.is_aware(now_builder):
            now_builder = timezone.make_naive(now, pytz.utc)
        else:
            now_builder = datetime.utcnow()

        builder = x509.CertificateRevocationListBuilder()
        builder = builder.issuer_name(self.x509.subject)
        builder = builder.last_update(now_builder)
        builder = builder.next_update(now_builder + timedelta(seconds=expires))

        if 'full_name' in kwargs:
            full_name = kwargs['full_name']
            full_name = [parse_general_name(n) for n in full_name]
        elif self.crl_url:
            crl_url = [url.strip() for url in self.crl_url.split()]
            full_name = [x509.UniformResourceIdentifier(c) for c in crl_url]
        else:
            full_name = None

        # Keyword arguments for the IssuingDistributionPoint extension
        idp_kwargs = {
            'only_contains_ca_certs': False,
            'only_contains_user_certs': False,
            'indirect_crl': False,
            'only_contains_attribute_certs': False,
            'only_some_reasons': None,
            'full_name': full_name,
            'relative_name': kwargs.get('relative_name'),
        }

        ca_qs = self.children.filter(expires__gt=now).revoked()
        cert_qs = self.certificate_set.filter(expires__gt=now).revoked()

        if scope == 'ca':
            certs = ca_qs
            idp_kwargs['only_contains_ca_certs'] = True
        elif scope == 'user':
            certs = cert_qs
            idp_kwargs['only_contains_user_certs'] = True
        elif scope == 'attribute':
            # sorry, nothing we support right now
            certs = []
            idp_kwargs['only_contains_attribute_certs'] = True
        else:
            certs = itertools.chain(ca_qs, cert_qs)

        for cert in certs:
            builder = builder.add_revoked_certificate(cert.get_revocation())

        # We can only add the IDP extension if one of these properties is set, see RFC 5280, 5.2.5.
        add_idp = idp_kwargs['only_contains_attribute_certs'] or idp_kwargs['only_contains_user_certs'] \
            or idp_kwargs['only_contains_ca_certs'] or idp_kwargs['full_name'] or idp_kwargs['relative_name']

        if add_idp and ca_settings.CRYPTOGRAPHY_HAS_IDP:  # pragma: no branch, pragma: only cryptography>=2.5
            builder = builder.add_extension(x509.IssuingDistributionPoint(**idp_kwargs), critical=True)

        # Add AuthorityKeyIdentifier from CA if present
        try:
            aki = self.x509.extensions.get_extension_for_oid(ExtensionOID.AUTHORITY_KEY_IDENTIFIER)
            builder = builder.add_extension(aki.value, critical=aki.critical)
        except x509.ExtensionNotFound:
            pass

        # Add the CRLNumber extension (RFC 5280, 5.2.3)
        if counter is None:
            counter = scope or 'all'
        crl_number_data = json.loads(self.crl_number)
        crl_number = int(crl_number_data['scope'].get(counter, 0))
        builder = builder.add_extension(x509.CRLNumber(crl_number=crl_number), critical=False)

        # increase crl_number for the given scope and save
        crl_number_data['scope'][counter] = crl_number + 1
        self.crl_number = json.dumps(crl_number_data)
        self.save()

        crl = builder.sign(private_key=self.key(password), algorithm=algorithm, backend=default_backend())
        return crl.public_bytes(encoding)