Make server prompts available in $auth<n> when plaintext is running as a
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Thu, 23 Feb 2006 12:41:22 +0000 (12:41 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Thu, 23 Feb 2006 12:41:22 +0000 (12:41 +0000)
client.

17 files changed:
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
doc/doc-txt/OptionLists.txt
src/ACKNOWLEDGMENTS
src/src/auths/README
src/src/auths/cram_md5.c
src/src/auths/plaintext.c
src/src/auths/plaintext.h
src/src/auths/spa.c
src/src/transports/smtp.c
test/confs/3401
test/confs/3404
test/log/3401
test/scripts/3400-plaintext/3401
test/scripts/3400-plaintext/3404
test/stdout/3401
test/stdout/3407

index 905e8d046dda83423c20fc693a8c6c0db07a0bb4..45ea2866d3e10e23fb80e6d997a28baae5dc5bc4 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.312 2006/02/22 15:10:28 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.313 2006/02/23 12:41:22 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -227,6 +227,15 @@ PH/43 If retry_interval_max is set greater than 24 hours, it is quietly reset
 
 PH/44 Added STRIP_COMMAND=/usr/bin/strip to the FreeBSD Makefile.
 
+PH/45 When the plaintext authenticator is running as a client, the server's
+      challenges are checked to ensure they are valid base64 strings. By
+      default, the authentication attempt is cancelled if an invalid string is
+      received. Setting client_ignore_invalid_base64 true ignores these errors.
+      The decoded challenge strings are now placed in $auth1, $auth2, etc. as
+      they are received. Thus, the responses can be made to depend on the
+      challenges. If an invalid string is ignored, an empty string is placed in
+      the variable.
+
 
 Exim version 4.60
 -----------------
index 14e08ee7893053e850a6f17abe2389d7bd3632fc..c807d931be51ca3f8d883fce01eec76a9c3b6424 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/NewStuff,v 1.89 2006/02/22 15:08:20 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/NewStuff,v 1.90 2006/02/23 12:41:22 ph10 Exp $
 
 New Features in Exim
 --------------------
@@ -74,6 +74,19 @@ PH/11 If retry_interval_max is set greater than 24 hours, it is quietly reset
       and H retry rules, and it seems reasonable to require a retry at least
       once a day.
 
+PH/12 When the plaintext authenticator is running as a client, the server
+      challenges are now checked to ensure they are valid base64 strings. The
+      default action on failure is to abort the authentication. However, if
+      client_ignore_invalid_base64 is set true, invalid responses are ignored.
+
+PH/13 When the plaintext authenticator is running as a client, the challenges
+      from the server are placed in $auth1, $auth2, etc. as they are received.
+      Thus, the challege that is received in response to sending the first
+      string (with the AUTH command) can be used in the expansion of the second
+      string, and so on. Currently, up to 3 challenge strings are available in
+      this way. If an invalid base64 string is received when client_ignore_
+      invalid_base64 is set, an empty string is put in the $auth<n> variable.
+
 
 Version 4.60
 ------------
index 17627e41c1bca230fa2ede3a930fbc2ca60076ab..5e5815b421440bcc423f315ebf312989e9c317ce 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/OptionLists.txt,v 1.17 2006/02/20 16:31:48 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/OptionLists.txt,v 1.18 2006/02/23 12:41:22 ph10 Exp $
 
 LISTS OF EXIM OPTIONS
 ---------------------
@@ -11,7 +11,7 @@ This file contains complete lists of four kinds of Exim option:
   4. Those that can appear in the build time configuration for the Exim monitor
      (Local/eximon.conf).
 
-This file was last updated for Exim release 4.60.
+This file was last updated for Exim release 4.61.
 
 
 1. RUN TIME OPTIONS
@@ -124,6 +124,7 @@ check_spool_space                    integer         0             main
 check_string                         string          "From "       appendfile        3.03
                                                      unset         pipe              3.03
 check_srv                            string*         unset         dnslookup         4.31
+client_ignore_invalid_base64         boolean         false         plaintext         4.61
 client_name                          string*         +             cram_md5          3.10
 client_secret                        string*         unset         cram_md5          3.10
 client_send                          string*         unset         plaintext         3.10
index b0285c65eadd9c48795db07aba6be0c626c60871..ce145ce21897e0087ec3523c054450757b90f9bc 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/src/ACKNOWLEDGMENTS,v 1.41 2006/02/14 15:24:10 ph10 Exp $
+$Cambridge: exim/src/ACKNOWLEDGMENTS,v 1.42 2006/02/23 12:41:22 ph10 Exp $
 
 EXIM ACKNOWLEDGEMENTS
 
@@ -20,7 +20,7 @@ relatively small patches.
 Philip Hazel
 
 Lists created: 20 November 2002
-Last updated:  13 February 2006
+Last updated:  23 February 2006
 
 
 THE OLD LIST
@@ -71,6 +71,7 @@ Claus Assmann             Example code for OpenSSL CRL support
 Ian Bell                  Analysis of a bug and an infelicity in clock tick code
                           Patch for ${quote_local_part
 Peter Benie               A number mistakes found by analysing the code
+Johannes Berg             Suggested patch for authentication client $auth<n> support
 Matt Bernstein            LMTP over socket
                           Suggested patch for dnslists '&' feature
 Mike Bethune              Help with debugging an elusive ALRM signal bug
index 9143b9e918bbeb76313151381d115e053eb49fb4..780e15dc4bc6e20c9bdd773dff663fc685487781 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/src/src/auths/README,v 1.4 2006/02/10 14:25:43 ph10 Exp $
+$Cambridge: exim/src/src/auths/README,v 1.5 2006/02/23 12:41:22 ph10 Exp $
 
 AUTHS
 
@@ -87,7 +87,8 @@ The yield of a client authentication check must be one of:
   FAIL        failed after reading a response;
               either errno is set (for timeouts, I/O failures) or
               the buffer contains the SMTP response line
-  FORCEFAIL   failed without reading a response (often "fail" in expansion)
+  CANCELLED   the client cancelled authentication (often "fail" in expansion)
+              the buffer may contain a message; if not, *buffer = 0
   ERROR       local problem (typically expansion error); message in buffer
 
 To communicate with the remote host the client should call
index 7b559876215a01f103d6a7666be8b452a8854606..26521fbe9b3cf6f3677b9d1e366eb225ad733609 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/auths/cram_md5.c,v 1.4 2006/02/10 14:25:43 ph10 Exp $ */
+/* $Cambridge: exim/src/src/auths/cram_md5.c,v 1.5 2006/02/23 12:41:22 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -250,7 +250,7 @@ auth_cram_md5_client(
   smtp_inblock *inblock,                 /* input connection */
   smtp_outblock *outblock,               /* output connection */
   int timeout,                           /* command timeout */
-  uschar *buffer,                          /* for reading response */
+  uschar *buffer,                        /* for reading response */
   int buffsize)                          /* size of buffer */
 {
 auth_cram_md5_options_block *ob =
@@ -266,7 +266,11 @@ or ERROR, as approriate. */
 
 if (secret == NULL || name == NULL)
   {
-  if (expand_string_forcedfail) return CANCELLED;
+  if (expand_string_forcedfail)
+    {
+    *buffer = 0;           /* No message */
+    return CANCELLED;
+    }
   string_format(buffer, buffsize, "expansion of \"%s\" failed in "
     "%s authenticator: %s",
     (secret == NULL)? ob->client_secret : ob->client_name,
index e5f261a161607a095209203a4a0ff5ce3912d55a..2aea4a4921538c6aa5b6d4f75ee909ffc55570ae 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/auths/plaintext.c,v 1.4 2006/02/10 14:25:43 ph10 Exp $ */
+/* $Cambridge: exim/src/src/auths/plaintext.c,v 1.5 2006/02/23 12:41:22 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -14,6 +14,8 @@
 /* Options specific to the plaintext authentication mechanism. */
 
 optionlist auth_plaintext_options[] = {
+  { "client_ignore_invalid_base64", opt_bool,
+      (void *)(offsetof(auth_plaintext_options_block, client_ignore_invalid_base64)) },
   { "client_send",        opt_stringptr,
       (void *)(offsetof(auth_plaintext_options_block, client_send)) },
   { "server_condition",   opt_stringptr,
@@ -33,7 +35,8 @@ int auth_plaintext_options_count =
 auth_plaintext_options_block auth_plaintext_option_defaults = {
   NULL,              /* server_condition */
   NULL,              /* server_prompts */
-  NULL               /* client_send */
+  NULL,              /* client_send */
+  FALSE              /* client_ignore_invalid_base64 */
 };
 
 
@@ -216,6 +219,7 @@ uschar *text = ob->client_send;
 uschar *s;
 BOOL first = TRUE;
 int sep = 0;
+int auth_var_idx = 0;
 
 /* The text is broken up into a number of different data items, which are
 sent one by one. The first one is sent with the AUTH command; the remainder are
@@ -223,8 +227,9 @@ sent in response to subsequent prompts. Each is expanded before being sent. */
 
 while ((s = string_nextinlist(&text, &sep, big_buffer, big_buffer_size)) != NULL)
   {
-  int i, len;
+  int i, len, clear_len;
   uschar *ss = expand_string(s);
+  uschar *clear;
 
   /* Forced expansion failure is not an error; authentication is abandoned. On
   all but the first string, we have to abandon the authentication attempt by
@@ -239,7 +244,11 @@ while ((s = string_nextinlist(&text, &sep, big_buffer, big_buffer_size)) != NULL
       if (smtp_write_command(outblock, FALSE, "*\r\n") >= 0)
         (void) smtp_read_response(inblock, US buffer, buffsize, '2', timeout);
       }
-    if (expand_string_forcedfail) return CANCELLED;
+    if (expand_string_forcedfail)
+      {
+      *buffer = 0;       /* No message */
+      return CANCELLED;
+      }
     string_format(buffer, buffsize, "expansion of \"%s\" failed in %s "
       "authenticator: %s", ssave, ablock->name, expand_string_message);
     return ERROR;
@@ -304,6 +313,34 @@ while ((s = string_nextinlist(&text, &sep, big_buffer, big_buffer_size)) != NULL
       "authenticator", ablock->name);
     return ERROR;
     }
+
+  /* Now that we know we'll continue, we put the received data into $auth<n>,
+  if possible. First, decode it: buffer+4 skips over the SMTP status code. */
+
+  clear_len = auth_b64decode(buffer+4, &clear);
+
+  /* If decoding failed, the default is to terminate the authentication, and
+  return FAIL, with the SMTP response still in the buffer. However, if client_
+  ignore_invalid_base64 is set, we ignore the error, and put an empty string
+  into $auth<n>. */
+
+  if (clear_len < 0)
+    {
+    uschar *save_bad = string_copy(buffer);
+    if (!ob->client_ignore_invalid_base64)
+      {
+      if (smtp_write_command(outblock, FALSE, "*\r\n") >= 0)
+        (void)smtp_read_response(inblock, US buffer, buffsize, '2', timeout);
+      string_format(buffer, buffsize, "Invalid base64 string in server "
+        "response \"%s\"", save_bad);
+      return CANCELLED;
+      }
+    clear = US"";
+    clear_len = 0;
+    }
+
+  if (auth_var_idx < AUTH_VARS)
+    auth_vars[auth_var_idx++] = string_copy(clear);
   }
 
 /* Control should never actually get here. */
index 46983d044c7590bfdbb80eeec743a4d09943a35d..7499a01d81fccc1fc2b08a25c82afe13e277cc17 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/auths/plaintext.h,v 1.3 2006/02/07 11:19:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/auths/plaintext.h,v 1.4 2006/02/23 12:41:22 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -13,6 +13,7 @@ typedef struct {
   uschar *server_condition;
   uschar *server_prompts;
   uschar *client_send;
+  BOOL    client_ignore_invalid_base64;
 } auth_plaintext_options_block;
 
 /* Data for reading the private options. */
index 264887607c49047651c065c747f609fc3f3ed80d..3fd4bde6a11906a8953a4a42abfad14b529c55ef 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/auths/spa.c,v 1.6 2006/02/10 14:25:43 ph10 Exp $ */
+/* $Cambridge: exim/src/src/auths/spa.c,v 1.7 2006/02/23 12:41:22 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -263,6 +263,8 @@ auth_spa_client(
 
        /* Code added by PH to expand the options */
 
+       *buffer = 0;    /* Default no message when cancelled */
+
        username = CS expand_string(ob->spa_username);
        if (username == NULL)
          {
index 3c915a4e1df5704f6812ae3a800a8c2ee882a139..93cbd221f425385828f56de3144cf48618786865 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/transports/smtp.c,v 1.21 2006/02/21 16:24:20 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/smtp.c,v 1.22 2006/02/23 12:41:23 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -1211,9 +1211,14 @@ if (continue_hostname == NULL
             /* Failure by some other means. In effect, the authenticator
             decided it wasn't prepared to handle this case. Typically this
             is the result of "fail" in an expansion string. Do we need to
-            log anything here? */
+            log anything here? Feb 2006: a message is now put in the buffer
+            if logging is required. */
 
             case CANCELLED:
+            if (*buffer != 0)
+              log_write(0, LOG_MAIN, "%s authenticator cancelled "
+                "authentication H=%s [%s] %s", au->name, host->name,
+                host->address, buffer);
             break;
 
             /* Internal problem, message in buffer. */
index d2cf9c97299b7a74e43689c5121183ce132a9e63..6406e3178c107ddb23d4f256e7b229c1af395e7f 100644 (file)
@@ -28,6 +28,11 @@ plain:
   public_name = PLAIN
   client_send = ^userx^secret
 
+xlogin:
+  driver = plaintext
+  public_name = XLOGIN
+  client_send = : $auth1 : $auth1+$auth2
+
 
 # ----- Routers -----
 
index afff4bf7320e471048666a2ef8e7a5f24b380855..dc556e961af7c047586b087d56da95fc84a7a22e 100644 (file)
@@ -27,6 +27,7 @@ login:
   driver = plaintext
   public_name = LOGIN
   client_send = :userx:secret
+  client_ignore_invalid_base64
 
 
 # ----- Routers -----
index dad29127a3a90287d8030d2c0b545864907e2d71..30e4b45bcb2bd843b7bd7b77fa8adf52a32078ac 100644 (file)
 1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
 1999-03-02 09:44:33 10HmbF-0005vi-00 => forcesender@domain.com R=try T=smtp_try H=127.0.0.1 [127.0.0.1]
 1999-03-02 09:44:33 10HmbF-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbG-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmbG-0005vi-00 login authenticator cancelled authentication H=127.0.0.1 [127.0.0.1] Invalid base64 string in server response "334 User?"
+1999-03-02 09:44:33 10HmbG-0005vi-00 ** userx@domain.com R=try T=smtp_try: SMTP error from remote mail server after MAIL FROM:<CALLER@myhost.test.ex>: host 127.0.0.1 [127.0.0.1]: 550 Not now
+1999-03-02 09:44:33 10HmbH-0005vi-00 <= <> R=10HmbG-0005vi-00 U=EXIMUSER P=local S=sss
+1999-03-02 09:44:33 10HmbH-0005vi-00 ** CALLER@myhost.test.ex: Unrouteable address
+1999-03-02 09:44:33 10HmbH-0005vi-00 Frozen (delivery error message)
+1999-03-02 09:44:33 10HmbG-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbI-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmbI-0005vi-00 => userx@domain.com R=try T=smtp_try H=127.0.0.1 [127.0.0.1]
+1999-03-02 09:44:33 10HmbI-0005vi-00 Completed
index b3e7c6a0a6834e13db79a1243c64d20ff9054420..590ae4333abb752acf5093bb4b28492815c24cba 100644 (file)
@@ -138,4 +138,50 @@ QUIT
 exim -odi forcesender@domain.com
 .
 ****
+# Bad basd64 from server; client aborts
+server PORT_S
+220 ESMTP
+EHLO
+250-OK
+250-HELP
+250 AUTH LOGIN
+AUTH LOGIN
+334 User?
+*
+501 Authentication cancelled
+MAIL FROM:
+550 Not now
+QUIT
+250 OK
+****
+exim -odi userx@domain.com
+.
+****
+# Test the server challenges in $auth<n>
+server PORT_S
+220 ESMTP
+EHLO
+250-OK
+250-HELP
+250 AUTH XLOGIN
+AUTH XLOGIN
+334 Y2hhbGxlbmdlLTE=
+Y2hhbGxlbmdlLTE=
+334 YW5vdGhlcm9uZQ==
+Y2hhbGxlbmdlLTErYW5vdGhlcm9uZQ==
+235 Authentication successful
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 Recipient OK
+DATA
+354 Send data
+.
+250 OK
+QUIT
+250 OK
+****
+exim -odi userx@domain.com
+.
+****
 no_msglog_check
index 98f737eac9af54172e3091efc0682d3f5787bd59..6f67b8512cebd876ef0a749072e155b2bbcf6868 100644 (file)
@@ -45,6 +45,8 @@ QUIT
 exim -v -oMas xxx@yyy -oMai zzz -odi userx@domain.com
 .
 ****
+# The server prompts sent here are not b64 encoded; hence they test
+# client_ignore_invalid_base64.
 server PORT_S
 220 ESMTP
 EHLO
index fdaf26cd6e8b0dd420fc12851fb5386837aff770..fda6814c59f20045bf3df23e2f330ee9cf163cfa 100644 (file)
@@ -150,3 +150,51 @@ Date: Tue, 2 Mar 1999 09:44:33 +0000
 QUIT
 250 OK
 End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 ESMTP
+EHLO myhost.test.ex
+250-OK
+250-HELP
+250 AUTH LOGIN
+AUTH LOGIN
+334 User?
+*
+501 Authentication cancelled
+MAIL FROM:<CALLER@myhost.test.ex>
+550 Not now
+QUIT
+250 OK
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 ESMTP
+EHLO myhost.test.ex
+250-OK
+250-HELP
+250 AUTH XLOGIN
+AUTH XLOGIN
+334 Y2hhbGxlbmdlLTE=
+Y2hhbGxlbmdlLTE=
+334 YW5vdGhlcm9uZQ==
+Y2hhbGxlbmdlLTErYW5vdGhlcm9uZQ==
+235 Authentication successful
+MAIL FROM:<CALLER@myhost.test.ex> AUTH=CALLER@myhost.test.ex
+250 Sender OK
+RCPT TO:<userx@domain.com>
+250 Recipient OK
+DATA
+354 Send data
+Received: from CALLER by myhost.test.ex with local (Exim x.yz)
+       (envelope-from <CALLER@myhost.test.ex>)
+       id 10HmbI-0005vi-00
+       for userx@domain.com; Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmbI-0005vi-00@myhost.test.ex>
+From: CALLER_NAME <CALLER@myhost.test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+.
+250 OK
+QUIT
+250 OK
+End of script
index 3888ec9ed915740e20231c6d8c95d90ca145ac45..d08999e28fc5520f46fe900a3486ca1c595b89cf 100644 (file)
@@ -6,6 +6,7 @@ server_advertise_condition =
 server_debug_print = 
 server_mail_auth_condition = 
 server_set_id = 
+no_client_ignore_invalid_base64
 client_send = 
 server_condition = xxx
 server_prompts = 
@@ -17,6 +18,7 @@ server_advertise_condition =
 server_debug_print = 
 server_mail_auth_condition = 
 server_set_id = 
+no_client_ignore_invalid_base64
 client_send = 
 server_condition = 
 server_prompts = 
@@ -28,6 +30,7 @@ server_advertise_condition =
 server_debug_print = 
 server_mail_auth_condition = 
 server_set_id = 
+no_client_ignore_invalid_base64
 client_send = 
 server_condition = 
 server_prompts = 
@@ -39,6 +42,7 @@ server_advertise_condition =
 server_debug_print = 
 server_mail_auth_condition = 
 server_set_id = 
+no_client_ignore_invalid_base64
 client_send = 
 server_condition = 
 server_prompts =