Couldn't we have - per perhaps shouldn't we have - a "safe domain name"
function in Exim that could be used for this and elsewhere where an
untrusted domain name enters - it would:
* remove white space (tab, space, etc)
* remove non-printing chars
* remove 'quoting' and 'escaping'
* make it lower case
* only allow valid characters for a FQDN
call it something like "safe_fqdn" and then you could do:
${if
exists{/etc/mail/ssl/${safe_fqdn:tls_sni}.pem}{/etc/mail/ssl/${safe_fqdn:tls_sni}.pem}{/etc/mail/default-cert.pem}
aren't computers are supposed to be doing the work for us...?
Mike
On 10/17/2016 10:09 PM, Phil Pennock wrote:
> On 2016-10-12 at 14:50 +0200, Arkadiusz Miśkiewicz wrote:
>> Docs say that $tls_sni has raw data from client:
>>
>> "Great care should be taken to deal with matters of case, various injection
>> attacks in the string (../ or SQL), and ensuring that a valid filename can
>> always be referenced; it is important to remember that $tls_sni is arbitrary
>> unverified data provided prior to authentication."
> Someone read the text I wrote! Woohoo!
>
> (It only took a few years ...)
>
>> What is safest approach to handle $tls_sni when trying
>> to expand it to file on filesystem?
> Use a cryptographic hash for the filename. Or base64-encode it.
> Use symlinks for human-convenience names and any aliases.
>
> Your trade-offs are:
> * a cryptographically-skilled attacker might find a collision and ...
> get you to issue, to _them_ (and only them) a certificate for a known
> system, while on their side they should be looking to validate against
> something else. Woo, they just attacked themselves: on your side, you
> don't need to care.
> * A very long SNI with base64 might look up a very long filename on
> disk. Shouldn't be an issue, unless you're mass-hosting on an OS
> which only maintains dir hashing for filenames up to a certain length
> and need to accept customer-controlled SNI names.
> Of course, the systems like that, if memory serves, broke at 32
> characters long and a SHA1 hex digest is 40 characters long, so you'd
> also want to use ${substr...} to take the first N characters.
> * If you have a lot of similar names, sha1 will give you more
> readily-distinct values which you can tell apart at a glance.
>
> > ${sha1:${lc:mx.spodhuis.org}}
> F0DF49E8B2ACF84D5D290E89F9B673EF44B60E74
> > ${str2b64:${lc:mx.spodhuis.org}}
> bXguc3BvZGh1aXMub3Jn
>
> So, eg, `/etc/mail/ssl/bXguc3BvZGh1aXMub3Jn.pem` should exist for this
> approach, to issue a cert for the name `mx.spodhuis.org`.
>
>> Rule like:
>> ${if exists{/etc/mail/ssl/${tls_sni}.pem}{/etc/mail/ssl/${tls_sni}.pem}{/etc/mail/default-cert.pem}
> ${if exists{/etc/mail/ssl/${str2b64:${lc:tls_sni}}.pem}{/etc/mail/ssl/${str2b64:${lc:tls_sni}}.pem}{/etc/mail/default-cert.pem}
> OR
> ${if exists{/etc/mail/ssl/${sha1:${lc:tls_sni}}.pem}{/etc/mail/ssl/${sha1:${lc:tls_sni}}.pem}{/etc/mail/default-cert.pem}
>
> -Phil
>