On Thu, Oct 06, 2016 at 12:49:30PM +0200, Sumit Bose wrote:
Hi,
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
https://fedorahosted.org/sssd/wiki/DesignDocs/MatchingAndMappingCertificates
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.
bye,
Sumit
Hi,
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
with
https://fedorahosted.org/sssd/wiki/DesignDocs/MatchingAndMappingCertifica...
The updated version can be found below as well. Of course more comments and
suggestions are still very welcome.
bye,
Sumit
= Matching and Mapping Certificates =
Related ticket(s):
*
http://www.freeipa.org/page/V4/User_Certificates#Certificate_Identity_Map...
=== 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.
=== 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.
<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.
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.
* <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 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.
Currently I see no usage for <ISSUER>, <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
{{{
<SUBJECT:samAccountName>/^CN=\([^,]*\).*$/\1/
}}}
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. has
[
https://developer.gnome.org/glib/stable/glib-Perl-compatible-regular-expr...
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 4.1.2.4 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=user(a)example.com', certtool as 'EMAIL=user(a)example.com' and
certutil as 'E=user(a)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 (2.5.4.3)
* L localityName (2.5.4.7)
* ST stateOrProvinceName (2.5.4.8)
* O organizationName (2.5.4.10)
* OU organizationalUnitName (2.5.4.11)
* C countryName (2.5.4.6)
* STREET streetAddress (2.5.4.9)
* 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 possible.
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 1.3.6.1.4.1.311.20.2.2 set.
use the whole certificate to look-up the user. The same result can be achieved with
* '''certificate_rules = {<EKU>1.3.6.1.4.1.311.20.2.2}''':
see above
* '''certificate_rules =
{<ISSUER>*my-company*<SAN:rfc822Name>*@my-company.com$}{<SAN:rfc822Name:mail>}''':
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.
=== 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.