[exim] Re: Problem with prvs functions

Top Page
Delete this message
Reply to this message
Author: Brian Candler
Date:  
To: exim-users
Subject: [exim] Re: Problem with prvs functions
On Wed, Jul 13, 2005 at 03:23:42PM +0100, Brian Candler wrote:
> OK so far - but if I break either the signature or the secret, I still get a
> validated answer:
>
> # exim -be '${prvscheck {prvs=brian/0123456789@???}{foobar}{$prvscheck_result}}'
> brian@???
>
> # exim -be '${prvscheck {prvs=brian/19844dfc9a@???}{wibble}{$prvscheck_result}}'
> brian@???
>
> Actually, according to doc/NewStuff, $prvscheck_result should either be
> empty string or "1", not an E-mail address.
>
> Am I doing something wrong, or is the doc broken, or is the code broken?


I think I can answer my own question. ${prvscheck} does not work in the same
way as other Exim expansions.

Firstly, it expands its parameter 3 *before* deciding whether the test
passed or not. Secondly, even though it doesn't allow parameter 3 to be
omitted, it treats empty-string as a special case; an empty string here
returns the contents of $prvscheck_address (the unencoded address), whether
or not the cryptographic validation passed or failed.

So:

# exim -d+expand -be '${prvscheck {prvs=brian/0123456789@???}{foobar}{ok}}'
returns 'ok', even though the crypto validation failed

# exim -d+expand -be '${prvscheck {prvs=brian/0123456789@???}{foobar}{$prvscheck_result}}'
returns the E-mail address, because $prvscheck_result is the empty string

# exim -d+expand -be '${prvscheck {prvs=brian/19844dfc9a@???}{foobar}{$prvscheck_result}}'
is the same, even though the signature is valid, because $prvscheck_result
was empty at the time the string was expanded.

So, the only way I can think of to get a sensible answer out of this is:

# exim -d+expand -be '${prvscheck {prvs=brian/19844dfc9a@???}{foobar}{0}}$prvscheck_result'

which returns "0" for failure and "01" for success (yuk).

I think it would be better if it worked like ${expand}: expand parameter 3
if success, expand parameter 4 if fail, and allow 'fail' for explicit
expansion failure in that case. I don't think there's any need to return the
decoded address in the event that cryptographic validation fails; there's
always $prvscheck_address if you need it.

Even better, make prvscheck a condition for use in ${if}, like crypteq or
match.

The patch below fixes some spelling errors in debug messages, but I don't
know enough about exim internals to make ${prvscheck} work in a more
exim-like way.

Also, I'm pretty sure the iexpire/inow logic is hosed. I think it should
check that inow lies between iexpire-7 and iexpire (modulo 1000). At the
moment, a case like
      iexpire = 900
      inow = 100
will be accepted, even though we are 200 days past the signature's expiry
date. To be fair, the BATV draft is not well-designed here.


Regards,

Brian.

--- exim-4.52/src/expand.c.orig    Fri Jul  1 12:09:15 2005
+++ exim-4.52/src/expand.c    Wed Jul 13 17:03:56 2005
@@ -3371,7 +3371,7 @@
       /* Ugliness: We want to expand parameter 1 first, then set
          up expansion variables that are used in the expansion of
          parameter 2. So we clone the string for the first
-         expansion, where we only expand paramter 1. */
+         expansion, where we only expand parameter 1. */
       uschar *s_backup = string_copy(s);


       /* Reset expansion variables */
@@ -3448,18 +3448,18 @@
           if (iexpire > inow)
             {
             prvscheck_result = US"1";
-            DEBUG(D_expand) debug_printf("prvscheck: success, $pvrs_result set to 1\n");
+            DEBUG(D_expand) debug_printf("prvscheck: success, $prvscheck_result set to 1\n");
             }
             else
             {
             prvscheck_result = NULL;
-            DEBUG(D_expand) debug_printf("prvscheck: signature expired, $pvrs_result unset\n");
+            DEBUG(D_expand) debug_printf("prvscheck: signature expired, $prvscheck_result unset\n");
             }
           }
         else
           {
           prvscheck_result = NULL;
-          DEBUG(D_expand) debug_printf("prvscheck: hash failure, $pvrs_result unset\n");
+          DEBUG(D_expand) debug_printf("prvscheck: hash failure, $prvscheck_result unset\n");
           }
       }
       else