From 42fc9d60d147743482113ecc6da07cf4ef191b79 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Sat, 5 Jul 2003 00:00:00 -0500 Subject: [PATCH] postfix-2.0.13-20030705 --- postfix/HISTORY | 16 +- postfix/README_FILES/FILTER_README | 259 +++++--------------- postfix/README_FILES/SMTPD_PROXY_README | 69 ++++-- postfix/RELEASE_NOTES | 10 + postfix/conf/access | 2 +- postfix/conf/sample-filter.cf | 30 ++- postfix/conf/sample-misc.cf | 4 +- postfix/html/access.5.html | 2 +- postfix/html/local.8.html | 52 ++-- postfix/html/pickup.8.html | 25 +- postfix/html/postcat.1.html | 8 +- postfix/html/qmqpd.8.html | 27 +- postfix/html/smtpd.8.html | 187 +++++++------- postfix/man/man1/postcat.1 | 4 +- postfix/man/man5/access.5 | 2 +- postfix/man/man8/pickup.8 | 13 + postfix/man/man8/qmqpd.8 | 13 + postfix/man/man8/smtpd.8 | 17 ++ postfix/proto/access | 2 +- postfix/src/bounce/bounce_notify_service.c | 7 +- postfix/src/bounce/bounce_notify_verp.c | 5 +- postfix/src/bounce/bounce_one_service.c | 7 +- postfix/src/bounce/bounce_trace_service.c | 3 +- postfix/src/bounce/bounce_warn_service.c | 7 +- postfix/src/cleanup/Makefile.in | 1 + postfix/src/cleanup/cleanup_addr.c | 60 +++-- postfix/src/cleanup/cleanup_api.c | 8 + postfix/src/cleanup/cleanup_init.c | 3 +- postfix/src/cleanup/cleanup_message.c | 40 +-- postfix/src/cleanup/cleanup_out_recipient.c | 4 +- postfix/src/global/Makefile.in | 12 +- postfix/src/global/cleanup_user.h | 13 + postfix/src/global/dict_proxy.c | 6 +- postfix/src/global/ext_prop.c | 17 +- postfix/src/global/ext_prop.h | 2 +- postfix/src/global/input_transp.c | 67 +++++ postfix/src/global/input_transp.h | 34 +++ postfix/src/global/mail_params.h | 9 + postfix/src/global/mail_version.h | 2 +- postfix/src/lmtp/lmtp_chat.c | 3 +- postfix/src/local/forward.c | 5 +- postfix/src/local/local.c | 3 +- postfix/src/pickup/Makefile.in | 1 + postfix/src/pickup/pickup.c | 45 +++- postfix/src/postcat/postcat.c | 4 +- postfix/src/qmqpd/qmqpd.c | 49 +++- postfix/src/smtp/smtp_chat.c | 3 +- postfix/src/smtpd/Makefile.in | 2 + postfix/src/smtpd/smtpd.c | 56 ++++- postfix/src/smtpd/smtpd.h | 6 + postfix/src/smtpd/smtpd_chat.c | 3 +- postfix/src/smtpd/smtpd_check.c | 3 + postfix/src/smtpd/smtpd_proxy.c | 47 ++-- postfix/src/smtpd/smtpd_proxy.h | 7 +- postfix/src/verify/verify.c | 3 +- 55 files changed, 804 insertions(+), 485 deletions(-) create mode 100644 postfix/src/global/input_transp.c create mode 100644 postfix/src/global/input_transp.h diff --git a/postfix/HISTORY b/postfix/HISTORY index e215dc4bc..483f10e57 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -8273,11 +8273,6 @@ Apologies for any names omitted. avoiding code tries a little harder when it encounters a race condition. File: util/safe_open.c. -20030623 - - Non-prod operator precedence bug with detecting end of - DATA. Matthias Andree. File: smtpd/smtpd.c. - 20030624 Bugfix: reject_unverified_address() set the defer_if_reject @@ -8335,10 +8330,15 @@ Apologies for any names omitted. Feature: TCP lookup table support, finally finished. Files: proto/tcp_table, proto/dict_tcp.[hc]. -20030703 +20030705 - Non-prod: the SMTPD proxy client lost the reply to ".". - Amazing. + Feature: new receive_override_options parameter controls + what happens before or after an external content filter: + rejecting unknown recipients, canonical and virtual address + mapping, address masquerading, automatic BCC recipients + and header/body checks. This is more convenient than having + to specify two different cleanup services in the master.cf + file. Open problems: diff --git a/postfix/README_FILES/FILTER_README b/postfix/README_FILES/FILTER_README index e403b523e..fb7469ff2 100644 --- a/postfix/README_FILES/FILTER_README +++ b/postfix/README_FILES/FILTER_README @@ -1,22 +1,33 @@ Introduction ============ -This is a very first implementation of Postfix content filtering. -A Postfix content filter receives unfiltered mail from Postfix and -does one of the following: +Normally, Postfix receives mail, stores it in the mail queue and +then delivers it. With the external content filter described here, +mail is filtered AFTER it is queued. This gives you maximal control +over how many filtering processes you are willing to run in parallel. -- re-injects the mail back into Postfix, perhaps after changing content -- rejects the mail (by sending a suitable status code back to - Postfix) so that it is returned to sender. -- sends the mail somewhere else +[This is not to be confused with the approach that is described in +the SMTPD_PROXY_README document, where SMTP mail is filtered BEFORE +it is queued] + +An external content filter receives unfiltered mail from Postfix +and does one of the following: + +1 - Re-inject the mail back into Postfix, perhaps after changing + content. + +2 - Reject the mail (by sending a suitable status code back to + Postfix) so that it is returned to sender. + +3 - Send the mail somewhere else. This document describes two approaches to content filtering: simple and advanced. Both filter all the mail by default. At the end are examples that show how to filter only mail from -users, about using different filters for different domains that -you provide MX service for, and about selective filtering on the -basis of message envelope and/or header/body patterns. +users, how to use different filters for different domains that you +provide MX service for, and how to set up selective filtering on +the basis of message envelope and/or header/body patterns. Simple content filtering example ================================ @@ -153,7 +164,7 @@ runs into a resource problem. This approach uses content filtering software that can receive and deliver mail via SMTP. Some Anti-virus software is built to receive and deliver mail via -SMTP and is ready to use as an advanced Postfix content filter. +SMTP and is ready to use as an advanced external content filter. For non-SMTP capable content filtering software, Bennett Todd's SMTP proxy implements a nice PERL/SMTP content filtering framework. See: http://bent.latency.net/smtpprox/ @@ -189,16 +200,21 @@ Postfix via localhost port 10026. : : ................. -To enable content filtering in this manner, specify in main.cf a -new parameter: +To enable content filtering in this manner, specify in main.cf: /etc/postfix/main.cf: content_filter = scan:localhost:10025 + receive_override_options = no_address_mappings -This causes Postfix to add one extra content filtering record to -each incoming mail message, with content scan:localhost:10025. -The content filtering records are added by the smtpd and pickup -servers. +The first line causes Postfix to add one extra content filtering +record to each incoming mail message, with content scan:localhost:10025. +The content filtering records are added by the smtpd, pickup and +qmqpd servers. + +The second line disables address mapping before the content filter, +so that the content filter sees the original mail addresses instead +of the result of virtual alias expansion, canonical mapping, address +masquerading, etc. When a queue file has content filtering information, the queue manager will deliver the mail to the specified content filter @@ -258,8 +274,7 @@ a dedicated listener on port localhost 10026: /etc/postfix/master.cf: localhost:10026 inet n - n - 10 smtpd -o content_filter= - -o local_recipient_maps= - -o relay_recipient_maps= + -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks -o myhostname=localhost.domain.tld -o smtpd_helo_restrictions= -o smtpd_client_restrictions= @@ -267,196 +282,30 @@ a dedicated listener on port localhost 10026: -o smtpd_recipient_restrictions=permit_mynetworks,reject -o mynetworks=127.0.0.0/8 -Warning for Postfix version 2 users: in this SMTP server after the -content filter, do not override main.cf settings for virtual_alias_maps -or virtual_alias_domains. That would cause mail to be rejected with -"User unknown". +Note: do not use spaces around the "=" or "," characters. This SMTP server has the same process limit as the "filter" master.cf entry. -The "-o content_filter=" requests no content filtering for incoming -mail. +The "-o content_filter=" overrides main.cf and requests no content +filtering for incoming mail. This is required or else mail will +stay in the content filtering loop. -The "-o local_recipient_maps=" and "-o relay_recipient_maps=" avoid -unnecessary table lookups. +The "-o receive_override_options" line overrides main.cf and turns +off table lookups that were already done before the content filter: +attempts to find out if a recipient is unknown, and header/body +checks that can suck up lots of CPU cycles. These override options +are either implemented by the SMTP server itself, or they are passed +on to the cleanup server. -The "-o myhostname=localhost.domain.tld" avoids false alarms ("host - greeted me with my own hostname") if your content -filter is based on a proxy that simply relays SMTP commands. +The "-o myhostname=localhost.domain.tld" overrides main.cf and +avoids false alarms ("host greeted me with my own +hostname") if your content filter is based on a proxy that simply +relays SMTP commands. The "-o smtpd_xxx_restrictions" and "-o mynetworks=127.0.0.0/8" -turn off UCE controls that would only waste time here. - -Squeezing out more performance -============================== - -Many refinements are possible, such as running a specially-configured -smtp delivery agent for feeding mail into the content filter, and -turning off address rewriting before content filtering. - -As the example below shows, things quickly become very complex, -because a lot of main.cf like information gets listed in the -master.cf file. This makes the system hard to understand. - -Even worse, details change as Postfix evolves and different -configuration parameters are implemented by different programs. - -If you need to squeeze out more performance, it is probably simpler -to run multiple Postfix instances, one before and one after the -content filter. That way, each instance can have simple main.cf -and master.cf files, each instance can have its own mail queue, -and the system will be easier to understand. - -As before, we will set up a content filtering program that receives -SMTP mail via localhost port 10025, and that submits SMTP mail back -into Postfix via localhost port 10026. - - ....................................... - : Postfix : - ----->smtpd \ : - : -pre-cleanup-\ /local----> - ---->pickup / -queue- : - : -cleanup-/ | \smtp-----> - : bounces/ ^ v : - : and locally | v : - : forwarded smtpd scan : - : messages 10026 | : - ...........................|........... - ^ | - | v - ....|............. - : | 10025 : - : filter : - : : - .................. - -To enable content filtering in this manner, specify in main.cf a -new parameter: - -/etc/postfix/main.cf: - content_filter = scan:localhost:10025 - -/etc/postfix/master.cf: -# -# These are the usual input "smtpd" and local "pickup" servers already -# present in master.cf. We add an option to select a non-default -# cleanup service (defined further below). -# -smtp inet n - n - - smtpd - -o cleanup_service_name=pre-cleanup -pickup fifo n - n 60 1 pickup - -o cleanup_service_name=pre-cleanup -# -# ------------------------------------------------------------------ -# -# This is the cleanup daemon that handles messages in front of -# the content filter. It does header_checks and body_checks (if -# any), but does no virtual alias or canonical address mapping, -# so that mail passes through your content filter with the original -# recipient addresses mostly intact. -# -# Virtual alias or canonical address mapping happens in the second -# cleanup phase after the content filter. This gives the content_filter -# access to *largely* unmodified addresses for maximum flexibility. -# -# Some sites may specifically want to perform canonical or virtual -# address mapping in front of the content_filter. In that case you -# still have to enable address rewriting in the after-filter cleanup -# instance, in order to correctly process forwarded mail or bounced -# mail. -# -pre-cleanup unix n - n - 0 cleanup - -o canonical_maps= - -o sender_canonical_maps= - -o recipient_canonical_maps= - -o masquerade_domains= - -o virtual_alias_maps= -# -# ------------------------------------------------------------------ -# -# This is the delivery agent that injects mail into the content -# filter. It is tuned for low concurrency, because most content -# filters burn CPU and use lots of memory. The process limit of 10 -# re-enforces the effect of $default_destination_concurrency_limit. -# Even without an explicit process limit, the concurrency is bounded -# because all messages heading into the content filter have the same -# destination. -# -scan unix - - n - 10 smtp -# -# ------------------------------------------------------------------ -# -# This is the SMTP listener that receives filtered messages from -# the content filter. It *MUST* clear the content_filter -# parameter to avoid loops, and use a different hostname to avoid -# triggering the Postfix SMTP loop detection code. -# -# This "smtpd" uses the normal cleanup service which is also used -# for bounces and for internally forwarded mail. -# -# The parameters from mynetworks onward disable all access -# control other than insisting on connections from one of the IP -# addresses of the host. This is typically overkill, but can -# reduce resource usage, if the default restrictions use lots of -# tables. -# -localhost:10026 inet n - n - - smtpd - -o content_filter= - -o myhostname=localhost.domain.tld - -o local_recipient_maps= - -o relay_recipient_maps= - -o mynetworks=127.0.0.0/8 - -o mynetworks_style=host - -o smtpd_restriction_classes= - -o smtpd_client_restrictions= - -o smtpd_helo_restrictions= - -o smtpd_sender_restrictions= - -o smtpd_recipient_restrictions=permit_mynetworks,reject -# -# Do not override main.cf settings here for virtual_alias_maps or -# virtual_mailbox_maps. This causes mail to be rejected with "User -# unknown in virtual (alias|mailbox) recipient table". -# -# ------------------------------------------------------------------ -# -# This is the normal cleanup daemon for use after content filtering. -# No header or body checks, because those have already been taken -# care of by the pre-cleanup service before the content filter. -# -# The normal cleanup instance does all the virtual alias and canonical -# address mapping that was disabled in the pre-cleanup instance before -# the content filter. This rewriting must be done even when you didn't -# disable address rewriting in the pre-cleanup instance, in order to -# correctly process bounces and locally forwarded mail. -# -cleanup unix n - n - 0 cleanup - -o header_checks= - -o mime_header_checks= - -o nested_header_checks= - -o body_checks= -# -# ------------------------------------------------------------------ -# -# The normal "smtp" delivery agent for contrast with "scan". -# -smtp unix - - n - - smtp - -The above example causes Postfix to add one content filtering record -to each incoming mail message, with content scan:localhost:10025. -You can use the same syntax as in the right-hand side of a Postfix -transport table. The content filtering records are added by the -smtpd and pickup servers. - -The "scan" transport is a dedicated instance of the "smtp" delivery -agent for injecting messages into the SMTP content filter. Using -a dedicated "smtp" transport allows one to tune it for the specific -task of delivering mail to a local content filter (low latency, -low concurrency, throughput dependent on predictably low latency). - -See the previous example for setting up the content filter with -the Postfix spawn service; you can of course use any server that -can be run stand-alone outside the Postfix environment. +override main.cf and turn off UCE controls that would only waste +time here. Filtering mail from outside users only ====================================== @@ -479,7 +328,13 @@ SMTP server addresses in master.cf: # SMTP service for external users, with content filtering. 1.2.3.5:smtp inet n - n - - smtpd - -o content_filter=foo:bar + -o content_filter=foo:bar + -o receive_override_options=no_address_mappings + +After this, you can follow the same procedure as outlined in the +"advanced" content filtering example above, except that you do not +need to specify "content_filter" or "receive_override_options" in +the main.cf file. Getting really nasty ==================== diff --git a/postfix/README_FILES/SMTPD_PROXY_README b/postfix/README_FILES/SMTPD_PROXY_README index 78f1c0d8f..28ddbce06 100644 --- a/postfix/README_FILES/SMTPD_PROXY_README +++ b/postfix/README_FILES/SMTPD_PROXY_README @@ -1,26 +1,26 @@ Purpose of the SMTPD pass-through proxy feature =============================================== -The Postfix SMTP server can be configured to forward all mail to -a proxy server, for example, a real-time SPAM filter. The proxy is -supposed to send the mail into another Postfix SMTP server process -for normal delivery. +Normally, Postfix receives mail, stores it in the mail queue and +then delivers it. The Postfix SMTP server can be configured to +forward all incoming mail to an SMTP proxy server (for example, a +real-time SPAM filter) that inspects all mail BEFORE it is stored +in the Postfix mail queue. -The proxy server receives only the commands that the Postfix SMTP -server has approved. The proxy server should accept the same MAIL -FROM and RCPT TO command syntax as Postfix, but does not need to -support ESMTP command pipelining. +[This is not to be confused with the approach described in the +FILTER_README document, where all mail is inspected AFTER it is +stored in the Postfix mail queue] -This feature is meant to be used as follows: +The SMTP proxy server receives unfiltered mail from Postfix and +does one of the following: - Internet -> smtpd -> proxy -> smtpd -> cleanup -> queue - Postfix Postfix Postfix Postfix +1 - Re-inject the mail back into Postfix, perhaps after changing + content. -For reference, this is the normal path from network to mail queue: - - Internet -> smtpd -> cleanup -> queue - Postfix Postfix Postfix +2 - Reject the mail (by sending a suitable status code back to + Postfix) so that it is returned to sender. +3 - Send the mail somewhere else. Limitations =========== @@ -47,6 +47,36 @@ triggers a Postfix header_checks FILTER action, or send the mail into Postfix via an alternative Postfix SMTP server that always turns on content filtering. +How the Postfix talks to the SMTP proxy +======================================= + +When Postfix talks to the SMTP proxy server it generates its own +EHLO, DATA and QUIT commands, and forwards unmodified copies of +the MAIL FROM and RCPT TO commands that the Postfix SMTP server +has approved. All commands are sent without using ESMTP command +pipelining. The SMTP proxy server must accept the same MAIL FROM +and RCPT TO command syntax as the Postfix SMTP server. + +This feature is meant to be used as follows: + / smtp + Internet -> smtpd -> proxy -> smtpd -> cleanup -> queue -> local + Postfix Postfix \ virtual etc. + +For reference, this is the normal path through Postfix: + + / smtp + Internet -> smtpd -> cleanup -> queue -> local + Postfix \ virtual etc. + +For comparison, this is the FILTER_README approach with an SMTP-based +content filter: + / smtp + Internet -> smtpd -> cleanup -> queue -> local + Postfix ^ v \ virtual etc. + smtpd smtp + Postfix Postfix + \ / + filter <- Configuration parameters ======================== @@ -77,13 +107,20 @@ process. /etc/postfix/master.cf smtp inet n - n - - smtpd - -o smtpd_proxy_filter=26 + -o smtpd_proxy_filter=26 :26 inet n - n - - smtpd + -o receive_override_options=no_unknown_recipient_checks + +Note: do not specify spaces around the "=" or "," characters. The ":26" causes Postfix to listen on the localhost address only. +DO NOT expose the secondary SMTP server to the Internet :-) The result is as follows: Internet -> smtpd on port 25 -> smtpd on port 26 -> cleanup -> queue This configuration is sufficient for stress testing. + +Other suggestions for test configurations: use the Postfix smtp-sink +command as the proxy, or something as basic as netcat. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 90434153d..028de4c2c 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -22,6 +22,16 @@ snapshot release). Patches change the patchlevel and the release date. Snapshots change only the release date, unless they include the same bugfixes as a patch release. +Major changes with Postfix snapshot 2.0.13-20030705 +=================================================== + +New receive_override_options parameter that eliminates the need +for different cleanup service instances before and after an external +content filter. One parameter controls what happens before or after +the content filter: rejecting unknown recipients, canonical mapping, +virtual alias expansion, masquerading, automatic BCC recipients +and header/body checks. See sample-filter.cf for details. + Incompatible changes with Postfix snapshot 2.0.13-20030704 ========================================================== diff --git a/postfix/conf/access b/postfix/conf/access index a09736f87..7eb324c91 100644 --- a/postfix/conf/access +++ b/postfix/conf/access @@ -110,7 +110,7 @@ # A network address is a sequence of one or more # octets separated by ".". # -# NOTE: use the cidr lookup table type if to specify +# NOTE: use the cidr lookup table type to specify # network/netmask patterns. See cidr_table(5) for # details. # diff --git a/postfix/conf/sample-filter.cf b/postfix/conf/sample-filter.cf index 115fdcb7f..8c2182d98 100644 --- a/postfix/conf/sample-filter.cf +++ b/postfix/conf/sample-filter.cf @@ -157,5 +157,33 @@ body_checks = regexp:/etc/postfix/body_checks # # By default, only the first 50 kbytes of a message body segment are # inspected with body_checks patterns. -# +# body_checks_max_size = 51200 + +# The receive_override_options parameter controls what input processing +# happens before or after an external content filter. +# +# Specify zero or more of the following options. The options override +# main.cf settings and are either implemented by the SMTP server, by +# the QMQP server, or by the pickup server, or they are passed on to +# the cleanup server. +# +# When the receive_override_options setting BEFORE the content filter +# is specified in the main.cf file, specify the "AFTER content filter" +# receive_override_options setting in master.cf (or vice versa). +# +# - no_unknown_recipient_checks: Do not try to reject unknown +# recipients (SMTP server only). This is typically specified AFTER +# an external content filter. +# +# - no_address_mappings: Disable canonical address mapping, virtual +# alias map expansion, address masquerading, and automatic BCC +# recipients. This is typically specified BEFORE an external content +# filter. +# +# - no_header_body_checks: Disable header/body_checks. This is +# typically specified AFTER an external content filter. +# +# receive_override_options = no_unknown_recipient_checks, no_header_body_checks +# receive_override_options = no_address_mappings +receive_override_options = diff --git a/postfix/conf/sample-misc.cf b/postfix/conf/sample-misc.cf index dbc5b699d..ce7698da6 100644 --- a/postfix/conf/sample-misc.cf +++ b/postfix/conf/sample-misc.cf @@ -429,7 +429,7 @@ recipient_delimiter = # By default, this feature is disabled. # # Specify the types and names of databases to use. After change, -# run "postmap /etc/postfix/relocated", then "postfix reload". +# run "postmap /etc/postfix/recipient_bcc". # # NOTE: if mail to the BCC address bounces it will be returned to # the sender. @@ -492,7 +492,7 @@ resolve_dequoted_address = no # By default, this feature is disabled. # # Specify the types and names of databases to use. After change, -# run "postmap /etc/postfix/relocated", then "postfix reload". +# run "postmap /etc/postfix/sender_bcc". # # NOTE: if mail to the BCC address bounces it will be returned to # the sender. diff --git a/postfix/html/access.5.html b/postfix/html/access.5.html index 59ab85999..1170783a7 100644 --- a/postfix/html/access.5.html +++ b/postfix/html/access.5.html @@ -111,7 +111,7 @@ ACCESS(5) ACCESS(5) A network address is a sequence of one or more octets separated by ".". - NOTE: use the cidr lookup table type if to specify + NOTE: use the cidr lookup table type to specify network/netmask patterns. See cidr_table(5) for details. diff --git a/postfix/html/local.8.html b/postfix/html/local.8.html index 85675e8b6..ab2f45f0e 100644 --- a/postfix/html/local.8.html +++ b/postfix/html/local.8.html @@ -21,7 +21,7 @@ LOCAL(8) LOCAL(8) reports are sent to the bounce(8) or defer(8) daemon as appropriate. -SYSTEM-WIDE AND USER-LEVEL ALIASING +SYSTEM-WIDE AND USER-LEVEL ALIASING The system administrator can set up one or more system- wide sendmail-style alias databases. Users can have send- mail-style ~/.forward files. Mail for name is delivered @@ -68,7 +68,7 @@ LOCAL(8) LOCAL(8) cate_filter_limit configuration parameter limits the num- ber of remembered recipients. -MAIL FORWARDING +MAIL FORWARDING For the sake of reliability, forwarded mail is re-submit- ted as a new message, so that each recipient has a sepa- rate on-file delivery status record. @@ -79,7 +79,7 @@ LOCAL(8) LOCAL(8) already listed in a Delivered-To: header, the message is bounced. -MAILBOX DELIVERY +MAILBOX DELIVERY The default per-user mailbox is a file in the UNIX mail spool directory (/var/mail/user or /var/spool/mail/user); the location can be specified with the mail_spool_direc- @@ -109,7 +109,7 @@ LOCAL(8) LOCAL(8) UNIX passwd database. In the case of UNIX-style mailbox delivery, the local dae- - mon prepends a "From sender time_stamp" envelope header to + mon prepends a "From sender time_stamp" envelope header to each message, prepends an X-Original-To: header with the recipient address as given to Postfix, prepends an optional Delivered-To: header with the envelope recipient @@ -126,10 +126,10 @@ LOCAL(8) LOCAL(8) the recipient address as given to Postfix, and prepends a Return-Path: header with the envelope sender address. -EXTERNAL COMMAND DELIVERY +EXTERNAL COMMAND DELIVERY The allow_mail_to_commands configuration parameter restricts delivery to external commands. The default set- - ting (alias, forward) forbids command destinations in + ting (alias, forward) forbids command destinations in :include: files. The command is executed directly where possible. Assis- @@ -179,14 +179,14 @@ LOCAL(8) LOCAL(8) The current working directory is the mail queue directory. - The local daemon prepends a "From sender time_stamp" enve- + The local daemon prepends a "From sender time_stamp" enve- lope header to each message, prepends an X-Original-To: header with the recipient address as given to Postfix, prepends an optional Delivered-To: header with the recipi- ent envelope address, prepends a Return-Path: header with the sender envelope address, and appends no empty line. -EXTERNAL FILE DELIVERY +EXTERNAL FILE DELIVERY The delivery format depends on the destination filename syntax. The default is to use UNIX-style mailbox format. Specify a name ending in / for qmail-compatible maildir @@ -197,7 +197,7 @@ LOCAL(8) LOCAL(8) forward) forbids file destinations in :include: files. In the case of UNIX-style mailbox delivery, the local dae- - mon prepends a "From sender time_stamp" envelope header to + mon prepends a "From sender time_stamp" envelope header to each message, prepends an X-Original-To: header with the recipient address as given to Postfix, prepends an optional Delivered-To: header with the recipient envelope @@ -215,12 +215,12 @@ LOCAL(8) LOCAL(8) the recipient address as given to Postfix. The envelope sender address is available in the Return-Path: header. -ADDRESS EXTENSION +ADDRESS EXTENSION The optional recipient_delimiter configuration parameter specifies how to separate address extensions from local recipient names. - For example, with "recipient_delimiter = +", mail for + For example, with "recipient_delimiter = +", mail for name+foo is delivered to the alias name+foo or to the alias name, to the destinations listed in ~name/.for- ward+foo or in ~name/.forward, to the mailbox owned by the @@ -229,7 +229,7 @@ LOCAL(8) LOCAL(8) In all cases the local daemon prepends an optional `Deliv- ered-To: name+foo' header line. -DELIVERY RIGHTS +DELIVERY RIGHTS Deliveries to external files and external commands are made with the rights of the receiving user on whose behalf the delivery is made. In the absence of a user context, @@ -261,10 +261,10 @@ LOCAL(8) LOCAL(8) detected early. The resulting mail forwarding loop is broken by the use of the Delivered-To: message header. -CONFIGURATION PARAMETERS +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 + details and for default values. Use the postfix reload command after a configuration change. Miscellaneous @@ -302,7 +302,7 @@ LOCAL(8) LOCAL(8) prepend_delivered_header Prepend an optional Delivered-To: header upon external forwarding, delivery to command or file. - Specify zero or more of: command, file, forward. + Specify zero or more of: command, file, forward. Turning off Delivered-To: when forwarding mail is not recommended. @@ -314,7 +314,7 @@ LOCAL(8) LOCAL(8) sible by the recipient before attempting delivery. Defer delivery otherwise. -Mailbox delivery +Mailbox delivery fallback_transport Message transport for recipients that are not found in the UNIX passwd database. This parameter over- @@ -323,7 +323,7 @@ LOCAL(8) LOCAL(8) Note: you must update the local_recipient_maps set- ting in the main.cf file, otherwise the Postfix SMTP server will reject mail for non-UNIX accounts - with "User unknown in local recipient table". + with "User unknown in local recipient table". home_mailbox Pathname of a mailbox relative to a user's home @@ -335,10 +335,10 @@ LOCAL(8) LOCAL(8) users. The address is subjected to $name expan- sion. - Note: you must specify "local_recipient_maps =" + Note: you must specify "local_recipient_maps =" (i.e. empty) in the main.cf file, otherwise the Postfix SMTP server will reject mail for non-UNIX - accounts with "User unknown in local recipient + accounts with "User unknown in local recipient table". mail_spool_directory @@ -368,10 +368,10 @@ LOCAL(8) LOCAL(8) non-UNIX accounts then you must update the local_recipient_maps setting in the main.cf file, otherwise the Postfix SMTP server will reject mail - for non-UNIX accounts with "User unknown in local - recipient table". + for non-UNIX accounts with "User unknown in local + recipient table". -Locking controls +Locking controls deliver_lock_attempts Limit the number of attempts to acquire an exclu- sive lock on a mailbox or external file. @@ -387,9 +387,9 @@ LOCAL(8) LOCAL(8) What file locking method(s) to use when delivering to a UNIX-style mailbox. The default setting is system dependent. For a list of available file - locking methods, use the postconf -l command. + locking methods, use the postconf -l command. -Resource controls +Resource controls command_time_limit Limit the amount of time for delivery to external command. @@ -417,7 +417,7 @@ LOCAL(8) LOCAL(8) that is written to upon delivery). Set to zero to disable the limit. -Security controls +Security controls allow_mail_to_commands Restrict the usage of mail delivery to external command. Specify zero or more of: alias, forward, @@ -449,7 +449,7 @@ LOCAL(8) LOCAL(8) The maildir structure appears in the qmail system by Daniel Bernstein. -SEE ALSO +SEE ALSO aliases(5) format of alias database bounce(8) non-delivery status reports postalias(1) create/update alias database diff --git a/postfix/html/pickup.8.html b/postfix/html/pickup.8.html index d30fa6544..a4a308f3f 100644 --- a/postfix/html/pickup.8.html +++ b/postfix/html/pickup.8.html @@ -37,13 +37,13 @@ PICKUP(8) PICKUP(8) already complex cleanup(8) daemon would have to deal with unfiltered user data. -CONFIGURATION PARAMETERS +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 + details and for default values. Use the postfix reload command after a configuration change. -Content inspection controls +Content inspection controls content_filter The name of a mail delivery transport that filters mail and that either bounces mail or re-injects the @@ -51,11 +51,28 @@ PICKUP(8) PICKUP(8) same syntax as the right-hand side of a Postfix transport table. + receive_override_options + The following options override main.cf settings. + The options are passed on to the downstream cleanup + server. + + no_address_mappings + Disable canonical address mapping, virtual + alias map expansion, address masquerading, + and automatic BCC recipients. Specify this + if address mapping etc. are to be done after + an external content filter. + + no_header_body_checks + Disable header/body_checks. Specify this if + header/body_checks are to be done after an + external content filter. + Miscellaneous queue_directory Top-level directory of the Postfix queue. -SEE ALSO +SEE ALSO cleanup(8) message canonicalization master(8) process manager sendmail(1), postdrop(8) mail posting agent diff --git a/postfix/html/postcat.1.html b/postfix/html/postcat.1.html index 3d70fb129..e601eccb0 100644 --- a/postfix/html/postcat.1.html +++ b/postfix/html/postcat.1.html @@ -20,8 +20,8 @@ POSTCAT(1) POSTCAT(1) directory instead of the default configuration directory. - -q Search the Postfix queue for files. By default, - file names are taken literally. + -q Search the Postfix queue for the named files + instead of taking the names literally. -v Enable verbose logging for debugging purposes. Mul- tiple -v options make the software increasingly @@ -34,9 +34,9 @@ POSTCAT(1) POSTCAT(1) MAIL_CONFIG Directory with Postfix configuration files. -CONFIGURATION PARAMETERS +CONFIGURATION PARAMETERS See the Postfix main.cf file for syntax details and for - default values. Use the postfix reload command after a + default values. Use the postfix reload command after a configuration change. queue_directory diff --git a/postfix/html/qmqpd.8.html b/postfix/html/qmqpd.8.html index 19d36f7ff..58dece64f 100644 --- a/postfix/html/qmqpd.8.html +++ b/postfix/html/qmqpd.8.html @@ -37,10 +37,10 @@ QMQPD(8) QMQPD(8) Postfix replies immediately and closes the connection. It is left up to the client to handle the situation. -CONFIGURATION PARAMETERS +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 + details and for default values. Use the postfix reload command after a configuration change. Miscellaneous @@ -71,7 +71,7 @@ QMQPD(8) QMQPD(8) reject responses. This can be useful for testing purposes. -Content inspection controls +Content inspection controls content_filter The name of a mail delivery transport that filters mail and that either bounces mail or re-injects the @@ -79,7 +79,24 @@ QMQPD(8) QMQPD(8) same syntax as the right-hand side of a Postfix transport table. -Resource controls + receive_override_options + The following options override main.cf settings. + The options are passed on to the downstream cleanup + server. + + no_address_mappings + Disable canonical address mapping, virtual + alias map expansion, address masquerading, + and automatic BCC recipients. Specify this + if address mapping etc. are to be done after + an external content filter. + + no_header_body_checks + Disable header/body_checks. Specify this if + header/body_checks are to be done after an + external content filter. + +Resource controls line_length_limit Limit the amount of memory in bytes used for the handling of partial input lines, and the length of @@ -96,7 +113,7 @@ QMQPD(8) QMQPD(8) Time to wait in seconds before informing the client of a problem. This slows down run-away errors. -SEE ALSO +SEE ALSO http://cr.yp.to/proto/qmqp.html, QMQP protocol cleanup(8) message canonicalization master(8) process manager diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index 7eb550c03..8eba72b2a 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -80,10 +80,33 @@ SMTPD(8) SMTPD(8) same syntax as the right-hand side of a Postfix transport table. + receive_override_options + The following options override main.cf settings. + The options are either implemented by the SMTP + server or are passed on to the downstream cleanup + server. + + no_unknown_recipient_checks + Do not try to reject unknown recipients. + This is typically specified with the SMTP + server after an external content filter. + + no_address_mappings + Disable canonical address mapping, virtual + alias map expansion, address masquerading, + and automatic BCC recipients. This is typi- + cally specified with the SMTP server before + an external content filter. + + no_header_body_checks + Disable header/body_checks. This is typi- + cally specified with the SMTP server after + an external content filter. + Authentication controls enable_sasl_authentication - Enable per-session authentication as per RFC 2554 - (SASL). This functionality is available only when + Enable per-session authentication as per RFC 2554 + (SASL). This functionality is available only when explicitly selected at program build time and explicitly enabled at runtime. @@ -109,16 +132,16 @@ SMTPD(8) SMTPD(8) Disallow anonymous logins. smtpd_sender_login_maps - Maps that specify the SASL login name that owns a - MAIL FROM sender address. Used by the + Maps that specify the SASL login name that owns a + MAIL FROM sender address. Used by the reject_sender_login_mismatch sender anti-spoofing restriction. Pass-through proxy - Optionally, the Postfix SMTP server can be configured to - forward all mail to a proxy server, for example a real- - time content filter. This proxy server should support the - same MAIL FROM and RCPT TO command syntax as Postfix, but + Optionally, the Postfix SMTP server can be configured to + forward all mail to a proxy server, for example a real- + time content filter. This proxy server should support the + same MAIL FROM and RCPT TO command syntax as Postfix, but does not need to support ESMTP command pipelining. smtpd_proxy_filter @@ -139,23 +162,23 @@ SMTPD(8) SMTPD(8) that are authorized to use the XVERP extension. debug_peer_level - Increment in verbose logging level when a remote + Increment in verbose logging level when a remote host matches a pattern in the debug_peer_list parameter. debug_peer_list - List of domain or network patterns. When a remote - host matches a pattern, increase the verbose log- - ging level by the amount specified in the + List of domain or network patterns. When a remote + host matches a pattern, increase the verbose log- + ging level by the amount specified in the debug_peer_level parameter. default_verp_delimiters The default VERP delimiter characters that are used - when the XVERP command is specified without + when the XVERP command is specified without explicit delimiters. error_notice_recipient - Recipient of protocol/policy/resource/software + Recipient of protocol/policy/resource/software error notices. hopcount_limit @@ -164,18 +187,18 @@ SMTPD(8) SMTPD(8) notify_classes List of error classes. Of special interest are: - policy When a client violates any policy, mail a + policy When a client violates any policy, mail a transcript of the entire SMTP session to the postmaster. protocol - When a client violates the SMTP protocol or + When a client violates the SMTP protocol or issues an unimplemented command, mail a transcript of the entire SMTP session to the postmaster. smtpd_banner - Text that follows the 220 status code in the SMTP + Text that follows the 220 status code in the SMTP greeting banner. smtpd_expansion_filter @@ -183,57 +206,57 @@ SMTPD(8) SMTPD(8) expansion of rbl template responses and other text. smtpd_recipient_limit - Restrict the number of recipients that the SMTP + Restrict the number of recipients that the SMTP server accepts per message delivery. smtpd_timeout - Limit the time to send a server response and to + Limit the time to send a server response and to receive a client request. soft_bounce - Change hard (5xx) reject responses into soft (4xx) - reject responses. This can be useful for testing + Change hard (5xx) reject responses into soft (4xx) + reject responses. This can be useful for testing purposes. verp_delimiter_filter - The characters that Postfix accepts as VERP delim- + The characters that Postfix accepts as VERP delim- iter characters. Known versus unknown recipients show_user_unknown_table_name - Whether or not to reveal the table name in the - "User unknown" responses. The extra detail makes - trouble shooting easier but also reveals informa- + Whether or not to reveal the table name in the + "User unknown" responses. The extra detail makes + trouble shooting easier but also reveals informa- tion that is nobody elses business. unknown_local_recipient_reject_code The response code when a client specifies a recipi- - ent whose domain matches $mydestination or + ent whose domain matches $mydestination or $inet_interfaces, while $local_recipient_maps is - non-empty and does not list the recipient address + non-empty and does not list the recipient address or address local-part. unknown_relay_recipient_reject_code The response code when a client specifies a recipi- ent whose domain matches $relay_domains, while - $relay_recipient_maps is non-empty and does not + $relay_recipient_maps is non-empty and does not list the recipient address. unknown_virtual_alias_reject_code The response code when a client specifies a recipi- - ent whose domain matches $virtual_alias_domains, - while the recipient is not listed in $vir- + ent whose domain matches $virtual_alias_domains, + while the recipient is not listed in $vir- tual_alias_maps. unknown_virtual_mailbox_reject_code The response code when a client specifies a recipi- - ent whose domain matches $virtual_mailbox_domains, + ent whose domain matches $virtual_mailbox_domains, while the recipient is not listed in $virtual_mail- box_maps. Resource controls line_length_limit - Limit the amount of memory in bytes used for the + Limit the amount of memory in bytes used for the handling of partial input lines. message_size_limit @@ -241,8 +264,8 @@ SMTPD(8) SMTPD(8) ing on-disk storage for envelope information. queue_minfree - Minimal amount of free space in bytes in the queue - file system for the SMTP server to accept any mail + Minimal amount of free space in bytes in the queue + file system for the SMTP server to accept any mail at all. smtpd_history_flush_threshold @@ -257,23 +280,23 @@ SMTPD(8) SMTPD(8) smtpd_soft_error_limit When an SMTP client has made this number of errors, - wait error_count seconds before responding to any + wait error_count seconds before responding to any client request. smtpd_hard_error_limit - Disconnect after a client has made this number of + Disconnect after a client has made this number of errors. smtpd_junk_command_limit Limit the number of times a client can issue a junk - command such as NOOP, VRFY, ETRN or RSET in one - SMTP session before it is penalized with tarpit + command such as NOOP, VRFY, ETRN or RSET in one + SMTP session before it is penalized with tarpit delays. UCE control restrictions parent_domain_matches_subdomains - List of Postfix features that use domain.tld pat- - terns to match sub.domain.tld (as opposed to + List of Postfix features that use domain.tld pat- + terns to match sub.domain.tld (as opposed to requiring .domain.tld patterns). smtpd_client_restrictions @@ -281,19 +304,19 @@ SMTPD(8) SMTPD(8) tem. smtpd_helo_required - Require that clients introduce themselves at the + Require that clients introduce themselves at the beginning of an SMTP session. smtpd_helo_restrictions - Restrict what client hostnames are allowed in HELO + Restrict what client hostnames are allowed in HELO and EHLO commands. smtpd_sender_restrictions - Restrict what sender addresses are allowed in MAIL + Restrict what sender addresses are allowed in MAIL FROM commands. smtpd_recipient_restrictions - Restrict what recipient addresses are allowed in + Restrict what recipient addresses are allowed in RCPT TO commands. smtpd_etrn_restrictions @@ -301,96 +324,96 @@ SMTPD(8) SMTPD(8) mands, and what clients may issue ETRN commands. smtpd_data_restrictions - Restrictions on the DATA command. Currently, the - only restriction that makes sense here is + Restrictions on the DATA command. Currently, the + only restriction that makes sense here is reject_unauth_pipelining. allow_untrusted_routing - Allow untrusted clients to specify addresses with - sender-specified routing. Enabling this opens up - nasty relay loopholes involving trusted backup MX + Allow untrusted clients to specify addresses with + sender-specified routing. Enabling this opens up + nasty relay loopholes involving trusted backup MX hosts. smtpd_restriction_classes - Declares the name of zero or more parameters that - contain a list of UCE restrictions. The names of - these parameters can then be used instead of the + Declares the name of zero or more parameters that + contain a list of UCE restrictions. The names of + these parameters can then be used instead of the restriction lists that they represent. smtpd_null_access_lookup_key - The lookup key to be used in SMTPD access tables - instead of the null sender address. A null sender + The lookup key to be used in SMTPD access tables + instead of the null sender address. A null sender address cannot be looked up. maps_rbl_domains (deprecated) - List of DNS domains that publish the addresses of + List of DNS domains that publish the addresses of blacklisted hosts. This is used with the deprecated reject_maps_rbl restriction. permit_mx_backup_networks - Only domains whose primary MX hosts match the - listed networks are eligible for the per- + Only domains whose primary MX hosts match the + listed networks are eligible for the per- mit_mx_backup feature. relay_domains - Restrict what domains this mail system will relay - mail to. The domains are routed to the delivery + Restrict what domains this mail system will relay + mail to. The domains are routed to the delivery agent specified with the relay_transport setting. Sender/recipient address verification Address verification is implemented by sending probe email - messages that are not actually delivered, and is enabled - via the reject_unverified_{sender,recipient} access - restriction. The status of verification probes is main- + messages that are not actually delivered, and is enabled + via the reject_unverified_{sender,recipient} access + restriction. The status of verification probes is main- tained by the address verification service. address_verify_poll_count - How many times to query the address verification - service for completion of an address verification - request. Specify 1 to implement a simple form of - greylisting, that is, always defer the request for + How many times to query the address verification + service for completion of an address verification + request. Specify 1 to implement a simple form of + greylisting, that is, always defer the request for a new sender or recipient address. address_verify_poll_delay - Time to wait after querying the address verifica- + Time to wait after querying the address verifica- tion service for completion of an address verifica- tion request. UCE control responses access_map_reject_code - Response code when a client violates an access + Response code when a client violates an access database restriction. default_rbl_reply Default template reply when a request is RBL black- - listed. This template is used by the reject_rbl_* - and reject_rhsbl_* restrictions. See also: + listed. This template is used by the reject_rbl_* + and reject_rhsbl_* restrictions. See also: rbl_reply_maps and smtpd_expansion_filter. defer_code - Response code when a client request is rejected by + Response code when a client request is rejected by the defer restriction. invalid_hostname_reject_code - Response code when a client violates the + Response code when a client violates the reject_invalid_hostname restriction. maps_rbl_reject_code Response code when a request is RBL blacklisted. multi_recipient_bounce_reject_code - Response code when a multi-recipient bounce is + Response code when a multi-recipient bounce is blocked. rbl_reply_maps - Table with template responses for RBL blacklisted - requests, indexed by RBL domain name. These tem- + Table with template responses for RBL blacklisted + requests, indexed by RBL domain name. These tem- plates are used by the reject_rbl_* and - reject_rhsbl_* restrictions. See also: + reject_rhsbl_* restrictions. See also: default_rbl_reply and smtpd_expansion_filter. reject_code - Response code when the client matches a reject + Response code when the client matches a reject restriction. relay_domains_reject_code @@ -398,7 +421,7 @@ SMTPD(8) SMTPD(8) mail relay policy. unknown_address_reject_code - Response code when a client violates the + Response code when a client violates the reject_unknown_address restriction. unknown_client_reject_code @@ -407,15 +430,15 @@ SMTPD(8) SMTPD(8) tion. unknown_hostname_reject_code - Response code when a client violates the + Response code when a client violates the reject_unknown_hostname restriction. unverified_sender_reject_code - Response code when a sender address is known to be + Response code when a sender address is known to be undeliverable. unverified_recipient_reject_code - Response code when a recipient address is known to + Response code when a recipient address is known to be undeliverable. SEE ALSO @@ -426,7 +449,7 @@ SMTPD(8) SMTPD(8) verify(8) address verification service 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/man/man1/postcat.1 b/postfix/man/man1/postcat.1 index 5b7f28a5f..27202dd9e 100644 --- a/postfix/man/man1/postcat.1 +++ b/postfix/man/man1/postcat.1 @@ -23,8 +23,8 @@ Options: The \fBmain.cf\fR configuration file is in the named directory instead of the default configuration directory. .IP \fB-q\fR -Search the Postfix queue for \fIfiles\fR. By default, -file names are taken literally. +Search the Postfix queue for the named \fIfiles\fR instead +of taking the names literally. .IP \fB-v\fR Enable verbose logging for debugging purposes. Multiple \fB-v\fR options make the software increasingly verbose. diff --git a/postfix/man/man5/access.5 b/postfix/man/man5/access.5 index 060f9b1ba..e7b0a21df 100644 --- a/postfix/man/man5/access.5 +++ b/postfix/man/man5/access.5 @@ -109,7 +109,7 @@ order to match subdomains. Matches any host address in the specified network. A network address is a sequence of one or more octets separated by ".". -NOTE: use the \fBcidr\fR lookup table type if to specify +NOTE: use the \fBcidr\fR lookup table type to specify network/netmask patterns. See cidr_table(5) for details. .SH ACTIONS .na diff --git a/postfix/man/man8/pickup.8 b/postfix/man/man8/pickup.8 index 92c98ae40..73d972484 100644 --- a/postfix/man/man8/pickup.8 +++ b/postfix/man/man8/pickup.8 @@ -61,6 +61,19 @@ The name of a mail delivery transport that filters mail and that either bounces mail or re-injects the result back into Postfix. This parameter uses the same syntax as the right-hand side of a Postfix transport table. +.IP \fBreceive_override_options\fB +The following options override \fBmain.cf\fR settings. +The options are passed on to the downstream cleanup server. +.RS +.IP \fBno_address_mappings\fR +Disable canonical address mapping, virtual alias map expansion, +address masquerading, and automatic BCC recipients. Specify this +if address mapping etc. are to be done \fBafter\fR an external +content filter. +.IP \fBno_header_body_checks\fR +Disable header/body_checks. Specify this if header/body_checks +are to be done \fBafter\fR an external content filter. +.RE .SH Miscellaneous .ad .fi diff --git a/postfix/man/man8/qmqpd.8 b/postfix/man/man8/qmqpd.8 index e6308c794..4a64b9e29 100644 --- a/postfix/man/man8/qmqpd.8 +++ b/postfix/man/man8/qmqpd.8 @@ -80,6 +80,19 @@ The name of a mail delivery transport that filters mail and that either bounces mail or re-injects the result back into Postfix. This parameter uses the same syntax as the right-hand side of a Postfix transport table. +.IP \fBreceive_override_options\fB +The following options override \fBmain.cf\fR settings. +The options are passed on to the downstream cleanup server. +.RS +.IP \fBno_address_mappings\fR +Disable canonical address mapping, virtual alias map expansion, +address masquerading, and automatic BCC recipients. Specify this +if address mapping etc. are to be done \fBafter\fR an external +content filter. +.IP \fBno_header_body_checks\fR +Disable header/body_checks. Specify this if header/body_checks +are to be done \fBafter\fR an external content filter. +.RE .SH "Resource controls" .ad .fi diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8 index 94b3c824b..b40558130 100644 --- a/postfix/man/man8/smtpd.8 +++ b/postfix/man/man8/smtpd.8 @@ -86,6 +86,23 @@ The name of a mail delivery transport that filters mail and that either bounces mail or re-injects the result back into Postfix. This parameter uses the same syntax as the right-hand side of a Postfix transport table. +.IP \fBreceive_override_options\fB +The following options override \fBmain.cf\fR settings. +The options are either implemented by the SMTP server or +are passed on to the downstream cleanup server. +.RS +.IP \fBno_unknown_recipient_checks\fR +Do not try to reject unknown recipients. This is typically specified +with the SMTP server \fBafter\fR an external content filter. +.IP \fBno_address_mappings\fR +Disable canonical address mapping, virtual alias map expansion, +address masquerading, and automatic BCC recipients. This is +typically specified with the SMTP server \fBbefore\fR an external +content filter. +.IP \fBno_header_body_checks\fR +Disable header/body_checks. This is typically specified with the +SMTP server \fBafter\fR an external content filter. +.RE .SH "Authentication controls" .IP \fBenable_sasl_authentication\fR Enable per-session authentication as per RFC 2554 (SASL). diff --git a/postfix/proto/access b/postfix/proto/access index 0ef1eed82..81f7e8a7b 100644 --- a/postfix/proto/access +++ b/postfix/proto/access @@ -95,7 +95,7 @@ # Matches any host address in the specified network. A network # address is a sequence of one or more octets separated by ".". # -# NOTE: use the \fBcidr\fR lookup table type if to specify +# NOTE: use the \fBcidr\fR lookup table type to specify # network/netmask patterns. See cidr_table(5) for details. # ACTIONS # .ad diff --git a/postfix/src/bounce/bounce_notify_service.c b/postfix/src/bounce/bounce_notify_service.c index 8ce07c11c..14d67ccd4 100644 --- a/postfix/src/bounce/bounce_notify_service.c +++ b/postfix/src/bounce/bounce_notify_service.c @@ -98,7 +98,6 @@ int bounce_notify_service(char *service, char *queue_name, encoding, BOUNCE_MSG_FAIL); #define NULL_SENDER MAIL_ADDR_EMPTY /* special address */ -#define NULL_CLEANUP_FLAGS 0 #define NULL_TRACE_FLAGS 0 #define BOUNCE_HEADERS 1 #define BOUNCE_ALL 0 @@ -142,7 +141,7 @@ int bounce_notify_service(char *service, char *queue_name, postmaster = var_2bounce_rcpt; if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(), postmaster, - NULL_CLEANUP_FLAGS, + CLEANUP_FLAG_MASK_INTERNAL, NULL_TRACE_FLAGS)) != 0) { /* @@ -166,7 +165,7 @@ int bounce_notify_service(char *service, char *queue_name, */ else { if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient, - NULL_CLEANUP_FLAGS, + CLEANUP_FLAG_MASK_INTERNAL, NULL_TRACE_FLAGS)) != 0) { /* @@ -204,7 +203,7 @@ int bounce_notify_service(char *service, char *queue_name, postmaster = var_bounce_rcpt; if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(), postmaster, - NULL_CLEANUP_FLAGS, + CLEANUP_FLAG_MASK_INTERNAL, NULL_TRACE_FLAGS)) != 0) { if (bounce_header(bounce, bounce_info, postmaster) == 0 && bounce_diagnostic_log(bounce, bounce_info) == 0 diff --git a/postfix/src/bounce/bounce_notify_verp.c b/postfix/src/bounce/bounce_notify_verp.c index 0577ad4d0..3ff372f3a 100644 --- a/postfix/src/bounce/bounce_notify_verp.c +++ b/postfix/src/bounce/bounce_notify_verp.c @@ -110,7 +110,6 @@ int bounce_notify_verp(char *service, char *queue_name, encoding, BOUNCE_MSG_FAIL); #define NULL_SENDER MAIL_ADDR_EMPTY /* special address */ -#define NULL_CLEANUP_FLAGS 0 #define NULL_TRACE_FLAGS 0 #define BOUNCE_HEADERS 1 #define BOUNCE_ALL 0 @@ -127,7 +126,7 @@ int bounce_notify_verp(char *service, char *queue_name, verp_sender(verp_buf, verp_delims, recipient, bounce_info->log_handle->recipient); if ((bounce = post_mail_fopen_nowait(NULL_SENDER, STR(verp_buf), - NULL_CLEANUP_FLAGS, + CLEANUP_FLAG_MASK_INTERNAL, NULL_TRACE_FLAGS)) != 0) { /* @@ -177,7 +176,7 @@ int bounce_notify_verp(char *service, char *queue_name, postmaster = var_bounce_rcpt; if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(), postmaster, - NULL_CLEANUP_FLAGS, + CLEANUP_FLAG_MASK_INTERNAL, NULL_TRACE_FLAGS)) != 0) { if (bounce_header(bounce, bounce_info, postmaster) == 0 && bounce_recipient_log(bounce, bounce_info) == 0 diff --git a/postfix/src/bounce/bounce_one_service.c b/postfix/src/bounce/bounce_one_service.c index 37210d6ce..4cab4c82f 100644 --- a/postfix/src/bounce/bounce_one_service.c +++ b/postfix/src/bounce/bounce_one_service.c @@ -101,7 +101,6 @@ int bounce_one_service(char *queue_name, char *queue_id, char *encoding, dsn_action, why); #define NULL_SENDER MAIL_ADDR_EMPTY /* special address */ -#define NULL_CLEANUP_FLAGS 0 #define NULL_TRACE_FLAGS 0 #define BOUNCE_HEADERS 1 #define BOUNCE_ALL 0 @@ -145,7 +144,7 @@ int bounce_one_service(char *queue_name, char *queue_id, char *encoding, } else { if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(), var_2bounce_rcpt, - NULL_CLEANUP_FLAGS, + CLEANUP_FLAG_MASK_INTERNAL, NULL_TRACE_FLAGS)) != 0) { /* @@ -169,7 +168,7 @@ int bounce_one_service(char *queue_name, char *queue_id, char *encoding, */ else { if ((bounce = post_mail_fopen_nowait(NULL_SENDER, orig_sender, - NULL_CLEANUP_FLAGS, + CLEANUP_FLAG_MASK_INTERNAL, NULL_TRACE_FLAGS)) != 0) { /* @@ -206,7 +205,7 @@ int bounce_one_service(char *queue_name, char *queue_id, char *encoding, */ if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(), var_bounce_rcpt, - NULL_CLEANUP_FLAGS, + CLEANUP_FLAG_MASK_INTERNAL, NULL_TRACE_FLAGS)) != 0) { if (bounce_header(bounce, bounce_info, var_bounce_rcpt) == 0 && bounce_recipient_log(bounce, bounce_info) == 0 diff --git a/postfix/src/bounce/bounce_trace_service.c b/postfix/src/bounce/bounce_trace_service.c index 4a142ffee..40a8b5c7e 100644 --- a/postfix/src/bounce/bounce_trace_service.c +++ b/postfix/src/bounce/bounce_trace_service.c @@ -88,7 +88,6 @@ int bounce_trace_service(char *service, char *queue_name, encoding, BOUNCE_MSG_STATUS); #define NULL_SENDER MAIL_ADDR_EMPTY /* special address */ -#define NULL_CLEANUP_FLAGS 0 #define NULL_TRACE_FLAGS 0 #define BOUNCE_ALL 0 @@ -98,7 +97,7 @@ int bounce_trace_service(char *service, char *queue_name, * per-recipient status, and a copy of the original message. */ if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient, - NULL_CLEANUP_FLAGS, + CLEANUP_FLAG_MASK_INTERNAL, NULL_TRACE_FLAGS)) != 0) { if (bounce_header(bounce, bounce_info, recipient) == 0 && bounce_boilerplate(bounce, bounce_info) == 0 diff --git a/postfix/src/bounce/bounce_warn_service.c b/postfix/src/bounce/bounce_warn_service.c index bbc3df298..170498a5d 100644 --- a/postfix/src/bounce/bounce_warn_service.c +++ b/postfix/src/bounce/bounce_warn_service.c @@ -96,7 +96,6 @@ int bounce_warn_service(char *service, char *queue_name, encoding, BOUNCE_MSG_WARN); #define NULL_SENDER MAIL_ADDR_EMPTY /* special address */ -#define NULL_CLEANUP_FLAGS 0 #define NULL_TRACE_FLAGS 0 #define BOUNCE_HEADERS 1 @@ -139,7 +138,7 @@ int bounce_warn_service(char *service, char *queue_name, postmaster = var_delay_rcpt; if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(), postmaster, - NULL_CLEANUP_FLAGS, + CLEANUP_FLAG_MASK_INTERNAL, NULL_TRACE_FLAGS)) != 0) { /* @@ -163,7 +162,7 @@ int bounce_warn_service(char *service, char *queue_name, */ else { if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient, - NULL_CLEANUP_FLAGS, + CLEANUP_FLAG_MASK_INTERNAL, NULL_TRACE_FLAGS)) != 0) { /* @@ -201,7 +200,7 @@ int bounce_warn_service(char *service, char *queue_name, postmaster = var_delay_rcpt; if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(), postmaster, - NULL_CLEANUP_FLAGS, + CLEANUP_FLAG_MASK_INTERNAL, NULL_TRACE_FLAGS)) != 0) { if (bounce_header(bounce, bounce_info, postmaster) == 0 && bounce_diagnostic_log(bounce, bounce_info) == 0 diff --git a/postfix/src/cleanup/Makefile.in b/postfix/src/cleanup/Makefile.in index 994c381b7..8eb9a8807 100644 --- a/postfix/src/cleanup/Makefile.in +++ b/postfix/src/cleanup/Makefile.in @@ -423,6 +423,7 @@ cleanup_out_recipient.o: ../../include/been_here.h cleanup_out_recipient.o: ../../include/mail_params.h cleanup_out_recipient.o: ../../include/rec_type.h cleanup_out_recipient.o: ../../include/ext_prop.h +cleanup_out_recipient.o: ../../include/cleanup_user.h cleanup_out_recipient.o: cleanup.h cleanup_out_recipient.o: ../../include/vstring.h cleanup_out_recipient.o: ../../include/vbuf.h diff --git a/postfix/src/cleanup/cleanup_addr.c b/postfix/src/cleanup/cleanup_addr.c index 8c7f2f892..24804db4e 100644 --- a/postfix/src/cleanup/cleanup_addr.c +++ b/postfix/src/cleanup/cleanup_addr.c @@ -98,15 +98,17 @@ void cleanup_addr_sender(CLEANUP_STATE *state, const char *buf) if (strcasecmp(STR(clean_addr), STR(state->temp1)) == 0) vstring_strcpy(clean_addr, ""); } - if (cleanup_send_canon_maps) - cleanup_map11_internal(state, clean_addr, cleanup_send_canon_maps, - cleanup_ext_prop_mask & EXT_PROP_CANONICAL); - 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_FROM)) - cleanup_masquerade_internal(clean_addr, cleanup_masq_domains); + if (state->flags & CLEANUP_FLAG_MAP_OK) { + if (cleanup_send_canon_maps) + cleanup_map11_internal(state, clean_addr, cleanup_send_canon_maps, + cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + 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_FROM)) + cleanup_masquerade_internal(clean_addr, cleanup_masq_domains); + } CLEANUP_OUT_BUF(state, REC_TYPE_FROM, clean_addr); if (state->sender == 0) state->sender = mystrdup(STR(clean_addr)); @@ -127,15 +129,17 @@ void cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf) const char *bcc; cleanup_rewrite_internal(clean_addr, *buf ? buf : var_empty_addr); - if (cleanup_rcpt_canon_maps) - cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, - cleanup_ext_prop_mask & EXT_PROP_CANONICAL); - 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); + if (state->flags & CLEANUP_FLAG_MAP_OK) { + if (cleanup_rcpt_canon_maps) + cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, + cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + 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, state->orig_rcpt, STR(clean_addr)); if (state->recip == 0) state->recip = mystrdup(STR(clean_addr)); @@ -155,15 +159,17 @@ void cleanup_addr_bcc(CLEANUP_STATE *state, const char *bcc) VSTRING *clean_addr = vstring_alloc(100); cleanup_rewrite_internal(clean_addr, bcc); - if (cleanup_rcpt_canon_maps) - cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, - cleanup_ext_prop_mask & EXT_PROP_CANONICAL); - 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); + if (state->flags & CLEANUP_FLAG_MAP_OK) { + if (cleanup_rcpt_canon_maps) + cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, + cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + 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), STR(clean_addr)); vstring_free(clean_addr); } diff --git a/postfix/src/cleanup/cleanup_api.c b/postfix/src/cleanup/cleanup_api.c index eb67ce244..8906894e9 100644 --- a/postfix/src/cleanup/cleanup_api.c +++ b/postfix/src/cleanup/cleanup_api.c @@ -46,7 +46,15 @@ /* Enable header/body filtering. This should be enabled only with mail /* that enters Postfix, not with locally forwarded mail or with bounce /* messages. +/* .IP CLEANUP_FLAG_MAP_OK +/* Enable canonical and virtual mapping, and address masquerading. /* .PP +/* For convenience the CLEANUP_FLAG_MASK_EXTERNAL macro specifies +/* the options that are normally needed for mail that enters +/* Postfix from outside, and CLEANUP_FLAG_MASK_INTERNAL specifies +/* the options that are normally needed for internally generated or +/* forwarded mail. +/* /* CLEANUP_RECORD() is a macro that processes one message record, /* that copies the result to the queue file, and that maintains a /* little state machine. The last record in a valid message has type diff --git a/postfix/src/cleanup/cleanup_init.c b/postfix/src/cleanup/cleanup_init.c index 30585e7d1..fe8015cad 100644 --- a/postfix/src/cleanup/cleanup_init.c +++ b/postfix/src/cleanup/cleanup_init.c @@ -264,5 +264,6 @@ void cleanup_post_jail(char *unused_name, char **unused_argv) /* * Control how unmatched extensions are propagated. */ - cleanup_ext_prop_mask = ext_prop_mask(var_prop_extension); + cleanup_ext_prop_mask = + ext_prop_mask(VAR_PROP_EXTENSION, var_prop_extension); } diff --git a/postfix/src/cleanup/cleanup_message.c b/postfix/src/cleanup/cleanup_message.c index c078ea663..2037fa857 100644 --- a/postfix/src/cleanup/cleanup_message.c +++ b/postfix/src/cleanup/cleanup_message.c @@ -176,15 +176,17 @@ static void cleanup_rewrite_sender(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts, addr_list = tok822_grep(tree, TOK822_ADDR); for (tpp = addr_list; *tpp; tpp++) { cleanup_rewrite_tree(*tpp); - if (cleanup_send_canon_maps) - cleanup_map11_tree(state, *tpp, cleanup_send_canon_maps, - cleanup_ext_prop_mask & EXT_PROP_CANONICAL); - 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 - && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_FROM)) - cleanup_masquerade_tree(*tpp, cleanup_masq_domains); + if (state->flags & CLEANUP_FLAG_MAP_OK) { + if (cleanup_send_canon_maps) + cleanup_map11_tree(state, *tpp, cleanup_send_canon_maps, + cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + 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 + && (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(header_buf, *tpp); if (hdr_opts->type == HDR_RESENT_FROM && state->resent_from == 0) @@ -228,16 +230,18 @@ static void cleanup_rewrite_recip(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts, addr_list = tok822_grep(tree, TOK822_ADDR); for (tpp = addr_list; *tpp; tpp++) { cleanup_rewrite_tree(*tpp); - if (cleanup_rcpt_canon_maps) - cleanup_map11_tree(state, *tpp, cleanup_rcpt_canon_maps, - cleanup_ext_prop_mask & EXT_PROP_CANONICAL); - if (cleanup_comm_canon_maps) - cleanup_map11_tree(state, *tpp, cleanup_comm_canon_maps, - cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + if (state->flags & CLEANUP_FLAG_MAP_OK) { + if (cleanup_rcpt_canon_maps) + cleanup_map11_tree(state, *tpp, cleanup_rcpt_canon_maps, + cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + 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 - && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_RCPT)) - cleanup_masquerade_tree(*tpp, cleanup_masq_domains); + if (cleanup_masq_domains + && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_RCPT)) + cleanup_masquerade_tree(*tpp, cleanup_masq_domains); + } } vstring_sprintf(header_buf, "%s: ", hdr_opts->name); tok822_externalize(header_buf, tree, TOK822_STR_HEAD); diff --git a/postfix/src/cleanup/cleanup_out_recipient.c b/postfix/src/cleanup/cleanup_out_recipient.c index b70747673..f05feb708 100644 --- a/postfix/src/cleanup/cleanup_out_recipient.c +++ b/postfix/src/cleanup/cleanup_out_recipient.c @@ -55,6 +55,7 @@ #include #include #include +#include /* Application-specific. */ @@ -79,7 +80,8 @@ void cleanup_out_recipient(CLEANUP_STATE *state, const char *orcpt, * onto the same mailbox. The recipient will use our original recipient * message header to figure things out. */ - if (cleanup_virt_alias_maps == 0) { + if ((state->flags & CLEANUP_FLAG_MAP_OK) == 0 + || cleanup_virt_alias_maps == 0) { if (been_here(state->dups, "%s\n%s", orcpt, recip) == 0) { cleanup_out_string(state, REC_TYPE_ORCP, orcpt); cleanup_out_string(state, REC_TYPE_RCPT, recip); diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 062735f6b..6f6b2b53c 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -21,7 +21,7 @@ SRCS = been_here.c bounce.c canon_addr.c cleanup_strerror.c clnt_stream.c \ flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c \ verp_sender.c match_parent_style.c mime_state.c header_token.c \ strip_addr.c virtual8_maps.c hold_message.c verify_clnt.c \ - trace.c log_adhoc.c verify.c dict_proxy.c mail_dict.c + trace.c log_adhoc.c verify.c dict_proxy.c mail_dict.c input_transp.c OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \ debug_peer.o debug_process.o defer.o deliver_completed.o \ deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \ @@ -44,7 +44,7 @@ OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \ flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o \ verp_sender.o match_parent_style.o mime_state.o header_token.o \ strip_addr.o virtual8_maps.o hold_message.o verify_clnt.o \ - trace.o log_adhoc.o verify.o dict_proxy.o mail_dict.o + trace.o log_adhoc.o verify.o dict_proxy.o mail_dict.o input_transp.o HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \ config.h debug_peer.h debug_process.h defer.h deliver_completed.h \ deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \ @@ -63,7 +63,8 @@ HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \ mbox_conf.h mbox_open.h abounce.h qmqp_proto.h verp_sender.h \ match_parent_style.h quote_flags.h mime_state.h header_token.h \ lex_822.h strip_addr.h virtual8_maps.h hold_message.h verify_clnt.h \ - trace.h log_adhoc.h verify.h dict_proxy.h mail_dict.h qmgr_user.h + trace.h log_adhoc.h verify.h dict_proxy.h mail_dict.h qmgr_user.h \ + input_transp.h TESTSRC = rec2stream.c stream2rec.c recdump.c WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \ -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \ @@ -611,6 +612,11 @@ hold_message.o: ../../include/vbuf.h hold_message.o: ../../include/vstream.h hold_message.o: mail_params.h hold_message.o: hold_message.h +input_transp.o: input_transp.c +input_transp.o: ../../include/sys_defs.h +input_transp.o: ../../include/name_mask.h +input_transp.o: mail_params.h +input_transp.o: input_transp.h is_header.o: is_header.c is_header.o: ../../include/sys_defs.h is_header.o: is_header.h diff --git a/postfix/src/global/cleanup_user.h b/postfix/src/global/cleanup_user.h index bfb7f6723..9f49d03c6 100644 --- a/postfix/src/global/cleanup_user.h +++ b/postfix/src/global/cleanup_user.h @@ -20,6 +20,19 @@ #define CLEANUP_FLAG_HOLD (1<<2) /* Place message on hold */ #define CLEANUP_FLAG_DISCARD (1<<3) /* Discard message silently */ #define CLEANUP_FLAG_BCC_OK (1<<4) /* Ok to add auto-BCC addresses */ +#define CLEANUP_FLAG_MAP_OK (1<<5) /* Ok to map addresses */ + + /* + * These are normally set when receiving mail from outside. + */ +#define CLEANUP_FLAG_MASK_EXTERNAL \ + (CLEANUP_FLAG_FILTER | CLEANUP_FLAG_BCC_OK | CLEANUP_FLAG_MAP_OK) + + /* + * These are normally set when generating notices or when forwarding mail + * internally. + */ +#define CLEANUP_FLAG_MASK_INTERNAL CLEANUP_FLAG_MAP_OK /* * These are set on the fly while processing SMTP envelopes or message diff --git a/postfix/src/global/dict_proxy.c b/postfix/src/global/dict_proxy.c index d50f2ba50..05b56c914 100644 --- a/postfix/src/global/dict_proxy.c +++ b/postfix/src/global/dict_proxy.c @@ -174,9 +174,11 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags) * Sanity checks. */ if (dict_flags & DICT_FLAG_NO_PROXY) - msg_fatal("%s: proxy map must not be used with this map type", map); + msg_fatal("%s: %s map is not allowed for security sensitive data", + map, DICT_TYPE_PROXY); if (open_flags != O_RDONLY) - msg_fatal("%s: proxy map open requires O_RDONLY access mode", map); + msg_fatal("%s: %s map open requires O_RDONLY access mode", + map, DICT_TYPE_PROXY); /* * Local initialization. diff --git a/postfix/src/global/ext_prop.c b/postfix/src/global/ext_prop.c index ebdc8f271..4d8cf3efc 100644 --- a/postfix/src/global/ext_prop.c +++ b/postfix/src/global/ext_prop.c @@ -6,7 +6,8 @@ /* SYNOPSIS /* #include /* -/* int ext_prop_mask(pattern) +/* int ext_prop_mask(param_name, pattern) +/* const char *param_name; /* const char *pattern; /* DESCRIPTION /* This module controld address extension propagation. @@ -15,19 +16,19 @@ /* computes the corresponding mask. The following names are /* recognized in \fBpattern\fR, with the corresponding bit mask /* given in parentheses: -/* .IP "canonical (EXP_PROP_CANONICAL)" +/* .IP "canonical (EXT_PROP_CANONICAL)" /* Propagate unmatched address extensions to the right-hand side /* of canonical table entries (not: regular expressions). -/* .IP "virtual (EXP_PROP_VIRTUAL) +/* .IP "virtual (EXT_PROP_VIRTUAL) /* Propagate unmatched address extensions to the right-hand side /* of virtual table entries (not: regular expressions). -/* .IP "alias (EXP_PROP_ALIAS) +/* .IP "alias (EXT_PROP_ALIAS) /* Propagate unmatched address extensions to the right-hand side /* of alias database entries. -/* .IP "forward (EXP_PROP_FORWARD)" +/* .IP "forward (EXT_PROP_FORWARD)" /* Propagate unmatched address extensions to the right-hand side /* of .forward file entries. -/* .IP "include (EXP_PROP_INCLUDE)" +/* .IP "include (EXT_PROP_INCLUDE)" /* Propagate unmatched address extensions to the right-hand side /* of :include: file entries. /* DIAGNOSTICS @@ -58,7 +59,7 @@ /* ext_prop_mask - compute extension propagation mask */ -int ext_prop_mask(const char *pattern) +int ext_prop_mask(const char *param_name, const char *pattern) { static NAME_MASK table[] = { "canonical", EXT_PROP_CANONICAL, @@ -69,5 +70,5 @@ int ext_prop_mask(const char *pattern) 0, }; - return (name_mask(VAR_PROP_EXTENSION, table, pattern)); + return (name_mask(param_name, table, pattern)); } diff --git a/postfix/src/global/ext_prop.h b/postfix/src/global/ext_prop.h index 99e09112b..413a44b5f 100644 --- a/postfix/src/global/ext_prop.h +++ b/postfix/src/global/ext_prop.h @@ -20,7 +20,7 @@ #define EXT_PROP_FORWARD (1<<3) #define EXT_PROP_INCLUDE (1<<4) -extern int ext_prop_mask(const char *); +extern int ext_prop_mask(const char *, const char *); /* LICENSE /* .ad diff --git a/postfix/src/global/input_transp.c b/postfix/src/global/input_transp.c new file mode 100644 index 000000000..2e9cc84dd --- /dev/null +++ b/postfix/src/global/input_transp.c @@ -0,0 +1,67 @@ +/*++ +/* NAME +/* input_transp 3 +/* SUMMARY +/* receive transparency control +/* SYNOPSIS +/* #include +/* +/* int input_transp_mask(param_name, pattern) +/* const char *param_name; +/* const char *pattern; +/* DESCRIPTION +/* This module controls how much processing happens before mail is +/* written to the Postfix queue. Each transparency option is either +/* implemented by a client of the cleanup service, or is passed +/* along in a client request to the cleanup service. +/* +/* input_transp_mask() takes a comma-separated list of names and +/* computes the corresponding mask. The following names are +/* recognized in \fBpattern\fR, with the corresponding bit mask +/* given in parentheses: +/* .IP "no_unknown_recipient_checks (INPUT_TRANSP_UNKNOWN_RCPT)" +/* Do not try to reject unknown recipients. +/* .IP "no_address_mapping (INPUT_TRANSP_ADDRESS_MAPPING) +/* Disable canonical address mapping, virtual alias map expansion, +/* address masquerading, and automatic BCC recipients. +/* .IP "no_header_body_checkss (INPUT_TRANSP_HEADER_BODY) +/* Disable header/body_checks. +/* DIAGNOSTICS +/* Panic: inappropriate use. +/* 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 + +/* Utility library. */ + +#include + +/* Global library. */ + +#include +#include + +/* input_transp_mask - compute mail receive transparency mask */ + +int input_transp_mask(const char *param_name, const char *pattern) +{ + static NAME_MASK table[] = { + "no_unknown_recipient_checks", INPUT_TRANSP_UNKNOWN_RCPT, + "no_address_mappings", INPUT_TRANSP_ADDRESS_MAPPING, + "no_header_body_checks", INPUT_TRANSP_HEADER_BODY, + 0, + }; + + return (name_mask(param_name, table, pattern)); +} diff --git a/postfix/src/global/input_transp.h b/postfix/src/global/input_transp.h new file mode 100644 index 000000000..48d5d6390 --- /dev/null +++ b/postfix/src/global/input_transp.h @@ -0,0 +1,34 @@ +#ifndef _EXT_PROP_INCLUDED_ +#define _EXT_PROP_INCLUDED_ + +/*++ +/* NAME +/* ext_prop 3h +/* SUMMARY +/* address extension propagation control +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * External interface. + */ +#define INPUT_TRANSP_UNKNOWN_RCPT (1<<0) +#define INPUT_TRANSP_ADDRESS_MAPPING (1<<1) +#define INPUT_TRANSP_HEADER_BODY (1<<2) + +extern int input_transp_mask(const char *, const char *); + +/* 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/global/mail_params.h b/postfix/src/global/mail_params.h index 203f71b47..c36fe78a8 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -1841,6 +1841,15 @@ extern char *var_smtpd_proxy_ehlo; #define DEF_SMTPD_PROXY_TMOUT "100s" extern int var_smtpd_proxy_tmout; + /* + * Transparency options for mail input interfaces and for the cleanup server + * behind them. These should turn off stuff we don't want to happen, because + * the default is to do a lot of things. + */ +#define VAR_INPUT_TRANSP "receive_override_options" +#define DEF_INPUT_TRANSP "" +extern char *var_smtpd_input_transp; + /* LICENSE /* .ad /* .fi diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 0a405c69b..30d220cf2 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change the patchlevel and the release date. Snapshots change the * release date only, unless they include the same bugfix as a patch release. */ -#define MAIL_RELEASE_DATE "20030704" +#define MAIL_RELEASE_DATE "20030705" #define VAR_MAIL_VERSION "mail_version" #define DEF_MAIL_VERSION "2.0.13-" MAIL_RELEASE_DATE diff --git a/postfix/src/lmtp/lmtp_chat.c b/postfix/src/lmtp/lmtp_chat.c index dfbeb4943..43379a753 100644 --- a/postfix/src/lmtp/lmtp_chat.c +++ b/postfix/src/lmtp/lmtp_chat.c @@ -262,14 +262,13 @@ void lmtp_chat_notify(LMTP_STATE *state) * mail bounce wars. Always prepend one space to message content that we * generate from untrusted data. */ -#define NULL_CLEANUP_FLAGS 0 #define NULL_TRACE_FLAGS 0 #define LENGTH 78 #define INDENT 4 notice = post_mail_fopen_nowait(mail_addr_double_bounce(), var_error_rcpt, - NULL_CLEANUP_FLAGS, + CLEANUP_FLAG_MASK_INTERNAL, NULL_TRACE_FLAGS); if (notice == 0) { msg_warn("postmaster notify: %m"); diff --git a/postfix/src/local/forward.c b/postfix/src/local/forward.c index 9e7bb192d..b50856000 100644 --- a/postfix/src/local/forward.c +++ b/postfix/src/local/forward.c @@ -140,8 +140,11 @@ static FORWARD_INFO *forward_open(char *sender) info->cleanup = cleanup; info->queue_id = mystrdup(vstring_str(buffer)); info->posting_time = time((time_t *) 0); + +#define FORWARD_CLEANUP_FLAGS (CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_MASK_INTERNAL) + attr_print(cleanup, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, CLEANUP_FLAG_BOUNCE, + ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, FORWARD_CLEANUP_FLAGS, ATTR_TYPE_END); /* diff --git a/postfix/src/local/local.c b/postfix/src/local/local.c index 0aff9f290..0a387d506 100644 --- a/postfix/src/local/local.c +++ b/postfix/src/local/local.c @@ -636,7 +636,8 @@ static void local_mask_init(void) var_allow_files); local_cmd_deliver_mask = name_mask(VAR_ALLOW_COMMANDS, command_mask, var_allow_commands); - local_ext_prop_mask = ext_prop_mask(var_prop_extension); + local_ext_prop_mask = + ext_prop_mask(VAR_PROP_EXTENSION, var_prop_extension); local_deliver_hdr_mask = name_mask(VAR_DELIVER_HDR, deliver_mask, var_deliver_hdr); local_mbox_lock_mask = mbox_lock_mask(var_mailbox_lock); diff --git a/postfix/src/pickup/Makefile.in b/postfix/src/pickup/Makefile.in index 42c8e60ff..44847920d 100644 --- a/postfix/src/pickup/Makefile.in +++ b/postfix/src/pickup/Makefile.in @@ -77,4 +77,5 @@ pickup.o: ../../include/mail_conf.h pickup.o: ../../include/record.h pickup.o: ../../include/rec_type.h pickup.o: ../../include/lex_822.h +pickup.o: ../../include/input_transp.h pickup.o: ../../include/mail_server.h diff --git a/postfix/src/pickup/pickup.c b/postfix/src/pickup/pickup.c index 24f8dd1d3..daa92429d 100644 --- a/postfix/src/pickup/pickup.c +++ b/postfix/src/pickup/pickup.c @@ -45,6 +45,19 @@ /* either bounces mail or re-injects the result back into Postfix. /* This parameter uses the same syntax as the right-hand side of /* a Postfix transport table. +/* .IP \fBreceive_override_options\fB +/* The following options override \fBmain.cf\fR settings. +/* The options are passed on to the downstream cleanup server. +/* .RS +/* .IP \fBno_address_mappings\fR +/* Disable canonical address mapping, virtual alias map expansion, +/* address masquerading, and automatic BCC recipients. Specify this +/* if address mapping etc. are to be done \fBafter\fR an external +/* content filter. +/* .IP \fBno_header_body_checks\fR +/* Disable header/body_checks. Specify this if header/body_checks +/* are to be done \fBafter\fR an external content filter. +/* .RE /* .SH Miscellaneous /* .ad /* .fi @@ -101,6 +114,7 @@ #include #include #include +#include /* Single-threaded server skeleton. */ @@ -109,6 +123,7 @@ /* Application-specific. */ char *var_filter_xport; +char *var_input_transp; /* * Structure to bundle a bunch of information about a queue file. @@ -128,6 +143,12 @@ typedef struct { #define REMOVE_MESSAGE_FILE 1 #define KEEP_MESSAGE_FILE 2 + /* + * Transparency: before mail is queued, do we allow address mapping, + * automatic bcc, header/body checks? + */ +int pickup_input_transp_mask; + /* file_read_error - handle error while reading queue file */ static int file_read_error(PICKUP_INFO *info, int type) @@ -324,6 +345,7 @@ static int pickup_file(PICKUP_INFO *info) int status; VSTREAM *qfile; VSTREAM *cleanup; + int cleanup_flags; /* * Open the submitted file. If we cannot open it, and we're not having a @@ -354,15 +376,18 @@ static int pickup_file(PICKUP_INFO *info) * easier to implement the many possible error exits without forgetting * to close files, or to release memory. */ -#define PICKUP_CLEANUP_FLAGS \ - (CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_FILTER | CLEANUP_FLAG_BCC_OK) + cleanup_flags = (CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_MASK_EXTERNAL); + if (pickup_input_transp_mask & INPUT_TRANSP_ADDRESS_MAPPING) + cleanup_flags &= ~(CLEANUP_FLAG_BCC_OK | CLEANUP_FLAG_MAP_OK); + if (pickup_input_transp_mask & INPUT_TRANSP_HEADER_BODY) + cleanup_flags &= ~CLEANUP_FLAG_FILTER; cleanup = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service); if (attr_scan(cleanup, ATTR_FLAG_STRICT, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, buf, ATTR_TYPE_END) != 1 || attr_print(cleanup, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, PICKUP_CLEANUP_FLAGS, + ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, cleanup_flags, ATTR_TYPE_END) != 0) { status = KEEP_MESSAGE_FILE; } else { @@ -440,9 +465,9 @@ static void pickup_service(char *unused_buf, int unused_len, } while (file_count); } -/* drop_privileges - drop privileges */ +/* post_jail_init - drop privileges */ -static void drop_privileges(char *unused_name, char **unused_argv) +static void post_jail_init(char *unused_name, char **unused_argv) { /* @@ -450,6 +475,13 @@ static void drop_privileges(char *unused_name, char **unused_argv) */ if (getuid() != var_owner_uid) set_ugid(var_owner_uid, var_owner_gid); + + /* + * Initialize the receive transparency options: do we want unknown + * recipient checks, do we want address mapping. + */ + pickup_input_transp_mask = + input_transp_mask(VAR_INPUT_TRANSP, var_input_transp); } /* main - pass control to the multi-threaded server skeleton */ @@ -458,6 +490,7 @@ int main(int argc, char **argv) { static CONFIG_STR_TABLE str_table[] = { VAR_FILTER_XPORT, DEF_FILTER_XPORT, &var_filter_xport, 0, 0, + VAR_INPUT_TRANSP, DEF_INPUT_TRANSP, &var_input_transp, 0, 0, 0, }; @@ -467,7 +500,7 @@ int main(int argc, char **argv) */ trigger_server_main(argc, argv, pickup_service, MAIL_SERVER_STR_TABLE, str_table, - MAIL_SERVER_POST_INIT, drop_privileges, + MAIL_SERVER_POST_INIT, post_jail_init, MAIL_SERVER_SOLITARY, 0); } diff --git a/postfix/src/postcat/postcat.c b/postfix/src/postcat/postcat.c index d45f376ac..7e1204a01 100644 --- a/postfix/src/postcat/postcat.c +++ b/postfix/src/postcat/postcat.c @@ -17,8 +17,8 @@ /* The \fBmain.cf\fR configuration file is in the named directory /* instead of the default configuration directory. /* .IP \fB-q\fR -/* Search the Postfix queue for \fIfiles\fR. By default, -/* file names are taken literally. +/* Search the Postfix queue for the named \fIfiles\fR instead +/* of taking the names literally. /* .IP \fB-v\fR /* Enable verbose logging for debugging purposes. Multiple \fB-v\fR /* options make the software increasingly verbose. diff --git a/postfix/src/qmqpd/qmqpd.c b/postfix/src/qmqpd/qmqpd.c index 28cbbcd68..1615e5157 100644 --- a/postfix/src/qmqpd/qmqpd.c +++ b/postfix/src/qmqpd/qmqpd.c @@ -52,7 +52,7 @@ /* .IP \fBhopcount_limit\fR /* Limit the number of \fBReceived:\fR message headers. /* .IP \fBqmqpd_authorized_clients\fR -/* A list of domain or network patterns that specifies what +/* A list of domain or network patterns that specifies what /* clients are allowed to use the service. /* .IP \fBqmqpd_timeout\fR /* Limit the time to send a server response and to receive a client @@ -66,6 +66,19 @@ /* either bounces mail or re-injects the result back into Postfix. /* This parameter uses the same syntax as the right-hand side of /* a Postfix transport table. +/* .IP \fBreceive_override_options\fB +/* The following options override \fBmain.cf\fR settings. +/* The options are passed on to the downstream cleanup server. +/* .RS +/* .IP \fBno_address_mappings\fR +/* Disable canonical address mapping, virtual alias map expansion, +/* address masquerading, and automatic BCC recipients. Specify this +/* if address mapping etc. are to be done \fBafter\fR an external +/* content filter. +/* .IP \fBno_header_body_checks\fR +/* Disable header/body_checks. Specify this if header/body_checks +/* are to be done \fBafter\fR an external content filter. +/* .RE /* .SH "Resource controls" /* .ad /* .fi @@ -136,6 +149,7 @@ #include #include #include +#include /* Single-threaded server skeleton. */ @@ -155,6 +169,7 @@ int var_qmqpd_timeout; int var_qmqpd_err_sleep; char *var_filter_xport; char *var_qmqpd_clients; +char *var_input_transp; /* * Silly little macros. @@ -171,20 +186,31 @@ char *var_qmqpd_clients; */ static NAMADR_LIST *qmqpd_clients; + /* + * Transparency: before mail is queued, do we allow address mapping, + * automatic bcc, header/body checks? + */ +int qmqpd_input_transp_mask; + /* qmqpd_open_file - open a queue file */ static void qmqpd_open_file(QMQPD_STATE *state) { + int cleanup_flags; /* * Connect to the cleanup server. Log client name/address with queue ID. */ -#define QMQPD_CLEANUP_FLAGS (CLEANUP_FLAG_FILTER | CLEANUP_FLAG_BCC_OK) + cleanup_flags = CLEANUP_FLAG_MASK_EXTERNAL; + if (qmqpd_input_transp_mask & INPUT_TRANSP_ADDRESS_MAPPING) + cleanup_flags &= ~(CLEANUP_FLAG_BCC_OK | CLEANUP_FLAG_MAP_OK); + if (qmqpd_input_transp_mask & INPUT_TRANSP_HEADER_BODY) + cleanup_flags &= ~CLEANUP_FLAG_FILTER; state->dest = mail_stream_service(MAIL_CLASS_PUBLIC, var_cleanup_service); if (state->dest == 0 || attr_print(state->dest->stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, QMQPD_CLEANUP_FLAGS, + ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, cleanup_flags, ATTR_TYPE_END) != 0) msg_fatal("unable to connect to the %s %s service", MAIL_CLASS_PUBLIC, var_cleanup_service); @@ -654,7 +680,7 @@ static void qmqpd_service(VSTREAM *stream, char *unused_service, char **argv) static void pre_accept(char *unused_name, char **unused_argv) { const char *table; - + if ((table = dict_changed_name()) != 0) { msg_info("table %s has changed -- restarting", table); exit(0); @@ -671,6 +697,19 @@ static void pre_jail_init(char *unused_name, char **unused_argv) var_qmqpd_clients); } +/* post_jail_init - post-jail initialization */ + +static void post_jail_init(char *unused_name, char **unused_argv) +{ + + /* + * Initialize the receive transparency options: do we want unknown + * recipient checks, do we want address mapping. + */ + qmqpd_input_transp_mask = + input_transp_mask(VAR_INPUT_TRANSP, var_input_transp); +} + /* main - the main program */ int main(int argc, char **argv) @@ -683,6 +722,7 @@ int main(int argc, char **argv) static CONFIG_STR_TABLE str_table[] = { VAR_FILTER_XPORT, DEF_FILTER_XPORT, &var_filter_xport, 0, 0, VAR_QMQPD_CLIENTS, DEF_QMQPD_CLIENTS, &var_qmqpd_clients, 0, 0, + VAR_INPUT_TRANSP, DEF_INPUT_TRANSP, &var_input_transp, 0, 0, 0, }; @@ -694,5 +734,6 @@ int main(int argc, char **argv) MAIL_SERVER_STR_TABLE, str_table, MAIL_SERVER_PRE_INIT, pre_jail_init, MAIL_SERVER_PRE_ACCEPT, pre_accept, + MAIL_SERVER_POST_INIT, post_jail_init, 0); } diff --git a/postfix/src/smtp/smtp_chat.c b/postfix/src/smtp/smtp_chat.c index 566af74d6..1eafdd73f 100644 --- a/postfix/src/smtp/smtp_chat.c +++ b/postfix/src/smtp/smtp_chat.c @@ -260,14 +260,13 @@ void smtp_chat_notify(SMTP_STATE *state) * mail bounce wars. Always prepend one space to message content that we * generate from untrusted data. */ -#define NULL_CLEANUP_FLAGS 0 #define NULL_TRACE_FLAGS 0 #define LENGTH 78 #define INDENT 4 notice = post_mail_fopen_nowait(mail_addr_double_bounce(), var_error_rcpt, - NULL_CLEANUP_FLAGS, + CLEANUP_FLAG_MASK_INTERNAL, NULL_TRACE_FLAGS); if (notice == 0) { msg_warn("postmaster notify: %m"); diff --git a/postfix/src/smtpd/Makefile.in b/postfix/src/smtpd/Makefile.in index 2f5c64e7d..30e443680 100644 --- a/postfix/src/smtpd/Makefile.in +++ b/postfix/src/smtpd/Makefile.in @@ -147,6 +147,7 @@ smtpd.o: ../../include/quote_822_local.h smtpd.o: ../../include/quote_flags.h smtpd.o: ../../include/lex_822.h smtpd.o: ../../include/namadr_list.h +smtpd.o: ../../include/input_transp.h smtpd.o: ../../include/mail_server.h smtpd.o: smtpd_token.h smtpd.o: smtpd.h @@ -226,6 +227,7 @@ smtpd_check.o: ../../include/mail_addr.h smtpd_check.o: ../../include/verify_clnt.h smtpd_check.o: ../../include/deliver_request.h smtpd_check.o: ../../include/recipient_list.h +smtpd_check.o: ../../include/input_transp.h smtpd_check.o: smtpd.h smtpd_check.o: ../../include/mail_stream.h smtpd_check.o: smtpd_sasl_glue.h diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index e1c1aa032..ec72a986e 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -72,6 +72,23 @@ /* either bounces mail or re-injects the result back into Postfix. /* This parameter uses the same syntax as the right-hand side of /* a Postfix transport table. +/* .IP \fBreceive_override_options\fB +/* The following options override \fBmain.cf\fR settings. +/* The options are either implemented by the SMTP server or +/* are passed on to the downstream cleanup server. +/* .RS +/* .IP \fBno_unknown_recipient_checks\fR +/* Do not try to reject unknown recipients. This is typically specified +/* with the SMTP server \fBafter\fR an external content filter. +/* .IP \fBno_address_mappings\fR +/* Disable canonical address mapping, virtual alias map expansion, +/* address masquerading, and automatic BCC recipients. This is +/* typically specified with the SMTP server \fBbefore\fR an external +/* content filter. +/* .IP \fBno_header_body_checks\fR +/* Disable header/body_checks. This is typically specified with the +/* SMTP server \fBafter\fR an external content filter. +/* .RE /* .SH "Authentication controls" /* .IP \fBenable_sasl_authentication\fR /* Enable per-session authentication as per RFC 2554 (SASL). @@ -396,6 +413,7 @@ #include #include #include +#include /* Single-threaded server skeleton. */ @@ -484,10 +502,10 @@ char *var_verp_clients; int var_show_unk_rcpt_table; int var_verify_poll_count; int var_verify_poll_delay; - char *var_smtpd_proxy_filt; int var_smtpd_proxy_tmout; char *var_smtpd_proxy_ehlo; +char *var_input_transp; /* * Silly little macros. @@ -503,6 +521,11 @@ char *var_smtpd_proxy_ehlo; static NAMADR_LIST *verp_clients; + /* + * Other application-specific globals. + */ +int smtpd_input_transp_mask; + /* * Forward declarations. */ @@ -624,6 +647,7 @@ static void mail_open_stream(SMTPD_STATE *state, SMTPD_TOKEN *argv, const char *encoding, const char *verp_delims) { char *postdrop_command; + int cleanup_flags; /* * XXX 2821: An SMTP server is not allowed to "clean up" mail except in @@ -641,14 +665,18 @@ static void mail_open_stream(SMTPD_STATE *state, SMTPD_TOKEN *argv, * If running from the master or from inetd, connect to the cleanup * service. */ -#define SMTPD_CLEANUP_FLAGS (CLEANUP_FLAG_FILTER | CLEANUP_FLAG_BCC_OK) + cleanup_flags = CLEANUP_FLAG_MASK_EXTERNAL; + if (smtpd_input_transp_mask & INPUT_TRANSP_ADDRESS_MAPPING) + cleanup_flags &= ~(CLEANUP_FLAG_BCC_OK | CLEANUP_FLAG_MAP_OK); + if (smtpd_input_transp_mask & INPUT_TRANSP_HEADER_BODY) + cleanup_flags &= ~CLEANUP_FLAG_FILTER; if (SMTPD_STAND_ALONE(state) == 0) { state->dest = mail_stream_service(MAIL_CLASS_PUBLIC, var_cleanup_service); if (state->dest == 0 || attr_print(state->dest->stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, SMTPD_CLEANUP_FLAGS, + ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, cleanup_flags, ATTR_TYPE_END) != 0) msg_fatal("unable to connect to the %s %s service", MAIL_CLASS_PUBLIC, var_cleanup_service); @@ -983,10 +1011,11 @@ static void mail_reset(SMTPD_STATE *state) state->discard = 0; /* - * Try to be nice. Don't bother when we lost the connection. + * Try to be nice. Don't bother when we lost the connection. Don't bother + * waiting for a reply, it just increases latency. */ if (state->proxy) { - (void) smtpd_proxy_cmd(state, SMTPD_PROX_WANT_ANY, "QUIT"); + (void) smtpd_proxy_cmd(state, SMTPD_PROX_WANT_NONE, "QUIT"); smtpd_proxy_close(state); } } @@ -1648,7 +1677,7 @@ static void smtpd_proto(SMTPD_STATE *state) } if (cmdp->flags & SMTPD_CMD_FLAG_FORBIDDEN) { msg_warn("%s sent non-SMTP command: %.100s", - state->namaddr, vstring_str(state->buffer)); + state->namaddr, vstring_str(state->buffer)); smtpd_chat_reply(state, "221 Error: I can break rules, too. Goodbye."); break; } @@ -1782,6 +1811,19 @@ static void pre_jail_init(char *unused_name, char **unused_argv) #endif } +/* post_jail_init - post-jail initialization */ + +static void post_jail_init(char *unused_name, char **unused_argv) +{ + + /* + * Initialize the receive transparency options: do we want unknown + * recipient checks, address mapping, header_body_checks?. + */ + smtpd_input_transp_mask = + input_transp_mask(VAR_INPUT_TRANSP, var_input_transp); +} + /* main - the main program */ int main(int argc, char **argv) @@ -1862,6 +1904,7 @@ int main(int argc, char **argv) VAR_VERP_CLIENTS, DEF_VERP_CLIENTS, &var_verp_clients, 0, 0, VAR_SMTPD_PROXY_FILT, DEF_SMTPD_PROXY_FILT, &var_smtpd_proxy_filt, 0, 0, VAR_SMTPD_PROXY_EHLO, DEF_SMTPD_PROXY_EHLO, &var_smtpd_proxy_ehlo, 0, 0, + VAR_INPUT_TRANSP, DEF_INPUT_TRANSP, &var_input_transp, 0, 0, 0, }; static CONFIG_RAW_TABLE raw_table[] = { @@ -1881,5 +1924,6 @@ int main(int argc, char **argv) MAIL_SERVER_TIME_TABLE, time_table, MAIL_SERVER_PRE_INIT, pre_jail_init, MAIL_SERVER_PRE_ACCEPT, pre_accept, + MAIL_SERVER_POST_INIT, post_jail_init, 0); } diff --git a/postfix/src/smtpd/smtpd.h b/postfix/src/smtpd/smtpd.h index bc825be1e..888055c9f 100644 --- a/postfix/src/smtpd/smtpd.h +++ b/postfix/src/smtpd/smtpd.h @@ -122,6 +122,12 @@ extern void smtpd_state_reset(SMTPD_STATE *); void smtpd_peer_init(SMTPD_STATE *state); void smtpd_peer_reset(SMTPD_STATE *state); + /* + * Transparency: before mail is queued, do we check for unknown recipients, + * do we allow address mapping, automatic bcc, header/body checks? + */ +int smtpd_input_transp_mask; + /* LICENSE /* .ad /* .fi diff --git a/postfix/src/smtpd/smtpd_chat.c b/postfix/src/smtpd/smtpd_chat.c index 2bb42adae..c9aa963ef 100644 --- a/postfix/src/smtpd/smtpd_chat.c +++ b/postfix/src/smtpd/smtpd_chat.c @@ -214,14 +214,13 @@ void smtpd_chat_notify(SMTPD_STATE *state) * mail bounce wars. Always prepend one space to message content that we * generate from untrusted data. */ -#define NULL_CLEANUP_FLAGS 0 #define NULL_TRACE_FLAGS 0 #define LENGTH 78 #define INDENT 4 notice = post_mail_fopen_nowait(mail_addr_double_bounce(), var_error_rcpt, - NULL_CLEANUP_FLAGS, + CLEANUP_FLAG_MASK_INTERNAL, NULL_TRACE_FLAGS); if (notice == 0) { msg_warn("postmaster notify: %m"); diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 027dc2d76..0eaa39c0c 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -319,6 +319,7 @@ #include #include #include +#include /* Application-specific. */ @@ -3294,6 +3295,8 @@ static int check_rcpt_maps(SMTPD_STATE *state, const char *recipient) * Duplicate suppression. There's an implicit check_recipient_maps * restriction at the end of all recipient restrictions. */ + if (smtpd_input_transp_mask & INPUT_TRANSP_UNKNOWN_RCPT) + return (0); if (state->rcptmap_checked == 1) return (0); state->rcptmap_checked = 1; diff --git a/postfix/src/smtpd/smtpd_proxy.c b/postfix/src/smtpd/smtpd_proxy.c index a9c8e8efb..b34a7ea09 100644 --- a/postfix/src/smtpd/smtpd_proxy.c +++ b/postfix/src/smtpd/smtpd_proxy.c @@ -11,7 +11,7 @@ /* .in +4 /* /* other fields... */ /* VSTREAM *proxy; /* connection to SMTP proxy */ -/* VSTRING *proxy_reply; /* last SMTP proxy response */ +/* VSTRING *proxy_buffer; /* last SMTP proxy response */ /* /* other fields... */ /* .in -4 /* } SMTPD_STATE; @@ -56,17 +56,17 @@ /* MAIL FROM command, and receives the reply. A non-zero result means /* trouble: either the proxy is unavailable, or it did not send the /* expected reply. -/* All results are reported via the state->proxy_reply field in a form +/* All results are reported via the state->proxy_buffer field in a form /* that can be sent to the SMTP client. In case of error, the /* state->error_mask and state->err fields are updated. -/* A state->proxy_reply field is created automatically; this field +/* A state->proxy_buffer field is created automatically; this field /* persists beyond the end of a proxy session. /* /* smtpd_proxy_cmd() formats and sends the specified command to the /* proxy server, and receives the proxy server reply. A non-zero result /* means trouble: either the proxy is unavailable, or it did not send the /* expected reply. -/* All results are reported via the state->proxy_reply field in a form +/* All results are reported via the state->proxy_buffer field in a form /* that can be sent to the SMTP client. In case of error, the /* state->error_mask and state->err fields are updated. /* @@ -100,12 +100,14 @@ /* Expected proxy server reply status code range. A warning is logged /* when an unexpected reply is received. Specify one of the following: /* .RS -/* .IP SMTPD_PROX_WANT_ANY -/* The caller has no expectation. Do not warn for unexpected replies. /* .IP SMTPD_PROX_WANT_OK /* The caller expects a reply in the 200 range. /* .IP SMTPD_PROX_WANT_MORE /* The caller expects a reply in the 300 range. +/* .IP SMTPD_PROX_WANT_ANY +/* The caller has no expectation. Do not warn for unexpected replies. +/* .IP SMTPD_PROX_WANT_NONE +/* Do not bother waiting for a reply. /* .RE /* .IP format /* A format string. @@ -200,7 +202,8 @@ int smtpd_proxy_open(SMTPD_STATE *state, const char *service, * Get server greeting banner. * * If this fails then we have a problem because the proxy should always - * accept our connection. + * accept our connection. Make up our own response instead of passing + * back the greeting banner: the client expects a MAIL FROM reply. */ if (smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, SMTPD_PROXY_CONNECT) != 0) { vstring_sprintf(state->proxy_buffer, @@ -210,10 +213,10 @@ int smtpd_proxy_open(SMTPD_STATE *state, const char *service, } /* - * Send our own EHLO command. - * - * If this fails then we have a problem because the proxy should always - * accept our EHLO command. + * Send our own EHLO command. If this fails then we have a problem + * because the proxy should always accept our EHLO command. Make up our + * own response instead of passing back the EHLO reply: the client + * expects a MAIL FROM reply. */ if (smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, "EHLO %s", ehlo_name) != 0) { vstring_sprintf(state->proxy_buffer, @@ -234,9 +237,9 @@ int smtpd_proxy_open(SMTPD_STATE *state, const char *service, return (0); } -/* smtpd_proxy_comms_error - report proxy communication error */ +/* smtpd_proxy_rdwr_error - report proxy communication error */ -static int smtpd_proxy_comms_error(VSTREAM *stream, int err) +static int smtpd_proxy_rdwr_error(VSTREAM *stream, int err) { switch (err) { case SMTP_ERR_EOF: @@ -246,7 +249,7 @@ static int smtpd_proxy_comms_error(VSTREAM *stream, int err) msg_warn("timeout talking to proxy %s", VSTREAM_PATH(stream)); return (err); default: - msg_panic("smtpd_proxy_comms_error: unknown proxy %s stream error %d", + msg_panic("smtpd_proxy_rdwr_error: unknown proxy %s stream error %d", VSTREAM_PATH(stream), err); } } @@ -287,7 +290,7 @@ int smtpd_proxy_cmd(SMTPD_STATE *state, int expect, const char *fmt,...) || vstream_ferror(state->proxy) || vstream_feof(state->proxy) || ((err = vstream_setjmp(state->proxy) != 0) - && smtpd_proxy_comms_error(state->proxy, err))) { + && smtpd_proxy_rdwr_error(state->proxy, err))) { state->error_mask |= MAIL_ERROR_SOFTWARE; state->err |= CLEANUP_STAT_PROXY; vstring_sprintf(state->proxy_buffer, @@ -325,6 +328,13 @@ int smtpd_proxy_cmd(SMTPD_STATE *state, int expect, const char *fmt,...) state->proxy); } + /* + * Early return if we don't want to wait for a server reply (such as + * after sending QUIT. + */ + if (expect == SMTPD_PROX_WANT_NONE) + return (0); + /* * Censor out non-printable characters in server responses and keep the * last line of multi-line responses. @@ -362,8 +372,7 @@ int smtpd_proxy_cmd(SMTPD_STATE *state, int expect, const char *fmt,...) * Log a warning in case the proxy does not send the expected response. * Silently accept any response when the client expressed no expectation. */ - if (expect != SMTPD_PROX_WANT_ANY - && expect != (STR(state->proxy_buffer)[0] - '0')) { + if (expect != SMTPD_PROX_WANT_ANY && expect != *STR(state->proxy_buffer)) { va_start(ap, fmt); smtpd_proxy_cmd_error(state, fmt, ap); va_end(ap); @@ -387,7 +396,7 @@ int smtpd_proxy_rec_put(VSTREAM *stream, int rec_type, || vstream_feof(stream)) return (REC_TYPE_ERROR); if ((err = vstream_setjmp(stream)) != 0) - return (smtpd_proxy_comms_error(stream, err), REC_TYPE_ERROR); + return (smtpd_proxy_rdwr_error(stream, err), REC_TYPE_ERROR); /* * Send one content record. Errors and results must be as with rec_put(). @@ -416,7 +425,7 @@ int smtpd_proxy_rec_fprintf(VSTREAM *stream, int rec_type, || vstream_feof(stream)) return (REC_TYPE_ERROR); if ((err = vstream_setjmp(stream)) != 0) - return (smtpd_proxy_comms_error(stream, err), REC_TYPE_ERROR); + return (smtpd_proxy_rdwr_error(stream, err), REC_TYPE_ERROR); /* * Send one content record. Errors and results must be as with diff --git a/postfix/src/smtpd/smtpd_proxy.h b/postfix/src/smtpd/smtpd_proxy.h index e9ff17ec5..a55fe75ea 100644 --- a/postfix/src/smtpd/smtpd_proxy.h +++ b/postfix/src/smtpd/smtpd_proxy.h @@ -18,9 +18,10 @@ /* * Application-specific. */ -#define SMTPD_PROX_WANT_ANY 0 -#define SMTPD_PROX_WANT_OK 2 -#define SMTPD_PROX_WANT_MORE 3 +#define SMTPD_PROX_WANT_NONE '\0' /* Do not receive reply */ +#define SMTPD_PROX_WANT_ANY '0' /* Expect any reply */ +#define SMTPD_PROX_WANT_OK '2' /* Expect 2XX reply */ +#define SMTPD_PROX_WANT_MORE '3' /* Expect 3XX reply */ extern int smtpd_proxy_open(SMTPD_STATE *, const char *, int, const char *, const char *); extern int smtpd_proxy_cmd(SMTPD_STATE *, int, const char *,...); diff --git a/postfix/src/verify/verify.c b/postfix/src/verify/verify.c index 443b07ecc..b32c97633 100644 --- a/postfix/src/verify/verify.c +++ b/postfix/src/verify/verify.c @@ -410,7 +410,6 @@ static void verify_query_service(VSTREAM *client_stream) (addr_status == DEL_RCPT_STAT_OK && updated + var_verify_pos_try < now) #define NEGATIVE_REFRESH_NEEDED(addr_status, updated) \ (addr_status != DEL_RCPT_STAT_OK && updated + var_verify_neg_try < now) -#define NULL_CLEANUP_FLAGS 0 if (now - probed > PROBE_TTL && (POSITIVE_REFRESH_NEEDED(addr_status, updated) @@ -420,7 +419,7 @@ static void verify_query_service(VSTREAM *client_stream) STR(addr), addr_status, now, updated); post_mail_fopen_async(strcmp(var_verify_sender, "<>") == 0 ? "" : var_verify_sender, STR(addr), - NULL_CLEANUP_FLAGS, + CLEANUP_FLAG_MASK_INTERNAL, DEL_REQ_FLAG_VERIFY, verify_post_mail_action, (void *) 0);