2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-25 03:18:41 +00:00

Compare commits

...

5 Commits

Author SHA1 Message Date
Wietse Z Venema
03efe71c9a postfix-3.10.4 2025-08-20 00:41:46 +10:00
Wietse Z Venema
cbbd8b65e0 postfix-3.10.3 2025-07-11 13:15:30 +10:00
Wietse Z Venema
ef01d8ffa9 postfix-3.10.2 2025-04-23 11:22:05 +10:00
Wietse Z Venema
186a72901f postfix-3.10.1 2025-02-25 12:15:13 +11:00
Wietse Z Venema
8599da0f46 postfix-3.10.0 2025-02-18 13:47:31 +11:00
34 changed files with 505 additions and 141 deletions

View File

@ -28966,9 +28966,9 @@ Apologies for any names omitted.
tls/tls_misc.c. tls/tls_misc.c.
Bugfix (defect introduced: Postfix 3.4, date 20181113): a Bugfix (defect introduced: Postfix 3.4, date 20181113): a
server with multiple TLS certificates could report for a server with multiple TLS certificates could report, for a
resumed TLS session, in logging and Received: message resumed TLS session, the wrong server-signature and
headers, the wrong server-signature and server-digest names. server-digest names in logging and Received: message headers.
Viktor Dukhovni. File: tls/tls_misc.c. Viktor Dukhovni. File: tls/tls_misc.c.
20250213 20250213
@ -28982,4 +28982,143 @@ Apologies for any names omitted.
tls_config_file description. File: proto/postconf.proto. tls_config_file description. File: proto/postconf.proto.
The unused parameters will be deleted in Postfix 3.11. The unused parameters will be deleted in Postfix 3.11.
Postfix 3.10 code freeze. 20250215
Safety: added a TLSRPT library version check. Log a warning
when the run-time TLSRPT library API version is not compatible
with the build-time TLSRPT API version, where 'compatible'
is defined according to the rules of semantic versioning.
This completes the Postfix 3.10 stable release.
20250216
Bugfix (defect introduced: Postfix 3.10): Postfix SMTP
client segfault while reporting a 'certificate expired'
event. Problem reported by Oemer Gueven. File: tls/tls_verify.c.
20250221
Bugfix (defect introduced: 20250210): a recent 'fix' for the
default smtp_tls_dane_insecure_mx_policy setting resulted in
unnecessary 'dnssec_probe' warnings, on systems that disable
DNSSEC lookups (the default). File: smtp/smtp_addr.c.
20250223
Documentation: updated link to Dovecot documentation. File:
proto/SASL_README.
20250227
Improved and corrected error messages when converting (host
or service) information to (symbolic text, numerical text,
or binary) form. File: util/myaddrinfo.c.
20250304
Bugfix (defect introduced: Postfix 2.3, date 20051222): the
Dovecot auth client did not attempt to create a new connection
after an I/O error on an existing connection. Reported by
Oleksandr Kozmenko. File: xsasl/xsasl_dovecot_server.c.
20250316
Bugfix (defect introduced: date 19991116): when appending
a setting to a main.cf or master.cf file that did not end
in a newline character, the "postconf -e" command did not
add an extra newline character before appending the new
setting, causing information to become garbled. Fix by
Michael Tokarev. File: postconf/postconf_edit.c.
20250619
Bugfix (defect introduced: Postfix-3.10, date 20250117):
include the current TLS security level in the SMTP connection
cache lookup key for lookups by next-hop destination. The
idea is that to deliver a message without "TLS-Required:
no" header, the Postfix SMTP client must not reuse a
connection that was created during a burst of deliveries
of messages with "TLS-Required: no" to the same destination.
Including the TLS security level in the SMTP connection
cache lookup key will also prevent false connection reuse
when any future feature is added that overrides the TLS
security level based on message content or envelope metadata.
Files: smtp/smtp.h.
Likewise, include the current TLS security level in the TLS
client serverid field. File: smtp/smtp_proto.c.
Bugfix (defect introduced: Postfix-3.10, date 20250117): the
Postfix SMTP client attempted to look up TLSA records even
with "TLS-Required: no". This could result in unnecessary
failures. Fix by Viktor Dukhovni & Wietse. Files: smtp/smtp.h,
smtp/smtp_policy.c, smtp/smtp_connect.c.
20250710
Bugfix (defect introduced: postfix-2.2, date 20050203):
after detecting a lookup table change, and after starting
a new postscreen process, the old postscreen process logged
an ENOTSOCK error while attempting to accept a connection
on a socket that it was no longer listening on. This error
was introduced first in the multi_server skeleton code, and
was five years later duplicated in the event_server skeleton
that was created for postscreen. Problem reported by Florian
Piekert. Files: master/multi_server.c, master/event_server.c.
20250714
Deleted an <openssl/engine.h> dependency, because the feature is
being removed from OpenSSL, and Postfix no longer needs it. File:
posttls-finger/posttls-finger.c.
20250716
Bugfix (defect introduced: Postfix 2.8, date 20101230):
after detecting a cache table change and before starting a
new postscreen process, the old postscreen process did not
close the postscreen_cache_map, and therefore kept an
exclusive lock that could prevent a new postscreen process
from starting. Problem reported by Florian Piekert. File:
postscreen/postscreen.c.
20250717
Workaround: Postfix daemons no longer automatically restart
after a btree:, dbm:, hash:, lmdb:, or sdbm: table file
modification time change, when they opened that table for
writing. Files: util/dict.c, util/dict_db.c, util/dict_dbm.c,
util/dict_lmdb.c, util/dict_sdbm.c.
20250730
Bugfix (defect introduced: Postfix 3.6, date 20200710):
Postfix TLS client code logged "Untrusted TLS connection"
(wrong) instead of "Trusted TLS connection" (right), for a
new or resumed TLS session, when a server offered a trusted
(valid PKI trust chain) certificate that did not match the
expected server name pattern. Viktor Dukhovni. Files:
tls/tls_client.c, tls/tls_verify.c.
20250801
Bugfix (defect introduced: Postfix 3.7): incorrect backwards
compatible support for the legacy configuration parameters
tlsproxy_client_level and tlsproxy_client_policy. This
disabled the tlsproxy TLS client role when a legacy parameter
was set. Reported by John Doe, diagnosed by Viktor Dukhovni.
File: global/mail_params.h.
Bugfix (defect introduced: Postfix 3.4): with the TLS client
role disabled by configuration, the tlsproxy daemon
dereferenced a null pointer while handling a tlsproxy client
request. Reported by John Doe. File: tlsproxy/tlsproxy.c.
20250803
Cleanup: with "tls_required_enable = yes", the Postfix SMTP
client will no longer maintain TLSRPT statistics for
messages that contain a "TLS-Required: no" header. This
can prevent TLSRPT notifications for TLSRPT notifications.
Files: smtp/smtp_connect.c, smtp_tls_policy.c.

View File

@ -1,12 +1,12 @@
This is the Postfix 3.10 experimental release. This is the Postfix 3.10 stable release.
The stable Postfix release is called postfix-3.9.x where 3=major The stable Postfix release is called postfix-3.10.x where 3=major
release number, 9=minor release number, x=patchlevel. The stable release number, 10=minor release number, x=patchlevel. The stable
release never changes except for patches that address bugs or release never changes except for patches that address bugs or
emergencies. Patches change the patchlevel and the release date. emergencies. Patches change the patchlevel and the release date.
New features are developed in snapshot releases. These are called New features are developed in snapshot releases. These are called
postfix-3.10-yyyymmdd where yyyymmdd is the release date (yyyy=year, postfix-3.11-yyyymmdd where yyyymmdd is the release date (yyyy=year,
mm=month, dd=day). Patches are never issued for snapshot releases; mm=month, dd=day). Patches are never issued for snapshot releases;
instead, a new snapshot is released. instead, a new snapshot is released.
@ -25,63 +25,74 @@ now also distributed with the more recent Eclipse Public License
(EPL) 2.0. Recipients can choose to take the software under the (EPL) 2.0. Recipients can choose to take the software under the
license of their choice. Those who are more comfortable with the license of their choice. Those who are more comfortable with the
IPL can continue with that license. IPL can continue with that license.
[Feature 20250117]
Support for the RFC 8689 "TLS-Required: no" message header to request Major changes - tls
delivery of messages such as TLSRPT summaries even if the preferred -------------------
TLS security policy cannot be enforced. This limits the Postfix
SMTP client to "smtp_tls_security_level = may" which does not [Forward compatibility 20250212] Support for OpenSSL 3.5 post-quantum
authenticate server certificates and which allows falling back to cryptography. To manage algorithm selection, OpenSSL introduces new
plaintext. TLS group syntax that Postfix will not attempt to imitate. Instead,
Postfix now allows the tls_eecdh_auto_curves and tls_ffdhe_auto_groups
parameter values to have an empty value. When both are set empty,
the algorithm selection can be managed through OpenSSL configuration.
For more, look for "Post-quantum" in the postconf(5) manpage.
[Feature 20250117] Support for the RFC 8689 "TLS-Required: no"
message header to request delivery of messages such as TLSRPT
summaries even if the preferred TLS security policy cannot be
enforced. This limits the Postfix SMTP client to "smtp_tls_security_level
= may" which does not authenticate server certificates and which
allows falling back to plaintext.
Support for the REQUIRETLS SMTP service extension remains future work. Support for the REQUIRETLS SMTP service extension remains future work.
[Incompat 20250116] [Feature 20240926] Support for the TLSRPT protocol (defined in RFC
8460). With this, a domain can publish a policy in DNS, and request
daily summary reports for successful and failed SMTP-over-TLS
connections to that domain's MX hosts.
Postfix needs "postfix reload" after upgrade, because of a change in Postfix supports TLSRPT summaries for DANE (built-in) and MTA-STS
the delivery agent protocol. If this step is skipped, Postfix delivery (via an smtp_tls_policy_maps plugin). For details, see TLSRPT_README.
agents will log a warning:
unexpected attribute smtputf8 from xxx socket (expecting: sendopts) Major changes - privacy
-----------------------
where xxx is the delivery agent service name. [Feature 20250205] With "smtpd_hide_client_session = yes", the
Postfix SMTP server generates a Received: header without client
session info This setting may be used with the MUA submission
services (port 465 and 587), but it must not be used with the MTA
service (port 25).
[Incompat 20250106] Depending on the number of recipients, a redacted Received: header
has one of the following forms:
The logging of the Milter 'quarantine' action has changed. Instead Received: by mail.example.com (Postfix) id postfix-queue-id
of logging "milter triggers HOLD action", it logs the reason given for <user@example.com>; Day, dd Mon yyyy hh:mm:ss tz-offset (zone)
by a Milter application, or "default_action" if a Milter application
was unavailable and the milter_default_action parameter or Milter
"default_action" property specifies "quarantine".
[Feature 20250106] Received: by mail.example.com (Postfix) id postfix-queue-id
Day, dd Mon yyyy hh:mm:ss tz-offset (zone)
The Postfix Milter implementation now logs the reason for a The redacted form hides that a message was received with SMTP, and
'quarantine' action, instead of "milter triggers HOLD action". therefore it does not need to provide the information required by
RFC 5321. It only has to satisfy RFC 5322.
- If the quarantine action was requested by a Milter application, Major changes - rfc2047
Postfix will log the reason given by the application. -----------------------
- If the quarantine action was requested with the "milter_default_action" [Feature 20250105] Support for automatic RFC 2047 encoding of
parameter setting or with a Milter "default_action" property, non-ASCII "full name" information in Postfix-generated From: message
Postfix will log "default_action". headers. Encoding non-ASCII full names can avoid the need to use
SMTPUTF8, and therefore can avoid incompatibility with sites that
[Feature 20250105] do not support SMTPUTF8.
Support for automatic RFC 2047 encoding of non-ASCII "full name"
information in Postfix-generated From: message headers. Encoding
non-ASCII full names can avoid the need to use SMTPUTF8, and therefore
can avoid incompatibility with sites that do not support SMTPUTF8.
The encoded result looks like "=?charset?Q?gibberish?=: for The encoded result looks like "=?charset?Q?gibberish?=: for
quoted-printable encoding, or "=?charset?B?gibberish?=" for base64 quoted-printable encoding, or "=?charset?B?gibberish?=" for base64
encoding. Postfix uses quoted-printable for a full name that is encoding. Postfix uses quoted-printable for a full name that is
short or mostly ASCII, and uses base64 otherwise. short or mostly ASCII, and uses base64 otherwise.
Background: when a message without a From: header is submitted with the Background: when a message without a From: header is submitted with
Postfix sendmail(1) command, Postfix will add a From: header and will the Postfix sendmail(1) command, Postfix may add a From: header and
try to use the sender's full name specified with the Postfix sendmail(1) use the sender's full name specified with the Postfix sendmail(1)
"-F" option, with the sendmail(1) "NAME" environment variable, or "-F" option, with the sendmail(1) "NAME" environment variable, or
with the GECOS field in the UNIX password database. with the GECOS field in the UNIX password database.
@ -89,31 +100,101 @@ This introduces a new configuration parameter "full_name_encoding_charset"
(default: utf8) which specifies the character set of the full name (default: utf8) which specifies the character set of the full name
information in the Postfix sendmail(1) "-F" option or "NAME" information in the Postfix sendmail(1) "-F" option or "NAME"
environment variable, or in the GECOS field in the UNIX password environment variable, or in the GECOS field in the UNIX password
database. The parameter value is also part of the encoded full name, database. The parameter value becomes part of the encoded full name,
and informs a Mail User Agent how to display the decoded gibberish. and informs a Mail User Agent how to display the decoded gibberish.
[Incompat 20250105] Major changes - bugfix
----------------------
The SMTP server now logs the queue ID (or "NOQUEUE") when a connection [Incompat 20241130] The spawn(8) daemon failed to enforce the command
ends abnormally (timeout, lost connection, or too many errors). time limit. It was sending the SIGKILL signal using the wrong
effective UID and GID. The pipe(8) daemon has always done this
right.
[Feature 20250105] Major changes - database
------------------------
The SMTP server now logs the queue ID (or "NOQUEUE") when a connection [Feature 20250207] When mysql: or pgsql: configuration specifies
ends abnormally (timeout, lost connection, or too many errors). a single host, assume that it is a load balancer and reconnect
immediately after a single failure, instead of failing all requests
for 60s.
[Feature 20241104] [Feature 20250114] first/next iterator support for cdb: tables, and
other cdb: table code cleanups by Michael Tokarev.
The cleanup server now logs "queueid: canceled" when a message [Feature 20241024] In a pgsql: client configuration, the setting
transaction is started but not completed. This provides a clear "dbname" is required, but ignored when the setting "hosts" contains
signal to logfile collation tools. an URI with a database name.
[Feature 20240926] [Feature 20241025] The Postfix pgsql: client configuration now
allows any well-formed URI prefix as a pgsql: client connection
target (the PostgreSQL URI parser decides what is allowed). The
dbname setting is now optional if the hosts setting specifies only
URIs.
Support for the TLSRPT protocol (defined in RFC 8460). With this, Major changes - internal protocol
an email receiving domain can publish a policy in DNS, and request ---------------------------------
daily summary reports for successful and failed SMTP-over-TLS
connections to that domain's MX hosts.
Postfix supports TLSRPT summaries for DANE (built-in) and MTA-STS [Incompat 20250116] Postfix needs "postfix reload" after upgrade,
(via an smtp_tls_policy_maps plugin). For details, see TLSRPT_README. because of a change in the delivery agent protocol. If this step
is skipped, Postfix delivery agents will log a warning:
unexpected attribute smtputf8 from xxx socket (expecting: sendopts)
where xxx is the delivery agent service name.
Major changes - milter
----------------------
[Incompat 20250106] The logging of the Milter 'quarantine' action
has changed. Instead of logging "milter triggers HOLD action", it
logs the reason given by a Milter application, or "default_action"
if a Milter application was unavailable and the milter_default_action
parameter or per-Milter "default_action" property specifies
"quarantine".
[Feature 20250106] The Postfix Milter implementation now logs the
reason for a 'quarantine' action, instead of "milter triggers HOLD
action".
- If the quarantine action was requested by a Milter application,
Postfix will log the reason given by the application.
- If the quarantine action was requested with the "milter_default_action"
parameter setting or with a per-Milter "default_action" property,
Postfix will log "default_action".
Major changes - logging
-----------------------
[Feature 20250106] The Postfix Milter implementation now logs the
reason for a 'quarantine' action, instead of "milter triggers HOLD
action".
- If the quarantine action was requested by a Milter application,
Postfix will log the reason given by the application.
- If the quarantine action was requested with the "milter_default_action"
parameter setting or with a per-Milter "default_action" property,
Postfix will log "default_action".
[Incompat 20250105] The SMTP server now logs the queue ID (or
"NOQUEUE") when a connection ends abnormally (timeout, lost connection,
or too many errors).
[Feature 20250105] The SMTP server now logs the queue ID (or
"NOQUEUE") when a connection ends abnormally (timeout, lost connection,
or too many errors).
[Incompat 20241104] The cleanup server now logs "queueid: canceled"
when a message transaction is started but not completed.
[Feature 20241104] The cleanup server now logs "queueid: canceled"
when a message transaction is started but not completed. This
provides a clear signal to logfile collation tools.
[Incompat 20241031] the Dovecot SASL client logging for "Invalid
authentication mechanism" now includes the name of that mechanism.
[Incompat 20241023] Postfix SMTP server 'reject' logging now shows
the sasl_method, sasl_username, and sasl_sender if available.

View File

@ -178,7 +178,7 @@ later. </p>
<p> Dovecot is a POP/IMAP server that has its own configuration to <p> Dovecot is a POP/IMAP server that has its own configuration to
authenticate POP/IMAP clients. When the Postfix SMTP server uses authenticate POP/IMAP clients. When the Postfix SMTP server uses
Dovecot SASL, it reuses parts of this configuration. Consult the Dovecot SASL, it reuses parts of this configuration. Consult the
<a href="https://wiki.dovecot.org">Dovecot documentation</a> for how <a href="https://doc.dovecot.org">Dovecot documentation</a> for how
to configure and operate the Dovecot authentication server. </p> to configure and operate the Dovecot authentication server. </p>
<h4><a name="server_dovecot_comm">Postfix to Dovecot SASL communication</a></h4> <h4><a name="server_dovecot_comm">Postfix to Dovecot SASL communication</a></h4>

View File

@ -20119,13 +20119,11 @@ openssl.cnf:
Groups = *X25519MLKEM768 / *X25519:X448 / P-256:P-384 Groups = *X25519MLKEM768 / *X25519:X448 / P-256:P-384
</pre> </pre>
<p> Caution: It is typically best to just use the default group <p> Caution: It is typically best to just use the default OpenSSL
settings, for which no $<a href="postconf.5.html#tls_config_file">tls_config_file</a> is required (you can set group settings, by setting "<a href="postconf.5.html#tls_config_file">tls_config_file</a> = none". Overly strict
"<a href="postconf.5.html#tls_config_file">tls_config_file</a> = none", to avoid unwanted leakage of system-wide system-wide TLS settings will conflict with Postfix's opportunistic
settings that strive to harden HTTPS against mostly browser-specific TLS, where being less restrictive is better than downgrading to
security and privacy issues into Postfix use of opportunistic TLS, cleartext SMTP. </p>
where they're they can be counterproductive, leading to downgrades
to cleartext, rather than more "secure" TLS). </p>
<p> This feature is available in Postfix &ge; 3.9, 3.8.1, 3.7.6, <p> This feature is available in Postfix &ge; 3.9, 3.8.1, 3.7.6,
3.6.10, and 3.5.20. </p> 3.6.10, and 3.5.20. </p>

View File

@ -975,7 +975,7 @@ case "$CC" in
esac esac
# Snapshot only. # Snapshot only.
CCARGS="$CCARGS -DSNAPSHOT" #CCARGS="$CCARGS -DSNAPSHOT"
# Non-production: needs thorough testing, or major changes are still # Non-production: needs thorough testing, or major changes are still
# needed before the code stabilizes. # needed before the code stabilizes.

View File

@ -13988,13 +13988,11 @@ openssl.cnf:
.fi .fi
.ad .ad
.PP .PP
Caution: It is typically best to just use the default group Caution: It is typically best to just use the default OpenSSL
settings, for which no $tls_config_file is required (you can set group settings, by setting "tls_config_file = none". Overly strict
"tls_config_file = none", to avoid unwanted leakage of system\-wide system\-wide TLS settings will conflict with Postfix's opportunistic
settings that strive to harden HTTPS against mostly browser\-specific TLS, where being less restrictive is better than downgrading to
security and privacy issues into Postfix use of opportunistic TLS, cleartext SMTP.
where they're they can be counterproductive, leading to downgrades
to cleartext, rather than more "secure" TLS).
.PP .PP
This feature is available in Postfix >= 3.9, 3.8.1, 3.7.6, This feature is available in Postfix >= 3.9, 3.8.1, 3.7.6,
3.6.10, and 3.5.20. 3.6.10, and 3.5.20.

View File

@ -178,7 +178,7 @@ later. </p>
<p> Dovecot is a POP/IMAP server that has its own configuration to <p> Dovecot is a POP/IMAP server that has its own configuration to
authenticate POP/IMAP clients. When the Postfix SMTP server uses authenticate POP/IMAP clients. When the Postfix SMTP server uses
Dovecot SASL, it reuses parts of this configuration. Consult the Dovecot SASL, it reuses parts of this configuration. Consult the
<a href="https://wiki.dovecot.org">Dovecot documentation</a> for how <a href="https://doc.dovecot.org">Dovecot documentation</a> for how
to configure and operate the Dovecot authentication server. </p> to configure and operate the Dovecot authentication server. </p>
<h4><a name="server_dovecot_comm">Postfix to Dovecot SASL communication</a></h4> <h4><a name="server_dovecot_comm">Postfix to Dovecot SASL communication</a></h4>

View File

@ -19245,13 +19245,11 @@ openssl.cnf:
Groups = *X25519MLKEM768 / *X25519:X448 / P-256:P-384 Groups = *X25519MLKEM768 / *X25519:X448 / P-256:P-384
</pre> </pre>
<p> Caution: It is typically best to just use the default group <p> Caution: It is typically best to just use the default OpenSSL
settings, for which no $tls_config_file is required (you can set group settings, by setting "tls_config_file = none". Overly strict
"tls_config_file = none", to avoid unwanted leakage of system-wide system-wide TLS settings will conflict with Postfix's opportunistic
settings that strive to harden HTTPS against mostly browser-specific TLS, where being less restrictive is better than downgrading to
security and privacy issues into Postfix use of opportunistic TLS, cleartext SMTP. </p>
where they're they can be counterproductive, leading to downgrades
to cleartext, rather than more "secure" TLS). </p>
<p> This feature is available in Postfix &ge; 3.9, 3.8.1, 3.7.6, <p> This feature is available in Postfix &ge; 3.9, 3.8.1, 3.7.6,
3.6.10, and 3.5.20. </p> 3.6.10, and 3.5.20. </p>

View File

@ -100,3 +100,5 @@ Roessner
bitflags bitflags
Schulze Schulze
tlspol tlspol
Gueven
Oemer

View File

@ -4171,7 +4171,9 @@ extern bool var_tlsp_clnt_enforce_tls;
/* Migrate an incorrect name. */ /* Migrate an incorrect name. */
#define OBS_TLSP_CLNT_LEVEL "tlsproxy_client_level" #define OBS_TLSP_CLNT_LEVEL "tlsproxy_client_level"
#define VAR_TLSP_CLNT_LEVEL "tlsproxy_client_security_level" #define VAR_TLSP_CLNT_LEVEL "tlsproxy_client_security_level"
#define DEF_TLSP_CLNT_LEVEL "${" OBS_TLSP_CLNT_LEVEL ":$" VAR_SMTP_TLS_LEVEL "}" #define DEF_TLSP_CLNT_LEVEL "${" OBS_TLSP_CLNT_LEVEL "?{$" \
OBS_TLSP_CLNT_LEVEL "}:{$" \
VAR_SMTP_TLS_LEVEL "}}"
extern char *var_tlsp_clnt_level; extern char *var_tlsp_clnt_level;
#define VAR_TLSP_CLNT_PER_SITE "tlsproxy_client_per_site" #define VAR_TLSP_CLNT_PER_SITE "tlsproxy_client_per_site"
@ -4181,7 +4183,9 @@ extern char *var_tlsp_clnt_per_site;
/* Migrate an incorrect name. */ /* Migrate an incorrect name. */
#define OBS_TLSP_CLNT_POLICY "tlsproxy_client_policy" #define OBS_TLSP_CLNT_POLICY "tlsproxy_client_policy"
#define VAR_TLSP_CLNT_POLICY "tlsproxy_client_policy_maps" #define VAR_TLSP_CLNT_POLICY "tlsproxy_client_policy_maps"
#define DEF_TLSP_CLNT_POLICY "${" OBS_TLSP_CLNT_POLICY ":$" VAR_SMTP_TLS_POLICY "}" #define DEF_TLSP_CLNT_POLICY "${" OBS_TLSP_CLNT_POLICY "?{$" \
OBS_TLSP_CLNT_POLICY "}:{$" \
VAR_SMTP_TLS_POLICY "}}"
extern char *var_tlsp_clnt_policy; extern char *var_tlsp_clnt_policy;
/* /*

View File

@ -20,8 +20,8 @@
* Patches change both the patchlevel and the release date. Snapshots have no * Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only. * patchlevel; they change the release date only.
*/ */
#define MAIL_RELEASE_DATE "20250215" #define MAIL_RELEASE_DATE "20250818"
#define MAIL_VERSION_NUMBER "3.10" #define MAIL_VERSION_NUMBER "3.10.4"
#ifdef SNAPSHOT #ifdef SNAPSHOT
#define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE #define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE

View File

@ -273,6 +273,7 @@ static unsigned event_server_generation;
static void (*event_server_pre_disconn) (VSTREAM *, char *, char **); static void (*event_server_pre_disconn) (VSTREAM *, char *, char **);
static void (*event_server_slow_exit) (char *, char **); static void (*event_server_slow_exit) (char *, char **);
static int event_server_watchdog = 1000; static int event_server_watchdog = 1000;
static int event_server_drain_was_called = 0;
/* event_server_exit - normal termination */ /* event_server_exit - normal termination */
@ -327,6 +328,9 @@ int event_server_drain(void)
const char *myname = "event_server_drain"; const char *myname = "event_server_drain";
int fd; int fd;
if (event_server_drain_was_called)
return (0);
switch (fork()) { switch (fork()) {
/* Try again later. */ /* Try again later. */
case -1: case -1:
@ -343,6 +347,7 @@ int event_server_drain(void)
msg_warn("%s: dup2(%d, %d): %m", myname, STDIN_FILENO, fd); msg_warn("%s: dup2(%d, %d): %m", myname, STDIN_FILENO, fd);
} }
var_use_limit = 1; var_use_limit = 1;
event_server_drain_was_called = 1;
return (0); return (0);
/* Let the master start a new process. */ /* Let the master start a new process. */
default: default:
@ -445,6 +450,9 @@ static void event_server_accept_local(int unused_event, void *context)
int time_left = -1; int time_left = -1;
int fd; int fd;
if (event_server_drain_was_called)
return;
/* /*
* Be prepared for accept() to fail because some other process already * Be prepared for accept() to fail because some other process already
* got the connection (the number of processes competing for clients is * got the connection (the number of processes competing for clients is
@ -457,6 +465,8 @@ static void event_server_accept_local(int unused_event, void *context)
if (event_server_pre_accept) if (event_server_pre_accept)
event_server_pre_accept(event_server_name, event_server_argv); event_server_pre_accept(event_server_name, event_server_argv);
if (event_server_drain_was_called)
return;
fd = LOCAL_ACCEPT(listen_fd); fd = LOCAL_ACCEPT(listen_fd);
if (event_server_lock != 0 if (event_server_lock != 0
&& myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK, && myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
@ -483,6 +493,9 @@ static void event_server_accept_pass(int unused_event, void *context)
int fd; int fd;
HTABLE *attr = 0; HTABLE *attr = 0;
if (event_server_drain_was_called)
return;
/* /*
* Be prepared for accept() to fail because some other process already * Be prepared for accept() to fail because some other process already
* got the connection (the number of processes competing for clients is * got the connection (the number of processes competing for clients is
@ -495,6 +508,8 @@ static void event_server_accept_pass(int unused_event, void *context)
if (event_server_pre_accept) if (event_server_pre_accept)
event_server_pre_accept(event_server_name, event_server_argv); event_server_pre_accept(event_server_name, event_server_argv);
if (event_server_drain_was_called)
return;
fd = pass_accept_attr(listen_fd, &attr); fd = pass_accept_attr(listen_fd, &attr);
if (event_server_lock != 0 if (event_server_lock != 0
&& myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK, && myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
@ -520,6 +535,9 @@ static void event_server_accept_inet(int unused_event, void *context)
int time_left = -1; int time_left = -1;
int fd; int fd;
if (event_server_drain_was_called)
return;
/* /*
* Be prepared for accept() to fail because some other process already * Be prepared for accept() to fail because some other process already
* got the connection (the number of processes competing for clients is * got the connection (the number of processes competing for clients is
@ -532,6 +550,8 @@ static void event_server_accept_inet(int unused_event, void *context)
if (event_server_pre_accept) if (event_server_pre_accept)
event_server_pre_accept(event_server_name, event_server_argv); event_server_pre_accept(event_server_name, event_server_argv);
if (event_server_drain_was_called)
return;
fd = inet_accept(listen_fd); fd = inet_accept(listen_fd);
if (event_server_lock != 0 if (event_server_lock != 0
&& myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK, && myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,

View File

@ -260,6 +260,7 @@ static VSTREAM *multi_server_lock;
static int multi_server_in_flow_delay; static int multi_server_in_flow_delay;
static unsigned multi_server_generation; static unsigned multi_server_generation;
static void (*multi_server_pre_disconn) (VSTREAM *, char *, char **); static void (*multi_server_pre_disconn) (VSTREAM *, char *, char **);
static int multi_server_drain_was_called = 0;
/* multi_server_exit - normal termination */ /* multi_server_exit - normal termination */
@ -295,6 +296,9 @@ int multi_server_drain(void)
const char *myname = "multi_server_drain"; const char *myname = "multi_server_drain";
int fd; int fd;
if (multi_server_drain_was_called)
return (0);
switch (fork()) { switch (fork()) {
/* Try again later. */ /* Try again later. */
case -1: case -1:
@ -311,6 +315,7 @@ int multi_server_drain(void)
msg_warn("%s: dup2(%d, %d): %m", myname, STDIN_FILENO, fd); msg_warn("%s: dup2(%d, %d): %m", myname, STDIN_FILENO, fd);
} }
var_use_limit = 1; var_use_limit = 1;
multi_server_drain_was_called = 1;
return (0); return (0);
/* Let the master start a new process. */ /* Let the master start a new process. */
default: default:
@ -429,6 +434,9 @@ static void multi_server_accept_local(int unused_event, void *context)
int time_left = -1; int time_left = -1;
int fd; int fd;
if (multi_server_drain_was_called)
return;
/* /*
* Be prepared for accept() to fail because some other process already * Be prepared for accept() to fail because some other process already
* got the connection (the number of processes competing for clients is * got the connection (the number of processes competing for clients is
@ -441,6 +449,8 @@ static void multi_server_accept_local(int unused_event, void *context)
if (multi_server_pre_accept) if (multi_server_pre_accept)
multi_server_pre_accept(multi_server_name, multi_server_argv); multi_server_pre_accept(multi_server_name, multi_server_argv);
if (multi_server_drain_was_called)
return;
fd = LOCAL_ACCEPT(listen_fd); fd = LOCAL_ACCEPT(listen_fd);
if (multi_server_lock != 0 if (multi_server_lock != 0
&& myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK, && myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
@ -467,6 +477,9 @@ static void multi_server_accept_pass(int unused_event, void *context)
int fd; int fd;
HTABLE *attr = 0; HTABLE *attr = 0;
if (multi_server_drain_was_called)
return;
/* /*
* Be prepared for accept() to fail because some other process already * Be prepared for accept() to fail because some other process already
* got the connection (the number of processes competing for clients is * got the connection (the number of processes competing for clients is
@ -479,6 +492,8 @@ static void multi_server_accept_pass(int unused_event, void *context)
if (multi_server_pre_accept) if (multi_server_pre_accept)
multi_server_pre_accept(multi_server_name, multi_server_argv); multi_server_pre_accept(multi_server_name, multi_server_argv);
if (multi_server_drain_was_called)
return;
fd = pass_accept_attr(listen_fd, &attr); fd = pass_accept_attr(listen_fd, &attr);
if (multi_server_lock != 0 if (multi_server_lock != 0
&& myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK, && myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
@ -504,6 +519,9 @@ static void multi_server_accept_inet(int unused_event, void *context)
int time_left = -1; int time_left = -1;
int fd; int fd;
if (multi_server_drain_was_called)
return;
/* /*
* Be prepared for accept() to fail because some other process already * Be prepared for accept() to fail because some other process already
* got the connection (the number of processes competing for clients is * got the connection (the number of processes competing for clients is
@ -516,6 +534,8 @@ static void multi_server_accept_inet(int unused_event, void *context)
if (multi_server_pre_accept) if (multi_server_pre_accept)
multi_server_pre_accept(multi_server_name, multi_server_argv); multi_server_pre_accept(multi_server_name, multi_server_argv);
if (multi_server_drain_was_called)
return;
fd = inet_accept(listen_fd); fd = inet_accept(listen_fd);
if (multi_server_lock != 0 if (multi_server_lock != 0
&& myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK, && myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,

View File

@ -113,8 +113,13 @@ static char *pcf_find_cf_info(VSTRING *buf, VSTREAM *dst)
static char *pcf_next_cf_line(VSTRING *buf, VSTREAM *src, VSTREAM *dst, int *lineno) static char *pcf_next_cf_line(VSTRING *buf, VSTREAM *src, VSTREAM *dst, int *lineno)
{ {
char *cp; char *cp;
int last_char;
while (vstring_get(buf, src) != VSTREAM_EOF) { while ((last_char = vstring_get(buf, src)) != VSTREAM_EOF) {
if (last_char != '\n') {
VSTRING_ADDCH(buf, '\n');
VSTRING_TERMINATE(buf);
}
if (lineno) if (lineno)
*lineno += 1; *lineno += 1;
if ((cp = pcf_find_cf_info(buf, dst)) != 0) if ((cp = pcf_find_cf_info(buf, dst)) != 0)

View File

@ -996,7 +996,7 @@ static void pre_accept(char *unused_name, char **unused_argv)
if (new_event_time >= last_event_time + 1 if (new_event_time >= last_event_time + 1
&& (name = dict_changed_name()) != 0) { && (name = dict_changed_name()) != 0) {
msg_info("table %s has changed - finishing in the background", name); msg_info("table %s has changed - finishing in the background", name);
event_server_drain(); psc_drain(unused_name, unused_argv);
} else { } else {
last_event_time = new_event_time; last_event_time = new_event_time;
} }

View File

@ -414,7 +414,6 @@
#ifdef USE_TLS #ifdef USE_TLS
#include <tls_proxy.h> #include <tls_proxy.h>
#include <openssl/engine.h>
#endif #endif
/* /*

View File

@ -113,6 +113,7 @@ smtp.o: ../../include/nvtable.h
smtp.o: ../../include/recipient_list.h smtp.o: ../../include/recipient_list.h
smtp.o: ../../include/resolve_clnt.h smtp.o: ../../include/resolve_clnt.h
smtp.o: ../../include/scache.h smtp.o: ../../include/scache.h
smtp.o: ../../include/sendopts.h
smtp.o: ../../include/sock_addr.h smtp.o: ../../include/sock_addr.h
smtp.o: ../../include/string_list.h smtp.o: ../../include/string_list.h
smtp.o: ../../include/stringops.h smtp.o: ../../include/stringops.h
@ -158,6 +159,7 @@ smtp_addr.o: ../../include/own_inet_addr.h
smtp_addr.o: ../../include/recipient_list.h smtp_addr.o: ../../include/recipient_list.h
smtp_addr.o: ../../include/resolve_clnt.h smtp_addr.o: ../../include/resolve_clnt.h
smtp_addr.o: ../../include/scache.h smtp_addr.o: ../../include/scache.h
smtp_addr.o: ../../include/sendopts.h
smtp_addr.o: ../../include/sock_addr.h smtp_addr.o: ../../include/sock_addr.h
smtp_addr.o: ../../include/string_list.h smtp_addr.o: ../../include/string_list.h
smtp_addr.o: ../../include/stringops.h smtp_addr.o: ../../include/stringops.h
@ -304,6 +306,7 @@ smtp_key.o: ../../include/nvtable.h
smtp_key.o: ../../include/recipient_list.h smtp_key.o: ../../include/recipient_list.h
smtp_key.o: ../../include/resolve_clnt.h smtp_key.o: ../../include/resolve_clnt.h
smtp_key.o: ../../include/scache.h smtp_key.o: ../../include/scache.h
smtp_key.o: ../../include/sendopts.h
smtp_key.o: ../../include/sock_addr.h smtp_key.o: ../../include/sock_addr.h
smtp_key.o: ../../include/string_list.h smtp_key.o: ../../include/string_list.h
smtp_key.o: ../../include/sys_defs.h smtp_key.o: ../../include/sys_defs.h
@ -344,6 +347,7 @@ smtp_map11.o: ../../include/quote_flags.h
smtp_map11.o: ../../include/recipient_list.h smtp_map11.o: ../../include/recipient_list.h
smtp_map11.o: ../../include/resolve_clnt.h smtp_map11.o: ../../include/resolve_clnt.h
smtp_map11.o: ../../include/scache.h smtp_map11.o: ../../include/scache.h
smtp_map11.o: ../../include/sendopts.h
smtp_map11.o: ../../include/sock_addr.h smtp_map11.o: ../../include/sock_addr.h
smtp_map11.o: ../../include/string_list.h smtp_map11.o: ../../include/string_list.h
smtp_map11.o: ../../include/sys_defs.h smtp_map11.o: ../../include/sys_defs.h
@ -384,6 +388,7 @@ smtp_misc.o: ../../include/quote_flags.h
smtp_misc.o: ../../include/recipient_list.h smtp_misc.o: ../../include/recipient_list.h
smtp_misc.o: ../../include/resolve_clnt.h smtp_misc.o: ../../include/resolve_clnt.h
smtp_misc.o: ../../include/scache.h smtp_misc.o: ../../include/scache.h
smtp_misc.o: ../../include/sendopts.h
smtp_misc.o: ../../include/sock_addr.h smtp_misc.o: ../../include/sock_addr.h
smtp_misc.o: ../../include/string_list.h smtp_misc.o: ../../include/string_list.h
smtp_misc.o: ../../include/sys_defs.h smtp_misc.o: ../../include/sys_defs.h
@ -491,6 +496,7 @@ smtp_rcpt.o: ../../include/nvtable.h
smtp_rcpt.o: ../../include/recipient_list.h smtp_rcpt.o: ../../include/recipient_list.h
smtp_rcpt.o: ../../include/resolve_clnt.h smtp_rcpt.o: ../../include/resolve_clnt.h
smtp_rcpt.o: ../../include/scache.h smtp_rcpt.o: ../../include/scache.h
smtp_rcpt.o: ../../include/sendopts.h
smtp_rcpt.o: ../../include/sent.h smtp_rcpt.o: ../../include/sent.h
smtp_rcpt.o: ../../include/sock_addr.h smtp_rcpt.o: ../../include/sock_addr.h
smtp_rcpt.o: ../../include/string_list.h smtp_rcpt.o: ../../include/string_list.h
@ -530,6 +536,7 @@ smtp_reuse.o: ../../include/nvtable.h
smtp_reuse.o: ../../include/recipient_list.h smtp_reuse.o: ../../include/recipient_list.h
smtp_reuse.o: ../../include/resolve_clnt.h smtp_reuse.o: ../../include/resolve_clnt.h
smtp_reuse.o: ../../include/scache.h smtp_reuse.o: ../../include/scache.h
smtp_reuse.o: ../../include/sendopts.h
smtp_reuse.o: ../../include/sock_addr.h smtp_reuse.o: ../../include/sock_addr.h
smtp_reuse.o: ../../include/string_list.h smtp_reuse.o: ../../include/string_list.h
smtp_reuse.o: ../../include/stringops.h smtp_reuse.o: ../../include/stringops.h
@ -572,6 +579,7 @@ smtp_sasl_auth_cache.o: ../../include/nvtable.h
smtp_sasl_auth_cache.o: ../../include/recipient_list.h smtp_sasl_auth_cache.o: ../../include/recipient_list.h
smtp_sasl_auth_cache.o: ../../include/resolve_clnt.h smtp_sasl_auth_cache.o: ../../include/resolve_clnt.h
smtp_sasl_auth_cache.o: ../../include/scache.h smtp_sasl_auth_cache.o: ../../include/scache.h
smtp_sasl_auth_cache.o: ../../include/sendopts.h
smtp_sasl_auth_cache.o: ../../include/sock_addr.h smtp_sasl_auth_cache.o: ../../include/sock_addr.h
smtp_sasl_auth_cache.o: ../../include/string_list.h smtp_sasl_auth_cache.o: ../../include/string_list.h
smtp_sasl_auth_cache.o: ../../include/stringops.h smtp_sasl_auth_cache.o: ../../include/stringops.h
@ -613,6 +621,7 @@ smtp_sasl_glue.o: ../../include/nvtable.h
smtp_sasl_glue.o: ../../include/recipient_list.h smtp_sasl_glue.o: ../../include/recipient_list.h
smtp_sasl_glue.o: ../../include/resolve_clnt.h smtp_sasl_glue.o: ../../include/resolve_clnt.h
smtp_sasl_glue.o: ../../include/scache.h smtp_sasl_glue.o: ../../include/scache.h
smtp_sasl_glue.o: ../../include/sendopts.h
smtp_sasl_glue.o: ../../include/smtp_stream.h smtp_sasl_glue.o: ../../include/smtp_stream.h
smtp_sasl_glue.o: ../../include/sock_addr.h smtp_sasl_glue.o: ../../include/sock_addr.h
smtp_sasl_glue.o: ../../include/split_at.h smtp_sasl_glue.o: ../../include/split_at.h
@ -657,6 +666,7 @@ smtp_sasl_proto.o: ../../include/recipient_list.h
smtp_sasl_proto.o: ../../include/resolve_clnt.h smtp_sasl_proto.o: ../../include/resolve_clnt.h
smtp_sasl_proto.o: ../../include/sasl_mech_filter.h smtp_sasl_proto.o: ../../include/sasl_mech_filter.h
smtp_sasl_proto.o: ../../include/scache.h smtp_sasl_proto.o: ../../include/scache.h
smtp_sasl_proto.o: ../../include/sendopts.h
smtp_sasl_proto.o: ../../include/sock_addr.h smtp_sasl_proto.o: ../../include/sock_addr.h
smtp_sasl_proto.o: ../../include/string_list.h smtp_sasl_proto.o: ../../include/string_list.h
smtp_sasl_proto.o: ../../include/stringops.h smtp_sasl_proto.o: ../../include/stringops.h
@ -697,6 +707,7 @@ smtp_session.o: ../../include/nvtable.h
smtp_session.o: ../../include/recipient_list.h smtp_session.o: ../../include/recipient_list.h
smtp_session.o: ../../include/resolve_clnt.h smtp_session.o: ../../include/resolve_clnt.h
smtp_session.o: ../../include/scache.h smtp_session.o: ../../include/scache.h
smtp_session.o: ../../include/sendopts.h
smtp_session.o: ../../include/sock_addr.h smtp_session.o: ../../include/sock_addr.h
smtp_session.o: ../../include/string_list.h smtp_session.o: ../../include/string_list.h
smtp_session.o: ../../include/stringops.h smtp_session.o: ../../include/stringops.h
@ -737,6 +748,7 @@ smtp_state.o: ../../include/nvtable.h
smtp_state.o: ../../include/recipient_list.h smtp_state.o: ../../include/recipient_list.h
smtp_state.o: ../../include/resolve_clnt.h smtp_state.o: ../../include/resolve_clnt.h
smtp_state.o: ../../include/scache.h smtp_state.o: ../../include/scache.h
smtp_state.o: ../../include/sendopts.h
smtp_state.o: ../../include/sock_addr.h smtp_state.o: ../../include/sock_addr.h
smtp_state.o: ../../include/string_list.h smtp_state.o: ../../include/string_list.h
smtp_state.o: ../../include/sys_defs.h smtp_state.o: ../../include/sys_defs.h
@ -778,6 +790,7 @@ smtp_tls_policy.o: ../../include/recipient_list.h
smtp_tls_policy.o: ../../include/resolve_clnt.h smtp_tls_policy.o: ../../include/resolve_clnt.h
smtp_tls_policy.o: ../../include/sane_strtol.h smtp_tls_policy.o: ../../include/sane_strtol.h
smtp_tls_policy.o: ../../include/scache.h smtp_tls_policy.o: ../../include/scache.h
smtp_tls_policy.o: ../../include/sendopts.h
smtp_tls_policy.o: ../../include/sock_addr.h smtp_tls_policy.o: ../../include/sock_addr.h
smtp_tls_policy.o: ../../include/string_list.h smtp_tls_policy.o: ../../include/string_list.h
smtp_tls_policy.o: ../../include/stringops.h smtp_tls_policy.o: ../../include/stringops.h
@ -821,6 +834,7 @@ smtp_tlsrpt.o: ../../include/nvtable.h
smtp_tlsrpt.o: ../../include/recipient_list.h smtp_tlsrpt.o: ../../include/recipient_list.h
smtp_tlsrpt.o: ../../include/resolve_clnt.h smtp_tlsrpt.o: ../../include/resolve_clnt.h
smtp_tlsrpt.o: ../../include/scache.h smtp_tlsrpt.o: ../../include/scache.h
smtp_tlsrpt.o: ../../include/sendopts.h
smtp_tlsrpt.o: ../../include/sock_addr.h smtp_tlsrpt.o: ../../include/sock_addr.h
smtp_tlsrpt.o: ../../include/string_list.h smtp_tlsrpt.o: ../../include/string_list.h
smtp_tlsrpt.o: ../../include/stringops.h smtp_tlsrpt.o: ../../include/stringops.h
@ -864,6 +878,7 @@ smtp_trouble.o: ../../include/nvtable.h
smtp_trouble.o: ../../include/recipient_list.h smtp_trouble.o: ../../include/recipient_list.h
smtp_trouble.o: ../../include/resolve_clnt.h smtp_trouble.o: ../../include/resolve_clnt.h
smtp_trouble.o: ../../include/scache.h smtp_trouble.o: ../../include/scache.h
smtp_trouble.o: ../../include/sendopts.h
smtp_trouble.o: ../../include/smtp_stream.h smtp_trouble.o: ../../include/smtp_stream.h
smtp_trouble.o: ../../include/sock_addr.h smtp_trouble.o: ../../include/sock_addr.h
smtp_trouble.o: ../../include/string_list.h smtp_trouble.o: ../../include/string_list.h
@ -903,6 +918,7 @@ smtp_unalias.o: ../../include/nvtable.h
smtp_unalias.o: ../../include/recipient_list.h smtp_unalias.o: ../../include/recipient_list.h
smtp_unalias.o: ../../include/resolve_clnt.h smtp_unalias.o: ../../include/resolve_clnt.h
smtp_unalias.o: ../../include/scache.h smtp_unalias.o: ../../include/scache.h
smtp_unalias.o: ../../include/sendopts.h
smtp_unalias.o: ../../include/sock_addr.h smtp_unalias.o: ../../include/sock_addr.h
smtp_unalias.o: ../../include/string_list.h smtp_unalias.o: ../../include/string_list.h
smtp_unalias.o: ../../include/sys_defs.h smtp_unalias.o: ../../include/sys_defs.h

View File

@ -32,6 +32,7 @@
#include <tok822.h> #include <tok822.h>
#include <dsn_buf.h> #include <dsn_buf.h>
#include <header_body_checks.h> #include <header_body_checks.h>
#include <sendopts.h>
/* /*
* Postfix TLS library. * Postfix TLS library.
@ -238,6 +239,12 @@ typedef struct SMTP_STATE {
unsigned logged_line_length_limit:1; unsigned logged_line_length_limit:1;
} SMTP_STATE; } SMTP_STATE;
#ifdef USE_TLS
#define STATE_TLS_NOT_REQUIRED(state) \
(var_tls_required_enable && \
((state)->request->sendopts & SOPT_REQUIRETLS_HEADER))
#endif
/* /*
* Primitives to enable/disable/test connection caching and reuse based on * Primitives to enable/disable/test connection caching and reuse based on
* the delivery request next-hop destination (i.e. not smtp_fallback_relay). * the delivery request next-hop destination (i.e. not smtp_fallback_relay).
@ -728,7 +735,7 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int);
*/ */
#define SMTP_KEY_MASK_SCACHE_DEST_LABEL \ #define SMTP_KEY_MASK_SCACHE_DEST_LABEL \
(SMTP_KEY_FLAG_SERVICE | COND_SASL_SMTP_KEY_FLAG_SENDER \ (SMTP_KEY_FLAG_SERVICE | COND_SASL_SMTP_KEY_FLAG_SENDER \
| SMTP_KEY_FLAG_REQ_NEXTHOP) | SMTP_KEY_FLAG_REQ_NEXTHOP | SMTP_KEY_FLAG_TLS_LEVEL)
/* /*
* Connection-cache endpoint lookup key. The SENDER, CUR_NEXTHOP, HOSTNAME, * Connection-cache endpoint lookup key. The SENDER, CUR_NEXTHOP, HOSTNAME,

View File

@ -299,7 +299,8 @@ static DNS_RR *smtp_addr_list(DNS_RR *mx_names, DSN_BUF *why)
if (mx_names->dnssec_valid) if (mx_names->dnssec_valid)
res_opt = RES_USE_DNSSEC; res_opt = RES_USE_DNSSEC;
#ifdef USE_TLS #ifdef USE_TLS
else if (smtp_tls_insecure_mx_policy > TLS_LEV_MAY) else if (smtp_tls_insecure_mx_policy > TLS_LEV_MAY
&& smtp_dns_support == SMTP_DNS_DNSSEC)
res_opt = RES_USE_DNSSEC; res_opt = RES_USE_DNSSEC;
#endif #endif

View File

@ -529,16 +529,6 @@ static int smtp_get_effective_tls_level(DSN_BUF *why, SMTP_STATE *state)
} }
#endif #endif
/*
* Otherwise, if the TLS level is not TLS_LEV_NONE or some non-level, and
* the message contains a "TLS-Required: no" header, limit the level to
* TLS_LEV_MAY.
*/
else if (var_tls_required_enable && tls->level > TLS_LEV_NONE
&& (state->request->sendopts & SOPT_REQUIRETLS_HEADER)) {
tls->level = TLS_LEV_MAY;
}
/* /*
* Success. * Success.
*/ */
@ -968,9 +958,15 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop,
* level of "may" to "encrypt"? This would disable falling back to * level of "may" to "encrypt"? This would disable falling back to
* plaintext, and could break interoperability with receivers that * plaintext, and could break interoperability with receivers that
* crank up security up to 11. * crank up security up to 11.
*
* With "TLS-Required: no" in effect, the SMTP client ignores the
* recipient-side policy mechanism TLSRPT, in addition to the already
* ignored DANE and MTA-STS mechanisms. This prevents TLSRPT
* notifications for all SMTP deliveries that do not require TLS.
*/ */
#ifdef USE_TLSRPT #ifdef USE_TLSRPT
if (smtp_mode && var_smtp_tlsrpt_enable if (smtp_mode && var_smtp_tlsrpt_enable
&& STATE_TLS_NOT_REQUIRED(state) == 0
&& tls_level_lookup(var_smtp_tls_level) > TLS_LEV_NONE && tls_level_lookup(var_smtp_tls_level) > TLS_LEV_NONE
&& !valid_hostaddr(domain, DONT_GRIPE)) && !valid_hostaddr(domain, DONT_GRIPE))
smtp_tlsrpt_create_wrapper(state, domain); smtp_tlsrpt_create_wrapper(state, domain);

View File

@ -926,13 +926,16 @@ static int smtp_start_tls(SMTP_STATE *state)
* XXX: The TLS library will salt the serverid with further details of the * XXX: The TLS library will salt the serverid with further details of the
* protocol and cipher requirements including the server ehlo response. * protocol and cipher requirements including the server ehlo response.
* Deferring the helo to the digested suffix results in more predictable * Deferring the helo to the digested suffix results in more predictable
* SSL session lookup key lengths. * SSL session lookup key lengths. Add the current TLS security level to
* account for TLS level overrides based on message content or envelope
* metadata.
*/ */
serverid = vstring_alloc(10); serverid = vstring_alloc(10);
smtp_key_prefix(serverid, "&", state->iterator, SMTP_KEY_FLAG_SERVICE smtp_key_prefix(serverid, "&", state->iterator, SMTP_KEY_FLAG_SERVICE
| SMTP_KEY_FLAG_CUR_NEXTHOP /* With port */ | SMTP_KEY_FLAG_CUR_NEXTHOP /* With port */
| SMTP_KEY_FLAG_HOSTNAME | SMTP_KEY_FLAG_HOSTNAME
| SMTP_KEY_FLAG_ADDR); | SMTP_KEY_FLAG_ADDR
| SMTP_KEY_FLAG_TLS_LEVEL);
if (state->tls->conn_reuse) { if (state->tls->conn_reuse) {
TLS_CLIENT_PARAMS tls_params; TLS_CLIENT_PARAMS tls_params;

View File

@ -647,11 +647,23 @@ static void *policy_create(const char *unused_key, void *context)
* Compute the per-site TLS enforcement level. For compatibility with the * Compute the per-site TLS enforcement level. For compatibility with the
* original TLS patch, this algorithm is gives equal precedence to host * original TLS patch, this algorithm is gives equal precedence to host
* and next-hop policies. * and next-hop policies.
*
* When "TLS-Required: no" is in effect, skip TLS policy lookup and limit
* the security level to "may". Do not reset the security level after
* policy lookup, as that would result in errors. For example, when TLSA
* records are looked up for security level "dane", and then the security
* level is reset to "may", the activation of those TLSA records will
* fail.
*/ */
tls->level = global_tls_level(); tls->level = global_tls_level();
site_level = TLS_LEV_NOTFOUND; site_level = TLS_LEV_NOTFOUND;
if (tls_policy) { if (STATE_TLS_NOT_REQUIRED(iter->parent)) {
if (msg_verbose)
msg_info("%s: no tls policy lookup", __func__);
if (tls->level > TLS_LEV_MAY)
tls->level = TLS_LEV_MAY;
} else if (tls_policy) {
tls_policy_lookup(tls, &site_level, dest, "next-hop destination"); tls_policy_lookup(tls, &site_level, dest, "next-hop destination");
} else if (tls_per_site) { } else if (tls_per_site) {
tls_site_lookup(tls, &site_level, dest, "next-hop destination"); tls_site_lookup(tls, &site_level, dest, "next-hop destination");

View File

@ -217,8 +217,13 @@ static int smtpd_peer_sockaddr_to_hostaddr(SMTPD_STATE *state)
*/ */
if ((aierr = sockaddr_to_hostaddr(sa, sa_length, &client_addr, if ((aierr = sockaddr_to_hostaddr(sa, sa_length, &client_addr,
&client_port, 0)) != 0) &client_port, 0)) != 0)
msg_fatal("%s: cannot convert client address/port to string: %s", msg_fatal("%s: cannot convert client sockaddr type %s length %ld "
myname, MAI_STRERROR(aierr)); "to string: %s", myname,
#ifdef AF_INET6
sa->sa_family == AF_INET6 ? "AF_INET6" :
#endif
sa->sa_family == AF_INET ? "AF_INET" : "other",
(long) sa_length, MAI_STRERROR(aierr));
state->port = mystrdup(client_port.buf); state->port = mystrdup(client_port.buf);
/* /*
@ -299,9 +304,15 @@ static int smtpd_peer_sockaddr_to_hostaddr(SMTPD_STATE *state)
state->dest_sockaddr_len, state->dest_sockaddr_len,
&server_addr, &server_addr,
&server_port, 0)) != 0) &server_port, 0)) != 0)
msg_fatal("%s: cannot convert server address/port to string: %s", /* TODO: convert IPv4-in-IPv6 to IPv4 form. */
myname, MAI_STRERROR(aierr)); msg_fatal("%s: cannot convert server sockaddr type %s length %ld "
/* TODO: convert IPv4-in-IPv6 to IPv4 form. */ "to string: %s", myname,
#ifdef AF_INET6
state->dest_sockaddr.ss_family == AF_INET6 ? "AF_INET6" :
#endif
state->dest_sockaddr.ss_family == AF_INET ? "AF_INET" :
"other", (long) state->dest_sockaddr_len,
MAI_STRERROR(aierr));
state->dest_addr = mystrdup(server_addr.buf); state->dest_addr = mystrdup(server_addr.buf);
state->dest_port = mystrdup(server_port.buf); state->dest_port = mystrdup(server_port.buf);
@ -409,8 +420,8 @@ static void smtpd_peer_hostaddr_to_sockaddr(SMTPD_STATE *state)
if ((aierr = hostaddr_to_sockaddr(state->addr, state->port, if ((aierr = hostaddr_to_sockaddr(state->addr, state->port,
SOCK_STREAM, &res)) != 0) SOCK_STREAM, &res)) != 0)
msg_fatal("%s: cannot convert client address/port to string: %s", msg_fatal("%s: cannot convert client address '%s' port '%s' to binary: %s",
myname, MAI_STRERROR(aierr)); myname, state->addr, state->port, MAI_STRERROR(aierr));
if (res->ai_addrlen > sizeof(state->sockaddr)) if (res->ai_addrlen > sizeof(state->sockaddr))
msg_panic("%s: address length > struct sockaddr_storage", myname); msg_panic("%s: address length > struct sockaddr_storage", myname);
memcpy((void *) &(state->sockaddr), res->ai_addr, res->ai_addrlen); memcpy((void *) &(state->sockaddr), res->ai_addr, res->ai_addrlen);

View File

@ -313,6 +313,7 @@ static void uncache_session(SSL_CTX *ctx, TLS_SESS_STATE *TLScontext)
static void verify_x509(TLS_SESS_STATE *TLScontext, X509 *peercert, static void verify_x509(TLS_SESS_STATE *TLScontext, X509 *peercert,
const TLS_CLIENT_START_PROPS *props) const TLS_CLIENT_START_PROPS *props)
{ {
int x509_err = SSL_get_verify_result(TLScontext->con);
/* /*
* On exit both peer_CN and issuer_CN should be set. * On exit both peer_CN and issuer_CN should be set.
@ -324,7 +325,7 @@ static void verify_x509(TLS_SESS_STATE *TLScontext, X509 *peercert,
* Is the certificate trust chain trusted and matched? Any required name * Is the certificate trust chain trusted and matched? Any required name
* checks are now performed internally in OpenSSL. * checks are now performed internally in OpenSSL.
*/ */
if (SSL_get_verify_result(TLScontext->con) == X509_V_OK) { if (x509_err == X509_V_OK) {
TLScontext->peer_status |= TLS_CERT_FLAG_TRUSTED; TLScontext->peer_status |= TLS_CERT_FLAG_TRUSTED;
if (TLScontext->must_fail) { if (TLScontext->must_fail) {
msg_panic("%s: cert valid despite trust init failure", msg_panic("%s: cert valid despite trust init failure",
@ -356,6 +357,13 @@ static void verify_x509(TLS_SESS_STATE *TLScontext, X509 *peercert,
tls_dane_log(TLScontext); tls_dane_log(TLScontext);
} }
} }
} else if (TLS_MUST_MATCH(TLScontext->level) &&
x509_err == X509_V_ERR_HOSTNAME_MISMATCH) {
/*
* If the only error is a hostname mismatch, the certificate must have
* been trusted.
*/
TLScontext->peer_status |= TLS_CERT_FLAG_TRUSTED;
} }
/* /*

View File

@ -120,12 +120,26 @@
/* update_error_state - safely stash away error state */ /* update_error_state - safely stash away error state */
static void update_error_state(TLS_SESS_STATE *TLScontext, int depth, static void update_error_state(X509_STORE_CTX *ctx, TLS_SESS_STATE *TLScontext,
X509 *errorcert, int errorcode) int depth, X509 *errorcert, int errorcode)
{ {
/* No news is good news */
if (TLScontext->errordepth >= 0 && TLScontext->errordepth <= depth) /*
return; * Report the error that is closest to the leaf certificate, any errors
* higher up the chain are immaterial until the "inner" errors are fixed.
*
* We special-case "X509_V_ERR_HOSTNAME_MISMATCH" (at depth 0) in order to
* distinguish between untrusted certificates and trusted certificates
* with a hostname mismatch. Any other error has a higher priority.
*/
if (TLScontext->errordepth >= 0) {
if ((TLScontext->errordepth <= depth &&
TLScontext->errorcode != X509_V_ERR_HOSTNAME_MISMATCH) ||
errorcode == X509_V_ERR_HOSTNAME_MISMATCH) {
X509_STORE_CTX_set_error(ctx, TLScontext->errorcode);
return;
}
}
/* /*
* The certificate pointer is stable during the verification callback, * The certificate pointer is stable during the verification callback,
@ -179,12 +193,12 @@ int tls_verify_certificate_callback(int ok, X509_STORE_CTX *ctx)
if (TLScontext->must_fail) { if (TLScontext->must_fail) {
if (depth == 0) { if (depth == 0) {
X509_STORE_CTX_set_error(ctx, err = X509_V_ERR_UNSPECIFIED); X509_STORE_CTX_set_error(ctx, err = X509_V_ERR_UNSPECIFIED);
update_error_state(TLScontext, depth, cert, err); update_error_state(ctx, TLScontext, depth, cert, err);
} }
return (1); return (1);
} }
if (ok == 0) if (ok == 0)
update_error_state(TLScontext, depth, cert, err); update_error_state(ctx, TLScontext, depth, cert, err);
if (TLScontext->log_mask & TLS_LOG_VERBOSE) { if (TLScontext->log_mask & TLS_LOG_VERBOSE) {
if (cert) { if (cert) {
@ -315,7 +329,7 @@ void tls_log_verify_error(TLS_SESS_STATE *TLScontext,
if (tlsrpt) if (tlsrpt)
trw_report_failure(tlsrpt, TLSRPT_CERTIFICATE_EXPIRED, trw_report_failure(tlsrpt, TLSRPT_CERTIFICATE_EXPIRED,
/* additional_info= */ (char *) 0, /* additional_info= */ (char *) 0,
/* failure_code= */ (char *) 8); /* failure_code= */ (char *) 0);
#endif #endif
break; break;
case X509_V_ERR_INVALID_PURPOSE: case X509_V_ERR_INVALID_PURPOSE:

View File

@ -252,6 +252,13 @@
#include <tlsrpt.h> #include <tlsrpt.h>
#endif #endif
#if !defined(TLSRPT_PREREQ)
#define TLSRPT_PREREQ(maj, min) \
(defined(TLSRPT_VERSION_MAJOR) && \
((TLSRPT_VERSION_MAJOR << 16) + TLSRPT_VERSION_MINOR >= \
((maj) << 16) + (min)))
#endif
/* /*
* Utility library. * Utility library.
*/ */
@ -321,6 +328,15 @@ TLSRPT_WRAPPER *trw_create(const char *rpt_socket_name,
myname, rpt_socket_name, rpt_policy_domain, myname, rpt_socket_name, rpt_policy_domain,
rpt_policy_string, skip_reused_hs); rpt_policy_string, skip_reused_hs);
#if TLSRPT_PREREQ(0, 6)
if (tlsrpt_version_check(TLSRPT_VERSION_MAJOR, TLSRPT_VERSION_MINOR,
TLSRPT_VERSION_PATCH) == 0)
msg_warn("run-time library vs. compile-time header version mismatch: "
"libtlsrpt API version '%s' is not compatible with "
"libtlsrpt API version '%s' ", tlsrpt_version(),
TLSRPT_VERSION_STRING);
#endif
/* /*
* memset() is not portable for pointer etc. types. * memset() is not portable for pointer etc. types.
*/ */

View File

@ -1267,6 +1267,12 @@ static TLS_APPL_STATE *tlsp_client_init(TLS_CLIENT_PARAMS *tls_params,
init_buf = vstring_alloc(100); init_buf = vstring_alloc(100);
init_key = tls_proxy_client_init_serialize(attr_print_plain, init_buf, init_key = tls_proxy_client_init_serialize(attr_print_plain, init_buf,
init_props); init_props);
#define TLSP_CLIENT_INIT_RETURN(retval) do { \
vstring_free(init_buf); \
vstring_free(param_buf); \
return (retval); \
} while (0)
if (tlsp_pre_jail_done == 0) { if (tlsp_pre_jail_done == 0) {
if (tlsp_pre_jail_client_param_key == 0 if (tlsp_pre_jail_client_param_key == 0
|| tlsp_pre_jail_client_init_key == 0) { || tlsp_pre_jail_client_init_key == 0) {
@ -1284,9 +1290,12 @@ static TLS_APPL_STATE *tlsp_client_init(TLS_CLIENT_PARAMS *tls_params,
* TLS_APPL_STATE instance; this makes a mismatch of TLS_CLIENT_PARAMS * TLS_APPL_STATE instance; this makes a mismatch of TLS_CLIENT_PARAMS
* settings problematic. * settings problematic.
*/ */
if (tlsp_pre_jail_done else if (tlsp_pre_jail_client_param_key == 0
&& !been_here_fixed(tlsp_params_mismatch_filter, param_key) || tlsp_pre_jail_client_init_key == 0) {
&& strcmp(tlsp_pre_jail_client_param_key, param_key) != 0) { msg_warn("TLS client role is disabled by configuration");
TLSP_CLIENT_INIT_RETURN(0);
} else if (!been_here_fixed(tlsp_params_mismatch_filter, param_key)
&& strcmp(tlsp_pre_jail_client_param_key, param_key) != 0) {
msg_warn("request from tlsproxy client with unexpected settings"); msg_warn("request from tlsproxy client with unexpected settings");
tlsp_log_config_diff(tlsp_pre_jail_client_param_key, param_key); tlsp_log_config_diff(tlsp_pre_jail_client_param_key, param_key);
log_hints = 1; log_hints = 1;
@ -1361,9 +1370,7 @@ static TLS_APPL_STATE *tlsp_client_init(TLS_CLIENT_PARAMS *tls_params,
SSL_MODE_ENABLE_PARTIAL_WRITE SSL_MODE_ENABLE_PARTIAL_WRITE
| SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
} }
vstring_free(init_buf); TLSP_CLIENT_INIT_RETURN(appl_state);
vstring_free(param_buf);
return (appl_state);
} }
/* tlsp_close_event - pre-handshake plaintext-client close event */ /* tlsp_close_event - pre-handshake plaintext-client close event */
@ -1497,6 +1504,7 @@ static void tlsp_get_request_event(int event, void *context)
TLSP_INIT_TIMEOUT, (void *) state); TLSP_INIT_TIMEOUT, (void *) state);
return; return;
} else { } else {
state->flags |= TLSP_FLAG_DO_HANDSHAKE;
tlsp_request_read_event(plaintext_fd, tlsp_get_fd_event, tlsp_request_read_event(plaintext_fd, tlsp_get_fd_event,
TLSP_INIT_TIMEOUT, (void *) state); TLSP_INIT_TIMEOUT, (void *) state);
return; return;

View File

@ -105,7 +105,7 @@ TLSP_STATE *tlsp_state_create(const char *service,
{ {
TLSP_STATE *state = (TLSP_STATE *) mymalloc(sizeof(*state)); TLSP_STATE *state = (TLSP_STATE *) mymalloc(sizeof(*state));
state->flags = TLSP_FLAG_DO_HANDSHAKE; state->flags = 0;
state->service = mystrdup(service); state->service = mystrdup(service);
state->plaintext_stream = plaintext_stream; state->plaintext_stream = plaintext_stream;
state->plaintext_buf = 0; state->plaintext_buf = 0;

View File

@ -147,8 +147,8 @@
/* .IP "char *context" /* .IP "char *context"
/* Application context from the caller. /* Application context from the caller.
/* .PP /* .PP
/* dict_changed_name() returns non-zero when any dictionary needs to /* dict_changed_name() returns non-zero when any dictionary is
/* be re-opened because it has changed or because it was unlinked. /* opened read-only and has changed, or because it was unlinked.
/* A non-zero result is the name of a changed dictionary. /* A non-zero result is the name of a changed dictionary.
/* /*
/* dict_load_file_xt() reads name-value entries from the named file. /* dict_load_file_xt() reads name-value entries from the named file.
@ -601,11 +601,12 @@ const char *dict_changed_name(void)
dict = ((DICT_NODE *) h->value)->dict; dict = ((DICT_NODE *) h->value)->dict;
if (dict->stat_fd < 0) /* not file-based */ if (dict->stat_fd < 0) /* not file-based */
continue; continue;
if (dict->mtime == 0) /* not bloody likely */ if (dict->mtime < 0) /* not bloody likely */
msg_warn("%s: table %s: null time stamp", myname, h->key); msg_warn("%s: table %s: negative time stamp", myname, h->key);
if (fstat(dict->stat_fd, &st) < 0) if (fstat(dict->stat_fd, &st) < 0)
msg_fatal("%s: fstat: %m", myname); msg_fatal("%s: fstat: %m", myname);
if (((dict->flags & DICT_FLAG_MULTI_WRITER) == 0 if (((dict->flags & DICT_FLAG_MULTI_WRITER) == 0
&& dict->mtime > 0
&& st.st_mtime != dict->mtime) && st.st_mtime != dict->mtime)
|| st.st_nlink == 0) || st.st_nlink == 0)
status = h->key; status = h->key;

View File

@ -789,7 +789,8 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
dict_db->dict.stat_fd = dbfd; dict_db->dict.stat_fd = dbfd;
if (fstat(dict_db->dict.stat_fd, &st) < 0) if (fstat(dict_db->dict.stat_fd, &st) < 0)
msg_fatal("dict_db_open: fstat: %m"); msg_fatal("dict_db_open: fstat: %m");
dict_db->dict.mtime = st.st_mtime; if (open_flags == O_RDONLY)
dict_db->dict.mtime = st.st_mtime;
dict_db->dict.owner.uid = st.st_uid; dict_db->dict.owner.uid = st.st_uid;
dict_db->dict.owner.status = (st.st_uid != 0); dict_db->dict.owner.status = (st.st_uid != 0);

View File

@ -472,7 +472,8 @@ DICT *dict_dbm_open(const char *path, int open_flags, int dict_flags)
msg_fatal("open database %s: cannot support GDBM", path); msg_fatal("open database %s: cannot support GDBM", path);
if (fstat(dict_dbm->dict.stat_fd, &st) < 0) if (fstat(dict_dbm->dict.stat_fd, &st) < 0)
msg_fatal("dict_dbm_open: fstat: %m"); msg_fatal("dict_dbm_open: fstat: %m");
dict_dbm->dict.mtime = st.st_mtime; if (open_mode == O_RDONLY)
dict_dbm->dict.mtime = st.st_mtime;
dict_dbm->dict.owner.uid = st.st_uid; dict_dbm->dict.owner.uid = st.st_uid;
dict_dbm->dict.owner.status = (st.st_uid != 0); dict_dbm->dict.owner.status = (st.st_uid != 0);

View File

@ -653,7 +653,8 @@ DICT *dict_lmdb_open(const char *path, int open_flags, int dict_flags)
msg_fatal("dict_lmdb_open: fstat: %m"); msg_fatal("dict_lmdb_open: fstat: %m");
dict_lmdb->dict.lock_fd = dict_lmdb->dict.stat_fd = db_fd; dict_lmdb->dict.lock_fd = dict_lmdb->dict.stat_fd = db_fd;
dict_lmdb->dict.lock_type = MYFLOCK_STYLE_FCNTL; dict_lmdb->dict.lock_type = MYFLOCK_STYLE_FCNTL;
dict_lmdb->dict.mtime = st.st_mtime; if (open_flags == O_RDONLY)
dict_lmdb->dict.mtime = st.st_mtime;
dict_lmdb->dict.owner.uid = st.st_uid; dict_lmdb->dict.owner.uid = st.st_uid;
dict_lmdb->dict.owner.status = (st.st_uid != 0); dict_lmdb->dict.owner.status = (st.st_uid != 0);

View File

@ -449,7 +449,8 @@ DICT *dict_sdbm_open(const char *path, int open_flags, int dict_flags)
dict_sdbm->dict.stat_fd = sdbm_pagfno(dbm); dict_sdbm->dict.stat_fd = sdbm_pagfno(dbm);
if (fstat(dict_sdbm->dict.stat_fd, &st) < 0) if (fstat(dict_sdbm->dict.stat_fd, &st) < 0)
msg_fatal("dict_sdbm_open: fstat: %m"); msg_fatal("dict_sdbm_open: fstat: %m");
dict_sdbm->dict.mtime = st.st_mtime; if (open_flags == O_RDONLY)
dict_sdbm->dict.mtime = st.st_mtime;
dict_sdbm->dict.owner.uid = st.st_uid; dict_sdbm->dict.owner.uid = st.st_uid;
dict_sdbm->dict.owner.status = (st.st_uid != 0); dict_sdbm->dict.owner.status = (st.st_uid != 0);

View File

@ -617,6 +617,7 @@ static int xsasl_dovecot_handle_reply(XSASL_DOVECOT_SERVER *server,
} }
vstring_strcpy(reply, "Connection lost to authentication server"); vstring_strcpy(reply, "Connection lost to authentication server");
xsasl_dovecot_server_disconnect(server->impl);
return XSASL_AUTH_TEMP; return XSASL_AUTH_TEMP;
} }
@ -707,6 +708,7 @@ int xsasl_dovecot_server_first(XSASL_SERVER *xp, const char *sasl_method,
if (i == 1) { if (i == 1) {
vstring_strcpy(reply, "Can't connect to authentication server"); vstring_strcpy(reply, "Can't connect to authentication server");
xsasl_dovecot_server_disconnect(server->impl);
return XSASL_AUTH_TEMP; return XSASL_AUTH_TEMP;
} }
@ -735,6 +737,7 @@ static int xsasl_dovecot_server_next(XSASL_SERVER *xp, const char *request,
"CONT\t%u\t%s\n", server->last_request_id, request); "CONT\t%u\t%s\n", server->last_request_id, request);
if (vstream_fflush(server->impl->sasl_stream) == VSTREAM_EOF) { if (vstream_fflush(server->impl->sasl_stream) == VSTREAM_EOF) {
vstring_strcpy(reply, "Connection lost to authentication server"); vstring_strcpy(reply, "Connection lost to authentication server");
xsasl_dovecot_server_disconnect(server->impl);
return XSASL_AUTH_TEMP; return XSASL_AUTH_TEMP;
} }
return xsasl_dovecot_handle_reply(server, reply); return xsasl_dovecot_handle_reply(server, reply);