Event for auth fail
authorJeremy Harris <jgh146exb@wizmail.org>
Tue, 19 Jul 2022 22:37:27 +0000 (23:37 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Tue, 19 Jul 2022 22:37:27 +0000 (23:37 +0100)
doc/doc-docbook/spec.xfpt
doc/doc-txt/NewStuff
src/src/smtp_in.c
test/aux-fixed/event-logger-acl
test/confs/3418 [new file with mode: 0644]
test/log/3418 [new file with mode: 0644]
test/rejectlog/3418 [new file with mode: 0644]
test/scripts/3418-plaintext-event/3418 [new file with mode: 0644]
test/scripts/3418-plaintext-event/REQUIRES [new file with mode: 0644]
test/stdout/3418 [new file with mode: 0644]

index c76aceb691593b43772d0f3befd69d6d2b4b367c..935a78a39d2252b6fb9a61b499bf763575e6fb19 100644 (file)
@@ -27647,7 +27647,16 @@ no successful authentication.
 Successful authentication sets up information used by the
 &%authresults%& expansion item.
 
-
+.new
+.cindex authentication "failure event"
+If an authenticator is run and does not succeed,
+an event (see &<<CHAPevents>>&) of type "auth:fail" is raised.
+While the event is being processed the variables
+&$sender_host_authenticated$& (with the authenticator name)
+and &$authenticated_fail_id$& (as set by the suthenticator &%server_set_id%& option)
+will be valid.
+See <<CHAPevents>> for details on events.
+.wen
 
 
 .section "Testing server authentication" "SECID169"
@@ -42701,6 +42710,7 @@ expansion must check this, as it will be called for every possible event type.
 
 The current list of events is:
 .itable all 0 0 4 25* left 10* center 15* center 50* left
+.row auth:fail             after    main       "per driver per authentication attempt"
 .row dane:fail              after    transport  "per connection"
 .row msg:complete           after    main       "per message"
 .row msg:defer              after    transport  "per message per delivery try"
@@ -42733,6 +42743,7 @@ should define the event action.
 An additional variable, &$event_data$&, is filled with information varying
 with the event type:
 .itable all 0 0 2 20* left 80* left
+.row auth:fail           "smtp response"
 .row dane:fail            "failure reason"
 .row msg:defer            "error string"
 .row msg:delivery         "smtp confirmation message"
index 807d9e43439011ef710694c1c515221d563d738b..bd7f02cfaf3415032b7f033c4dbb07c1acdaf7e9 100644 (file)
@@ -11,6 +11,8 @@ Version 4.97
 
  1. The expansion-test faciility (exim -be) can set variables.
 
+ 2. An event on a failing SMTP AUTH, server side.
+
 Version 4.96
 ------------
 
index edb0adfafbb68aaaac47e6020f91c4e970bd3ce8..4a5c44714fcac9735389b004485ab96269cf6060 100644 (file)
@@ -3765,7 +3765,7 @@ smtp_respond(code, len, TRUE, user_msg);
 
 
 static int
-smtp_in_auth(auth_instance *au, uschar ** s, uschar ** ss)
+smtp_in_auth(auth_instance *au, uschar ** smtp_resp, uschar ** errmsg)
 {
 const uschar *set_id = NULL;
 int rc;
@@ -3829,7 +3829,7 @@ switch(rc)
       received_protocol =
        (sender_host_address ? protocols : protocols_local)
          [pextend + pauthed + (tls_in.active.sock >= 0 ? pcrpted:0)];
-      *s = *ss = US"235 Authentication succeeded";
+      *smtp_resp = *errmsg = US"235 Authentication succeeded";
       authenticated_by = au;
       break;
       }
@@ -3842,34 +3842,34 @@ switch(rc)
 
   case DEFER:
     if (set_id) authenticated_fail_id = string_copy_perm(set_id, TRUE);
-    *s = string_sprintf("435 Unable to authenticate at present%s",
+    *smtp_resp = string_sprintf("435 Unable to authenticate at present%s",
       auth_defer_user_msg);
-    *ss = string_sprintf("435 Unable to authenticate at present%s: %s",
+    *errmsg = string_sprintf("435 Unable to authenticate at present%s: %s",
       set_id, auth_defer_msg);
     break;
 
   case BAD64:
-    *s = *ss = US"501 Invalid base64 data";
+    *smtp_resp = *errmsg = US"501 Invalid base64 data";
     break;
 
   case CANCELLED:
-    *s = *ss = US"501 Authentication cancelled";
+    *smtp_resp = *errmsg = US"501 Authentication cancelled";
     break;
 
   case UNEXPECTED:
-    *s = *ss = US"553 Initial data not expected";
+    *smtp_resp = *errmsg = US"553 Initial data not expected";
     break;
 
   case FAIL:
     if (set_id) authenticated_fail_id = string_copy_perm(set_id, TRUE);
-    *s = US"535 Incorrect authentication data";
-    *ss = string_sprintf("535 Incorrect authentication data%s", set_id);
+    *smtp_resp = US"535 Incorrect authentication data";
+    *errmsg = string_sprintf("535 Incorrect authentication data%s", set_id);
     break;
 
   default:
     if (set_id) authenticated_fail_id = string_copy_perm(set_id, TRUE);
-    *s = US"435 Internal error";
-    *ss = string_sprintf("435 Internal error%s: return %d from authentication "
+    *smtp_resp = US"435 Internal error";
+    *errmsg = string_sprintf("435 Internal error%s: return %d from authentication "
       "check", set_id, rc);
     break;
   }
@@ -4098,7 +4098,13 @@ while (done <= 0)
          if (smtp_in_auth(au, &s, &ss) == OK)
            { DEBUG(D_auth) debug_printf("tls auth succeeded\n"); }
          else
-           { DEBUG(D_auth) debug_printf("tls auth not succeeded\n"); }
+           {
+           uschar * save_name = sender_host_authenticated;
+           DEBUG(D_auth) debug_printf("tls auth not succeeded\n");
+           sender_host_authenticated = au->name;
+           (void) event_raise(event_action, US"auth:fail", s, NULL);
+           sender_host_authenticated = save_name;
+           }
          }
        break;
        }
@@ -4188,6 +4194,8 @@ while (done <= 0)
 
        {
        auth_instance * au;
+       uschar * smtp_resp, * errmsg;
+
        for (au = auths; au; au = au->next)
          if (strcmpic(s, au->public_name) == 0 && au->server &&
              (au->advertised || f.allow_auth_unadvertised))
@@ -4195,12 +4203,19 @@ while (done <= 0)
 
        if (au)
          {
-         c = smtp_in_auth(au, &s, &ss);
+         int rc = smtp_in_auth(au, &smtp_resp, &errmsg);
+
+         smtp_printf("%s\r\n", FALSE, smtp_resp);
+         if (rc != OK)
+           {
+           uschar * save_name = sender_host_authenticated;
 
-         smtp_printf("%s\r\n", FALSE, s);
-         if (c != OK)
            log_write(0, LOG_MAIN|LOG_REJECT, "%s authenticator failed for %s: %s",
-             au->name, host_and_ident(FALSE), ss);
+             au->name, host_and_ident(FALSE), errmsg);
+           sender_host_authenticated = au->name;
+           (void) event_raise(event_action, US"auth:fail", smtp_resp, NULL);
+           sender_host_authenticated = save_name;
+           }
          }
        else
          done = synprot_error(L_smtp_protocol_error, 504, NULL,
@@ -4389,7 +4404,7 @@ while (done <= 0)
 
       else
        {
-       char *ss;
+       char * ss;
        int codelen = 4;
        smtp_message_code(&smtp_code, &codelen, &user_msg, NULL, TRUE);
        s = string_sprintf("%.*s%s", codelen, smtp_code, user_msg);
index 15321724efb62f7fa442ae513186c468a536850c..cc18c0692ffa4325e2f32a8721cb3d7388252dae 100644 (file)
@@ -75,12 +75,19 @@ ev_msg:
     accept condition = ${if eq {$event_name}{msg:rcpt:host:defer}}
     accept logwrite =  UNEXPECTED $event_name
 
+ev_auth:
+    accept condition = ${if eq {$event_name}{auth:fail}}
+          logwrite = . \
+                     "auth fail" \
+                     event_data <$event_data> \
+                     sender_host_authenticated <$sender_host_authenticated> \
+                     authenticated_fail_id <$authenticated_fail_id>
+
+    accept logwrite =  UNEXPECTED $event_name
+
 logger:
     warn   logwrite = event $event_name
-    accept condition = ${if eq {tcp} {${listextract{1}{$event_name}}}}
-          acl = ev_tcp
-    accept condition = ${if eq {smtp} {${listextract{1}{$event_name}}}}
-          acl = ev_smtp
-    accept condition = ${if eq {msg} {${listextract{1}{$event_name}}}}
-          acl = ev_msg
-    accept logwrite =  UNEXPECTED $event_name
+          set acl_m1 = ${listextract{1}{$event_name}}
+    accept condition = ${if !inlist{$acl_m1}{tcp:smtp:msg:auth}}
+          logwrite =   UNEXPECTED $event_name
+    accept acl = ev_$acl_m1
diff --git a/test/confs/3418 b/test/confs/3418
new file mode 100644 (file)
index 0000000..42413b4
--- /dev/null
@@ -0,0 +1,38 @@
+# Exim test configuration 3418
+
+.include DIR/aux-var/std_conf_prefix
+
+primary_hostname = myhost.test.ex
+
+# ----- Main settings -----
+
+domainlist local_domains = test.ex : *.test.ex
+
+auth_advertise_hosts = 10.0.0.5
+trusted_users = CALLER
+
+event_action = ${acl {logger}}
+
+# ----- ACL -----
+
+begin acl
+
+.include DIR/aux-fixed/event-logger-acl
+
+
+
+# ----- Authentication -----
+
+begin authenticators
+
+testname:
+  driver = plaintext
+  public_name = mylogin
+  server_debug_print = +++MYLOGIN \$1="$1" \$2=\"$2" \$3="$3"
+  server_condition = "\
+    ${if match{$1}{^(\\\\S+)\\\\s+(\\\\S+)\\$}\
+    {${if and {{eq{$1}{userx}}{eq{$2}{secret}}}{yes}{no}}}{no}}"
+  server_set_id = $auth1
+
+
+# End
diff --git a/test/log/3418 b/test/log/3418
new file mode 100644 (file)
index 0000000..2de0ec6
--- /dev/null
@@ -0,0 +1,6 @@
+1999-03-02 09:44:33 testname authenticator failed for (testing.testing) [10.0.0.5] U=CALLER: 535 Incorrect authentication data (set_id=rx secret)
+1999-03-02 09:44:33 event auth:fail
+1999-03-02 09:44:33 . "auth fail" event_data <535 Incorrect authentication data> sender_host_authenticated <testname> authenticated_fail_id < (set_id=rx secret)>
+1999-03-02 09:44:33 testname authenticator failed for (testing.testing) [10.0.0.5] U=CALLER: 501 Invalid base64 data
+1999-03-02 09:44:33 event auth:fail
+1999-03-02 09:44:33 . "auth fail" event_data <501 Invalid base64 data> sender_host_authenticated <testname> authenticated_fail_id <>
diff --git a/test/rejectlog/3418 b/test/rejectlog/3418
new file mode 100644 (file)
index 0000000..dca3604
--- /dev/null
@@ -0,0 +1,2 @@
+1999-03-02 09:44:33 testname authenticator failed for (testing.testing) [10.0.0.5] U=CALLER: 535 Incorrect authentication data (set_id=rx secret)
+1999-03-02 09:44:33 testname authenticator failed for (testing.testing) [10.0.0.5] U=CALLER: 501 Invalid base64 data
diff --git a/test/scripts/3418-plaintext-event/3418 b/test/scripts/3418-plaintext-event/3418
new file mode 100644 (file)
index 0000000..2df7dd3
--- /dev/null
@@ -0,0 +1,17 @@
+# plaintext server fail event
+#
+# Incorrect auth
+exim -odi -bs -oMa 10.0.0.5
+ehlo testing.testing
+auth mylogin cnggc2VjcmV0
+quit
+****
+#
+# Bad base64
+exim -odi -bs -oMa 10.0.0.5
+ehlo testing.testing
+auth mylogin XNlcnggc2VjcmV0
+quit
+****
+#
+no_msglog_check
diff --git a/test/scripts/3418-plaintext-event/REQUIRES b/test/scripts/3418-plaintext-event/REQUIRES
new file mode 100644 (file)
index 0000000..2c5eb3f
--- /dev/null
@@ -0,0 +1,2 @@
+authenticator plaintext
+support Event
diff --git a/test/stdout/3418 b/test/stdout/3418
new file mode 100644 (file)
index 0000000..0ed179c
--- /dev/null
@@ -0,0 +1,18 @@
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
+250-myhost.test.ex Hello CALLER at testing.testing [10.0.0.5]\r
+250-SIZE 52428800\r
+250-8BITMIME\r
+250-PIPELINING\r
+250-AUTH MYLOGIN\r
+250 HELP\r
+535 Incorrect authentication data\r
+221 myhost.test.ex closing connection\r
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
+250-myhost.test.ex Hello CALLER at testing.testing [10.0.0.5]\r
+250-SIZE 52428800\r
+250-8BITMIME\r
+250-PIPELINING\r
+250-AUTH MYLOGIN\r
+250 HELP\r
+501 Invalid base64 data\r
+221 myhost.test.ex closing connection\r