mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-29 21:27:57 +00:00
postfix-2.3-20051010
This commit is contained in:
parent
14313fe35c
commit
88a2e39fc7
2
postfix/.indent.pro
vendored
2
postfix/.indent.pro
vendored
@ -3,7 +3,9 @@
|
||||
-TALIAS_TOKEN
|
||||
-TANVIL_CLNT
|
||||
-TANVIL_LOCAL
|
||||
-TANVIL_MAX
|
||||
-TANVIL_REMOTE
|
||||
-TANVIL_REQ_TABLE
|
||||
-TARGV
|
||||
-TATTR_CLNT
|
||||
-TATTR_TABLE
|
||||
|
@ -11148,19 +11148,47 @@ Apologies for any names omitted.
|
||||
others. Files: local/local.c, local/aliases.c, local/dotforward.c,
|
||||
local/mailbox.c, local/maildir.c.
|
||||
|
||||
Cleanup: while expanding a local(8) alias that has an owner
|
||||
alias, don't reset the owner-alias information when recursing
|
||||
into an alias that has no owner alias. This produces better
|
||||
error reports when delivering mail to nested aliases that
|
||||
have an owner alias only at the top level. To get the old
|
||||
behavior, specify "sticky_owner_alias = no". Problem
|
||||
reported by Victor Duchovni. File: local/alias.c.
|
||||
|
||||
Logging: additional SASL debug logging by Andreas Winkelmann.
|
||||
Files: */*sasl_glue.c.
|
||||
|
||||
20050929
|
||||
|
||||
Paranoia: don't ignore garbage in SMTP or LMTP server replies
|
||||
when ESMTP command pipelining is turned on. For example,
|
||||
after sending ".<CR><LF>QUIT<CR><LF>", Postfix could recognize
|
||||
the server's 2XX QUIT reply as a 2XX END-OF-DATA reply after
|
||||
garbage, causing mail to be lost. The SMTP and LMTP clients
|
||||
now report a remote protocol error and defer delivery.
|
||||
Files: smtp/smtp_chat.c, smtp/smtp_trouble.c, lmtp/lmtp_chat.c,
|
||||
lmtp/lmtp_trouble.c.
|
||||
|
||||
Performance: specify "smtpd_peername_lookup = no" to disable
|
||||
client hostname lookups in the SMTP server. All clients are
|
||||
treated as "unknown". This should be used only under extreme
|
||||
conditions where DNS lookup latencies are critical. File:
|
||||
smtpd/smtpd_peer.c.
|
||||
|
||||
20051010
|
||||
|
||||
Feature: smtpd_client_new_tls_session_rate_limit parameter
|
||||
to limit the number of new (i.e. uncached) TLS sessions
|
||||
that a remote SMTP client may negotiate per unit time. This
|
||||
feature, which is off by default, can limit the CPU load
|
||||
due to expensive crypto operations. Files: global/anvil_clnt.c,
|
||||
anvil/anvil.c, smtpd/smtpd.c.
|
||||
|
||||
Cleanup: eliminated code duplicatiom in the anvil server
|
||||
that resulted from adding similar features one at a time.
|
||||
File: anvil/anvil.c.
|
||||
|
||||
Open problems:
|
||||
|
||||
Try to recognize that Resent- headers appear in blocks,
|
||||
newest block first. But don't break on incorrect header
|
||||
block organization.
|
||||
|
||||
Hard limits on cache sizes (anvil, specifically).
|
||||
|
||||
Look for systems with XPG basename() declared in <libgen.h>,
|
||||
and prepare for phasing out the Postfix-supplied one.
|
||||
Beware, however, that XPG basename() takes (char *), and
|
||||
|
@ -17,7 +17,8 @@ Postfix source code, in the directory examples/smtpd-policy.
|
||||
Policy delegation is now the preferred method for adding policies to Postfix.
|
||||
It's much easier to develop a new feature in few lines of Perl, than trying to
|
||||
do the same in C code. The difference in performance will be unnoticeable
|
||||
except in the most demanding environments.
|
||||
except in the most demanding environments. On active systems a policy daemon
|
||||
process is used multiple times, for up to 100 incoming SMTP connections.
|
||||
|
||||
This document covers the following topics:
|
||||
|
||||
|
@ -26,12 +26,9 @@ files. With deeply nested aliases or .forward files, this can greatly
|
||||
reduce the number of queue files and cleanup process instances. To
|
||||
get the earlier behavior, specify "frozen_delivered_to = no".
|
||||
|
||||
While expanding an alias that has an owner alias, the Postfix
|
||||
local(8) delivery agent no longer resets the owner information when
|
||||
it expands a subordinate alias that has no owner alias. This
|
||||
produces better error reporting with nested aliases that have an
|
||||
owner alias only at the top level. To get the earlier behavior,
|
||||
specify "sticky_owner_alias = no".
|
||||
The frozen_delivered_to feature also fixes an old problem with
|
||||
duplicate deliveries to recipients that are listed in multiple
|
||||
nested aliases.
|
||||
|
||||
Incompatibility with snapshot 20050828
|
||||
======================================
|
||||
|
@ -36,7 +36,8 @@ the Postfix source code, in the directory examples/smtpd-policy.
|
||||
to Postfix. It's much easier to develop a new feature in few lines
|
||||
of Perl, than trying to do the same in C code. The difference in
|
||||
performance will be unnoticeable except in the most demanding
|
||||
environments. </p>
|
||||
environments. On active systems a policy daemon process is used
|
||||
multiple times, for up to 100 incoming SMTP connections. </p>
|
||||
|
||||
<p> This document covers the following topics: </p>
|
||||
|
||||
|
@ -13,151 +13,167 @@ ANVIL(8) ANVIL(8)
|
||||
<b>anvil</b> [generic Postfix daemon options]
|
||||
|
||||
<b>DESCRIPTION</b>
|
||||
The Postfix <a href="anvil.8.html"><b>anvil</b>(8)</a> server maintains short-term statis-
|
||||
tics to defend against clients that hammer a server with
|
||||
either too many simultaneous sessions, or with too many
|
||||
successive requests within a configurable time interval.
|
||||
This server is designed to run under control by the Post-
|
||||
fix <a href="master.8.html"><b>master</b>(8)</a> server.
|
||||
The Postfix <a href="anvil.8.html"><b>anvil</b>(8)</a> server maintains statistics about
|
||||
client connection counts or client request rates. This
|
||||
information can be used to defend against clients that
|
||||
hammer a server with either too many simultaneous ses-
|
||||
sions, or with too many successive requests within a con-
|
||||
figurable time interval. This server is designed to run
|
||||
under control by the Postfix <a href="master.8.html"><b>master</b>(8)</a> server.
|
||||
|
||||
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server maintains no persistent database.
|
||||
Standard library utilities do not meet Postfix performance
|
||||
and robustness requirements.
|
||||
In the following text, <b>ident</b> specifies a (service, client)
|
||||
combination. The exact syntax of that information is
|
||||
application-dependent; the <a href="anvil.8.html"><b>anvil</b>(8)</a> server does not care.
|
||||
|
||||
<b>CONNECTION COUNT/RATE LIMITING</b>
|
||||
When a remote client connects, a connection count (or
|
||||
rate) limited server should send the following request to
|
||||
<b>CONNECTION COUNT/RATE CONTROL</b>
|
||||
To register a new connection send the following request to
|
||||
the <a href="anvil.8.html"><b>anvil</b>(8)</a> server:
|
||||
|
||||
<b>request=connect</b>
|
||||
<b>ident=</b><i>string</i>
|
||||
|
||||
This registers a new connection for the (service, client)
|
||||
combination specified with <b>ident</b>. The <a href="anvil.8.html"><b>anvil</b>(8)</a> server
|
||||
answers with the number of simultaneous connections and
|
||||
the number of connections per unit time for that (service,
|
||||
client) combination:
|
||||
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server answers with the number of simultane-
|
||||
ous connections and the number of connections per unit
|
||||
time for the (service, client) combination specified with
|
||||
<b>ident</b>:
|
||||
|
||||
<b>status=0</b>
|
||||
<b>count=</b><i>number</i>
|
||||
<b>rate=</b><i>number</i>
|
||||
|
||||
The <b>rate</b> is computed as the number of connections that
|
||||
were registered in the current "time unit" interval. It
|
||||
is left up to the server to decide if the remote client
|
||||
exceeds the connection count (or rate) limit.
|
||||
|
||||
When a remote client disconnects, a connection count (or
|
||||
rate) limited server should send the following request to
|
||||
the <a href="anvil.8.html"><b>anvil</b>(8)</a> server:
|
||||
To register a disconnect event send the following request
|
||||
to the <a href="anvil.8.html"><b>anvil</b>(8)</a> server:
|
||||
|
||||
<b>request=disconnect</b>
|
||||
<b>ident=</b><i>string</i>
|
||||
|
||||
This registers a disconnect event for the (service,
|
||||
client) combination specified with <b>ident</b>. The <a href="anvil.8.html"><b>anvil</b>(8)</a>
|
||||
server replies with:
|
||||
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server replies with:
|
||||
|
||||
<b>status=0</b>
|
||||
|
||||
<b>MESSAGE RATE LIMITING</b>
|
||||
When a remote client sends a message delivery request, a
|
||||
message rate limited server should send the following
|
||||
<b>MESSAGE RATE CONTROL</b>
|
||||
To register a message delivery request send the following
|
||||
request to the <a href="anvil.8.html"><b>anvil</b>(8)</a> server:
|
||||
|
||||
<b>request=message</b>
|
||||
<b>ident=</b><i>string</i>
|
||||
|
||||
This registers a message delivery request for the (ser-
|
||||
vice, client) combination specified with <b>ident</b>. The
|
||||
<a href="anvil.8.html"><b>anvil</b>(8)</a> server answers with the number of message deliv-
|
||||
ery requests per unit time for that (service, client) com-
|
||||
bination:
|
||||
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server answers with the number of message
|
||||
delivery requests per unit time for the (service, client)
|
||||
combination specified with <b>ident</b>:
|
||||
|
||||
<b>status=0</b>
|
||||
<b>rate=</b><i>number</i>
|
||||
|
||||
In order to prevent the <a href="anvil.8.html"><b>anvil</b>(8)</a> server from discarding
|
||||
client request rates too early or too late, a message rate
|
||||
limited service should also register connect/disconnect
|
||||
events.
|
||||
|
||||
<b>RECIPIENT RATE LIMITING</b>
|
||||
When a remote client sends a recipient address, a recipi-
|
||||
ent rate limited server should send the following request
|
||||
<b>RECIPIENT RATE CONTROL</b>
|
||||
To register a recipient request send the following request
|
||||
to the <a href="anvil.8.html"><b>anvil</b>(8)</a> server:
|
||||
|
||||
<b>request=recipient</b>
|
||||
<b>ident=</b><i>string</i>
|
||||
|
||||
This registers a recipient request for the (service,
|
||||
client) combination specified with <b>ident</b>. The <a href="anvil.8.html"><b>anvil</b>(8)</a>
|
||||
server answers with the number of recipient addresses per
|
||||
unit time for that (service, client) combination:
|
||||
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server answers with the number of recipient
|
||||
addresses per unit time for the (service, client) combina-
|
||||
tion specified with <b>ident</b>:
|
||||
|
||||
<b>status=0</b>
|
||||
<b>rate=</b><i>number</i>
|
||||
|
||||
In order to prevent the <a href="anvil.8.html"><b>anvil</b>(8)</a> server from discarding
|
||||
client request rates too early or too late, a recipient
|
||||
rate limited service should also register connect/discon-
|
||||
nect events.
|
||||
<b>TLS SESSION NEGOTIATION RATE CONTROL</b>
|
||||
The features described in this section are available with
|
||||
Postfix 2.3 and later.
|
||||
|
||||
To register a request for a new (i.e. not cached) TLS ses-
|
||||
sion send the following request to the <a href="anvil.8.html"><b>anvil</b>(8)</a> server:
|
||||
|
||||
<b>request=newtls</b>
|
||||
<b>ident=</b><i>string</i>
|
||||
|
||||
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server answers with the number of new TLS
|
||||
session requests per unit time for the (service, client)
|
||||
combination specified with <b>ident</b>:
|
||||
|
||||
<b>status=0</b>
|
||||
<b>rate=</b><i>number</i>
|
||||
|
||||
To retrieve new TLS session request rate information with-
|
||||
out updating the counter information, use:
|
||||
|
||||
<b>request=newtls_report</b>
|
||||
<b>ident=</b><i>string</i>
|
||||
|
||||
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server answers with the number of new TLS
|
||||
session requests per unit time for the (service, client)
|
||||
combination specified with <b>ident</b>.
|
||||
|
||||
<b>status=0</b>
|
||||
<b>rate=</b><i>number</i>
|
||||
|
||||
<b>SECURITY</b>
|
||||
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server does not talk to the network or to
|
||||
local users, and can run chrooted at fixed low privilege.
|
||||
|
||||
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server maintains an in-memory table with
|
||||
information about recent clients of a connection count (or
|
||||
rate) limited service. Although state is kept only tempo-
|
||||
rarily, this may require a lot of memory on systems that
|
||||
handle connections from many remote clients. To reduce
|
||||
memory usage, reduce the time unit over which state is
|
||||
kept.
|
||||
information about recent clients requests. No persistent
|
||||
state is kept because standard system library routines are
|
||||
not sufficiently robust for update-intensive applications.
|
||||
|
||||
Although the in-memory state is kept only temporarily,
|
||||
this may require a lot of memory on systems that handle
|
||||
connections from many remote clients. To reduce memory
|
||||
usage, reduce the time unit over which state is kept.
|
||||
|
||||
<b>DIAGNOSTICS</b>
|
||||
Problems and transactions are logged to <b>syslogd</b>(8).
|
||||
|
||||
Upon exit, and every <b><a href="postconf.5.html#anvil_status_update_time">anvil_status_update_time</a></b> seconds, the
|
||||
server logs the maximal count and rate values measured,
|
||||
together with (service, client) information and the time
|
||||
of day associated with those events. In order to avoid
|
||||
unnecessary overhead, no measurements are done for activ-
|
||||
server logs the maximal count and rate values measured,
|
||||
together with (service, client) information and the time
|
||||
of day associated with those events. In order to avoid
|
||||
unnecessary overhead, no measurements are done for activ-
|
||||
ity that isn't concurrency limited or rate limited.
|
||||
|
||||
<b>BUGS</b>
|
||||
Systems behind network address translating routers or
|
||||
Systems behind network address translating routers or
|
||||
proxies appear to have the same client address and can run
|
||||
into connection count and/or rate limits falsely.
|
||||
|
||||
In this preliminary implementation, a count (or rate) lim-
|
||||
ited server can have only one remote client at a time. If
|
||||
a server reports multiple simultaneous clients, all but
|
||||
ited server can have only one remote client at a time. If
|
||||
a server reports multiple simultaneous clients, all but
|
||||
the last reported client are ignored.
|
||||
|
||||
<b>CONFIGURATION PARAMETERS</b>
|
||||
Changes to <b>main.cf</b> are picked up automatically as <a href="anvil.8.html"><b>anvil</b>(8)</a>
|
||||
processes run for only a limited amount of time. Use the
|
||||
command "<b>postfix reload</b>" to speed up a change.
|
||||
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server automatically discards client request
|
||||
information after it expires. To prevent the <a href="anvil.8.html"><b>anvil</b>(8)</a>
|
||||
server from discarding client request rate information too
|
||||
early or too late, a rate limited service should always
|
||||
register connect/disconnect events even when it does not
|
||||
explicitly limit them.
|
||||
|
||||
The text below provides only a parameter summary. See
|
||||
<b>CONFIGURATION PARAMETERS</b>
|
||||
On low-traffic mail systems, changes to <b>main.cf</b> are picked
|
||||
up automatically as <a href="anvil.8.html"><b>anvil</b>(8)</a> processes run for only a lim-
|
||||
ited amount of time. On other mail systems, use the com-
|
||||
mand "<b>postfix reload</b>" to speed up a change.
|
||||
|
||||
The text below provides only a parameter summary. See
|
||||
<a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
|
||||
|
||||
<b><a href="postconf.5.html#anvil_rate_time_unit">anvil_rate_time_unit</a> (60s)</b>
|
||||
The time unit over which client connection rates
|
||||
The time unit over which client connection rates
|
||||
and other rates are calculated.
|
||||
|
||||
<b><a href="postconf.5.html#anvil_status_update_time">anvil_status_update_time</a> (600s)</b>
|
||||
How frequently the <a href="anvil.8.html"><b>anvil</b>(8)</a> connection and rate
|
||||
How frequently the <a href="anvil.8.html"><b>anvil</b>(8)</a> connection and rate
|
||||
limiting server logs peak usage information.
|
||||
|
||||
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
|
||||
The default location of the Postfix main.cf and
|
||||
The default location of the Postfix main.cf and
|
||||
master.cf configuration files.
|
||||
|
||||
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
|
||||
How much time a Postfix daemon process may take to
|
||||
handle a request before it is terminated by a
|
||||
How much time a Postfix daemon process may take to
|
||||
handle a request before it is terminated by a
|
||||
built-in watchdog timer.
|
||||
|
||||
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
|
||||
@ -165,28 +181,28 @@ ANVIL(8) ANVIL(8)
|
||||
over an internal communication channel.
|
||||
|
||||
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
|
||||
The maximum amount of time that an idle Postfix
|
||||
daemon process waits for the next service request
|
||||
The maximum amount of time that an idle Postfix
|
||||
daemon process waits for the next service request
|
||||
before exiting.
|
||||
|
||||
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
|
||||
The maximal number of connection requests before a
|
||||
The maximal number of connection requests before a
|
||||
Postfix daemon process terminates.
|
||||
|
||||
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
|
||||
The process ID of a Postfix command or daemon
|
||||
The process ID of a Postfix command or daemon
|
||||
process.
|
||||
|
||||
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
|
||||
The process name of a Postfix command or daemon
|
||||
The process name of a Postfix command or daemon
|
||||
process.
|
||||
|
||||
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
|
||||
The syslog facility of Postfix logging.
|
||||
|
||||
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
|
||||
The mail system name that is prepended to the
|
||||
process name in syslog records, so that "smtpd"
|
||||
The mail system name that is prepended to the
|
||||
process name in syslog records, so that "smtpd"
|
||||
becomes, for example, "postfix/smtpd".
|
||||
|
||||
<b>SEE ALSO</b>
|
||||
@ -198,7 +214,7 @@ ANVIL(8) ANVIL(8)
|
||||
<a href="TUNING_README.html">TUNING_README</a>, performance tuning
|
||||
|
||||
<b>LICENSE</b>
|
||||
The Secure Mailer license must be distributed with this
|
||||
The Secure Mailer license must be distributed with this
|
||||
software.
|
||||
|
||||
<b>HISTORY</b>
|
||||
|
@ -386,13 +386,6 @@ LOCAL(8) LOCAL(8)
|
||||
attempt; do not update the Delivered-To: address
|
||||
while expanding aliases or .forward files.
|
||||
|
||||
<b><a href="postconf.5.html#sticky_owner_alias">sticky_owner_alias</a> (yes)</b>
|
||||
When expanding a <a href="local.8.html"><b>local</b>(8)</a> alias that has an owner
|
||||
alias (see owner-<i>name</i> discussion in <a href="aliases.5.html"><b>aliases</b>(5)</a>),
|
||||
use the owner information even when the expansion
|
||||
invokes a subordinate alias that has no owner
|
||||
alias.
|
||||
|
||||
<b>DELIVERY METHOD CONTROLS</b>
|
||||
The precedence of <a href="local.8.html"><b>local</b>(8)</a> delivery methods from high to
|
||||
low is: aliases, .forward files, <a href="postconf.5.html#mailbox_transport">mailbox_transport</a>, <a href="postconf.5.html#mailbox_command_maps">mail</a>-
|
||||
|
@ -7205,6 +7205,47 @@ Example:
|
||||
</pre>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="smtpd_client_new_tls_session_rate_limit">smtpd_client_new_tls_session_rate_limit</a>
|
||||
(default: 0)</b></DT><DD>
|
||||
|
||||
<p>
|
||||
The maximal number of new (i.e., uncached) TLS sessions that a
|
||||
remote SMTP client is allowed to negotiate with this service per
|
||||
time unit. The time unit is specified with the <a href="postconf.5.html#anvil_rate_time_unit">anvil_rate_time_unit</a>
|
||||
configuration parameter.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
By default, a remote SMTP client can negotiate as many new TLS
|
||||
sessions per time unit as Postfix can accept.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To disable this feature, specify a limit of 0. Otherwise, specify
|
||||
a limit that is at least the per-client concurrent session limit,
|
||||
or else legitimate client sessions may be rejected.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
WARNING: The purpose of this feature is to limit abuse. It must
|
||||
not be used to regulate legitimate mail traffic.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This feature is available in Postfix 2.3 and later.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Example:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
<a href="postconf.5.html#smtpd_client_new_tls_session_rate_limit">smtpd_client_new_tls_session_rate_limit</a> = 100
|
||||
</pre>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="smtpd_client_recipient_rate_limit">smtpd_client_recipient_rate_limit</a>
|
||||
@ -7924,6 +7965,18 @@ null sender address.
|
||||
</p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="smtpd_peername_lookup">smtpd_peername_lookup</a>
|
||||
(default: yes)</b></DT><DD>
|
||||
|
||||
<p> Attempt to look up the SMTP client hostname, and verify that
|
||||
the name matches the client IP address. A client name is set to
|
||||
"unknown" when it cannot be looked up or verified, or when name
|
||||
lookup is disabled. Turning off name lookup reduces delays due to
|
||||
DNS lookup and increases the maximal inbound delivery rate. </p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="smtpd_policy_service_max_idle">smtpd_policy_service_max_idle</a>
|
||||
@ -9149,22 +9202,6 @@ The default time unit is s (seconds).
|
||||
</p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="sticky_owner_alias">sticky_owner_alias</a>
|
||||
(default: yes)</b></DT><DD>
|
||||
|
||||
<p> When expanding a <a href="local.8.html">local(8)</a> alias that has an owner alias (see
|
||||
owner-<i>name</i> discussion in <a href="aliases.5.html">aliases(5)</a>), use the owner information
|
||||
even when the expansion invokes a subordinate alias that has no
|
||||
owner alias. </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.3 and later. With older
|
||||
Postfix releases, the behavior is as if this parameter is set to
|
||||
"no". The old setting provides poorer error reporting with nested
|
||||
aliases that only have an owner alias at the top level. </p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="strict_7bit_headers">strict_7bit_headers</a>
|
||||
|
@ -548,6 +548,12 @@ SMTPD(8) SMTPD(8)
|
||||
server command history before it is flushed upon
|
||||
receipt of EHLO, RSET, or end of DATA.
|
||||
|
||||
Available in Postfix version 2.3 and later:
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_peername_lookup">smtpd_peername_lookup</a> (yes)</b>
|
||||
Attempt to look up the SMTP client hostname, and
|
||||
verify that the name matches the client IP address.
|
||||
|
||||
The per SMTP client connection count and request rate lim-
|
||||
its are implemented in co-operation with the <a href="anvil.8.html"><b>anvil</b>(8)</a> ser-
|
||||
vice, and are available in Postfix version 2.2 and later.
|
||||
@ -577,6 +583,13 @@ SMTPD(8) SMTPD(8)
|
||||
Clients that are excluded from connection count,
|
||||
connection rate, or SMTP request rate restrictions.
|
||||
|
||||
Available in Postfix version 2.3 and later:
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_client_new_tls_session_rate_limit">smtpd_client_new_tls_session_rate_limit</a> (0)</b>
|
||||
The maximal number of new (i.e., uncached) TLS ses-
|
||||
sions that any client is allowed to negotiate with
|
||||
this service per time unit.
|
||||
|
||||
<b>TARPIT CONTROLS</b>
|
||||
When a remote SMTP client makes errors, the Postfix SMTP
|
||||
server can insert delays before responding. This can help
|
||||
|
@ -4070,6 +4070,33 @@ smtpd_client_message_rate_limit = 1000
|
||||
.fi
|
||||
.ad
|
||||
.ft R
|
||||
.SH smtpd_client_new_tls_session_rate_limit (default: 0)
|
||||
The maximal number of new (i.e., uncached) TLS sessions that a
|
||||
remote SMTP client is allowed to negotiate with this service per
|
||||
time unit. The time unit is specified with the anvil_rate_time_unit
|
||||
configuration parameter.
|
||||
.PP
|
||||
By default, a remote SMTP client can negotiate as many new TLS
|
||||
sessions per time unit as Postfix can accept.
|
||||
.PP
|
||||
To disable this feature, specify a limit of 0. Otherwise, specify
|
||||
a limit that is at least the per-client concurrent session limit,
|
||||
or else legitimate client sessions may be rejected.
|
||||
.PP
|
||||
WARNING: The purpose of this feature is to limit abuse. It must
|
||||
not be used to regulate legitimate mail traffic.
|
||||
.PP
|
||||
This feature is available in Postfix 2.3 and later.
|
||||
.PP
|
||||
Example:
|
||||
.PP
|
||||
.nf
|
||||
.na
|
||||
.ft C
|
||||
smtpd_client_new_tls_session_rate_limit = 100
|
||||
.fi
|
||||
.ad
|
||||
.ft R
|
||||
.SH smtpd_client_recipient_rate_limit (default: 0)
|
||||
The maximal number of recipient addresses that any client is allowed
|
||||
to send to this service per time unit, regardless of whether or not
|
||||
@ -4540,6 +4567,12 @@ This list overrides any commands built into the Postfix SMTP server.
|
||||
.SH smtpd_null_access_lookup_key (default: <>)
|
||||
The lookup key to be used in SMTP \fBaccess\fR(5) tables instead of the
|
||||
null sender address.
|
||||
.SH smtpd_peername_lookup (default: yes)
|
||||
Attempt to look up the SMTP client hostname, and verify that
|
||||
the name matches the client IP address. A client name is set to
|
||||
"unknown" when it cannot be looked up or verified, or when name
|
||||
lookup is disabled. Turning off name lookup reduces delays due to
|
||||
DNS lookup and increases the maximal inbound delivery rate.
|
||||
.SH smtpd_policy_service_max_idle (default: 300s)
|
||||
The time after which an idle SMTPD policy service connection is
|
||||
closed.
|
||||
@ -5349,16 +5382,6 @@ This is used for delivery to file or mailbox.
|
||||
.PP
|
||||
Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
|
||||
The default time unit is s (seconds).
|
||||
.SH sticky_owner_alias (default: yes)
|
||||
When expanding a \fBlocal\fR(8) alias that has an owner alias (see
|
||||
owner-\fIname\fR discussion in \fBaliases\fR(5)), use the owner information
|
||||
even when the expansion invokes a subordinate alias that has no
|
||||
owner alias.
|
||||
.PP
|
||||
This feature is available in Postfix 2.3 and later. With older
|
||||
Postfix releases, the behavior is as if this parameter is set to
|
||||
"no". The old setting provides poorer error reporting with nested
|
||||
aliases that only have an owner alias at the top level.
|
||||
.SH strict_7bit_headers (default: no)
|
||||
Reject mail with 8-bit text in message headers. This blocks mail
|
||||
from poorly written applications.
|
||||
|
@ -12,23 +12,25 @@ Postfix session count and request rate control
|
||||
.SH DESCRIPTION
|
||||
.ad
|
||||
.fi
|
||||
The Postfix \fBanvil\fR(8) server maintains short-term statistics
|
||||
to defend against clients that hammer a server with either too
|
||||
many simultaneous sessions, or with too many successive requests
|
||||
within a configurable time interval.
|
||||
This server is designed to run under control by the Postfix
|
||||
\fBmaster\fR(8) server.
|
||||
The Postfix \fBanvil\fR(8) server maintains statistics about
|
||||
client connection counts or client request rates. This
|
||||
information can be used to defend against clients that
|
||||
hammer a server with either too many simultaneous sessions,
|
||||
or with too many successive requests within a configurable
|
||||
time interval. This server is designed to run under control
|
||||
by the Postfix \fBmaster\fR(8) server.
|
||||
|
||||
The \fBanvil\fR(8) server maintains no persistent database. Standard
|
||||
library utilities do not meet Postfix performance and robustness
|
||||
requirements.
|
||||
.SH "CONNECTION COUNT/RATE LIMITING"
|
||||
In the following text, \fBident\fR specifies a (service,
|
||||
client) combination. The exact syntax of that information
|
||||
is application-dependent; the \fBanvil\fR(8) server does
|
||||
not care.
|
||||
.SH "CONNECTION COUNT/RATE CONTROL"
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
When a remote client connects, a connection count (or rate) limited
|
||||
server should send the following request to the \fBanvil\fR(8) server:
|
||||
To register a new connection send the following request to
|
||||
the \fBanvil\fR(8) server:
|
||||
.PP
|
||||
.in +4
|
||||
\fBrequest=connect\fR
|
||||
@ -36,11 +38,10 @@ server should send the following request to the \fBanvil\fR(8) server:
|
||||
\fBident=\fIstring\fR
|
||||
.in
|
||||
.PP
|
||||
This registers a new connection for the (service, client)
|
||||
combination specified with \fBident\fR. The \fBanvil\fR(8) server
|
||||
answers with the number of simultaneous connections and the
|
||||
number of connections per unit time for that (service, client)
|
||||
combination:
|
||||
The \fBanvil\fR(8) server answers with the number of
|
||||
simultaneous connections and the number of connections per
|
||||
unit time for the (service, client) combination specified
|
||||
with \fBident\fR:
|
||||
.PP
|
||||
.in +4
|
||||
\fBstatus=0\fR
|
||||
@ -50,13 +51,8 @@ combination:
|
||||
\fBrate=\fInumber\fR
|
||||
.in
|
||||
.PP
|
||||
The \fBrate\fR is computed as the number of connections
|
||||
that were registered in the current "time unit" interval.
|
||||
It is left up to the server to decide if the remote client
|
||||
exceeds the connection count (or rate) limit.
|
||||
.PP
|
||||
When a remote client disconnects, a connection count (or rate) limited
|
||||
server should send the following request to the \fBanvil\fR(8) server:
|
||||
To register a disconnect event send the following request
|
||||
to the \fBanvil\fR(8) server:
|
||||
.PP
|
||||
.in +4
|
||||
\fBrequest=disconnect\fR
|
||||
@ -64,19 +60,16 @@ server should send the following request to the \fBanvil\fR(8) server:
|
||||
\fBident=\fIstring\fR
|
||||
.in
|
||||
.PP
|
||||
This registers a disconnect event for the (service, client)
|
||||
combination specified with \fBident\fR. The \fBanvil\fR(8)
|
||||
server replies with:
|
||||
The \fBanvil\fR(8) server replies with:
|
||||
.PP
|
||||
.ti +4
|
||||
\fBstatus=0\fR
|
||||
.SH "MESSAGE RATE LIMITING"
|
||||
.SH "MESSAGE RATE CONTROL"
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
When a remote client sends a message delivery request, a
|
||||
message rate limited server should send the following
|
||||
To register a message delivery request send the following
|
||||
request to the \fBanvil\fR(8) server:
|
||||
.PP
|
||||
.in +4
|
||||
@ -85,28 +78,22 @@ request to the \fBanvil\fR(8) server:
|
||||
\fBident=\fIstring\fR
|
||||
.in
|
||||
.PP
|
||||
This registers a message delivery request for the (service, client)
|
||||
combination specified with \fBident\fR. The \fBanvil\fR(8) server
|
||||
answers with the number of message delivery requests per unit time
|
||||
for that (service, client) combination:
|
||||
The \fBanvil\fR(8) server answers with the number of message
|
||||
delivery requests per unit time for the (service, client)
|
||||
combination specified with \fBident\fR:
|
||||
.PP
|
||||
.in +4
|
||||
\fBstatus=0\fR
|
||||
.br
|
||||
\fBrate=\fInumber\fR
|
||||
.in
|
||||
.PP
|
||||
In order to prevent the \fBanvil\fR(8) server from discarding client
|
||||
request rates too early or too late, a message rate limited
|
||||
service should also register connect/disconnect events.
|
||||
.SH "RECIPIENT RATE LIMITING"
|
||||
.SH "RECIPIENT RATE CONTROL"
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
When a remote client sends a recipient address, a recipient
|
||||
rate limited server should send the following request to
|
||||
the \fBanvil\fR(8) server:
|
||||
To register a recipient request send the following request
|
||||
to the \fBanvil\fR(8) server:
|
||||
.PP
|
||||
.in +4
|
||||
\fBrequest=recipient\fR
|
||||
@ -114,10 +101,35 @@ the \fBanvil\fR(8) server:
|
||||
\fBident=\fIstring\fR
|
||||
.in
|
||||
.PP
|
||||
This registers a recipient request for the (service, client)
|
||||
combination specified with \fBident\fR. The \fBanvil\fR(8) server
|
||||
answers with the number of recipient addresses per unit time
|
||||
for that (service, client) combination:
|
||||
The \fBanvil\fR(8) server answers with the number of recipient
|
||||
addresses per unit time for the (service, client) combination
|
||||
specified with \fBident\fR:
|
||||
.PP
|
||||
.in +4
|
||||
\fBstatus=0\fR
|
||||
.br
|
||||
\fBrate=\fInumber\fR
|
||||
.in
|
||||
.SH "TLS SESSION NEGOTIATION RATE CONTROL"
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
The features described in this section are available with
|
||||
Postfix 2.3 and later.
|
||||
|
||||
To register a request for a new (i.e. not cached) TLS session
|
||||
send the following request to the \fBanvil\fR(8) server:
|
||||
.PP
|
||||
.in +4
|
||||
\fBrequest=newtls\fR
|
||||
.br
|
||||
\fBident=\fIstring\fR
|
||||
.in
|
||||
.PP
|
||||
The \fBanvil\fR(8) server answers with the number of new
|
||||
TLS session requests per unit time for the (service, client)
|
||||
combination specified with \fBident\fR:
|
||||
.PP
|
||||
.in +4
|
||||
\fBstatus=0\fR
|
||||
@ -125,9 +137,24 @@ for that (service, client) combination:
|
||||
\fBrate=\fInumber\fR
|
||||
.in
|
||||
.PP
|
||||
In order to prevent the \fBanvil\fR(8) server from discarding client
|
||||
request rates too early or too late, a recipient rate limited
|
||||
service should also register connect/disconnect events.
|
||||
To retrieve new TLS session request rate information without
|
||||
updating the counter information, use:
|
||||
.PP
|
||||
.in +4
|
||||
\fBrequest=newtls_report\fR
|
||||
.br
|
||||
\fBident=\fIstring\fR
|
||||
.in
|
||||
.PP
|
||||
The \fBanvil\fR(8) server answers with the number of new
|
||||
TLS session requests per unit time for the (service, client)
|
||||
combination specified with \fBident\fR.
|
||||
.PP
|
||||
.in +4
|
||||
\fBstatus=0\fR
|
||||
.br
|
||||
\fBrate=\fInumber\fR
|
||||
.in
|
||||
.SH "SECURITY"
|
||||
.na
|
||||
.nf
|
||||
@ -136,12 +163,15 @@ service should also register connect/disconnect events.
|
||||
The \fBanvil\fR(8) server does not talk to the network or to local
|
||||
users, and can run chrooted at fixed low privilege.
|
||||
|
||||
The \fBanvil\fR(8) server maintains an in-memory table with information
|
||||
about recent clients of a connection count (or rate) limited service.
|
||||
Although state is kept only temporarily, this may require a lot of
|
||||
memory on systems that handle connections from many remote clients.
|
||||
To reduce memory usage, reduce the time unit over which state
|
||||
is kept.
|
||||
The \fBanvil\fR(8) server maintains an in-memory table with
|
||||
information about recent clients requests. No persistent
|
||||
state is kept because standard system library routines are
|
||||
not sufficiently robust for update-intensive applications.
|
||||
|
||||
Although the in-memory state is kept only temporarily, this
|
||||
may require a lot of memory on systems that handle connections
|
||||
from many remote clients. To reduce memory usage, reduce
|
||||
the time unit over which state is kept.
|
||||
.SH DIAGNOSTICS
|
||||
.ad
|
||||
.fi
|
||||
@ -165,14 +195,22 @@ In this preliminary implementation, a count (or rate) limited server
|
||||
can have only one remote client at a time. If a server reports
|
||||
multiple simultaneous clients, all but the last reported client
|
||||
are ignored.
|
||||
|
||||
The \fBanvil\fR(8) server automatically discards client
|
||||
request information after it expires. To prevent the
|
||||
\fBanvil\fR(8) server from discarding client request rate
|
||||
information too early or too late, a rate limited service
|
||||
should always register connect/disconnect events even when
|
||||
it does not explicitly limit them.
|
||||
.SH "CONFIGURATION PARAMETERS"
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
Changes to \fBmain.cf\fR are picked up automatically as \fBanvil\fR(8)
|
||||
processes run for only a limited amount of time. Use the command
|
||||
"\fBpostfix reload\fR" to speed up a change.
|
||||
On low-traffic mail systems, changes to \fBmain.cf\fR are
|
||||
picked up automatically as \fBanvil\fR(8) processes run for
|
||||
only a limited amount of time. On other mail systems, use
|
||||
the command "\fBpostfix reload\fR" to speed up a change.
|
||||
|
||||
The text below provides only a parameter summary. See
|
||||
\fBpostconf\fR(5) for more details including examples.
|
||||
|
@ -399,11 +399,6 @@ Update the \fBlocal\fR(8) delivery agent's idea of the Delivered-To:
|
||||
address (see prepend_delivered_header) only once, at the start of
|
||||
a delivery attempt; do not update the Delivered-To: address while
|
||||
expanding aliases or .forward files.
|
||||
.IP "\fBsticky_owner_alias (yes)\fR"
|
||||
When expanding a \fBlocal\fR(8) alias that has an owner alias (see
|
||||
owner-\fIname\fR discussion in \fBaliases\fR(5)), use the owner information
|
||||
even when the expansion invokes a subordinate alias that has no
|
||||
owner alias.
|
||||
.SH "DELIVERY METHOD CONTROLS"
|
||||
.na
|
||||
.nf
|
||||
|
@ -453,6 +453,11 @@ receiving a remote SMTP client request.
|
||||
The maximal number of lines in the Postfix SMTP server command history
|
||||
before it is flushed upon receipt of EHLO, RSET, or end of DATA.
|
||||
.PP
|
||||
Available in Postfix version 2.3 and later:
|
||||
.IP "\fBsmtpd_peername_lookup (yes)\fR"
|
||||
Attempt to look up the SMTP client hostname, and verify that
|
||||
the name matches the client IP address.
|
||||
.PP
|
||||
The per SMTP client connection count and request rate limits are
|
||||
implemented in co-operation with the \fBanvil\fR(8) service, and
|
||||
are available in Postfix version 2.2 and later.
|
||||
@ -473,6 +478,11 @@ Postfix actually accepts those recipients.
|
||||
.IP "\fBsmtpd_client_event_limit_exceptions ($mynetworks)\fR"
|
||||
Clients that are excluded from connection count, connection rate,
|
||||
or SMTP request rate restrictions.
|
||||
.PP
|
||||
Available in Postfix version 2.3 and later:
|
||||
.IP "\fBsmtpd_client_new_tls_session_rate_limit (0)\fR"
|
||||
The maximal number of new (i.e., uncached) TLS sessions that any
|
||||
client is allowed to negotiate with this service per time unit.
|
||||
.SH "TARPIT CONTROLS"
|
||||
.na
|
||||
.nf
|
||||
|
@ -372,6 +372,7 @@ while (<>) {
|
||||
s;\bsmtpd_client_connection_rate_limit\b;<a href="postconf.5.html#smtpd_client_connection_rate_limit">$&</a>;g;
|
||||
s;\bsmtpd_client_message_rate_limit\b;<a href="postconf.5.html#smtpd_client_message_rate_limit">$&</a>;g;
|
||||
s;\bsmtpd_client_recipient_rate_limit\b;<a href="postconf.5.html#smtpd_client_recipient_rate_limit">$&</a>;g;
|
||||
s;\bsmtpd_client_new_tls_session_rate_limit\b;<a href="postconf.5.html#smtpd_client_new_tls_session_rate_limit">$&</a>;g;
|
||||
s;\bsmtpd_client_restrictions\b;<a href="postconf.5.html#smtpd_client_restrictions">$&</a>;g;
|
||||
s;\bsmtpd_data_restrictions\b;<a href="postconf.5.html#smtpd_data_restrictions">$&</a>;g;
|
||||
s;\bsmtpd_delay_reject\b;<a href="postconf.5.html#smtpd_delay_reject">$&</a>;g;
|
||||
@ -390,6 +391,7 @@ while (<>) {
|
||||
s;\bsmtpd_noop_commands\b;<a href="postconf.5.html#smtpd_noop_commands">$&</a>;g;
|
||||
s;\bsmtpd_null_access_lookup_key\b;<a href="postconf.5.html#smtpd_null_access_lookup_key">$&</a>;g;
|
||||
s;\bsmtpd_recipient_overshoot_limit\b;<a href="postconf.5.html#smtpd_recipient_overshoot_limit">$&</a>;g;
|
||||
s;\bsmtpd_peername_lookup\b;<a href="postconf.5.html#smtpd_peername_lookup">$&</a>;g;
|
||||
s;\bsmtpd_policy_service_max_idle\b;<a href="postconf.5.html#smtpd_policy_service_max_idle">$&</a>;g;
|
||||
s;\bsmtpd_policy_service_max_ttl\b;<a href="postconf.5.html#smtpd_policy_service_max_ttl">$&</a>;g;
|
||||
s;\bsmtpd_policy_service_timeout\b;<a href="postconf.5.html#smtpd_policy_service_timeout">$&</a>;g;
|
||||
@ -502,7 +504,6 @@ while (<>) {
|
||||
s;\btls_ran[-</Bb>]*\n* *[<Bb>]*dom_source\b;<a href="postconf.5.html#tls_random_source">$&</a>;g;
|
||||
|
||||
s;\bfrozen_delivered_to\b;<a href="postconf.5.html#frozen_delivered_to">$&</a>;g;
|
||||
s;\bsticky_owner_alias\b;<a href="postconf.5.html#sticky_owner_alias">$&</a>;g;
|
||||
|
||||
# Undo hyperlinks of manual pages with the same name as parameters.
|
||||
|
||||
|
@ -36,7 +36,8 @@ the Postfix source code, in the directory examples/smtpd-policy.
|
||||
to Postfix. It's much easier to develop a new feature in few lines
|
||||
of Perl, than trying to do the same in C code. The difference in
|
||||
performance will be unnoticeable except in the most demanding
|
||||
environments. </p>
|
||||
environments. On active systems a policy daemon process is used
|
||||
multiple times, for up to 100 incoming SMTP connections. </p>
|
||||
|
||||
<p> This document covers the following topics: </p>
|
||||
|
||||
|
@ -4399,6 +4399,43 @@ Example:
|
||||
smtpd_client_recipient_rate_limit = 1000
|
||||
</pre>
|
||||
|
||||
%PARAM smtpd_client_new_tls_session_rate_limit 0
|
||||
|
||||
<p>
|
||||
The maximal number of new (i.e., uncached) TLS sessions that a
|
||||
remote SMTP client is allowed to negotiate with this service per
|
||||
time unit. The time unit is specified with the anvil_rate_time_unit
|
||||
configuration parameter.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
By default, a remote SMTP client can negotiate as many new TLS
|
||||
sessions per time unit as Postfix can accept.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To disable this feature, specify a limit of 0. Otherwise, specify
|
||||
a limit that is at least the per-client concurrent session limit,
|
||||
or else legitimate client sessions may be rejected.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
WARNING: The purpose of this feature is to limit abuse. It must
|
||||
not be used to regulate legitimate mail traffic.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This feature is available in Postfix 2.3 and later.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Example:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
smtpd_client_new_tls_session_rate_limit = 100
|
||||
</pre>
|
||||
|
||||
%PARAM smtpd_client_restrictions
|
||||
|
||||
<p>
|
||||
@ -8542,18 +8579,6 @@ message_strip_characters = \0
|
||||
|
||||
<p> This feature is available in Postfix 2.3 and later. </p>
|
||||
|
||||
%PARAM sticky_owner_alias yes
|
||||
|
||||
<p> When expanding a local(8) alias that has an owner alias (see
|
||||
owner-<i>name</i> discussion in aliases(5)), use the owner information
|
||||
even when the expansion invokes a subordinate alias that has no
|
||||
owner alias. </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.3 and later. With older
|
||||
Postfix releases, the behavior is as if this parameter is set to
|
||||
"no". The old setting provides poorer error reporting with nested
|
||||
aliases that only have an owner alias at the top level. </p>
|
||||
|
||||
%PARAM frozen_delivered_to yes
|
||||
|
||||
<p> Update the local(8) delivery agent's idea of the Delivered-To:
|
||||
@ -8567,3 +8592,11 @@ Postfix releases, the behavior is as if this parameter is set to
|
||||
or .forward files. When an alias or .forward file changes the
|
||||
Delivered-To: address, it ties up one queue file and one cleanup
|
||||
process instance while mail is being forwarded. </p>
|
||||
|
||||
%PARAM smtpd_peername_lookup yes
|
||||
|
||||
<p> Attempt to look up the SMTP client hostname, and verify that
|
||||
the name matches the client IP address. A client name is set to
|
||||
"unknown" when it cannot be looked up or verified, or when name
|
||||
lookup is disabled. Turning off name lookup reduces delays due to
|
||||
DNS lookup and increases the maximal inbound delivery rate. </p>
|
||||
|
@ -6,21 +6,23 @@
|
||||
/* SYNOPSIS
|
||||
/* \fBanvil\fR [generic Postfix daemon options]
|
||||
/* DESCRIPTION
|
||||
/* The Postfix \fBanvil\fR(8) server maintains short-term statistics
|
||||
/* to defend against clients that hammer a server with either too
|
||||
/* many simultaneous sessions, or with too many successive requests
|
||||
/* within a configurable time interval.
|
||||
/* This server is designed to run under control by the Postfix
|
||||
/* \fBmaster\fR(8) server.
|
||||
/* The Postfix \fBanvil\fR(8) server maintains statistics about
|
||||
/* client connection counts or client request rates. This
|
||||
/* information can be used to defend against clients that
|
||||
/* hammer a server with either too many simultaneous sessions,
|
||||
/* or with too many successive requests within a configurable
|
||||
/* time interval. This server is designed to run under control
|
||||
/* by the Postfix \fBmaster\fR(8) server.
|
||||
/*
|
||||
/* The \fBanvil\fR(8) server maintains no persistent database. Standard
|
||||
/* library utilities do not meet Postfix performance and robustness
|
||||
/* requirements.
|
||||
/* CONNECTION COUNT/RATE LIMITING
|
||||
/* In the following text, \fBident\fR specifies a (service,
|
||||
/* client) combination. The exact syntax of that information
|
||||
/* is application-dependent; the \fBanvil\fR(8) server does
|
||||
/* not care.
|
||||
/* CONNECTION COUNT/RATE CONTROL
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* When a remote client connects, a connection count (or rate) limited
|
||||
/* server should send the following request to the \fBanvil\fR(8) server:
|
||||
/* To register a new connection send the following request to
|
||||
/* the \fBanvil\fR(8) server:
|
||||
/* .PP
|
||||
/* .in +4
|
||||
/* \fBrequest=connect\fR
|
||||
@ -28,11 +30,10 @@
|
||||
/* \fBident=\fIstring\fR
|
||||
/* .in
|
||||
/* .PP
|
||||
/* This registers a new connection for the (service, client)
|
||||
/* combination specified with \fBident\fR. The \fBanvil\fR(8) server
|
||||
/* answers with the number of simultaneous connections and the
|
||||
/* number of connections per unit time for that (service, client)
|
||||
/* combination:
|
||||
/* The \fBanvil\fR(8) server answers with the number of
|
||||
/* simultaneous connections and the number of connections per
|
||||
/* unit time for the (service, client) combination specified
|
||||
/* with \fBident\fR:
|
||||
/* .PP
|
||||
/* .in +4
|
||||
/* \fBstatus=0\fR
|
||||
@ -42,13 +43,8 @@
|
||||
/* \fBrate=\fInumber\fR
|
||||
/* .in
|
||||
/* .PP
|
||||
/* The \fBrate\fR is computed as the number of connections
|
||||
/* that were registered in the current "time unit" interval.
|
||||
/* It is left up to the server to decide if the remote client
|
||||
/* exceeds the connection count (or rate) limit.
|
||||
/* .PP
|
||||
/* When a remote client disconnects, a connection count (or rate) limited
|
||||
/* server should send the following request to the \fBanvil\fR(8) server:
|
||||
/* To register a disconnect event send the following request
|
||||
/* to the \fBanvil\fR(8) server:
|
||||
/* .PP
|
||||
/* .in +4
|
||||
/* \fBrequest=disconnect\fR
|
||||
@ -56,17 +52,14 @@
|
||||
/* \fBident=\fIstring\fR
|
||||
/* .in
|
||||
/* .PP
|
||||
/* This registers a disconnect event for the (service, client)
|
||||
/* combination specified with \fBident\fR. The \fBanvil\fR(8)
|
||||
/* server replies with:
|
||||
/* The \fBanvil\fR(8) server replies with:
|
||||
/* .PP
|
||||
/* .ti +4
|
||||
/* \fBstatus=0\fR
|
||||
/* MESSAGE RATE LIMITING
|
||||
/* MESSAGE RATE CONTROL
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* When a remote client sends a message delivery request, a
|
||||
/* message rate limited server should send the following
|
||||
/* To register a message delivery request send the following
|
||||
/* request to the \fBanvil\fR(8) server:
|
||||
/* .PP
|
||||
/* .in +4
|
||||
@ -75,26 +68,20 @@
|
||||
/* \fBident=\fIstring\fR
|
||||
/* .in
|
||||
/* .PP
|
||||
/* This registers a message delivery request for the (service, client)
|
||||
/* combination specified with \fBident\fR. The \fBanvil\fR(8) server
|
||||
/* answers with the number of message delivery requests per unit time
|
||||
/* for that (service, client) combination:
|
||||
/* The \fBanvil\fR(8) server answers with the number of message
|
||||
/* delivery requests per unit time for the (service, client)
|
||||
/* combination specified with \fBident\fR:
|
||||
/* .PP
|
||||
/* .in +4
|
||||
/* \fBstatus=0\fR
|
||||
/* .br
|
||||
/* \fBrate=\fInumber\fR
|
||||
/* .in
|
||||
/* .PP
|
||||
/* In order to prevent the \fBanvil\fR(8) server from discarding client
|
||||
/* request rates too early or too late, a message rate limited
|
||||
/* service should also register connect/disconnect events.
|
||||
/* RECIPIENT RATE LIMITING
|
||||
/* RECIPIENT RATE CONTROL
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* When a remote client sends a recipient address, a recipient
|
||||
/* rate limited server should send the following request to
|
||||
/* the \fBanvil\fR(8) server:
|
||||
/* To register a recipient request send the following request
|
||||
/* to the \fBanvil\fR(8) server:
|
||||
/* .PP
|
||||
/* .in +4
|
||||
/* \fBrequest=recipient\fR
|
||||
@ -102,10 +89,33 @@
|
||||
/* \fBident=\fIstring\fR
|
||||
/* .in
|
||||
/* .PP
|
||||
/* This registers a recipient request for the (service, client)
|
||||
/* combination specified with \fBident\fR. The \fBanvil\fR(8) server
|
||||
/* answers with the number of recipient addresses per unit time
|
||||
/* for that (service, client) combination:
|
||||
/* The \fBanvil\fR(8) server answers with the number of recipient
|
||||
/* addresses per unit time for the (service, client) combination
|
||||
/* specified with \fBident\fR:
|
||||
/* .PP
|
||||
/* .in +4
|
||||
/* \fBstatus=0\fR
|
||||
/* .br
|
||||
/* \fBrate=\fInumber\fR
|
||||
/* .in
|
||||
/* TLS SESSION NEGOTIATION RATE CONTROL
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The features described in this section are available with
|
||||
/* Postfix 2.3 and later.
|
||||
/*
|
||||
/* To register a request for a new (i.e. not cached) TLS session
|
||||
/* send the following request to the \fBanvil\fR(8) server:
|
||||
/* .PP
|
||||
/* .in +4
|
||||
/* \fBrequest=newtls\fR
|
||||
/* .br
|
||||
/* \fBident=\fIstring\fR
|
||||
/* .in
|
||||
/* .PP
|
||||
/* The \fBanvil\fR(8) server answers with the number of new
|
||||
/* TLS session requests per unit time for the (service, client)
|
||||
/* combination specified with \fBident\fR:
|
||||
/* .PP
|
||||
/* .in +4
|
||||
/* \fBstatus=0\fR
|
||||
@ -113,21 +123,39 @@
|
||||
/* \fBrate=\fInumber\fR
|
||||
/* .in
|
||||
/* .PP
|
||||
/* In order to prevent the \fBanvil\fR(8) server from discarding client
|
||||
/* request rates too early or too late, a recipient rate limited
|
||||
/* service should also register connect/disconnect events.
|
||||
/* To retrieve new TLS session request rate information without
|
||||
/* updating the counter information, use:
|
||||
/* .PP
|
||||
/* .in +4
|
||||
/* \fBrequest=newtls_report\fR
|
||||
/* .br
|
||||
/* \fBident=\fIstring\fR
|
||||
/* .in
|
||||
/* .PP
|
||||
/* The \fBanvil\fR(8) server answers with the number of new
|
||||
/* TLS session requests per unit time for the (service, client)
|
||||
/* combination specified with \fBident\fR.
|
||||
/* .PP
|
||||
/* .in +4
|
||||
/* \fBstatus=0\fR
|
||||
/* .br
|
||||
/* \fBrate=\fInumber\fR
|
||||
/* .in
|
||||
/* SECURITY
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The \fBanvil\fR(8) server does not talk to the network or to local
|
||||
/* users, and can run chrooted at fixed low privilege.
|
||||
/*
|
||||
/* The \fBanvil\fR(8) server maintains an in-memory table with information
|
||||
/* about recent clients of a connection count (or rate) limited service.
|
||||
/* Although state is kept only temporarily, this may require a lot of
|
||||
/* memory on systems that handle connections from many remote clients.
|
||||
/* To reduce memory usage, reduce the time unit over which state
|
||||
/* is kept.
|
||||
/* The \fBanvil\fR(8) server maintains an in-memory table with
|
||||
/* information about recent clients requests. No persistent
|
||||
/* state is kept because standard system library routines are
|
||||
/* not sufficiently robust for update-intensive applications.
|
||||
/*
|
||||
/* Although the in-memory state is kept only temporarily, this
|
||||
/* may require a lot of memory on systems that handle connections
|
||||
/* from many remote clients. To reduce memory usage, reduce
|
||||
/* the time unit over which state is kept.
|
||||
/* DIAGNOSTICS
|
||||
/* Problems and transactions are logged to \fBsyslogd\fR(8).
|
||||
/*
|
||||
@ -147,12 +175,20 @@
|
||||
/* can have only one remote client at a time. If a server reports
|
||||
/* multiple simultaneous clients, all but the last reported client
|
||||
/* are ignored.
|
||||
/*
|
||||
/* The \fBanvil\fR(8) server automatically discards client
|
||||
/* request information after it expires. To prevent the
|
||||
/* \fBanvil\fR(8) server from discarding client request rate
|
||||
/* information too early or too late, a rate limited service
|
||||
/* should always register connect/disconnect events even when
|
||||
/* it does not explicitly limit them.
|
||||
/* CONFIGURATION PARAMETERS
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* Changes to \fBmain.cf\fR are picked up automatically as \fBanvil\fR(8)
|
||||
/* processes run for only a limited amount of time. Use the command
|
||||
/* "\fBpostfix reload\fR" to speed up a change.
|
||||
/* On low-traffic mail systems, changes to \fBmain.cf\fR are
|
||||
/* picked up automatically as \fBanvil\fR(8) processes run for
|
||||
/* only a limited amount of time. On other mail systems, use
|
||||
/* the command "\fBpostfix reload\fR" to speed up a change.
|
||||
/*
|
||||
/* The text below provides only a parameter summary. See
|
||||
/* \fBpostconf\fR(5) for more details including examples.
|
||||
@ -252,28 +288,53 @@ static HTABLE *anvil_remote_map; /* indexed by service+ remote client */
|
||||
* Absent a real-time query interface, these are logged at process exit time
|
||||
* and at regular intervals.
|
||||
*/
|
||||
static int max_count;
|
||||
static char *max_count_user;
|
||||
static time_t max_count_time;
|
||||
typedef struct {
|
||||
int value; /* peak value */
|
||||
char *ident; /* lookup key */
|
||||
time_t when; /* time of peak value */
|
||||
} ANVIL_MAX;
|
||||
|
||||
static int max_rate;
|
||||
static char *max_rate_user;
|
||||
static time_t max_rate_time;
|
||||
static ANVIL_MAX max_conn_count; /* peak connection count */
|
||||
static ANVIL_MAX max_conn_rate; /* peak connection rate */
|
||||
static ANVIL_MAX max_mail_rate; /* peak message rate */
|
||||
static ANVIL_MAX max_rcpt_rate; /* peak recipient rate */
|
||||
static ANVIL_MAX max_ntls_rate; /* peak new TLS session rate */
|
||||
|
||||
static int max_mail;
|
||||
static char *max_mail_user;
|
||||
static time_t max_mail_time;
|
||||
static int max_cache_size; /* peak cache size */
|
||||
static time_t max_cache_time; /* time of peak size */
|
||||
|
||||
static int max_rcpt;
|
||||
static char *max_rcpt_user;
|
||||
static time_t max_rcpt_time;
|
||||
/* Update/report peak usage. */
|
||||
|
||||
static int max_newtls;
|
||||
static char *max_newtls_user;
|
||||
static time_t max_newtls_time;
|
||||
#define ANVIL_MAX_UPDATE(_max, _value, _ident) \
|
||||
do { \
|
||||
_max.value = _value; \
|
||||
if (_max.ident == 0) { \
|
||||
_max.ident = mystrdup(_ident); \
|
||||
} else if (!STREQ(_max.ident, _ident)) { \
|
||||
myfree(_max.ident); \
|
||||
_max.ident = mystrdup(_ident); \
|
||||
} \
|
||||
_max.when = event_time(); \
|
||||
} while (0)
|
||||
|
||||
static int max_cache;
|
||||
static time_t max_cache_time;
|
||||
#define ANVIL_MAX_RATE_REPORT(_max, _name) \
|
||||
do { \
|
||||
if (_max.value > 0) { \
|
||||
msg_info("statistics: max " _name " rate %d/%ds for (%s) at %.15s", \
|
||||
_max.value, var_anvil_time_unit, \
|
||||
_max.ident, ctime(&_max.when) + 4); \
|
||||
_max.value = 0; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define ANVIL_MAX_COUNT_REPORT(_max, _name) \
|
||||
do { \
|
||||
if (_max.value > 0) { \
|
||||
msg_info("statistics: max " _name " count %d for (%s) at %.15s", \
|
||||
_max.value, _max.ident, ctime(&_max.when) + 4); \
|
||||
_max.value = 0; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
/*
|
||||
* Remote connection state, one instance for each (service, client) pair.
|
||||
@ -284,7 +345,7 @@ typedef struct {
|
||||
int rate; /* connection rate */
|
||||
int mail; /* message rate */
|
||||
int rcpt; /* recipient rate */
|
||||
int newtls; /* newtls rate */
|
||||
int ntls; /* new TLS session rate */
|
||||
time_t start; /* time of first rate sample */
|
||||
} ANVIL_REMOTE;
|
||||
|
||||
@ -296,12 +357,6 @@ typedef struct {
|
||||
ANVIL_REMOTE *anvil_remote; /* XXX should be list */
|
||||
} ANVIL_LOCAL;
|
||||
|
||||
/*
|
||||
* Silly little macros.
|
||||
*/
|
||||
#define STR(x) vstring_str(x)
|
||||
#define STREQ(x,y) (strcmp((x), (y)) == 0)
|
||||
|
||||
/*
|
||||
* The following operations are implemented as macros with recognizable
|
||||
* names so that we don't lose sight of what the code is trying to do.
|
||||
@ -312,14 +367,14 @@ typedef struct {
|
||||
|
||||
/* Create new (service, client) state. */
|
||||
|
||||
#define ANVIL_REMOTE_FIRST(remote, id) \
|
||||
#define ANVIL_REMOTE_FIRST_CONN(remote, id) \
|
||||
do { \
|
||||
(remote)->ident = mystrdup(id); \
|
||||
(remote)->count = 1; \
|
||||
(remote)->rate = 1; \
|
||||
(remote)->mail = 0; \
|
||||
(remote)->rcpt = 0; \
|
||||
(remote)->newtls = 0; \
|
||||
(remote)->ntls = 0; \
|
||||
(remote)->start = event_time(); \
|
||||
} while(0)
|
||||
|
||||
@ -331,66 +386,41 @@ typedef struct {
|
||||
myfree((char *) (remote)); \
|
||||
} while(0)
|
||||
|
||||
/* Reset event rate counters and start of data collection interval. */
|
||||
|
||||
#define ANVIL_REMOTE_RSET_RATE(remote, _start) \
|
||||
do { \
|
||||
(remote)->rate = 0; \
|
||||
(remote)->mail = 0; \
|
||||
(remote)->rcpt = 0; \
|
||||
(remote)->ntls = 0; \
|
||||
(remote)->start = _start; \
|
||||
} while(0)
|
||||
|
||||
/* Add connection to (service, client) state. */
|
||||
|
||||
#define ANVIL_REMOTE_NEXT(remote) \
|
||||
#define ANVIL_REMOTE_INCR_RATE(remote, _what) \
|
||||
do { \
|
||||
time_t _now = event_time(); \
|
||||
if ((remote)->start + var_anvil_time_unit < _now) { \
|
||||
(remote)->rate = 1; \
|
||||
(remote)->mail = 0; \
|
||||
(remote)->rcpt = 0; \
|
||||
(remote)->newtls = 0; \
|
||||
(remote)->start = _now; \
|
||||
} else if ((remote)->rate < INT_MAX) { \
|
||||
(remote)->rate += 1; \
|
||||
} \
|
||||
if ((remote)->start + var_anvil_time_unit < _now) \
|
||||
ANVIL_REMOTE_RSET_RATE((remote), _now); \
|
||||
if ((remote)->_what < INT_MAX) \
|
||||
(remote)->_what += 1; \
|
||||
} while(0)
|
||||
|
||||
#define ANVIL_REMOTE_NEXT_CONN(remote) \
|
||||
do { \
|
||||
ANVIL_REMOTE_INCR_RATE((remote), rate); \
|
||||
if ((remote)->count == 0) \
|
||||
event_cancel_timer(anvil_remote_expire, (char *) remote); \
|
||||
(remote)->count++; \
|
||||
} while(0)
|
||||
|
||||
#define ANVIL_ADD_MAIL(remote) \
|
||||
do { \
|
||||
time_t _now = event_time(); \
|
||||
if ((remote)->start + var_anvil_time_unit < _now) { \
|
||||
(remote)->rate = 0; \
|
||||
(remote)->mail = 1; \
|
||||
(remote)->rcpt = 0; \
|
||||
(remote)->newtls = 0; \
|
||||
(remote)->start = _now; \
|
||||
} else if ((remote)->mail < INT_MAX) { \
|
||||
(remote)->mail += 1; \
|
||||
} \
|
||||
} while(0)
|
||||
#define ANVIL_REMOTE_INCR_MAIL(remote) ANVIL_REMOTE_INCR_RATE((remote), mail)
|
||||
|
||||
#define ANVIL_ADD_RCPT(remote) \
|
||||
do { \
|
||||
time_t _now = event_time(); \
|
||||
if ((remote)->start + var_anvil_time_unit < _now) { \
|
||||
(remote)->rate = 0; \
|
||||
(remote)->mail = 0; \
|
||||
(remote)->rcpt = 1; \
|
||||
(remote)->newtls = 0; \
|
||||
(remote)->start = _now; \
|
||||
} else if ((remote)->rcpt < INT_MAX) { \
|
||||
(remote)->rcpt += 1; \
|
||||
} \
|
||||
} while(0)
|
||||
#define ANVIL_REMOTE_INCR_RCPT(remote) ANVIL_REMOTE_INCR_RATE((remote), rcpt)
|
||||
|
||||
#define ANVIL_ADD_STARTTLS(remote) \
|
||||
do { \
|
||||
time_t _now = event_time(); \
|
||||
if ((remote)->start + var_anvil_time_unit < _now) { \
|
||||
(remote)->rate = 0; \
|
||||
(remote)->mail = 0; \
|
||||
(remote)->rcpt = 0; \
|
||||
(remote)->newtls = 1; \
|
||||
(remote)->start = _now; \
|
||||
} else if ((remote)->newtls < INT_MAX) { \
|
||||
(remote)->newtls += 1; \
|
||||
} \
|
||||
} while(0)
|
||||
#define ANVIL_REMOTE_INCR_NTLS(remote) ANVIL_REMOTE_INCR_RATE((remote), ntls)
|
||||
|
||||
/* Drop connection from (service, client) state. */
|
||||
|
||||
@ -443,6 +473,20 @@ typedef struct {
|
||||
anvil_remote_disconnect((stream), (local)->anvil_remote->ident); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Lookup table to map request names to action routines.
|
||||
*/
|
||||
typedef struct {
|
||||
const char *name;
|
||||
void (*action) (VSTREAM *, const char *);
|
||||
} ANVIL_REQ_TABLE;
|
||||
|
||||
/*
|
||||
* Silly little macros.
|
||||
*/
|
||||
#define STR(x) vstring_str(x)
|
||||
#define STREQ(x,y) (strcmp((x), (y)) == 0)
|
||||
|
||||
/* anvil_remote_expire - purge expired connection state */
|
||||
|
||||
static void anvil_remote_expire(int unused_event, char *context)
|
||||
@ -472,8 +516,6 @@ static void anvil_remote_lookup(VSTREAM *client_stream, const char *ident)
|
||||
{
|
||||
ANVIL_REMOTE *anvil_remote;
|
||||
char *myname = "anvil_remote_lookup";
|
||||
HTABLE_INFO **ht_info;
|
||||
HTABLE_INFO **ht;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s fd=%d stream=0x%lx ident=%s",
|
||||
@ -483,39 +525,31 @@ static void anvil_remote_lookup(VSTREAM *client_stream, const char *ident)
|
||||
/*
|
||||
* Look up remote client information.
|
||||
*/
|
||||
if (STREQ(ident, "*")) {
|
||||
attr_print_plain(client_stream, ATTR_FLAG_MORE,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
||||
ATTR_TYPE_END);
|
||||
ht_info = htable_list(anvil_remote_map);
|
||||
for (ht = ht_info; *ht; ht++) {
|
||||
anvil_remote = (ANVIL_REMOTE *) ht[0]->value;
|
||||
attr_print_plain(client_stream, ATTR_FLAG_MORE,
|
||||
ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ht[0]->key,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, anvil_remote->count,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->rate,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, anvil_remote->mail,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, anvil_remote->rcpt,
|
||||
ATTR_TYPE_END);
|
||||
}
|
||||
attr_print_plain(client_stream, ATTR_FLAG_NONE, ATTR_TYPE_END);
|
||||
myfree((char *) ht_info);
|
||||
} else if ((anvil_remote =
|
||||
(ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) {
|
||||
if ((anvil_remote =
|
||||
(ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) {
|
||||
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_FAIL,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, 0,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, 0,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, 0,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, 0,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_NTLS, 0,
|
||||
ATTR_TYPE_END);
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Do not report stale information.
|
||||
*/
|
||||
if (anvil_remote->start != 0
|
||||
&& anvil_remote->start + var_anvil_time_unit < event_time())
|
||||
ANVIL_REMOTE_RSET_RATE(anvil_remote, 0);
|
||||
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, anvil_remote->count,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->rate,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, anvil_remote->mail,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, anvil_remote->rcpt,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_NTLS, anvil_remote->ntls,
|
||||
ATTR_TYPE_END);
|
||||
}
|
||||
}
|
||||
@ -542,14 +576,14 @@ static ANVIL_REMOTE *anvil_remote_conn_update(VSTREAM *client_stream, const char
|
||||
if ((anvil_remote =
|
||||
(ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) {
|
||||
anvil_remote = (ANVIL_REMOTE *) mymalloc(sizeof(*anvil_remote));
|
||||
ANVIL_REMOTE_FIRST(anvil_remote, ident);
|
||||
ANVIL_REMOTE_FIRST_CONN(anvil_remote, ident);
|
||||
htable_enter(anvil_remote_map, ident, (char *) anvil_remote);
|
||||
if (max_cache < anvil_remote_map->used) {
|
||||
max_cache = anvil_remote_map->used;
|
||||
if (max_cache_size < anvil_remote_map->used) {
|
||||
max_cache_size = anvil_remote_map->used;
|
||||
max_cache_time = event_time();
|
||||
}
|
||||
} else {
|
||||
ANVIL_REMOTE_NEXT(anvil_remote);
|
||||
ANVIL_REMOTE_NEXT_CONN(anvil_remote);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -592,28 +626,12 @@ static void anvil_remote_connect(VSTREAM *client_stream, const char *ident)
|
||||
ATTR_TYPE_END);
|
||||
|
||||
/*
|
||||
* Update local statistics.
|
||||
* Update peak statistics.
|
||||
*/
|
||||
if (anvil_remote->rate > max_rate) {
|
||||
max_rate = anvil_remote->rate;
|
||||
if (max_rate_user == 0) {
|
||||
max_rate_user = mystrdup(anvil_remote->ident);
|
||||
} else if (!STREQ(max_rate_user, anvil_remote->ident)) {
|
||||
myfree(max_rate_user);
|
||||
max_rate_user = mystrdup(anvil_remote->ident);
|
||||
}
|
||||
max_rate_time = event_time();
|
||||
}
|
||||
if (anvil_remote->count > max_count) {
|
||||
max_count = anvil_remote->count;
|
||||
if (max_count_user == 0) {
|
||||
max_count_user = mystrdup(anvil_remote->ident);
|
||||
} else if (!STREQ(max_count_user, anvil_remote->ident)) {
|
||||
myfree(max_count_user);
|
||||
max_count_user = mystrdup(anvil_remote->ident);
|
||||
}
|
||||
max_count_time = event_time();
|
||||
}
|
||||
if (anvil_remote->rate > max_conn_rate.value)
|
||||
ANVIL_MAX_UPDATE(max_conn_rate, anvil_remote->rate, anvil_remote->ident);
|
||||
if (anvil_remote->count > max_conn_count.value)
|
||||
ANVIL_MAX_UPDATE(max_conn_count, anvil_remote->count, anvil_remote->ident);
|
||||
}
|
||||
|
||||
/* anvil_remote_mail - register message delivery request */
|
||||
@ -632,25 +650,17 @@ static void anvil_remote_mail(VSTREAM *client_stream, const char *ident)
|
||||
/*
|
||||
* Update message delivery request rate and respond to local client.
|
||||
*/
|
||||
ANVIL_ADD_MAIL(anvil_remote);
|
||||
ANVIL_REMOTE_INCR_MAIL(anvil_remote);
|
||||
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->mail,
|
||||
ATTR_TYPE_END);
|
||||
|
||||
/*
|
||||
* Update local statistics.
|
||||
* Update peak statistics.
|
||||
*/
|
||||
if (anvil_remote->mail > max_mail) {
|
||||
max_mail = anvil_remote->mail;
|
||||
if (max_mail_user == 0) {
|
||||
max_mail_user = mystrdup(anvil_remote->ident);
|
||||
} else if (!STREQ(max_mail_user, anvil_remote->ident)) {
|
||||
myfree(max_mail_user);
|
||||
max_mail_user = mystrdup(anvil_remote->ident);
|
||||
}
|
||||
max_mail_time = event_time();
|
||||
}
|
||||
if (anvil_remote->mail > max_mail_rate.value)
|
||||
ANVIL_MAX_UPDATE(max_mail_rate, anvil_remote->mail, anvil_remote->ident);
|
||||
}
|
||||
|
||||
/* anvil_remote_rcpt - register recipient address event */
|
||||
@ -669,25 +679,17 @@ static void anvil_remote_rcpt(VSTREAM *client_stream, const char *ident)
|
||||
/*
|
||||
* Update recipient address rate and respond to local client.
|
||||
*/
|
||||
ANVIL_ADD_RCPT(anvil_remote);
|
||||
ANVIL_REMOTE_INCR_RCPT(anvil_remote);
|
||||
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->rcpt,
|
||||
ATTR_TYPE_END);
|
||||
|
||||
/*
|
||||
* Update local statistics.
|
||||
* Update peak statistics.
|
||||
*/
|
||||
if (anvil_remote->rcpt > max_rcpt) {
|
||||
max_rcpt = anvil_remote->rcpt;
|
||||
if (max_rcpt_user == 0) {
|
||||
max_rcpt_user = mystrdup(anvil_remote->ident);
|
||||
} else if (!STREQ(max_rcpt_user, anvil_remote->ident)) {
|
||||
myfree(max_rcpt_user);
|
||||
max_rcpt_user = mystrdup(anvil_remote->ident);
|
||||
}
|
||||
max_rcpt_time = event_time();
|
||||
}
|
||||
if (anvil_remote->rcpt > max_rcpt_rate.value)
|
||||
ANVIL_MAX_UPDATE(max_rcpt_rate, anvil_remote->rcpt, anvil_remote->ident);
|
||||
}
|
||||
|
||||
/* anvil_remote_newtls - register newtls event */
|
||||
@ -706,25 +708,51 @@ static void anvil_remote_newtls(VSTREAM *client_stream, const char *ident)
|
||||
/*
|
||||
* Update newtls rate and respond to local client.
|
||||
*/
|
||||
ANVIL_ADD_STARTTLS(anvil_remote);
|
||||
ANVIL_REMOTE_INCR_NTLS(anvil_remote);
|
||||
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->newtls,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->ntls,
|
||||
ATTR_TYPE_END);
|
||||
|
||||
/*
|
||||
* Update local statistics.
|
||||
* Update peak statistics.
|
||||
*/
|
||||
if (anvil_remote->newtls > max_newtls) {
|
||||
max_newtls = anvil_remote->newtls;
|
||||
if (max_newtls_user == 0) {
|
||||
max_newtls_user = mystrdup(anvil_remote->ident);
|
||||
} else if (!STREQ(max_newtls_user, anvil_remote->ident)) {
|
||||
myfree(max_newtls_user);
|
||||
max_newtls_user = mystrdup(anvil_remote->ident);
|
||||
}
|
||||
max_newtls_time = event_time();
|
||||
if (anvil_remote->ntls > max_ntls_rate.value)
|
||||
ANVIL_MAX_UPDATE(max_ntls_rate, anvil_remote->ntls, anvil_remote->ident);
|
||||
}
|
||||
|
||||
/* anvil_remote_newtls_stat - report newtls stats */
|
||||
|
||||
static void anvil_remote_newtls_stat(VSTREAM *client_stream, const char *ident)
|
||||
{
|
||||
ANVIL_REMOTE *anvil_remote;
|
||||
int rate;
|
||||
|
||||
/*
|
||||
* Be prepared for "postfix reload" after "connect".
|
||||
*/
|
||||
if ((anvil_remote =
|
||||
(ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) {
|
||||
rate = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not report stale information.
|
||||
*/
|
||||
else {
|
||||
if (anvil_remote->start != 0
|
||||
&& anvil_remote->start + var_anvil_time_unit < event_time())
|
||||
ANVIL_REMOTE_RSET_RATE(anvil_remote, 0);
|
||||
rate = anvil_remote->ntls;
|
||||
}
|
||||
|
||||
/*
|
||||
* Respond to local client.
|
||||
*/
|
||||
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, rate,
|
||||
ATTR_TYPE_END);
|
||||
}
|
||||
|
||||
/* anvil_remote_disconnect - report disconnect event */
|
||||
@ -796,8 +824,19 @@ static void anvil_service_done(VSTREAM *client_stream, char *unused_service,
|
||||
|
||||
static void anvil_service(VSTREAM *client_stream, char *unused_service, char **argv)
|
||||
{
|
||||
VSTRING *request = vstring_alloc(10);
|
||||
VSTRING *ident = vstring_alloc(10);
|
||||
static VSTRING *request;
|
||||
static VSTRING *ident;
|
||||
static ANVIL_REQ_TABLE request_table[] = {
|
||||
ANVIL_REQ_CONN, anvil_remote_connect,
|
||||
ANVIL_REQ_MAIL, anvil_remote_mail,
|
||||
ANVIL_REQ_RCPT, anvil_remote_rcpt,
|
||||
ANVIL_REQ_NTLS, anvil_remote_newtls,
|
||||
ANVIL_REQ_DISC, anvil_remote_disconnect,
|
||||
ANVIL_REQ_NTLS_STAT, anvil_remote_newtls_stat,
|
||||
ANVIL_REQ_LOOKUP, anvil_remote_lookup,
|
||||
0, 0,
|
||||
};
|
||||
ANVIL_REQ_TABLE *rp;
|
||||
|
||||
/*
|
||||
* Sanity check. This service takes no command-line arguments.
|
||||
@ -805,6 +844,14 @@ static void anvil_service(VSTREAM *client_stream, char *unused_service, char **a
|
||||
if (argv[0])
|
||||
msg_fatal("unexpected command-line argument: %s", argv[0]);
|
||||
|
||||
/*
|
||||
* Initialize.
|
||||
*/
|
||||
if (request == 0) {
|
||||
request = vstring_alloc(10);
|
||||
ident = vstring_alloc(10);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine runs whenever a client connects to the socket dedicated
|
||||
* to the client connection rate management service. All
|
||||
@ -818,23 +865,18 @@ static void anvil_service(VSTREAM *client_stream, char *unused_service, char **a
|
||||
ATTR_TYPE_STR, ANVIL_ATTR_REQ, request,
|
||||
ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident,
|
||||
ATTR_TYPE_END) == 2) {
|
||||
if (STREQ(STR(request), ANVIL_REQ_CONN)) {
|
||||
anvil_remote_connect(client_stream, STR(ident));
|
||||
} else if (STREQ(STR(request), ANVIL_REQ_MAIL)) {
|
||||
anvil_remote_mail(client_stream, STR(ident));
|
||||
} else if (STREQ(STR(request), ANVIL_REQ_RCPT)) {
|
||||
anvil_remote_rcpt(client_stream, STR(ident));
|
||||
} else if (STREQ(STR(request), ANVIL_REQ_NEWTLS)) {
|
||||
anvil_remote_newtls(client_stream, STR(ident));
|
||||
} else if (STREQ(STR(request), ANVIL_REQ_DISC)) {
|
||||
anvil_remote_disconnect(client_stream, STR(ident));
|
||||
} else if (STREQ(STR(request), ANVIL_REQ_LOOKUP)) {
|
||||
anvil_remote_lookup(client_stream, STR(ident));
|
||||
} else {
|
||||
msg_warn("unrecognized request: \"%s\", ignored", STR(request));
|
||||
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
||||
for (rp = request_table; /* see below */ ; rp++) {
|
||||
if (rp->name == 0) {
|
||||
msg_warn("unrecognized request: \"%s\", ignored", STR(request));
|
||||
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_FAIL,
|
||||
ATTR_TYPE_END);
|
||||
ATTR_TYPE_END);
|
||||
break;
|
||||
}
|
||||
if (STREQ(rp->name, STR(request))) {
|
||||
rp->action(client_stream, STR(ident));
|
||||
break;
|
||||
}
|
||||
}
|
||||
vstream_fflush(client_stream);
|
||||
} else {
|
||||
@ -843,8 +885,6 @@ static void anvil_service(VSTREAM *client_stream, char *unused_service, char **a
|
||||
}
|
||||
if (msg_verbose)
|
||||
msg_info("--- end request ---");
|
||||
vstring_free(ident);
|
||||
vstring_free(request);
|
||||
}
|
||||
|
||||
/* post_jail_init - post-jail initialization */
|
||||
@ -874,39 +914,16 @@ static void post_jail_init(char *unused_name, char **unused_argv)
|
||||
|
||||
static void anvil_status_dump(char *unused_name, char **unused_argv)
|
||||
{
|
||||
if (max_rate > 0) {
|
||||
msg_info("statistics: max connection rate %d/%ds for (%s) at %.15s",
|
||||
max_rate, var_anvil_time_unit,
|
||||
max_rate_user, ctime(&max_rate_time) + 4);
|
||||
max_rate = 0;
|
||||
}
|
||||
if (max_count > 0) {
|
||||
msg_info("statistics: max connection count %d for (%s) at %.15s",
|
||||
max_count, max_count_user, ctime(&max_count_time) + 4);
|
||||
max_count = 0;
|
||||
}
|
||||
if (max_mail > 0) {
|
||||
msg_info("statistics: max message rate %d/%ds for (%s) at %.15s",
|
||||
max_mail, var_anvil_time_unit,
|
||||
max_mail_user, ctime(&max_mail_time) + 4);
|
||||
max_mail = 0;
|
||||
}
|
||||
if (max_rcpt > 0) {
|
||||
msg_info("statistics: max recipient rate %d/%ds for (%s) at %.15s",
|
||||
max_rcpt, var_anvil_time_unit,
|
||||
max_rcpt_user, ctime(&max_rcpt_time) + 4);
|
||||
max_rcpt = 0;
|
||||
}
|
||||
if (max_newtls > 0) {
|
||||
msg_info("statistics: max newtls rate %d/%ds for (%s) at %.15s",
|
||||
max_newtls, var_anvil_time_unit,
|
||||
max_newtls_user, ctime(&max_newtls_time) + 4);
|
||||
max_newtls = 0;
|
||||
}
|
||||
if (max_cache > 0) {
|
||||
ANVIL_MAX_RATE_REPORT(max_conn_rate, "connection");
|
||||
ANVIL_MAX_COUNT_REPORT(max_conn_count, "connection");
|
||||
ANVIL_MAX_RATE_REPORT(max_mail_rate, "message");
|
||||
ANVIL_MAX_RATE_REPORT(max_rcpt_rate, "recipient");
|
||||
ANVIL_MAX_RATE_REPORT(max_ntls_rate, "newtls");
|
||||
|
||||
if (max_cache_size > 0) {
|
||||
msg_info("statistics: max cache size %d at %.15s",
|
||||
max_cache, ctime(&max_cache_time) + 4);
|
||||
max_cache = 0;
|
||||
max_cache_size, ctime(&max_cache_time) + 4);
|
||||
max_cache_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,12 @@
|
||||
/* const char *addr;
|
||||
/* int *newtls;
|
||||
/*
|
||||
/* int anvil_clnt_newtls_stat(anvil_clnt, service, addr, newtls)
|
||||
/* ANVIL_CLNT *anvil_clnt;
|
||||
/* const char *service;
|
||||
/* const char *addr;
|
||||
/* int *newtls;
|
||||
/*
|
||||
/* int anvil_clnt_disconnect(anvil_clnt, service, addr)
|
||||
/* ANVIL_CLNT *anvil_clnt;
|
||||
/* const char *service;
|
||||
@ -52,29 +58,36 @@
|
||||
/* int *msgs;
|
||||
/* int *rcpts;
|
||||
/* DESCRIPTION
|
||||
/* anvil_clnt_create() instantiates an anvil service client endpoint.
|
||||
/* anvil_clnt_create() instantiates a local anvil service
|
||||
/* client endpoint.
|
||||
/*
|
||||
/* anvil_clnt_connect() informs the anvil server that a
|
||||
/* client has connected, and returns the current connection
|
||||
/* count and connection rate for that client.
|
||||
/* remote client has connected, and returns the current
|
||||
/* connection count and connection rate for that remote client.
|
||||
/*
|
||||
/* anvil_clnt_mail() registers a MAIL FROM event and returns
|
||||
/* the current MAIL FROM rate for the specified client.
|
||||
/* anvil_clnt_mail() registers a MAIL FROM event and
|
||||
/* returns the current MAIL FROM rate for the specified remote
|
||||
/* client.
|
||||
/*
|
||||
/* anvil_clnt_rcpt() registers a RCPT TO event and returns
|
||||
/* the current RCPT TO rate for the specified client.
|
||||
/* anvil_clnt_rcpt() registers a RCPT TO event and
|
||||
/* returns the current RCPT TO rate for the specified remote
|
||||
/* client.
|
||||
/*
|
||||
/* anvil_clnt_newtls() registers a request to negotiate a new
|
||||
/* (uncached) TLS session and returns the current request rate
|
||||
/* for the specified client.
|
||||
/* anvil_clnt_newtls() registers a remote client request
|
||||
/* to negotiate a new (uncached) TLS session and returns the
|
||||
/* current newtls request rate for the specified remote client.
|
||||
/*
|
||||
/* anvil_clnt_disconnect() informs the anvil server that a
|
||||
/* anvil_clnt_newtls_stat() returns the current newtls request
|
||||
/* rate for the specified remote client.
|
||||
/*
|
||||
/* anvil_clnt_disconnect() informs the anvil server that a remote
|
||||
/* client has disconnected.
|
||||
/*
|
||||
/* anvil_clnt_lookup() looks up the current connection
|
||||
/* count and connection rate for that client.
|
||||
/* anvil_clnt_lookup() returns the current count and rate
|
||||
/* information for the specified client.
|
||||
/*
|
||||
/* anvil_clnt_free() destroys an anvil service client endpoint.
|
||||
/* anvil_clnt_free() destroys a local anvil service client
|
||||
/* endpoint.
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP anvil_clnt
|
||||
@ -99,7 +112,7 @@
|
||||
/* Pointer to storage for the current "new TLS session" rate
|
||||
/* for this remote client.
|
||||
/* DIAGNOSTICS
|
||||
/* anvil_clnt_connect() and anvil_clnt_disconnect() return
|
||||
/* The update and status query routines return
|
||||
/* ANVIL_STAT_OK in case of success, ANVIL_STAT_FAIL otherwise
|
||||
/* (either the communication with the server is broken or the
|
||||
/* server experienced a problem).
|
||||
@ -168,7 +181,7 @@ void anvil_clnt_free(ANVIL_CLNT *anvil_clnt)
|
||||
|
||||
int anvil_clnt_lookup(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||
const char *addr, int *count, int *rate,
|
||||
int *msgs, int *rcpts)
|
||||
int *msgs, int *rcpts, int *newtls)
|
||||
{
|
||||
char *ident = ANVIL_IDENT(service, addr);
|
||||
int status;
|
||||
@ -184,7 +197,8 @@ int anvil_clnt_lookup(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, rate,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, msgs,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, rcpts,
|
||||
ATTR_TYPE_END) != 5)
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_NTLS, newtls,
|
||||
ATTR_TYPE_END) != 6)
|
||||
status = ANVIL_STAT_FAIL;
|
||||
else if (status != ANVIL_STAT_OK)
|
||||
status = ANVIL_STAT_FAIL;
|
||||
@ -192,7 +206,7 @@ int anvil_clnt_lookup(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||
return (status);
|
||||
}
|
||||
|
||||
/* anvil_clnt_connect - heads-up and policy query */
|
||||
/* anvil_clnt_connect - heads-up and status query */
|
||||
|
||||
int anvil_clnt_connect(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||
const char *addr, int *count, int *rate)
|
||||
@ -217,7 +231,7 @@ int anvil_clnt_connect(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||
return (status);
|
||||
}
|
||||
|
||||
/* anvil_clnt_mail - heads-up and policy query */
|
||||
/* anvil_clnt_mail - heads-up and status query */
|
||||
|
||||
int anvil_clnt_mail(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||
const char *addr, int *msgs)
|
||||
@ -241,7 +255,7 @@ int anvil_clnt_mail(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||
return (status);
|
||||
}
|
||||
|
||||
/* anvil_clnt_rcpt - heads-up and policy query */
|
||||
/* anvil_clnt_rcpt - heads-up and status query */
|
||||
|
||||
int anvil_clnt_rcpt(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||
const char *addr, int *rcpts)
|
||||
@ -265,17 +279,41 @@ int anvil_clnt_rcpt(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||
return (status);
|
||||
}
|
||||
|
||||
/* anvil_clnt_newtls - heads-up and policy query */
|
||||
/* anvil_clnt_newtls - heads-up and status query */
|
||||
|
||||
int anvil_clnt_newtls(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||
const char *addr, int *newtls)
|
||||
int anvil_clnt_newtls(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||
const char *addr, int *newtls)
|
||||
{
|
||||
char *ident = ANVIL_IDENT(service, addr);
|
||||
int status;
|
||||
int status;
|
||||
|
||||
if (attr_clnt_request((ATTR_CLNT *)anvil_clnt,
|
||||
if (attr_clnt_request((ATTR_CLNT *) anvil_clnt,
|
||||
ATTR_FLAG_NONE, /* Query attributes. */
|
||||
ATTR_TYPE_STR, ANVIL_ATTR_REQ, ANVIL_REQ_NEWTLS,
|
||||
ATTR_TYPE_STR, ANVIL_ATTR_REQ, ANVIL_REQ_NTLS,
|
||||
ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident,
|
||||
ATTR_TYPE_END,
|
||||
ATTR_FLAG_MISSING, /* Reply attributes. */
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, &status,
|
||||
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, newtls,
|
||||
ATTR_TYPE_END) != 2)
|
||||
status = ANVIL_STAT_FAIL;
|
||||
else if (status != ANVIL_STAT_OK)
|
||||
status = ANVIL_STAT_FAIL;
|
||||
myfree(ident);
|
||||
return (status);
|
||||
}
|
||||
|
||||
/* anvil_clnt_newtls_stat - status query */
|
||||
|
||||
int anvil_clnt_newtls_stat(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||
const char *addr, int *newtls)
|
||||
{
|
||||
char *ident = ANVIL_IDENT(service, addr);
|
||||
int status;
|
||||
|
||||
if (attr_clnt_request((ATTR_CLNT *) anvil_clnt,
|
||||
ATTR_FLAG_NONE, /* Query attributes. */
|
||||
ATTR_TYPE_STR, ANVIL_ATTR_REQ, ANVIL_REQ_NTLS_STAT,
|
||||
ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident,
|
||||
ATTR_TYPE_END,
|
||||
ATTR_FLAG_MISSING, /* Reply attributes. */
|
||||
@ -291,13 +329,13 @@ int anvil_clnt_newtls(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||
|
||||
/* anvil_clnt_disconnect - heads-up only */
|
||||
|
||||
int anvil_clnt_disconnect(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||
const char *addr)
|
||||
int anvil_clnt_disconnect(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||
const char *addr)
|
||||
{
|
||||
char *ident = ANVIL_IDENT(service, addr);
|
||||
int status;
|
||||
int status;
|
||||
|
||||
if (attr_clnt_request((ATTR_CLNT *)anvil_clnt,
|
||||
if (attr_clnt_request((ATTR_CLNT *) anvil_clnt,
|
||||
ATTR_FLAG_NONE, /* Query attributes. */
|
||||
ATTR_TYPE_STR, ANVIL_ATTR_REQ, ANVIL_REQ_DISC,
|
||||
ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident,
|
||||
@ -326,13 +364,17 @@ int anvil_clnt_disconnect(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
vstream_printf("usage: %s service addr | %s service addr |"
|
||||
" %s service addr | %s service addr\n",
|
||||
ANVIL_REQ_CONN, ANVIL_REQ_DISC,
|
||||
ANVIL_REQ_MAIL, ANVIL_REQ_RCPT);
|
||||
vstream_printf("usage: "
|
||||
ANVIL_REQ_CONN " service addr | "
|
||||
ANVIL_REQ_DISC " service addr | "
|
||||
ANVIL_REQ_MAIL " service addr | "
|
||||
ANVIL_REQ_RCPT " service addr | "
|
||||
ANVIL_REQ_NTLS " service addr | "
|
||||
ANVIL_REQ_NTLS_STAT " service addr | "
|
||||
ANVIL_REQ_LOOKUP " service addr\n");
|
||||
}
|
||||
|
||||
int main(int unused_argc, char **argv)
|
||||
int main(int unused_argc, char **argv)
|
||||
{
|
||||
VSTRING *inbuf = vstring_alloc(1);
|
||||
char *bufp;
|
||||
@ -340,10 +382,11 @@ int main(int unused_argc, char **argv)
|
||||
ssize_t cmd_len;
|
||||
char *service;
|
||||
char *addr;
|
||||
int count;
|
||||
int rate;
|
||||
int msgs;
|
||||
int rcpts;
|
||||
int count;
|
||||
int rate;
|
||||
int msgs;
|
||||
int rcpts;
|
||||
int newtls;
|
||||
ANVIL_CLNT *anvil;
|
||||
|
||||
msg_vstream_init(argv[0], VSTREAM_ERR);
|
||||
@ -384,6 +427,16 @@ int main(int unused_argc, char **argv)
|
||||
msg_warn("error!");
|
||||
else
|
||||
vstream_printf("rate=%d\n", rcpts);
|
||||
} else if (strncmp(cmd, ANVIL_REQ_NTLS, cmd_len) == 0) {
|
||||
if (anvil_clnt_newtls(anvil, service, addr, &newtls) != ANVIL_STAT_OK)
|
||||
msg_warn("error!");
|
||||
else
|
||||
vstream_printf("rate=%d\n", newtls);
|
||||
} else if (strncmp(cmd, ANVIL_REQ_NTLS_STAT, cmd_len) == 0) {
|
||||
if (anvil_clnt_newtls_stat(anvil, service, addr, &newtls) != ANVIL_STAT_OK)
|
||||
msg_warn("error!");
|
||||
else
|
||||
vstream_printf("rate=%d\n", newtls);
|
||||
} else if (strncmp(cmd, ANVIL_REQ_DISC, cmd_len) == 0) {
|
||||
if (anvil_clnt_disconnect(anvil, service, addr) != ANVIL_STAT_OK)
|
||||
msg_warn("error!");
|
||||
@ -391,11 +444,11 @@ int main(int unused_argc, char **argv)
|
||||
vstream_printf("OK\n");
|
||||
} else if (strncmp(cmd, ANVIL_REQ_LOOKUP, cmd_len) == 0) {
|
||||
if (anvil_clnt_lookup(anvil, service, addr, &count, &rate,
|
||||
&msgs, &rcpts) != ANVIL_STAT_OK)
|
||||
&msgs, &rcpts, &newtls) != ANVIL_STAT_OK)
|
||||
msg_warn("error!");
|
||||
else
|
||||
vstream_printf("count=%d, rate=%d msgs=%d rcpts=%d\n",
|
||||
count, rate, msgs, rcpts);
|
||||
vstream_printf("count=%d, rate=%d msgs=%d rcpts=%d newtls=%d\n",
|
||||
count, rate, msgs, rcpts, newtls);
|
||||
} else {
|
||||
vstream_printf("bad command: \"%s\"\n", cmd);
|
||||
usage();
|
||||
|
@ -32,13 +32,15 @@
|
||||
#define ANVIL_REQ_DISC "disconnect"
|
||||
#define ANVIL_REQ_MAIL "message"
|
||||
#define ANVIL_REQ_RCPT "recipient"
|
||||
#define ANVIL_REQ_NEWTLS "newtls"
|
||||
#define ANVIL_REQ_NTLS "newtls"
|
||||
#define ANVIL_REQ_NTLS_STAT "newtls_status"
|
||||
#define ANVIL_REQ_LOOKUP "lookup"
|
||||
#define ANVIL_ATTR_IDENT "ident"
|
||||
#define ANVIL_ATTR_COUNT "count"
|
||||
#define ANVIL_ATTR_RATE "rate"
|
||||
#define ANVIL_ATTR_MAIL "mail"
|
||||
#define ANVIL_ATTR_RCPT "rcpt"
|
||||
#define ANVIL_ATTR_NTLS "newtls"
|
||||
#define ANVIL_ATTR_STATUS "status"
|
||||
|
||||
#define ANVIL_STAT_OK 0
|
||||
@ -54,7 +56,8 @@ extern int anvil_clnt_connect(ANVIL_CLNT *, const char *, const char *, int *, i
|
||||
extern int anvil_clnt_mail(ANVIL_CLNT *, const char *, const char *, int *);
|
||||
extern int anvil_clnt_rcpt(ANVIL_CLNT *, const char *, const char *, int *);
|
||||
extern int anvil_clnt_newtls(ANVIL_CLNT *, const char *, const char *, int *);
|
||||
extern int anvil_clnt_lookup(ANVIL_CLNT *, const char *, const char *, int *, int *, int *, int *);
|
||||
extern int anvil_clnt_newtls_stat(ANVIL_CLNT *, const char *, const char *, int *);
|
||||
extern int anvil_clnt_lookup(ANVIL_CLNT *, const char *, const char *, int *, int *, int *, int *, int *);
|
||||
extern int anvil_clnt_disconnect(ANVIL_CLNT *, const char *, const char *);
|
||||
extern void anvil_clnt_free(ANVIL_CLNT *);
|
||||
|
||||
|
@ -355,6 +355,7 @@ static DELIVER_REQUEST *deliver_request_alloc(void)
|
||||
request->sasl_username = 0;
|
||||
request->sasl_sender = 0;
|
||||
request->rewrite_context = 0;
|
||||
request->dsn_envid = 0;
|
||||
return (request);
|
||||
}
|
||||
|
||||
|
@ -1728,6 +1728,10 @@ ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`\
|
||||
abcdefghijklmnopqrstuvwxyz{|}~"
|
||||
extern char *var_smtpd_exp_filter;
|
||||
|
||||
#define VAR_SMTPD_PEERNAME_LOOKUP "smtpd_peername_lookup"
|
||||
#define DEF_SMTPD_PEERNAME_LOOKUP 1
|
||||
extern bool var_smtpd_peername_lookup;
|
||||
|
||||
/*
|
||||
* Heuristic to reject unknown local recipients at the SMTP port.
|
||||
*/
|
||||
@ -2301,6 +2305,10 @@ extern int var_smtpd_cmail_limit;
|
||||
#define DEF_SMTPD_CRCPT_LIMIT 0
|
||||
extern int var_smtpd_crcpt_limit;
|
||||
|
||||
#define VAR_SMTPD_CNTLS_LIMIT "smtpd_client_new_tls_session_rate_limit"
|
||||
#define DEF_SMTPD_CNTLS_LIMIT 0
|
||||
extern int var_smtpd_cntls_limit;
|
||||
|
||||
#define VAR_SMTPD_HOGGERS "smtpd_client_event_limit_exceptions"
|
||||
#define DEF_SMTPD_HOGGERS "${smtpd_client_connection_limit_exceptions:$" VAR_MYNETWORKS "}"
|
||||
extern char *var_smtpd_hoggers;
|
||||
@ -2380,10 +2388,6 @@ extern char *var_msg_strip_chars;
|
||||
#define DEF_FROZEN_DELIVERED 1
|
||||
extern bool var_frozen_delivered;
|
||||
|
||||
#define VAR_STICKY_OWNER_ALIAS "sticky_owner_alias"
|
||||
#define DEF_STICKY_OWNER_ALIAS 1
|
||||
extern bool var_sticky_owner_alias;
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
|
@ -20,7 +20,7 @@
|
||||
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||
* patchlevel; they change the release date only.
|
||||
*/
|
||||
#define MAIL_RELEASE_DATE "20050923"
|
||||
#define MAIL_RELEASE_DATE "20051010"
|
||||
#define MAIL_VERSION_NUMBER "2.3"
|
||||
|
||||
#ifdef SNAPSHOT
|
||||
|
@ -95,6 +95,9 @@
|
||||
/* An I/O error happened, or the peer has disconnected unexpectedly.
|
||||
/* .IP SMTP_ERR_TIME
|
||||
/* The time limit specified to smtp_timeout_setup() was exceeded.
|
||||
/* .IP SMTP_ERR_PROTO
|
||||
/* This error is never generated by the smtp_stream(3) module, but
|
||||
/* is defined for application-specific use.
|
||||
/* BUGS
|
||||
/* The timeout deadline affects all I/O on the named stream, not
|
||||
/* just the I/O done on behalf of this module.
|
||||
|
@ -28,6 +28,7 @@
|
||||
*/
|
||||
#define SMTP_ERR_EOF 1 /* unexpected client disconnect */
|
||||
#define SMTP_ERR_TIME 2 /* time out */
|
||||
#define SMTP_ERR_PROTO 3 /* protocol (application) */
|
||||
|
||||
extern void smtp_timeout_setup(VSTREAM *, int);
|
||||
extern void PRINTFLIKE(2, 3) smtp_printf(VSTREAM *, const char *,...);
|
||||
|
@ -231,7 +231,21 @@ LMTP_RESP *lmtp_chat_resp(LMTP_STATE *state)
|
||||
if (*cp == ' ' || *cp == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX Do not ignore garbage when ESMTP command pipelining is turned
|
||||
* on. After sending ".<CR><LF>QUIT<CR><LF>", Postfix might recognize
|
||||
* the server's 2XX QUIT reply as a 2XX END-OF-DATA reply after
|
||||
* garbage, causing mail to be lost. Instead, make a long jump so
|
||||
* that all recipients of multi-recipient mail get consistent
|
||||
* treatment.
|
||||
*/
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
if (state->features & LMTP_FEATURE_PIPELINING) {
|
||||
msg_warn("non-SMTP response from %s: %s",
|
||||
session->namaddr, STR(state->buffer));
|
||||
vstream_longjmp(session->stream, SMTP_ERR_PROTO);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -378,6 +378,12 @@ int lmtp_stream_except(LMTP_STATE *state, int code, const char *description)
|
||||
"conversation with %s timed out while %s",
|
||||
session->namaddr, description);
|
||||
break;
|
||||
case SMTP_ERR_PROTO:
|
||||
lmtp_fill_dsn(state, &dsn, DSN_BY_LOCAL_MTA,
|
||||
"4.5.0", "403 remote protocol error",
|
||||
"protocol error in reply from %s while %s",
|
||||
session->namaddr, description);
|
||||
break;
|
||||
}
|
||||
return (lmtp_bulk_fail(state, &dsn, LMTP_THROTTLE));
|
||||
}
|
||||
|
@ -263,8 +263,7 @@ int deliver_alias(LOCAL_STATE state, USER_ATTR usr_attr,
|
||||
SET_OWNER_ATTR(state.msg_attr, STR(canon_owner), state.level);
|
||||
} else {
|
||||
canon_owner = 0;
|
||||
if (var_sticky_owner_alias == 0)
|
||||
RESET_OWNER_ATTR(state.msg_attr, state.level);
|
||||
RESET_OWNER_ATTR(state.msg_attr, state.level);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -367,11 +367,6 @@
|
||||
/* address (see prepend_delivered_header) only once, at the start of
|
||||
/* a delivery attempt; do not update the Delivered-To: address while
|
||||
/* expanding aliases or .forward files.
|
||||
/* .IP "\fBsticky_owner_alias (yes)\fR"
|
||||
/* When expanding a \fBlocal\fR(8) alias that has an owner alias (see
|
||||
/* owner-\fIname\fR discussion in \fBaliases\fR(5)), use the owner information
|
||||
/* even when the expansion invokes a subordinate alias that has no
|
||||
/* owner alias.
|
||||
/* DELIVERY METHOD CONTROLS
|
||||
/* .ad
|
||||
/* .fi
|
||||
@ -620,7 +615,6 @@ int var_mailtool_compat;
|
||||
char *var_mailbox_lock;
|
||||
int var_mailbox_limit;
|
||||
bool var_frozen_delivered;
|
||||
bool var_sticky_owner_alias;
|
||||
|
||||
int local_cmd_deliver_mask;
|
||||
int local_file_deliver_mask;
|
||||
@ -861,7 +855,6 @@ int main(int argc, char **argv)
|
||||
VAR_STAT_HOME_DIR, DEF_STAT_HOME_DIR, &var_stat_home_dir,
|
||||
VAR_MAILTOOL_COMPAT, DEF_MAILTOOL_COMPAT, &var_mailtool_compat,
|
||||
VAR_FROZEN_DELIVERED, DEF_FROZEN_DELIVERED, &var_frozen_delivered,
|
||||
VAR_STICKY_OWNER_ALIAS, DEF_STICKY_OWNER_ALIAS, &var_sticky_owner_alias,
|
||||
0,
|
||||
};
|
||||
|
||||
|
@ -251,7 +251,21 @@ SMTP_RESP *smtp_chat_resp(SMTP_SESSION *session)
|
||||
if (*cp == ' ' || *cp == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX Do not ignore garbage when ESMTP command pipelining is turned
|
||||
* on. After sending ".<CR><LF>QUIT<CR><LF>", Postfix might recognize
|
||||
* the server's 2XX QUIT reply as a 2XX END-OF-DATA reply after
|
||||
* garbage, causing mail to be lost. Instead, make a long jump so
|
||||
* that all recipients of multi-recipient mail get consistent
|
||||
* treatment.
|
||||
*/
|
||||
session->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
if (session->features & SMTP_FEATURE_PIPELINING) {
|
||||
msg_warn("non-SMTP response from %s: %s",
|
||||
session->namaddr, STR(session->buffer));
|
||||
vstream_longjmp(session->stream, SMTP_ERR_PROTO);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -432,6 +432,12 @@ int smtp_stream_except(SMTP_STATE *state, int code, const char *description)
|
||||
"conversation with %s timed out while %s",
|
||||
session->namaddr, description);
|
||||
break;
|
||||
case SMTP_ERR_PROTO:
|
||||
smtp_fill_dsn(state, &dsn, DSN_BY_LOCAL_MTA,
|
||||
"4.5.0", "403 remote protocol error",
|
||||
"protocol error in reply from %s while %s",
|
||||
session->namaddr, description);
|
||||
break;
|
||||
}
|
||||
return (smtp_bulk_fail(state, &dsn, SMTP_THROTTLE));
|
||||
}
|
||||
|
@ -275,6 +275,7 @@ smtpd_peer.o: ../../include/argv.h
|
||||
smtpd_peer.o: ../../include/attr.h
|
||||
smtpd_peer.o: ../../include/inet_proto.h
|
||||
smtpd_peer.o: ../../include/iostuff.h
|
||||
smtpd_peer.o: ../../include/mail_params.h
|
||||
smtpd_peer.o: ../../include/mail_proto.h
|
||||
smtpd_peer.o: ../../include/mail_stream.h
|
||||
smtpd_peer.o: ../../include/msg.h
|
||||
|
@ -415,6 +415,11 @@
|
||||
/* The maximal number of lines in the Postfix SMTP server command history
|
||||
/* before it is flushed upon receipt of EHLO, RSET, or end of DATA.
|
||||
/* .PP
|
||||
/* Available in Postfix version 2.3 and later:
|
||||
/* .IP "\fBsmtpd_peername_lookup (yes)\fR"
|
||||
/* Attempt to look up the SMTP client hostname, and verify that
|
||||
/* the name matches the client IP address.
|
||||
/* .PP
|
||||
/* The per SMTP client connection count and request rate limits are
|
||||
/* implemented in co-operation with the \fBanvil\fR(8) service, and
|
||||
/* are available in Postfix version 2.2 and later.
|
||||
@ -435,6 +440,11 @@
|
||||
/* .IP "\fBsmtpd_client_event_limit_exceptions ($mynetworks)\fR"
|
||||
/* Clients that are excluded from connection count, connection rate,
|
||||
/* or SMTP request rate restrictions.
|
||||
/* .PP
|
||||
/* Available in Postfix version 2.3 and later:
|
||||
/* .IP "\fBsmtpd_client_new_tls_session_rate_limit (0)\fR"
|
||||
/* The maximal number of new (i.e., uncached) TLS sessions that any
|
||||
/* client is allowed to negotiate with this service per time unit.
|
||||
/* TARPIT CONTROLS
|
||||
/* .ad
|
||||
/* .fi
|
||||
@ -912,6 +922,7 @@ int var_smtpd_crate_limit;
|
||||
int var_smtpd_cconn_limit;
|
||||
int var_smtpd_cmail_limit;
|
||||
int var_smtpd_crcpt_limit;
|
||||
int var_smtpd_cntls_limit;
|
||||
char *var_smtpd_hoggers;
|
||||
char *var_local_rwr_clients;
|
||||
char *var_smtpd_ehlo_dis_words;
|
||||
@ -933,6 +944,8 @@ char *var_smtpd_sasl_tls_opts;
|
||||
|
||||
#endif
|
||||
|
||||
bool var_smtpd_peername_lookup;
|
||||
|
||||
/*
|
||||
* Silly little macros.
|
||||
*/
|
||||
@ -982,6 +995,7 @@ int smtpd_input_transp_mask;
|
||||
static void helo_reset(SMTPD_STATE *);
|
||||
static void mail_reset(SMTPD_STATE *);
|
||||
static void rcpt_reset(SMTPD_STATE *);
|
||||
static void tls_reset(SMTPD_STATE *);
|
||||
static void chat_reset(SMTPD_STATE *, int);
|
||||
|
||||
/*
|
||||
@ -3025,6 +3039,25 @@ static void chat_reset(SMTPD_STATE *state, int threshold)
|
||||
|
||||
static void smtpd_start_tls(SMTPD_STATE *state)
|
||||
{
|
||||
int rate;
|
||||
|
||||
/*
|
||||
* XXX The client event count/rate control must be consistent in its use
|
||||
* of client address information in connect and disconnect events. For
|
||||
* now we exclude xclient authorized hosts from event count/rate control.
|
||||
*/
|
||||
if (SMTPD_STAND_ALONE(state) == 0
|
||||
&& !xclient_allowed
|
||||
&& anvil_clnt
|
||||
&& var_smtpd_cntls_limit > 0
|
||||
&& !namadr_list_match(hogger_list, state->name, state->addr)
|
||||
&& anvil_clnt_newtls_stat(anvil_clnt, state->service, state->addr,
|
||||
&rate) == ANVIL_STAT_OK
|
||||
&& rate > var_smtpd_cntls_limit) {
|
||||
msg_warn("Refusing STARTTLS request from %s for service %s",
|
||||
state->namaddr, state->service);
|
||||
vstream_longjmp(state->client, SMTP_ERR_EOF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper mode uses a dedicated port and always requires TLS.
|
||||
@ -3037,9 +3070,30 @@ static void smtpd_start_tls(SMTPD_STATE *state)
|
||||
* verification unless TLS is required.
|
||||
*/
|
||||
state->tls_context =
|
||||
tls_server_start(smtpd_tls_ctx, state->client,
|
||||
var_smtpd_starttls_tmout, state->name, state->addr,
|
||||
(var_smtpd_tls_req_ccert && state->tls_enforce_tls));
|
||||
tls_server_start(smtpd_tls_ctx, state->client,
|
||||
var_smtpd_starttls_tmout, state->name, state->addr,
|
||||
(var_smtpd_tls_req_ccert && state->tls_enforce_tls));
|
||||
|
||||
/*
|
||||
* XXX The client event count/rate control must be consistent in its use
|
||||
* of client address information in connect and disconnect events. For
|
||||
* now we exclude xclient authorized hosts from event count/rate control.
|
||||
*/
|
||||
if (state->tls_context
|
||||
&& state->tls_context->session_reused == 0
|
||||
&& SMTPD_STAND_ALONE(state) == 0
|
||||
&& !xclient_allowed
|
||||
&& anvil_clnt
|
||||
&& var_smtpd_cntls_limit > 0
|
||||
&& !namadr_list_match(hogger_list, state->name, state->addr)
|
||||
&& anvil_clnt_newtls(anvil_clnt, state->service, state->addr,
|
||||
&rate) == ANVIL_STAT_OK
|
||||
&& rate > var_smtpd_cntls_limit) {
|
||||
msg_warn("Too many uncached TLS sessions: "
|
||||
"%d from %s for service %s",
|
||||
rate, state->namaddr, state->service);
|
||||
tls_reset(state);
|
||||
}
|
||||
|
||||
/*
|
||||
* When the TLS handshake fails, the conversation is in an unknown state.
|
||||
@ -3587,7 +3641,8 @@ static void post_jail_init(char *unused_name, char **unused_argv)
|
||||
* Connection rate management.
|
||||
*/
|
||||
if (var_smtpd_crate_limit || var_smtpd_cconn_limit
|
||||
|| var_smtpd_cmail_limit || var_smtpd_crcpt_limit)
|
||||
|| var_smtpd_cmail_limit || var_smtpd_crcpt_limit
|
||||
|| var_smtpd_cntls_limit)
|
||||
anvil_clnt = anvil_clnt_create();
|
||||
}
|
||||
|
||||
@ -3625,6 +3680,7 @@ int main(int argc, char **argv)
|
||||
VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0,
|
||||
VAR_SMTPD_CMAIL_LIMIT, DEF_SMTPD_CMAIL_LIMIT, &var_smtpd_cmail_limit, 0, 0,
|
||||
VAR_SMTPD_CRCPT_LIMIT, DEF_SMTPD_CRCPT_LIMIT, &var_smtpd_crcpt_limit, 0, 0,
|
||||
VAR_SMTPD_CNTLS_LIMIT, DEF_SMTPD_CNTLS_LIMIT, &var_smtpd_cntls_limit, 0, 0,
|
||||
#ifdef USE_TLS
|
||||
VAR_SMTPD_TLS_CCERT_VD, DEF_SMTPD_TLS_CCERT_VD, &var_smtpd_tls_ccert_vd, 0, 0,
|
||||
#endif
|
||||
@ -3664,6 +3720,7 @@ int main(int argc, char **argv)
|
||||
VAR_SMTPD_TLS_RCERT, DEF_SMTPD_TLS_RCERT, &var_smtpd_tls_req_ccert,
|
||||
VAR_SMTPD_TLS_RECHEAD, DEF_SMTPD_TLS_RECHEAD, &var_smtpd_tls_received_header,
|
||||
#endif
|
||||
VAR_SMTPD_PEERNAME_LOOKUP, DEF_SMTPD_PEERNAME_LOOKUP, &var_smtpd_peername_lookup,
|
||||
0,
|
||||
};
|
||||
static CONFIG_STR_TABLE str_table[] = {
|
||||
|
@ -118,6 +118,7 @@
|
||||
|
||||
#include <mail_proto.h>
|
||||
#include <valid_mailhost_addr.h>
|
||||
#include <mail_params.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@ -251,8 +252,19 @@ void smtpd_peer_init(SMTPD_STATE *state)
|
||||
state->name_status = code; \
|
||||
}
|
||||
|
||||
if ((aierr = sockaddr_to_hostname(sa, sa_len, &client_name,
|
||||
(MAI_SERVNAME_STR *) 0, 0)) != 0) {
|
||||
if (var_smtpd_peername_lookup == 0) {
|
||||
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||
state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||
#ifdef FORWARD_CLIENT_NAME
|
||||
state->forward_name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||
#endif
|
||||
state->name_status = SMTPD_PEER_CODE_PERM;
|
||||
state->reverse_name_status = SMTPD_PEER_CODE_PERM;
|
||||
#ifdef FORWARD_CLIENT_NAME
|
||||
state->forward_name_status = SMTPD_PEER_CODE_PERM;
|
||||
#endif
|
||||
} else if ((aierr = sockaddr_to_hostname(sa, sa_len, &client_name,
|
||||
(MAI_SERVNAME_STR *) 0, 0)) != 0) {
|
||||
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||
state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||
#ifdef FORWARD_CLIENT_NAME
|
||||
|
@ -56,7 +56,8 @@ typedef struct {
|
||||
const char *cipher_name;
|
||||
int cipher_usebits;
|
||||
int cipher_algbits;
|
||||
int log_level;
|
||||
int log_level; /* TLS library logging level */
|
||||
int session_reused; /* this session was reused */
|
||||
} TLScontext_t;
|
||||
|
||||
#define TLS_BIO_BUFSIZE 8192
|
||||
|
@ -693,6 +693,12 @@ TLScontext_t *tls_client_start(SSL_CTX *client_ctx, VSTREAM *stream,
|
||||
if (var_smtp_tls_loglevel < 4)
|
||||
BIO_set_callback(SSL_get_rbio(TLScontext->con), 0);
|
||||
|
||||
/*
|
||||
* The caller may want to know if this session was reused or if a new
|
||||
* session was negotiated.
|
||||
*/
|
||||
TLScontext->session_reused = SSL_session_reused(TLScontext->con);
|
||||
|
||||
/*
|
||||
* Do peername verification if requested and extract useful information
|
||||
* from the certificate for later use.
|
||||
|
@ -564,6 +564,12 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
|
||||
if (var_smtpd_tls_loglevel < 4)
|
||||
BIO_set_callback(SSL_get_rbio(TLScontext->con), 0);
|
||||
|
||||
/*
|
||||
* The caller may want to know if this session was reused or if a new
|
||||
* session was negotiated.
|
||||
*/
|
||||
TLScontext->session_reused = SSL_session_reused(TLScontext->con);
|
||||
|
||||
/*
|
||||
* Let's see whether a peer certificate is available and what is the
|
||||
* actual information. We want to save it for later use.
|
||||
@ -618,6 +624,8 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
|
||||
*/
|
||||
if (requirecert) {
|
||||
if (!TLScontext->peer_verified || !TLScontext->peer_CN) {
|
||||
if (TLScontext->session_reused == 0)
|
||||
msg_panic("tls_server_start: peer was not verified");
|
||||
msg_info("Re-used session without peer certificate removed");
|
||||
uncache_session(server_ctx, TLScontext);
|
||||
tls_free_context(TLScontext);
|
||||
|
@ -15,7 +15,8 @@
|
||||
/* DICT *ptr;
|
||||
/* DESCRIPTION
|
||||
/* dict_alloc() allocates memory for a dictionary structure of
|
||||
/* \fIsize\fR bytes, initializes all properties to default settings,
|
||||
/* \fIsize\fR bytes, initializes all generic dictionary
|
||||
/* properties to default settings,
|
||||
/* and installs default methods that do not support any operation.
|
||||
/* The caller is supposed to override the default methods with
|
||||
/* ones that it supports.
|
||||
|
Loading…
x
Reference in New Issue
Block a user