[exim-cvs] authenticator dynamic modules

Góra strony
Delete this message
Reply to this message
Autor: Exim Git Commits Mailing List
Data:  
Dla: exim-cvs
Temat: [exim-cvs] authenticator dynamic modules
Gitweb: https://git.exim.org/exim.git/commitdiff/51a87a4dd1f2999485da7fe50c313e821dcc8dba
Commit:     51a87a4dd1f2999485da7fe50c313e821dcc8dba
Parent:     62ccb00d5ca29f962c3691201e143667ff80bc6c
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Fri Aug 16 19:33:48 2024 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Fri Aug 16 23:03:55 2024 +0100


    authenticator dynamic modules
---
 doc/doc-docbook/spec.xfpt               |   4 +-
 doc/doc-txt/ChangeLog                   |   5 +
 doc/doc-txt/NewStuff                    |   5 +-
 src/OS/Makefile-Base                    |   8 +-
 src/scripts/Configure-Makefile          |   3 +-
 src/scripts/MakeLinks                   |   9 +-
 src/scripts/drivers-Makefile            |  22 +--
 src/src/EDITME                          |  14 ++
 src/src/auths/Makefile                  |  89 ++++++----
 src/src/auths/cram_md5.c                |  26 ++-
 src/src/auths/cyrus_sasl.c              |  23 +++
 src/src/auths/dovecot.c                 |  40 +++--
 src/src/auths/external.c                |  22 +++
 src/src/auths/{gsasl_exim.c => gsasl.c} |  26 ++-
 src/src/auths/{gsasl_exim.h => gsasl.h} |   0
 src/src/auths/heimdal_gssapi.c          |  32 +++-
 src/src/auths/heimdal_gssapi.h          |   2 +-
 src/src/auths/plaintext.c               |  23 +++
 src/src/auths/spa.c                     |  22 +++
 src/src/auths/tls.c                     |  22 +++
 src/src/drtables.c                      | 278 ++++++++------------------------
 src/src/exim.c                          |   3 +-
 src/src/globals.h                       |   3 +-
 src/src/readconf.c                      |  71 ++++++--
 src/src/transports/Makefile             |   6 +-
 test/confs/0000                         |   1 +
 test/runtest                            |   7 +-
 test/stderr/0402                        |  15 ++
 test/stderr/0544                        |   6 +
 test/stderr/5410                        |  18 +++
 30 files changed, 490 insertions(+), 315 deletions(-)


diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index 9fbf7a2db..f73792ac5 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -2073,6 +2073,7 @@ withdrawn.
.cindex "lookup modules"
.cindex "router modules"
.cindex "transport modules"
+.cindex "authenticator modules"
.cindex "dynamic modules"
.cindex ".so building"
On some platforms, Exim supports not compiling all lookup types directly into
@@ -2084,7 +2085,8 @@ dependencies.
Most, but not all, lookup types can be built this way.

 .new
-Similarly, router and transport drivers can be built as external modules.
+Similarly, authenticator, router and transport drivers can be built
+as external modules.
 This permits a smaller exim binary, growing only as needed for the
 runtime cofiguration.
 .wen
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 3a0e3efc5..adfd5cb8f 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -40,6 +40,11 @@ JH/07 Bug 3106: Fix coding in SPA authenticator. A macro argument was not
 JH/08 The output of "exim -bV" now includes lookup types built as dynamic-load
       modules.


+JH/09 Not a change, but worthy of note: There is no test coverage of the
+      heimdall-gssapi authenticator driver.  It does build, though with (on at
+      least one platform) library version conflicts with the gsasl auth
+      driver).  Confidence in its operation is lacking.
+
 Exim version 4.98
 -----------------


diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff
index be0f0c679..1910ad002 100644
--- a/doc/doc-txt/NewStuff
+++ b/doc/doc-txt/NewStuff
@@ -14,8 +14,9 @@ Version 4.98

3. Events smtp:fail:protocol and smtp:fail:syntax

- 4. JSON lookup support, all the router drivers except manualroute, and all the transport
-    drivers except smtp can now be built as lodable modules
+ 4. JSON lookup support, all the router drivers except manualroute, all the
+    transport drivers except smtp, and all the authenticator drivers except
+    plaintext, gsasl and spa can now be built as loadable modules


 Version 4.98
 ------------
diff --git a/src/OS/Makefile-Base b/src/OS/Makefile-Base
index d45524561..3f2d4d883 100644
--- a/src/OS/Makefile-Base
+++ b/src/OS/Makefile-Base
@@ -119,7 +119,7 @@ OBJ_MACRO = macro_predef.o \
     macro-appendfile.o macro-autoreply.o macro-lmtp.o macro-pipe.o macro-queuefile.o \
     macro-smtp.o macro-accept.o macro-dnslookup.o macro-ipliteral.o macro-iplookup.o \
     macro-manualroute.o macro-queryprogram.o macro-redirect.o \
-    macro-auth-spa.o macro-cram_md5.o macro-cyrus_sasl.o macro-dovecot.o macro-gsasl_exim.o \
+    macro-auth-spa.o macro-cram_md5.o macro-cyrus_sasl.o macro-dovecot.o macro-gsasl.o \
     macro-heimdal_gssapi.o macro-plaintext.o macro-spa.o macro-authtls.o macro-external.o \
     macro-dkim.o macro-malware.o macro-signing.o


@@ -206,9 +206,9 @@ macro-dovecot.o:    auths/dovecot.c
 macro-external.o:    auths/external.c
     @echo "$(CC) -DMACRO_PREDEF auths/external.c"
     $(FE)$(CC) -c $(CFLAGS) -DMACRO_PREDEF $(INCLUDE) -o $@ auths/external.c
-macro-gsasl_exim.o :    auths/gsasl_exim.c
-    @echo "$(CC) -DMACRO_PREDEF auths/gsasl_exim.c"
-    $(FE)$(CC) -c $(CFLAGS) -DMACRO_PREDEF $(INCLUDE) -o $@ auths/gsasl_exim.c
+macro-gsasl.o :    auths/gsasl.c
+    @echo "$(CC) -DMACRO_PREDEF auths/gsasl.c"
+    $(FE)$(CC) -c $(CFLAGS) -DMACRO_PREDEF $(INCLUDE) -o $@ auths/gsasl.c
 macro-heimdal_gssapi.o:    auths/heimdal_gssapi.c
     @echo "$(CC) -DMACRO_PREDEF auths/heimdal_gssapi.c"
     $(FE)$(CC) -c $(CFLAGS) -DMACRO_PREDEF $(INCLUDE) -o $@ auths/heimdal_gssapi.c
diff --git a/src/scripts/Configure-Makefile b/src/scripts/Configure-Makefile
index 79ab19dcc..9179392f3 100755
--- a/src/scripts/Configure-Makefile
+++ b/src/scripts/Configure-Makefile
@@ -298,8 +298,9 @@ do
   mv $class/Makefile.postdynamic $class/Makefile
   rm $class/Makefile.predynamic
 done <<-END
- routers ROUTER        ACCEPT DNSLOOKUP IPLITERAL IPLOOKUP MANUALROUTE QUERYPROGRAM REDIRECT
+ routers    ROUTER    ACCEPT DNSLOOKUP IPLITERAL IPLOOKUP MANUALROUTE QUERYPROGRAM REDIRECT
  transports TRANSPORT    APPENDFILE AUTOREPLY LMTP PIPE QUEUEFILE SMTP
+ auths        AUTH    CRAM_MD5 CYRUS_SASL DOVECOT EXTERNAL GSASL HEIMDAL_GSSAPI PLAINTEXT SPA TLS
 END


# See if there is a definition of EXIM_PERL in what we have built so far.
diff --git a/src/scripts/MakeLinks b/src/scripts/MakeLinks
index 998b73bf9..76859ce9a 100755
--- a/src/scripts/MakeLinks
+++ b/src/scripts/MakeLinks
@@ -77,11 +77,12 @@ cd ..
d="auths"
mkdir $d
cd $d
-for f in README Makefile call_pam.c call_pwcheck.c \
- call_radius.c check_serv_cond.c cyrus_sasl.c cyrus_sasl.h gsasl_exim.c \
- gsasl_exim.h get_data.c get_no64_data.c heimdal_gssapi.c heimdal_gssapi.h \
+# Makefile is generated
+for f in README call_pam.c call_pwcheck.c \
+ call_radius.c check_serv_cond.c cyrus_sasl.c cyrus_sasl.h gsasl.c \
+ gsasl.h get_data.c get_no64_data.c heimdal_gssapi.c heimdal_gssapi.h \
cram_md5.c cram_md5.h plaintext.c plaintext.h \
- pwcheck.c pwcheck.h auth-spa.c auth-spa.h dovecot.c dovecot.h sha1.c spa.c \
+ pwcheck.c pwcheck.h auth-spa.c auth-spa.h dovecot.c dovecot.h spa.c \
spa.h tls.c tls.h external.c external.h
do
ln -s ../../src/$d/$f $f
diff --git a/src/scripts/drivers-Makefile b/src/scripts/drivers-Makefile
index 0c3da19cb..2dd958043 100755
--- a/src/scripts/drivers-Makefile
+++ b/src/scripts/drivers-Makefile
@@ -3,7 +3,6 @@
# Copyright (c) The Exim Maintainers 1995 - 2024
# SPDX-License-Identifier: GPL-2.0-or-later

-set -e
 class=${CLASS:?}
 classdef=${CLASSDEF:?}
 drnames="${DRNAMES:?}"
@@ -137,16 +136,17 @@ emit_module_rule() {
       exit 1
     fi
     MODS="${MODS} ${mod_name}.so"
-#    pkgconf=$(grep "^${classdef}_${name}_PC" "$defs_source")
-#    if [ $? -eq 0 ]; then
-#      pkgconf=$(echo $pkgconf | sed 's/^.*= *//')
-#      echo "${classdef}_${mod_name}_INCLUDE = $(pkg-config --cflags $pkgconf)"
-#      echo "${classdef}_${mod_name}_LIBS = $(pkg-config --libs $pkgconf)"
-#    else
-#      grep "^${classdef}_${name}_" "$defs_source"
-#      echo "${classdef}_${mod_name}_INCLUDE = \$(${classdef}_${name}_INCLUDE)"
-#      echo "${classdef}_${mod_name}_LIBS = \$(${classdef}_${name}_LIBS)"
-#    fi
+    grep "^${classdef}_${name}_PC" "$defs_source" 1>&2
+    pkgconf=$(grep "^${classdef}_${name}_PC" "$defs_source")
+    if [ $? -eq 0 ]; then
+      pkgconf=$(echo $pkgconf | sed 's/^.*= *//')
+      echo "${classdef}_${mod_name}_INCLUDE = $(pkg-config --cflags $pkgconf)"
+      echo "${classdef}_${mod_name}_LIBS = $(pkg-config --libs $pkgconf)"
+    else
+      grep "^${classdef}_${name}_" "$defs_source"
+      echo "${classdef}_${mod_name}_INCLUDE = \$(${classdef}_${name}_INCLUDE)"
+      echo "${classdef}_${mod_name}_LIBS = \$(${classdef}_${name}_LIBS)"
+    fi
   elif want_at_all "$name"
   then
     OBJ="${OBJ} ${mod_name}.o"
diff --git a/src/src/EDITME b/src/src/EDITME
index 820793032..b930f00a7 100644
--- a/src/src/EDITME
+++ b/src/src/EDITME
@@ -827,6 +827,20 @@ FIXED_NEVER_USERS=root
 # you must uncomment at least one of the following, so that appropriate code is
 # included in the Exim binary. You will then need to set up the run time
 # configuration to make use of the mechanism(s) selected.
+#
+# If set to "2" instead of "yes" then the corresponding driver will be
+# built as a module and must be installed into LOOKUP_MODULE_DIR (the name
+# is historic).
+# You need to add -export-dynamic -rdynamic to EXTRALIBS. You may also need to
+# add -ldl to EXTRALIBS so that dlopen() is available to Exim. You need to
+# define CFLAGS_DYNAIC and LOOKUP_MODULE_DIR below so the builds are done right,
+# and so the exim binary actually loads dynamic lookup modules.
+#
+# Libraries being built as modules should be added to respective
+# LOOKUP_*_INCLUDE and LOOKUP_*_LIBS rather than the the ones for the
+# core exim build.  This gets them linked with the module instead
+# Only the cram_md5, cyrus_sasl, dovecot, external and tls builds for modules
+# are known to work. The heimdal does build, but we have no test coverage.


# AUTH_CRAM_MD5=yes
# AUTH_CYRUS_SASL=yes
diff --git a/src/src/auths/Makefile b/src/src/auths/Makefile
index ac5cf865b..fa60acba9 100644
--- a/src/src/auths/Makefile
+++ b/src/src/auths/Makefile
@@ -4,40 +4,61 @@
# linked in only when needed. This Makefile is called from the main make file,
# after cd'ing to the auths subdirectory. When the relevant AUTH_ macros are
# defined, the equivalent modules herein is not included in the final binary.
+#
+# Copyright (c) The Exim Maintainers 2024

-OBJ = auth-spa.o call_pam.o call_pwcheck.o \
-      call_radius.o check_serv_cond.o cram_md5.o cyrus_sasl.o dovecot.o \
-      external.o get_data.o get_no64_data.o gsasl_exim.o heimdal_gssapi.o \
-      plaintext.o pwcheck.o \
-      spa.o tls.o
-
-auths.a:         $(OBJ)
-         @$(RM_COMMAND) -f auths.a
-         @echo "$(AR) auths.a"
-         $(FE)$(AR) auths.a $(OBJ)
-         $(RANLIB) $@
-
-.SUFFIXES:       .o .c
-.c.o:;           @echo "$(CC) $*.c"
-         $(FE)$(CC) -c $(CFLAGS) $(INCLUDE) $*.c
-
-auth-spa.o:         $(HDRS) auth-spa.c
-call_pam.o:         $(HDRS) call_pam.c
-call_pwcheck.o:     $(HDRS) call_pwcheck.c pwcheck.h
-call_radius.o:      $(HDRS) call_radius.c
-check_serv_cond.o:  $(HDRS) check_serv_cond.c
-get_data.o:         $(HDRS) get_data.c
-get_no64_data.o:    $(HDRS) get_no64_data.c
-pwcheck.o:          $(HDRS) pwcheck.c pwcheck.h
-
-cram_md5.o:         $(HDRS) cram_md5.c cram_md5.h
-cyrus_sasl.o:       $(HDRS) cyrus_sasl.c cyrus_sasl.h
-dovecot.o:          $(HDRS) dovecot.c dovecot.h
-external.o:         $(HDRS) external.c external.h
-gsasl_exim.o:       $(HDRS) gsasl_exim.c gsasl_exim.h
-heimdal_gssapi.o:   $(HDRS) heimdal_gssapi.c heimdal_gssapi.h
-plaintext.o:        $(HDRS) plaintext.c plaintext.h
-spa.o:              $(HDRS) spa.c spa.h
-tls.o:              $(HDRS) tls.c tls.h
+# nb: at build time, the version of this file used will have had some
+#     extra variable definitions and prepended to it and module build rules
+#     interpolated below. This is done by scripts/drivers-Makefile with
+#     definitions from scripts/Configure-Makefile
+
+# MAGIC-TAG-MODS-OBJ-RULES-GO-HERE
+
+OBJ += auth-spa.o call_pam.o call_pwcheck.o call_radius.o check_serv_cond.o \
+    get_data.o get_no64_data.o pwcheck.o
+
+all:        auths.a $(MODS)
+
+auths.a:    $(OBJ)
+        @$(RM_COMMAND) -f auths.a
+        @echo "$(AR) auths.a"
+        $(FE)$(AR) auths.a $(OBJ)
+        $(RANLIB) $@
+
+.SUFFIXES:    .o .c .so
+.c.o:;        @echo "$(CC) $*.c"
+        $(FE)$(CC) -c $(CFLAGS) $(INCLUDE) $*.c
+
+SO_FLAGS = -DDYNLOOKUP $(CFLAGS_DYNAMIC) $(CFLAGS) $(INCLUDE) $(DLFLAGS)
+.c.so:;        @echo "$(CC) -shared $*.c"
+        $(FE)$(CC) $(SO_FLAGS) $(AUTH_$*_INCLUDE) $(AUTH_$*_LIBS) \
+            $*.c -o $@
+
+
+$(OBJ) $(MOD): $(HDRS)
+
+auth-spa.o:         auth-spa.c
+call_pam.o:         call_pam.c
+call_pwcheck.o:     call_pwcheck.c pwcheck.h
+call_radius.o:      call_radius.c
+check_serv_cond.o:  check_serv_cond.c
+get_data.o:         get_data.c
+get_no64_data.o:    get_no64_data.c
+pwcheck.o:          pwcheck.c pwcheck.h
+
+cram_md5.o:         cram_md5.c cram_md5.h
+cyrus_sasl.o:       cyrus_sasl.c cyrus_sasl.h
+dovecot.o:          dovecot.c dovecot.h
+external.o:         external.c external.h
+gsasl.o:        gsasl.c gsasl.h
+heimdal_gssapi.o:   heimdal_gssapi.c heimdal_gssapi.h
+plaintext.o:        plaintext.c plaintext.h
+spa.o:              spa.c spa.h
+tls.o:              tls.c tls.h
+
+# These depend on more than one .c source
+
+spa.so:    spa.c auth-spa.c spa.h
+    $(FE)$(CC) $(SO_FLAGS) spa.c auth-spa.c -o $@


 # End
diff --git a/src/src/auths/cram_md5.c b/src/src/auths/cram_md5.c
index a64177f2a..7b41ee065 100644
--- a/src/src/auths/cram_md5.c
+++ b/src/src/auths/cram_md5.c
@@ -334,10 +334,34 @@ if (smtp_write_command(sx, SCMD_FLUSH, "%s\r\n", b64encode(CUS big_buffer,
 return smtp_read_response(sx, US buffer, buffsize, '2', timeout)
   ? OK : FAIL;
 }
+
+
+# ifdef DYNLOOKUP
+#  define cram_md5_auth_info _auth_info
+# endif
+
+auth_info cram_md5_auth_info = {
+.drinfo = {
+  .driver_name =    US"cram_md5",                   /* lookup name */
+  .options =        auth_cram_md5_options,
+  .options_count =    &auth_cram_md5_options_count,
+  .options_block =    &auth_cram_md5_option_defaults,
+  .options_len =    sizeof(auth_cram_md5_options_block),
+  .init =        auth_cram_md5_init,
+# ifdef DYNLOOKUP
+  .dyn_magic =        AUTH_MAGIC,
+# endif
+  },
+.servercode =        auth_cram_md5_server,
+.clientcode =        auth_cram_md5_client,
+.version_report =    NULL,
+.macros_create =    NULL,
+};
+
+
 #  endif  /*AUTH_CRAM_MD5*/
 # endif  /*!STAND_ALONE*/


-
 /*************************************************
 **************************************************
 *             Stand-alone test program           *
diff --git a/src/src/auths/cyrus_sasl.c b/src/src/auths/cyrus_sasl.c
index 8266e2319..ed0995637 100644
--- a/src/src/auths/cyrus_sasl.c
+++ b/src/src/auths/cyrus_sasl.c
@@ -508,6 +508,29 @@ auth_cyrus_sasl_client(
 return FAIL;
 }


+
+# ifdef DYNLOOKUP
+#  define cyrus_sasl_auth_info _auth_info
+# endif
+
+auth_info cyrus_sasl_auth_info = {
+.drinfo = {
+  .driver_name =    US"cyrus_sasl",                   /* lookup name */
+  .options =        auth_cyrus_sasl_options,
+  .options_count =    &auth_cyrus_sasl_options_count,
+  .options_block =    &auth_cyrus_sasl_option_defaults,
+  .options_len =    sizeof(auth_cyrus_sasl_options_block),
+  .init =        auth_cyrus_sasl_init,
+# ifdef DYNLOOKUP
+  .dyn_magic =        AUTH_MAGIC,
+# endif
+  },
+.servercode =        auth_cyrus_sasl_server,
+.clientcode =        NULL,
+.version_report =    auth_cyrus_sasl_version_report,
+.macros_create =    NULL,
+};
+
 #endif   /*!MACRO_PREDEF*/
 #endif  /* AUTH_CYRUS_SASL */


diff --git a/src/src/auths/dovecot.c b/src/src/auths/dovecot.c
index fdfdbc749..ee69436be 100644
--- a/src/src/auths/dovecot.c
+++ b/src/src/auths/dovecot.c
@@ -1,13 +1,13 @@
/*
- * Copyright (c) The Exim Maintainers 2006 - 2024
- * Copyright (c) 2004 Andrey Panin <pazke@???>
- * SPDX-License-Identifier: GPL-2.0-or-later
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+Copyright (c) The Exim Maintainers 2006 - 2024
+Copyright (c) 2004 Andrey Panin <pazke@???>
+SPDX-License-Identifier: GPL-2.0-or-later
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+*/

/* A number of modifications have been made to the original code. Originally I
commented them specially, but now they are getting quite extensive, so I have
@@ -541,6 +541,28 @@ return ret;
}


+# ifdef DYNLOOKUP
+#  define dovecot_auth_info _auth_info
+# endif
+
+auth_info dovecot_auth_info = {
+.drinfo = {
+  .driver_name =    US"dovecot",                   /* lookup name */
+  .options =        auth_dovecot_options,
+  .options_count =    &auth_dovecot_options_count,
+  .options_block =    &auth_dovecot_option_defaults,
+  .options_len =    sizeof(auth_dovecot_options_block),
+  .init =        auth_dovecot_init,
+# ifdef DYNLOOKUP
+  .dyn_magic =        AUTH_MAGIC,
+# endif
+  },
+.servercode =        auth_dovecot_server,
+.clientcode =        NULL,
+.version_report =    NULL,
+.macros_create =    NULL,
+};
+
 #endif    /*!MACRO_PREDEF*/
 #endif    /*AUTH_DOVECOT*/
 /* end of auths/dovecot.c */
diff --git a/src/src/auths/external.c b/src/src/auths/external.c
index 137d1e043..de0d07f86 100644
--- a/src/src/auths/external.c
+++ b/src/src/auths/external.c
@@ -159,6 +159,28 @@ return OK;




+# ifdef DYNLOOKUP
+#  define external_auth_info _auth_info
+# endif
+
+auth_info external_auth_info = {
+.drinfo = {
+  .driver_name =    US"external",                   /* lookup name */
+  .options =        auth_external_options,
+  .options_count =    &auth_external_options_count,
+  .options_block =    &auth_external_option_defaults,
+  .options_len =    sizeof(auth_external_options_block),
+  .init =        auth_external_init,
+# ifdef DYNLOOKUP
+  .dyn_magic =        AUTH_MAGIC,
+# endif
+  },
+.servercode =        auth_external_server,
+.clientcode =        auth_external_client,
+.version_report =    NULL,
+.macros_create =    NULL,
+};
+
 #endif    /*!MACRO_PREDEF*/
 #endif    /*AUTH_EXTERNAL*/
 /* End of external.c */
diff --git a/src/src/auths/gsasl_exim.c b/src/src/auths/gsasl.c
similarity index 98%
rename from src/src/auths/gsasl_exim.c
rename to src/src/auths/gsasl.c
index 55ac15b4b..e128dac69 100644
--- a/src/src/auths/gsasl_exim.c
+++ b/src/src/auths/gsasl.c
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/


-/* Copyright (c) The Exim Maintainers 2019 - 2023 */
+/* Copyright (c) The Exim Maintainers 2019 - 2024 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
/* SPDX-License-Identifier: GPL-2.0-or-later */
@@ -37,7 +37,7 @@ static void dummy(int x) { dummy2(x-1); }
#else

#include <gsasl.h>
-#include "gsasl_exim.h"
+#include "gsasl.h"


#if GSASL_VERSION_MAJOR == 2
@@ -1060,6 +1060,28 @@ return string_fmt_append(g, "Library version: GNU SASL: Compile: %s\n"
/* Dummy */
void auth_gsasl_macros(void) {}

+# ifdef DYNLOOKUP
+#  define gsasl_auth_info _auth_info
+# endif
+
+auth_info gsasl_auth_info = {
+.drinfo = {
+  .driver_name =    US"gsasl",                   /* lookup name */
+  .options =        auth_gsasl_options,
+  .options_count =    &auth_gsasl_options_count,
+  .options_block =    &auth_gsasl_option_defaults,
+  .options_len =    sizeof(auth_gsasl_options_block),
+  .init =        auth_gsasl_init,
+# ifdef DYNLOOKUP
+  .dyn_magic =        AUTH_MAGIC,
+# endif
+  },
+.servercode =        auth_gsasl_server,
+.clientcode =        auth_gsasl_client,
+.version_report =    auth_gsasl_version_report,
+.macros_create =    auth_gsasl_macros,
+};
+
 #endif   /*!MACRO_PREDEF*/
 #endif  /* AUTH_GSASL */


diff --git a/src/src/auths/gsasl_exim.h b/src/src/auths/gsasl.h
similarity index 100%
rename from src/src/auths/gsasl_exim.h
rename to src/src/auths/gsasl.h
diff --git a/src/src/auths/heimdal_gssapi.c b/src/src/auths/heimdal_gssapi.c
index a5eef8d95..8e9e38660 100644
--- a/src/src/auths/heimdal_gssapi.c
+++ b/src/src/auths/heimdal_gssapi.c
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/


-/* Copyright (c) The Exim Maintainers 2020 - 2023 */
+/* Copyright (c) The Exim Maintainers 2020 - 2024 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
/* SPDX-License-Identifier: GPL-2.0-or-later */
@@ -228,7 +228,7 @@ int
auth_heimdal_gssapi_server(auth_instance *ablock, uschar *initial_data)
{
auth_heimdal_gssapi_options_block * ob =
- (auth_heimdal_gssapi_options_block *)(ablock->drinfo.options_block);
+ (auth_heimdal_gssapi_options_block *)(ablock->drinst.options_block);
gss_name_t gclient = GSS_C_NO_NAME;
gss_name_t gserver = GSS_C_NO_NAME;
gss_cred_id_t gcred = GSS_C_NO_CREDENTIAL;
@@ -250,7 +250,7 @@ uschar requested_qop;
store_reset_point = store_mark();

HDEBUG(D_auth)
- debug_printf("heimdal: initialising auth context for %s\n", ablock->name);
+ debug_printf("heimdal: initialising auth context for %s\n", ablock->drinst.name);

/* Construct our gss_name_t gserver describing ourselves */
tmp1 = expand_string(ob->server_service);
@@ -548,7 +548,7 @@ va_list ap;
OM_uint32 maj_stat, min_stat;
OM_uint32 msgcontext = 0;
gss_buffer_desc status_string;
-gstring * g;
+gstring * g = NULL;

HDEBUG(D_auth)
{
@@ -610,9 +610,31 @@ build-time and export the result as a string into a header ourselves. */

 return string_fmt_append(g, "Library version: Heimdal: Runtime: %s\n"
                 " Build Info: %s\n",
-    heimdal_version, heimdal_long_version));
+    heimdal_version, heimdal_long_version);
 }


+# ifdef DYNLOOKUP
+#  define heimdal_gssapi_auth_info _auth_info
+# endif
+
+auth_info heimdal_gssapi_auth_info = {
+.drinfo = {
+  .driver_name =    US"heimdal_gssapi",                   /* lookup name */
+  .options =        auth_heimdal_gssapi_options,
+  .options_count =    &auth_heimdal_gssapi_options_count,
+  .options_block =    &auth_heimdal_gssapi_option_defaults,
+  .options_len =    sizeof(auth_heimdal_gssapi_options_block),
+  .init =        auth_heimdal_gssapi_init,
+# ifdef DYNLOOKUP
+  .dyn_magic =        AUTH_MAGIC,
+# endif
+  },
+.servercode =        auth_heimdal_gssapi_server,
+.clientcode =        NULL,
+.version_report =    auth_heimdal_gssapi_version_report,
+.macros_create =    NULL,
+};
+
 #endif   /*!MACRO_PREDEF*/
 #endif  /* AUTH_HEIMDAL_GSSAPI */


diff --git a/src/src/auths/heimdal_gssapi.h b/src/src/auths/heimdal_gssapi.h
index c438aae91..e1d308ac9 100644
--- a/src/src/auths/heimdal_gssapi.h
+++ b/src/src/auths/heimdal_gssapi.h
@@ -35,6 +35,6 @@ extern auth_heimdal_gssapi_options_block auth_heimdal_gssapi_option_defaults;
extern void auth_heimdal_gssapi_init(driver_instance *);
extern int auth_heimdal_gssapi_server(auth_instance *, uschar *);
extern int auth_heimdal_gssapi_client(auth_instance *, void *, int, uschar *, int);
-extern void auth_heimdal_gssapi_version_report(BOOL);
+extern gstring * auth_heimdal_gssapi_version_report(gstring *);

/* End of heimdal_gssapi.h */
diff --git a/src/src/auths/plaintext.c b/src/src/auths/plaintext.c
index 26ac4aeff..13d05d1e5 100644
--- a/src/src/auths/plaintext.c
+++ b/src/src/auths/plaintext.c
@@ -180,6 +180,29 @@ while ((s = string_nextinlist(&text, &sep, NULL, 0)))
return FAIL;
}

+
+# ifdef DYNLOOKUP
+#  define plaintext_auth_info _auth_info
+# endif
+
+auth_info plaintext_auth_info = {
+.drinfo = {
+  .driver_name =    US"plaintext",                   /* lookup name */
+  .options =        auth_plaintext_options,
+  .options_count =    &auth_plaintext_options_count,
+  .options_block =    &auth_plaintext_option_defaults,
+  .options_len =    sizeof(auth_plaintext_options_block),
+  .init =        auth_plaintext_init,
+# ifdef DYNLOOKUP
+  .dyn_magic =        AUTH_MAGIC,
+# endif
+  },
+.servercode =        auth_plaintext_server,
+.clientcode =        auth_plaintext_client,
+.version_report =    NULL,
+.macros_create =    NULL,
+};
+
 #endif    /*!MACRO_PREDEF*/
 #endif    /*AUTH_PLAINTEST*/
 /* End of plaintext.c */
diff --git a/src/src/auths/spa.c b/src/src/auths/spa.c
index 09d4e43a6..e76e0fc16 100644
--- a/src/src/auths/spa.c
+++ b/src/src/auths/spa.c
@@ -375,6 +375,28 @@ if (errno != 0 || buffer[0] != '3')
 return FAIL;
 }


+# ifdef DYNLOOKUP
+#  define spa_auth_info _auth_info
+# endif
+
+auth_info spa_auth_info = {
+.drinfo = {
+  .driver_name =    US"spa",                   /* lookup name */
+  .options =        auth_spa_options,
+  .options_count =    &auth_spa_options_count,
+  .options_block =    &auth_spa_option_defaults,
+  .options_len =    sizeof(auth_spa_options_block),
+  .init =        auth_spa_init,
+# ifdef DYNLOOKUP
+  .dyn_magic =        AUTH_MAGIC,
+# endif
+  },
+.servercode =        auth_spa_server,
+.clientcode =        auth_spa_client,
+.version_report =    NULL,
+.macros_create =    NULL,
+};
+
 #endif    /*!MACRO_PREDEF*/
 #endif    /*AUTH_SPA*/
 /* End of spa.c */
diff --git a/src/src/auths/tls.c b/src/src/auths/tls.c
index 0bcb675f7..534b53639 100644
--- a/src/src/auths/tls.c
+++ b/src/src/auths/tls.c
@@ -95,6 +95,28 @@ return auth_check_serv_cond(ablock);
 }



+# ifdef DYNLOOKUP
+#  define tls_auth_info _auth_info
+# endif
+
+auth_info tls_auth_info = {
+.drinfo = {
+  .driver_name =    US"tls",                   /* lookup name */
+  .options =        auth_tls_options,
+  .options_count =    &auth_tls_options_count,
+  .options_block =    &auth_tls_option_defaults,
+  .options_len =    sizeof(auth_tls_options_block),
+  .init =        auth_tls_init,
+# ifdef DYNLOOKUP
+  .dyn_magic =        AUTH_MAGIC,
+# endif
+  },
+.servercode =        auth_tls_server,
+.clientcode =        NULL,
+.version_report =    NULL,
+.macros_create =    NULL,
+};
+
 #endif    /*!MACRO_PREDEF*/
 #endif    /*AUTH_TLS*/
 /* End of tls.c */
diff --git a/src/src/drtables.c b/src/src/drtables.c
index 026f2ff97..c490e7f86 100644
--- a/src/src/drtables.c
+++ b/src/src/drtables.c
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/


-/* Copyright (c) The Exim Maintainers 2020 - 2023 */
+/* Copyright (c) The Exim Maintainers 2020 - 2024 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
/* SPDX-License-Identifier: GPL-2.0-or-later */
@@ -21,230 +21,82 @@ all described in src/EDITME. */
lookup_info **lookup_list;
int lookup_list_count = 0;

-/* Table of information about all possible authentication mechanisms. All
-entries are always present if any mechanism is declared, but the functions are
-set to NULL for those that are not compiled into the binary. */
+/* Lists of information about which drivers are included in the exim binary. */

-#ifdef AUTH_CRAM_MD5
-#include "auths/cram_md5.h"
-#endif
+auth_info * auths_available= NULL;
+router_info * routers_available = NULL;
+transport_info * transports_available = NULL;

-#ifdef AUTH_CYRUS_SASL
-#include "auths/cyrus_sasl.h"
-#endif

-#ifdef AUTH_DOVECOT
-#include "auths/dovecot.h"
-#endif

-#ifdef AUTH_EXTERNAL
-#include "auths/external.h"
-#endif
+#ifndef MACRO_PREDEF

-#ifdef AUTH_GSASL
-#include "auths/gsasl_exim.h"
+gstring *
+auth_show_supported(gstring * g)
+{
+uschar * b = US""               /* static-build authenticatornames */
+#if defined(AUTH_CRAM_MD5) && AUTH_CRAM_MD5!=2
+  " cram_md5"
 #endif
-
-#ifdef AUTH_HEIMDAL_GSSAPI
-#include "auths/heimdal_gssapi.h"
+#if defined(AUTH_CYRUS_SASL) && AUTH_CYRUS_SASL!=2
+  " cyrus_sasl"
 #endif
-
-#ifdef AUTH_PLAINTEXT
-#include "auths/plaintext.h"
+#if defined(AUTH_DOVECOT) && AUTH_DOVECOT!=2
+  " dovecot"
 #endif
-
-#ifdef AUTH_SPA
-#include "auths/spa.h"
+#if defined(AUTH_EXTERNAL) && AUTH_EXTERNAL!=2
+  " external"
 #endif
-
-#ifdef AUTH_TLS
-#include "auths/tls.h"
+#if defined(AUTH_GSASL) && AUTH_GSASL!=2
+  " gsasl"
 #endif
+#if defined(AUTH_HEIMDAL_GSSAPI) && AUTH_HEIMDAL_GSSAPI!=2
+  " heimdal_gssapi"
+#endif
+#if defined(AUTH_PLAINTEXT) && AUTH_PLAINTEXT!=2
+  " plaintext"
+#endif
+#if defined(AUTH_SPA) && AUTH_SPA!=2
+  " spa"
+#endif
+#if defined(AUTH_TLS) && AUTH_TLS!=2
+  " tls"
+#endif
+  ;


-auth_info * auths_available_newlist = NULL;
-auth_info auths_available_oldarray[] = {
-
-/* Checking by an expansion condition on plain text */
-
-#ifdef AUTH_CRAM_MD5
-  {
-  .drinfo = {
-    .driver_name =    US"cram_md5",            /* lookup name */
-    .options =        auth_cram_md5_options,
-    .options_count =    &auth_cram_md5_options_count,
-    .options_block =    &auth_cram_md5_option_defaults,
-    .options_len =    sizeof(auth_cram_md5_options_block),
-    .init =        auth_cram_md5_init,
-    },
-  .servercode =        auth_cram_md5_server,
-  .clientcode =        auth_cram_md5_client,
-  .version_report =    NULL,
-  .macros_create =    NULL,
-  },
-#endif
-
-#ifdef AUTH_CYRUS_SASL
-  {
-  .drinfo = {
-    .driver_name =    US"cyrus_sasl",
-    .options =        auth_cyrus_sasl_options,
-    .options_count =    &auth_cyrus_sasl_options_count,
-    .options_block =    &auth_cyrus_sasl_option_defaults,
-    .options_len =    sizeof(auth_cyrus_sasl_options_block),
-    .init =        auth_cyrus_sasl_init,
-    },
-  .servercode =        auth_cyrus_sasl_server,
-  .clientcode =        NULL,
-  .version_report =    auth_cyrus_sasl_version_report,
-  .macros_create =    NULL,
-  },
-#endif
-
-#ifdef AUTH_DOVECOT
-  {
-  .drinfo = {
-    .driver_name =    US"dovecot",
-    .options =        auth_dovecot_options,
-    .options_count =    &auth_dovecot_options_count,
-    .options_block =    &auth_dovecot_option_defaults,
-    .options_len =    sizeof(auth_dovecot_options_block),
-    .init =        auth_dovecot_init,
-    },
-  .servercode =        auth_dovecot_server,
-  .clientcode =        NULL,
-  .version_report =    NULL,
-  .macros_create =    NULL,
-  },
-#endif
-
-#ifdef AUTH_EXTERNAL
-  {
-  .drinfo = {
-    .driver_name =    US"external",
-    .options =        auth_external_options,
-    .options_count =    &auth_external_options_count,
-    .options_block =    &auth_external_option_defaults,
-    .options_len =    sizeof(auth_external_options_block),
-    .init =        auth_external_init,
-    },
-  .servercode =        auth_external_server,
-  .clientcode =        auth_external_client,
-  .version_report =    NULL,
-  .macros_create =    NULL,
-  },
-#endif
-
-#ifdef AUTH_GSASL
-  {
-  .drinfo = {
-    .driver_name =    US"gsasl",
-    .options =        auth_gsasl_options,
-    .options_count =    &auth_gsasl_options_count,
-    .options_block =    &auth_gsasl_option_defaults,
-    .options_len =    sizeof(auth_gsasl_options_block),
-    .init =        auth_gsasl_init,
-    },
-  .servercode =        auth_gsasl_server,
-  .clientcode =        auth_gsasl_client,
-  .version_report =    auth_gsasl_version_report,
-  .macros_create =    auth_gsasl_macros,
-  },
-#endif
-
-#ifdef AUTH_HEIMDAL_GSSAPI
-  {
-  .drinfo = {
-    .driver_name =    US"heimdal_gssapi",
-    .options =        auth_heimdal_gssapi_options,
-    .options_count =    &auth_heimdal_gssapi_options_count,
-    .options_block =    &auth_heimdal_gssapi_option_defaults,
-    .options_len =    sizeof(auth_heimdal_gssapi_options_block),
-    .init =        auth_heimdal_gssapi_init,
-    },
-  .servercode =        auth_heimdal_gssapi_server,
-  .clientcode =        NULL,
-  .version_report =    auth_heimdal_gssapi_version_report,
-  .macros_create =    NULL,
-  },
-#endif
-
-#ifdef AUTH_PLAINTEXT
-  {
-  .drinfo = {
-    .driver_name =    US"plaintext",
-    .options =        auth_plaintext_options,
-    .options_count =    &auth_plaintext_options_count,
-    .options_block =    &auth_plaintext_option_defaults,
-    .options_len =    sizeof(auth_plaintext_options_block),
-    .init =        auth_plaintext_init,
-    },
-  .servercode =        auth_plaintext_server,
-  .clientcode =        auth_plaintext_client,
-  .version_report =    NULL,
-  .macros_create =    NULL,
-  },
-#endif
-
-#ifdef AUTH_SPA
-  {
-  .drinfo = {
-    .driver_name =    US"spa",
-    .options =        auth_spa_options,
-    .options_count =    &auth_spa_options_count,
-    .options_block =    &auth_spa_option_defaults,
-    .options_len =    sizeof(auth_spa_options_block),
-    .init =        auth_spa_init,
-    },
-  .servercode =        auth_spa_server,
-  .clientcode =        auth_spa_client,
-  .version_report =    NULL,
-  .macros_create =    NULL,
-  },
-#endif
-
-#ifdef AUTH_TLS
-  {
-  .drinfo = {
-    .driver_name =    US"tls",
-    .options =        auth_tls_options,
-    .options_count =    &auth_tls_options_count,
-    .options_block =    &auth_tls_option_defaults,
-    .options_len =    sizeof(auth_tls_options_block),
-    .init =        auth_tls_init,
-    },
-  .servercode =        auth_tls_server,
-  .clientcode =        NULL,
-  .version_report =    NULL,
-  .macros_create =    NULL,
-  },
-#endif
-
-  { .drinfo = { .driver_name = US"" }}        /* end marker */
-};
-
-
-/* Tables of information about which routers and transports are included in the
-exim binary. */
-
-/* Pull in the necessary header files */
-
-#include "routers/rf_functions.h"
-
-
-router_info * routers_available = NULL;
-transport_info * transports_available = NULL;
-
-
-
-#ifndef MACRO_PREDEF
+uschar * d = US""        /* dynamic-module authenticator names */
+#if defined(AUTH_CRAM_MD5) && AUTH_CRAM_MD5==2
+  " cram_md5"
+#endif
+#if defined(AUTH_CYRUS_SASL) && AUTH_CYRUS_SASL==2
+  " cyrus_sasl"
+#endif
+#if defined(AUTH_DOVECOT) && AUTH_DOVECOT==2
+  " dovecot"
+#endif
+#if defined(AUTH_EXTERNAL) && AUTH_EXTERNAL==2
+  " external"
+#endif
+#if defined(AUTH_GSASL) && AUTH_GSASL==2
+  " gsasl"
+#endif
+#if defined(AUTH_HEIMDAL_GSSAPI) && AUTH_HEIMDAL_GSSAPI==2
+  " heimdal_gssapi"
+#endif
+#if defined(AUTH_PLAINTEXT) && AUTH_PLAINTEXT==2
+  " plaintext"
+#endif
+#if defined(AUTH_SPA) && AUTH_SPA==2
+  " spa"
+#endif
+#if defined(AUTH_TLS) && AUTH_TLS==2
+  " tls"
+#endif
+  ;


-gstring *
-auth_show_supported(gstring * g)
-{
-g = string_cat(g, US"Authenticators:");
-for (auth_info * ai = auths_available_oldarray; ai->drinfo.driver_name[0]; ai++)
-           g = string_fmt_append(g, " %s", ai->drinfo.driver_name);
-return string_cat(g, US"\n");
+if (*b) g = string_fmt_append(g, "Authenticators (built-in):%s\n", b);
+if (*d) g = string_fmt_append(g, "Authenticators (dynamic): %s\n", d);
+return g;
 }


gstring *
diff --git a/src/src/exim.c b/src/src/exim.c
index 8eb602a17..66746e6bb 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -1382,8 +1382,7 @@ g = show_db_version(g);
show_string(is_stdout, g);
g = NULL;

-//for (auth_info * ai= auths_available; *ai->drinfo.driver_name != '\0'; ai++)
-for (auth_info * ai = auths_available_newlist; ai; ai = (auth_info *)ai->drinfo.next)
+for (auth_info * ai = auths_available; ai; ai = (auth_info *)ai->drinfo.next)
   if (ai->version_report)
     g = (*ai->version_report)(g);


diff --git a/src/src/globals.h b/src/src/globals.h
index 7fc888f5b..9731b7b58 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -374,8 +374,7 @@ extern uschar *authenticated_sender;   /* From AUTH on MAIL */
 extern BOOL    authentication_failed;  /* TRUE if AUTH was tried and failed */
 extern uschar *authenticator_name;     /* for debug and error messages */
 extern uschar *auth_advertise_hosts;   /* Only advertise to these */
-extern auth_info auths_available_oldarray[];    /* Vector of available auth mechanisms */
-extern auth_info * auths_available_newlist;
+extern auth_info * auths_available;    /* List of available auth mechanisms */
 extern auth_instance *auths;           /* Chain of instantiated auths */
 extern auth_instance auth_defaults;    /* Default values */
 extern uschar *auth_defer_msg;         /* Error message for log */
diff --git a/src/src/readconf.c b/src/src/readconf.c
index 57788afc3..532e0774c 100644
--- a/src/src/readconf.c
+++ b/src/src/readconf.c
@@ -435,10 +435,7 @@ uschar buf[EXIM_DRIVERNAME_MAX];
 options_from_list(optionlist_auths, optionlist_auths_size,
   US"AUTHENTICATORS", NULL);


-#ifdef old
-for (struct auth_info * ai = auths_available; ai->drinfo.driver_name[0]; ai++)
-#endif
-for (driver_info * di = (driver_info *)auths_available_newlist; di; di = di->next)
+for (driver_info * di = (driver_info *)auths_available; di; di = di->next)
{
auth_info * ai = (auth_info *)di;

@@ -3738,7 +3735,7 @@ driver_info * di;
int len;
DIR * dd;

-/* First scan the list of statically-built drivers. */
+/* First scan the list of driver seen so far. */

 for (di = *info_anchor; di; di = di->next)
   if (Ustrcmp(d->driver_name, di->driver_name) == 0)
@@ -3859,8 +3856,8 @@ Arguments:
   instance_size              size of instance block
   driver_optionlist          generic option list
   driver_optionlist_count    count of generic option list
-  class                      "router", "transport", or "authenticator"
-                  for error message
+  class                      "router", "transport", or "auth"
+                  for filename component (and error message)


 Returns:                     nothing
 */
@@ -4328,25 +4325,65 @@ auths_init(void)
 #ifndef DISABLE_PIPE_CONNECT
 int nauths = 0;
 #endif
-
-for (auth_info * tblent = auths_available_oldarray;
-    *tblent->drinfo.driver_name; tblent++)
+int old_pool = store_pool;
+store_pool = POOL_PERM;
   {
-  driver_info * listent = store_get(sizeof(auth_info), tblent);
-  memcpy(listent, tblent, sizeof(auth_info));
-  listent->next = (driver_info *)auths_available_newlist;
-  auths_available_newlist = (auth_info *)listent;
+  driver_info ** anchor = (driver_info **) &auths_available;
+  extern auth_info cram_md5_auth_info;
+  extern auth_info cyrus_sasl_auth_info;
+  extern auth_info dovecot_auth_info;
+  extern auth_info external_auth_info;
+  extern auth_info gsasl_auth_info;
+  extern auth_info heimdal_gssapi_auth_info;
+  extern auth_info plaintext_auth_info;
+  extern auth_info spa_auth_info;
+  extern auth_info tls_auth_info;
+
+  /* Add the transport drivers that are built for static linkage to the
+  list of availables. */
+
+#if defined(AUTH_CRAM_MD5) && AUTH_CRAM_MD5!=2
+  add_driver_info(anchor, &cram_md5_auth_info.drinfo, sizeof(auth_info));
+#endif
+#if defined(AUTH_CYRUS_SASL) && AUTH_CYRUS_SASL!=2
+  add_driver_info(anchor, &cyrus_sasl_auth_info.drinfo, sizeof(auth_info));
+#endif
+#if defined(AUTH_DOVECOT) && AUTH_DOVECOT!=2
+  add_driver_info(anchor, &dovecot_auth_info.drinfo, sizeof(auth_info));
+#endif
+#if defined(AUTH_EXTERNAL) && AUTH_EXTERNAL!=2
+  add_driver_info(anchor, &external_auth_info.drinfo, sizeof(auth_info));
+#endif
+#if defined(AUTH_GSASL) && AUTH_GSASL!=2
+  add_driver_info(anchor, &gsasl_auth_info.drinfo, sizeof(auth_info));
+#endif
+#if defined(AUTH_HEIMDAL_GSSAPI) && AUTH_HEIMDAL_GSSAPI!=2
+  add_driver_info(anchor, &heimdal_gssapi_auth_info.drinfo, sizeof(auth_info));
+#endif
+#if defined(AUTH_PLAINTEXT) && AUTH_PLAINTEXT!=2
+  add_driver_info(anchor, &plaintext_auth_info.drinfo, sizeof(auth_info));
+#endif
+#if defined(AUTH_SPA) && AUTH_SPA!=2
+  add_driver_info(anchor, &spa_auth_info.drinfo, sizeof(auth_info));
+#endif
+#if defined(AUTH_TLS) && AUTH_TLS!=2
+  add_driver_info(anchor, &tls_auth_info.drinfo, sizeof(auth_info));
+#endif
   }
+store_pool = old_pool;


+/* Read the config file "authenticators" section, creating an auth instance list.
+For any yet-undiscovered driver, check for a loadable module and add it to
+those available. */

 readconf_driver_init((driver_instance **)&auths,      /* chain anchor */
-  (driver_info **)&auths_available_newlist,    /* available drivers */
+  (driver_info **)&auths_available,  /* available drivers */
   sizeof(auth_info),                 /* size of info block */
   &auth_defaults,                    /* default values for generic options */
   sizeof(auth_instance),             /* size of instance block */
   optionlist_auths,                  /* generic options */
   optionlist_auths_size,
-  US"authenticator");
+  US"auth");


 for (auth_instance * au = auths; au; au = au->drinst.next)
   {
@@ -4367,7 +4404,7 @@ for (auth_instance * au = auths; au; au = au->drinst.next)
 #endif
   }
 #ifndef DISABLE_PIPE_CONNECT
-f.smtp_in_early_pipe_no_auth = nauths > 16;
+f.smtp_in_early_pipe_no_auth = nauths > 16;    /* bits in bitmap limit */
 #endif
 }


diff --git a/src/src/transports/Makefile b/src/src/transports/Makefile
index 43418fd22..895dad57f 100644
--- a/src/src/transports/Makefile
+++ b/src/src/transports/Makefile
@@ -25,8 +25,9 @@ transports.a:    $(OBJ) smtp_socks.o tf_maildir.o
 .c.o:;           @echo "$(CC) $*.c"
          $(FE)$(CC) -c $(CFLAGS) $(INCLUDE) $*.c


+SO_FLAGS = -DDYNLOOKUP $(CFLAGS_DYNAMIC) $(CFLAGS) $(INCLUDE) $(DLFLAGS)
 .c.so:;          @echo "$(CC) -shared $*.c"
-         $(FE)$(CC) -DDYNLOOKUP $(CFLAGS_DYNAMIC) $(CFLAGS) $(INCLUDE) $(DLFLAGS) $*.c -o $@
+         $(FE)$(CC) $(SO_FLAGS) $*.c -o $@



 $(OBJ) $(MOD): $(HDRS)
@@ -47,7 +48,6 @@ tf_maildir.o:            tf_maildir.c tf_maildir.h appendfile.h


 appendfile.so: appendfile.c appendfile.h tf_maildir.c tf_maildir.h
     @echo "$(CC) -shared appendfile.c tf_maildir.c"
-    $(FE)$(CC) -DDYNLOOKUP $(CFLAGS_DYNAMIC) $(CFLAGS) $(INCLUDE) $(DLFLAGS) \
-        appendfile.c tf_maildir.c -o $@
+    $(FE)$(CC) $(SO_FLAGS) appendfile.c tf_maildir.c -o $@


# End
diff --git a/test/confs/0000 b/test/confs/0000
index 5db8ac8cf..e25ac4b4f 100644
--- a/test/confs/0000
+++ b/test/confs/0000
@@ -12,5 +12,6 @@ keep_environment =

begin routers
begin transports
+begin authenticators

 # End
diff --git a/test/runtest b/test/runtest
index 632672324..0c9f2808b 100755
--- a/test/runtest
+++ b/test/runtest
@@ -1160,7 +1160,7 @@ RESET_AFTER_EXTRA_LINE_READ:
         (?: .*\sBerkeley\ DB
           | \sProbably\ (?:Berkeley\ DB|ndbm|GDBM)
           | \sUsing\ (?:tdb|sqlite3)
-          | Authenticators:
+          | Authenticators\ \((?:built-in|dynamic)\):
           | Lookups(?:\(built-in\))?:
           | Support\ for:
           | Routers\ \((?:built-in|dynamic)\):
@@ -3741,12 +3741,13 @@ while (<EXIMINFO>)
     @parm_lookups{keys %temp_lookups} = values %temp_lookups;
     }


-  elsif (/^Authenticators: (.*)/)
+  elsif (/^Authenticators \((?:built-in|dynamic)\):  ?(.*)/)
     {
     print;
     @temp = split /(\s+)/, $1;
     push(@temp, ' ');
-    %parm_authenticators = @temp;
+    my %temp_auths= @temp;
+    @parm_authenticators{keys %temp_auths} = values %temp_auths;
     }


elsif (/^Routers \((?:built-in|dynamic)\): ?(.*)/)
diff --git a/test/stderr/0402 b/test/stderr/0402
index 8c4dda874..d0906810d 100644
--- a/test/stderr/0402
+++ b/test/stderr/0402
@@ -546,6 +546,9 @@ expanded: 'TESTSUITE/test-mail/junk'
file is not a filter file
parse_forward_list: TESTSUITE/test-mail/junk
extract item: TESTSUITE/test-mail/junk
+try option errors_to
+try option headers_add
+try option headers_remove
try option file_transport
try option transport
set transport ft1
@@ -604,6 +607,9 @@ expanded: 'TESTSUITE/test-mail/junk'
file is not a filter file
parse_forward_list: TESTSUITE/test-mail/junk
extract item: TESTSUITE/test-mail/junk
+try option errors_to
+try option headers_add
+try option headers_remove
try option file_transport
try option transport
set transport ft1
@@ -650,6 +656,9 @@ try option set
calling r3 router
r3 router called for userz@???
domain = test.ex
+try option errors_to
+try option headers_add
+try option headers_remove
try option transport
set transport t2
queued for t2 transport: local_part = userz
@@ -688,6 +697,9 @@ try option set
calling r2 router
r2 router called for usery@???
domain = test.ex
+try option errors_to
+try option headers_add
+try option headers_remove
try option transport
set transport t1
queued for t1 transport: local_part = usery
@@ -719,6 +731,9 @@ try option set
calling r1 router
r1 router called for CALLER@???
domain = test.ex
+try option errors_to
+try option headers_add
+try option headers_remove
try option transport
set transport t1
queued for t1 transport: local_part = CALLER
diff --git a/test/stderr/0544 b/test/stderr/0544
index de449b123..84ecb04f3 100644
--- a/test/stderr/0544
+++ b/test/stderr/0544
@@ -369,10 +369,16 @@ admin user
dropping to exim gid; retaining priv uid
try option router_home_directory
try option set
+try option errors_to
+try option headers_add
+try option headers_remove
try option transport
try option unseen
try option router_home_directory
try option set
+try option errors_to
+try option headers_add
+try option headers_remove
try option transport
try option unseen
try option multi_domain
diff --git a/test/stderr/5410 b/test/stderr/5410
index 4ee810ac3..471e04156 100644
--- a/test/stderr/5410
+++ b/test/stderr/5410
@@ -95,6 +95,9 @@ processing address_data
domain.com in "*"?
list element: *
domain.com in "*"? yes (matched "*")
+try option errors_to
+try option headers_add
+try option headers_remove
try option transport
try option unseen
----------- end verify ------------
@@ -122,6 +125,9 @@ processing address_data
domain.com in "*"?
list element: *
domain.com in "*"? yes (matched "*")
+try option errors_to
+try option headers_add
+try option headers_remove
try option transport
try option unseen
try option interface
@@ -766,6 +772,9 @@ processing address_data
domain.com in "*"?
list element: *
domain.com in "*"? yes (matched "*")
+try option errors_to
+try option headers_add
+try option headers_remove
try option transport
try option unseen
----------- end verify ------------
@@ -793,6 +802,9 @@ processing address_data
domain.com in "*"?
list element: *
domain.com in "*"? yes (matched "*")
+try option errors_to
+try option headers_add
+try option headers_remove
try option transport
try option unseen
try option interface
@@ -1386,6 +1398,9 @@ processing address_data
domain.com in "*"?
list element: *
domain.com in "*"? yes (matched "*")
+try option errors_to
+try option headers_add
+try option headers_remove
try option transport
try option unseen
----------- end verify ------------
@@ -1413,6 +1428,9 @@ processing address_data
domain.com in "*"?
list element: *
domain.com in "*"? yes (matched "*")
+try option errors_to
+try option headers_add
+try option headers_remove
try option transport
try option unseen
try option interface

--
## subscription configuration (requires account):
## https://lists.exim.org/mailman3/postorius/lists/exim-cvs.lists.exim.org/
## unsubscribe (doesn't require an account):
## exim-cvs-unsubscribe@???
## Exim details at http://www.exim.org/
## Please use the Wiki with this list - http://wiki.exim.org/