2063 lines
73 KiB
Diff
2063 lines
73 KiB
Diff
diff -ruN a/doc/ChangeLog b/doc/ChangeLog
|
|
--- a/doc/ChangeLog 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/doc/ChangeLog 2023-09-14 18:46:51.395566820 +0300
|
|
@@ -220,6 +220,17 @@
|
|
QS/04 Always die if requested from internal logging, even is logging is
|
|
disabled.
|
|
|
|
+JH/52 Fix ${ip6norm:} operator. Previously, any trailing line text was dropped,
|
|
+ making it unusable in complex expressions.
|
|
+
|
|
+JH/53 Bug 2743: fix immediate-delivery via named queue. Previously this would
|
|
+ fail with a taint-check on the spoolfile name, and leave the message
|
|
+ queued.
|
|
+
|
|
+JH/57 Fix control=fakreject for a custom message containing tainted data.
|
|
+ Previously this resulted in a log complaint, due to a re-expansion present
|
|
+ since fakereject was originally introduced.
|
|
+
|
|
|
|
Exim version 4.94
|
|
-----------------
|
|
diff -ruN a/doc/exim.8 b/doc/exim.8
|
|
--- a/doc/exim.8 2021-04-30 15:12:05.000000000 +0300
|
|
+++ b/doc/exim.8 2023-09-14 18:49:54.436045697 +0300
|
|
@@ -1,9 +1,9 @@
|
|
-.TH EXIM 8
|
|
+.TH EXIM4 8
|
|
.SH NAME
|
|
-exim \- a Mail Transfer Agent
|
|
+exim4 \- a Mail Transfer Agent
|
|
.SH SYNOPSIS
|
|
.nf
|
|
-.B exim [options] arguments ...
|
|
+.B exim4 [options] arguments ...
|
|
.B mailq [options] arguments ...
|
|
.B rsmtp [options] arguments ...
|
|
.B rmail [options] arguments ...
|
|
@@ -40,7 +40,7 @@
|
|
recipients) is assumed. Thus, for example, if Exim is installed in
|
|
\fI/usr/sbin\fP, you can send a message from the command line like this:
|
|
.sp
|
|
- /usr/sbin/exim -i <recipient-address(es)>
|
|
+ /usr/sbin/exim4 -i <recipient-address(es)>
|
|
<message content, including all the header lines>
|
|
CTRL-D
|
|
.sp
|
|
@@ -125,8 +125,8 @@
|
|
.sp
|
|
When a listening daemon
|
|
is started without the use of \fB\-oX\fP (that is, without overriding the normal
|
|
-configuration), it writes its process id to a file called exim\-daemon.pid
|
|
-in Exim's spool directory. This location can be overridden by setting
|
|
+configuration), it writes its process id to a file called
|
|
+/run/exim4/exim.pid. This location can be overridden by setting
|
|
PID_FILE_PATH in Local/Makefile. The file is written while Exim is still
|
|
running as root.
|
|
.sp
|
|
@@ -180,7 +180,7 @@
|
|
This option operates like \fB\-be\fP except that it must be followed by the name
|
|
of a file. For example:
|
|
.sp
|
|
- exim \-bem /tmp/testmessage
|
|
+ exim4 \-bem /tmp/testmessage
|
|
.sp
|
|
The file is read as a message (as if receiving a locally\-submitted non\-SMTP
|
|
message) before any of the test expansions are done. Thus, message\-specific
|
|
@@ -206,7 +206,7 @@
|
|
can use both \fB\-bF\fP and \fB\-bf\fP on the same command, in order to test a system
|
|
filter and a user filter in the same run. For example:
|
|
.sp
|
|
- exim \-bF /system/filter \-bf /user/filter </test/message
|
|
+ exim4 \-bF /system/filter \-bf /user/filter </test/message
|
|
.sp
|
|
This is helpful when the system filter adds header lines or sets filter
|
|
variables that are used by the user filter.
|
|
@@ -258,8 +258,8 @@
|
|
standard input and output. The IP address may include a port number at the end,
|
|
after a full stop. For example:
|
|
.sp
|
|
- exim \-bh 10.9.8.7.1234
|
|
- exim \-bh fe80::a00:20ff:fe86:a061.5678
|
|
+ exim4 \-bh 10.9.8.7.1234
|
|
+ exim4 \-bh fe80::a00:20ff:fe86:a061.5678
|
|
.sp
|
|
When an IPv6 address is given, it is converted into canonical form. In the case
|
|
of the second example above, the value of \fI$sender_host_address\fP after
|
|
@@ -417,7 +417,7 @@
|
|
of one or more specific options can be requested by giving their names as
|
|
arguments, for example:
|
|
.sp
|
|
- exim \-bP qualify_domain hold_domains
|
|
+ exim4 \-bP qualify_domain hold_domains
|
|
.sp
|
|
However, any option setting that is preceded by the word "hide" in the
|
|
configuration file is not shown in full, except to an admin user. For other
|
|
@@ -445,7 +445,7 @@
|
|
.sp
|
|
If \fB\-bP\fP is followed by a name preceded by +, for example,
|
|
.sp
|
|
- exim \-bP +local_domains
|
|
+ exim4 \-bP +local_domains
|
|
.sp
|
|
it searches for a matching named list of any type (domain, host, address, or
|
|
local part) and outputs what it finds.
|
|
@@ -454,7 +454,7 @@
|
|
followed by the name of an appropriate driver instance, the option settings for
|
|
that driver are output. For example:
|
|
.sp
|
|
- exim \-bP transport local_delivery
|
|
+ exim4 \-bP transport local_delivery
|
|
.sp
|
|
The generic driver options are output first, followed by the driver's private
|
|
options. A list of the names of drivers of a particular type can be obtained by
|
|
@@ -539,7 +539,7 @@
|
|
arguments. It causes Exim to look for a retry rule that matches the values
|
|
and to write it to the standard output. For example:
|
|
.sp
|
|
- exim \-brt bach.comp.mus.example
|
|
+ exim4 \-brt bach.comp.mus.example
|
|
Retry rule: *.comp.mus.example F,2h,15m; F,4d,30m;
|
|
.sp
|
|
The first
|
|
@@ -552,7 +552,7 @@
|
|
sought. Finally, an argument that is the name of a specific delivery error, as
|
|
used in setting up retry rules, can be given. For example:
|
|
.sp
|
|
- exim \-brt haydn.comp.mus.example quota_3d
|
|
+ exim4 \-brt haydn.comp.mus.example quota_3d
|
|
Retry rule: *@haydn.comp.mus.example quota_3d F,1h,15m
|
|
.TP 10
|
|
\fB\-brw\fP
|
|
@@ -655,7 +655,7 @@
|
|
.TP 10
|
|
\fB\-bV\fP
|
|
This option causes Exim to write the current version number, compilation
|
|
-number, and compilation date of the \fIexim\fP binary to the standard output.
|
|
+number, and compilation date of the \fIexim4\fP binary to the standard output.
|
|
It also lists the DBM library that is being used, the optional modules (such as
|
|
specific lookup types), the drivers that are included in the binary, and the
|
|
name of the runtime configuration file that is in use.
|
|
@@ -683,7 +683,7 @@
|
|
right angle bracket for addresses to be verified.
|
|
.sp
|
|
Unlike the \fB\-be\fP test option, you cannot arrange for Exim to use the
|
|
-readline() function, because it is running as \fIexim\fP and there are
|
|
+readline() function, because it is running as \fIexim4\fP and there are
|
|
security issues.
|
|
.sp
|
|
Verification differs from address testing (the \fB\-bt\fP option) in that routers
|
|
@@ -796,14 +796,14 @@
|
|
string, in which case the equals sign is optional. These two commands are
|
|
synonymous:
|
|
.sp
|
|
- exim \-DABC ...
|
|
- exim \-DABC= ...
|
|
+ exim4 \-DABC ...
|
|
+ exim4 \-DABC= ...
|
|
.sp
|
|
To include spaces in a macro definition item, quotes must be used. If you use
|
|
quotes, spaces are permitted around the macro name and the equals sign. For
|
|
example:
|
|
.sp
|
|
- exim '\-D ABC = something' ...
|
|
+ exim4 '\-D ABC = something' ...
|
|
.sp
|
|
\fB\-D\fP may be repeated up to 10 times on a command line.
|
|
Only macro names up to 22 letters long can be set.
|
|
@@ -939,8 +939,8 @@
|
|
string, or as a pair of angle brackets with nothing between them, as in these
|
|
examples of shell commands:
|
|
.sp
|
|
- exim \-f '<>' user@domain
|
|
- exim \-f "" user@domain
|
|
+ exim4 \-f '<>' user@domain
|
|
+ exim4 \-f "" user@domain
|
|
.sp
|
|
In addition, the use of \fB\-f\fP is not restricted when testing a filter file
|
|
with \fB\-bf\fP or when testing or verifying addresses using the \fB\-bt\fP or
|
|
@@ -1337,12 +1337,12 @@
|
|
The \fB\-oMa\fP option sets the sender host address. This may include a port
|
|
number at the end, after a full stop (period). For example:
|
|
.sp
|
|
- exim \-bs \-oMa 10.9.8.7.1234
|
|
+ exim4 \-bs \-oMa 10.9.8.7.1234
|
|
.sp
|
|
An alternative syntax is to enclose the IP address in square brackets,
|
|
followed by a colon and the port number:
|
|
.sp
|
|
- exim \-bs \-oMa [10.9.8.7]:1234
|
|
+ exim4 \-bs \-oMa [10.9.8.7]:1234
|
|
.sp
|
|
The IP address is placed in the \fI$sender_host_address\fP variable, and the
|
|
port, if present, in \fI$sender_host_port\fP. If both \fB\-oMa\fP and \fB\-bh\fP
|
|
@@ -1449,6 +1449,17 @@
|
|
is also given. It controls which ports and interfaces the daemon uses. When \fB\-oX\fP is used to start a daemon, no pid
|
|
file is written unless \fB\-oP\fP is also present to specify a pid filename.
|
|
.TP 10
|
|
+\fB\-oY\fP
|
|
+This option controls the creation of an inter-process communications endpoint
|
|
+by the Exim daemon. It is only relevant when the \fB\-bd\fP (start listening
|
|
+daemon) option is also given.
|
|
+Normally the daemon creates this socket, unless a \fB\-oX\fP and no \fB\-oP\fP
|
|
+option is also present.
|
|
+If this option is given then the socket will not be created. This could be
|
|
+required if the system is running multiple daemons.
|
|
+The socket is currently used for fast ramp-up of queue runner processes and
|
|
+obtaining a current queue size.
|
|
+.TP 10
|
|
\fB\-pd\fP
|
|
This option applies when an embedded Perl interpreter is linked with Exim. It overrides the setting of the \fBperl_at_start\fP
|
|
option, forcing the starting of the interpreter to be delayed until it is
|
|
@@ -1555,22 +1566,22 @@
|
|
will specify a queue to operate on.
|
|
For example:
|
|
.sp
|
|
- exim \-bp \-qGquarantine
|
|
+ exim4 \-bp \-qGquarantine
|
|
mailq \-qGquarantine
|
|
- exim \-qGoffpeak \-Rf @special.domain.example
|
|
+ exim4 \-qGoffpeak \-Rf @special.domain.example
|
|
.TP 10
|
|
\fB\-q\fP<\fIqflags\fP> <\fIstart id\fP> <\fIend id\fP>
|
|
When scanning the queue, Exim can be made to skip over messages whose ids are
|
|
lexically less than a given value by following the \fB\-q\fP option with a
|
|
starting message id. For example:
|
|
.sp
|
|
- exim \-q 0t5C6f\-0000c8\-00
|
|
+ exim4 \-q 0t5C6f\-0000c8\-00
|
|
.sp
|
|
Messages that arrived earlier than 0t5C6f\-0000c8\-00 are not inspected. If a
|
|
second message id is given, messages whose ids are lexically greater than it
|
|
are also skipped. If the same id is given twice, for example,
|
|
.sp
|
|
- exim \-q 0t5C6f\-0000c8\-00 0t5C6f\-0000c8\-00
|
|
+ exim4 \-q 0t5C6f\-0000c8\-00 0t5C6f\-0000c8\-00
|
|
.sp
|
|
just one delivery process is started, for that message. This differs from
|
|
\fB\-M\fP in that retry data is respected, and it also differs from \fB\-Mc\fP in
|
|
@@ -1586,7 +1597,7 @@
|
|
single daemon process handles both functions. A common way of starting up a
|
|
combined daemon at system boot time is to use a command such as
|
|
.sp
|
|
- /usr/exim/bin/exim \-bd \-q30m
|
|
+ /usr/sbin/exim4 \-bd \-q30m
|
|
.sp
|
|
Such a daemon listens for incoming SMTP calls, and also starts a queue runner
|
|
process every 30 minutes.
|
|
@@ -1617,7 +1628,7 @@
|
|
If you want to do periodic queue runs for messages with specific recipients,
|
|
you can combine \fB\-R\fP with \fB\-q\fP and a time value. For example:
|
|
.sp
|
|
- exim \-q25m \-R @special.domain.example
|
|
+ exim4 \-q25m \-R @special.domain.example
|
|
.sp
|
|
This example does a queue run for messages with recipients in the given domain
|
|
every 25 minutes. Any additional flags that are specified with \fB\-q\fP are
|
|
@@ -1733,6 +1744,26 @@
|
|
.sp
|
|
.
|
|
.SH "SEE ALSO"
|
|
+.BR exicyclog (8),
|
|
+.BR exigrep (8),
|
|
+.BR exim_checkaccess (8),
|
|
+.BR exim_convert4r4 (8),
|
|
+.BR exim_db (8),
|
|
+.BR exim_dbmbuild (8),
|
|
+.BR exim_lock (8),
|
|
+.BR eximon (8),
|
|
+.BR exinext (8),
|
|
+.BR exiqgrep (8),
|
|
+.BR exiqsumm (8),
|
|
+.BR exiwhat (8),
|
|
+.BR update\-exim4.conf (8),
|
|
+.BR update\-exim4defaults (8),
|
|
+/usr/share/doc/exim4\-base/,
|
|
+/usr/share/doc/exim4\-base/README.Debian.[gz|html].
|
|
.rs
|
|
.sp
|
|
The full Exim specification, the Exim book, and the Exim wiki.
|
|
+
|
|
+.SH AUTHOR
|
|
+This manual page was provided with the upstream Exim source package.
|
|
+It was enhanced for the Debian GNU/Linux system.
|
|
diff -ruN a/doc/NewStuff b/doc/NewStuff
|
|
--- a/doc/NewStuff 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/doc/NewStuff 2023-09-14 18:49:54.420045306 +0300
|
|
@@ -6,6 +6,57 @@
|
|
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.
|
|
|
|
+Cherrypicked from GIT master:
|
|
+------------
|
|
+
|
|
+10. A command-line option to have a daemon not create a notifier socket.
|
|
+
|
|
+
|
|
+Version 4.95
|
|
+------------
|
|
+
|
|
+ 1. The fast-ramp two phase queue run support, previously experimental, is
|
|
+ now supported by default.
|
|
+
|
|
+ 2. The native SRS support, previously experimental, is now supported. It is
|
|
+ not built unless specified in the Local/Makefile.
|
|
+
|
|
+ 3. TLS resumption support, previously experimental, is now supported and
|
|
+ included in default builds.
|
|
+
|
|
+ 4. Single-key LMDB lookups, previously experimental, are now supported.
|
|
+ The support is not built unless specified in the Local/Makefile.
|
|
+
|
|
+ 5. Option "message_linelength_limit" on the smtp transport to enforce (by
|
|
+ default) the RFC 998 character limit.
|
|
+
|
|
+ 6. An option to ignore the cache on a lookup.
|
|
+
|
|
+ 7. Quota checking during reception (i.e. at SMTP time) for appendfile-
|
|
+ transport-managed quotas.
|
|
+
|
|
+ 8. Sqlite lookups accept a "file=<path>" option to specify a per-operation
|
|
+ db file, replacing the previous prefix to the SQL string (which had
|
|
+ issues when the SQL used tainted values).
|
|
+
|
|
+ 9. Lsearch lookups accept a "ret=full" option, to return both the portion
|
|
+ of the line matching the key, and the remainder.
|
|
+
|
|
+10. A command-line option to have a daemon not create a notifier socket.
|
|
+
|
|
+11. Faster TLS startup. When various configuration options contain no
|
|
+ expandable elements, the information can be preloaded and cached rather
|
|
+ than the provious behaviour of always loading at startup time for every
|
|
+ connection. This helps particularly for the CA bundle.
|
|
+
|
|
+12. Proxy Protocol Timeout is configurable via "proxy_protocol_timeout"
|
|
+ main config option.
|
|
+
|
|
+13. Option "smtp_accept_msx_per_connection" is now expanded.
|
|
+
|
|
+13. A main config option "allow_insecure_tainted_data" allows to turn
|
|
+ taint errors into warnings.
|
|
+
|
|
Version 4.94
|
|
------------
|
|
|
|
diff -ruN a/doc/spec.txt b/doc/spec.txt
|
|
--- a/doc/spec.txt 2021-04-30 15:12:05.000000000 +0300
|
|
+++ b/doc/spec.txt 2023-09-14 18:49:54.436045697 +0300
|
|
@@ -4193,6 +4193,19 @@
|
|
options, are given in chapter 13. When -oX is used to start a daemon, no
|
|
pid file is written unless -oP is also present to specify a pid filename.
|
|
|
|
+-oY
|
|
+
|
|
+ This option controls the creation of an inter-process communications
|
|
+ endpoint by the Exim daemon. It is only relevant when the -bd
|
|
+ (start listening daemon) option is also given. Normally the daemon
|
|
+ creates this socket, unless a oX and no -oP option is also
|
|
+ present. If this option is given then the socket will not be created.
|
|
+ This could be required if the system is running multiple daemons.
|
|
+
|
|
+ The socket is currently used for
|
|
+ * fast ramp-up of queue runner processes
|
|
+ * obtaining a current queue size
|
|
+
|
|
-pd
|
|
|
|
This option applies when an embedded Perl interpreter is linked with Exim
|
|
@@ -8651,8 +8664,16 @@
|
|
options for which string expansion is performed are marked with * after the
|
|
data type. ACL rules always expand strings. A couple of expansion conditions do
|
|
not expand some of the brace-delimited branches, for security reasons, and
|
|
-expansion of data deriving from the sender ("tainted data") is not permitted.
|
|
-
|
|
+expansion of data deriving from the sender ("tainted data") is not permitted
|
|
+(including acessing a file using a tainted name). The main config
|
|
+option allow_insecure_tainted_data can be used as mitigation during
|
|
+uprades to more secure configurations.
|
|
+
|
|
+Common ways of obtaining untainted equivalents of variables with tainted
|
|
+values come down to using the tainted value as a lookup key in a trusted
|
|
+database. This database could be the filesystem structure, or the
|
|
+password file, or accessed via a DBMS. Specific methods are indexed
|
|
+under "de-tainting".
|
|
|
|
11.1 Literal text in expanded strings
|
|
-------------------------------------
|
|
@@ -11729,6 +11750,8 @@
|
|
|
|
This variable contains the number of messages queued. It is evaluated on
|
|
demand, but no more often than once every minute.
|
|
+ If there is no daemon notifier socket open, the value will be
|
|
+ an empty string.
|
|
|
|
$r_...
|
|
|
|
@@ -12944,6 +12967,8 @@
|
|
14.1 Miscellaneous
|
|
------------------
|
|
|
|
+add_environment environment variables
|
|
+allow_insecure_tainted_data turn taint errors into warnings
|
|
bi_command to run for -bi command line option
|
|
debug_store do extra internal checks
|
|
disable_ipv6 do no IPv6 processing
|
|
@@ -13551,6 +13576,16 @@
|
|
matches the domain literal form of all the local host's IP addresses.
|
|
|
|
+-----------------------------------------------------+
|
|
+|allow_insecure_tainted_data main boolean false |
|
|
++-----------------------------------------------------+
|
|
+
|
|
+The handling of tainted data may break older (pre 4.94) configurations.
|
|
+Setting this option to "true" turns taint errors (which result in a temporary
|
|
+message rejection) into warnings. This option is meant as mitigation only
|
|
+and deprecated already today. Future releases of Exim may ignore it.
|
|
+The taint log selector can be used to suppress even the warnings.
|
|
+
|
|
++-----------------------------------------------------+
|
|
|allow_mx_to_ip|Use: main|Type: boolean|Default: false|
|
|
+-----------------------------------------------------+
|
|
|
|
@@ -15211,10 +15246,12 @@
|
|
sharing a spool directory should need to modify the default.
|
|
|
|
The option is expanded before use. If the platform supports Linux-style
|
|
-abstract socket names, the result is used with a nul byte prefixed. Otherwise,
|
|
-it should be a full path name and use a directory accessible to Exim.
|
|
+abstract socket names, the result is used with a nul byte prefixed.
|
|
+Otherwise, if nonempty, it should be a full path name and use a directory
|
|
+accessible to Exim.
|
|
|
|
-If the Exim command line uses a -oX option and does not use -oP then a notifier
|
|
+If this option is set as empty, or the command line -oY option is used, or
|
|
+the command line uses a -oX option and does not use -oP, then a notifier
|
|
socket is not created.
|
|
|
|
+-----------------------------------------------------------------------------+
|
|
@@ -35330,6 +35367,7 @@
|
|
smtp_protocol_error SMTP protocol errors
|
|
smtp_syntax_error SMTP syntax errors
|
|
subject contents of Subject: on <= lines
|
|
+*taint taint errors or warnings
|
|
*tls_certificate_verified certificate verification status
|
|
*tls_cipher TLS cipher suite on <= and => lines
|
|
tls_peerdn TLS peer DN on <= and => lines
|
|
@@ -35618,7 +35656,9 @@
|
|
when TLS is in use. The item is "CV=yes" if the peer's certificate was
|
|
verified using a CA trust anchor, "CA=dane" if using a DNS trust anchor,
|
|
and "CV=no" if not.
|
|
-
|
|
+ * taint: Log warnings about tainted data. This selector can't be
|
|
+ turned of if allow_insecure_tainted_data is false (which is the
|
|
+ default).
|
|
* tls_cipher: When a message is sent or received over an encrypted
|
|
connection, the cipher suite used is added to the log line, preceded by X=.
|
|
|
|
diff -ruN a/OS/eximon.conf-Default b/OS/eximon.conf-Default
|
|
--- a/OS/eximon.conf-Default 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/OS/eximon.conf-Default 2023-09-14 18:45:28.069528181 +0300
|
|
@@ -5,7 +5,7 @@
|
|
# The name of the eximon binary, usually the same as the eximon script,
|
|
# with .bin stuck on the end.
|
|
|
|
-EXIMON_BINARY="${EXIMON_BINARY-$0.bin}"
|
|
+EXIMON_BINARY="/usr/libexec/exim4/${EXIMON_BINARY-${0##*/}.bin}"
|
|
|
|
# The remaining parameters are values likely to be changed to suit the
|
|
# user's taste. They are documented in the EDITME file.
|
|
diff -ruN a/OS/Makefile-Base b/OS/Makefile-Base
|
|
--- a/OS/Makefile-Base 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/OS/Makefile-Base 2023-09-14 18:41:42.980022143 +0300
|
|
@@ -228,7 +228,7 @@
|
|
$(FE)$(LNCC) -o $@ $(LFLAGS) $(OBJ_MACRO)
|
|
|
|
macro.c: macro_predef
|
|
- ./macro_predef > macro.c
|
|
+ macro_predef > macro.c
|
|
|
|
# This target is recognized specially by GNU make. It records those targets
|
|
# that do not correspond to files that are being built and which should
|
|
diff -ruN a/OS/Makefile-Linux b/OS/Makefile-Linux
|
|
--- a/OS/Makefile-Linux 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/OS/Makefile-Linux 2023-09-14 18:45:21.885376889 +0300
|
|
@@ -31,9 +31,9 @@
|
|
X11_LD_LIB=$(X11)/lib
|
|
|
|
EXIWHAT_PS_ARG=ax
|
|
-EXIWHAT_EGREP_ARG='/exim( |$$)'
|
|
+EXIWHAT_EGREP_ARG='/exim4( |$$)'
|
|
EXIWHAT_MULTIKILL_CMD=killall
|
|
-EXIWHAT_MULTIKILL_ARG=exim
|
|
+EXIWHAT_MULTIKILL_ARG=exim4
|
|
EXIWHAT_KILL_SIGNAL=-USR1
|
|
|
|
# End
|
|
diff -ruN a/README b/README
|
|
--- a/README 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/README 2023-09-14 18:46:14.142655374 +0300
|
|
@@ -14,8 +14,16 @@
|
|
older book may be helpful for the background, but a lot of the detail has
|
|
changed, so it is likely to be confusing to newcomers.
|
|
|
|
-There is a website at https://www.exim.org; this contains details of the
|
|
-mailing list exim-users@exim.org.
|
|
+Information about the way Debian has built the binary packages is
|
|
+obtainable in /usr/share/doc/exim4-base/README.Debian.gz, and there
|
|
+is a Debian-centered mailing list,
|
|
+pkg-exim4-users@lists.alioth.debian.org. Please ask Debian-specific
|
|
+questions there, and only write to the upstream exim-users mailing
|
|
+list if you are sure that your question is not Debian-specific. You
|
|
+can find the subscription web page on
|
|
+http://lists.alioth.debian.org/mailman/listinfo/pkg-exim4-users
|
|
+
|
|
+There is a website at https://www.exim.org/.
|
|
|
|
A copy of the Exim FAQ should be available from the same source that you used
|
|
to obtain the Exim distribution. Additional formats for the documentation
|
|
diff -ruN a/src/acl.c b/src/acl.c
|
|
--- a/src/acl.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/acl.c 2023-09-14 18:48:55.194596003 +0300
|
|
@@ -3137,7 +3137,9 @@
|
|
{
|
|
const uschar *pp = p + 1;
|
|
while (*pp) pp++;
|
|
- fake_response_text = expand_string(string_copyn(p+1, pp-p-1));
|
|
+ /* The entire control= line was expanded at top so no need to expand
|
|
+ the part after the / */
|
|
+ fake_response_text = string_copyn(p+1, pp-p-1);
|
|
p = pp;
|
|
}
|
|
else /* Explicitly reset to default string */
|
|
@@ -3598,20 +3600,22 @@
|
|
#endif
|
|
|
|
case ACLC_QUEUE:
|
|
- if (is_tainted(arg))
|
|
{
|
|
- *log_msgptr = string_sprintf("Tainted name '%s' for queue not permitted",
|
|
- arg);
|
|
- return ERROR;
|
|
- }
|
|
- if (Ustrchr(arg, '/'))
|
|
- {
|
|
- *log_msgptr = string_sprintf(
|
|
- "Directory separator not permitted in queue name: '%s'", arg);
|
|
- return ERROR;
|
|
+ uschar *m;
|
|
+ if ((m = is_tainted2(arg, 0, "Tainted name '%s' for queue not permitted", arg)))
|
|
+ {
|
|
+ *log_msgptr = m;
|
|
+ return ERROR;
|
|
+ }
|
|
+ if (Ustrchr(arg, '/'))
|
|
+ {
|
|
+ *log_msgptr = string_sprintf(
|
|
+ "Directory separator not permitted in queue name: '%s'", arg);
|
|
+ return ERROR;
|
|
+ }
|
|
+ queue_name = string_copy_perm(arg, FALSE);
|
|
+ break;
|
|
}
|
|
- queue_name = string_copy_perm(arg, FALSE);
|
|
- break;
|
|
|
|
case ACLC_RATELIMIT:
|
|
rc = acl_ratelimit(arg, where, log_msgptr);
|
|
@@ -4007,10 +4011,8 @@
|
|
else if (*ss == '/')
|
|
{
|
|
struct stat statbuf;
|
|
- if (is_tainted(ss))
|
|
+ if (is_tainted2(ss, LOG_MAIN|LOG_PANIC, "Tainted ACL file name '%s'", ss))
|
|
{
|
|
- log_write(0, LOG_MAIN|LOG_PANIC,
|
|
- "attempt to open tainted ACL file name \"%s\"", ss);
|
|
/* Avoid leaking info to an attacker */
|
|
*log_msgptr = US"internal configuration error";
|
|
return ERROR;
|
|
diff -ruN a/src/config.h.defaults b/src/config.h.defaults
|
|
--- a/src/config.h.defaults 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/config.h.defaults 2023-09-14 18:50:04.368288757 +0300
|
|
@@ -17,6 +17,8 @@
|
|
#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
|
|
@@ -33,6 +35,8 @@
|
|
|
|
#define AUTH_VARS 3
|
|
|
|
+#define DLOPEN_LOCAL_SCAN
|
|
+
|
|
#define BIN_DIRECTORY
|
|
|
|
#define CONFIGURE_FILE
|
|
diff -ruN a/src/convert4r4.src b/src/convert4r4.src
|
|
--- a/src/convert4r4.src 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/convert4r4.src 2023-09-14 18:45:56.406221440 +0300
|
|
@@ -666,6 +666,32 @@
|
|
|
|
print STDERR "Runtime configuration file converter for Exim release 4.\n";
|
|
|
|
+if( !defined $ENV{"CONVERT4R4"} || $ENV{"CONVERT4R4"} ne "I understand this is an unsupported tool" ) {
|
|
+
|
|
+ print STDERR <<EOF;
|
|
+convert4r4 on Debian GNU/Linux deprecated
|
|
+
|
|
+This tool is unsupported by upstream and discouraged by the Debian Exim 4
|
|
+maintainers. It has multiple known bugs, and you need to manually
|
|
+review its output after using it anyway. Please seriously consider complete
|
|
+manual regeneration of the Exim 4 configuration, preferably by using the new
|
|
+Debconf interface to Exim 4.
|
|
+
|
|
+If you decide to ignore this advice and to use this script anyway,
|
|
+setting the environment variable CONVERT4R4 to the value
|
|
+\"I understand this is an unsupported tool\"
|
|
+will allow you to run the script. If you find bugs, you get to keep
|
|
+the pieces. Please do not file bugs against this script in the Debian
|
|
+BTS without providing a patch fixing the bugs, and please do not
|
|
+expect the upstream exim-users mailing list to answer questions.
|
|
+
|
|
+Kind regards
|
|
+the Debian Exim4 Maintainers
|
|
+EOF
|
|
+
|
|
+ exit 1;
|
|
+}
|
|
+
|
|
$transport_start = $director_start = $router_start = $retry_start
|
|
= $rewrite_start = $auth_start = 999999;
|
|
|
|
diff -ruN a/src/daemon.c b/src/daemon.c
|
|
--- a/src/daemon.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/daemon.c 2023-09-14 18:49:54.424045404 +0300
|
|
@@ -1144,6 +1144,11 @@
|
|
struct sockaddr_un sa_un = {.sun_family = AF_UNIX};
|
|
int len;
|
|
|
|
+if (!notifier_socket || !*notifier_socket)
|
|
+ {
|
|
+ DEBUG(D_any) debug_printf("-oY used so not creating notifier socket\n");
|
|
+ return;
|
|
+ }
|
|
if (override_local_interfaces && !override_pid_file_path)
|
|
{
|
|
DEBUG(D_any)
|
|
diff -ruN a/src/dbstuff.h b/src/dbstuff.h
|
|
--- a/src/dbstuff.h 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/dbstuff.h 2023-09-14 18:47:22.300322976 +0300
|
|
@@ -643,11 +643,9 @@
|
|
: (flags) == O_RDWR ? "O_RDWR" \
|
|
: (flags) == (O_RDWR|O_CREAT) ? "O_RDWR|O_CREAT" \
|
|
: "??"); \
|
|
- if (is_tainted(name) || is_tainted(dirname)) \
|
|
- { \
|
|
- log_write(0, LOG_MAIN|LOG_PANIC, "Tainted name for DB file not permitted"); \
|
|
+ if (is_tainted2(name, LOG_MAIN|LOG_PANIC, "Tainted name '%s' for DB file not permitted", name) \
|
|
+ || is_tainted2(dirname, LOG_MAIN|LOG_PANIC, "Tainted name '%s' for DB directory not permitted", dirname)) \
|
|
*dbpp = NULL; \
|
|
- } \
|
|
else \
|
|
{ EXIM_DBOPEN__(name, dirname, flags, mode, dbpp); } \
|
|
DEBUG(D_hints_lookup) debug_printf_indent("returned from EXIM_DBOPEN: %p\n", *dbpp); \
|
|
diff -ruN a/src/deliver.c b/src/deliver.c
|
|
--- a/src/deliver.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/deliver.c 2023-09-14 18:48:55.194596003 +0300
|
|
@@ -5538,10 +5538,11 @@
|
|
if (!s || !*s)
|
|
log_write(0, LOG_MAIN|LOG_PANIC,
|
|
"Failed to expand %s: '%s'\n", varname, filename);
|
|
-else if (*s != '/' || is_tainted(s))
|
|
- log_write(0, LOG_MAIN|LOG_PANIC,
|
|
- "%s is not %s after expansion: '%s'\n",
|
|
- varname, *s == '/' ? "untainted" : "absolute", s);
|
|
+else if (*s != '/')
|
|
+ log_write(0, LOG_MAIN|LOG_PANIC, "%s is not absolute after expansion: '%s'\n",
|
|
+ varname, s);
|
|
+else if (is_tainted2(s, LOG_MAIN|LOG_PANIC, "Tainted %s after expansion: '%s'\n", varname, s))
|
|
+ ;
|
|
else if (!(fp = Ufopen(s, "rb")))
|
|
log_write(0, LOG_MAIN|LOG_PANIC, "Failed to open %s for %s "
|
|
"message texts: %s", s, reason, strerror(errno));
|
|
@@ -6151,9 +6152,10 @@
|
|
if (!tmp)
|
|
p->message = string_sprintf("failed to expand \"%s\" as a "
|
|
"system filter transport name", tpname);
|
|
- if (is_tainted(tmp))
|
|
- p->message = string_sprintf("attempt to used tainted value '%s' for"
|
|
- "transport '%s' as a system filter", tmp, tpname);
|
|
+ { uschar *m;
|
|
+ if ((m = is_tainted2(tmp, 0, "Tainted values '%s' " "for transport '%s' as a system filter", tmp, tpname)))
|
|
+ p->message = m;
|
|
+ }
|
|
tpname = tmp;
|
|
}
|
|
else
|
|
diff -ruN a/src/directory.c b/src/directory.c
|
|
--- a/src/directory.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/directory.c 2023-09-14 18:49:28.279405608 +0300
|
|
@@ -44,6 +44,11 @@
|
|
struct stat statbuf;
|
|
uschar * path;
|
|
|
|
+/* does not work with 4.94
|
|
+if (is_tainted2(name, LOG_MAIN|LOG_PANIC, "Tainted path '%s' for new directory", name))
|
|
+ { p = US"create"; path = US name; errno = EACCES; goto bad; }
|
|
+*/
|
|
+
|
|
if (parent)
|
|
{
|
|
path = string_sprintf("%s%s%s", parent, US"/", name);
|
|
diff -ruN a/src/EDITME b/src/EDITME
|
|
--- a/src/EDITME 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/EDITME 2023-09-14 18:50:04.368288757 +0300
|
|
@@ -749,6 +749,13 @@
|
|
|
|
# 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
|
|
@@ -877,6 +884,21 @@
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
+# On systems which support dynamic loading of shared libraries, Exim can
|
|
+# load a local_scan function specified in its config file instead of having
|
|
+# to be recompiled with the desired local_scan function. For a full
|
|
+# description of the API to this function, see the Exim specification.
|
|
+
|
|
+DLOPEN_LOCAL_SCAN=yes
|
|
+
|
|
+# If you set DLOPEN_LOCAL_SCAN, then you need to include -rdynamic in the
|
|
+# linker flags. Without it, the loaded .so won't be able to access any
|
|
+# functions from exim.
|
|
+
|
|
+LDFLAGS += -rdynamic
|
|
+CFLAGS += -fvisibility=hidden
|
|
+
|
|
+#------------------------------------------------------------------------------
|
|
# The default distribution of Exim contains only the plain text form of the
|
|
# documentation. Other forms are available separately. If you want to install
|
|
# the documentation in "info" format, first fetch the Texinfo documentation
|
|
diff -ruN a/src/exicyclog.src b/src/exicyclog.src
|
|
--- a/src/exicyclog.src 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/exicyclog.src 2023-09-14 18:46:06.870477454 +0300
|
|
@@ -149,12 +149,12 @@
|
|
|
|
st=' '
|
|
exim_path=`grep "^[$st]*exim_path" $config | sed "s/.*=[$st]*//"`
|
|
-if test "$exim_path" = ""; then exim_path=BIN_DIRECTORY/exim; fi
|
|
+if test "$exim_path" = ""; then exim_path=BIN_DIRECTORY/exim4; fi
|
|
|
|
-spool_directory=`$exim_path -C $config -bP spool_directory | sed 's/.*=[ ]*//'`
|
|
+spool_directory=`$exim_path -bP spool_directory | sed 's/.*=[ ]*//'`
|
|
|
|
if [ "$log_file_path" = "" ] ; then
|
|
- log_file_path=`$exim_path -C $config -bP log_file_path | sed 's/.*=[ ]*//'`
|
|
+ log_file_path=`$exim_path -bP log_file_path | sed 's/.*=[ ]*//'`
|
|
fi
|
|
|
|
# If log_file_path contains only "syslog" then no Exim log files are in use.
|
|
diff -ruN a/src/exim.c b/src/exim.c
|
|
--- a/src/exim.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/exim.c 2023-09-14 18:49:54.424045404 +0300
|
|
@@ -2789,9 +2789,11 @@
|
|
else badarg = TRUE;
|
|
break;
|
|
|
|
- /* -MCG: set the queue name, to a non-default value */
|
|
+ /* -MCG: set the queue name, to a non-default value. Arguably, anything
|
|
+ from the commandline should be tainted - but we will need an untainted
|
|
+ value for the spoolfile when doing a -odi delivery process. */
|
|
|
|
- case 'G': if (++i < argc) queue_name = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_DRIVERNAME_MAX, "-MCG"), TRUE);
|
|
+ case 'G': if (++i < argc) queue_name = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_DRIVERNAME_MAX, "-MCG"), FALSE);
|
|
else badarg = TRUE;
|
|
break;
|
|
|
|
@@ -3233,6 +3235,13 @@
|
|
else override_local_interfaces = string_copy_taint(exim_str_fail_toolong(argv[++i], 1024, "-oX"), TRUE);
|
|
break;
|
|
|
|
+ /* -oY: Override creation of daemon notifier socket */
|
|
+
|
|
+ case 'Y':
|
|
+ if (*argrest) badarg = TRUE;
|
|
+ else notifier_socket = NULL;
|
|
+ break;
|
|
+
|
|
/* Unknown -o argument */
|
|
|
|
default:
|
|
@@ -4820,7 +4829,7 @@
|
|
/* Ensure that the user name is in a suitable form for use as a "phrase" in an
|
|
RFC822 address.*/
|
|
|
|
-originator_name = parse_fix_phrase(originator_name, Ustrlen(originator_name));
|
|
+originator_name = US parse_fix_phrase(originator_name, Ustrlen(originator_name));
|
|
|
|
/* If a message is created by this call of Exim, the uid/gid of its originator
|
|
are those of the caller. These values are overridden if an existing message is
|
|
diff -ruN a/src/exim_checkaccess.src b/src/exim_checkaccess.src
|
|
--- a/src/exim_checkaccess.src 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/exim_checkaccess.src 2023-09-14 18:45:21.885376889 +0300
|
|
@@ -52,7 +52,7 @@
|
|
# a tab to keep the tab in one place.
|
|
|
|
exim_path=`perl -ne 'chop;if (/^\s*exim_path\s*=\s*(.*)/){print "$1\n";last;}' $config`
|
|
-if test "$exim_path" = ""; then exim_path=BIN_DIRECTORY/exim; fi
|
|
+if test "$exim_path" = ""; then exim_path=BIN_DIRECTORY/exim4; fi
|
|
|
|
|
|
#########################################################################
|
|
diff -ruN a/src/eximon.src b/src/eximon.src
|
|
--- a/src/eximon.src 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/eximon.src 2023-09-14 18:46:06.870477454 +0300
|
|
@@ -79,10 +79,10 @@
|
|
|
|
st=' '
|
|
EXIM_PATH=`grep "^[$st]*exim_path" $config | sed "s/.*=[$st]*//"`
|
|
-if test "$EXIM_PATH" = ""; then EXIM_PATH=BIN_DIRECTORY/exim; fi
|
|
+if test "$EXIM_PATH" = ""; then EXIM_PATH=BIN_DIRECTORY/exim4; fi
|
|
|
|
-SPOOL_DIRECTORY=`$EXIM_PATH -C $config -bP spool_directory | sed 's/.*=[ ]*//'`
|
|
-LOG_FILE_PATH=`$EXIM_PATH -C $config -bP log_file_path | sed 's/.*=[ ]*//'`
|
|
+SPOOL_DIRECTORY=`$EXIM_PATH -bP spool_directory | sed 's/.*=[ ]*//'`
|
|
+LOG_FILE_PATH=`$EXIM_PATH -bP log_file_path | sed 's/.*=[ ]*//'`
|
|
|
|
# If log_file_path is "syslog" then logging is only to syslog, and the monitor
|
|
# is unable to display a log tail unless EXIMON_LOG_FILE_PATH is set to tell
|
|
diff -ruN a/src/eximstats.src b/src/eximstats.src
|
|
--- a/src/eximstats.src 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/eximstats.src 2023-09-14 18:46:14.142655374 +0300
|
|
@@ -501,6 +501,10 @@
|
|
make test
|
|
make install
|
|
|
|
+On B<Debian GNU/Linux> you can use
|
|
+C<apt-get install libgd-perl libgd-text-perl libgd-graph-perl>
|
|
+instead.
|
|
+
|
|
=item B<-chartdir>I <dir>
|
|
|
|
Create the charts in the directory <dir>
|
|
@@ -533,8 +537,7 @@
|
|
|
|
=head1 AUTHOR
|
|
|
|
-There is a website at https://www.exim.org - this contains details of the
|
|
-mailing list exim-users@exim.org.
|
|
+There is a website at https://www.exim.org/.
|
|
|
|
=head1 TO DO
|
|
|
|
diff -ruN a/src/exinext.src b/src/exinext.src
|
|
--- a/src/exinext.src 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/exinext.src 2023-09-14 18:46:06.870477454 +0300
|
|
@@ -97,9 +97,9 @@
|
|
exim_path=`grep "^[$st]*exim_path" $config | sed "s/.*=[$st]*//"`
|
|
fi
|
|
|
|
-if test "$exim_path" = ""; then exim_path=BIN_DIRECTORY/exim; fi
|
|
-spool_directory=`$exim_path $eximmacdef -C $config -bP spool_directory | sed 's/.*=[ ]*//'`
|
|
-qualify_domain=`$exim_path $eximmacdef -C $config -bP qualify_domain | sed 's/.*=[ ]*//'`
|
|
+if test "$exim_path" = ""; then exim_path=BIN_DIRECTORY/exim4; fi
|
|
+spool_directory=`$exim_path $eximmacdef -bP spool_directory | sed 's/.*=[ ]*//'`
|
|
+qualify_domain=`$exim_path $eximmacdef -bP qualify_domain | sed 's/.*=[ ]*//'`
|
|
|
|
# Now do the job. Perl uses $ so frequently that we don't want to have to
|
|
# escape them all from the shell, so pass in shell variable values as
|
|
@@ -144,7 +144,7 @@
|
|
# Run Exim to get a list of hosts for the given domain; for
|
|
# each one construct the appropriate retry key.
|
|
|
|
- open(LIST, "$exim -C $config -v -bt $address |") ||
|
|
+ open(LIST, "$exim -v -bt $address |") ||
|
|
die "can't run exim to route $address";
|
|
|
|
while (<LIST>)
|
|
@@ -181,7 +181,7 @@
|
|
|
|
# Run exim_dumpdb to get out the retry data and pick off what we want
|
|
|
|
- open(DATA, "${exim}_dumpdb $spool retry |") ||
|
|
+ open(DATA, "/usr/sbin/exim_dumpdb $spool retry |") ||
|
|
die "can't run exim_dumpdb";
|
|
|
|
while (<DATA>)
|
|
diff -ruN a/src/exiqgrep.src b/src/exiqgrep.src
|
|
--- a/src/exiqgrep.src 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/exiqgrep.src 2023-09-14 18:45:21.885376889 +0300
|
|
@@ -24,7 +24,7 @@
|
|
use File::Basename;
|
|
|
|
# Have this variable point to your exim binary.
|
|
-my $exim = 'BIN_DIRECTORY/exim';
|
|
+my $exim = 'BIN_DIRECTORY/exim4';
|
|
my $eargs = '-bpu';
|
|
my %id;
|
|
my %opt;
|
|
diff -ruN a/src/exiwhat.src b/src/exiwhat.src
|
|
--- a/src/exiwhat.src 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/exiwhat.src 2023-09-14 18:46:06.870477454 +0300
|
|
@@ -98,9 +98,9 @@
|
|
|
|
st=' '
|
|
exim_path=`grep "^[$st]*exim_path" $config | sed "s/.*=[$st]*//"`
|
|
-if test "$exim_path" = ""; then exim_path=BIN_DIRECTORY/exim; fi
|
|
-spool_directory=`$exim_path -C $config -bP spool_directory | sed "s/.*=[ ]*//"`
|
|
-process_log_path=`$exim_path -C $config -bP process_log_path | sed "s/.*=[ ]*//"`
|
|
+if test "$exim_path" = ""; then exim_path=BIN_DIRECTORY/exim4; fi
|
|
+spool_directory=`$exim_path -bP spool_directory | sed "s/.*=[ ]*//"`
|
|
+process_log_path=`$exim_path -bP process_log_path | sed "s/.*=[ ]*//"`
|
|
|
|
# The file that Exim writes when sent the SIGUSR1 signal is specified by
|
|
# the process_log_path option. If that is not defined, Exim uses the file
|
|
diff -ruN a/src/expand.c b/src/expand.c
|
|
--- a/src/expand.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/expand.c 2023-09-14 18:48:55.198596101 +0300
|
|
@@ -4383,13 +4383,13 @@
|
|
f.expand_string_forcedfail = FALSE;
|
|
expand_string_message = US"";
|
|
|
|
-if (is_tainted(string))
|
|
+{ uschar *m;
|
|
+if ((m = is_tainted2(string, LOG_MAIN|LOG_PANIC, "Tainted string '%s' in expansion", s)))
|
|
{
|
|
- expand_string_message =
|
|
- string_sprintf("attempt to expand tainted string '%s'", s);
|
|
- log_write(0, LOG_MAIN|LOG_PANIC, "%s", expand_string_message);
|
|
+ expand_string_message = m;
|
|
goto EXPAND_FAILED;
|
|
}
|
|
+}
|
|
|
|
while (*s != 0)
|
|
{
|
|
@@ -7629,10 +7629,12 @@
|
|
/* Manually track tainting, as we deal in individual chars below */
|
|
|
|
if (is_tainted(sub))
|
|
+ {
|
|
if (yield->s && yield->ptr)
|
|
gstring_rebuffer(yield);
|
|
else
|
|
yield->s = store_get(yield->size = Ustrlen(sub), TRUE);
|
|
+ }
|
|
|
|
/* Check the UTF-8, byte-by-byte */
|
|
|
|
@@ -8193,6 +8195,7 @@
|
|
EXPAND_FAILED:
|
|
if (left) *left = s;
|
|
DEBUG(D_expand)
|
|
+ {
|
|
DEBUG(D_noutf8)
|
|
{
|
|
debug_printf_indent("|failed to expand: %s\n", string);
|
|
@@ -8212,6 +8215,7 @@
|
|
if (f.expand_string_forcedfail)
|
|
debug_printf_indent(UTF8_UP_RIGHT "failure was forced\n");
|
|
}
|
|
+ }
|
|
if (resetok_p && !resetok) *resetok_p = FALSE;
|
|
expand_level--;
|
|
return NULL;
|
|
diff -ruN a/src/functions.h b/src/functions.h
|
|
--- a/src/functions.h 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/functions.h 2023-09-14 18:48:55.198596101 +0300
|
|
@@ -1084,36 +1084,66 @@
|
|
|
|
/******************************************************************************/
|
|
/* Taint-checked file opens */
|
|
+static inline uschar *
|
|
+is_tainted2(const void *p, int lflags, const char* fmt, ...)
|
|
+{
|
|
+va_list ap;
|
|
+uschar *msg;
|
|
+rmark mark;
|
|
+
|
|
+if (!is_tainted(p))
|
|
+ return NULL;
|
|
+
|
|
+mark = store_mark();
|
|
+va_start(ap, fmt);
|
|
+msg = string_from_gstring(string_vformat(NULL, SVFMT_TAINT_NOCHK|SVFMT_EXTEND, fmt, ap));
|
|
+va_end(ap);
|
|
+
|
|
+#ifdef ALLOW_INSECURE_TAINTED_DATA
|
|
+if (allow_insecure_tainted_data)
|
|
+ {
|
|
+ if LOGGING(tainted) log_write(0, LOG_MAIN, "Warning: %s", msg);
|
|
+ store_reset(mark);
|
|
+ return NULL;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+if (lflags) log_write(0, lflags, "%s", msg);
|
|
+return msg; /* no store_reset(), as the message might be used afterwards and Exim
|
|
+ is expected to exit anyway, so we do not care about the leaked
|
|
+ storage */
|
|
+}
|
|
|
|
static inline int
|
|
exim_open2(const char *pathname, int flags)
|
|
{
|
|
-if (!is_tainted(pathname)) return open(pathname, flags);
|
|
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
|
|
+if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
|
|
+ return open(pathname, flags);
|
|
errno = EACCES;
|
|
return -1;
|
|
}
|
|
+
|
|
static inline int
|
|
exim_open(const char *pathname, int flags, mode_t mode)
|
|
{
|
|
-if (!is_tainted(pathname)) return open(pathname, flags, mode);
|
|
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
|
|
+if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
|
|
+ return open(pathname, flags, mode);
|
|
errno = EACCES;
|
|
return -1;
|
|
}
|
|
static inline int
|
|
exim_openat(int dirfd, const char *pathname, int flags)
|
|
{
|
|
-if (!is_tainted(pathname)) return openat(dirfd, pathname, flags);
|
|
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
|
|
+if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
|
|
+ return openat(dirfd, pathname, flags);
|
|
errno = EACCES;
|
|
return -1;
|
|
}
|
|
static inline int
|
|
exim_openat4(int dirfd, const char *pathname, int flags, mode_t mode)
|
|
{
|
|
-if (!is_tainted(pathname)) return openat(dirfd, pathname, flags, mode);
|
|
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
|
|
+if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
|
|
+ return openat(dirfd, pathname, flags, mode);
|
|
errno = EACCES;
|
|
return -1;
|
|
}
|
|
@@ -1121,8 +1151,8 @@
|
|
static inline FILE *
|
|
exim_fopen(const char *pathname, const char *mode)
|
|
{
|
|
-if (!is_tainted(pathname)) return fopen(pathname, mode);
|
|
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
|
|
+if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
|
|
+ return fopen(pathname, mode);
|
|
errno = EACCES;
|
|
return NULL;
|
|
}
|
|
@@ -1130,8 +1160,8 @@
|
|
static inline DIR *
|
|
exim_opendir(const uschar * name)
|
|
{
|
|
-if (!is_tainted(name)) return opendir(CCS name);
|
|
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted dirname '%s'", name);
|
|
+if (!is_tainted2(name, LOG_MAIN|LOG_PANIC, "Tainted dirname '%s'", name))
|
|
+ return opendir(CCS name);
|
|
errno = EACCES;
|
|
return NULL;
|
|
}
|
|
diff -ruN a/src/globals.c b/src/globals.c
|
|
--- a/src/globals.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/globals.c 2023-09-14 18:50:04.368288757 +0300
|
|
@@ -98,6 +98,10 @@
|
|
BOOL move_frozen_messages = FALSE;
|
|
#endif
|
|
|
|
+#ifdef ALLOW_INSECURE_TAINTED_DATA
|
|
+BOOL allow_insecure_tainted_data = FALSE;
|
|
+#endif
|
|
+
|
|
/* These variables are outside the #ifdef because it keeps the code less
|
|
cluttered in several places (e.g. during logging) if we can always refer to
|
|
them. Also, the tls_ variables are now always visible. Note that these are
|
|
@@ -117,6 +121,10 @@
|
|
const pcre *regex_DSN = NULL;
|
|
uschar *dsn_advertise_hosts = NULL;
|
|
|
|
+#ifdef DLOPEN_LOCAL_SCAN
|
|
+uschar *local_scan_path = NULL;
|
|
+#endif
|
|
+
|
|
#ifndef DISABLE_TLS
|
|
BOOL gnutls_compat_mode = FALSE;
|
|
BOOL gnutls_allow_auto_pkcs11 = FALSE;
|
|
@@ -899,7 +907,7 @@
|
|
|
|
|
|
gid_t exim_gid = EXIM_GID;
|
|
-uschar *exim_path = US BIN_DIRECTORY "/exim"
|
|
+uschar *exim_path = US BIN_DIRECTORY "/exim4"
|
|
"\0<---------------Space to patch exim_path->";
|
|
uid_t exim_uid = EXIM_UID;
|
|
int expand_level = 0; /* Nesting depth, indent for debug */
|
|
@@ -1034,6 +1042,9 @@
|
|
Li_size_reject,
|
|
Li_skip_delivery,
|
|
Li_smtp_confirmation,
|
|
+#ifdef ALLOW_INSECURE_TAINTED_DATA
|
|
+ Li_tainted,
|
|
+#endif
|
|
Li_tls_certificate_verified,
|
|
Li_tls_cipher,
|
|
-1
|
|
@@ -1101,6 +1112,9 @@
|
|
BIT_TABLE(L, smtp_protocol_error),
|
|
BIT_TABLE(L, smtp_syntax_error),
|
|
BIT_TABLE(L, subject),
|
|
+#ifdef ALLOW_INSECURE_TAINTED_DATA
|
|
+ BIT_TABLE(L, tainted),
|
|
+#endif
|
|
BIT_TABLE(L, tls_certificate_verified),
|
|
BIT_TABLE(L, tls_cipher),
|
|
BIT_TABLE(L, tls_peerdn),
|
|
diff -ruN a/src/globals.h b/src/globals.h
|
|
--- a/src/globals.h 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/globals.h 2023-09-14 18:50:04.368288757 +0300
|
|
@@ -77,6 +77,10 @@
|
|
extern BOOL move_frozen_messages; /* Get them out of the normal directory */
|
|
#endif
|
|
|
|
+#ifdef ALLOW_INSECURE_TAINTED_DATA
|
|
+extern BOOL allow_insecure_tainted_data;
|
|
+#endif
|
|
+
|
|
/* These variables are outside the #ifdef because it keeps the code less
|
|
cluttered in several places (e.g. during logging) if we can always refer to
|
|
them. Also, the tls_ variables are now always visible. */
|
|
@@ -148,6 +152,9 @@
|
|
extern const pcre *regex_DSN; /* For recognizing DSN settings */
|
|
extern uschar *dsn_advertise_hosts; /* host for which TLS is advertised */
|
|
|
|
+#ifdef DLOPEN_LOCAL_SCAN
|
|
+extern uschar *local_scan_path; /* Path to local_scan() library */
|
|
+#endif
|
|
/* Input-reading functions for messages, so we can use special ones for
|
|
incoming TCP/IP. */
|
|
|
|
diff -ruN a/src/host.c b/src/host.c
|
|
--- a/src/host.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/host.c 2023-09-14 18:46:43.911383705 +0300
|
|
@@ -1197,9 +1197,9 @@
|
|
c++;
|
|
}
|
|
|
|
-c[-1] = '\0'; /* drop trailing colon */
|
|
+*--c = '\0'; /* drop trailing colon */
|
|
|
|
-/* debug_printf("%s: D k %d <%s> <%s>\n", __FUNCTION__, k, d, d + 2*(k+1)); */
|
|
+/* debug_printf("%s: D k %d <%s> <%s>\n", __FUNCTION__, k, buffer, buffer + 2*(k+1)); */
|
|
if (k >= 0)
|
|
{ /* collapse */
|
|
c = d + 2*(k+1);
|
|
@@ -1581,7 +1581,7 @@
|
|
|
|
if (hosts->h_aliases)
|
|
{
|
|
- int count = 1;
|
|
+ int count = 1; /* need 1 more for terminating NULL */
|
|
uschar **ptr;
|
|
|
|
for (uschar ** aliases = USS hosts->h_aliases; *aliases; aliases++) count++;
|
|
@@ -1690,7 +1690,7 @@
|
|
{
|
|
uschar **aptr = NULL;
|
|
int ssize = 264;
|
|
- int count = 0;
|
|
+ int count = 1; /* need 1 more for terminating NULL */
|
|
int old_pool = store_pool;
|
|
|
|
sender_host_dnssec = dns_is_secure(dnsa);
|
|
diff -ruN a/src/local_scan.c b/src/local_scan.c
|
|
--- a/src/local_scan.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/local_scan.c 2023-09-14 18:50:04.368288757 +0300
|
|
@@ -6,22 +6,6 @@
|
|
/* See the file NOTICE for conditions of use and distribution. */
|
|
|
|
|
|
-/******************************************************************************
|
|
-This file contains a template local_scan() function that just returns ACCEPT.
|
|
-If you want to implement your own version, you should copy this file to, say
|
|
-Local/local_scan.c, and edit the copy. To use your version instead of the
|
|
-default, you must set
|
|
-
|
|
-HAVE_LOCAL_SCAN=yes
|
|
-LOCAL_SCAN_SOURCE=Local/local_scan.c
|
|
-
|
|
-in your Local/Makefile. This makes it easy to copy your version for use with
|
|
-subsequent Exim releases.
|
|
-
|
|
-For a full description of the API to this function, see the Exim specification.
|
|
-******************************************************************************/
|
|
-
|
|
-
|
|
/* This is the only Exim header that you should include. The effect of
|
|
including any other Exim header is not defined, and may change from release to
|
|
release. Use only the documented interface! */
|
|
@@ -29,37 +13,129 @@
|
|
#include "local_scan.h"
|
|
|
|
|
|
-/* This is a "do-nothing" version of a local_scan() function. The arguments
|
|
-are:
|
|
-
|
|
- fd The file descriptor of the open -D file, which contains the
|
|
- body of the message. The file is open for reading and
|
|
- writing, but modifying it is dangerous and not recommended.
|
|
-
|
|
- return_text A pointer to an unsigned char* variable which you can set in
|
|
- order to return a text string. It is initialized to NULL.
|
|
-
|
|
-The return values of this function are:
|
|
-
|
|
- LOCAL_SCAN_ACCEPT
|
|
- The message is to be accepted. The return_text argument is
|
|
- saved in $local_scan_data.
|
|
-
|
|
- LOCAL_SCAN_REJECT
|
|
- The message is to be rejected. The returned text is used
|
|
- in the rejection message.
|
|
-
|
|
- LOCAL_SCAN_TEMPREJECT
|
|
- This specifies a temporary rejection. The returned text
|
|
- is used in the rejection message.
|
|
-*/
|
|
+#ifdef DLOPEN_LOCAL_SCAN
|
|
+#include <dlfcn.h>
|
|
+static int (*local_scan_fn)(int fd, uschar **return_text) = NULL;
|
|
+static int load_local_scan_library(void);
|
|
+#endif
|
|
|
|
int
|
|
local_scan(int fd, uschar **return_text)
|
|
{
|
|
fd = fd; /* Keep picky compilers happy */
|
|
return_text = return_text;
|
|
-return LOCAL_SCAN_ACCEPT;
|
|
+#ifdef DLOPEN_LOCAL_SCAN
|
|
+/* local_scan_path is defined AND not the empty string */
|
|
+if (local_scan_path && *local_scan_path)
|
|
+ {
|
|
+ if (!local_scan_fn)
|
|
+ {
|
|
+ if (!load_local_scan_library())
|
|
+ {
|
|
+ char *base_msg , *error_msg , *final_msg ;
|
|
+ int final_length = -1 ;
|
|
+
|
|
+ base_msg=US"Local configuration error - local_scan() library failure\n";
|
|
+ error_msg = dlerror() ;
|
|
+
|
|
+ final_length = strlen(base_msg) + strlen(error_msg) + 1 ;
|
|
+ final_msg = (char*)malloc( final_length*sizeof(char) ) ;
|
|
+ *final_msg = '\0' ;
|
|
+
|
|
+ strcat( final_msg , base_msg ) ;
|
|
+ strcat( final_msg , error_msg ) ;
|
|
+
|
|
+ *return_text = final_msg ;
|
|
+ return LOCAL_SCAN_TEMPREJECT;
|
|
+ }
|
|
+ }
|
|
+ return local_scan_fn(fd, return_text);
|
|
+ }
|
|
+else
|
|
+#endif
|
|
+ return LOCAL_SCAN_ACCEPT;
|
|
}
|
|
|
|
+#ifdef DLOPEN_LOCAL_SCAN
|
|
+
|
|
+static int load_local_scan_library(void)
|
|
+{
|
|
+/* No point in keeping local_scan_lib since we'll never dlclose() anyway */
|
|
+void *local_scan_lib = NULL;
|
|
+int (*local_scan_version_fn)(void);
|
|
+int vers_maj;
|
|
+int vers_min;
|
|
+
|
|
+local_scan_lib = dlopen(local_scan_path, RTLD_NOW);
|
|
+if (!local_scan_lib)
|
|
+ {
|
|
+ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library open failed - "
|
|
+ "message temporarily rejected");
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+local_scan_version_fn = dlsym(local_scan_lib, "local_scan_version_major");
|
|
+if (!local_scan_version_fn)
|
|
+ {
|
|
+ dlclose(local_scan_lib);
|
|
+ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library doesn't contain "
|
|
+ "local_scan_version_major() function - message temporarily rejected");
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+/* The major number is increased when the ABI is changed in a non
|
|
+ backward compatible way. */
|
|
+vers_maj = local_scan_version_fn();
|
|
+
|
|
+local_scan_version_fn = dlsym(local_scan_lib, "local_scan_version_minor");
|
|
+if (!local_scan_version_fn)
|
|
+ {
|
|
+ dlclose(local_scan_lib);
|
|
+ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library doesn't contain "
|
|
+ "local_scan_version_minor() function - message temporarily rejected");
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+/* The minor number is increased each time a new feature is added (in a
|
|
+ way that doesn't break backward compatibility) -- Marc */
|
|
+vers_min = local_scan_version_fn();
|
|
+
|
|
+
|
|
+if (vers_maj != LOCAL_SCAN_ABI_VERSION_MAJOR)
|
|
+ {
|
|
+ dlclose(local_scan_lib);
|
|
+ local_scan_lib = NULL;
|
|
+ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() has an incompatible major"
|
|
+ "version number, you need to recompile your module for this version"
|
|
+ "of exim (The module was compiled for version %d.%d and this exim provides"
|
|
+ "ABI version %d.%d)", vers_maj, vers_min, LOCAL_SCAN_ABI_VERSION_MAJOR,
|
|
+ LOCAL_SCAN_ABI_VERSION_MINOR);
|
|
+ return FALSE;
|
|
+ }
|
|
+else if (vers_min > LOCAL_SCAN_ABI_VERSION_MINOR)
|
|
+ {
|
|
+ dlclose(local_scan_lib);
|
|
+ local_scan_lib = NULL;
|
|
+ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() has an incompatible minor"
|
|
+ "version number, you need to recompile your module for this version"
|
|
+ "of exim (The module was compiled for version %d.%d and this exim provides"
|
|
+ "ABI version %d.%d)", vers_maj, vers_min, LOCAL_SCAN_ABI_VERSION_MAJOR,
|
|
+ LOCAL_SCAN_ABI_VERSION_MINOR);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+local_scan_fn = dlsym(local_scan_lib, "local_scan");
|
|
+if (!local_scan_fn)
|
|
+ {
|
|
+ dlclose(local_scan_lib);
|
|
+ log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library doesn't contain "
|
|
+ "local_scan() function - message temporarily rejected");
|
|
+ return FALSE;
|
|
+ }
|
|
+return TRUE;
|
|
+}
|
|
+
|
|
+#endif /* DLOPEN_LOCAL_SCAN */
|
|
+
|
|
+
|
|
/* End of local_scan.c */
|
|
diff -ruN a/src/local_scan.h b/src/local_scan.h
|
|
--- a/src/local_scan.h 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/local_scan.h 2023-09-14 18:50:04.368288757 +0300
|
|
@@ -27,6 +27,7 @@
|
|
|
|
#include <stdarg.h>
|
|
#include <sys/types.h>
|
|
+#pragma GCC visibility push(default)
|
|
#include "config.h"
|
|
#include "mytypes.h"
|
|
#include "store.h"
|
|
@@ -166,6 +167,9 @@
|
|
extern BOOL host_checking; /* Set when checking a host */
|
|
extern uschar *interface_address; /* Interface for incoming call */
|
|
extern int interface_port; /* Port number for incoming call */
|
|
+#ifdef DLOPEN_LOCAL_SCAN
|
|
+extern uschar *local_scan_path;
|
|
+#endif
|
|
extern uschar *message_id; /* Internal id of message being handled */
|
|
extern uschar *received_protocol; /* Name of incoming protocol */
|
|
extern int recipients_count; /* Number of recipients */
|
|
@@ -235,4 +239,6 @@
|
|
extern pid_t child_open_function(uschar **, uschar **, int, int *, int *, BOOL, const uschar *);
|
|
#endif
|
|
|
|
+#pragma GCC visibility pop
|
|
+
|
|
/* End of local_scan.h */
|
|
diff -ruN a/src/log.c b/src/log.c
|
|
--- a/src/log.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/log.c 2023-09-14 18:49:41.743735097 +0300
|
|
@@ -287,8 +287,11 @@
|
|
uschar *lastslash = Ustrrchr(name, '/');
|
|
*lastslash = 0;
|
|
created = directory_make(NULL, name, LOG_DIRECTORY_MODE, FALSE);
|
|
- DEBUG(D_any) debug_printf("%s log directory %s\n",
|
|
- created ? "created" : "failed to create", name);
|
|
+ DEBUG(D_any)
|
|
+ if (created)
|
|
+ debug_printf("created log directory %s\n", name);
|
|
+ else
|
|
+ debug_printf("failed to create log directory %s: %s\n", name, strerror(errno));
|
|
*lastslash = '/';
|
|
if (created) fd = Uopen(name, flags, LOG_MODE);
|
|
}
|
|
@@ -394,9 +397,7 @@
|
|
const uid_t euid = geteuid();
|
|
|
|
if (euid == exim_uid)
|
|
- {
|
|
fd = log_open_already_exim(name);
|
|
- }
|
|
else if (euid == root_uid)
|
|
{
|
|
int sock[2];
|
|
@@ -457,7 +458,7 @@
|
|
it does not exist. This may be called recursively on failure, in order to open
|
|
the panic log.
|
|
|
|
-The directory is in the static variable file_path. This is static so that it
|
|
+The directory is in the static variable file_path. This is static so that
|
|
the work of sorting out the path is done just once per Exim process.
|
|
|
|
Exim is normally configured to avoid running as root wherever possible, the log
|
|
@@ -492,60 +493,64 @@
|
|
|
|
ok = string_format(buffer, sizeof(buffer), CS file_path, log_names[type]);
|
|
|
|
-/* Save the name of the mainlog for rollover processing. Without a datestamp,
|
|
-it gets statted to see if it has been cycled. With a datestamp, the datestamp
|
|
-will be compared. The static slot for saving it is the same size as buffer,
|
|
-and the text has been checked above to fit, so this use of strcpy() is OK. */
|
|
-
|
|
-if (type == lt_main && string_datestamp_offset >= 0)
|
|
+switch (type)
|
|
{
|
|
- Ustrcpy(mainlog_name, buffer);
|
|
- mainlog_datestamp = mainlog_name + string_datestamp_offset;
|
|
- }
|
|
+ case lt_main:
|
|
+ /* Save the name of the mainlog for rollover processing. Without a datestamp,
|
|
+ it gets statted to see if it has been cycled. With a datestamp, the datestamp
|
|
+ will be compared. The static slot for saving it is the same size as buffer,
|
|
+ and the text has been checked above to fit, so this use of strcpy() is OK. */
|
|
+
|
|
+ Ustrcpy(mainlog_name, buffer);
|
|
+ if (string_datestamp_offset > 0)
|
|
+ mainlog_datestamp = mainlog_name + string_datestamp_offset;
|
|
+ break;
|
|
|
|
-/* Ditto for the reject log */
|
|
+ case lt_reject:
|
|
+ /* Ditto for the reject log */
|
|
|
|
-else if (type == lt_reject && string_datestamp_offset >= 0)
|
|
- {
|
|
- Ustrcpy(rejectlog_name, buffer);
|
|
- rejectlog_datestamp = rejectlog_name + string_datestamp_offset;
|
|
- }
|
|
+ Ustrcpy(rejectlog_name, buffer);
|
|
+ if (string_datestamp_offset > 0)
|
|
+ rejectlog_datestamp = rejectlog_name + string_datestamp_offset;
|
|
+ break;
|
|
|
|
-/* and deal with the debug log (which keeps the datestamp, but does not
|
|
-update it) */
|
|
+ case lt_debug:
|
|
+ /* and deal with the debug log (which keeps the datestamp, but does not
|
|
+ update it) */
|
|
|
|
-else if (type == lt_debug)
|
|
- {
|
|
- Ustrcpy(debuglog_name, buffer);
|
|
- if (tag)
|
|
- {
|
|
- /* this won't change the offset of the datestamp */
|
|
- ok2 = string_format(buffer, sizeof(buffer), "%s%s",
|
|
- debuglog_name, tag);
|
|
- if (ok2)
|
|
- Ustrcpy(debuglog_name, buffer);
|
|
- }
|
|
- }
|
|
+ Ustrcpy(debuglog_name, buffer);
|
|
+ if (tag)
|
|
+ {
|
|
+ /* this won't change the offset of the datestamp */
|
|
+ ok2 = string_format(buffer, sizeof(buffer), "%s%s",
|
|
+ debuglog_name, tag);
|
|
+ if (ok2)
|
|
+ Ustrcpy(debuglog_name, buffer);
|
|
+ }
|
|
+ break;
|
|
|
|
-/* Remove any datestamp if this is the panic log. This is rare, so there's no
|
|
-need to optimize getting the datestamp length. We remove one non-alphanumeric
|
|
-char afterwards if at the start, otherwise one before. */
|
|
+ default:
|
|
+ /* Remove any datestamp if this is the panic log. This is rare, so there's no
|
|
+ need to optimize getting the datestamp length. We remove one non-alphanumeric
|
|
+ char afterwards if at the start, otherwise one before. */
|
|
|
|
-else if (string_datestamp_offset >= 0)
|
|
- {
|
|
- uschar * from = buffer + string_datestamp_offset;
|
|
- uschar * to = from + string_datestamp_length;
|
|
+ if (string_datestamp_offset >= 0)
|
|
+ {
|
|
+ uschar * from = buffer + string_datestamp_offset;
|
|
+ uschar * to = from + string_datestamp_length;
|
|
|
|
- if (from == buffer || from[-1] == '/')
|
|
- {
|
|
- if (!isalnum(*to)) to++;
|
|
- }
|
|
- else
|
|
- if (!isalnum(from[-1])) from--;
|
|
+ if (from == buffer || from[-1] == '/')
|
|
+ {
|
|
+ if (!isalnum(*to)) to++;
|
|
+ }
|
|
+ else
|
|
+ if (!isalnum(from[-1])) from--;
|
|
|
|
- /* This copy is ok, because we know that to is a substring of from. But
|
|
- due to overlap we must use memmove() not Ustrcpy(). */
|
|
- memmove(from, to, Ustrlen(to)+1);
|
|
+ /* This copy is ok, because we know that to is a substring of from. But
|
|
+ due to overlap we must use memmove() not Ustrcpy(). */
|
|
+ memmove(from, to, Ustrlen(to)+1);
|
|
+ }
|
|
+ break;
|
|
}
|
|
|
|
/* If the file name is too long, it is an unrecoverable disaster */
|
|
@@ -559,9 +564,7 @@
|
|
*fd = log_open_as_exim(buffer);
|
|
|
|
if (*fd >= 0)
|
|
- {
|
|
return;
|
|
- }
|
|
|
|
euid = geteuid();
|
|
|
|
@@ -713,26 +716,62 @@
|
|
}
|
|
|
|
|
|
+/* Pull the file out of the configured or the compiled-in list.
|
|
+Called for an empty log_file_path element, for debug logging activation
|
|
+when file_path has not previously been set, and from the appenfile transport setup. */
|
|
|
|
-static void
|
|
-set_file_path(void)
|
|
+void
|
|
+set_file_path(BOOL *multiple)
|
|
{
|
|
+uschar *s;
|
|
int sep = ':'; /* Fixed separator - outside use */
|
|
-uschar *t;
|
|
-const uschar *tt = US LOG_FILE_PATH;
|
|
-while ((t = string_nextinlist(&tt, &sep, log_buffer, LOG_BUFFER_SIZE)))
|
|
- {
|
|
- if (Ustrcmp(t, "syslog") == 0 || t[0] == 0) continue;
|
|
- file_path = string_copy(t);
|
|
- break;
|
|
- }
|
|
+const uschar *ss = *log_file_path ? log_file_path : US LOG_FILE_PATH;
|
|
+
|
|
+if (*ss)
|
|
+ for (logging_mode = 0;
|
|
+ s = string_nextinlist(&ss, &sep, log_buffer, LOG_BUFFER_SIZE); )
|
|
+ {
|
|
+ if (Ustrcmp(s, "syslog") == 0)
|
|
+ logging_mode |= LOG_MODE_SYSLOG;
|
|
+ else if (!(logging_mode & LOG_MODE_FILE)) /* no file yet */
|
|
+ {
|
|
+ logging_mode |= LOG_MODE_FILE;
|
|
+ if (*s) file_path = string_copy(s); /* If a non-empty path is given, use it */
|
|
+ }
|
|
+ else if (multiple) *multiple = TRUE;
|
|
+ }
|
|
+else
|
|
+ logging_mode = LOG_MODE_FILE;
|
|
+
|
|
+/* Set up the ultimate default if necessary. */
|
|
+
|
|
+if (logging_mode & LOG_MODE_FILE && !*file_path)
|
|
+ if (LOG_FILE_PATH[0])
|
|
+ {
|
|
+ /* If we still do not have a file_path, we take
|
|
+ the first non-empty, non-syslog item in LOG_FILE_PATH, if there is
|
|
+ one. If there is no such item, use the ultimate default in the
|
|
+ spool directory. */
|
|
+
|
|
+ for (ss = US LOG_FILE_PATH;
|
|
+ s = string_nextinlist(&ss, &sep, log_buffer, LOG_BUFFER_SIZE);)
|
|
+ {
|
|
+ if (*s != '/') continue;
|
|
+ file_path = string_copy(s);
|
|
+ }
|
|
+ }
|
|
+ else file_path = string_sprintf("%s/log/%%slog", spool_directory);
|
|
}
|
|
|
|
|
|
void
|
|
mainlog_close(void)
|
|
{
|
|
-if (mainlogfd < 0) return;
|
|
+/* avoid closing it if it is closed already or if we do not see a chance
|
|
+to open the file mainlog later again */
|
|
+if (mainlogfd < 0 /* already closed */
|
|
+ || !(geteuid() == 0 || geteuid() == exim_uid))
|
|
+ return;
|
|
(void)close(mainlogfd);
|
|
mainlogfd = -1;
|
|
mainlog_inode = 0;
|
|
@@ -844,41 +883,9 @@
|
|
|
|
store_pool = POOL_PERM;
|
|
|
|
- /* If nothing has been set, don't waste effort... the default values for the
|
|
- statics are file_path="" and logging_mode = LOG_MODE_FILE. */
|
|
-
|
|
- if (*log_file_path)
|
|
- {
|
|
- int sep = ':'; /* Fixed separator - outside use */
|
|
- uschar *s;
|
|
- const uschar *ss = log_file_path;
|
|
-
|
|
- logging_mode = 0;
|
|
- while ((s = string_nextinlist(&ss, &sep, log_buffer, LOG_BUFFER_SIZE)))
|
|
- {
|
|
- if (Ustrcmp(s, "syslog") == 0)
|
|
- logging_mode |= LOG_MODE_SYSLOG;
|
|
- else if (logging_mode & LOG_MODE_FILE)
|
|
- multiple = TRUE;
|
|
- else
|
|
- {
|
|
- logging_mode |= LOG_MODE_FILE;
|
|
-
|
|
- /* If a non-empty path is given, use it */
|
|
-
|
|
- if (*s)
|
|
- file_path = string_copy(s);
|
|
-
|
|
- /* If the path is empty, we want to use the first non-empty, non-
|
|
- syslog item in LOG_FILE_PATH, if there is one, since the value of
|
|
- log_file_path may have been set at runtime. If there is no such item,
|
|
- use the ultimate default in the spool directory. */
|
|
-
|
|
- else
|
|
- set_file_path(); /* Empty item in log_file_path */
|
|
- } /* First non-syslog item in log_file_path */
|
|
- } /* Scan of log_file_path */
|
|
- }
|
|
+ /* make sure that we have a valid log file path in "file_path",
|
|
+ the open_log() later relies on it */
|
|
+ set_file_path(&multiple);
|
|
|
|
/* If no modes have been selected, it is a major disaster */
|
|
|
|
@@ -886,11 +893,8 @@
|
|
die(US"Neither syslog nor file logging set in log_file_path",
|
|
US"Unexpected logging failure");
|
|
|
|
- /* Set up the ultimate default if necessary. Then revert to the old store
|
|
- pool, and record that we've sorted out the path. */
|
|
+ /* Revert to the old store pool, and record that we've sorted out the path. */
|
|
|
|
- if (logging_mode & LOG_MODE_FILE && !file_path[0])
|
|
- file_path = string_sprintf("%s/log/%%slog", spool_directory);
|
|
store_pool = old_pool;
|
|
path_inspected = TRUE;
|
|
|
|
@@ -1244,6 +1248,7 @@
|
|
|
|
if (logging_mode & LOG_MODE_FILE)
|
|
{
|
|
+ if (!*file_path) set_file_path(NULL);
|
|
panic_recurseflag = TRUE;
|
|
open_log(&paniclogfd, lt_panic, NULL); /* Won't return on failure */
|
|
panic_recurseflag = FALSE;
|
|
@@ -1499,7 +1504,7 @@
|
|
resulting in certain setup not having been done. Hack this for now so we
|
|
do not segfault; note that nondefault log locations will not work */
|
|
|
|
-if (!*file_path) set_file_path();
|
|
+if (!*file_path) set_file_path(NULL);
|
|
|
|
open_log(&fd, lt_debug, tag_name);
|
|
|
|
@@ -1521,5 +1526,14 @@
|
|
unlink_log(lt_debug);
|
|
}
|
|
|
|
+/* Called from the appendfile transport setup. */
|
|
+void
|
|
+open_logs(void)
|
|
+{
|
|
+set_file_path(NULL);
|
|
+if (!(logging_mode & LOG_MODE_FILE)) return;
|
|
+open_log(&mainlogfd, lt_main, 0);
|
|
+open_log(&rejectlogfd, lt_reject, 0);
|
|
+}
|
|
|
|
/* End of log.c */
|
|
diff -ruN a/src/lookups/lf_sqlperform.c b/src/lookups/lf_sqlperform.c
|
|
--- a/src/lookups/lf_sqlperform.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/lookups/lf_sqlperform.c 2023-09-14 18:48:55.198596101 +0300
|
|
@@ -102,11 +102,13 @@
|
|
}
|
|
}
|
|
|
|
- if (is_tainted(server))
|
|
- {
|
|
- *errmsg = string_sprintf("%s server \"%s\" is tainted", name, server);
|
|
+ { uschar *m;
|
|
+ if ((m = is_tainted2(server, 0, "Tainted %s server '%s'", name, server)))
|
|
+ {
|
|
+ *errmsg = m;
|
|
return DEFER;
|
|
}
|
|
+ }
|
|
|
|
rc = (*fn)(ss+1, server, result, errmsg, &defer_break, do_cache, opts);
|
|
if (rc != DEFER || defer_break) return rc;
|
|
@@ -158,11 +160,13 @@
|
|
server = ele;
|
|
}
|
|
|
|
- if (is_tainted(server))
|
|
+ { uschar *m;
|
|
+ if ((m = is_tainted2(server, 0, "Tainted %s server '%s'", name, server)))
|
|
{
|
|
- *errmsg = string_sprintf("%s server \"%s\" is tainted", name, server);
|
|
+ *errmsg = m;
|
|
return DEFER;
|
|
}
|
|
+ }
|
|
|
|
rc = (*fn)(query, server, result, errmsg, &defer_break, do_cache, opts);
|
|
if (rc != DEFER || defer_break) return rc;
|
|
diff -ruN a/src/macros.h b/src/macros.h
|
|
--- a/src/macros.h 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/macros.h 2023-09-14 18:47:06.747942448 +0300
|
|
@@ -497,6 +497,9 @@
|
|
Li_smtp_mailauth,
|
|
Li_smtp_no_mail,
|
|
Li_subject,
|
|
+#ifdef ALLOW_INSECURE_TAINTED_DATA
|
|
+ Li_tainted,
|
|
+#endif
|
|
Li_tls_certificate_verified,
|
|
Li_tls_cipher,
|
|
Li_tls_peerdn,
|
|
diff -ruN a/src/parse.c b/src/parse.c
|
|
--- a/src/parse.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/parse.c 2023-09-14 18:48:55.198596101 +0300
|
|
@@ -1410,12 +1410,8 @@
|
|
return FF_ERROR;
|
|
}
|
|
|
|
- if (is_tainted(filename))
|
|
- {
|
|
- *error = string_sprintf("Tainted name '%s' for included file not permitted\n",
|
|
- filename);
|
|
+ if ((*error = is_tainted2(filename, 0, "Tainted name '%s' for included file not permitted\n", filename)))
|
|
return FF_ERROR;
|
|
- }
|
|
|
|
/* Check file name if required */
|
|
|
|
diff -ruN a/src/rda.c b/src/rda.c
|
|
--- a/src/rda.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/rda.c 2023-09-14 18:48:55.198596101 +0300
|
|
@@ -179,10 +179,8 @@
|
|
/* Reading a file is a form of expansion; we wish to deny attackers the
|
|
capability to specify the file name. */
|
|
|
|
-if (is_tainted(filename))
|
|
+if ((*error = is_tainted2(filename, 0, "Tainted name '%s' for file read not permitted\n", filename)))
|
|
{
|
|
- *error = string_sprintf("Tainted name '%s' for file read not permitted\n",
|
|
- filename);
|
|
*yield = FF_ERROR;
|
|
return NULL;
|
|
}
|
|
diff -ruN a/src/readconf.c b/src/readconf.c
|
|
--- a/src/readconf.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/readconf.c 2023-09-14 18:50:04.372288856 +0300
|
|
@@ -68,6 +68,9 @@
|
|
{ "add_environment", opt_stringptr, {&add_environment} },
|
|
{ "admin_groups", opt_gidlist, {&admin_groups} },
|
|
{ "allow_domain_literals", opt_bool, {&allow_domain_literals} },
|
|
+#ifdef ALLOW_INSECURE_TAINTED_DATA
|
|
+ { "allow_insecure_tainted_data", opt_bool, {&allow_insecure_tainted_data} },
|
|
+#endif
|
|
{ "allow_mx_to_ip", opt_bool, {&allow_mx_to_ip} },
|
|
{ "allow_utf8_domains", opt_bool, {&allow_utf8_domains} },
|
|
{ "auth_advertise_hosts", opt_stringptr, {&auth_advertise_hosts} },
|
|
@@ -205,6 +208,9 @@
|
|
{ "local_from_prefix", opt_stringptr, {&local_from_prefix} },
|
|
{ "local_from_suffix", opt_stringptr, {&local_from_suffix} },
|
|
{ "local_interfaces", opt_stringptr, {&local_interfaces} },
|
|
+#ifdef DLOPEN_LOCAL_SCAN
|
|
+ { "local_scan_path", opt_stringptr, &local_scan_path },
|
|
+#endif
|
|
#ifdef HAVE_LOCAL_SCAN
|
|
{ "local_scan_timeout", opt_time, {&local_scan_timeout} },
|
|
#endif
|
|
diff -ruN a/src/routers/rf_get_transport.c b/src/routers/rf_get_transport.c
|
|
--- a/src/routers/rf_get_transport.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/routers/rf_get_transport.c 2023-09-14 18:48:15.485624338 +0300
|
|
@@ -66,10 +66,8 @@
|
|
"\"%s\" in %s router: %s", tpname, router_name, expand_string_message);
|
|
return FALSE;
|
|
}
|
|
- if (is_tainted(ss))
|
|
+ if (is_tainted2(ss, LOG_MAIN|LOG_PANIC, "Tainted tainted value '%s' from '%s' for transport", ss, tpname))
|
|
{
|
|
- log_write(0, LOG_MAIN|LOG_PANIC,
|
|
- "attempt to use tainted value '%s' from '%s' for transport", ss, tpname);
|
|
addr->basic_errno = ERRNO_BADTRANSPORT;
|
|
/* Avoid leaking info to an attacker */
|
|
addr->message = US"internal configuration error";
|
|
diff -ruN a/src/search.c b/src/search.c
|
|
--- a/src/search.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/search.c 2023-09-14 18:47:18.844238414 +0300
|
|
@@ -343,12 +343,8 @@
|
|
uschar keybuffer[256];
|
|
int old_pool = store_pool;
|
|
|
|
-if (filename && is_tainted(filename))
|
|
- {
|
|
- log_write(0, LOG_MAIN|LOG_PANIC,
|
|
- "Tainted filename for search: '%s'", filename);
|
|
+if (filename && is_tainted2(filename, LOG_MAIN|LOG_PANIC, "Tainted filename for search '%s'", filename))
|
|
return NULL;
|
|
- }
|
|
|
|
/* Change to the search store pool and remember our reset point */
|
|
|
|
@@ -639,7 +635,7 @@
|
|
/* Arrange to put this database at the top of the LRU chain if it is a type
|
|
that opens real files. */
|
|
|
|
-if ( open_top != (tree_node *)handle
|
|
+if ( open_top != (tree_node *)handle
|
|
&& lookup_list[t->name[0]-'0']->type == lookup_absfile)
|
|
{
|
|
search_cache *c = (search_cache *)(t->data.ptr);
|
|
diff -ruN a/src/smtp_out.c b/src/smtp_out.c
|
|
--- a/src/smtp_out.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/smtp_out.c 2023-09-14 18:48:24.277839477 +0300
|
|
@@ -53,11 +53,8 @@
|
|
return FALSE;
|
|
}
|
|
|
|
-if (is_tainted(expint))
|
|
+if (is_tainted2(expint, LOG_MAIN|LOG_PANIC, "Tainted value '%s' from '%s' for interface", expint, istring))
|
|
{
|
|
- log_write(0, LOG_MAIN|LOG_PANIC,
|
|
- "attempt to use tainted value '%s' from '%s' for interface",
|
|
- expint, istring);
|
|
addr->transport_return = PANIC;
|
|
addr->message = string_sprintf("failed to expand \"interface\" "
|
|
"option for %s: configuration error", msg);
|
|
@@ -425,7 +422,7 @@
|
|
{
|
|
int sock = socks_sock_connect(sc->host, sc->host_af, port, sc->interface,
|
|
sc->tblock, ob->connect_timeout);
|
|
-
|
|
+
|
|
if (sock >= 0)
|
|
{
|
|
if (early_data && early_data->data && early_data->len)
|
|
diff -ruN a/src/string.c b/src/string.c
|
|
--- a/src/string.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/string.c 2023-09-14 18:50:04.372288856 +0300
|
|
@@ -418,6 +418,7 @@
|
|
|
|
#if (defined(HAVE_LOCAL_SCAN) || defined(EXPAND_DLFUNC)) \
|
|
&& !defined(MACRO_PREDEF) && !defined(COMPILE_UTILITY)
|
|
+#pragma GCC visibility push(default)
|
|
/*************************************************
|
|
* Copy and save string *
|
|
*************************************************/
|
|
@@ -470,6 +471,7 @@
|
|
ss[n] = 0;
|
|
return ss;
|
|
}
|
|
+#pragma GCC visibility pop
|
|
#endif
|
|
|
|
|
|
diff -ruN a/src/transports/appendfile.c b/src/transports/appendfile.c
|
|
--- a/src/transports/appendfile.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/transports/appendfile.c 2023-09-14 18:49:20.139206410 +0300
|
|
@@ -217,6 +217,9 @@
|
|
Returns: OK, FAIL, or DEFER
|
|
*/
|
|
|
|
+void
|
|
+open_logs(void);
|
|
+
|
|
static int
|
|
appendfile_transport_setup(transport_instance *tblock, address_item *addrlist,
|
|
transport_feedback *dummy, uid_t uid, gid_t gid, uschar **errmsg)
|
|
@@ -231,6 +234,9 @@
|
|
uid = uid;
|
|
gid = gid;
|
|
|
|
+/* we can't wait until we're not privileged anymore */
|
|
+open_logs();
|
|
+
|
|
if (ob->expand_maildir_use_size_file)
|
|
ob->maildir_use_size_file = expand_check_condition(ob->expand_maildir_use_size_file,
|
|
US"`maildir_use_size_file` in transport", tblock->name);
|
|
@@ -1286,12 +1292,14 @@
|
|
expand_string_message);
|
|
goto ret_panic;
|
|
}
|
|
-if (is_tainted(path))
|
|
+{ uschar *m;
|
|
+if ((m = is_tainted2(path, 0, "Tainted '%s' (file or directory "
|
|
+ "name for %s transport) not permitted", path, tblock->name)))
|
|
{
|
|
- addr->message = string_sprintf("Tainted '%s' (file or directory "
|
|
- "name for %s transport) not permitted", path, tblock->name);
|
|
+ addr->message = m;
|
|
goto ret_panic;
|
|
}
|
|
+}
|
|
|
|
if (path[0] != '/')
|
|
{
|
|
diff -ruN a/src/transports/autoreply.c b/src/transports/autoreply.c
|
|
--- a/src/transports/autoreply.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/transports/autoreply.c 2023-09-14 18:48:55.198596101 +0300
|
|
@@ -404,14 +404,15 @@
|
|
|
|
if (oncelog && *oncelog && to)
|
|
{
|
|
+ uschar *m;
|
|
time_t then = 0;
|
|
|
|
- if (is_tainted(oncelog))
|
|
+ if ((m = is_tainted2(oncelog, 0, "Tainted '%s' (once file for %s transport)"
|
|
+ " not permitted", oncelog, tblock->name)))
|
|
{
|
|
addr->transport_return = DEFER;
|
|
addr->basic_errno = EACCES;
|
|
- addr->message = string_sprintf("Tainted '%s' (once file for %s transport)"
|
|
- " not permitted", oncelog, tblock->name);
|
|
+ addr->message = m;
|
|
goto END_OFF;
|
|
}
|
|
|
|
@@ -515,13 +516,14 @@
|
|
|
|
if (then != 0 && (once_repeat_sec <= 0 || now - then < once_repeat_sec))
|
|
{
|
|
+ uschar *m;
|
|
int log_fd;
|
|
- if (is_tainted(logfile))
|
|
+ if ((m = is_tainted2(logfile, 0, "Tainted '%s' (logfile for %s transport)"
|
|
+ " not permitted", logfile, tblock->name)))
|
|
{
|
|
addr->transport_return = DEFER;
|
|
addr->basic_errno = EACCES;
|
|
- addr->message = string_sprintf("Tainted '%s' (logfile for %s transport)"
|
|
- " not permitted", logfile, tblock->name);
|
|
+ addr->message = m;
|
|
goto END_OFF;
|
|
}
|
|
|
|
@@ -548,12 +550,13 @@
|
|
/* We are going to send a message. Ensure any requested file is available. */
|
|
if (file)
|
|
{
|
|
- if (is_tainted(file))
|
|
+ uschar *m;
|
|
+ if ((m = is_tainted2(file, 0, "Tainted '%s' (file for %s transport)"
|
|
+ " not permitted", file, tblock->name)))
|
|
{
|
|
addr->transport_return = DEFER;
|
|
addr->basic_errno = EACCES;
|
|
- addr->message = string_sprintf("Tainted '%s' (file for %s transport)"
|
|
- " not permitted", file, tblock->name);
|
|
+ addr->message = m;
|
|
return FALSE;
|
|
}
|
|
if (!(ff = Ufopen(file, "rb")) && !ob->file_optional)
|
|
diff -ruN a/src/transports/pipe.c b/src/transports/pipe.c
|
|
--- a/src/transports/pipe.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/transports/pipe.c 2023-09-14 18:48:55.202596199 +0300
|
|
@@ -599,13 +599,16 @@
|
|
tblock->name);
|
|
return FALSE;
|
|
}
|
|
-if (is_tainted(cmd))
|
|
+
|
|
+{ uschar *m;
|
|
+if ((m = is_tainted2(cmd, 0, "Tainted '%s' (command "
|
|
+ "for %s transport) not permitted", cmd, tblock->name)))
|
|
{
|
|
- addr->message = string_sprintf("Tainted '%s' (command "
|
|
- "for %s transport) not permitted", cmd, tblock->name);
|
|
addr->transport_return = PANIC;
|
|
+ addr->message = m;
|
|
return FALSE;
|
|
}
|
|
+}
|
|
|
|
/* When a pipe is set up by a filter file, there may be values for $thisaddress
|
|
and numerical the variables in existence. These are passed in
|
|
diff -ruN a/src/transports/smtp.c b/src/transports/smtp.c
|
|
--- a/src/transports/smtp.c 2021-04-30 15:08:21.000000000 +0300
|
|
+++ b/src/transports/smtp.c 2023-09-14 18:48:28.641946264 +0300
|
|
@@ -2015,7 +2015,7 @@
|
|
{
|
|
case OK: sx->conn_args.dane = TRUE;
|
|
ob->tls_tempfail_tryclear = FALSE; /* force TLS */
|
|
- ob->tls_sni = sx->first_addr->domain; /* force SNI */
|
|
+ ob->tls_sni = sx->conn_args.host->name; /* force SNI */
|
|
break;
|
|
case FAIL_FORCED: break;
|
|
default: set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER,
|
|
@@ -2097,7 +2097,7 @@
|
|
{
|
|
case OK: sx->conn_args.dane = TRUE;
|
|
ob->tls_tempfail_tryclear = FALSE; /* force TLS */
|
|
- ob->tls_sni = sx->first_addr->domain; /* force SNI */
|
|
+ ob->tls_sni = sx->conn_args.host->name; /* force SNI */
|
|
break;
|
|
case FAIL_FORCED: break;
|
|
default: set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER,
|
|
@@ -4715,11 +4715,8 @@
|
|
else
|
|
if (ob->hosts_randomize) s = expanded_hosts = string_copy(s);
|
|
|
|
- if (is_tainted(s))
|
|
+ if (is_tainted2(s, LOG_MAIN|LOG_PANIC, "Tainted host list '%s' from '%s' in transport %s", s, ob->hosts, tblock->name))
|
|
{
|
|
- log_write(0, LOG_MAIN|LOG_PANIC,
|
|
- "attempt to use tainted host list '%s' from '%s' in transport %s",
|
|
- s, ob->hosts, tblock->name);
|
|
/* Avoid leaking info to an attacker */
|
|
addrlist->message = US"internal configuration error";
|
|
addrlist->transport_return = PANIC;
|