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 <[email protected]> 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 <[email protected]> > 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 <[email protected]> >> 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 --------> [email protected] <-------- >>> 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 [email protected] 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 -- ## List details at https://lists.exim.org/mailman/listinfo/exim-users ## Exim details at http://www.exim.org/ ## Please use the Wiki with this list - http://wiki.exim.org/
