On 2012-11-17 at 12:21 -0800, Todd Lyons wrote:
> Re the following bit of code (line 142) :
>
> http://git.exim.org/users/tlyons/exim.git/blob/40367a0461cd662d081991d1edf2d891695ff255:/src/src/dmarc.c#l142
>
> Jeremy and I had this conversation:
>
> <cannonball> Is this an insane way to extract the domain of the
> (first) email address from the From: header?
> <jgh_hm> it's sure a horrid layer-crossing....
> <cannonball> I'm not denying that :-/
> <jgh_hm> there may well be no better though
>
> Can anybody suggest a better way to get that to work? One that
> doesn't do so much "horrid layer crossing" ? Or is this a quite
> acceptable way of doing this? I find that hard to believe, but I'll
> take it if that's the answer.
An email address LHS can contain a $dollar, even without being in
double-quotes. So the code as written is a security hole, because the
address is injected directly into the string and is equivalent to "eval"
of untrusted text. If you use $rh_From: instead, then the expansion
only expands that $string to its value and won't recursively expand the
content.
An email address LHS can contain a colon, albeit in quotes, so the
numeric extract will fail: it's geared for things like passwd files and
doesn't use the doubling-to-escape convention. Perhaps:
${reduce{${addresses:$rh_from:}}{}{$item}}
to just take the last address. If it has to be the first, rather than
just picking one, then there are some examples from me on exim-users of
how to do this.
Exim uses expand_string() in a few places, it's not too bad, but if you
want to avoid bouncing through the layers, then look in expand.c to see
how how the functionality you want is implemented and if there's a nice
way to get it directly. [Also avoids slip-ups injecting untrusted code
directly into the evaluation language. *cough*]
If there's not, perhaps add it? "This function gets the local_part and
domain of the first address in the first From: header of the message";
between DMARC, DKIM, and other bits, I'm sure we could use it more than
once. :)
-Phil