You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Kaspar Brand <ht...@velox.ch> on 2014/11/01 10:47:03 UTC

Re: [Patch] mod_ssl SSL_CLIENT_CERT_SUBJECTS - access to full client certificate chain

On 29.10.2014 16:40, Graham Leggett wrote:
> The attached patch makes the variable SSL_CLIENT_CERT_SUBJECTS
> available, which contains a list of subject DNs in each certificate
> in the chain. It is designed to be able to match against a full
> certificate chain where the subject and issuer of the certificate
> alone is not good enough to identify a certificate uniquely.

Does this relate to your post from January [1]?

> The subject DNs are themselves escaped and used to create a new DN as
> follows: name=subject1,name=subject2,name=subject3 (and so on).

Feels like a fairly idiosyncratic solution to me (essentially sticking
multiple things together into a single environment variable, with the
[known] problems of how to separate them again / do proper matching in
the application). I would prefer these DNs being exported to the
environment in the same way as it is currently done with the
SSL_CLIENT_CERT_CHAIN_n variables.

Kaspar


[1] https://mail-archives.apache.org/mod_mbox/httpd-dev/201401.mbox/%3C1A61F988-F33B-4E65-A141-E4516F8424CC%40sharp.fm%3E

Re: [Patch] mod_ssl SSL_CLIENT_CERT_SUBJECTS - access to full client certificate chain

Posted by Tim Bannister <is...@c8h10n4o2.org.uk>.
On 1 Nov 2014, at 12:41, Graham Leggett <mi...@sharp.fm> wrote:
> 
> The use case this solves is that I want to uniquely identify a certificate and store that identity in an LDAP directory. The most obvious solution - just store the cert in the userCertificate attribute and do a direct binary match - doesn’t work in most directories, as direct certificate matching was forgotten in the specs that were involved (unfortunately).

What's stopping this from working? RFC 4523 calls for the userCertificate to contain a DER-encoded version of the user's certificate.

The approach I have in mind is to have the directory searchable by issuer DN and serial number, with a subsequent comparison of the certificate retrieved by LDAP (DER+base64) against SSL_CLIENT_CERT.

I speculate that this could look like:
   Require expr %{SSL_CLIENT_CERT} -x509certeq %{LDAP_ATTRIBUTE_USERCERTIFICATE} 

-- 
Tim Bannister – isoma@c8h10n4o2.org.uk

Re: [Patch] mod_ssl SSL_CLIENT_CERT_SUBJECTS - access to full client certificate chain

Posted by Graham Leggett <mi...@sharp.fm>.
On 02 Nov 2014, at 4:44 PM, Graham Leggett <mi...@sharp.fm> wrote:

>> I don't dispute that such a string "can be stored in any DN formatted
>> field in LDAP", but consider the use of the "name" RDN (OID 2.5.4.41)
>> fairly nonstandard. X.520 defines "Name" as "the attribute supertype
>> from which string attribute types typically used for naming may be
>> formed" (and "string attribute types" referring to things like
>> commonName, surname etc.). "distinguishedName" (2.5.4.49) would be more
>> appropriate, though it isn't really meant for use as an RDN attribute
>> type (but "an attribute for specifying the name of an object" in an
>> X.500 DIT).
> 
> Good point, let me change that.

Updated patch is attached.

Regards,
Graham
—

Re: [Patch] mod_ssl SSL_CLIENT_CERT_SNAI - access to client certificate serialNumber and issuer

Posted by Graham Leggett <mi...@sharp.fm>.
On 08 Feb 2015, at 10:23 AM, Kaspar Brand <ht...@velox.ch> wrote:

> It's probably a rarely used format, but if the CertificateExactAssertion
> thing is useful for LDAP querying, then fine with me. One caveat
> to keep in mind is that GSER (the "Generic String Encoding Rules",
> on which RFC 4523 relies) "do not define a canonical encoding",
> as stated in RFC 3641 section 5. The following strings for identifying
> the certificate from RFC 5280 appendix C.2 are equivalent according
> to RFC 4523 (and RFC 4514), e.g.:
> 
> {serialNumber 18,issuer rdnSequence:"CN=Example CA,DC=example,DC=com"}
> { serialNumber 18, issuer rdnSequence:"CN=#130A4578616D706C65204341,DC=#16076578616D706C65,DC=#1603636F6D” }

I originally used the deprecated serial$issuer format, and then changed it - my head was bleeding once I’d done it.

> Implementation-wise, there's some room for improvement:
> 
> - "..._SNAI" sounds like fairly cryptic naming to me, I would prefer
> an explicit RFC reference, e.g. SSL_CLIENT_CERT_RFC4523_CEA (searching
> for "cea" in that RFC will quickly turn up its definition)
> 
> - the syntax of the value isn't correct yet: your code does not add
> the "rdnSequence:" before the issuer DN, and it needs to be quoted,
> 
> - instead of adding another BIO_* dance to ssl_engine_vars.c,
> relying on SSL_X509_NAME_to_string (and apr_pstrcat) allows saving
> quite some code
> 
> - to also export the variable with "SSLOptions StdEnvVars", you need
> to add it to ssl_hook_Fixup_vars[] in ssl_engine_kernel.c, too

I have updated the patch accordingly. “SNAI” was “subject name and issuer” but writing that out made a variable name that was too long.

> That's what I meant when suggesting something like SSL_CLIENT_CERT_DER
> in my last message in the "Re: [Patch] mod_ssl SSL_CLIENT_CERT_SUBJECTS -
> access to full client certificate chain" thread, yes. I would probably
> go for Base64 encoded DER values, to avoid '\0'-byte issues when
> shuffling things around (i.e., it would be "PEM without headers",
> so to say).

I’m keen on a mechanism that avoids a cycle of base64/unbase64, and I don’t want any of the LDAP code to have any knowledge of PEM or base64. What I had in mind was a generic mechanism that allowed binary data to be provided by any module that wanted to provide data to any module that wanted to consume it, and then teaching mod_ssl to provide it and mod_authnz_ldap to use it (and other mod_auth* modules as needed).

Regards,
Graham
—

Re: [Patch] mod_ssl SSL_CLIENT_CERT_SNAI - access to client certificate serialNumber and issuer

Posted by Kaspar Brand <ht...@velox.ch>.
On 05.02.2015 19:22, Graham Leggett wrote:
> What I’ve done is broken the problem into two sections, the first is
> to give a unique handle on the certificate that can be used in LDAP
> queries. RFC4523 defines a CertificateExactAssertion, which is “{
> serialNumber <decimal-serial-number-string>, issuer <issuer-string>
> }”.

It's probably a rarely used format, but if the CertificateExactAssertion
thing is useful for LDAP querying, then fine with me. One caveat
to keep in mind is that GSER (the "Generic String Encoding Rules",
on which RFC 4523 relies) "do not define a canonical encoding",
as stated in RFC 3641 section 5. The following strings for identifying
the certificate from RFC 5280 appendix C.2 are equivalent according
to RFC 4523 (and RFC 4514), e.g.:

{serialNumber 18,issuer rdnSequence:"CN=Example CA,DC=example,DC=com"}
{ serialNumber 18, issuer rdnSequence:"CN=#130A4578616D706C65204341,DC=#16076578616D706C65,DC=#1603636F6D" }

> The attached patch provides an SSL_CLIENT_CERT_SNAI variable that
> gives the above string, which in turn can be used for LDAP queries
> against the userCertificate attribute (or another attribute for
> directories that don’t support certificateExactMatch).

Implementation-wise, there's some room for improvement:

- "..._SNAI" sounds like fairly cryptic naming to me, I would prefer
an explicit RFC reference, e.g. SSL_CLIENT_CERT_RFC4523_CEA (searching
for "cea" in that RFC will quickly turn up its definition)

- the syntax of the value isn't correct yet: your code does not add
the "rdnSequence:" before the issuer DN, and it needs to be quoted,

- instead of adding another BIO_* dance to ssl_engine_vars.c,
relying on SSL_X509_NAME_to_string (and apr_pstrcat) allows saving
quite some code

- to also export the variable with "SSLOptions StdEnvVars", you need
to add it to ssl_hook_Fixup_vars[] in ssl_engine_kernel.c, too

> The second part of the problem is “is this certificate the one we’re
> looking for”. The formal definition of certificateExactMatch doesn’t
> allow for binary matches of a cert, and some directories allow it,
> and some don’t. What I have in mind for this is to create a mechanism
> that allows mod_ssl to expose binary data like the DER of the cert
> and allow other modules to query that data and check it. In this case
> mod_authnz_ldap can then optionally verify that the cert returned
> from the directory matches the cert returned by mod_ssl.

That's what I meant when suggesting something like SSL_CLIENT_CERT_DER
in my last message in the "Re: [Patch] mod_ssl SSL_CLIENT_CERT_SUBJECTS -
access to full client certificate chain" thread, yes. I would probably
go for Base64 encoded DER values, to avoid '\0'-byte issues when
shuffling things around (i.e., it would be "PEM without headers",
so to say).

Kaspar

[Patch] mod_ssl SSL_CLIENT_CERT_SNAI - access to client certificate serialNumber and issuer

Posted by Graham Leggett <mi...@sharp.fm>.
On 12 Nov 2014, at 8:03 AM, Kaspar Brand <ht...@velox.ch> wrote:

> We seem to talk about two separate issues, I think: (1) "to uniquely
> identify a certificate and store that identity in an LDAP directory"
> (from your 1 Nov message), and (2) "that I trust both CA1 and CA2 to
> issue certificates, but I don’t trust CA2 not to (accidentally or
> purposefully) issue a certificate with the same issuer as CA1”.

This is the crux of the problem, yes.

What I’ve done is broken the problem into two sections, the first is to give a unique handle on the certificate that can be used in LDAP queries. RFC4523 defines a CertificateExactAssertion, which is “{ serialNumber <decimal-serial-number-string>, issuer <issuer-string> }”.

The attached patch provides an SSL_CLIENT_CERT_SNAI variable that gives the above string, which in turn can be used for LDAP queries against the userCertificate attribute (or another attribute for directories that don’t support certificateExactMatch).

The second part of the problem is “is this certificate the one we’re looking for”. The formal definition of certificateExactMatch doesn’t allow for binary matches of a cert, and some directories allow it, and some don’t. What I have in mind for this is to create a mechanism that allows mod_ssl to expose binary data like the DER of the cert and allow other modules to query that data and check it. In this case mod_authnz_ldap can then optionally verify that the cert returned from the directory matches the cert returned by mod_ssl.

Regards,
Graham
—

Re: [Patch] mod_ssl SSL_CLIENT_CERT_SUBJECTS - access to full client certificate chain

Posted by Kaspar Brand <ht...@velox.ch>.
On 09.11.2014 14:30, Graham Leggett wrote:
> On 06 Nov 2014, at 8:05 AM, Kaspar Brand <ht...@velox.ch> wrote:
> 
>>> Is there another way to do this?
>>
>> "Manually" performing what certificateExactMatch is specifying, I would
>> say - i.e., use the (SSL_CLIENT_M_SERIAL,SSL_CLIENT_I_DN) tuple as a
>> unique identifier for a specific client certificate.
> 
> Imagine I trust two roots, A and X, where X has been compromised.
> 
> I authorize the certificate chain A->B->C to perform a specific
> action. What stops the root X from issuing an intermediate
> certificate with subject “B” and a leaf certificate with subject “C”
> to produce a chain that goes X->B->C, and the client provides both
> the intermediate cert B and leaf certificate C during the SSL
> handshake?
> 
> In other words, if I only consider the serial number and issuer
> during authorization, what stops a compromised-but-still-trusted CA
> from issuing an intermediate cert that replaces another trusted
> issuer?

We seem to talk about two separate issues, I think: (1) "to uniquely
identify a certificate and store that identity in an LDAP directory"
(from your 1 Nov message), and (2) "that I trust both CA1 and CA2 to
issue certificates, but I don’t trust CA2 not to (accidentally or
purposefully) issue a certificate with the same issuer as CA1".

For (2), which is about authorization, the certification path can be a
suitable criterion (note that X.509 also defines a "CertificationPath"
ASN.1 type in this context, though in a more complex/complete way than
what you're proposing). For (1), however, it's not sufficient to pick
the subjectDN from an end-entity certificate - even from a "trusted"
issuing CA, you may expect multiple certificates with the same issuer
(think of dual-keying e.g.). Or another case to take into account is
that an end-endity certificate may have an empty subject DN (RFC 5280
section 4.1.2.6), in which case the concatenation of the subjectDNs (the
proposed SSL_CLIENT_CERT_SUBJECTS string) wouldn't work at all.

As pointed out by Tim Bannister meanwhile, comparing the complete
certificate against a "userCertificate" LDAP attribute would be the most
secure way to make sure that the user has indeed authenticated with the
certificate you require. If mod_authnz_ldap's "Require ldap-attribute"
could be extended to allow value definitions based on SSL_CLIENT_CERT,
then you wouldn't depend on CertificateExactMatch support in the LDAP
server (the PEM headers in SSL_CLIENT_CERT would have to be stripped
before comparing to the LDAP attribute, perhaps an additional var like
SSL_CLIENT_CERT_DER could be introduced if this makes things simpler in
mod_authnz_ldap).

Kaspar

Re: [Patch] mod_ssl SSL_CLIENT_CERT_SUBJECTS - access to full client certificate chain

Posted by Graham Leggett <mi...@sharp.fm>.
On 06 Nov 2014, at 8:05 AM, Kaspar Brand <ht...@velox.ch> wrote:

>> Is there another way to do this?
> 
> "Manually" performing what certificateExactMatch is specifying, I would
> say - i.e., use the (SSL_CLIENT_M_SERIAL,SSL_CLIENT_I_DN) tuple as a
> unique identifier for a specific client certificate.

Imagine I trust two roots, A and X, where X has been compromised.

I authorize the certificate chain A->B->C to perform a specific action. What stops the root X from issuing an intermediate certificate with subject “B” and a leaf certificate with subject “C” to produce a chain that goes X->B->C, and the client provides both the intermediate cert B and leaf certificate C during the SSL handshake?

In other words, if I only consider the serial number and issuer during authorization, what stops a compromised-but-still-trusted CA from issuing an intermediate cert that replaces another trusted issuer?

Regards,
Graham
—


Re: [Patch] mod_ssl SSL_CLIENT_CERT_SUBJECTS - access to full client certificate chain

Posted by Kaspar Brand <ht...@velox.ch>.
On 06.11.2014 14:19, Dirk-Willem van Gulik wrote:
> 
>> On 06 Nov 2014, at 14:14, Andreas B. <re...@progandy.de> wrote:
>>
>> Am 06.11.2014 um 08:34 schrieb Dirk-Willem van Gulik:
>>>> On 06 Nov 2014, at 07:05, Kaspar Brand <ht...@velox.ch> <ma...@velox.ch> wrote:
>>>>
>>>> (i.e., we are again back at the point that uniqueness of an X.509
>>>> certificate is achieved by its issuer DN plus serial number)
>>> And even that is LDAPs take on it

I beg to differ. It's X.509 in its purest sense. From clauses 11.1.1 and
11.2.1 of X.509:

> The PKI user object class is used in defining entries for objects
> that may be the subject of public-key certificates.
>
>   pkiUser OBJECT-CLASS ::= {
>       SUBCLASS OF  {top}
>       KIND         auxiliary
>       MAY CONTAIN  {userCertificate}
>       ID           id-oc-pkiUser }

> A user may obtain one or more public-key certificates from one or more CAs.
> The userCertificate attribute type contains the public-key certificates
> a user has obtained from one or more CAs.
>
>   userCertificate ATTRIBUTE ::= {
>       WITH SYNTAX             Certificate
>       EQUALITY MATCHING RULE  certificateExactMatch
>       ID                      id-at-userCertificate}

The matching rules in RFC 4523 ("LDAP X.509 Schema") are those from
X.509, or as RFC 4523 says in section 1: "As the semantics of these
elements are as defined in X.509 and X.521, knowledge of X.509 and X.521
is necessary to make use of the LDAP schema definitions provided herein."

> - in a lot of practical cases it gets more complex; especially if the
> leave of the  one but last intermediate is cross signed.

Sure, but trying to identify a certificate by its certification path
(and in particular, the "other" end of it, i.e. the root / trust
anchor), is an unworkable solution, as it ignores fundamental properties
of X.509.

>>> I would argue that the ‘best’ thing we can do is first on the SSL
>>> termination side — follow the chain; and if there we *conclude*
>>> that all is well - and we present the evidence of that conclusion
>>> ’to what is behind’.

Let me add that "follow the chain" (and use X509_verify_cert to get at
the trust anchor) may give inconsistent results depending on a) what
chain the client provides in the TLS handshake (RFC 5246 section 7.4.6)
and b) what intermediate CAs and trust anchors are configured
server-side (SSLCACertificate{File,Path}), and also on what OpenSSL
version is used - see e.g.
https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=d65b8b2162f33ac0d53dace588a0847ed827626c#patch1.

>>> And ideally make that as hard to mis-interpret. So Graham his
>>> idea of providing a single ‘unique' string which gives the DN’s
>>> in order (along with the usual SSL_CLIENT.. env vars; including
>>> the full ANS.1 if you are so inclined) is quite pragmatic. As
>>> that string is ‘unique’ within the promise the web frontend with
>>> its current settings is making.

It's pragmatic but incorrect, and is definitely not a "promise" which
mod_ssl can make. To repeat: I'm fine with adding support for
SSL_CLIENT_S_DN_n to mod_ssl, but am opposed to inventing custom schemes
for "uniquely" identifying a certificate and hardcode this into mod_ssl
(in the end, it would convey the message that SSL_CLIENT_CERT_SUBJECTS
is a sound solution for that problem, which it isn't).

> The issue is that in some systems (e.g. a medical one I am
> currently trying to come to terms with) the certs ar renewed very
> often; and the fingerprint does not stay stable. This is also an
> issue with using the serial and the issuer DN.

It seems that you're trying to solve an authorization issue with some
sort of certificate-to-identity mapping (strictly speaking, client
certificate authentication is about authenticating with a key, not with
an X.509 DN). Coming back to Graham's statement "In other words, you may
come in if a) your cert validates to any trusted anchor, and b) your
cert is issued by a specific pre-agreed trust anchor", the fallacy is
trying to rely on the path to the trust anchor. The proper thing is to
require the client certificate(s) to be issued by one or more specific
issuing CAs (which can be configured by means of an SSLRequire directive
which checks for specific SSL_CLIENT_I_DN or SSL_CLIENT_I_DN_x509
values, and optionally SSL_CLIENT_S_* things).

Kaspar

Re: [Patch] mod_ssl SSL_CLIENT_CERT_SUBJECTS - access to full client certificate chain

Posted by Dirk-Willem van Gulik <di...@webweaving.org>.
> On 06 Nov 2014, at 14:14, Andreas B. <re...@progandy.de> wrote:
> 
> Am 06.11.2014 um 08:34 schrieb Dirk-Willem van Gulik:
>>> On 06 Nov 2014, at 07:05, Kaspar Brand <ht...@velox.ch> <ma...@velox.ch> wrote:
>>> 
>>>> 11.3.1 Certificate exact match
>>>> …
>>>>  CertificateExactAssertion ::= SEQUENCE {
>>>>      serialNumber  CertificateSerialNumber,
>>>>      issuer        Name }
>> ...
>>> (i.e., we are again back at the point that uniqueness of an X.509
>>> certificate is achieved by its issuer DN plus serial number)
>> And even that is LDAPs take on it - in a lot of practical cases it gets more complex; especially if the leave of the  one but last intermediate is cross signed.
>> 
>> Making above more of an LDAP thing than a ‘protocol’ thing.
>> 
>> So therefore:
>> 
>>>> Is there another way to do this?
>>> "Manually" performing what certificateExactMatch is specifying, I would
>>> say - i.e., use the (SSL_CLIENT_M_SERIAL,SSL_CLIENT_I_DN) tuple as a
>>> unique identifier for a specific client certificate.
>> I would argue that the ‘best’ thing we can do is first on the SSL termination side — follow the chain; and if there we *conclude* that all is well - and we present the evidence of that conclusion ’to what is behind’.
>> 
>> And ideally make that as hard to mis-interpret. So Graham his idea of providing a single ‘unique' string which gives the DN’s in order (along with the usual SSL_CLIENT.. env vars; including the full ANS.1 if you are so inclined) is quite pragmatic. As that string is ‘unique’ within the promise the web frontend with its current settings is making.
>> 
>> And it cuts out a lot of easy to make errors. And those who want to do better can simply use SSL_CLIENT_CERT and SSL_CLIENT_CERT_0…N — with sufficient code to understand things like cross signing and funny order issues. As parsing that is not trivial when there are multiple selfsigned/roots in a chain ‘up’.
>> 
>> Dw.
> If you want to identify a specific certificate, wouldn't it be possible to use sha1/256 fingerprints created with X509_digest? Or is that something LDAP doesn't support? That could be exported with SSL_CLIENT_CERT_THUMB and SSL_CLIENT_CERT_THUMB_ALG for the algorithm used.

One could. The issue is that in some systems (e.g. a medical one I am currently trying to come to terms with) the certs ar renewed very often; and the fingerprint does not stay stable. This is also an issue with using the serial and the issuer DN.

Dw.

Re: [Patch] mod_ssl SSL_CLIENT_CERT_SUBJECTS - access to full client certificate chain

Posted by "Andreas B." <re...@progandy.de>.
Am 06.11.2014 um 08:34 schrieb Dirk-Willem van Gulik:
>> On 06 Nov 2014, at 07:05, Kaspar Brand <ht...@velox.ch> wrote:
>>
>>> 11.3.1 Certificate exact match
>>> …
>>>   CertificateExactAssertion ::= SEQUENCE {
>>>       serialNumber  CertificateSerialNumber,
>>>       issuer        Name }
> ...
>> (i.e., we are again back at the point that uniqueness of an X.509
>> certificate is achieved by its issuer DN plus serial number)
> And even that is LDAPs take on it - in a lot of practical cases it gets more complex; especially if the leave of the  one but last intermediate is cross signed.
>
> Making above more of an LDAP thing than a ‘protocol’ thing.
>
> So therefore:
>
>>> Is there another way to do this?
>> "Manually" performing what certificateExactMatch is specifying, I would
>> say - i.e., use the (SSL_CLIENT_M_SERIAL,SSL_CLIENT_I_DN) tuple as a
>> unique identifier for a specific client certificate.
> I would argue that the ‘best’ thing we can do is first on the SSL termination side — follow the chain; and if there we *conclude* that all is well - and we present the evidence of that conclusion ’to what is behind’.
>
> And ideally make that as hard to mis-interpret. So Graham his idea of providing a single ‘unique' string which gives the DN’s in order (along with the usual SSL_CLIENT.. env vars; including the full ANS.1 if you are so inclined) is quite pragmatic. As that string is ‘unique’ within the promise the web frontend with its current settings is making.
>
> And it cuts out a lot of easy to make errors. And those who want to do better can simply use SSL_CLIENT_CERT and SSL_CLIENT_CERT_0…N — with sufficient code to understand things like cross signing and funny order issues. As parsing that is not trivial when there are multiple selfsigned/roots in a chain ‘up’.
>
> Dw.
If you want to identify a specific certificate, wouldn't it be possible 
to use sha1/256 fingerprints created with X509_digest||||||? Or is that 
something LDAP doesn't support? That could be exported with 
SSL_CLIENT_CERT_THUMB and SSL_CLIENT_CERT_THUMB_ALG for the algorithm used.

Re: [Patch] mod_ssl SSL_CLIENT_CERT_SUBJECTS - access to full client certificate chain

Posted by Dirk-Willem van Gulik <di...@webweaving.org>.
> On 06 Nov 2014, at 07:05, Kaspar Brand <ht...@velox.ch> wrote:
> 
>> 11.3.1 Certificate exact match
>> …
>>  CertificateExactAssertion ::= SEQUENCE {
>>      serialNumber  CertificateSerialNumber,
>>      issuer        Name }
...
> (i.e., we are again back at the point that uniqueness of an X.509
> certificate is achieved by its issuer DN plus serial number)

And even that is LDAPs take on it - in a lot of practical cases it gets more complex; especially if the leave of the  one but last intermediate is cross signed.

Making above more of an LDAP thing than a ‘protocol’ thing.

So therefore:

>> Is there another way to do this?
> 
> "Manually" performing what certificateExactMatch is specifying, I would
> say - i.e., use the (SSL_CLIENT_M_SERIAL,SSL_CLIENT_I_DN) tuple as a
> unique identifier for a specific client certificate.

I would argue that the ‘best’ thing we can do is first on the SSL termination side — follow the chain; and if there we *conclude* that all is well - and we present the evidence of that conclusion ’to what is behind’.

And ideally make that as hard to mis-interpret. So Graham his idea of providing a single ‘unique' string which gives the DN’s in order (along with the usual SSL_CLIENT.. env vars; including the full ANS.1 if you are so inclined) is quite pragmatic. As that string is ‘unique’ within the promise the web frontend with its current settings is making.

And it cuts out a lot of easy to make errors. And those who want to do better can simply use SSL_CLIENT_CERT and SSL_CLIENT_CERT_0…N — with sufficient code to understand things like cross signing and funny order issues. As parsing that is not trivial when there are multiple selfsigned/roots in a chain ‘up’.

Dw.

Re: [Patch] mod_ssl SSL_CLIENT_CERT_SUBJECTS - access to full client certificate chain

Posted by Kaspar Brand <ht...@velox.ch>.
On 05.11.2014 14:26, Graham Leggett wrote:
> The problem I am trying to solve is to find a practical way to
> integrate an SSL client cert identity with LDAP, in such a way where
> I can say “we recognise this certificate is mapped to that
> capability”. I am struggling to find an accurate indicator of “this
> certificate” (as opposed to “this similar looking certificate with a
> different chain”). Annoyingly the simplest solution - a simple binary
> match on the cert - isn’t supported by certificateExactMatch in most
> LDAP servers.

certificateExactMatch isn't really a "binary" match (i.e., a binary
comparison of the certificate's DER encoding or such). As its
description in RFC 4523 section 3.1 says:

>    The certificateExactMatch matching rule compares the presented
>    certificate exact assertion value with an attribute value of the
>    certificate syntax as described in clause 11.3.1 of [X.509].

And said clause from X.509 reads:

> 11.3.1 Certificate exact match
>
> The certificate exact match rule compares for equality a presented
> value with an attribute value of type Certificate. It uniquely selects
> a single certificate.
>
>   certificateExactMatch MATCHING-RULE ::= {
>       SYNTAX  CertificateExactAssertion
>       ID      id-mr-certificateExactMatch }
>
>   CertificateExactAssertion ::= SEQUENCE {
>       serialNumber  CertificateSerialNumber,
>       issuer        Name }
>
> This matching rule returns TRUE if the components in the attribute
> value match those in the presented value.

(i.e., we are again back at the point that uniqueness of an X.509
certificate is achieved by its issuer DN plus serial number)

> Is there another way to do this?

"Manually" performing what certificateExactMatch is specifying, I would
say - i.e., use the (SSL_CLIENT_M_SERIAL,SSL_CLIENT_I_DN) tuple as a
unique identifier for a specific client certificate.

Kaspar

Re: [Patch] mod_ssl SSL_CLIENT_CERT_SUBJECTS - access to full client certificate chain

Posted by Graham Leggett <mi...@sharp.fm>.
On 05 Nov 2014, at 11:04 AM, Kaspar Brand <ht...@velox.ch> wrote:

> Given that ssl_var_lookup() is available for use in other modules, and
> provided that in addition SSL_CLIENT_S_DN_n, we would export an
> additional variable with the chain length (SSL_CLIENT_CERT_CHAIN_LENGTH
> or similar), wouldn't it be possible to do the manipulations required by
> mod_authnz_ldap in that module? mod_ssl really seems the wrong place to
> me for implementing application-specific requirements (such as these
> "matryoshka doll"-style subject DNs).

mod_authnz_ldap would also be the wrong place - the real place you would do such a thing is in the expression parser, which doesn’t (yet) have an ordered “foreach” concept that would map practically to the ssl variables. In addition this same capability needs to be built into other (non-web) servers, which won’t have the same level of expression-parser flexibility that httpd has.

The problem I am trying to solve is to find a practical way to integrate an SSL client cert identity with LDAP, in such a way where I can say “we recognise this certificate is mapped to that capability”. I am struggling to find an accurate indicator of “this certificate” (as opposed to “this similar looking certificate with a different chain”). Annoyingly the simplest solution - a simple binary match on the cert - isn’t supported by certificateExactMatch in most LDAP servers.

Is there another way to do this?

Regards,
Graham
—


Re: [Patch] mod_ssl SSL_CLIENT_CERT_SUBJECTS - access to full client certificate chain

Posted by Kaspar Brand <ht...@velox.ch>.
On 02.11.2014 15:44, Graham Leggett wrote:
> Currently the application in this case is mod_authnz_ldap. While it
> is possible to build a complex expression to match a series of DNs,
> you are limited in knowing the length of the chain in advance, and in
> my case that isn’t possible - chains may be of arbitrary length.

Given that ssl_var_lookup() is available for use in other modules, and
provided that in addition SSL_CLIENT_S_DN_n, we would export an
additional variable with the chain length (SSL_CLIENT_CERT_CHAIN_LENGTH
or similar), wouldn't it be possible to do the manipulations required by
mod_authnz_ldap in that module? mod_ssl really seems the wrong place to
me for implementing application-specific requirements (such as these
"matryoshka doll"-style subject DNs).

Kaspar

Re: [Patch] mod_ssl SSL_CLIENT_CERT_SUBJECTS - access to full client certificate chain

Posted by Graham Leggett <mi...@sharp.fm>.
On 02 Nov 2014, at 12:07 PM, Kaspar Brand <ht...@velox.ch> wrote:

> Assuming that mod_ssl exported the subject DNs as SSL_CLIENT_S_DN_0,
> SSL_CLIENT_S_DN_1 etc., what would be left to the application is
> assembling them properly (by prepending "name=" and inserting comma
> separators) to get the string you're looking for. Seems fairly
> straightforward IMO, and shouldn't be too complex to code in the
> application.

Currently the application in this case is mod_authnz_ldap. While it is possible to build a complex expression to match a series of DNs, you are limited in knowing the length of the chain in advance, and in my case that isn’t possible - chains may be of arbitrary length.

> I'm not in the position of making a judgement about the fitness of the
> suggested approach to your use case, of course (that's your call), but
> let me add that an X.509 certificate isn't uniquely identified by the
> subject DNs of its certification path. Uniqueness of an X.509
> certificate is ensured through its (issuer DN, serial number) tuple.
> Certification paths (and hence the suggested SSL_CLIENT_CERT_SUBJECTS
> string) may change when cross-certified CAs are added to the mix, see
> e.g. RFC 4158.

The problem I am trying to solve is that I trust both CA1 and CA2 to issue certificates, but I don’t trust CA2 not to (accidentally or purposefully) issue a certificate with the same issuer as CA1. As a result I want to store a record of the full sequence of DNs all the way to the root.

Back when CAs were one level deep the issuer was enough, but with arbitrary certificate chains this isn’t possible any more.

In other words, you may come in if a) your cert validates to any trusted anchor, and b) your cert is issued by a specific pre-agreed trust anchor.

> I don't dispute that such a string "can be stored in any DN formatted
> field in LDAP", but consider the use of the "name" RDN (OID 2.5.4.41)
> fairly nonstandard. X.520 defines "Name" as "the attribute supertype
> from which string attribute types typically used for naming may be
> formed" (and "string attribute types" referring to things like
> commonName, surname etc.). "distinguishedName" (2.5.4.49) would be more
> appropriate, though it isn't really meant for use as an RDN attribute
> type (but "an attribute for specifying the name of an object" in an
> X.500 DIT).

Good point, let me change that.

Regards,
Graham
—


Re: [Patch] mod_ssl SSL_CLIENT_CERT_SUBJECTS - access to full client certificate chain

Posted by Kaspar Brand <ht...@velox.ch>.
On 01.11.2014 13:41, Graham Leggett wrote:
> The trouble with doing that is that it makes life really difficult to
> match arbitrary certificate chains - you need to know in advance how
> many certs are in each chain, and you need to perform a lot of
> messing about to perform a match, and to ensure the subjects are in
> the right order.

Assuming that mod_ssl exported the subject DNs as SSL_CLIENT_S_DN_0,
SSL_CLIENT_S_DN_1 etc., what would be left to the application is
assembling them properly (by prepending "name=" and inserting comma
separators) to get the string you're looking for. Seems fairly
straightforward IMO, and shouldn't be too complex to code in the
application.

> The use case this solves is that I want to uniquely identify a
> certificate and store that identity in an LDAP directory.

I'm not in the position of making a judgement about the fitness of the
suggested approach to your use case, of course (that's your call), but
let me add that an X.509 certificate isn't uniquely identified by the
subject DNs of its certification path. Uniqueness of an X.509
certificate is ensured through its (issuer DN, serial number) tuple.
Certification paths (and hence the suggested SSL_CLIENT_CERT_SUBJECTS
string) may change when cross-certified CAs are added to the mix, see
e.g. RFC 4158.

> The format chosen is the subjects of the certs encoded as RFC2253,
> which are turned into a DN that is in turn RFC2253 encoded again. The
> result is therefore still a valid DN, and so can be stored in any DN
> formatted field in LDAP. This works nicely with 389ds.

I don't dispute that such a string "can be stored in any DN formatted
field in LDAP", but consider the use of the "name" RDN (OID 2.5.4.41)
fairly nonstandard. X.520 defines "Name" as "the attribute supertype
from which string attribute types typically used for naming may be
formed" (and "string attribute types" referring to things like
commonName, surname etc.). "distinguishedName" (2.5.4.49) would be more
appropriate, though it isn't really meant for use as an RDN attribute
type (but "an attribute for specifying the name of an object" in an
X.500 DIT).

> In terms of separating them, simply unpack the outer DN as per
> RFC2253, leaving you with the inner subject DNs. In practise you’re
> unlikely to want to separate them, instead you want to say “I want to
> trust this specific certificate issued by this specific CA”. Back in
> time matching the issuer was enough, but as soon as intermediate
> certs came along it became significantly more difficult to do.
> 
> (Having said the above I don’t disagree that the _n variables could
> be useful, it’s just that they don’t solve the use case I am
> facing).

My concern with the proposed SSL_CLIENT_CERT_SUBJECTS variable is that
it hardcodes a specific use case instead of adding a generic way to
retrieve the subject DNs of the complete certification path. The latter
is what should be implemented in mod_ssl, while constructing
SSL_CLIENT_CERT_SUBJECTS (or similar stuff) should be done in the
application, IMO.

Kaspar

Re: [Patch] mod_ssl SSL_CLIENT_CERT_SUBJECTS - access to full client certificate chain

Posted by Graham Leggett <mi...@sharp.fm>.
On 01 Nov 2014, at 11:47 AM, Kaspar Brand <ht...@velox.ch> wrote:

> Feels like a fairly idiosyncratic solution to me (essentially sticking
> multiple things together into a single environment variable, with the
> [known] problems of how to separate them again / do proper matching in
> the application). I would prefer these DNs being exported to the
> environment in the same way as it is currently done with the
> SSL_CLIENT_CERT_CHAIN_n variables.

The trouble with doing that is that it makes life really difficult to match arbitrary certificate chains - you need to know in advance how many certs are in each chain, and you need to perform a lot of messing about to perform a match, and to ensure the subjects are in the right order.

The use case this solves is that I want to uniquely identify a certificate and store that identity in an LDAP directory. The most obvious solution - just store the cert in the userCertificate attribute and do a direct binary match - doesn’t work in most directories, as direct certificate matching was forgotten in the specs that were involved (unfortunately).

The format chosen is the subjects of the certs encoded as RFC2253, which are turned into a DN that is in turn RFC2253 encoded again. The result is therefore still a valid DN, and so can be stored in any DN formatted field in LDAP. This works nicely with 389ds.

In terms of separating them, simply unpack the outer DN as per RFC2253, leaving you with the inner subject DNs. In practise you’re unlikely to want to separate them, instead you want to say “I want to trust this specific certificate issued by this specific CA”. Back in time matching the issuer was enough, but as soon as intermediate certs came along it became significantly more difficult to do.

(Having said the above I don’t disagree that the _n variables could be useful, it’s just that they don’t solve the use case I am facing).

Regards,
Graham
—