Re: [exim] Signing messages with DKIM in SMTP transport

Top Page
Delete this message
Reply to this message
Author: Mike Brudenell
Date:  
To: Exim Users
Subject: Re: [exim] Signing messages with DKIM in SMTP transport
Doh! Over the weekend I realised that my regexp doesn't handle the optional
CFWS comment text that can precede the authserv-id, and that CFWS is
non-trivial as it can be a run of characters, a quoted string or (possibly
nested) comments.

Does anyone have an ACL they'd be willing to share to deal with detecting
and removing your 'own' Authentication-Results headers when received from
untrusted sources?

With many thanks!
Mike B-)

On 22 January 2016 at 17:39, Mike Brudenell <mike.brudenell@???>
wrote:

> Dear all,
>
> I'm almost there with DKIM signing (Yay!)…
>
> The last step is to remove any "Authentication-Results:" headers from
> incoming messages arriving from untrusted sources when the header's
> AuthservId matches ours (york.ac.uk)
>
> In my ACLs I have a *warn* verb that:
>
>    1. triggers for sending hosts not in our +relay_from_hosts list,
>    2. extracts the AuthservId from the Authentication-Results header,
>    3. checks this value in a file holding AuthServIds we use when
>    signing, and
>    4. if it's found removes the header.

>
> It looks like this:
>
> warn    message       = Removing Authentication-Results header from
> incoming message via [$sender_host_address]
>         ! hosts       = +relay_from_hosts
>         set acl_m_authserv_id = ${if match {$h_Authentication-Results:} \
>                                            {\N^\s*([^"][^
> ;]*|".*?(?<!\\)")\N} \
>                                            {${sg {$1} {\N^"(.*)"$\N}
> {\$1}}} }
>         logwrite      = Found Authentication-Results header with
> authserv_id "$acl_m_authserv_id"
>         condition     = ${if bool_lax {${lookup {$acl_m_authserv_id}
> lsearch {/etc/exim4/cfg.d/dkim-signing-selectors}}}}
>         logwrite      = Matched authserv_id "$acl_m_authserv_id" in
> dkim-signing-selectors list! -- Removing header
>         remove_header = Authentication-Results

>
> This seems to be working, but I'm a little unsure of the rexexp that
> extracts the AuthservId from the header and would really appreciate someone
> seeing if they think it's right!
>
> \N^\s*([^"][^ ;]*|".*?(?<!\\)")\N
>
>
> I reckon this should match:
>
>    - A run of zero or more whitespace characters at the start of the
>    header's value (I'm not sure whether this is necessary: I have a feeling
>    Exim trims these?), followed by *either*
>       - A *token*: A character that isn't a ", zero or more characters
>       that aren't either whitespace or a semi-colon *OR*
>       - A *quoted-string*: A " character followed by a minimal run of
>       characters up to a " character not preceded by a \ escape.

>
> Basically I'm trying to match and remember the *authserv-id* of the
> Authentication-Results header as defined in section 2.2 of RFC 7001
> <https://tools.ietf.org/html/rfc7001#section-2.2>.
>
> Does what I have look right?
> Do you have a better pattern in your DKIM setup?
> Or a better way of removing the Authentication-Results header *if and
> only if* it's from an untrusted source *and* is using one of your
> AuthservIDs?
>
> Cheers,
> Mike B-)
>
> On 19 January 2016 at 17:48, Mike Brudenell <mike.brudenell@???>
> wrote:
>
>> AARGHH!!!!
>>
>> Looks like it was a horrible combination of:
>>
>>    - a typo in the name of the key file (so Exim couldn't find it so
>>    wasn't signing), and

>>
>>    - it appears the debug_print gets actioned before the dkim_domain and
>>    dkim_selector options, meaning it's before the variables get their values
>>    assigned.

>>
>> Groan! At least I can go home happy now though.
>>
>> Cheers,
>> Mike B-)
>>
>> PS: Jeremy… I'm guessing the "should" should be a "can"?
>> (But not a can-can, of course. 💃💃💃)
>>
>>
>> On 19 January 2016 at 17:25, Mike Brudenell <mike.brudenell@???>
>> wrote:
>>
>>> Hi, all -
>>>
>>> I'm sure I must be missing something obvious, but it's defeating me…
>>>
>>> I'm experimenting on a test server, trying to add DKIM signing to
>>> messages going out through a transport named remote_smtp_dkim. That
>>> transport looks like this:
>>>
>>> remote_smtp_dkim:
>>>   driver = smtp
>>>   dkim_domain       = york.ac.uk
>>>   dkim_selector     = 20160118
>>>   debug_print       = remote_smtp_dkim : '$dkim_domain' :
>>> '$dkim_selector' : '/etc/exim4/dkim/$dkim_domain-$dkim_selector.pem'
>>>   dkim_private_key  = ${if
>>> exists{/etc/exim4/dkim/$dkim_domain-$dkim_selector.pem} \

>>>
>>>  {/etc/exim4/dkim/$dkim_domain-$dkim_selector.pem}}
>>>   dkim_canon        = relaxed
>>>   dkim_strict       = false

>>>
>>> (It'll get fancier over time; I'm just trying to get even one message
>>> signed to start with!)
>>>
>>> Sending a message through does not sign it. (And yes, my routers call
>>> this transport! :-)
>>>
>>> Running Exim in Debug mode (with "-d -bd" on the command line) and using
>>> telnet to construct a message through it shows this logging, which includes
>>> the output from the debug_print directive…
>>>
>>> 25638 >>>>>>>>>>>>>>>> Remote deliveries >>>>>>>>>>>>>>>>
>>> 25638 --------> testaddress@??? <--------
>>> 25638 search_tidyup called
>>> 25638 set_process_info: 25638 delivering 1aLZr4-0006fR-7X: waiting for a
>>> remote delivery subprocess to finish
>>> 25638 selecting on subprocess pipes
>>> 25640 changed uid/gid: remote delivery to testaddress@??? with
>>> transport=remote_smtp_dkim
>>> 25640 uid=110 gid=118 pid=25640
>>> 25640 auxiliary group list: <none>
>>> 25640 set_process_info: 25640 delivering 1aLZr4-0006fR-7X using
>>> remote_smtp_dkim
>>> 25640 remote_smtp_dkim : '' : '' : '/etc/exim4/dkim/-.pem'
>>> 25640 remote_smtp_dkim transport entered
>>> …
>>>
>>> Note that where I use debug_print to output the values of $dkim_domain
>>> and $dkim_selector I'm getting empty strings which, coupled with the
>>> resulting non-existent filename, leads to the message not being signed.
>>>
>>> But the Exim Specification says for the dkim_domain and dkim_selector
>>> directives…
>>>
>>> Signing is implemented by setting private options on the SMTP transport.
>>> These options take (expandable) strings as arguments.
>>>
>>> dkim_domain
>>>
>>> MANDATORY: The domain you want to sign with. The result of this expanded
>>> option is put into the $dkim_domain expansion variable.
>>>
>>> dkim_selector
>>>
>>> MANDATORY: This sets the key selector string. You can use the $dkim_domain
>>> expansion variable to look up a matching selector. The result is put in
>>> the expansion variable $dkim_selector which should be used in the dkim_private_key
>>> option along with $dkim_domain.
>>>
>>> From which I'm expecting the values I set using the options within the
>>> remote_smtp_dkim transport to be available within the matching variables.
>>> But they're not!
>>>
>>> What am I missing?
>>>
>>> Cheers,
>>> Mike B-)
>>>
>>> --
>>> Systems Administrator & Change Manager
>>> IT Services, University of York, Heslington, York YO10 5DD, UK
>>> Tel: +44-(0)1904-323811
>>>
>>> Web: www.york.ac.uk/it-services
>>> Disclaimer: www.york.ac.uk/docs/disclaimer/email.htm
>>>
>>
>>
>>
>> --
>> Systems Administrator & Change Manager
>> IT Services, University of York, Heslington, York YO10 5DD, UK
>> Tel: +44-(0)1904-323811
>>
>> Web: www.york.ac.uk/it-services
>> Disclaimer: www.york.ac.uk/docs/disclaimer/email.htm
>>
>
>
>
> --
> Systems Administrator & Change Manager
> IT Services, University of York, Heslington, York YO10 5DD, UK
> Tel: +44-(0)1904-323811
>
> Web: www.york.ac.uk/it-services
> Disclaimer: www.york.ac.uk/docs/disclaimer/email.htm
>




--
Systems Administrator & Change Manager
IT Services, University of York, Heslington, York YO10 5DD, UK
Tel: +44-(0)1904-323811

Web: www.york.ac.uk/it-services
Disclaimer: www.york.ac.uk/docs/disclaimer/email.htm