From 89867bfc4b82c6cb24396e1dbaa3362604a0bff5 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Mon, 6 Aug 2001 00:00:00 -0500 Subject: [PATCH] snapshot-20010806 --- postfix/HISTORY | 16 ++ postfix/RELEASE_NOTES | 24 ++- postfix/conf/canonical | 14 +- postfix/conf/master.cf | 5 + postfix/conf/pcre_table | 24 +-- postfix/conf/regexp_table | 22 +-- postfix/conf/sample-rewrite.cf | 13 ++ postfix/conf/sample-smtpd.cf | 17 ++- postfix/html/canonical.5.html | 5 + postfix/html/cleanup.8.html | 54 ++++--- postfix/html/faq.html | 5 +- postfix/html/rewrite.html | 26 +++- postfix/html/uce.html | 63 +++++++- postfix/man/man5/canonical.5 | 4 + postfix/man/man8/cleanup.8 | 6 +- postfix/proto/canonical | 4 + postfix/src/cleanup/cleanup.c | 6 +- postfix/src/cleanup/cleanup.h | 9 ++ postfix/src/cleanup/cleanup_envelope.c | 6 +- postfix/src/cleanup/cleanup_extracted.c | 18 ++- postfix/src/cleanup/cleanup_init.c | 17 ++- postfix/src/cleanup/cleanup_message.c | 6 +- postfix/src/global/mail_params.h | 17 ++- postfix/src/global/mail_version.h | 2 +- postfix/src/smtpd/smtpd.c | 2 + postfix/src/smtpd/smtpd_check.c | 189 +++++++++++++++++++++++- 26 files changed, 487 insertions(+), 87 deletions(-) diff --git a/postfix/HISTORY b/postfix/HISTORY index e3d94f5d4..e57440d02 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -5405,3 +5405,19 @@ Apologies for any names omitted. for myhostname, inet_interfaces, and mynetworks_style. This broke the default mynetworks setting calculation. File: postconf/postconf.c. + +20010803 + + Feature: masquerade_classes parameter for fine control of + address masquerading. The default setting is backwards + compatible: envelope_sender header_sender header_recipient. + Files: cleanup/whatever.c. + +20010806 + + Bugfix: did not address masquerade the always_bcc recipient + after extracting envelope recipients from message headers. + File: cleanup/cleanup_extracted.c. + + Bugfix: did not address masquerade the envelope recipients + extracted from message headers. File: cleanup/cleanup_message.c. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 026c4140f..d5c715dc2 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -1,17 +1,29 @@ -Incompatible changes with snapshot-20010801 +Incompatible changes with snapshot-20010802 =========================================== +The default setting for the maps_rbl_domains parameter is "empty", +because mail-abuse.org has become a subscription-based service. + +The permit_mx_backup feature has changed. It accepts mail only when +the primary MX hosts for the recipient match the networks that are +specified with the new auth_permit_mx_backup configuration parameter. +Postfix will not accept mail when permit_mx_backup is used while +auth_permit_mx_backup is not configured. + The protocol between Postfix master and child processes has changed. You must stop and start Postfix in order to switch between Snapshot 20010801 and releases that implement the older protocol. -Major changes with snapshot-20010801 +Major changes with snapshot-20010802 ==================================== Specify "disable_verp_bounces = yes" to have Postfix send one RFC-standard, non-VERP, bounce report for multi-recipient mail, even when VERP style delivery is requested. +Fine control over address masquerading. The masquerade_classes +parameter controls header and envelope sender and recipient addresses. + Variable coupling between message receiving rates and message delivery rates. When the message receiving rate exceeds the message delivery rate, an SMTP server will pause for $in_flow_delay seconds @@ -20,14 +32,14 @@ a chance catch up and access the disk, while still allowing new mail to arrive. The in_flow_delay feature has effect mainly when your system is -being flooded port through a limited number of SMTP connections. -This is also useful for mass-mailing applications, because it avoids -the need to hand-tune the rate at which mail is sent into Postfix. +being flooded through a limited number of SMTP connections. This +is useful for mass-mailing applications, because it eliminates the +need to hand-tune the rate for sending mail into Postfix. The in_flow_delay feature has negligible effect when mail arrives via many different SMTP connections. With the default limit of 50 SMTP server processes and with the default $in_flow_delay of 1 -second, total mail inflow is limited to 50 messages per second more +second, the mail inflow is limited to 50 messages per second more than the number of messages that are delivered per second. Many systems saturate at values much smaller than 50 messages per second. diff --git a/postfix/conf/canonical b/postfix/conf/canonical index 6be24c040..34288f8ca 100644 --- a/postfix/conf/canonical +++ b/postfix/conf/canonical @@ -151,6 +151,11 @@ # The network interface addresses that this system # receives mail on. # +# masquerade_classes +# List of address classes subject to masquerading: +# zero or more of envelope_sender, envelope_recipi- +# ent, header_sender, header_recipient. +# # masquerade_domains # List of domains that hide their subdomain struc- # ture. @@ -166,17 +171,16 @@ # myorigin # The domain that is appended to locally-posted mail. # +# 3 +# +# CANONICAL(5) CANONICAL(5) +# # owner_request_special # Give special treatment to owner-xxx and xxx-request # addresses. # # SEE ALSO # cleanup(8) canonicalize and enqueue mail -# -# 3 -# -# CANONICAL(5) CANONICAL(5) -# # postmap(1) create mapping table # virtual(5) virtual domain mapping # pcre_table(5) format of PCRE tables diff --git a/postfix/conf/master.cf b/postfix/conf/master.cf index fc4417323..d4cd4fb35 100644 --- a/postfix/conf/master.cf +++ b/postfix/conf/master.cf @@ -84,6 +84,11 @@ error unix - - n - - error local unix - n n - - local virtual unix - n n - - virtual lmtp unix - - n - - lmtp +# +# Interfaces to non-Postfix software. Be sure to examine the manual +# pages of the non-Postfix software to find out what options it wants. +# The Cyrus deliver program has changed incompatibly. +# cyrus unix - n n - - pipe flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user} uucp unix - n n - - pipe diff --git a/postfix/conf/pcre_table b/postfix/conf/pcre_table index 389466383..d34d5b28d 100644 --- a/postfix/conf/pcre_table +++ b/postfix/conf/pcre_table @@ -43,13 +43,13 @@ # is `U', which makes matching ungreedy (see PCRE documenta- # tion and source for more info). # -# Each pattern is applied to the entire string being looked -# up. Depending on the application, that string is an -# entire client hostname, an entire client IP address, or an -# entire mail address. Thus, no parent domain or parent -# network search is done, and user@domain mail addresses are -# not broken up into their user and domain constituent -# parts, nor is user+foo broken up into user and foo. +# Each pattern is applied to the entire lookup key string. +# Depending on the application, that string is an entire +# client hostname, an entire client IP address, or an entire +# mail address. Thus, no parent domain or parent network +# search is done, and user@domain mail addresses are not +# broken up into their user and domain constituent parts, +# nor is user+foo broken up into user and foo. # # Patterns are applied in the order as specified in the # table, until a pattern is found that matches the search @@ -59,11 +59,11 @@ # # PCRE_TABLE(5) PCRE_TABLE(5) # -# Substitution of sub-strings from the matched expression is -# possible using the conventional perl syntax ($1, $2, -# etc.). The macros in the replacement string may need to be -# written as ${n} or $(n) if they aren't followed by whites- -# pace. +# Substitution of substrings from the matched expression +# into the result string is possible using the conventional +# perl syntax ($1, $2, etc.). The macros in the result +# string may need to be written as ${n} or $(n) if they +# aren't followed by whitespace. # # EXAMPLES # # Protect your outgoing majordomo exploders diff --git a/postfix/conf/regexp_table b/postfix/conf/regexp_table index f9b8a5e2e..5da339f48 100644 --- a/postfix/conf/regexp_table +++ b/postfix/conf/regexp_table @@ -46,13 +46,13 @@ # Other flags are `x' (disable extended expression syntax), # and `m' (enable multi-line mode). # -# Each pattern is applied to the entire string being looked -# up. Depending on the application, that string is an -# entire client hostname, an entire client IP address, or an -# entire mail address. Thus, no parent domain or parent -# network search is done, and user@domain mail addresses are -# not broken up into their user and domain constituent -# parts, nor is user+foo broken up into user and foo. +# Each pattern is applied to the entire lookup key string. +# Depending on the application, that string is an entire +# client hostname, an entire client IP address, or an entire +# mail address. Thus, no parent domain or parent network +# search is done, and user@domain mail addresses are not +# broken up into their user and domain constituent parts, +# nor is user+foo broken up into user and foo. # # Patterns are applied in the order as specified in the # @@ -63,10 +63,10 @@ # table, until a pattern is found that matches the search # string. # -# Substitution of sub-strings from the matched expression is -# possible using $1, $2, etc.. The macros in the replacement -# string may need to be written as ${n} or $(n) if they -# aren't followed by whitespace. +# Substitution of substrings from the matched expression +# into the result string is possible using $1, $2, etc.. The +# macros in the result string may need to be written as ${n} +# or $(n) if they aren't followed by whitespace. # # EXAMPLES # # Disallow sender-specified routing. This is a must if you relay mail diff --git a/postfix/conf/sample-rewrite.cf b/postfix/conf/sample-rewrite.cf index b4073fb4b..deed2785f 100644 --- a/postfix/conf/sample-rewrite.cf +++ b/postfix/conf/sample-rewrite.cf @@ -27,6 +27,19 @@ append_dot_mydomain = yes # empty_address_recipient = MAILER-DAEMON +# The masquerade_classes parameter controls what addresses are +# subject to address masquerading. +# +# By default, address masquerading is limited to envelope recipient +# addresses, and to header sender and header recipient addresses. +# This allows you to use address masquerading on a mail gateway while +# still being able to forward mail to users on individual machines. +# +# Specify zero or more of: envelope_sender, envelope_recipient, +# header_sender, header_recipient +# +masquerade_classes = envelope_sender, header_sender, header_recipient + # The masquerade_domains parameter gives an optional list of domains # that must have their subdomain structure stripped off. # diff --git a/postfix/conf/sample-smtpd.cf b/postfix/conf/sample-smtpd.cf index 082cb760c..fc513f145 100644 --- a/postfix/conf/sample-smtpd.cf +++ b/postfix/conf/sample-smtpd.cf @@ -282,7 +282,8 @@ smtpd_sender_restrictions = # - to destinations matching $relay_domains or subdomain thereof, # except for addresses with sender-specified routing. # reject_unauth_pipelining: reject mail from improperly pipelining spamware -# permit_mx_backup: accept mail for sites that list me as MX host. +# permit_mx_backup: accept mail for sites whose primary MX hosts +# match the networks specified with auth_mx_backup_networks. # reject_unknown_recipient_domain: reject domains without A or MX record. # check_recipient_access maptype:mapname # maptype:mapname: look up recipient address, parent domain, or localpart@. @@ -309,6 +310,20 @@ smtpd_sender_restrictions = # smtpd_recipient_restrictions = permit_mynetworks,check_relay_domains +# The auth_mx_backup_networks parameter specifies a list of networks +# for which the permit_mx_backup feature (see above) can be used. +# +# By default, auth_mx_backup_networks is empty and no networks are +# authorized to use the permit_mx_backup feature. You can specify +# a complete class A network (X.0.0.0/8), a complete class B network +# (X.X.0.0/16), and so on. If you want stricter control, specify a +# list of network/mask patterns, where the mask specifies the number +# of bits in the network part of a host address. You can also specify +# the absolute pathname of a pattern file instead of listing the +# patterns here. +# +auth_mx_backup_networks = + # # ADDITIONAL UCE CONTROLS # diff --git a/postfix/html/canonical.5.html b/postfix/html/canonical.5.html index aab106032..53ce0960d 100644 --- a/postfix/html/canonical.5.html +++ b/postfix/html/canonical.5.html @@ -143,6 +143,11 @@ CANONICAL(5) CANONICAL(5) The network interface addresses that this system receives mail on. + masquerade_classes + List of address classes subject to masquerading: + zero or more of envelope_sender, envelope_recipi- + ent, header_sender, header_recipient. + masquerade_domains List of domains that hide their subdomain struc- ture. diff --git a/postfix/html/cleanup.8.html b/postfix/html/cleanup.8.html index 48ab1db87..f1ce60526 100644 --- a/postfix/html/cleanup.8.html +++ b/postfix/html/cleanup.8.html @@ -40,17 +40,18 @@ CLEANUP(8) CLEANUP(8) and message header addresses (i.e. strip host or domain information below all domains listed in the masquerade_domains parameter, except for user names - listed in masquerade_exceptions). Address mas- - querading does not affect envelope recipients. + listed in masquerade_exceptions). By default, + address masquerading does not affect envelope + recipients. o Optionally, expand envelope recipients according to - information found in the virtual(5) lookup tables. + information found in the virtual(5) lookup tables. - The cleanup daemon performs sanity checks on the content - of each message. When it finds a problem, by default it - returns a diagnostic status to the client, and leaves it - up to the client to deal with the problem. Alternatively, - the client can request the cleanup daemon to bounce the + The cleanup daemon performs sanity checks on the content + of each message. When it finds a problem, by default it + returns a diagnostic status to the client, and leaves it + up to the client to deal with the problem. Alternatively, + the client can request the cleanup daemon to bounce the message back to the sender in case of trouble. STANDARDS @@ -60,30 +61,30 @@ CLEANUP(8) CLEANUP(8) Problems and transactions are logged to syslogd(8). BUGS - Table-driven rewriting rules make it hard to express if + Table-driven rewriting rules make it hard to express if then else and other logical relationships. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant - to this program. See the Postfix main.cf file for syntax - details and for default values. Use the postfix reload + The following main.cf parameters are especially relevant + to this program. See the Postfix main.cf file for syntax + details and for default values. Use the postfix reload command after a configuration change. Content filtering body_checks Lookup tables with content filters for message body - lines. These filters see physical lines one at a + lines. These filters see physical lines one at a time, in chunks of at most line_length_limit bytes. header_checks - Lookup tables with content filters for message - header lines. These filters see logical headers + Lookup tables with content filters for message + header lines. These filters see logical headers one at a time, including headers that span multiple lines. Miscellaneous always_bcc - Address to send a copy of each message that enters + Address to send a copy of each message that enters the system. hopcount_limit @@ -96,8 +97,8 @@ CLEANUP(8) CLEANUP(8) Address transformations empty_address_recipient - The destination for undeliverable mail from <>. - This substitution is done before all other address + The destination for undeliverable mail from <>. + This substitution is done before all other address rewriting. canonical_maps @@ -112,12 +113,17 @@ CLEANUP(8) CLEANUP(8) Address mapping lookup table for envelope and header sender addresses. + masquerade_classes + List of address classes subject to masquerading: + zero or more of envelope_sender, envelope_recipi- + ent, header_sender, header_recipient. + masquerade_domains - List of domains that hide their subdomain struc- + List of domains that hide their subdomain struc- ture. masquerade_exceptions - List of user names that are not subject to address + List of user names that are not subject to address masquerading. virtual_maps @@ -126,7 +132,7 @@ CLEANUP(8) CLEANUP(8) Resource controls duplicate_filter_limit - Limit the number of envelope recipients that are + Limit the number of envelope recipients that are remembered. header_size_limit @@ -135,11 +141,11 @@ CLEANUP(8) CLEANUP(8) in_flow_delay Amount of time to pause before accepting a message, - when the message arrival rate exceeds the message + when the message arrival rate exceeds the message delivery rate. extract_recipient_limit - Limit the amount of recipients extracted from mes- + Limit the amount of recipients extracted from mes- sage headers. SEE ALSO @@ -154,7 +160,7 @@ CLEANUP(8) CLEANUP(8) /etc/postfix/virtual*, virtual mapping table LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/html/faq.html b/postfix/html/faq.html index 64ea296ba..734337f5b 100644 --- a/postfix/html/faq.html +++ b/postfix/html/faq.html @@ -1521,7 +1521,10 @@ href="uce.html#reject_unauth_destination">reject_unauth_destination: reject when the destination is not local.
  • permit_mx_backup: -reject when the destination is not local. +permit if the local system is listed as MX host for the recipient +domain, provided that the primary MX host for the recipient domain +is within the networks specified with auth_mx_backup_networks.
  • Other UCE restrictions (e.g., SMTPD access maps) are not aware of sender-provided routing information. diff --git a/postfix/html/rewrite.html b/postfix/html/rewrite.html index fae9e4a48..b1ade9a61 100644 --- a/postfix/html/rewrite.html +++ b/postfix/html/rewrite.html @@ -226,7 +226,7 @@ send mail to the those ugly address without creating a mailer loop.

    Address masquerading

    -Address masquerading is a method to hide all hosts below a domain +Address masquerading is a method to hide all hosts inside a domain behind their mail gateway, and to make it appear as if the mail comes from the gateway itself, instead of from individual machines. @@ -267,8 +267,28 @@ For example, By default, Postfix makes no exceptions.

    -Subtle point: address masquerading is applied only to message -headers and envelope sender addresses, not to envelope recipients. +Subtle point: by default, address masquerading is applied only to +message headers and to envelope sender addresses, but not to envelope +recipients. This allows you to use address masquerading on a mail +gateway machine, while still being able to forward mail from outside +to users on individual machines. + +

    + +In order to subject envelope recipient addresses to masquerading, +too, specify (only available with Postfix versions after 20010802): + +

    + +
    masquerade_classes = envelope_sender, envelope_recipient, +header_sender, header_recipient + +
    + +

    + +If you do this, Postfix will no longer be able to send mail to +individual machines.

    Virtual address mapping

    diff --git a/postfix/html/uce.html b/postfix/html/uce.html index b756a43be..a7c5a609e 100644 --- a/postfix/html/uce.html +++ b/postfix/html/uce.html @@ -722,17 +722,20 @@ code for rejected requests (default: 554).
    permit_mx_backup
    Permit the request when the local -mail system is MX host for the resolved destination. This includes -the case that the local mail system is the final destination. -However, the SMTP server will not forward mail with addresses that -have sender-specified routing information (example: +mail system is MX host for the resolved destination, provided that +the primary MX host is within the networks specified with auth_mx_backup_networks parameter. +This includes the case that the local mail system is the final +destination. However, the SMTP server will not forward mail with +addresses that have sender-specified routing information (example: user@elsewhere@domain),

    -Relevant configuration parameters: -$mydestination, -$inet_interfaces. +Relevant configuration parameters: auth_mx_backup_networks, $mydestination, $inet_interfaces.

    @@ -966,6 +969,52 @@ to speed up deliveries.

    + + +
    auth_mx_backup_networks + +
    This parameter specifies the networks that are allowed to +use the permit_mx_backup +relay control feature. + +

    + +

    + +
    Default: + +
    auth_mx_backup_networks = + +

    + +That is, no networks are authorized by default. + +

    + +

    Syntax: + +
    Specify a list of network +blocks in CIDR (network/mask) notation, for example: + +

    + +

    + +
    auth_mx_backup_networks = 168.100.0.0/16 + +
    + +

    + +You can also specify the absolute pathname of a pattern file instead +of listing the patterns in the main.cf file. + +

    + +
    + +
    +
    maps_rbl_domains diff --git a/postfix/man/man5/canonical.5 b/postfix/man/man5/canonical.5 index 8dfaf2933..1bddf88ff 100644 --- a/postfix/man/man5/canonical.5 +++ b/postfix/man/man5/canonical.5 @@ -139,6 +139,10 @@ addresses. Other parameters of interest: .IP \fBinet_interfaces\fR The network interface addresses that this system receives mail on. +.IP \fBmasquerade_classes\fR +List of address classes subject to masquerading: zero or more of +\fBenvelope_sender\fR, \fBenvelope_recipient\fR, \fBheader_sender\fR, +\fBheader_recipient\fR. .IP \fBmasquerade_domains\fR List of domains that hide their subdomain structure. .IP \fBmasquerade_exceptions\fR diff --git a/postfix/man/man8/cleanup.8 b/postfix/man/man8/cleanup.8 index 098cc2942..ed01ee8b6 100644 --- a/postfix/man/man8/cleanup.8 +++ b/postfix/man/man8/cleanup.8 @@ -41,7 +41,7 @@ Optionally, masquerade envelope sender addresses and message header addresses (i.e. strip host or domain information below all domains listed in the \fBmasquerade_domains\fR parameter, except for user names listed in \fBmasquerade_exceptions\fR). -Address masquerading does not affect envelope recipients. +By default, address masquerading does not affect envelope recipients. .IP \(bu Optionally, expand envelope recipients according to information found in the \fBvirtual\fR(5) lookup tables. @@ -108,6 +108,10 @@ addresses. .IP \fBsender_canonical_maps\fR Address mapping lookup table for envelope and header sender addresses. +.IP \fBmasquerade_classes\fR +List of address classes subject to masquerading: zero or +more of \fBenvelope_sender\fR, \fBenvelope_recipient\fR, +\fBheader_sender\fR, \fBheader_recipient\fR. .IP \fBmasquerade_domains\fR List of domains that hide their subdomain structure. .IP \fBmasquerade_exceptions\fR diff --git a/postfix/proto/canonical b/postfix/proto/canonical index 4eaf21f79..74346dd18 100644 --- a/postfix/proto/canonical +++ b/postfix/proto/canonical @@ -123,6 +123,10 @@ # Other parameters of interest: # .IP \fBinet_interfaces\fR # The network interface addresses that this system receives mail on. +# .IP \fBmasquerade_classes\fR +# List of address classes subject to masquerading: zero or more of +# \fBenvelope_sender\fR, \fBenvelope_recipient\fR, \fBheader_sender\fR, +# \fBheader_recipient\fR. # .IP \fBmasquerade_domains\fR # List of domains that hide their subdomain structure. # .IP \fBmasquerade_exceptions\fR diff --git a/postfix/src/cleanup/cleanup.c b/postfix/src/cleanup/cleanup.c index 3026f9740..01a67f09f 100644 --- a/postfix/src/cleanup/cleanup.c +++ b/postfix/src/cleanup/cleanup.c @@ -35,7 +35,7 @@ /* header addresses (i.e. strip host or domain information below /* all domains listed in the \fBmasquerade_domains\fR parameter, /* except for user names listed in \fBmasquerade_exceptions\fR). -/* Address masquerading does not affect envelope recipients. +/* By default, address masquerading does not affect envelope recipients. /* .IP \(bu /* Optionally, expand envelope recipients according to information /* found in the \fBvirtual\fR(5) lookup tables. @@ -94,6 +94,10 @@ /* .IP \fBsender_canonical_maps\fR /* Address mapping lookup table for envelope and header sender /* addresses. +/* .IP \fBmasquerade_classes\fR +/* List of address classes subject to masquerading: zero or +/* more of \fBenvelope_sender\fR, \fBenvelope_recipient\fR, +/* \fBheader_sender\fR, \fBheader_recipient\fR. /* .IP \fBmasquerade_domains\fR /* List of domains that hide their subdomain structure. /* .IP \fBmasquerade_exceptions\fR diff --git a/postfix/src/cleanup/cleanup.h b/postfix/src/cleanup/cleanup.h index a1e56848c..d5ae9c3cd 100644 --- a/postfix/src/cleanup/cleanup.h +++ b/postfix/src/cleanup/cleanup.h @@ -71,6 +71,15 @@ extern MAPS *cleanup_header_checks; extern MAPS *cleanup_body_checks; extern MAPS *cleanup_virtual_maps; extern ARGV *cleanup_masq_domains; +extern int cleanup_masq_flags; + + /* + * Address masquerading fine control. + */ +#define CLEANUP_MASQ_FLAG_ENV_FROM (1<<0) /* envelope sender */ +#define CLEANUP_MASQ_FLAG_ENV_RCPT (1<<1) /* envelope recipient */ +#define CLEANUP_MASQ_FLAG_HDR_FROM (1<<2) /* header sender */ +#define CLEANUP_MASQ_FLAG_HDR_RCPT (1<<3) /* header recipient */ /* * Restrictions on extension propagation. diff --git a/postfix/src/cleanup/cleanup_envelope.c b/postfix/src/cleanup/cleanup_envelope.c index 3c5e300d6..f4fd30e75 100644 --- a/postfix/src/cleanup/cleanup_envelope.c +++ b/postfix/src/cleanup/cleanup_envelope.c @@ -149,7 +149,8 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type, char *buf, if (cleanup_comm_canon_maps) cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, cleanup_ext_prop_mask & EXT_PROP_CANONICAL); - if (cleanup_masq_domains) + if (cleanup_masq_domains + && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_FROM)) cleanup_masquerade_internal(clean_addr, cleanup_masq_domains); CLEANUP_OUT_BUF(state, type, clean_addr); if (state->sender == 0) @@ -171,6 +172,9 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type, char *buf, if (cleanup_comm_canon_maps) cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + if (cleanup_masq_domains + && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) + cleanup_masquerade_internal(clean_addr, cleanup_masq_domains); cleanup_out_recipient(state, STR(clean_addr)); if (state->recip == 0) state->recip = mystrdup(STR(clean_addr)); diff --git a/postfix/src/cleanup/cleanup_extracted.c b/postfix/src/cleanup/cleanup_extracted.c index 243404be1..eaa687a98 100644 --- a/postfix/src/cleanup/cleanup_extracted.c +++ b/postfix/src/cleanup/cleanup_extracted.c @@ -123,6 +123,9 @@ static void cleanup_extracted_process(CLEANUP_STATE *state, int type, char *buf, if (cleanup_comm_canon_maps) cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + if (cleanup_masq_domains + && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) + cleanup_masquerade_internal(clean_addr, cleanup_masq_domains); cleanup_out_recipient(state, STR(clean_addr)); if (state->recip == 0) state->recip = mystrdup(STR(clean_addr)); @@ -150,8 +153,8 @@ static void cleanup_extracted_process(CLEANUP_STATE *state, int type, char *buf, if (rcpt->argc >= var_extra_rcpt_limit) { state->errs |= CLEANUP_STAT_ROVFL; } else { + clean_addr = vstring_alloc(100); if (*var_always_bcc && rcpt->argv[0]) { - clean_addr = vstring_alloc(100); cleanup_rewrite_internal(clean_addr, var_always_bcc); if (cleanup_rcpt_canon_maps) cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, @@ -160,13 +163,20 @@ static void cleanup_extracted_process(CLEANUP_STATE *state, int type, char *buf, cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, cleanup_ext_prop_mask & EXT_PROP_CANONICAL); argv_add(rcpt, STR(clean_addr), (char *) 0); - vstring_free(clean_addr); } argv_terminate(rcpt); - for (cpp = rcpt->argv; CLEANUP_OUT_OK(state) && *cpp; cpp++) - cleanup_out_recipient(state, *cpp); + for (cpp = rcpt->argv; CLEANUP_OUT_OK(state) && *cpp; cpp++) { + if (cleanup_masq_domains + && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) { + vstring_strcpy(clean_addr, *cpp); + cleanup_masquerade_internal(clean_addr, cleanup_masq_domains); + cleanup_out_recipient(state, STR(clean_addr)); + } else + cleanup_out_recipient(state, *cpp); + } if (rcpt->argv[0]) state->recip = mystrdup(rcpt->argv[0]); + vstring_free(clean_addr); } } diff --git a/postfix/src/cleanup/cleanup_init.c b/postfix/src/cleanup/cleanup_init.c index 0cb5812c5..b3e7a0157 100644 --- a/postfix/src/cleanup/cleanup_init.c +++ b/postfix/src/cleanup/cleanup_init.c @@ -69,6 +69,7 @@ #include #include +#include /* Global library. */ @@ -106,6 +107,7 @@ char *var_prop_extension; /* propagate unmatched extension */ char *var_always_bcc; /* big brother */ int var_extra_rcpt_limit; /* recipient extract limit */ char *var_rcpt_witheld; /* recipients not disclosed */ +char *var_masq_classes; /* what to masquerade */ CONFIG_INT_TABLE cleanup_int_table[] = { VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0, @@ -133,6 +135,7 @@ CONFIG_STR_TABLE cleanup_str_table[] = { VAR_PROP_EXTENSION, DEF_PROP_EXTENSION, &var_prop_extension, 0, 0, VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0, VAR_RCPT_WITHELD, DEF_RCPT_WITHELD, &var_rcpt_witheld, 1, 0, + VAR_MASQ_CLASSES, DEF_MASQ_CLASSES, &var_masq_classes, 0, 0, 0, }; @@ -146,6 +149,7 @@ MAPS *cleanup_header_checks; MAPS *cleanup_body_checks; MAPS *cleanup_virtual_maps; ARGV *cleanup_masq_domains; +int cleanup_masq_flags; /* * Address extension propagation restrictions. @@ -164,9 +168,17 @@ void cleanup_all(void) void cleanup_pre_jail(char *unused_name, char **unused_argv) { + static NAME_MASK masq_class_table[] = { + MASQ_CLASS_ENV_FROM, CLEANUP_MASQ_FLAG_ENV_FROM, + MASQ_CLASS_ENV_RCPT, CLEANUP_MASQ_FLAG_ENV_RCPT, + MASQ_CLASS_HDR_FROM, CLEANUP_MASQ_FLAG_HDR_FROM, + MASQ_CLASS_HDR_RCPT, CLEANUP_MASQ_FLAG_HDR_RCPT, + 0, + }; + if (*var_canonical_maps) cleanup_comm_canon_maps = - maps_create(VAR_CANONICAL_MAPS, var_canonical_maps, DICT_FLAG_LOCK); + maps_create(VAR_CANONICAL_MAPS, var_canonical_maps, DICT_FLAG_LOCK); if (*var_send_canon_maps) cleanup_send_canon_maps = maps_create(VAR_SEND_CANON_MAPS, var_send_canon_maps, @@ -186,6 +198,9 @@ void cleanup_pre_jail(char *unused_name, char **unused_argv) if (*var_body_checks) cleanup_body_checks = maps_create(VAR_BODY_CHECKS, var_body_checks, DICT_FLAG_LOCK); + if (*var_masq_classes) + cleanup_masq_flags = name_mask(VAR_MASQ_CLASSES, masq_class_table, + var_masq_classes); } /* cleanup_post_jail - initialize after entering the chroot jail */ diff --git a/postfix/src/cleanup/cleanup_message.c b/postfix/src/cleanup/cleanup_message.c index 2c84ff60c..9d67e239b 100644 --- a/postfix/src/cleanup/cleanup_message.c +++ b/postfix/src/cleanup/cleanup_message.c @@ -178,7 +178,8 @@ static void cleanup_rewrite_sender(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts) if (cleanup_comm_canon_maps) cleanup_map11_tree(state, *tpp, cleanup_comm_canon_maps, cleanup_ext_prop_mask & EXT_PROP_CANONICAL); - if (cleanup_masq_domains) + if (cleanup_masq_domains + && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_FROM)) cleanup_masquerade_tree(*tpp, cleanup_masq_domains); if (hdr_opts->type == HDR_FROM && state->from == 0) state->from = cleanup_extract_internal(state->header_buf, *tpp); @@ -230,7 +231,8 @@ static void cleanup_rewrite_recip(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts) argv_add(rcpt, vstring_str(state->temp1), (char *) 0); } } - if (cleanup_masq_domains) + if (cleanup_masq_domains + && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_RCPT)) cleanup_masquerade_tree(*tpp, cleanup_masq_domains); if (hdr_opts->type == HDR_RETURN_RECEIPT_TO && !state->return_receipt) state->return_receipt = diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index bf273b250..655ebd260 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -124,6 +124,17 @@ extern char *var_masq_domains; #define DEF_MASQ_EXCEPTIONS "" extern char *var_masq_exceptions; +#define MASQ_CLASS_ENV_FROM "envelope_sender" +#define MASQ_CLASS_ENV_RCPT "envelope_recipient" +#define MASQ_CLASS_HDR_FROM "header_sender" +#define MASQ_CLASS_HDR_RCPT "header_recipient" + +#define VAR_MASQ_CLASSES "masquerade_classes" +#define DEF_MASQ_CLASSES MASQ_CLASS_ENV_FROM ", " \ + MASQ_CLASS_HDR_FROM ", " \ + MASQ_CLASS_HDR_RCPT +extern char *var_masq_classes; + /* * Intranet versus internet. */ @@ -1111,6 +1122,10 @@ extern int var_relay_code; #define PERMIT_MX_BACKUP "permit_mx_backup" +#define VAR_AUTH_MX_NETWORKS "auth_mx_backup_networks" +#define DEF_AUTH_MX_NETWORKS "" +extern char *var_auth_mx_networks; + #define VAR_ACCESS_MAP_CODE "access_map_reject_code" #define DEF_ACCESS_MAP_CODE 554 extern int var_access_map_code; @@ -1127,7 +1142,7 @@ extern int var_access_map_code; extern int var_maps_rbl_code; #define VAR_MAPS_RBL_DOMAINS "maps_rbl_domains" -#define DEF_MAPS_RBL_DOMAINS "blackholes.mail-abuse.org" +#define DEF_MAPS_RBL_DOMAINS "" extern char *var_maps_rbl_domains; #define VAR_SMTPD_DELAY_REJECT "smtpd_delay_reject" diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 2e2aa1b6c..baf903f19 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -15,7 +15,7 @@ * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" -#define DEF_MAIL_VERSION "Snapshot-20010801" +#define DEF_MAIL_VERSION "Snapshot-20010806" extern char *var_mail_version; /* LICENSE diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 27f808890..4e0eaefb1 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -356,6 +356,7 @@ char *var_smtpd_sasl_opts; char *var_smtpd_sasl_realm; char *var_filter_xport; bool var_broken_auth_clients; +char *var_auth_mx_networks; /* * Global state, for stand-alone mode queue file cleanup. When this is @@ -1590,6 +1591,7 @@ int main(int argc, char **argv) VAR_SMTPD_SASL_OPTS, DEF_SMTPD_SASL_OPTS, &var_smtpd_sasl_opts, 0, 0, VAR_SMTPD_SASL_REALM, DEF_SMTPD_SASL_REALM, &var_smtpd_sasl_realm, 1, 0, VAR_FILTER_XPORT, DEF_FILTER_XPORT, &var_filter_xport, 0, 0, + VAR_AUTH_MX_NETWORKS, DEF_AUTH_MX_NETWORKS, &var_auth_mx_networks, 0, 0, 0, }; diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 7e7631520..01a4b74cc 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -145,9 +145,10 @@ /* Reject the request when the client has already sent the next request /* without being told that the server implements SMTP command pipelining. /* .IP permit_mx_backup -/* Allow the request when the local mail system is mail exchanger -/* for the recipient domain (this includes the case where the local -/* system is the final destination). +/* Allow the request when all primary MX hosts for the recipient +/* are in the networks specified with the $auth_mx_backup_networks +/* configuration parameter, or when the local system is the final +/* destination. /* .IP restriction_classes /* Defines a list of parameter names, each parameter being a list /* of restrictions that can be used anywhere a restriction is legal. @@ -307,6 +308,11 @@ static jmp_buf smtpd_check_buf; #define SMTPD_CHECK_OK 1 /* explicitly permit */ #define SMTPD_CHECK_REJECT 2 /* explicitly reject */ + /* + * XXX For now define SMTPD_CHECK_TRYAGAIN as SMTPD_CHECK_OK. + */ +#define SMTPD_CHECK_TRYAGAIN 1 /* return 4xx try again */ + /* * Intermediate results. These are static to avoid unnecessary stress on the * memory manager routines. @@ -331,6 +337,7 @@ static MAPS *relocated_maps; */ static DOMAIN_LIST *relay_domains; static NAMADR_LIST *mynetworks; +static NAMADR_LIST *auth_mx_networks; /* * Pre-parsed restriction lists. @@ -499,6 +506,7 @@ void smtpd_check_init(void) */ mynetworks = namadr_list_init(var_mynetworks); relay_domains = domain_list_init(var_relay_domains); + auth_mx_networks = namadr_list_init(var_auth_mx_networks); /* * Pre-parse and pre-open the recipient maps. @@ -1014,6 +1022,59 @@ static int reject_unauth_pipelining(SMTPD_STATE *state) return (SMTPD_CHECK_DUNNO); } +/* all_auth_mx_addr - match host addresses against auth_mx_backup_networks */ + +static int all_auth_mx_addr(char *host) +{ + char *myname = "all_auth_mx_addr"; + struct in_addr addr; + DNS_RR *rr; + DNS_RR *addr_list; + int dns_status; + + if (msg_verbose) + msg_info("%s: host %s", myname, host); + + /* + * If we can't lookup the host, try again. + */ +#define NOPE 0 +#define YUP 1 +#define TRYAGAIN 2 + + /* + * Resolve this host into IP addresses, and check if thy are within + * auth_mx_backup_networks + */ + dns_status = dns_lookup(host, T_A, 0, &addr_list, (VSTRING *) 0, (VSTRING *) 0); + if (dns_status != DNS_OK) + return (TRYAGAIN); + + for (rr = addr_list; rr != 0; rr = rr->next) { + if (rr->data_len > sizeof(addr)) { + msg_warn("skipping address length %d", rr->data_len); + continue; + } + memcpy((char *) &addr, rr->data, sizeof(addr)); + if (msg_verbose) + msg_info("%s: checking: %s", myname, inet_ntoa(addr)); + + if (!namadr_list_match(auth_mx_networks, host, inet_ntoa(addr))) { + + /* + * Reject: IP address not listed in auth_mx_backup_networks. + */ + if (msg_verbose) + msg_info("%s: address %s does not match %s", + myname, inet_ntoa(addr), VAR_AUTH_MX_NETWORKS); + dns_rr_free(addr_list); + return (NOPE); + } + } + dns_rr_free(addr_list); + return (YUP); +} + /* has_my_addr - see if this host name lists one of my network addresses */ static int has_my_addr(const char *host) @@ -1055,6 +1116,8 @@ static int has_my_addr(const char *host) return (NOPE); } +#if 0 + /* permit_mx_backup - permit use of me as MX backup for recipient domain */ static int permit_mx_backup(SMTPD_STATE *state, const char *recipient) @@ -1117,7 +1180,7 @@ static int permit_mx_backup(SMTPD_STATE *state, const char *recipient) if (dns_status == DNS_NOTFOUND) return (has_my_addr(domain) ? SMTPD_CHECK_OK : SMTPD_CHECK_DUNNO); if (dns_status != DNS_OK) - return (SMTPD_CHECK_OK); + return (SMTPD_CHECK_TRYAGAIN); /* * First, see if we match any of the MX host names listed. Only if no @@ -1150,6 +1213,122 @@ static int permit_mx_backup(SMTPD_STATE *state, const char *recipient) return (SMTPD_CHECK_DUNNO); } +#endif + +/* permit_auth_mx_backup - relay for authorized networks */ + +static int permit_auth_mx_backup(SMTPD_STATE *state, const char *recipient) +{ + char *myname = "permit_auth_mx_backup"; + const RESOLVE_REPLY *reply; + const char *domain; + + DNS_RR *mx_list; + DNS_RR *mx; + int dns_status; + int best_pref; + + if (msg_verbose) + msg_info("%s: %s", myname, recipient); + + /* + * Sanity check. + */ + if (*var_auth_mx_networks == 0) { + msg_warn("The %s feature requires that you specify authorized networks", + PERMIT_MX_BACKUP); + msg_warn("via the %s configuration parameter. See examples", + VAR_AUTH_MX_NETWORKS); + msg_warn("in the %s/sample-smtpd.cf configuration file.", + var_config_dir); + longjmp(smtpd_check_buf, smtpd_check_reject(state, MAIL_ERROR_SOFTWARE, + "%d <%s>: Configuration error in %s", + 451, recipient, + VAR_AUTH_MX_NETWORKS)); + } + + /* + * Resolve the address. + */ + reply = (const RESOLVE_REPLY *) + ctable_locate(smtpd_resolve_cache, recipient); + + /* + * If the destination is local, it is acceptable, because we are + * supposedly MX for our own address. + */ + if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0) + return (SMTPD_CHECK_OK); + domain += 1; + if (resolve_local(domain) + || (*var_virtual_maps + && check_maps_find(state, recipient, virtual_maps, domain, 0)) + || (*var_virt_mailbox_maps + && check_maps_find(state, recipient, virt_mailbox_maps, domain, 0))) + return (SMTPD_CHECK_OK); + + if (msg_verbose) + msg_info("%s: not local: %s", myname, recipient); + + /* + * Skip source-routed mail (uncertain destination). + */ + if (var_allow_untrust_route == 0 && (reply->flags & RESOLVE_FLAG_ROUTED)) + return (SMTPD_CHECK_DUNNO); + + /* + * Skip numerical forms that didn't match the local system. + */ + if (domain[0] == '#' + || (domain[0] == '[' && domain[strlen(domain) - 1] == ']')) + return (SMTPD_CHECK_DUNNO); + + /* + * Look up the list of MX host names for this domain. If no MX host is + * found, perhaps it is a CNAME for the local machine. Clients aren't + * supposed to send CNAMEs in SMTP commands, but it happens anyway. + */ + dns_status = dns_lookup(domain, T_MX, 0, &mx_list, + (VSTRING *) 0, (VSTRING *) 0); + if (dns_status == DNS_NOTFOUND) + return (has_my_addr(domain) ? SMTPD_CHECK_OK : SMTPD_CHECK_DUNNO); + if (dns_status != DNS_OK) + return (SMTPD_CHECK_TRYAGAIN); + + /* + * Find the preference of the primary MX hosts. + */ + for (best_pref = 0xffff, mx = mx_list; mx != 0; mx = mx->next) + if (mx->pref < best_pref) + best_pref = mx->pref; + + /* + * See if each best MX host has all IP addresses in + * auth_mx_backup_networks. + */ + for (mx = mx_list; mx != 0; mx = mx->next) { + if (mx->pref != best_pref) + continue; + switch (all_auth_mx_addr((char *) mx->data)) { + case NOPE: + dns_rr_free(mx_list); + return (SMTPD_CHECK_DUNNO); + case YUP: + continue; + case TRYAGAIN: + dns_rr_free(mx_list); + return (SMTPD_CHECK_TRYAGAIN); + } + } + + /* + * All IP addresses of the best MX hosts are within + * auth_mx_backup_networks. + */ + dns_rr_free(mx_list); + return (SMTPD_CHECK_OK); +} + /* reject_non_fqdn_address - fail if address is not in fqdn form */ static int reject_non_fqdn_address(SMTPD_STATE *state, char *addr, @@ -1808,7 +1987,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, SMTPD_NAME_RECIPIENT, def_acl); } else if (strcasecmp(name, PERMIT_MX_BACKUP) == 0) { if (state->recipient) - status = permit_mx_backup(state, state->recipient); + status = permit_auth_mx_backup(state, state->recipient); } else if (strcasecmp(name, PERMIT_AUTH_DEST) == 0) { if (state->recipient) status = permit_auth_destination(state, state->recipient);