From: Wietse Venema Date: Mon, 14 Jul 2003 05:00:00 +0000 (-0500) Subject: postfix-2.0.14-20030714 X-Git-Tag: v2.1-RC1-20040331~49 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=47cace1e6f2b34591bf4c9f7ba397209396133d2;p=thirdparty%2Fpostfix.git postfix-2.0.14-20030714 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 075de2f22..cb2b0805e 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -8348,15 +8348,12 @@ Apologies for any names omitted. 20030708 Hardened the attr_scan routines for exposure to an untrusted - environment, in preparation of the tuple0 and tuple64 - protocols that will be used for SMTP policy delegation. + environment, in preparation for possible use with SMTP + policy delegation to an external server. Feature: address filter for RBL lookups, for use with multi-valued RBL services. File: smtpd/smtpd_check.c. - Feature: accept_socket option to pass the spawn(8) listen - socket to a persistent non-Postfix process. File: spawn/spawn.c. - 20030709 Cleanup: use off_t instead of int for VSTREAM file offsets. @@ -8387,7 +8384,6 @@ Apologies for any names omitted. "check_smtpd_policy_service" in smtpd_mumble_restrictions. See SMTPD_POLICY_SERVICE_README for details. - Open problems: Low: smtp-source may block when sending large test messages. diff --git a/postfix/README_FILES/SMTPD_POLICY_README b/postfix/README_FILES/SMTPD_POLICY_README new file mode 100644 index 000000000..9951633d8 --- /dev/null +++ b/postfix/README_FILES/SMTPD_POLICY_README @@ -0,0 +1,160 @@ +SMTPD POLICY DELEGATION PROTOCOL +================================ + +The Postfix SMTP server has a number of built-in mechanisms to +block or accept mail at the SMTP protocol stage. Optionally, it +can delegate policy decisions to an external server. + +This document describes the following: + +- The SMTPD policy delegation protocol. + +- Using the example greylist policy server. + +PROTOCOL DESCRIPTION +==================== + +The SMTPD policy delegation protocol is really simple. The client +request is a sequence of name=value attributes separated by newline, +and is terminated by an empty line. Here is an example of all the +attributes that the Postfix SMTP server sends in a delegated policy +request: + + protocol_state=RCPT + protocol_name=SMTP + helo_name=some.domain.tld + queue_id=8045F2AB23 + sender=foo@bar.tld + recipient=bar@foo.tld + client_address=1.2.3.4 + client_name=another.domain.tld + [empty line] + +The order of the attributes does not matter, and the server ignores +any attributes that it does not recognize. Protocol names are ESMTP +or SMTP; protocol states are CONNECT, EHLO, HELO, MAIL, RCPT, or +DATA. Other attributes speak for themselves. When the same attribute +name is sent more than once, the server may keep the first or the +last attribute value. An attribute name does not contain "=", null +or newline, and an attribute value does not contain null or newline. + +The policy server replies in the same style, with any action that +is allowed in a Postfix SMTPD access table. Example: + + action=450 You are greylisted + [empty line] + +CLIENT SIDE CONFIGURATION +========================= + +The SMTPD delegated policy client can connect to a TCP socket or +to a UNIX-domain socket. Examples: + + inet:localhost:9998 + unix:/some/where/policy + unix:private/policy + +The first example specifies that the policy server listens on +localhost port 9998. The second example specifies an absolute +pathname of a UNIX-domain socket. The third example specifies a +pathname relative to the Postfix queue directory; use this for +policy servers that are spawned by the Postfix master daemon. + +To use the delegated policy service, specify "check_policy_service" +anywhere in the list of smtpd_recipient_restrictions: + +/etc/postfix/main.cf: + smtpd_recipient_restrictions = + ... + reject_unauth_destination + check_policy_service unix:private/policy + ... + +NOTE: specify "check_policy_service" AFTER "reject_unauth_destination" +or else your system could become an open relay. + +EXAMPLE: GREYLIST POLICY SERVER +=============================== + +The file examples/smtpd-policy/smtpd-policy.pl in the Postfix source +tree implements an example greylist policy server. This server +stores a time stamp for every (client, sender, recipient) triple. +Mail is not accepted until a triple's time stamp is more than 3600 +seconds old. This stops junk mail with random sender addresses, +and mail from randomly selected open proxies. It also stops junk +mail from spammers that change IP address frequently. + +The example greylist policy server is a PERL script that runs under +control by the Postfix master daemon: + +/etc/postfix/master.cf: + policy unix - n n - - spawn + user=nobody argv=/usr/bin/perl /usr/libexec/postfix/smtpd-policy.pl + +/etc/postfix/main.cf: + smtpd_recipient_restrictions = + permit_mynetworks + reject_unauth_destination + check_policy_service unix:private/policy unix:private/policy + ... + +There are other delegated policy client configuration parameters +that control timeouts etc. but you should never have to change +those. + +In the smtpd-policy.pl PERL script you need to specify the location +of the greylist database file. DO NOT create the greylist database +in a world-writable directory such as /tmp or /var/tmp, and DO NOT +create the greylist database in a file system that can run out of +space easily. If the file becomes corrupted you will not be able +to receive mail until you delete the file by hand. + +When the status file exceeds some reasonable size you can simply +delete the file without adverse effects. In the worst case, new +mail will be delayed by one hour. To lessen the impact, delete the +file in the middle of the night. + +SAMPLE POLICY ROUTINE +===================== + +This is the PERL subroutine that implements the example greylist policy. + +# +# greylist status database and greylist time interval. DO NOT create the +# greylist status database in a world-writable directory such as /tmp +# or /var/tmp. DO NOT create the greylist database in a file system +# that can run out of space. +# +$database_name="/var/mta/smtpd-policy.db"; +$greylist_delay=3600; + +# +# Demo policy routine. The result is an action just like it would +# be specified on the right-hand side of a Postfix access table. +# Request attributes are passed in via the %attr hash. +# +sub policy { + local(*attr) = @_; + my($key, $time_stamp, $now); + + # Open the database on the fly. + open_database() unless $database_obj; + + # Lookup the time stamp for this client/sender/recipient. + $key = $attr{"client_address"}."/".$attr{"sender"}."/".$attr{"recipient"}; + $time_stamp = read_database($key); + $now = time(); + + # If new request, add this client/sender/recipient to the database. + if ($time_stamp == 0) { + $time_stamp = $now; + update_database($key, $time_stamp); + } + + syslog $syslog_priority, "request age %d", $now - $time_stamp if $verbose; + if ($time_stamp + $greylist_delay < $now) { + return "ok"; + } else { + return "450 request is greylisted"; + } +} diff --git a/postfix/examples/smtpd-policy/smtpd-policy.pl b/postfix/examples/smtpd-policy/smtpd-policy.pl index aed1e72e4..0d374aaa6 100755 --- a/postfix/examples/smtpd-policy/smtpd-policy.pl +++ b/postfix/examples/smtpd-policy/smtpd-policy.pl @@ -11,6 +11,13 @@ use Sys::Syslog qw(:DEFAULT setlogsock); # greylisting. State is kept in a Berkeley DB database. Logging is # sent to syslogd. # +# How it works: each time a Postfix SMTP server process is started +# it connects to the policy service socket, and Postfix runs one +# instance of this PERL script. By default, a Postfix SMTP server +# process terminates after 100 seconds of idle time, or after serving +# 100 clients. Thus, the cost of starting this PERL script is smoothed +# out over time. +# # To run this from /etc/postfix/master.cf: # # policy unix - n n - - spawn @@ -18,12 +25,35 @@ use Sys::Syslog qw(:DEFAULT setlogsock); # # To use this from Postfix SMTPD, use in /etc/postfix/main.cf: # -# smtpd_policy_service_endpoint = plain:unix:private/policy -# smtpd_recipient_restrictions = ... check_policy_service ... +# smtpd_recipient_restrictions = +# ... reject_unauth_destination +# check_policy_service unix:private/policy ... +# +# NOTE: specify check_policy_service AFTER reject_unauth_destination +# or else your system can become an open relay. +# +# To test this script by hand, execute: +# +# % perl smtpd-policy.pl +# +# Each query is a bunch of attributes. Order does not matter, and +# the demo script uses only a few of all the attributes shown below: +# +# protocol_state=RCPT +# protocol_name=SMTP +# helo_name=some.domain.tld +# queue_id=8045F2AB23 +# sender=foo@bar.tld +# recipient=bar@foo.tld +# client_address=1.2.3.4 +# client_name=another.domain.tld +# [empty line] +# +# The policy server script will answer in the same style, with an +# attribute list followed by a empty line: # -# This script runs as one PERL process per SMTP server process. -# By default, a Postfix SMTP server process terminates after 100 -# seconds of idle time, or after serving 100 clients. +# action=ok +# [empty line] # # @@ -36,8 +66,9 @@ $database_name="/var/mta/smtpd-policy.db"; $greylist_delay=3600; # -# Syslogging options for verbose mode and for fatal errors. Comment -# out the $syslog_socktype line if syslogging does not work. +# Syslogging options for verbose mode and for fatal errors. +# NOTE: comment out the $syslog_socktype line if syslogging does not +# work on your system. # $syslog_socktype = 'unix'; # inet, unix, stream, console $syslog_facility="mail"; @@ -99,43 +130,45 @@ sub open_database { $database_obj = tie(%db_hash, 'DB_File', $database_name, O_CREAT|O_RDWR, 0644) || - fatal_exit "Cannot open database %s: %m", $database_name; + fatal_exit "Cannot open database %s: $!", $database_name; $database_fd = $database_obj->fd; open DATABASE_HANDLE, "+<&=$database_fd" || - fatal_exit "Cannot fdopen database %s: %m", $database_name; + fatal_exit "Cannot fdopen database %s: $!", $database_name; syslog $syslog_priority, "open %s", $database_name if $verbose; } # -# Read database. +# Read database. Use a shared lock to avoid reading the database +# while it is being changed. # sub read_database { my($key) = @_; my($value); flock DATABASE_HANDLE, LOCK_SH || - fatal_exit "Can't get shared lock on %s: %m", $database_name; + fatal_exit "Can't get shared lock on %s: $!", $database_name; $value = $db_hash{$key}; syslog $syslog_priority, "lookup %s: %s", $key, $value if $verbose; flock DATABASE_HANDLE, LOCK_UN || - fatal_exit "Can't unlock %s: %m", $database_name; + fatal_exit "Can't unlock %s: $!", $database_name; return $value; } # -# Update database. +# Update database. Use an exclusive lock to avoid collisions with +# other updaters, and to avoid surprises in database readers. # sub update_database { my($key, $value) = @_; syslog $syslog_priority, "store %s: %s", $key, $value if $verbose; flock DATABASE_HANDLE, LOCK_EX || - fatal_exit "Can't exclusively lock %s: %m", $database_name; + fatal_exit "Can't exclusively lock %s: $!", $database_name; $db_hash{$key} = $value; $database_obj->sync() && - fatal_exit "Can't update %s: %m", $database_name; + fatal_exit "Can't update %s: $!", $database_name; flock DATABASE_HANDLE, LOCK_UN || - fatal_exit "Can't unlock %s: %m", $database_name; + fatal_exit "Can't unlock %s: $!", $database_name; } # diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index fd9e64219..08359c941 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -45,7 +45,7 @@ SMTPD(8) SMTPD(8) DIAGNOSTICS Problems and transactions are logged to syslogd(8). - Depending on the setting of the notify_classes parameter, + Depending on the setting of the notify_classes parameter, the postmaster is notified of bounces, protocol problems, policy violations, and of other trouble. @@ -56,17 +56,17 @@ SMTPD(8) SMTPD(8) command after a configuration change. Compatibility controls - strict_rfc821_envelopes + strict_rfc821_envelopes Disallow non-RFC 821 style addresses in SMTP com- mands. For example, the RFC822-style address forms with comments that Sendmail allows. - broken_sasl_auth_clients + broken_sasl_auth_clients Support older Microsoft clients that mis-implement the AUTH protocol, and that expect an EHLO response of "250 AUTH=list" instead of "250 AUTH list". - smtpd_noop_commands + smtpd_noop_commands List of commands that are treated as NOOP (no oper- ation) commands, without any parameter syntax checking and without any state change. This list @@ -76,32 +76,32 @@ SMTPD(8) SMTPD(8) Optionally, Postfix can be configured to send new mail to external content filter software AFTER the mail is queued. - content_filter + content_filter 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. - receive_override_options + 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 + 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 + 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 + no_header_body_checks Disable header/body_checks. This is typi- cally specified with the SMTP server after an external content filter. @@ -111,29 +111,29 @@ SMTPD(8) SMTPD(8) forward all mail to a proxy server, for example a real- time content filter, BEFORE mail is queued. - smtpd_proxy_filter + smtpd_proxy_filter The host:port of the SMTP proxy server. The host or host: portion is optional. - smtpd_proxy_timeout + smtpd_proxy_timeout Timeout for connecting to, sending to and receiving from the SMTP proxy server. - smtpd_proxy_ehlo + smtpd_proxy_ehlo The hostname to use when sending an EHLO command to the SMTP proxy server. Authentication controls - enable_sasl_authentication + enable_sasl_authentication 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. - smtpd_sasl_local_domain + smtpd_sasl_local_domain The name of the local authentication realm. - smtpd_sasl_security_options + smtpd_sasl_security_options Zero or more of the following. noplaintext @@ -151,41 +151,41 @@ SMTPD(8) SMTPD(8) noanonymous Disallow anonymous logins. - smtpd_sender_login_maps + smtpd_sender_login_maps Maps that specify the SASL login name that owns a MAIL FROM sender address. Used by the - reject_sender_login_mismatch sender anti-spoofing + reject_sender_login_mismatch sender anti-spoofing restriction. Miscellaneous - authorized_verp_clients + authorized_verp_clients Hostnames, domain names and/or addresses of clients that are authorized to use the XVERP extension. - debug_peer_level + debug_peer_level Increment in verbose logging level when a remote - host matches a pattern in the debug_peer_list + host matches a pattern in the debug_peer_list parameter. - debug_peer_list + 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 - debug_peer_level parameter. + debug_peer_level parameter. - default_verp_delimiters + default_verp_delimiters The default VERP delimiter characters that are used when the XVERP command is specified without explicit delimiters. - error_notice_recipient + error_notice_recipient Recipient of protocol/policy/resource/software error notices. - hopcount_limit + hopcount_limit Limit the number of Received: message headers. - notify_classes + notify_classes List of error classes. Of special interest are: policy When a client violates any policy, mail a @@ -198,267 +198,261 @@ SMTPD(8) SMTPD(8) transcript of the entire SMTP session to the postmaster. - smtpd_banner + smtpd_banner Text that follows the 220 status code in the SMTP greeting banner. - smtpd_expansion_filter + smtpd_expansion_filter Controls what characters are allowed in $name expansion of rbl template responses and other text. - smtpd_recipient_limit + smtpd_recipient_limit Restrict the number of recipients that the SMTP server accepts per message delivery. - smtpd_timeout + smtpd_timeout Limit the time to send a server response and to receive a client request. - soft_bounce + soft_bounce Change hard (5xx) reject responses into soft (4xx) reject responses. This can be useful for testing purposes. - verp_delimiter_filter + verp_delimiter_filter The characters that Postfix accepts as VERP delim- iter characters. Known versus unknown recipients - show_user_unknown_table_name + 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- tion that is nobody elses business. - unknown_local_recipient_reject_code + unknown_local_recipient_reject_code The response code when a client specifies a recipi- ent whose domain matches $mydestination or - $inet_interfaces, while $local_recipient_maps is + $inet_interfaces, while $local_recipient_maps is non-empty and does not list the recipient address or address local-part. - unknown_relay_recipient_reject_code + 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 + ent whose domain matches $relay_domains, while + $relay_recipient_maps is non-empty and does not list the recipient address. - unknown_virtual_alias_reject_code + unknown_virtual_alias_reject_code The response code when a client specifies a recipi- - ent whose domain matches $virtual_alias_domains, + ent whose domain matches $virtual_alias_domains, while the recipient is not listed in $vir- - tual_alias_maps. + tual_alias_maps. - unknown_virtual_mailbox_reject_code + unknown_virtual_mailbox_reject_code The response code when a client specifies a recipi- - ent whose domain matches $virtual_mailbox_domains, - while the recipient is not listed in $virtual_mail- - box_maps. + ent whose domain matches $virtual_mailbox_domains, + while the recipient is not listed in $virtual_mail- + box_maps. Resource controls - line_length_limit + line_length_limit Limit the amount of memory in bytes used for the handling of partial input lines. - message_size_limit + message_size_limit Limit the total size in bytes of a message, includ- ing on-disk storage for envelope information. - queue_minfree + queue_minfree 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 + smtpd_history_flush_threshold Flush the command history to postmaster after receipt of RSET etc. only if the number of history lines exceeds the given threshold. Tarpitting - smtpd_error_sleep_time + smtpd_error_sleep_time Time to wait in seconds before sending a 4xx or 5xx server error response. - smtpd_soft_error_limit + 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 + smtpd_hard_error_limit Disconnect after a client has made this number of errors. - smtpd_junk_command_limit + 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 delays. Delegated policy - smtpd_policy_service_endpoint - The transport:endpoint of a server that speaks the - delegated SMTP policy protocol. transport is either - inet or unix. endpoint is either host:port, pri- - vate/servicename or public/servicename. - - smtpd_policy_service_timeout + smtpd_policy_service_timeout Time limit for connecting to, writing to and - receiving from a delegated SMTP policy server. + receiving from a delegated SMTPD policy server. - smtpd_policy_service_max_idle - Time after which an unused policy service connec- - tion is closed. + smtpd_policy_service_max_idle + Time after which an unused SMTPD policy service + connection is closed. - smtpd_policy_service_timeout - Time after which an active policy service connec- - tion is closed. + smtpd_policy_service_timeout + Time after which an active SMTPD policy service + connection is closed. 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 + parent_domain_matches_subdomains + 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 + smtpd_client_restrictions Restrict what clients may connect to this mail sys- tem. - smtpd_helo_required - Require that clients introduce themselves at the + smtpd_helo_required + Require that clients introduce themselves at the beginning of an SMTP session. - smtpd_helo_restrictions - Restrict what client hostnames are allowed in HELO + smtpd_helo_restrictions + Restrict what client hostnames are allowed in HELO and EHLO commands. - smtpd_sender_restrictions - Restrict what sender addresses are allowed in MAIL + smtpd_sender_restrictions + Restrict what sender addresses are allowed in MAIL FROM commands. - smtpd_recipient_restrictions - Restrict what recipient addresses are allowed in + smtpd_recipient_restrictions + Restrict what recipient addresses are allowed in RCPT TO commands. - smtpd_etrn_restrictions + smtpd_etrn_restrictions Restrict what domain names can be used in ETRN com- 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 - reject_unauth_pipelining. + smtpd_data_restrictions + 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_routing + 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 + 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 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 + smtpd_null_access_lookup_key + 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 + maps_rbl_domains (deprecated) + List of DNS domains that publish the addresses of blacklisted hosts. This is used with the deprecated - reject_maps_rbl restriction. + reject_maps_rbl restriction. - permit_mx_backup_networks - Only domains whose primary MX hosts match the - listed networks are eligible for the per- - mit_mx_backup feature. + permit_mx_backup_networks + 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 - agent specified with the relay_transport setting. + relay_domains + 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 + 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 a new sender or recipient address. - address_verify_poll_delay - Time to wait after querying the address verifica- + address_verify_poll_delay + 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 + access_map_reject_code + Response code when a client violates an access database restriction. - default_rbl_reply + 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: - rbl_reply_maps and smtpd_expansion_filter. + 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 + defer_code + Response code when a client request is rejected by the defer restriction. - invalid_hostname_reject_code - Response code when a client violates the - reject_invalid_hostname restriction. + invalid_hostname_reject_code + Response code when a client violates the + reject_invalid_hostname restriction. - maps_rbl_reject_code + 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 + multi_recipient_bounce_reject_code + 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- - plates are used by the reject_rbl_* and - reject_rhsbl_* restrictions. See also: - default_rbl_reply and smtpd_expansion_filter. + rbl_reply_maps + 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: + default_rbl_reply and smtpd_expansion_filter. - reject_code - Response code when the client matches a reject + reject_code + Response code when the client matches a reject restriction. - relay_domains_reject_code + relay_domains_reject_code Response code when a client attempts to violate the mail relay policy. - unknown_address_reject_code - Response code when a client violates the - reject_unknown_address restriction. + unknown_address_reject_code + Response code when a client violates the + reject_unknown_address restriction. - unknown_client_reject_code + unknown_client_reject_code Response code when a client without address to name - mapping violates the reject_unknown_client restric- + mapping violates the reject_unknown_client restric- tion. - unknown_hostname_reject_code - Response code when a client violates the - reject_unknown_hostname restriction. + unknown_hostname_reject_code + 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 + unverified_sender_reject_code + Response code when a sender address is known to be undeliverable. - unverified_recipient_reject_code - Response code when a recipient address is known to + unverified_recipient_reject_code + Response code when a recipient address is known to be undeliverable. SEE ALSO @@ -469,7 +463,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/man8/smtpd.8 b/postfix/man/man8/smtpd.8 index f5a939851..0f149af63 100644 --- a/postfix/man/man8/smtpd.8 +++ b/postfix/man/man8/smtpd.8 @@ -250,19 +250,15 @@ it is penalized with tarpit delays. .SH "Delegated policy" .ad .fi -.IP \fBsmtpd_policy_service_endpoint\fR -The \fItransport\fR:\fIendpoint\fR of a server that speaks -the delegated SMTP policy protocol. \fItransport\fR is -either \fBinet\fR or \fBunix\fR. \fIendpoint\fR is either -\fIhost:port\fR, \fBprivate/\fIservicename\fR or -\fBpublic/\fIservicename\fR. .IP \fBsmtpd_policy_service_timeout\fR Time limit for connecting to, writing to and receiving from -a delegated SMTP policy server. +a delegated SMTPD policy server. .IP \fBsmtpd_policy_service_max_idle\fR -Time after which an unused policy service connection is closed. +Time after which an unused SMTPD policy service connection +is closed. .IP \fBsmtpd_policy_service_timeout\fR -Time after which an active policy service connection is closed. +Time after which an active SMTPD policy service connection +is closed. .SH "UCE control restrictions" .ad .fi diff --git a/postfix/mantools/man2html b/postfix/mantools/man2html index 9f34c7419..be7c1c822 100755 --- a/postfix/mantools/man2html +++ b/postfix/mantools/man2html @@ -9,7 +9,7 @@ sed ' s/&/\&/g s//\>/g - s;_\(.\);\1;g + s;_\([^_]\);\1;g s;.\(.\);\1;g s;\( *\);\1;g s;\( *\);\1;g diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index bd96bcd96..7d8961c6f 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -1853,10 +1853,6 @@ extern char *var_smtpd_input_transp; /* * SMTP server policy delegation. */ -#define VAR_SMTPD_POLICY_SRV "smtpd_policy_service_endpoint" -#define DEF_SMTPD_POLICY_SRV "" -extern char *var_smtpd_policy_srv; - #define VAR_SMTPD_POLICY_TMOUT "smtpd_policy_service_timeout" #define DEF_SMTPD_POLICY_TMOUT "100s" extern int var_smtpd_policy_tmout; @@ -1869,7 +1865,7 @@ extern int var_smtpd_policy_idle; #define DEF_SMTPD_POLICY_TTL "1000s" extern int var_smtpd_policy_ttl; -#define CHECK_POLICY_SERVICE "check_smtpd_policy_service" +#define CHECK_POLICY_SERVICE "check_policy_service" /* LICENSE /* .ad diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h index 7cb0dd4c6..04ad9bda4 100644 --- a/postfix/src/global/mail_proto.h +++ b/postfix/src/global/mail_proto.h @@ -145,6 +145,7 @@ extern char *mail_pathname(const char *, const char *); #define MAIL_ATTR_CLIENT_ADDR "client_address" /* client address */ #define MAIL_ATTR_HELO_NAME "helo_name" /* SMTP helo name */ #define MAIL_ATTR_PROTO_NAME "protocol_name" /* SMTP/ESMTP/QMQP/... */ +#define MAIL_ATTR_PROTO_STATE "protocol_state" /* MAIL/RCPT/... */ #define MAIL_ATTR_ORIGIN "message_origin" /* hostname[address] */ #define MAIL_ATTR_ORG_NONE "unknown" /* origin unknown */ #define MAIL_ATTR_ORG_LOCAL "local" /* local submission */ diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index f9b390b0b..bf39f9746 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 "20030712" +#define MAIL_RELEASE_DATE "20030714" #define VAR_MAIL_VERSION "mail_version" #define DEF_MAIL_VERSION "2.0.14-" MAIL_RELEASE_DATE diff --git a/postfix/src/lmtp/lmtp_sasl_glue.c b/postfix/src/lmtp/lmtp_sasl_glue.c index ca11019ca..9b0e673c0 100644 --- a/postfix/src/lmtp/lmtp_sasl_glue.c +++ b/postfix/src/lmtp/lmtp_sasl_glue.c @@ -11,7 +11,7 @@ /* void lmtp_sasl_connect(state) /* LMTP_STATE *state; /* -/* void lmtp_sasl_start(state, sasl_opts_name, sasl_opts_var) +/* void lmtp_sasl_start(state, sasl_opts_name, sasl_opts_val) /* LMTP_STATE *state; /* /* int lmtp_sasl_passwd_lookup(state) @@ -33,7 +33,7 @@ /* /* lmtp_sasl_start() performs per-session initialization. This /* routine must be called once per session before doing any SASL -/* authentication. The sasl_opts_name and sasl_opts_var parameters are +/* authentication. The sasl_opts_name and sasl_opts_val parameters are /* the postfix configuration parameters setting the security /* policy of the SASL authentication. /* @@ -337,7 +337,7 @@ void lmtp_sasl_connect(LMTP_STATE *state) /* lmtp_sasl_start - per-session SASL initialization */ void lmtp_sasl_start(LMTP_STATE *state, const char *sasl_opts_name, - const char *sasl_opts_var) + const char *sasl_opts_val) { static sasl_callback_t callbacks[] = { {SASL_CB_USER, &lmtp_sasl_get_user, 0}, @@ -380,7 +380,7 @@ void lmtp_sasl_start(LMTP_STATE *state, const char *sasl_opts_name, sec_props.max_ssf = 1; /* don't allow real SASL * security layer */ sec_props.security_flags = name_mask(sasl_opts_name, lmtp_sasl_sec_mask, - sasl_opts_var); + sasl_opts_val); sec_props.maxbufsize = 0; sec_props.property_names = 0; sec_props.property_values = 0; diff --git a/postfix/src/smtp/smtp_sasl_glue.c b/postfix/src/smtp/smtp_sasl_glue.c index d357d85b0..211a30a4e 100644 --- a/postfix/src/smtp/smtp_sasl_glue.c +++ b/postfix/src/smtp/smtp_sasl_glue.c @@ -11,7 +11,7 @@ /* void smtp_sasl_connect(state) /* SMTP_STATE *state; /* -/* void smtp_sasl_start(state, sasl_opts_name, sasl_opts_var) +/* void smtp_sasl_start(state, sasl_opts_name, sasl_opts_val) /* SMTP_STATE *state; /* /* int smtp_sasl_passwd_lookup(state) @@ -33,7 +33,7 @@ /* /* smtp_sasl_start() performs per-session initialization. This /* routine must be called once per session before doing any SASL -/* authentication. The sasl_opts_name and sasl_opts_var parameters are +/* authentication. The sasl_opts_name and sasl_opts_val parameters are /* the postfix configuration parameters setting the security /* policy of the SASL authentication. /* @@ -337,7 +337,7 @@ void smtp_sasl_connect(SMTP_STATE *state) /* smtp_sasl_start - per-session SASL initialization */ void smtp_sasl_start(SMTP_STATE *state, const char *sasl_opts_name, - const char *sasl_opts_var) + const char *sasl_opts_val) { static sasl_callback_t callbacks[] = { {SASL_CB_USER, &smtp_sasl_get_user, 0}, @@ -380,7 +380,7 @@ void smtp_sasl_start(SMTP_STATE *state, const char *sasl_opts_name, sec_props.max_ssf = 1; /* don't allow real SASL * security layer */ sec_props.security_flags = name_mask(sasl_opts_name, smtp_sasl_sec_mask, - sasl_opts_var); + sasl_opts_val); sec_props.maxbufsize = 0; sec_props.property_names = 0; sec_props.property_values = 0; diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index e6b6a31b8..b869ef026 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -67,7 +67,7 @@ /* without any parameter syntax checking and without any state change. /* This list overrides built-in command definitions. /* .SH "Content inspection controls" -/* Optionally, Postfix can be configured to send new mail to +/* Optionally, Postfix can be configured to send new mail to /* external content filter software AFTER the mail is queued. /* .IP \fBcontent_filter\fR /* The name of a mail delivery transport that filters mail and that @@ -236,19 +236,15 @@ /* .SH "Delegated policy" /* .ad /* .fi -/* .IP \fBsmtpd_policy_service_endpoint\fR -/* The \fItransport\fR:\fIendpoint\fR of a server that speaks -/* the delegated SMTP policy protocol. \fItransport\fR is -/* either \fBinet\fR or \fBunix\fR. \fIendpoint\fR is either -/* \fIhost:port\fR, \fBprivate/\fIservicename\fR or -/* \fBpublic/\fIservicename\fR. /* .IP \fBsmtpd_policy_service_timeout\fR /* Time limit for connecting to, writing to and receiving from -/* a delegated SMTP policy server. +/* a delegated SMTPD policy server. /* .IP \fBsmtpd_policy_service_max_idle\fR -/* Time after which an unused policy service connection is closed. +/* Time after which an unused SMTPD policy service connection +/* is closed. /* .IP \fBsmtpd_policy_service_timeout\fR -/* Time after which an active policy service connection is closed. +/* Time after which an active SMTPD policy service connection +/* is closed. /* .SH "UCE control restrictions" /* .ad /* .fi @@ -522,7 +518,6 @@ char *var_smtpd_proxy_filt; int var_smtpd_proxy_tmout; char *var_smtpd_proxy_ehlo; char *var_input_transp; -char *var_smtpd_policy_srv; int var_smtpd_policy_tmout; int var_smtpd_policy_idle; int var_smtpd_policy_ttl; @@ -1928,7 +1923,6 @@ int main(int argc, char **argv) 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, - VAR_SMTPD_POLICY_SRV, DEF_SMTPD_POLICY_SRV, &var_smtpd_policy_srv, 0, 0, 0, }; static CONFIG_RAW_TABLE raw_table[] = { diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 7d87b06e8..102ddbbc8 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -57,7 +57,7 @@ /* Reject, defer or permit the request unconditionally. This is to be used /* at the end of a restriction list in order to make the default /* action explicit. -/* .IP check_policy_service +/* .IP "check_policy_service transport:server" /* query an external policy service with client, helo, sender, recipient /* and queue ID attributes. /* .IP reject_unknown_client @@ -407,6 +407,7 @@ static ARGV *etrn_restrctions; static ARGV *data_restrctions; static HTABLE *smtpd_rest_classes; +static HTABLE *policy_clnt_table; /* * Pre-parsed expansion filter. @@ -423,11 +424,6 @@ static int generic_checks(SMTPD_STATE *, ARGV *, const char *, const char *, con */ static int check_rcpt_maps(SMTPD_STATE *state, const char *recipient); - /* - * Delegated policy. - */ -static ATTR_CLNT *policy_clnt; - /* * Reject context. */ @@ -551,6 +547,21 @@ static void resolve_pageout(void *data, void *unused_context) myfree((void *) reply); } +/* policy_client_register - register policy service endpoint */ + +static void policy_client_register(const char *name) +{ + if (policy_clnt_table == 0) + policy_clnt_table = htable_create(1); + + if (htable_find(policy_clnt_table, name) == 0) + htable_enter(policy_clnt_table, name, + (char *) attr_clnt_create(name, + var_smtpd_policy_tmout, + var_smtpd_policy_idle, + var_smtpd_policy_ttl)); +} + /* smtpd_check_parse - pre-parse restrictions */ static ARGV *smtpd_check_parse(const char *checks) @@ -559,6 +570,7 @@ static ARGV *smtpd_check_parse(const char *checks) ARGV *argv = argv_alloc(1); char *bp = saved_checks; char *name; + char *last = 0; /* * Pre-parse the restriction list, and open any dictionaries that we @@ -567,8 +579,12 @@ static ARGV *smtpd_check_parse(const char *checks) */ while ((name = mystrtok(&bp, " \t\r\n,")) != 0) { argv_add(argv, name, (char *) 0); - if (strchr(name, ':') && dict_handle(name) == 0) + if (last && strcasecmp(last, CHECK_POLICY_SERVICE) == 0) + policy_client_register(name); + else if (strchr(name, ':') && dict_handle(name) == 0) { dict_register(name, dict_open(name, O_RDONLY, DICT_FLAG_LOCK)); + } + last = name; } argv_terminate(argv); @@ -764,15 +780,6 @@ void smtpd_check_init(void) */ expand_filter = vstring_alloc(10); unescape(expand_filter, var_smtpd_exp_filter); - - /* - * Delegated policy. - */ - if (*var_smtpd_policy_srv) - policy_clnt = attr_clnt_create(var_smtpd_policy_srv, - var_smtpd_policy_tmout, - var_smtpd_policy_idle, - var_smtpd_policy_ttl); } /* log_whatsup - log as much context as we have */ @@ -2714,29 +2721,30 @@ static int reject_sender_login_mismatch(SMTPD_STATE *state, const char *sender) /* check_policy_service - check delegated policy service */ -static int check_policy_service(SMTPD_STATE *state, const char *reply_name, - const char *reply_class, const char *def_acl) +static int check_policy_service(SMTPD_STATE *state, const char *server, + const char *reply_name, const char *reply_class, + const char *def_acl) { static VSTRING *action = 0; + ATTR_CLNT *policy_clnt; /* * Sanity check. */ - if (policy_clnt == 0) { - msg_warn("%s is used in %s restrictions, but no service is defined", - CHECK_POLICY_SERVICE, reply_class); - return (SMTPD_CHECK_DUNNO); - } + if (!policy_clnt_table + || !(policy_clnt = (ATTR_CLNT *) htable_find(policy_clnt_table, server))) + msg_panic("check_policy_service: no client endpoint for server %s", + server); /* * Initialize. */ if (action == 0) action = vstring_alloc(10); - if (attr_clnt_request(policy_clnt, ATTR_FLAG_NONE, /* Query attributes. */ - ATTR_TYPE_STR, MAIL_ATTR_CLIENT, state->namaddr, + ATTR_TYPE_STR, MAIL_ATTR_PROTO_STATE, state->where, + ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, state->protocol, ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, state->addr, ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, state->name, ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME, @@ -2759,7 +2767,7 @@ static int check_policy_service(SMTPD_STATE *state, const char *reply_name, * XXX This produces bogus error messages when the reply is * malformed. */ - return (check_table_result(state, var_smtpd_policy_srv, STR(action), + return (check_table_result(state, server, STR(action), "policy query", reply_name, reply_class, def_acl)); } @@ -2867,8 +2875,12 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, } else if (strcasecmp(name, REJECT_UNAUTH_PIPE) == 0) { status = reject_unauth_pipelining(state, reply_name, reply_class); } else if (strcasecmp(name, CHECK_POLICY_SERVICE) == 0) { - status = check_policy_service(state, reply_name, - reply_class, def_acl); + if (cpp[1] == 0) + msg_warn("restriction %s must be followed by transport:server", + CHECK_POLICY_SERVICE); + else + status = check_policy_service(state, *++cpp, reply_name, + reply_class, def_acl); } else if (strcasecmp(name, DEFER_IF_PERMIT) == 0) { DEFER_IF_PERMIT2(state, MAIL_ERROR_POLICY, "450 <%s>: %s rejected: defer_if_permit requested", @@ -3689,7 +3701,6 @@ char *var_def_rbl_reply; char *var_relay_rcpt_maps; char *var_verify_sender; char *var_smtpd_sasl_opts; -char *var_smtpd_policy_srv; typedef struct { char *name; @@ -3730,7 +3741,6 @@ static STRING_TABLE string_table[] = { VAR_VERIFY_SENDER, DEF_VERIFY_SENDER, &var_verify_sender, VAR_MAIL_NAME, DEF_MAIL_NAME, &var_mail_name, VAR_SMTPD_SASL_OPTS, DEF_SMTPD_SASL_OPTS, &var_smtpd_sasl_opts, - VAR_SMTPD_POLICY_SRV, DEF_SMTPD_POLICY_SRV, &var_smtpd_policy_srv, 0, 0, 0, }; diff --git a/postfix/src/smtpd/smtpd_sasl_glue.c b/postfix/src/smtpd/smtpd_sasl_glue.c index 490a2633c..da5074655 100644 --- a/postfix/src/smtpd/smtpd_sasl_glue.c +++ b/postfix/src/smtpd/smtpd_sasl_glue.c @@ -8,7 +8,7 @@ /* /* void smtpd_sasl_initialize() /* -/* void smtpd_sasl_connect(state, sasl_opts_name, sasl_opts_var) +/* void smtpd_sasl_connect(state, sasl_opts_name, sasl_opts_val) /* SMTPD_STATE *state; /* /* char *smtpd_sasl_authenticate(state, sasl_method, init_response) @@ -32,7 +32,7 @@ /* /* smtpd_sasl_connect() performs per-connection initialization. /* This routine should be called once at the start of every -/* connection. The sasl_opts_name and sasl_opts_var parameters +/* connection. The sasl_opts_name and sasl_opts_val parameters /* are the postfix configuration parameters setting the security /* policy of the SASL authentication. /* @@ -219,7 +219,7 @@ void smtpd_sasl_initialize(void) /* smtpd_sasl_connect - per-connection initialization */ void smtpd_sasl_connect(SMTPD_STATE *state, const char *sasl_opts_name, - const char *sasl_opts_var) + const char *sasl_opts_val) { #if SASL_VERSION_MAJOR < 2 unsigned sasl_mechanism_count; @@ -288,7 +288,7 @@ void smtpd_sasl_connect(SMTPD_STATE *state, const char *sasl_opts_name, sec_props.max_ssf = 1; /* don't allow real SASL * security layer */ sec_props.security_flags = name_mask(sasl_opts_name, smtpd_sasl_mask, - sasl_opts_var); + sasl_opts_val); sec_props.maxbufsize = 0; sec_props.property_names = 0; sec_props.property_values = 0; diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index e1012ea06..5dbf530db 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -93,7 +93,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \ vstring vstring_vstream doze select_bug stream_test mac_expand \ watchdog unescape hex_quote name_mask rand_sleep sane_time ctable \ inet_addr_list attr_print64 attr_scan64 base64_code attr_print0 \ - attr_scan0 host_port + attr_scan0 host_port attr_scan_plain attr_print_plain LIB_DIR = ../../lib INC_DIR = ../../include diff --git a/postfix/src/util/attr_clnt.c b/postfix/src/util/attr_clnt.c index a0edae793..e12644a1e 100644 --- a/postfix/src/util/attr_clnt.c +++ b/postfix/src/util/attr_clnt.c @@ -27,7 +27,7 @@ /* ATTR_CLNT *client; /* DESCRIPTION /* This module implements a client for a simple attribute-based -/* protocol as described in attr_scan0(3) and attr_scan64(3). +/* protocol as described in attr_scan_plain(3). /* /* attr_clnt_create() creates a client handle. The server /* argument specifies "transport:servername" where transport is @@ -134,8 +134,10 @@ ATTR_CLNT *attr_clnt_create(const char *service, int timeout, char *endpoint; ATTR_CLNT *client; - if ((endpoint = split_at(transport, ':')) == 0 || *endpoint == 0) - msg_fatal("missing attribute server endpoint: %s", service); + if ((endpoint = split_at(transport, ':')) == 0 + || *endpoint == 0 || *transport == 0) + msg_fatal("service \"%s\" should be specified as transport:endpoint", + service); if (msg_verbose) msg_info("%s: transport=%s endpoint=%s", myname, transport, endpoint); @@ -222,7 +224,7 @@ int attr_clnt_request(ATTR_CLNT *client, int send_flags,...) || msg_verbose || (errno != EPIPE && errno != ENOENT && errno != ECONNRESET)) msg_warn("problem talking to server %s: %m", client->endpoint); - if (count >= 3) + if (count >= 2) return (-1); sleep(1); /* XXX make configurable */ auto_clnt_recover(client->auto_clnt);