From a2244a0dd09744cd57da13c47b3f5db7aba9bf71 Mon Sep 17 00:00:00 2001
From: Wietse Venema
Date: Tue, 30 Nov 2010 00:00:00 -0500
Subject: [PATCH] postfix-2.8-20101130
---
postfix/HISTORY | 18 +
postfix/README_FILES/POSTSCREEN_README | 98 ++---
postfix/RELEASE_NOTES | 10 +-
postfix/WISHLIST | 5 -
postfix/html/POSTSCREEN_README.html | 71 ++--
postfix/html/postconf.5.html | 84 ++--
postfix/html/postscreen.8.html | 45 ++-
postfix/man/man5/postconf.5 | 77 ++--
postfix/man/man8/postscreen.8 | 3 +
postfix/mantools/postlink | 1 +
postfix/proto/POSTSCREEN_README.html | 71 ++--
postfix/proto/postconf.proto | 80 ++--
postfix/src/global/mail_params.h | 4 +
postfix/src/global/mail_version.h | 2 +-
postfix/src/postscreen/Makefile.in | 9 +
postfix/src/postscreen/postscreen.c | 38 +-
postfix/src/postscreen/postscreen.h | 17 +-
postfix/src/postscreen/postscreen_dnsbl.c | 12 +-
postfix/src/postscreen/postscreen_early.c | 12 +-
postfix/src/postscreen/postscreen_misc.c | 10 +-
postfix/src/postscreen/postscreen_send.c | 8 +-
postfix/src/postscreen/postscreen_smtpd.c | 30 +-
postfix/src/postscreen/postscreen_state.c | 23 ++
postfix/src/postscreen/postscreen_tests.c | 1 -
postfix/src/util/Makefile.in | 27 +-
postfix/src/util/ip_lmatch.c | 450 ----------------------
postfix/src/util/ip_lmatch.h | 35 --
postfix/src/util/ip_lmatch.in | 21 -
postfix/src/util/ip_lmatch.ref | 51 ---
postfix/src/util/ip_match.c | 21 +-
postfix/src/util/ip_match.in | 1 +
postfix/src/util/ip_match.ref | 2 +
32 files changed, 483 insertions(+), 854 deletions(-)
delete mode 100644 postfix/src/util/ip_lmatch.c
delete mode 100644 postfix/src/util/ip_lmatch.h
delete mode 100644 postfix/src/util/ip_lmatch.in
delete mode 100644 postfix/src/util/ip_lmatch.ref
diff --git a/postfix/HISTORY b/postfix/HISTORY
index 960ad72bd..793c2aab9 100644
--- a/postfix/HISTORY
+++ b/postfix/HISTORY
@@ -16176,3 +16176,21 @@ Apologies for any names omitted.
Cleanup: don't log "blocked using example.com=127.0.0.1",
just log the domain name. File: smtpd/smtpd_check.c.
+
+20101129
+
+ Cleanup: postscreen_client_connection_count_limit (default:
+ $smtpd_client_connection_count_limit) to limit the number
+ of connections from the same IP address to the postscreen(8)
+ daemon. Files: postscreen/postscreen.c, postscreen/postscreen.h,
+ postscreen/postscreen_state.c.
+
+20101130
+
+ Cleanup: all postscreen(8) logging now reports the client
+ as [address]:port. This requires an update of tools that
+ process postscreen logging. Files: postscreen/*.c,
+ proto/POSTSCREEN_README.html.
+
+ Cleanup: polishing recent documentation and code. Files:
+ postscreen/postscreen_dnsbl.c, util/ip_match.c.
diff --git a/postfix/README_FILES/POSTSCREEN_README b/postfix/README_FILES/POSTSCREEN_README
index d06b7237c..a03ebe34a 100644
--- a/postfix/README_FILES/POSTSCREEN_README
+++ b/postfix/README_FILES/POSTSCREEN_README
@@ -93,9 +93,10 @@ PPeerrmmaanneenntt wwhhiitteelliisstt tteesstt
The postscreen_whitelist_networks parameter (default: $mynetworks) specifies a
permanent whitelist for SMTP client IP addresses. When the SMTP client address
-matches the permanent whitelist, this is logged as:
+matches the permanent whitelist, postscreen(8) logs this with the client
+address and port number as:
- WWHHIITTEELLIISSTTEEDD address
+ WWHHIITTEELLIISSTTEEDD [address]:port
The action is not configurable: immediately hand off the connection to a
Postfix SMTP server process.
@@ -105,9 +106,9 @@ PPeerrmmaanneenntt bbllaacckklliisstt tteesstt
The postscreen_blacklist_networks parameter (default: empty) specifies a
permanent blacklist for SMTP client IP addresses. The address syntax is as with
mynetworks. When the SMTP client address matches the permanent blacklist,
-postscreen(8) logs this as:
+postscreen(8) logs this with the client address and port number as:
- BBLLAACCKKLLIISSTTEEDD address
+ BBLLAACCKKLLIISSTTEEDD [address]:port
The postscreen_blacklist_action parameter specifies the action that is taken
next. See "When tests fail before the 220 SMTP server greeting" below.
@@ -121,9 +122,9 @@ whitelist. The temporary whitelist is not used for SMTP client addresses that
appear on the permanent blacklist or whitelist.
When the SMTP client address appears on the temporary whitelist, postscreen(8)
-logs this as:
+logs this with the client address and port number as:
- PPAASSSS OOLLDD address
+ PPAASSSS OOLLDD [address]:port
The action is not configurable: immediately hand off the connection to a
Postfix SMTP server process. The client is excluded from further tests until
@@ -174,12 +175,12 @@ postscreen_whitelist_networks feature or else specify an empty teaser banner:
When an SMTP client sends a command before the postscreen_greet_wait time has
elapsed, postscreen(8) logs this as:
- PPRREEGGRREEEETT count aafftteerr time ffrroomm address text...
+ PPRREEGGRREEEETT count aafftteerr time ffrroomm [address]:port text...
-Translation: the client at address sent count bytes before its turn to speak.
-This happened time seconds after the postscreen_greet_wait timer was started.
-The text is what the client sent (truncated to 100 bytes, and with non-
-printable characters replaced with "?").
+Translation: the client at [address]:port sent count bytes before its turn to
+speak. This happened time seconds after the postscreen_greet_wait timer was
+started. The text is what the client sent (truncated to 100 bytes, and with
+non-printable characters replaced with "?").
The postscreen_greet_action parameter specifies the action that is taken next.
See "When tests fail before the 220 SMTP server greeting" below.
@@ -199,9 +200,10 @@ When the postscreen_greet_wait time has elapsed, and the combined DNSBL score
is equal to or greater than the postscreen_dnsbl_threshold parameter value,
postscreen(8) logs this as:
- DDNNSSBBLL rraannkk count ffoorr address
+ DDNNSSBBLL rraannkk count ffoorr [address]:port
-Translation: the SMTP client at address has a combined DNSBL score of count.
+Translation: the SMTP client at [address]:port has a combined DNSBL score of
+count.
The postscreen_dnsbl_action parameter specifies the action that is taken when
the combined DNSBL score is equal to or greater than the threshold. See "When
@@ -278,11 +280,11 @@ in SMTP engine anyway. This is to make postscreen(8) logging more informative.
When a client sends multiple commands, postscreen(8) logs this as:
- CCOOMMMMAANNDD PPIIPPEELLIINNIINNGG aafftteerr time ffrroomm address
+ CCOOMMMMAANNDD PPIIPPEELLIINNIINNGG aafftteerr time ffrroomm [address]:port
-Translation: the SMTP client at address sent multiple SMTP commands, instead of
-sending one command and then waiting for the server to reply. This happened
-time seconds after the "220 " server greeting was sent.
+Translation: the SMTP client at [address]:port sent multiple SMTP commands,
+instead of sending one command and then waiting for the server to reply. This
+happened time seconds after the "220 " server greeting was sent.
The postscreen_pipelining_action parameter specifies the action that is taken
next. See "When tests fail after the 220 SMTP server greeting" below.
@@ -306,9 +308,9 @@ in SMTP engine anyway. This is to make postscreen(8) logging more informative.
When a client sends non-SMTP commands, postscreen(8) logs this as:
- NNOONN--SSMMTTPP CCOOMMMMAANNDD ffrroomm address command
+ NNOONN--SSMMTTPP CCOOMMMMAANNDD ffrroomm [address]:port command
-Translation: the SMTP client at address sent a command that matches the
+Translation: the SMTP client at [address]:port sent a command that matches the
postscreen_forbidden_commands parameter, or that has the syntax of a message
header label.
@@ -330,10 +332,10 @@ in SMTP engine anyway. This is to make postscreen(8) logging more informative.
When a client sends bare newline characters, postscreen(8) logs this as:
- BBAARREE NNEEWWLLIINNEE ffrroomm address
+ BBAARREE NNEEWWLLIINNEE ffrroomm [address]:port
-Translation: the SMTP client at address sent a bare newline character, that is
-newline not preceded by carriage return.
+Translation: the SMTP client at [address]:port sent a bare newline character,
+that is newline not preceded by carriage return.
The postscreen_bare_newline_action parameter specifies the action that is taken
next. See "When tests fail after the 220 SMTP server greeting" below.
@@ -364,44 +366,54 @@ OOtthheerr eerrrroorrss
When an SMTP client hangs up unexpectedly during any tests, postscreen(8) logs
this as:
- HHAANNGGUUPP aafftteerr time ffrroomm address iinn test name
+ HHAANNGGUUPP aafftteerr time ffrroomm [address]:port iinn test name
-Translation: the SMTP client at address disconnected unexpectedly, time seconds
-after the start of the test named test name.
+Translation: the SMTP client at [address]:port disconnected unexpectedly, time
+seconds after the start of the test named test name.
The following errors are reported by the built-in SMTP engine. This engine
never accepts mail, therefore it has per-session limits on the number of
commands and on the session length.
- CCOOMMMMAANNDD TTIIMMEE LLIIMMIITT ffrroomm address
+ CCOOMMMMAANNDD TTIIMMEE LLIIMMIITT ffrroomm [address]:port
-Translation: the SMTP client at address reached the per-command time limit as
-specified with the postscreen_command_time_limit parameter. The session is
-terminated immediately.
-
- CCOOMMMMAANNDD CCOOUUNNTT LLIIMMIITT ffrroomm address
-
-Translation: the SMTP client at address reached the per-session command count
-limit as specified with the postscreen_command_count_limit parameter. The
+Translation: the SMTP client at [address]:port reached the per-command time
+limit as specified with the postscreen_command_time_limit parameter. The
session is terminated immediately.
- CCOOMMMMAANNDD LLEENNGGTTHH LLIIMMIITT ffrroomm address
+ CCOOMMMMAANNDD CCOOUUNNTT LLIIMMIITT ffrroomm [address]:port
-Translation: the SMTP client at address reached the per-command length limit,
-as specified with the line_length_limit parameter. The session is terminated
-immediately.
+Translation: the SMTP client at [address]:port reached the per-session command
+count limit as specified with the postscreen_command_count_limit parameter. The
+session is terminated immediately.
+
+ CCOOMMMMAANNDD LLEENNGGTTHH LLIIMMIITT ffrroomm [address]:port
+
+Translation: the SMTP client at [address]:port reached the per-command length
+limit, as specified with the line_length_limit parameter. The session is
+terminated immediately.
+
+When an SMTP client makes too many connections at the same time, or when all
+postscreen(8) ports are busy, postscreen(8) rejects the connection with a 421
+status code and logs:
+
+ NNOOQQUUEEUUEE:: rreejjeecctt:: CCOONNNNEECCTT ffrroomm [address]:port:: ttoooo mmaannyy ccoonnnneeccttiioonnss
+ NNOOQQUUEEUUEE:: rreejjeecctt:: CCOONNNNEECCTT ffrroomm [address]:port:: aallll sseerrvveerr ppoorrttss bbuussyy
+
+The postscreen_client_connection_count_limit and postscreen_pre_queue_limit
+parameters control these limits.
WWhheenn aallll tteessttss ssuucccceeeedd
When a new SMTP client passes all tests (i.e. it is not whitelisted via some
mechanism), postscreen(8) logs this as:
- PPAASSSS NNEEWW address
+ PPAASSSS NNEEWW [address]:port
-Where address is the client IP address. Then, postscreen(8) creates a temporary
-whitelist entry that excludes the client IP address from further tests until
-the temporary whitelist entry expires, as controlled with the postscreen_*_ttl
-parameters.
+Where [address]:port are the client IP address and port. Then, postscreen(8)
+creates a temporary whitelist entry that excludes the client IP address from
+further tests until the temporary whitelist entry expires, as controlled with
+the postscreen_*_ttl parameters.
When no "deep protocol tests" are configured, postscreen(8) hands off the
"live" connection to a Postfix SMTP server process. The client can then
diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES
index c22627260..501e4baac 100644
--- a/postfix/RELEASE_NOTES
+++ b/postfix/RELEASE_NOTES
@@ -33,12 +33,20 @@ This is supported only when the default value is stress-dependent
postscreen parameters always evaluate as if the stress value is
equal to the empty string.
+Incompatibility with snapshot 20101130
+======================================
+
+The postscreen(8) daemon now logs the client as [address]:port.
+The port helps to distinguish between simultaneous sessions from
+the same address, and the [] allow the same tool to be used with
+old and new format logfiles, without producing errors for IPv6.
+
Major changes with snapshot 20101126
====================================
Support for address patterns in DNSBL and DNSWL lookup results.
-For example, "reject_rbl_client example.com = 127.0.0.[2,4,6..8]"
+For example, "reject_rbl_client example.com=127.0.0.[2,4,6..8]"
will reject clients when the lookup result is 127.0.0.2, 127.0.0.4,
127.0.0.6, 127.0.0.7, or 127.0.0.8.
diff --git a/postfix/WISHLIST b/postfix/WISHLIST
index a57d28a59..e9dd7ac95 100644
--- a/postfix/WISHLIST
+++ b/postfix/WISHLIST
@@ -4,13 +4,8 @@ Wish list:
anvil rate limit for sasl_username.
- postscreen per-client connection count limit.
-
smtpd xclient option for sasl_username.
- Documentation: add a note that smtpd_helo_required=yes is
- needed to really enforce HELO restrictions.
-
Use different ipc_timeout settings for email message
transactions (smtpd, pickup)->cleanup and for quick query/reply
transactions such as address rewriting/resolution.
diff --git a/postfix/html/POSTSCREEN_README.html b/postfix/html/POSTSCREEN_README.html
index 4f2a1fd18..b59eecd13 100644
--- a/postfix/html/POSTSCREEN_README.html
+++ b/postfix/html/POSTSCREEN_README.html
@@ -131,11 +131,11 @@ handling of known clients.
The postscreen_whitelist_networks parameter (default: $mynetworks)
specifies a permanent whitelist for SMTP client IP addresses. When
-the SMTP client address matches the permanent whitelist, this is
-logged as:
+the SMTP client address matches the permanent whitelist, postscreen(8)
+logs this with the client address and port number as:
- WHITELISTED address
+ WHITELISTED [address]:port
The action is not configurable: immediately hand off the
@@ -146,10 +146,11 @@ connection to a Postfix SMTP server process.
The postscreen_blacklist_networks parameter (default: empty)
specifies a permanent blacklist for SMTP client IP addresses. The
address syntax is as with mynetworks. When the SMTP client address
-matches the permanent blacklist, postscreen(8) logs this as:
+matches the permanent blacklist, postscreen(8) logs this with the
+client address and port number as:
- BLACKLISTED address
+ BLACKLISTED [address]:port
The postscreen_blacklist_action parameter specifies the action
@@ -166,10 +167,11 @@ temporary whitelist is not used for SMTP client addresses
that appear on the permanent blacklist or whitelist.
When the SMTP client address appears on the temporary
-whitelist, postscreen(8) logs this as:
+whitelist, postscreen(8) logs this with the client address and port
+number as:
- PASS OLD address
+ PASS OLD [address]:port
The action is not configurable: immediately hand off the
@@ -238,10 +240,10 @@ an empty teaser banner:
- PREGREET count after time from address text...
+ PREGREET count after time from [address]:port text...
- Translation: the client at address sent count
+
Translation: the client at [address]:port sent count
bytes before its turn to speak. This happened time seconds
after the postscreen_greet_wait timer was started. The text
is what the client sent (truncated to 100 bytes, and with non-printable
@@ -271,10 +273,10 @@ DNSBL score is equal to or greater than the postscreen(8) logs this as:
- DNSBL rank count for address
+ DNSBL rank count for [address]:port
- Translation: the SMTP client at address has a combined
+
Translation: the SMTP client at [address]:port has a combined
DNSBL score of count.
The postscreen_dnsbl_action parameter specifies the action that
@@ -380,10 +382,10 @@ logging more informative.
as:
- COMMAND PIPELINING after time from address
+ COMMAND PIPELINING after time from [address]:port
- Translation: the SMTP client at address sent multiple
+
Translation: the SMTP client at [address]:port sent multiple
SMTP commands, instead of sending one command and then waiting for
the server to reply. This happened time seconds after the
"220 " server greeting was sent.
@@ -416,10 +418,10 @@ logging more informative.
as:
- NON-SMTP COMMAND from address command
+ NON-SMTP COMMAND from [address]:port command
- Translation: the SMTP client at address sent a
+
Translation: the SMTP client at [address]:port sent a
command that matches the postscreen_forbidden_commands
parameter, or that has the syntax of a message header label.
@@ -448,10 +450,10 @@ this as:
- BARE NEWLINE from address
+ BARE NEWLINE from [address]:port
- Translation: the SMTP client at address sent a bare
+
Translation: the SMTP client at [address]:port sent a bare
newline character, that is newline not preceded by carriage
return.
@@ -499,10 +501,10 @@ feature.
postscreen(8) logs this as:
- HANGUP after time from address in test name
+ HANGUP after time from [address]:port in test name
- Translation: the SMTP client at address disconnected
+
Translation: the SMTP client at [address]:port disconnected
unexpectedly, time seconds after the start of the
test named test name.
@@ -513,7 +515,7 @@ allowed to pass any tests, and postscreen(8) lo
with the remaining amount of penalty time as:
- PENALTY time for address
+ PENALTY time for [address]:port
During this time, all attempts by the client to deliver mail
@@ -526,40 +528,53 @@ This engine never accepts mail, therefore it has per-session limits
on the number of commands and on the session length.
- COMMAND TIME LIMIT from address
+ COMMAND TIME LIMIT from [address]:port
- Translation: the SMTP client at address reached the
+
Translation: the SMTP client at [address]:port reached the
per-command time limit as specified with the postscreen_command_time_limit
parameter. The session is terminated immediately.
- COMMAND COUNT LIMIT from address
+ COMMAND COUNT LIMIT from [address]:port
- Translation: the SMTP client at address reached the
+
Translation: the SMTP client at [address]:port reached the
per-session command count limit as specified with the
postscreen_command_count_limit parameter. The session is terminated
immediately.
- COMMAND LENGTH LIMIT from address
+ COMMAND LENGTH LIMIT from [address]:port
- Translation: the SMTP client at address reached the
+
Translation: the SMTP client at [address]:port reached the
per-command length limit, as specified with the line_length_limit
parameter. The session is terminated immediately.
+ When an SMTP client makes too many connections at the same time,
+or when all postscreen(8) ports are busy, postscreen(8) rejects the
+connection with a 421 status code and logs:
+
+
+ NOQUEUE: reject: CONNECT from [address]:port: too many connections
+ NOQUEUE: reject: CONNECT from [address]:port: all server ports busy
+
+
+ The postscreen_client_connection_count_limit and
+postscreen_pre_queue_limit parameters control these limits.
+
When a new SMTP client passes all tests (i.e. it is not whitelisted
via some mechanism), postscreen(8) logs this as:
- PASS NEW address
+ PASS NEW [address]:port
- Where address is the client IP address. Then, postscreen(8)
+
Where [address]:port are the client IP address and port.
+Then, postscreen(8)
creates a temporary whitelist entry that excludes the client IP
address from further tests until the temporary whitelist entry
expires, as controlled with the postscreen_*_ttl parameters.
diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html
index c9d86854b..37525409a 100644
--- a/postfix/html/postconf.5.html
+++ b/postfix/html/postconf.5.html
@@ -6782,6 +6782,21 @@ that passed some deep protocol test once and never came back.
This feature is available in Postfix 2.8.
+
+
+postscreen_client_connection_count_limit
+(default: $smtpd_client_connection_count_limit)
+
+ How many simultaneous connections any client is allowed to have
+with the postscreen(8) daemon. By default, this limit is the same
+as with the Postfix SMTP server. Note that the triage process can
+take several seconds, with the time spent in postscreen_greet_wait
+delay, and with the time spent talking to the postscreen(8) built-in
+dummy SMTP protocol engine.
+
+ This feature is available in Postfix 2.8.
+
+
postscreen_command_count_limit
@@ -11680,8 +11695,8 @@ Postfix version 2.5). This feature is available with Postfix version
Reject the request when the reversed client network address is
listed with the A record "d.d.d.d" under rbl_domain
-(Postfix version 2.1 and later only). Each "d" can be a
-pattern inside "[]" that contains one or more comma-separated decimal
+(Postfix version 2.1 and later only). Each "d" is a number,
+or a pattern inside "[]" that contains one or more comma-separated
numbers or number..number ranges (Postfix version 2.8 and later).
If no "=d.d.d.d" is specified, reject the request when the
reversed client network address is listed with any A record under
@@ -11696,8 +11711,8 @@ This feature is available in Postfix 2.0 and later.
Accept the request when the reversed client network address is
listed with the A record "d.d.d.d" under dnswl_domain.
-Each "d" can be a pattern inside "[]" that contains one or
-more comma-separated decimal numbers or number..number ranges.
+Each "d" is a number, or a pattern inside "[]" that contains
+one or more comma-separated numbers or number..number ranges.
If no "=d.d.d.d" is specified, accept the request when the
reversed client network address is listed with any A record under
dnswl_domain.
For safety, permit_dnswl_client is silently
@@ -11709,8 +11724,8 @@ is available in Postfix 2.8 and later.
Reject the request when the client hostname is listed with the
A record "d.d.d.d" under rbl_domain (Postfix version
-2.1 and later only). Each "d" can be a pattern inside "[]"
-that contains one or more comma-separated decimal numbers or
+2.1 and later only). Each "d" is a number, or a pattern
+inside "[]" that contains one or more comma-separated numbers or
number..number ranges (Postfix version 2.8 and later). If no
"=d.d.d.d" is specified, reject the request when the client
hostname is listed with
@@ -11724,8 +11739,8 @@ produce better results.
Accept the request when the client hostname is listed with the
A record "d.d.d.d" under rhswl_domain. Each "d"
-can be a pattern inside "[]" that contains one or more comma-separated
-decimal numbers or number..number ranges. If no
+is a number, or a pattern inside "[]" that contains one or more
+comma-separated numbers or number..number ranges. If no
"=d.d.d.d" is specified, accept the request when the client
hostname is listed with any A record under rhswl_domain.
Caution: client name whitelisting is fragile, since the client
@@ -11741,8 +11756,8 @@ when whitelist lookup fails. This feature is available in Postfix
Reject the request when the unverified reverse client hostname
is listed with the A record "d.d.d.d" under rbl_domain.
-Each "d" can be a pattern inside "[]" that contains one or
-more comma-separated decimal numbers or number..number ranges.
+Each "d" is a number, or a pattern inside "[]" that contains
+one or more comma-separated numbers or number..number ranges.
If no "=d.d.d.d" is specified, reject the request when the
unverified reverse client hostname is listed with any A record under
rbl_domain. See the reject_rbl_client description above for
@@ -12346,50 +12361,58 @@ received with the HELO or EHLO command.
Search the specified access(5) database for the HELO or EHLO
hostname or parent domains, and execute the corresponding action.
-
+Note: specify "smtpd_helo_required = yes" to fully enforce this
+restriction.
check_helo_mx_access type:table
Search the specified access(5) database for the MX hosts for
the HELO or EHLO hostname, and execute the corresponding action.
-Note: a result of "OK" is not allowed for safety reasons. Instead,
-use DUNNO in order to exclude specific hosts from blacklists. This
-feature is available in Postfix 2.1 and later.
+Note 1: a result of "OK" is not allowed for safety reasons. Instead,
+use DUNNO in order to exclude specific hosts from blacklists. Note
+2: specify "smtpd_helo_required = yes" to fully enforce this
+restriction. This feature is available in Postfix 2.1 and later.
+
check_helo_ns_access type:table
Search the specified access(5) database for the DNS servers
for the HELO or EHLO hostname, and execute the corresponding action.
-Note: a result of "OK" is not allowed for safety reasons. Instead,
-use DUNNO in order to exclude specific hosts from blacklists. This
-feature is available in Postfix 2.1 and later.
+Note 1: a result of "OK" is not allowed for safety reasons. Instead,
+use DUNNO in order to exclude specific hosts from blacklists. Note
+2: specify "smtpd_helo_required = yes" to fully enforce this
+restriction. This feature is available in Postfix 2.1 and later.
+
reject_invalid_helo_hostname (with Postfix < 2.3: reject_invalid_hostname)
Reject the request when the HELO or EHLO hostname syntax is
-invalid.
The invalid_hostname_reject_code specifies the response
-code for rejected requests (default: 501).
+invalid. Note: specify "smtpd_helo_required = yes" to fully enforce
+this restriction.
The invalid_hostname_reject_code specifies
+the response code for rejected requests (default: 501).
reject_non_fqdn_helo_hostname (with Postfix < 2.3: reject_non_fqdn_hostname)
Reject the request when the HELO or EHLO hostname is not in
-fully-qualified domain form, as required by the RFC.
The
-non_fqdn_reject_code parameter specifies the response code for
+fully-qualified domain form, as required by the RFC. Note: specify
+"smtpd_helo_required = yes" to fully enforce this restriction.
+The non_fqdn_reject_code parameter specifies the response code for
rejected requests (default: 504).
reject_rhsbl_helo rbl_domain=d.d.d.d
Reject the request when the HELO or EHLO hostname hostname is
listed with the A record "d.d.d.d" under rbl_domain
-(Postfix version 2.1 and later only). Each "d" can be a
-pattern inside "[]" that contains one or more comma-separated decimal
+(Postfix version 2.1 and later only). Each "d" is a number,
+or a pattern inside "[]" that contains one or more comma-separated
numbers or number..number ranges (Postfix version 2.8 and later).
If no "=d.d.d.d" is
specified, reject the request when the HELO or EHLO hostname is
listed with any A record under rbl_domain. See the
reject_rbl_client description for additional RBL related configuration
-parameters. This feature is available in Postfix 2.0 and later.
-
+parameters. Note: specify "smtpd_helo_required = yes" to fully
+enforce this restriction. This feature is available in Postfix 2.0
+and later.
reject_unknown_helo_hostname (with Postfix < 2.3: reject_unknown_hostname)
@@ -12398,7 +12421,8 @@ or MX record.
The un
specifies the numerical response code for rejected requests (default:
450).
The unknown_helo_hostname_tempfail_action parameter
specifies the action after a temporary DNS error (default:
-defer_if_permit).
+defer_if_permit). Note: specify "smtpd_helo_required = yes" to fully
+enforce this restriction.
@@ -12800,8 +12824,8 @@ rejected requests (default: 504).
Reject the request when the RCPT TO domain is listed with the
A record "d.d.d.d" under rbl_domain (Postfix version
-2.1 and later only). Each "d" can be a pattern inside "[]"
-that contains one or more comma-separated decimal numbers or
+2.1 and later only). Each "d" is a number, or a pattern
+inside "[]" that contains one or more comma-separated numbers or
number..number ranges (Postfix version 2.8 and later). If no
"=d.d.d.d" is specified, reject
the request when the RCPT TO domain is listed with
@@ -13347,8 +13371,8 @@ rejected requests (default: 504).
Reject the request when the MAIL FROM domain is listed with
the A record "d.d.d.d" under rbl_domain (Postfix
-version 2.1 and later only). Each "d" can be a pattern
-inside "[]" that contains one or more comma-separated decimal numbers
+version 2.1 and later only). Each "d" is a number, or a
+pattern inside "[]" that contains one or more comma-separated numbers
or number..number ranges (Postfix version 2.8 and later). If no
"=d.d.d.d" is specified,
reject the request when the MAIL FROM domain is
diff --git a/postfix/html/postscreen.8.html b/postfix/html/postscreen.8.html
index 45a4c6f67..b3c71a8bf 100644
--- a/postfix/html/postscreen.8.html
+++ b/postfix/html/postscreen.8.html
@@ -233,41 +233,46 @@ POSTSCREEN(8) POSTSCREEN(8)
of at most this length; upon delivery, long lines
are reconstructed.
+ postscreen_client_connection_count_limit
+ ($smtpd_client_connection_count_limit)
+ How many simultaneous connections any client is
+ allowed to have with the postscreen(8) daemon.
+
postscreen_command_count_limit (20)
- The limit on the total number of commands per SMTP
- session for postscreen(8)'s built-in SMTP protocol
+ The limit on the total number of commands per SMTP
+ session for postscreen(8)'s built-in SMTP protocol
engine.
postscreen_command_time_limit (${stress?10}${stress:300}s)
- The command "read" time limit for postscreen(8)'s
+ The command "read" time limit for postscreen(8)'s
built-in SMTP protocol engine.
postscreen_post_queue_limit ($default_process_limit)
- The number of clients that can be waiting for ser-
+ The number of clients that can be waiting for ser-
vice from a real SMTP server process.
postscreen_pre_queue_limit ($default_process_limit)
- The number of non-whitelisted clients that can be
- waiting for a decision whether they will receive
+ The number of non-whitelisted clients that can be
+ waiting for a decision whether they will receive
service from a real SMTP server process.
postscreen_watchdog_timeout (10s)
- How much time a postscreen(8) process may take to
- respond to an SMTP client command or to perform a
+ How much time a postscreen(8) process may take to
+ respond to an SMTP client command or to perform a
cache operation before it is terminated by a built-
in watchdog timer.
MISCELLANEOUS CONTROLS
config_directory (see 'postconf -d' output)
- The default location of the Postfix main.cf and
+ The default location of the Postfix main.cf and
master.cf configuration files.
delay_logging_resolution_limit (2)
- The maximal number of digits after the decimal
+ The maximal number of digits after the decimal
point when logging sub-second delay values.
command_directory (see 'postconf -d' output)
- The location of all postfix administrative com-
+ The location of all postfix administrative com-
mands.
ipc_timeout (3600s)
@@ -275,24 +280,24 @@ POSTSCREEN(8) POSTSCREEN(8)
over an internal communication channel.
max_idle (100s)
- The maximum amount of time that an idle Postfix
- daemon process waits for an incoming connection
+ The maximum amount of time that an idle Postfix
+ daemon process waits for an incoming connection
before terminating voluntarily.
process_id (read-only)
- The process ID of a Postfix command or daemon
+ The process ID of a Postfix command or daemon
process.
process_name (read-only)
- The process name of a Postfix command or daemon
+ The process name of a Postfix command or daemon
process.
syslog_facility (mail)
The syslog facility of Postfix logging.
syslog_name (see 'postconf -d' output)
- 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".
SEE ALSO
@@ -304,12 +309,12 @@ POSTSCREEN(8) POSTSCREEN(8)
POSTSCREEN_README, Postfix Postscreen Howto
LICENSE
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
HISTORY
- Many ideas in postscreen(8) were explored in earlier work
- by Michael Tokarev, in OpenBSD spamd, and in MailChannels
+ Many ideas in postscreen(8) were explored in earlier work
+ by Michael Tokarev, in OpenBSD spamd, and in MailChannels
Traffic Control.
AUTHOR(S)
diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5
index 3a98c78b8..3df9798a7 100644
--- a/postfix/man/man5/postconf.5
+++ b/postfix/man/man5/postconf.5
@@ -3818,6 +3818,15 @@ Time units: s (seconds), m (minutes), h (hours), d (days), w
(weeks).
.PP
This feature is available in Postfix 2.8.
+.SH postscreen_client_connection_count_limit (default: $smtpd_client_connection_count_limit)
+How many simultaneous connections any client is allowed to have
+with the \fBpostscreen\fR(8) daemon. By default, this limit is the same
+as with the Postfix SMTP server. Note that the triage process can
+take several seconds, with the time spent in postscreen_greet_wait
+delay, and with the time spent talking to the \fBpostscreen\fR(8) built-in
+dummy SMTP protocol engine.
+.PP
+This feature is available in Postfix 2.8.
.SH postscreen_command_count_limit (default: 20)
The limit on the total number of commands per SMTP session for
\fBpostscreen\fR(8)'s built-in SMTP protocol engine. This SMTP engine
@@ -7166,8 +7175,8 @@ Postfix version 2.5). This feature is available with Postfix version
.IP "\fBreject_rbl_client \fIrbl_domain=d.d.d.d\fR\fR"
Reject the request when the reversed client network address is
listed with the A record "\fId.d.d.d\fR" under \fIrbl_domain\fR
-(Postfix version 2.1 and later only). Each "\fId\fR" can be a
-pattern inside "[]" that contains one or more comma-separated decimal
+(Postfix version 2.1 and later only). Each "\fId\fR" is a number,
+or a pattern inside "[]" that contains one or more comma-separated
numbers or number..number ranges (Postfix version 2.8 and later).
If no "\fI=d.d.d.d\fR" is specified, reject the request when the
reversed client network address is listed with any A record under
@@ -7181,8 +7190,8 @@ This feature is available in Postfix 2.0 and later.
.IP "\fBpermit_dnswl_client \fIdnswl_domain=d.d.d.d\fR\fR"
Accept the request when the reversed client network address is
listed with the A record "\fId.d.d.d\fR" under \fIdnswl_domain\fR.
-Each "\fId\fR" can be a pattern inside "[]" that contains one or
-more comma-separated decimal numbers or number..number ranges.
+Each "\fId\fR" is a number, or a pattern inside "[]" that contains
+one or more comma-separated numbers or number..number ranges.
If no "\fI=d.d.d.d\fR" is specified, accept the request when the
reversed client network address is listed with any A record under
\fIdnswl_domain\fR.
@@ -7194,8 +7203,8 @@ is available in Postfix 2.8 and later.
.IP "\fBreject_rhsbl_client \fIrbl_domain=d.d.d.d\fR\fR"
Reject the request when the client hostname is listed with the
A record "\fId.d.d.d\fR" under \fIrbl_domain\fR (Postfix version
-2.1 and later only). Each "\fId\fR" can be a pattern inside "[]"
-that contains one or more comma-separated decimal numbers or
+2.1 and later only). Each "\fId\fR" is a number, or a pattern
+inside "[]" that contains one or more comma-separated numbers or
number..number ranges (Postfix version 2.8 and later). If no
"\fI=d.d.d.d\fR" is specified, reject the request when the client
hostname is listed with
@@ -7207,8 +7216,8 @@ produce better results.
.IP "\fBpermit_rhswl_client \fIrhswl_domain=d.d.d.d\fR\fR"
Accept the request when the client hostname is listed with the
A record "\fId.d.d.d\fR" under \fIrhswl_domain\fR. Each "\fId\fR"
-can be a pattern inside "[]" that contains one or more comma-separated
-decimal numbers or number..number ranges. If no
+is a number, or a pattern inside "[]" that contains one or more
+comma-separated numbers or number..number ranges. If no
"\fI=d.d.d.d\fR" is specified, accept the request when the client
hostname is listed with any A record under \fIrhswl_domain\fR.
.br
@@ -7224,8 +7233,8 @@ when whitelist lookup fails. This feature is available in Postfix
.IP "\fBreject_rhsbl_reverse_client \fIrbl_domain=d.d.d.d\fR\fR"
Reject the request when the unverified reverse client hostname
is listed with the A record "\fId.d.d.d\fR" under \fIrbl_domain\fR.
-Each "\fId\fR" can be a pattern inside "[]" that contains one or
-more comma-separated decimal numbers or number..number ranges.
+Each "\fId\fR" is a number, or a pattern inside "[]" that contains
+one or more comma-separated numbers or number..number ranges.
If no "\fI=d.d.d.d\fR" is specified, reject the request when the
unverified reverse client hostname is listed with any A record under
\fIrbl_domain\fR. See the reject_rbl_client description above for
@@ -7666,42 +7675,49 @@ received with the HELO or EHLO command.
.IP "\fBcheck_helo_access \fItype:table\fR\fR"
Search the specified \fBaccess\fR(5) database for the HELO or EHLO
hostname or parent domains, and execute the corresponding action.
+Note: specify "smtpd_helo_required = yes" to fully enforce this
+restriction.
.IP "\fBcheck_helo_mx_access \fItype:table\fR\fR"
Search the specified \fBaccess\fR(5) database for the MX hosts for
the HELO or EHLO hostname, and execute the corresponding action.
-Note: a result of "OK" is not allowed for safety reasons. Instead,
-use DUNNO in order to exclude specific hosts from blacklists. This
-feature is available in Postfix 2.1 and later.
+Note 1: a result of "OK" is not allowed for safety reasons. Instead,
+use DUNNO in order to exclude specific hosts from blacklists. Note
+2: specify "smtpd_helo_required = yes" to fully enforce this
+restriction. This feature is available in Postfix 2.1 and later.
.IP "\fBcheck_helo_ns_access \fItype:table\fR\fR"
Search the specified \fBaccess\fR(5) database for the DNS servers
for the HELO or EHLO hostname, and execute the corresponding action.
-Note: a result of "OK" is not allowed for safety reasons. Instead,
-use DUNNO in order to exclude specific hosts from blacklists. This
-feature is available in Postfix 2.1 and later.
+Note 1: a result of "OK" is not allowed for safety reasons. Instead,
+use DUNNO in order to exclude specific hosts from blacklists. Note
+2: specify "smtpd_helo_required = yes" to fully enforce this
+restriction. This feature is available in Postfix 2.1 and later.
.IP "\fBreject_invalid_helo_hostname\fR (with Postfix < 2.3: reject_invalid_hostname)"
Reject the request when the HELO or EHLO hostname syntax is
-invalid.
+invalid. Note: specify "smtpd_helo_required = yes" to fully enforce
+this restriction.
.br
-The invalid_hostname_reject_code specifies the response
-code for rejected requests (default: 501).
+The invalid_hostname_reject_code specifies
+the response code for rejected requests (default: 501).
.IP "\fBreject_non_fqdn_helo_hostname\fR (with Postfix < 2.3: reject_non_fqdn_hostname)"
Reject the request when the HELO or EHLO hostname is not in
-fully-qualified domain form, as required by the RFC.
+fully-qualified domain form, as required by the RFC. Note: specify
+"smtpd_helo_required = yes" to fully enforce this restriction.
.br
-The
-non_fqdn_reject_code parameter specifies the response code for
+The non_fqdn_reject_code parameter specifies the response code for
rejected requests (default: 504).
.IP "\fBreject_rhsbl_helo \fIrbl_domain=d.d.d.d\fR\fR"
Reject the request when the HELO or EHLO hostname hostname is
listed with the A record "\fId.d.d.d\fR" under \fIrbl_domain\fR
-(Postfix version 2.1 and later only). Each "\fId\fR" can be a
-pattern inside "[]" that contains one or more comma-separated decimal
+(Postfix version 2.1 and later only). Each "\fId\fR" is a number,
+or a pattern inside "[]" that contains one or more comma-separated
numbers or number..number ranges (Postfix version 2.8 and later).
If no "\fI=d.d.d.d\fR" is
specified, reject the request when the HELO or EHLO hostname is
listed with any A record under \fIrbl_domain\fR. See the
reject_rbl_client description for additional RBL related configuration
-parameters. This feature is available in Postfix 2.0 and later.
+parameters. Note: specify "smtpd_helo_required = yes" to fully
+enforce this restriction. This feature is available in Postfix 2.0
+and later.
.IP "\fBreject_unknown_helo_hostname\fR (with Postfix < 2.3: reject_unknown_hostname)"
Reject the request when the HELO or EHLO hostname has no DNS A
or MX record.
@@ -7712,7 +7728,8 @@ specifies the numerical response code for rejected requests (default:
.br
The unknown_helo_hostname_tempfail_action parameter
specifies the action after a temporary DNS error (default:
-defer_if_permit).
+defer_if_permit). Note: specify "smtpd_helo_required = yes" to fully
+enforce this restriction.
.PP
Other restrictions that are valid in this context:
.IP \(bu
@@ -7939,8 +7956,8 @@ rejected requests (default: 504).
.IP "\fBreject_rhsbl_recipient \fIrbl_domain=d.d.d.d\fR\fR"
Reject the request when the RCPT TO domain is listed with the
A record "\fId.d.d.d\fR" under \fIrbl_domain\fR (Postfix version
-2.1 and later only). Each "\fId\fR" can be a pattern inside "[]"
-that contains one or more comma-separated decimal numbers or
+2.1 and later only). Each "\fId\fR" is a number, or a pattern
+inside "[]" that contains one or more comma-separated numbers or
number..number ranges (Postfix version 2.8 and later). If no
"\fI=d.d.d.d\fR" is specified, reject
the request when the RCPT TO domain is listed with
@@ -8312,8 +8329,8 @@ rejected requests (default: 504).
.IP "\fBreject_rhsbl_sender \fIrbl_domain=d.d.d.d\fR\fR"
Reject the request when the MAIL FROM domain is listed with
the A record "\fId.d.d.d\fR" under \fIrbl_domain\fR (Postfix
-version 2.1 and later only). Each "\fId\fR" can be a pattern
-inside "[]" that contains one or more comma-separated decimal numbers
+version 2.1 and later only). Each "\fId\fR" is a number, or a
+pattern inside "[]" that contains one or more comma-separated numbers
or number..number ranges (Postfix version 2.8 and later). If no
"\fI=d.d.d.d\fR" is specified,
reject the request when the MAIL FROM domain is
diff --git a/postfix/man/man8/postscreen.8 b/postfix/man/man8/postscreen.8
index c75c11feb..09ed7de90 100644
--- a/postfix/man/man8/postscreen.8
+++ b/postfix/man/man8/postscreen.8
@@ -210,6 +210,9 @@ a successful "pipelining" SMTP protocol test.
.IP "\fBline_length_limit (2048)\fR"
Upon input, long lines are chopped up into pieces of at most
this length; upon delivery, long lines are reconstructed.
+.IP "\fBpostscreen_client_connection_count_limit ($smtpd_client_connection_count_limit)\fR"
+How many simultaneous connections any client is allowed to have
+with the \fBpostscreen\fR(8) daemon.
.IP "\fBpostscreen_command_count_limit (20)\fR"
The limit on the total number of commands per SMTP session for
\fBpostscreen\fR(8)'s built-in SMTP protocol engine.
diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink
index f72c1aaeb..a20e3c207 100755
--- a/postfix/mantools/postlink
+++ b/postfix/mantools/postlink
@@ -944,6 +944,7 @@ while (<>) {
s;\bpostscreen_whitelist_networks\b;$&;g;
s;\bpostscreen_black[-]*\n*[ ]*list_networks\b;$&;g;
s;\bpostscreen_black[-]*\n*[ ]*list_action\b;$&;g;
+ s;\bpostscreen_client_connection_count_limit\b;$&;g;
# Hyperlink URLs and RFC documents
diff --git a/postfix/proto/POSTSCREEN_README.html b/postfix/proto/POSTSCREEN_README.html
index 2a7492f32..6d0c7e166 100644
--- a/postfix/proto/POSTSCREEN_README.html
+++ b/postfix/proto/POSTSCREEN_README.html
@@ -131,11 +131,11 @@ handling of known clients.
The postscreen_whitelist_networks parameter (default: $mynetworks)
specifies a permanent whitelist for SMTP client IP addresses. When
-the SMTP client address matches the permanent whitelist, this is
-logged as:
+the SMTP client address matches the permanent whitelist, postscreen(8)
+logs this with the client address and port number as:
- WHITELISTED address
+ WHITELISTED [address]:port
The action is not configurable: immediately hand off the
@@ -146,10 +146,11 @@ connection to a Postfix SMTP server process.
The postscreen_blacklist_networks parameter (default: empty)
specifies a permanent blacklist for SMTP client IP addresses. The
address syntax is as with mynetworks. When the SMTP client address
-matches the permanent blacklist, postscreen(8) logs this as:
+matches the permanent blacklist, postscreen(8) logs this with the
+client address and port number as:
- BLACKLISTED address
+ BLACKLISTED [address]:port
The postscreen_blacklist_action parameter specifies the action
@@ -166,10 +167,11 @@ temporary whitelist is not used for SMTP client addresses
that appear on the permanent blacklist or whitelist.
When the SMTP client address appears on the temporary
-whitelist, postscreen(8) logs this as:
+whitelist, postscreen(8) logs this with the client address and port
+number as:
- PASS OLD address
+ PASS OLD [address]:port
The action is not configurable: immediately hand off the
@@ -238,10 +240,10 @@ postscreen_greet_wait time has elapsed, postscreen(8) logs this as:
- PREGREET count after time from address text...
+ PREGREET count after time from [address]:port text...
- Translation: the client at address sent count
+
Translation: the client at [address]:port sent count
bytes before its turn to speak. This happened time seconds
after the postscreen_greet_wait timer was started. The text
is what the client sent (truncated to 100 bytes, and with non-printable
@@ -271,10 +273,10 @@ DNSBL score is equal to or greater than the postscreen_dnsbl_threshold
parameter value, postscreen(8) logs this as:
- DNSBL rank count for address
+ DNSBL rank count for [address]:port
- Translation: the SMTP client at address has a combined
+
Translation: the SMTP client at [address]:port has a combined
DNSBL score of count.
The postscreen_dnsbl_action parameter specifies the action that
@@ -380,10 +382,10 @@ logging more informative.
as:
- COMMAND PIPELINING after time from address
+ COMMAND PIPELINING after time from [address]:port
- Translation: the SMTP client at address sent multiple
+
Translation: the SMTP client at [address]:port sent multiple
SMTP commands, instead of sending one command and then waiting for
the server to reply. This happened time seconds after the
"220 " server greeting was sent.
@@ -416,10 +418,10 @@ logging more informative.
as:
- NON-SMTP COMMAND from address command
+ NON-SMTP COMMAND from [address]:port command
- Translation: the SMTP client at address sent a
+
Translation: the SMTP client at [address]:port sent a
command that matches the postscreen_forbidden_commands
parameter, or that has the syntax of a message header label.
@@ -448,10 +450,10 @@ this as:
- BARE NEWLINE from address
+ BARE NEWLINE from [address]:port
- Translation: the SMTP client at address sent a bare
+
Translation: the SMTP client at [address]:port sent a bare
newline character, that is newline not preceded by carriage
return.
@@ -499,10 +501,10 @@ feature.
postscreen(8) logs this as:
- HANGUP after time from address in test name
+ HANGUP after time from [address]:port in test name
- Translation: the SMTP client at address disconnected
+
Translation: the SMTP client at [address]:port disconnected
unexpectedly, time seconds after the start of the
test named test name.
@@ -513,7 +515,7 @@ allowed to pass any tests, and postscreen(8) logs each connection
with the remaining amount of penalty time as:
- PENALTY time for address
+ PENALTY time for [address]:port
During this time, all attempts by the client to deliver mail
@@ -526,40 +528,53 @@ This engine never accepts mail, therefore it has per-session limits
on the number of commands and on the session length.
- COMMAND TIME LIMIT from address
+ COMMAND TIME LIMIT from [address]:port
- Translation: the SMTP client at address reached the
+
Translation: the SMTP client at [address]:port reached the
per-command time limit as specified with the postscreen_command_time_limit
parameter. The session is terminated immediately.
- COMMAND COUNT LIMIT from address
+ COMMAND COUNT LIMIT from [address]:port
- Translation: the SMTP client at address reached the
+
Translation: the SMTP client at [address]:port reached the
per-session command count limit as specified with the
postscreen_command_count_limit parameter. The session is terminated
immediately.
- COMMAND LENGTH LIMIT from address
+ COMMAND LENGTH LIMIT from [address]:port
- Translation: the SMTP client at address reached the
+
Translation: the SMTP client at [address]:port reached the
per-command length limit, as specified with the line_length_limit
parameter. The session is terminated immediately.
+ When an SMTP client makes too many connections at the same time,
+or when all postscreen(8) ports are busy, postscreen(8) rejects the
+connection with a 421 status code and logs:
+
+
+ NOQUEUE: reject: CONNECT from [address]:port: too many connections
+ NOQUEUE: reject: CONNECT from [address]:port: all server ports busy
+
+
+ The postscreen_client_connection_count_limit and
+postscreen_pre_queue_limit parameters control these limits.
+
When a new SMTP client passes all tests (i.e. it is not whitelisted
via some mechanism), postscreen(8) logs this as:
- PASS NEW address
+ PASS NEW [address]:port
- Where address is the client IP address. Then, postscreen(8)
+
Where [address]:port are the client IP address and port.
+Then, postscreen(8)
creates a temporary whitelist entry that excludes the client IP
address from further tests until the temporary whitelist entry
expires, as controlled with the postscreen_*_ttl parameters.
diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto
index 16d9d3942..7334ea079 100644
--- a/postfix/proto/postconf.proto
+++ b/postfix/proto/postconf.proto
@@ -4879,8 +4879,8 @@ Postfix version 2.5). This feature is available with Postfix version
Reject the request when the reversed client network address is
listed with the A record "d.d.d.d" under rbl_domain
-(Postfix version 2.1 and later only). Each "d" can be a
-pattern inside "[]" that contains one or more comma-separated decimal
+(Postfix version 2.1 and later only). Each "d" is a number,
+or a pattern inside "[]" that contains one or more comma-separated
numbers or number..number ranges (Postfix version 2.8 and later).
If no "=d.d.d.d" is specified, reject the request when the
reversed client network address is listed with any A record under
@@ -4895,8 +4895,8 @@ This feature is available in Postfix 2.0 and later.
Accept the request when the reversed client network address is
listed with the A record "d.d.d.d" under dnswl_domain.
-Each "d" can be a pattern inside "[]" that contains one or
-more comma-separated decimal numbers or number..number ranges.
+Each "d" is a number, or a pattern inside "[]" that contains
+one or more comma-separated numbers or number..number ranges.
If no "=d.d.d.d" is specified, accept the request when the
reversed client network address is listed with any A record under
dnswl_domain.
For safety, permit_dnswl_client is silently
@@ -4908,8 +4908,8 @@ is available in Postfix 2.8 and later.
Reject the request when the client hostname is listed with the
A record "d.d.d.d" under rbl_domain (Postfix version
-2.1 and later only). Each "d" can be a pattern inside "[]"
-that contains one or more comma-separated decimal numbers or
+2.1 and later only). Each "d" is a number, or a pattern
+inside "[]" that contains one or more comma-separated numbers or
number..number ranges (Postfix version 2.8 and later). If no
"=d.d.d.d" is specified, reject the request when the client
hostname is listed with
@@ -4923,8 +4923,8 @@ produce better results.
Accept the request when the client hostname is listed with the
A record "d.d.d.d" under rhswl_domain. Each "d"
-can be a pattern inside "[]" that contains one or more comma-separated
-decimal numbers or number..number ranges. If no
+is a number, or a pattern inside "[]" that contains one or more
+comma-separated numbers or number..number ranges. If no
"=d.d.d.d" is specified, accept the request when the client
hostname is listed with any A record under rhswl_domain.
Caution: client name whitelisting is fragile, since the client
@@ -4940,8 +4940,8 @@ when whitelist lookup fails. This feature is available in Postfix
Reject the request when the unverified reverse client hostname
is listed with the A record "d.d.d.d" under rbl_domain.
-Each "d" can be a pattern inside "[]" that contains one or
-more comma-separated decimal numbers or number..number ranges.
+Each "d" is a number, or a pattern inside "[]" that contains
+one or more comma-separated numbers or number..number ranges.
If no "=d.d.d.d" is specified, reject the request when the
unverified reverse client hostname is listed with any A record under
rbl_domain. See the reject_rbl_client description above for
@@ -5346,50 +5346,58 @@ received with the HELO or EHLO command.
Search the specified access(5) database for the HELO or EHLO
hostname or parent domains, and execute the corresponding action.
-
+Note: specify "smtpd_helo_required = yes" to fully enforce this
+restriction.
check_helo_mx_access type:table
Search the specified access(5) database for the MX hosts for
the HELO or EHLO hostname, and execute the corresponding action.
-Note: a result of "OK" is not allowed for safety reasons. Instead,
-use DUNNO in order to exclude specific hosts from blacklists. This
-feature is available in Postfix 2.1 and later.
+Note 1: a result of "OK" is not allowed for safety reasons. Instead,
+use DUNNO in order to exclude specific hosts from blacklists. Note
+2: specify "smtpd_helo_required = yes" to fully enforce this
+restriction. This feature is available in Postfix 2.1 and later.
+
check_helo_ns_access type:table
Search the specified access(5) database for the DNS servers
for the HELO or EHLO hostname, and execute the corresponding action.
-Note: a result of "OK" is not allowed for safety reasons. Instead,
-use DUNNO in order to exclude specific hosts from blacklists. This
-feature is available in Postfix 2.1 and later.
+Note 1: a result of "OK" is not allowed for safety reasons. Instead,
+use DUNNO in order to exclude specific hosts from blacklists. Note
+2: specify "smtpd_helo_required = yes" to fully enforce this
+restriction. This feature is available in Postfix 2.1 and later.
+
reject_invalid_helo_hostname (with Postfix < 2.3: reject_invalid_hostname)
Reject the request when the HELO or EHLO hostname syntax is
-invalid.
The invalid_hostname_reject_code specifies the response
-code for rejected requests (default: 501).
+invalid. Note: specify "smtpd_helo_required = yes" to fully enforce
+this restriction.
The invalid_hostname_reject_code specifies
+the response code for rejected requests (default: 501).
reject_non_fqdn_helo_hostname (with Postfix < 2.3: reject_non_fqdn_hostname)
Reject the request when the HELO or EHLO hostname is not in
-fully-qualified domain form, as required by the RFC.
The
-non_fqdn_reject_code parameter specifies the response code for
+fully-qualified domain form, as required by the RFC. Note: specify
+"smtpd_helo_required = yes" to fully enforce this restriction.
+The non_fqdn_reject_code parameter specifies the response code for
rejected requests (default: 504).
reject_rhsbl_helo rbl_domain=d.d.d.d
Reject the request when the HELO or EHLO hostname hostname is
listed with the A record "d.d.d.d" under rbl_domain
-(Postfix version 2.1 and later only). Each "d" can be a
-pattern inside "[]" that contains one or more comma-separated decimal
+(Postfix version 2.1 and later only). Each "d" is a number,
+or a pattern inside "[]" that contains one or more comma-separated
numbers or number..number ranges (Postfix version 2.8 and later).
If no "=d.d.d.d" is
specified, reject the request when the HELO or EHLO hostname is
listed with any A record under rbl_domain. See the
reject_rbl_client description for additional RBL related configuration
-parameters. This feature is available in Postfix 2.0 and later.
-
+parameters. Note: specify "smtpd_helo_required = yes" to fully
+enforce this restriction. This feature is available in Postfix 2.0
+and later.
reject_unknown_helo_hostname (with Postfix < 2.3: reject_unknown_hostname)
@@ -5398,7 +5406,8 @@ or MX record.
The unknown_hostname_reject_code parameter
specifies the numerical response code for rejected requests (default:
450).
The unknown_helo_hostname_tempfail_action parameter
specifies the action after a temporary DNS error (default:
-defer_if_permit).
+defer_if_permit). Note: specify "smtpd_helo_required = yes" to fully
+enforce this restriction.
@@ -5674,8 +5683,8 @@ rejected requests (default: 504).
Reject the request when the RCPT TO domain is listed with the
A record "d.d.d.d" under rbl_domain (Postfix version
-2.1 and later only). Each "d" can be a pattern inside "[]"
-that contains one or more comma-separated decimal numbers or
+2.1 and later only). Each "d" is a number, or a pattern
+inside "[]" that contains one or more comma-separated numbers or
number..number ranges (Postfix version 2.8 and later). If no
"=d.d.d.d" is specified, reject
the request when the RCPT TO domain is listed with
@@ -6052,8 +6061,8 @@ rejected requests (default: 504).
Reject the request when the MAIL FROM domain is listed with
the A record "d.d.d.d" under rbl_domain (Postfix
-version 2.1 and later only). Each "d" can be a pattern
-inside "[]" that contains one or more comma-separated decimal numbers
+version 2.1 and later only). Each "d" is a number, or a
+pattern inside "[]" that contains one or more comma-separated numbers
or number..number ranges (Postfix version 2.8 and later). If no
"=d.d.d.d" is specified,
reject the request when the MAIL FROM domain is
@@ -13331,6 +13340,17 @@ it passes the test, before it can talk to a real Postfix SMTP server.
This feature is available in Postfix 2.8.
+%PARAM postscreen_client_connection_count_limit $smtpd_client_connection_count_limit
+
+ How many simultaneous connections any client is allowed to have
+with the postscreen(8) daemon. By default, this limit is the same
+as with the Postfix SMTP server. Note that the triage process can
+take several seconds, with the time spent in postscreen_greet_wait
+delay, and with the time spent talking to the postscreen(8) built-in
+dummy SMTP protocol engine.
+
+ This feature is available in Postfix 2.8.
+
%PARAM dnsblog_reply_delay 0s
A debugging aid to artifically delay DNS responses.
diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h
index 7901248cd..09b4a7d58 100644
--- a/postfix/src/global/mail_params.h
+++ b/postfix/src/global/mail_params.h
@@ -3366,6 +3366,10 @@ extern bool var_ps_helo_required;
#define DEF_PS_DISABLE_VRFY "$" VAR_DISABLE_VRFY_CMD
extern bool var_ps_disable_vrfy;
+#define VAR_PS_CCONN_LIMIT "postscreen_client_connection_count_limit"
+#define DEF_PS_CCONN_LIMIT "$" VAR_SMTPD_CCONN_LIMIT
+extern int var_ps_cconn_limit;
+
#define VAR_DNSBLOG_DELAY "dnsblog_reply_delay"
#define DEF_DNSBLOG_DELAY "0s"
extern int var_dnsblog_delay;
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index a5e6a34bb..6758078fd 100644
--- a/postfix/src/global/mail_version.h
+++ b/postfix/src/global/mail_version.h
@@ -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 "20101126"
+#define MAIL_RELEASE_DATE "20101130"
#define MAIL_VERSION_NUMBER "2.8"
#ifdef SNAPSHOT
diff --git a/postfix/src/postscreen/Makefile.in b/postfix/src/postscreen/Makefile.in
index 6957030b2..227e211a5 100644
--- a/postfix/src/postscreen/Makefile.in
+++ b/postfix/src/postscreen/Makefile.in
@@ -68,6 +68,7 @@ postscreen.o: ../../include/data_redirect.h
postscreen.o: ../../include/dict.h
postscreen.o: ../../include/dict_cache.h
postscreen.o: ../../include/events.h
+postscreen.o: ../../include/htable.h
postscreen.o: ../../include/iostuff.h
postscreen.o: ../../include/mail_conf.h
postscreen.o: ../../include/mail_params.h
@@ -93,6 +94,7 @@ postscreen_dict.o: ../../include/argv.h
postscreen_dict.o: ../../include/dict.h
postscreen_dict.o: ../../include/dict_cache.h
postscreen_dict.o: ../../include/events.h
+postscreen_dict.o: ../../include/htable.h
postscreen_dict.o: ../../include/match_list.h
postscreen_dict.o: ../../include/match_ops.h
postscreen_dict.o: ../../include/msg.h
@@ -118,6 +120,7 @@ postscreen_dnsbl.o: ../../include/mail_proto.h
postscreen_dnsbl.o: ../../include/match_list.h
postscreen_dnsbl.o: ../../include/match_ops.h
postscreen_dnsbl.o: ../../include/msg.h
+postscreen_dnsbl.o: ../../include/myaddrinfo.h
postscreen_dnsbl.o: ../../include/mymalloc.h
postscreen_dnsbl.o: ../../include/split_at.h
postscreen_dnsbl.o: ../../include/string_list.h
@@ -133,6 +136,7 @@ postscreen_early.o: ../../include/argv.h
postscreen_early.o: ../../include/dict.h
postscreen_early.o: ../../include/dict_cache.h
postscreen_early.o: ../../include/events.h
+postscreen_early.o: ../../include/htable.h
postscreen_early.o: ../../include/mail_params.h
postscreen_early.o: ../../include/match_list.h
postscreen_early.o: ../../include/match_ops.h
@@ -152,6 +156,7 @@ postscreen_misc.o: ../../include/dict.h
postscreen_misc.o: ../../include/dict_cache.h
postscreen_misc.o: ../../include/events.h
postscreen_misc.o: ../../include/format_tv.h
+postscreen_misc.o: ../../include/htable.h
postscreen_misc.o: ../../include/iostuff.h
postscreen_misc.o: ../../include/mail_params.h
postscreen_misc.o: ../../include/match_list.h
@@ -170,6 +175,7 @@ postscreen_send.o: ../../include/connect.h
postscreen_send.o: ../../include/dict.h
postscreen_send.o: ../../include/dict_cache.h
postscreen_send.o: ../../include/events.h
+postscreen_send.o: ../../include/htable.h
postscreen_send.o: ../../include/iostuff.h
postscreen_send.o: ../../include/match_list.h
postscreen_send.o: ../../include/match_ops.h
@@ -187,6 +193,7 @@ postscreen_smtpd.o: ../../include/attr.h
postscreen_smtpd.o: ../../include/dict.h
postscreen_smtpd.o: ../../include/dict_cache.h
postscreen_smtpd.o: ../../include/events.h
+postscreen_smtpd.o: ../../include/htable.h
postscreen_smtpd.o: ../../include/iostuff.h
postscreen_smtpd.o: ../../include/is_header.h
postscreen_smtpd.o: ../../include/mail_params.h
@@ -209,6 +216,7 @@ postscreen_state.o: ../../include/attr.h
postscreen_state.o: ../../include/dict.h
postscreen_state.o: ../../include/dict_cache.h
postscreen_state.o: ../../include/events.h
+postscreen_state.o: ../../include/htable.h
postscreen_state.o: ../../include/iostuff.h
postscreen_state.o: ../../include/mail_proto.h
postscreen_state.o: ../../include/mail_server.h
@@ -229,6 +237,7 @@ postscreen_tests.o: ../../include/argv.h
postscreen_tests.o: ../../include/dict.h
postscreen_tests.o: ../../include/dict_cache.h
postscreen_tests.o: ../../include/events.h
+postscreen_tests.o: ../../include/htable.h
postscreen_tests.o: ../../include/mail_params.h
postscreen_tests.o: ../../include/match_list.h
postscreen_tests.o: ../../include/match_ops.h
diff --git a/postfix/src/postscreen/postscreen.c b/postfix/src/postscreen/postscreen.c
index 74a32f4e4..37fca2746 100644
--- a/postfix/src/postscreen/postscreen.c
+++ b/postfix/src/postscreen/postscreen.c
@@ -188,6 +188,9 @@
/* .IP "\fBline_length_limit (2048)\fR"
/* Upon input, long lines are chopped up into pieces of at most
/* this length; upon delivery, long lines are reconstructed.
+/* .IP "\fBpostscreen_client_connection_count_limit ($smtpd_client_connection_count_limit)\fR"
+/* How many simultaneous connections any client is allowed to have
+/* with the \fBpostscreen\fR(8) daemon.
/* .IP "\fBpostscreen_command_count_limit (20)\fR"
/* The limit on the total number of commands per SMTP session for
/* \fBpostscreen\fR(8)'s built-in SMTP protocol engine.
@@ -348,6 +351,8 @@ int var_ps_barlf_ttl;
int var_ps_cmd_count;
char *var_ps_cmd_time;
+int var_ps_cconn_limit;
+
/*
* Global variables.
*/
@@ -372,6 +377,7 @@ int ps_stress; /* stress level */
int ps_check_queue_length_lowat; /* stress low-water mark */
int ps_check_queue_length_hiwat; /* stress high-water mark */
DICT *ps_dnsbl_reply; /* DNSBL name mapper */
+HTABLE *ps_client_concurrency; /* per-client concurrency */
/*
* Local variables.
@@ -501,11 +507,11 @@ static void ps_service(VSTREAM *smtp_client_stream,
memmove(smtp_client_addr.buf, smtp_client_addr.buf + 7,
sizeof(smtp_client_addr.buf) - 7);
if (msg_verbose > 1)
- msg_info("%s: sq=%d cq=%d connect from %s:%s",
+ msg_info("%s: sq=%d cq=%d connect from [%s]:%s",
myname, ps_post_queue_length, ps_check_queue_length,
smtp_client_addr.buf, smtp_client_port.buf);
- msg_info("CONNECT from %s", smtp_client_addr.buf);
+ msg_info("CONNECT from [%s]:%s", smtp_client_addr.buf, smtp_client_port.buf);
/*
* Bundle up all the loose session pieces. This zeroes all flags and time
@@ -514,12 +520,24 @@ static void ps_service(VSTREAM *smtp_client_stream,
state = ps_new_session_state(smtp_client_stream, smtp_client_addr.buf,
smtp_client_port.buf);
+ /*
+ * Reply with 421 when the client has too many open connections.
+ */
+ if (var_ps_cconn_limit > 0
+ && state->client_concurrency > var_ps_cconn_limit) {
+ msg_info("NOQUEUE: reject: CONNECT from [%s]:%s: too many connections",
+ state->smtp_client_addr, state->smtp_client_port);
+ PS_DROP_SESSION_STATE(state,
+ "421 4.7.0 Error: too many connections\r\n");
+ return;
+ }
+
/*
* Reply with 421 when we can't forward more connections.
*/
if (var_ps_post_queue_limit > 0
&& ps_post_queue_length >= var_ps_post_queue_limit) {
- msg_info("reject: connect from %s:%s: all server ports busy",
+ msg_info("NOQUEUE: reject: CONNECT from [%s]:%s: all server ports busy",
state->smtp_client_addr, state->smtp_client_port);
PS_DROP_SESSION_STATE(state,
"421 4.3.2 All server ports are busy\r\n");
@@ -532,7 +550,7 @@ static void ps_service(VSTREAM *smtp_client_stream,
*/
if (ps_wlist_nets != 0
&& ps_addr_match_list_match(ps_wlist_nets, state->smtp_client_addr)) {
- msg_info("WHITELISTED %s", state->smtp_client_addr);
+ msg_info("WHITELISTED [%s]:%s", PS_CLIENT_ADDR_PORT(state));
ps_conclude(state);
return;
}
@@ -544,7 +562,7 @@ static void ps_service(VSTREAM *smtp_client_stream,
*/
if (ps_blist_nets != 0
&& ps_addr_match_list_match(ps_blist_nets, state->smtp_client_addr)) {
- msg_info("BLACKLISTED %s", state->smtp_client_addr);
+ msg_info("BLACKLISTED [%s]:%s", PS_CLIENT_ADDR_PORT(state));
PS_FAIL_SESSION_STATE(state, PS_STATE_FLAG_BLIST_FAIL);
switch (ps_blist_action) {
case PS_ACT_DROP:
@@ -581,7 +599,7 @@ static void ps_service(VSTREAM *smtp_client_stream,
msg_info("%s: cached + recent flags: %s",
myname, ps_print_state_flags(state->flags, myname));
if ((state->flags & PS_STATE_MASK_ANY_TODO_FAIL) == 0) {
- msg_info("PASS OLD %s", state->smtp_client_addr);
+ msg_info("PASS OLD [%s]:%s", PS_CLIENT_ADDR_PORT(state));
ps_conclude(state);
return;
}
@@ -599,7 +617,7 @@ static void ps_service(VSTREAM *smtp_client_stream,
*/
if (var_ps_pre_queue_limit > 0
&& ps_check_queue_length - ps_post_queue_length >= var_ps_pre_queue_limit) {
- msg_info("reject: connect from %s:%s: all screening ports busy",
+ msg_info("reject: connect from [%s]:%s: all screening ports busy",
state->smtp_client_addr, state->smtp_client_port);
PS_DROP_SESSION_STATE(state,
"421 4.3.2 All screening ports are busy\r\n");
@@ -807,6 +825,11 @@ static void post_jail_init(char *unused_name, char **unused_argv)
msg_info(VAR_PS_CMD_TIME ": stress=%d normal=%d lowat=%d hiwat=%d",
ps_stress_cmd_time_limit, ps_normal_cmd_time_limit,
ps_check_queue_length_lowat, ps_check_queue_length_hiwat);
+
+ /*
+ * Per-client concurrency.
+ */
+ ps_client_concurrency = htable_create(var_ps_pre_queue_limit);
}
MAIL_VERSION_STAMP_DECLARE;
@@ -848,6 +871,7 @@ int main(int argc, char **argv)
static const CONFIG_NINT_TABLE nint_table[] = {
VAR_PS_POST_QLIMIT, DEF_PS_POST_QLIMIT, &var_ps_post_queue_limit, 5, 0,
VAR_PS_PRE_QLIMIT, DEF_PS_PRE_QLIMIT, &var_ps_pre_queue_limit, 10, 0,
+ VAR_PS_CCONN_LIMIT, DEF_PS_CCONN_LIMIT, &var_ps_cconn_limit, 0, 0,
0,
};
static const CONFIG_TIME_TABLE time_table[] = {
diff --git a/postfix/src/postscreen/postscreen.h b/postfix/src/postscreen/postscreen.h
index 4470756b3..a93a036bb 100644
--- a/postfix/src/postscreen/postscreen.h
+++ b/postfix/src/postscreen/postscreen.h
@@ -19,6 +19,7 @@
#include
#include
#include
+#include
/*
* Global library.
@@ -41,6 +42,7 @@ typedef struct {
int smtp_server_fd; /* real SMTP server */
char *smtp_client_addr; /* client address */
char *smtp_client_port; /* client port */
+ int client_concurrency; /* per-client */
const char *final_reply; /* cause for hanging up */
/* Test context. */
struct timeval start_time; /* start of current test */
@@ -288,6 +290,7 @@ extern int ps_stress; /* stress level */
extern int ps_check_queue_length_lowat; /* stress low-water mark */
extern int ps_check_queue_length_hiwat; /* stress high-water mark */
extern DICT *ps_dnsbl_reply; /* DNSBL name mapper */
+extern HTABLE *ps_client_concurrency; /* per-client concurrency */
#define PS_EFF_GREET_WAIT \
(ps_stress ? ps_stress_greet_wait : ps_normal_greet_wait)
@@ -323,40 +326,40 @@ extern DICT *ps_dnsbl_reply; /* DNSBL name mapper */
#define PS_PASS_SESSION_STATE(state, what, bits) do { \
if (msg_verbose) \
- msg_info("PASS %s %s:%s", (what), PS_CLIENT_ADDR_PORT(state)); \
+ msg_info("PASS %s [%s]:%s", (what), PS_CLIENT_ADDR_PORT(state)); \
(state)->flags |= (bits); \
} while (0)
#define PS_FAIL_SESSION_STATE(state, bits) do { \
if (msg_verbose) \
- msg_info("FAIL %s:%s", PS_CLIENT_ADDR_PORT(state)); \
+ msg_info("FAIL [%s]:%s", PS_CLIENT_ADDR_PORT(state)); \
(state)->flags |= (bits); \
} while (0)
#define PS_SKIP_SESSION_STATE(state, what, bits) do { \
if (msg_verbose) \
- msg_info("SKIP %s %s:%s", (what), PS_CLIENT_ADDR_PORT(state)); \
+ msg_info("SKIP %s [%s]:%s", (what), PS_CLIENT_ADDR_PORT(state)); \
(state)->flags |= (bits); \
} while (0)
#define PS_DROP_SESSION_STATE(state, reply) do { \
if (msg_verbose) \
- msg_info("DROP %s:%s", PS_CLIENT_ADDR_PORT(state)); \
+ msg_info("DROP [%s]:%s", PS_CLIENT_ADDR_PORT(state)); \
(state)->flags |= PS_STATE_FLAG_NOFORWARD; \
(state)->final_reply = (reply); \
ps_conclude(state); \
} while (0)
#define PS_ENFORCE_SESSION_STATE(state, reply) do { \
if (msg_verbose) \
- msg_info("ENFORCE %s:%s", PS_CLIENT_ADDR_PORT(state)); \
+ msg_info("ENFORCE [%s]:%s", PS_CLIENT_ADDR_PORT(state)); \
(state)->rcpt_reply = (reply); \
(state)->flags |= PS_STATE_FLAG_NOFORWARD; \
} while (0)
#define PS_UNPASS_SESSION_STATE(state, bits) do { \
if (msg_verbose) \
- msg_info("UNPASS %s:%s", PS_CLIENT_ADDR_PORT(state)); \
+ msg_info("UNPASS [%s]:%s", PS_CLIENT_ADDR_PORT(state)); \
(state)->flags &= ~(bits); \
} while (0)
#define PS_UNFAIL_SESSION_STATE(state, bits) do { \
if (msg_verbose) \
- msg_info("UNFAIL %s:%s", PS_CLIENT_ADDR_PORT(state)); \
+ msg_info("UNFAIL [%s]:%s", PS_CLIENT_ADDR_PORT(state)); \
(state)->flags &= ~(bits); \
} while (0)
#define PS_ADD_SERVER_STATE(state, fd) do { \
diff --git a/postfix/src/postscreen/postscreen_dnsbl.c b/postfix/src/postscreen/postscreen_dnsbl.c
index d28c90e42..2b68b0097 100644
--- a/postfix/src/postscreen/postscreen_dnsbl.c
+++ b/postfix/src/postscreen/postscreen_dnsbl.c
@@ -107,7 +107,8 @@ typedef struct {
} PS_DNSBL_HEAD;
typedef struct PS_DNSBL_SITE {
- char *filter; /* reply filter (default: null) */
+ char *filter; /* printable filter (default: null) */
+ char *byte_codes; /* encoded filter (default: null) */
int weight; /* reply weight (default: 1) */
struct PS_DNSBL_SITE *next; /* linked list */
} PS_DNSBL_SITE;
@@ -209,7 +210,7 @@ static void ps_dnsbl_add_site(const char *site)
PS_DNSBL_SITE *new_site;
char junk;
const char *weight_text;
- char *pattern_text;
+ char *pattern_text;
int weight;
HTABLE_INFO *ht;
char *parse_err;
@@ -263,7 +264,8 @@ static void ps_dnsbl_add_site(const char *site)
* name.
*/
new_site = (PS_DNSBL_SITE *) mymalloc(sizeof(*new_site));
- new_site->filter = (pattern_text ? ip_match_save(byte_codes) : 0);
+ new_site->filter = (pattern_text ? mystrdup(pattern_text) : 0);
+ new_site->byte_codes = (byte_codes ? ip_match_save(byte_codes) : 0);
new_site->weight = weight;
new_site->next = head->first;
head->first = new_site;
@@ -382,8 +384,8 @@ static void ps_dnsbl_receive(int event, char *context)
htable_find(dnsbl_site_cache, STR(reply_dnsbl));
site = (head ? head->first : (PS_DNSBL_SITE *) 0);
for (reply_argv = 0; site != 0; site = site->next) {
- if (site->filter == 0
- || ps_dnsbl_match(site->filter, reply_argv ? reply_argv :
+ if (site->byte_codes == 0
+ || ps_dnsbl_match(site->byte_codes, reply_argv ? reply_argv :
(reply_argv = argv_split(STR(reply_addr), " ")))) {
if (score->dnsbl == 0)
score->dnsbl = head->safe_dnsbl;
diff --git a/postfix/src/postscreen/postscreen_early.c b/postfix/src/postscreen/postscreen_early.c
index 27e22e284..54e27bc71 100644
--- a/postfix/src/postscreen/postscreen_early.c
+++ b/postfix/src/postscreen/postscreen_early.c
@@ -62,7 +62,7 @@ static void ps_early_event(int event, char *context)
const char *dnsbl_name;
if (msg_verbose > 1)
- msg_info("%s: sq=%d cq=%d event %d on smtp socket %d from %s:%s flags=%s",
+ msg_info("%s: sq=%d cq=%d event %d on smtp socket %d from [%s]:%s flags=%s",
myname, ps_post_queue_length, ps_check_queue_length,
event, vstream_fileno(state->smtp_client_stream),
state->smtp_client_addr, state->smtp_client_port,
@@ -117,8 +117,8 @@ static void ps_early_event(int event, char *context)
PS_PASS_SESSION_STATE(state, "dnsbl test",
PS_STATE_FLAG_DNSBL_PASS);
} else {
- msg_info("DNSBL rank %d for %s",
- dnsbl_score, state->smtp_client_addr);
+ msg_info("DNSBL rank %d for [%s]:%s",
+ dnsbl_score, PS_CLIENT_ADDR_PORT(state));
PS_FAIL_SESSION_STATE(state, PS_STATE_FLAG_DNSBL_FAIL);
switch (ps_dnsbl_action) {
case PS_ACT_DROP:
@@ -174,9 +174,9 @@ static void ps_early_event(int event, char *context)
return;
}
read_buf[read_count] = 0;
- msg_info("PREGREET %d after %s from %s: %.100s", read_count,
+ msg_info("PREGREET %d after %s from [%s]:%s: %.100s", read_count,
ps_format_delta_time(ps_temp, state->start_time, &elapsed),
- state->smtp_client_addr, printable(read_buf, '?'));
+ PS_CLIENT_ADDR_PORT(state), printable(read_buf, '?'));
PS_FAIL_SESSION_STATE(state, PS_STATE_FLAG_PREGR_FAIL);
switch (ps_pregr_action) {
case PS_ACT_DROP:
@@ -228,7 +228,7 @@ static void ps_early_dnsbl_event(int unused_event, char *context)
PS_STATE *state = (PS_STATE *) context;
if (msg_verbose)
- msg_info("%s: notify %s:%s", myname, PS_CLIENT_ADDR_PORT(state));
+ msg_info("%s: notify [%s]:%s", myname, PS_CLIENT_ADDR_PORT(state));
/*
* Terminate the greet delay if we're just waiting for DNSBL lookup to
diff --git a/postfix/src/postscreen/postscreen_misc.c b/postfix/src/postscreen/postscreen_misc.c
index 263a85020..f077a57e6 100644
--- a/postfix/src/postscreen/postscreen_misc.c
+++ b/postfix/src/postscreen/postscreen_misc.c
@@ -104,8 +104,8 @@ void ps_conclude(PS_STATE *state)
if ((state->flags & PS_STATE_MASK_ANY_PASS) != 0
&& (state->flags & PS_STATE_MASK_ANY_PASS) ==
PS_STATE_FLAGS_TODO_TO_PASS(state->flags & PS_STATE_MASK_ANY_TODO))
- msg_info("PASS %s %s", (state->flags & PS_STATE_FLAG_NEW) == 0 ?
- "OLD" : "NEW", state->smtp_client_addr);
+ msg_info("PASS %s [%s]:%s", (state->flags & PS_STATE_FLAG_NEW) == 0 ?
+ "OLD" : "NEW", PS_CLIENT_ADDR_PORT(state));
/*
* Update the postscreen cache. This still supports a scenario where a
@@ -128,7 +128,7 @@ void ps_conclude(PS_STATE *state)
(void) ps_send_reply(vstream_fileno(state->smtp_client_stream),
state->smtp_client_addr, state->smtp_client_port,
state->final_reply);
- msg_info("DISCONNECT %s", state->smtp_client_addr);
+ msg_info("DISCONNECT [%s]:%s", PS_CLIENT_ADDR_PORT(state));
ps_free_session_state(state);
}
}
@@ -148,9 +148,9 @@ void ps_hangup_event(PS_STATE *state)
* phase.
*/
state->flags |= PS_STATE_FLAG_HANGUP;
- msg_info("HANGUP after %s from %s in %s",
+ msg_info("HANGUP after %s from [%s]:%s in %s",
ps_format_delta_time(ps_temp, state->start_time, &elapsed),
- state->smtp_client_addr, state->test_name);
+ PS_CLIENT_ADDR_PORT(state), state->test_name);
state->flags |= PS_STATE_FLAG_NOFORWARD;
ps_conclude(state);
}
diff --git a/postfix/src/postscreen/postscreen_send.c b/postfix/src/postscreen/postscreen_send.c
index 5b8fc1f22..9a47e4fe8 100644
--- a/postfix/src/postscreen/postscreen_send.c
+++ b/postfix/src/postscreen/postscreen_send.c
@@ -78,7 +78,7 @@ int ps_send_reply(int smtp_client_fd, const char *smtp_client_addr,
int ret;
if (msg_verbose)
- msg_info("> %s:%s: %.*s", smtp_client_addr, smtp_client_port,
+ msg_info("> [%s]:%s: %.*s", smtp_client_addr, smtp_client_port,
(int) strlen(text) - 2, text);
/*
@@ -88,7 +88,7 @@ int ps_send_reply(int smtp_client_fd, const char *smtp_client_addr,
ret = (write_buf(smtp_client_fd, text, strlen(text),
PS_SEND_TEXT_TIMEOUT) < 0);
if (ret != 0 && errno != EPIPE)
- msg_warn("write %s:%s: %m", smtp_client_addr, smtp_client_port);
+ msg_warn("write [%s]:%s: %m", smtp_client_addr, smtp_client_port);
return (ret);
}
@@ -100,7 +100,7 @@ static void ps_send_socket_close_event(int event, char *context)
PS_STATE *state = (PS_STATE *) context;
if (msg_verbose > 1)
- msg_info("%s: sq=%d cq=%d event %d on send socket %d from %s:%s",
+ msg_info("%s: sq=%d cq=%d event %d on send socket %d from [%s]:%s",
myname, ps_post_queue_length, ps_check_queue_length,
event, state->smtp_server_fd, state->smtp_client_addr,
state->smtp_client_port);
@@ -128,7 +128,7 @@ void ps_send_socket(PS_STATE *state)
int window_size;
if (msg_verbose > 1)
- msg_info("%s: sq=%d cq=%d send socket %d from %s:%s",
+ msg_info("%s: sq=%d cq=%d send socket %d from [%s]:%s",
myname, ps_post_queue_length, ps_check_queue_length,
vstream_fileno(state->smtp_client_stream),
state->smtp_client_addr, state->smtp_client_port);
diff --git a/postfix/src/postscreen/postscreen_smtpd.c b/postfix/src/postscreen/postscreen_smtpd.c
index f3d6c4267..c05d1fe5c 100644
--- a/postfix/src/postscreen/postscreen_smtpd.c
+++ b/postfix/src/postscreen/postscreen_smtpd.c
@@ -321,9 +321,9 @@ static int ps_rcpt_cmd(PS_STATE *state, char *args)
if ((addr = ps_extract_addr(ps_temp, colon + 1)) == 0)
return (PS_SEND_REPLY(state,
"501 5.1.3 Bad recipient address syntax\r\n"));
- msg_info("NOQUEUE: reject: RCPT from [%s]: %.*s; "
+ msg_info("NOQUEUE: reject: RCPT from [%s]:%s: %.*s; "
"from=<%s>, to=<%s>, proto=%s, helo=<%s>",
- state->smtp_client_addr,
+ PS_CLIENT_ADDR_PORT(state),
(int) strlen(state->rcpt_reply) - 2, state->rcpt_reply,
state->sender, addr, state->protocol,
state->helo_name ? state->helo_name : "");
@@ -428,13 +428,13 @@ static void ps_smtpd_time_event(int event, char *context)
PS_STATE *state = (PS_STATE *) context;
if (msg_verbose > 1)
- msg_info("%s: sq=%d cq=%d event %d on smtp socket %d from %s:%s flags=%s",
+ msg_info("%s: sq=%d cq=%d event %d on smtp socket %d from [%s]:%s flags=%s",
myname, ps_post_queue_length, ps_check_queue_length,
event, vstream_fileno(state->smtp_client_stream),
state->smtp_client_addr, state->smtp_client_port,
ps_print_state_flags(state->flags, myname));
- msg_info("COMMAND TIME LIMIT from %s", state->smtp_client_addr);
+ msg_info("COMMAND TIME LIMIT from [%s]:%s", PS_CLIENT_ADDR_PORT(state));
PS_CLEAR_EVENT_DROP_SESSION_STATE(state, ps_smtpd_time_event,
ps_smtpd_timeout_reply);
}
@@ -499,7 +499,7 @@ static void ps_smtpd_read_event(int event, char *context)
int write_stat;
if (msg_verbose > 1)
- msg_info("%s: sq=%d cq=%d event %d on smtp socket %d from %s:%s flags=%s",
+ msg_info("%s: sq=%d cq=%d event %d on smtp socket %d from [%s]:%s flags=%s",
myname, ps_post_queue_length, ps_check_queue_length,
event, vstream_fileno(state->smtp_client_stream),
state->smtp_client_addr, state->smtp_client_port,
@@ -543,8 +543,8 @@ static void ps_smtpd_read_event(int event, char *context)
*/
if (state->read_state == PS_SMTPD_CMD_ST_ANY
&& VSTRING_LEN(state->cmd_buffer) >= var_line_limit) {
- msg_info("COMMAND LENGTH LIMIT from %s",
- state->smtp_client_addr);
+ msg_info("COMMAND LENGTH LIMIT from [%s]:%s",
+ PS_CLIENT_ADDR_PORT(state));
PS_CLEAR_EVENT_DROP_SESSION_STATE(state, ps_smtpd_time_event,
ps_smtpd_421_reply);
return;
@@ -580,7 +580,8 @@ static void ps_smtpd_read_event(int event, char *context)
if (ch == '\n') {
if ((state->flags & PS_STATE_MASK_BARLF_TODO_SKIP)
== PS_STATE_FLAG_BARLF_TODO) {
- msg_info("BARE NEWLINE from %s", state->smtp_client_addr);
+ msg_info("BARE NEWLINE from [%s]:%s",
+ PS_CLIENT_ADDR_PORT(state));
PS_FAIL_SESSION_STATE(state, PS_STATE_FLAG_BARLF_FAIL);
PS_UNPASS_SESSION_STATE(state, PS_STATE_FLAG_BARLF_PASS);
state->barlf_stamp = PS_TIME_STAMP_DISABLED; /* XXX */
@@ -644,7 +645,7 @@ static void ps_smtpd_read_event(int event, char *context)
*/
cmd_buffer_ptr = vstring_str(state->cmd_buffer);
if (msg_verbose)
- msg_info("< %s:%s: %s", state->smtp_client_addr,
+ msg_info("< [%s]:%s: %s", state->smtp_client_addr,
state->smtp_client_port, cmd_buffer_ptr);
/* Parse the command name. */
@@ -668,8 +669,8 @@ static void ps_smtpd_read_event(int event, char *context)
|| (*var_ps_forbid_cmds
&& string_list_match(ps_forbid_cmds, command)))) {
printable(command, '?');
- msg_info("NON-SMTP COMMAND from %s %.100s",
- state->smtp_client_addr, command);
+ msg_info("NON-SMTP COMMAND from [%s]:%s %.100s",
+ PS_CLIENT_ADDR_PORT(state), command);
PS_FAIL_SESSION_STATE(state, PS_STATE_FLAG_NSMTP_FAIL);
PS_UNPASS_SESSION_STATE(state, PS_STATE_FLAG_NSMTP_PASS);
state->nsmtp_stamp = PS_TIME_STAMP_DISABLED; /* XXX */
@@ -703,8 +704,8 @@ static void ps_smtpd_read_event(int event, char *context)
if ((state->flags & PS_STATE_MASK_PIPEL_TODO_SKIP)
== PS_STATE_FLAG_PIPEL_TODO && !PS_SMTPD_BUFFER_EMPTY(state)) {
printable(command, '?');
- msg_info("COMMAND PIPELINING from %s after %.100s",
- state->smtp_client_addr, command);
+ msg_info("COMMAND PIPELINING from [%s]:%s after %.100s",
+ PS_CLIENT_ADDR_PORT(state), command);
PS_FAIL_SESSION_STATE(state, PS_STATE_FLAG_PIPEL_FAIL);
PS_UNPASS_SESSION_STATE(state, PS_STATE_FLAG_PIPEL_PASS);
state->pipel_stamp = PS_TIME_STAMP_DISABLED; /* XXX */
@@ -766,7 +767,8 @@ static void ps_smtpd_read_event(int event, char *context)
/* Command COUNT limit test. */
if (++state->command_count > var_ps_cmd_count
&& cmdp->action != ps_quit_cmd) {
- msg_info("COMMAND COUNT LIMIT from %s", state->smtp_client_addr);
+ msg_info("COMMAND COUNT LIMIT from [%s]:%s",
+ PS_CLIENT_ADDR_PORT(state));
PS_CLEAR_EVENT_DROP_SESSION_STATE(state, ps_smtpd_time_event,
ps_smtpd_421_reply);
return;
diff --git a/postfix/src/postscreen/postscreen_state.c b/postfix/src/postscreen/postscreen_state.c
index 740c02454..729800494 100644
--- a/postfix/src/postscreen/postscreen_state.c
+++ b/postfix/src/postscreen/postscreen_state.c
@@ -123,6 +123,7 @@
#include
#include
#include
+#include
/* Global library. */
@@ -143,6 +144,7 @@ PS_STATE *ps_new_session_state(VSTREAM *stream,
const char *port)
{
PS_STATE *state;
+ HTABLE_INFO *ht;
state = (PS_STATE *) mymalloc(sizeof(*state));
PS_INIT_TESTS(state);
@@ -171,6 +173,15 @@ PS_STATE *ps_new_session_state(VSTREAM *stream,
msg_info("entering STRESS mode with %d connections",
ps_check_queue_length);
}
+
+ /*
+ * Update the per-client session count.
+ */
+ if ((ht = htable_locate(ps_client_concurrency, addr)) == 0)
+ ht = htable_enter(ps_client_concurrency, addr, (char *) 0);
+ ht->value += 1;
+ state->client_concurrency = (int) ht->value;
+
return (state);
}
@@ -178,6 +189,18 @@ PS_STATE *ps_new_session_state(VSTREAM *stream,
void ps_free_session_state(PS_STATE *state)
{
+ const char *myname = "ps_free_session_state";
+ HTABLE_INFO *ht;
+
+ /*
+ * Update the per-client session count.
+ */
+ if ((ht = htable_locate(ps_client_concurrency, state->smtp_client_addr)) == 0)
+ msg_panic("%s: unknown client address: %s",
+ myname, state->smtp_client_addr);
+ if (--(ht->value) == 0)
+ htable_delete(ps_client_concurrency, state->smtp_client_addr, (void (*) (char *)) 0);
+
if (state->smtp_client_stream != 0) {
event_server_disconnect(state->smtp_client_stream);
ps_check_queue_length--;
diff --git a/postfix/src/postscreen/postscreen_tests.c b/postfix/src/postscreen/postscreen_tests.c
index a281d4a50..3ba7adc76 100644
--- a/postfix/src/postscreen/postscreen_tests.c
+++ b/postfix/src/postscreen/postscreen_tests.c
@@ -156,7 +156,6 @@ void ps_parse_tests(PS_STATE *state,
const char *stamp_str,
time_t time_value)
{
- const char *myname = "ps_parse_tests";
unsigned long pregr_stamp;
unsigned long dnsbl_stamp;
unsigned long pipel_stamp;
diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in
index b07f74fdb..69c669812 100644
--- a/postfix/src/util/Makefile.in
+++ b/postfix/src/util/Makefile.in
@@ -33,7 +33,7 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
allascii.c load_file.c killme_after.c vstream_tweak.c upass_connect.c \
upass_listen.c upass_trigger.c edit_file.c inet_windowsize.c \
unix_pass_fd_fix.c dict_cache.c valid_utf_8.c dict_thash.c \
- ip_match.c ip_lmatch.c
+ ip_match.c
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
@@ -68,7 +68,7 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
allascii.o load_file.o killme_after.o vstream_tweak.o upass_connect.o \
upass_listen.o upass_trigger.o edit_file.o inet_windowsize.o \
unix_pass_fd_fix.o dict_cache.o valid_utf_8.o dict_thash.o \
- ip_match.o ip_lmatch.o
+ ip_match.o
HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \
dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \
@@ -89,7 +89,7 @@ HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
username.h valid_hostname.h vbuf.h vbuf_print.h vstream.h vstring.h \
vstring_vstream.h watchdog.h format_tv.h load_file.h killme_after.h \
edit_file.h dict_cache.h dict_thash.h \
- ip_match.h ip_lmatch.h
+ ip_match.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c test_send_fd test_recv_fd
DEFS = -I. -D$(SYSTYPE)
@@ -107,7 +107,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
attr_scan0 host_port attr_scan_plain attr_print_plain htable \
unix_recv_fd unix_send_fd stream_recv_fd stream_send_fd hex_code \
myaddrinfo myaddrinfo4 inet_proto sane_basename format_tv \
- test_send_fd test_recv_fd valid_utf_8 ip_match ip_lmatch
+ test_send_fd test_recv_fd valid_utf_8 ip_match
LIB_DIR = ../../lib
INC_DIR = ../../include
@@ -427,16 +427,11 @@ ip_match: $(LIB)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
mv junk $@.o
-ip_lmatch: $(LIB)
- mv $@.o junk
- $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
- mv junk $@.o
-
tests: valid_hostname_test mac_expand_test dict_test unescape_test \
hex_quote_test ctable_test inet_addr_list_test base64_code_test \
attr_scan64_test attr_scan0_test dict_pcre_test host_port_test \
dict_cidr_test attr_scan_plain_test htable_test hex_code_test \
- myaddrinfo_test format_tv_test ip_match_test ip_lmatch_test
+ myaddrinfo_test format_tv_test ip_match_test
root_tests:
@@ -563,11 +558,6 @@ ip_match_test: ip_match ip_match.in ip_match.ref
diff ip_match.ref ip_match.tmp
rm -f ip_match.tmp
-ip_lmatch_test: ip_lmatch ip_lmatch.in ip_lmatch.ref
- ./ip_lmatch ip_lmatch.tmp
- diff ip_lmatch.ref ip_lmatch.tmp
- rm -f ip_lmatch.tmp
-
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
@@ -1214,13 +1204,6 @@ ip_match.o: mymalloc.h
ip_match.o: sys_defs.h
ip_match.o: vbuf.h
ip_match.o: vstring.h
-ip_lmatch.o: ip_lmatch.c
-ip_lmatch.o: ip_lmatch.h
-ip_lmatch.o: msg.h
-ip_lmatch.o: mymalloc.h
-ip_lmatch.o: sys_defs.h
-ip_lmatch.o: vbuf.h
-ip_lmatch.o: vstring.h
killme_after.o: killme_after.c
killme_after.o: killme_after.h
killme_after.o: sys_defs.h
diff --git a/postfix/src/util/ip_lmatch.c b/postfix/src/util/ip_lmatch.c
deleted file mode 100644
index 70dc1ecbb..000000000
--- a/postfix/src/util/ip_lmatch.c
+++ /dev/null
@@ -1,450 +0,0 @@
-/*++
-/* NAME
-/* ip_lmatch 3
-/* SUMMARY
-/* lazy IP address pattern matching
-/* SYNOPSIS
-/* #include
-/*
-/* int ip_lmatch(pattern, addr, why)
-/* char *pattern;
-/* const char *addr;
-/* VSTRING **why;
-/* DESCRIPTION
-/* This module supports IP address pattern matching. See below
-/* for a description of the supported address pattern syntax.
-/*
-/* This version optimizes for implementation convenience. The
-/* lazy parser stops as soon as the address does not match the
-/* pattern. This results in a poor user interface: a pattern
-/* syntax error at the end will be reported ONLY when an address
-/* matches the entire pattern before the syntax error.
-/*
-/* Use the ip_match() module for an implementation that has
-/* separate parsing and matching stages. That implementation
-/* reports a syntax error immediately, and provides faster
-/* matching at the cost of a more complex programming interface.
-/*
-/* ip_lmatch_parse() matches the address bytes while parsing
-/* the pattern, and terminates as soon as a non-match or syntax
-/* error is found. The result is -1 in case of syntax error,
-/* 0 in case of no match, 1 in case of a match.
-/*
-/* Arguments
-/* .IP addr
-/* Network address in printable form.
-/* .IP pattern
-/* Address pattern. This argument may be modified.
-/* .IP why
-/* Pointer to storage for error reports (result value -1). If
-/* the target is a null pointer, ip_lmatch() will allocate a
-/* buffer that should be freed by the application.
-/* IPV4 PATTERN SYNTAX
-/* .ad
-/* .fi
-/* An IPv4 address pattern has four fields separated by ".".
-/* Each field is either a decimal number, or a sequence inside
-/* "[]" that contains one or more comma-separated decimal
-/* numbers or number..number ranges.
-/*
-/* Examples of patterns are 1.2.3.4 (matches itself, as one
-/* would expect) and 1.2.3.[2,4,6..8] (matches 1.2.3.2, 1.2.3.4,
-/* 1.2.3.6, 1.2.3.7, 1.2.3.8).
-/*
-/* Thus, any pattern field can be a sequence inside "[]", but
-/* a "[]" sequence cannot span multiple address fields, and
-/* a pattern field cannot contain both a number and a "[]"
-/* sequence at the same time.
-/*
-/* This means that the pattern 1.2.[3.4] is not valid (the
-/* sequence [3.4] cannot span two address fields) and the
-/* pattern 1.2.3.3[6..9] is also not valid (the last field
-/* cannot be both number 3 and sequence [6..9] at the same
-/* time).
-/*
-/* The syntax for IPv4 patterns is as follows:
-/*
-/* .in +5
-/* v4pattern = v4field "." v4field "." v4field "." v4field
-/* .br
-/* v4field = v4octet | "[" v4sequence "]
-/* .br
-/* v4octet = any decimal number in the range 0 through 255
-/* .br
-/* v4sequence = v4seq_member | v4sequence "," v4seq_member
-/* .br
-/* v4seq_member = v4octet | v4octet ".." v4octet
-/* .in
-/* LICENSE
-/* .ad
-/* .fi
-/* The Secure Mailer license must be distributed with this
-/* software.
-/* AUTHOR(S)
-/* Wietse Venema
-/* IBM T.J. Watson Research
-/* P.O. Box 704
-/* Yorktown Heights, NY 10598, USA
-/*--*/
-
-/* System library. */
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-/* Utility library. */
-
-#include
-#include
-#include
-#include
-#include
-
- /*
- * Token values.
- */
-#define IP_LMATCH_CODE_OPEN '[' /* start of set */
-#define IP_LMATCH_CODE_CLOSE ']' /* end of set */
-#define IP_LMATCH_CODE_OVAL 'N' /* octet value */
-#define IP_LMATCH_CODE_EOF '\0' /* oops */
-#define IP_LMATCH_CODE_ERR 256 /* oops */
-
- /*
- * Address length is protocol dependent. Find out how large our address byte
- * strings should be.
- */
-#ifdef HAS_IPV6
-#define IP_LMATCH_ABYTES MAI_V6ADDR_BYTES
-#else
-#define IP_LMATCH_ABYTES MAI_V4ADDR_BYTES
-#endif
-
- /*
- * SLMs.
- */
-#define STR vstring_str
-#define LEN VSTRING_LEN
-
-/* ip_lmatch_next_token - carve out the next token from user input */
-
-static int ip_lmatch_next_token(char **pstart, char **psaved_start, int *poval)
-{
- unsigned char *cp;
- unsigned char *next;
- int oval;
-
- /*
- * Return a value-less token (i.e. a literal, error, or EOF.
- */
-#define IP_LMATCH_RETURN_TOK(next, type) \
- do { *pstart = (char *) (next); return (type); } while (0)
-
- /*
- * Return a token that contains an IPv4 address octet value.
- */
-#define IP_LMATCH_RETURN_TOK_OVAL(next, oval) do { \
- *poval = (oval); IP_LMATCH_RETURN_TOK((next), IP_LMATCH_CODE_OVAL); \
- } while (0)
-
- /*
- * Light-weight tokenizer. Each result is an IPv4 address octet value, a
- * literal character value, error, or EOF.
- */
- *psaved_start = *pstart;
- cp = (unsigned char *) *pstart;
- if (ISDIGIT(*cp)) {
- oval = *cp - '0';
- for (next = cp + 1; ISDIGIT(*next); next++) {
- oval *= 10;
- oval += *next - '0';
- if (oval > 255)
- IP_LMATCH_RETURN_TOK(next + 1, IP_LMATCH_CODE_ERR);
- }
- IP_LMATCH_RETURN_TOK_OVAL(next, oval);
- } else {
- IP_LMATCH_RETURN_TOK(*cp ? cp + 1 : cp, *cp);
- }
-}
-
-/* ip_lmatch_print_parse_error - report parsing error in context */
-
-static void PRINTFLIKE(5, 6) ip_lmatch_print_parse_error(VSTRING **why,
- char *start,
- char *here,
- char *next,
- const char *fmt,...)
-{
- va_list ap;
- int start_width;
- int here_width;
-
- /*
- * On-the-fly allocation.
- */
- if (*why == 0)
- *why = vstring_alloc(20);
-
- /*
- * Format the error type.
- */
- va_start(ap, fmt);
- vstring_vsprintf(*why, fmt, ap);
- va_end(ap);
-
- /*
- * Format the error context. The syntax is complex enough that it is
- * worth the effort to precisely indicate what input is in error.
- *
- * XXX Workaround for %.*s to avoid output when a zero width is specified.
- */
-#define IP_LMATCH_NO_ERROR_CONTEXT (char *) 0, (char *) 0, (char *) 0
-
- if (start != 0) {
- start_width = here - start;
- here_width = next - here;
- vstring_sprintf_append(*why, " at \"%.*s>%.*s<%s\"",
- start_width, start_width == 0 ? "" : start,
- here_width, here_width == 0 ? "" : here, next);
- }
-}
-
-/* ip_lmatch - match an address pattern */
-
-int ip_lmatch(char *pattern, const char *addr, VSTRING **why)
-{
- const char *myname = "ip_lmatch";
- char addr_bytes[IP_LMATCH_ABYTES];
- const unsigned char *ap;
- int octet_count;
- char *saved_cp;
- char *cp;
- int token_type;
- int look_ahead;
- int oval;
- int saved_oval;
- int matched;
-
- /*
- * For now, IPv4 support only. Use different parser loops for IPv4 and
- * IPv6.
- */
- switch (inet_pton(AF_INET, addr, addr_bytes)) {
- case -1:
- msg_fatal("%s: address conversion error: %m", myname);
- case 0:
- msg_warn("%s: unexpected address form: %s", myname, addr);
- return (0);
- }
-
- /*
- * Simplify this if we change to {} for "octet set" notation.
- */
-#define FIND_TERMINATOR(start, cp) do { \
- int _level = 1; \
- for (cp = (start) ; *cp; cp++) { \
- if (*cp == '[') _level++; \
- if (*cp != ']') continue; \
- if (--_level == 0) break; \
- } \
- } while (0)
-
- /*
- * Strip [] around the entire pattern.
- */
- if (*pattern == '[') {
- FIND_TERMINATOR(pattern, cp);
- if (cp[0] == 0) {
- ip_lmatch_print_parse_error(why, IP_LMATCH_NO_ERROR_CONTEXT,
- "missing \"]\" character");
- return (-1);
- }
- if (cp[1] == 0) {
- *cp = 0;
- pattern += 1;
- }
- }
-
- /*
- * Sanity check. In this case we can't show any error context.
- */
- if (*pattern == 0) {
- ip_lmatch_print_parse_error(why, IP_LMATCH_NO_ERROR_CONTEXT,
- "empty address pattern");
- return (-1);
- }
-
- /*
- * Simple on-the-fly pattern matching.
- */
- octet_count = 0;
- cp = pattern;
-
- /*
- * Require four address fields separated by ".", each field containing a
- * numeric octet value or a sequence inside []. The loop head has no test
- * and does not step the loop variable. The tokenizer advances the loop
- * variable, and the loop termination logic is inside the loop.
- */
- for (ap = (const unsigned char *) addr_bytes; /* void */ ; ap++) {
- switch (token_type = ip_lmatch_next_token(&cp, &saved_cp, &oval)) {
-
- /*
- * Numeric address field.
- */
- case IP_LMATCH_CODE_OVAL:
- if (*ap == oval)
- break;
- return (0);
-
- /*
- * Wild-card address field.
- */
- case IP_LMATCH_CODE_OPEN:
- matched = 0;
- /* Require comma-separated numbers or numeric ranges. */
- for (;;) {
- token_type = ip_lmatch_next_token(&cp, &saved_cp, &oval);
- if (token_type == IP_LMATCH_CODE_OVAL) {
- saved_oval = oval;
- look_ahead = ip_lmatch_next_token(&cp, &saved_cp, &oval);
- /* Numeric range. */
- if (look_ahead == '.') {
- /* Brute-force parsing. */
- if (ip_lmatch_next_token(&cp, &saved_cp, &oval) == '.'
- && ip_lmatch_next_token(&cp, &saved_cp, &oval)
- == IP_LMATCH_CODE_OVAL
- && saved_oval <= oval) {
- if (!matched)
- matched = (*ap >= saved_oval && *ap <= oval);
- look_ahead =
- ip_lmatch_next_token(&cp, &saved_cp, &oval);
- } else {
- ip_lmatch_print_parse_error(why, pattern,
- saved_cp, cp,
- "numeric range error");
- return (-1);
- }
- }
- /* Single number. */
- else {
- if (!matched)
- matched = (*ap == oval);
- }
- /* Require "," or end-of-wildcard. */
- token_type = look_ahead;
- if (token_type == ',') {
- continue;
- } else if (token_type == IP_LMATCH_CODE_CLOSE) {
- break;
- } else {
- ip_lmatch_print_parse_error(why, pattern, saved_cp, cp,
- "need \",\" or \"%c\"",
- IP_LMATCH_CODE_CLOSE);
- return (-1);
- }
- } else {
- ip_lmatch_print_parse_error(why, pattern, saved_cp, cp,
- "need decimal number 0..255");
- return (-1);
- }
- }
- if (matched == 0)
- return (0);
- break;
-
- /*
- * Invalid field.
- */
- default:
- ip_lmatch_print_parse_error(why, pattern, saved_cp, cp,
- "need decimal number 0..255 or \"%c\"",
- IP_LMATCH_CODE_OPEN);
- return (-1);
- }
- octet_count += 1;
-
- /*
- * Require four address fields. Not one more, not one less.
- */
- if (octet_count == 4) {
- if (*cp != 0) {
- (void) ip_lmatch_next_token(&cp, &saved_cp, &oval);
- ip_lmatch_print_parse_error(why, pattern, saved_cp, cp,
- "garbage after pattern");
- return (-1);
- }
- return (1);
- }
-
- /*
- * Require "." before the next address field.
- */
- if (ip_lmatch_next_token(&cp, &saved_cp, &oval) != '.') {
- ip_lmatch_print_parse_error(why, pattern, saved_cp, cp,
- "need \".\"");
- return (-1);
- }
- }
-}
-
-#ifdef TEST
-
- /*
- * Dummy main program for regression tests.
- */
-#include
-#include
-#include
-#include
-#include
-#include
-
-int main(int argc, char **argv)
-{
- VSTRING *why = vstring_alloc(100);
- VSTRING *line_buf = vstring_alloc(100);
- char *bufp;
- char *user_pattern;
- char *user_address;
- int echo_input = !isatty(0);
- int match_status;
-
- /*
- * Iterate over the input stream. The input format is a pattern, followed
- * by addresses to match against.
- */
- while (vstring_fgets_nonl(line_buf, VSTREAM_IN)) {
- bufp = STR(line_buf);
- if (echo_input) {
- vstream_printf("> %s\n", bufp);
- vstream_fflush(VSTREAM_OUT);
- }
- if (*bufp == '#')
- continue;
- if ((user_pattern = mystrtok(&bufp, " \t")) == 0)
- continue;
-
- /*
- * Match the patterns.
- */
- while ((user_address = mystrtok(&bufp, " \t")) != 0) {
- match_status = ip_lmatch(user_pattern, user_address, &why);
- if (match_status < 0) {
- vstream_printf("Error: %s\n", STR(why));
- } else {
- vstream_printf("Match %s: %s\n", user_address,
- match_status ? "yes" : "no");
- }
- vstream_fflush(VSTREAM_OUT);
- }
- }
- vstring_free(line_buf);
- vstring_free(why);
- exit(0);
-}
-
-#endif
diff --git a/postfix/src/util/ip_lmatch.h b/postfix/src/util/ip_lmatch.h
deleted file mode 100644
index 788956f88..000000000
--- a/postfix/src/util/ip_lmatch.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef _IP_LMATCH_H_INCLUDED_
-#define _IP_LMATCH_H_INCLUDED_
-
-/*++
-/* NAME
-/* ip_lmatch 3h
-/* SUMMARY
-/* lazy IP address pattern matching
-/* SYNOPSIS
-/* #include
-/* DESCRIPTION
-/* .nf
-
- /*
- * Utility library.
- */
-#include
-
- /*
- * External interface.
- */
-extern int ip_lmatch(char *, const char *, VSTRING **);
-
-/* LICENSE
-/* .ad
-/* .fi
-/* The Secure Mailer license must be distributed with this software.
-/* AUTHOR(S)
-/* Wietse Venema
-/* IBM T.J. Watson Research
-/* P.O. Box 704
-/* Yorktown Heights, NY 10598, USA
-/*--*/
-
-#endif
diff --git a/postfix/src/util/ip_lmatch.in b/postfix/src/util/ip_lmatch.in
deleted file mode 100644
index 9b7aba33a..000000000
--- a/postfix/src/util/ip_lmatch.in
+++ /dev/null
@@ -1,21 +0,0 @@
-1.2.3.4 1.2.3.4
-1.2.300.4 1.2.3.4
-1.2.3. 1.2.3.4
-1.2.3 1.2.3.4
-a 1.2.3.4
-1.2.3,4 1.2.3.4
-1.2.[3].4 1.2.3.4
-1.2.[].4 1.2.3.4
-1.2.[.4 1.2.3.4
-1.2.].4 1.2.3.4
-1.2.[1..127,128..255].5 1.2.3.4
-1.2.[1-255].5 1.2.3.4
-1.2.[1..127.128..255].5 1.2.3.4
-1.2.3.[4] 1.2.3.4
-1.2.3.[4..1] 1.2.3.4
-1.2.3.[4.1] 1.2.3.4
-1.2.3.[4.x] 1.2.3.4
-1.2.3.[x] 1.2.3.4
-1.2.3.4x 1.2.3.4
-1.2.[3..11].5 1.2.3.5 1.2.2.5 1.2.11.5 1.2.12.5 1.2.11.6
-1.2.[3,5,7,9,11].5 1.2.3.5 1.2.2.5 1.2.4.5 1.2.11.5 1.2.12.5 1.2.11.6
diff --git a/postfix/src/util/ip_lmatch.ref b/postfix/src/util/ip_lmatch.ref
deleted file mode 100644
index d8431bd91..000000000
--- a/postfix/src/util/ip_lmatch.ref
+++ /dev/null
@@ -1,51 +0,0 @@
-> 1.2.3.4 1.2.3.4
-Match 1.2.3.4: yes
-> 1.2.300.4 1.2.3.4
-Error: need decimal number 0..255 or "[" at "1.2.>300<.4"
-> 1.2.3. 1.2.3.4
-Error: need decimal number 0..255 or "[" at "1.2.3.><"
-> 1.2.3 1.2.3.4
-Error: need "." at "1.2.3><"
-> a 1.2.3.4
-Error: need decimal number 0..255 or "[" at ">a<"
-> 1.2.3,4 1.2.3.4
-Error: need "." at "1.2.3>,<4"
-> 1.2.[3].4 1.2.3.4
-Match 1.2.3.4: yes
-> 1.2.[].4 1.2.3.4
-Error: need decimal number 0..255 at "1.2.[>]<.4"
-> 1.2.[.4 1.2.3.4
-Error: need decimal number 0..255 at "1.2.[>.<4"
-> 1.2.].4 1.2.3.4
-Error: need decimal number 0..255 or "[" at "1.2.>]<.4"
-> 1.2.[1..127,128..255].5 1.2.3.4
-Match 1.2.3.4: no
-> 1.2.[1-255].5 1.2.3.4
-Error: need "," or "]" at "1.2.[1>-<255].5"
-> 1.2.[1..127.128..255].5 1.2.3.4
-Error: need "," or "]" at "1.2.[1..127>.<128..255].5"
-> 1.2.3.[4] 1.2.3.4
-Match 1.2.3.4: yes
-> 1.2.3.[4..1] 1.2.3.4
-Error: numeric range error at "1.2.3.[4..>1<]"
-> 1.2.3.[4.1] 1.2.3.4
-Error: numeric range error at "1.2.3.[4.>1<]"
-> 1.2.3.[4.x] 1.2.3.4
-Error: numeric range error at "1.2.3.[4.>x<]"
-> 1.2.3.[x] 1.2.3.4
-Error: need decimal number 0..255 at "1.2.3.[>x<]"
-> 1.2.3.4x 1.2.3.4
-Error: garbage after pattern at "1.2.3.4>x<"
-> 1.2.[3..11].5 1.2.3.5 1.2.2.5 1.2.11.5 1.2.12.5 1.2.11.6
-Match 1.2.3.5: yes
-Match 1.2.2.5: no
-Match 1.2.11.5: yes
-Match 1.2.12.5: no
-Match 1.2.11.6: no
-> 1.2.[3,5,7,9,11].5 1.2.3.5 1.2.2.5 1.2.4.5 1.2.11.5 1.2.12.5 1.2.11.6
-Match 1.2.3.5: yes
-Match 1.2.2.5: no
-Match 1.2.4.5: no
-Match 1.2.11.5: yes
-Match 1.2.12.5: no
-Match 1.2.11.6: no
diff --git a/postfix/src/util/ip_match.c b/postfix/src/util/ip_match.c
index 17d1db29c..eb9333481 100644
--- a/postfix/src/util/ip_match.c
+++ b/postfix/src/util/ip_match.c
@@ -24,8 +24,8 @@
/* This module supports IP address pattern matching. See below
/* for a description of the supported address pattern syntax.
/*
-/* This implementation aims to minimize the cost of translating
-/* the pattern to internal form, while still providing good
+/* This implementation aims to minimize the cost of encoding
+/* the pattern in internal form, while still providing good
/* matching performance in the typical case. The first byte
/* of an encoded pattern specifies the expected address family
/* (for example, AF_INET); other details of the encoding are
@@ -357,8 +357,8 @@ int ip_match_execute(const char *byte_codes, const char *addr_bytes)
static int ip_match_next_token(char **pstart, char **psaved_start, int *poval)
{
unsigned char *cp;
- unsigned char *next;
- int oval;
+ int oval; /* octet value */
+ int type; /* token value */
/*
* Return a literal, error, or EOF token. Update the read pointer to the
@@ -370,8 +370,8 @@ static int ip_match_next_token(char **pstart, char **psaved_start, int *poval)
/*
* Return a token that contains an IPv4 address octet value.
*/
-#define IP_MATCH_RETURN_TOK_OVAL(next, oval) do { \
- *poval = (oval); IP_MATCH_RETURN_TOK((next), IP_MATCH_CODE_OVAL); \
+#define IP_MATCH_RETURN_TOK_VAL(next, type, oval) do { \
+ *poval = (oval); IP_MATCH_RETURN_TOK((next), type); \
} while (0)
/*
@@ -382,13 +382,14 @@ static int ip_match_next_token(char **pstart, char **psaved_start, int *poval)
cp = (unsigned char *) *pstart;
if (ISDIGIT(*cp)) {
oval = *cp - '0';
- for (next = cp + 1; ISDIGIT(*next); next++) {
+ type = IP_MATCH_CODE_OVAL;
+ for (cp += 1; ISDIGIT(*cp); cp++) {
oval *= 10;
- oval += *next - '0';
+ oval += *cp - '0';
if (oval > 255)
- IP_MATCH_RETURN_TOK(next + 1, IP_MATCH_CODE_ERR);
+ type = IP_MATCH_CODE_ERR;
}
- IP_MATCH_RETURN_TOK_OVAL(next, oval);
+ IP_MATCH_RETURN_TOK_VAL(cp, type, oval);
} else {
IP_MATCH_RETURN_TOK(*cp ? cp + 1 : cp, *cp);
}
diff --git a/postfix/src/util/ip_match.in b/postfix/src/util/ip_match.in
index 97964fbfb..0aae84b58 100644
--- a/postfix/src/util/ip_match.in
+++ b/postfix/src/util/ip_match.in
@@ -1,5 +1,6 @@
1.2.3.4
1.2.300.4
+1.2.3000.4
1.2.3.
1.2.3
a
diff --git a/postfix/src/util/ip_match.ref b/postfix/src/util/ip_match.ref
index ba75840c5..3293b10ec 100644
--- a/postfix/src/util/ip_match.ref
+++ b/postfix/src/util/ip_match.ref
@@ -2,6 +2,8 @@
Code: 1.2.3.4
> 1.2.300.4
Error: need decimal number 0..255 or "[" at "1.2.>300<.4"
+> 1.2.3000.4
+Error: need decimal number 0..255 or "[" at "1.2.>3000<.4"
> 1.2.3.
Error: need decimal number 0..255 or "[" at "1.2.3.><"
> 1.2.3