1,230 changes: 698 additions & 532 deletions doc/doc-docbook/spec.xfpt

Large diffs are not rendered by default.

153 changes: 153 additions & 0 deletions doc/doc-txt/ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,155 @@ This document describes *changes* to previous versions, that might
affect Exim's operation, with an unchanged configuration file. For new
options, and new features, see the NewStuff file next to this ChangeLog.

Exim version 4.96
-----------------

JH/01 Move the wait-for-next-tick (needed for unique messmage IDs) from
after reception to before a subsequent reception. This should
mean slightly faster delivery, and also confirmation of reception
to senders.

JH/02 Move from using the pcre library to pcre2. The former is no longer
being developed or supported (by the original developer).

JH/03 Constification work in the filters module required a major version
bump for the local-scan API. Specifically, the "headers_charset"
global which is visible via the API is now const and may therefore
not be modified by local-scan code.

JH/04 Fix ClamAV TCP use under FreeBSD. Previously the OS-specific shim for
sendfile() didi not account for the way the ClamAV driver code called it.

JH/05 Bug 2819: speed up command-line messages being read in. Previously a
time check was being done for every character; replace that with one
per buffer.

JH/06 Bug 2815: Fix ALPN sent by server under OpenSSL. Previously the string
sent was prefixed with a length byte.

JH/07 Change the SMTP feature name for pipelining connect to be compliant with
RFC 5321. Previously Dovecot (at least) would log errors during
submission.

JH/08 Remove stripping of the binaries from the FreeBSD build. This was added
in 4.61 without a reason logged. Binaries will be bigger, which might
matter on diskspace-constrained systems, but debug is easier.

JH/09 Fix macro-definition during "-be" expansion testing. The move to
write-protected store for macros had not accounted for these runtime
additions; fix by removing this protection for "-be" mode.

JH/10 Convert all uses of select() to poll(). FreeBSD 12.2 was found to be
handing out large-numbered file descriptors, violating the usual Unix
assumption (and required by Posix) that the lowest possible number will be
allocated by the kernel when a new one is needed. In the daemon, and any
child procesees, values higher than 1024 (being bigger than FD_SETSIZE)
are not useable for FD_SET() [and hence select()] and overwrite the stack.
Assorted crashes happen.

JH/11 Fix use of $sender_host_name in daemon process. When used in certain
main-section options or in a connect ACL, the value from the first ever
connection was never replaced for subsequent connections. Found by
Wakko Warner.

JH/12 Bug 2838: Fix for i32lp64 hard-align platforms. Found for SPARC Linux,
though only once PCRE2 was introduced: the memory accounting used under
debug offset allocations by an int, giving a hard trap in early startup.
Change to using a size_t. Debug and fix by John Paul Adrian Glaubitz.

JH/13 Bug 2845: Fix handling of tls_require_ciphers for OpenSSL when a value
with underbars is given. The write-protection of configuration introduced
in 4.95 trapped when normalisation was applied to an option not needing
expansion action.

JH/14 Bug 1895: TLS: Deprecate RFC 5114 Diffie-Hellman parameters.

JH/15 Fix a resource leak in *BSD. An off-by-one error resulted in the daemon
failing to close the certificates directory, every hour or any time it
was touched.

JH/16 Debugging initiated by an ACL control now continues through into routing
and transport processes. Previously debugging stopped any time Exim
re-execs, or for processing a queued message.

JH/17 The "expand" debug selector now gives more detail, specifically on the
result of expansion operators and items.

JH/18 Bug 2751: Fix include_directory in redirect routers. Previously a
bad comparison between the option value and the name of the file to
be included was done, and a mismatch was wrongly identified.
4.88 to 4.95 are affected.

JH/19 Support for Berkeley DB versions 1 and 2 is withdrawn.

JH/20 When built with NDBM for hints DB's check for nonexistence of a name
supplied as the db file-pair basename. Previously, if a directory
path was given, for example via the autoreply "once" option, the DB
file.pag and file.dir files would be created in that directory's
parent.

JH/21 Remove the "allow_insecure_tainted_data" main config option and the
"taint" log_selector. These were previously deprecated.

JH/22 Fix static address-list lookups to properly return the matched item.
Previously only the domain part was returned.

JH/23 Bug 2864: FreeBSD: fix transport hang after 4xx/5xx response. Previously
the call into OpenSSL to send a TLS Close was being repeated; this
resulted in the library waiting for the peer's Close. If that was never
sent we waited forever. Fix by tracking send calls.

JH/24 The ${run} expansion item now expands its command string elements after
splitting. Previously it was before; the new ordering makes handling
zero-length arguments simpler. The old ordering can be obtained by
appending a new option "preexpand", after a comma, to the "run".

JH/25 Taint-check exec arguments for transport-initiated external processes.
Previously, tainted values could be used. This affects "pipe", "lmtp" and
"queryprogram" transport, transport-filter, and ETRN commands.
The ${run} expansion is also affected: in "preexpand" mode no part of
the command line may be tainted, in default mode the executable name
may not be tainted.

JH/26 Fix CHUNKING on a continued-transport. Previously the usabliility of
the the facility was not passed across execs, and only the first message
passed over a connection could use BDAT; any further ones using DATA.

JH/27 Support the PIPECONNECT facility in the smtp transport when the helo_data
uses $sending_ip_address and an interface is specified.
Previously any use of the local address in the EHLO name disabled
PIPECONNECT, the common case being to use the rDNS of it.

JH/28 OpenSSL: fix transport-required OCSP stapling verification under session
resumption. Previously verify failed because no certificate status is
passed on the wire for the restarted session. Fix by using the recorded
ocsp status of the stored session for the new connection.

JH/29 TLS resumption: the key for session lookup in the client now includes
more info that a server could potentially use in configuring a TLS
session, avoiding oferring mismatching sessions to such a server.
Previously only the server IP was used.

JH/30 Fix string_copyn() for limit greater than actual string length.
Previously the copied amount was the limit, which could result in a
overlapping memcpy for newly allocated destination soon after a
source string shorter than the limit. Found/investigated by KM.

JH/31 Bug 2886: GnuTLS: Do not free the cached creds on transport connection
close; it may be needed for a subsequent connection. This caused a
SEGV on primary-MX defer. Found/investigated by Gedalya & Andreas.

JH/32 Fix CHUNKING for a second message on a connection when the first was
rejected. Previously we did not reset the chunking-offered state, and
erroneously rejected the BDAT command. Investigation help from
Jesse Hathaway.

JH/33 Fis ${srs_encode ...} to handle an empty sender address, now returning
an empty address. Previously the expansion returned an error.

HS/01 Bug 2855: Handle a v4mapped sender address given us by a frontending
proxy. Previously these were misparsed, leading to paniclog entries.


Exim version 4.95
-----------------
Expand Down Expand Up @@ -760,6 +909,10 @@ JH/47 ARC: fix crash in signing, triggered when a configuration error failed
to do ARC verification. The Authentication-Results: header line added
by the configuration then had no ARC item.

JH/48 Bug 2784: fix shutdown=no in the ${readsocket) expansion item. Previously
an incorrect mode was used for reading the result, resulting in it being
ignored.


Exim version 4.92
-----------------
Expand Down
26 changes: 25 additions & 1 deletion doc/doc-txt/NewStuff
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,30 @@ Before a formal release, there may be quite a lot of detail so that people can
test from the snapshots or the Git before the documentation is updated. Once
the documentation is updated, this file is reduced to a short list.

Version 4.96
------------

1. A new ACL condition: seen. Records/tests a timestamp against a key.

2. A variant of the "mask" expansion operator to give normalised IPv6.

3. UTC output option for exim_dumpdb, exim_fixdb.

4. An event for failing TLS connects to the daemon.

5. The ACL "debug" control gains options "stop", "pretrigger" and "trigger".

6. Query-style lookups are now checked for quoting, if the query string is
built using untrusted data ("tainted"). For now lack of quoting is merely
logged; a future release will upgrade this to an error.

7. The expansion conditions match_<list-type> and inlist now set $value for
the expansion of the "true" result of the ${if}. With a static list, this
can be used for de-tainting.

8. Recipient verify callouts now set $domain_data & $local_part_data, with
de-tainted values.

Version 4.95
------------

Expand Down Expand Up @@ -48,7 +72,7 @@ Version 4.95

13. Option "smtp_accept_max_per_connection" is now expanded.

14. Log selector "queue_size_exclusive", enabled by default, to exclude the
14. Log selector "queue_time_exclusive", enabled by default, to exclude the
time taken for reception from QT log elements.

15. Main option "smtp_backlog_monitor", to set a level above which listen
Expand Down
3 changes: 3 additions & 0 deletions doc/doc-txt/OptionLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,9 @@ hold_domains domain list unset main
home_directory string* unset transports 4.00 replaces individual options
host_all_ignored string "defer" manualroute 4.67
host_find_failed string "freeze" manualroute 4.00
host_name_extract string
"${if and {{match{.outlook.com\\$}{$host}} {match{$item}{\\N^250-([\\w.]+)\\s\\N}}} {$1}}"
smtp 4.96
host_lookup host list unset main 3.00
host_lookup_order string list "bydns:byaddr" main 4.30
host_reject_connection host list unset main 4.00
Expand Down
3 changes: 2 additions & 1 deletion doc/doc-txt/dbm.discuss.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ some time, and various releases 2.x began to appear towards the end of 1997. In
November 1999, version 3.0 was released, and the ending of support for 2.7.7,
the last 2.x release, was announced for November 2000. (Support for 1.85 has
already ceased.) There were further 3.x releases, but by the end of 2001, the
current release was 4.0.14.
current release was 4.0.14. In 2022 it was 5.3.28 on Linux (the then-owner
has developed it further but Exim does not support anything after 5.x).

There are major differences in implementation and interface between the DB 1.x
and 2.x/3.x/4.x releases, and they are best considered as two independent dbm
Expand Down
56 changes: 0 additions & 56 deletions doc/doc-txt/experimental-spec.txt
Original file line number Diff line number Diff line change
Expand Up @@ -292,62 +292,6 @@ These four steps are explained in more details below.



SRS (Sender Rewriting Scheme) Support (using libsrs_alt)
--------------------------------------------------------------
See also the main docs, for an alternative native support implementation.

Exim can be built with SRS support using Miles Wilton's
libsrs_alt library. The current version of the supported
library is 0.5, there are reports of 1.0 working.

In order to use SRS, you must get a copy of libsrs_alt from

https://opsec.eu/src/srs/

(not the original source, which has disappeared.)

Unpack the tarball, then refer to MTAs/README.EXIM
to proceed. You need to set

EXPERIMENTAL_SRS_ALT=yes

in your Local/Makefile.

The built-in support, included by SUPPORT_SRS,
shuold *not* be enabled if you wish to use the libsrs_alt
version.

The following main-section options become available:
srs_config string
srs_hashlength int
srs_hashmin int
srs_maxage int
srs_secrets string
srs_usehash bool
srs_usetimestamp bool

The redirect router gains these options (all of type string, unset by default):
srs
srs_alias
srs_condition
srs_dbinsert
srs_dbselect

The following variables become available:
$srs_db_address
$srs_db_key
$srs_orig_recipient
$srs_orig_sender
$srs_recipient
$srs_status

The predefined feature-macro _HAVE_SRS will be present.
Additional delivery log line elements, tagged with "SRS=" will show the srs sender.
For configuration information see https://github.com/Exim/exim/wiki/SRS .




DCC Support
--------------------------------------------------------------
Distributed Checksum Clearinghouse; http://www.rhyolite.com/dcc/
Expand Down
2 changes: 1 addition & 1 deletion release-process/scripts/mk_exim_release
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env perl
# Copyright (c) The Exim Maintainers 2016-2018
# Copyright (c) The Exim Maintainers 2016 - 2021

use strict;
use warnings;
Expand Down
2 changes: 2 additions & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# appropriate links, and then creating and running the main makefile in that
# directory.

# Copyright (c) The Exim Maintainers 2022
# Copyright (c) University of Cambridge, 1995 - 2018
# See the file NOTICE for conditions of use and distribution.

Expand Down Expand Up @@ -102,6 +103,7 @@ distclean:; $(RM_COMMAND) -rf build-* cscope*
cscope.files: FRC
echo "-q" > $@
echo "-p3" >> $@
-bd=build-$(buildname); [ -d $$bd ] && echo -e "$$bd/config.h\n$$bd/Makefile" >> $@
find src Local OS exim_monitor -name "*.[cshyl]" -print \
-o -name "os.[ch]*" -print \
-o -name "*akefile*" -print \
Expand Down
11 changes: 5 additions & 6 deletions src/OS/Makefile-Base
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
# optional, Local/* files at the front of this file, to create Makefile in the
# build directory.
#
# Copyright (c) The Exim Maintainers 1995 - 2018
# Copyright (c) The Exim Maintainers 2020
# Copyright (c) The Exim Maintainers 1995 - 2022

SHELL = $(MAKE_SHELL)
SCRIPTS = ../scripts
Expand Down Expand Up @@ -476,7 +475,6 @@ OBJ_EXPERIMENTAL = arc.o \
dmarc.o \
imap_utf7.o \
spf.o \
srs.o \
utf8.o

# Targets for final binaries; the main one has a build number which is
Expand Down Expand Up @@ -637,11 +635,12 @@ eximon.bin: $(EXIMON_EDITME) eximon $(OBJ_MONBIN) ../exim_monitor/em_version.c \
HDRS = blob.h \
config.h \
dbfunctions.h \
dbstuff.h \
exim.h \
functions.h \
globals.h \
hash.h \
hintsdb.h \
hintsdb_structs.h \
local_scan.h \
macros.h \
mytypes.h \
Expand All @@ -650,10 +649,11 @@ HDRS = blob.h \
os.h
PHDRS = ../config.h \
../dbfunctions.h \
../dbstuff.h \
../exim.h \
../functions.h \
../globals.h \
../hintsdb.h \
../hintsdb_structs.h \
../local_scan.h \
../macros.h \
../mytypes.h \
Expand Down Expand Up @@ -842,7 +842,6 @@ dcc.o: $(HDRS) dcc.h dcc.c
dmarc.o: $(HDRS) pdkim/pdkim.h dmarc.h dmarc.c
imap_utf7.o: $(HDRS) imap_utf7.c
spf.o: $(HDRS) spf.h spf.c
srs.o: $(HDRS) srs.h srs.c
utf8.o: $(HDRS) utf8.c

# The module containing tables of available lookups, routers, auths, and
Expand Down
2 changes: 1 addition & 1 deletion src/OS/Makefile-Default
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ CC=gcc

# PCRE_LIBS contains the library to be linked for PCRE

PCRE_LIBS=-lpcre
PCRE_LIBS=-lpcre2-8


# LIBS and EXTRALIBS contain library settings that are used on linking
Expand Down
2 changes: 1 addition & 1 deletion src/OS/Makefile-FreeBSD
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Copyright (c) The Exim Maintainers 2020

CHOWN_COMMAND=/usr/sbin/chown
STRIP_COMMAND=/usr/bin/strip
#STRIP_COMMAND=/usr/bin/strip
CHMOD_COMMAND=/bin/chmod


Expand Down
6 changes: 3 additions & 3 deletions src/OS/Makefile-OpenBSD
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Exim: OS-specific make file for OpenBSD
# Copyright (c) The Exim Maintainers 2020
# Copyright (c) The Exim Maintainers 2022

CHOWN_COMMAND=/usr/sbin/chown
CHGRP_COMMAND=/usr/sbin/chgrp
Expand All @@ -24,7 +24,7 @@ EXIWHAT_KILL_SIGNAL=-USR1

HAVE_IPV6=YES

# OpenBSD always ships with Berkeley DB
USE_DB=yes
# OpenBSD ships with a too-old Berkeley DB. NDBM is the default if we don't specify one.
#USE_DB=yes

# End
6 changes: 4 additions & 2 deletions src/OS/os.c-FreeBSD
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*************************************************/

/* Copyright (c) Jeremy Harris 1995 - 2020 */
/* Copyright (c) The Exim Maintainers 2021 */
/* See the file NOTICE for conditions of use and distribution. */

/* FreeBSD-specific code. This is concatenated onto the generic
Expand All @@ -16,10 +17,11 @@ Sendfile shim
ssize_t
os_sendfile(int out, int in, off_t * offp, size_t cnt)
{
off_t loff = *offp, written;
off_t loff = offp ? *offp : 0;
off_t written;

if (sendfile(in, out, loff, cnt, NULL, &written, 0) < 0) return (ssize_t)-1;
*offp = loff + written;
if (offp) *offp = loff + written;
return (ssize_t)written;
}

Expand Down
7 changes: 6 additions & 1 deletion src/OS/os.h-FreeBSD
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* Exim: OS-specific C header file for FreeBSD */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* Copyright (c) The Exim Maintainers 2020 */
/* Copyright (c) The Exim Maintainers 2020 - 2021 */
/* See the file NOTICE for conditions of use and distribution. */


Expand Down Expand Up @@ -58,6 +58,11 @@ performance on outgoing mail a bit. */
#define OS_SENDFILE
extern ssize_t os_sendfile(int, int, off_t *, size_t);

#ifdef PID_T_FMT
# undef PID_T_FMT
#endif
#define PID_T_FMT "%d"


/*******************/

Expand Down
2 changes: 1 addition & 1 deletion src/OS/os.h-GNU
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Exim: OS-specific C header file for GNU/Hurd */
/* Copyright (c) The Exim Maintainers 2020 */
/* Copyright (c) The Exim Maintainers 2020 - 2021 */

#include <features.h>

Expand Down
1 change: 1 addition & 0 deletions src/OS/os.h-Linux
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* Exim: OS-specific C header file for Linux */
/* Copyright (c) University of Cambridge 1995 - 2020 */
/* Copyright (c) The Exim Maintainers 2021 */
/* See the file NOTICE for conditions of use and distribution. */


Expand Down
1 change: 1 addition & 0 deletions src/OS/os.h-OpenBSD
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* Exim: OS-specific C header file for OpenBSD */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* Copyright (c) The Exim Maintainers 2021 */
/* See the file NOTICE for conditions of use and distribution. */


Expand Down
1 change: 1 addition & 0 deletions src/OS/os.h-SunOS5
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* Exim: OS-specific C header file for SunOS5 aka Solaris */
/* Copyright (c) The Exim Maintainers 2021 */

#define CRYPT_H
#define HAVE_MMAP
Expand Down
3 changes: 2 additions & 1 deletion src/OS/unsupported/os.c-IRIX
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2022 */
/* Copyright (c) University of Cambridge 2001 */
/* See the file NOTICE for conditions of use and distribution. */

Expand Down Expand Up @@ -59,7 +60,7 @@ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
log_write(0, LOG_PANIC_DIE, "iflist-sysctl-estimate failed: %s",
strerror(errno));

buf = store_get(needed, FALSE);
buf = store_get(needed, GET_UNTAINTED);

if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
log_write(0, LOG_PANIC_DIE, "sysctl of ifnet list failed: %s",
Expand Down
3 changes: 2 additions & 1 deletion src/OS/unsupported/os.c-IRIX6
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2022 */
/* Copyright (c) University of Cambridge 2001 */
/* See the file NOTICE for conditions of use and distribution. */

Expand Down Expand Up @@ -59,7 +60,7 @@ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
log_write(0, LOG_PANIC_DIE, "iflist-sysctl-estimate failed: %s",
strerror(errno));

buf = store_get(needed, FALSE);
buf = store_get(needed, GET_UNTAINTED);

if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
log_write(0, LOG_PANIC_DIE, "sysctl of ifnet list failed: %s",
Expand Down
3 changes: 2 additions & 1 deletion src/OS/unsupported/os.c-IRIX632
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2022 */
/* Copyright (c) University of Cambridge 2001 */
/* See the file NOTICE for conditions of use and distribution. */

Expand Down Expand Up @@ -59,7 +60,7 @@ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
log_write(0, LOG_PANIC_DIE, "iflist-sysctl-estimate failed: %s",
strerror(errno));

buf = store_get(needed, FALSE);
buf = store_get(needed, GET_UNTAINTED);

if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
log_write(0, LOG_PANIC_DIE, "sysctl of ifnet list failed: %s",
Expand Down
3 changes: 2 additions & 1 deletion src/OS/unsupported/os.c-IRIX65
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2022 */
/* Copyright (c) University of Cambridge 2001 */
/* See the file NOTICE for conditions of use and distribution. */

Expand Down Expand Up @@ -59,7 +60,7 @@ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
log_write(0, LOG_PANIC_DIE, "iflist-sysctl-estimate failed: %s",
strerror(errno));

buf = store_get(needed, FALSE);
buf = store_get(needed, GET_UNTAINTED);

if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
log_write(0, LOG_PANIC_DIE, "sysctl of ifnet list failed: %s",
Expand Down
1 change: 1 addition & 0 deletions src/OS/unsupported/os.h-NetBSD
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* Exim: OS-specific C header file for NetBSD */
/* Copyright (c) The Exim Maintainers 2021 */

#define HAVE_BSD_GETLOADAVG
#define HAVE_GETIFADDRS
Expand Down
8 changes: 4 additions & 4 deletions src/exim_monitor/em_TextPop.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/***********************************************************
Copyright (c) The Exim Maintainers 2022
Copyright 1989 by the Massachusetts Institute of Technology,
Cambridge, Massachusetts.
Expand Down Expand Up @@ -246,7 +247,7 @@ Cardinal * num_params;
Arg args[1];

#ifdef notdef
if (ctx->text.source->Search == NULL) {
if (!ctx->text.source->Search) {
XBell(XtDisplay(w), 0);
return;
}
Expand Down Expand Up @@ -279,16 +280,15 @@ Cardinal * num_params;
return;
}

if (ctx->text.search== NULL) {
if (!ctx->text.search) {
ctx->text.search = XtNew(struct SearchAndReplace);
ctx->text.search->search_popup = CreateDialog(w, ptr, "search",
AddSearchChildren);
XtRealizeWidget(ctx->text.search->search_popup);
SetWMProtocolTranslations(ctx->text.search->search_popup);
}
else if (*num_params > 1) {
else if (*num_params > 1)
XtVaSetValues(ctx->text.search->search_text, XtNstring, ptr, NULL);
}

XtSetArg(args[0], XtNeditType,&edit_mode);
XtGetValues(ctx->text.source, args, ONE);
Expand Down
5 changes: 3 additions & 2 deletions src/exim_monitor/em_globals.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*************************************************/

/* Copyright (c) University of Cambridge 1995 - 2018 */
/* Copyright (c) The Exim Maintainers 2021 */
/* See the file NOTICE for conditions of use and distribution. */


Expand Down Expand Up @@ -81,15 +82,15 @@ uschar *queue_stripchart_name = NULL;
int queue_update = 60;
int queue_width = 600;

pcre *yyyymmdd_regex;
pcre2_code *yyyymmdd_regex;

uschar *size_stripchart = NULL;
uschar *size_stripchart_name = NULL;
int spool_is_split = FALSE;
int start_small = FALSE;
int stripchart_height = 90;
int stripchart_number = 1;
pcre **stripchart_regex;
pcre2_code **stripchart_regex;
uschar **stripchart_title;
int *stripchart_total;
int stripchart_update = 60;
Expand Down
13 changes: 8 additions & 5 deletions src/exim_monitor/em_hdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*************************************************/

/* Copyright (c) University of Cambridge 1995 - 2009 */
/* Copyright (c) The Exim Maintainers 2021 - 2022 */
/* See the file NOTICE for conditions of use and distribution. */


Expand Down Expand Up @@ -85,22 +86,24 @@ anything. */

/* Regular expression include */

#include <pcre.h>
#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>

/* Includes from the main source of Exim. One of these days I should tidy up
this interface so that this kind of kludge isn't needed. */

#ifndef NS_MAXMSG
# define NS_MAXMSG 65535
#endif
typedef void hctx;
typedef void * hctx;

#include "local_scan.h"
#include "macros.h"
#include "structs.h"
#include "blob.h"
#include "globals.h"
#include "dbstuff.h"
#include "hintsdb.h"
#include "hintsdb_structs.h"
#include "functions.h"
#include "osfunctions.h"

Expand Down Expand Up @@ -273,7 +276,7 @@ extern uschar *queue_stripchart_name; /* sic */
extern int queue_update; /* update interval */
extern int queue_width; /* width of queue window */

extern pcre *yyyymmdd_regex; /* for matching yyyy-mm-dd */
extern pcre2_code *yyyymmdd_regex; /* for matching yyyy-mm-dd */

extern uschar *size_stripchart; /* path for size monitoring */
extern uschar *size_stripchart_name; /* name for size stripchart */
Expand All @@ -282,7 +285,7 @@ extern int spool_is_split; /* True if detected split spool */
extern int start_small; /* True to start with small window */
extern int stripchart_height; /* height of stripcharts */
extern int stripchart_number; /* number of stripcharts */
extern pcre **stripchart_regex; /* vector of regexps */
extern pcre2_code **stripchart_regex; /* vector of regexps */
extern uschar **stripchart_title; /* vector of titles */
extern int *stripchart_total; /* vector of accumulating values */
extern int stripchart_update; /* update interval */
Expand Down
109 changes: 55 additions & 54 deletions src/exim_monitor/em_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*************************************************/

/* Copyright (c) University of Cambridge 1995 - 2009 */
/* Copyright (c) The Exim Maintainers 2020 */
/* Copyright (c) The Exim Maintainers 2020 - 2021 */
/* See the file NOTICE for conditions of use and distribution. */

/* This module contains code to initialize things from the
Expand Down Expand Up @@ -32,7 +32,6 @@ int i;
work. */

for (i = 0; i <= 1; i++)

{
int first = 1;
int count = 0;
Expand Down Expand Up @@ -69,13 +68,18 @@ for (i = 0; i <= 1; i++)
buffer[p-pp] = 0;
if (first)
{
int offset;
const uschar *error;
if (!(stripchart_regex[indx] = pcre_compile(CS buffer, PCRE_COPT,
CCSS &error, &offset, NULL)))
size_t offset;
int err;

if (!(stripchart_regex[indx] =
pcre2_compile((PCRE2_SPTR)buffer,
PCRE2_ZERO_TERMINATED, PCRE_COPT,
&err, &offset, NULL)))
{
printf("regular expression error: %s at offset %d "
"while compiling %s\n", error, offset, buffer);
uschar errbuf[128];
pcre2_get_error_message(err, errbuf, sizeof(errbuf));
printf("regular expression error: %s at offset %ld "
"while compiling %s\n", errbuf, (long)offset, buffer);
exit(99);
}
}
Expand All @@ -95,7 +99,7 @@ for (i = 0; i <= 1; i++)
if (i == 0)
{
stripchart_number += count;
stripchart_regex = (pcre **)store_malloc(stripchart_number * sizeof(pcre *));
stripchart_regex = (pcre2_code **)store_malloc(stripchart_number * sizeof(pcre2_code *));
stripchart_title = (uschar **)store_malloc(stripchart_number * sizeof(uschar *));
}
}
Expand All @@ -109,40 +113,36 @@ for (i = 0; i <= 1; i++)
void init(int argc, uschar **argv)
{
int x;
int erroroffset;
size_t erroroffset;
uschar *s;
const uschar *error;

argc = argc; /* These are currently unused. */
argv = argv;

/* Deal with simple values in the environment. */

s = US getenv("ACTION_OUTPUT");
if (s != NULL)
if ((s = US getenv("ACTION_OUTPUT")))
{
if (Ustrcmp(s, "no") == 0) action_output = FALSE;
if (Ustrcmp(s, "yes") == 0) action_output = TRUE;
}

s = US getenv("ACTION_QUEUE_UPDATE");
if (s != NULL)
if ((s = US getenv("ACTION_QUEUE_UPDATE")))
{
if (Ustrcmp(s, "no") == 0) action_queue_update = FALSE;
if (Ustrcmp(s, "yes") == 0) action_queue_update = TRUE;
}

s = US getenv("BODY_MAX");
if (s != NULL && (x = Uatoi(s)) != 0) body_max = x;
if (s && (x = Uatoi(s)) != 0) body_max = x;

s = US getenv("EXIM_PATH");
if (s != NULL) exim_path = string_copy(s);
if ((s = US getenv("EXIM_PATH")))
exim_path = string_copy(s);

s = US getenv("EXIMON_EXIM_CONFIG");
if (s != NULL) alternate_config = string_copy(s);
if ((s = US getenv("EXIMON_EXIM_CONFIG")))
alternate_config = string_copy(s);

s = US getenv("LOG_BUFFER");
if (s != NULL)
if ((s = US getenv("LOG_BUFFER")))
{
uschar c[1];
if (sscanf(CS s, "%d%c", &x, c) > 0)
Expand All @@ -154,63 +154,64 @@ if (s != NULL)
}

s = US getenv("LOG_DEPTH");
if (s != NULL && (x = Uatoi(s)) != 0) log_depth = x;
if (s && (x = Uatoi(s)) != 0) log_depth = x;

s = US getenv("LOG_FILE_NAME");
if (s != NULL) log_file = string_copy(s);
if ((s = US getenv("LOG_FILE_NAME")))
log_file = string_copy(s);

s = US getenv("LOG_FONT");
if (s != NULL) log_font = string_copy(s);
if ((s = US getenv("LOG_FONT")))
log_font = string_copy(s);

s = US getenv("LOG_WIDTH");
if (s != NULL && (x = Uatoi(s)) != 0) log_width = x;
if (s && (x = Uatoi(s)) != 0) log_width = x;

s = US getenv("MENU_EVENT");
if (s != NULL) menu_event = string_copy(s);
if ((s = US getenv("MENU_EVENT")))
menu_event = string_copy(s);

s = US getenv("MIN_HEIGHT");
if (s != NULL && (x = Uatoi(s)) > 0) min_height = x;
if (s && (x = Uatoi(s)) > 0) min_height = x;

s = US getenv("MIN_WIDTH");
if (s != NULL && (x = Uatoi(s)) > 0) min_width = x;
if (s && (x = Uatoi(s)) > 0) min_width = x;

s = US getenv("QUALIFY_DOMAIN");
if (s != NULL) qualify_domain = string_copy(s);
else qualify_domain = US""; /* Don't want NULL */
if ((s = US getenv("QUALIFY_DOMAIN")))
qualify_domain = string_copy(s);
else
qualify_domain = US""; /* Don't want NULL */

s = US getenv("QUEUE_DEPTH");
if (s != NULL && (x = Uatoi(s)) != 0) queue_depth = x;
if (s && (x = Uatoi(s)) != 0) queue_depth = x;

s = US getenv("QUEUE_FONT");
if (s != NULL) queue_font = string_copy(s);
if ((s = US getenv("QUEUE_FONT")))
queue_font = string_copy(s);

s = US getenv("QUEUE_INTERVAL");
if (s != NULL && (x = Uatoi(s)) != 0) queue_update = x;
if (s && (x = Uatoi(s)) != 0) queue_update = x;

s = US getenv("QUEUE_MAX_ADDRESSES");
if (s != NULL && (x = Uatoi(s)) != 0) queue_max_addresses = x;
if (s && (x = Uatoi(s)) != 0) queue_max_addresses = x;

s = US getenv("QUEUE_WIDTH");
if (s != NULL && (x = Uatoi(s)) != 0) queue_width = x;
if (s && (x = Uatoi(s)) != 0) queue_width = x;

s = US getenv("SPOOL_DIRECTORY");
if (s != NULL) spool_directory = string_copy(s);
if ((s = US getenv("SPOOL_DIRECTORY")))
spool_directory = string_copy(s);

s = US getenv("START_SMALL");
if (s != NULL && Ustrcmp(s, "yes") == 0) start_small = 1;
if (s && Ustrcmp(s, "yes") == 0) start_small = 1;

s = US getenv("TEXT_DEPTH");
if (s != NULL && (x = Uatoi(s)) != 0) text_depth = x;
if (s && (x = Uatoi(s)) != 0) text_depth = x;

s = US getenv("WINDOW_TITLE");
if (s != NULL) window_title = string_copy(s);
if ((s = US getenv("WINDOW_TITLE")))
window_title = string_copy(s);

/* Deal with stripchart configuration. First see if we are monitoring
the size of a partition, then deal with log stripcharts in a separate
function */

s = US getenv("SIZE_STRIPCHART");
if (s != NULL && *s != 0)
if (s && *s)
{
stripchart_number++;
stripchart_varstart++;
Expand All @@ -219,19 +220,19 @@ if (s != NULL && *s != 0)
if (s != NULL && *s != 0) size_stripchart_name = string_copy(s);
}

s = US getenv("LOG_STRIPCHARTS");
if (s != NULL) decode_stripchart_config(s);
if ((s = US getenv("LOG_STRIPCHARTS")))
decode_stripchart_config(s);

s = US getenv("STRIPCHART_INTERVAL");
if (s != NULL && (x = Uatoi(s)) != 0) stripchart_update = x;
if (s && (x = Uatoi(s)) != 0) stripchart_update = x;

s = US getenv("QUEUE_STRIPCHART_NAME");
queue_stripchart_name = (s != NULL)? string_copy(s) : US"queue";
queue_stripchart_name = s ? string_copy(s) : US"queue";

/* Compile the regex for matching yyyy-mm-dd at the start of a string. */

yyyymmdd_regex = pcre_compile("^\\d{4}-\\d\\d-\\d\\d\\s", PCRE_COPT,
CCSS &error, &erroroffset, NULL);
yyyymmdd_regex = pcre2_compile((PCRE2_SPTR)"^\\d{4}-\\d\\d-\\d\\d\\s",
PCRE2_ZERO_TERMINATED, PCRE_COPT, &x, &erroroffset, NULL);
}

/* End of em_init.c */
26 changes: 13 additions & 13 deletions src/exim_monitor/em_log.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*************************************************/

/* Copyright (c) University of Cambridge 1995 - 2018 */
/* Copyright (c) The Exim Maintainters 2021 - 2022 */
/* See the file NOTICE for conditions of use and distribution. */

/* This module contains code for scanning the main log,
Expand Down Expand Up @@ -229,7 +230,7 @@ if (LOG != NULL)
uschar *p = buffer;
rmark reset_point;
int length = Ustrlen(buffer);
int i;
pcre2_match_data * md = pcre2_match_data_create(1, NULL);

/* Skip totally blank lines (paranoia: there shouldn't be any) */

Expand All @@ -246,27 +247,25 @@ if (LOG != NULL)
stripchart is the queue length, which is handled elsewhere, and the
1st may the a size monitor. */

for (i = stripchart_varstart; i < stripchart_number; i++)
{
if (pcre_exec(stripchart_regex[i], NULL, CS buffer, length, 0, PCRE_EOPT,
NULL, 0) >= 0)
for (int i = stripchart_varstart; i < stripchart_number; i++)
if (pcre2_match(stripchart_regex[i], (PCRE2_SPTR)buffer, length,
0, PCRE_EOPT, md, NULL) >= 0)
stripchart_total[i]++;
}

/* Munge the log entry and display shortened form on one line.
We omit the date and show only the time. Remove any time zone offset.
Take note of the presence of [pid]. */

if (pcre_exec(yyyymmdd_regex,NULL,CS buffer,length,0,PCRE_EOPT,NULL,0) >= 0)
if (pcre2_match(yyyymmdd_regex, (PCRE2_SPTR) buffer, length, 0, PCRE_EOPT,
md, NULL) >= 0)
{
int pidlength = 0;
if ((buffer[20] == '+' || buffer[20] == '-') &&
isdigit(buffer[21]) && buffer[25] == ' ')
if ( (buffer[20] == '+' || buffer[20] == '-')
&& isdigit(buffer[21]) && buffer[25] == ' ')
memmove(buffer + 20, buffer + 26, Ustrlen(buffer + 26) + 1);
if (buffer[20] == '[')
{
while (Ustrchr("[]0123456789", buffer[20+pidlength++]) != NULL);
}
while (Ustrchr("[]0123456789", buffer[20+pidlength++]) != NULL)
;
id = string_copyn(buffer + 20 + pidlength, MESSAGE_ID_LENGTH);
show_log("%s", buffer+11);
}
Expand All @@ -275,6 +274,7 @@ if (LOG != NULL)
id = US"";
show_log("%s", buffer);
}
pcre2_match_data_free(md);

/* Deal with frozen and unfrozen messages */

Expand All @@ -292,7 +292,7 @@ if (LOG != NULL)
if ((p = Ustrstr(buffer, "==")) != NULL)
{
queue_item *qq = find_queue(id, queue_noop, 0);
if (qq != NULL)
if (qq)
{
dest_item *d;
uschar *q, *r;
Expand Down
51 changes: 40 additions & 11 deletions src/exim_monitor/em_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*************************************************/

/* Copyright (c) University of Cambridge 1995 - 2018 */
/* Copyright (c) The Exim Maintainers 2021 - 2022 */
/* See the file NOTICE for conditions of use and distribution. */


Expand Down Expand Up @@ -196,19 +197,47 @@ Returns: 0 if there is no port, else the port number.
*/

int
host_address_extract_port(uschar *address)
host_address_extract_port(uschar * address)
{
int skip = -3; /* Skip 3 dots in IPv4 addresses */
address--;
while (*(++address) != 0)
int port = 0;
uschar *endptr;

/* Handle the "bracketed with colon on the end" format */

if (*address == '[')
{
uschar *rb = address + 1;
while (*rb != 0 && *rb != ']') rb++;
if (*rb++ == 0) return 0; /* Missing ]; leave invalid address */
if (*rb == ':')
{
port = Ustrtol(rb + 1, &endptr, 10);
if (*endptr != 0) return 0; /* Invalid port; leave invalid address */
}
else if (*rb != 0) return 0; /* Bad syntax; leave invalid address */
memmove(address, address + 1, rb - address - 2);
rb[-2] = 0;
}

/* Handle the "dot on the end" format */

else
{
int ch = *address;
if (ch == ':') skip = 0; /* Skip 0 dots in IPv6 addresses */
else if (ch == '.' && skip++ >= 0) break;
int skip = -3; /* Skip 3 dots in IPv4 addresses */
address--;
while (*(++address) != 0)
{
int ch = *address;
if (ch == ':') skip = 0; /* Skip 0 dots in IPv6 addresses */
else if (ch == '.' && skip++ >= 0) break;
}
if (*address == 0) return 0;
port = Ustrtol(address + 1, &endptr, 10);
if (*endptr != 0) return 0; /* Invalid port; leave invalid address */
*address = 0;
}
if (*address == 0) return 0;
*address++ = 0;
return Uatoi(address);

return port;
}


Expand Down Expand Up @@ -593,7 +622,7 @@ constructing file names and things. This call will initialize
the store_get() function. */

store_init();
big_buffer = store_get(big_buffer_size, FALSE);
big_buffer = store_get(big_buffer_size, GET_UNTAINTED);

/* Set up the version string and date and output them */

Expand Down
1 change: 1 addition & 0 deletions src/exim_monitor/em_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*************************************************/

/* Copyright (c) University of Cambridge 1995 - 2018 */
/* Copyright (c) The Exim Maintainers 2021 */
/* See the file NOTICE for conditions of use and distribution. */


Expand Down
6 changes: 3 additions & 3 deletions src/exim_monitor/em_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*************************************************/

/* Copyright (c) University of Cambridge 1995 - 2018 */
/* Copyright (c) The Exim Maintainers 2020 */
/* Copyright (c) The Exim Maintainers 2020 - 2022 */
/* See the file NOTICE for conditions of use and distribution. */


Expand Down Expand Up @@ -138,8 +138,8 @@ tree_node *
acl_var_create(uschar *name)
{
tree_node *node, **root;
root = (name[0] == 'c')? &acl_var_c : &acl_var_m;
node = store_get(sizeof(tree_node) + Ustrlen(name), FALSE);
root = name[0] == 'c' ? &acl_var_c : &acl_var_m;
node = store_get(sizeof(tree_node) + Ustrlen(name), GET_UNTAINTED);
Ustrcpy(node->name, name);
node->data.ptr = NULL;
(void)tree_insertnode(root, node);
Expand Down
2 changes: 1 addition & 1 deletion src/exim_monitor/em_version.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*************************************************/

/* Copyright (c) University of Cambridge 1995 - 2018 */
/* Copyright (c) The Exim Maintainers 2020 */
/* Copyright (c) The Exim Maintainers 2020 - 2021 */
/* See the file NOTICE for conditions of use and distribution. */

#define EM_VERSION_C
Expand Down
30 changes: 25 additions & 5 deletions src/scripts/Configure-Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export LC_ALL
# just got too horrendous to get it right in "make", because of the optionally
# existing configuration files.
#
# Copyright (c) The Exim Maintainers 1995 - 2020
# Copyright (c) The Exim Maintainers 1995 - 2021


# First off, get the OS type, and check that there is a make file for it.
Expand Down Expand Up @@ -150,7 +150,7 @@ rm -f ./$mftepcp ./$mftepcp2
egrep "^[$st]*(AUTH|LOOKUP)_[A-Z0-9_]*[$st]*=[$st]*" $mft | \
sed "s/[$st]*=/='/" | \
sed "s/\$/'/" > $mftt
egrep "^[$st]*((USE_(OPENSSL|GNUTLS)_PC)|SUPPORT_TLS|USE_GNUTLS|PCRE_CONFIG|AVOID_GNUTLS_PKCS11)[$st]*=[$st]*" $mft | \
egrep "^[$st]*((USE_(OPENSSL|GNUTLS)_PC)|SUPPORT_TLS|USE_GNUTLS|PCRE2?_CONFIG|AVOID_GNUTLS_PKCS11)[$st]*=[$st]*" $mft | \
sed "s/[$st]*=/='/" | \
sed "s/\$/'/" >> $mftt
if test -s $mftt
Expand Down Expand Up @@ -233,12 +233,32 @@ then
PCRE_CONFIG)
case $PCRE_CONFIG in
yes|YES|y|Y)
cflags=`pcre-config --cflags`
echo >&2 "pcre is no longer supported; migrate to pcre2"
exit 1

# cflags=`pcre-config --cflags`
# if [ $? -ne 0 ]; then
# echo >&2 "*** Missing pcre-config for regular expression support"
# exit 1
# fi
# libs=`pcre-config --libs`
# if [ ".$cflags" != "." ]; then
# echo "INCLUDE += $cflags"
# fi
# echo "PCRE_LIBS=$libs"
;;
esac
;;

PCRE2_CONFIG)
case $PCRE2_CONFIG in
yes|YES|y|Y)
cflags=`pcre2-config --cflags`
if [ $? -ne 0 ]; then
echo >&2 "*** Missing pcre-config for regular expression support"
echo >&2 "*** Missing pcre2-config for regular expression support"
exit 1
fi
libs=`pcre-config --libs`
libs=`pcre2-config --libs8`
if [ ".$cflags" != "." ]; then
echo "INCLUDE += $cflags"
fi
Expand Down
6 changes: 3 additions & 3 deletions src/scripts/MakeLinks
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Script to build links for all the exim source files from the system-
# specific build directory. It should be run from within that directory.
#
# Copyright (c) The Exim Maintainers 1995 - 2020
# Copyright (c) The Exim Maintainers 1995 - 2022

test ! -d ../src && \
echo "*** $0 should be run in a system-specific subdirectory." && \
Expand Down Expand Up @@ -95,8 +95,8 @@ cd ..
# but local_scan.c does not, because its location is taken from the build-time
# configuration. Likewise for the os.c file, which gets build dynamically.

for f in blob.h dbfunctions.h dbstuff.h exim.h functions.h globals.h \
hash.h local_scan.h \
for f in blob.h dbfunctions.h exim.h functions.h globals.h \
hash.h hintsdb.h hintsdb_structs.h local_scan.h \
macros.h mytypes.h osfunctions.h store.h structs.h lookupapi.h sha_ver.h \
\
acl.c buildconfig.c base64.c child.c crypt16.c daemon.c dbfn.c debug.c \
Expand Down
9 changes: 3 additions & 6 deletions src/scripts/lookups-Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#! /bin/sh

# Copyright (c) The Exim Maintainers 1995 - 2021

# We turn the configure-built build-$foo/lookups/Makefile.predynamic into Makefile

# We always re-exec ourselves at least once, because it's the cleanest and
Expand Down Expand Up @@ -160,7 +162,7 @@ exec > "$target"
sed -n "1,/$tag_marker/p" < "$input"

for name_mod in \
CDB DBM:dbmdb DNSDB DSEARCH IBASE JSON LSEARCH MYSQL NIS NISPLUS ORACLE \
CDB DBM:dbmdb DNSDB DSEARCH IBASE JSON LMDB LSEARCH MYSQL NIS NISPLUS ORACLE \
PASSWD PGSQL REDIS SQLITE TESTDB WHOSON
do
emit_module_rule $name_mod
Expand All @@ -177,11 +179,6 @@ fi

OBJ="${OBJ} spf.o"

if want_experimental LMDB
then
OBJ="${OBJ} lmdb.o"
fi

# readsock is always wanted as it implements the ${readsock } expansion
OBJ="${OBJ} readsock.o"

Expand Down
2 changes: 1 addition & 1 deletion src/scripts/reversion
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/sh
# Copyright (c) The Exim Maintainers 1995 - 2018
# Copyright (c) The Exim Maintainers 1995 - 2021

set -e
LC_ALL=C
Expand Down
41 changes: 18 additions & 23 deletions src/src/EDITME
Original file line number Diff line number Diff line change
Expand Up @@ -457,19 +457,19 @@ LOOKUP_DNSDB=yes


#------------------------------------------------------------------------------
# The PCRE library is required for Exim. There is no longer an embedded
# The PCRE2 library is required for Exim. There is no longer an embedded
# version of the PCRE library included with the source code, instead you
# must use a system library or build your own copy of PCRE.
# must use a system library or build your own copy of PCRE2.
# In either case you must specify the library link info here. If the
# PCRE header files are not in the standard search path you must also
# PCRE2 header files are not in the standard search path you must also
# modify the INCLUDE path (above)
#
# Use PCRE_CONFIG to query the pcre-config command (first found in $PATH)
# to find the include files and libraries, else use PCRE_LIBS and set INCLUDE
# too if needed.

PCRE_CONFIG=yes
# PCRE_LIBS=-lpcre
PCRE2_CONFIG=yes
# PCRE_LIBS=-lpcre2


#------------------------------------------------------------------------------
Expand All @@ -495,6 +495,13 @@ SUPPORT_DANE=yes
# LOOKUP_INCLUDE +=-I /usr/local/include
# LOOKUP_LIBS=-L/usr/local/lib -lldap -llber -lmysqlclient -lpq -lgds -lsqlite3 -llmdb

#------------------------------------------------------------------------------
# If you included LOOKUP_LMDB above you will need the library. Depending
# on where installed you may also need an include directory
#
# LOOKUP_INCLUDE += -I/usr/local/include
# LOOKUP_LIBS += -llmdb


#------------------------------------------------------------------------------
# Compiling the Exim monitor: If you want to compile the Exim monitor, a
Expand Down Expand Up @@ -578,7 +585,7 @@ DISABLE_MAL_MKS=yes
# DISABLE_QUEUE_RAMP=yes

# Uncomment the following lines to add SRS (Sender Rewriting Scheme) support
# using only native facilities. See EXPERIMENTAL_SRS_ALT for an alternative.
# using only native facilities.
# SUPPORT_SRS=yes


Expand All @@ -593,16 +600,6 @@ DISABLE_MAL_MKS=yes

# EXPERIMENTAL_DCC=yes

# Uncomment the following lines to add SRS (Sender rewriting scheme) support
# using the implementation in linbsrs_alt.
# You need to have libsrs_alt installed on your system (srs.mirtol.com).
# Depending on where it is installed you may have to edit the CFLAGS and
# LDFLAGS lines.

# EXPERIMENTAL_SRS_ALT=yes
# CFLAGS += -I/usr/local/include
# LDFLAGS += -lsrs_alt

# Uncomment the following line to add DMARC checking capability, implemented
# using libopendmarc libraries. You must have SPF and DKIM support enabled also.
# Library version libopendmarc-1.4.1-1.fc33.x86_64 (on Fedora 33) is known broken;
Expand Down Expand Up @@ -748,13 +745,6 @@ FIXED_NEVER_USERS=root

# WHITELIST_D_MACROS=TLS:SPOOL

# The next setting enables a main config option
# "allow_insecure_tainted_data" to turn taint failures into warnings.
# Though this option is new, it is deprecated already now, and will be
# ignored in future releases of Exim. It is meant as mitigation for
# upgrading old (possibly insecure) configurations to more secure ones.
ALLOW_INSECURE_TAINTED_DATA=yes

#------------------------------------------------------------------------------
# Exim has support for the AUTH (authentication) extension of the SMTP
# protocol, as defined by RFC 2554. If you don't know what SMTP authentication
Expand Down Expand Up @@ -1499,4 +1489,9 @@ EXIM_TMPDIR="/tmp"
# For development, add this to include code to time various stages and report.
# CFLAGS += -DMEASURE_TIMING

# For a very slightly smaller build, for constrained systems, uncomment this.
# The feature involved is purely for debugging.

# DISABLE_CLIENT_CMD_LOG=yes

# End of EDITME for Exim 4.
283 changes: 229 additions & 54 deletions src/src/acl.c

Large diffs are not rendered by default.

42 changes: 22 additions & 20 deletions src/src/arc.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*************************************************/
/* Experimental ARC support for Exim
Copyright (c) Jeremy Harris 2018 - 2020
Copyright (c) The Exim Maintainers 2021 - 2022
License: GPL
*/

Expand Down Expand Up @@ -141,7 +142,7 @@ for (pas = &ctx->arcset_chain, prev = NULL, next = ctx->arcset_chain;
}

DEBUG(D_acl) debug_printf("ARC: new instance %u\n", i);
*pas = as = store_get(sizeof(arc_set), FALSE);
*pas = as = store_get(sizeof(arc_set), GET_UNTAINTED);
memset(as, 0, sizeof(arc_set));
as->next = next;
as->prev = prev;
Expand Down Expand Up @@ -199,7 +200,7 @@ al->complete = h;

if (!instance_only)
{
al->rawsig_no_b_val.data = store_get(h->slen + 1, TRUE); /* tainted */
al->rawsig_no_b_val.data = store_get(h->slen + 1, GET_TAINTED);
memcpy(al->rawsig_no_b_val.data, h->text, off); /* copy the header name blind */
r = al->rawsig_no_b_val.data + off;
al->rawsig_no_b_val.len = off;
Expand Down Expand Up @@ -385,7 +386,7 @@ arc_insert_hdr(arc_ctx * ctx, header_line * h, unsigned off, unsigned hoff,
{
unsigned i;
arc_set * as;
arc_line * al = store_get(sizeof(arc_line), FALSE), ** alp;
arc_line * al = store_get(sizeof(arc_line), GET_UNTAINTED), ** alp;
uschar * e;

memset(al, 0, sizeof(arc_line));
Expand Down Expand Up @@ -496,7 +497,7 @@ const uschar * e;
DEBUG(D_acl) debug_printf("ARC: collecting arc sets\n");
for (h = header_list; h; h = h->next)
{
r = store_get(sizeof(hdr_rlist), FALSE);
r = store_get(sizeof(hdr_rlist), GET_UNTAINTED);
r->prev = rprev;
r->used = FALSE;
r->h = h;
Expand Down Expand Up @@ -568,7 +569,7 @@ while ((hn = string_nextinlist(&headernames, &sep, NULL, 0)))

len = Ustrlen(s);
DEBUG(D_acl) pdkim_quoteprint(s, len);
exim_sha_update(&hhash_ctx, s, Ustrlen(s));
exim_sha_update_string(&hhash_ctx, s);
r->used = TRUE;
break;
}
Expand Down Expand Up @@ -1102,7 +1103,7 @@ res = US"pass";
static hdr_rlist *
arc_rlist_entry(hdr_rlist * list, const uschar * s, int len)
{
hdr_rlist * r = store_get(sizeof(hdr_rlist) + sizeof(header_line), FALSE);
hdr_rlist * r = store_get(sizeof(hdr_rlist) + sizeof(header_line), GET_UNTAINTED);
header_line * h = r->h = (header_line *)(r+1);

r->prev = list;
Expand All @@ -1112,11 +1113,6 @@ h->type = 0;
h->slen = len;
h->text = US s;

/* This works for either NL or CRLF lines; also nul-termination */
while (*++s)
if (*s == '\n' && s[1] != '\t' && s[1] != ' ') break;
s++; /* move past end of line */

return r;
}

Expand Down Expand Up @@ -1194,7 +1190,7 @@ arc_sign_append_aar(gstring * g, arc_ctx * ctx,
{
int aar_off = gstring_length(g);
arc_set * as =
store_get(sizeof(arc_set) + sizeof(arc_line) + sizeof(header_line), FALSE);
store_get(sizeof(arc_set) + sizeof(arc_line) + sizeof(header_line), GET_UNTAINTED);
arc_line * al = (arc_line *)(as+1);
header_line * h = (header_line *)(al+1);

Expand Down Expand Up @@ -1304,7 +1300,7 @@ int col;
int hashtype = pdkim_hashname_to_hashtype(US"sha256", 6); /*XXX hardwired */
blob sig;
int ams_off;
arc_line * al = store_get(sizeof(header_line) + sizeof(arc_line), FALSE);
arc_line * al = store_get(sizeof(header_line) + sizeof(arc_line), GET_UNTAINTED);
header_line * h = (header_line *)(al+1);

/* debug_printf("%s\n", __FUNCTION__); */
Expand Down Expand Up @@ -1419,7 +1415,7 @@ arc_sign_prepend_as(gstring * arcset_interim, arc_ctx * ctx,
{
gstring * arcset;
uschar * status = arc_ar_cv_status(ar);
arc_line * al = store_get(sizeof(header_line) + sizeof(arc_line), FALSE);
arc_line * al = store_get(sizeof(header_line) + sizeof(arc_line), GET_UNTAINTED);
header_line * h = (header_line *)(al+1);
uschar * badline_str;

Expand Down Expand Up @@ -1531,6 +1527,7 @@ void
arc_sign_init(void)
{
memset(&arc_sign_ctx, 0, sizeof(arc_sign_ctx));
headers_rlist = NULL;
}


Expand Down Expand Up @@ -1618,7 +1615,7 @@ if (!arc_valid_id(identity))
if (!arc_valid_id(selector))
{ s = US"selector"; goto bad_arg_ret; }
if (*privkey == '/' && !(privkey = expand_file_big_buffer(privkey)))
return sigheaders ? sigheaders : string_get(0);
goto ret_sigheaders;

if ((opts = string_nextinlist(&signspec, &sep, NULL, 0)))
{
Expand Down Expand Up @@ -1677,7 +1674,7 @@ if ((rheaders = arc_sign_scan_headers(&arc_sign_ctx, sigheaders)))
if (!(arc_sign_find_ar(headers, identity, &ar)))
{
log_write(0, LOG_MAIN, "ARC: no Authentication-Results header for signing");
return sigheaders ? sigheaders : string_get(0);
goto ret_sigheaders;
}

/* We previously built the data-struct for the existing ARC chain, if any, using a headers
Expand Down Expand Up @@ -1733,14 +1730,19 @@ if (g)
/* Finally, append the dkim headers and return the lot. */

if (sigheaders) g = string_catn(g, sigheaders->s, sigheaders->ptr);
(void) string_from_gstring(g);
gstring_release_unused(g);
return g;

out:
if (!g) return string_get(1);
(void) string_from_gstring(g);
gstring_release_unused(g);
return g;


bad_arg_ret:
log_write(0, LOG_MAIN, "ARC: bad signing-specification (%s)", s);
return sigheaders ? sigheaders : string_get(0);
ret_sigheaders:
g = sigheaders;
goto out;
}


Expand Down
2 changes: 2 additions & 0 deletions src/src/auths/auth-spa.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
* All the original code used here was torn by Marc Prud'hommeaux out of the
* Samba project (by Andrew Tridgell, Jeremy Allison, and others).
*
* Copyright (c) The Exim Maintainers 2021
* Tom Kistner provided additional code, adding spa_build_auth_challenge() to
* support server authentication mode.
Expand Down
4 changes: 2 additions & 2 deletions src/src/auths/call_pam.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*************************************************/

/* Copyright (c) University of Cambridge 1995 - 2018 */
/* Copyright (c) The Exim Maintainers 2020 */
/* Copyright (c) The Exim Maintainers 2020 - 2021 */
/* See the file NOTICE for conditions of use and distribution. */

#include "../exim.h"
Expand Down Expand Up @@ -88,7 +88,7 @@ for (int i = 0; i < num_msg; i++)
arg = US"";
pam_arg_ended = TRUE;
}
reply[i].resp = CS string_copy_malloc(arg); /* PAM frees resp */
reply[i].resp = strdup(CCS arg); /* Use libc malloc, PAM frees resp directly*/
reply[i].resp_retcode = PAM_SUCCESS;
break;

Expand Down
33 changes: 12 additions & 21 deletions src/src/auths/call_radius.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,13 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2020 */
/* Copyright (c) The Exim Maintainers 2020 - 2022 */
/* Copyright (c) University of Cambridge 1995 - 2016 */
/* See the file NOTICE for conditions of use and distribution. */

/* This file was originally supplied by Ian Kirk. The libradius support came
from Alex Kiernan. */

/* ugly hack to work around redefinition of ENV by radiusclient.h and
* db.h: define _DB_H_ so the db.h include thinks it's already included,
* we can get away with it like this, since this file doesn't use any db
* functions. */
#ifndef _DB_H_
# define _DB_H_ 1
# define _DB_EXT_PROT_IN_ 1
# define DB void
#endif

#include "../exim.h"

/* This module contains functions that call the Radius authentication
Expand All @@ -44,17 +34,18 @@ static void dummy(int x) { dummy2(x-1); }
using its original API. At release 0.4.0 the API changed. */

#ifdef RADIUS_LIB_RADLIB
#include <radlib.h>
# include <radlib.h>
#else
#if !defined(RADIUS_LIB_RADIUSCLIENT) && !defined(RADIUS_LIB_RADIUSCLIENTNEW)
# define RADIUS_LIB_RADIUSCLIENT
#endif

#ifdef RADIUS_LIB_RADIUSCLIENTNEW
# include <freeradius-client.h>
#else
# include <radiusclient.h>
#endif
# if !defined(RADIUS_LIB_RADIUSCLIENT) && !defined(RADIUS_LIB_RADIUSCLIENTNEW)
# define RADIUS_LIB_RADIUSCLIENT
# endif

# ifdef RADIUS_LIB_RADIUSCLIENTNEW
# define ENV FREERADIUSCLIENT_ENV /* Avoid clash with Berkeley DB */
# include <freeradius-client.h>
# else
# include <radiusclient.h>
# endif
#endif


Expand Down
24 changes: 13 additions & 11 deletions src/src/auths/cyrus_sasl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2020 - 2022 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */

/* This code was originally contributed by Matthew Byng-Maddick */
Expand Down Expand Up @@ -71,7 +71,7 @@ void auth_cyrus_sasl_init(auth_instance *ablock) {}
int auth_cyrus_sasl_server(auth_instance *ablock, uschar *data) {return 0;}
int auth_cyrus_sasl_client(auth_instance *ablock, void * sx,
int timeout, uschar *buffer, int buffsize) {return 0;}
void auth_cyrus_sasl_version_report(FILE *f) {}
gstring * auth_cyrus_sasl_version_report(gstring * g) {return NULL;}

#else /*!MACRO_PREDEF*/

Expand Down Expand Up @@ -378,7 +378,7 @@ for (rc = SASL_CONTINUE; rc == SASL_CONTINUE; )
HDEBUG(D_auth)
debug_printf("Cyrus SASL library will not tell us the username: %s\n",
sasl_errstring(rc, NULL, NULL));
log_write(0, LOG_REJECT, "%s authenticator (%s):\n "
log_write(0, LOG_REJECT, "%s authenticator (%s): "
"Cyrus SASL username fetch problem: %s", ablock->name, ob->server_mech,
sasl_errstring(rc, NULL, NULL));
sasl_dispose(&conn);
Expand All @@ -397,7 +397,7 @@ for (rc = SASL_CONTINUE; rc == SASL_CONTINUE; )
/* these are considered permanent failure codes */
HDEBUG(D_auth)
debug_printf("Cyrus SASL permanent failure %d (%s)\n", rc, sasl_errstring(rc, NULL, NULL));
log_write(0, LOG_REJECT, "%s authenticator (%s):\n "
log_write(0, LOG_REJECT, "%s authenticator (%s): "
"Cyrus SASL permanent failure: %s", ablock->name, ob->server_mech,
sasl_errstring(rc, NULL, NULL));
sasl_dispose(&conn);
Expand Down Expand Up @@ -427,7 +427,7 @@ for (rc = SASL_CONTINUE; rc == SASL_CONTINUE; )
HDEBUG(D_auth)
debug_printf("Cyrus SASL library will not tell us the SSF: %s\n",
sasl_errstring(rc, NULL, NULL));
log_write(0, LOG_REJECT, "%s authenticator (%s):\n "
log_write(0, LOG_REJECT, "%s authenticator (%s): "
"Cyrus SASL SSF value not available: %s", ablock->name, ob->server_mech,
sasl_errstring(rc, NULL, NULL));
sasl_dispose(&conn);
Expand All @@ -441,7 +441,7 @@ for (rc = SASL_CONTINUE; rc == SASL_CONTINUE; )
{
HDEBUG(D_auth)
debug_printf("Exim does not implement SASL wrapping (needed for SSF %d).\n", negotiated_ssf);
log_write(0, LOG_REJECT, "%s authenticator (%s):\n "
log_write(0, LOG_REJECT, "%s authenticator (%s): "
"Cyrus SASL SSF %d not supported by Exim", ablock->name, ob->server_mech, negotiated_ssf);
sasl_dispose(&conn);
sasl_done();
Expand Down Expand Up @@ -476,15 +476,17 @@ return 0; /* Stop compiler complaints */
* Diagnostic API *
*************************************************/

void
auth_cyrus_sasl_version_report(FILE *f)
gstring *
auth_cyrus_sasl_version_report(gstring * g)
{
const char *implementation, *version;
const char * implementation, * version;
sasl_version_info(&implementation, &version, NULL, NULL, NULL, NULL);
fprintf(f, "Library version: Cyrus SASL: Compile: %d.%d.%d\n"
" Runtime: %s [%s]\n",
g = string_fmt_append(g,
"Library version: Cyrus SASL: Compile: %d.%d.%d\n"
" Runtime: %s [%s]\n",
SASL_VERSION_MAJOR, SASL_VERSION_MINOR, SASL_VERSION_STEP,
version, implementation);
return g;
}

/*************************************************
Expand Down
3 changes: 2 additions & 1 deletion src/src/auths/cyrus_sasl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2022 */
/* Copyright (c) University of Cambridge 1995 - 2012 */
/* See the file NOTICE for conditions of use and distribution. */

Expand Down Expand Up @@ -30,6 +31,6 @@ extern auth_cyrus_sasl_options_block auth_cyrus_sasl_option_defaults;
extern void auth_cyrus_sasl_init(auth_instance *);
extern int auth_cyrus_sasl_server(auth_instance *, uschar *);
extern int auth_cyrus_sasl_client(auth_instance *, void *, int, uschar *, int);
extern void auth_cyrus_sasl_version_report(FILE *f);
extern gstring * auth_cyrus_sasl_version_report(gstring *);

/* End of cyrus_sasl.h */
15 changes: 12 additions & 3 deletions src/src/auths/dovecot.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) The Exim Maintainers 2006 - 2022
* Copyright (c) 2004 Andrey Panin <pazke@donpac.ru>
* Copyright (c) 2006-2020 The Exim Maintainers
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
Expand Down Expand Up @@ -275,11 +275,20 @@ if (cctx.sock < 0)
# ifndef DISABLE_TLS
if (ob->server_tls)
{
uschar * s;
union sockaddr_46 interface_sock;
EXIM_SOCKLEN_T size = sizeof(interface_sock);
smtp_connect_args conn_args = { .host = &host };
tls_support tls_dummy = {.sni=NULL};
tls_support tls_dummy = { .sni = NULL };
uschar * errstr;

if (getsockname(cctx->sock, (struct sockaddr *) &interface_sock, &size) == 0)
conn_args.sending_ip_address = host_ntoa(-1, &interface_sock, NULL, NULL);
else
{
*errmsg = string_sprintf("getsockname failed: %s", strerror(errno));
goto bad;
}

if (!tls_client_start(&cctx, &conn_args, NULL, &tls_dummy, &errstr))
{
auth_defer_msg = string_sprintf("TLS connect failed: %s", errstr);
Expand Down
2 changes: 1 addition & 1 deletion src/src/auths/get_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*************************************************/

/* Copyright (c) University of Cambridge 1995 - 2018 */
/* Copyright (c) The Exim Maintainers 2020 */
/* Copyright (c) The Exim Maintainers 2020 - 2021 */
/* See the file NOTICE for conditions of use and distribution. */

#include "../exim.h"
Expand Down
88 changes: 46 additions & 42 deletions src/src/auths/gsasl_exim.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2019-2020 */
/* Copyright (c) The Exim Maintainers 2019 - 2022 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */

Expand Down Expand Up @@ -57,6 +57,10 @@ static void dummy(int x) { dummy2(x-1); }
# define CHANNELBIND_HACK
#endif

/* Convenience for testing strings */

#define STREQIC(Foo, Bar) (strcmpic((Foo), (Bar)) == 0)


/* Authenticator-specific options. */
/* I did have server_*_condition options for various mechanisms, but since
Expand Down Expand Up @@ -108,7 +112,7 @@ void auth_gsasl_init(auth_instance *ablock) {}
int auth_gsasl_server(auth_instance *ablock, uschar *data) {return 0;}
int auth_gsasl_client(auth_instance *ablock, void * sx,
int timeout, uschar *buffer, int buffsize) {return 0;}
void auth_gsasl_version_report(FILE *f) {}
gstring * auth_gsasl_version_report(gstring * g) {return NULL;}

void
auth_gsasl_macros(void)
Expand Down Expand Up @@ -200,15 +204,21 @@ if (!gsasl_client_support_p(gsasl_ctx, CCS ob->server_mech))
"GNU SASL does not support mechanism \"%s\"",
ablock->name, ob->server_mech);

ablock->server = TRUE;

if ( !ablock->server_condition
&& ( streqic(ob->server_mech, US"EXTERNAL")
|| streqic(ob->server_mech, US"ANONYMOUS")
|| streqic(ob->server_mech, US"PLAIN")
|| streqic(ob->server_mech, US"LOGIN")
) )
if (ablock->server_condition)
ablock->server = TRUE;
else if( ob->server_mech
&& !STREQIC(ob->server_mech, US"EXTERNAL")
&& !STREQIC(ob->server_mech, US"ANONYMOUS")
&& !STREQIC(ob->server_mech, US"PLAIN")
&& !STREQIC(ob->server_mech, US"LOGIN")
)
{
/* At present, for mechanisms we don't panic on absence of server_condition;
need to figure out the most generically correct approach to deciding when
it's critical and when it isn't. Eg, for simple validation (PLAIN mechanism,
etc) it clearly is critical.
*/

ablock->server = FALSE;
HDEBUG(D_auth) debug_printf("%s authenticator: "
"Need server_condition for %s mechanism\n",
Expand All @@ -219,20 +229,14 @@ if ( !ablock->server_condition
which properties will be needed. */

if ( !ob->server_realm
&& streqic(ob->server_mech, US"DIGEST-MD5"))
&& STREQIC(ob->server_mech, US"DIGEST-MD5"))
{
ablock->server = FALSE;
HDEBUG(D_auth) debug_printf("%s authenticator: "
"Need server_realm for %s mechanism\n",
ablock->name, ob->server_mech);
}

/* At present, for mechanisms we don't panic on absence of server_condition;
need to figure out the most generically correct approach to deciding when
it's critical and when it isn't. Eg, for simple validation (PLAIN mechanism,
etc) it clearly is critical.
*/

ablock->client = ob->client_username && ob->client_password;
}

Expand Down Expand Up @@ -638,10 +642,10 @@ static int
server_callback(Gsasl *ctx, Gsasl_session *sctx, Gsasl_property prop,
auth_instance *ablock)
{
char *tmps;
uschar *s, *propval;
char * tmps;
uschar * s;
int cbrc = GSASL_NO_CALLBACK;
auth_gsasl_options_block *ob =
auth_gsasl_options_block * ob =
(auth_gsasl_options_block *)(ablock->options_block);

HDEBUG(D_auth) debug_printf("GNU SASL callback %s for %s/%s as server\n",
Expand Down Expand Up @@ -782,7 +786,6 @@ set_client_prop(Gsasl_session * sctx, Gsasl_property prop, uschar * val,
unsigned flags, uschar * buffer, int buffsize)
{
uschar * s;
int rc;

if (!val) return !!(flags & PROP_OPTIONAL);
if (!(s = expand_string(val)) || !(flags & PROP_OPTIONAL) && !*s)
Expand Down Expand Up @@ -894,24 +897,27 @@ if (tls_out.channelbinding)
for(s = NULL; ;)
{
uschar * outstr;
BOOL fail;
BOOL fail = TRUE;

rc = gsasl_step64(sctx, CS s, CSS &outstr);

fail = initial
? smtp_write_command(sx, SCMD_FLUSH,
outstr ? "AUTH %s %s\r\n" : "AUTH %s\r\n",
ablock->public_name, outstr) <= 0
: outstr
? smtp_write_command(sx, SCMD_FLUSH, "%s\r\n", outstr) <= 0
: FALSE;
if (outstr && *outstr) free(outstr);
if (fail)
if (rc == GSASL_NEEDS_MORE || rc == GSASL_OK)
{
yield = FAIL_SEND;
goto done;
fail = initial
? smtp_write_command(sx, SCMD_FLUSH,
outstr ? "AUTH %s %s\r\n" : "AUTH %s\r\n",
ablock->public_name, outstr) <= 0
: outstr
? smtp_write_command(sx, SCMD_FLUSH, "%s\r\n", outstr) <= 0
: FALSE;
free(outstr);
if (fail)
{
yield = FAIL_SEND;
goto done;
}
initial = FALSE;
}
initial = FALSE;

if (rc != GSASL_NEEDS_MORE)
{
Expand Down Expand Up @@ -966,7 +972,7 @@ switch (prop)
HDEBUG(D_auth)
debug_printf(" filling in\n");
gsasl_property_set(sctx, GSASL_CB_TLS_UNIQUE, CCS tls_out.channelbinding);
break;
return GSASL_OK;
case GSASL_SCRAM_SALTED_PASSWORD:
{
uschar * client_spassword =
Expand Down Expand Up @@ -999,14 +1005,12 @@ return GSASL_NO_CALLBACK;
* Diagnostic API *
*************************************************/

void
auth_gsasl_version_report(FILE *f)
gstring *
auth_gsasl_version_report(gstring * g)
{
const char *runtime;
runtime = gsasl_check_version(NULL);
fprintf(f, "Library version: GNU SASL: Compile: %s\n"
" Runtime: %s\n",
GSASL_VERSION, runtime);
return string_fmt_append(g, "Library version: GNU SASL: Compile: %s\n"
" Runtime: %s\n",
GSASL_VERSION, gsasl_check_version(NULL));
}


Expand Down
4 changes: 2 additions & 2 deletions src/src/auths/gsasl_exim.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2019 - 2022 */
/* Copyright (c) University of Cambridge 1995 - 2012 */
/* Copyright (c) The Exim Maintainers 2019-2020 */
/* See the file NOTICE for conditions of use and distribution. */

/* Copyright (c) Twitter Inc 2012 */
Expand Down Expand Up @@ -47,7 +47,7 @@ extern void auth_gsasl_init(auth_instance *);
extern int auth_gsasl_server(auth_instance *, uschar *);
extern int auth_gsasl_client(auth_instance *, void *,
int, uschar *, int);
extern void auth_gsasl_version_report(FILE *f);
extern gstring * auth_gsasl_version_report(gstring *);
extern void auth_gsasl_macros(void);

/* End of gsasl_exim.h */
15 changes: 8 additions & 7 deletions src/src/auths/heimdal_gssapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2020 - 2022 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */

/* Copyright (c) Twitter Inc 2012
Expand Down Expand Up @@ -85,7 +85,7 @@ void auth_heimdal_gssapi_init(auth_instance *ablock) {}
int auth_heimdal_gssapi_server(auth_instance *ablock, uschar *data) {return 0;}
int auth_heimdal_gssapi_client(auth_instance *ablock, void * sx,
int timeout, uschar *buffer, int buffsize) {return 0;}
void auth_heimdal_gssapi_version_report(FILE *f) {}
gstring * auth_heimdal_gssapi_version_report(gstring * g) {}

#else /*!MACRO_PREDEF*/

Expand Down Expand Up @@ -601,14 +601,15 @@ return FAIL;
* Diagnostic API *
*************************************************/

void
auth_heimdal_gssapi_version_report(FILE *f)
gstring *
auth_heimdal_gssapi_version_report(gstring * g)
{
/* No build-time constants available unless we link against libraries at
build-time and export the result as a string into a header ourselves. */
fprintf(f, "Library version: Heimdal: Runtime: %s\n"
" Build Info: %s\n",
heimdal_version, heimdal_long_version);

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

#endif /*!MACRO_PREDEF*/
Expand Down
3 changes: 2 additions & 1 deletion src/src/auths/heimdal_gssapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2022 */
/* Copyright (c) University of Cambridge 1995 - 2012 */
/* See the file NOTICE for conditions of use and distribution. */

Expand Down Expand Up @@ -33,6 +34,6 @@ extern auth_heimdal_gssapi_options_block auth_heimdal_gssapi_option_defaults;
extern void auth_heimdal_gssapi_init(auth_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(FILE *f);
extern void auth_heimdal_gssapi_version_report(BOOL);

/* End of heimdal_gssapi.h */
2 changes: 1 addition & 1 deletion src/src/auths/plaintext.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*************************************************/

/* Copyright (c) University of Cambridge 1995 - 2018 */
/* Copyright (c) The Exim Maintainers 2020 */
/* Copyright (c) The Exim Maintainers 2020 - 2021 */
/* See the file NOTICE for conditions of use and distribution. */

#include "../exim.h"
Expand Down
3 changes: 2 additions & 1 deletion src/src/auths/pwcheck.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Tim Martin
* $Id: checkpw.c,v 1.49 2002/03/07 19:14:04 ken3 Exp $
*/
/* Copyright (c) The Exim Maintainers 2021 - 2022 */
/*
* Copyright (c) 2001 Carnegie Mellon University. All rights reserved.
*
Expand Down Expand Up @@ -291,7 +292,7 @@ static int read_string(int fd, uschar **retval) {
return -1;
} else {
/* Assume the file is trusted, so no tainting */
*retval = store_get(count + 1, FALSE);
*retval = store_get(count + 1, GET_UNTAINTED);
rc = (retry_read(fd, *retval, count) < (int) count);
(*retval)[count] = '\0';
return count;
Expand Down
3 changes: 2 additions & 1 deletion src/src/auths/xtextdecode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2022 */
/* Copyright (c) University of Cambridge 1995 - 2009 */
/* See the file NOTICE for conditions of use and distribution. */

Expand Down Expand Up @@ -33,7 +34,7 @@ int
auth_xtextdecode(uschar *code, uschar **ptr)
{
register int x;
uschar *result = store_get(Ustrlen(code) + 1, is_tainted(code));
uschar * result = store_get(Ustrlen(code) + 1, code);
*ptr = result;

while ((x = (*code++)) != 0)
Expand Down
3 changes: 2 additions & 1 deletion src/src/auths/xtextencode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2022 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */

Expand Down Expand Up @@ -40,7 +41,7 @@ in order to get the right amount of store. */
while (c -- > 0)
count += ((x = *p++) < 33 || x > 127 || x == '+' || x == '=')? 3 : 1;

pp = code = store_get(count, is_tainted(clear));
pp = code = store_get(count, clear);

p = US clear;
c = len;
Expand Down
17 changes: 9 additions & 8 deletions src/src/base64.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/* License: GPL */

/* Copyright (c) University of Cambridge 1995 - 2018 */
/* Copyright (c) The Exim Maintainers 2020 */
/* Copyright (c) The Exim Maintainers 2020 - 2022 */
/* See the file NOTICE for conditions of use and distribution. */


Expand Down Expand Up @@ -157,10 +157,10 @@ b64decode(const uschar *code, uschar **ptr)
int x, y;
uschar *result;

{
{
int l = Ustrlen(code);
*ptr = result = store_get(1 + l/4 * 3 + l%4, is_tainted(code));
}
*ptr = result = store_get(1 + l/4 * 3 + l%4, code);
}

/* Each cycle of the loop handles a quantum of 4 input bytes. For the last
quantum this may decode to 1, 2, or 3 output bytes. */
Expand Down Expand Up @@ -234,6 +234,7 @@ would probably run more slowly.
Arguments:
clear points to the clear text bytes
len the number of bytes to encode
proto_mem taint indicator

Returns: a pointer to the zero-terminated base 64 string, which
is in working store
Expand All @@ -243,10 +244,10 @@ static uschar *enc64table =
US"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

uschar *
b64encode_taint(const uschar * clear, int len, BOOL tainted)
b64encode_taint(const uschar * clear, int len, const void * proto_mem)
{
uschar *code = store_get(4*((len+2)/3) + 1, tainted);
uschar *p = code;
uschar * code = store_get(4*((len+2)/3) + 1, proto_mem);
uschar * p = code;

while (len-- >0)
{
Expand Down Expand Up @@ -287,7 +288,7 @@ return code;
uschar *
b64encode(const uschar * clear, int len)
{
return b64encode_taint(clear, len, is_tainted(clear));
return b64encode_taint(clear, len, clear);
}


Expand Down
11 changes: 6 additions & 5 deletions src/src/bmi_spam.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
/* Code for calling Brightmail AntiSpam.
Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004
License: GPL */
/* Copyright (c) The Exim Maintainers 2021 - 2022 */

#include "exim.h"
#ifdef EXPERIMENTAL_BRIGHTMAIL
Expand Down Expand Up @@ -193,16 +194,16 @@ uschar *bmi_process_message(header_line *header_list, int data_fd) {
/* Get store for the verdict string. Since we are processing message data, assume that
the verdict is tainted. XXX this should use a growable-string */

verdicts = store_get(1, TRUE);
verdicts = store_get(1, GET_TAINTED);
*verdicts = '\0';

for ( err = bmiAccessFirstVerdict(message, &verdict);
verdict != NULL;
verdict;
err = bmiAccessNextVerdict(message, verdict, &verdict) ) {
char *verdict_str;

err = bmiCreateStrFromVerdict(verdict,&verdict_str);
if (!store_extend(verdicts, TRUE,
if (!store_extend(verdicts,
Ustrlen(verdicts)+1, Ustrlen(verdicts)+1+strlen(verdict_str)+1)) {
/* can't allocate more store */
return NULL;
Expand Down Expand Up @@ -302,7 +303,7 @@ uschar *bmi_get_alt_location(uschar *base64_verdict) {
}
else {
/* deliver to alternate location */
rc = store_get(strlen(bmiVerdictAccessDestination(verdict))+1, TRUE);
rc = store_get(strlen(bmiVerdictAccessDestination(verdict))+1, GET_TAINTED);
Ustrcpy(rc, bmiVerdictAccessDestination(verdict));
rc[strlen(bmiVerdictAccessDestination(verdict))] = '\0';
};
Expand All @@ -327,7 +328,7 @@ uschar *bmi_get_base64_verdict(uschar *bmi_local_part, uschar *bmi_domain) {
return NULL;

/* allocate room for the b64 verdict string */
verdict_buffer = store_get(Ustrlen(bmi_verdicts)+1, TRUE);
verdict_buffer = store_get(Ustrlen(bmi_verdicts)+1, GET_TAINTED);

/* loop through verdicts */
verdict_ptr = bmi_verdicts;
Expand Down
8 changes: 3 additions & 5 deletions src/src/buildconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2022 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */

Expand Down Expand Up @@ -51,7 +52,7 @@ typedef struct {
char *data;
} save_item;

static const char *db_opts[] = { "", "USE_DB", "USE_GDBM", "USE_TDB" };
static const char *db_opts[] = { "", "USE_DB", "USE_GDBM", "USE_TDB", "USE_NDBM" };

static int have_ipv6 = 0;
static int have_iconv = 0;
Expand Down Expand Up @@ -221,8 +222,7 @@ else

/* Now search the makefile for certain settings */

base = fopen("Makefile", "rb");
if (base == NULL)
if (!(base = fopen("Makefile", "rb")))
{
printf("*** Buildconfig: failed to open Makefile\n");
(void)fclose(new);
Expand Down Expand Up @@ -387,7 +387,6 @@ while (fgets(buffer, sizeof(buffer), base) != NULL)
encountered. */

for (i = 1; i < sizeof(db_opts)/sizeof(char *); i++)
{
if (strcmp(name, db_opts[i]) == 0)
{
if (use_which_db == i)
Expand All @@ -397,7 +396,6 @@ while (fgets(buffer, sizeof(buffer), base) != NULL)
fprintf(new, "/* %s not set */\n", name);
break;
}
}
if (i < sizeof(db_opts)/sizeof(char *)) continue;

/* EXIM_USER is a special case. We look in the environment for EXIM_USER or
Expand Down
47 changes: 31 additions & 16 deletions src/src/child.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2020 - 2022 */
/* Copyright (c) University of Cambridge 1995 - 2015 */
/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */


Expand Down Expand Up @@ -76,22 +76,19 @@ int n = 0;
int extra = pcount ? *pcount : 0;
uschar **argv;

argv = store_get((extra + acount + MAX_CLMACROS + 21) * sizeof(char *), FALSE);
argv = store_get((extra + acount + MAX_CLMACROS + 24) * sizeof(char *), GET_UNTAINTED);

/* In all case, the list starts out with the path, any macros, and a changed
config file. */

argv[n++] = exim_path;
argv[n++] = exim_path; /* assume untainted */
if (clmacro_count > 0)
{
memcpy(argv + n, clmacros, clmacro_count * sizeof(uschar *));
n += clmacro_count;
}
if (f.config_changed)
{
argv[n++] = US"-C";
argv[n++] = config_main_filename;
}
{ argv[n++] = US"-C"; argv[n++] = config_main_filename; }

/* These values are added only for non-minimal cases. If debug_selector is
precisely D_v, we have to assume this was started by a non-admin user, and
Expand All @@ -108,24 +105,35 @@ if (!minimal)
else
{
if (debug_selector != 0)
{
argv[n++] = string_sprintf("-d=0x%x", debug_selector);
if (debug_fd > 2)
{
int flags = fcntl(debug_fd, F_GETFD);
if (flags != -1) (void)fcntl(debug_fd, F_SETFD, flags & ~FD_CLOEXEC);
close(2);
dup2(debug_fd, 2);
close(debug_fd);
}
}
}
if (debug_pretrigger_buf)
{ argv[n++] = US"-dp"; argv[n++] = string_sprintf("0x%x", debug_pretrigger_bsize); }
if (dtrigger_selector != 0)
argv[n++] = string_sprintf("-dt=0x%x", dtrigger_selector);
DEBUG(D_any)
{
argv[n++] = US"-MCd";
argv[n++] = US process_purpose;
}
if (!f.testsuite_delays) argv[n++] = US"-odd";
if (f.dont_deliver) argv[n++] = US"-N";
if (f.queue_smtp) argv[n++] = US"-odqs";
if (f.synchronous_delivery) argv[n++] = US"-odi";
if (!f.testsuite_delays) argv[n++] = US"-odd";
if (f.dont_deliver) argv[n++] = US"-N";
if (f.queue_smtp) argv[n++] = US"-odqs";
if (f.synchronous_delivery) argv[n++] = US"-odi";
if (connection_max_messages >= 0)
argv[n++] = string_sprintf("-oB%d", connection_max_messages);
if (*queue_name)
{
argv[n++] = US"-MCG";
argv[n++] = queue_name;
}
{ argv[n++] = US"-MCG"; argv[n++] = queue_name; }
}

/* Now add in any others that are in the call. Remember which they were,
Expand Down Expand Up @@ -159,7 +167,7 @@ exim_nullstd(); /* Make sure std{in,out,err} exist */
execv(CS argv[0], (char *const *)argv);

log_write(0,
LOG_MAIN | ((exec_type == CEE_EXEC_EXIT)? LOG_PANIC : LOG_PANIC_DIE),
LOG_MAIN | (exec_type == CEE_EXEC_EXIT ? LOG_PANIC : LOG_PANIC_DIE),
"re-exec of exim (%s) with %s failed: %s", exim_path, argv[first_special],
strerror(errno));

Expand Down Expand Up @@ -335,6 +343,13 @@ int save_errno;
int inpfd[2], outpfd[2];
pid_t pid;

if (is_tainted(argv[0]))
{
log_write(0, LOG_MAIN | LOG_PANIC, "Attempt to exec tainted path: '%s'", argv[0]);
errno = EPERM;
return (pid_t)(-1);
}

/* Create the pipes. */

if (pipe(inpfd) != 0) return (pid_t)(-1);
Expand Down
10 changes: 5 additions & 5 deletions src/src/config.h.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2018 - 2022 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* Copyright (c) The Exim Maintainers 2018-2020 */
/* See the file NOTICE for conditions of use and distribution. */

/* The default settings for Exim configuration variables. A #define without
Expand All @@ -17,8 +17,6 @@ Do not put spaces between # and the 'define'.
#define ALT_CONFIG_PREFIX
#define TRUSTED_CONFIG_LIST

#define ALLOW_INSECURE_TAINTED_DATA

#define APPENDFILE_MODE 0600
#define APPENDFILE_DIRECTORY_MODE 0700
#define APPENDFILE_LOCKFILE_MODE 0600
Expand Down Expand Up @@ -48,6 +46,9 @@ Do not put spaces between # and the 'define'.
#define DEFAULT_CRYPT crypt
#define DELIVER_IN_BUFFER_SIZE 8192
#define DELIVER_OUT_BUFFER_SIZE 8192

#define DISABLE_CLIENT_CMD_LOG
#define DISABLE_D_OPTION
#define DISABLE_DNSSEC
#define DISABLE_DKIM
#define DISABLE_EVENT
Expand All @@ -57,7 +58,6 @@ Do not put spaces between # and the 'define'.
#define DISABLE_QUEUE_RAMP
#define DISABLE_TLS
#define DISABLE_TLS_RESUME
#define DISABLE_D_OPTION

#define ENABLE_DISABLE_FSYNC

Expand Down Expand Up @@ -181,6 +181,7 @@ Do not put spaces between # and the 'define'.
#define USE_GDBM
#define USE_GNUTLS
#define AVOID_GNUTLS_PKCS11
#define USE_NDBM
#define USE_OPENSSL
#define USE_READLINE
#define USE_TCP_WRAPPERS
Expand Down Expand Up @@ -209,7 +210,6 @@ Do not put spaces between # and the 'define'.
#define EXPERIMENTAL_DSN_INFO
#define EXPERIMENTAL_ESMTP_LIMITS
#define EXPERIMENTAL_QUEUEFILE
#define EXPERIMENTAL_SRS_ALT


/* For developers */
Expand Down
140 changes: 69 additions & 71 deletions src/src/daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2020 - 2022 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */

/* Functions concerned with running Exim as a daemon */
Expand Down Expand Up @@ -87,7 +87,7 @@ sigchld_seen = TRUE;
}


/* SIGTERM handler. Try to get the damon pif file removed
/* SIGTERM handler. Try to get the daemon pid file removed
before exiting. */

static void
Expand Down Expand Up @@ -141,7 +141,7 @@ Uunlink(s);

static void
close_daemon_sockets(int daemon_notifier_fd,
int * listen_sockets, int listen_socket_count)
struct pollfd * fd_polls, int listen_socket_count)
{
if (daemon_notifier_fd >= 0)
{
Expand All @@ -152,7 +152,7 @@ if (daemon_notifier_fd >= 0)
#endif
}

for (int i = 0; i < listen_socket_count; i++) (void) close(listen_sockets[i]);
for (int i = 0; i < listen_socket_count; i++) (void) close(fd_polls[i].fd);
}


Expand All @@ -167,7 +167,7 @@ is required so that they can be closed in the sub-process. Take care not to
leak store in this process - reset the stacking pool at the end.

Arguments:
listen_sockets sockets which are listening for incoming calls
fd_polls sockets which are listening for incoming calls
listen_socket_count count of listening sockets
accept_socket socket of the current accepted call
accepted socket information about the current call
Expand All @@ -176,7 +176,7 @@ Returns: nothing
*/

static void
handle_smtp_call(int *listen_sockets, int listen_socket_count,
handle_smtp_call(struct pollfd *fd_polls, int listen_socket_count,
int accept_socket, struct sockaddr *accepted)
{
pid_t pid;
Expand Down Expand Up @@ -459,7 +459,7 @@ if (pid == 0)
extensive comment before the reception loop in exim.c for a fuller
explanation of this logic. */

close_daemon_sockets(daemon_notifier_fd, listen_sockets, listen_socket_count);
close_daemon_sockets(daemon_notifier_fd, fd_polls, listen_socket_count);

/* Set FD_CLOEXEC on the SMTP socket. We don't want any rogue child processes
to be able to communicate with them, under any circumstances. */
Expand Down Expand Up @@ -793,10 +793,8 @@ else (void)close(dup_accept_socket);
the incoming host address and an expanded active_hostname. */

log_close_all();
interface_address =
sender_host_address = NULL;
interface_address = sender_host_name = sender_host_address = NULL;
store_reset(reset_point);
sender_host_address = NULL;
}


Expand Down Expand Up @@ -1305,13 +1303,6 @@ return FALSE;



static void
add_listener_socket(int fd, fd_set * fds, int * fd_max)
{
FD_SET(fd, fds);
if (fd > *fd_max) *fd_max = fd;
}

/*************************************************
* Exim Daemon Mainline *
*************************************************/
Expand Down Expand Up @@ -1339,9 +1330,8 @@ void
daemon_go(void)
{
struct passwd * pw;
int * listen_sockets = NULL;
int listen_socket_count = 0, listen_fd_max = 0;
fd_set select_listen;
struct pollfd * fd_polls, * tls_watch_poll = NULL, * dnotify_poll = NULL;
int listen_socket_count = 0, poll_fd_count;
ip_address_item * addresses = NULL;
time_t last_connection_time = (time_t)0;
int local_queue_run_max = atoi(CS expand_string(queue_run_max));
Expand All @@ -1353,17 +1343,21 @@ debugging lines get the pid added. */

DEBUG(D_any|D_v) debug_selector |= D_pid;

FD_ZERO(&select_listen);
/* Allocate enough pollstructs for inetd mode plus the ancillary sockets;
also used when there are no listen sockets. */

fd_polls = store_get(sizeof(struct pollfd) * 3, GET_UNTAINTED);

if (f.inetd_wait_mode)
{
listen_socket_count = 1;
listen_sockets = store_get(sizeof(int), FALSE);
(void) close(3);
if (dup2(0, 3) == -1)
log_write(0, LOG_MAIN|LOG_PANIC_DIE,
"failed to dup inetd socket safely away: %s", strerror(errno));

listen_sockets[0] = 3;
fd_polls[0].fd = 3;
fd_polls[0].events = POLLIN;
(void) close(0);
(void) close(1);
(void) close(2);
Expand All @@ -1390,9 +1384,6 @@ if (f.inetd_wait_mode)
if (setsockopt(3, IPPROTO_TCP, TCP_NODELAY, US &on, sizeof(on)))
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to set socket NODELAY: %s",
strerror(errno));

FD_SET(3, &select_listen);
listen_fd_max = 3;
}


Expand Down Expand Up @@ -1543,7 +1534,7 @@ if (f.daemon_listen && !f.inetd_wait_mode)
sep = 0;
while ((s = string_nextinlist(&list, &sep, NULL, 0)))
pct++;
default_smtp_port = store_get((pct+1) * sizeof(int), FALSE);
default_smtp_port = store_get((pct+1) * sizeof(int), GET_UNTAINTED);
list = daemon_smtp_port;
sep = 0;
for (pct = 0;
Expand Down Expand Up @@ -1632,7 +1623,7 @@ if (f.daemon_listen && !f.inetd_wait_mode)
ipa->port = default_smtp_port[0];
for (int i = 1; default_smtp_port[i] > 0; i++)
{
ip_address_item *new = store_get(sizeof(ip_address_item), FALSE);
ip_address_item * new = store_get(sizeof(ip_address_item), GET_UNTAINTED);

memcpy(new->address, ipa->address, Ustrlen(ipa->address) + 1);
new->port = default_smtp_port[i];
Expand Down Expand Up @@ -1686,11 +1677,16 @@ if (f.daemon_listen && !f.inetd_wait_mode)
}
}

/* Get a vector to remember all the sockets in */
/* Get a vector to remember all the sockets in.
Two extra elements for the ancillary sockets */

for (ipa = addresses; ipa; ipa = ipa->next)
listen_socket_count++;
listen_sockets = store_get(sizeof(int) * listen_socket_count, FALSE);
fd_polls = store_get(sizeof(struct pollfd) * (listen_socket_count + 2),
GET_UNTAINTED);
for (struct pollfd * p = fd_polls; p < fd_polls + listen_socket_count + 2;
p++)
{ p->fd = -1; p->events = POLLIN; }

} /* daemon_listen but not inetd_wait_mode */

Expand All @@ -1713,7 +1709,7 @@ if (f.daemon_listen)

if (smtp_accept_max > 0)
{
smtp_slots = store_get(smtp_accept_max * sizeof(smtp_slot), FALSE);
smtp_slots = store_get(smtp_accept_max * sizeof(smtp_slot), GET_UNTAINTED);
for (int i = 0; i < smtp_accept_max; i++) smtp_slots[i] = empty_smtp_slot;
}
}
Expand Down Expand Up @@ -1795,7 +1791,7 @@ if (f.daemon_listen && !f.inetd_wait_mode)
wildcard = ipa->address[0] == 0;
}

if ((listen_sockets[sk] = fd = ip_socket(SOCK_STREAM, af)) < 0)
if ((fd_polls[sk].fd = fd = ip_socket(SOCK_STREAM, af)) < 0)
{
if (check_special_case(0, addresses, ipa, FALSE))
{
Expand All @@ -1804,7 +1800,7 @@ if (f.daemon_listen && !f.inetd_wait_mode)
goto SKIP_SOCKET;
}
log_write(0, LOG_PANIC_DIE, "IPv%c socket creation failed: %s",
(af == AF_INET6)? '6' : '4', strerror(errno));
af == AF_INET6 ? '6' : '4', strerror(errno));
}

/* If this is an IPv6 wildcard socket, set IPV6_V6ONLY if that option is
Expand Down Expand Up @@ -1903,8 +1899,7 @@ if (f.daemon_listen && !f.inetd_wait_mode)
f.tcp_fastopen_ok = FALSE;
}
#endif

add_listener_socket(fd, &select_listen, &listen_fd_max);
fd_polls[sk].fd = fd;
continue;
}

Expand Down Expand Up @@ -1996,7 +1991,7 @@ of them (and also if we are doing queue runs). */

if (queue_interval > 0 && local_queue_run_max > 0)
{
queue_pid_slots = store_get(local_queue_run_max * sizeof(pid_t), FALSE);
queue_pid_slots = store_get(local_queue_run_max * sizeof(pid_t), GET_UNTAINTED);
for (int i = 0; i < local_queue_run_max; i++) queue_pid_slots[i] = 0;
}

Expand Down Expand Up @@ -2187,14 +2182,21 @@ tls_daemon_init();

/* Add ancillary sockets to the set for select */

poll_fd_count = listen_socket_count;
#ifndef DISABLE_TLS
if (tls_watch_fd >= 0)
add_listener_socket(tls_watch_fd, &select_listen, &listen_fd_max);
{
tls_watch_poll = &fd_polls[poll_fd_count++];
tls_watch_poll->fd = tls_watch_fd;
tls_watch_poll->events = POLLIN;
}
#endif
if (daemon_notifier_fd >= 0)
add_listener_socket(daemon_notifier_fd, &select_listen, &listen_fd_max);

listen_fd_max++;
{
dnotify_poll = &fd_polls[poll_fd_count++];
dnotify_poll->fd = daemon_notifier_fd;
dnotify_poll->events = POLLIN;
}

/* Close the log so it can be renamed and moved. In the few cases below where
this long-running process writes to the log (always exceptional conditions), it
Expand Down Expand Up @@ -2293,7 +2295,7 @@ for (;;)
/* Close any open listening sockets in the child */

close_daemon_sockets(daemon_notifier_fd,
listen_sockets, listen_socket_count);
fd_polls, listen_socket_count);

/* Reset SIGHUP and SIGCHLD in the child in both cases. */

Expand Down Expand Up @@ -2421,9 +2423,8 @@ for (;;)

if (f.daemon_listen)
{
int check_lsk = 0, lcount;
int lcount;
BOOL select_failed = FALSE;
fd_set fds = select_listen;

DEBUG(D_any) debug_printf("Listening...\n");

Expand All @@ -2440,8 +2441,7 @@ for (;;)
errno = EINTR;
}
else
lcount = select(listen_fd_max, (SELECT_ARG2_TYPE *)&fds,
NULL, NULL, NULL);
lcount = poll(fd_polls, poll_fd_count, -1);

if (lcount < 0)
{
Expand All @@ -2461,15 +2461,15 @@ for (;;)
handle_ending_processes();

#ifndef DISABLE_TLS
{
int old_tfd;
/* Create or rotate any required keys; handle (delayed) filewatch event */
for (int old_tfd = tls_daemon_tick(); old_tfd >= 0; )
{
FD_CLR(old_tfd, &select_listen);
if (old_tfd == listen_fd_max - 1) listen_fd_max = old_tfd;
if (tls_watch_fd >= 0)
add_listener_socket(tls_watch_fd, &select_listen, &listen_fd_max);
break;
}

if ((old_tfd = tls_daemon_tick()) >= 0)
for (struct pollfd * p = &fd_polls[listen_socket_count];
p < fd_polls + poll_fd_count; p++)
if (p->fd == old_tfd) { p->fd = tls_watch_fd ; break; }
}
#endif
errno = select_errno;
}
Expand All @@ -2490,22 +2490,23 @@ for (;;)
if (!select_failed)
{
#if !defined(DISABLE_TLS) && (defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT))
if (tls_watch_fd >= 0 && FD_ISSET(tls_watch_fd, &fds))
if (tls_watch_poll && tls_watch_poll->revents & POLLIN)
{
tls_watch_poll->revents = 0;
tls_watch_trigger_time = time(NULL); /* Set up delayed event */
tls_watch_discard_event(tls_watch_fd);
break; /* to top of daemon loop */
}
#endif
if (daemon_notifier_fd >= 0 && FD_ISSET(daemon_notifier_fd, &fds))
if (dnotify_poll && dnotify_poll->revents & POLLIN)
{
dnotify_poll->revents = 0;
sigalrm_seen = daemon_notification();
break; /* to top of daemon loop */
}
while (check_lsk < listen_socket_count)
{
int lfd = listen_sockets[check_lsk++];
if (FD_ISSET(lfd, &fds))
for (struct pollfd * p = fd_polls; p < fd_polls + listen_socket_count;
p++)
if (p->revents & POLLIN)
{
EXIM_SOCKLEN_T alen = sizeof(accepted);
#ifdef TCP_INFO
Expand All @@ -2516,23 +2517,23 @@ for (;;)

smtp_listen_backlog = 0;
if ( smtp_backlog_monitor > 0
&& getsockopt(lfd, IPPROTO_TCP, TCP_INFO, &ti, &tlen) == 0)
&& getsockopt(p->fd, IPPROTO_TCP, TCP_INFO, &ti, &tlen) == 0)
{
# ifdef EXIM_HAVE_TCPI_UNACKED
DEBUG(D_interface) debug_printf("listen fd %d queue max %u curr %u\n",
lfd, ti.tcpi_sacked, ti.tcpi_unacked);
p->fd, ti.tcpi_sacked, ti.tcpi_unacked);
smtp_listen_backlog = ti.tcpi_unacked;
# elif defined(__FreeBSD__) /* This does not work. Investigate kernel sourcecode. */
DEBUG(D_interface) debug_printf("listen fd %d queue max %u curr %u\n",
lfd, ti.__tcpi_sacked, ti.__tcpi_unacked);
p->fd, ti.__tcpi_sacked, ti.__tcpi_unacked);
smtp_listen_backlog = ti.__tcpi_unacked;
# endif
}
#endif
accept_socket = accept(lfd, (struct sockaddr *)&accepted, &alen);
p->revents = 0;
accept_socket = accept(p->fd, (struct sockaddr *)&accepted, &alen);
break;
}
}
}

/* If select or accept has failed and this was not caused by an
Expand Down Expand Up @@ -2591,7 +2592,7 @@ for (;;)
#endif
if (inetd_wait_timeout)
last_connection_time = time(NULL);
handle_smtp_call(listen_sockets, listen_socket_count, accept_socket,
handle_smtp_call(fd_polls, listen_socket_count, accept_socket,
(struct sockaddr *)&accepted);
}
}
Expand All @@ -2606,10 +2607,8 @@ for (;;)

else
{
struct timeval tv;
tv.tv_sec = queue_interval;
tv.tv_usec = 0;
select(0, NULL, NULL, NULL, &tv);
struct pollfd p;
poll(&p, 0, queue_interval * 1000);
handle_ending_processes();
}

Expand All @@ -2634,8 +2633,7 @@ for (;;)
{
log_write(0, LOG_MAIN, "pid %d: SIGHUP received: re-exec daemon",
getpid());
close_daemon_sockets(daemon_notifier_fd,
listen_sockets, listen_socket_count);
close_daemon_sockets(daemon_notifier_fd, fd_polls, listen_socket_count);
ALARM_CLR(0);
signal(SIGHUP, SIG_IGN);
sighup_argv[0] = exim_path;
Expand Down
93 changes: 34 additions & 59 deletions src/src/dbfn.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2020 - 2022 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */


Expand Down Expand Up @@ -38,31 +38,6 @@ arrange to hold the locks for the bare minimum of time. */



/*************************************************
* Berkeley DB error callback *
*************************************************/

/* For Berkeley DB >= 2, we can define a function to be called in case of DB
errors. This should help with debugging strange DB problems, e.g. getting "File
exists" when you try to open a db file. The API for this function was changed
at DB release 4.3. */

#if defined(USE_DB) && defined(DB_VERSION_STRING)
void
#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)
dbfn_bdb_error_callback(const DB_ENV *dbenv, const char *pfx, const char *msg)
{
dbenv = dbenv;
#else
dbfn_bdb_error_callback(const char *pfx, char *msg)
{
#endif
pfx = pfx;
log_write(0, LOG_MAIN, "Berkeley DB error: %s", msg);
}
#endif


/*************************************************
* Open and lock a database file *
*************************************************/
Expand Down Expand Up @@ -172,12 +147,12 @@ open call. */
snprintf(CS filename, sizeof(filename), "%s/%s", dirname, name);

priv_drop_temp(exim_uid, exim_gid);
EXIM_DBOPEN(filename, dirname, flags, EXIMDB_MODE, &(dbblock->dbptr));
dbblock->dbptr = exim_dbopen(filename, dirname, flags, EXIMDB_MODE);
if (!dbblock->dbptr && errno == ENOENT && flags == O_RDWR)
{
DEBUG(D_hints_lookup)
debug_printf_indent("%s appears not to exist: trying to create\n", filename);
EXIM_DBOPEN(filename, dirname, flags|O_CREAT, EXIMDB_MODE, &(dbblock->dbptr));
dbblock->dbptr = exim_dbopen(filename, dirname, flags|O_CREAT, EXIMDB_MODE);
}
save_errno = errno;
priv_restore();
Expand Down Expand Up @@ -232,7 +207,7 @@ Returns: nothing
void
dbfn_close(open_db *dbblock)
{
EXIM_DBCLOSE(dbblock->dbptr);
exim_dbclose(dbblock->dbptr);
(void)close(dbblock->lockfd);
DEBUG(D_hints_lookup)
{ debug_printf_indent("closed hints database and lockfile\n"); acl_level--; }
Expand Down Expand Up @@ -268,27 +243,27 @@ dbfn_read_with_length(open_db *dbblock, const uschar *key, int *length)
void *yield;
EXIM_DATUM key_datum, result_datum;
int klen = Ustrlen(key) + 1;
uschar * key_copy = store_get(klen, is_tainted(key));
uschar * key_copy = store_get(klen, key);

memcpy(key_copy, key, klen);

DEBUG(D_hints_lookup) debug_printf_indent("dbfn_read: key=%s\n", key);

EXIM_DATUM_INIT(key_datum); /* Some DBM libraries require the datum */
EXIM_DATUM_INIT(result_datum); /* to be cleared before use. */
EXIM_DATUM_DATA(key_datum) = CS key_copy;
EXIM_DATUM_SIZE(key_datum) = klen;
exim_datum_init(&key_datum); /* Some DBM libraries require the datum */
exim_datum_init(&result_datum); /* to be cleared before use. */
exim_datum_data_set(&key_datum, key_copy);
exim_datum_size_set(&key_datum, klen);

if (!EXIM_DBGET(dbblock->dbptr, key_datum, result_datum)) return NULL;
if (!exim_dbget(dbblock->dbptr, &key_datum, &result_datum)) return NULL;

/* Assume the data store could have been tainted. Properly, we should
store the taint status with the data. */

yield = store_get(EXIM_DATUM_SIZE(result_datum), TRUE);
memcpy(yield, EXIM_DATUM_DATA(result_datum), EXIM_DATUM_SIZE(result_datum));
if (length != NULL) *length = EXIM_DATUM_SIZE(result_datum);
yield = store_get(exim_datum_size_get(&result_datum), GET_TAINTED);
memcpy(yield, exim_datum_data_get(&result_datum), exim_datum_size_get(&result_datum));
if (length) *length = exim_datum_size_get(&result_datum);

EXIM_DATUM_FREE(result_datum); /* Some DBM libs require freeing */
exim_datum_free(&result_datum); /* Some DBM libs require freeing */
return yield;
}

Expand Down Expand Up @@ -343,20 +318,20 @@ dbfn_write(open_db *dbblock, const uschar *key, void *ptr, int length)
EXIM_DATUM key_datum, value_datum;
dbdata_generic *gptr = (dbdata_generic *)ptr;
int klen = Ustrlen(key) + 1;
uschar * key_copy = store_get(klen, is_tainted(key));
uschar * key_copy = store_get(klen, key);

memcpy(key_copy, key, klen);
gptr->time_stamp = time(NULL);

DEBUG(D_hints_lookup) debug_printf_indent("dbfn_write: key=%s\n", key);

EXIM_DATUM_INIT(key_datum); /* Some DBM libraries require the datum */
EXIM_DATUM_INIT(value_datum); /* to be cleared before use. */
EXIM_DATUM_DATA(key_datum) = CS key_copy;
EXIM_DATUM_SIZE(key_datum) = klen;
EXIM_DATUM_DATA(value_datum) = CS ptr;
EXIM_DATUM_SIZE(value_datum) = length;
return EXIM_DBPUT(dbblock->dbptr, key_datum, value_datum);
exim_datum_init(&key_datum); /* Some DBM libraries require the datum */
exim_datum_init(&value_datum); /* to be cleared before use. */
exim_datum_data_set(&key_datum, key_copy);
exim_datum_size_set(&key_datum, klen);
exim_datum_data_set(&value_datum, ptr);
exim_datum_size_set(&value_datum, length);
return exim_dbput(dbblock->dbptr, &key_datum, &value_datum);
}


Expand All @@ -377,16 +352,16 @@ int
dbfn_delete(open_db *dbblock, const uschar *key)
{
int klen = Ustrlen(key) + 1;
uschar * key_copy = store_get(klen, is_tainted(key));
uschar * key_copy = store_get(klen, key);
EXIM_DATUM key_datum;

DEBUG(D_hints_lookup) debug_printf_indent("dbfn_delete: key=%s\n", key);

memcpy(key_copy, key, klen);
EXIM_DATUM key_datum;
EXIM_DATUM_INIT(key_datum); /* Some DBM libraries require clearing */
EXIM_DATUM_DATA(key_datum) = CS key_copy;
EXIM_DATUM_SIZE(key_datum) = klen;
return EXIM_DBDEL(dbblock->dbptr, key_datum);
exim_datum_init(&key_datum); /* Some DBM libraries require clearing */
exim_datum_data_set(&key_datum, key_copy);
exim_datum_size_set(&key_datum, klen);
return exim_dbdel(dbblock->dbptr, &key_datum);
}


Expand Down Expand Up @@ -417,17 +392,17 @@ DEBUG(D_hints_lookup) debug_printf_indent("dbfn_scan\n");

/* Some dbm require an initialization */

if (start) EXIM_DBCREATE_CURSOR(dbblock->dbptr, cursor);
if (start) *cursor = exim_dbcreate_cursor(dbblock->dbptr);

EXIM_DATUM_INIT(key_datum); /* Some DBM libraries require the datum */
EXIM_DATUM_INIT(value_datum); /* to be cleared before use. */
exim_datum_init(&key_datum); /* Some DBM libraries require the datum */
exim_datum_init(&value_datum); /* to be cleared before use. */

yield = (EXIM_DBSCAN(dbblock->dbptr, key_datum, value_datum, start, *cursor))?
US EXIM_DATUM_DATA(key_datum) : NULL;
yield = exim_dbscan(dbblock->dbptr, &key_datum, &value_datum, start, *cursor)
? US exim_datum_data_get(&key_datum) : NULL;

/* Some dbm require a termination */

if (!yield) EXIM_DBDELETE_CURSOR(*cursor);
if (!yield) exim_dbdelete_cursor(*cursor);
return yield;
}

Expand Down
10 changes: 7 additions & 3 deletions src/src/dbfunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
* Exim - an Internet mail transport agent *
*************************************************/

/* Copyright (c) The Exim Maintainers 2022 */
/* Copyright (c) University of Cambridge 1995 - 2021 */
/* See the file NOTICE for conditions of use and distribution. */

#ifndef DBFUNCTIONS_H
#define DBFUNCTIONS_H

/* Functions for reading/writing exim database files */

Expand All @@ -24,11 +27,12 @@ int dbfn_write(open_db *, const uschar *, void *, int);
changed at release 4.3. */

#if defined(USE_DB) && defined(DB_VERSION_STRING)
#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)
# if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)
void dbfn_bdb_error_callback(const DB_ENV *, const char *, const char *);
#else
# else
void dbfn_bdb_error_callback(const char *, char *);
#endif
# endif
#endif

#endif
/* End of dbfunctions.h */
Loading