Re: [exim] De-tainting with ${sg} expansion

Top Page
Delete this message
Reply to this message
Author: Jeremy Harris
Date:  
To: exim-users
Subject: Re: [exim] De-tainting with ${sg} expansion
On 27/07/2020 19:45, Jamie Barnes via Exim-users wrote:> I've been avoiding check_local_user (since it tries to chdir into home directories that the exim user has no access to), so I don't think I have access to $local_part_data (as nothing populates it).
Not so. Any lookup done by a local_parts= condition on a router
also sets it.

You didn't show the routers calling these transports.

> in need of an alternative for the following two transports, where I need to be able to store *any* received mail (not handled by earlier routers/transports)


Transports are only run when called by a router...

> local_delivery:
>   driver                        = appendfile
>   file                          = ${if or{{bool{$acl_m_localdiscard}}           \
>                                           {bool{${lookup{$local_part}           \
>                                                         lsearch{/etc/passwd}    \
>                                                         {no}                    \
>                                                         {yes}}}}}               \
>                                        {/dev/null}                              \
>                                        {/var/spool/mail/${sg{$local_part}{BADFILECHARS}{_}}}}


The discard invoked by the /dev/null choice could be done by
a router (redirect, to :blackhole:). Doing that would simplify this to

file = /var/spool/mail/${sg{$local_part}{BADFILECHARS}{_}}

... and then we can detaint easily with a lookup rather than the ${sg}

file = /var/spool/mail/${lookup{$local_part}lsearch,ret=key{/etc/passwd}}

(whether you need any further cleaning depends on your policies on username
creation).

Depending on the router calling this transport, you might be able to do the
lookup there, populating $local_part_data for use here.

>   user                          = ${if or{{bool{$acl_m_localdiscard}}           \
>                                           {eqi {$local_part}{root}}             \
>                                           {bool{${lookup{$local_part}           \
>                                                          lsearch{/etc/passwd}   \
>                                                          {no}                   \
>                                                          {yes}}}}}              \
>                                        {mail}                                   \
>                                        {$local_part}}


This looks like it uses the same lookup or value as the file= option.


> local_unhandled:
>   driver                        = appendfile
>   create_directory              = yes
>   directory                     = /var/spool/exim/unhandled/\
>                                   ${sg{$domain}{BADFILECHARS}{_}}/\
>                                   ${sg{$local_part}{BADFILECHARS}{_}}/\
>                                   $tod_logfile


This transport is much harder to deal with. Currently you have to use
one of the gross hacks presented as a get-out-of-jail-free, to
obtain untainted strings for that path. I hate them, but there were
always going to be ways for shooting oneself in the foot.

I fully expect them to be cargo-culted, probably via serverfault.

Hint: Use a lookup which matches anything, and returns the key.



I'm not happy with the situation either - but I've not been able to
think of a principled way of dealing with it. I do not regard the
above hack as principled because there are zero limits on it.

> Is ${sg} not a suitable expansion to de-taint $local_part or $domain?


No - because there are no limits on it, and I see no way for Exim
to interpret the replacement pattern in a $(sg) to infer useful limits.



Possibly some form of operator which had the semantics of
"anything below this given path is fair game" would work. But it
could not be a general de-tainting string expansion, because taint
not only prevents use as a file path but also prevents further
expansion.
--
Cheers,
Jeremy