summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2023-01-30 13:31:40 +0000
committerJeremy Harris <jgh146exb@wizmail.org>2023-01-30 13:34:33 +0000
commit04e5caa9a7e84b2afca642d28096d988cb6802e7 (patch)
tree47a499d034d1c66151c8d8d38ebfc12a25c00ca2
parent9ee30919f807678b0bc9f675dcfa73225b486574 (diff)
Testsuite: dovecot suthenticator testing
-rw-r--r--doc/doc-docbook/spec.xfpt10
-rw-r--r--src/src/auths/check_serv_cond.c10
-rw-r--r--src/src/auths/dovecot.c25
-rw-r--r--src/src/auths/plaintext.c6
-rw-r--r--test/aux-fixed/3550.dovecot.passwd1
-rw-r--r--test/aux-var-src/3550.dovecot.conf163
-rw-r--r--test/aux-var-src/3551.dovecot.conf164
-rw-r--r--test/confs/355068
-rw-r--r--test/confs/355169
-rw-r--r--test/log/35501
-rw-r--r--test/log/35518
-rw-r--r--test/mail/3551.userx13
-rw-r--r--test/rejectlog/35501
-rw-r--r--test/rejectlog/35515
-rwxr-xr-xtest/runtest15
-rw-r--r--test/scripts/3550-dovecot/355055
-rw-r--r--test/scripts/3550-dovecot/355180
-rw-r--r--test/scripts/3550-dovecot/REQUIRES2
-rw-r--r--test/stderr/355061
-rw-r--r--test/stderr/355120
-rw-r--r--test/stdout/355064
-rw-r--r--test/stdout/355197
22 files changed, 919 insertions, 19 deletions
diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index dc4e38c4a..fd2b47f22 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -28293,7 +28293,7 @@ Dovecot 2 POP/IMAP server, which can support a number of authentication methods.
Note that Dovecot must be configured to use auth-client not auth-userdb.
If you are using Dovecot to authenticate POP/IMAP clients, it might be helpful
to use the same mechanisms for SMTP authentication. This is a server
-authenticator only. There is only one option:
+authenticator only. There is only one non-generic option:
.option server_socket dovecot string unset
@@ -28305,6 +28305,7 @@ authenticators for different mechanisms. For example:
dovecot_plain:
driver = dovecot
public_name = PLAIN
+ server_advertise_condition = ${if def:tls_in_cipher}
server_socket = /var/run/dovecot/auth-client
server_set_id = $auth1
@@ -28314,6 +28315,13 @@ dovecot_ntlm:
server_socket = /var/run/dovecot/auth-client
server_set_id = $auth1
.endd
+
+.new
+&*Note*&: plaintext authentication methods such as PLAIN and LOGIN
+should not be advertised on cleartext SMTP connections.
+See the discussion in section &<<SECTplain_TLS>>&.
+.wen
+
If the SMTP connection is encrypted, or if &$sender_host_address$& is equal to
&$received_ip_address$& (that is, the connection is local), the &"secured"&
option is passed in the Dovecot authentication command. If, for a TLS
diff --git a/src/src/auths/check_serv_cond.c b/src/src/auths/check_serv_cond.c
index 5201d2177..1b0430ab1 100644
--- a/src/src/auths/check_serv_cond.c
+++ b/src/src/auths/check_serv_cond.c
@@ -31,9 +31,9 @@ Returns:
*/
int
-auth_check_serv_cond(auth_instance *ablock)
+auth_check_serv_cond(auth_instance * ablock)
{
- return auth_check_some_cond(ablock,
+return auth_check_some_cond(ablock,
US"server_condition", ablock->server_condition, OK);
}
@@ -58,10 +58,10 @@ Returns:
*/
int
-auth_check_some_cond(auth_instance *ablock,
- uschar *label, uschar *condition, int unset)
+auth_check_some_cond(auth_instance * ablock,
+ uschar * label, uschar * condition, int unset)
{
-uschar *cond;
+uschar * cond;
HDEBUG(D_auth)
{
diff --git a/src/src/auths/dovecot.c b/src/src/auths/dovecot.c
index ed56ab8cd..85d029c9c 100644
--- a/src/src/auths/dovecot.c
+++ b/src/src/auths/dovecot.c
@@ -97,13 +97,15 @@ static int socket_buffer_left;
enable consistency checks to be done, or anything else that needs
to be set up. */
-void auth_dovecot_init(auth_instance *ablock)
+void
+auth_dovecot_init(auth_instance * ablock)
{
-auth_dovecot_options_block *ob =
+auth_dovecot_options_block * ob =
(auth_dovecot_options_block *)(ablock->options_block);
if (!ablock->public_name) ablock->public_name = ablock->name;
if (ob->server_socket) ablock->server = TRUE;
+else DEBUG(D_auth) debug_printf("Dovecot auth driver: no server_socket for %s\n", ablock->public_name);
ablock->client = FALSE;
}
@@ -304,16 +306,14 @@ auth_defer_msg = US"authentication socket protocol error";
socket_buffer_left = 0; /* Global, used to read more than a line but return by line */
for (;;)
{
-debug_printf("%s %d\n", __FUNCTION__, __LINE__);
if (!dc_gets(buffer, sizeof(buffer), &cctx))
OUT("authentication socket read error or premature eof");
-debug_printf("%s %d\n", __FUNCTION__, __LINE__);
p = buffer + Ustrlen(buffer) - 1;
if (*p != '\n')
OUT("authentication socket protocol line too long");
*p = '\0';
- HDEBUG(D_auth) debug_printf("received: '%s'\n", buffer);
+ HDEBUG(D_auth) debug_printf(" DOVECOT<< '%s'\n", buffer);
nargs = strcut(buffer, args, nelem(args));
@@ -423,12 +423,12 @@ if ((
HDEBUG(D_auth) debug_printf("error sending auth_command: %s\n",
strerror(errno));
-HDEBUG(D_auth) debug_printf("sent: '%s'\n", auth_command);
+HDEBUG(D_auth) debug_printf(" DOVECOT>> '%s'\n", auth_command);
while (1)
{
- uschar *temp;
- uschar *auth_id_pre = NULL;
+ uschar * temp;
+ uschar * auth_id_pre = NULL;
if (!dc_gets(buffer, sizeof(buffer), &cctx))
{
@@ -437,7 +437,7 @@ while (1)
}
buffer[Ustrlen(buffer) - 1] = 0;
- HDEBUG(D_auth) debug_printf("received: '%s'\n", buffer);
+ HDEBUG(D_auth) debug_printf(" DOVECOT<< '%s'\n", buffer);
nargs = strcut(buffer, args, nelem(args));
HDEBUG(D_auth) debug_strcut(args, nargs, nelem(args));
@@ -471,6 +471,8 @@ while (1)
#endif
write(cctx.sock, temp, Ustrlen(temp))) < 0)
OUT("authentication socket write error");
+
+ HDEBUG(D_auth) debug_printf(" DOVECOT>> '%s'\n", temp);
break;
case 'F':
@@ -524,7 +526,10 @@ if (cctx.sock >= 0)
close(cctx.sock);
/* Expand server_condition as an authorization check */
-return ret == OK ? auth_check_serv_cond(ablock) : ret;
+if (ret == OK) ret = auth_check_serv_cond(ablock);
+
+HDEBUG(D_auth) debug_printf("dovecot auth ret: %s\n", rc_names[ret]);
+return ret;
}
diff --git a/src/src/auths/plaintext.c b/src/src/auths/plaintext.c
index 6692a676e..1392b369f 100644
--- a/src/src/auths/plaintext.c
+++ b/src/src/auths/plaintext.c
@@ -62,9 +62,9 @@ auth_plaintext_init(auth_instance *ablock)
{
auth_plaintext_options_block *ob =
(auth_plaintext_options_block *)(ablock->options_block);
-if (ablock->public_name == NULL) ablock->public_name = ablock->name;
-if (ablock->server_condition != NULL) ablock->server = TRUE;
-if (ob->client_send != NULL) ablock->client = TRUE;
+if (!ablock->public_name) ablock->public_name = ablock->name;
+if (ablock->server_condition) ablock->server = TRUE;
+if (ob->client_send) ablock->client = TRUE;
}
diff --git a/test/aux-fixed/3550.dovecot.passwd b/test/aux-fixed/3550.dovecot.passwd
new file mode 100644
index 000000000..6b22e3b5d
--- /dev/null
+++ b/test/aux-fixed/3550.dovecot.passwd
@@ -0,0 +1 @@
+userx:{PLAIN}secret:4242:4242::/home/user2
diff --git a/test/aux-var-src/3550.dovecot.conf b/test/aux-var-src/3550.dovecot.conf
new file mode 100644
index 000000000..df3f1d105
--- /dev/null
+++ b/test/aux-var-src/3550.dovecot.conf
@@ -0,0 +1,163 @@
+
+base_dir = DIR/tmp
+default_login_user = CALLER
+default_internal_group = CALLERGROUP
+default_internal_user = CALLER
+
+# Disabled POP, IMAP
+protocols =
+
+log_path = DIR/tmp/dovecot.log
+auth_debug = yes
+
+service auth {
+#SASL
+ unix_listener auth-client {
+ mode = 0666
+ user = CALLER
+
+ # this goes in base_dir
+ path = dovecot_auth_socket
+ }
+}
+
+
+service anvil {
+ unix_listener anvil-auth-penalty {
+ mode = 0
+ }
+}
+
+
+
+
+# /usr/share/doc/dovecot/example-config/conf.d/10-auth.conf
+##
+## Authentication processes
+##
+
+# Disable LOGIN command and all other plaintext authentications unless
+# SSL/TLS is used (LOGINDISABLED capability). Note that if the remote IP
+# matches the local IP (ie. you're connecting from the same computer), the
+# connection is considered secure and plaintext authentication is allowed.
+# See also ssl=required setting.
+disable_plaintext_auth = yes
+
+# Authentication cache size (e.g. 10M). 0 means it's disabled. Note that
+# bsdauth and PAM require cache_key to be set for caching to be used.
+#auth_cache_size = 0
+# Time to live for cached data. After TTL expires the cached record is no
+# longer used, *except* if the main database lookup returns internal failure.
+# We also try to handle password changes automatically: If user's previous
+# authentication was successful, but this one wasn't, the cache isn't used.
+# For now this works only with plaintext authentication.
+#auth_cache_ttl = 1 hour
+# TTL for negative hits (user not found, password mismatch).
+# 0 disables caching them completely.
+#auth_cache_negative_ttl = 1 hour
+auth_cache_negative_ttl = 0
+
+# Space separated list of realms for SASL authentication mechanisms that need
+# them. You can leave it empty if you don't want to support multiple realms.
+# Many clients simply use the first one listed here, so keep the default realm
+# first.
+#auth_realms =
+
+# Default realm/domain to use if none was specified. This is used for both
+# SASL realms and appending @domain to username in plaintext logins.
+#auth_default_realm =
+
+# List of allowed characters in username. If the user-given username contains
+# a character not listed in here, the login automatically fails. This is just
+# an extra check to make sure user can't exploit any potential quote escaping
+# vulnerabilities with SQL/LDAP databases. If you want to allow all characters,
+# set this value to empty.
+#auth_username_chars = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.-_@
+
+# Username character translations before it's looked up from databases. The
+# value contains series of from -> to characters. For example "#@/@" means
+# that '#' and '/' characters are translated to '@'.
+#auth_username_translation =
+
+# Username formatting before it's looked up from databases. You can use
+# the standard variables here, eg. %Lu would lowercase the username, %n would
+# drop away the domain if it was given, or "%n-AT-%d" would change the '@' into
+# "-AT-". This translation is done after auth_username_translation changes.
+#auth_username_format = %Lu
+
+# If you want to allow master users to log in by specifying the master
+# username within the normal username string (ie. not using SASL mechanism's
+# support for it), you can specify the separator character here. The format
+# is then <username><separator><master username>. UW-IMAP uses "*" as the
+# separator, so that could be a good choice.
+#auth_master_user_separator =
+
+# Username to use for users logging in with ANONYMOUS SASL mechanism
+#auth_anonymous_username = anonymous
+
+# Maximum number of dovecot-auth worker processes. They're used to execute
+# blocking passdb and userdb queries (eg. MySQL and PAM). They're
+# automatically created and destroyed as needed.
+#auth_worker_max_count = 30
+
+# Host name to use in GSSAPI principal names. The default is to use the
+# name returned by gethostname(). Use "$ALL" (with quotes) to allow all keytab
+# entries.
+#auth_gssapi_hostname =
+
+# Kerberos keytab to use for the GSSAPI mechanism. Will use the system
+# default (usually /etc/krb5.keytab) if not specified. You may need to change
+# the auth service to run as root to be able to read this file.
+#auth_krb5_keytab =
+
+# Do NTLM and GSS-SPNEGO authentication using Samba's winbind daemon and
+# ntlm_auth helper. <doc/wiki/Authentication/Mechanisms/Winbind.txt>
+#auth_use_winbind = no
+
+# Path for Samba's ntlm_auth helper binary.
+#auth_winbind_helper_path = /usr/bin/ntlm_auth
+
+# Time to delay before replying to failed authentications.
+#auth_failure_delay = 2 secs
+auth_failure_delay = 0 secs
+
+# Require a valid SSL client certificate or the authentication fails.
+#auth_ssl_require_client_cert = no
+
+# Take the username from client's SSL certificate, using
+# X509_NAME_get_text_by_NID() which returns the subject's DN's
+# CommonName.
+#auth_ssl_username_from_cert = no
+
+# Space separated list of wanted authentication mechanisms:
+# plain login digest-md5 cram-md5 ntlm rpa apop anonymous gssapi otp
+# gss-spnego
+# NOTE: See also disable_plaintext_auth setting.
+auth_mechanisms = plain login
+
+##
+## Password and user databases
+##
+
+#
+# Password database is used to verify user's password (and nothing more).
+# You can have multiple passdbs and userdbs. This is useful if you want to
+# allow both system users (/etc/passwd) and virtual users to login without
+# duplicating the system users into virtual database.
+#
+# <doc/wiki/PasswordDatabase.txt>
+#
+# User database specifies where mails are located and what user/group IDs
+# own them. For single-UID configuration use "static" userdb.
+#
+# <doc/wiki/UserDatabase.txt>
+
+passdb {
+ driver = passwd-file
+ args = DIR/aux-fixed/3550.dovecot.passwd
+}
+userdb {
+ driver = passwd-file
+ args = DIR/aux-fixed/3550.dovecot.passwd
+}
+
diff --git a/test/aux-var-src/3551.dovecot.conf b/test/aux-var-src/3551.dovecot.conf
new file mode 100644
index 000000000..2b34e3beb
--- /dev/null
+++ b/test/aux-var-src/3551.dovecot.conf
@@ -0,0 +1,164 @@
+
+base_dir = DIR/tmp
+default_login_user = CALLER
+default_internal_group = CALLERGROUP
+default_internal_user = CALLER
+
+# Disabled POP, IMAP
+protocols =
+
+log_path = DIR/tmp/dovecot.log
+auth_debug = yes
+auth_debug_passwords = yes
+
+service auth {
+#SASL
+ unix_listener auth-client {
+ mode = 0666
+ user = CALLER
+
+ # this goes in base_dir
+ path = dovecot_auth_socket
+ }
+}
+
+
+service anvil {
+ unix_listener anvil-auth-penalty {
+ mode = 0
+ }
+}
+
+
+
+
+# /usr/share/doc/dovecot/example-config/conf.d/10-auth.conf
+##
+## Authentication processes
+##
+
+# Disable LOGIN command and all other plaintext authentications unless
+# SSL/TLS is used (LOGINDISABLED capability). Note that if the remote IP
+# matches the local IP (ie. you're connecting from the same computer), the
+# connection is considered secure and plaintext authentication is allowed.
+# See also ssl=required setting.
+disable_plaintext_auth = yes
+
+# Authentication cache size (e.g. 10M). 0 means it's disabled. Note that
+# bsdauth and PAM require cache_key to be set for caching to be used.
+#auth_cache_size = 0
+# Time to live for cached data. After TTL expires the cached record is no
+# longer used, *except* if the main database lookup returns internal failure.
+# We also try to handle password changes automatically: If user's previous
+# authentication was successful, but this one wasn't, the cache isn't used.
+# For now this works only with plaintext authentication.
+#auth_cache_ttl = 1 hour
+# TTL for negative hits (user not found, password mismatch).
+# 0 disables caching them completely.
+#auth_cache_negative_ttl = 1 hour
+auth_cache_negative_ttl = 0
+
+# Space separated list of realms for SASL authentication mechanisms that need
+# them. You can leave it empty if you don't want to support multiple realms.
+# Many clients simply use the first one listed here, so keep the default realm
+# first.
+#auth_realms =
+
+# Default realm/domain to use if none was specified. This is used for both
+# SASL realms and appending @domain to username in plaintext logins.
+#auth_default_realm =
+
+# List of allowed characters in username. If the user-given username contains
+# a character not listed in here, the login automatically fails. This is just
+# an extra check to make sure user can't exploit any potential quote escaping
+# vulnerabilities with SQL/LDAP databases. If you want to allow all characters,
+# set this value to empty.
+#auth_username_chars = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.-_@
+
+# Username character translations before it's looked up from databases. The
+# value contains series of from -> to characters. For example "#@/@" means
+# that '#' and '/' characters are translated to '@'.
+#auth_username_translation =
+
+# Username formatting before it's looked up from databases. You can use
+# the standard variables here, eg. %Lu would lowercase the username, %n would
+# drop away the domain if it was given, or "%n-AT-%d" would change the '@' into
+# "-AT-". This translation is done after auth_username_translation changes.
+#auth_username_format = %Lu
+
+# If you want to allow master users to log in by specifying the master
+# username within the normal username string (ie. not using SASL mechanism's
+# support for it), you can specify the separator character here. The format
+# is then <username><separator><master username>. UW-IMAP uses "*" as the
+# separator, so that could be a good choice.
+#auth_master_user_separator =
+
+# Username to use for users logging in with ANONYMOUS SASL mechanism
+#auth_anonymous_username = anonymous
+
+# Maximum number of dovecot-auth worker processes. They're used to execute
+# blocking passdb and userdb queries (eg. MySQL and PAM). They're
+# automatically created and destroyed as needed.
+#auth_worker_max_count = 30
+
+# Host name to use in GSSAPI principal names. The default is to use the
+# name returned by gethostname(). Use "$ALL" (with quotes) to allow all keytab
+# entries.
+#auth_gssapi_hostname =
+
+# Kerberos keytab to use for the GSSAPI mechanism. Will use the system
+# default (usually /etc/krb5.keytab) if not specified. You may need to change
+# the auth service to run as root to be able to read this file.
+#auth_krb5_keytab =
+
+# Do NTLM and GSS-SPNEGO authentication using Samba's winbind daemon and
+# ntlm_auth helper. <doc/wiki/Authentication/Mechanisms/Winbind.txt>
+#auth_use_winbind = no
+
+# Path for Samba's ntlm_auth helper binary.
+#auth_winbind_helper_path = /usr/bin/ntlm_auth
+
+# Time to delay before replying to failed authentications.
+#auth_failure_delay = 2 secs
+auth_failure_delay = 0 secs
+
+# Require a valid SSL client certificate or the authentication fails.
+#auth_ssl_require_client_cert = no
+
+# Take the username from client's SSL certificate, using
+# X509_NAME_get_text_by_NID() which returns the subject's DN's
+# CommonName.
+#auth_ssl_username_from_cert = no
+
+# Space separated list of wanted authentication mechanisms:
+# plain login digest-md5 cram-md5 ntlm rpa apop anonymous gssapi otp
+# gss-spnego
+# NOTE: See also disable_plaintext_auth setting.
+auth_mechanisms = plain login
+
+##
+## Password and user databases
+##
+
+#
+# Password database is used to verify user's password (and nothing more).
+# You can have multiple passdbs and userdbs. This is useful if you want to
+# allow both system users (/etc/passwd) and virtual users to login without
+# duplicating the system users into virtual database.
+#
+# <doc/wiki/PasswordDatabase.txt>
+#
+# User database specifies where mails are located and what user/group IDs
+# own them. For single-UID configuration use "static" userdb.
+#
+# <doc/wiki/UserDatabase.txt>
+
+passdb {
+ driver = passwd-file
+ args = DIR/aux-fixed/3550.dovecot.passwd
+}
+userdb {
+ driver = passwd-file
+ args = DIR/aux-fixed/3550.dovecot.passwd
+}
+
diff --git a/test/confs/3550 b/test/confs/3550
new file mode 100644
index 000000000..46d35bfbd
--- /dev/null
+++ b/test/confs/3550
@@ -0,0 +1,68 @@
+# Exim test configuration 3550
+
+AUTHS=DIR/tmp/dovecot_auth_socket
+
+.include DIR/aux-var/std_conf_prefix
+
+primary_hostname = myhost.test.ex
+
+# ----- Main settings -----
+
+domainlist local_domains = test.ex : *.test.ex
+
+hostlist auth_hosts = 10.0.0.1
+hostlist relay_hosts = 10.0.0.4
+hostlist auth_relay_hosts = 10.0.0.3 : 10.0.0.4
+
+acl_smtp_rcpt = check_recipient
+auth_advertise_hosts = +auth_hosts : !+relay_hosts : +auth_relay_hosts : \
+ 10.0.0.5
+smtp_accept_max_nonmail = 20
+trusted_users = CALLER
+
+
+# ----- ACL -----
+
+begin acl
+
+check_recipient:
+ deny message = authentication required
+ !authenticated = *
+ accept
+
+# ----- Authentication -----
+
+begin authenticators
+
+plain:
+ driver = dovecot
+ public_name = PLAIN
+ server_socket = AUTHS
+ server_condition = ${if eq {$auth1}{userx} {yes}{no}}
+ server_set_id = $auth1
+
+# ----- Routers -----
+
+begin routers
+
+localuser:
+ driver = accept
+ local_parts = userx
+ transport = appendfile
+
+
+# ----- Transports -----
+
+begin transports
+
+appendfile:
+ driver = appendfile
+ delivery_date_add
+ envelope_to_add
+ file = DIR/test-mail/$local_part
+ create_file = DIR/test-mail
+ return_path_add
+ user = CALLER
+
+
+# End
diff --git a/test/confs/3551 b/test/confs/3551
new file mode 100644
index 000000000..ef85ee006
--- /dev/null
+++ b/test/confs/3551
@@ -0,0 +1,69 @@
+# Exim test configuration 3550
+
+AUTHS=DIR/tmp/dovecot_auth_socket
+
+.include DIR/aux-var/std_conf_prefix
+
+primary_hostname = myhost.test.ex
+
+# ----- Main settings -----
+
+domainlist local_domains = test.ex : *.test.ex
+
+hostlist auth_hosts = 10.0.0.1
+hostlist relay_hosts = 10.0.0.4
+hostlist auth_relay_hosts = 10.0.0.3 : 10.0.0.4
+
+acl_smtp_rcpt = check_recipient
+auth_advertise_hosts = +auth_hosts : !+relay_hosts : +auth_relay_hosts : \
+ 10.0.0.5
+smtp_accept_max_nonmail = 20
+trusted_users = CALLER
+
+
+# ----- ACL -----
+
+begin acl
+
+check_recipient:
+ deny message = authentication required
+ !authenticated = *
+ accept
+
+# ----- Authentication -----
+
+begin authenticators
+
+login:
+ driver = dovecot
+ public_name = LOGIN
+ server_socket = AUTHS
+ server_condition = ${if eq {$auth1}{userx} {yes}{no}}
+ server_set_id = $auth1
+
+
+# ----- Routers -----
+
+begin routers
+
+localuser:
+ driver = accept
+ local_parts = userx
+ transport = appendfile
+
+
+# ----- Transports -----
+
+begin transports
+
+appendfile:
+ driver = appendfile
+ delivery_date_add
+ envelope_to_add
+ file = DIR/test-mail/$local_part
+ create_file = DIR/test-mail
+ return_path_add
+ user = CALLER
+
+
+# End
diff --git a/test/log/3550 b/test/log/3550
new file mode 100644
index 000000000..df8a9686d
--- /dev/null
+++ b/test/log/3550
@@ -0,0 +1 @@
+1999-03-02 09:44:33 plain authenticator failed for (test.host) [10.0.0.1] U=CALLER: 535 Incorrect authentication data (set_id=eserx)
diff --git a/test/log/3551 b/test/log/3551
new file mode 100644
index 000000000..0f295cbca
--- /dev/null
+++ b/test/log/3551
@@ -0,0 +1,8 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= userx@cus.cam.ac.uk H=(test.host) [10.0.0.1] U=CALLER P=esmtpa A=login:userx S=sss
+1999-03-02 09:44:33 10HmaX-0005vi-00 => userx <userx@test.ex> R=localuser T=appendfile
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 login authenticator failed for (test.host) [10.0.0.1] U=CALLER: 535 Incorrect authentication data
+1999-03-02 09:44:33 login authenticator failed for (test.host) [10.0.0.1] U=CALLER: 535 Incorrect authentication data
+1999-03-02 09:44:33 login authenticator failed for (test.host) [10.0.0.1] U=CALLER: 501 Authentication cancelled
+1999-03-02 09:44:33 login authenticator failed for (test.host) [10.0.0.1] U=CALLER: 535 Incorrect authentication data
+1999-03-02 09:44:33 login authenticator failed for (test.host) [10.0.0.1] U=CALLER: 535 Incorrect authentication data (set_id=\001rserx)
diff --git a/test/mail/3551.userx b/test/mail/3551.userx
new file mode 100644
index 000000000..11f9e5654
--- /dev/null
+++ b/test/mail/3551.userx
@@ -0,0 +1,13 @@
+From userx@cus.cam.ac.uk Tue Mar 02 09:44:33 1999
+Return-path: <userx@cus.cam.ac.uk>
+Envelope-to: userx@test.ex
+Delivery-date: Tue, 2 Mar 1999 09:44:33 +0000
+Received: from [10.0.0.1] (helo=test.host ident=CALLER)
+ by myhost.test.ex with esmtpa (Exim x.yz)
+ (envelope-from <userx@cus.cam.ac.uk>)
+ id 10HmaX-0005vi-00
+ for userx@test.ex;
+ Tue, 2 Mar 1999 09:44:33 +0000
+
+Testing authenticated.
+
diff --git a/test/rejectlog/3550 b/test/rejectlog/3550
new file mode 100644
index 000000000..df8a9686d
--- /dev/null
+++ b/test/rejectlog/3550
@@ -0,0 +1 @@
+1999-03-02 09:44:33 plain authenticator failed for (test.host) [10.0.0.1] U=CALLER: 535 Incorrect authentication data (set_id=eserx)
diff --git a/test/rejectlog/3551 b/test/rejectlog/3551
new file mode 100644
index 000000000..2fe157f5c
--- /dev/null
+++ b/test/rejectlog/3551
@@ -0,0 +1,5 @@
+1999-03-02 09:44:33 login authenticator failed for (test.host) [10.0.0.1] U=CALLER: 535 Incorrect authentication data
+1999-03-02 09:44:33 login authenticator failed for (test.host) [10.0.0.1] U=CALLER: 535 Incorrect authentication data
+1999-03-02 09:44:33 login authenticator failed for (test.host) [10.0.0.1] U=CALLER: 501 Authentication cancelled
+1999-03-02 09:44:33 login authenticator failed for (test.host) [10.0.0.1] U=CALLER: 535 Incorrect authentication data
+1999-03-02 09:44:33 login authenticator failed for (test.host) [10.0.0.1] U=CALLER: 535 Incorrect authentication data (set_id=\001rserx)
diff --git a/test/runtest b/test/runtest
index 84cf4df4f..5e4b160b9 100755
--- a/test/runtest
+++ b/test/runtest
@@ -3206,6 +3206,20 @@ if (defined $parm_lookups{redis})
}
}
+sub check_running_dovecot
+{
+system('dovecot --version >/dev/null');
+if ($? == 0)
+ {
+ print "Dovecot appears to be available\n";
+ $parm_running{dovecot} = ' ';
+ }
+else
+ {
+ print "Dovecot not found\n";
+ }
+}
+
###############################################################################
@@ -3568,6 +3582,7 @@ if (defined $parm_support{Content_Scanning})
check_running_clamav();
}
check_running_redis();
+check_running_dovecot();
##################################################
# Test for the basic requirements #
diff --git a/test/scripts/3550-dovecot/3550 b/test/scripts/3550-dovecot/3550
new file mode 100644
index 000000000..803de86e3
--- /dev/null
+++ b/test/scripts/3550-dovecot/3550
@@ -0,0 +1,55 @@
+# dovecot server auth, PLAIN
+#
+mkdir DIR/tmp
+#
+background
+dovecot -F -c DIR/aux-var/TESTNUM.dovecot.conf
+****
+sleep 1
+#
+#
+#
+#
+### Lack of attempt to auth
+exim -bh 10.0.0.2
+HELO test
+MAIL FROM:<junk@jink.jonk.test.ex>
+RCPT TO:<fail_no_auth@test.ex>
+QUIT
+****
+#
+### PLAIN/userx/secret
+exim -bs -oMa 10.0.0.1
+EHLO test.host
+AUTH PLAIN AHVzZXJ4AHNlY3JldA==
+QUIT
+****
+### ditto, split over two lines
+exim -bs -oMa 10.0.0.1
+EHLO test.host
+AUTH PLAIN
+AHVzZXJ4AHNlY3JldA==
+QUIT
+****
+#
+#
+### Check auth_advertise_hosts no-match
+exim -bh 10.0.0.4
+ehlo test.host
+quit
+****
+#
+#
+### PLAIN (bad auth) should fail
+exim -bs -oMa 10.0.0.1
+ehlo test.host
+auth plain AGVzZXJ4AHNlY3JldA==
+quit
+****
+#
+#
+### Shut down dovecot
+killdaemon
+#
+sudo rm -fr DIR/tmp
+no_msglog_check
diff --git a/test/scripts/3550-dovecot/3551 b/test/scripts/3550-dovecot/3551
new file mode 100644
index 000000000..9bcb5ce9b
--- /dev/null
+++ b/test/scripts/3550-dovecot/3551
@@ -0,0 +1,80 @@
+# dovecot server auth, LOGIN
+#
+mkdir DIR/tmp
+#
+background
+dovecot -F -c DIR/aux-var/TESTNUM.dovecot.conf
+****
+sleep 1
+#
+#
+#
+### LOGIN/userx/secret
+exim -odi -bs -oMa 10.0.0.1
+EHLO test.host
+AUTH LOGIN
+dXNlcng=
+c2VjcmV0
+MAIL FROM:<userx@cus.cam.ac.uk>
+RCPT TO:<userx@test.ex>
+DATA
+Testing authenticated.
+.
+quit
+****
+### ditto, on two lines from client rather than three; fails
+### (not legit; the username & passwd should be suplied separately in response to prompts)
+# the Exim "plaintext" authenticator is fine with it, but it's outside what we know of the "specification"
+exim -bs -oMa 10.0.0.1
+ehlo test.host
+AUTH LOGIN
+dXNlcngAc2VjcmV0
+quit
+****
+### ditto, on one line; fails
+exim -bs -oMa 10.0.0.1
+ehlo test.host
+AUTH LOGIN dXNlcngAc2VjcmV0
+quit
+****
+### ditto, a different split of two lines; passes (though not strictly within spec)
+exim -bs -oMa 10.0.0.1
+ehlo test.host
+AUTH LOGIN dXNlcng=
+c2VjcmV0
+quit
+****
+### LOGIN - cancelled part-way through (returns a fail)
+exim -bs -oMa 10.0.0.1
+ehlo test.host
+AUTH LOGIN
+dXNlcng=
+*
+quit
+****
+#
+#
+### LOGIN (empty username; bad auth) should fail
+exim -odi -bs -oMa 10.0.0.1
+ehlo test.host
+AUTH LOGIN
+
+c2VjcmV0
+quit
+****
+#
+### LOGIN (bad username; bad auth) should fail
+exim -odi -bs -oMa 10.0.0.1
+ehlo test.host
+AUTH LOGIN
+DXNlcng=
+c2VjcmV0
+quit
+****
+#
+#
+### Shut down dovecot
+killdaemon
+#
+sudo rm -fr DIR/tmp
+no_msglog_check
diff --git a/test/scripts/3550-dovecot/REQUIRES b/test/scripts/3550-dovecot/REQUIRES
new file mode 100644
index 000000000..2d95fc53d
--- /dev/null
+++ b/test/scripts/3550-dovecot/REQUIRES
@@ -0,0 +1,2 @@
+authenticator dovecot
+running dovecot
diff --git a/test/stderr/3550 b/test/stderr/3550
new file mode 100644
index 000000000..c8fef7ef3
--- /dev/null
+++ b/test/stderr/3550
@@ -0,0 +1,61 @@
+### Lack of attempt to auth
+>>> host in hosts_connection_nolog? no (option unset)
+>>> host in host_lookup? no (option unset)
+>>> host in host_reject_connection? no (option unset)
+>>> host in sender_unqualified_hosts? no (option unset)
+>>> host in recipient_unqualified_hosts? no (option unset)
+>>> host in helo_verify_hosts? no (option unset)
+>>> host in helo_try_verify_hosts? no (option unset)
+>>> host in helo_accept_junk_hosts? no (option unset)
+>>> test in helo_lookup_domains?
+>>> list element: @
+>>> list element: @[]
+>>> test in helo_lookup_domains? no (end of list)
+>>> using ACL "check_recipient"
+>>> processing "deny" (TESTSUITE/test-config 29)
+>>> message: authentication required
+>>> check !authenticated = *
+>>> deny: condition test succeeded in ACL "check_recipient"
+>>> end of ACL "check_recipient": DENY
+LOG: H=(test) [10.0.0.2] F=<junk@jink.jonk.test.ex> rejected RCPT <fail_no_auth@test.ex>: authentication required
+### PLAIN/userx/secret
+### ditto, split over two lines
+### Check auth_advertise_hosts no-match
+>>> host in hosts_connection_nolog? no (option unset)
+>>> host in host_lookup? no (option unset)
+>>> host in host_reject_connection? no (option unset)
+>>> host in sender_unqualified_hosts? no (option unset)
+>>> host in recipient_unqualified_hosts? no (option unset)
+>>> host in helo_verify_hosts? no (option unset)
+>>> host in helo_try_verify_hosts? no (option unset)
+>>> host in helo_accept_junk_hosts? no (option unset)
+>>> test.host in helo_lookup_domains?
+>>> list element: @
+>>> list element: @[]
+>>> test.host in helo_lookup_domains? no (end of list)
+>>> host in dsn_advertise_hosts? no (option unset)
+>>> host in pipelining_advertise_hosts?
+>>> list element: *
+>>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in auth_advertise_hosts?
+>>> list element: +auth_hosts
+>>> host in "10.0.0.1"?
+>>> list element: 10.0.0.1
+>>> host in "10.0.0.1"? no (end of list)
+>>> list element: !+relay_hosts
+>>> host in "10.0.0.4"?
+>>> list element: 10.0.0.4
+>>> host in "10.0.0.4"? yes (matched "10.0.0.4")
+>>> host in auth_advertise_hosts? no (matched "!+relay_hosts")
+>>> host in chunking_advertise_hosts?
+>>> host in chunking_advertise_hosts? no (end of list)
+### PLAIN (bad auth) should fail
+### Shut down dovecot
+
+******** SERVER ********
+### Lack of attempt to auth
+### PLAIN/userx/secret
+### ditto, split over two lines
+### Check auth_advertise_hosts no-match
+### PLAIN (bad auth) should fail
+### Shut down dovecot
diff --git a/test/stderr/3551 b/test/stderr/3551
new file mode 100644
index 000000000..064d108b7
--- /dev/null
+++ b/test/stderr/3551
@@ -0,0 +1,20 @@
+### LOGIN/userx/secret
+### ditto, on two lines from client rather than three; fails
+### (not legit; the username & passwd should be suplied separately in response to prompts)
+### ditto, on one line; fails
+### ditto, a different split of two lines; passes (though not strictly within spec)
+### LOGIN - cancelled part-way through (returns a fail)
+### LOGIN (empty username; bad auth) should fail
+### LOGIN (bad username; bad auth) should fail
+### Shut down dovecot
+
+******** SERVER ********
+### LOGIN/userx/secret
+### ditto, on two lines from client rather than three; fails
+### (not legit; the username & passwd should be suplied separately in response to prompts)
+### ditto, on one line; fails
+### ditto, a different split of two lines; passes (though not strictly within spec)
+### LOGIN - cancelled part-way through (returns a fail)
+### LOGIN (empty username; bad auth) should fail
+### LOGIN (bad username; bad auth) should fail
+### Shut down dovecot
diff --git a/test/stdout/3550 b/test/stdout/3550
new file mode 100644
index 000000000..5dc50295e
--- /dev/null
+++ b/test/stdout/3550
@@ -0,0 +1,64 @@
+### Lack of attempt to auth
+
+**** SMTP testing session as if from host 10.0.0.2
+**** but without any ident (RFC 1413) callback.
+**** This is not for real!
+
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250 myhost.test.ex Hello test [10.0.0.2]
+250 OK
+550 authentication required
+221 myhost.test.ex closing connection
+### PLAIN/userx/secret
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello CALLER at test.host [10.0.0.1]
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250-AUTH PLAIN
+250 HELP
+235 Authentication succeeded
+221 myhost.test.ex closing connection
+### ditto, split over two lines
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello CALLER at test.host [10.0.0.1]
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250-AUTH PLAIN
+250 HELP
+334
+235 Authentication succeeded
+221 myhost.test.ex closing connection
+### Check auth_advertise_hosts no-match
+
+**** SMTP testing session as if from host 10.0.0.4
+**** but without any ident (RFC 1413) callback.
+**** This is not for real!
+
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello test.host [10.0.0.4]
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250 HELP
+221 myhost.test.ex closing connection
+### PLAIN (bad auth) should fail
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello CALLER at test.host [10.0.0.1]
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250-AUTH PLAIN
+250 HELP
+535 Incorrect authentication data
+221 myhost.test.ex closing connection
+### Shut down dovecot
+
+******** SERVER ********
+### Lack of attempt to auth
+### PLAIN/userx/secret
+### ditto, split over two lines
+### Check auth_advertise_hosts no-match
+### PLAIN (bad auth) should fail
+### Shut down dovecot
diff --git a/test/stdout/3551 b/test/stdout/3551
new file mode 100644
index 000000000..8d9d882f7
--- /dev/null
+++ b/test/stdout/3551
@@ -0,0 +1,97 @@
+### LOGIN/userx/secret
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello CALLER at test.host [10.0.0.1]
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250-AUTH LOGIN
+250 HELP
+334 VXNlcm5hbWU6
+334 UGFzc3dvcmQ6
+235 Authentication succeeded
+250 OK
+250 Accepted
+354 Enter message, ending with "." on a line by itself
+250 OK id=10HmaX-0005vi-00
+221 myhost.test.ex closing connection
+### ditto, on two lines from client rather than three; fails
+### (not legit; the username & passwd should be suplied separately in response to prompts)
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello CALLER at test.host [10.0.0.1]
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250-AUTH LOGIN
+250 HELP
+334 VXNlcm5hbWU6
+535 Incorrect authentication data
+221 myhost.test.ex closing connection
+### ditto, on one line; fails
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello CALLER at test.host [10.0.0.1]
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250-AUTH LOGIN
+250 HELP
+535 Incorrect authentication data
+221 myhost.test.ex closing connection
+### ditto, a different split of two lines; passes (though not strictly within spec)
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello CALLER at test.host [10.0.0.1]
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250-AUTH LOGIN
+250 HELP
+334 UGFzc3dvcmQ6
+235 Authentication succeeded
+221 myhost.test.ex closing connection
+### LOGIN - cancelled part-way through (returns a fail)
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello CALLER at test.host [10.0.0.1]
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250-AUTH LOGIN
+250 HELP
+334 VXNlcm5hbWU6
+334 UGFzc3dvcmQ6
+501 Authentication cancelled
+221 myhost.test.ex closing connection
+### LOGIN (empty username; bad auth) should fail
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello CALLER at test.host [10.0.0.1]
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250-AUTH LOGIN
+250 HELP
+334 VXNlcm5hbWU6
+535 Incorrect authentication data
+500 unrecognized command
+221 myhost.test.ex closing connection
+### LOGIN (bad username; bad auth) should fail
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello CALLER at test.host [10.0.0.1]
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250-AUTH LOGIN
+250 HELP
+334 VXNlcm5hbWU6
+535 Incorrect authentication data
+500 unrecognized command
+221 myhost.test.ex closing connection
+### Shut down dovecot
+
+******** SERVER ********
+### LOGIN/userx/secret
+### ditto, on two lines from client rather than three; fails
+### (not legit; the username & passwd should be suplied separately in response to prompts)
+### ditto, on one line; fails
+### ditto, a different split of two lines; passes (though not strictly within spec)
+### LOGIN - cancelled part-way through (returns a fail)
+### LOGIN (empty username; bad auth) should fail
+### LOGIN (bad username; bad auth) should fail
+### Shut down dovecot