On 13.10.2016 18:52, Sumit Bose wrote:
On Tue, Oct 11, 2016 at 01:37:09PM +0200, Sumit Bose wrote:
On Thu, Oct 06, 2016 at 12:49:30PM +0200, Sumit Bose wrote:

I've started to write a SSSD design page about enhancing the current
mapping of certificates to users and how to select/match a suitable
certificate if multiple certificates are on a Smartcard.

My currently thoughts and idea and be found at
and for your convenience below as well.

Comments and suggestions are welcome. Please let me know about concerns,
alternatives and missing use-cases/user-stories.



Rob, Fraser, Alexander, thank you for your comments. I think both the
issuer specific matching and the OID in the SUBJECT matching are good
ideas. I updated the design page accordingly. The changes can be shown

The updated version can be found below as well. Of course more comments and
suggestions are still very welcome.

I did another update. A "Compatibility with Active Director" section is
added which made me realize that there are use-cases for using the
issuer in the mapping as well and the sub-strings in LDAP search filters
might be useful as well.

The changes can be seen with

Please let me know your comments and suggestions.


= Matching and Mapping Certificates =

Related ticket(s):
 * http://www.freeipa.org/page/V4/User_Certificates#Certificate_Identity_Mapping

=== Problem statement ===
==== Mapping ====
Currently it is required that a certificate used for authentication is either 
stored in the LDAP user entry or in a matching override. This might not always 
be applicable and other ways are needed to relate a user with a certificate.

==== Matching ====
Even if SSSD will support multiple certificates on a Smartcard in the context 
of https://fedorahosted.org/sssd/ticket/3050 it might be necessary to restrict 
(or relax) the current certificate selection in certain environments.

=== Use cases ===
==== Mapping ====
In some environments it might not be possible or would cause unwanted effort to 
add certificates to the LDAP entry of the users to allow Smartcard based 
authentication. Reasons might be:
* Certificates/Smartcards are issued externally
* LDAP schema extension is not possible or not allowed

==== Matching ====
A user might have multiple certificate on a Smartcard which are suitable for 
authentication. But on some host in the environment only certificates from a 
specific CA (while all other CAs are trusted as well) or with some special 
extension should be valid for login.

=== Overview of the solution ===
To match a certificate a language/syntax has to be defined which allows to 
reference items from the certificate and compare the values with the expected 
data. To map the certificates to a user the language/syntax should allow to 
relate certificate items with LDAP attributes so that the value(s) from the 
certificate item can be used in a LDAP search filter.

Note that in some cases it might be possible to map a certificate to a user without having to do an extra LDAP search, for example when the certificate contains the principal name of the user. Does the design allow this? Or is there no extra LDAP search?

=== Implementation details ===
==== Matching ====
The pkinit plugin of MIT Kerberos must find a suitable certificate from a 
Smartcard as well and has defined the following syntax (see the 
pkinit_cert_match section of the krb5.conf man page or 
http://web.mit.edu/Kerberos/krb5-1.14/doc/admin/conf_files/krb5_conf.html for 
details). The main components are

* <SUBJECT>regular-expression
* <ISSUER>regular-expression
* <SAN>regular-expression
* <EKU>extended-key-usage-list
* <KU>key-usage-list

and can be grouped together with a prefixed '&&' (and) or '`||`' (or) operator 
('&&' is the default). If multiple rules are given they are iterated with the order in 
the config file as long as a rule matches exactly one certificate.

'''Question: MIT Kerberos use case-sensitive matching and POSIX Extended 
Regular Expression syntax, shall we do the same?'''

While <SUBJECT> and <ISSUER> are (imo) already quite flexible I can see some 
potential extensions for the other components.

I don't think regular expressions are a particularly good choice for DN matching. It is difficult to express assertions which are quite natural for DNs (matching multi-attribute RDNs, matching the same attribute type by different identifiers, respecting the defined matching rules of attribute types) and at the same time it is easy to express assertions which do not make much sense for DNs (matching substrings in attribute names, matching accross multiple syntactical elements, etc.).

That said, does the design have to be based on the MIT pkinit matching? To me it looks like something quickly hacked together rather than thoughtfully designed. I would personally base the design on the concepts of CertificateMatch, which is the standard way of matching certificates, defined in X.509, rather than reinvent the wheel.

<EKU> and <KU> in MIT Kerberos only accept certain string values related to 
some allowed values in those field as defined in https://www.ietf.org/rfc/rfc3280.txt . The 
selection is basically determined by what is supported on server side of the pkinit plugin 
of MIT Kerberos. Since we plan to extend pkinit and support local authentication without 
pkinit as well I would suggest to allow OID strings for those components as well (the 
comparison is done on the OID level nonetheless).

The <SAN> component in MIT Kerberos only checks the otherName SAN component for the 
id-pkinit-san OID as defined in https://www.ietf.org/rfc/rfc4556.txt or the 
szOID_NT_PRINCIPAL_NAME OID as mentioned in https://support.microsoft.com/en-us/kb/287547. 
While this is sufficient for the default pkinit user case of MIT Kerberos I would suggest 
to extend this component by allowing to specific an OID with <SAN:O.I.D>

===== Issuer specific matching =====
Although the MIT Kerberos rules allow to select the issuer of a certificate there are 
use cases where a more specific selection is needed. E.g. if there are some default 
matching rules for all issuers and some other issuer specific rules where the default 
rules should not apply. To make this possible with the above scheme the default rules 
must have an <ISSUER> clause which matches all but the issuer with the specific 
rules. Writing regular-expressions to not match a specific string or a list of 
strings is at least error-prone if not impossible.

To make it easier to define issuer specific rules and default rules at the same 
time and optional issuer string can be added to the rule to indicate that for 
the given issuer only those rules should be considered. Given the use-case I 
think it is acceptable to require that the full issuer must be specified here 
in LDAP order (see below) and case-sensitive matching is used.

This could also be solved by adding priority to rules - if two rules match, the one with higher priority (the issuer specific rule) is preferred over the one with lower priority (the default rule). IMO this is better than an optional issuer string as it offers greater flexibility.

How the issuer string is linked to the matching rules depends on the storage 
(LDAP or sssd.conf, see below for details).
==== Mapping ====
Since different certificates, e.g. issued by different CAs, might have 
different mapping rule, a matching rule must be added if there are more than 1 
mapping rule. A single mapping rule without a matching rule might be used as 
default/catch-all rule in this case.

If multiple rules matches the derived LDAP filter components can be grouped with the 
or-operator "|".

A mapping rule can use a similar syntax like the matching rule where the LDAP 
attribute can be added with a ':', e.g.
* <ISSUER:O.I.D.:ldapAttributeName:*>
* <SUBJECT:O.I.D.:ldapAttributeName:*>
* <SAN:O.I.D.:ldapAttributeName:*>

where O.I.D. is either the OID or name of a RDN type or the OID or some well-known-name of the SAN 
component respectively. Since the SUBJECT might contain multiple RDNs of the same type always the 
"most specific" is selected because in general this will be the most suited one to map 
the certificate to a specific user. "most specific" means the last in X.500 order and the 
first in LDAP order (see discussion below for details).

If the O.I.D. is missing the full SUBJECT/ISSUER is used for mapping. If 'DN' 
is used as ldapAttributeName SUBJECT is expected to be the DN of the user. If 
the O.I.D. is missing in the SAN case the same default as with matching 
(id-pkinit-san and szOID_NT_PRINCIPAL_NAME OID) is used. If both SAN values can 
be found in the certificate and are different the LDAP search filter will 
combine both with the or-operator.

The optional '*' in the end indicates that a sub-string search 
(ldapAttributeName=*value*) should be used and not an exact match 
(ldapAttributeName=value). Please note that it depends on the server-side 
definition of the LDAP attribute if case-sensitive or case-insensitve matching 
is used.

This seems like a rather quirky way to write down an LDAP filter. IMHO a better way would be to use a single attribute containing a filter template, e.g.:


Currently I see no usage for <KU> and <EKU> in mapping rules because they do not 
contain any user-specific data. If at some point we will have personal CAs we might consider to 
add <ISSUER> based mappings.

===== Future consideration =====
Most of the interesting values from the SAN should be directly map-able to LDAP 
attributes. And processing the string representation of <SUBJECT> might be 
tricky as discussed below. Nevertheless it might be possible to add to following in a 
future release if more complex operations on the values are needed:

* <SUBJECT:ldapAttributeName>/regexp/replacement/
* <SAN:O.I.D.:ldapAttributeName>/regexp/replacement/

where "/regexp/replacement/" stands for optional sed-like substitution rules. 
E.g. a rule like
would take the subject string 'CN=Certuser,CN=Users,DC=example,DC=com' from the 
certificate and generate a LDAP search filter component 
'(samAccountName=Certuser)' which can be included in a LDAP search filter which 
includes additional components like e.g. an objectClass.

The search-and-replace does not has to be sed-like because afaik there is not 
library which offers this and I would like to avoid implementing it. GLib e.g. 
 g_regex_replace]. Since we already have a GLib dependency in SSSD due to soem 
utf8 helper functions using might be acceptable as well. Nevertheless it would 
be nice to hear if there are alternative libraries available as well.

Maybe even search-and-replace are not sufficient for all cases and something 
like embedded lua scripts are needed. But since certificate mapping is about 
access control and authorization it should be always considered if adding a new 
attribute to the users LDAP entry which makes mapping easy and straight-forward 
wouldn't be the better solution.

===== Some notes about DNs =====
The X.500 family of standards define names as "SEQUENCE OF RelativeDistinguishedName" where the 
sequence is "starting with the root and ending with the object being named" (see X.501 section 9.2 
for details). On the other hand RFC4514 section 2.1 says "Otherwise, the output consists of the string 
encoding of each RelativeDistinguishedName in the RDNSequence (according to Section 2.2), starting with the 
last element of the sequence and moving backwards toward the first." This means that the ASN.1 encoded 
issuer and subject DN from the X.509 certificate can be either displayed as string in the
* X.500 order: DC=com,DC=example,CN=users,CN=Certuser
or in the
* LDAP order: CN=Certuser,CN=Users,DC=example,DC=com

As a consequence different tools will use a different order when printing the 
issuer and subject DN. While NSS's certutil will use the LDAP order, 'openssl 
x509' and gnutls's certtool will use the X.500 order (the latter might change 
due to https://gitlab.com/gnutls/gnutls/issues/111).

This makes it important to specific the order which is used by SSSD for mapping and 
matching. I would prefer the LDAP order here. E.g. by default the AD CA uses the DN 
of the users entry in AD as subject in the issues certificate. So a matching rule 
like '<SUBJECT:dn>' could tell SSSD to directly search the user based on its DN 
(which btw is the original intention of the subject field in the certificate, only 
that the DN should be looked up in a more general DAP as defined by X.500 and not in 
the lightweight version called LDAP)

Another issue is the limited set of attribute names/types required by the RFCs 
(see section of RFC 3280 and section 3 of RFC 4514). If e.g. the 
deprecated OID [http://www.oid-info.com/get/1.2.840.113549.1.9.1 
1.2.840.113549.1.9.1] is used all tools are able to identify it as an email 
address but OpenSSL displays it as 'emailAddress=u...@example.com', certtool as 
'EMAIL=u...@example.com' and certutil as 'E=u...@example.com'. So matching 
rules should try to avoid attribute names or only the ones from 
[https://www.ietf.org/rfc/rfc4514.txt RFC 4514]:
* CN      commonName (
* L       localityName (
* ST      stateOrProvinceName (
* O       organizationName (
* OU      organizationalUnitName (
* C       countryName (
* STREET  streetAddress (
* DC      domainComponent (0.9.2342.19200300.100.1.25)
* UID     userId (0.9.2342.19200300.100.1.1)

==== About restricting or enforcing the mapping an matching any further ====
The goal of the matching rules in MIT Kerberos is to select a single 
certificate from a Smartcard which will then be used for PKINIT. Since we 
already plan to enhance SSSD to support multiple certificates on a Smartcard 
and if needed prompt the user which one to use for login we should not enforce 
that the matching rules should return only a single certificate or nothing.

Similar we plan to enhance SSSD to use the same certificate to log in with 
different user identities, e.g. as a user with standard privileges or as a user 
with administrator privileges. So it can make sense that multiple mapping rules 
apply to the same certificate and the related LDAP search filter components are 
or-ed together.

In many cases the login program will first ask for a user name which will help 
to restrict the number of suitable certificates even further and the mapping 
rules are only needed to check if the certificate belongs to the user trying to 
log in.

But gdm has a feature where gdm will detect when a Smartcard is inserted and 
call PAM without a user name. In this case SSSD has to determine the user name 
based on the certificates found on the Smartcard. If in this case multiple 
valid certificates are on the card and the mapping rules will return multiple 
users for each certificate gdm has to display a quite long selection of 
certificate-user pairs the user has to choose from.

So it should be underlined in the documentation that the matching and mapping 
rules should be detailed and specific so that for the given environment they 
help to avoid cases where the user is prompted to select a certificate (or user 
name in the gdm case) when trying to log in.

==== Storing matching and mapping configuration ====
On the IPA server a new objectclass can be created to store an matching-mapping 
rule pair together with a specific issuer. All attributes are optional because 
a missing mapping rule would mean that the user entry will be search with the 
whole certificate. A missing matching rule will indicate catch-all rule with a 
default mapping. If only a specific issuer is given certificates from this 
issuer must be stored in the LDAP entry of the user to make authentication 

Specifying matching-mapping rules in sssd.conf is a bit more complicated 
because SSSD does not respect multiple entries with the same keyword, only the 
last one is used. So all rules have to be added to a single line. To give it a 
little bit of structure the rules can be enclosed by curly-braces '{}{}{}' and 
each rule pair is separated by a comma ','. A single rule in curly braces 
indicates a matching rule and the mapping will be done with the whole 
certificate. A default/catch-all mapping rule will start with an empty pair of 
curly braces followed by a pair containing the mapping rule. Issuer specific 
rules will have three pairs of curly braces where the first pair must contain 
an issuer string.

===== Future considerations =====
If it turns out that this option is used quite often and it gets complicated to 
manage a larger set of rules with it and storing the rules in LDAP/IPA/AD is 
not an option we might add support to read the rules from a separate file 
(certificate_rules = FILE:///etc/sssd/cert_rules) with a more suitable format, 
e.g. ini where a list can be defined by given the same option multiple times.

===== Examples =====
* '''certificate_rules = {<EKU>msScLogin}''': only allow certificates with have 
the Microsoft OID for Smartcard logon set. use the whole 
certificate to look-up the user. The same result can be achieved with
* '''certificate_rules = {<EKU>}''': see above
* '''certificate_rules = 
 only allow certificates form the 'my-company' issuer which have an email address from the 
'my-company.com' domain in the rfc882Name SAN attribute. Use the email address in a LDAP search 
filter '(mail=email-address)' to find the matching user.

==== Compatibility with Active Directory ====
Active Directory uses a per-user LDAP attribute 
[https://msdn.microsoft.com/en-us/library/cc220106.aspx altSecurityIdentities] 
to allow arbitrary user-certificate mappings is there is no suitable 
user-principal-name entry in the SAN of the certificate.

Unfortunately it is more or less undocumented how AD use the values of this 
attribute. The best overview I found is in 

It looks like the most important variant is the issuer-subject pair. This one 
is e.g. created when a certificate is added via the 'Name Mappings' context 
menu entry in AD's 'Users and Computers' utility ('Advanced Features' must be 
activated in the 'View' menu). The attribute value might look like
altSecurityIdentities: X509:<I>O=Red Hat,OU=prod,CN=Certificate Authority<S>DC
 m,CN=Sumit Bose Sumit Bose
First it can be seen that X.500 ordering is used. Second, if RDN types not explicitly 
mentioned in the RFCs are used, you are on your own. As can be seen AD can translate the 
deprecated OID [http://www.oid-info.com/get/1.2.840.113549.1.9.1 1.2.840.113549.1.9.1] 
and uses 'E' as NSS. But the OID [http://www.oid-info.com/get/0.9.2342.19200300.100.1.1 
0.9.2342.19200300.100.1.1] which is explicitly mentioned in RFC4514 is not translated as 
UID but the plain OID syntax is used (my guess it that Microsoft tries to be compatible 
with "older" versions because the UID was added in RFC2253 from 1997 but was 
not present in the RFC1779 from 1995 and RFC1485 from 1993).

Nevertheless with the mapping rules described above a rule like
would product a LDAP search filter like
(&(altSecurityIdentities=*Red Hat*)(altSecurityIdentities=*Sumit Bose Sumit 
which should quite reliable find the right LDAP entry.

As an alternative it would be possible to add special mapping rules like 
<ALT-SEC-ID-I-S:ldapAttributeName> which would try in a best effort to produce 
the exact attribute value AD is using. This should work reliable with standard RDN 
types (see above). I think an optional 'ldapAttributeName' is useful here so that the 
same mapping rule can be used with different LDAP servers (e.g. IPA) where 
user-specific mapping attributes are used with the same content but a different 
attribute name.

According to the blob post describing altSecurityIdentities some other 
additional mapping rules might be useful too. This will give us
* <ALT-SEC-ID-I-S:ldapAttributeName>
* <ALT-SEC-ID-S:ldapAttributeName>
* <ALT-SEC-ID-SKI:ldapAttributeName>
* <ALT-SEC-ID-I-SR:ldapAttributeName>
* <ALT-SEC-ID-SHA1-PUBKEY:ldapAttributeName>
* <ALT-SEC-ID-RFC822:ldapAttributeName>

So far I didn't found a AD tool which creates to other mappings, if you know 
one, please let me know.
=== Configuration changes ===
Does your feature involve changes to configuration, like new options or options 
changing values? Summarize them here. There's no need to go into too many 
details, that's what man pages are for.

=== How To Test ===
This section should explain to a person with admin-level of SSSD understanding 
how this change affects run time behaviour of SSSD and how can an SSSD user 
test this change. If the feature is internal-only, please list what areas of 
SSSD are affected so that testers know where to focus.

=== How To Debug ===
Explain how to debug this feature if something goes wrong. This section might 
include examples of additional commands the user might run (such as keytab or 
certificate sanity checks) or explain what message to look for.

=== Authors ===
Give credit to authors of the design in this section.


Jan Cholasta
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org

Reply via email to