DevHeads.net

TLS client certificates and auth external

Hello,

I have an email client (K-9 on Android), which, when using TLS client
certificates insists on sending an auth external. However, postfix/SASL
does not advertise external auth, which causes the client to not being
able to use client certificates with postfix.

As I see it, postfix is missing the external mechanism as specified in
RFC 2222 (SASL) completely. Thus, I have implemented this feature (for
TLS CA client certs) and I am currently successfully running this on a
local installation using cyrus sasl.

I would be willing to provide a patch and would really like to see this
integrated in future versions of postfix.

I hope this is the right postfix mailing list for this request.

Bastian

Comments

Re: TLS client certificates and auth external

By Viktor Dukhovni at 01/08/2019 - 18:35

Well perhaps postfix-devel is equally or more appropriate.

There is a key design issue here:

* In typical Postfix configurations we see relay restrictions of
the form:

smtpd_relay_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination

which is fine, when the user has enrolled for a login account
on the receiving system. But with client certs, anyone can get
a client certificate from some CA, or even mint their own.

So what does "SASL authenticated" mean with client certs? Is
there a particular issuing CA that's the only one trusted to
issue client certs? Or does the client certificate fingerprint
need to match a lookup table for it to be considered authenticated?

My advice is that a trusted CA, and likely often accidentally every
CA on the planet from one of the usual CA bundles, is much too risky
in this context, and would drag in revocation lists, OCSP, and that
whole dumpster-fire of PKI issues.

Therefore, the meaning of SASL authenticated for EXTERNAL should be
that the client certificate fingerprint matches a lookup table that
maps the client certificate to something resembling a SASL user name.

You would then either "permit_sasl_authenticated" without distinguishing
between one user and another, or else use "check_sasl_access" based on
username obtained from the fingerprint->username map. You could also
then use the "sender login mismatch" features by matching the username
with valid sender addresses, ...

Otherwise, "EXTERNAL" should be fairly straight-forward. Feel free to
move the discussion to postfix-devel, or continue here to the extent
the discussion stays high level, rather than dives into the implementation.

Re: TLS client certificates and auth external

By Matthew Horan at 03/10/2019 - 22:47

I'm quite excited about seeing this feature added to Postfix. I have a
similar configuration, and have been putting off making the proposed changes
myself. I had previously posted on the Dovecot mailing list [1] to no avail.
I'm happy to know that there are at least two of us out there who would
benefit from this feature!

Thanks,
Matt

[1] <a href="https://www.dovecot.org/list/dovecot/2017-February/106884.html" title="https://www.dovecot.org/list/dovecot/2017-February/106884.html">https://www.dovecot.org/list/dovecot/2017-February/106884.html</a>

Re: TLS client certificates and auth external

By Bastian Schmidt at 03/18/2019 - 17:45

In the meantime I have completed a patch and sent it to Wietse and
Victor, which adds an option smtpd_sasl_tls_ccert_username.
As the patch is rather small, I also attached it to this message.

This smtpd_sasl_tls_ccert_username option can be used in the following way:

Using smtpd_sasl_tls_ccert_username = commonName
After providing a verified client certificate, postfix advertises auth
external and the user can authenticate with the username being the
commonName of the certificate. This is for users having control over the
CA issuing the certificates and resembles the way cyrus imap handles the
situation.

Using smtpd_sasl_tls_ccert_username = relay_clientcerts
When a client presents a certificate, where the fingerprint matches in
relay_clientcerts, the lookup value (previously unused) is used to get
the username for sasl. The client can then perform an auth external with
this username successfully. This is a solution for users, which cannot
control the CAs or do not want to trust them or cope with crls, ... It
fits in the way postfix currently handles client certificates.

Both solutions then cause permit_sasl_authenticated to succeed and the
sasl username to be set correctly.

The default for smtpd_sasl_tls_ccert_username (the empty value) or any
other value cause auth external to not be advertised and neither
succeed; the same situation as without the patch.

I have the first version running successfully in a small local
installation using cyrus sasl, where K-9 and Thunderbird are both able
to use client certificates (and simple username/password login). With
cyrus sasl the setup is more or less straight forward.
I also setup a virtual machine to test a dovecot sasl setup. Here the
setup is more complicated, as dovecot has to be setup to allow an empty
password, when using external auth (and only, when using external auth).
This is only possible since version dovecot version 2.2.28. Here I have
tested my patch using the s_client only.

Best regards,
Bastian

On 11.03.19 03:47, Matthew Horan wrote:

Re: TLS client certificates and auth external

By =?ISO-8859-1?Q?... at 03/27/2019 - 11:31

Hello,

Great piece of work ! It solve a big part of my problem, but sadly I
need to go deeper.

Le 18/03/2019 à 22:45, Bastian Schmidt a écrit :
I have to deal with products that do not support SMTP AUTH (big email
security appliance provider .....) but are able to present a TLS
certificate.
On my platform, the use of the smtpd_sender_login_maps and associated
restrictions (reject_sender_login_mismatch) is mandatory to achieve our
goal.
At first, I was thinking about using the lookup value of
relay_clientcerts to map a sasl username.
It is nicely done with your patch with smtpd_sasl_tls_ccert_username =
relay_clientcerts, but I need to go one step further:
I need to completely bypass the sasl provider call and act as if the
mapped user successfully authenticate.
It would be something like "smtpd_sasl_tls_ccert_username =
relay_clientcerts_nosasl" or relay_clientcerts_saslbypass or other (I'm
not good at finding good option naming ...)

The goal is to be as transparent as possible :
- if the client is not found in the relay_clientcerts, act as usual
- if the client is found in the relay_clientcerts, no longer announce
AUTH support, the auth and identity mapping is already done by the
relay_clientcerts map

I think it is not a big code complexity addition on top of your work,
but before going further I would like to request for comments about this.
Viktor, Wietse, would you accept such addition ?

Emmanuel.

Re: TLS client certificates and auth external

By MailingListe at 04/18/2019 - 06:05

Zitat von Emmanuel Fusté <emmanuel. ... at external dot thalesgroup.com>:

I tested this with a patched postfix for my usage scenario (relaying
based on validated CN) but i fail to get it work. Note that i don't
need a sasl username at all, but also tested with sasl username and
check_sasl_access.

The config basically looks like this:

smtpd_relay_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
check_sasl_access hash://etc/postfix/check_sasl_access,
defer_unauth_destination

# tested both
#smtpd_sasl_tls_ccert_username = commonName
smtpd_sasl_tls_ccert_username = relay_clientcerts_auto
#relay_clientcerts = hash://etc/postfix/relay_clientcerts
smtpd_tls_loglevel = 2
smtpd_tls_ask_ccert = yes
smtpd_sasl_auth_enable = yes

smtpd_use_tls=yes
smtpd_tls_CApath = /etc/ssl/certs

But this leads to
Apr 18 11:46:05 linux-test postfix/smtpd[4257]:
kw-tools.hq.kwsoft.de[10.1.7.15]: subject_CN=xxx.kwsoft.de,
issuer=SwissSign Server Silver CA 2014 - G22,
fingerprint=B8:D9:ED:1F:33:FE:DB:36:11:A6:D9:3F:BA:B5:1D:44,
pkey_fingerprint=43:B6:FE:07:BB:2E:BF:86:8A:4D:2A:DD:78:07:09:C6
Apr 18 11:46:05 linux-test postfix/smtpd[4257]: Trusted TLS connection
established from kw-tools.hq.kwsoft.de[10.1.7.15]: TLSv1.2 with cipher
ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
Apr 18 11:46:05 linux-test postfix/smtpd[4257]: NOQUEUE: reject: RCPT
from kw-tools.hq.kwsoft.de[10.1.7.15]: 454 4.7.1 < ... at kwsoft dot eu>:
Relay access denied; from=< ... at kwsoft dot de> to=< ... at kwsoft dot eu>
proto=ESMTP helo=<kw-tools>
Apr 18 11:46:05 linux-test postfix/smtpd[4257]: disconnect from
kw-tools.hq.kwsoft.de[10.1.7.15] ehlo=2 starttls=1 mail=1 rcpt=0/1
data=0/1 rset=1 quit=1 commands=6/8

What i actually need is relaying based on validated certificate CN
without forcing the client to use some form of authentication, so this
would basically mean relay_clientcerts with CN lookup key or a
relay_clientcerts_auto_cn to always skip AUTH and use the CN as
username i guess.

Any other idea?

Thanks

Andreas

Any othe idea

Re: TLS client certificates and auth external

By =?ISO-8859-1?Q?... at 04/18/2019 - 08:07

Le 18/04/2019 à 12:05, <a href="mailto: ... at kwsoft dot de"> ... at kwsoft dot de</a> a écrit :
Yes, if you don't want fingerprint to something maps, you need a
"commonName_auto" mode which rely on SASL external provider to validate
the user (provide the map of valid users) but auto triggered.
For that, you need to invoke SASL external auth directly in the smtpd
sasl glue code as it is in the processing of the AUTH verb (a simplified
single step version).
Will look at it if I have time, but I prefer to wait Viktor/Wietse
comments before.

Emmanuel.

Re: TLS client certificates and auth external

By MailingListe at 04/18/2019 - 08:42

Zitat von Emmanuel Fusté <emmanuel. ... at external dot thalesgroup.com>:
Will try that, but for our final use case we have no way fix the
fingerprint of the remote client, it can change any time. The only
thing which should stay is the CN.

Thanks, so i will wait for comment if we can include our special case also.

Andreas

Re: TLS client certificates and auth external

By Viktor Dukhovni at 03/27/2019 - 12:14

I believe you're asking Postfix to (when configured to do that)
simulate "AUTH EXTERNAL" when the client has presented a client
certificate, but proceeds from "EHLO" to "MAIL FROM" with no
intevening explicit "AUTH".

The simulated "AUTH EXTERNAL" would never "fail" (5XX), it either
yields an authenticated user or proceeds with the user unauthenticated,
and acts accordingly.

Does that sound right?

Re: TLS client certificates and auth external

By =?ISO-8859-1?Q?... at 03/27/2019 - 13:10

Le 27/03/2019 à 17:14, Viktor Dukhovni a écrit :
Emmanuel.

Re: TLS client certificates and auth external

By =?ISO-8859-1?Q?... at 04/10/2019 - 07:03

Le 27/03/2019 à 18:10, Emmanuel Fusté a écrit :
Ok, patch attached.
Need to be applied on top of Bastian one.
Work well here, thanks to the hard part done by Bastian !
Please comment.

Emmanuel.

Re: TLS client certificates and auth external

By MailingListe at 04/11/2019 - 06:09

Zitat von Emmanuel Fusté <emmanuel. ... at external dot thalesgroup.com>:

This sounds like the feature we will need. I doubt the client would be
able to do real AUTH, but we have to trust/relay based on the CN of a
validated certificate. Is there any progress merging this in the 3.5
line or do i have to poke around with patches some longer?

Thanks

Andreas

Re: TLS client certificates and auth external

By Wietse Venema at 04/11/2019 - 08:34

Yes and yes. It is ready when it is ready.

Wietser

Re: TLS client certificates and auth external

By MailingListe at 04/18/2019 - 07:09

Zitat von Wietse Venema < ... at porcupine dot org>:

What is the way to go to take part of the feature development? I looks
like we need a slight modification of the auth external as described.

Thanks

Andreas

Re: TLS client certificates and auth external

By Wietse Venema at 04/18/2019 - 12:01

Mailin glist discussions.

Eventually there will be a postfix-xxxx-nonprod release that combines
all the code (jay) and none of the guarantees (bleh).

I am not convinced that stuffing arbitrary PKI identities into a
SASL identity is necessarily a good idea. Maybe it is safer to solve
this problem without PKI-to-SASL cross-talk.

Wietse

Re: TLS client certificates and auth external

By Viktor Dukhovni at 04/18/2019 - 15:45

I would expect the mapping to be indirect. That is, a table lookup
key of either the client public key fingerprint to a SASL name (roughly
what we have now, but with an explicit RHS indicating the desired SASL
identity), or else the client's subject name in a standard (likely
RFC2254) form, again mapped to the desired identity, provided the
client certificate is from a trusted PKI issuer.

Re: TLS client certificates and auth external

By =?UTF-8?B?TWlja... at 04/19/2019 - 12:44

On 4/18/19 9:45 PM, Viktor Dukhovni wrote:
Using a name instead of cert fingerprint also requires revocation checking.

Ciao, Michael.

Re: TLS client certificates and auth external

By Wietse Venema at 04/19/2019 - 13:10

Michael Str?der:
Cert revocation is not needed, as long as there is an an explicit
mapping like:

certificate identity -> permit/etc action
certificate identity -> ersatz SASL login name

By removing such a mapping, one can 'revoke' the privileges that
were associated with the certificate.

Wietse

Re: TLS client certificates and auth external

By =?UTF-8?B?TWlja... at 04/19/2019 - 18:42

On 4/19/19 7:10 PM, Wietse Venema wrote:
If a cert's key get compromised (e.g. laptop lost/stolen) I expect the
user's cert to be revoked and a new cert to be issued for the *same*
subject name. How to deal with that without revocation check?

I think that people are asking for this feature because they just want
to issue a new cert and *not* deal with any postfix map update.

Maybe I'm missing something though.

Ciao, Michael.

Re: TLS client certificates and auth external

By Viktor Dukhovni at 04/19/2019 - 19:09

Delete the name match, and match by the key fingerprint until the old
certificate is expired. Then go back to name checks.

CRLs don't make for reliable infrastructure. My view is that, pretending
otherwise would be disservice to the Postfix user community. It is much
easier to update the Postfix tables than to provision a working CRL
infrastructure.

I have no plans to spend any time working on CRL support to Postfix.

Re: TLS client certificates and auth external

By =?UTF-8?B?TWlja... at 04/19/2019 - 19:37

On 4/20/19 1:09 AM, Viktor Dukhovni wrote:
Sounds complicated to get that right.

Fair enough. Personally I'd continue to use fingerprints anyway.

I'm rather questioning whether it's worth the effort to implement
something else.

Ciao, Michael.

Re: TLS client certificates and auth external

By Viktor Dukhovni at 04/19/2019 - 13:27

My thoughts exactly! We should probably document this:

Note: No revocation checks are performed. To revoke privileges,
remove the table entry matching a given certificate or "subject".

As for "CN" matching, I'm concerned that multiple certificates can have
the same CN, which is not required unique, especially if the certificates
have different "O" or "OU" values. What's more likely to be unique is
an rfc822Name subjectAlternative name, or the full subject DN. More
recently, we also have SmtpUTF8Mailbox:

<a href="https://tools.ietf.org/html/rfc8398#section-3" title="https://tools.ietf.org/html/rfc8398#section-3">https://tools.ietf.org/html/rfc8398#section-3</a>

So I think that more thought needs to go into what lookup key or
keys are extract from the candidate certificates. This may need
to be configurable, or we could try:

1. The full subject DN (in RFC2854 form, suitably quoted).
2. Each rfc822Name SAN.
3. Each SmtpUTF8Mailbox (note U-label domain part).

Re: TLS client certificates and auth external

By MailingListe at 04/23/2019 - 04:05

Zitat von Viktor Dukhovni <postfix- ... at dukhovni dot org>:

The multiple certificates with one common CN would be a feature in my
case. We need to relay O365 mail and don't want to open the whole IP
space used by O365 which is changing anyway. So the plan was to use
the common CN for the whole outgoing servers.

One example is:

Apr 17 17:03:45 mailin postfix/smtpd[6909]:
mail-ve1eur02lp0207.outbound.protection.outlook.com[2a01:111:f400:7e06::207]:
depth=0 verify=1 subject=/C=US/ST=Washington/L=Redmond/O=Microsoft
Corporation/CN=mail.protection.outlook.com

There are many DNS names an the full subject is also different, but to
my knowledge we always have
"CN=mail.protection.outlook.com"

The question is if the CAs check/validate the CN and protect it
against misuse.

Andreas

Re: TLS client certificates and auth external

By Wietse Venema at 04/19/2019 - 20:59

Viktor Dukhovni:
Here is a strawman user interface, similar to smtpd_milters:

smtpd_mumble_restrictions =
...
check_access { maptype:mapname, { search = rfc822name, cccert_dn } }
...

where the 'search' attribute specifies a list with one or more of
rfc822name, cccert_dn, ccert_key_fingerprint, and so on.

The check_access 'search' attribute would not need to be specific
to TLS at all; the search list could specify other things:

check_access { maptype:mapname, search=client }

which is equivalent to "check_client_access maptype:mapname".

Or we could ignore the opportunity for generalization and call
it check_tls_access.

The only real work is to implement support for a set of named
integers (internally, a vector of NAME_CODE results). The rest of
the work would be writing trivial wrappers, and documenting this.

Wietse

Re: TLS client certificates and auth external

By Wietse Venema at 04/28/2019 - 15:49

Continuing the discussion of a strawman user interface, I see some
opportunities to generalize this and to make some improvements
elsewhere in Postfix.

We start with Postfix access control based on client certificate
feartures:

smtpd_mumble_restrictions =
...
check_tls_access {
maptype:mapname,
{ search = rfc822name, subject_dn, smtputf8mailbox, ... } }
...

where the 'search' attribute specifies a list with one or more of
rfc822name, subject_dn, smtputf8mailbox, key_fingerprint, and so on.

This requires new infrastructure that converts the 'search' list
into a list of named constants (internally, a vector of NAME_CODE
results). check_tls_access is then implemented as a loop over the
internal form of the search list.

So far, so good.

Would this syntax also be useful for other Postfix features? It
would be good if it does. Here's a strawman inside a strawman.

Once the above is implemented, the same approach could be used to
improve other parts of Postfix by making existing hard-coded behavior
configurable, for example how check_client_access looks up subnet
and partial address information, or how virtual_alias_maps looks
up full and partial address forms. The examples below show the
lookup order that is currently hard-coded.

smtpd_mumble_restrictions =
...
check_client_access {
maptype:mapname,
# instead of parent, maybe use dot-parent or no parent
{ search = domain, parent, address, subnet }
}
...

virtual_alias_maps = {
hash:/etc/postfix/virtual,
{ search = full, full-noext, localpart-if-local, at-domain }
} {
other table ...
}

Ditto for canonical_maps and transport_maps.

This would be a compatibility break, because with the above, all
virtual_alias_maps searches are done on the first table before
trying the next table. One could argue that current behavior is
non-intuitive.

Another possible benefit: this syntax may be useful to support
substring queries with 'postmap -q'.

To make the main.cf configuration easier to use, the config file
parser could be modified to process '}' at the start of a line as
the continuation of the preceding line. This would be a simple change.

Wietse

Re: TLS client certificates and auth external

By John Fawcett at 05/01/2019 - 15:57

On 28/04/2019 21:49, Wietse Venema wrote:
Sounds like a good idea which should make the code more robust by
removing hard coded logic in multiple places.

If virtual_alias_maps are the only place where postfix searches for a
pattern across multiple tables before passing on to the next pattern
then it should not be too much of a surprise to bring it in line with
the rest of the lookup logic.

I guess that virtual_alias_maps configurations with multiple tables are
less common than those with a single table. However, if strong reasons
come out against the change, the search order could be configurable
either "horizontally" across multiple tables or "vertically" into single
tables. It would just mean sorting the name_code vector a different way
from the default. Though personally I would vote for the incompatible
change.

John

Re: TLS client certificates and auth external

By Viktor Dukhovni at 05/01/2019 - 16:04

As mentioned above, it is not just virtual aliases, but the proposed
compatibility break is likely what most users actually expect, and
then have to learn the actual non-intuitive behaviour.

I also would support the compatibility break. The proposed new
behaviour is more intuitive, and I think more useful. When the
first table has a matching "partial" key, and the second table has
a matching "full" key. I would still expect the first table to
win, with the second table consulted only when the first table would
yield no result on its own.

Re: TLS client certificates and auth external

By John Fawcett at 05/01/2019 - 16:45

On 01/05/2019 22:04, Viktor Dukhovni wrote:
Thanks for clarifying. I had missed that.

I can only answer for myself, but still it would be no issue even if the
search order is changed for all these because I tend to use single tables.

I do use multiple tables in local_recipient_maps but for lists it does
not make any difference to the result if the search order is changed.

John

Re: TLS client certificates and auth external

By =?ISO-8859-1?Q?... at 04/19/2019 - 05:10

Le 18/04/2019 à 21:45, Viktor Dukhovni a écrit :
Emmanuel.

Re: TLS client certificates and auth external

By MailingListe at 04/18/2019 - 14:17

Zitat von Wietse Venema < ... at porcupine dot org>:

At least in my case no SASL would be needed. For me a
relay_clientcerts able to list allowed validated CNs would be enough.
The SASL stuff will be handy for tie a "identity" to certificates and
assign additional rights/limits of course.

Andreas

Re: TLS client certificates and auth external

By Wietse Venema at 04/19/2019 - 10:30

One SASL-less option that I can think of is check_cname_access: map
the CNAME to an action. Requires that the certificate is verified.

Would that work? Thius approach avoids the mixing of PKI identities
and SASL identities.

Implementation note: this would require that check_cname_access
looks up a quoted string if the CNAME contains spaces. The postnap
command understands quoted strings as of Postfix 3.2.

Wietse

Re: TLS client certificates and auth external

By Bastian Schmidt at 01/09/2019 - 17:49

Ok, taking this over to postfix-devel.

I understand the concern of default security.
As the default smtpd_relay_restrictions are permit_my_networks,
permit_sasl_authenticated, defer_unauth_destination. Silently adding
external auth is not an option, as then verified client certs are
permitted by default due to permit_sasl_authenticated succeeding.
This means, in order to not have problems with existing configurations
allowing more access suddenly, we would need an option
smptd_tls_ccert_verified_is_sasl_authenticated or something.

I took cyrus imap server as an example for what SASL authenticated means
with a client cert. It simply uses the CN of the subject of the cert as
a username.
And one can just specify one or several CAs, which are trusted. Cyrus
also lacks support for ocsp and crls.
Exactly what cyrus imap does is what I already have implemented.

I personally don't use the fingerprint solution from postfix due to
adminstrative effort.
Thus, I have not yet implemented something like the suggested
"fingerprint to user map" but I see this fits very well to postfix's
current security design and would be willing to implement this if it
helps auth external to be integrated.

You are right the implementation is rather straight forward as SASL
libraries already suppport it.

Bastian

On 08.01.19 23:35, Viktor Dukhovni wrote:

Re: TLS client certificates and auth external

By Bastian Schmidt at 01/14/2019 - 14:13

I have reworked my implementation for SASL auth external support. I now
have a patch available that would introduce the following possibilities:

Using an option: smtpd_sasl_tls_ccert_username = commonName
After providing a verified client certificate, postfix advertises auth
external and the user can authenticate with the username being the
commonName of the certificate. This is for users having control over the
CA issuing the certificates and resembles the way cyrus imap handles the
situation.

Using an option: smtpd_sasl_tls_ccert_username = relay_clientcerts
When a client presents a certificate, where the fingerprint matches in
relay_clientcerts, the lookup value (previously unused) is used to get
the username for sasl. The client can then perform an auth external with
this username successfully. This is a solution for users, which cannot
control the CAs or do not want to trust them or cope with crls, ... It
fits in the way postfix currently handles client certificates.

Both solutions then cause permit_sasl_authenticated to succeed and the
sasl username to be set correctly.

The default for smtpd_sasl_tls_ccert_username (the empty value) or any
other value cause auth external to not be advertised and neither
succeed; the same situation as without the patch.

I would really like to get SASL auth external integrated, how can I
submit the patch for these changes? Shall I simply post it to this
mailing list?

Bastian

On 09.01.19 22:49, Bastian Schmidt wrote:

Re: TLS client certificates and auth external

By Wietse Venema at 01/14/2019 - 14:30

Bastian Schmidt:
It's probably too large for a mailing list, because it should not
only contain raw code, but also documentation (updates for proto/*
and ideally also for mantools/postlink). Please use <a href="http://www.w3.org/validator" title="www.w3.org/validator">www.w3.org/validator</a>,
spell checker, and if possible, valgrind.

You can send the code to me and Viktor. I do not expect to include
this in Postfix 3.4, as we are still racing to finish things for
Postfix 3.4, and we have limited time resources.

Wietse