Hey guys,
Answering a few email in a row below.
Thanks,
Sebastian
On Wed, Jan 9, 2019 at 12:19 AM John Dennis <jdennis(a)redhat.com> wrote:
On 1/8/19 5:02 PM, Nalyvayko, Peter wrote:
> Hi,
>
>>> I believe that's a bug. The `X509ClientCertificateAuthenticator`
should ignore those extra spaces. May I kindly ask you to create a ticket
for us and assign it either to me or Sebastien?
>
> Sebastian/Michael,
>
> According to
https://tools.ietf.org/html/rfc1779, BNF for distinguished
name allows for optional space before and after the separator. Do you know
of any reason why the DN returned by LDAP and the DN returned by calling
to X509Certificate.getSubjectDN().getName() should or expected be
identical? It seems to me BNF allows for some discrepancies in
representation thus comparing two strings verbatim may not be a good idea,
no?
Let me try to reiterate the whole flow to make sure I understand everything
correctly:
- X509ClientCertificateAuthenticator extracts certificates from an incoming
HTTP request using one of the implementations
of X509ClientCertificateLookup.
- Obtained certificate chain is of a type X509Certificate[].
- Then we extract a User identity based on his certificate
(certs[0].getSubjectDN().getName()).
- Once we have a User identity in our hands, we can extract a UserModel,
our representation of a User in Keycloak. This user might be imported from
LDAP. Here's where those two pieces play together.
- If we find a user and he's valid, we end the flow.
So the root problem is that certificate obtained from the request doesn't
match the one from LDAP, even though they are maintained in a single place
(somehow, details omitted).
So, yes, this situation may happen since in the essence, we do just a DN
comparison by strings. The easiest workaround in my opinion is to normalize
those DNs across Keycloak codebase. The simplest solution is to
modify LDAPDn class as Michel suggested. I believe it should also work if
we modify a user certificate attribute and put spaces there (", ").
At first I though the fix should go X509ClientCertificateAuthenticator but
obviously, I was wrong. It's just a mismatch problem.
RFC 1779 (A String Representation of Distinguished Names) also mentions
different separators like for example ";", "," or ", "
(comma with or
without a space). In order to support all this usecases, we'd probably need
to implement a custom DN comparator and modify our database queries that
extract users based on DN. At this point I'm not 100% convinced we need
this. Maybe we should just say in the docs that if you synchronize users
with LDAP, you should use ", " as a separator when specifying user
certificates?
@Michael, @Peter - WDYT about that? Would that solution solve your problem?
@Hynek, @Marek - maybe you guys have some thoughts around this?
On previous projects I did a lot of work with DN handling, I believe
the
relevant RFC is 4514 (unless it's been superseded). The short answer is
it's never correct to compare DN's via string comparison unless the DN
was normalized to a consistent representation. The reason is there are
multiple valid string representations of the same DN. Aside from issues
related to whitespace, encoding, etc. you need to remember that there is
such a thing as multi-valued RDN's (e.g. an RDN with an UNORDERED set of
AVA's), any ordering of the AVA's in the RDN yield a semantically
equivalent RDN.
Most libraries that compare DN's do so by parsing the string
representation and building a data structure consisting of the
individual components which are then iterated over during comparison.
Once the DN has been parsed into it's constituent components there is
usually a routine to convert it back into a string representation. This
can be used to normalize the string representation thus permitting a
simple string compare to check for equality.
> Kindly,
> Peter
>
>
> -----Original Message-----
> From: keycloak-dev-bounces(a)lists.jboss.org <
keycloak-dev-bounces(a)lists.jboss.org> On Behalf Of Sebastian Laskawiec
> Sent: Monday, January 7, 2019 7:36 AM
> To: Peck, Michael A <mpeck(a)mitre.org>; sblanc(a)redhat.com
> Cc: keycloak-dev(a)lists.jboss.org
> Subject: Re: [keycloak-dev] User TLS client certificate authentication -
inconsistent DN string representation with LDAP
>
> Hey Michael,
>
> Adding +Sebastien Blanc <sblanc(a)redhat.com> for visibility.
>
> I believe that's a bug. The `X509ClientCertificateAuthenticator` should
ignore those extra spaces. May I kindly ask you to create a ticket for us
and assign it either to me or Sebastien?
>
> Thanks,
> Sebastian
>
> On Sun, Dec 23, 2018 at 6:49 PM Peck, Michael A <mpeck(a)mitre.org> wrote:
>
>> Hello,
>>
>> I’ve configured Keycloak to authenticate users using TLS client
>> certificate authentication.
>> I’ve also configured Keycloak to synchronize users with my LDAP server.
>>
>> I’d like to match the TLS client certificate’s Subject DN to the
>> Subject DNs synchronized from my LDAP server (which are stored by
>> Keycloak in each user’s LDAP_ENTRY_DN attribute).
>>
>> I’ve set that up, but am running into an issue that Keycloak appears
>> to have inconsistent string representations of DNs between those two
>> methods - so the Subject DNs from the TLS client certificate and the
>> LDAP server aren’t matching as I was expecting.
>>
>> The TLS client certificate DNs look like this:
>> CN=Peck Michael, OU=People, DC=test, DC=net
>>
>> While the LDAP_ENTRY_DN attribute is formatted like this:
>> cn=Peck Michael,ou=People,dc=test,dc=net
>>
>> It looks to me that the TLS client certificate DN string
>> representation is coming from the standard Java X500Principal class
>> used by calls to
>> X509Certificate.getSubjectDN().getName() in
>> keycloak/services/src/main/java/org/keycloak/authentication/authentica
>> tors/x509/X509ClientCertificateAuthenticator.java
>> and the LDAP_ENTRY_DN string representation is coming from the
>> toString method in
>>
keycloak/federation/ldap/src/main/java/org/keycloak/storage/ldap/idm/model/LDAPDn.java.
>>
>> I modified the LDAPDn class’s toString method to follow the same
>> format as used in the TLS client certificate DNs, and authentication
works for me now.
>> Would the Keycloak project consider accepting a pull request to change
>> the way LDAPDn formats DNs as strings?
>> (However I have not checked if this would impact other uses of the
>> LDAPDn class within Keycloak or cause problems with upgrading existing
>> deployments?)
>>
>> The suggested change follows:
>> diff --git
>> a/federation/ldap/src/main/java/org/keycloak/storage/ldap/idm/model/LD
>> APDn.java
>> b/federation/ldap/src/main/
>> index 39e7d97..2f8c805 100644
>> ---
>> a/federation/ldap/src/main/java/org/keycloak/storage/ldap/idm/model/LD
>> APDn.java
>> +++
>> b/federation/ldap/src/main/java/org/keycloak/storage/ldap/idm/model/LD
>> APDn.java @@ -87,9 +87,9 @@ public class LDAPDn {
>> if (first) {
>> first = false;
>> } else {
>> - builder.append(",");
>> + builder.append(", ");
>> }
>> -
>> builder.append(rdn.attrName).append("=").append(rdn.attrValue);
>> +
>>
builder.append(rdn.attrName.toUpperCase()).append("=").append(rdn.attrValue);
>> }
>>
>> return builder.toString();
>>
>>
>>
>> Thank you,
>> Michael Peck
>> The MITRE Corporation
>> _______________________________________________
>> keycloak-dev mailing list
>> keycloak-dev(a)lists.jboss.org
>>
https://lists.jboss.org/mailman/listinfo/keycloak-dev
> _______________________________________________
> keycloak-dev mailing list
> keycloak-dev(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/keycloak-dev
>
> _______________________________________________
> keycloak-dev mailing list
> keycloak-dev(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/keycloak-dev
>
--
John Dennis