Add client_condition to authenticators.
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Mon, 18 Jun 2007 13:57:49 +0000 (13:57 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Mon, 18 Jun 2007 13:57:49 +0000 (13:57 +0000)
13 files changed:
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/src/globals.c
src/src/structs.h
src/src/transports/smtp.c
test/confs/3455 [new file with mode: 0644]
test/confs/3465 [new file with mode: 0644]
test/log/3455 [new file with mode: 0644]
test/log/3465 [new file with mode: 0644]
test/scripts/3450-plaintext-GnuTLS/3455 [new file with mode: 0644]
test/scripts/3460-plaintext-OpenSSL/3465 [new file with mode: 0644]
test/stdout/2022
test/stdout/3407

index 6a8e4d1..cd80270 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.512 2007/06/14 14:18:19 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.513 2007/06/18 13:57:49 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -50,6 +50,13 @@ PH/03 The body_linecount and body_zerocount variables are now exported in the
 
 PH/04 Added the $dnslist_matched variable.
 
+PH/05 Unset $tls_cipher and $tls_peerdn before making a connection as a client.
+      This means they are set thereafter only if the connection becomes
+      encrypted.
+
+PH/06 Added the client_condition to authenticators so that some can be skipped
+      by clients under certain conditions.
+
 
 Exim version 4.67
 -----------------
index a630273..7e0c472 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/NewStuff,v 1.148 2007/06/14 14:18:19 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/NewStuff,v 1.149 2007/06/18 13:57:49 ph10 Exp $
 
 New Features in Exim
 --------------------
@@ -31,6 +31,18 @@ Version 4.68
     If this condition succeeds, the value in $dnslist_matched might be
     192.168.6.7 (for example).
 
+ 3. Authenticators now have a client_condition option. When Exim is running as
+    a client, it skips an authenticator whose client_condition expansion yields
+    "0", "no", or "false". This can be used, for example, to skip plain text
+    authenticators when the connection is not encrypted by a setting such as:
+
+      client_condition = ${if !eq{$tls_cipher}{}}
+
+    Note that the 4.67 documentation states that $tls_cipher contains the
+    cipher used for incoming messages. In fact, during SMTP delivery, it
+    contains the cipher used for the delivery. The same is true for
+    $tls_peerdn.
+
 
 Version 4.67
 ------------
index 7b14f7b..7d34c66 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/globals.c,v 1.73 2007/06/14 14:18:19 ph10 Exp $ */
+/* $Cambridge: exim/src/src/globals.c,v 1.74 2007/06/18 13:57:50 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -32,6 +32,8 @@ static void dummy(int x) { dummy(x-1); }
 data blocks and hence have the opt_public flag set. */
 
 optionlist optionlist_auths[] = {
+  { "client_condition", opt_stringptr | opt_public,
+                 (void *)(offsetof(auth_instance, client_condition)) },
   { "driver",        opt_stringptr | opt_public,
                  (void *)(offsetof(auth_instance, driver_name)) },
   { "public_name",   opt_stringptr | opt_public,
@@ -327,6 +329,7 @@ auth_instance auth_defaults    = {
     NULL,                      /* private options block pointer */
     NULL,                      /* driver_name */
     NULL,                      /* advertise_condition */
+    NULL,                      /* client_condition */
     NULL,                      /* public_name */
     NULL,                      /* set_id */
     NULL,                      /* server_mail_auth_condition */
index 71d9d3a..cc0e521 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/structs.h,v 1.15 2007/01/08 10:50:18 ph10 Exp $ */
+/* $Cambridge: exim/src/src/structs.h,v 1.16 2007/06/18 13:57:50 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -362,6 +362,7 @@ typedef struct auth_instance {
   void   *options_block;          /* Pointer to private options */
   uschar *driver_name;            /* Must be first */
   uschar *advertise_condition;    /* Are we going to advertise this?*/
+  uschar *client_condition;       /* Should the client try this? */
   uschar *public_name;            /* Advertised name */
   uschar *set_id;                 /* String to set as authenticated id */
   uschar *mail_auth_condition;    /* Condition for AUTH on MAIL command */
index 2fce7ba..537f32a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/transports/smtp.c,v 1.36 2007/02/08 15:16:19 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/smtp.c,v 1.37 2007/06/18 13:57:50 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -789,7 +789,8 @@ return yield;
 
 /* If continue_hostname is not null, we get here only when continuing to
 deliver down an existing channel. The channel was passed as the standard
-input.
+input. TLS is never active on a passed channel; the previous process always
+closes it down before passing the connection on.
 
 Otherwise, we have to make a connection to the remote host, and do the
 initial protocol exchange.
@@ -886,6 +887,11 @@ outblock.ptr = outbuffer;
 outblock.cmd_count = 0;
 outblock.authenticating = FALSE;
 
+/* Reset the parameters of a TLS session. */
+
+tls_cipher = NULL;
+tls_peerdn = NULL;
+
 /* If an authenticated_sender override has been specified for this transport
 instance, expand it. If the expansion is forced to fail, and there was already
 an authenticated_sender for this message, the original value will be used.
@@ -1233,14 +1239,25 @@ if (continue_hostname == NULL
       DEBUG(D_transport) debug_printf("scanning authentication mechanisms\n");
 
       /* Scan the configured authenticators looking for one which is configured
-      for use as a client and whose name matches an authentication mechanism
-      supported by the server. If one is found, attempt to authenticate by
-      calling its client function. */
+      for use as a client, which is not suppressed by client_condition, and
+      whose name matches an authentication mechanism supported by the server.
+      If one is found, attempt to authenticate by calling its client function.
+      */
 
       for (au = auths; !smtp_authenticated && au != NULL; au = au->next)
         {
         uschar *p = names;
-        if (!au->client) continue;
+        if (!au->client ||
+            (au->client_condition != NULL &&
+             !expand_check_condition(au->client_condition, au->name,
+               US"client authenticator")))
+          {
+          DEBUG(D_transport) debug_printf("skipping %s authenticator: %s\n",
+            au->name,
+            (au->client)? "client_condition is false" :
+                          "not configured as a client");
+          continue;
+          }
 
         /* Loop to scan supported server mechanisms */
 
diff --git a/test/confs/3455 b/test/confs/3455
new file mode 100644 (file)
index 0000000..274de63
--- /dev/null
@@ -0,0 +1,74 @@
+# Exim test configuration 3455
+
+HOSTS_AVOID_TLS=
+
+exim_path = EXIM_PATH
+host_lookup_order = bydns
+primary_hostname = myhost.test.ex
+rfc1413_query_timeout = 0s
+spool_directory = DIR/spool
+log_file_path = DIR/spool/log/%slog
+gecos_pattern = ""
+gecos_name = CALLER_NAME
+
+# ----- Main settings -----
+
+acl_smtp_rcpt = accept
+
+domainlist local_domains = test.ex
+
+log_selector = +smtp_no_mail
+
+queue_only = true
+
+tls_advertise_hosts = *
+tls_certificate = DIR/aux-fixed/cert1
+tls_privatekey = DIR/aux-fixed/cert1
+
+
+# ----- Authenticators -----
+
+begin authenticators
+
+plain:
+  driver = plaintext
+  public_name = PLAIN
+  server_condition = "\
+    ${if and {{eq{$2}{userx}}{eq{$3}{secret1}}}{yes}{no}}"
+  server_set_id = $2
+  client_condition = ${if !eq {$tls_cipher}{}}
+  client_send = ^userx^secret1
+
+login:
+  driver = plaintext
+  public_name = LOGIN
+  server_prompts = User Name : Password
+  server_condition = "\
+    ${if and {{eq{$auth1}{usery}}{eq{$auth2}{secret2}}}{yes}{no}}"
+  server_set_id = $auth1
+  client_send = : usery : secret2
+
+
+# ----- Routers -----
+
+begin routers
+
+r1:
+  driver = accept
+  transport = t1
+
+
+# ----- Transports -----
+
+begin transports
+
+t1:
+  driver = smtp
+  hosts = 127.0.0.1
+  port = PORT_D
+  hosts_avoid_tls = HOSTS_AVOID_TLS
+  hosts_require_auth = *
+  allow_localhost
+
+
+# End
diff --git a/test/confs/3465 b/test/confs/3465
new file mode 100644 (file)
index 0000000..adadeb0
--- /dev/null
@@ -0,0 +1,74 @@
+# Exim test configuration 3465
+
+HOSTS_AVOID_TLS=
+
+exim_path = EXIM_PATH
+host_lookup_order = bydns
+primary_hostname = myhost.test.ex
+rfc1413_query_timeout = 0s
+spool_directory = DIR/spool
+log_file_path = DIR/spool/log/%slog
+gecos_pattern = ""
+gecos_name = CALLER_NAME
+
+# ----- Main settings -----
+
+acl_smtp_rcpt = accept
+
+domainlist local_domains = test.ex
+
+log_selector = +smtp_no_mail
+
+queue_only = true
+
+tls_advertise_hosts = *
+tls_certificate = DIR/aux-fixed/cert1
+tls_privatekey = DIR/aux-fixed/cert1
+
+
+# ----- Authenticators -----
+
+begin authenticators
+
+plain:
+  driver = plaintext
+  public_name = PLAIN
+  server_condition = "\
+    ${if and {{eq{$2}{userx}}{eq{$3}{secret1}}}{yes}{no}}"
+  server_set_id = $2
+  client_condition = ${if !eq {$tls_cipher}{}}
+  client_send = ^userx^secret1
+
+login:
+  driver = plaintext
+  public_name = LOGIN
+  server_prompts = User Name : Password
+  server_condition = "\
+    ${if and {{eq{$auth1}{usery}}{eq{$auth2}{secret2}}}{yes}{no}}"
+  server_set_id = $auth1
+  client_send = : usery : secret2
+
+
+# ----- Routers -----
+
+begin routers
+
+r1:
+  driver = accept
+  transport = t1
+
+
+# ----- Transports -----
+
+begin transports
+
+t1:
+  driver = smtp
+  hosts = 127.0.0.1
+  port = PORT_D
+  hosts_avoid_tls = HOSTS_AVOID_TLS
+  hosts_require_auth = *
+  allow_localhost
+
+
+# End
diff --git a/test/log/3455 b/test/log/3455
new file mode 100644 (file)
index 0000000..7e58536
--- /dev/null
@@ -0,0 +1,12 @@
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex H=localhost (myhost.test.ex) [127.0.0.1] P=esmtpsa X=TLS-1.0:RSA_AES_256_CBC_SHA1:32 A=plain:userx S=sss id=E10HmaX-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmaX-0005vi-00 => userz@test.ex R=r1 T=t1 H=127.0.0.1 [127.0.0.1] X=TLS-1.0:RSA_AES_256_CBC_SHA1:32
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp -qf
+1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex H=localhost (myhost.test.ex) [127.0.0.1] P=esmtpa A=login:usery S=sss id=E10HmaX-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmaY-0005vi-00 => userz@test.ex R=r1 T=t1 H=127.0.0.1 [127.0.0.1]
+1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp -qf
diff --git a/test/log/3465 b/test/log/3465
new file mode 100644 (file)
index 0000000..2316368
--- /dev/null
@@ -0,0 +1,12 @@
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex H=localhost (myhost.test.ex) [127.0.0.1] P=esmtpsa X=TLSv1:AES256-SHA:256 A=plain:userx S=sss id=E10HmaX-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmaX-0005vi-00 => userz@test.ex R=r1 T=t1 H=127.0.0.1 [127.0.0.1] X=TLSv1:AES256-SHA:256
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp -qf
+1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex H=localhost (myhost.test.ex) [127.0.0.1] P=esmtpa A=login:usery S=sss id=E10HmaX-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmaY-0005vi-00 => userz@test.ex R=r1 T=t1 H=127.0.0.1 [127.0.0.1]
+1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp -qf
diff --git a/test/scripts/3450-plaintext-GnuTLS/3455 b/test/scripts/3450-plaintext-GnuTLS/3455
new file mode 100644 (file)
index 0000000..52a93b5
--- /dev/null
@@ -0,0 +1,12 @@
+# TLS (client: test for encrypted before authenticating)
+exim -DSERVER=server -bd -oX PORT_D
+****
+exim userz@test.ex
+Message 1.
+****
+exim -qf
+****
+exim -qf -DHOSTS_AVOID_TLS=*
+****
+killdaemon
+no_msglog_check
diff --git a/test/scripts/3460-plaintext-OpenSSL/3465 b/test/scripts/3460-plaintext-OpenSSL/3465
new file mode 100644 (file)
index 0000000..52a93b5
--- /dev/null
@@ -0,0 +1,12 @@
+# TLS (client: test for encrypted before authenticating)
+exim -DSERVER=server -bd -oX PORT_D
+****
+exim userz@test.ex
+Message 1.
+****
+exim -qf
+****
+exim -qf -DHOSTS_AVOID_TLS=*
+****
+killdaemon
+no_msglog_check
index 4630f08..b2f4a14 100644 (file)
@@ -21,7 +21,7 @@ Succeeded in starting TLS
 ??? 214-
 <<< 214-Commands supported:
 ??? 214
-<<< 214 AUTH STARTTLS HELO EHLO MAIL RCPT DATA NOOP QUIT RSET HELP
+<<< 214 AUTH HELO EHLO MAIL RCPT DATA NOOP QUIT RSET HELP
 >>> quit
 ??? 221
 <<< 221 myhost.test.ex closing connection
index 274c68c..73fe544 100644 (file)
@@ -1,5 +1,6 @@
 
 a1 authenticator:
+client_condition = 
 driver = plaintext
 public_name = PLAIN
 server_advertise_condition = 
@@ -12,6 +13,7 @@ client_send =
 server_prompts = 
 
 a2 authenticator:
+client_condition = 
 driver = plaintext
 public_name = PLAIN
 server_advertise_condition = 
@@ -24,6 +26,7 @@ client_send =
 server_prompts = 
 
 a3 authenticator:
+client_condition = 
 driver = plaintext
 public_name = LOGIN
 server_advertise_condition = 
@@ -36,6 +39,7 @@ client_send =
 server_prompts = 
 
 a4 authenticator:
+client_condition = 
 driver = plaintext
 public_name = LOGIN
 server_advertise_condition =