On Fri, Nov 25, 2016 at 02:19:10PM +0100, Jan Cholasta wrote:
> Bump, Sumit, have you seen my comments? I haven't heard back from you.
Yes, I've seen it and added a comment about it on the page
https://fedorahosted.org/sssd/wiki/DesignDocs/MatchingAndMappingCertifica...
To cut it short I would prefer to use a standard, but I think RFC4523
currently does nit meet out needs. But I would be happy if there are
ways to mitigate my concerns.
What I actually had in mind was not to use the full RFC 4523 syntax, but
rather re-use the concepts used in it - for example, instead of using
regular expressions to match subject names, we could use a scheme based
on name constraints, where the subject name is matched using base +
minimum distance + maximum distance, which could look like this, written
down using glob-like syntax:
directoryName=CN=a,O=b
(base = CN=a,O=b, minimum distance = 0, maximum distance = 0)
directoryName=*,O=b
(base = O=b, minimum distance = 1, maximum distance = 1)
directoryName=*,*,O=b
(base = O=b, minimum distance = 2, maximum distance = 2)
directoryName=**,*,O=b
(base = O=b, minimum distance = 1, maximum distance unspecified)
I'm working on updating and changing other sections as well and planned
to reply when I'm done with the other sections as well.
bye,
Sumit
>
> On 17.10.2016 09:50, Jan Cholasta wrote:
>> Hi,
>>
>> 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:
>>>>> 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.
>>>>
>>>
>>> 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
>>>
https://fedorahosted.org/sssd/wiki/DesignDocs/MatchingAndMappingCertifica...
>>>
>>>
>>> Please let me know your comments and suggestions.
>>>
>>> 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.
>>
>> 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.:
>>
>> (&(someAttr={issuer})(someOtherAttr=*{subject:O.I.D}*))
>>
>>>
>>> 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
>>> {{{
>>> <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.
>>>
>>> ==== 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
>>>
https://blogs.msdn.microsoft.com/spatdsg/2010/06/18/howto-map-a-user-to-a....
>>>
>>>
>>> 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
>>>
=com,DC=redhat,OU=users,OID.0.9.2342.19200300.100.1.1=sbose,E=sbose(a)redhat.co
>>>
>>> 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
>>> {{{
>>>
<ISSUER:O:altSecurityIdentities:*><SUBJECT:CN:altSecurityIdentities:*>
>>> }}}
>>> would product a LDAP search filter like
>>> {{{
>>> (&(altSecurityIdentities=*Red Hat*)(altSecurityIdentities=*Sumit Bose
>>> Sumit Bose*))
>>> }}}
>>> 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.
>>>
>>
>> Honza
>>
>
>
> --
> Jan Cholasta