mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-28 12:48:01 +00:00
postfix-2.0.13-20030702
This commit is contained in:
parent
b1771bb6f5
commit
5884ef624c
2
postfix/.indent.pro
vendored
2
postfix/.indent.pro
vendored
@ -26,6 +26,8 @@
|
||||
-TDELIVER_ATTR
|
||||
-TDELIVER_REQUEST
|
||||
-TDICT
|
||||
-TDICT_CIDR
|
||||
-TDICT_CIDR_ENTRY
|
||||
-TDICT_DB
|
||||
-TDICT_DBM
|
||||
-TDICT_DEBUG
|
||||
|
122
postfix/HISTORY
122
postfix/HISTORY
@ -8189,8 +8189,8 @@ Apologies for any names omitted.
|
||||
of mail probes, so it will no longer block for in_flow_delay
|
||||
seconds when mail arrives faster than it is delivered.
|
||||
Still need to make mail_stream_finish() asynchronous in
|
||||
order to avoid blocking for trigger_timeout seconds when
|
||||
the queue manager is overwhelmed. Files: global/post_mail.c,
|
||||
order to avoid blocking for trigger_timeout seconds when the
|
||||
queue manager is overwhelmed. Files: global/post_mail.c,
|
||||
verify/verify.c.
|
||||
|
||||
Bugfix: removed extraneous sleep() after the last attempt
|
||||
@ -8201,6 +8201,42 @@ Apologies for any names omitted.
|
||||
Bugfix: the stricter postdrop input filter broke "sendmail
|
||||
-bs". Found by Lutz Jaenicke. File: smtpd/smtpd.c.
|
||||
|
||||
20030614
|
||||
|
||||
Portability: Dropped support for client side LDAP caching.
|
||||
As of release 2.1.13 OpenLDAP no longer supports client
|
||||
side caching, it has been deprecated for some time, and
|
||||
never worked well. Implemented by Victor Duchovni, Morgan
|
||||
Stanley, and further enhanced by Lamont Jones, HP. Files:
|
||||
src/util/dict_ldap.c, conf/sample-ldap.cf,
|
||||
README_FILES/LDAP_README.
|
||||
|
||||
Safety: Given suitable invalid database contents, LDAP
|
||||
lookups can produce too many results, enter an infinite
|
||||
loop in the expansion of "special result attributes" (LDAP
|
||||
DNs and LDAP URLs) or just consume excessive server resources
|
||||
returning large result sets. Three new (per LDAP map)
|
||||
configuration parameters enable one to set limits on
|
||||
recursive nesting, result expansion and the server response
|
||||
"entry" count. Implemented by Victor Duchovni, Morgan
|
||||
Stanley, further enanced by Lamont Jones, HP. Files:
|
||||
src/util/dict_ldap.c, conf/sample-ldap.cf,
|
||||
README_FILES/LDAP_README.
|
||||
|
||||
20030616
|
||||
|
||||
Feature: in mail delivery status reports, report the sender
|
||||
address as X-Postfix-Sender. Matthias Andree. File:
|
||||
bounce/bounce_notify_util.c.
|
||||
|
||||
Cleanup: in mail delivery status reports, transform the
|
||||
original recipient into xtext format as required by RFC
|
||||
1891. Files: bounce/bounce_notify_util.c, util/xtext.[hc].
|
||||
|
||||
Cleanup: more accurate "postfix check" warning for files
|
||||
that miss one or more of the required mode 02111 execute
|
||||
permission bits. Matthias Andree. File: conf/postfix-script.
|
||||
|
||||
20030618
|
||||
|
||||
After "postfix reload", the master daemon now warns when
|
||||
@ -8208,6 +8244,20 @@ Apologies for any names omitted.
|
||||
of passing incorrect information to the smtp server. File:
|
||||
master/master_ent.c.
|
||||
|
||||
20030619
|
||||
|
||||
Feature: the Postfix SMTP server can send all mail into a
|
||||
proxy server, for example a real-time SPAM filter. This
|
||||
proxy is supposed to send the mail into another Postfix
|
||||
SMTP server process for normal delivery. Files: smtpd/smtpd.c
|
||||
smtpd/smtpd_proxy.[hc].
|
||||
|
||||
20030620
|
||||
|
||||
Bugfix: a cut-and-paste error caused the proxy server's
|
||||
354 status code to be reported when a proxy connection
|
||||
broke during the DATA phase. File: smtpd.c.
|
||||
|
||||
20030620
|
||||
|
||||
Bugfix: after the last change to postdrop, postcat no longer
|
||||
@ -8217,6 +8267,74 @@ Apologies for any names omitted.
|
||||
sendmail, "-t" broke multi-line recipient headers. Victor
|
||||
Duchovni, Morgan Stanley. File: sendmail/sendmail.c.
|
||||
|
||||
20030621
|
||||
|
||||
Workaround: the safe_open(O_CREAT) race condition exploit
|
||||
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
|
||||
flag when the verify service was unavailable (which never
|
||||
happens). Victor Duchovni, Morgan Stanley. File:
|
||||
smtpd/smtpd_check.c.
|
||||
|
||||
New parameters address_verify_poll_{count,delay} that
|
||||
control how often to poll the address verification service
|
||||
for the completion of an address verification request.
|
||||
Specify address_verify_poll_count=1 to implement a crude
|
||||
form of greylisting, that is, always defer the first delivery
|
||||
attempt for an unknown address. File: smtpd/smtpd_check.c.
|
||||
|
||||
Bugfix: after the last change to postdrop, postcat no longer
|
||||
recognized non-maildrop queue files as valid. File:
|
||||
postcat/postcat.c.
|
||||
|
||||
20030629
|
||||
|
||||
Cleanup: replaced references to "simulated virtual domains"
|
||||
by "virtual alias domains". Victor Duchovni, Morgan Stanley.
|
||||
|
||||
20030630
|
||||
|
||||
Feature: smtp_quote_rfc821_envelope=(yes|no) to control
|
||||
RFC 821 style quoting of MAIL FROM and RCPT TO addresses.
|
||||
Files: global/mail_params.h, smtp/smtp.c, smtp/smtp_proto.c.
|
||||
|
||||
20030701
|
||||
|
||||
Bugfix: multi-recipient probes triggered a bug in the SMTP
|
||||
client. File: smtp/smtp_proto.c.
|
||||
|
||||
Feature: enable_original_recipient (default: yes) to control
|
||||
whether Postfix keeps track of original recipient address
|
||||
information. Victor Duchovni, Morgan Stanley. Files:
|
||||
cleanup/cleanup.c, cleanup/cleanup_init.c,
|
||||
cleanup/cleanup_out_recipient.c, global/log_adhoc.c,
|
||||
global/mail_copy.c, *qmgr/qmgr_message.c.
|
||||
|
||||
Feature: !/pattern/ support for PCRE lookup tables. Victor
|
||||
Duchovni, Morgan Stanley. Files: util/dict_pcre.c.
|
||||
|
||||
Cleanup: allow whitespace after patterns in repexp and pcre
|
||||
tables. Victor Duchovni, Morgan Stanley. Files:
|
||||
util/dict_pcre.c, util/dict_regexp.c.
|
||||
|
||||
20030702
|
||||
|
||||
Feature: CIDR lookup table support, very remotely based on
|
||||
code by Jozsef Kadlecsik. Files: proto/cidr_table,
|
||||
util/dict_cidr.[hc].
|
||||
|
||||
Feature: TCP lookup table support, finally finished. Files:
|
||||
proto/tcp_table, proto/dict_tcp.[hc].
|
||||
|
||||
Open problems:
|
||||
|
||||
Low: smtp-source may block when sending large test messages.
|
||||
|
@ -154,21 +154,41 @@ parameter below, "server_host", would be defined in main.cf as
|
||||
the Postfix user. Example:
|
||||
ldapsource_bind_pw = postfixpw
|
||||
|
||||
cache (no)
|
||||
Whether to use a client-side cache for the LDAP connection. See
|
||||
ldap_enable_cache(3). It's off by default.
|
||||
cache (IGNORED with a warning)
|
||||
cache_expiry (IGNORED with a warning)
|
||||
cache_size (IGNORED with a warning)
|
||||
The above parameters are NO LONGER SUPPORTED by Postfix.
|
||||
Cache support has been dropped from OpenLDAP as of release 2.1.13.
|
||||
|
||||
cache_expiry (30 seconds)
|
||||
If the client-side cache is enabled, cached results will expire
|
||||
after this many seconds.
|
||||
recursion_limit (1000)
|
||||
A limit on the nesting depth of DN and URL special result
|
||||
attribute evaluation. The limit must be a non-zero positive
|
||||
number.
|
||||
|
||||
cache_size (32768 bytes)
|
||||
If the client-side cache is enabled, this is its size in bytes.
|
||||
expansion_limit (0)
|
||||
A limit on the total number of result elements returned (as a
|
||||
comma separated list) by a lookup against the map. A setting of
|
||||
zero disables the limit. Lookups fail with a temporary error
|
||||
if the limit is exceeded. Setting the limit to 1 ensures that
|
||||
lookups do not return multiple values.
|
||||
|
||||
size_limit ($expansion_limit)
|
||||
A limit on the number of LDAP entries returned by any single LDAP
|
||||
query performed as part of the lookup. A setting of 0 disables
|
||||
the limit. Expansion of DN and URL references involves nested
|
||||
LDAP queries, each of which is separately subjected to this
|
||||
limit.
|
||||
|
||||
Note: even a single LDAP entry can generate multiple lookup
|
||||
results, via multiple result attributes and/or multi-valued
|
||||
result attributes. This limit caps the per query resource
|
||||
utilization on the LDAP server, not the final multiplicity of the
|
||||
lookup result. It is analogous to the "-z" option of "ldapsearch".
|
||||
|
||||
dereference (0)
|
||||
When to dereference LDAP aliases. (Note that this has nothing
|
||||
do with Postfix aliases.) The permitted values are those
|
||||
legal for the OpenLDAP/UM LDAP implementations:
|
||||
When to dereference LDAP aliases. (Note that this has nothing
|
||||
do with Postfix aliases.) The permitted values are those legal
|
||||
for the OpenLDAP/UM LDAP implementations:
|
||||
|
||||
0 never
|
||||
1 when searching
|
||||
|
81
postfix/README_FILES/SMTPD_PROXY_README
Normal file
81
postfix/README_FILES/SMTPD_PROXY_README
Normal file
@ -0,0 +1,81 @@
|
||||
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.
|
||||
|
||||
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 feature is meant to be used as follows:
|
||||
|
||||
Internet -> smtpd -> proxy -> smtpd -> cleanup -> queue
|
||||
Postfix Postfix Postfix Postfix
|
||||
|
||||
Limitations
|
||||
===========
|
||||
|
||||
When used with a real-time SPAM filter, this approach allows Postfix
|
||||
to reject mail before the SMTP mail transfer completes, so that
|
||||
Postfix does not have to send rejected mail back to the sender.
|
||||
Mail that is not accepted remains the responsibility of the client.
|
||||
|
||||
In all other respects this content filtering approach is inferior
|
||||
to the existing content filter (see FILTER_README) which processes
|
||||
mail AFTER it is queued, because that gives you full control over
|
||||
how many filtering processes can be run in parallel.
|
||||
|
||||
The problem with real-time content filtering is that the remote
|
||||
SMTP client expects an SMTP reply within a deadline. As the system
|
||||
load increases, fewer and fewer CPU cycles remain available to
|
||||
answer within the deadline, and eventually you either have to stop
|
||||
accepting mail or you have to accept unfiltered mail.
|
||||
|
||||
A possible workaround is to have the proxy take special action when
|
||||
the deadline is reached: add a distinctive message header that
|
||||
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.
|
||||
|
||||
Configuration parameters
|
||||
========================
|
||||
|
||||
Parameters that control proxying:
|
||||
|
||||
smtpd_proxy_filter (syntax: host:port)
|
||||
|
||||
The host and TCP port of the SMTP proxy server. When no host
|
||||
or host: is specified, localhost is assumed.
|
||||
|
||||
smtpd_proxy_timeout (default: 100s)
|
||||
|
||||
Timeout for connecting to the SMTP proxy server and for sending
|
||||
and receiving data. All proxy errors are logged to the maillog
|
||||
file, but the client sees "451 Error: queue file write error".
|
||||
|
||||
smtpd_proxy_ehlo (default: $myhostname)
|
||||
|
||||
The hostname to use when sending an EHLO command to the SMTP
|
||||
proxy server.
|
||||
|
||||
Testing the SMTP pass-through proxy feature
|
||||
===========================================
|
||||
|
||||
The following example sets up a null proxy, that is, the Postfix
|
||||
SMTP server gives the mail directly to another Postfix SMTP server
|
||||
process.
|
||||
|
||||
/etc/postfix/master.cf
|
||||
smtp inet n - n - - smtpd
|
||||
-o smtpd_proxy_filter=26
|
||||
26 inet n - n - - smtpd
|
||||
|
||||
The result is as follows:
|
||||
|
||||
Internet -> smtpd on port 25 -> smtpd on port 26 -> cleanup -> queue
|
||||
|
||||
This configuration is sufficient for stress testing.
|
@ -8,7 +8,7 @@ Purpose of this software
|
||||
You can use the virtual delivery agent for mailbox delivery of some
|
||||
or all domains that are handled by a machine.
|
||||
|
||||
This mechanism is different from simulated virtual domains. Those
|
||||
This mechanism is different from virtual alias domains. Those
|
||||
are implemented by translating every recipient address into a
|
||||
different address. For that, see the virtual(5) manual page.
|
||||
|
||||
|
@ -22,6 +22,51 @@ 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.
|
||||
|
||||
Incompatible changes with Postfix snapshot 2.0.13-20030702
|
||||
==========================================================
|
||||
|
||||
Support for client side LDAP caching is gone. OpenLDAP 2.1.13 and
|
||||
later no longer support it, and the feature never worked well.
|
||||
Postfix now ignores cache controlling parameters in an LDAP
|
||||
configuration file and logs a warning. Credits to Victor Duchovni
|
||||
and Lamont Jones.
|
||||
|
||||
Major changes with Postfix snapshot 2.0.13-20030702
|
||||
===================================================
|
||||
|
||||
The Postfix SMTP server can be configured to send all mail into a
|
||||
proxy server, for example a real-time SPAM filter. This proxy is
|
||||
expected to send the mail into another Postfix SMTP server process
|
||||
for normal delivery. See the SMTPD_PROXY_README file for details.
|
||||
|
||||
Improved LDAP client robustness. Given suitable invalid database
|
||||
contents, LDAP lookups can produce too many results, enter an
|
||||
infinite loop in the expansion of "special result attributes" (LDAP
|
||||
DNs and LDAP URLs) or can simply consume excessive server resources.
|
||||
Credits to Victor Duchovni and Lamont Jones.
|
||||
|
||||
New CIDR-based lookup table, remotely based on code by Jozsef
|
||||
Kadlecsik. For details and examples, see "man cidr_table".
|
||||
|
||||
The TCP-based client-server table lookup protocol is finished.
|
||||
For details and examples, see "man tcp_table". This will allow you
|
||||
to implement your own greylisting.
|
||||
|
||||
Support for !/pattern/ (negative matches) in PCRE lookup tables by
|
||||
Victor Duchovni. See "man pcre_table" for more.
|
||||
|
||||
New enable_original_recipient parameter (default: yes) to control
|
||||
whether Postfix keeps track of original recipient address information.
|
||||
If this is turned off Postfix produces no X-Original-To: headers
|
||||
and ignores the original recipient when eliminating duplicates
|
||||
after virtual alias expansion. Code by Victor Duchovni.
|
||||
|
||||
Finer control over how long the SMTP server waits for address
|
||||
verification probes to complete. address_verify_poll_{count,delay}
|
||||
control how often to query the verify server and how long to wait
|
||||
between queries. Specify address_verify_poll_count=1 to implement
|
||||
a crude form of greylisting.
|
||||
|
||||
Major changes with Postfix snapshot 2.0.11-20030611
|
||||
===================================================
|
||||
|
||||
|
@ -108,72 +108,75 @@
|
||||
# A network address is a sequence of one or more
|
||||
# octets separated by ".".
|
||||
#
|
||||
# NOTE: use the cidr lookup table type if you want to
|
||||
# specify arbitrary network blocks.
|
||||
#
|
||||
# ACTIONS
|
||||
# [45]NN text
|
||||
# Reject the address etc. that matches the pattern,
|
||||
# Reject the address etc. that matches the pattern,
|
||||
# and respond with the numerical code and text.
|
||||
#
|
||||
# REJECT
|
||||
#
|
||||
# REJECT optional text...
|
||||
# Reject the address etc. that matches the pattern.
|
||||
# Reply with $reject_code optional text... when the
|
||||
# optional text is specified, otherwise reply with a
|
||||
# Reject the address etc. that matches the pattern.
|
||||
# Reply with $reject_code optional text... when the
|
||||
# optional text is specified, otherwise reply with a
|
||||
# generic error response message.
|
||||
#
|
||||
# OK Accept the address etc. that matches the pattern.
|
||||
#
|
||||
# all-numerical
|
||||
# An all-numerical result is treated as OK. This for-
|
||||
# mat is generated by address-based relay authoriza-
|
||||
# mat is generated by address-based relay authoriza-
|
||||
# tion schemes.
|
||||
#
|
||||
# DUNNO Pretend that the lookup key was not found in this
|
||||
# DUNNO Pretend that the lookup key was not found in this
|
||||
# table. This prevents Postfix from trying substrings
|
||||
# of the lookup key (such as a subdomain name, or a
|
||||
# of the lookup key (such as a subdomain name, or a
|
||||
# network address subnetwork).
|
||||
#
|
||||
# HOLD
|
||||
#
|
||||
# HOLD optional text...
|
||||
# Place the message on the hold queue, where it will
|
||||
# sit until someone either deletes it or releases it
|
||||
# for delivery. Log the optional text if specified,
|
||||
# Place the message on the hold queue, where it will
|
||||
# sit until someone either deletes it or releases it
|
||||
# for delivery. Log the optional text if specified,
|
||||
# otherwise log a generic message.
|
||||
#
|
||||
# Mail that is placed on hold can be examined with
|
||||
# the postcat(1) command, and can be destroyed or
|
||||
# Mail that is placed on hold can be examined with
|
||||
# the postcat(1) command, and can be destroyed or
|
||||
# released with the postsuper(1) command.
|
||||
#
|
||||
# Note: this action currently affects all recipients
|
||||
# Note: this action currently affects all recipients
|
||||
# of the message.
|
||||
#
|
||||
# DISCARD
|
||||
#
|
||||
# DISCARD optional text...
|
||||
# Claim successful delivery and silently discard the
|
||||
# message. Log the optional text if specified, oth-
|
||||
# Claim successful delivery and silently discard the
|
||||
# message. Log the optional text if specified, oth-
|
||||
# erwise log a generic message.
|
||||
#
|
||||
# Note: this action currently affects all recipients
|
||||
# Note: this action currently affects all recipients
|
||||
# of the message.
|
||||
#
|
||||
# FILTER transport:destination
|
||||
# After the message is queued, send the entire mes-
|
||||
# sage through a content filter. More information
|
||||
# After the message is queued, send the entire mes-
|
||||
# sage through a content filter. More information
|
||||
# about content filters is in the Postfix FIL-
|
||||
# TER_README file.
|
||||
#
|
||||
# Note: this action overrides the main.cf con-
|
||||
# Note: this action overrides the main.cf con-
|
||||
# tent_filter setting, and currently affects all
|
||||
# recipients of the message.
|
||||
#
|
||||
# REDIRECT user@domain
|
||||
# After the message is queued, send the message to
|
||||
# After the message is queued, send the message to
|
||||
# the specified address instead of the intended
|
||||
# recipient(s).
|
||||
#
|
||||
# Note: this action overrides the FILTER action, and
|
||||
# Note: this action overrides the FILTER action, and
|
||||
# currently affects all recipients of the message.
|
||||
#
|
||||
# restriction...
|
||||
@ -181,39 +184,40 @@
|
||||
# reject_unauth_destination, and so on).
|
||||
#
|
||||
# REGULAR EXPRESSION TABLES
|
||||
# This section describes how the table lookups change when
|
||||
# This section describes how the table lookups change when
|
||||
# the table is given in the form of regular expressions. For
|
||||
# a description of regular expression lookup table syntax,
|
||||
# a description of regular expression lookup table syntax,
|
||||
# see regexp_table(5) or pcre_table(5).
|
||||
#
|
||||
# Each pattern is a regular expression that is applied to
|
||||
# Each pattern is a regular expression that is applied to
|
||||
# the entire string being looked up. Depending on the appli-
|
||||
# cation, that string is an entire client hostname, an
|
||||
# cation, that string is an entire client hostname, an
|
||||
# entire client IP address, or an entire mail address. Thus,
|
||||
# no parent domain or parent network search is done,
|
||||
# user@domain mail addresses are not broken up into their
|
||||
# user@domain mail addresses are not broken up into their
|
||||
# user@ and domain constituent parts, nor is user+foo broken
|
||||
# up into user and foo.
|
||||
#
|
||||
# Patterns are applied in the order as specified in the
|
||||
# table, until a pattern is found that matches the search
|
||||
# Patterns are applied in the order as specified in the
|
||||
# table, until a pattern is found that matches the search
|
||||
# string.
|
||||
#
|
||||
# Actions are the same as with indexed file lookups, with
|
||||
# the additional feature that parenthesized substrings from
|
||||
# Actions are the same as with indexed file lookups, with
|
||||
# the additional feature that parenthesized substrings from
|
||||
# the pattern can be interpolated as $1, $2 and so on.
|
||||
#
|
||||
# BUGS
|
||||
# The table format does not understand quoting conventions.
|
||||
# The table format does not understand quoting conventions.
|
||||
#
|
||||
# SEE ALSO
|
||||
# postmap(1) create mapping table
|
||||
# postmap(1) create lookup table
|
||||
# smtpd(8) smtp server
|
||||
# cidr_table(5) format of CIDR tables
|
||||
# pcre_table(5) format of PCRE tables
|
||||
# regexp_table(5) format of POSIX regular expression tables
|
||||
#
|
||||
# LICENSE
|
||||
# The Secure Mailer license must be distributed with this
|
||||
# The Secure Mailer license must be distributed with this
|
||||
# software.
|
||||
#
|
||||
# AUTHOR(S)
|
||||
|
77
postfix/conf/cidr_table
Normal file
77
postfix/conf/cidr_table
Normal file
@ -0,0 +1,77 @@
|
||||
# CIDR_TABLE(5) CIDR_TABLE(5)
|
||||
#
|
||||
# NAME
|
||||
# cidr_table - format of Postfix CIDR tables
|
||||
#
|
||||
# SYNOPSIS
|
||||
# postmap -q "string" cidr:/etc/postfix/filename
|
||||
#
|
||||
# postmap -q - cidr:/etc/postfix/filename <inputfile
|
||||
#
|
||||
# DESCRIPTION
|
||||
# The Postfix mail system uses optional access control
|
||||
# tables. These tables are usually in dbm or db format.
|
||||
# Alternatively, access control tables can be specified in
|
||||
# CIDR form.
|
||||
#
|
||||
# To find out what types of lookup tables your Postfix sys-
|
||||
# tem supports use the postconf -m command.
|
||||
#
|
||||
# To test lookup tables, use the postmap command as
|
||||
# described in the SYNOPSIS above.
|
||||
#
|
||||
# TABLE FORMAT
|
||||
# The general form of a Postfix CIDR table is:
|
||||
#
|
||||
# network_address/network_mask result
|
||||
# When a search string matches the specified network
|
||||
# block, use the corresponding result value.
|
||||
#
|
||||
# network_address result
|
||||
# When a search string matches the specified network
|
||||
# address, use the corresponding result value.
|
||||
#
|
||||
# blank lines and comments
|
||||
# Empty lines and whitespace-only lines are ignored,
|
||||
# as are lines whose first non-whitespace character
|
||||
# is a `#'.
|
||||
#
|
||||
# multi-line text
|
||||
# A logical line starts with non-whitespace text. A
|
||||
# line that starts with whitespace continues a logi-
|
||||
# cal line.
|
||||
#
|
||||
# Patterns are applied in the order as specified in the
|
||||
# table, until a pattern is found that matches the search
|
||||
# string.
|
||||
#
|
||||
# EXAMPLE SMTPD ACCESS MAP
|
||||
# /etc/postfix/main.cf:
|
||||
# smtpd_client_restrictions = ... cidr:/etc/postfix/client_cidr ...
|
||||
#
|
||||
# /etc/postfix/client_cidr:
|
||||
# # Rule order matters. Put more specific whitelist entries
|
||||
# # before more general blacklist entries.
|
||||
# 192.168.1.1 OK
|
||||
# 192.168.0.0/16 REJECT
|
||||
#
|
||||
# SEE ALSO
|
||||
# regexp_table(5) format of regular expression tables
|
||||
# pcre_table(5) format of PCRE tables
|
||||
# tcp_table(5) TCP client/server table lookup protocol
|
||||
#
|
||||
# AUTHOR(S)
|
||||
# The CIDR table lookup code was originally written by:
|
||||
# Jozsef Kadlecsik
|
||||
# kadlec@blackhole.kfki.hu
|
||||
# KFKI Research Institute for Particle and Nuclear Physics
|
||||
# POB. 49
|
||||
# 1525 Budapest, Hungary
|
||||
#
|
||||
# Adopted and adapted by:
|
||||
# Wietse Venema
|
||||
# IBM T.J. Watson Research
|
||||
# P.O. Box 704
|
||||
# Yorktown Heights, NY 10598, USA
|
||||
#
|
||||
# CIDR_TABLE(5)
|
@ -4,8 +4,6 @@
|
||||
# pcre_table - format of Postfix PCRE tables
|
||||
#
|
||||
# SYNOPSIS
|
||||
# pcre:/etc/postfix/filename
|
||||
#
|
||||
# postmap -q "string" pcre:/etc/postfix/filename
|
||||
#
|
||||
# postmap -q - pcre:/etc/postfix/filename <inputfile
|
||||
@ -25,8 +23,10 @@
|
||||
# The general form of a PCRE table is:
|
||||
#
|
||||
# /pattern/flags result
|
||||
# When pattern matches a search string, use the cor-
|
||||
# responding result value.
|
||||
#
|
||||
# !/pattern/flags result
|
||||
# When pattern matches (does not match) a search
|
||||
# string, use the corresponding result value.
|
||||
#
|
||||
# blank lines and comments
|
||||
# Empty lines and whitespace-only lines are ignored,
|
||||
@ -40,98 +40,104 @@
|
||||
#
|
||||
# if /pattern/flags
|
||||
#
|
||||
# if !/pattern/flags
|
||||
#
|
||||
# endif Examine the lines between if..endif only if pattern
|
||||
# matches. The if..endif can nest. Do not prepend
|
||||
# whitespace to patterns inside if..endif.
|
||||
# matches (does not match). The if..endif can nest.
|
||||
# Do not prepend whitespace to patterns inside
|
||||
# if..endif.
|
||||
#
|
||||
# Each pattern is a perl-like regular expression. The
|
||||
# expression delimiter can be any character, except whites-
|
||||
# pace or characters that have special meaning (tradition-
|
||||
# ally the forward slash is used). The regular expression
|
||||
# expression delimiter can be any character, except whites-
|
||||
# pace or characters that have special meaning (tradition-
|
||||
# ally the forward slash is used). The regular expression
|
||||
# can contain whitespace.
|
||||
#
|
||||
# By default, matching is case-insensitive, and newlines are
|
||||
# not treated as special characters. The behavior is con-
|
||||
# trolled by flags, which are toggled by appending one or
|
||||
# not treated as special characters. The behavior is con-
|
||||
# trolled by flags, which are toggled by appending one or
|
||||
# more of the following characters after the pattern:
|
||||
#
|
||||
# i (default: on)
|
||||
# Toggles the case sensitivity flag. By default,
|
||||
# Toggles the case sensitivity flag. By default,
|
||||
# matching is case insensitive.
|
||||
#
|
||||
# m (default: off)
|
||||
# Toggles the PCRE_MULTILINE flag. When this flag is
|
||||
# on, the ^ and $ metacharacters match immediately
|
||||
# after and immediately before a newline character,
|
||||
# respectively, in addition to matching at the start
|
||||
# Toggles the PCRE_MULTILINE flag. When this flag is
|
||||
# on, the ^ and $ metacharacters match immediately
|
||||
# after and immediately before a newline character,
|
||||
# respectively, in addition to matching at the start
|
||||
# and end of the subject string.
|
||||
#
|
||||
# s (default: on)
|
||||
# Toggles the PCRE_DOTALL flag. When this flag is on,
|
||||
# the . metacharacter matches the newline character.
|
||||
# With Postfix versions prior to 20020528, The flag
|
||||
# With Postfix versions prior to 20020528, The flag
|
||||
# is off by default, which is inconvenient for multi-
|
||||
# line message header matching.
|
||||
#
|
||||
# x (default: off)
|
||||
# Toggles the pcre extended flag. When this flag is
|
||||
# on, whitespace in the pattern (other than in a
|
||||
# Toggles the pcre extended flag. When this flag is
|
||||
# on, whitespace in the pattern (other than in a
|
||||
# character class) and characters between a # outside
|
||||
# a character class and the next newline character
|
||||
# are ignored. An escaping backslash can be used to
|
||||
# include a whitespace or # character as part of the
|
||||
# a character class and the next newline character
|
||||
# are ignored. An escaping backslash can be used to
|
||||
# include a whitespace or # character as part of the
|
||||
# pattern.
|
||||
#
|
||||
# A (default: off)
|
||||
# Toggles the PCRE_ANCHORED flag. When this flag is
|
||||
# on, the pattern is forced to be "anchored", that
|
||||
# Toggles the PCRE_ANCHORED flag. When this flag is
|
||||
# on, the pattern is forced to be "anchored", that
|
||||
# is, it is constrained to match only at the start of
|
||||
# the string which is being searched (the "subject
|
||||
# string"). This effect can also be achieved by
|
||||
# the string which is being searched (the "subject
|
||||
# string"). This effect can also be achieved by
|
||||
# appropriate constructs in the pattern itself.
|
||||
#
|
||||
# E (default: off)
|
||||
# Toggles the PCRE_DOLLAR_ENDONLY flag. When this
|
||||
# flag is on, a $ metacharacter in the pattern
|
||||
# matches only at the end of the subject string.
|
||||
# Without this flag, a dollar also matches immedi-
|
||||
# Toggles the PCRE_DOLLAR_ENDONLY flag. When this
|
||||
# flag is on, a $ metacharacter in the pattern
|
||||
# matches only at the end of the subject string.
|
||||
# Without this flag, a dollar also matches immedi-
|
||||
# ately before the final character if it is a newline
|
||||
# character (but not before any other newline charac-
|
||||
# ters). This flag is ignored if PCRE_MULTILINE flag
|
||||
# ters). This flag is ignored if PCRE_MULTILINE flag
|
||||
# is set.
|
||||
#
|
||||
# U (default: off)
|
||||
# Toggles the ungreedy matching flag. When this flag
|
||||
# is on, the pattern matching engine inverts the
|
||||
# "greediness" of the quantifiers so that they are
|
||||
# not greedy by default, but become greedy if fol-
|
||||
# lowed by "?". This flag can also set by a (?U)
|
||||
# is on, the pattern matching engine inverts the
|
||||
# "greediness" of the quantifiers so that they are
|
||||
# not greedy by default, but become greedy if fol-
|
||||
# lowed by "?". This flag can also set by a (?U)
|
||||
# modifier within the pattern.
|
||||
#
|
||||
# X (default: off)
|
||||
# Toggles the PCRE_EXTRA flag. When this flag is on,
|
||||
# any backslash in a pattern that is followed by a
|
||||
# any backslash in a pattern that is followed by a
|
||||
# letter that has no special meaning causes an error,
|
||||
# thus reserving these combinations for future expan-
|
||||
# sion.
|
||||
#
|
||||
# Each pattern is applied to the entire lookup key string.
|
||||
# Depending on the application, that string is an entire
|
||||
# Each pattern is applied to the entire lookup key string.
|
||||
# Depending on the application, that string is an entire
|
||||
# client hostname, an entire client IP address, or an entire
|
||||
# mail address. Thus, no parent domain or parent network
|
||||
# search is done, and user@domain mail addresses are not
|
||||
# broken up into their user and domain constituent parts,
|
||||
# mail address. Thus, no parent domain or parent network
|
||||
# search is done, and user@domain mail addresses are not
|
||||
# broken up into their user and domain constituent parts,
|
||||
# nor is user+foo broken up into user and foo.
|
||||
#
|
||||
# Patterns are applied in the order as specified in the
|
||||
# table, until a pattern is found that matches the search
|
||||
# Patterns are applied in the order as specified in the
|
||||
# table, until a pattern is found that matches the search
|
||||
# string.
|
||||
#
|
||||
# Substitution of substrings from the matched expression
|
||||
# into the result string is possible using the conventional
|
||||
# perl syntax ($1, $2, etc.). The macros in the result
|
||||
# string may need to be written as ${n} or $(n) if they
|
||||
# aren't followed by whitespace.
|
||||
# Substitution of substrings from the matched expression
|
||||
# into the result string is possible using the conventional
|
||||
# perl syntax ($1, $2, etc.). The macros in the result
|
||||
# string may need to be written as ${n} or $(n) if they
|
||||
# aren't followed by whitespace. Since negated patterns
|
||||
# (those preceded by !) return a result when the expression
|
||||
# does not match, substitutions are not available for
|
||||
# negated patterns.
|
||||
#
|
||||
# EXAMPLE SMTPD ACCESS MAP
|
||||
# # Protect your outgoing majordomo exploders
|
||||
@ -160,6 +166,8 @@
|
||||
#
|
||||
# SEE ALSO
|
||||
# regexp_table(5) format of POSIX regular expression tables
|
||||
# cidr_table(5) format of CIDR tables
|
||||
# tcp_table(5) TCP client/server table lookup protocol
|
||||
#
|
||||
# AUTHOR(S)
|
||||
# The PCRE table lookup code was originally written by:
|
||||
|
@ -92,6 +92,7 @@ $config_directory/LICENSE:f:root:-:644
|
||||
$config_directory/access:f:root:-:644:p
|
||||
$config_directory/aliases:f:root:-:644:p
|
||||
$config_directory/canonical:f:root:-:644:p
|
||||
$config_directory/cidr_table:f:root:-:644:p
|
||||
$config_directory/main.cf:f:root:-:644:p
|
||||
$config_directory/main.cf.default:f:root:-:644
|
||||
$config_directory/makedefs.out:f:root:-:644
|
||||
@ -100,6 +101,7 @@ $config_directory/pcre_table:f:root:-:644:p
|
||||
$config_directory/postfix-files:f:root:-:644
|
||||
$config_directory/regexp_table:f:root:-:644:p
|
||||
$config_directory/relocated:f:root:-:644:p
|
||||
$config_directory/tcp_table:f:root:-:644:p
|
||||
$config_directory/transport:f:root:-:644:p
|
||||
$config_directory/virtual:f:root:-:644:p
|
||||
$config_directory/postfix-script:f:root:-:755
|
||||
@ -121,9 +123,11 @@ $manpage_directory/man1/sendmail.1:f:root:-:644
|
||||
$manpage_directory/man5/access.5:f:root:-:644
|
||||
$manpage_directory/man5/aliases.5:f:root:-:644
|
||||
$manpage_directory/man5/canonical.5:f:root:-:644
|
||||
$manpage_directory/man5/cidr_table.5:f:root:-:644
|
||||
$manpage_directory/man5/pcre_table.5:f:root:-:644
|
||||
$manpage_directory/man5/regexp_table.5:f:root:-:644
|
||||
$manpage_directory/man5/relocated.5:f:root:-:644
|
||||
$manpage_directory/man5/tcp_table.5:f:root:-:644
|
||||
$manpage_directory/man5/transport.5:f:root:-:644
|
||||
$manpage_directory/man5/virtual.5:f:root:-:644
|
||||
$manpage_directory/man8/bounce.8:f:root:-:644
|
||||
|
@ -181,7 +181,7 @@ check)
|
||||
|
||||
find $command_directory/postqueue $command_directory/postdrop \
|
||||
-prune ! -perm -02111 \
|
||||
-exec $WARN not set-gid: {} \;
|
||||
-exec $WARN not set-gid or not owner+group+world executable: {} \;
|
||||
|
||||
for name in `ls -d $queue_directory/* | \
|
||||
egrep '/(bin|etc|lib|usr)$'` ; \
|
||||
|
@ -4,8 +4,6 @@
|
||||
# regexp_table - format of Postfix regular expression tables
|
||||
#
|
||||
# SYNOPSIS
|
||||
# regexp:/etc/postfix/filename
|
||||
#
|
||||
# postmap -q "string" regexp:/etc/postfix/filename
|
||||
#
|
||||
# postmap -q - regexp:/etc/postfix/filename <inputfile
|
||||
@ -77,7 +75,10 @@
|
||||
# Substitution of substrings from the matched expression
|
||||
# into the result string is possible using $1, $2, etc.. The
|
||||
# macros in the result string may need to be written as ${n}
|
||||
# or $(n) if they aren't followed by whitespace.
|
||||
# or $(n) if they aren't followed by whitespace. Since
|
||||
# negated patterns (those preceded by !) return a result
|
||||
# when the expression does not match, substitutions are not
|
||||
# available for negated patterns.
|
||||
#
|
||||
# EXAMPLE SMTPD ACCESS MAP
|
||||
# # Disallow sender-specified routing. This is a must if you relay mail
|
||||
@ -106,6 +107,8 @@
|
||||
#
|
||||
# SEE ALSO
|
||||
# pcre_table(5) format of PCRE tables
|
||||
# cidr_table(5) format of CIDR tables
|
||||
# tcp_table(5) TCP client/server table lookup protocol
|
||||
#
|
||||
# AUTHOR(S)
|
||||
# The regexp table lookup code was originally written by:
|
||||
|
@ -68,19 +68,40 @@
|
||||
#
|
||||
#ldap_bind_pw =
|
||||
|
||||
# The ldap_cache parameter specifies whether or not to turn on client-side
|
||||
# caching.
|
||||
#ldap_cache (IGNORED with a warning)
|
||||
#ldap_cache_expiry (IGNORED with a warning)
|
||||
#ldap_cache_size (IGNORED with a warning)
|
||||
#
|
||||
#ldap_cache = no
|
||||
# The above parameters are NO LONGER SUPPORTED by Postfix.
|
||||
# Cache support has been dropped from OpenLDAP as of release 2.1.13.
|
||||
|
||||
# The ldap_cache_expiry parameter specifies how many seconds to cache results
|
||||
# for (if ldap_cache=yes)
|
||||
#
|
||||
#ldap_cache_expiry = 30
|
||||
# The ldap_recursion_limit parameter specifies a limit on the nesting
|
||||
# depth of DN and URL special result attribute evaluation. The limit
|
||||
# must be a non-zero positive number. The default value is 1000.
|
||||
#
|
||||
#ldap_recursion_limit = 1000
|
||||
|
||||
# The ldap_cache_size parameter specifies the cache size, in bytes.
|
||||
# The ldap_expansion_limit parameter specifies a limit on the total
|
||||
# number of result elements returned (as a comma separated list) by a lookup
|
||||
# against the map. A setting of 0 disables the limit. Lookups fail with a
|
||||
# temporary error if the limit is exceeded. Setting the limit to 1 ensures
|
||||
# that lookups do not return multiple values. The default value is 0.
|
||||
#
|
||||
#ldap_cache_size = 32768
|
||||
#ldap_expansion_limit = 0
|
||||
|
||||
# The ldap_size_limit parameter specifies a limit on the number of LDAP
|
||||
# entries returned by any single LDAP query performed as part of the
|
||||
# lookup. A setting of 0 disables the limit. Expansion of DN and URL
|
||||
# references involves nested LDAP queries, each of which is separately
|
||||
# subjected to this limit. The default value is $ldap_expansion_limit.
|
||||
#
|
||||
# Note: even a single LDAP entry can generate multiple lookup results, via
|
||||
# multiple result attributes and/or multi-valued result attributes.
|
||||
# This limit caps the per query resource utilization on the LDAP server,
|
||||
# not the final multiplicity of the lookup result. It is analogous to the
|
||||
# "-z" option of "ldapsearch".
|
||||
#
|
||||
#ldap_size_limit = $ldap_expansion_limit
|
||||
|
||||
# The ldap_deference parameter specifies how to handle LDAP aliases. See the
|
||||
# ldap_open(3) man page.
|
||||
|
@ -71,6 +71,18 @@ default_transport = smtp
|
||||
#
|
||||
double_bounce_sender = double-bounce
|
||||
|
||||
# The enable_original_recipient parameter enables support for the
|
||||
# X-Original-To message header, which is needed for multi-recipient
|
||||
# mailboxes. When this parameter is set to yes, the cleanup daemon
|
||||
# performs duplicate elimination on distinct pairs of (original
|
||||
# recipient, rewritten recipient), and generates non-empty original
|
||||
# recipient queue file records. When this parameter is set to no,
|
||||
# the cleanup daemon performs duplicate elimination on the rewritten
|
||||
# recipient address only, and generates empty original recipient
|
||||
# queue file records. The default value is "yes".
|
||||
#
|
||||
enable_original_recipient = yes
|
||||
|
||||
# The export_environment parameter specifies the names of environment
|
||||
# parameters that Postfix will export to non-Postfix processes.
|
||||
#
|
||||
|
@ -215,6 +215,41 @@ smtpd_soft_error_limit = 10
|
||||
#
|
||||
smtpd_hard_error_limit = 20
|
||||
|
||||
#
|
||||
# PASS-THROUGH PROXY OPERATION
|
||||
#
|
||||
|
||||
# The smtpd_proxy_filter parameter specifies the host:port of a proxy
|
||||
# filter, for example a real-time SPAM filter. The proxy receives
|
||||
# all mail from the Postfix SMTP server, and is supposed to give the
|
||||
# result to another Postfix SMTP server process.
|
||||
#
|
||||
# WARNING: the proxy filter must reply within a fixed deadline or
|
||||
# else the remote SMTP client times out and mail duplication happens.
|
||||
# This becomes a problem as mail load increases so that fewer and
|
||||
# fewer CPU cycles remain available to mead the fixed deadline.
|
||||
#
|
||||
# Specify host:port. When no host or host: are specified, the local
|
||||
# machine is assumed.
|
||||
#
|
||||
smtpd_proxy_filter =
|
||||
|
||||
# The smtpd_proxy_timeout parameter specifies a deadline for
|
||||
# connecting to a proxy filter and for sending or receiving information.
|
||||
# When a connection fails the client gets a generic error message
|
||||
# while more detailed information is logged to the maillog file.
|
||||
#
|
||||
# Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
|
||||
# The default time unit is s (seconds).
|
||||
#
|
||||
smtpd_proxy_timeout = 100s
|
||||
|
||||
# The smtpd_proxy_ehlo parameter specifies how the Postfix SMTP
|
||||
# server announces itself to the proxy filter. By default, the
|
||||
# Postfix hostname is used.
|
||||
#
|
||||
smtpd_proxy_ehlo = $myhostname
|
||||
|
||||
#
|
||||
# UCE RESTRICTIONS
|
||||
#
|
||||
|
@ -8,22 +8,6 @@
|
||||
# ADDRESS VERIFICATION (see also: verify(8) and SENDER_VERIFICATION_README)
|
||||
#
|
||||
|
||||
# The address_verify_map configuration parameter specifies an optional
|
||||
# table for persistent recipient status storage. The file is opened
|
||||
# before the process enters a chroot jail and before it drops root
|
||||
# privileges.
|
||||
#
|
||||
# By default, the information is kept in volatile memory, and is lost
|
||||
# after postfix reload or postfix stop.
|
||||
#
|
||||
# Specify a pathname in a file system that will not fill up. If the
|
||||
# database becomes corrupted, the world comes to an end. To recover
|
||||
# you have to delete the file and do "postfix reload".
|
||||
#
|
||||
#address_verify_map = hash:/etc/postfix/verify
|
||||
#address_verify_map = btree:/etc/postfix/verify
|
||||
address_verify_map =
|
||||
|
||||
# The address_verify_sender configuration parameter specifies the
|
||||
# sender address that Postfix will use in address verification probe
|
||||
# messages.
|
||||
@ -38,6 +22,40 @@ address_verify_map =
|
||||
#address_verify_sender = postmaster@my.domain
|
||||
address_verify_sender = postmaster
|
||||
|
||||
# The address_verify_poll_count parameter specifies how many times
|
||||
# to query the address verification service for completion of an
|
||||
# address verification request. Specify 0 to implement a simple form
|
||||
# of greylisting, that is, always defer the first delivery request
|
||||
# from an unknown sender address.
|
||||
#
|
||||
#address_verify_poll_count = 0
|
||||
address_verify_poll_count = 3
|
||||
|
||||
# The address_verify_poll_delay parameter specifies how long to wait
|
||||
# after querying the address verification service for completion of
|
||||
# an address verification request.
|
||||
#
|
||||
address_verify_poll_delay = 3
|
||||
|
||||
#
|
||||
# CACHE CONTROL
|
||||
#
|
||||
# The address_verify_map configuration parameter specifies an optional
|
||||
# table for persistent address status storage. The file is opened
|
||||
# before the process enters a chroot jail and before it drops root
|
||||
# privileges.
|
||||
#
|
||||
# By default, the information is kept in volatile memory, and is lost
|
||||
# after postfix reload or postfix stop.
|
||||
#
|
||||
# Specify a pathname in a file system that will not fill up. If the
|
||||
# database becomes corrupted, the world comes to an end. To recover
|
||||
# you have to delete the file and do "postfix reload".
|
||||
#
|
||||
#address_verify_map = hash:/etc/postfix/verify
|
||||
#address_verify_map = btree:/etc/postfix/verify
|
||||
address_verify_map =
|
||||
|
||||
# The address_verify_positive_expire_time configuration parameter
|
||||
# specifies the amount of time after which a known to be good address
|
||||
# expires.
|
||||
|
85
postfix/conf/tcp_table
Normal file
85
postfix/conf/tcp_table
Normal file
@ -0,0 +1,85 @@
|
||||
# TCP_TABLE(5) TCP_TABLE(5)
|
||||
#
|
||||
# NAME
|
||||
# tcp_table - Postfix client/server table lookup protocol
|
||||
#
|
||||
# SYNOPSIS
|
||||
# postmap -q "string" tcp:host:port
|
||||
#
|
||||
# postmap -q - regexp:host:port <inputfile
|
||||
#
|
||||
# DESCRIPTION
|
||||
# The Postfix mail system uses optional tables for address
|
||||
# rewriting or mail routing. These tables are usually in dbm
|
||||
# or db format. Alternatively, lookup tables can be speci-
|
||||
# fied as a TCP client/server pair.
|
||||
#
|
||||
# To find out what types of lookup tables your Postfix sys-
|
||||
# tem supports use the postconf -m command.
|
||||
#
|
||||
# To test lookup tables, use the postmap command as
|
||||
# described in the SYNOPSIS above.
|
||||
#
|
||||
# PROTOCOL DESCRIPTION
|
||||
# The TCP map class implements a very simple protocol: the
|
||||
# client sends a request, and the server sends one reply.
|
||||
# Requests and replies are sent as one line of ASCII text,
|
||||
# terminated by the ASCII newline character. Request and
|
||||
# reply parameters (see below) are separated by whitespace.
|
||||
#
|
||||
# ENCODING
|
||||
# In request and reply parameters, the character % and any
|
||||
# non-printing and whitespace characters must be replaced by
|
||||
# %XX, XX being the corresponding ASCII hexadecimal charac-
|
||||
# ter value. The hexadecimal codes can be specified in any
|
||||
# case (upper, lower, mixed).
|
||||
#
|
||||
# REQUEST FORMAT
|
||||
# Requests are strings that serve as lookup key in the simu-
|
||||
# lated table.
|
||||
#
|
||||
# get SPACE key NEWLINE
|
||||
# Look up data under the specified key.
|
||||
#
|
||||
# put SPACE key SPACE value NEWLINE
|
||||
# This request is currently not implemented.
|
||||
#
|
||||
# REPLY FORMAT
|
||||
# Replies must be no longer than 4096 characters including
|
||||
# the newline terminator, and must have the following form:
|
||||
#
|
||||
# 500 SPACE optional-text NEWLINE
|
||||
# In case of a lookup request, the requested data
|
||||
# does not exist. In case of an update request, the
|
||||
# request was rejected.
|
||||
#
|
||||
# 400 SPACE optional-text NEWLINE
|
||||
# This indicates an error condition. The text gives
|
||||
# the nature of the problem. The client should retry
|
||||
# the request later.
|
||||
#
|
||||
# 200 SPACE text NEWLINE
|
||||
# The request was successful. In the case of a lookup
|
||||
# request, the text contains an encoded version of
|
||||
# the requested data. Otherwise the text is
|
||||
# optional.
|
||||
#
|
||||
# SEE ALSO
|
||||
# regexp_table(5) format of regular expression tables
|
||||
# pcre_table(5) format of PCRE tables
|
||||
# cidr_table(5) format of CIDR tables
|
||||
#
|
||||
# BUGS
|
||||
# Only the lookup method is currently implemented.
|
||||
#
|
||||
# LICENSE
|
||||
# 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
|
||||
#
|
||||
# TCP_TABLE(5)
|
@ -16,21 +16,40 @@
|
||||
# relay hosts. The mapping is used by the trivial-rewrite(8)
|
||||
# daemon.
|
||||
#
|
||||
# Normally, the transport table is specified as a text file
|
||||
# that serves as input to the postmap(1) command. The
|
||||
# result, an indexed file in dbm or db format, is used for
|
||||
# fast searching by the mail system. Execute the command
|
||||
# postmap /etc/postfix/transport in order to rebuild the
|
||||
# This mapping overrides the default routing that is built
|
||||
# into Postfix:
|
||||
#
|
||||
# mydestination
|
||||
# A list of domains that is by default delivered via
|
||||
# $local_transport.
|
||||
#
|
||||
# virtual_mailbox_domains
|
||||
# A list of domains that is by default delivered via
|
||||
# $virtual_transport.
|
||||
#
|
||||
# relay_domains
|
||||
# A list of domains that is by default delivered via
|
||||
# $relay_transport.
|
||||
#
|
||||
# any other destination
|
||||
# Mail for any other destination is by default deliv-
|
||||
# ered via $default_transport.
|
||||
#
|
||||
# Normally, the transport table is specified as a text file
|
||||
# that serves as input to the postmap(1) command. The
|
||||
# result, an indexed file in dbm or db format, is used for
|
||||
# fast searching by the mail system. Execute the command
|
||||
# postmap /etc/postfix/transport in order to rebuild the
|
||||
# indexed file after changing the transport table.
|
||||
#
|
||||
# When the table is provided via other means such as NIS,
|
||||
# LDAP or SQL, the same lookups are done as for ordinary
|
||||
# When the table is provided via other means such as NIS,
|
||||
# LDAP or SQL, the same lookups are done as for ordinary
|
||||
# indexed files.
|
||||
#
|
||||
# Alternatively, the table can be provided as a regular-
|
||||
# Alternatively, the table can be provided as a regular-
|
||||
# expression map where patterns are given as regular expres-
|
||||
# sions. In that case, the lookups are done in a slightly
|
||||
# different way as described in section "REGULAR EXPRESSION
|
||||
# sions. In that case, the lookups are done in a slightly
|
||||
# different way as described in section "REGULAR EXPRESSION
|
||||
# TABLES".
|
||||
#
|
||||
# TABLE FORMAT
|
||||
@ -41,28 +60,28 @@
|
||||
# domain, use the corresponding result.
|
||||
#
|
||||
# blank lines and comments
|
||||
# Empty lines and whitespace-only lines are ignored,
|
||||
# as are lines whose first non-whitespace character
|
||||
# Empty lines and whitespace-only lines are ignored,
|
||||
# as are lines whose first non-whitespace character
|
||||
# is a `#'.
|
||||
#
|
||||
# multi-line text
|
||||
# A logical line starts with non-whitespace text. A
|
||||
# line that starts with whitespace continues a logi-
|
||||
# A logical line starts with non-whitespace text. A
|
||||
# line that starts with whitespace continues a logi-
|
||||
# cal line.
|
||||
#
|
||||
# The pattern specifies an email address, a domain name, or
|
||||
# a domain name hierarchy, as described in section "TABLE
|
||||
# The pattern specifies an email address, a domain name, or
|
||||
# a domain name hierarchy, as described in section "TABLE
|
||||
# LOOKUP".
|
||||
#
|
||||
# The result is of the form transport:nexthop. The trans-
|
||||
# port field specifies a mail delivery transport such as
|
||||
# smtp or local. The nexthop field specifies where and how
|
||||
# The result is of the form transport:nexthop. The trans-
|
||||
# port field specifies a mail delivery transport such as
|
||||
# smtp or local. The nexthop field specifies where and how
|
||||
# to deliver mail. More details are given in section "RESULT
|
||||
# FORMAT".
|
||||
#
|
||||
# TABLE LOOKUP
|
||||
# With lookups from indexed files such as DB or DBM, or from
|
||||
# networked tables such as NIS, LDAP or SQL, patterns are
|
||||
# networked tables such as NIS, LDAP or SQL, patterns are
|
||||
# tried in the order as listed below:
|
||||
#
|
||||
# user+extension@domain transport:nexthop
|
||||
@ -74,134 +93,134 @@
|
||||
# to nexthop.
|
||||
#
|
||||
# domain transport:nexthop
|
||||
# Mail for domain is delivered through transport to
|
||||
# Mail for domain is delivered through transport to
|
||||
# nexthop.
|
||||
#
|
||||
# .domain transport:nexthop
|
||||
# Mail for any subdomain of domain is delivered
|
||||
# through transport to nexthop. This applies only
|
||||
# Mail for any subdomain of domain is delivered
|
||||
# through transport to nexthop. This applies only
|
||||
# when the string transport_maps is not listed in the
|
||||
# parent_domain_matches_subdomains configuration set-
|
||||
# ting. Otherwise, a domain name matches itself and
|
||||
# ting. Otherwise, a domain name matches itself and
|
||||
# its subdomains.
|
||||
#
|
||||
# Note 1: the special pattern * represents any address (i.e.
|
||||
# it functions as the wild-card pattern).
|
||||
#
|
||||
# Note 2: the null recipient address is looked up as
|
||||
# Note 2: the null recipient address is looked up as
|
||||
# $empty_address_recipient@$myhostname (default: mailer-dae-
|
||||
# mon@hostname).
|
||||
#
|
||||
# RESULT FORMAT
|
||||
# The transport field specifies the name of a mail delivery
|
||||
# The transport field specifies the name of a mail delivery
|
||||
# transport (the first name of a mail delivery service entry
|
||||
# in the Postfix master.cf file).
|
||||
#
|
||||
# The interpretation of the nexthop field is transport
|
||||
# The interpretation of the nexthop field is transport
|
||||
# dependent. In the case of SMTP, specify host:service for a
|
||||
# non-default server port, and use [host] or [host]:port in
|
||||
# order to disable MX (mail exchanger) DNS lookups. The []
|
||||
# non-default server port, and use [host] or [host]:port in
|
||||
# order to disable MX (mail exchanger) DNS lookups. The []
|
||||
# form is required when you specify an IP address instead of
|
||||
# a hostname.
|
||||
#
|
||||
# A null transport and null nexthop result means "do not
|
||||
# change": use the delivery transport and nexthop informa-
|
||||
# tion that would be used when the entire transport table
|
||||
# A null transport and null nexthop result means "do not
|
||||
# change": use the delivery transport and nexthop informa-
|
||||
# tion that would be used when the entire transport table
|
||||
# did not exist.
|
||||
#
|
||||
# A non-null transport field with a null nexthop field
|
||||
# A non-null transport field with a null nexthop field
|
||||
# resets the nexthop information to the recipient domain.
|
||||
#
|
||||
# A null transport field with non-null nexthop field does
|
||||
# A null transport field with non-null nexthop field does
|
||||
# not modify the transport information.
|
||||
#
|
||||
# EXAMPLES
|
||||
# In order to deliver internal mail directly, while using a
|
||||
# mail relay for all other mail, specify a null entry for
|
||||
# internal destinations (do not change the delivery trans-
|
||||
# port or the nexthop information) and specify a wildcard
|
||||
# In order to deliver internal mail directly, while using a
|
||||
# mail relay for all other mail, specify a null entry for
|
||||
# internal destinations (do not change the delivery trans-
|
||||
# port or the nexthop information) and specify a wildcard
|
||||
# for all other destinations.
|
||||
#
|
||||
# my.domain :
|
||||
# .my.domain :
|
||||
# * smtp:outbound-relay.my.domain
|
||||
#
|
||||
# In order to send mail for foo.org and its subdomains via
|
||||
# In order to send mail for foo.org and its subdomains via
|
||||
# the uucp transport to the UUCP host named foo:
|
||||
#
|
||||
# foo.org uucp:foo
|
||||
# .foo.org uucp:foo
|
||||
#
|
||||
# When no nexthop host name is specified, the destination
|
||||
# domain name is used instead. For example, the following
|
||||
# directs mail for user@foo.org via the slow transport to a
|
||||
# mail exchanger for foo.org. The slow transport could be
|
||||
# something that runs at most one delivery process at a
|
||||
# When no nexthop host name is specified, the destination
|
||||
# domain name is used instead. For example, the following
|
||||
# directs mail for user@foo.org via the slow transport to a
|
||||
# mail exchanger for foo.org. The slow transport could be
|
||||
# something that runs at most one delivery process at a
|
||||
# time:
|
||||
#
|
||||
# foo.org slow:
|
||||
#
|
||||
# When no transport is specified, Postfix uses the transport
|
||||
# that matches the address domain class (see TRANSPORT FIELD
|
||||
# discussion above). The following sends all mail for
|
||||
# discussion above). The following sends all mail for
|
||||
# foo.org and its subdomains to host gateway.foo.org:
|
||||
#
|
||||
# foo.org :[gateway.foo.org]
|
||||
# .foo.org :[gateway.foo.org]
|
||||
#
|
||||
# In the above example, the [] are used to suppress MX
|
||||
# lookups. The result would likely point to your local
|
||||
# In the above example, the [] are used to suppress MX
|
||||
# lookups. The result would likely point to your local
|
||||
# machine.
|
||||
#
|
||||
# In the case of delivery via SMTP, one may specify host-
|
||||
# In the case of delivery via SMTP, one may specify host-
|
||||
# name:service instead of just a host:
|
||||
#
|
||||
# foo.org smtp:bar.org:2025
|
||||
#
|
||||
# This directs mail for user@foo.org to host bar.org port
|
||||
# 2025. Instead of a numerical port a symbolic name may be
|
||||
# used. Specify [] around the hostname in order to disable
|
||||
# This directs mail for user@foo.org to host bar.org port
|
||||
# 2025. Instead of a numerical port a symbolic name may be
|
||||
# used. Specify [] around the hostname in order to disable
|
||||
# MX lookups.
|
||||
#
|
||||
# The error mailer can be used to bounce mail:
|
||||
#
|
||||
# .foo.org error:mail for *.foo.org is not deliv-
|
||||
# .foo.org error:mail for *.foo.org is not deliv-
|
||||
# erable
|
||||
#
|
||||
# This causes all mail for user@anything.foo.org to be
|
||||
# This causes all mail for user@anything.foo.org to be
|
||||
# bounced.
|
||||
#
|
||||
# REGULAR EXPRESSION TABLES
|
||||
# This section describes how the table lookups change when
|
||||
# This section describes how the table lookups change when
|
||||
# the table is given in the form of regular expressions. For
|
||||
# a description of regular expression lookup table syntax,
|
||||
# a description of regular expression lookup table syntax,
|
||||
# see regexp_table(5) or pcre_table(5).
|
||||
#
|
||||
# Each pattern is a regular expression that is applied to
|
||||
# Each pattern is a regular expression that is applied to
|
||||
# the entire domain being looked up. Thus, some.domain.hier-
|
||||
# archy is not broken up into parent domains.
|
||||
#
|
||||
# Patterns are applied in the order as specified in the
|
||||
# table, until a pattern is found that matches the search
|
||||
# Patterns are applied in the order as specified in the
|
||||
# table, until a pattern is found that matches the search
|
||||
# string.
|
||||
#
|
||||
# Results are the same as with indexed file lookups, with
|
||||
# the additional feature that parenthesized substrings from
|
||||
# Results are the same as with indexed file lookups, with
|
||||
# the additional feature that parenthesized substrings from
|
||||
# the pattern can be interpolated as $1, $2 and so on.
|
||||
#
|
||||
# CONFIGURATION PARAMETERS
|
||||
# The following main.cf parameters are especially relevant
|
||||
# to this topic. See the Postfix main.cf file for syntax
|
||||
# details and for default values. Use the postfix reload
|
||||
# The following main.cf parameters are especially relevant
|
||||
# to this topic. See the Postfix main.cf file for syntax
|
||||
# details and for default values. Use the postfix reload
|
||||
# command after a configuration change.
|
||||
#
|
||||
# empty_address_recipient
|
||||
# The address that is looked up instead of the null
|
||||
# The address that is looked up instead of the null
|
||||
# sender address.
|
||||
#
|
||||
# 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).
|
||||
#
|
||||
# transport_maps
|
||||
@ -214,7 +233,7 @@
|
||||
# regexp_table(5) format of POSIX regular expression tables
|
||||
#
|
||||
# LICENSE
|
||||
# The Secure Mailer license must be distributed with this
|
||||
# The Secure Mailer license must be distributed with this
|
||||
# software.
|
||||
#
|
||||
# AUTHOR(S)
|
||||
|
@ -109,72 +109,75 @@ ACCESS(5) ACCESS(5)
|
||||
A network address is a sequence of one or more
|
||||
octets separated by ".".
|
||||
|
||||
NOTE: use the <b>cidr</b> lookup table type if you want to
|
||||
specify arbitrary network blocks.
|
||||
|
||||
<b>ACTIONS</b>
|
||||
[<b>45</b>]<i>NN</i> <i>text</i>
|
||||
Reject the address etc. that matches the pattern,
|
||||
Reject the address etc. that matches the pattern,
|
||||
and respond with the numerical code and text.
|
||||
|
||||
<b>REJECT</b>
|
||||
|
||||
<b>REJECT</b> <i>optional</i> <i>text...</i>
|
||||
Reject the address etc. that matches the pattern.
|
||||
Reply with <i>$reject_code</i> <i>optional</i> <i>text...</i> when the
|
||||
optional text is specified, otherwise reply with a
|
||||
Reject the address etc. that matches the pattern.
|
||||
Reply with <i>$reject_code</i> <i>optional</i> <i>text...</i> when the
|
||||
optional text is specified, otherwise reply with a
|
||||
generic error response message.
|
||||
|
||||
<b>OK</b> Accept the address etc. that matches the pattern.
|
||||
|
||||
<i>all-numerical</i>
|
||||
An all-numerical result is treated as OK. This for-
|
||||
mat is generated by address-based relay authoriza-
|
||||
mat is generated by address-based relay authoriza-
|
||||
tion schemes.
|
||||
|
||||
<b>DUNNO</b> Pretend that the lookup key was not found in this
|
||||
<b>DUNNO</b> Pretend that the lookup key was not found in this
|
||||
table. This prevents Postfix from trying substrings
|
||||
of the lookup key (such as a subdomain name, or a
|
||||
of the lookup key (such as a subdomain name, or a
|
||||
network address subnetwork).
|
||||
|
||||
<b>HOLD</b>
|
||||
|
||||
<b>HOLD</b> <i>optional</i> <i>text...</i>
|
||||
Place the message on the <b>hold</b> queue, where it will
|
||||
sit until someone either deletes it or releases it
|
||||
for delivery. Log the optional text if specified,
|
||||
Place the message on the <b>hold</b> queue, where it will
|
||||
sit until someone either deletes it or releases it
|
||||
for delivery. Log the optional text if specified,
|
||||
otherwise log a generic message.
|
||||
|
||||
Mail that is placed on hold can be examined with
|
||||
the <a href="postcat.1.html"><b>postcat</b>(1)</a> command, and can be destroyed or
|
||||
Mail that is placed on hold can be examined with
|
||||
the <a href="postcat.1.html"><b>postcat</b>(1)</a> command, and can be destroyed or
|
||||
released with the <a href="postsuper.1.html"><b>postsuper</b>(1)</a> command.
|
||||
|
||||
Note: this action currently affects all recipients
|
||||
Note: this action currently affects all recipients
|
||||
of the message.
|
||||
|
||||
<b>DISCARD</b>
|
||||
|
||||
<b>DISCARD</b> <i>optional</i> <i>text...</i>
|
||||
Claim successful delivery and silently discard the
|
||||
message. Log the optional text if specified, oth-
|
||||
Claim successful delivery and silently discard the
|
||||
message. Log the optional text if specified, oth-
|
||||
erwise log a generic message.
|
||||
|
||||
Note: this action currently affects all recipients
|
||||
Note: this action currently affects all recipients
|
||||
of the message.
|
||||
|
||||
<b>FILTER</b> <i>transport:destination</i>
|
||||
After the message is queued, send the entire mes-
|
||||
sage through a content filter. More information
|
||||
After the message is queued, send the entire mes-
|
||||
sage through a content filter. More information
|
||||
about content filters is in the Postfix FIL-
|
||||
TER_README file.
|
||||
|
||||
Note: this action overrides the <b>main.cf</b> <b>con-</b>
|
||||
Note: this action overrides the <b>main.cf</b> <b>con-</b>
|
||||
<b>tent</b><i>_</i><b>filter</b> setting, and currently affects all
|
||||
recipients of the message.
|
||||
|
||||
<b>REDIRECT</b> <i>user@domain</i>
|
||||
After the message is queued, send the message to
|
||||
After the message is queued, send the message to
|
||||
the specified address instead of the intended
|
||||
recipient(s).
|
||||
|
||||
Note: this action overrides the FILTER action, and
|
||||
Note: this action overrides the FILTER action, and
|
||||
currently affects all recipients of the message.
|
||||
|
||||
<i>restriction...</i>
|
||||
@ -182,39 +185,40 @@ ACCESS(5) ACCESS(5)
|
||||
<b>reject</b><i>_</i><b>unauth</b><i>_</i><b>destination</b>, and so on).
|
||||
|
||||
<b>REGULAR</b> <b>EXPRESSION</b> <b>TABLES</b>
|
||||
This section describes how the table lookups change when
|
||||
This section describes how the table lookups change when
|
||||
the table is given in the form of regular expressions. For
|
||||
a description of regular expression lookup table syntax,
|
||||
a description of regular expression lookup table syntax,
|
||||
see <a href="regexp_table.5.html"><b>regexp</b><i>_</i><b>table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre</b><i>_</i><b>table</b>(5)</a>.
|
||||
|
||||
Each pattern is a regular expression that is applied to
|
||||
Each pattern is a regular expression that is applied to
|
||||
the entire string being looked up. Depending on the appli-
|
||||
cation, that string is an entire client hostname, an
|
||||
cation, that string is an entire client hostname, an
|
||||
entire client IP address, or an entire mail address. Thus,
|
||||
no parent domain or parent network search is done,
|
||||
<i>user@domain</i> mail addresses are not broken up into their
|
||||
<i>user@domain</i> mail addresses are not broken up into their
|
||||
<i>user@</i> and <i>domain</i> constituent parts, nor is <i>user+foo</i> broken
|
||||
up into <i>user</i> and <i>foo</i>.
|
||||
|
||||
Patterns are applied in the order as specified in the
|
||||
table, until a pattern is found that matches the search
|
||||
Patterns are applied in the order as specified in the
|
||||
table, until a pattern is found that matches the search
|
||||
string.
|
||||
|
||||
Actions are the same as with indexed file lookups, with
|
||||
the additional feature that parenthesized substrings from
|
||||
Actions are the same as with indexed file lookups, with
|
||||
the additional feature that parenthesized substrings from
|
||||
the pattern can be interpolated as <b>$1</b>, <b>$2</b> and so on.
|
||||
|
||||
<b>BUGS</b>
|
||||
The table format does not understand quoting conventions.
|
||||
The table format does not understand quoting conventions.
|
||||
|
||||
<b>SEE</b> <b>ALSO</b>
|
||||
<a href="postmap.1.html">postmap(1)</a> create mapping table
|
||||
<a href="postmap.1.html">postmap(1)</a> create lookup table
|
||||
<a href="smtpd.8.html">smtpd(8)</a> smtp server
|
||||
cidr_table(5) format of CIDR tables
|
||||
<a href="pcre_table.5.html">pcre_table(5)</a> format of PCRE tables
|
||||
<a href="regexp_table.5.html">regexp_table(5)</a> format of POSIX regular expression tables
|
||||
|
||||
<b>LICENSE</b>
|
||||
The Secure Mailer license must be distributed with this
|
||||
The Secure Mailer license must be distributed with this
|
||||
software.
|
||||
|
||||
<b>AUTHOR(S)</b>
|
||||
|
@ -171,6 +171,14 @@ CLEANUP(8) CLEANUP(8)
|
||||
Address mapping lookup table for sender and recipi-
|
||||
ent addresses in envelopes and headers.
|
||||
|
||||
<b>enable</b><i>_</i><b>original</b><i>_</i><b>recipient</b>
|
||||
Enable support for the X-Original-To message
|
||||
header, which is needed for multi-recipient mail-
|
||||
boxes. When this is enabled, Postfix performs
|
||||
duplicate elimination on (original recipient,
|
||||
rewritten recipient) pairs, instead of looking at
|
||||
the rewritten recipient only.
|
||||
|
||||
<b>recipient</b><i>_</i><b>canonical</b><i>_</i><b>maps</b>
|
||||
Address mapping lookup table for envelope and
|
||||
header recipient addresses.
|
||||
@ -180,16 +188,16 @@ CLEANUP(8) CLEANUP(8)
|
||||
header sender addresses.
|
||||
|
||||
<b>masquerade</b><i>_</i><b>classes</b>
|
||||
List of address classes subject to masquerading:
|
||||
zero or more of <b>envelope</b><i>_</i><b>sender</b>, <b>envelope</b><i>_</i><b>recipi-</b>
|
||||
List of address classes subject to masquerading:
|
||||
zero or more of <b>envelope</b><i>_</i><b>sender</b>, <b>envelope</b><i>_</i><b>recipi-</b>
|
||||
<b>ent</b>, <b>header</b><i>_</i><b>sender</b>, <b>header</b><i>_</i><b>recipient</b>.
|
||||
|
||||
<b>masquerade</b><i>_</i><b>domains</b>
|
||||
List of domains that hide their subdomain struc-
|
||||
List of domains that hide their subdomain struc-
|
||||
ture.
|
||||
|
||||
<b>masquerade</b><i>_</i><b>exceptions</b>
|
||||
List of user names that are not subject to address
|
||||
List of user names that are not subject to address
|
||||
masquerading.
|
||||
|
||||
<b>virtual</b><i>_</i><b>alias</b><i>_</i><b>maps</b>
|
||||
@ -198,7 +206,7 @@ CLEANUP(8) CLEANUP(8)
|
||||
|
||||
<b>Resource</b> <b>controls</b>
|
||||
<b>duplicate</b><i>_</i><b>filter</b><i>_</i><b>limit</b>
|
||||
Limits the number of envelope recipients that are
|
||||
Limits the number of envelope recipients that are
|
||||
remembered.
|
||||
|
||||
<b>header</b><i>_</i><b>address</b><i>_</i><b>token</b><i>_</i><b>limit</b>
|
||||
@ -206,21 +214,21 @@ CLEANUP(8) CLEANUP(8)
|
||||
a message header.
|
||||
|
||||
<b>header</b><i>_</i><b>size</b><i>_</i><b>limit</b>
|
||||
Limits the amount of memory in bytes used to pro-
|
||||
Limits the amount of memory in bytes used to pro-
|
||||
cess a message header.
|
||||
|
||||
<b>in</b><i>_</i><b>flow</b><i>_</i><b>delay</b>
|
||||
Amount of time to pause before accepting a message,
|
||||
when the message arrival rate exceeds the message
|
||||
when the message arrival rate exceeds the message
|
||||
delivery rate.
|
||||
|
||||
<b>virtual</b><i>_</i><b>alias</b><i>_</i><b>expansion</b><i>_</i><b>limit</b>
|
||||
Limit the number of actual recipients produced by
|
||||
virtual alias expansion from each original recipi-
|
||||
Limit the number of actual recipients produced by
|
||||
virtual alias expansion from each original recipi-
|
||||
ent.
|
||||
|
||||
<b>virtual</b><i>_</i><b>alias</b><i>_</i><b>recursion</b><i>_</i><b>limit</b>
|
||||
Limit the recursion depth of virtual alias expan-
|
||||
Limit the recursion depth of virtual alias expan-
|
||||
sion.
|
||||
|
||||
<b>SEE</b> <b>ALSO</b>
|
||||
@ -235,7 +243,7 @@ CLEANUP(8) CLEANUP(8)
|
||||
/etc/postfix/virtual*, virtual mapping table
|
||||
|
||||
<b>LICENSE</b>
|
||||
The Secure Mailer license must be distributed with this
|
||||
The Secure Mailer license must be distributed with this
|
||||
software.
|
||||
|
||||
<b>AUTHOR(S)</b>
|
||||
|
@ -2618,8 +2618,9 @@ the <b>virtual_mailbox_maps</b> parameter.
|
||||
|
||||
<p>
|
||||
|
||||
If you want to deliver the domain as a Postfix simulated <a
|
||||
href="virtual.8.html">virtual</a>(5) domain, then you should list
|
||||
If you want to deliver the domain as a <a href="virtual.8.html">
|
||||
virtual</a>(5) alias domain, where each address is aliased to
|
||||
a real local or remote address, then you should list
|
||||
the virtual domain name in the tables specified with the
|
||||
<b>virtual_alias_domains</b> parameter instead.
|
||||
|
||||
@ -2638,7 +2639,7 @@ Solutions:
|
||||
|
||||
<ul>
|
||||
|
||||
<li>Specify a simulated virtual domain as per the
|
||||
<li>Specify a virtual alias domain as per the
|
||||
<a href="virtual.5.html">virtual(5)</a> manual page.
|
||||
|
||||
<p>
|
||||
@ -2715,6 +2716,15 @@ that the mail was sent to.
|
||||
Answer: Postfix logs the original recipient address in the
|
||||
<b>X-Original-To:</b> message header.
|
||||
|
||||
<p>
|
||||
|
||||
This requires that the <b>enable_original_recipient</b> parameter
|
||||
is not changed from its default value of <b>yes</b>. With
|
||||
<b>enable_original_recipient</b> set to <b>no</b>, messages to
|
||||
multiple recipients in the domain will only be delivered to
|
||||
the first recipient, and the <b>X-Original-To:<b> header will
|
||||
not be added to the message.
|
||||
|
||||
<hr>
|
||||
|
||||
<a name="masquerade"><h3>Address masquerading with exceptions</h3></a>
|
||||
|
@ -5,8 +5,6 @@ PCRE_TABLE(5) PCRE_TABLE(5)
|
||||
pcre_table - format of Postfix PCRE tables
|
||||
|
||||
<b>SYNOPSIS</b>
|
||||
<b>pcre:/etc/postfix/</b><i>filename</i>
|
||||
|
||||
<b>postmap</b> <b>-q</b> <b>"</b><i>string</i><b>"</b> <b>pcre:/etc/postfix/</b><i>filename</i>
|
||||
|
||||
<b>postmap</b> <b>-q</b> <b>-</b> <b>pcre:/etc/postfix/</b><i>filename</i> <<i>inputfile</i>
|
||||
@ -26,8 +24,10 @@ PCRE_TABLE(5) PCRE_TABLE(5)
|
||||
The general form of a PCRE table is:
|
||||
|
||||
<b>/</b><i>pattern</i><b>/</b><i>flags</i> <i>result</i>
|
||||
When <i>pattern</i> matches a search string, use the cor-
|
||||
responding <i>result</i> value.
|
||||
|
||||
<b>!/</b><i>pattern</i><b>/</b><i>flags</i> <i>result</i>
|
||||
When <i>pattern</i> matches (does not match) a search
|
||||
string, use the corresponding <i>result</i> value.
|
||||
|
||||
blank lines and comments
|
||||
Empty lines and whitespace-only lines are ignored,
|
||||
@ -41,98 +41,104 @@ PCRE_TABLE(5) PCRE_TABLE(5)
|
||||
|
||||
<b>if</b> <b>/</b><i>pattern</i><b>/</b><i>flags</i>
|
||||
|
||||
<b>if</b> <b>!/</b><i>pattern</i><b>/</b><i>flags</i>
|
||||
|
||||
<b>endif</b> Examine the lines between <b>if</b>..<b>endif</b> only if <i>pattern</i>
|
||||
matches. The <b>if</b>..<b>endif</b> can nest. Do not prepend
|
||||
whitespace to patterns inside <b>if</b>..<b>endif</b>.
|
||||
matches (does not match). The <b>if</b>..<b>endif</b> can nest.
|
||||
Do not prepend whitespace to patterns inside
|
||||
<b>if</b>..<b>endif</b>.
|
||||
|
||||
Each pattern is a perl-like regular expression. The
|
||||
expression delimiter can be any character, except whites-
|
||||
pace or characters that have special meaning (tradition-
|
||||
ally the forward slash is used). The regular expression
|
||||
expression delimiter can be any character, except whites-
|
||||
pace or characters that have special meaning (tradition-
|
||||
ally the forward slash is used). The regular expression
|
||||
can contain whitespace.
|
||||
|
||||
By default, matching is case-insensitive, and newlines are
|
||||
not treated as special characters. The behavior is con-
|
||||
trolled by flags, which are toggled by appending one or
|
||||
not treated as special characters. The behavior is con-
|
||||
trolled by flags, which are toggled by appending one or
|
||||
more of the following characters after the pattern:
|
||||
|
||||
<b>i</b> (default: on)
|
||||
Toggles the case sensitivity flag. By default,
|
||||
Toggles the case sensitivity flag. By default,
|
||||
matching is case insensitive.
|
||||
|
||||
<b>m</b> (default: off)
|
||||
Toggles the PCRE_MULTILINE flag. When this flag is
|
||||
on, the <b>^</b> and <b>$</b> metacharacters match immediately
|
||||
after and immediately before a newline character,
|
||||
respectively, in addition to matching at the start
|
||||
Toggles the PCRE_MULTILINE flag. When this flag is
|
||||
on, the <b>^</b> and <b>$</b> metacharacters match immediately
|
||||
after and immediately before a newline character,
|
||||
respectively, in addition to matching at the start
|
||||
and end of the subject string.
|
||||
|
||||
<b>s</b> (default: on)
|
||||
Toggles the PCRE_DOTALL flag. When this flag is on,
|
||||
the <b>.</b> metacharacter matches the newline character.
|
||||
With Postfix versions prior to 20020528, The flag
|
||||
With Postfix versions prior to 20020528, The flag
|
||||
is off by default, which is inconvenient for multi-
|
||||
line message header matching.
|
||||
|
||||
<b>x</b> (default: off)
|
||||
Toggles the pcre extended flag. When this flag is
|
||||
on, whitespace in the pattern (other than in a
|
||||
Toggles the pcre extended flag. When this flag is
|
||||
on, whitespace in the pattern (other than in a
|
||||
character class) and characters between a <b>#</b> outside
|
||||
a character class and the next newline character
|
||||
are ignored. An escaping backslash can be used to
|
||||
include a whitespace or <b>#</b> character as part of the
|
||||
a character class and the next newline character
|
||||
are ignored. An escaping backslash can be used to
|
||||
include a whitespace or <b>#</b> character as part of the
|
||||
pattern.
|
||||
|
||||
<b>A</b> (default: off)
|
||||
Toggles the PCRE_ANCHORED flag. When this flag is
|
||||
on, the pattern is forced to be "anchored", that
|
||||
Toggles the PCRE_ANCHORED flag. When this flag is
|
||||
on, the pattern is forced to be "anchored", that
|
||||
is, it is constrained to match only at the start of
|
||||
the string which is being searched (the "subject
|
||||
string"). This effect can also be achieved by
|
||||
the string which is being searched (the "subject
|
||||
string"). This effect can also be achieved by
|
||||
appropriate constructs in the pattern itself.
|
||||
|
||||
<b>E</b> (default: off)
|
||||
Toggles the PCRE_DOLLAR_ENDONLY flag. When this
|
||||
flag is on, a <b>$</b> metacharacter in the pattern
|
||||
matches only at the end of the subject string.
|
||||
Without this flag, a dollar also matches immedi-
|
||||
Toggles the PCRE_DOLLAR_ENDONLY flag. When this
|
||||
flag is on, a <b>$</b> metacharacter in the pattern
|
||||
matches only at the end of the subject string.
|
||||
Without this flag, a dollar also matches immedi-
|
||||
ately before the final character if it is a newline
|
||||
character (but not before any other newline charac-
|
||||
ters). This flag is ignored if PCRE_MULTILINE flag
|
||||
ters). This flag is ignored if PCRE_MULTILINE flag
|
||||
is set.
|
||||
|
||||
<b>U</b> (default: off)
|
||||
Toggles the ungreedy matching flag. When this flag
|
||||
is on, the pattern matching engine inverts the
|
||||
"greediness" of the quantifiers so that they are
|
||||
not greedy by default, but become greedy if fol-
|
||||
lowed by "?". This flag can also set by a (?U)
|
||||
is on, the pattern matching engine inverts the
|
||||
"greediness" of the quantifiers so that they are
|
||||
not greedy by default, but become greedy if fol-
|
||||
lowed by "?". This flag can also set by a (?U)
|
||||
modifier within the pattern.
|
||||
|
||||
<b>X</b> (default: off)
|
||||
Toggles the PCRE_EXTRA flag. When this flag is on,
|
||||
any backslash in a pattern that is followed by a
|
||||
any backslash in a pattern that is followed by a
|
||||
letter that has no special meaning causes an error,
|
||||
thus reserving these combinations for future expan-
|
||||
sion.
|
||||
|
||||
Each pattern is applied to the entire lookup key string.
|
||||
Depending on the application, that string is an entire
|
||||
Each pattern is applied to the entire lookup key string.
|
||||
Depending on the application, that string is an entire
|
||||
client hostname, an entire client IP address, or an entire
|
||||
mail address. Thus, no parent domain or parent network
|
||||
search is done, and <i>user@domain</i> mail addresses are not
|
||||
broken up into their <i>user</i> and <i>domain</i> constituent parts,
|
||||
mail address. Thus, no parent domain or parent network
|
||||
search is done, and <i>user@domain</i> mail addresses are not
|
||||
broken up into their <i>user</i> and <i>domain</i> constituent parts,
|
||||
nor is <i>user+foo</i> broken up into <i>user</i> and <i>foo</i>.
|
||||
|
||||
Patterns are applied in the order as specified in the
|
||||
table, until a pattern is found that matches the search
|
||||
Patterns are applied in the order as specified in the
|
||||
table, until a pattern is found that matches the search
|
||||
string.
|
||||
|
||||
Substitution of substrings from the matched expression
|
||||
into the result string is possible using the conventional
|
||||
perl syntax ($1, $2, etc.). The macros in the result
|
||||
string may need to be written as ${n} or $(n) if they
|
||||
aren't followed by whitespace.
|
||||
Substitution of substrings from the matched expression
|
||||
into the result string is possible using the conventional
|
||||
perl syntax ($1, $2, etc.). The macros in the result
|
||||
string may need to be written as ${n} or $(n) if they
|
||||
aren't followed by whitespace. Since negated patterns
|
||||
(those preceded by <b>!</b>) return a result when the expression
|
||||
does not match, substitutions are not available for
|
||||
negated patterns.
|
||||
|
||||
<b>EXAMPLE</b> <b>SMTPD</b> <b>ACCESS</b> <b>MAP</b>
|
||||
# Protect your outgoing majordomo exploders
|
||||
@ -161,6 +167,8 @@ PCRE_TABLE(5) PCRE_TABLE(5)
|
||||
|
||||
<b>SEE</b> <b>ALSO</b>
|
||||
<a href="regexp_table.5.html">regexp_table(5)</a> format of POSIX regular expression tables
|
||||
cidr_table(5) format of CIDR tables
|
||||
tcp_table(5) TCP client/server table lookup protocol
|
||||
|
||||
<b>AUTHOR(S)</b>
|
||||
The PCRE table lookup code was originally written by:
|
||||
|
@ -5,8 +5,6 @@ REGEXP_TABLE(5) REGEXP_TABLE(5)
|
||||
regexp_table - format of Postfix regular expression tables
|
||||
|
||||
<b>SYNOPSIS</b>
|
||||
<b>regexp:/etc/postfix/</b><i>filename</i>
|
||||
|
||||
<b>postmap</b> <b>-q</b> <b>"</b><i>string</i><b>"</b> <b>regexp:/etc/postfix/</b><i>filename</i>
|
||||
|
||||
<b>postmap</b> <b>-q</b> <b>-</b> <b>regexp:/etc/postfix/</b><i>filename</i> <<i>inputfile</i>
|
||||
@ -78,7 +76,10 @@ REGEXP_TABLE(5) REGEXP_TABLE(5)
|
||||
Substitution of substrings from the matched expression
|
||||
into the result string is possible using $1, $2, etc.. The
|
||||
macros in the result string may need to be written as ${n}
|
||||
or $(n) if they aren't followed by whitespace.
|
||||
or $(n) if they aren't followed by whitespace. Since
|
||||
negated patterns (those preceded by <b>!</b>) return a result
|
||||
when the expression does not match, substitutions are not
|
||||
available for negated patterns.
|
||||
|
||||
<b>EXAMPLE</b> <b>SMTPD</b> <b>ACCESS</b> <b>MAP</b>
|
||||
# Disallow sender-specified routing. This is a must if you relay mail
|
||||
@ -107,6 +108,8 @@ REGEXP_TABLE(5) REGEXP_TABLE(5)
|
||||
|
||||
<b>SEE</b> <b>ALSO</b>
|
||||
<a href="pcre_table.5.html">pcre_table(5)</a> format of PCRE tables
|
||||
cidr_table(5) format of CIDR tables
|
||||
tcp_table(5) TCP client/server table lookup protocol
|
||||
|
||||
<b>AUTHOR(S)</b>
|
||||
The regexp table lookup code was originally written by:
|
||||
|
@ -318,8 +318,8 @@ href="cleanup.8.html">cleanup</a> daemon uses the <a
|
||||
href="virtual.5.html">virtual alias</a> table to redirect mail for all
|
||||
recipients, local or remote. The mapping affects only envelope
|
||||
recipients; it has no effect on message headers or envelope senders.
|
||||
Virtual alias lookups are useful to redirect mail for simulated
|
||||
virtual domains to real user mailboxes, and to redirect mail for
|
||||
Virtual alias lookups are useful to redirect mail for virtual
|
||||
alias domains to real user mailboxes, and to redirect mail for
|
||||
domains that no longer exist. Virtual alias lookups can also be
|
||||
used to transform <i> Firstname.Lastname </i> back into UNIX login
|
||||
names, although it seems that local <a href="#aliases">aliases</a>
|
||||
|
@ -25,11 +25,6 @@ SMTP(8) SMTP(8)
|
||||
preference, and connects to each listed address until it
|
||||
finds a server that responds.
|
||||
|
||||
When the domain or host is specified as a comma/whitespace
|
||||
separated list, the SMTP client repeats the above process
|
||||
for all destinations until it finds a server that
|
||||
responds.
|
||||
|
||||
Once the SMTP client has received the server greeting ban-
|
||||
ner, no error will cause it to proceed to the next address
|
||||
on the mail exchanger list. Instead, the message is either
|
||||
@ -37,7 +32,7 @@ SMTP(8) SMTP(8)
|
||||
|
||||
<b>SECURITY</b>
|
||||
The SMTP client is moderately security-sensitive. It talks
|
||||
to SMTP servers and to DNS servers on the network. The
|
||||
to SMTP servers and to DNS servers on the network. The
|
||||
SMTP client can be run chrooted at fixed low privilege.
|
||||
|
||||
<b>STANDARDS</b>
|
||||
@ -53,80 +48,80 @@ SMTP(8) SMTP(8)
|
||||
<a href="http://www.faqs.org/rfcs/rfc2920.html">RFC 2920</a> (SMTP Pipelining)
|
||||
|
||||
<b>DIAGNOSTICS</b>
|
||||
Problems and transactions are logged to <b>syslogd</b>(8). Cor-
|
||||
rupted message files are marked so that the queue manager
|
||||
Problems and transactions are logged to <b>syslogd</b>(8). Cor-
|
||||
rupted message files are marked so that the queue manager
|
||||
can move them to the <b>corrupt</b> queue for further inspection.
|
||||
|
||||
Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
|
||||
the postmaster is notified of bounces, protocol problems,
|
||||
Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
|
||||
the postmaster is notified of bounces, protocol problems,
|
||||
and of other trouble.
|
||||
|
||||
<b>BUGS</b>
|
||||
<b>CONFIGURATION</b> <b>PARAMETERS</b>
|
||||
The following <b>main.cf</b> parameters are especially relevant
|
||||
to this program. See the Postfix <b>main.cf</b> file for syntax
|
||||
details and for default values. Use the <b>postfix</b> <b>reload</b>
|
||||
The following <b>main.cf</b> parameters are especially relevant
|
||||
to this program. See the Postfix <b>main.cf</b> file for syntax
|
||||
details and for default values. Use the <b>postfix</b> <b>reload</b>
|
||||
command after a configuration change.
|
||||
|
||||
<b>Miscellaneous</b>
|
||||
<b>best</b><i>_</i><b>mx</b><i>_</i><b>transport</b>
|
||||
Name of the delivery transport to use when the
|
||||
local machine is the most-preferred mail exchanger
|
||||
(by default, a mailer loop is reported, and the
|
||||
Name of the delivery transport to use when the
|
||||
local machine is the most-preferred mail exchanger
|
||||
(by default, a mailer loop is reported, and the
|
||||
message is bounced).
|
||||
|
||||
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>level</b>
|
||||
Verbose logging level increment for hosts that
|
||||
Verbose logging level increment for hosts that
|
||||
match a pattern in the <b>debug</b><i>_</i><b>peer</b><i>_</i><b>list</b> parameter.
|
||||
|
||||
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>list</b>
|
||||
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
|
||||
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>level</b> parameter.
|
||||
|
||||
<b>disable</b><i>_</i><b>dns</b><i>_</i><b>lookups</b>
|
||||
Disable DNS lookups. This means that mail must be
|
||||
Disable DNS lookups. This means that mail must be
|
||||
forwarded via a smart relay host.
|
||||
|
||||
<b>smtp</b><i>_</i><b>host</b><i>_</i><b>lookup</b>
|
||||
What host lookup mechanism the SMTP client should
|
||||
use. Specify <b>dns</b> (use DNS lookup) and/or <b>native</b>
|
||||
(use the native naming service which also uses
|
||||
/etc/hosts). This setting is ignored when DNS
|
||||
What host lookup mechanism the SMTP client should
|
||||
use. Specify <b>dns</b> (use DNS lookup) and/or <b>native</b>
|
||||
(use the native naming service which also uses
|
||||
/etc/hosts). This setting is ignored when DNS
|
||||
lookups are disabled.
|
||||
|
||||
<b>error</b><i>_</i><b>notice</b><i>_</i><b>recipient</b>
|
||||
Recipient of protocol/policy/resource/software
|
||||
Recipient of protocol/policy/resource/software
|
||||
error notices.
|
||||
|
||||
<b>fallback</b><i>_</i><b>relay</b>
|
||||
Hosts to hand off mail to if a message destination
|
||||
Hosts to hand off mail to if a message destination
|
||||
is not found or if a destination is unreachable.
|
||||
|
||||
<b>ignore</b><i>_</i><b>mx</b><i>_</i><b>lookup</b><i>_</i><b>error</b>
|
||||
When a name server fails to respond to an MX query,
|
||||
search for an A record instead deferring mail
|
||||
search for an A record instead deferring mail
|
||||
delivery.
|
||||
|
||||
<b>inet</b><i>_</i><b>interfaces</b>
|
||||
The network interface addresses that this mail sys-
|
||||
tem receives mail on. When any of those addresses
|
||||
tem receives mail on. When any of those addresses
|
||||
appears in the list of mail exchangers for a remote
|
||||
destination, the list is truncated to avoid mail
|
||||
destination, the list is truncated to avoid mail
|
||||
delivery loops. See also the <b>proxy</b><i>_</i><b>interfaces</b>
|
||||
parameter.
|
||||
|
||||
<b>notify</b><i>_</i><b>classes</b>
|
||||
When this parameter includes the <b>protocol</b> class,
|
||||
send mail to the postmaster with transcripts of
|
||||
When this parameter includes the <b>protocol</b> class,
|
||||
send mail to the postmaster with transcripts of
|
||||
SMTP sessions with protocol errors.
|
||||
|
||||
<b>proxy</b><i>_</i><b>interfaces</b>
|
||||
Network interfaces that this mail system receives
|
||||
Network interfaces that this mail system receives
|
||||
mail on by way of a proxy or network address trans-
|
||||
lator. When any of those addresses appears in the
|
||||
list of mail exchangers for a remote destination,
|
||||
lator. When any of those addresses appears in the
|
||||
list of mail exchangers for a remote destination,
|
||||
the list is truncated to avoid mail delivery loops.
|
||||
See also the <b>inet</b><i>_</i><b>interfaces</b> parameter.
|
||||
|
||||
@ -137,16 +132,20 @@ SMTP(8) SMTP(8)
|
||||
Never send EHLO at the start of a connection.
|
||||
|
||||
<b>smtp</b><i>_</i><b>bind</b><i>_</i><b>address</b>
|
||||
Numerical source network address to bind to when
|
||||
Numerical source network address to bind to when
|
||||
making a connection.
|
||||
|
||||
<b>smtp</b><i>_</i><b>line</b><i>_</i><b>length</b><i>_</i><b>limit</b>
|
||||
Length limit for SMTP message content lines. Zero
|
||||
means no limit. Some SMTP servers misbehave on
|
||||
Length limit for SMTP message content lines. Zero
|
||||
means no limit. Some SMTP servers misbehave on
|
||||
long lines.
|
||||
|
||||
<b>smtp</b><i>_</i><b>helo</b><i>_</i><b>name</b>
|
||||
The hostname to be used in HELO and EHLO commands.
|
||||
The hostname to be used in HELO and EHLO commands.
|
||||
|
||||
<b>smtp</b><i>_</i><b>quote</b><i>_</i><b>rfc821</b><i>_</i><b>envelope</b>
|
||||
Whether or not to quote MAIL FROM and RCPT TO
|
||||
addresses as per the rules laid out in <a href="http://www.faqs.org/rfcs/rfc821.html">RFC 821</a>.
|
||||
|
||||
<b>smtp</b><i>_</i><b>skip</b><i>_</i><b>4xx</b><i>_</i><b>greeting</b>
|
||||
Skip servers that greet us with a 4xx status code.
|
||||
|
@ -114,29 +114,48 @@ SMTPD(8) SMTPD(8)
|
||||
<b>reject</b><i>_</i><b>sender</b><i>_</i><b>login</b><i>_</i><b>mismatch</b> sender anti-spoofing
|
||||
restriction.
|
||||
|
||||
<b>Pass-through</b> <b>proxy</b>
|
||||
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.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>proxy</b><i>_</i><b>filter</b>
|
||||
The <i>host:port</i> of the SMTP proxy server. The <i>host</i> or
|
||||
<i>host:</i> portion is optional.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>proxy</b><i>_</i><b>timeout</b>
|
||||
Timeout for connecting to, sending to and receiving
|
||||
from the SMTP proxy server.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>proxy</b><i>_</i><b>ehlo</b>
|
||||
The hostname to use when sending an EHLO command to
|
||||
the SMTP proxy server.
|
||||
|
||||
<b>Miscellaneous</b>
|
||||
<b>authorized</b><i>_</i><b>verp</b><i>_</i><b>clients</b>
|
||||
Hostnames, domain names and/or addresses of clients
|
||||
that are authorized to use the XVERP extension.
|
||||
|
||||
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>level</b>
|
||||
Increment in verbose logging level when a remote
|
||||
Increment in verbose logging level when a remote
|
||||
host matches a pattern in the <b>debug</b><i>_</i><b>peer</b><i>_</i><b>list</b>
|
||||
parameter.
|
||||
|
||||
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>list</b>
|
||||
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
|
||||
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>level</b> parameter.
|
||||
|
||||
<b>default</b><i>_</i><b>verp</b><i>_</i><b>delimiters</b>
|
||||
The default VERP delimiter characters that are used
|
||||
when the XVERP command is specified without
|
||||
when the XVERP command is specified without
|
||||
explicit delimiters.
|
||||
|
||||
<b>error</b><i>_</i><b>notice</b><i>_</i><b>recipient</b>
|
||||
Recipient of protocol/policy/resource/software
|
||||
Recipient of protocol/policy/resource/software
|
||||
error notices.
|
||||
|
||||
<b>hopcount</b><i>_</i><b>limit</b>
|
||||
@ -145,18 +164,18 @@ SMTPD(8) SMTPD(8)
|
||||
<b>notify</b><i>_</i><b>classes</b>
|
||||
List of error classes. Of special interest are:
|
||||
|
||||
<b>policy</b> When a client violates any policy, mail a
|
||||
<b>policy</b> When a client violates any policy, mail a
|
||||
transcript of the entire SMTP session to the
|
||||
postmaster.
|
||||
|
||||
<b>protocol</b>
|
||||
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.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>banner</b>
|
||||
Text that follows the <b>220</b> status code in the SMTP
|
||||
Text that follows the <b>220</b> status code in the SMTP
|
||||
greeting banner.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>
|
||||
@ -164,57 +183,57 @@ SMTPD(8) SMTPD(8)
|
||||
expansion of rbl template responses and other text.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
|
||||
Restrict the number of recipients that the SMTP
|
||||
Restrict the number of recipients that the SMTP
|
||||
server accepts per message delivery.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>timeout</b>
|
||||
Limit the time to send a server response and to
|
||||
Limit the time to send a server response and to
|
||||
receive a client request.
|
||||
|
||||
<b>soft</b><i>_</i><b>bounce</b>
|
||||
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.
|
||||
|
||||
<b>verp</b><i>_</i><b>delimiter</b><i>_</i><b>filter</b>
|
||||
The characters that Postfix accepts as VERP delim-
|
||||
The characters that Postfix accepts as VERP delim-
|
||||
iter characters.
|
||||
|
||||
<b>Known</b> <b>versus</b> <b>unknown</b> <b>recipients</b>
|
||||
<b>show</b><i>_</i><b>user</b><i>_</i><b>unknown</b><i>_</i><b>table</b><i>_</i><b>name</b>
|
||||
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.
|
||||
|
||||
<b>unknown</b><i>_</i><b>local</b><i>_</i><b>recipient</b><i>_</i><b>reject</b><i>_</i><b>code</b>
|
||||
The response code when a client specifies a recipi-
|
||||
ent whose domain matches <b>$mydestination</b> or
|
||||
ent whose domain matches <b>$mydestination</b> or
|
||||
<b>$inet</b><i>_</i><b>interfaces</b>, while <b>$local</b><i>_</i><b>recipient</b><i>_</i><b>maps</b> is
|
||||
non-empty and does not list the recipient address
|
||||
non-empty and does not list the recipient address
|
||||
or address local-part.
|
||||
|
||||
<b>unknown</b><i>_</i><b>relay</b><i>_</i><b>recipient</b><i>_</i><b>reject</b><i>_</i><b>code</b>
|
||||
The response code when a client specifies a recipi-
|
||||
ent whose domain matches <b>$relay</b><i>_</i><b>domains</b>, while
|
||||
<b>$relay</b><i>_</i><b>recipient</b><i>_</i><b>maps</b> is non-empty and does not
|
||||
<b>$relay</b><i>_</i><b>recipient</b><i>_</i><b>maps</b> is non-empty and does not
|
||||
list the recipient address.
|
||||
|
||||
<b>unknown</b><i>_</i><b>virtual</b><i>_</i><b>alias</b><i>_</i><b>reject</b><i>_</i><b>code</b>
|
||||
The response code when a client specifies a recipi-
|
||||
ent whose domain matches <b>$virtual</b><i>_</i><b>alias</b><i>_</i><b>domains</b>,
|
||||
while the recipient is not listed in <b>$vir-</b>
|
||||
ent whose domain matches <b>$virtual</b><i>_</i><b>alias</b><i>_</i><b>domains</b>,
|
||||
while the recipient is not listed in <b>$vir-</b>
|
||||
<b>tual</b><i>_</i><b>alias</b><i>_</i><b>maps</b>.
|
||||
|
||||
<b>unknown</b><i>_</i><b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>reject</b><i>_</i><b>code</b>
|
||||
The response code when a client specifies a recipi-
|
||||
ent whose domain matches <b>$virtual</b><i>_</i><b>mailbox</b><i>_</i><b>domains</b>,
|
||||
ent whose domain matches <b>$virtual</b><i>_</i><b>mailbox</b><i>_</i><b>domains</b>,
|
||||
while the recipient is not listed in <b>$virtual</b><i>_</i><b>mail-</b>
|
||||
<b>box</b><i>_</i><b>maps</b>.
|
||||
|
||||
<b>Resource</b> <b>controls</b>
|
||||
<b>line</b><i>_</i><b>length</b><i>_</i><b>limit</b>
|
||||
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.
|
||||
|
||||
<b>message</b><i>_</i><b>size</b><i>_</i><b>limit</b>
|
||||
@ -222,8 +241,8 @@ SMTPD(8) SMTPD(8)
|
||||
ing on-disk storage for envelope information.
|
||||
|
||||
<b>queue</b><i>_</i><b>minfree</b>
|
||||
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.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>history</b><i>_</i><b>flush</b><i>_</i><b>threshold</b>
|
||||
@ -238,23 +257,23 @@ SMTPD(8) SMTPD(8)
|
||||
|
||||
<b>smtpd</b><i>_</i><b>soft</b><i>_</i><b>error</b><i>_</i><b>limit</b>
|
||||
When an SMTP client has made this number of errors,
|
||||
wait <i>error_count</i> seconds before responding to any
|
||||
wait <i>error_count</i> seconds before responding to any
|
||||
client request.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>hard</b><i>_</i><b>error</b><i>_</i><b>limit</b>
|
||||
Disconnect after a client has made this number of
|
||||
Disconnect after a client has made this number of
|
||||
errors.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>junk</b><i>_</i><b>command</b><i>_</i><b>limit</b>
|
||||
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.
|
||||
|
||||
<b>UCE</b> <b>control</b> <b>restrictions</b>
|
||||
<b>parent</b><i>_</i><b>domain</b><i>_</i><b>matches</b><i>_</i><b>subdomains</b>
|
||||
List of Postfix features that use <i>domain.tld</i> pat-
|
||||
terns to match <i>sub.domain.tld</i> (as opposed to
|
||||
List of Postfix features that use <i>domain.tld</i> pat-
|
||||
terns to match <i>sub.domain.tld</i> (as opposed to
|
||||
requiring <i>.domain.tld</i> patterns).
|
||||
|
||||
<b>smtpd</b><i>_</i><b>client</b><i>_</i><b>restrictions</b>
|
||||
@ -262,19 +281,19 @@ SMTPD(8) SMTPD(8)
|
||||
tem.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>helo</b><i>_</i><b>required</b>
|
||||
Require that clients introduce themselves at the
|
||||
Require that clients introduce themselves at the
|
||||
beginning of an SMTP session.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>helo</b><i>_</i><b>restrictions</b>
|
||||
Restrict what client hostnames are allowed in <b>HELO</b>
|
||||
Restrict what client hostnames are allowed in <b>HELO</b>
|
||||
and <b>EHLO</b> commands.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>sender</b><i>_</i><b>restrictions</b>
|
||||
Restrict what sender addresses are allowed in <b>MAIL</b>
|
||||
Restrict what sender addresses are allowed in <b>MAIL</b>
|
||||
<b>FROM</b> commands.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>recipient</b><i>_</i><b>restrictions</b>
|
||||
Restrict what recipient addresses are allowed in
|
||||
Restrict what recipient addresses are allowed in
|
||||
<b>RCPT</b> <b>TO</b> commands.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>etrn</b><i>_</i><b>restrictions</b>
|
||||
@ -282,42 +301,60 @@ SMTPD(8) SMTPD(8)
|
||||
mands, and what clients may issue <b>ETRN</b> commands.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>data</b><i>_</i><b>restrictions</b>
|
||||
Restrictions on the <b>DATA</b> command. Currently, the
|
||||
only restriction that makes sense here is
|
||||
Restrictions on the <b>DATA</b> command. Currently, the
|
||||
only restriction that makes sense here is
|
||||
<b>reject</b><i>_</i><b>unauth</b><i>_</i><b>pipelining</b>.
|
||||
|
||||
<b>allow</b><i>_</i><b>untrusted</b><i>_</i><b>routing</b>
|
||||
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.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>restriction</b><i>_</i><b>classes</b>
|
||||
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.
|
||||
|
||||
<b>smtpd</b><i>_</i><b>null</b><i>_</i><b>access</b><i>_</i><b>lookup</b><i>_</i><b>key</b>
|
||||
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.
|
||||
|
||||
<b>maps</b><i>_</i><b>rbl</b><i>_</i><b>domains</b> (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
|
||||
<b>reject</b><i>_</i><b>maps</b><i>_</i><b>rbl</b> restriction.
|
||||
|
||||
<b>permit</b><i>_</i><b>mx</b><i>_</i><b>backup</b><i>_</i><b>networks</b>
|
||||
Only domains whose primary MX hosts match the
|
||||
listed networks are eligible for the <b>per-</b>
|
||||
Only domains whose primary MX hosts match the
|
||||
listed networks are eligible for the <b>per-</b>
|
||||
<b>mit</b><i>_</i><b>mx</b><i>_</i><b>backup</b> feature.
|
||||
|
||||
<b>relay</b><i>_</i><b>domains</b>
|
||||
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 <b>relay</b><i>_</i><b>transport</b> setting.
|
||||
|
||||
<b>Sender/recipient</b> <b>address</b> <b>verification</b>
|
||||
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-
|
||||
tained by the address verification service.
|
||||
|
||||
<b>address</b><i>_</i><b>verify</b><i>_</i><b>poll</b><i>_</i><b>count</b>
|
||||
How many times to query the address verification
|
||||
service for completion of an address verification
|
||||
request. Specify 0 to implement a simple form of
|
||||
greylisting.
|
||||
|
||||
<b>address</b><i>_</i><b>verify</b><i>_</i><b>poll</b><i>_</i><b>delay</b>
|
||||
Time to wait after querying the address verifica-
|
||||
tion service for completion of an address verifica-
|
||||
tion request.
|
||||
|
||||
<b>UCE</b> <b>control</b> <b>responses</b>
|
||||
<b>access</b><i>_</i><b>map</b><i>_</i><b>reject</b><i>_</i><b>code</b>
|
||||
Response code when a client violates an access
|
||||
@ -381,10 +418,11 @@ SMTPD(8) SMTPD(8)
|
||||
be undeliverable.
|
||||
|
||||
<b>SEE</b> <b>ALSO</b>
|
||||
<a href="trivial-rewrite.8.html">trivial-rewrite(8)</a> address resolver
|
||||
<a href="cleanup.8.html">cleanup(8)</a> message canonicalization
|
||||
<a href="master.8.html">master(8)</a> process manager
|
||||
syslogd(8) system logging
|
||||
<a href="trivial-rewrite.8.html">trivial-rewrite(8)</a> address resolver
|
||||
<a href="verify.8.html">verify(8)</a> address verification service
|
||||
|
||||
<b>LICENSE</b>
|
||||
The Secure Mailer license must be distributed with this
|
||||
|
@ -17,21 +17,40 @@ TRANSPORT(5) TRANSPORT(5)
|
||||
relay hosts. The mapping is used by the <a href="trivial-rewrite.8.html"><b>trivial-rewrite</b>(8)</a>
|
||||
daemon.
|
||||
|
||||
Normally, the <b>transport</b> table is specified as a text file
|
||||
that serves as input to the <a href="postmap.1.html"><b>postmap</b>(1)</a> command. The
|
||||
result, an indexed file in <b>dbm</b> or <b>db</b> format, is used for
|
||||
fast searching by the mail system. Execute the command
|
||||
<b>postmap</b> <b>/etc/postfix/transport</b> in order to rebuild the
|
||||
This mapping overrides the default routing that is built
|
||||
into Postfix:
|
||||
|
||||
<b>mydestination</b>
|
||||
A list of domains that is by default delivered via
|
||||
<b>$local</b><i>_</i><b>transport</b>.
|
||||
|
||||
<b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>domains</b>
|
||||
A list of domains that is by default delivered via
|
||||
<b>$virtual</b><i>_</i><b>transport</b>.
|
||||
|
||||
<b>relay</b><i>_</i><b>domains</b>
|
||||
A list of domains that is by default delivered via
|
||||
<b>$relay</b><i>_</i><b>transport</b>.
|
||||
|
||||
any other destination
|
||||
Mail for any other destination is by default deliv-
|
||||
ered via <b>$default</b><i>_</i><b>transport</b>.
|
||||
|
||||
Normally, the <b>transport</b> table is specified as a text file
|
||||
that serves as input to the <a href="postmap.1.html"><b>postmap</b>(1)</a> command. The
|
||||
result, an indexed file in <b>dbm</b> or <b>db</b> format, is used for
|
||||
fast searching by the mail system. Execute the command
|
||||
<b>postmap</b> <b>/etc/postfix/transport</b> in order to rebuild the
|
||||
indexed file after changing the transport table.
|
||||
|
||||
When the table is provided via other means such as NIS,
|
||||
LDAP or SQL, the same lookups are done as for ordinary
|
||||
When the table is provided via other means such as NIS,
|
||||
LDAP or SQL, the same lookups are done as for ordinary
|
||||
indexed files.
|
||||
|
||||
Alternatively, the table can be provided as a regular-
|
||||
Alternatively, the table can be provided as a regular-
|
||||
expression map where patterns are given as regular expres-
|
||||
sions. In that case, the lookups are done in a slightly
|
||||
different way as described in section "REGULAR EXPRESSION
|
||||
sions. In that case, the lookups are done in a slightly
|
||||
different way as described in section "REGULAR EXPRESSION
|
||||
TABLES".
|
||||
|
||||
<b>TABLE</b> <b>FORMAT</b>
|
||||
@ -42,28 +61,28 @@ TRANSPORT(5) TRANSPORT(5)
|
||||
domain, use the corresponding <i>result</i>.
|
||||
|
||||
blank lines and comments
|
||||
Empty lines and whitespace-only lines are ignored,
|
||||
as are lines whose first non-whitespace character
|
||||
Empty lines and whitespace-only lines are ignored,
|
||||
as are lines whose first non-whitespace character
|
||||
is a `#'.
|
||||
|
||||
multi-line text
|
||||
A logical line starts with non-whitespace text. A
|
||||
line that starts with whitespace continues a logi-
|
||||
A logical line starts with non-whitespace text. A
|
||||
line that starts with whitespace continues a logi-
|
||||
cal line.
|
||||
|
||||
The <i>pattern</i> specifies an email address, a domain name, or
|
||||
a domain name hierarchy, as described in section "TABLE
|
||||
The <i>pattern</i> specifies an email address, a domain name, or
|
||||
a domain name hierarchy, as described in section "TABLE
|
||||
LOOKUP".
|
||||
|
||||
The <i>result</i> is of the form <i>transport</i><b>:</b><i>nexthop</i>. The <i>trans-</i>
|
||||
<i>port</i> field specifies a mail delivery transport such as
|
||||
<b>smtp</b> or <b>local</b>. The <i>nexthop</i> field specifies where and how
|
||||
The <i>result</i> is of the form <i>transport</i><b>:</b><i>nexthop</i>. The <i>trans-</i>
|
||||
<i>port</i> field specifies a mail delivery transport such as
|
||||
<b>smtp</b> or <b>local</b>. The <i>nexthop</i> field specifies where and how
|
||||
to deliver mail. More details are given in section "RESULT
|
||||
FORMAT".
|
||||
|
||||
<b>TABLE</b> <b>LOOKUP</b>
|
||||
With lookups from indexed files such as DB or DBM, or from
|
||||
networked tables such as NIS, LDAP or SQL, patterns are
|
||||
networked tables such as NIS, LDAP or SQL, patterns are
|
||||
tried in the order as listed below:
|
||||
|
||||
<i>user+extension@domain</i> <i>transport</i>:<i>nexthop</i>
|
||||
@ -75,134 +94,134 @@ TRANSPORT(5) TRANSPORT(5)
|
||||
to <i>nexthop</i>.
|
||||
|
||||
<i>domain</i> <i>transport</i>:<i>nexthop</i>
|
||||
Mail for <i>domain</i> is delivered through <i>transport</i> to
|
||||
Mail for <i>domain</i> is delivered through <i>transport</i> to
|
||||
<i>nexthop</i>.
|
||||
|
||||
<i>.domain</i> <i>transport</i>:<i>nexthop</i>
|
||||
Mail for any subdomain of <i>domain</i> is delivered
|
||||
through <i>transport</i> to <i>nexthop</i>. This applies only
|
||||
Mail for any subdomain of <i>domain</i> is delivered
|
||||
through <i>transport</i> to <i>nexthop</i>. This applies only
|
||||
when the string <b>transport</b><i>_</i><b>maps</b> is not listed in the
|
||||
<b>parent</b><i>_</i><b>domain</b><i>_</i><b>matches</b><i>_</i><b>subdomains</b> configuration set-
|
||||
ting. Otherwise, a domain name matches itself and
|
||||
ting. Otherwise, a domain name matches itself and
|
||||
its subdomains.
|
||||
|
||||
Note 1: the special pattern <b>*</b> represents any address (i.e.
|
||||
it functions as the wild-card pattern).
|
||||
|
||||
Note 2: the null recipient address is looked up as
|
||||
Note 2: the null recipient address is looked up as
|
||||
<b>$empty</b><i>_</i><b>address</b><i>_</i><b>recipient</b>@<b>$myhostname</b> (default: mailer-dae-
|
||||
mon@hostname).
|
||||
|
||||
<b>RESULT</b> <b>FORMAT</b>
|
||||
The transport field specifies the name of a mail delivery
|
||||
The transport field specifies the name of a mail delivery
|
||||
transport (the first name of a mail delivery service entry
|
||||
in the Postfix <b>master.cf</b> file).
|
||||
|
||||
The interpretation of the nexthop field is transport
|
||||
The interpretation of the nexthop field is transport
|
||||
dependent. In the case of SMTP, specify <i>host</i>:<i>service</i> for a
|
||||
non-default server port, and use [<i>host</i>] or [<i>host</i>]:<i>port</i> in
|
||||
order to disable MX (mail exchanger) DNS lookups. The []
|
||||
non-default server port, and use [<i>host</i>] or [<i>host</i>]:<i>port</i> in
|
||||
order to disable MX (mail exchanger) DNS lookups. The []
|
||||
form is required when you specify an IP address instead of
|
||||
a hostname.
|
||||
|
||||
A null <i>transport</i> and null <i>nexthop</i> result means "do not
|
||||
change": use the delivery transport and nexthop informa-
|
||||
tion that would be used when the entire transport table
|
||||
A null <i>transport</i> and null <i>nexthop</i> result means "do not
|
||||
change": use the delivery transport and nexthop informa-
|
||||
tion that would be used when the entire transport table
|
||||
did not exist.
|
||||
|
||||
A non-null <i>transport</i> field with a null <i>nexthop</i> field
|
||||
A non-null <i>transport</i> field with a null <i>nexthop</i> field
|
||||
resets the nexthop information to the recipient domain.
|
||||
|
||||
A null <i>transport</i> field with non-null <i>nexthop</i> field does
|
||||
A null <i>transport</i> field with non-null <i>nexthop</i> field does
|
||||
not modify the transport information.
|
||||
|
||||
<b>EXAMPLES</b>
|
||||
In order to deliver internal mail directly, while using a
|
||||
mail relay for all other mail, specify a null entry for
|
||||
internal destinations (do not change the delivery trans-
|
||||
port or the nexthop information) and specify a wildcard
|
||||
In order to deliver internal mail directly, while using a
|
||||
mail relay for all other mail, specify a null entry for
|
||||
internal destinations (do not change the delivery trans-
|
||||
port or the nexthop information) and specify a wildcard
|
||||
for all other destinations.
|
||||
|
||||
<b>my.domain</b> <b>:</b>
|
||||
<b>.my.domain</b> <b>:</b>
|
||||
<b>*</b> <b>smtp:outbound-relay.my.domain</b>
|
||||
|
||||
In order to send mail for <b>foo.org</b> and its subdomains via
|
||||
In order to send mail for <b>foo.org</b> and its subdomains via
|
||||
the <b>uucp</b> transport to the UUCP host named <b>foo</b>:
|
||||
|
||||
<b>foo.org</b> <b>uucp:foo</b>
|
||||
<b>.foo.org</b> <b>uucp:foo</b>
|
||||
|
||||
When no nexthop host name is specified, the destination
|
||||
domain name is used instead. For example, the following
|
||||
directs mail for <i>user</i>@<b>foo.org</b> via the <b>slow</b> transport to a
|
||||
mail exchanger for <b>foo.org</b>. The <b>slow</b> transport could be
|
||||
something that runs at most one delivery process at a
|
||||
When no nexthop host name is specified, the destination
|
||||
domain name is used instead. For example, the following
|
||||
directs mail for <i>user</i>@<b>foo.org</b> via the <b>slow</b> transport to a
|
||||
mail exchanger for <b>foo.org</b>. The <b>slow</b> transport could be
|
||||
something that runs at most one delivery process at a
|
||||
time:
|
||||
|
||||
<b>foo.org</b> <b>slow:</b>
|
||||
|
||||
When no transport is specified, Postfix uses the transport
|
||||
that matches the address domain class (see TRANSPORT FIELD
|
||||
discussion above). The following sends all mail for
|
||||
discussion above). The following sends all mail for
|
||||
<b>foo.org</b> and its subdomains to host <b>gateway.foo.org</b>:
|
||||
|
||||
<b>foo.org</b> <b>:[gateway.foo.org]</b>
|
||||
<b>.foo.org</b> <b>:[gateway.foo.org]</b>
|
||||
|
||||
In the above example, the [] are used to suppress MX
|
||||
lookups. The result would likely point to your local
|
||||
In the above example, the [] are used to suppress MX
|
||||
lookups. The result would likely point to your local
|
||||
machine.
|
||||
|
||||
In the case of delivery via SMTP, one may specify <i>host-</i>
|
||||
In the case of delivery via SMTP, one may specify <i>host-</i>
|
||||
<i>name</i>:<i>service</i> instead of just a host:
|
||||
|
||||
<b>foo.org</b> <b>smtp:bar.org:2025</b>
|
||||
|
||||
This directs mail for <i>user</i>@<b>foo.org</b> to host <b>bar.org</b> port
|
||||
<b>2025</b>. Instead of a numerical port a symbolic name may be
|
||||
used. Specify [] around the hostname in order to disable
|
||||
This directs mail for <i>user</i>@<b>foo.org</b> to host <b>bar.org</b> port
|
||||
<b>2025</b>. Instead of a numerical port a symbolic name may be
|
||||
used. Specify [] around the hostname in order to disable
|
||||
MX lookups.
|
||||
|
||||
The error mailer can be used to bounce mail:
|
||||
|
||||
<b>.foo.org</b> <b>error:mail</b> <b>for</b> <b>*.foo.org</b> <b>is</b> <b>not</b> <b>deliv-</b>
|
||||
<b>.foo.org</b> <b>error:mail</b> <b>for</b> <b>*.foo.org</b> <b>is</b> <b>not</b> <b>deliv-</b>
|
||||
<b>erable</b>
|
||||
|
||||
This causes all mail for <i>user</i>@<i>anything</i><b>.foo.org</b> to be
|
||||
This causes all mail for <i>user</i>@<i>anything</i><b>.foo.org</b> to be
|
||||
bounced.
|
||||
|
||||
<b>REGULAR</b> <b>EXPRESSION</b> <b>TABLES</b>
|
||||
This section describes how the table lookups change when
|
||||
This section describes how the table lookups change when
|
||||
the table is given in the form of regular expressions. For
|
||||
a description of regular expression lookup table syntax,
|
||||
a description of regular expression lookup table syntax,
|
||||
see <a href="regexp_table.5.html"><b>regexp</b><i>_</i><b>table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre</b><i>_</i><b>table</b>(5)</a>.
|
||||
|
||||
Each pattern is a regular expression that is applied to
|
||||
Each pattern is a regular expression that is applied to
|
||||
the entire domain being looked up. Thus, <i>some.domain.hier-</i>
|
||||
<i>archy</i> is not broken up into parent domains.
|
||||
|
||||
Patterns are applied in the order as specified in the
|
||||
table, until a pattern is found that matches the search
|
||||
Patterns are applied in the order as specified in the
|
||||
table, until a pattern is found that matches the search
|
||||
string.
|
||||
|
||||
Results are the same as with indexed file lookups, with
|
||||
the additional feature that parenthesized substrings from
|
||||
Results are the same as with indexed file lookups, with
|
||||
the additional feature that parenthesized substrings from
|
||||
the pattern can be interpolated as <b>$1</b>, <b>$2</b> and so on.
|
||||
|
||||
<b>CONFIGURATION</b> <b>PARAMETERS</b>
|
||||
The following <b>main.cf</b> parameters are especially relevant
|
||||
to this topic. See the Postfix <b>main.cf</b> file for syntax
|
||||
details and for default values. Use the <b>postfix</b> <b>reload</b>
|
||||
The following <b>main.cf</b> parameters are especially relevant
|
||||
to this topic. See the Postfix <b>main.cf</b> file for syntax
|
||||
details and for default values. Use the <b>postfix</b> <b>reload</b>
|
||||
command after a configuration change.
|
||||
|
||||
<b>empty</b><i>_</i><b>address</b><i>_</i><b>recipient</b>
|
||||
The address that is looked up instead of the null
|
||||
The address that is looked up instead of the null
|
||||
sender address.
|
||||
|
||||
<b>parent</b><i>_</i><b>domain</b><i>_</i><b>matches</b><i>_</i><b>subdomains</b>
|
||||
List of Postfix features that use <i>domain.tld</i> pat-
|
||||
terns to match <i>sub.domain.tld</i> (as opposed to
|
||||
List of Postfix features that use <i>domain.tld</i> pat-
|
||||
terns to match <i>sub.domain.tld</i> (as opposed to
|
||||
requiring <i>.domain.tld</i> patterns).
|
||||
|
||||
<b>transport</b><i>_</i><b>maps</b>
|
||||
@ -215,7 +234,7 @@ TRANSPORT(5) TRANSPORT(5)
|
||||
<a href="regexp_table.5.html">regexp_table(5)</a> format of POSIX regular expression tables
|
||||
|
||||
<b>LICENSE</b>
|
||||
The Secure Mailer license must be distributed with this
|
||||
The Secure Mailer license must be distributed with this
|
||||
software.
|
||||
|
||||
<b>AUTHOR(S)</b>
|
||||
|
@ -33,9 +33,9 @@ VERIFY(8) VERIFY(8)
|
||||
Update the status of the specified address.
|
||||
|
||||
<b>VRFY</b><i>_</i><b>ADDR</b><i>_</i><b>QUERY</b> <i>address</i>
|
||||
Look up the <i>status</i> and <i>text</i> of the specified
|
||||
address. If the status is unknown, a probe is sent
|
||||
and a default status is returned.
|
||||
Look up the <i>status</i>, <i>last</i> <i>update</i> <i>time</i> and <i>text</i> of
|
||||
the specified address. If the status is unknown, a
|
||||
probe is sent and a default status is returned.
|
||||
|
||||
The server reply status is one of:
|
||||
|
||||
|
@ -12,7 +12,8 @@ COMMANDS= man1/postalias.1 man1/postcat.1 man1/postconf.1 man1/postfix.1 \
|
||||
man1/postmap.1 man1/sendmail.1 man1/mailq.1 man1/newaliases.1 \
|
||||
man1/postqueue.1 man1/postsuper.1
|
||||
CONFIG = man5/access.5 man5/aliases.5 man5/canonical.5 man5/relocated.5 \
|
||||
man5/transport.5 man5/virtual.5 man5/pcre_table.5 man5/regexp_table.5
|
||||
man5/transport.5 man5/virtual.5 man5/pcre_table.5 man5/regexp_table.5 \
|
||||
man5/cidr_table.5 man5/tcp_table.5
|
||||
TOOLS = man1/smtp-sink.1 man1/smtp-source.1 man1/qmqp-sink.1 \
|
||||
man1/qmqp-source.1
|
||||
|
||||
@ -149,6 +150,9 @@ man5/aliases.5: ../proto/aliases
|
||||
man5/canonical.5: ../proto/canonical
|
||||
../mantools/srctoman - $? >$@
|
||||
|
||||
man5/cidr_table.5: ../proto/cidr_table
|
||||
../mantools/srctoman - $? >$@
|
||||
|
||||
man5/pcre_table.5: ../proto/pcre_table
|
||||
../mantools/srctoman - $? >$@
|
||||
|
||||
@ -170,6 +174,9 @@ man1/smtp-sink.1: ../src/smtpstone/smtp-sink.c
|
||||
man1/smtp-source.1: ../src/smtpstone/smtp-source.c
|
||||
../mantools/srctoman $? >$@
|
||||
|
||||
man5/tcp_table.5: ../proto/tcp_table
|
||||
../mantools/srctoman - $? >$@
|
||||
|
||||
man1/qmqp-sink.1: ../src/smtpstone/qmqp-sink.c
|
||||
../mantools/srctoman $? >$@
|
||||
|
||||
|
@ -106,6 +106,9 @@ order to match subdomains.
|
||||
.IP \fInet\fR
|
||||
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 you want to
|
||||
specify arbitrary network blocks.
|
||||
.SH ACTIONS
|
||||
.na
|
||||
.nf
|
||||
@ -194,8 +197,9 @@ The table format does not understand quoting conventions.
|
||||
.SH SEE ALSO
|
||||
.na
|
||||
.nf
|
||||
postmap(1) create mapping table
|
||||
postmap(1) create lookup table
|
||||
smtpd(8) smtp server
|
||||
cidr_table(5) format of CIDR tables
|
||||
pcre_table(5) format of PCRE tables
|
||||
regexp_table(5) format of POSIX regular expression tables
|
||||
.SH LICENSE
|
||||
|
81
postfix/man/man5/cidr_table.5
Normal file
81
postfix/man/man5/cidr_table.5
Normal file
@ -0,0 +1,81 @@
|
||||
.TH CIDR_TABLE 5
|
||||
.ad
|
||||
.fi
|
||||
.SH NAME
|
||||
cidr_table
|
||||
\-
|
||||
format of Postfix CIDR tables
|
||||
.SH SYNOPSIS
|
||||
.na
|
||||
.nf
|
||||
\fBpostmap -q "\fIstring\fB" cidr:/etc/postfix/\fIfilename\fR
|
||||
|
||||
\fBpostmap -q - cidr:/etc/postfix/\fIfilename\fR <\fIinputfile\fR
|
||||
.SH DESCRIPTION
|
||||
.ad
|
||||
.fi
|
||||
The Postfix mail system uses optional access control tables.
|
||||
These tables are usually in \fBdbm\fR or \fBdb\fR format.
|
||||
Alternatively, access control tables can be specified in CIDR form.
|
||||
|
||||
To find out what types of lookup tables your Postfix system
|
||||
supports use the \fBpostconf -m\fR command.
|
||||
|
||||
To test lookup tables, use the \fBpostmap\fR command as
|
||||
described in the SYNOPSIS above.
|
||||
.SH TABLE FORMAT
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
The general form of a Postfix CIDR table is:
|
||||
.IP "\fInetwork_address\fB/\fInetwork_mask result\fR"
|
||||
When a search string matches the specified network block,
|
||||
use the corresponding \fIresult\fR value.
|
||||
.IP "\fInetwork_address result\fR"
|
||||
When a search string matches the specified network address,
|
||||
use the corresponding \fIresult\fR value.
|
||||
.IP "blank lines and comments"
|
||||
Empty lines and whitespace-only lines are ignored, as
|
||||
are lines whose first non-whitespace character is a `#'.
|
||||
.IP "multi-line text"
|
||||
A logical line starts with non-whitespace text. A line that
|
||||
starts with whitespace continues a logical line.
|
||||
.PP
|
||||
Patterns are applied in the order as specified in the table, until a
|
||||
pattern is found that matches the search string.
|
||||
.SH EXAMPLE SMTPD ACCESS MAP
|
||||
.na
|
||||
.nf
|
||||
/etc/postfix/main.cf:
|
||||
.ti +4
|
||||
smtpd_client_restrictions = ... cidr:/etc/postfix/client_cidr ...
|
||||
|
||||
/etc/postfix/client_cidr:
|
||||
.in +4
|
||||
# Rule order matters. Put more specific whitelist entries
|
||||
# before more general blacklist entries.
|
||||
192.168.1.1 OK
|
||||
192.168.0.0/16 REJECT
|
||||
.in -4
|
||||
.SH SEE ALSO
|
||||
.na
|
||||
.nf
|
||||
regexp_table(5) format of regular expression tables
|
||||
pcre_table(5) format of PCRE tables
|
||||
tcp_table(5) TCP client/server table lookup protocol
|
||||
.SH AUTHOR(S)
|
||||
.na
|
||||
.nf
|
||||
The CIDR table lookup code was originally written by:
|
||||
Jozsef Kadlecsik
|
||||
kadlec@blackhole.kfki.hu
|
||||
KFKI Research Institute for Particle and Nuclear Physics
|
||||
POB. 49
|
||||
1525 Budapest, Hungary
|
||||
|
||||
Adopted and adapted by:
|
||||
Wietse Venema
|
||||
IBM T.J. Watson Research
|
||||
P.O. Box 704
|
||||
Yorktown Heights, NY 10598, USA
|
@ -8,8 +8,6 @@ format of Postfix PCRE tables
|
||||
.SH SYNOPSIS
|
||||
.na
|
||||
.nf
|
||||
\fBpcre:/etc/postfix/\fIfilename\fR
|
||||
|
||||
\fBpostmap -q "\fIstring\fB" pcre:/etc/postfix/\fIfilename\fR
|
||||
|
||||
\fBpostmap -q - pcre:/etc/postfix/\fIfilename\fR <\fIinputfile\fR
|
||||
@ -29,8 +27,9 @@ described in the SYNOPSIS above.
|
||||
|
||||
The general form of a PCRE table is:
|
||||
.IP "\fB/\fIpattern\fB/\fIflags result\fR"
|
||||
When \fIpattern\fR matches a search string, use the corresponding
|
||||
\fIresult\fR value.
|
||||
.IP "\fB!/\fIpattern\fB/\fIflags result\fR"
|
||||
When \fIpattern\fR matches (does not match) a search string, use
|
||||
the corresponding \fIresult\fR value.
|
||||
.IP "blank lines and comments"
|
||||
Empty lines and whitespace-only lines are ignored, as
|
||||
are lines whose first non-whitespace character is a `#'.
|
||||
@ -38,10 +37,12 @@ are lines whose first non-whitespace character is a `#'.
|
||||
A logical line starts with non-whitespace text. A line that
|
||||
starts with whitespace continues a logical line.
|
||||
.IP "\fBif /\fIpattern\fB/\fIflags\fR"
|
||||
.IP "\fBif !/\fIpattern\fB/\fIflags\fR"
|
||||
.IP "\fBendif\fR"
|
||||
Examine the lines between \fBif\fR..\fBendif\fR only if
|
||||
\fIpattern\fR matches. The \fBif\fR..\fBendif\fR can nest.
|
||||
Do not prepend whitespace to patterns inside \fBif\fR..\fBendif\fR.
|
||||
\fIpattern\fR matches (does not match). The \fBif\fR..\fBendif\fR
|
||||
can nest. Do not prepend whitespace to patterns inside
|
||||
\fBif\fR..\fBendif\fR.
|
||||
.PP
|
||||
Each pattern is a perl-like regular expression. The expression
|
||||
delimiter can be any character, except whitespace or characters
|
||||
@ -114,7 +115,9 @@ pattern is found that matches the search string.
|
||||
Substitution of substrings from the matched expression into the result
|
||||
string is possible using the conventional perl syntax ($1, $2, etc.).
|
||||
The macros in the result string may need to be written as ${n}
|
||||
or $(n) if they aren't followed by whitespace.
|
||||
or $(n) if they aren't followed by whitespace. Since negated patterns
|
||||
(those preceded by \fB!\fR) return a result when the expression does
|
||||
not match, substitutions are not available for negated patterns.
|
||||
.SH EXAMPLE SMTPD ACCESS MAP
|
||||
.na
|
||||
.nf
|
||||
@ -147,6 +150,8 @@ or $(n) if they aren't followed by whitespace.
|
||||
.na
|
||||
.nf
|
||||
regexp_table(5) format of POSIX regular expression tables
|
||||
cidr_table(5) format of CIDR tables
|
||||
tcp_table(5) TCP client/server table lookup protocol
|
||||
.SH AUTHOR(S)
|
||||
.na
|
||||
.nf
|
||||
|
@ -8,8 +8,6 @@ format of Postfix regular expression tables
|
||||
.SH SYNOPSIS
|
||||
.na
|
||||
.nf
|
||||
\fBregexp:/etc/postfix/\fIfilename\fR
|
||||
|
||||
\fBpostmap -q "\fIstring\fB" regexp:/etc/postfix/\fIfilename\fR
|
||||
|
||||
\fBpostmap -q - regexp:/etc/postfix/\fIfilename\fR <\fIinputfile\fR
|
||||
@ -71,7 +69,9 @@ pattern is found that matches the search string.
|
||||
Substitution of substrings from the matched expression into the result
|
||||
string is possible using $1, $2, etc.. The macros in the result string
|
||||
may need to be written as ${n} or $(n) if they aren't followed
|
||||
by whitespace.
|
||||
by whitespace. Since negated patterns (those preceded by \fB!\fR)
|
||||
return a result when the expression does not match, substitutions are
|
||||
not available for negated patterns.
|
||||
.SH EXAMPLE SMTPD ACCESS MAP
|
||||
.na
|
||||
.nf
|
||||
@ -104,6 +104,8 @@ endif
|
||||
.na
|
||||
.nf
|
||||
pcre_table(5) format of PCRE tables
|
||||
cidr_table(5) format of CIDR tables
|
||||
tcp_table(5) TCP client/server table lookup protocol
|
||||
.SH AUTHOR(S)
|
||||
.na
|
||||
.nf
|
||||
|
96
postfix/man/man5/tcp_table.5
Normal file
96
postfix/man/man5/tcp_table.5
Normal file
@ -0,0 +1,96 @@
|
||||
.TH TCP_TABLE 5
|
||||
.ad
|
||||
.fi
|
||||
.SH NAME
|
||||
tcp_table
|
||||
\-
|
||||
Postfix client/server table lookup protocol
|
||||
.SH SYNOPSIS
|
||||
.na
|
||||
.nf
|
||||
\fBpostmap -q "\fIstring\fB" tcp:\fIhost:port\fR
|
||||
|
||||
\fBpostmap -q - regexp:\fIhost:port\fR <\fIinputfile\fR
|
||||
.SH DESCRIPTION
|
||||
.ad
|
||||
.fi
|
||||
The Postfix mail system uses optional tables for address
|
||||
rewriting or mail routing. These tables are usually in
|
||||
\fBdbm\fR or \fBdb\fR format. Alternatively, lookup tables
|
||||
can be specified as a TCP client/server pair.
|
||||
|
||||
To find out what types of lookup tables your Postfix system
|
||||
supports use the \fBpostconf -m\fR command.
|
||||
|
||||
To test lookup tables, use the \fBpostmap\fR command as
|
||||
described in the SYNOPSIS above.
|
||||
.SH PROTOCOL DESCRIPTION
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
The TCP map class implements a very simple protocol: the client
|
||||
sends a request, and the server sends one reply. Requests and
|
||||
replies are sent as one line of ASCII text, terminated by the
|
||||
ASCII newline character. Request and reply parameters (see below)
|
||||
are separated by whitespace.
|
||||
.SH ENCODING
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
In request and reply parameters, the character % and any non-printing
|
||||
and whitespace characters must be replaced by %XX, XX being the
|
||||
corresponding ASCII hexadecimal character value. The hexadecimal codes
|
||||
can be specified in any case (upper, lower, mixed).
|
||||
.SH REQUEST FORMAT
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
Requests are strings that serve as lookup key in the simulated
|
||||
table.
|
||||
.IP "\fBget\fR SPACE \fIkey\fR NEWLINE"
|
||||
Look up data under the specified key.
|
||||
.IP "\fBput\fR SPACE \fIkey\fR SPACE \fIvalue\fR NEWLINE"
|
||||
This request is currently not implemented.
|
||||
.SH REPLY FORMAT
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
Replies must be no longer than 4096 characters including the
|
||||
newline terminator, and must have the following form:
|
||||
.IP "\fB500\fR SPACE \fIoptional-text\fR NEWLINE"
|
||||
In case of a lookup request, the requested data does not exist.
|
||||
In case of an update request, the request was rejected.
|
||||
.IP "\fB400\fR SPACE \fIoptional-text\fR NEWLINE"
|
||||
This indicates an error condition. The text gives the nature of
|
||||
the problem. The client should retry the request later.
|
||||
.IP "\fB200\fR SPACE \fItext\fR NEWLINE"
|
||||
The request was successful. In the case of a lookup request,
|
||||
the text contains an encoded version of the requested data.
|
||||
Otherwise the text is optional.
|
||||
.SH SEE ALSO
|
||||
.na
|
||||
.nf
|
||||
regexp_table(5) format of regular expression tables
|
||||
pcre_table(5) format of PCRE tables
|
||||
cidr_table(5) format of CIDR tables
|
||||
.SH BUGS
|
||||
.ad
|
||||
.fi
|
||||
Only the lookup method is currently implemented.
|
||||
.SH LICENSE
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
The Secure Mailer license must be distributed with this software.
|
||||
.SH AUTHOR(S)
|
||||
.na
|
||||
.nf
|
||||
Wietse Venema
|
||||
IBM T.J. Watson Research
|
||||
P.O. Box 704
|
||||
Yorktown Heights, NY 10598, USA
|
@ -20,6 +20,21 @@ The optional \fBtransport\fR table specifies a mapping from email
|
||||
addresses to message delivery transports and/or relay hosts. The
|
||||
mapping is used by the \fBtrivial-rewrite\fR(8) daemon.
|
||||
|
||||
This mapping overrides the default routing that is built into
|
||||
Postfix:
|
||||
.IP \fBmydestination\fR
|
||||
A list of domains that is by default delivered via
|
||||
\fB$local_transport\fR.
|
||||
.IP \fBvirtual_mailbox_domains\fR
|
||||
A list of domains that is by default delivered via
|
||||
\fB$virtual_transport\fR.
|
||||
.IP \fBrelay_domains\fR
|
||||
A list of domains that is by default delivered via
|
||||
\fB$relay_transport\fR.
|
||||
.IP "any other destination"
|
||||
Mail for any other destination is by default delivered via
|
||||
\fB$default_transport\fR.
|
||||
.PP
|
||||
Normally, the \fBtransport\fR table is specified as a text file
|
||||
that serves as input to the \fBpostmap\fR(1) command.
|
||||
The result, an indexed file in \fBdbm\fR or \fBdb\fR format, is used
|
||||
|
@ -150,6 +150,11 @@ substitution is done before all other address rewriting.
|
||||
.IP \fBcanonical_maps\fR
|
||||
Address mapping lookup table for sender and recipient addresses
|
||||
in envelopes and headers.
|
||||
.IP \fBenable_original_recipient\fR
|
||||
Enable support for the X-Original-To message header, which is
|
||||
needed for multi-recipient mailboxes. When this is enabled, Postfix
|
||||
performs duplicate elimination on (original recipient, rewritten
|
||||
recipient) pairs, instead of looking at the rewritten recipient only.
|
||||
.IP \fBrecipient_canonical_maps\fR
|
||||
Address mapping lookup table for envelope and header recipient
|
||||
addresses.
|
||||
|
@ -27,10 +27,6 @@ The SMTP client looks up a list of mail exchanger addresses for
|
||||
the destination host, sorts the list by preference, and connects
|
||||
to each listed address until it finds a server that responds.
|
||||
|
||||
When the domain or host is specified as a comma/whitespace
|
||||
separated list, the SMTP client repeats the above process
|
||||
for all destinations until it finds a server that responds.
|
||||
|
||||
Once the SMTP client has received the server greeting banner, no
|
||||
error will cause it to proceed to the next address on the mail
|
||||
exchanger list. Instead, the message is either bounced, or its
|
||||
@ -134,6 +130,9 @@ Length limit for SMTP message content lines. Zero means no limit.
|
||||
Some SMTP servers misbehave on long lines.
|
||||
.IP \fBsmtp_helo_name\fR
|
||||
The hostname to be used in HELO and EHLO commands.
|
||||
.IP \fBsmtp_quote_rfc821_envelope\fR
|
||||
Whether or not to quote MAIL FROM and RCPT TO addresses as
|
||||
per the rules laid out in RFC 821.
|
||||
.IP \fBsmtp_skip_4xx_greeting\fR
|
||||
Skip servers that greet us with a 4xx status code.
|
||||
.IP \fBsmtp_skip_5xx_greeting\fR
|
||||
|
@ -111,6 +111,24 @@ Disallow anonymous logins.
|
||||
Maps that specify the SASL login name that owns a MAIL FROM sender
|
||||
address. Used by the \fBreject_sender_login_mismatch\fR sender
|
||||
anti-spoofing restriction.
|
||||
.SH "Pass-through proxy"
|
||||
.ad
|
||||
.fi
|
||||
.ad
|
||||
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.
|
||||
.IP \fBsmtpd_proxy_filter\fR
|
||||
The \fIhost:port\fR of the SMTP proxy server. The \fIhost\fR
|
||||
or \fIhost:\fR portion is optional.
|
||||
.IP \fBsmtpd_proxy_timeout\fR
|
||||
Timeout for connecting to, sending to and receiving from
|
||||
the SMTP proxy server.
|
||||
.IP \fBsmtpd_proxy_ehlo\fR
|
||||
The hostname to use when sending an EHLO command to the
|
||||
SMTP proxy server.
|
||||
.SH Miscellaneous
|
||||
.ad
|
||||
.fi
|
||||
@ -259,6 +277,21 @@ are eligible for the \fBpermit_mx_backup\fR feature.
|
||||
Restrict what domains this mail system will relay
|
||||
mail to. The domains are routed to the delivery agent
|
||||
specified with the \fBrelay_transport\fR setting.
|
||||
.SH "Sender/recipient address verification"
|
||||
.ad
|
||||
.fi
|
||||
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 maintained by the address
|
||||
verification service.
|
||||
.IP \fBaddress_verify_poll_count\fR
|
||||
How many times to query the address verification service
|
||||
for completion of an address verification request.
|
||||
Specify 0 to implement a simple form of greylisting.
|
||||
.IP \fBaddress_verify_poll_delay\fR
|
||||
Time to wait after querying the address verification service
|
||||
for completion of an address verification request.
|
||||
.SH "UCE control responses"
|
||||
.ad
|
||||
.fi
|
||||
@ -305,10 +338,11 @@ Response code when a recipient address is known to be undeliverable.
|
||||
.SH SEE ALSO
|
||||
.na
|
||||
.nf
|
||||
trivial-rewrite(8) address resolver
|
||||
cleanup(8) message canonicalization
|
||||
master(8) process manager
|
||||
syslogd(8) system logging
|
||||
trivial-rewrite(8) address resolver
|
||||
verify(8) address verification service
|
||||
.SH LICENSE
|
||||
.na
|
||||
.nf
|
||||
|
@ -35,7 +35,8 @@ This server implements the following requests:
|
||||
.IP "\fBVRFY_ADDR_UPDATE\fI address status text\fR"
|
||||
Update the status of the specified address.
|
||||
.IP "\fBVRFY_ADDR_QUERY\fI address\fR"
|
||||
Look up the \fIstatus\fR and \fItext\fR of the specified address.
|
||||
Look up the \fIstatus\fR, \fIlast update time\fR and \fItext\fR
|
||||
of the specified address.
|
||||
If the status is unknown, a probe is sent and a default status is
|
||||
returned.
|
||||
.PP
|
||||
|
@ -4,7 +4,7 @@ SHELL = /bin/sh
|
||||
|
||||
CONFIG = ../conf/access ../conf/aliases ../conf/canonical ../conf/relocated \
|
||||
../conf/transport ../conf/virtual ../conf/pcre_table \
|
||||
../conf/regexp_table
|
||||
../conf/regexp_table ../conf/cidr_table ../conf/tcp_table
|
||||
|
||||
AWK = awk '{ print; if (NR == 1) print ".pl 9999" }'
|
||||
|
||||
@ -30,6 +30,9 @@ clobber:
|
||||
../conf/canonical: canonical
|
||||
srctoman - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
|
||||
|
||||
../conf/cidr_table: cidr_table
|
||||
srctoman - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
|
||||
|
||||
../conf/pcre_table: pcre_table
|
||||
srctoman - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
|
||||
|
||||
@ -39,6 +42,9 @@ clobber:
|
||||
../conf/relocated: relocated
|
||||
srctoman - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
|
||||
|
||||
../conf/tcp_table: tcp_table
|
||||
srctoman - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
|
||||
|
||||
../conf/transport: transport
|
||||
srctoman - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
|
||||
|
||||
|
@ -92,6 +92,9 @@
|
||||
# .IP \fInet\fR
|
||||
# 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 you want to
|
||||
# specify arbitrary network blocks.
|
||||
# ACTIONS
|
||||
# .ad
|
||||
# .fi
|
||||
@ -172,8 +175,9 @@
|
||||
# BUGS
|
||||
# The table format does not understand quoting conventions.
|
||||
# SEE ALSO
|
||||
# postmap(1) create mapping table
|
||||
# postmap(1) create lookup table
|
||||
# smtpd(8) smtp server
|
||||
# cidr_table(5) format of CIDR tables
|
||||
# pcre_table(5) format of PCRE tables
|
||||
# regexp_table(5) format of POSIX regular expression tables
|
||||
# LICENSE
|
||||
|
68
postfix/proto/cidr_table
Normal file
68
postfix/proto/cidr_table
Normal file
@ -0,0 +1,68 @@
|
||||
#++
|
||||
# NAME
|
||||
# cidr_table 5
|
||||
# SUMMARY
|
||||
# format of Postfix CIDR tables
|
||||
# SYNOPSIS
|
||||
# \fBpostmap -q "\fIstring\fB" cidr:/etc/postfix/\fIfilename\fR
|
||||
#
|
||||
# \fBpostmap -q - cidr:/etc/postfix/\fIfilename\fR <\fIinputfile\fR
|
||||
# DESCRIPTION
|
||||
# The Postfix mail system uses optional access control tables.
|
||||
# These tables are usually in \fBdbm\fR or \fBdb\fR format.
|
||||
# Alternatively, access control tables can be specified in CIDR form.
|
||||
#
|
||||
# To find out what types of lookup tables your Postfix system
|
||||
# supports use the \fBpostconf -m\fR command.
|
||||
#
|
||||
# To test lookup tables, use the \fBpostmap\fR command as
|
||||
# described in the SYNOPSIS above.
|
||||
# TABLE FORMAT
|
||||
# .ad
|
||||
# .fi
|
||||
# The general form of a Postfix CIDR table is:
|
||||
# .IP "\fInetwork_address\fB/\fInetwork_mask result\fR"
|
||||
# When a search string matches the specified network block,
|
||||
# use the corresponding \fIresult\fR value.
|
||||
# .IP "\fInetwork_address result\fR"
|
||||
# When a search string matches the specified network address,
|
||||
# use the corresponding \fIresult\fR value.
|
||||
# .IP "blank lines and comments"
|
||||
# Empty lines and whitespace-only lines are ignored, as
|
||||
# are lines whose first non-whitespace character is a `#'.
|
||||
# .IP "multi-line text"
|
||||
# A logical line starts with non-whitespace text. A line that
|
||||
# starts with whitespace continues a logical line.
|
||||
# .PP
|
||||
# Patterns are applied in the order as specified in the table, until a
|
||||
# pattern is found that matches the search string.
|
||||
# EXAMPLE SMTPD ACCESS MAP
|
||||
# /etc/postfix/main.cf:
|
||||
# .ti +4
|
||||
# smtpd_client_restrictions = ... cidr:/etc/postfix/client_cidr ...
|
||||
#
|
||||
# /etc/postfix/client_cidr:
|
||||
# .in +4
|
||||
# # Rule order matters. Put more specific whitelist entries
|
||||
# # before more general blacklist entries.
|
||||
# 192.168.1.1 OK
|
||||
# 192.168.0.0/16 REJECT
|
||||
# .in -4
|
||||
# SEE ALSO
|
||||
# regexp_table(5) format of regular expression tables
|
||||
# pcre_table(5) format of PCRE tables
|
||||
# tcp_table(5) TCP client/server table lookup protocol
|
||||
# AUTHOR(S)
|
||||
# The CIDR table lookup code was originally written by:
|
||||
# Jozsef Kadlecsik
|
||||
# kadlec@blackhole.kfki.hu
|
||||
# KFKI Research Institute for Particle and Nuclear Physics
|
||||
# POB. 49
|
||||
# 1525 Budapest, Hungary
|
||||
#
|
||||
# Adopted and adapted by:
|
||||
# Wietse Venema
|
||||
# IBM T.J. Watson Research
|
||||
# P.O. Box 704
|
||||
# Yorktown Heights, NY 10598, USA
|
||||
#--
|
@ -4,8 +4,6 @@
|
||||
# SUMMARY
|
||||
# format of Postfix PCRE tables
|
||||
# SYNOPSIS
|
||||
# \fBpcre:/etc/postfix/\fIfilename\fR
|
||||
#
|
||||
# \fBpostmap -q "\fIstring\fB" pcre:/etc/postfix/\fIfilename\fR
|
||||
#
|
||||
# \fBpostmap -q - pcre:/etc/postfix/\fIfilename\fR <\fIinputfile\fR
|
||||
@ -23,8 +21,9 @@
|
||||
#
|
||||
# The general form of a PCRE table is:
|
||||
# .IP "\fB/\fIpattern\fB/\fIflags result\fR"
|
||||
# When \fIpattern\fR matches a search string, use the corresponding
|
||||
# \fIresult\fR value.
|
||||
# .IP "\fB!/\fIpattern\fB/\fIflags result\fR"
|
||||
# When \fIpattern\fR matches (does not match) a search string, use
|
||||
# the corresponding \fIresult\fR value.
|
||||
# .IP "blank lines and comments"
|
||||
# Empty lines and whitespace-only lines are ignored, as
|
||||
# are lines whose first non-whitespace character is a `#'.
|
||||
@ -32,10 +31,12 @@
|
||||
# A logical line starts with non-whitespace text. A line that
|
||||
# starts with whitespace continues a logical line.
|
||||
# .IP "\fBif /\fIpattern\fB/\fIflags\fR"
|
||||
# .IP "\fBif !/\fIpattern\fB/\fIflags\fR"
|
||||
# .IP "\fBendif\fR"
|
||||
# Examine the lines between \fBif\fR..\fBendif\fR only if
|
||||
# \fIpattern\fR matches. The \fBif\fR..\fBendif\fR can nest.
|
||||
# Do not prepend whitespace to patterns inside \fBif\fR..\fBendif\fR.
|
||||
# \fIpattern\fR matches (does not match). The \fBif\fR..\fBendif\fR
|
||||
# can nest. Do not prepend whitespace to patterns inside
|
||||
# \fBif\fR..\fBendif\fR.
|
||||
# .PP
|
||||
# Each pattern is a perl-like regular expression. The expression
|
||||
# delimiter can be any character, except whitespace or characters
|
||||
@ -108,7 +109,9 @@
|
||||
# Substitution of substrings from the matched expression into the result
|
||||
# string is possible using the conventional perl syntax ($1, $2, etc.).
|
||||
# The macros in the result string may need to be written as ${n}
|
||||
# or $(n) if they aren't followed by whitespace.
|
||||
# or $(n) if they aren't followed by whitespace. Since negated patterns
|
||||
# (those preceded by \fB!\fR) return a result when the expression does
|
||||
# not match, substitutions are not available for negated patterns.
|
||||
# EXAMPLE SMTPD ACCESS MAP
|
||||
# # Protect your outgoing majordomo exploders
|
||||
# /^(?!owner-)(.*)-outgoing@(.*)/ 550 Use ${1}@${2} instead
|
||||
@ -133,6 +136,8 @@
|
||||
# # Put your own body patterns here.
|
||||
# SEE ALSO
|
||||
# regexp_table(5) format of POSIX regular expression tables
|
||||
# cidr_table(5) format of CIDR tables
|
||||
# tcp_table(5) TCP client/server table lookup protocol
|
||||
# AUTHOR(S)
|
||||
# The PCRE table lookup code was originally written by:
|
||||
# Andrew McNamara
|
||||
|
@ -4,8 +4,6 @@
|
||||
# SUMMARY
|
||||
# format of Postfix regular expression tables
|
||||
# SYNOPSIS
|
||||
# \fBregexp:/etc/postfix/\fIfilename\fR
|
||||
#
|
||||
# \fBpostmap -q "\fIstring\fB" regexp:/etc/postfix/\fIfilename\fR
|
||||
#
|
||||
# \fBpostmap -q - regexp:/etc/postfix/\fIfilename\fR <\fIinputfile\fR
|
||||
@ -65,7 +63,9 @@
|
||||
# Substitution of substrings from the matched expression into the result
|
||||
# string is possible using $1, $2, etc.. The macros in the result string
|
||||
# may need to be written as ${n} or $(n) if they aren't followed
|
||||
# by whitespace.
|
||||
# by whitespace. Since negated patterns (those preceded by \fB!\fR)
|
||||
# return a result when the expression does not match, substitutions are
|
||||
# not available for negated patterns.
|
||||
# EXAMPLE SMTPD ACCESS MAP
|
||||
# # Disallow sender-specified routing. This is a must if you relay mail
|
||||
# # for other domains.
|
||||
@ -90,6 +90,8 @@
|
||||
# # Put your own body patterns here.
|
||||
# SEE ALSO
|
||||
# pcre_table(5) format of PCRE tables
|
||||
# cidr_table(5) format of CIDR tables
|
||||
# tcp_table(5) TCP client/server table lookup protocol
|
||||
# AUTHOR(S)
|
||||
# The regexp table lookup code was originally written by:
|
||||
# LaMont Jones
|
||||
|
75
postfix/proto/tcp_table
Normal file
75
postfix/proto/tcp_table
Normal file
@ -0,0 +1,75 @@
|
||||
#++
|
||||
# NAME
|
||||
# tcp_table 5
|
||||
# SUMMARY
|
||||
# Postfix client/server table lookup protocol
|
||||
# SYNOPSIS
|
||||
# \fBpostmap -q "\fIstring\fB" tcp:\fIhost:port\fR
|
||||
#
|
||||
# \fBpostmap -q - regexp:\fIhost:port\fR <\fIinputfile\fR
|
||||
# DESCRIPTION
|
||||
# The Postfix mail system uses optional tables for address
|
||||
# rewriting or mail routing. These tables are usually in
|
||||
# \fBdbm\fR or \fBdb\fR format. Alternatively, lookup tables
|
||||
# can be specified as a TCP client/server pair.
|
||||
#
|
||||
# To find out what types of lookup tables your Postfix system
|
||||
# supports use the \fBpostconf -m\fR command.
|
||||
#
|
||||
# To test lookup tables, use the \fBpostmap\fR command as
|
||||
# described in the SYNOPSIS above.
|
||||
# PROTOCOL DESCRIPTION
|
||||
# .ad
|
||||
# .fi
|
||||
# The TCP map class implements a very simple protocol: the client
|
||||
# sends a request, and the server sends one reply. Requests and
|
||||
# replies are sent as one line of ASCII text, terminated by the
|
||||
# ASCII newline character. Request and reply parameters (see below)
|
||||
# are separated by whitespace.
|
||||
# ENCODING
|
||||
# .ad
|
||||
# .fi
|
||||
# In request and reply parameters, the character % and any non-printing
|
||||
# and whitespace characters must be replaced by %XX, XX being the
|
||||
# corresponding ASCII hexadecimal character value. The hexadecimal codes
|
||||
# can be specified in any case (upper, lower, mixed).
|
||||
# REQUEST FORMAT
|
||||
# .ad
|
||||
# .fi
|
||||
# Requests are strings that serve as lookup key in the simulated
|
||||
# table.
|
||||
# .IP "\fBget\fR SPACE \fIkey\fR NEWLINE"
|
||||
# Look up data under the specified key.
|
||||
# .IP "\fBput\fR SPACE \fIkey\fR SPACE \fIvalue\fR NEWLINE"
|
||||
# This request is currently not implemented.
|
||||
# REPLY FORMAT
|
||||
# .ad
|
||||
# .fi
|
||||
# Replies must be no longer than 4096 characters including the
|
||||
# newline terminator, and must have the following form:
|
||||
# .IP "\fB500\fR SPACE \fIoptional-text\fR NEWLINE"
|
||||
# In case of a lookup request, the requested data does not exist.
|
||||
# In case of an update request, the request was rejected.
|
||||
# .IP "\fB400\fR SPACE \fIoptional-text\fR NEWLINE"
|
||||
# This indicates an error condition. The text gives the nature of
|
||||
# the problem. The client should retry the request later.
|
||||
# .IP "\fB200\fR SPACE \fItext\fR NEWLINE"
|
||||
# The request was successful. In the case of a lookup request,
|
||||
# the text contains an encoded version of the requested data.
|
||||
# Otherwise the text is optional.
|
||||
# SEE ALSO
|
||||
# regexp_table(5) format of regular expression tables
|
||||
# pcre_table(5) format of PCRE tables
|
||||
# cidr_table(5) format of CIDR tables
|
||||
# BUGS
|
||||
# Only the lookup method is currently implemented.
|
||||
# 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
|
||||
#--*/
|
@ -14,6 +14,21 @@
|
||||
# addresses to message delivery transports and/or relay hosts. The
|
||||
# mapping is used by the \fBtrivial-rewrite\fR(8) daemon.
|
||||
#
|
||||
# This mapping overrides the default routing that is built into
|
||||
# Postfix:
|
||||
# .IP \fBmydestination\fR
|
||||
# A list of domains that is by default delivered via
|
||||
# \fB$local_transport\fR.
|
||||
# .IP \fBvirtual_mailbox_domains\fR
|
||||
# A list of domains that is by default delivered via
|
||||
# \fB$virtual_transport\fR.
|
||||
# .IP \fBrelay_domains\fR
|
||||
# A list of domains that is by default delivered via
|
||||
# \fB$relay_transport\fR.
|
||||
# .IP "any other destination"
|
||||
# Mail for any other destination is by default delivered via
|
||||
# \fB$default_transport\fR.
|
||||
# .PP
|
||||
# Normally, the \fBtransport\fR table is specified as a text file
|
||||
# that serves as input to the \fBpostmap\fR(1) command.
|
||||
# The result, an indexed file in \fBdbm\fR or \fBdb\fR format, is used
|
||||
|
@ -132,6 +132,8 @@ bounce_notify_util.o: ../../include/vstring.h
|
||||
bounce_notify_util.o: ../../include/vbuf.h
|
||||
bounce_notify_util.o: ../../include/vstream.h
|
||||
bounce_notify_util.o: ../../include/line_wrap.h
|
||||
bounce_notify_util.o: ../../include/stringops.h
|
||||
bounce_notify_util.o: ../../include/xtext.h
|
||||
bounce_notify_util.o: ../../include/mail_queue.h
|
||||
bounce_notify_util.o: ../../include/quote_822_local.h
|
||||
bounce_notify_util.o: ../../include/quote_flags.h
|
||||
|
@ -155,6 +155,8 @@
|
||||
#include <vstring.h>
|
||||
#include <vstream.h>
|
||||
#include <line_wrap.h>
|
||||
#include <stringops.h>
|
||||
#include <xtext.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
@ -210,10 +212,19 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
|
||||
}
|
||||
bounce_info->flush = flush;
|
||||
bounce_info->buf = vstring_alloc(100);
|
||||
bounce_info->sender = vstring_alloc(100);
|
||||
bounce_info->arrival_time = 0;
|
||||
bounce_info->orig_offs = 0;
|
||||
bounce_info->log_handle = log_handle;
|
||||
|
||||
/*
|
||||
* RFC 1894: diagnostic-type is an RFC 822 atom. We use X-$mail_name and
|
||||
* must ensure it is valid.
|
||||
*/
|
||||
bounce_info->mail_name = mystrdup(var_mail_name);
|
||||
translit(bounce_info->mail_name, " \t\r\n()<>@,;:\\\".[]",
|
||||
"-----------------");
|
||||
|
||||
/*
|
||||
* Compute a supposedly unique boundary string. This assumes that a queue
|
||||
* ID and a hostname contain acceptable characters for a boundary string,
|
||||
@ -247,7 +258,16 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
|
||||
if (rec_type == REC_TYPE_TIME && bounce_info->arrival_time == 0) {
|
||||
if ((bounce_info->arrival_time = atol(STR(bounce_info->buf))) < 0)
|
||||
bounce_info->arrival_time = 0;
|
||||
} else if (rec_type == REC_TYPE_FROM) {
|
||||
quote_822_local_flags(bounce_info->sender,
|
||||
VSTRING_LEN(bounce_info->buf) ?
|
||||
STR(bounce_info->buf) :
|
||||
mail_addr_mail_daemon(), 0);
|
||||
} else if (rec_type == REC_TYPE_MESG) {
|
||||
/* XXX Future: sender+recipient after message content. */
|
||||
if (VSTRING_LEN(bounce_info->sender) == 0)
|
||||
msg_warn("%s: no sender before message content record",
|
||||
bounce_info->queue_id);
|
||||
bounce_info->orig_offs = vstream_ftell(bounce_info->orig_fp);
|
||||
break;
|
||||
}
|
||||
@ -322,6 +342,8 @@ void bounce_mail_free(BOUNCE_INFO *bounce_info)
|
||||
bounce_info->queue_id, bounce_info->queue_name,
|
||||
bounce_info->queue_id);
|
||||
vstring_free(bounce_info->buf);
|
||||
vstring_free(bounce_info->sender);
|
||||
myfree(bounce_info->mail_name);
|
||||
myfree((char *) bounce_info->mime_boundary);
|
||||
myfree((char *) bounce_info);
|
||||
}
|
||||
@ -542,6 +564,11 @@ int bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
|
||||
#if 0
|
||||
post_mail_fprintf(bounce, "Received-From-MTA: dns; %s", "whatever");
|
||||
#endif
|
||||
post_mail_fprintf(bounce, "X-%s-Queue-ID: %s",
|
||||
bounce_info->mail_name, bounce_info->queue_id);
|
||||
if (VSTRING_LEN(bounce_info->sender) > 0)
|
||||
post_mail_fprintf(bounce, "X-%s-Sender: rfc822; %s",
|
||||
bounce_info->mail_name, STR(bounce_info->sender));
|
||||
if (bounce_info->arrival_time > 0)
|
||||
post_mail_fprintf(bounce, "Arrival-Date: %s",
|
||||
mail_date(bounce_info->arrival_time));
|
||||
@ -552,25 +579,21 @@ int bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
|
||||
|
||||
int bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
|
||||
{
|
||||
char *fixed_mail_name;
|
||||
|
||||
post_mail_fputs(bounce, "");
|
||||
post_mail_fprintf(bounce, "Final-Recipient: rfc822; %s",
|
||||
bounce_info->log_handle->recipient);
|
||||
if (bounce_info->log_handle->orig_rcpt)
|
||||
if (bounce_info->log_handle->orig_rcpt) {
|
||||
xtext_quote(bounce_info->buf, bounce_info->log_handle->orig_rcpt, "+=");
|
||||
post_mail_fprintf(bounce, "Original-Recipient: rfc822; %s",
|
||||
bounce_info->log_handle->orig_rcpt);
|
||||
STR(bounce_info->buf));
|
||||
}
|
||||
post_mail_fprintf(bounce, "Action: %s",
|
||||
bounce_info->flush == BOUNCE_MSG_FAIL ?
|
||||
"failed" : bounce_info->log_handle->dsn_action);
|
||||
post_mail_fprintf(bounce, "Status: %s",
|
||||
bounce_info->log_handle->dsn_status);
|
||||
/* RFC 1894: diagnostic-type is an RFC 822 atom. */
|
||||
fixed_mail_name = mystrdup(var_mail_name);
|
||||
translit(fixed_mail_name, " \t\r\n()<>@,;:\\\".[]", "-----------------");
|
||||
bounce_print_wrap(bounce, bounce_info, "Diagnostic-Code: X-%s; %s",
|
||||
fixed_mail_name, bounce_info->log_handle->text);
|
||||
myfree(fixed_mail_name);
|
||||
bounce_info->mail_name, bounce_info->log_handle->text);
|
||||
#if 0
|
||||
post_mail_fprintf(bounce, "Last-Attempt-Date: %s",
|
||||
bounce_info->log_handle->log_time);
|
||||
|
@ -69,10 +69,12 @@ typedef struct {
|
||||
const char *mime_boundary; /* for MIME */
|
||||
int flush; /* 0=defer, other=bounce */
|
||||
VSTRING *buf; /* scratch pad */
|
||||
VSTRING *sender; /* envelope sender */
|
||||
VSTREAM *orig_fp; /* open queue file */
|
||||
long orig_offs; /* start of content */
|
||||
time_t arrival_time; /* time of arrival */
|
||||
BOUNCE_LOG *log_handle; /* open logfile */
|
||||
char *mail_name; /* $mail_name, cooked */
|
||||
} BOUNCE_INFO;
|
||||
|
||||
extern BOUNCE_INFO *bounce_mail_init(const char *, const char *, const char *, const char *, int);
|
||||
|
@ -136,6 +136,11 @@
|
||||
/* .IP \fBcanonical_maps\fR
|
||||
/* Address mapping lookup table for sender and recipient addresses
|
||||
/* in envelopes and headers.
|
||||
/* .IP \fBenable_original_recipient\fR
|
||||
/* Enable support for the X-Original-To message header, which is
|
||||
/* needed for multi-recipient mailboxes. When this is enabled, Postfix
|
||||
/* performs duplicate elimination on (original recipient, rewritten
|
||||
/* recipient) pairs, instead of looking at the rewritten recipient only.
|
||||
/* .IP \fBrecipient_canonical_maps\fR
|
||||
/* Address mapping lookup table for envelope and header recipient
|
||||
/* addresses.
|
||||
@ -342,6 +347,7 @@ int main(int argc, char **argv)
|
||||
*/
|
||||
single_server_main(argc, argv, cleanup_service,
|
||||
MAIL_SERVER_INT_TABLE, cleanup_int_table,
|
||||
MAIL_SERVER_BOOL_TABLE, cleanup_bool_table,
|
||||
MAIL_SERVER_STR_TABLE, cleanup_str_table,
|
||||
MAIL_SERVER_TIME_TABLE, cleanup_time_table,
|
||||
MAIL_SERVER_PRE_INIT, cleanup_pre_jail,
|
||||
|
@ -127,6 +127,7 @@ extern void cleanup_all(void);
|
||||
extern void cleanup_pre_jail(char *, char **);
|
||||
extern void cleanup_post_jail(char *, char **);
|
||||
extern CONFIG_INT_TABLE cleanup_int_table[];
|
||||
extern CONFIG_BOOL_TABLE cleanup_bool_table[];
|
||||
extern CONFIG_STR_TABLE cleanup_str_table[];
|
||||
extern CONFIG_TIME_TABLE cleanup_time_table[];
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
/*
|
||||
/* CONFIG_INT_TABLE cleanup_int_table[];
|
||||
/*
|
||||
/* CONFIG_BOOL_TABLE cleanup_bool_table[];
|
||||
/*
|
||||
/* CONFIG_STR_TABLE cleanup_str_table[];
|
||||
/*
|
||||
/* CONFIG_TIME_TABLE cleanup_time_table[];
|
||||
@ -102,6 +104,7 @@ char *var_mimehdr_checks; /* mime header checks */
|
||||
char *var_nesthdr_checks; /* nested header checks */
|
||||
char *var_body_checks; /* any body checks */
|
||||
int var_dup_filter_limit; /* recipient dup filter */
|
||||
bool var_enable_orcpt; /* Include orcpt in dup filter? */
|
||||
char *var_empty_addr; /* destination of bounced bounces */
|
||||
int var_delay_warn_time; /* delay that triggers warning */
|
||||
char *var_prop_extension; /* propagate unmatched extension */
|
||||
@ -125,6 +128,11 @@ CONFIG_INT_TABLE cleanup_int_table[] = {
|
||||
0,
|
||||
};
|
||||
|
||||
CONFIG_BOOL_TABLE cleanup_bool_table[] = {
|
||||
VAR_ENABLE_ORCPT, DEF_ENABLE_ORCPT, &var_enable_orcpt,
|
||||
0,
|
||||
};
|
||||
|
||||
CONFIG_TIME_TABLE cleanup_time_table[] = {
|
||||
VAR_DELAY_WARN_TIME, DEF_DELAY_WARN_TIME, &var_delay_warn_time, 0, 0,
|
||||
0,
|
||||
|
@ -68,6 +68,12 @@ void cleanup_out_recipient(CLEANUP_STATE *state, const char *orcpt,
|
||||
ARGV *argv;
|
||||
char **cpp;
|
||||
|
||||
/*
|
||||
* XXX Not elegant, but eliminates complexity in the record reading loop.
|
||||
*/
|
||||
if (!var_enable_orcpt)
|
||||
orcpt = "";
|
||||
|
||||
/*
|
||||
* Distinguish between different original recipient addresses that map
|
||||
* onto the same mailbox. The recipient will use our original recipient
|
||||
|
@ -77,7 +77,7 @@ TESTPROG= domain_list dot_lockfile mail_addr_crunch mail_addr_find \
|
||||
off_cvt quote_822_local rec2stream recdump resolve_clnt \
|
||||
resolve_local rewrite_clnt stream2rec string_list tok822_parse \
|
||||
quote_821_local mail_conf_time mime_state strip_addr \
|
||||
virtual8_maps verify_clnt
|
||||
virtual8_maps verify_clnt xtext
|
||||
|
||||
LIBS = ../../lib/libutil.a
|
||||
LIB_DIR = ../../lib
|
||||
@ -240,9 +240,14 @@ verify_clnt: $(LIB) $(LIBS)
|
||||
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
|
||||
mv junk $@.o
|
||||
|
||||
xtext: $(LIB)
|
||||
mv $@.o junk
|
||||
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
|
||||
mv junk $@.o
|
||||
|
||||
tests: tok822_test mime_test mime_nest mime_8bit mime_dom mime_trunc \
|
||||
mime_cvt mime_cvt2 mime_cvt3 strip_addr_test tok822_limit_test \
|
||||
virtual8_test
|
||||
virtual8_test xtext_test
|
||||
|
||||
tok822_test: tok822_parse tok822_parse.in tok822_parse.ref
|
||||
./tok822_parse <tok822_parse.in >tok822_parse.tmp 2>&1
|
||||
@ -306,6 +311,12 @@ virtual8_test: virtual8_maps virtual8_map virtual8.in virtual8.ref \
|
||||
diff virtual8.ref virtual8.tmp
|
||||
rm -f virtual8.tmp virtual8_map.db
|
||||
|
||||
xtext_test: xtext
|
||||
./xtext <xtext.c | od -cb >xtext.tmp
|
||||
od -cb <xtext.c >xtext.ref
|
||||
cmp xtext.ref xtext.tmp
|
||||
rm -f xtext.ref xtext.tmp
|
||||
|
||||
# Requires: Postfix running, root privileges
|
||||
|
||||
rewrite_clnt_test: rewrite_clnt rewrite_clnt.in rewrite_clnt.ref
|
||||
@ -1344,7 +1355,7 @@ virtual8_maps.o: strip_addr.h
|
||||
virtual8_maps.o: virtual8_maps.h
|
||||
xtext.o: xtext.c
|
||||
xtext.o: ../../include/sys_defs.h
|
||||
xtext.o: ../../include/vstream.h
|
||||
xtext.o: ../../include/vbuf.h
|
||||
xtext.o: ../../include/msg.h
|
||||
xtext.o: ../../include/vstring.h
|
||||
xtext.o: ../../include/vbuf.h
|
||||
xtext.o: xtext.h
|
||||
|
@ -38,6 +38,7 @@
|
||||
#define CLEANUP_STAT_CONT (1<<3) /* Message content rejected */
|
||||
#define CLEANUP_STAT_HOPS (1<<4) /* Too many hops */
|
||||
#define CLEANUP_STAT_RCPT (1<<6) /* No recipients found */
|
||||
#define CLEANUP_STAT_PROXY (1<<7) /* Proxy reject */
|
||||
|
||||
/*
|
||||
* These are set when we can't bounce even if we were asked to.
|
||||
|
@ -176,11 +176,14 @@ int header_token(HEADER_TOKEN *token, int token_len,
|
||||
if (ch == '"')
|
||||
break;
|
||||
if (ch == '\n') { /* unfold */
|
||||
len = LEN(token_buffer);
|
||||
while (len > 0 && IS_SPACE_TAB_CR_LF(STR(token_buffer)[len - 1]))
|
||||
len--;
|
||||
if (len < LEN(token_buffer))
|
||||
vstring_truncate(token_buffer, len);
|
||||
if (tok_count < token_len) {
|
||||
len = LEN(token_buffer);
|
||||
while (len > 0
|
||||
&& IS_SPACE_TAB_CR_LF(STR(token_buffer)[len - 1]))
|
||||
len--;
|
||||
if (len < LEN(token_buffer))
|
||||
vstring_truncate(token_buffer, len);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (ch == '\\') {
|
||||
|
@ -115,9 +115,7 @@ void vlog_adhoc(const char *id, const char *orig_rcpt,
|
||||
int delay = time((time_t *) 0) - entry;
|
||||
|
||||
vstring_vsprintf(why, fmt, ap);
|
||||
if (orig_rcpt == 0)
|
||||
orig_rcpt = "";
|
||||
if (strcasecmp(recipient, orig_rcpt) != 0)
|
||||
if (orig_rcpt && *orig_rcpt && strcasecmp(recipient, orig_rcpt) != 0)
|
||||
msg_info("%s: to=<%s>, orig_to=<%s>, relay=%s, delay=%d, status=%s (%s)",
|
||||
id, recipient, orig_rcpt, relay, delay, status, vstring_str(why));
|
||||
else
|
||||
|
@ -112,9 +112,9 @@ static int convert_mail_conf_int(const char *name, int *intval)
|
||||
static void check_mail_conf_int(const char *name, int intval, int min, int max)
|
||||
{
|
||||
if (min && intval < min)
|
||||
msg_fatal("invalid %s: %d (min %d)", name, intval, min);
|
||||
msg_fatal("invalid %s parameter value %d < %d", name, intval, min);
|
||||
if (max && intval > max)
|
||||
msg_fatal("invalid %s: %d (max %d)", name, intval, max);
|
||||
msg_fatal("invalid %s parameter value %d > %d", name, intval, max);
|
||||
}
|
||||
|
||||
/* get_mail_conf_int - evaluate integer-valued configuration variable */
|
||||
|
@ -87,10 +87,10 @@ static void check_mail_conf_str(const char *name, const char *strval,
|
||||
int len = strlen(strval);
|
||||
|
||||
if (min && len < min)
|
||||
msg_fatal("bad string length (%d < %d): %s = %s",
|
||||
msg_fatal("bad string length %d < %d: %s = %s",
|
||||
len, min, name, strval);
|
||||
if (max && len > max)
|
||||
msg_fatal("bad string length (%d > %d): %s = %s",
|
||||
msg_fatal("bad string length %d > %d: %s = %s",
|
||||
len, max, name, strval);
|
||||
}
|
||||
|
||||
|
@ -165,8 +165,15 @@ int mail_copy(const char *sender,
|
||||
if (flags & MAIL_COPY_ORIG_RCPT) {
|
||||
if (orig_rcpt == 0)
|
||||
msg_panic("%s: null orig_rcpt", myname);
|
||||
quote_822_local(buf, orig_rcpt);
|
||||
vstream_fprintf(dst, "X-Original-To: %s%s", vstring_str(buf), eol);
|
||||
|
||||
/*
|
||||
* An empty original recipient record almost certainly means that
|
||||
* original recipient processing was disabled.
|
||||
*/
|
||||
if (*orig_rcpt) {
|
||||
quote_822_local(buf, orig_rcpt);
|
||||
vstream_fprintf(dst, "X-Original-To: %s%s", vstring_str(buf), eol);
|
||||
}
|
||||
}
|
||||
if (flags & MAIL_COPY_DELIVERED) {
|
||||
if (delivered == 0)
|
||||
|
@ -486,6 +486,16 @@ extern char *var_fwd_exp_filter;
|
||||
#define DEF_DELIVER_HDR "command, file, forward"
|
||||
extern char *var_deliver_hdr;
|
||||
|
||||
/*
|
||||
* Cleanup: enable support for X-Original-To message headers, which are
|
||||
* needed for multi-recipient mailboxes. When this is turned on, perform
|
||||
* duplicate elimination on (original rcpt, rewritten rcpt) pairs, and
|
||||
* generating non-empty original recipient records in the queue file.
|
||||
*/
|
||||
#define VAR_ENABLE_ORCPT "enable_original_recipient"
|
||||
#define DEF_ENABLE_ORCPT 1
|
||||
extern bool var_enable_orcpt;
|
||||
|
||||
#define VAR_EXP_OWN_ALIAS "expand_owner_alias"
|
||||
#define DEF_EXP_OWN_ALIAS 0
|
||||
extern bool var_exp_own_alias;
|
||||
@ -763,6 +773,10 @@ extern int var_smtp_rset_tmout;
|
||||
#define DEF_SMTP_QUIT_TMOUT "300s"
|
||||
extern int var_smtp_quit_tmout;
|
||||
|
||||
#define VAR_SMTP_QUOTE_821_ENV "smtp_quote_rfc821_envelope"
|
||||
#define DEF_SMTP_QUOTE_821_ENV 1
|
||||
extern int var_smtp_quote_821_env;
|
||||
|
||||
#define VAR_SMTP_SKIP_4XX "smtp_skip_4xx_greeting"
|
||||
#define DEF_SMTP_SKIP_4XX 1
|
||||
extern bool var_smtp_skip_4xx_greeting;
|
||||
@ -1691,6 +1705,14 @@ extern bool var_verify_neg_cache;
|
||||
#define DEF_VERIFY_SENDER "postmaster"
|
||||
extern char *var_verify_sender;
|
||||
|
||||
#define VAR_VERIFY_POLL_COUNT "address_verify_poll_count"
|
||||
#define DEF_VERIFY_POLL_COUNT 3
|
||||
extern int var_verify_poll_count;
|
||||
|
||||
#define VAR_VERIFY_POLL_DELAY "address_verify_poll_delay"
|
||||
#define DEF_VERIFY_POLL_DELAY "3s"
|
||||
extern int var_verify_poll_delay;
|
||||
|
||||
#define VAR_VRFY_LOCAL_XPORT "address_verify_local_transport"
|
||||
#define DEF_VRFY_LOCAL_XPORT "$" VAR_LOCAL_TRANSPORT
|
||||
extern char *var_vrfy_local_xport;
|
||||
@ -1804,6 +1826,21 @@ extern char *var_xport_null_key;
|
||||
#define DEF_OLDLOG_COMPAT 1
|
||||
extern bool var_oldlog_compat;
|
||||
|
||||
/*
|
||||
* SMTPD content proxy.
|
||||
*/
|
||||
#define VAR_SMTPD_PROXY_FILT "smtpd_proxy_filter"
|
||||
#define DEF_SMTPD_PROXY_FILT ""
|
||||
extern char *var_smtpd_proxy_filt;
|
||||
|
||||
#define VAR_SMTPD_PROXY_EHLO "smtpd_proxy_ehlo"
|
||||
#define DEF_SMTPD_PROXY_EHLO "$" VAR_MYHOSTNAME
|
||||
extern char *var_smtpd_proxy_ehlo;
|
||||
|
||||
#define VAR_SMTPD_PROXY_TMOUT "smtpd_proxy_timeout"
|
||||
#define DEF_SMTPD_PROXY_TMOUT "100s"
|
||||
extern int var_smtpd_proxy_tmout;
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
|
@ -20,10 +20,10 @@
|
||||
* 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 "20030621"
|
||||
#define MAIL_RELEASE_DATE "20030702"
|
||||
|
||||
#define VAR_MAIL_VERSION "mail_version"
|
||||
#define DEF_MAIL_VERSION "2.0.12-" MAIL_RELEASE_DATE
|
||||
#define DEF_MAIL_VERSION "2.0.13-" MAIL_RELEASE_DATE
|
||||
extern char *var_mail_version;
|
||||
|
||||
/*
|
||||
|
@ -66,8 +66,8 @@
|
||||
/* .IP RESOLVE_CLASS_LOCAL
|
||||
/* The address domain matches $mydestination or $inet_interfaces.
|
||||
/* .IP RESOLVE_CLASS_ALIAS
|
||||
/* The address domain matches $virtual_alias_domains (simulated
|
||||
/* virtual domains, where each address is redirected to a real
|
||||
/* The address domain matches $virtual_alias_domains (virtual
|
||||
/* alias domains, where each address is redirected to a real
|
||||
/* local or remote address).
|
||||
/* .IP RESOLVE_CLASS_VIRTUAL
|
||||
/* The address domain matches $virtual_mailbox_domains (true
|
||||
|
@ -1,13 +1,13 @@
|
||||
#ifndef _VRFY_STAT_H_INCLUDED_
|
||||
#define _VRFY_STAT_H_INCLUDED_
|
||||
#ifndef _VRFY_CLNT_H_INCLUDED_
|
||||
#define _VRFY_CLNT_H_INCLUDED_
|
||||
|
||||
/*++
|
||||
/* NAME
|
||||
/* mail_proto 3h
|
||||
/* verify_clnt 3h
|
||||
/* SUMMARY
|
||||
/* mail internal IPC support
|
||||
/* address verification client interface
|
||||
/* SYNOPSIS
|
||||
/* #include <mail_proto.h>
|
||||
/* #include <verify_clnt.h>
|
||||
/* DESCRIPTION
|
||||
/* .nf
|
||||
|
||||
|
@ -2,22 +2,29 @@
|
||||
/* NAME
|
||||
/* xtext 3
|
||||
/* SUMMARY
|
||||
/* translate characters according to RFC 1894
|
||||
/* quote/unquote text, HTTP style.
|
||||
/* SYNOPSIS
|
||||
/* #include <xtext.h>
|
||||
/*
|
||||
/* VSTRING *xtext(result, original)
|
||||
/* VSTRING *result;
|
||||
/* const char *original;
|
||||
/* DESCRIPTION
|
||||
/* xtext() takes a null-terminated string, and produces a translation
|
||||
/* according to RFC 1894 (DSN).
|
||||
/* BUGS
|
||||
/* Cannot replace null characters.
|
||||
/* VSTRING *xtext_quote(quoted, unquoted, special)
|
||||
/* VSTRING *quoted;
|
||||
/* const char *unquoted;
|
||||
/* const char *special;
|
||||
/*
|
||||
/* Does not insert CR LF SPACE to limit output line length.
|
||||
/* SEE ALSO
|
||||
/* RFC 1894, Delivery Status Notifications
|
||||
/* VSTRING *xtext_unquote(unquoted, quoted)
|
||||
/* VSTRING *unquoted;
|
||||
/* const char *quoted;
|
||||
/* DESCRIPTION
|
||||
/* xtext_quote() takes a null-terminated string and replaces characters
|
||||
/* <33(10) and >126(10), as well as characters specified with "special"
|
||||
/* by +XX, XX being the two-digit uppercase hexadecimal equivalent.
|
||||
/*
|
||||
/* xtext_unquote() performs the opposite transformation. This function
|
||||
/* understands lowercase, uppercase, and mixed case %XX sequences. The
|
||||
/* result value is the unquoted argument in case of success, a null pointer
|
||||
/* otherwise.
|
||||
/* BUGS
|
||||
/* This module cannot process null characters in data.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
@ -31,56 +38,112 @@
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include "sys_defs.h"
|
||||
#include <vstream.h>
|
||||
#include <sys_defs.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <vstring.h>
|
||||
#include "msg.h"
|
||||
#include "vstring.h"
|
||||
#include "xtext.h"
|
||||
|
||||
/* Global library. */
|
||||
/* Application-specific. */
|
||||
|
||||
#include <xtext.h>
|
||||
#define STR(x) vstring_str(x)
|
||||
#define LEN(x) VSTRING_LEN(x)
|
||||
|
||||
/* xtext - translate text according to RFC 1894 */
|
||||
/* xtext_quote - unquoted data to quoted */
|
||||
|
||||
VSTRING *xtext(VSTRING *result, const char *original)
|
||||
VSTRING *xtext_quote(VSTRING *quoted, const char *unquoted, const char *special)
|
||||
{
|
||||
const char *cp;
|
||||
int ch;
|
||||
|
||||
/*
|
||||
* Preliminary implementation. ASCII specific!!
|
||||
*/
|
||||
VSTRING_RESET(result);
|
||||
for (cp = original; (ch = *(unsigned char *) cp) != 0; cp++) {
|
||||
if (ch == '+' || ch == '\\' || ch == '(' || ch < 33 || ch > 126)
|
||||
vstring_sprintf_append(result, "+%02X", ch);
|
||||
else
|
||||
VSTRING_ADDCH(result, ch);
|
||||
VSTRING_RESET(quoted);
|
||||
for (cp = unquoted; (ch = *(unsigned const char *) cp) != 0; cp++) {
|
||||
if (ch != '+' && ch > 32 && ch < 127 && strchr(special, ch) == 0) {
|
||||
VSTRING_ADDCH(quoted, ch);
|
||||
} else {
|
||||
vstring_sprintf_append(quoted, "+%02X", ch);
|
||||
}
|
||||
}
|
||||
VSTRING_TERMINATE(result);
|
||||
VSTRING_TERMINATE(quoted);
|
||||
return (quoted);
|
||||
}
|
||||
|
||||
return (result);
|
||||
/* xtext_unquote - quoted data to unquoted */
|
||||
|
||||
VSTRING *xtext_unquote(VSTRING *unquoted, const char *quoted)
|
||||
{
|
||||
const char *cp;
|
||||
int ch;
|
||||
|
||||
VSTRING_RESET(unquoted);
|
||||
for (cp = quoted; (ch = *cp) != 0; cp++) {
|
||||
if (ch == '+') {
|
||||
if (ISDIGIT(cp[1]))
|
||||
ch = (cp[1] - '0') << 4;
|
||||
else if (cp[1] >= 'a' && cp[1] <= 'f')
|
||||
ch = (cp[1] - 'a' + 10) << 4;
|
||||
else if (cp[1] >= 'A' && cp[1] <= 'F')
|
||||
ch = (cp[1] - 'A' + 10) << 4;
|
||||
else
|
||||
return (0);
|
||||
if (ISDIGIT(cp[2]))
|
||||
ch |= (cp[2] - '0');
|
||||
else if (cp[2] >= 'a' && cp[2] <= 'f')
|
||||
ch |= (cp[2] - 'a' + 10);
|
||||
else if (cp[2] >= 'A' && cp[2] <= 'F')
|
||||
ch |= (cp[2] - 'A' + 10);
|
||||
else
|
||||
return (0);
|
||||
cp += 2;
|
||||
}
|
||||
VSTRING_ADDCH(unquoted, ch);
|
||||
}
|
||||
VSTRING_TERMINATE(unquoted);
|
||||
return (unquoted);
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#define STR(x) vstring_str(x)
|
||||
|
||||
/*
|
||||
* Proof-of-concept test program: convert to quoted and back.
|
||||
*/
|
||||
#include <vstream.h>
|
||||
|
||||
int main(int unused_argc, char **unused_argv)
|
||||
{
|
||||
VSTRING *ibuf = vstring_alloc(100);
|
||||
VSTRING *obuf = vstring_alloc(100);
|
||||
#define BUFLEN 1024
|
||||
|
||||
while (vstring_fgets(ibuf, VSTREAM_IN)) {
|
||||
vstream_fputs(STR(xtext(obuf, STR(ibuf))));
|
||||
vstream_fflush(VSTREAM_OUT);
|
||||
static int read_buf(VSTREAM *fp, VSTRING *buf)
|
||||
{
|
||||
int len;
|
||||
|
||||
VSTRING_RESET(buf);
|
||||
len = vstream_fread(fp, STR(buf), vstring_avail(buf));
|
||||
VSTRING_AT_OFFSET(buf, len); /* XXX */
|
||||
VSTRING_TERMINATE(buf);
|
||||
return (len);
|
||||
}
|
||||
|
||||
main(int unused_argc, char **unused_argv)
|
||||
{
|
||||
VSTRING *unquoted = vstring_alloc(BUFLEN);
|
||||
VSTRING *quoted = vstring_alloc(100);
|
||||
int len;
|
||||
|
||||
while ((len = read_buf(VSTREAM_IN, unquoted)) > 0) {
|
||||
xtext_quote(quoted, STR(unquoted), "+=");
|
||||
if (xtext_unquote(unquoted, STR(quoted)) == 0)
|
||||
msg_fatal("bad input: %.100s", STR(quoted));
|
||||
if (LEN(unquoted) != len)
|
||||
msg_fatal("len %d != unquoted len %d", len, LEN(unquoted));
|
||||
if (vstream_fwrite(VSTREAM_OUT, STR(unquoted), LEN(unquoted)) != LEN(unquoted))
|
||||
msg_fatal("write error: %m");
|
||||
}
|
||||
vstring_free(ibuf);
|
||||
vstring_free(obuf);
|
||||
vstream_fflush(VSTREAM_OUT);
|
||||
vstring_free(unquoted);
|
||||
vstring_free(quoted);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
#ifndef _XTEXT_H_INCLUDED_
|
||||
#define _XTEXT_H_INCLUDED_
|
||||
|
||||
/*++
|
||||
/* NAME
|
||||
/* xtext 3h
|
||||
/* SUMMARY
|
||||
/* translate characters according to RFC 1894
|
||||
/* quote/unquote text, xtext style.
|
||||
/* SYNOPSIS
|
||||
/* #include <xtext.h>
|
||||
/* DESCRIPTION
|
||||
@ -10,13 +13,14 @@
|
||||
|
||||
/*
|
||||
* Utility library.
|
||||
*/
|
||||
*/
|
||||
#include <vstring.h>
|
||||
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
extern VSTRING *xtext(VSTRING *, const char *);
|
||||
extern VSTRING *xtext_quote(VSTRING *, const char *, const char *);
|
||||
extern VSTRING *xtext_unquote(VSTRING *, const char *);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
@ -28,3 +32,5 @@ extern VSTRING *xtext(VSTRING *, const char *);
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
#endif
|
||||
|
@ -389,7 +389,7 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
|
||||
if (message->rcpt_offset == 0) {
|
||||
message->rcpt_unread--;
|
||||
qmgr_rcpt_list_add(&message->rcpt_list, curr_offset,
|
||||
orig_rcpt ? orig_rcpt : "unknown", start);
|
||||
orig_rcpt ? orig_rcpt : "", start);
|
||||
if (orig_rcpt) {
|
||||
myfree(orig_rcpt);
|
||||
orig_rcpt = 0;
|
||||
|
@ -98,7 +98,7 @@ static void postcat(VSTREAM *fp, VSTRING *buffer)
|
||||
* See if this is a plausible file.
|
||||
*/
|
||||
if ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF) {
|
||||
if (!strchr(REC_TYPE_POST_ENVELOPE, ch)) {
|
||||
if (!strchr(REC_TYPE_ENVELOPE, ch)) {
|
||||
msg_warn("%s: input is not a valid queue file", VSTREAM_PATH(fp));
|
||||
return;
|
||||
}
|
||||
|
@ -357,7 +357,7 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
|
||||
#define FUDGE(x) ((x) * (var_qmgr_fudge / 100.0))
|
||||
if (message->rcpt_offset == 0) {
|
||||
qmgr_rcpt_list_add(&message->rcpt_list, curr_offset,
|
||||
orig_rcpt ? orig_rcpt : "unknown", start);
|
||||
orig_rcpt ? orig_rcpt : "", start);
|
||||
if (orig_rcpt) {
|
||||
myfree(orig_rcpt);
|
||||
orig_rcpt = 0;
|
||||
|
@ -104,7 +104,7 @@ static void showq_reasons(VSTREAM *, BOUNCE_LOG *, HTABLE *);
|
||||
/* showq_report - report status of sender and recipients */
|
||||
|
||||
static void showq_report(VSTREAM *client, char *queue, char *id,
|
||||
VSTREAM *qfile, long size)
|
||||
VSTREAM *qfile, long size, time_t mtime)
|
||||
{
|
||||
VSTRING *buf = vstring_alloc(100);
|
||||
VSTRING *printable_quoted_addr = vstring_alloc(100);
|
||||
@ -152,7 +152,8 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
|
||||
printable(STR(printable_quoted_addr), '?');
|
||||
vstream_fprintf(client, DATA_FORMAT, id, status,
|
||||
msg_size > 0 ? msg_size : size, arrival_time > 0 ?
|
||||
asctime(localtime(&arrival_time)) : "??",
|
||||
asctime(localtime(&arrival_time)) :
|
||||
asctime(localtime(&mtime)),
|
||||
STR(printable_quoted_addr));
|
||||
break;
|
||||
case REC_TYPE_RCPT:
|
||||
@ -302,7 +303,8 @@ static void showq_service(VSTREAM *client, char *unused_service, char **argv)
|
||||
vstream_fprintf(client, "\n");
|
||||
if ((qfile = mail_queue_open(qp->name, id, O_RDONLY, 0)) != 0) {
|
||||
queue_size += st.st_size;
|
||||
showq_report(client, qp->name, id, qfile, (long) st.st_size);
|
||||
showq_report(client, qp->name, id, qfile, (long) st.st_size,
|
||||
st.st_mtime);
|
||||
if (vstream_fclose(qfile))
|
||||
msg_warn("close file %s %s: %m", qp->name, id);
|
||||
} else if (strcmp(qp->name, MAIL_QUEUE_MAILDROP) == 0) {
|
||||
|
@ -21,10 +21,6 @@
|
||||
/* the destination host, sorts the list by preference, and connects
|
||||
/* to each listed address until it finds a server that responds.
|
||||
/*
|
||||
/* When the domain or host is specified as a comma/whitespace
|
||||
/* separated list, the SMTP client repeats the above process
|
||||
/* for all destinations until it finds a server that responds.
|
||||
/*
|
||||
/* Once the SMTP client has received the server greeting banner, no
|
||||
/* error will cause it to proceed to the next address on the mail
|
||||
/* exchanger list. Instead, the message is either bounced, or its
|
||||
@ -118,6 +114,9 @@
|
||||
/* Some SMTP servers misbehave on long lines.
|
||||
/* .IP \fBsmtp_helo_name\fR
|
||||
/* The hostname to be used in HELO and EHLO commands.
|
||||
/* .IP \fBsmtp_quote_rfc821_envelope\fR
|
||||
/* Whether or not to quote MAIL FROM and RCPT TO addresses as
|
||||
/* per the rules laid out in RFC 821.
|
||||
/* .IP \fBsmtp_skip_4xx_greeting\fR
|
||||
/* Skip servers that greet us with a 4xx status code.
|
||||
/* .IP \fBsmtp_skip_5xx_greeting\fR
|
||||
@ -298,6 +297,7 @@ int var_smtp_pix_delay;
|
||||
int var_smtp_line_limit;
|
||||
char *var_smtp_helo_name;
|
||||
char *var_smtp_host_lookup;
|
||||
int var_smtp_quote_821_env;
|
||||
|
||||
/*
|
||||
* Global variables. smtp_errno is set by the address lookup routines and by
|
||||
@ -509,6 +509,7 @@ int main(int argc, char **argv)
|
||||
VAR_SMTP_NEVER_EHLO, DEF_SMTP_NEVER_EHLO, &var_smtp_never_ehlo,
|
||||
VAR_SMTP_SASL_ENABLE, DEF_SMTP_SASL_ENABLE, &var_smtp_sasl_enable,
|
||||
VAR_SMTP_RAND_ADDR, DEF_SMTP_RAND_ADDR, &var_smtp_rand_addr,
|
||||
VAR_SMTP_QUOTE_821_ENV, DEF_SMTP_QUOTE_821_ENV, &var_smtp_quote_821_env,
|
||||
0,
|
||||
};
|
||||
|
||||
|
@ -379,7 +379,7 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
* Macros for readability.
|
||||
*/
|
||||
#define REWRITE_ADDRESS(dst, mid, src) do { \
|
||||
if (*(src)) { \
|
||||
if (*(src) && var_smtp_quote_821_env) { \
|
||||
quote_821_local(mid, src); \
|
||||
smtp_unalias_addr(dst, vstring_str(mid)); \
|
||||
} else { \
|
||||
@ -388,7 +388,7 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
} while (0)
|
||||
|
||||
#define QUOTE_ADDRESS(dst, src) do { \
|
||||
if (*(src)) { \
|
||||
if (*(src) && var_smtp_quote_821_env) { \
|
||||
quote_821_local(dst, src); \
|
||||
} else { \
|
||||
vstring_strcpy(dst, src); \
|
||||
@ -640,6 +640,7 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
if (resp->code == 552)
|
||||
resp->code = 452;
|
||||
#endif
|
||||
rcpt = request->rcpt_list.info + recv_rcpt;
|
||||
if (resp->code / 100 == 2) {
|
||||
++nrcpt;
|
||||
/* If trace-only, mark the recipient done. */
|
||||
@ -654,7 +655,6 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
rcpt->offset = 0; /* in case deferred */
|
||||
}
|
||||
} else {
|
||||
rcpt = request->rcpt_list.info + recv_rcpt;
|
||||
smtp_rcpt_fail(state, resp->code, rcpt,
|
||||
"host %s said: %s (in reply to %s)",
|
||||
session->namaddr,
|
||||
|
@ -1,10 +1,10 @@
|
||||
SHELL = /bin/sh
|
||||
SRCS = smtpd.c smtpd_token.c smtpd_check.c smtpd_chat.c smtpd_state.c \
|
||||
smtpd_peer.c smtpd_sasl_proto.c smtpd_sasl_glue.c
|
||||
smtpd_peer.c smtpd_sasl_proto.c smtpd_sasl_glue.c smtpd_proxy.c
|
||||
OBJS = smtpd.o smtpd_token.o smtpd_check.o smtpd_chat.o smtpd_state.o \
|
||||
smtpd_peer.o smtpd_sasl_proto.o smtpd_sasl_glue.o
|
||||
smtpd_peer.o smtpd_sasl_proto.o smtpd_sasl_glue.o smtpd_proxy.o
|
||||
HDRS = smtpd_token.h smtpd_check.h smtpd_chat.h smtpd_sasl_proto.h \
|
||||
smtpd_sasl_glue.h
|
||||
smtpd_sasl_glue.h smtpd_proxy.h
|
||||
TESTSRC = smtpd_token_test.c
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
@ -154,6 +154,7 @@ smtpd.o: smtpd_check.h
|
||||
smtpd.o: smtpd_chat.h
|
||||
smtpd.o: smtpd_sasl_proto.h
|
||||
smtpd.o: smtpd_sasl_glue.h
|
||||
smtpd.o: smtpd_proxy.h
|
||||
smtpd_chat.o: smtpd_chat.c
|
||||
smtpd_chat.o: ../../include/sys_defs.h
|
||||
smtpd_chat.o: ../../include/msg.h
|
||||
@ -241,6 +242,25 @@ smtpd_peer.o: smtpd.h
|
||||
smtpd_peer.o: ../../include/vstream.h
|
||||
smtpd_peer.o: ../../include/argv.h
|
||||
smtpd_peer.o: ../../include/mail_stream.h
|
||||
smtpd_proxy.o: smtpd_proxy.c
|
||||
smtpd_proxy.o: ../../include/sys_defs.h
|
||||
smtpd_proxy.o: ../../include/msg.h
|
||||
smtpd_proxy.o: ../../include/vstream.h
|
||||
smtpd_proxy.o: ../../include/vbuf.h
|
||||
smtpd_proxy.o: ../../include/vstring.h
|
||||
smtpd_proxy.o: ../../include/stringops.h
|
||||
smtpd_proxy.o: ../../include/connect.h
|
||||
smtpd_proxy.o: ../../include/iostuff.h
|
||||
smtpd_proxy.o: ../../include/mail_error.h
|
||||
smtpd_proxy.o: ../../include/name_mask.h
|
||||
smtpd_proxy.o: ../../include/smtp_stream.h
|
||||
smtpd_proxy.o: ../../include/cleanup_user.h
|
||||
smtpd_proxy.o: ../../include/mail_params.h
|
||||
smtpd_proxy.o: ../../include/rec_type.h
|
||||
smtpd_proxy.o: smtpd.h
|
||||
smtpd_proxy.o: ../../include/argv.h
|
||||
smtpd_proxy.o: ../../include/mail_stream.h
|
||||
smtpd_proxy.o: smtpd_proxy.h
|
||||
smtpd_sasl_glue.o: smtpd_sasl_glue.c
|
||||
smtpd_sasl_glue.o: ../../include/sys_defs.h
|
||||
smtpd_sasl_glue.o: ../../include/msg.h
|
||||
|
@ -97,6 +97,24 @@
|
||||
/* Maps that specify the SASL login name that owns a MAIL FROM sender
|
||||
/* address. Used by the \fBreject_sender_login_mismatch\fR sender
|
||||
/* anti-spoofing restriction.
|
||||
/* .SH "Pass-through proxy"
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* .ad
|
||||
/* 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.
|
||||
/* .IP \fBsmtpd_proxy_filter\fR
|
||||
/* The \fIhost:port\fR of the SMTP proxy server. The \fIhost\fR
|
||||
/* or \fIhost:\fR portion is optional.
|
||||
/* .IP \fBsmtpd_proxy_timeout\fR
|
||||
/* Timeout for connecting to, sending to and receiving from
|
||||
/* the SMTP proxy server.
|
||||
/* .IP \fBsmtpd_proxy_ehlo\fR
|
||||
/* The hostname to use when sending an EHLO command to the
|
||||
/* SMTP proxy server.
|
||||
/* .SH Miscellaneous
|
||||
/* .ad
|
||||
/* .fi
|
||||
@ -245,6 +263,21 @@
|
||||
/* Restrict what domains this mail system will relay
|
||||
/* mail to. The domains are routed to the delivery agent
|
||||
/* specified with the \fBrelay_transport\fR setting.
|
||||
/* .SH "Sender/recipient address verification"
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* 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 maintained by the address
|
||||
/* verification service.
|
||||
/* .IP \fBaddress_verify_poll_count\fR
|
||||
/* How many times to query the address verification service
|
||||
/* for completion of an address verification request.
|
||||
/* Specify 0 to implement a simple form of greylisting.
|
||||
/* .IP \fBaddress_verify_poll_delay\fR
|
||||
/* Time to wait after querying the address verification service
|
||||
/* for completion of an address verification request.
|
||||
/* .SH "UCE control responses"
|
||||
/* .ad
|
||||
/* .fi
|
||||
@ -289,10 +322,11 @@
|
||||
/* .IP \fBunverified_recipient_reject_code\fR
|
||||
/* Response code when a recipient address is known to be undeliverable.
|
||||
/* SEE ALSO
|
||||
/* trivial-rewrite(8) address resolver
|
||||
/* cleanup(8) message canonicalization
|
||||
/* master(8) process manager
|
||||
/* syslogd(8) system logging
|
||||
/* trivial-rewrite(8) address resolver
|
||||
/* verify(8) address verification service
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
@ -368,12 +402,13 @@
|
||||
|
||||
/* Application-specific */
|
||||
|
||||
#include "smtpd_token.h"
|
||||
#include "smtpd.h"
|
||||
#include "smtpd_check.h"
|
||||
#include "smtpd_chat.h"
|
||||
#include "smtpd_sasl_proto.h"
|
||||
#include "smtpd_sasl_glue.h"
|
||||
#include <smtpd_token.h>
|
||||
#include <smtpd.h>
|
||||
#include <smtpd_check.h>
|
||||
#include <smtpd_chat.h>
|
||||
#include <smtpd_sasl_proto.h>
|
||||
#include <smtpd_sasl_glue.h>
|
||||
#include <smtpd_proxy.h>
|
||||
|
||||
/*
|
||||
* Tunable parameters. Make sure that there is some bound on the length of
|
||||
@ -446,6 +481,12 @@ int var_virt_mailbox_code;
|
||||
int var_relay_rcpt_code;
|
||||
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;
|
||||
|
||||
/*
|
||||
* Silly little macros.
|
||||
@ -762,7 +803,9 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
smtpd_chat_reply(state, "503 Error: send HELO/EHLO first");
|
||||
return (-1);
|
||||
}
|
||||
if (state->cleanup != 0) {
|
||||
#define IN_MAIL_TRANSACTION(state) ((state)->cleanup || (state)->proxy)
|
||||
|
||||
if (IN_MAIL_TRANSACTION(state)) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "503 Error: nested MAIL command");
|
||||
return (-1);
|
||||
@ -840,50 +883,58 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
smtpd_chat_reply(state, "%s", err);
|
||||
return (-1);
|
||||
}
|
||||
if ((err = smtpd_check_size(state, state->msg_size)) != 0) {
|
||||
smtpd_chat_reply(state, "%s", err);
|
||||
return (-1);
|
||||
}
|
||||
if (SMTPD_STAND_ALONE(state) == 0 && *var_smtpd_proxy_filt) {
|
||||
if (smtpd_proxy_open(state, var_smtpd_proxy_filt, var_smtpd_proxy_tmout,
|
||||
var_smtpd_proxy_ehlo, STR(state->buffer)) != 0) {
|
||||
smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
if ((err = smtpd_check_size(state, state->msg_size)) != 0) {
|
||||
smtpd_chat_reply(state, "%s", err);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open queue file or IPC stream.
|
||||
*/
|
||||
mail_open_stream(state);
|
||||
/*
|
||||
* Open queue file or IPC stream.
|
||||
*/
|
||||
mail_open_stream(state);
|
||||
#ifdef USE_SASL_AUTH
|
||||
if (var_smtpd_sasl_enable)
|
||||
smtpd_sasl_mail_log(state);
|
||||
else
|
||||
if (var_smtpd_sasl_enable)
|
||||
smtpd_sasl_mail_log(state);
|
||||
else
|
||||
#endif
|
||||
msg_info("%s: client=%s[%s]", state->queue_id, state->name, state->addr);
|
||||
msg_info("%s: client=%s[%s]", state->queue_id, state->name, state->addr);
|
||||
|
||||
/*
|
||||
* Record the time of arrival and the sender envelope address.
|
||||
*/
|
||||
if (SMTPD_STAND_ALONE(state) == 0) {
|
||||
rec_fprintf(state->cleanup, REC_TYPE_TIME, "%ld",
|
||||
(long) time((time_t *) 0));
|
||||
if (*var_filter_xport)
|
||||
rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport);
|
||||
}
|
||||
rec_fputs(state->cleanup, REC_TYPE_FROM, argv[2].strval);
|
||||
if (encoding != 0)
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_ENCODING, encoding);
|
||||
if (SMTPD_STAND_ALONE(state) == 0) {
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_CLIENT_NAME, state->name);
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_CLIENT_ADDR, state->addr);
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_ORIGIN, state->namaddr);
|
||||
if (state->helo_name != 0)
|
||||
/*
|
||||
* Record the time of arrival and the sender envelope address.
|
||||
*/
|
||||
if (SMTPD_STAND_ALONE(state) == 0) {
|
||||
rec_fprintf(state->cleanup, REC_TYPE_TIME, "%ld",
|
||||
(long) time((time_t *) 0));
|
||||
if (*var_filter_xport)
|
||||
rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport);
|
||||
}
|
||||
rec_fputs(state->cleanup, REC_TYPE_FROM, argv[2].strval);
|
||||
if (encoding != 0)
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_HELO_NAME, state->helo_name);
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_PROTO_NAME, state->protocol);
|
||||
MAIL_ATTR_ENCODING, encoding);
|
||||
if (SMTPD_STAND_ALONE(state) == 0) {
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_CLIENT_NAME, state->name);
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_CLIENT_ADDR, state->addr);
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_ORIGIN, state->namaddr);
|
||||
if (state->helo_name != 0)
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_HELO_NAME, state->helo_name);
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_PROTO_NAME, state->protocol);
|
||||
}
|
||||
if (verp_delims)
|
||||
rec_fputs(state->cleanup, REC_TYPE_VERP, verp_delims);
|
||||
}
|
||||
if (verp_delims)
|
||||
rec_fputs(state->cleanup, REC_TYPE_VERP, verp_delims);
|
||||
state->sender = mystrdup(argv[2].strval);
|
||||
smtpd_chat_reply(state, "250 Ok");
|
||||
return (0);
|
||||
@ -918,6 +969,8 @@ static void mail_reset(SMTPD_STATE *state)
|
||||
smtpd_sasl_mail_reset(state);
|
||||
#endif
|
||||
state->discard = 0;
|
||||
if (state->proxy)
|
||||
smtpd_proxy_close(state);
|
||||
}
|
||||
|
||||
/* rcpt_cmd - process RCPT TO command */
|
||||
@ -937,7 +990,7 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
* command with a 501 response. So much for the principle of "be liberal
|
||||
* in what you accept, be strict in what you send".
|
||||
*/
|
||||
if (state->cleanup == 0) {
|
||||
if (!IN_MAIL_TRANSACTION(state)) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "503 Error: need MAIL command");
|
||||
return (-1);
|
||||
@ -977,6 +1030,11 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
if (state->proxy && smtpd_proxy_cmd(state, SMTPD_PROX_STAT_OK,
|
||||
"%s", STR(state->buffer)) != 0) {
|
||||
smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the recipient. Remember the first one.
|
||||
@ -984,7 +1042,8 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
state->rcpt_count++;
|
||||
if (state->recipient == 0)
|
||||
state->recipient = mystrdup(argv[2].strval);
|
||||
rec_fputs(state->cleanup, REC_TYPE_RCPT, argv[2].strval);
|
||||
if (state->cleanup)
|
||||
rec_fputs(state->cleanup, REC_TYPE_RCPT, argv[2].strval);
|
||||
smtpd_chat_reply(state, "250 Ok");
|
||||
return (0);
|
||||
}
|
||||
@ -1012,6 +1071,10 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
||||
int first = 1;
|
||||
VSTRING *why = 0;
|
||||
int saved_err;
|
||||
int (*out_record) (VSTREAM *, int, const char *, int);
|
||||
int (*out_fprintf) (VSTREAM *, int, const char *,...);
|
||||
VSTREAM *out_stream;
|
||||
int out_error;
|
||||
|
||||
/*
|
||||
* Sanity checks. With ESMTP command pipelining the client can send DATA
|
||||
@ -1019,7 +1082,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
||||
* error.
|
||||
*/
|
||||
if (state->rcpt_count == 0) {
|
||||
if (state->cleanup == 0) {
|
||||
if (!IN_MAIL_TRANSACTION(state)) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "503 Error: need RCPT command");
|
||||
} else {
|
||||
@ -1036,35 +1099,61 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
||||
smtpd_chat_reply(state, "%s", err);
|
||||
return (-1);
|
||||
}
|
||||
if (state->proxy && smtpd_proxy_cmd(state, SMTPD_PROX_STAT_MORE,
|
||||
"%s", STR(state->buffer)) != 0) {
|
||||
smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* One level of indirection to choose between normal or proxied
|
||||
* operation. We want to avoid massive code duplication within tons of
|
||||
* if-else clauses.
|
||||
*/
|
||||
if (state->proxy) {
|
||||
out_stream = state->proxy;
|
||||
out_record = smtpd_proxy_rec_put;
|
||||
out_fprintf = smtpd_proxy_rec_fprintf;
|
||||
out_error = CLEANUP_STAT_PROXY;
|
||||
} else {
|
||||
out_stream = state->cleanup;
|
||||
out_record = rec_put;
|
||||
out_fprintf = rec_fprintf;
|
||||
out_error = CLEANUP_STAT_WRITE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Terminate the message envelope segment. Start the message content
|
||||
* segment, and prepend our own Received: header. If there is only one
|
||||
* recipient, list the recipient address.
|
||||
*/
|
||||
rec_fputs(state->cleanup, REC_TYPE_MESG, "");
|
||||
rec_fprintf(state->cleanup, REC_TYPE_NORM,
|
||||
if (state->cleanup)
|
||||
rec_fputs(state->cleanup, REC_TYPE_MESG, "");
|
||||
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||
"Received: from %s (%s [%s])",
|
||||
state->helo_name ? state->helo_name : state->name,
|
||||
state->name, state->addr);
|
||||
if (state->rcpt_count == 1 && state->recipient) {
|
||||
rec_fprintf(state->cleanup, REC_TYPE_NORM,
|
||||
"\tby %s (%s) with %s id %s",
|
||||
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||
state->cleanup ? "\tby %s (%s) with %s id %s" :
|
||||
"\tby %s (%s) with %s",
|
||||
var_myhostname, var_mail_name,
|
||||
state->protocol, state->queue_id);
|
||||
quote_822_local(state->buffer, state->recipient);
|
||||
rec_fprintf(state->cleanup, REC_TYPE_NORM,
|
||||
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||
"\tfor <%s>; %s", STR(state->buffer), mail_date(state->time));
|
||||
} else {
|
||||
rec_fprintf(state->cleanup, REC_TYPE_NORM,
|
||||
"\tby %s (%s) with %s",
|
||||
var_myhostname, var_mail_name, state->protocol);
|
||||
rec_fprintf(state->cleanup, REC_TYPE_NORM,
|
||||
"\tid %s; %s", state->queue_id, mail_date(state->time));
|
||||
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||
state->cleanup ? "\tby %s (%s) with %s id %s;" :
|
||||
"\tby %s (%s) with %s;",
|
||||
var_myhostname, var_mail_name,
|
||||
state->protocol, state->queue_id);
|
||||
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||
"\t%s", mail_date(state->time));
|
||||
}
|
||||
#ifdef RECEIVED_ENVELOPE_FROM
|
||||
quote_822_local(state->buffer, state->sender);
|
||||
rec_fprintf(state->cleanup, REC_TYPE_NORM,
|
||||
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||
"\t(envelope-from %s)", STR(state->buffer));
|
||||
#endif
|
||||
smtpd_chat_reply(state, "354 End data with <CR><LF>.<CR><LF>");
|
||||
@ -1081,9 +1170,6 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
||||
* XXX Deal with UNIX-style From_ lines at the start of message content
|
||||
* because sendmail permits it.
|
||||
*/
|
||||
if (vstream_fflush(state->cleanup))
|
||||
state->err = CLEANUP_STAT_WRITE;
|
||||
|
||||
for (prev_rec_type = 0; /* void */ ; prev_rec_type = curr_rec_type) {
|
||||
if (smtp_get(state->buffer, state->client, var_line_limit) == '\n')
|
||||
curr_rec_type = REC_TYPE_NORM;
|
||||
@ -1093,40 +1179,46 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
||||
len = VSTRING_LEN(state->buffer);
|
||||
if (first) {
|
||||
if (strncmp(start + strspn(start, ">"), "From ", 5) == 0) {
|
||||
rec_fprintf(state->cleanup, curr_rec_type,
|
||||
out_fprintf(out_stream, curr_rec_type,
|
||||
"X-Mailbox-Line: %s", start);
|
||||
continue;
|
||||
}
|
||||
first = 0;
|
||||
if (len > 0 && IS_SPACE_TAB(start[0]))
|
||||
rec_put(state->cleanup, REC_TYPE_NORM, "", 0);
|
||||
out_record(out_stream, REC_TYPE_NORM, "", 0);
|
||||
}
|
||||
if (prev_rec_type != REC_TYPE_CONT
|
||||
&& *start == '.' && (++start, --len) == 0)
|
||||
if (prev_rec_type != REC_TYPE_CONT && *start == '.'
|
||||
&& (state->proxy == 0 ? (++start, --len) == 0 : len == 1))
|
||||
break;
|
||||
if (state->err == CLEANUP_STAT_OK
|
||||
&& rec_put(state->cleanup, curr_rec_type, start, len) < 0)
|
||||
state->err = CLEANUP_STAT_WRITE;
|
||||
&& out_record(out_stream, curr_rec_type, start, len) < 0)
|
||||
state->err = out_error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the end-of-segment markers.
|
||||
*/
|
||||
if (state->err == CLEANUP_STAT_OK)
|
||||
if (rec_fputs(state->cleanup, REC_TYPE_XTRA, "") < 0
|
||||
|| rec_fputs(state->cleanup, REC_TYPE_END, "") < 0
|
||||
|| vstream_fflush(state->cleanup))
|
||||
state->err = CLEANUP_STAT_WRITE;
|
||||
if (state->proxy) {
|
||||
if (state->err == CLEANUP_STAT_OK)
|
||||
(void) smtpd_proxy_cmd(state, SMTPD_PROX_STAT_ANY, ".");
|
||||
smtpd_proxy_close(state);
|
||||
} else {
|
||||
if (state->err == CLEANUP_STAT_OK)
|
||||
if (rec_fputs(state->cleanup, REC_TYPE_XTRA, "") < 0
|
||||
|| rec_fputs(state->cleanup, REC_TYPE_END, "") < 0
|
||||
|| vstream_fflush(state->cleanup))
|
||||
state->err = CLEANUP_STAT_WRITE;
|
||||
|
||||
/*
|
||||
* Finish the queue file or finish the cleanup conversation.
|
||||
*/
|
||||
if (state->err == 0)
|
||||
state->err = mail_stream_finish(state->dest, why = vstring_alloc(10));
|
||||
else
|
||||
mail_stream_cleanup(state->dest);
|
||||
state->dest = 0;
|
||||
state->cleanup = 0;
|
||||
/*
|
||||
* Finish the queue file or finish the cleanup conversation.
|
||||
*/
|
||||
if (state->err == 0)
|
||||
state->err = mail_stream_finish(state->dest, why = vstring_alloc(10));
|
||||
else
|
||||
mail_stream_cleanup(state->dest);
|
||||
state->dest = 0;
|
||||
state->cleanup = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle any errors. One message may suffer from multiple errors, so
|
||||
@ -1139,7 +1231,10 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
||||
state->error_count = 0;
|
||||
state->error_mask = 0;
|
||||
state->junk_cmds = 0;
|
||||
smtpd_chat_reply(state, "250 Ok: queued as %s", state->queue_id);
|
||||
if (state->queue_id)
|
||||
smtpd_chat_reply(state, "250 Ok: queued as %s", state->queue_id);
|
||||
else
|
||||
smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
|
||||
} else if ((state->err & CLEANUP_STAT_BAD) != 0) {
|
||||
state->error_mask |= MAIL_ERROR_SOFTWARE;
|
||||
smtpd_chat_reply(state, "451 Error: internal error %d", state->err);
|
||||
@ -1156,6 +1251,9 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
||||
} else if ((state->err & CLEANUP_STAT_WRITE) != 0) {
|
||||
state->error_mask |= MAIL_ERROR_RESOURCE;
|
||||
smtpd_chat_reply(state, "451 Error: queue file write error");
|
||||
} else if ((state->err & CLEANUP_STAT_PROXY) != 0) {
|
||||
state->error_mask |= MAIL_ERROR_SOFTWARE;
|
||||
smtpd_chat_reply(state, "451 Error: queue file write error");
|
||||
} else {
|
||||
state->error_mask |= MAIL_ERROR_SOFTWARE;
|
||||
smtpd_chat_reply(state, "451 Error: internal error %d", state->err);
|
||||
@ -1310,7 +1408,7 @@ static int etrn_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
smtpd_chat_reply(state, "503 Error: send HELO/EHLO first");
|
||||
return (-1);
|
||||
}
|
||||
if (state->cleanup != 0) {
|
||||
if (IN_MAIL_TRANSACTION(state)) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "503 Error: MAIL transaction in progress");
|
||||
return (-1);
|
||||
@ -1409,7 +1507,7 @@ typedef struct SMTPD_CMD {
|
||||
} SMTPD_CMD;
|
||||
|
||||
#define SMTPD_CMD_FLAG_LIMIT (1<<0) /* limit usage */
|
||||
#define SMTPD_CMD_FLAG_HEADER (1<<1) /* RFC 2822 mail header */
|
||||
#define SMTPD_CMD_FLAG_FORBIDDEN (1<<1) /* RFC 2822 mail header */
|
||||
|
||||
static SMTPD_CMD smtpd_cmd_table[] = {
|
||||
"HELO", helo_cmd, SMTPD_CMD_FLAG_LIMIT,
|
||||
@ -1427,11 +1525,13 @@ static SMTPD_CMD smtpd_cmd_table[] = {
|
||||
"VRFY", vrfy_cmd, SMTPD_CMD_FLAG_LIMIT,
|
||||
"ETRN", etrn_cmd, SMTPD_CMD_FLAG_LIMIT,
|
||||
"QUIT", quit_cmd, 0,
|
||||
"Received:", 0, SMTPD_CMD_FLAG_HEADER,
|
||||
"Reply-To:", 0, SMTPD_CMD_FLAG_HEADER,
|
||||
"Message-ID:", 0, SMTPD_CMD_FLAG_HEADER,
|
||||
"Subject:", 0, SMTPD_CMD_FLAG_HEADER,
|
||||
"From:", 0, SMTPD_CMD_FLAG_HEADER,
|
||||
"Received:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
|
||||
"Reply-To:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
|
||||
"Message-ID:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
|
||||
"Subject:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
|
||||
"From:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
|
||||
"CONNECT", 0, SMTPD_CMD_FLAG_FORBIDDEN,
|
||||
"User-Agent:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
|
||||
0,
|
||||
};
|
||||
|
||||
@ -1521,8 +1621,8 @@ static void smtpd_proto(SMTPD_STATE *state)
|
||||
state->error_count++;
|
||||
continue;
|
||||
}
|
||||
if (cmdp->flags & SMTPD_CMD_FLAG_HEADER) {
|
||||
msg_warn("%s sent %s header instead of SMTP command: %.100s",
|
||||
if (cmdp->flags & SMTPD_CMD_FLAG_FORBIDDEN) {
|
||||
msg_warn("%s sent %s instead of SMTP command: %.100s",
|
||||
state->namaddr, cmdp->name, vstring_str(state->buffer));
|
||||
smtpd_chat_reply(state, "221 Error: I can break rules, too. Goodbye.");
|
||||
break;
|
||||
@ -1685,11 +1785,14 @@ int main(int argc, char **argv)
|
||||
VAR_VIRT_ALIAS_CODE, DEF_VIRT_ALIAS_CODE, &var_virt_alias_code, 0, 0,
|
||||
VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code, 0, 0,
|
||||
VAR_RELAY_RCPT_CODE, DEF_RELAY_RCPT_CODE, &var_relay_rcpt_code, 0, 0,
|
||||
VAR_VERIFY_POLL_COUNT, DEF_VERIFY_POLL_COUNT, &var_verify_poll_count, 1, 0,
|
||||
0,
|
||||
};
|
||||
static CONFIG_TIME_TABLE time_table[] = {
|
||||
VAR_SMTPD_TMOUT, DEF_SMTPD_TMOUT, &var_smtpd_tmout, 1, 0,
|
||||
VAR_SMTPD_ERR_SLEEP, DEF_SMTPD_ERR_SLEEP, &var_smtpd_err_sleep, 0, 0,
|
||||
VAR_SMTPD_PROXY_TMOUT, DEF_SMTPD_PROXY_TMOUT, &var_smtpd_proxy_tmout, 1, 0,
|
||||
VAR_VERIFY_POLL_DELAY, DEF_VERIFY_POLL_DELAY, &var_verify_poll_delay, 1, 0,
|
||||
0,
|
||||
};
|
||||
static CONFIG_BOOL_TABLE bool_table[] = {
|
||||
@ -1732,6 +1835,8 @@ int main(int argc, char **argv)
|
||||
VAR_RELAY_RCPT_MAPS, DEF_RELAY_RCPT_MAPS, &var_relay_rcpt_maps, 0, 0,
|
||||
VAR_VERIFY_SENDER, DEF_VERIFY_SENDER, &var_verify_sender, 0, 0,
|
||||
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,
|
||||
0,
|
||||
};
|
||||
static CONFIG_RAW_TABLE raw_table[] = {
|
||||
|
@ -95,6 +95,8 @@ typedef struct SMTPD_STATE {
|
||||
int defer_if_permit_sender; /* force permit into warning */
|
||||
int discard; /* discard message */
|
||||
VSTRING *expand_buf; /* scratch space for $name expansion */
|
||||
VSTREAM *proxy; /* proxy handle */
|
||||
VSTRING *proxy_buffer; /* proxy query/reply buffer */
|
||||
} SMTPD_STATE;
|
||||
|
||||
extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
|
||||
|
@ -1153,8 +1153,9 @@ static int check_relay_domains(SMTPD_STATE *state, char *recipient,
|
||||
|
||||
if (once == 0) {
|
||||
once = 1;
|
||||
msg_warn("the \"%s\" restriction is going away; use \"%s\" instead",
|
||||
CHECK_RELAY_DOMAINS, REJECT_UNAUTH_DEST);
|
||||
msg_warn("support for restriction \"%s\" will be removed from %s; "
|
||||
"use \"%s\" instead",
|
||||
CHECK_RELAY_DOMAINS, var_mail_name, REJECT_UNAUTH_DEST);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1650,17 +1651,17 @@ static int reject_unverified_address(SMTPD_STATE *state, const char *addr,
|
||||
/*
|
||||
* Verify the address. Don't waste too much of their or our time.
|
||||
*/
|
||||
for (count = 0; /* see below */ ; count++) {
|
||||
for (count = 0; /* see below */ ; /* see below */ ) {
|
||||
verify_status = verify_clnt_query(addr, &rcpt_status, why);
|
||||
if (verify_status != VRFY_STAT_OK || rcpt_status != DEL_RCPT_STAT_TODO)
|
||||
break;
|
||||
if (count >= 2)
|
||||
if (++count >= var_verify_poll_count)
|
||||
break;
|
||||
sleep(3);
|
||||
sleep(var_verify_poll_delay);
|
||||
}
|
||||
if (verify_status != VRFY_STAT_OK) {
|
||||
msg_warn("%s service failure", var_verify_service);
|
||||
DEFER_IF_REJECT2(state, MAIL_ERROR_POLICY,
|
||||
DEFER_IF_PERMIT2(state, MAIL_ERROR_POLICY,
|
||||
"450 <%s>: %s rejected: address verification problem",
|
||||
reply_name, reply_class);
|
||||
rqst_status = SMTPD_CHECK_DUNNO;
|
||||
@ -2589,8 +2590,9 @@ static int reject_maps_rbl(SMTPD_STATE *state)
|
||||
|
||||
if (warned == 0) {
|
||||
warned++;
|
||||
msg_warn("restriction %s is going away. Please use %s <domain> instead",
|
||||
REJECT_MAPS_RBL, REJECT_RBL_CLIENT);
|
||||
msg_warn("support for restriction \"%s\" will be removed from %s; "
|
||||
"use \"%s <domain-name>\" instead",
|
||||
REJECT_MAPS_RBL, var_mail_name, REJECT_RBL_CLIENT);
|
||||
}
|
||||
while ((rbl_domain = mystrtok(&bp, " \t\r\n,")) != 0) {
|
||||
result = reject_rbl_addr(state, rbl_domain, state->addr,
|
||||
@ -2683,7 +2685,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
|
||||
int saved_recursion = state->recursion++;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s: START", myname);
|
||||
msg_info(">>> START %s RESTRICTIONS <<<", reply_class);
|
||||
|
||||
for (cpp = restrictions->argv; (name = *cpp) != 0; cpp++) {
|
||||
|
||||
@ -2980,7 +2982,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
|
||||
break;
|
||||
}
|
||||
if (msg_verbose && name == 0)
|
||||
msg_info("%s: END", myname);
|
||||
msg_info(">>> END %s RESTRICTIONS <<<", reply_class);
|
||||
|
||||
state->recursion = saved_recursion;
|
||||
|
||||
@ -3296,6 +3298,9 @@ static int check_rcpt_maps(SMTPD_STATE *state, const char *recipient)
|
||||
return (0);
|
||||
state->rcptmap_checked = 1;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info(">>> CHECKING RECIPIENT MAPS <<<");
|
||||
|
||||
/*
|
||||
* Resolve the address.
|
||||
*/
|
||||
@ -3653,6 +3658,8 @@ int var_relay_rcpt_code;
|
||||
int var_virt_mailbox_code;
|
||||
int var_virt_alias_code;
|
||||
int var_show_unk_rcpt_table;
|
||||
int var_verify_poll_count;
|
||||
int var_verify_poll_delay;
|
||||
|
||||
static INT_TABLE int_table[] = {
|
||||
"msg_verbose", 0, &msg_verbose,
|
||||
@ -3676,6 +3683,8 @@ static INT_TABLE int_table[] = {
|
||||
VAR_VIRT_ALIAS_CODE, DEF_VIRT_ALIAS_CODE, &var_virt_alias_code,
|
||||
VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code,
|
||||
VAR_SHOW_UNK_RCPT_TABLE, DEF_SHOW_UNK_RCPT_TABLE, &var_show_unk_rcpt_table,
|
||||
VAR_VERIFY_POLL_COUNT, DEF_VERIFY_POLL_COUNT, &var_verify_poll_count,
|
||||
VAR_VERIFY_POLL_DELAY, DEF_VERIFY_POLL_DELAY, &var_verify_poll_delay,
|
||||
0,
|
||||
};
|
||||
|
||||
@ -3803,6 +3812,14 @@ int permit_sasl_auth(SMTPD_STATE *state, int ifyes, int ifnot)
|
||||
|
||||
#endif
|
||||
|
||||
/* verify_clnt_query - stub */
|
||||
|
||||
int verify_clnt_query(const char *addr, int *addr_status, VSTRING *why)
|
||||
{
|
||||
*addr_status = DEL_RCPT_STAT_OK;
|
||||
return (VRFY_STAT_OK);
|
||||
}
|
||||
|
||||
/* canon_addr_internal - stub */
|
||||
|
||||
VSTRING *canon_addr_internal(VSTRING *result, const char *addr)
|
||||
@ -3816,7 +3833,7 @@ VSTRING *canon_addr_internal(VSTRING *result, const char *addr)
|
||||
|
||||
/* resolve_clnt_query - stub */
|
||||
|
||||
void resolve_clnt_query(const char *addr, RESOLVE_REPLY *reply)
|
||||
void resolve_clnt(const char *class, const char *addr, RESOLVE_REPLY *reply)
|
||||
{
|
||||
const char *domain;
|
||||
|
||||
|
437
postfix/src/smtpd/smtpd_proxy.c
Normal file
437
postfix/src/smtpd/smtpd_proxy.c
Normal file
@ -0,0 +1,437 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* smtpd_proto 3
|
||||
/* SUMMARY
|
||||
/* SMTP server pass-through proxy client
|
||||
/* SYNOPSIS
|
||||
/* #include <smtpd.h>
|
||||
/* #include <smtpd_proxy.h>
|
||||
/*
|
||||
/* typedef struct {
|
||||
/* .in +4
|
||||
/* /* other fields... */
|
||||
/* VSTREAM *proxy; /* connection to SMTP proxy */
|
||||
/* VSTRING *proxy_reply; /* last SMTP proxy response */
|
||||
/* /* other fields... */
|
||||
/* .in -4
|
||||
/* } SMTPD_STATE;
|
||||
/*
|
||||
/* int smtpd_proxy_open(state, service, timeout, ehlo_name, mail_from)
|
||||
/* SMTPD_STATE *state;
|
||||
/* const char *service;
|
||||
/* int timeout;
|
||||
/* const char *ehlo_name;
|
||||
/* const char *mail_from;
|
||||
/*
|
||||
/* int smtpd_proxy_cmd(state, expect, format, ...)
|
||||
/* SMTPD_STATE *state;
|
||||
/* int expect;
|
||||
/* cont char *format;
|
||||
/*
|
||||
/* void smtpd_proxy_open(state)
|
||||
/* SMTPD_STATE *state;
|
||||
/* RECORD-LEVEL ROUTINES
|
||||
/* int smtpd_proxy_rec_put(stream, rec_type, data, len)
|
||||
/* VSTREAM *stream;
|
||||
/* int rec_type;
|
||||
/* const char *data;
|
||||
/* int len;
|
||||
/*
|
||||
/* int smtpd_proxy_rec_fprintf(stream, rec_type, format, ...)
|
||||
/* VSTREAM *stream;
|
||||
/* int rec_type;
|
||||
/* cont char *format;
|
||||
/* DESCRIPTION
|
||||
/* The functions in this module implement a pass-through proxy
|
||||
/* client.
|
||||
/*
|
||||
/* In order to minimize the intrusiveness of pass-through proxying, 1) the
|
||||
/* proxy server must support the same MAIL FROM/RCPT syntax that Postfix
|
||||
/* supports, 2) the record-level routines for message content proxying
|
||||
/* have the same interface as the routines that are used for non-proxied
|
||||
/* mail.
|
||||
/*
|
||||
/* smtpd_proxy_open() should be called after receiving the MAIL FROM
|
||||
/* command. It connects to the proxy service, sends EHLO, sends the
|
||||
/* 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
|
||||
/* 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
|
||||
/* 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
|
||||
/* that can be sent to the SMTP client. In case of error, the
|
||||
/* state->error_mask and state->err fields are updated.
|
||||
/*
|
||||
/* smtpd_proxy_close() disconnects from a proxy server and resets
|
||||
/* the state->proxy field. The last proxy server reply or error
|
||||
/* description remains available via state->proxy-reply.
|
||||
/*
|
||||
/* smtpd_proxy_rec_put() is a rec_put() clone that passes arbitrary
|
||||
/* message content records to the proxy server. The data is expected
|
||||
/* to be in SMTP dot-escaped form. All errors are reported as a
|
||||
/* REC_TYPE_ERROR result value.
|
||||
/*
|
||||
/* smtpd_proxy_rec_fprintf() is a rec_fprintf() clone that formats
|
||||
/* message content and sends it to the proxy server. Leading dots are
|
||||
/* not escaped. All errors are reported as a REC_TYPE_ERROR result
|
||||
/* value.
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP server
|
||||
/* The SMTP proxy server host:port. The host or host: part is optional.
|
||||
/* .IP timeout
|
||||
/* Time limit for connecting to the proxy server and for
|
||||
/* sending and receiving proxy server commands and replies.
|
||||
/* .IP ehlo_name
|
||||
/* The EHLO Hostname that will be sent to the proxy server.
|
||||
/* .IP mail_from
|
||||
/* The MAIL FROM command.
|
||||
/* .IP state
|
||||
/* SMTP server state.
|
||||
/* .IP expect
|
||||
/* 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_STAT_ANY
|
||||
/* The caller has no expectation. Do not warn for unexpected replies.
|
||||
/* .IP SMTPD_PROX_STAT_OK
|
||||
/* The caller expects a reply in the 200 range.
|
||||
/* .IP SMTPD_PROX_STAT_MORE
|
||||
/* The caller expects a reply in the 300 range.
|
||||
/* .IP SMTPD_PROX_STAT_DEFER
|
||||
/* .IP SMTPD_PROX_STAT_FAIL
|
||||
/* The caller perversely expects a reply in the 400 and 500 range,
|
||||
/* respectively.
|
||||
/* .RE
|
||||
/* .IP format
|
||||
/* A format string.
|
||||
/* .IP stream
|
||||
/* Connection to proxy server.
|
||||
/* .IP data
|
||||
/* Pointer to the content of one message content record.
|
||||
/* .IP len
|
||||
/* The length of a message content record.
|
||||
/* SEE ALSO
|
||||
/* smtpd(8) Postfix smtp server
|
||||
/* DIAGNOSTICS
|
||||
/* Fatal errors: memory allocation problem.
|
||||
/*
|
||||
/* Warnings: unexpected response from proxy server, unable
|
||||
/* to connect to proxy server, proxy server read/write error.
|
||||
/* 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 <sys_defs.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <msg.h>
|
||||
#include <vstream.h>
|
||||
#include <vstring.h>
|
||||
#include <stringops.h>
|
||||
#include <connect.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
#include <mail_error.h>
|
||||
#include <smtp_stream.h>
|
||||
#include <cleanup_user.h>
|
||||
#include <mail_params.h>
|
||||
#include <rec_type.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include <smtpd.h>
|
||||
#include <smtpd_proxy.h>
|
||||
|
||||
/*
|
||||
* SLMs.
|
||||
*/
|
||||
#define STR(x) vstring_str(x)
|
||||
#define LEN(x) VSTRING_LEN(x)
|
||||
|
||||
/* smtpd_proxy_open - open proxy connection after MAIL FROM */
|
||||
|
||||
int smtpd_proxy_open(SMTPD_STATE *state, const char *service,
|
||||
int timeout, const char *ehlo_name,
|
||||
const char *mail_from)
|
||||
{
|
||||
int fd;
|
||||
|
||||
/*
|
||||
* This buffer persists beyond the end of a proxy session so we can
|
||||
* inspect the last command's reply.
|
||||
*/
|
||||
if (state->proxy_buffer == 0)
|
||||
state->proxy_buffer = vstring_alloc(10);
|
||||
|
||||
/*
|
||||
* Connect to proxy.
|
||||
*/
|
||||
if ((fd = inet_connect(service, BLOCKING, timeout)) < 0) {
|
||||
state->error_mask |= MAIL_ERROR_SOFTWARE;
|
||||
state->err |= CLEANUP_STAT_PROXY;
|
||||
msg_warn("connect to proxy service %s: %m", service);
|
||||
vstring_sprintf(state->proxy_buffer,
|
||||
"451 Error: queue file write error");
|
||||
return (-1);
|
||||
}
|
||||
state->proxy = vstream_fdopen(fd, O_RDWR);
|
||||
vstream_control(state->proxy, VSTREAM_CTL_PATH, service, VSTREAM_CTL_END);
|
||||
smtp_timeout_setup(state->proxy, timeout);
|
||||
|
||||
/*
|
||||
* Get server greeting banner.
|
||||
*
|
||||
* XXX If this fails then we should not send the initial reply when the
|
||||
* client expects the MAIL FROM reply.
|
||||
*/
|
||||
if (smtpd_proxy_cmd(state, SMTPD_PROX_STAT_OK, (char *) 0) != 0) {
|
||||
vstring_sprintf(state->proxy_buffer,
|
||||
"451 Error: queue file write error");
|
||||
smtpd_proxy_close(state);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send our own EHLO command.
|
||||
*
|
||||
* XXX If this fails then we should not send the EHLO reply when the client
|
||||
* expects the MAIL FROM reply.
|
||||
*/
|
||||
if (smtpd_proxy_cmd(state, SMTPD_PROX_STAT_OK, "EHLO %s", ehlo_name) != 0) {
|
||||
vstring_sprintf(state->proxy_buffer,
|
||||
"451 Error: queue file write error");
|
||||
smtpd_proxy_close(state);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass-through the client's MAIL FROM command.
|
||||
*/
|
||||
if (smtpd_proxy_cmd(state, SMTPD_PROX_STAT_OK, "%s", mail_from) != 0) {
|
||||
smtpd_proxy_close(state);
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* smtpd_proxy_comms_error - report proxy communication error */
|
||||
|
||||
static int smtpd_proxy_comms_error(VSTREAM *stream, int err)
|
||||
{
|
||||
switch (err) {
|
||||
case SMTP_ERR_EOF:
|
||||
msg_warn("lost connection with proxy %s", VSTREAM_PATH(stream));
|
||||
return (err);
|
||||
case SMTP_ERR_TIME:
|
||||
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",
|
||||
VSTREAM_PATH(stream), err);
|
||||
}
|
||||
}
|
||||
|
||||
/* smtpd_proxy_cmd_error - report unexpected proxy reply */
|
||||
|
||||
static void smtpd_proxy_cmd_error(SMTPD_STATE *state, const char *fmt,
|
||||
va_list ap)
|
||||
{
|
||||
VSTRING *buf;
|
||||
|
||||
/*
|
||||
* The command can be omitted at the start of an SMTP session. A null
|
||||
* format string is not documented as part of the official interface
|
||||
* because it is used only internally to this module.
|
||||
*/
|
||||
buf = vstring_alloc(100);
|
||||
vstring_vsprintf(buf, fmt && *fmt ? fmt : "connection request", ap);
|
||||
msg_warn("proxy %s rejected \"%s\": \"%s\"", VSTREAM_PATH(state->proxy),
|
||||
STR(buf), STR(state->proxy_buffer));
|
||||
vstring_free(buf);
|
||||
}
|
||||
|
||||
/* smtpd_proxy_cmd - send command to proxy, receive reply */
|
||||
|
||||
int smtpd_proxy_cmd(SMTPD_STATE *state, int expect, const char *fmt,...)
|
||||
{
|
||||
va_list ap;
|
||||
char *cp;
|
||||
int last_char;
|
||||
int err = 0;
|
||||
|
||||
/*
|
||||
* Errors first. Be prepared for delayed errors from the DATA phase.
|
||||
*/
|
||||
if (vstream_ftimeout(state->proxy)
|
||||
|| vstream_ferror(state->proxy)
|
||||
|| vstream_feof(state->proxy)
|
||||
|| ((err = vstream_setjmp(state->proxy) != 0)
|
||||
&& smtpd_proxy_comms_error(state->proxy, err))) {
|
||||
state->error_mask |= MAIL_ERROR_SOFTWARE;
|
||||
state->err |= CLEANUP_STAT_PROXY;
|
||||
vstring_sprintf(state->proxy_buffer,
|
||||
"451 Error: queue file write error");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* The command can be omitted at the start of an SMTP session. A null
|
||||
* format string is not documented as part of the official interface
|
||||
* because it is used only internally to this module.
|
||||
*/
|
||||
if (fmt && *fmt) {
|
||||
|
||||
/*
|
||||
* Format the command.
|
||||
*/
|
||||
va_start(ap, fmt);
|
||||
vstring_vsprintf(state->proxy_buffer, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
/*
|
||||
* Optionally log the command first, so that we can see in the log
|
||||
* what the program is trying to do.
|
||||
*/
|
||||
if (msg_verbose)
|
||||
msg_info("> %s: %s", VSTREAM_PATH(state->proxy),
|
||||
STR(state->proxy_buffer));
|
||||
|
||||
/*
|
||||
* Send the command to the proxy server. Since we're going to read a
|
||||
* reply immediately, there is no need to flush buffers.
|
||||
*/
|
||||
smtp_fputs(STR(state->proxy_buffer), LEN(state->proxy_buffer),
|
||||
state->proxy);
|
||||
}
|
||||
|
||||
/*
|
||||
* Censor out non-printable characters in server responses and keep the
|
||||
* last line of multi-line responses.
|
||||
*/
|
||||
for (;;) {
|
||||
last_char = smtp_get(state->proxy_buffer, state->proxy, var_line_limit);
|
||||
printable(STR(state->proxy_buffer), '?');
|
||||
if (last_char != '\n')
|
||||
msg_warn("%s: response longer than %d: %.30s...",
|
||||
VSTREAM_PATH(state->proxy), var_line_limit,
|
||||
STR(state->proxy_buffer));
|
||||
if (msg_verbose)
|
||||
msg_info("< %s: %s", VSTREAM_PATH(state->proxy),
|
||||
STR(state->proxy_buffer));
|
||||
|
||||
/*
|
||||
* Parse the response into code and text. Ignore unrecognized
|
||||
* garbage. This means that any character except space (or end of
|
||||
* line) will have the same effect as the '-' line continuation
|
||||
* character.
|
||||
*/
|
||||
for (cp = STR(state->proxy_buffer); *cp && ISDIGIT(*cp); cp++)
|
||||
/* void */ ;
|
||||
if (cp - STR(state->proxy_buffer) == 3) {
|
||||
if (*cp == '-')
|
||||
continue;
|
||||
if (*cp == ' ' || *cp == 0)
|
||||
break;
|
||||
}
|
||||
msg_warn("received garbage from proxy %s: %.100s",
|
||||
VSTREAM_PATH(state->proxy), STR(state->proxy_buffer));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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_STAT_ANY
|
||||
&& expect != (STR(state->proxy_buffer)[0] - '0')) {
|
||||
va_start(ap, fmt);
|
||||
smtpd_proxy_cmd_error(state, fmt, ap);
|
||||
va_end(ap);
|
||||
return (-1);
|
||||
} else {
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* smtpd_proxy_rec_put - send message content, rec_put() clone */
|
||||
|
||||
int smtpd_proxy_rec_put(VSTREAM *stream, int rec_type,
|
||||
const char *data, int len)
|
||||
{
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Errors first.
|
||||
*/
|
||||
if (vstream_ftimeout(stream) || vstream_ferror(stream)
|
||||
|| vstream_feof(stream))
|
||||
return (REC_TYPE_ERROR);
|
||||
if ((err = vstream_setjmp(stream)) != 0)
|
||||
return (smtpd_proxy_comms_error(stream, err), REC_TYPE_ERROR);
|
||||
|
||||
/*
|
||||
* Send one content record. Errors and results must be as with rec_put().
|
||||
*/
|
||||
if (rec_type == REC_TYPE_NORM)
|
||||
smtp_fputs(data, len, stream);
|
||||
else
|
||||
smtp_fwrite(data, len, stream);
|
||||
return (rec_type);
|
||||
}
|
||||
|
||||
/* smtpd_proxy_rec_fprintf - send message content, rec_fprintf() clone */
|
||||
|
||||
int smtpd_proxy_rec_fprintf(VSTREAM *stream, int rec_type,
|
||||
const char *fmt,...)
|
||||
{
|
||||
va_list ap;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Errors first.
|
||||
*/
|
||||
if (vstream_ftimeout(stream) || vstream_ferror(stream)
|
||||
|| vstream_feof(stream))
|
||||
return (REC_TYPE_ERROR);
|
||||
if ((err = vstream_setjmp(stream)) != 0)
|
||||
return (smtpd_proxy_comms_error(stream, err), REC_TYPE_ERROR);
|
||||
|
||||
/*
|
||||
* Send one content record. Errors and results must be as with
|
||||
* rec_fprintf().
|
||||
*/
|
||||
va_start(ap, fmt);
|
||||
if (rec_type != REC_TYPE_NORM)
|
||||
msg_panic("smtpd_proxy_rec_fprintf: need REC_TYPE_NORM");
|
||||
smtp_vprintf(stream, fmt, ap);
|
||||
va_end(ap);
|
||||
return (rec_type);
|
||||
}
|
||||
|
||||
/* smtpd_proxy_close - close proxy connection */
|
||||
|
||||
void smtpd_proxy_close(SMTPD_STATE *state)
|
||||
{
|
||||
(void) vstream_fclose(state->proxy);
|
||||
state->proxy = 0;
|
||||
}
|
42
postfix/src/smtpd/smtpd_proxy.h
Normal file
42
postfix/src/smtpd/smtpd_proxy.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* smtpd_proxy 3h
|
||||
/* SUMMARY
|
||||
/* SMTP server pass-through proxy client
|
||||
/* SYNOPSIS
|
||||
/* #include <smtpd.h>
|
||||
/* #include <smtpd_proxy.h>
|
||||
/* DESCRIPTION
|
||||
/* .nf
|
||||
|
||||
/*
|
||||
* Utility library.
|
||||
*/
|
||||
#include <vstream.h>
|
||||
#include <vstring.h>
|
||||
|
||||
/*
|
||||
* Application-specific.
|
||||
*/
|
||||
#define SMTPD_PROX_STAT_ANY 0
|
||||
#define SMTPD_PROX_STAT_OK 2
|
||||
#define SMTPD_PROX_STAT_MORE 3
|
||||
#define SMTPD_PROX_STAT_DEFER 4
|
||||
#define SMTPD_PROX_STAT_FAIL 5
|
||||
|
||||
extern int smtpd_proxy_open(SMTPD_STATE *, const char *, int, const char *, const char *);
|
||||
extern int smtpd_proxy_cmd(SMTPD_STATE *, int, const char *,...);
|
||||
extern int smtpd_proxy_rec_put(VSTREAM *, int, const char *, int);
|
||||
extern int smtpd_proxy_rec_fprintf(VSTREAM *, int, const char *,...);
|
||||
extern void smtpd_proxy_close(SMTPD_STATE *);
|
||||
|
||||
/* 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
|
||||
/*--*/
|
@ -99,6 +99,8 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
|
||||
state->defer_if_permit.reason = 0;
|
||||
state->discard = 0;
|
||||
state->expand_buf = 0;
|
||||
state->proxy = 0;
|
||||
state->proxy_buffer = 0;
|
||||
|
||||
#ifdef USE_SASL_AUTH
|
||||
if (SMTPD_STAND_ALONE(state))
|
||||
@ -137,6 +139,8 @@ void smtpd_state_reset(SMTPD_STATE *state)
|
||||
vstring_free(state->defer_if_reject.reason);
|
||||
if (state->expand_buf)
|
||||
vstring_free(state->expand_buf);
|
||||
if (state->proxy_buffer)
|
||||
vstring_free(state->proxy_buffer);
|
||||
|
||||
#ifdef USE_SASL_AUTH
|
||||
if (var_smtpd_sasl_enable)
|
||||
|
@ -3,7 +3,7 @@ SRCS = alldig.c argv.c argv_split.c attr_print0.c attr_print64.c \
|
||||
attr_scan0.c attr_scan64.c base64_code.c basename.c binhash.c \
|
||||
chroot_uid.c clean_env.c close_on_exec.c concatenate.c ctable.c \
|
||||
dict.c dict_alloc.c dict_db.c dict_dbm.c dict_debug.c dict_env.c \
|
||||
dict_ht.c dict_ldap.c dict_mysql.c dict_ni.c dict_nis.c \
|
||||
dict_cidr.c dict_ht.c dict_ldap.c dict_mysql.c dict_ni.c dict_nis.c \
|
||||
dict_nisplus.c dict_open.c dict_pcre.c dict_pgsql.c dict_regexp.c \
|
||||
dict_static.c dict_tcp.c dict_unix.c dir_forest.c doze.c \
|
||||
duplex_pipe.c environ.c events.c exec_command.c fifo_listen.c \
|
||||
@ -31,7 +31,7 @@ OBJS = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
|
||||
attr_scan0.o attr_scan64.o base64_code.o basename.o binhash.o \
|
||||
chroot_uid.o clean_env.o close_on_exec.o concatenate.o ctable.o \
|
||||
dict.o dict_alloc.o dict_db.o dict_dbm.o dict_debug.o dict_env.o \
|
||||
dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \
|
||||
dict_cidr.o dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \
|
||||
dict_nisplus.o dict_open.o dict_pcre.o dict_pgsql.o dict_regexp.o \
|
||||
dict_static.o dict_tcp.o dict_unix.o dir_forest.o doze.o \
|
||||
duplex_pipe.o environ.o events.o exec_command.o fifo_listen.o \
|
||||
@ -57,7 +57,7 @@ OBJS = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
|
||||
write_buf.o write_wait.o $(STRCASE)
|
||||
HDRS = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
|
||||
connect.h ctable.h dict.h dict_db.h dict_dbm.h dict_env.h \
|
||||
dict_ht.h dict_ldap.h dict_mysql.h dict_ni.h dict_nis.h \
|
||||
dict_cidr.h dict_ht.h dict_ldap.h dict_mysql.h dict_ni.h dict_nis.h \
|
||||
dict_nisplus.h dict_pcre.h dict_pgsql.h dict_regexp.h \
|
||||
dict_static.h dict_tcp.h dict_unix.h dir_forest.h events.h \
|
||||
exec_command.h find_inet.h fsspace.h fullname.h get_domainname.h \
|
||||
@ -337,7 +337,8 @@ stream_test: stream_test.c $(LIB)
|
||||
|
||||
tests: valid_hostname_test mac_expand_test dict_test unescape_test \
|
||||
hex_quote_test ctable_test inet_addr_list_test base64_code_test \
|
||||
attr_scan64_test attr_scan0_test dict_pcre_test host_port_test
|
||||
attr_scan64_test attr_scan0_test dict_pcre_test host_port_test \
|
||||
dict_cidr_test
|
||||
|
||||
valid_hostname_test: valid_hostname valid_hostname.in valid_hostname.ref
|
||||
./valid_hostname <valid_hostname.in 2>valid_hostname.tmp
|
||||
@ -403,6 +404,11 @@ dict_regexp_test: dict_open dict_regexp.in dict_regexp.map dict_regexp.ref
|
||||
diff dict_regexp.ref dict_regexp.tmp
|
||||
rm -f dict_regexp.tmp
|
||||
|
||||
dict_cidr_test: dict_open dict_cidr.in dict_cidr.map dict_cidr.ref
|
||||
./dict_open cidr:dict_cidr.map read <dict_cidr.in >dict_cidr.tmp 2>&1
|
||||
diff dict_cidr.ref dict_cidr.tmp
|
||||
rm -f dict_cidr.tmp
|
||||
|
||||
host_port_test: host_port host_port.in host_port.ref
|
||||
./host_port <host_port.in >host_port.tmp 2>&1
|
||||
diff host_port.ref host_port.tmp
|
||||
@ -529,6 +535,19 @@ dict_alloc.o: dict.h
|
||||
dict_alloc.o: vstream.h
|
||||
dict_alloc.o: vbuf.h
|
||||
dict_alloc.o: argv.h
|
||||
dict_cidr.o: dict_cidr.c
|
||||
dict_cidr.o: sys_defs.h
|
||||
dict_cidr.o: mymalloc.h
|
||||
dict_cidr.o: msg.h
|
||||
dict_cidr.o: vstream.h
|
||||
dict_cidr.o: vbuf.h
|
||||
dict_cidr.o: vstring.h
|
||||
dict_cidr.o: stringops.h
|
||||
dict_cidr.o: readlline.h
|
||||
dict_cidr.o: dict.h
|
||||
dict_cidr.o: argv.h
|
||||
dict_cidr.o: dict_cidr.h
|
||||
dict_cidr.o: split_at.h
|
||||
dict_db.o: dict_db.c
|
||||
dict_db.o: sys_defs.h
|
||||
dict_db.o: msg.h
|
||||
@ -619,6 +638,7 @@ dict_open.o: dict_pgsql.h
|
||||
dict_open.o: dict_pcre.h
|
||||
dict_open.o: dict_regexp.h
|
||||
dict_open.o: dict_static.h
|
||||
dict_open.o: dict_cidr.h
|
||||
dict_open.o: stringops.h
|
||||
dict_open.o: vstring.h
|
||||
dict_open.o: split_at.h
|
||||
|
242
postfix/src/util/dict_cidr.c
Normal file
242
postfix/src/util/dict_cidr.c
Normal file
@ -0,0 +1,242 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* dict_cidr 3
|
||||
/* SUMMARY
|
||||
/* Dictionary interface for CIDR data
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_cidr.h>
|
||||
/*
|
||||
/* DICT *dict_cidr_open(name, dummy, dict_flags)
|
||||
/* const char *name;
|
||||
/* int dummy;
|
||||
/* int dict_flags;
|
||||
/* DESCRIPTION
|
||||
/* dict_cidr_open() opens the named file and stores
|
||||
/* the key/value pairs where the key must be either a
|
||||
/* "naked" IP address or a netblock in CIDR notation.
|
||||
/* SEE ALSO
|
||||
/* dict(3) generic dictionary manager
|
||||
/* AUTHOR(S)
|
||||
/* Jozsef Kadlecsik
|
||||
/* kadlec@blackhole.kfki.hu
|
||||
/* KFKI Research Institute for Particle and Nuclear Physics
|
||||
/* POB. 49
|
||||
/* 1525 Budapest, Hungary
|
||||
/*
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
#define INADDR_NONE 0xffffffff
|
||||
#endif
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <mymalloc.h>
|
||||
#include <msg.h>
|
||||
#include <vstream.h>
|
||||
#include <vstring.h>
|
||||
#include <stringops.h>
|
||||
#include <readlline.h>
|
||||
#include <dict.h>
|
||||
#include <dict_cidr.h>
|
||||
#include <split_at.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
/*
|
||||
* Each rule in a CIDR table is parsed and stored in a linked list.
|
||||
* Obviously all this is IPV4 specific and needs to be redone for IPV6.
|
||||
*/
|
||||
typedef struct DICT_CIDR_ENTRY {
|
||||
unsigned long net_bits; /* network portion of address */
|
||||
unsigned long mask_bits; /* network mask */
|
||||
char *value; /* lookup result */
|
||||
struct DICT_CIDR_ENTRY *next; /* next entry */
|
||||
} DICT_CIDR_ENTRY;
|
||||
|
||||
typedef struct {
|
||||
DICT dict; /* generic members */
|
||||
DICT_CIDR_ENTRY *head; /* first entry */
|
||||
} DICT_CIDR;
|
||||
|
||||
#define BITS_PER_ADDR 32
|
||||
|
||||
/* dict_cidr_lookup - CIDR table lookup */
|
||||
|
||||
static const char *dict_cidr_lookup(DICT *dict, const char *key)
|
||||
{
|
||||
DICT_CIDR *dict_cidr = (DICT_CIDR *) dict;
|
||||
DICT_CIDR_ENTRY *entry;
|
||||
unsigned long addr;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("dict_cidr_lookup: %s: %s", dict_cidr->dict.name, key);
|
||||
|
||||
if ((addr = inet_addr(key)) == INADDR_NONE)
|
||||
return (0);
|
||||
|
||||
for (entry = dict_cidr->head; entry; entry = entry->next)
|
||||
if ((addr & entry->mask_bits) == entry->net_bits)
|
||||
return (entry->value);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* dict_cidr_close - close the CIDR table */
|
||||
|
||||
static void dict_cidr_close(DICT *dict)
|
||||
{
|
||||
DICT_CIDR *dict_cidr = (DICT_CIDR *) dict;
|
||||
DICT_CIDR_ENTRY *entry;
|
||||
DICT_CIDR_ENTRY *next;
|
||||
|
||||
for (entry = dict_cidr->head; entry; entry = next) {
|
||||
next = entry->next;
|
||||
myfree(entry->value);
|
||||
myfree((char *) entry);
|
||||
}
|
||||
dict_free(dict);
|
||||
}
|
||||
|
||||
/* dict_cidr_parse_rule - parse CIDR table rule into network, mask and value */
|
||||
|
||||
static DICT_CIDR_ENTRY *dict_cidr_parse_rule(const char *mapname, int lineno,
|
||||
char *p)
|
||||
{
|
||||
DICT_CIDR_ENTRY *rule;
|
||||
char *key;
|
||||
char *value;
|
||||
char *mask;
|
||||
int mask_shift;
|
||||
unsigned long net_bits;
|
||||
unsigned long mask_bits;
|
||||
struct in_addr net_addr;
|
||||
|
||||
/*
|
||||
* Split into key and value. We already eliminated leading whitespace,
|
||||
* comments, empty lines or lines with whitespace only. This means a null
|
||||
* key can't happen but we will handle this anyway.
|
||||
*/
|
||||
key = p;
|
||||
while (*p && !ISSPACE(*p)) /* Skip over key */
|
||||
p++;
|
||||
if (*p) /* Terminate key */
|
||||
*p++ = 0;
|
||||
while (*p && ISSPACE(*p)) /* Skip whitespace */
|
||||
p++;
|
||||
value = p;
|
||||
trimblanks(value, 0)[0] = 0; /* Trim trailing blanks */
|
||||
if (*key == 0) {
|
||||
msg_warn("cidr map %s, line %d: no address pattern: skipping this rule",
|
||||
mapname, lineno);
|
||||
return (0);
|
||||
}
|
||||
if (*value == 0) {
|
||||
msg_warn("cidr map %s, line %d: no lookup result: skipping this rule",
|
||||
mapname, lineno);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the key into network and mask, and destroy the key. Treat a bare
|
||||
* network address as /32.
|
||||
*/
|
||||
if ((mask = split_at(key, '/')) != 0) {
|
||||
if ((mask_shift = atoi(mask)) <= 0 || mask_shift > BITS_PER_ADDR
|
||||
|| (net_bits = inet_addr(key)) == INADDR_NONE) {
|
||||
msg_warn("cidr map %s, line %d: bad net/mask pattern: \"%s/%s\": "
|
||||
"skipping this rule", mapname, lineno, key, mask);
|
||||
return (0);
|
||||
}
|
||||
mask_bits = htonl((0xffffffff) << (BITS_PER_ADDR - mask_shift));
|
||||
if (net_bits & ~mask_bits) {
|
||||
net_addr.s_addr = (net_bits & mask_bits);
|
||||
msg_warn("cidr map %s, line %d: net/mask pattern \"%s/%s\" with "
|
||||
"non-null host portion: skipping this rule",
|
||||
mapname, lineno, key, mask);
|
||||
msg_warn("specify \"%s/%d\" if this is really what you want",
|
||||
inet_ntoa(net_addr), mask_shift);
|
||||
return (0);
|
||||
}
|
||||
} else {
|
||||
if ((net_bits = inet_addr(key)) == INADDR_NONE) {
|
||||
msg_warn("cidr map %s, line %d: bad address pattern: \"%s\": "
|
||||
"skipping this rule", mapname, lineno, key);
|
||||
return (0);
|
||||
}
|
||||
mask_shift = 32;
|
||||
mask_bits = htonl(0xffffffff);
|
||||
}
|
||||
|
||||
rule = (DICT_CIDR_ENTRY *) mymalloc(sizeof(DICT_CIDR_ENTRY));
|
||||
rule->net_bits = net_bits;
|
||||
rule->mask_bits = mask_bits;
|
||||
rule->value = mystrdup(value);
|
||||
rule->next = 0;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("dict_cidr_open: %s: %lu/%d %s",
|
||||
mapname, rule->net_bits, mask_shift, rule->value);
|
||||
|
||||
return (rule);
|
||||
}
|
||||
|
||||
/* dict_cidr_open - parse CIDR table */
|
||||
|
||||
DICT *dict_cidr_open(const char *mapname, int unused_flags, int dict_flags)
|
||||
{
|
||||
DICT_CIDR *dict_cidr;
|
||||
VSTREAM *map_fp;
|
||||
VSTRING *line_buffer = vstring_alloc(100);
|
||||
DICT_CIDR_ENTRY *rule;
|
||||
DICT_CIDR_ENTRY *last_rule = 0;
|
||||
int lineno = 0;
|
||||
|
||||
/*
|
||||
* XXX Eliminate unnecessary queries by setting a flag that says "this
|
||||
* map matches network addresses only".
|
||||
*/
|
||||
dict_cidr = (DICT_CIDR *) dict_alloc(DICT_TYPE_CIDR, mapname,
|
||||
sizeof(*dict_cidr));
|
||||
dict_cidr->dict.lookup = dict_cidr_lookup;
|
||||
dict_cidr->dict.close = dict_cidr_close;
|
||||
dict_cidr->dict.flags = dict_flags | DICT_FLAG_PATTERN;
|
||||
dict_cidr->head = 0;
|
||||
|
||||
if ((map_fp = vstream_fopen(mapname, O_RDONLY, 0)) == 0)
|
||||
msg_fatal("open %s: %m", mapname);
|
||||
|
||||
while (readlline(line_buffer, map_fp, &lineno)) {
|
||||
rule = dict_cidr_parse_rule(mapname, lineno, vstring_str(line_buffer));
|
||||
if (rule == 0)
|
||||
continue;
|
||||
if (last_rule == 0)
|
||||
dict_cidr->head = rule;
|
||||
else
|
||||
last_rule->next = rule;
|
||||
last_rule = rule;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up.
|
||||
*/
|
||||
if (vstream_fclose(map_fp))
|
||||
msg_fatal("cidr map %s: read error: %m", mapname);
|
||||
vstring_free(line_buffer);
|
||||
|
||||
return (DICT_DEBUG (&dict_cidr->dict));
|
||||
}
|
43
postfix/src/util/dict_cidr.h
Normal file
43
postfix/src/util/dict_cidr.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef _DICT_CIDR_H_INCLUDED_
|
||||
#define _DICT_CIDR_H_INCLUDED_
|
||||
|
||||
/*++
|
||||
/* NAME
|
||||
/* dict_cidr 3h
|
||||
/* SUMMARY
|
||||
/* Dictionary manager interface to handle cidr data.
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_cidr.h>
|
||||
/* DESCRIPTION
|
||||
/* .nf
|
||||
|
||||
/*
|
||||
* Utility library.
|
||||
*/
|
||||
#include <dict.h>
|
||||
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
extern DICT *dict_cidr_open(const char *, int, int);
|
||||
|
||||
#define DICT_TYPE_CIDR "cidr"
|
||||
|
||||
/* 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
|
||||
/*
|
||||
/* Jozsef Kadlecsik
|
||||
/* kadlec@blackhole.kfki.hu
|
||||
/* KFKI Research Institute for Particle and Nuclear Physics
|
||||
/* POB. 49
|
||||
/* 1525 Budapest 114, Hungary
|
||||
/*--*/
|
||||
|
||||
#endif
|
7
postfix/src/util/dict_cidr.in
Normal file
7
postfix/src/util/dict_cidr.in
Normal file
@ -0,0 +1,7 @@
|
||||
get 172.16.0.0
|
||||
get 172.16.0.1
|
||||
get 172.16.7.255
|
||||
get 172.16.8.1
|
||||
get 172.16.17.1
|
||||
get 172.17.1.1
|
||||
get 172.17.1.2
|
9
postfix/src/util/dict_cidr.map
Normal file
9
postfix/src/util/dict_cidr.map
Normal file
@ -0,0 +1,9 @@
|
||||
172.16.0.0/21 554 match bad netblock 172.16.0.0/21
|
||||
172.16.8.0/21 554 match bad netblock 172.16.8.0/21
|
||||
172.16.0.0/16 554 match bad netblock 172.16.0.0/16
|
||||
172.17.1.1 554 match bad naked address
|
||||
172.16.1.3/21 whatever
|
||||
172.16.1.3/33 whatever
|
||||
172.999.0.0/21 whatever
|
||||
172.16.1.999 whatever
|
||||
172.16.1.4
|
13
postfix/src/util/dict_cidr.ref
Normal file
13
postfix/src/util/dict_cidr.ref
Normal file
@ -0,0 +1,13 @@
|
||||
./dict_open: warning: cidr map dict_cidr.map, line 5: net/mask pattern "172.16.1.3/21" with non-null host portion: skipping this rule
|
||||
./dict_open: warning: specify "172.16.0.0/21" if this is really what you want
|
||||
./dict_open: warning: cidr map dict_cidr.map, line 6: bad net/mask pattern: "172.16.1.3/33": skipping this rule
|
||||
./dict_open: warning: cidr map dict_cidr.map, line 7: bad net/mask pattern: "172.999.0.0/21": skipping this rule
|
||||
./dict_open: warning: cidr map dict_cidr.map, line 8: bad address pattern: "172.16.1.999": skipping this rule
|
||||
./dict_open: warning: cidr map dict_cidr.map, line 9: no lookup result: skipping this rule
|
||||
172.16.0.0=554 match bad netblock 172.16.0.0/21
|
||||
172.16.0.1=554 match bad netblock 172.16.0.0/21
|
||||
172.16.7.255=554 match bad netblock 172.16.0.0/21
|
||||
172.16.8.1=554 match bad netblock 172.16.8.0/21
|
||||
172.16.17.1=554 match bad netblock 172.16.0.0/16
|
||||
172.17.1.1=554 match bad naked address
|
||||
172.17.1.2: not found
|
@ -57,12 +57,27 @@
|
||||
/* If you must bind to the server, do it with this distinguished name ...
|
||||
/* .IP \fIldapsource_\fRbind_pw
|
||||
/* \&... and this password.
|
||||
/* .IP \fIldapsource_\fRcache
|
||||
/* .IP \fIldapsource_\fRcache (no longer supported)
|
||||
/* Whether or not to turn on client-side caching.
|
||||
/* .IP \fIldapsource_\fRcache_expiry
|
||||
/* .IP \fIldapsource_\fRcache_expiry (no longer supported)
|
||||
/* If you do cache results, expire them after this many seconds.
|
||||
/* .IP \fIldapsource_\fRcache_size
|
||||
/* .IP \fIldapsource_\fRcache_size (no longer supported)
|
||||
/* The cache size in bytes. Does nothing if the cache is off, of course.
|
||||
/* .IP \fIldapsource_\fRrecursion_limit
|
||||
/* Maximum recursion depth when expanding DN or URL references.
|
||||
/* Queries which exceed the recursion limit fail with
|
||||
/* dict_errno = DICT_ERR_RETRY.
|
||||
/* .IP \fIldapsource_\fRexpansion_limit
|
||||
/* Limit (if any) on the total number of lookup result values. Lookups which
|
||||
/* exceed the limit fail with dict_errno=DICT_ERR_RETRY. Note that
|
||||
/* each value of a multivalued result attribute counts as one result.
|
||||
/* .IP \fIldapsource_\fRsize_limit
|
||||
/* Limit on the number of entries returned by individual LDAP queries.
|
||||
/* Queries which exceed the limit fail with dict_errno=DICT_ERR_RETRY.
|
||||
/* This is an *entry* count, for any single query performed during the
|
||||
/* possibly recursive lookup.
|
||||
/* .IP \fIldapsource_\fRchase_referrals
|
||||
/* Controls whether LDAP referrals are obeyed.
|
||||
/* .IP \fIldapsource_\fRdereference
|
||||
/* How to handle LDAP aliases. See ldap.h or ldap_open(3) man page.
|
||||
/* .IP \fIldapsource_\fRdebuglevel
|
||||
@ -152,10 +167,10 @@ typedef struct {
|
||||
char *bind_dn;
|
||||
char *bind_pw;
|
||||
int timeout;
|
||||
int cache;
|
||||
long cache_expiry;
|
||||
long cache_size;
|
||||
int dereference;
|
||||
long recursion_limit;
|
||||
long expansion_limit;
|
||||
long size_limit;
|
||||
int chase_referrals;
|
||||
int debuglevel;
|
||||
int version;
|
||||
@ -231,11 +246,6 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
|
||||
char *myname = "dict_ldap_connect";
|
||||
int rc = 0;
|
||||
|
||||
#ifdef LDAP_API_FEATURE_X_MEMCACHE
|
||||
LDAPMemCache *dircache;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef LDAP_OPT_NETWORK_TIMEOUT
|
||||
struct timeval mytimeval;
|
||||
|
||||
@ -313,6 +323,16 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Limit the number of entries returned by each query.
|
||||
*/
|
||||
if (dict_ldap->size_limit) {
|
||||
if (ldap_set_option(dict_ldap->ld, LDAP_OPT_SIZELIMIT,
|
||||
&dict_ldap->size_limit) != LDAP_OPT_SUCCESS)
|
||||
msg_warn("%s: %s: Unable to set query result size limit to %ld.",
|
||||
myname, dict_ldap->ldapsource, dict_ldap->size_limit);
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure alias dereferencing for this connection. Thanks to Mike
|
||||
* Mattice for this, and to Hery Rakotoarisoa for the v3 update.
|
||||
@ -370,52 +390,6 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
|
||||
msg_info("%s: Successful bind to server %s as %s ",
|
||||
myname, dict_ldap->server_host, dict_ldap->bind_dn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up client-side caching if it's configured.
|
||||
*/
|
||||
if (dict_ldap->cache) {
|
||||
if (msg_verbose)
|
||||
msg_info
|
||||
("%s: Enabling %ld-byte cache for %s with %ld-second expiry",
|
||||
myname, dict_ldap->cache_size, dict_ldap->ldapsource,
|
||||
dict_ldap->cache_expiry);
|
||||
|
||||
#ifdef LDAP_API_FEATURE_X_MEMCACHE
|
||||
rc = ldap_memcache_init(dict_ldap->cache_expiry, dict_ldap->cache_size,
|
||||
NULL, NULL, &dircache);
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
msg_warn
|
||||
("%s: Unable to configure cache for %s: %d (%s) -- continuing",
|
||||
myname, dict_ldap->ldapsource, rc, ldap_err2string(rc));
|
||||
} else {
|
||||
rc = ldap_memcache_set(dict_ldap->ld, dircache);
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
msg_warn
|
||||
("%s: Unable to configure cache for %s: %d (%s) -- continuing",
|
||||
myname, dict_ldap->ldapsource, rc, ldap_err2string(rc));
|
||||
} else {
|
||||
if (msg_verbose)
|
||||
msg_info("%s: Caching enabled for %s",
|
||||
myname, dict_ldap->ldapsource);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
rc = ldap_enable_cache(dict_ldap->ld, dict_ldap->cache_expiry,
|
||||
dict_ldap->cache_size);
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
msg_warn
|
||||
("%s: Unable to configure cache for %s: %d (%s) -- continuing",
|
||||
myname, dict_ldap->ldapsource, rc, ldap_err2string(rc));
|
||||
} else {
|
||||
if (msg_verbose)
|
||||
msg_info("%s: Caching enabled for %s",
|
||||
myname, dict_ldap->ldapsource);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
if (msg_verbose)
|
||||
msg_info("%s: Cached connection handle for LDAP source %s",
|
||||
myname, dict_ldap->ldapsource);
|
||||
@ -426,7 +400,8 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
|
||||
/*
|
||||
* expand a filter (lookup or result)
|
||||
*/
|
||||
static void dict_ldap_expand_filter(char *filter, char *value, VSTRING *out)
|
||||
static void dict_ldap_expand_filter(char *ldapsource, char *filter,
|
||||
char *value, VSTRING *out)
|
||||
{
|
||||
char *myname = "dict_ldap_expand_filter";
|
||||
char *sub,
|
||||
@ -461,9 +436,8 @@ static void dict_ldap_expand_filter(char *filter, char *value, VSTRING *out)
|
||||
vstring_strcat(out, u);
|
||||
break;
|
||||
default:
|
||||
msg_warn
|
||||
("%s: Invalid filter substitution format '%%%c'!",
|
||||
myname, *(sub + 1));
|
||||
msg_warn("%s: %s: Invalid filter substitution format '%%%c'!",
|
||||
myname, ldapsource, *(sub + 1));
|
||||
/* fall through */
|
||||
case 's':
|
||||
vstring_strcat(out, u);
|
||||
@ -486,6 +460,9 @@ static void dict_ldap_expand_filter(char *filter, char *value, VSTRING *out)
|
||||
static void dict_ldap_get_values(DICT_LDAP *dict_ldap, LDAPMessage * res,
|
||||
VSTRING *result)
|
||||
{
|
||||
static int recursion = 0;
|
||||
static int expansion;
|
||||
long entries = 0;
|
||||
long i = 0;
|
||||
int rc = 0;
|
||||
LDAPMessage *resloop = 0;
|
||||
@ -500,13 +477,27 @@ static void dict_ldap_get_values(DICT_LDAP *dict_ldap, LDAPMessage * res,
|
||||
tv.tv_sec = dict_ldap->timeout;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if (++recursion == 1)
|
||||
expansion = 0;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s: Search found %d match(es)", myname,
|
||||
msg_info("%s[%d]: Search found %d match(es)", myname, recursion,
|
||||
ldap_count_entries(dict_ldap->ld, res));
|
||||
|
||||
for (entry = ldap_first_entry(dict_ldap->ld, res); entry != NULL;
|
||||
entry = ldap_next_entry(dict_ldap->ld, entry)) {
|
||||
ber = NULL;
|
||||
|
||||
/*
|
||||
* LDAP should not, but may produce more than the requested maximum
|
||||
* number of entries.
|
||||
*/
|
||||
if (dict_errno == 0 && ++entries > dict_ldap->size_limit
|
||||
&& dict_ldap->size_limit) {
|
||||
msg_warn("%s[%d]: %s: Query size limit (%ld) exceeded", myname,
|
||||
recursion, dict_ldap->ldapsource, dict_ldap->size_limit);
|
||||
dict_errno = DICT_ERR_RETRY;
|
||||
}
|
||||
for (attr = ldap_first_attribute(dict_ldap->ld, entry, &ber);
|
||||
attr != NULL;
|
||||
ldap_memfree(attr), attr = ldap_next_attribute(dict_ldap->ld,
|
||||
@ -514,17 +505,38 @@ static void dict_ldap_get_values(DICT_LDAP *dict_ldap, LDAPMessage * res,
|
||||
vals = ldap_get_values(dict_ldap->ld, entry, attr);
|
||||
if (vals == NULL) {
|
||||
if (msg_verbose)
|
||||
msg_info("%s: Entry doesn't have any values for %s",
|
||||
myname, attr);
|
||||
msg_info("%s[%d]: Entry doesn't have any values for %s",
|
||||
myname, recursion, attr);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we previously encountered an error, we still continue
|
||||
* through the loop, to avoid memory leaks, but we don't waste
|
||||
* time accumulating any further results.
|
||||
*
|
||||
* XXX: There may be a more efficient way to exit the loop with no
|
||||
* leaks, but it will likely be more fragile and not worth the
|
||||
* extra code.
|
||||
*/
|
||||
if (dict_errno != 0 || vals[0] == 0) {
|
||||
ldap_value_free(vals);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* The "result_attributes" list enumerates all the requested
|
||||
* attributes, first the ordinary result attribtutes and then the
|
||||
* special result attributes that hold DN or LDAP URL values.
|
||||
*
|
||||
* The number of ordinary attributes is "num_attributes".
|
||||
*
|
||||
* We compute the attribute type (ordinary or special) from its
|
||||
* index on the "result_attributes" list.
|
||||
*/
|
||||
for (i = 0; dict_ldap->result_attributes->argv[i]; i++) {
|
||||
if (strcasecmp(dict_ldap->result_attributes->argv[i],
|
||||
attr) == 0) {
|
||||
if (msg_verbose)
|
||||
msg_info("%s: search returned %ld value(s) for requested result attribute %s", myname, i, attr);
|
||||
if (strcasecmp(dict_ldap->result_attributes->argv[i], attr) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -532,21 +544,39 @@ static void dict_ldap_get_values(DICT_LDAP *dict_ldap, LDAPMessage * res,
|
||||
* recursing (for dn or url attributes).
|
||||
*/
|
||||
if (i < dict_ldap->num_attributes) {
|
||||
/* Ordinary result attribute */
|
||||
for (i = 0; vals[i] != NULL; i++) {
|
||||
if (++expansion > dict_ldap->expansion_limit &&
|
||||
dict_ldap->expansion_limit) {
|
||||
msg_warn("%s[%d]: %s: Expansion limit exceeded at"
|
||||
" result attribute %s=%s", myname, recursion,
|
||||
dict_ldap->ldapsource, attr, vals[i]);
|
||||
dict_errno = DICT_ERR_RETRY;
|
||||
break;
|
||||
}
|
||||
if (VSTRING_LEN(result) > 0)
|
||||
vstring_strcat(result, ",");
|
||||
if (dict_ldap->result_filter == NULL)
|
||||
vstring_strcat(result, vals[i]);
|
||||
else
|
||||
dict_ldap_expand_filter(dict_ldap->result_filter,
|
||||
dict_ldap_expand_filter(dict_ldap->ldapsource,
|
||||
dict_ldap->result_filter,
|
||||
vals[i], result);
|
||||
}
|
||||
} else if (dict_ldap->result_attributes->argv[i]) {
|
||||
if (dict_errno != 0)
|
||||
continue;
|
||||
if (msg_verbose)
|
||||
msg_info("%s[%d]: search returned %ld value(s) for"
|
||||
" requested result attribute %s",
|
||||
myname, recursion, i, attr);
|
||||
} else if (recursion < dict_ldap->recursion_limit
|
||||
&& dict_ldap->result_attributes->argv[i]) {
|
||||
/* Special result attribute */
|
||||
for (i = 0; vals[i] != NULL; i++) {
|
||||
if (ldap_is_ldap_url(vals[i])) {
|
||||
if (msg_verbose)
|
||||
msg_info("%s: looking up URL %s", myname,
|
||||
vals[i]);
|
||||
msg_info("%s[%d]: looking up URL %s", myname,
|
||||
recursion, vals[i]);
|
||||
rc = ldap_url_parse(vals[i], &url);
|
||||
if (rc == 0) {
|
||||
rc = ldap_search_st(dict_ldap->ld, url->lud_dn,
|
||||
@ -557,7 +587,8 @@ static void dict_ldap_get_values(DICT_LDAP *dict_ldap, LDAPMessage * res,
|
||||
}
|
||||
} else {
|
||||
if (msg_verbose)
|
||||
msg_info("%s: looking up DN %s", myname, vals[i]);
|
||||
msg_info("%s[%d]: looking up DN %s",
|
||||
myname, recursion, vals[i]);
|
||||
rc = ldap_search_st(dict_ldap->ld, vals[i],
|
||||
LDAP_SCOPE_BASE, "objectclass=*",
|
||||
dict_ldap->result_attributes->argv,
|
||||
@ -573,27 +604,44 @@ static void dict_ldap_get_values(DICT_LDAP *dict_ldap, LDAPMessage * res,
|
||||
* Go ahead and treat this as though the DN existed
|
||||
* and just didn't have any result attributes.
|
||||
*/
|
||||
msg_warn("%s: DN %s not found, skipping ", myname,
|
||||
vals[i]);
|
||||
msg_warn("%s[%d]: DN %s not found, skipping ", myname,
|
||||
recursion, vals[i]);
|
||||
break;
|
||||
default:
|
||||
msg_warn("%s: search error %d: %s ", myname, rc,
|
||||
ldap_err2string(rc));
|
||||
msg_warn("%s[%d]: search error %d: %s ", myname,
|
||||
recursion, rc, ldap_err2string(rc));
|
||||
dict_errno = DICT_ERR_RETRY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (resloop != 0)
|
||||
ldap_msgfree(resloop);
|
||||
|
||||
if (dict_errno != 0)
|
||||
break;
|
||||
}
|
||||
if (dict_errno != 0)
|
||||
continue;
|
||||
if (msg_verbose)
|
||||
msg_info("%s[%d]: search returned %ld value(s) for"
|
||||
" special result attribute %s",
|
||||
myname, recursion, i, attr);
|
||||
} else if (recursion >= dict_ldap->recursion_limit
|
||||
&& dict_ldap->result_attributes->argv[i]) {
|
||||
msg_warn("%s[%d]: %s: Recursion limit exceeded"
|
||||
" for special attribute %s=%s",
|
||||
myname, recursion, dict_ldap->ldapsource, attr, vals[0]);
|
||||
dict_errno = DICT_ERR_RETRY;
|
||||
}
|
||||
ldap_value_free(vals);
|
||||
}
|
||||
if (ber)
|
||||
ber_free(ber, 0);
|
||||
}
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s: Leaving %s", myname, myname);
|
||||
msg_info("%s[%d]: Leaving %s", myname, recursion, myname);
|
||||
--recursion;
|
||||
}
|
||||
|
||||
/* dict_ldap_lookup - find database entry */
|
||||
@ -720,11 +768,11 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
|
||||
/*
|
||||
* No, log the fact and continue.
|
||||
*/
|
||||
msg_warn("%s: Fixed query_filter %s is probably useless", myname,
|
||||
dict_ldap->query_filter);
|
||||
msg_warn("%s: %s: Fixed query_filter %s is probably useless",
|
||||
myname, dict_ldap->ldapsource, dict_ldap->query_filter);
|
||||
vstring_strcpy(filter_buf, dict_ldap->query_filter);
|
||||
} else {
|
||||
dict_ldap_expand_filter(dict_ldap->query_filter,
|
||||
dict_ldap_expand_filter(dict_ldap->ldapsource, dict_ldap->query_filter,
|
||||
vstring_str(escaped_name), filter_buf);
|
||||
}
|
||||
|
||||
@ -858,6 +906,7 @@ DICT *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
|
||||
char *domainlist;
|
||||
char *scope;
|
||||
char *attr;
|
||||
int tmp;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s: Using LDAP source %s", myname, ldapsource);
|
||||
@ -1040,31 +1089,58 @@ DICT *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
|
||||
* get configured value of "ldapsource_cache"; default to false
|
||||
*/
|
||||
vstring_sprintf(config_param, "%s_cache", ldapsource);
|
||||
dict_ldap->cache = get_mail_conf_bool(vstring_str(config_param), 0);
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s is %d", myname, vstring_str(config_param),
|
||||
dict_ldap->cache);
|
||||
tmp = get_mail_conf_bool(vstring_str(config_param), 0);
|
||||
if (tmp)
|
||||
msg_warn("%s: ignoring %s", myname, vstring_str(config_param));
|
||||
|
||||
/*
|
||||
* get configured value of "ldapsource_cache_expiry"; default to 30
|
||||
* seconds
|
||||
*/
|
||||
vstring_sprintf(config_param, "%s_cache_expiry", ldapsource);
|
||||
dict_ldap->cache_expiry = get_mail_conf_int(vstring_str(config_param),
|
||||
30, 0, 0);
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s is %ld", myname, vstring_str(config_param),
|
||||
dict_ldap->cache_expiry);
|
||||
tmp = get_mail_conf_int(vstring_str(config_param), -1, 0, 0);
|
||||
if (tmp >= 0)
|
||||
msg_warn("%s: ignoring %s", myname, vstring_str(config_param));
|
||||
|
||||
/*
|
||||
* get configured value of "ldapsource_cache_size"; default to 32k
|
||||
*/
|
||||
vstring_sprintf(config_param, "%s_cache_size", ldapsource);
|
||||
dict_ldap->cache_size = get_mail_conf_int(vstring_str(config_param),
|
||||
32768, 0, 0);
|
||||
tmp = get_mail_conf_int(vstring_str(config_param), -1, 0, 0);
|
||||
if (tmp >= 0)
|
||||
msg_warn("%s: ignoring %s", myname, vstring_str(config_param));
|
||||
|
||||
/*
|
||||
* get configured value of "ldapsource_recursion_limit"; default to 1000
|
||||
*/
|
||||
vstring_sprintf(config_param, "%s_recursion_limit", ldapsource);
|
||||
dict_ldap->recursion_limit = get_mail_conf_int(vstring_str(config_param),
|
||||
1000, 1, 0);
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s is %ld", myname, vstring_str(config_param),
|
||||
dict_ldap->cache_size);
|
||||
dict_ldap->recursion_limit);
|
||||
|
||||
/*
|
||||
* get configured value of "ldapsource_expansion_limit"; default to 1000
|
||||
*/
|
||||
vstring_sprintf(config_param, "%s_expansion_limit", ldapsource);
|
||||
dict_ldap->expansion_limit = get_mail_conf_int(vstring_str(config_param),
|
||||
0, 0, 0);
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s is %ld", myname, vstring_str(config_param),
|
||||
dict_ldap->expansion_limit);
|
||||
|
||||
/*
|
||||
* get configured value of "ldapsource_size_limit"; default to
|
||||
* expansion_limit
|
||||
*/
|
||||
vstring_sprintf(config_param, "%s_size_limit", ldapsource);
|
||||
dict_ldap->size_limit = get_mail_conf_int(vstring_str(config_param),
|
||||
dict_ldap->expansion_limit,
|
||||
0, 0);
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s is %ld", myname, vstring_str(config_param),
|
||||
dict_ldap->size_limit);
|
||||
|
||||
/*
|
||||
* Alias dereferencing suggested by Mike Mattice.
|
||||
|
@ -178,6 +178,7 @@
|
||||
#include <dict_pcre.h>
|
||||
#include <dict_regexp.h>
|
||||
#include <dict_static.h>
|
||||
#include <dict_cidr.h>
|
||||
#include <stringops.h>
|
||||
#include <split_at.h>
|
||||
#include <htable.h>
|
||||
@ -193,9 +194,7 @@ typedef struct {
|
||||
static DICT_OPEN_INFO dict_open_info[] = {
|
||||
DICT_TYPE_ENVIRON, dict_env_open,
|
||||
DICT_TYPE_UNIX, dict_unix_open,
|
||||
#if 0
|
||||
DICT_TYPE_TCP, dict_tcp_open,
|
||||
#endif
|
||||
#ifdef HAS_DBM
|
||||
DICT_TYPE_DBM, dict_dbm_open,
|
||||
#endif
|
||||
@ -228,6 +227,7 @@ static DICT_OPEN_INFO dict_open_info[] = {
|
||||
DICT_TYPE_REGEXP, dict_regexp_open,
|
||||
#endif
|
||||
DICT_TYPE_STATIC, dict_static_open,
|
||||
DICT_TYPE_CIDR, dict_cidr_open,
|
||||
0,
|
||||
};
|
||||
|
||||
|
@ -73,6 +73,7 @@
|
||||
typedef struct {
|
||||
char *regexp; /* regular expression */
|
||||
int options; /* options */
|
||||
int match; /* positive or negative match */
|
||||
} DICT_PCRE_REGEXP;
|
||||
|
||||
typedef struct {
|
||||
@ -95,12 +96,14 @@ typedef struct {
|
||||
pcre *pattern; /* compiled pattern */
|
||||
pcre_extra *hints; /* hints to speed pattern execution */
|
||||
char *replacement; /* replacement string */
|
||||
int match; /* positive or negative match */
|
||||
} DICT_PCRE_MATCH_RULE;
|
||||
|
||||
typedef struct {
|
||||
DICT_PCRE_RULE rule; /* generic members */
|
||||
pcre *pattern; /* compiled pattern */
|
||||
pcre_extra *hints; /* hints to speed pattern execution */
|
||||
int match; /* positive or negative match */
|
||||
} DICT_PCRE_IF_RULE;
|
||||
|
||||
/*
|
||||
@ -132,6 +135,7 @@ typedef struct {
|
||||
const char *mapname; /* name of regexp map */
|
||||
int lineno; /* where in file */
|
||||
int flags; /* dict_flags */
|
||||
size_t max_sub; /* Largest $n seen */
|
||||
} DICT_PCRE_PRESCAN_CONTEXT;
|
||||
|
||||
/*
|
||||
@ -251,13 +255,23 @@ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string)
|
||||
lookup_string, lookup_len,
|
||||
NULL_STARTOFFSET, NULL_EXEC_OPTIONS,
|
||||
ctxt.offsets, PCRE_MAX_CAPTURE * 3);
|
||||
if (ctxt.matches == PCRE_ERROR_NOMATCH)
|
||||
continue;
|
||||
if (ctxt.matches <= 0) {
|
||||
|
||||
if (ctxt.matches > 0) {
|
||||
if (!match_rule->match)
|
||||
continue; /* Negative rule matched */
|
||||
} else if (ctxt.matches == PCRE_ERROR_NOMATCH) {
|
||||
if (match_rule->match)
|
||||
continue; /* Positive rule did not
|
||||
* match */
|
||||
} else {
|
||||
dict_pcre_exec_error(dict->name, rule->lineno, ctxt.matches);
|
||||
continue;
|
||||
continue; /* pcre_exec failed */
|
||||
}
|
||||
|
||||
/* Negative rules can't have any substitutions */
|
||||
if (!match_rule->match)
|
||||
return match_rule->replacement;
|
||||
|
||||
/*
|
||||
* We've got a match. Perform substitution on replacement string.
|
||||
*/
|
||||
@ -289,11 +303,17 @@ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string)
|
||||
lookup_string, lookup_len,
|
||||
NULL_STARTOFFSET, NULL_EXEC_OPTIONS,
|
||||
ctxt.offsets, PCRE_MAX_CAPTURE * 3);
|
||||
if (ctxt.matches == PCRE_ERROR_NOMATCH)
|
||||
continue;
|
||||
if (ctxt.matches <= 0) {
|
||||
|
||||
if (ctxt.matches > 0) {
|
||||
if (!if_rule->match)
|
||||
continue; /* Negative rule matched */
|
||||
} else if (ctxt.matches == PCRE_ERROR_NOMATCH) {
|
||||
if (if_rule->match)
|
||||
continue; /* Positive rule did not
|
||||
* match */
|
||||
} else {
|
||||
dict_pcre_exec_error(dict->name, rule->lineno, ctxt.matches);
|
||||
continue;
|
||||
continue; /* pcre_exec failed */
|
||||
}
|
||||
nesting++;
|
||||
continue;
|
||||
@ -359,6 +379,25 @@ static int dict_pcre_get_pattern(const char *mapname, int lineno, char **bufp,
|
||||
char *p = *bufp;
|
||||
char re_delimiter;
|
||||
|
||||
/*
|
||||
* Process negation operators.
|
||||
*/
|
||||
pattern->match = 1;
|
||||
while (*p == '!') {
|
||||
pattern->match = !pattern->match;
|
||||
p++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Grr...aceful handling of whitespace after '!'.
|
||||
*/
|
||||
while (*p && ISSPACE(*p))
|
||||
p++;
|
||||
if (*p == 0) {
|
||||
msg_warn("pcre map %s, line %d: no regexp: skipping this rule",
|
||||
mapname, lineno);
|
||||
return (0);
|
||||
}
|
||||
re_delimiter = *p++;
|
||||
pattern->regexp = p;
|
||||
|
||||
@ -433,11 +472,10 @@ static int dict_pcre_prescan(int type, VSTRING *buf, char *context)
|
||||
if (type == MAC_PARSE_VARNAME) {
|
||||
if (ctxt->flags & DICT_FLAG_NO_REGSUB) {
|
||||
msg_warn("pcre map %s, line %d: "
|
||||
"regular expression substitution is not allowed",
|
||||
ctxt->mapname, ctxt->lineno);
|
||||
"regular expression substitution is not allowed",
|
||||
ctxt->mapname, ctxt->lineno);
|
||||
return (MAC_PARSE_ERROR);
|
||||
}
|
||||
|
||||
if (!alldig(vstring_str(buf))) {
|
||||
msg_warn("pcre map %s, line %d: non-numeric replacement index \"%s\"",
|
||||
ctxt->mapname, ctxt->lineno, vstring_str(buf));
|
||||
@ -449,6 +487,8 @@ static int dict_pcre_prescan(int type, VSTRING *buf, char *context)
|
||||
ctxt->mapname, ctxt->lineno, vstring_str(buf));
|
||||
return (MAC_PARSE_ERROR);
|
||||
}
|
||||
if (n > ctxt->max_sub)
|
||||
ctxt->max_sub = n;
|
||||
}
|
||||
return (MAC_PARSE_OK);
|
||||
}
|
||||
@ -536,6 +576,7 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno,
|
||||
prescan_context.mapname = mapname;
|
||||
prescan_context.lineno = lineno;
|
||||
prescan_context.flags = dict_flags;
|
||||
prescan_context.max_sub = 0;
|
||||
|
||||
if (mac_parse(p, dict_pcre_prescan, (char *) &prescan_context)
|
||||
& MAC_PARSE_ERROR) {
|
||||
@ -544,6 +585,15 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno,
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Substring replacement not possible with negative regexps.
|
||||
*/
|
||||
if (prescan_context.max_sub > 0 && regexp.match == 0) {
|
||||
msg_warn("pcre map %s, line %d: $number found in negative match "
|
||||
"replacement text: skipping this rule", mapname, lineno);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compile the pattern.
|
||||
*/
|
||||
@ -556,6 +606,7 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno,
|
||||
match_rule = (DICT_PCRE_MATCH_RULE *)
|
||||
dict_pcre_rule_alloc(DICT_PCRE_OP_MATCH, nesting, lineno,
|
||||
sizeof(DICT_PCRE_MATCH_RULE));
|
||||
match_rule->match = regexp.match;
|
||||
match_rule->replacement = mystrdup(p);
|
||||
match_rule->pattern = engine.pattern;
|
||||
match_rule->hints = engine.hints;
|
||||
@ -583,6 +634,8 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno,
|
||||
/*
|
||||
* Warn about out-of-place text.
|
||||
*/
|
||||
while (*p && ISSPACE(*p))
|
||||
++p;
|
||||
if (*p)
|
||||
msg_warn("pcre map %s, line %d: ignoring extra text after IF",
|
||||
mapname, lineno);
|
||||
@ -599,6 +652,7 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno,
|
||||
if_rule = (DICT_PCRE_IF_RULE *)
|
||||
dict_pcre_rule_alloc(DICT_PCRE_OP_IF, nesting, lineno,
|
||||
sizeof(DICT_PCRE_IF_RULE));
|
||||
if_rule->match = regexp.match;
|
||||
if_rule->pattern = engine.pattern;
|
||||
if_rule->hints = engine.hints;
|
||||
return ((DICT_PCRE_RULE *) if_rule);
|
||||
@ -624,6 +678,8 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno,
|
||||
/*
|
||||
* Warn about out-of-place text.
|
||||
*/
|
||||
while (*p && ISSPACE(*p))
|
||||
++p;
|
||||
if (*p)
|
||||
msg_warn("pcre map %s, line %d: ignoring extra text after ENDIF",
|
||||
mapname, lineno);
|
||||
|
@ -8,3 +8,7 @@ get c
|
||||
get d
|
||||
get 1234
|
||||
get 123
|
||||
get bar/find
|
||||
get bar/whynot
|
||||
get bar/elbereth
|
||||
get say/elbereth
|
||||
|
@ -10,3 +10,12 @@ endif
|
||||
/(1)(2)(3)(5)/ ($1)($2)($3)($4)($5)
|
||||
/(1)(2)(3)(4)/ ($1)($2)($3)($4)
|
||||
/(1)(2)(3)/ ($1)($2)($3)
|
||||
# trailing whitespace below
|
||||
if /bar/
|
||||
if !/xyzzy/
|
||||
/(elbereth)/ ($1)
|
||||
!/(bogus)/ ($1)
|
||||
!/find/ Don't have a liquor license
|
||||
endif
|
||||
endif
|
||||
# trailing whitespace above
|
||||
|
@ -2,6 +2,7 @@
|
||||
./dict_open: warning: pcre map dict_pcre.map, line 5: ignoring extra text after ENDIF
|
||||
./dict_open: warning: pcre map dict_pcre.map, line 8: unknown regexp option "!": skipping this rule
|
||||
./dict_open: warning: dict_pcre.map, line 9: no replacement text: using empty string
|
||||
./dict_open: warning: pcre map dict_pcre.map, line 17: $number found in negative match replacement text: skipping this rule
|
||||
true: not found
|
||||
true1=1
|
||||
true2: not found
|
||||
@ -12,3 +13,7 @@ c=
|
||||
d: not found
|
||||
1234=(1)(2)(3)(4)
|
||||
123=(1)(2)(3)
|
||||
bar/find: not found
|
||||
bar/whynot=Don't have a liquor license
|
||||
bar/elbereth=(elbereth)
|
||||
say/elbereth: not found
|
||||
|
@ -584,9 +584,9 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno,
|
||||
first_pat.options |= REG_NOSUB;
|
||||
} else if (dict_flags & DICT_FLAG_NO_REGSUB) {
|
||||
msg_warn("regexp map %s, line %d: "
|
||||
"regular expression substitution is not allowed: "
|
||||
"skipping this rule", mapname, lineno);
|
||||
return(0);
|
||||
"regular expression substitution is not allowed: "
|
||||
"skipping this rule", mapname, lineno);
|
||||
return (0);
|
||||
}
|
||||
if ((first_exp = dict_regexp_compile_pat(mapname, lineno,
|
||||
&first_pat)) == 0)
|
||||
@ -636,6 +636,8 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno,
|
||||
p++;
|
||||
if (!dict_regexp_get_pat(mapname, lineno, &p, &pattern))
|
||||
return (0);
|
||||
while (*p && ISSPACE(*p))
|
||||
++p;
|
||||
if (*p)
|
||||
msg_warn("regexp map %s, line %d: ignoring extra text after IF",
|
||||
mapname, lineno);
|
||||
@ -661,6 +663,8 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno,
|
||||
mapname, lineno);
|
||||
return (0);
|
||||
}
|
||||
while (*p && ISSPACE(*p))
|
||||
++p;
|
||||
if (*p)
|
||||
msg_warn("regexp map %s, line %d: ignoring extra text after ENDIF",
|
||||
mapname, lineno);
|
||||
|
@ -11,3 +11,7 @@ get aa
|
||||
get 1235
|
||||
get 1234
|
||||
get 123
|
||||
get bar/find
|
||||
get bar/whynot
|
||||
get bar/elbereth
|
||||
get say/elbereth
|
||||
|
@ -10,3 +10,12 @@ endif
|
||||
/(1)(2)(3)(5)/ ($1)($2)($3)($4)($5)
|
||||
/(1)(2)(3)(4)/ ($1)($2)($3)($4)
|
||||
/(1)(2)(3)/ ($1)($2)($3)
|
||||
# trailing whitespace below
|
||||
if /bar/
|
||||
if !/xyzzy/
|
||||
/(elbereth)/ ($1)
|
||||
!/(bogus)/ ($1)
|
||||
!/find/ Don't have a liquor license
|
||||
endif
|
||||
endif
|
||||
# trailing whitespace above
|
||||
|
@ -2,6 +2,7 @@
|
||||
./dict_open: warning: regexp map dict_regexp.map, line 5: ignoring extra text after ENDIF
|
||||
./dict_open: warning: regexp map dict_regexp.map, line 9: using empty replacement string
|
||||
./dict_open: warning: regexp map dict_regexp.map, line 10: out of range replacement index "5": skipping this rule
|
||||
./dict_open: warning: regexp map dict_regexp.map, line 17: $number found in negative match replacement text: skipping this rule
|
||||
true: not found
|
||||
true1=1
|
||||
true2: not found
|
||||
@ -15,3 +16,7 @@ aa=a!b
|
||||
1235=(1)(2)(3)
|
||||
1234=(1)(2)(3)(4)
|
||||
123=(1)(2)(3)
|
||||
bar/find: not found
|
||||
bar/whynot=Don't have a liquor license
|
||||
bar/elbereth=(elbereth)
|
||||
say/elbereth: not found
|
||||
|
@ -27,8 +27,8 @@
|
||||
/* ENCODING
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* In request and reply parameters, the character % and any non-printable
|
||||
/* characters (including whitespace) are replaced by %XX, XX being the
|
||||
/* In request and reply parameters, the character % and any non-printing
|
||||
/* and whitespace characters must be replaced by %XX, XX being the
|
||||
/* corresponding ASCII hexadecimal character value. The hexadecimal codes
|
||||
/* can be specified in any case (upper, lower, mixed).
|
||||
/* REQUEST FORMAT
|
||||
@ -43,7 +43,8 @@
|
||||
/* REPLY FORMAT
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* Replies can have the following form:
|
||||
/* Replies must be no longer than 4096 characters including the
|
||||
/* newline terminator, and must have the following form:
|
||||
/* .IP "500 SPACE optional-text NEWLINE"
|
||||
/* In case of a lookup request, the requested data does not exist.
|
||||
/* In case of an update request, the request was rejected.
|
||||
@ -83,16 +84,16 @@
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include "msg.h"
|
||||
#include "mymalloc.h"
|
||||
#include "vstring.h"
|
||||
#include "vstream.h"
|
||||
#include "vstring_vstream.h"
|
||||
#include "connect.h"
|
||||
#include "hex_quote.h"
|
||||
#include "dict.h"
|
||||
#include "stringops.h"
|
||||
#include "dict_tcp.h"
|
||||
#include <msg.h>
|
||||
#include <mymalloc.h>
|
||||
#include <vstring.h>
|
||||
#include <vstream.h>
|
||||
#include <vstring_vstream.h>
|
||||
#include <connect.h>
|
||||
#include <hex_quote.h>
|
||||
#include <dict.h>
|
||||
#include <stringops.h>
|
||||
#include <dict_tcp.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@ -103,8 +104,9 @@ typedef struct {
|
||||
VSTREAM *fp; /* I/O stream */
|
||||
} DICT_TCP;
|
||||
|
||||
#define DICT_TCP_MAXTRY 10
|
||||
#define DICT_TCP_TMOUT 100
|
||||
#define DICT_TCP_MAXTRY 10 /* attempts before giving up */
|
||||
#define DICT_TCP_TMOUT 100 /* connect/read/write timeout */
|
||||
#define DICT_TCP_MAXLEN 4096 /* server reply size limit */
|
||||
|
||||
#define STR(x) vstring_str(x)
|
||||
|
||||
@ -115,10 +117,10 @@ static int dict_tcp_connect(DICT_TCP *dict_tcp)
|
||||
int fd;
|
||||
|
||||
/*
|
||||
* Connect to the server. Enforce a time limit on read/write operations
|
||||
* so that we do not get stuck.
|
||||
* Connect to the server. Enforce a time limit on all operations so that
|
||||
* we do not get stuck.
|
||||
*/
|
||||
if ((fd = inet_connect(dict_tcp->dict.name, BLOCKING, 0)) < 0) {
|
||||
if ((fd = inet_connect(dict_tcp->dict.name, NON_BLOCKING, DICT_TCP_TMOUT)) < 0) {
|
||||
msg_warn("connect to TCP map %s: %m", dict_tcp->dict.name);
|
||||
return (-1);
|
||||
}
|
||||
@ -153,6 +155,7 @@ static const char *dict_tcp_lookup(DICT *dict, const char *key)
|
||||
char *myname = "dict_tcp_lookup";
|
||||
int tries;
|
||||
char *start;
|
||||
int last_ch;
|
||||
|
||||
#define RETURN(errval, result) { dict_errno = errval; return (result); }
|
||||
|
||||
@ -173,14 +176,22 @@ static const char *dict_tcp_lookup(DICT *dict, const char *key)
|
||||
*/
|
||||
hex_quote(dict_tcp->hex_buf, key);
|
||||
vstream_fprintf(dict_tcp->fp, "get %s\n", STR(dict_tcp->hex_buf));
|
||||
if (vstring_get_nonl(dict_tcp->hex_buf, dict_tcp->fp) > 0)
|
||||
if (msg_verbose)
|
||||
msg_info("%s: send \"get %s\"", myname, STR(dict_tcp->hex_buf));
|
||||
last_ch = vstring_get_nonl_bound(dict_tcp->hex_buf, dict_tcp->fp,
|
||||
DICT_TCP_MAXLEN);
|
||||
if (last_ch == '\n')
|
||||
break;
|
||||
|
||||
/*
|
||||
* Disconnect from the server if it can't talk to us.
|
||||
*/
|
||||
msg_warn("read TCP map reply from %s: unexpected EOF (%m)",
|
||||
dict_tcp->dict.name);
|
||||
if (last_ch < 0)
|
||||
msg_warn("read TCP map reply from %s: unexpected EOF (%m)",
|
||||
dict_tcp->dict.name);
|
||||
else
|
||||
msg_warn("read TCP map reply from %s: text longer than %d",
|
||||
dict_tcp->dict.name, DICT_TCP_MAXLEN);
|
||||
dict_tcp_disconnect(dict_tcp);
|
||||
}
|
||||
|
||||
@ -195,6 +206,8 @@ static const char *dict_tcp_lookup(DICT *dict, const char *key)
|
||||
*/
|
||||
sleep(1);
|
||||
}
|
||||
if (msg_verbose)
|
||||
msg_info("%s: recv: \"%s\"", myname, STR(dict_tcp->hex_buf));
|
||||
|
||||
/*
|
||||
* Check the general reply syntax. If the reply is malformed, disconnect
|
||||
@ -205,7 +218,7 @@ static const char *dict_tcp_lookup(DICT *dict, const char *key)
|
||||
|| !ISDIGIT(start[2]) || !ISSPACE(start[3])
|
||||
|| !hex_unquote(dict_tcp->raw_buf, start + 4)) {
|
||||
msg_warn("read TCP map reply from %s: malformed reply %.100s",
|
||||
dict_tcp->dict.name, printable(STR(dict_tcp->hex_buf), '_'));
|
||||
dict_tcp->dict.name, printable(STR(dict_tcp->hex_buf), '_'));
|
||||
dict_tcp_disconnect(dict_tcp);
|
||||
RETURN(DICT_ERR_RETRY, 0);
|
||||
}
|
||||
@ -217,7 +230,7 @@ static const char *dict_tcp_lookup(DICT *dict, const char *key)
|
||||
switch (start[0]) {
|
||||
default:
|
||||
msg_warn("read TCP map reply from %s: bad status code %.100s",
|
||||
dict_tcp->dict.name, printable(STR(dict_tcp->hex_buf), '_'));
|
||||
dict_tcp->dict.name, printable(STR(dict_tcp->hex_buf), '_'));
|
||||
dict_tcp_disconnect(dict_tcp);
|
||||
RETURN(DICT_ERR_RETRY, 0);
|
||||
case '4':
|
||||
@ -268,5 +281,5 @@ DICT *dict_tcp_open(const char *map, int unused_flags, int dict_flags)
|
||||
dict_tcp->dict.lookup = dict_tcp_lookup;
|
||||
dict_tcp->dict.close = dict_tcp_close;
|
||||
dict_tcp->dict.flags = dict_flags | DICT_FLAG_FIXED;
|
||||
return (DICT_DEBUG(&dict_tcp->dict));
|
||||
return (DICT_DEBUG (&dict_tcp->dict));
|
||||
}
|
||||
|
@ -15,7 +15,8 @@
|
||||
/* const char *hex;
|
||||
/* DESCRIPTION
|
||||
/* hex_quote() takes a null-terminated string and replaces non-printable
|
||||
/* characters and % by %XX, XX being the two-digit hexadecimal equivalent.
|
||||
/* and whitespace characters and the % by %XX, XX being the two-digit
|
||||
/* hexadecimal equivalent.
|
||||
/* The hexadecimal codes are produced as upper-case characters. The result
|
||||
/* value is the hex argument.
|
||||
/*
|
||||
@ -61,7 +62,7 @@ VSTRING *hex_quote(VSTRING *hex, const char *raw)
|
||||
|
||||
VSTRING_RESET(hex);
|
||||
for (cp = raw; (ch = *(unsigned const char *) cp) != 0; cp++) {
|
||||
if (ch != '%' && ISPRINT(ch)) {
|
||||
if (ch != '%' && !ISSPACE(ch) && ISPRINT(ch)) {
|
||||
VSTRING_ADDCH(hex, ch);
|
||||
} else {
|
||||
vstring_sprintf_append(hex, "%%%02X", ch);
|
||||
|
@ -69,7 +69,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
#define INADDR_NONE 0xffffff
|
||||
#define INADDR_NONE 0xffffffff
|
||||
#endif
|
||||
|
||||
/* Utility library. */
|
||||
|
@ -244,12 +244,16 @@ VSTREAM *safe_open(const char *path, int flags, int mode,
|
||||
/*
|
||||
* Open an existing file or create a new one, carefully. When opening
|
||||
* an existing file, we are prepared to deal with "no file" errors
|
||||
* only. Any other error means we better give up trying.
|
||||
* only. When creating a file, we are prepared for "file exists"
|
||||
* errors only. Any other error means we better give up trying.
|
||||
*/
|
||||
case O_CREAT:
|
||||
if ((fp = safe_open_exist(path, flags, st, why)) == 0)
|
||||
if (errno == ENOENT)
|
||||
fp = safe_open_create(path, flags, mode, st, user, group, why);
|
||||
fp = safe_open_exist(path, flags, st, why);
|
||||
if (fp == 0 && errno == ENOENT) {
|
||||
fp = safe_open_create(path, flags, mode, st, user, group, why);
|
||||
if (fp == 0 && errno == EEXIST)
|
||||
fp = safe_open_exist(path, flags, st, why);
|
||||
}
|
||||
return (fp);
|
||||
|
||||
/*
|
||||
|
@ -234,7 +234,7 @@ int valid_hostliteral(const char *addr, int gripe)
|
||||
msg_warn("%s: unexpected text after ']': %.100s", myname, addr);
|
||||
return (0);
|
||||
}
|
||||
if (last - addr >= sizeof(buf)) {
|
||||
if (last >= addr + sizeof(buf)) {
|
||||
if (gripe)
|
||||
msg_warn("%s: too much text: %.100s", myname, addr);
|
||||
return (0);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user