19991224
Bugfix: the relative symlink code in INSTALL.sh computed
- the ../ segments from the wrong pathname.
+ the ../ prefix from the wrong pathname.
+
+1999122[56]
+
+ Feature: "allow_routed_relaying = no" (default) disallows
+ forwarding of mail with sender-specified routing (example:
+ user%domain2@domain1, user@domain2@domain1, etc.). This
+ plugs an "open relay" loophole where a backup MX host would
+ forward junk mail to a primary MX host which would forward
+ it to the Internet. Files: global/quote_822_local.c,
+ smtp/quote_821_local.c, trivial-rewrite/rewrite.c,
+ trivial-rewrite/resolve.c, smtp/smtpd_check.c.
+
+ In order to make this possible, the resolver now passes a
+ status back to the client that says if the result is a
+ routed address.
+
+ Side effect from the above change: from now on, an address
+ with @ in the recipient localpart no longer bounces with
+ "user unknown" but instead is rejected with "relay access
+ denied" or "source-routed relay access denied".
-Incompatible changes with snapshot 19991223
+Incompatible changes with snapshot 19991226
===========================================
+- The SMTP server by default no longer forwards mail to non-local
+destinations with sender-specified routing (stuff[@%!]stuff[@%!]stuff).
+This closes an open relay loophole with primary and secondary MX
+hosts. To get old behavior, specify "allow_routed_relaying = yes".
+
+- In order to support the above, the data structure and protocol
+of the trivial-rewrite service was changed. This means you must
+re-compile and re-link existing software that uses the Postfix
+resolve_clnt interface.
+
+- As a side effect of the above, an address with @ in the localpart
+(user@there@here) no longer bounces with "user unknown" but instead
+is rejected with "relay access denied".
+
- The experimental permit_recipient_map and local_transports features
are gone. They were never part of an official release. Both are
replaced by a "local_recipient_map" parameter that allows the SMTP
all domain names you have in $mydestination. See the html/faq.html
sections for firewalls and intranets.
-Major changes with snapshot 19991223
+Major changes with snapshot 19991226
====================================
- It is now much more difficult to configure Postfix as an open
is the default). There were too many accidents with changes to
the UCE restrictions.
+- An "open relay" loophole is now plugged where a backup MX host
+would forward stuff[@%!]stuff[@%!]stuff to a primary MX host which
+would then spam it out to the world. To get the old behavior,
+specify "allow_routed_relaying = yes". The old behavior is safe
+only for non-MX hosts, and for primary MX hosts of domains that
+have no backup MX hosts.
+
- The relay_domains parameter no longer needs to contain $virtual_maps.
- Overhauled FAQ (html/faq.html) with many more examples.
# ADDITIONAL UCE CONTROLS
#
+# The allow_routed_relaying parameter controls whether the host will
+# forward addresses with sender-specified routing. This is disabled
+# by default, in order to close a nasty open relay loophole where a
+# backup MX host can be tricked into forwarding mail to a primary MX
+# host which then spams it out to the world. Don't change this if
+# this system is backup MX host for any domain, or if this system
+# receives mail from any backup MX host.
+#
+allow_routed_relaying = no
+
# The maps_rbl_domains parameter specifies an optional list of DNS
# domains that publish the network addresses of blacklisted hosts.
#
#define DEF_REST_CLASSES ""
extern char *var_rest_classes;
+#define VAR_ALLOW_ROUTED_RELAY "allow_routed_relaying"
+#define DEF_ALLOW_ROUTED_RELAY 0
+extern bool var_allow_routed_relay;
+
/*
* Names of specific restrictions, and the corresponding configuration
* parameters that control the status codes sent in response to rejected
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "Snapshot-19991225"
+#define DEF_MAIL_VERSION "Snapshot-19991226"
extern char *var_mail_version;
/* LICENSE
<pre>
>>> MAIL FROM:<someone@some.where>
<<< 250 Ok
- >>> RCPT TO:<test@some.other.site@your.site>
+ >>> RCPT TO:<test@some.other.site@some.site>
<<< 250 Ok
>>> DATA
<<< 354 End data with <CR><LF>.<CR><LF>
<p>
-Don't Panic!
+Don't Panic! Upgrade to a Postfix version of 19991226 or later.
<p>
-If the mail for domain <i>your.site</i> is handled by a Postfix
-machine, the mail bounces because <i>test@some.other.site</i> is
-not a known user in domain <i>your.site</i>. In fact, the above
-mail is rejected immediately when the Postfix SMTP server is
-configured to <a href="#bogus">reject mail for unknown local
-users</a>.
-
-<p>
-
-However, problems lurk when you are responsible for a backup MX
-host, either for your own domain or for the domain of some other
-organization. Especially troublesome address forms are:
-
-<p>
-
-<pre>
- user@else.where@some.domain
- user%else.where@some.domain
- elsewhere!user@some.domain
-</pre>
-
-<p>
-
-The problem is that the primary MX host may forward such mail to
-user@else.where, either because the primary MX host somehow "trusts"
-yor backup MX host, or because the primary MX host is badly
-configured.
-
-<p>
-
-The bad news is that your backup MX machine can end up on a black
-list because it accepted the mail, even though the problem could
-be with the configuration of a primary MX machine that is not even
-under your control.
-
-<p>
-
-So, if you're backup MX relay it is prudent to block addresses with
-multiple address operators at the SMTP port, even though you would
-also block legitimate addresses.
-
-<p>
-
-<pre>
- <b>/etc/postfix/main.cf:</b>
- smtpd_recipient_restrictions =
- regexp:/etc/postfix/regexp_access
- ...other UCE restrictions...
-
- <b>/etc/postfix/regexp_access</b>:
- /[%!@].*[%!@]/ 550 Sender specified routing is not supported here.
-</pre>
+Older Postfix versions would either bounce the mail because
+"test@some.other.site" is not a known local username (which is
+good), or they would forward the mail to a primary MX host for
+"some.site" which would then spam it into the Internet (which is
+bad).
<hr>
/* .IP \fBsmtpd_etrn_restrictions\fR
/* Restrict what domain names can be used in \fBETRN\fR commands,
/* and what clients may issue \fBETRN\fR commands.
+/* .IP \fBallow_routed_relaying\fR
+/* Allow the relaying of addresses with sender-specified routing.
+/* Enabling this opens up nasty relay loopholes if your domain has
+/* primary and backup MX hosts.
/* .IP \fBrestriction_classes\fR
/* Declares the name of zero or more parameters that contain a
/* list of UCE restrictions. The names of these parameters can
char *var_virtual_maps;
char *var_alias_maps;
char *var_local_rcpt_maps;
+bool var_allow_routed_relay;
/*
* Global state, for stand-alone mode queue file cleanup. When this is
VAR_SMTPD_DELAY_REJECT, DEF_SMTPD_DELAY_REJECT, &var_smtpd_delay_reject,
VAR_STRICT_RFC821_ENV, DEF_STRICT_RFC821_ENV, &var_strict_rfc821_env,
VAR_DISABLE_VRFY_CMD, DEF_DISABLE_VRFY_CMD, &var_disable_vrfy_cmd,
+ VAR_ALLOW_ROUTED_RELAY, DEF_ALLOW_ROUTED_RELAY, &var_allow_routed_relay,
0,
};
static CONFIG_STR_TABLE str_table[] = {
* People screw up the relay restrictions too often. Require that they
* list at least one restriction that rejects mail by default.
*/
+#ifndef TEST
check_required(VAR_RCPT_CHECKS, rcpt_restrctions, rcpt_required);
+#endif
/*
* Parse the pre-defined restriction classes.
char *reply_name, char *reply_class)
{
char *myname = "check_relay_domains";
- char *domain;
static int permit_auth_destination(char *recipient);
if (msg_verbose)
/*
* Handle special case that is not supposed to happen.
*/
- if ((domain = split_at_right(STR(reply.recipient), '@')) == 0)
+ if ((domain = strrchr(STR(reply.recipient), '@')) == 0)
return (SMTPD_CHECK_OK);
+ domain += 1;
/*
* Permit final delivery: the destination matches mydestination or
return (SMTPD_CHECK_OK);
/*
- * Permit non-routed mail to a destination on the relay_domains list.
+ * Permit if the destination matches the relay_domains list.
*/
- if ((reply.flags & RESOLVE_FLAG_ROUTED) == 0
- && domain_list_match(relay_domains, domain))
+ if (domain_list_match(relay_domains, domain))
return (SMTPD_CHECK_OK);
/*
- * Something else.
+ * Skip when not matched
*/
return (SMTPD_CHECK_DUNNO);
}
static int reject_unauth_destination(SMTPD_STATE *state, char *recipient)
{
char *myname = "reject_unauth_destination";
- char *domain;
if (msg_verbose)
msg_info("%s: %s", myname, recipient);
return (SMTPD_CHECK_DUNNO);
/*
- * Reject unauthorized destination.
+ * Reject relaying to sites that are not listed in relay_domains.
*/
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
"%d <%s>: Relay access denied",
return (SMTPD_CHECK_DUNNO);
}
+/* reject_routed_relay - FAIL for relaying via sender-specified route */
+
+static int reject_routed_relay(SMTPD_STATE *state, char *recipient,
+ char *reply_name, char *reply_class)
+{
+ char *myname = "reject_routed_relay";
+ char *domain;
+
+ if (msg_verbose)
+ msg_info("%s: %s", myname, recipient);
+
+ /*
+ * Resolve the address.
+ */
+ canon_addr_internal(query, recipient);
+ resolve_clnt_query(STR(query), &reply);
+
+ /*
+ * Handle special case that is not supposed to happen.
+ */
+ if ((domain = strrchr(STR(reply.recipient), '@')) == 0)
+ return (SMTPD_CHECK_DUNNO);
+ domain += 1;
+
+ /*
+ * Permit final delivery: the destination matches mydestination or
+ * virtual_maps.
+ */
+ if (resolve_local(domain)
+ || (*var_virtual_maps && maps_find(virtual_maps, domain, 0)))
+ return (SMTPD_CHECK_DUNNO);
+
+ /*
+ * Reject source-routed mail to a non-local destination.
+ */
+ if ((reply.flags & RESOLVE_FLAG_ROUTED) != 0)
+ return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
+ "%d <%s>: %s rejected: Source-routed relay access denied",
+ var_relay_code, reply_name, reply_class));
+
+ /*
+ * Something else.
+ */
+ return (SMTPD_CHECK_DUNNO);
+}
+
/* has_my_addr - see if this host name lists one of my network addresses */
static int has_my_addr(char *host)
*/
state->recursion = 0;
status = setjmp(smtpd_check_buf);
- if (status == 0 && rcpt_restrctions->argc)
+ if (status == 0 && rcpt_restrctions->argc) {
status = generic_checks(state, rcpt_restrctions,
recipient, SMTPD_NAME_RECIPIENT, CHECK_RECIP_ACL);
-
+ if (var_allow_routed_relay == 0 && status != SMTPD_CHECK_REJECT)
+ status = reject_routed_relay(state, recipient,
+ recipient, SMTPD_NAME_RECIPIENT);
+ }
SMTPD_CHECK_RCPT_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
}
char *var_mydest;
char *var_inet_interfaces;
char *var_rest_classes;
-char *var_local_transports;
+char *var_alias_maps;
+char *var_rcpt_canon_maps;
+char *var_canonical_maps;
+char *var_virtual_maps;
+char *var_local_rcpt_maps;
typedef struct {
char *name;
VAR_MYDEST, DEF_MYDEST, &var_mydest,
VAR_INET_INTERFACES, DEF_INET_INTERFACES, &var_inet_interfaces,
VAR_REST_CLASSES, DEF_REST_CLASSES, &var_rest_classes,
- VAR_LOCAL_TRANSP, DEF_LOCAL_TRANSP, &var_local_transports,
+ VAR_ALIAS_MAPS, DEF_ALIAS_MAPS, &var_alias_maps,
+ VAR_RCPT_CANON_MAPS, DEF_RCPT_CANON_MAPS, &var_rcpt_canon_maps,
+ VAR_CANONICAL_MAPS, DEF_CANONICAL_MAPS, &var_canonical_maps,
+ VAR_VIRTUAL_MAPS, DEF_VIRTUAL_MAPS, &var_virtual_maps,
+ VAR_LOCAL_RCPT_MAPS, DEF_LOCAL_RCPT_MAPS, &var_local_rcpt_maps,
0,
};
int var_reject_code;
int var_non_fqdn_code;
int var_smtpd_delay_reject;
+int var_allow_routed_relay;
static INT_TABLE int_table[] = {
"msg_verbose", 0, &msg_verbose,
VAR_REJECT_CODE, DEF_REJECT_CODE, &var_reject_code,
VAR_NON_FQDN_CODE, DEF_NON_FQDN_CODE, &var_non_fqdn_code,
VAR_SMTPD_DELAY_REJECT, DEF_SMTPD_DELAY_REJECT, &var_smtpd_delay_reject,
+ VAR_ALLOW_ROUTED_RELAY, DEF_ALLOW_ROUTED_RELAY, &var_allow_routed_relay,
0,
};
typedef struct {
char *name;
ARGV **target;
-} REST_TABLE;
+} REST_TABLE;
static REST_TABLE rest_table[] = {
"client_restrictions", &client_restrctions,
#
# Test the client restrictions.
#
-client_restrictions permit_mynetworks,reject_unknown_client,dbm:./smtpd_check_access
+client_restrictions permit_mynetworks,reject_unknown_client,hash:./smtpd_check_access
client unknown 131.155.210.17
client unknown 168.100.189.13
client random.bad.domain 123.123.123.123
#
# Test the helo restrictions
#
-helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,reject_unknown_hostname,dbm:./smtpd_check_access
+helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,reject_unknown_hostname,hash:./smtpd_check_access
client unknown 131.155.210.17
helo foo.
client foo 123.123.123.123
helo foo.
helo foo
helo spike.porcupine.org
-helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,dbm:./smtpd_check_access
+helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,hash:./smtpd_check_access
helo random.bad.domain
helo friend.bad.domain
helo_restrictions reject_invalid_hostname,reject_unknown_hostname
sender_restrictions reject_unknown_address
mail foo@watson.ibm.com
mail foo@bad.domain
-sender_restrictions dbm:./smtpd_check_access
+sender_restrictions hash:./smtpd_check_access
mail bad-sender@any.domain
mail bad-sender@good.domain
mail reject@this.address
client foo 123.123.123.123
rcpt foo@watson.ibm.com
rcpt foo@porcupine.org
-recipient_restrictions dbm:./smtpd_check_access
+recipient_restrictions hash:./smtpd_check_access
mail bad-sender@any.domain
mail bad-sender@good.domain
mail reject@this.address
recipient_restrictions check_relay_domains
client foo 131.155.210.17
rcpt foo@watson.ibm.com
-recipient_restrictions check_client_access,dbm:./smtpd_check_access,check_relay_domains
+recipient_restrictions check_client_access,hash:./smtpd_check_access,check_relay_domains
client foo 131.155.210.17
rcpt foo@porcupine.org
-helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,dbm:./smtpd_check_access
-recipient_restrictions check_helo_access,dbm:./smtpd_check_access,check_relay_domains
+helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,hash:./smtpd_check_access
+recipient_restrictions check_helo_access,hash:./smtpd_check_access,check_relay_domains
helo bad.domain
rcpt foo@porcupine.org
helo 131.155.210.17
rcpt foo@porcupine.org
-recipient_restrictions check_sender_access,dbm:./smtpd_check_access,check_relay_domains
+recipient_restrictions check_sender_access,hash:./smtpd_check_access,check_relay_domains
mail foo@bad.domain
rcpt foo@porcupine.org
mail foo@friend.bad.domain
client_restrictions permit
helo_restrictions permit
sender_restrictions permit
-recipient_restrictions check_helo_access,dbm:./smtpd_check_access,check_sender_access,dbm:./smtpd_check_access
+recipient_restrictions check_helo_access,hash:./smtpd_check_access,check_sender_access,hash:./smtpd_check_access
helo bad.domain
mail foo@good.domain
rcpt foo@porcupine.org
#
# Test the client restrictions.
#
-client_restrictions permit_mynetworks,reject_unknown_client,check_client_access,dbm:./smtpd_check_access
+client_restrictions permit_mynetworks,reject_unknown_client,check_client_access,hash:./smtpd_check_access
client unknown 131.155.210.17
client unknown 168.100.189.13
client random.bad.domain 123.123.123.123
#
# Test the helo restrictions
#
-helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,reject_unknown_hostname,check_helo_access,dbm:./smtpd_check_access
+helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,reject_unknown_hostname,check_helo_access,hash:./smtpd_check_access
client unknown 131.155.210.17
helo foo.
client foo 123.123.123.123
helo foo.
helo foo
helo spike.porcupine.org
-helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,check_helo_access,dbm:./smtpd_check_access
+helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,check_helo_access,hash:./smtpd_check_access
helo random.bad.domain
helo friend.bad.domain
#
sender_restrictions reject_unknown_address
mail foo@watson.ibm.com
mail foo@bad.domain
-sender_restrictions check_sender_access,dbm:./smtpd_check_access
+sender_restrictions check_sender_access,hash:./smtpd_check_access
mail bad-sender@any.domain
mail bad-sender@good.domain
mail reject@this.address
client foo 123.123.123.123
rcpt foo@watson.ibm.com
rcpt foo@porcupine.org
-recipient_restrictions check_recipient_access,dbm:./smtpd_check_access
+recipient_restrictions check_recipient_access,hash:./smtpd_check_access
mail bad-sender@any.domain
mail bad-sender@good.domain
mail reject@this.address
>>> #
>>> # Test the client restrictions.
>>> #
->>> client_restrictions permit_mynetworks,reject_unknown_client,dbm:./smtpd_check_access
+>>> client_restrictions permit_mynetworks,reject_unknown_client,hash:./smtpd_check_access
OK
>>> client unknown 131.155.210.17
./smtpd_check: reject: CONNECT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> #
>>> # Test the helo restrictions
>>> #
->>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,reject_unknown_hostname,dbm:./smtpd_check_access
+>>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,reject_unknown_hostname,hash:./smtpd_check_access
OK
>>> client unknown 131.155.210.17
OK
450 <foo>: Helo command rejected: Host not found
>>> helo spike.porcupine.org
OK
->>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,dbm:./smtpd_check_access
+>>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,hash:./smtpd_check_access
OK
>>> helo random.bad.domain
./smtpd_check: reject: HELO from foo[123.123.123.123]: 554 <random.bad.domain>: Helo command rejected: match bad.domain
>>> mail foo@bad.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 450 <foo@bad.domain>: Sender address rejected: Domain not found; from=<foo@bad.domain>
450 <foo@bad.domain>: Sender address rejected: Domain not found
->>> sender_restrictions dbm:./smtpd_check_access
+>>> sender_restrictions hash:./smtpd_check_access
OK
>>> mail bad-sender@any.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@; from=<bad-sender@any.domain>
554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
->>> recipient_restrictions dbm:./smtpd_check_access
+>>> recipient_restrictions hash:./smtpd_check_access
OK
>>> mail bad-sender@any.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@; from=<bad-sender@any.domain>
>>> client spike.porcupine.org 168.100.189.2
OK
>>> client foo 127.0.0.2
-./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com, reason: EBlackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>; from=<foo@friend.bad.domain>
-554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com, reason: EBlackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
+./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com, reason: Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>; from=<foo@friend.bad.domain>
+554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com, reason: Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
>>> #
>>> # Hybrids
>>> #
>>> rcpt foo@watson.ibm.com
./smtpd_check: reject: RCPT from foo[131.155.210.17]: 554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
->>> recipient_restrictions check_client_access,dbm:./smtpd_check_access,check_relay_domains
+>>> recipient_restrictions check_client_access,hash:./smtpd_check_access,check_relay_domains
OK
>>> client foo 131.155.210.17
OK
>>> rcpt foo@porcupine.org
OK
->>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,dbm:./smtpd_check_access
+>>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,hash:./smtpd_check_access
OK
->>> recipient_restrictions check_helo_access,dbm:./smtpd_check_access,check_relay_domains
+>>> recipient_restrictions check_helo_access,hash:./smtpd_check_access,check_relay_domains
OK
>>> helo bad.domain
./smtpd_check: reject: HELO from foo[131.155.210.17]: 554 <bad.domain>: Helo command rejected: match bad.domain; from=<foo@friend.bad.domain>
OK
>>> rcpt foo@porcupine.org
OK
->>> recipient_restrictions check_sender_access,dbm:./smtpd_check_access,check_relay_domains
+>>> recipient_restrictions check_sender_access,hash:./smtpd_check_access,check_relay_domains
OK
>>> mail foo@bad.domain
./smtpd_check: reject: MAIL from foo[131.155.210.17]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain>
OK
>>> sender_restrictions permit
OK
->>> recipient_restrictions check_helo_access,dbm:./smtpd_check_access,check_sender_access,dbm:./smtpd_check_access
+>>> recipient_restrictions check_helo_access,hash:./smtpd_check_access,check_sender_access,hash:./smtpd_check_access
OK
>>> helo bad.domain
OK
>>> #
>>> # Test the client restrictions.
>>> #
->>> client_restrictions permit_mynetworks,reject_unknown_client,check_client_access,dbm:./smtpd_check_access
+>>> client_restrictions permit_mynetworks,reject_unknown_client,check_client_access,hash:./smtpd_check_access
OK
>>> client unknown 131.155.210.17
./smtpd_check: reject: CONNECT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> #
>>> # Test the helo restrictions
>>> #
->>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,reject_unknown_hostname,check_helo_access,dbm:./smtpd_check_access
+>>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,reject_unknown_hostname,check_helo_access,hash:./smtpd_check_access
OK
>>> client unknown 131.155.210.17
OK
450 <foo>: Helo command rejected: Host not found
>>> helo spike.porcupine.org
OK
->>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,check_helo_access,dbm:./smtpd_check_access
+>>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,check_helo_access,hash:./smtpd_check_access
OK
>>> helo random.bad.domain
./smtpd_check: reject: HELO from foo[123.123.123.123]: 554 <random.bad.domain>: Helo command rejected: match bad.domain
>>> mail foo@bad.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 450 <foo@bad.domain>: Sender address rejected: Domain not found; from=<foo@bad.domain>
450 <foo@bad.domain>: Sender address rejected: Domain not found
->>> sender_restrictions check_sender_access,dbm:./smtpd_check_access
+>>> sender_restrictions check_sender_access,hash:./smtpd_check_access
OK
>>> mail bad-sender@any.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@; from=<bad-sender@any.domain>
554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
->>> recipient_restrictions check_recipient_access,dbm:./smtpd_check_access
+>>> recipient_restrictions check_recipient_access,hash:./smtpd_check_access
OK
>>> mail bad-sender@any.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@; from=<bad-sender@any.domain>
>>> client spike.porcupine.org 168.100.189.2
OK
>>> client foo 127.0.0.2
-./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com, reason: EBlackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>; from=<foo@friend.bad.domain>
-554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com, reason: EBlackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
+./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com, reason: Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>; from=<foo@friend.bad.domain>
+554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com, reason: Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
>>> #
>>> # unknown sender/recipient domain
>>> #
&& VSTRING_LEN(tree->head->vstr) == 0) {
tok822_free(tree->head);
tree->head = tok822_scan(MAIL_ADDR_POSTMASTER, &tree->tail);
+ rewrite_tree(REWRITE_CANON, tree);
}
/*
}
/*
- * After stripping the local domain, replace foo%bar by foo@bar,
- * site!user by user@site, rewrite to canonical form, and retry.
+ * After stripping the local domain, if any, replace foo%bar by
+ * foo@bar, site!user by user@site, rewrite to canonical form, and
+ * retry. Recognize routing operators in the address localpart. This
+ * is needed to prevent primary MX hosts from relaying third-party
+ * destinations from backup MX hosts, otherwise the primary could end
+ * up on black lists.
+ *
* Otherwise we're done.
*/
- if ((domain = tok822_rfind_type(tree->tail, '@')) == 0) {
- if (var_swap_bangpath && tok822_rfind_type(tree->tail, '!') != 0) {
- rewrite_tree(REWRITE_CANON, tree);
- } else if (var_percent_hack
- && (domain = tok822_rfind_type(tree->tail, '%')) != 0) {
- domain->type = '@';
- rewrite_tree(REWRITE_CANON, tree);
- } else {
- break;
- }
+ if (tok822_rfind_type(tree->tail, '@')
+ || (var_swap_bangpath && tok822_rfind_type(tree->tail, '!'))
+ || (var_percent_hack && tok822_rfind_type(tree->tail, '%'))) {
+ *flags |= RESOLVE_FLAG_ROUTED;
+ rewrite_tree(REWRITE_CANON, tree);
+ } else {
+ domain = 0;
+ break;
}
}
/*
* If the destination is non-local, recognize routing operators in the
- * address localpart. This is needed to protect backup hosts against
- * relaying by primary hosts, because the backup host would end up on
- * black lists.
+ * address localpart. This is needed to prevent backup MX hosts from
+ * relaying third-party destinations through primary MX hosts, otherwise
+ * the backup host could end up on black lists. Ignore local
+ * swap_bangpath and percent_hack settings because we can't know how the
+ * primary MX host is set up.
*/
if (domain && domain->prev)
if (tok822_rfind_type(domain->prev, '@') != 0
}
/*
- * Append missing @origin.
+ * Append missing @origin
*/
else if (var_append_at_myorigin != 0) {
domain = tok822_sub_append(tree, tok822_alloc('@', (char *) 0));