mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-29 05:07:58 +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_ATTR
|
||||||
-TDELIVER_REQUEST
|
-TDELIVER_REQUEST
|
||||||
-TDICT
|
-TDICT
|
||||||
|
-TDICT_CIDR
|
||||||
|
-TDICT_CIDR_ENTRY
|
||||||
-TDICT_DB
|
-TDICT_DB
|
||||||
-TDICT_DBM
|
-TDICT_DBM
|
||||||
-TDICT_DEBUG
|
-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
|
of mail probes, so it will no longer block for in_flow_delay
|
||||||
seconds when mail arrives faster than it is delivered.
|
seconds when mail arrives faster than it is delivered.
|
||||||
Still need to make mail_stream_finish() asynchronous in
|
Still need to make mail_stream_finish() asynchronous in
|
||||||
order to avoid blocking for trigger_timeout seconds when
|
order to avoid blocking for trigger_timeout seconds when the
|
||||||
the queue manager is overwhelmed. Files: global/post_mail.c,
|
queue manager is overwhelmed. Files: global/post_mail.c,
|
||||||
verify/verify.c.
|
verify/verify.c.
|
||||||
|
|
||||||
Bugfix: removed extraneous sleep() after the last attempt
|
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
|
Bugfix: the stricter postdrop input filter broke "sendmail
|
||||||
-bs". Found by Lutz Jaenicke. File: smtpd/smtpd.c.
|
-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
|
20030618
|
||||||
|
|
||||||
After "postfix reload", the master daemon now warns when
|
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:
|
of passing incorrect information to the smtp server. File:
|
||||||
master/master_ent.c.
|
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
|
20030620
|
||||||
|
|
||||||
Bugfix: after the last change to postdrop, postcat no longer
|
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
|
sendmail, "-t" broke multi-line recipient headers. Victor
|
||||||
Duchovni, Morgan Stanley. File: sendmail/sendmail.c.
|
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:
|
Open problems:
|
||||||
|
|
||||||
Low: smtp-source may block when sending large test messages.
|
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:
|
the Postfix user. Example:
|
||||||
ldapsource_bind_pw = postfixpw
|
ldapsource_bind_pw = postfixpw
|
||||||
|
|
||||||
cache (no)
|
cache (IGNORED with a warning)
|
||||||
Whether to use a client-side cache for the LDAP connection. See
|
cache_expiry (IGNORED with a warning)
|
||||||
ldap_enable_cache(3). It's off by default.
|
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)
|
recursion_limit (1000)
|
||||||
If the client-side cache is enabled, cached results will expire
|
A limit on the nesting depth of DN and URL special result
|
||||||
after this many seconds.
|
attribute evaluation. The limit must be a non-zero positive
|
||||||
|
number.
|
||||||
|
|
||||||
cache_size (32768 bytes)
|
expansion_limit (0)
|
||||||
If the client-side cache is enabled, this is its size in bytes.
|
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)
|
dereference (0)
|
||||||
When to dereference LDAP aliases. (Note that this has nothing
|
When to dereference LDAP aliases. (Note that this has nothing
|
||||||
do with Postfix aliases.) The permitted values are those
|
do with Postfix aliases.) The permitted values are those legal
|
||||||
legal for the OpenLDAP/UM LDAP implementations:
|
for the OpenLDAP/UM LDAP implementations:
|
||||||
|
|
||||||
0 never
|
0 never
|
||||||
1 when searching
|
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
|
You can use the virtual delivery agent for mailbox delivery of some
|
||||||
or all domains that are handled by a machine.
|
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
|
are implemented by translating every recipient address into a
|
||||||
different address. For that, see the virtual(5) manual page.
|
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
|
date. Snapshots change only the release date, unless they include
|
||||||
the same bugfixes as a patch release.
|
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
|
Major changes with Postfix snapshot 2.0.11-20030611
|
||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
|
@ -108,6 +108,9 @@
|
|||||||
# A network address is a sequence of one or more
|
# A network address is a sequence of one or more
|
||||||
# octets separated by ".".
|
# octets separated by ".".
|
||||||
#
|
#
|
||||||
|
# NOTE: use the cidr lookup table type if you want to
|
||||||
|
# specify arbitrary network blocks.
|
||||||
|
#
|
||||||
# ACTIONS
|
# ACTIONS
|
||||||
# [45]NN text
|
# [45]NN text
|
||||||
# Reject the address etc. that matches the pattern,
|
# Reject the address etc. that matches the pattern,
|
||||||
@ -207,8 +210,9 @@
|
|||||||
# The table format does not understand quoting conventions.
|
# The table format does not understand quoting conventions.
|
||||||
#
|
#
|
||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
# postmap(1) create mapping table
|
# postmap(1) create lookup table
|
||||||
# smtpd(8) smtp server
|
# smtpd(8) smtp server
|
||||||
|
# cidr_table(5) format of CIDR tables
|
||||||
# pcre_table(5) format of PCRE tables
|
# pcre_table(5) format of PCRE tables
|
||||||
# regexp_table(5) format of POSIX regular expression tables
|
# regexp_table(5) format of POSIX regular expression tables
|
||||||
#
|
#
|
||||||
|
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
|
# pcre_table - format of Postfix PCRE tables
|
||||||
#
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
# pcre:/etc/postfix/filename
|
|
||||||
#
|
|
||||||
# postmap -q "string" pcre:/etc/postfix/filename
|
# postmap -q "string" pcre:/etc/postfix/filename
|
||||||
#
|
#
|
||||||
# postmap -q - pcre:/etc/postfix/filename <inputfile
|
# postmap -q - pcre:/etc/postfix/filename <inputfile
|
||||||
@ -25,8 +23,10 @@
|
|||||||
# The general form of a PCRE table is:
|
# The general form of a PCRE table is:
|
||||||
#
|
#
|
||||||
# /pattern/flags result
|
# /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
|
# blank lines and comments
|
||||||
# Empty lines and whitespace-only lines are ignored,
|
# Empty lines and whitespace-only lines are ignored,
|
||||||
@ -40,9 +40,12 @@
|
|||||||
#
|
#
|
||||||
# if /pattern/flags
|
# if /pattern/flags
|
||||||
#
|
#
|
||||||
|
# if !/pattern/flags
|
||||||
|
#
|
||||||
# endif Examine the lines between if..endif only if pattern
|
# endif Examine the lines between if..endif only if pattern
|
||||||
# matches. The if..endif can nest. Do not prepend
|
# matches (does not match). The if..endif can nest.
|
||||||
# whitespace to patterns inside if..endif.
|
# Do not prepend whitespace to patterns inside
|
||||||
|
# if..endif.
|
||||||
#
|
#
|
||||||
# Each pattern is a perl-like regular expression. The
|
# Each pattern is a perl-like regular expression. The
|
||||||
# expression delimiter can be any character, except whites-
|
# expression delimiter can be any character, except whites-
|
||||||
@ -131,7 +134,10 @@
|
|||||||
# into the result string is possible using the conventional
|
# into the result string is possible using the conventional
|
||||||
# perl syntax ($1, $2, etc.). The macros in the result
|
# perl syntax ($1, $2, etc.). The macros in the result
|
||||||
# string may need to be written as ${n} or $(n) if they
|
# string may need to be written as ${n} or $(n) if they
|
||||||
# aren't followed by whitespace.
|
# 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
|
# EXAMPLE SMTPD ACCESS MAP
|
||||||
# # Protect your outgoing majordomo exploders
|
# # Protect your outgoing majordomo exploders
|
||||||
@ -160,6 +166,8 @@
|
|||||||
#
|
#
|
||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
# regexp_table(5) format of POSIX regular expression tables
|
# 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)
|
# AUTHOR(S)
|
||||||
# The PCRE table lookup code was originally written by:
|
# 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/access:f:root:-:644:p
|
||||||
$config_directory/aliases:f:root:-:644:p
|
$config_directory/aliases:f:root:-:644:p
|
||||||
$config_directory/canonical: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:f:root:-:644:p
|
||||||
$config_directory/main.cf.default:f:root:-:644
|
$config_directory/main.cf.default:f:root:-:644
|
||||||
$config_directory/makedefs.out: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/postfix-files:f:root:-:644
|
||||||
$config_directory/regexp_table:f:root:-:644:p
|
$config_directory/regexp_table:f:root:-:644:p
|
||||||
$config_directory/relocated: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/transport:f:root:-:644:p
|
||||||
$config_directory/virtual:f:root:-:644:p
|
$config_directory/virtual:f:root:-:644:p
|
||||||
$config_directory/postfix-script:f:root:-:755
|
$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/access.5:f:root:-:644
|
||||||
$manpage_directory/man5/aliases.5:f:root:-:644
|
$manpage_directory/man5/aliases.5:f:root:-:644
|
||||||
$manpage_directory/man5/canonical.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/pcre_table.5:f:root:-:644
|
||||||
$manpage_directory/man5/regexp_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/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/transport.5:f:root:-:644
|
||||||
$manpage_directory/man5/virtual.5:f:root:-:644
|
$manpage_directory/man5/virtual.5:f:root:-:644
|
||||||
$manpage_directory/man8/bounce.8:f:root:-:644
|
$manpage_directory/man8/bounce.8:f:root:-:644
|
||||||
|
@ -181,7 +181,7 @@ check)
|
|||||||
|
|
||||||
find $command_directory/postqueue $command_directory/postdrop \
|
find $command_directory/postqueue $command_directory/postdrop \
|
||||||
-prune ! -perm -02111 \
|
-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/* | \
|
for name in `ls -d $queue_directory/* | \
|
||||||
egrep '/(bin|etc|lib|usr)$'` ; \
|
egrep '/(bin|etc|lib|usr)$'` ; \
|
||||||
|
@ -4,8 +4,6 @@
|
|||||||
# regexp_table - format of Postfix regular expression tables
|
# regexp_table - format of Postfix regular expression tables
|
||||||
#
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
# regexp:/etc/postfix/filename
|
|
||||||
#
|
|
||||||
# postmap -q "string" regexp:/etc/postfix/filename
|
# postmap -q "string" regexp:/etc/postfix/filename
|
||||||
#
|
#
|
||||||
# postmap -q - regexp:/etc/postfix/filename <inputfile
|
# postmap -q - regexp:/etc/postfix/filename <inputfile
|
||||||
@ -77,7 +75,10 @@
|
|||||||
# Substitution of substrings from the matched expression
|
# Substitution of substrings from the matched expression
|
||||||
# into the result string is possible using $1, $2, etc.. The
|
# into the result string is possible using $1, $2, etc.. The
|
||||||
# macros in the result string may need to be written as ${n}
|
# 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
|
# EXAMPLE SMTPD ACCESS MAP
|
||||||
# # Disallow sender-specified routing. This is a must if you relay mail
|
# # Disallow sender-specified routing. This is a must if you relay mail
|
||||||
@ -106,6 +107,8 @@
|
|||||||
#
|
#
|
||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
# pcre_table(5) format of PCRE tables
|
# 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)
|
# AUTHOR(S)
|
||||||
# The regexp table lookup code was originally written by:
|
# The regexp table lookup code was originally written by:
|
||||||
|
@ -68,19 +68,40 @@
|
|||||||
#
|
#
|
||||||
#ldap_bind_pw =
|
#ldap_bind_pw =
|
||||||
|
|
||||||
# The ldap_cache parameter specifies whether or not to turn on client-side
|
#ldap_cache (IGNORED with a warning)
|
||||||
# caching.
|
#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
|
# The ldap_recursion_limit parameter specifies a limit on the nesting
|
||||||
# for (if ldap_cache=yes)
|
# depth of DN and URL special result attribute evaluation. The limit
|
||||||
|
# must be a non-zero positive number. The default value is 1000.
|
||||||
#
|
#
|
||||||
#ldap_cache_expiry = 30
|
#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
|
# The ldap_deference parameter specifies how to handle LDAP aliases. See the
|
||||||
# ldap_open(3) man page.
|
# ldap_open(3) man page.
|
||||||
|
@ -71,6 +71,18 @@ default_transport = smtp
|
|||||||
#
|
#
|
||||||
double_bounce_sender = double-bounce
|
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
|
# The export_environment parameter specifies the names of environment
|
||||||
# parameters that Postfix will export to non-Postfix processes.
|
# parameters that Postfix will export to non-Postfix processes.
|
||||||
#
|
#
|
||||||
|
@ -215,6 +215,41 @@ smtpd_soft_error_limit = 10
|
|||||||
#
|
#
|
||||||
smtpd_hard_error_limit = 20
|
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
|
# UCE RESTRICTIONS
|
||||||
#
|
#
|
||||||
|
@ -8,22 +8,6 @@
|
|||||||
# ADDRESS VERIFICATION (see also: verify(8) and SENDER_VERIFICATION_README)
|
# 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
|
# The address_verify_sender configuration parameter specifies the
|
||||||
# sender address that Postfix will use in address verification probe
|
# sender address that Postfix will use in address verification probe
|
||||||
# messages.
|
# messages.
|
||||||
@ -38,6 +22,40 @@ address_verify_map =
|
|||||||
#address_verify_sender = postmaster@my.domain
|
#address_verify_sender = postmaster@my.domain
|
||||||
address_verify_sender = postmaster
|
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
|
# The address_verify_positive_expire_time configuration parameter
|
||||||
# specifies the amount of time after which a known to be good address
|
# specifies the amount of time after which a known to be good address
|
||||||
# expires.
|
# 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,6 +16,25 @@
|
|||||||
# relay hosts. The mapping is used by the trivial-rewrite(8)
|
# relay hosts. The mapping is used by the trivial-rewrite(8)
|
||||||
# daemon.
|
# daemon.
|
||||||
#
|
#
|
||||||
|
# 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
|
# Normally, the transport table is specified as a text file
|
||||||
# that serves as input to the postmap(1) command. The
|
# that serves as input to the postmap(1) command. The
|
||||||
# result, an indexed file in dbm or db format, is used for
|
# result, an indexed file in dbm or db format, is used for
|
||||||
|
@ -109,6 +109,9 @@ ACCESS(5) ACCESS(5)
|
|||||||
A network address is a sequence of one or more
|
A network address is a sequence of one or more
|
||||||
octets separated by ".".
|
octets separated by ".".
|
||||||
|
|
||||||
|
NOTE: use the <b>cidr</b> lookup table type if you want to
|
||||||
|
specify arbitrary network blocks.
|
||||||
|
|
||||||
<b>ACTIONS</b>
|
<b>ACTIONS</b>
|
||||||
[<b>45</b>]<i>NN</i> <i>text</i>
|
[<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,
|
||||||
@ -208,8 +211,9 @@ ACCESS(5) ACCESS(5)
|
|||||||
The table format does not understand quoting conventions.
|
The table format does not understand quoting conventions.
|
||||||
|
|
||||||
<b>SEE</b> <b>ALSO</b>
|
<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
|
<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="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
|
<a href="regexp_table.5.html">regexp_table(5)</a> format of POSIX regular expression tables
|
||||||
|
|
||||||
|
@ -171,6 +171,14 @@ CLEANUP(8) CLEANUP(8)
|
|||||||
Address mapping lookup table for sender and recipi-
|
Address mapping lookup table for sender and recipi-
|
||||||
ent addresses in envelopes and headers.
|
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>
|
<b>recipient</b><i>_</i><b>canonical</b><i>_</i><b>maps</b>
|
||||||
Address mapping lookup table for envelope and
|
Address mapping lookup table for envelope and
|
||||||
header recipient addresses.
|
header recipient addresses.
|
||||||
|
@ -2618,8 +2618,9 @@ the <b>virtual_mailbox_maps</b> parameter.
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
If you want to deliver the domain as a Postfix simulated <a
|
If you want to deliver the domain as a <a href="virtual.8.html">
|
||||||
href="virtual.8.html">virtual</a>(5) domain, then you should list
|
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
|
the virtual domain name in the tables specified with the
|
||||||
<b>virtual_alias_domains</b> parameter instead.
|
<b>virtual_alias_domains</b> parameter instead.
|
||||||
|
|
||||||
@ -2638,7 +2639,7 @@ Solutions:
|
|||||||
|
|
||||||
<ul>
|
<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.
|
<a href="virtual.5.html">virtual(5)</a> manual page.
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -2715,6 +2716,15 @@ that the mail was sent to.
|
|||||||
Answer: Postfix logs the original recipient address in the
|
Answer: Postfix logs the original recipient address in the
|
||||||
<b>X-Original-To:</b> message header.
|
<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>
|
<hr>
|
||||||
|
|
||||||
<a name="masquerade"><h3>Address masquerading with exceptions</h3></a>
|
<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
|
pcre_table - format of Postfix PCRE tables
|
||||||
|
|
||||||
<b>SYNOPSIS</b>
|
<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><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>
|
<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:
|
The general form of a PCRE table is:
|
||||||
|
|
||||||
<b>/</b><i>pattern</i><b>/</b><i>flags</i> <i>result</i>
|
<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
|
blank lines and comments
|
||||||
Empty lines and whitespace-only lines are ignored,
|
Empty lines and whitespace-only lines are ignored,
|
||||||
@ -41,9 +41,12 @@ 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>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>
|
<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
|
matches (does not match). The <b>if</b>..<b>endif</b> can nest.
|
||||||
whitespace to patterns inside <b>if</b>..<b>endif</b>.
|
Do not prepend whitespace to patterns inside
|
||||||
|
<b>if</b>..<b>endif</b>.
|
||||||
|
|
||||||
Each pattern is a perl-like regular expression. The
|
Each pattern is a perl-like regular expression. The
|
||||||
expression delimiter can be any character, except whites-
|
expression delimiter can be any character, except whites-
|
||||||
@ -132,7 +135,10 @@ PCRE_TABLE(5) PCRE_TABLE(5)
|
|||||||
into the result string is possible using the conventional
|
into the result string is possible using the conventional
|
||||||
perl syntax ($1, $2, etc.). The macros in the result
|
perl syntax ($1, $2, etc.). The macros in the result
|
||||||
string may need to be written as ${n} or $(n) if they
|
string may need to be written as ${n} or $(n) if they
|
||||||
aren't followed by whitespace.
|
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>
|
<b>EXAMPLE</b> <b>SMTPD</b> <b>ACCESS</b> <b>MAP</b>
|
||||||
# Protect your outgoing majordomo exploders
|
# Protect your outgoing majordomo exploders
|
||||||
@ -161,6 +167,8 @@ PCRE_TABLE(5) PCRE_TABLE(5)
|
|||||||
|
|
||||||
<b>SEE</b> <b>ALSO</b>
|
<b>SEE</b> <b>ALSO</b>
|
||||||
<a href="regexp_table.5.html">regexp_table(5)</a> format of POSIX regular expression tables
|
<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>
|
<b>AUTHOR(S)</b>
|
||||||
The PCRE table lookup code was originally written by:
|
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
|
regexp_table - format of Postfix regular expression tables
|
||||||
|
|
||||||
<b>SYNOPSIS</b>
|
<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><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>
|
<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
|
Substitution of substrings from the matched expression
|
||||||
into the result string is possible using $1, $2, etc.. The
|
into the result string is possible using $1, $2, etc.. The
|
||||||
macros in the result string may need to be written as ${n}
|
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>
|
<b>EXAMPLE</b> <b>SMTPD</b> <b>ACCESS</b> <b>MAP</b>
|
||||||
# Disallow sender-specified routing. This is a must if you relay mail
|
# 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>
|
<b>SEE</b> <b>ALSO</b>
|
||||||
<a href="pcre_table.5.html">pcre_table(5)</a> format of PCRE tables
|
<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>
|
<b>AUTHOR(S)</b>
|
||||||
The regexp table lookup code was originally written by:
|
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
|
href="virtual.5.html">virtual alias</a> table to redirect mail for all
|
||||||
recipients, local or remote. The mapping affects only envelope
|
recipients, local or remote. The mapping affects only envelope
|
||||||
recipients; it has no effect on message headers or envelope senders.
|
recipients; it has no effect on message headers or envelope senders.
|
||||||
Virtual alias lookups are useful to redirect mail for simulated
|
Virtual alias lookups are useful to redirect mail for virtual
|
||||||
virtual domains to real user mailboxes, and to redirect mail for
|
alias domains to real user mailboxes, and to redirect mail for
|
||||||
domains that no longer exist. Virtual alias lookups can also be
|
domains that no longer exist. Virtual alias lookups can also be
|
||||||
used to transform <i> Firstname.Lastname </i> back into UNIX login
|
used to transform <i> Firstname.Lastname </i> back into UNIX login
|
||||||
names, although it seems that local <a href="#aliases">aliases</a>
|
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
|
preference, and connects to each listed address until it
|
||||||
finds a server that responds.
|
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-
|
Once the SMTP client has received the server greeting ban-
|
||||||
ner, no error will cause it to proceed to the next address
|
ner, no error will cause it to proceed to the next address
|
||||||
on the mail exchanger list. Instead, the message is either
|
on the mail exchanger list. Instead, the message is either
|
||||||
@ -148,6 +143,10 @@ SMTP(8) SMTP(8)
|
|||||||
<b>smtp</b><i>_</i><b>helo</b><i>_</i><b>name</b>
|
<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>
|
<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.
|
Skip servers that greet us with a 4xx status code.
|
||||||
|
|
||||||
|
@ -114,6 +114,25 @@ 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
|
<b>reject</b><i>_</i><b>sender</b><i>_</i><b>login</b><i>_</i><b>mismatch</b> sender anti-spoofing
|
||||||
restriction.
|
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>Miscellaneous</b>
|
||||||
<b>authorized</b><i>_</i><b>verp</b><i>_</i><b>clients</b>
|
<b>authorized</b><i>_</i><b>verp</b><i>_</i><b>clients</b>
|
||||||
Hostnames, domain names and/or addresses of clients
|
Hostnames, domain names and/or addresses of clients
|
||||||
@ -318,6 +337,24 @@ SMTPD(8) SMTPD(8)
|
|||||||
mail to. The domains are routed to the delivery
|
mail to. The domains are routed to the delivery
|
||||||
agent specified with the <b>relay</b><i>_</i><b>transport</b> setting.
|
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>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>
|
<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
|
Response code when a client violates an access
|
||||||
@ -381,10 +418,11 @@ SMTPD(8) SMTPD(8)
|
|||||||
be undeliverable.
|
be undeliverable.
|
||||||
|
|
||||||
<b>SEE</b> <b>ALSO</b>
|
<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="cleanup.8.html">cleanup(8)</a> message canonicalization
|
||||||
<a href="master.8.html">master(8)</a> process manager
|
<a href="master.8.html">master(8)</a> process manager
|
||||||
syslogd(8) system logging
|
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>
|
<b>LICENSE</b>
|
||||||
The Secure Mailer license must be distributed with this
|
The Secure Mailer license must be distributed with this
|
||||||
|
@ -17,6 +17,25 @@ TRANSPORT(5) TRANSPORT(5)
|
|||||||
relay hosts. The mapping is used by the <a href="trivial-rewrite.8.html"><b>trivial-rewrite</b>(8)</a>
|
relay hosts. The mapping is used by the <a href="trivial-rewrite.8.html"><b>trivial-rewrite</b>(8)</a>
|
||||||
daemon.
|
daemon.
|
||||||
|
|
||||||
|
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
|
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
|
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
|
result, an indexed file in <b>dbm</b> or <b>db</b> format, is used for
|
||||||
|
@ -33,9 +33,9 @@ VERIFY(8) VERIFY(8)
|
|||||||
Update the status of the specified address.
|
Update the status of the specified address.
|
||||||
|
|
||||||
<b>VRFY</b><i>_</i><b>ADDR</b><i>_</i><b>QUERY</b> <i>address</i>
|
<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
|
Look up the <i>status</i>, <i>last</i> <i>update</i> <i>time</i> and <i>text</i> of
|
||||||
address. If the status is unknown, a probe is sent
|
the specified address. If the status is unknown, a
|
||||||
and a default status is returned.
|
probe is sent and a default status is returned.
|
||||||
|
|
||||||
The server reply status is one of:
|
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/postmap.1 man1/sendmail.1 man1/mailq.1 man1/newaliases.1 \
|
||||||
man1/postqueue.1 man1/postsuper.1
|
man1/postqueue.1 man1/postsuper.1
|
||||||
CONFIG = man5/access.5 man5/aliases.5 man5/canonical.5 man5/relocated.5 \
|
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 \
|
TOOLS = man1/smtp-sink.1 man1/smtp-source.1 man1/qmqp-sink.1 \
|
||||||
man1/qmqp-source.1
|
man1/qmqp-source.1
|
||||||
|
|
||||||
@ -149,6 +150,9 @@ man5/aliases.5: ../proto/aliases
|
|||||||
man5/canonical.5: ../proto/canonical
|
man5/canonical.5: ../proto/canonical
|
||||||
../mantools/srctoman - $? >$@
|
../mantools/srctoman - $? >$@
|
||||||
|
|
||||||
|
man5/cidr_table.5: ../proto/cidr_table
|
||||||
|
../mantools/srctoman - $? >$@
|
||||||
|
|
||||||
man5/pcre_table.5: ../proto/pcre_table
|
man5/pcre_table.5: ../proto/pcre_table
|
||||||
../mantools/srctoman - $? >$@
|
../mantools/srctoman - $? >$@
|
||||||
|
|
||||||
@ -170,6 +174,9 @@ man1/smtp-sink.1: ../src/smtpstone/smtp-sink.c
|
|||||||
man1/smtp-source.1: ../src/smtpstone/smtp-source.c
|
man1/smtp-source.1: ../src/smtpstone/smtp-source.c
|
||||||
../mantools/srctoman $? >$@
|
../mantools/srctoman $? >$@
|
||||||
|
|
||||||
|
man5/tcp_table.5: ../proto/tcp_table
|
||||||
|
../mantools/srctoman - $? >$@
|
||||||
|
|
||||||
man1/qmqp-sink.1: ../src/smtpstone/qmqp-sink.c
|
man1/qmqp-sink.1: ../src/smtpstone/qmqp-sink.c
|
||||||
../mantools/srctoman $? >$@
|
../mantools/srctoman $? >$@
|
||||||
|
|
||||||
|
@ -106,6 +106,9 @@ order to match subdomains.
|
|||||||
.IP \fInet\fR
|
.IP \fInet\fR
|
||||||
Matches any host address in the specified network. A network
|
Matches any host address in the specified network. A network
|
||||||
address is a sequence of one or more octets separated by ".".
|
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
|
.SH ACTIONS
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
@ -194,8 +197,9 @@ The table format does not understand quoting conventions.
|
|||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
postmap(1) create mapping table
|
postmap(1) create lookup table
|
||||||
smtpd(8) smtp server
|
smtpd(8) smtp server
|
||||||
|
cidr_table(5) format of CIDR tables
|
||||||
pcre_table(5) format of PCRE tables
|
pcre_table(5) format of PCRE tables
|
||||||
regexp_table(5) format of POSIX regular expression tables
|
regexp_table(5) format of POSIX regular expression tables
|
||||||
.SH LICENSE
|
.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
|
.SH SYNOPSIS
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
\fBpcre:/etc/postfix/\fIfilename\fR
|
|
||||||
|
|
||||||
\fBpostmap -q "\fIstring\fB" pcre:/etc/postfix/\fIfilename\fR
|
\fBpostmap -q "\fIstring\fB" pcre:/etc/postfix/\fIfilename\fR
|
||||||
|
|
||||||
\fBpostmap -q - pcre:/etc/postfix/\fIfilename\fR <\fIinputfile\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:
|
The general form of a PCRE table is:
|
||||||
.IP "\fB/\fIpattern\fB/\fIflags result\fR"
|
.IP "\fB/\fIpattern\fB/\fIflags result\fR"
|
||||||
When \fIpattern\fR matches a search string, use the corresponding
|
.IP "\fB!/\fIpattern\fB/\fIflags result\fR"
|
||||||
\fIresult\fR value.
|
When \fIpattern\fR matches (does not match) a search string, use
|
||||||
|
the corresponding \fIresult\fR value.
|
||||||
.IP "blank lines and comments"
|
.IP "blank lines and comments"
|
||||||
Empty lines and whitespace-only lines are ignored, as
|
Empty lines and whitespace-only lines are ignored, as
|
||||||
are lines whose first non-whitespace character is a `#'.
|
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
|
A logical line starts with non-whitespace text. A line that
|
||||||
starts with whitespace continues a logical line.
|
starts with whitespace continues a logical line.
|
||||||
.IP "\fBif /\fIpattern\fB/\fIflags\fR"
|
.IP "\fBif /\fIpattern\fB/\fIflags\fR"
|
||||||
|
.IP "\fBif !/\fIpattern\fB/\fIflags\fR"
|
||||||
.IP "\fBendif\fR"
|
.IP "\fBendif\fR"
|
||||||
Examine the lines between \fBif\fR..\fBendif\fR only if
|
Examine the lines between \fBif\fR..\fBendif\fR only if
|
||||||
\fIpattern\fR matches. The \fBif\fR..\fBendif\fR can nest.
|
\fIpattern\fR matches (does not match). The \fBif\fR..\fBendif\fR
|
||||||
Do not prepend whitespace to patterns inside \fBif\fR..\fBendif\fR.
|
can nest. Do not prepend whitespace to patterns inside
|
||||||
|
\fBif\fR..\fBendif\fR.
|
||||||
.PP
|
.PP
|
||||||
Each pattern is a perl-like regular expression. The expression
|
Each pattern is a perl-like regular expression. The expression
|
||||||
delimiter can be any character, except whitespace or characters
|
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
|
Substitution of substrings from the matched expression into the result
|
||||||
string is possible using the conventional perl syntax ($1, $2, etc.).
|
string is possible using the conventional perl syntax ($1, $2, etc.).
|
||||||
The macros in the result string may need to be written as ${n}
|
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
|
.SH EXAMPLE SMTPD ACCESS MAP
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
@ -147,6 +150,8 @@ or $(n) if they aren't followed by whitespace.
|
|||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
regexp_table(5) format of POSIX regular expression tables
|
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)
|
.SH AUTHOR(S)
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
|
@ -8,8 +8,6 @@ format of Postfix regular expression tables
|
|||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
\fBregexp:/etc/postfix/\fIfilename\fR
|
|
||||||
|
|
||||||
\fBpostmap -q "\fIstring\fB" regexp:/etc/postfix/\fIfilename\fR
|
\fBpostmap -q "\fIstring\fB" regexp:/etc/postfix/\fIfilename\fR
|
||||||
|
|
||||||
\fBpostmap -q - regexp:/etc/postfix/\fIfilename\fR <\fIinputfile\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
|
Substitution of substrings from the matched expression into the result
|
||||||
string is possible using $1, $2, etc.. The macros in the result string
|
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
|
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
|
.SH EXAMPLE SMTPD ACCESS MAP
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
@ -104,6 +104,8 @@ endif
|
|||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
pcre_table(5) format of PCRE tables
|
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)
|
.SH AUTHOR(S)
|
||||||
.na
|
.na
|
||||||
.nf
|
.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
|
addresses to message delivery transports and/or relay hosts. The
|
||||||
mapping is used by the \fBtrivial-rewrite\fR(8) daemon.
|
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
|
Normally, the \fBtransport\fR table is specified as a text file
|
||||||
that serves as input to the \fBpostmap\fR(1) command.
|
that serves as input to the \fBpostmap\fR(1) command.
|
||||||
The result, an indexed file in \fBdbm\fR or \fBdb\fR format, is used
|
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
|
.IP \fBcanonical_maps\fR
|
||||||
Address mapping lookup table for sender and recipient addresses
|
Address mapping lookup table for sender and recipient addresses
|
||||||
in envelopes and headers.
|
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
|
.IP \fBrecipient_canonical_maps\fR
|
||||||
Address mapping lookup table for envelope and header recipient
|
Address mapping lookup table for envelope and header recipient
|
||||||
addresses.
|
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
|
the destination host, sorts the list by preference, and connects
|
||||||
to each listed address until it finds a server that responds.
|
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
|
Once the SMTP client has received the server greeting banner, no
|
||||||
error will cause it to proceed to the next address on the mail
|
error will cause it to proceed to the next address on the mail
|
||||||
exchanger list. Instead, the message is either bounced, or its
|
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.
|
Some SMTP servers misbehave on long lines.
|
||||||
.IP \fBsmtp_helo_name\fR
|
.IP \fBsmtp_helo_name\fR
|
||||||
The hostname to be used in HELO and EHLO commands.
|
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
|
.IP \fBsmtp_skip_4xx_greeting\fR
|
||||||
Skip servers that greet us with a 4xx status code.
|
Skip servers that greet us with a 4xx status code.
|
||||||
.IP \fBsmtp_skip_5xx_greeting\fR
|
.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
|
Maps that specify the SASL login name that owns a MAIL FROM sender
|
||||||
address. Used by the \fBreject_sender_login_mismatch\fR sender
|
address. Used by the \fBreject_sender_login_mismatch\fR sender
|
||||||
anti-spoofing restriction.
|
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
|
.SH Miscellaneous
|
||||||
.ad
|
.ad
|
||||||
.fi
|
.fi
|
||||||
@ -259,6 +277,21 @@ are eligible for the \fBpermit_mx_backup\fR feature.
|
|||||||
Restrict what domains this mail system will relay
|
Restrict what domains this mail system will relay
|
||||||
mail to. The domains are routed to the delivery agent
|
mail to. The domains are routed to the delivery agent
|
||||||
specified with the \fBrelay_transport\fR setting.
|
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"
|
.SH "UCE control responses"
|
||||||
.ad
|
.ad
|
||||||
.fi
|
.fi
|
||||||
@ -305,10 +338,11 @@ Response code when a recipient address is known to be undeliverable.
|
|||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
trivial-rewrite(8) address resolver
|
|
||||||
cleanup(8) message canonicalization
|
cleanup(8) message canonicalization
|
||||||
master(8) process manager
|
master(8) process manager
|
||||||
syslogd(8) system logging
|
syslogd(8) system logging
|
||||||
|
trivial-rewrite(8) address resolver
|
||||||
|
verify(8) address verification service
|
||||||
.SH LICENSE
|
.SH LICENSE
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
|
@ -35,7 +35,8 @@ This server implements the following requests:
|
|||||||
.IP "\fBVRFY_ADDR_UPDATE\fI address status text\fR"
|
.IP "\fBVRFY_ADDR_UPDATE\fI address status text\fR"
|
||||||
Update the status of the specified address.
|
Update the status of the specified address.
|
||||||
.IP "\fBVRFY_ADDR_QUERY\fI address\fR"
|
.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
|
If the status is unknown, a probe is sent and a default status is
|
||||||
returned.
|
returned.
|
||||||
.PP
|
.PP
|
||||||
|
@ -4,7 +4,7 @@ SHELL = /bin/sh
|
|||||||
|
|
||||||
CONFIG = ../conf/access ../conf/aliases ../conf/canonical ../conf/relocated \
|
CONFIG = ../conf/access ../conf/aliases ../conf/canonical ../conf/relocated \
|
||||||
../conf/transport ../conf/virtual ../conf/pcre_table \
|
../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" }'
|
AWK = awk '{ print; if (NR == 1) print ".pl 9999" }'
|
||||||
|
|
||||||
@ -30,6 +30,9 @@ clobber:
|
|||||||
../conf/canonical: canonical
|
../conf/canonical: canonical
|
||||||
srctoman - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
|
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
|
../conf/pcre_table: pcre_table
|
||||||
srctoman - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
|
srctoman - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
|
||||||
|
|
||||||
@ -39,6 +42,9 @@ clobber:
|
|||||||
../conf/relocated: relocated
|
../conf/relocated: relocated
|
||||||
srctoman - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
|
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
|
../conf/transport: transport
|
||||||
srctoman - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
|
srctoman - $? | $(AWK) | nroff -man | col -bx | uniq | sed 's/^/# /' >$@
|
||||||
|
|
||||||
|
@ -92,6 +92,9 @@
|
|||||||
# .IP \fInet\fR
|
# .IP \fInet\fR
|
||||||
# Matches any host address in the specified network. A network
|
# Matches any host address in the specified network. A network
|
||||||
# address is a sequence of one or more octets separated by ".".
|
# 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
|
# ACTIONS
|
||||||
# .ad
|
# .ad
|
||||||
# .fi
|
# .fi
|
||||||
@ -172,8 +175,9 @@
|
|||||||
# BUGS
|
# BUGS
|
||||||
# The table format does not understand quoting conventions.
|
# The table format does not understand quoting conventions.
|
||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
# postmap(1) create mapping table
|
# postmap(1) create lookup table
|
||||||
# smtpd(8) smtp server
|
# smtpd(8) smtp server
|
||||||
|
# cidr_table(5) format of CIDR tables
|
||||||
# pcre_table(5) format of PCRE tables
|
# pcre_table(5) format of PCRE tables
|
||||||
# regexp_table(5) format of POSIX regular expression tables
|
# regexp_table(5) format of POSIX regular expression tables
|
||||||
# LICENSE
|
# 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
|
# SUMMARY
|
||||||
# format of Postfix PCRE tables
|
# format of Postfix PCRE tables
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
# \fBpcre:/etc/postfix/\fIfilename\fR
|
|
||||||
#
|
|
||||||
# \fBpostmap -q "\fIstring\fB" pcre:/etc/postfix/\fIfilename\fR
|
# \fBpostmap -q "\fIstring\fB" pcre:/etc/postfix/\fIfilename\fR
|
||||||
#
|
#
|
||||||
# \fBpostmap -q - pcre:/etc/postfix/\fIfilename\fR <\fIinputfile\fR
|
# \fBpostmap -q - pcre:/etc/postfix/\fIfilename\fR <\fIinputfile\fR
|
||||||
@ -23,8 +21,9 @@
|
|||||||
#
|
#
|
||||||
# The general form of a PCRE table is:
|
# The general form of a PCRE table is:
|
||||||
# .IP "\fB/\fIpattern\fB/\fIflags result\fR"
|
# .IP "\fB/\fIpattern\fB/\fIflags result\fR"
|
||||||
# When \fIpattern\fR matches a search string, use the corresponding
|
# .IP "\fB!/\fIpattern\fB/\fIflags result\fR"
|
||||||
# \fIresult\fR value.
|
# When \fIpattern\fR matches (does not match) a search string, use
|
||||||
|
# the corresponding \fIresult\fR value.
|
||||||
# .IP "blank lines and comments"
|
# .IP "blank lines and comments"
|
||||||
# Empty lines and whitespace-only lines are ignored, as
|
# Empty lines and whitespace-only lines are ignored, as
|
||||||
# are lines whose first non-whitespace character is a `#'.
|
# are lines whose first non-whitespace character is a `#'.
|
||||||
@ -32,10 +31,12 @@
|
|||||||
# A logical line starts with non-whitespace text. A line that
|
# A logical line starts with non-whitespace text. A line that
|
||||||
# starts with whitespace continues a logical line.
|
# starts with whitespace continues a logical line.
|
||||||
# .IP "\fBif /\fIpattern\fB/\fIflags\fR"
|
# .IP "\fBif /\fIpattern\fB/\fIflags\fR"
|
||||||
|
# .IP "\fBif !/\fIpattern\fB/\fIflags\fR"
|
||||||
# .IP "\fBendif\fR"
|
# .IP "\fBendif\fR"
|
||||||
# Examine the lines between \fBif\fR..\fBendif\fR only if
|
# Examine the lines between \fBif\fR..\fBendif\fR only if
|
||||||
# \fIpattern\fR matches. The \fBif\fR..\fBendif\fR can nest.
|
# \fIpattern\fR matches (does not match). The \fBif\fR..\fBendif\fR
|
||||||
# Do not prepend whitespace to patterns inside \fBif\fR..\fBendif\fR.
|
# can nest. Do not prepend whitespace to patterns inside
|
||||||
|
# \fBif\fR..\fBendif\fR.
|
||||||
# .PP
|
# .PP
|
||||||
# Each pattern is a perl-like regular expression. The expression
|
# Each pattern is a perl-like regular expression. The expression
|
||||||
# delimiter can be any character, except whitespace or characters
|
# delimiter can be any character, except whitespace or characters
|
||||||
@ -108,7 +109,9 @@
|
|||||||
# Substitution of substrings from the matched expression into the result
|
# Substitution of substrings from the matched expression into the result
|
||||||
# string is possible using the conventional perl syntax ($1, $2, etc.).
|
# string is possible using the conventional perl syntax ($1, $2, etc.).
|
||||||
# The macros in the result string may need to be written as ${n}
|
# 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
|
# EXAMPLE SMTPD ACCESS MAP
|
||||||
# # Protect your outgoing majordomo exploders
|
# # Protect your outgoing majordomo exploders
|
||||||
# /^(?!owner-)(.*)-outgoing@(.*)/ 550 Use ${1}@${2} instead
|
# /^(?!owner-)(.*)-outgoing@(.*)/ 550 Use ${1}@${2} instead
|
||||||
@ -133,6 +136,8 @@
|
|||||||
# # Put your own body patterns here.
|
# # Put your own body patterns here.
|
||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
# regexp_table(5) format of POSIX regular expression tables
|
# 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)
|
# AUTHOR(S)
|
||||||
# The PCRE table lookup code was originally written by:
|
# The PCRE table lookup code was originally written by:
|
||||||
# Andrew McNamara
|
# Andrew McNamara
|
||||||
|
@ -4,8 +4,6 @@
|
|||||||
# SUMMARY
|
# SUMMARY
|
||||||
# format of Postfix regular expression tables
|
# format of Postfix regular expression tables
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
# \fBregexp:/etc/postfix/\fIfilename\fR
|
|
||||||
#
|
|
||||||
# \fBpostmap -q "\fIstring\fB" regexp:/etc/postfix/\fIfilename\fR
|
# \fBpostmap -q "\fIstring\fB" regexp:/etc/postfix/\fIfilename\fR
|
||||||
#
|
#
|
||||||
# \fBpostmap -q - regexp:/etc/postfix/\fIfilename\fR <\fIinputfile\fR
|
# \fBpostmap -q - regexp:/etc/postfix/\fIfilename\fR <\fIinputfile\fR
|
||||||
@ -65,7 +63,9 @@
|
|||||||
# Substitution of substrings from the matched expression into the result
|
# Substitution of substrings from the matched expression into the result
|
||||||
# string is possible using $1, $2, etc.. The macros in the result string
|
# 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
|
# 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
|
# EXAMPLE SMTPD ACCESS MAP
|
||||||
# # Disallow sender-specified routing. This is a must if you relay mail
|
# # Disallow sender-specified routing. This is a must if you relay mail
|
||||||
# # for other domains.
|
# # for other domains.
|
||||||
@ -90,6 +90,8 @@
|
|||||||
# # Put your own body patterns here.
|
# # Put your own body patterns here.
|
||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
# pcre_table(5) format of PCRE tables
|
# 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)
|
# AUTHOR(S)
|
||||||
# The regexp table lookup code was originally written by:
|
# The regexp table lookup code was originally written by:
|
||||||
# LaMont Jones
|
# 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
|
# addresses to message delivery transports and/or relay hosts. The
|
||||||
# mapping is used by the \fBtrivial-rewrite\fR(8) daemon.
|
# 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
|
# Normally, the \fBtransport\fR table is specified as a text file
|
||||||
# that serves as input to the \fBpostmap\fR(1) command.
|
# that serves as input to the \fBpostmap\fR(1) command.
|
||||||
# The result, an indexed file in \fBdbm\fR or \fBdb\fR format, is used
|
# 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/vbuf.h
|
||||||
bounce_notify_util.o: ../../include/vstream.h
|
bounce_notify_util.o: ../../include/vstream.h
|
||||||
bounce_notify_util.o: ../../include/line_wrap.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/mail_queue.h
|
||||||
bounce_notify_util.o: ../../include/quote_822_local.h
|
bounce_notify_util.o: ../../include/quote_822_local.h
|
||||||
bounce_notify_util.o: ../../include/quote_flags.h
|
bounce_notify_util.o: ../../include/quote_flags.h
|
||||||
|
@ -155,6 +155,8 @@
|
|||||||
#include <vstring.h>
|
#include <vstring.h>
|
||||||
#include <vstream.h>
|
#include <vstream.h>
|
||||||
#include <line_wrap.h>
|
#include <line_wrap.h>
|
||||||
|
#include <stringops.h>
|
||||||
|
#include <xtext.h>
|
||||||
|
|
||||||
/* Global library. */
|
/* Global library. */
|
||||||
|
|
||||||
@ -210,10 +212,19 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
|
|||||||
}
|
}
|
||||||
bounce_info->flush = flush;
|
bounce_info->flush = flush;
|
||||||
bounce_info->buf = vstring_alloc(100);
|
bounce_info->buf = vstring_alloc(100);
|
||||||
|
bounce_info->sender = vstring_alloc(100);
|
||||||
bounce_info->arrival_time = 0;
|
bounce_info->arrival_time = 0;
|
||||||
bounce_info->orig_offs = 0;
|
bounce_info->orig_offs = 0;
|
||||||
bounce_info->log_handle = log_handle;
|
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
|
* Compute a supposedly unique boundary string. This assumes that a queue
|
||||||
* ID and a hostname contain acceptable characters for a boundary string,
|
* 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 (rec_type == REC_TYPE_TIME && bounce_info->arrival_time == 0) {
|
||||||
if ((bounce_info->arrival_time = atol(STR(bounce_info->buf))) < 0)
|
if ((bounce_info->arrival_time = atol(STR(bounce_info->buf))) < 0)
|
||||||
bounce_info->arrival_time = 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) {
|
} 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);
|
bounce_info->orig_offs = vstream_ftell(bounce_info->orig_fp);
|
||||||
break;
|
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, bounce_info->queue_name,
|
||||||
bounce_info->queue_id);
|
bounce_info->queue_id);
|
||||||
vstring_free(bounce_info->buf);
|
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->mime_boundary);
|
||||||
myfree((char *) bounce_info);
|
myfree((char *) bounce_info);
|
||||||
}
|
}
|
||||||
@ -542,6 +564,11 @@ int bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
|
|||||||
#if 0
|
#if 0
|
||||||
post_mail_fprintf(bounce, "Received-From-MTA: dns; %s", "whatever");
|
post_mail_fprintf(bounce, "Received-From-MTA: dns; %s", "whatever");
|
||||||
#endif
|
#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)
|
if (bounce_info->arrival_time > 0)
|
||||||
post_mail_fprintf(bounce, "Arrival-Date: %s",
|
post_mail_fprintf(bounce, "Arrival-Date: %s",
|
||||||
mail_date(bounce_info->arrival_time));
|
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)
|
int bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
|
||||||
{
|
{
|
||||||
char *fixed_mail_name;
|
|
||||||
|
|
||||||
post_mail_fputs(bounce, "");
|
post_mail_fputs(bounce, "");
|
||||||
post_mail_fprintf(bounce, "Final-Recipient: rfc822; %s",
|
post_mail_fprintf(bounce, "Final-Recipient: rfc822; %s",
|
||||||
bounce_info->log_handle->recipient);
|
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",
|
post_mail_fprintf(bounce, "Original-Recipient: rfc822; %s",
|
||||||
bounce_info->log_handle->orig_rcpt);
|
STR(bounce_info->buf));
|
||||||
|
}
|
||||||
post_mail_fprintf(bounce, "Action: %s",
|
post_mail_fprintf(bounce, "Action: %s",
|
||||||
bounce_info->flush == BOUNCE_MSG_FAIL ?
|
bounce_info->flush == BOUNCE_MSG_FAIL ?
|
||||||
"failed" : bounce_info->log_handle->dsn_action);
|
"failed" : bounce_info->log_handle->dsn_action);
|
||||||
post_mail_fprintf(bounce, "Status: %s",
|
post_mail_fprintf(bounce, "Status: %s",
|
||||||
bounce_info->log_handle->dsn_status);
|
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",
|
bounce_print_wrap(bounce, bounce_info, "Diagnostic-Code: X-%s; %s",
|
||||||
fixed_mail_name, bounce_info->log_handle->text);
|
bounce_info->mail_name, bounce_info->log_handle->text);
|
||||||
myfree(fixed_mail_name);
|
|
||||||
#if 0
|
#if 0
|
||||||
post_mail_fprintf(bounce, "Last-Attempt-Date: %s",
|
post_mail_fprintf(bounce, "Last-Attempt-Date: %s",
|
||||||
bounce_info->log_handle->log_time);
|
bounce_info->log_handle->log_time);
|
||||||
|
@ -69,10 +69,12 @@ typedef struct {
|
|||||||
const char *mime_boundary; /* for MIME */
|
const char *mime_boundary; /* for MIME */
|
||||||
int flush; /* 0=defer, other=bounce */
|
int flush; /* 0=defer, other=bounce */
|
||||||
VSTRING *buf; /* scratch pad */
|
VSTRING *buf; /* scratch pad */
|
||||||
|
VSTRING *sender; /* envelope sender */
|
||||||
VSTREAM *orig_fp; /* open queue file */
|
VSTREAM *orig_fp; /* open queue file */
|
||||||
long orig_offs; /* start of content */
|
long orig_offs; /* start of content */
|
||||||
time_t arrival_time; /* time of arrival */
|
time_t arrival_time; /* time of arrival */
|
||||||
BOUNCE_LOG *log_handle; /* open logfile */
|
BOUNCE_LOG *log_handle; /* open logfile */
|
||||||
|
char *mail_name; /* $mail_name, cooked */
|
||||||
} BOUNCE_INFO;
|
} BOUNCE_INFO;
|
||||||
|
|
||||||
extern BOUNCE_INFO *bounce_mail_init(const char *, const char *, const char *, const char *, int);
|
extern BOUNCE_INFO *bounce_mail_init(const char *, const char *, const char *, const char *, int);
|
||||||
|
@ -136,6 +136,11 @@
|
|||||||
/* .IP \fBcanonical_maps\fR
|
/* .IP \fBcanonical_maps\fR
|
||||||
/* Address mapping lookup table for sender and recipient addresses
|
/* Address mapping lookup table for sender and recipient addresses
|
||||||
/* in envelopes and headers.
|
/* 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
|
/* .IP \fBrecipient_canonical_maps\fR
|
||||||
/* Address mapping lookup table for envelope and header recipient
|
/* Address mapping lookup table for envelope and header recipient
|
||||||
/* addresses.
|
/* addresses.
|
||||||
@ -342,6 +347,7 @@ int main(int argc, char **argv)
|
|||||||
*/
|
*/
|
||||||
single_server_main(argc, argv, cleanup_service,
|
single_server_main(argc, argv, cleanup_service,
|
||||||
MAIL_SERVER_INT_TABLE, cleanup_int_table,
|
MAIL_SERVER_INT_TABLE, cleanup_int_table,
|
||||||
|
MAIL_SERVER_BOOL_TABLE, cleanup_bool_table,
|
||||||
MAIL_SERVER_STR_TABLE, cleanup_str_table,
|
MAIL_SERVER_STR_TABLE, cleanup_str_table,
|
||||||
MAIL_SERVER_TIME_TABLE, cleanup_time_table,
|
MAIL_SERVER_TIME_TABLE, cleanup_time_table,
|
||||||
MAIL_SERVER_PRE_INIT, cleanup_pre_jail,
|
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_pre_jail(char *, char **);
|
||||||
extern void cleanup_post_jail(char *, char **);
|
extern void cleanup_post_jail(char *, char **);
|
||||||
extern CONFIG_INT_TABLE cleanup_int_table[];
|
extern CONFIG_INT_TABLE cleanup_int_table[];
|
||||||
|
extern CONFIG_BOOL_TABLE cleanup_bool_table[];
|
||||||
extern CONFIG_STR_TABLE cleanup_str_table[];
|
extern CONFIG_STR_TABLE cleanup_str_table[];
|
||||||
extern CONFIG_TIME_TABLE cleanup_time_table[];
|
extern CONFIG_TIME_TABLE cleanup_time_table[];
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
/*
|
/*
|
||||||
/* CONFIG_INT_TABLE cleanup_int_table[];
|
/* CONFIG_INT_TABLE cleanup_int_table[];
|
||||||
/*
|
/*
|
||||||
|
/* CONFIG_BOOL_TABLE cleanup_bool_table[];
|
||||||
|
/*
|
||||||
/* CONFIG_STR_TABLE cleanup_str_table[];
|
/* CONFIG_STR_TABLE cleanup_str_table[];
|
||||||
/*
|
/*
|
||||||
/* CONFIG_TIME_TABLE cleanup_time_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_nesthdr_checks; /* nested header checks */
|
||||||
char *var_body_checks; /* any body checks */
|
char *var_body_checks; /* any body checks */
|
||||||
int var_dup_filter_limit; /* recipient dup filter */
|
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 */
|
char *var_empty_addr; /* destination of bounced bounces */
|
||||||
int var_delay_warn_time; /* delay that triggers warning */
|
int var_delay_warn_time; /* delay that triggers warning */
|
||||||
char *var_prop_extension; /* propagate unmatched extension */
|
char *var_prop_extension; /* propagate unmatched extension */
|
||||||
@ -125,6 +128,11 @@ CONFIG_INT_TABLE cleanup_int_table[] = {
|
|||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CONFIG_BOOL_TABLE cleanup_bool_table[] = {
|
||||||
|
VAR_ENABLE_ORCPT, DEF_ENABLE_ORCPT, &var_enable_orcpt,
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
CONFIG_TIME_TABLE cleanup_time_table[] = {
|
CONFIG_TIME_TABLE cleanup_time_table[] = {
|
||||||
VAR_DELAY_WARN_TIME, DEF_DELAY_WARN_TIME, &var_delay_warn_time, 0, 0,
|
VAR_DELAY_WARN_TIME, DEF_DELAY_WARN_TIME, &var_delay_warn_time, 0, 0,
|
||||||
0,
|
0,
|
||||||
|
@ -68,6 +68,12 @@ void cleanup_out_recipient(CLEANUP_STATE *state, const char *orcpt,
|
|||||||
ARGV *argv;
|
ARGV *argv;
|
||||||
char **cpp;
|
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
|
* Distinguish between different original recipient addresses that map
|
||||||
* onto the same mailbox. The recipient will use our original recipient
|
* 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 \
|
off_cvt quote_822_local rec2stream recdump resolve_clnt \
|
||||||
resolve_local rewrite_clnt stream2rec string_list tok822_parse \
|
resolve_local rewrite_clnt stream2rec string_list tok822_parse \
|
||||||
quote_821_local mail_conf_time mime_state strip_addr \
|
quote_821_local mail_conf_time mime_state strip_addr \
|
||||||
virtual8_maps verify_clnt
|
virtual8_maps verify_clnt xtext
|
||||||
|
|
||||||
LIBS = ../../lib/libutil.a
|
LIBS = ../../lib/libutil.a
|
||||||
LIB_DIR = ../../lib
|
LIB_DIR = ../../lib
|
||||||
@ -240,9 +240,14 @@ verify_clnt: $(LIB) $(LIBS)
|
|||||||
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
|
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
|
||||||
mv junk $@.o
|
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 \
|
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 \
|
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_test: tok822_parse tok822_parse.in tok822_parse.ref
|
||||||
./tok822_parse <tok822_parse.in >tok822_parse.tmp 2>&1
|
./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
|
diff virtual8.ref virtual8.tmp
|
||||||
rm -f virtual8.tmp virtual8_map.db
|
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
|
# Requires: Postfix running, root privileges
|
||||||
|
|
||||||
rewrite_clnt_test: rewrite_clnt rewrite_clnt.in rewrite_clnt.ref
|
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
|
virtual8_maps.o: virtual8_maps.h
|
||||||
xtext.o: xtext.c
|
xtext.o: xtext.c
|
||||||
xtext.o: ../../include/sys_defs.h
|
xtext.o: ../../include/sys_defs.h
|
||||||
xtext.o: ../../include/vstream.h
|
xtext.o: ../../include/msg.h
|
||||||
xtext.o: ../../include/vbuf.h
|
|
||||||
xtext.o: ../../include/vstring.h
|
xtext.o: ../../include/vstring.h
|
||||||
|
xtext.o: ../../include/vbuf.h
|
||||||
xtext.o: xtext.h
|
xtext.o: xtext.h
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#define CLEANUP_STAT_CONT (1<<3) /* Message content rejected */
|
#define CLEANUP_STAT_CONT (1<<3) /* Message content rejected */
|
||||||
#define CLEANUP_STAT_HOPS (1<<4) /* Too many hops */
|
#define CLEANUP_STAT_HOPS (1<<4) /* Too many hops */
|
||||||
#define CLEANUP_STAT_RCPT (1<<6) /* No recipients found */
|
#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.
|
* 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 == '"')
|
if (ch == '"')
|
||||||
break;
|
break;
|
||||||
if (ch == '\n') { /* unfold */
|
if (ch == '\n') { /* unfold */
|
||||||
|
if (tok_count < token_len) {
|
||||||
len = LEN(token_buffer);
|
len = LEN(token_buffer);
|
||||||
while (len > 0 && IS_SPACE_TAB_CR_LF(STR(token_buffer)[len - 1]))
|
while (len > 0
|
||||||
|
&& IS_SPACE_TAB_CR_LF(STR(token_buffer)[len - 1]))
|
||||||
len--;
|
len--;
|
||||||
if (len < LEN(token_buffer))
|
if (len < LEN(token_buffer))
|
||||||
vstring_truncate(token_buffer, len);
|
vstring_truncate(token_buffer, len);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ch == '\\') {
|
if (ch == '\\') {
|
||||||
|
@ -115,9 +115,7 @@ void vlog_adhoc(const char *id, const char *orig_rcpt,
|
|||||||
int delay = time((time_t *) 0) - entry;
|
int delay = time((time_t *) 0) - entry;
|
||||||
|
|
||||||
vstring_vsprintf(why, fmt, ap);
|
vstring_vsprintf(why, fmt, ap);
|
||||||
if (orig_rcpt == 0)
|
if (orig_rcpt && *orig_rcpt && strcasecmp(recipient, orig_rcpt) != 0)
|
||||||
orig_rcpt = "";
|
|
||||||
if (strcasecmp(recipient, orig_rcpt) != 0)
|
|
||||||
msg_info("%s: to=<%s>, orig_to=<%s>, relay=%s, delay=%d, status=%s (%s)",
|
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));
|
id, recipient, orig_rcpt, relay, delay, status, vstring_str(why));
|
||||||
else
|
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)
|
static void check_mail_conf_int(const char *name, int intval, int min, int max)
|
||||||
{
|
{
|
||||||
if (min && intval < min)
|
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)
|
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 */
|
/* 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);
|
int len = strlen(strval);
|
||||||
|
|
||||||
if (min && len < min)
|
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);
|
len, min, name, strval);
|
||||||
if (max && len > max)
|
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);
|
len, max, name, strval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,9 +165,16 @@ int mail_copy(const char *sender,
|
|||||||
if (flags & MAIL_COPY_ORIG_RCPT) {
|
if (flags & MAIL_COPY_ORIG_RCPT) {
|
||||||
if (orig_rcpt == 0)
|
if (orig_rcpt == 0)
|
||||||
msg_panic("%s: null orig_rcpt", myname);
|
msg_panic("%s: null orig_rcpt", myname);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An empty original recipient record almost certainly means that
|
||||||
|
* original recipient processing was disabled.
|
||||||
|
*/
|
||||||
|
if (*orig_rcpt) {
|
||||||
quote_822_local(buf, orig_rcpt);
|
quote_822_local(buf, orig_rcpt);
|
||||||
vstream_fprintf(dst, "X-Original-To: %s%s", vstring_str(buf), eol);
|
vstream_fprintf(dst, "X-Original-To: %s%s", vstring_str(buf), eol);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (flags & MAIL_COPY_DELIVERED) {
|
if (flags & MAIL_COPY_DELIVERED) {
|
||||||
if (delivered == 0)
|
if (delivered == 0)
|
||||||
msg_panic("%s: null delivered", myname);
|
msg_panic("%s: null delivered", myname);
|
||||||
|
@ -486,6 +486,16 @@ extern char *var_fwd_exp_filter;
|
|||||||
#define DEF_DELIVER_HDR "command, file, forward"
|
#define DEF_DELIVER_HDR "command, file, forward"
|
||||||
extern char *var_deliver_hdr;
|
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 VAR_EXP_OWN_ALIAS "expand_owner_alias"
|
||||||
#define DEF_EXP_OWN_ALIAS 0
|
#define DEF_EXP_OWN_ALIAS 0
|
||||||
extern bool var_exp_own_alias;
|
extern bool var_exp_own_alias;
|
||||||
@ -763,6 +773,10 @@ extern int var_smtp_rset_tmout;
|
|||||||
#define DEF_SMTP_QUIT_TMOUT "300s"
|
#define DEF_SMTP_QUIT_TMOUT "300s"
|
||||||
extern int var_smtp_quit_tmout;
|
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 VAR_SMTP_SKIP_4XX "smtp_skip_4xx_greeting"
|
||||||
#define DEF_SMTP_SKIP_4XX 1
|
#define DEF_SMTP_SKIP_4XX 1
|
||||||
extern bool var_smtp_skip_4xx_greeting;
|
extern bool var_smtp_skip_4xx_greeting;
|
||||||
@ -1691,6 +1705,14 @@ extern bool var_verify_neg_cache;
|
|||||||
#define DEF_VERIFY_SENDER "postmaster"
|
#define DEF_VERIFY_SENDER "postmaster"
|
||||||
extern char *var_verify_sender;
|
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 VAR_VRFY_LOCAL_XPORT "address_verify_local_transport"
|
||||||
#define DEF_VRFY_LOCAL_XPORT "$" VAR_LOCAL_TRANSPORT
|
#define DEF_VRFY_LOCAL_XPORT "$" VAR_LOCAL_TRANSPORT
|
||||||
extern char *var_vrfy_local_xport;
|
extern char *var_vrfy_local_xport;
|
||||||
@ -1804,6 +1826,21 @@ extern char *var_xport_null_key;
|
|||||||
#define DEF_OLDLOG_COMPAT 1
|
#define DEF_OLDLOG_COMPAT 1
|
||||||
extern bool var_oldlog_compat;
|
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
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
|
@ -20,10 +20,10 @@
|
|||||||
* Patches change the patchlevel and the release date. Snapshots change the
|
* Patches change the patchlevel and the release date. Snapshots change the
|
||||||
* release date only, unless they include the same bugfix as a patch release.
|
* 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 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;
|
extern char *var_mail_version;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -66,8 +66,8 @@
|
|||||||
/* .IP RESOLVE_CLASS_LOCAL
|
/* .IP RESOLVE_CLASS_LOCAL
|
||||||
/* The address domain matches $mydestination or $inet_interfaces.
|
/* The address domain matches $mydestination or $inet_interfaces.
|
||||||
/* .IP RESOLVE_CLASS_ALIAS
|
/* .IP RESOLVE_CLASS_ALIAS
|
||||||
/* The address domain matches $virtual_alias_domains (simulated
|
/* The address domain matches $virtual_alias_domains (virtual
|
||||||
/* virtual domains, where each address is redirected to a real
|
/* alias domains, where each address is redirected to a real
|
||||||
/* local or remote address).
|
/* local or remote address).
|
||||||
/* .IP RESOLVE_CLASS_VIRTUAL
|
/* .IP RESOLVE_CLASS_VIRTUAL
|
||||||
/* The address domain matches $virtual_mailbox_domains (true
|
/* The address domain matches $virtual_mailbox_domains (true
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
#ifndef _VRFY_STAT_H_INCLUDED_
|
#ifndef _VRFY_CLNT_H_INCLUDED_
|
||||||
#define _VRFY_STAT_H_INCLUDED_
|
#define _VRFY_CLNT_H_INCLUDED_
|
||||||
|
|
||||||
/*++
|
/*++
|
||||||
/* NAME
|
/* NAME
|
||||||
/* mail_proto 3h
|
/* verify_clnt 3h
|
||||||
/* SUMMARY
|
/* SUMMARY
|
||||||
/* mail internal IPC support
|
/* address verification client interface
|
||||||
/* SYNOPSIS
|
/* SYNOPSIS
|
||||||
/* #include <mail_proto.h>
|
/* #include <verify_clnt.h>
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* .nf
|
/* .nf
|
||||||
|
|
||||||
|
@ -2,22 +2,29 @@
|
|||||||
/* NAME
|
/* NAME
|
||||||
/* xtext 3
|
/* xtext 3
|
||||||
/* SUMMARY
|
/* SUMMARY
|
||||||
/* translate characters according to RFC 1894
|
/* quote/unquote text, HTTP style.
|
||||||
/* SYNOPSIS
|
/* SYNOPSIS
|
||||||
/* #include <xtext.h>
|
/* #include <xtext.h>
|
||||||
/*
|
/*
|
||||||
/* VSTRING *xtext(result, original)
|
/* VSTRING *xtext_quote(quoted, unquoted, special)
|
||||||
/* VSTRING *result;
|
/* VSTRING *quoted;
|
||||||
/* const char *original;
|
/* const char *unquoted;
|
||||||
/* DESCRIPTION
|
/* const char *special;
|
||||||
/* xtext() takes a null-terminated string, and produces a translation
|
|
||||||
/* according to RFC 1894 (DSN).
|
|
||||||
/* BUGS
|
|
||||||
/* Cannot replace null characters.
|
|
||||||
/*
|
/*
|
||||||
/* Does not insert CR LF SPACE to limit output line length.
|
/* VSTRING *xtext_unquote(unquoted, quoted)
|
||||||
/* SEE ALSO
|
/* VSTRING *unquoted;
|
||||||
/* RFC 1894, Delivery Status Notifications
|
/* 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
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@ -31,56 +38,112 @@
|
|||||||
|
|
||||||
/* System library. */
|
/* System library. */
|
||||||
|
|
||||||
#include "sys_defs.h"
|
#include <sys_defs.h>
|
||||||
#include <vstream.h>
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
/* Utility library. */
|
/* 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;
|
const char *cp;
|
||||||
int ch;
|
int ch;
|
||||||
|
|
||||||
/*
|
VSTRING_RESET(quoted);
|
||||||
* Preliminary implementation. ASCII specific!!
|
for (cp = unquoted; (ch = *(unsigned const char *) cp) != 0; cp++) {
|
||||||
*/
|
if (ch != '+' && ch > 32 && ch < 127 && strchr(special, ch) == 0) {
|
||||||
VSTRING_RESET(result);
|
VSTRING_ADDCH(quoted, ch);
|
||||||
for (cp = original; (ch = *(unsigned char *) cp) != 0; cp++) {
|
} else {
|
||||||
if (ch == '+' || ch == '\\' || ch == '(' || ch < 33 || ch > 126)
|
vstring_sprintf_append(quoted, "+%02X", ch);
|
||||||
vstring_sprintf_append(result, "+%02X", ch);
|
}
|
||||||
else
|
}
|
||||||
VSTRING_ADDCH(result, ch);
|
VSTRING_TERMINATE(quoted);
|
||||||
|
return (quoted);
|
||||||
}
|
}
|
||||||
VSTRING_TERMINATE(result);
|
|
||||||
|
|
||||||
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
|
#ifdef TEST
|
||||||
|
|
||||||
#define STR(x) vstring_str(x)
|
/*
|
||||||
|
* Proof-of-concept test program: convert to quoted and back.
|
||||||
|
*/
|
||||||
#include <vstream.h>
|
#include <vstream.h>
|
||||||
|
|
||||||
int main(int unused_argc, char **unused_argv)
|
#define BUFLEN 1024
|
||||||
{
|
|
||||||
VSTRING *ibuf = vstring_alloc(100);
|
|
||||||
VSTRING *obuf = vstring_alloc(100);
|
|
||||||
|
|
||||||
while (vstring_fgets(ibuf, VSTREAM_IN)) {
|
static int read_buf(VSTREAM *fp, VSTRING *buf)
|
||||||
vstream_fputs(STR(xtext(obuf, STR(ibuf))));
|
{
|
||||||
vstream_fflush(VSTREAM_OUT);
|
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);
|
||||||
}
|
}
|
||||||
vstring_free(ibuf);
|
|
||||||
vstring_free(obuf);
|
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");
|
||||||
|
}
|
||||||
|
vstream_fflush(VSTREAM_OUT);
|
||||||
|
vstring_free(unquoted);
|
||||||
|
vstring_free(quoted);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
|
#ifndef _XTEXT_H_INCLUDED_
|
||||||
|
#define _XTEXT_H_INCLUDED_
|
||||||
|
|
||||||
/*++
|
/*++
|
||||||
/* NAME
|
/* NAME
|
||||||
/* xtext 3h
|
/* xtext 3h
|
||||||
/* SUMMARY
|
/* SUMMARY
|
||||||
/* translate characters according to RFC 1894
|
/* quote/unquote text, xtext style.
|
||||||
/* SYNOPSIS
|
/* SYNOPSIS
|
||||||
/* #include <xtext.h>
|
/* #include <xtext.h>
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
@ -16,7 +19,8 @@
|
|||||||
/*
|
/*
|
||||||
* External interface.
|
* 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
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
@ -28,3 +32,5 @@ extern VSTRING *xtext(VSTRING *, const char *);
|
|||||||
/* P.O. Box 704
|
/* P.O. Box 704
|
||||||
/* Yorktown Heights, NY 10598, USA
|
/* Yorktown Heights, NY 10598, USA
|
||||||
/*--*/
|
/*--*/
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -389,7 +389,7 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
|
|||||||
if (message->rcpt_offset == 0) {
|
if (message->rcpt_offset == 0) {
|
||||||
message->rcpt_unread--;
|
message->rcpt_unread--;
|
||||||
qmgr_rcpt_list_add(&message->rcpt_list, curr_offset,
|
qmgr_rcpt_list_add(&message->rcpt_list, curr_offset,
|
||||||
orig_rcpt ? orig_rcpt : "unknown", start);
|
orig_rcpt ? orig_rcpt : "", start);
|
||||||
if (orig_rcpt) {
|
if (orig_rcpt) {
|
||||||
myfree(orig_rcpt);
|
myfree(orig_rcpt);
|
||||||
orig_rcpt = 0;
|
orig_rcpt = 0;
|
||||||
|
@ -98,7 +98,7 @@ static void postcat(VSTREAM *fp, VSTRING *buffer)
|
|||||||
* See if this is a plausible file.
|
* See if this is a plausible file.
|
||||||
*/
|
*/
|
||||||
if ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF) {
|
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));
|
msg_warn("%s: input is not a valid queue file", VSTREAM_PATH(fp));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -357,7 +357,7 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
|
|||||||
#define FUDGE(x) ((x) * (var_qmgr_fudge / 100.0))
|
#define FUDGE(x) ((x) * (var_qmgr_fudge / 100.0))
|
||||||
if (message->rcpt_offset == 0) {
|
if (message->rcpt_offset == 0) {
|
||||||
qmgr_rcpt_list_add(&message->rcpt_list, curr_offset,
|
qmgr_rcpt_list_add(&message->rcpt_list, curr_offset,
|
||||||
orig_rcpt ? orig_rcpt : "unknown", start);
|
orig_rcpt ? orig_rcpt : "", start);
|
||||||
if (orig_rcpt) {
|
if (orig_rcpt) {
|
||||||
myfree(orig_rcpt);
|
myfree(orig_rcpt);
|
||||||
orig_rcpt = 0;
|
orig_rcpt = 0;
|
||||||
|
@ -104,7 +104,7 @@ static void showq_reasons(VSTREAM *, BOUNCE_LOG *, HTABLE *);
|
|||||||
/* showq_report - report status of sender and recipients */
|
/* showq_report - report status of sender and recipients */
|
||||||
|
|
||||||
static void showq_report(VSTREAM *client, char *queue, char *id,
|
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 *buf = vstring_alloc(100);
|
||||||
VSTRING *printable_quoted_addr = 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), '?');
|
printable(STR(printable_quoted_addr), '?');
|
||||||
vstream_fprintf(client, DATA_FORMAT, id, status,
|
vstream_fprintf(client, DATA_FORMAT, id, status,
|
||||||
msg_size > 0 ? msg_size : size, arrival_time > 0 ?
|
msg_size > 0 ? msg_size : size, arrival_time > 0 ?
|
||||||
asctime(localtime(&arrival_time)) : "??",
|
asctime(localtime(&arrival_time)) :
|
||||||
|
asctime(localtime(&mtime)),
|
||||||
STR(printable_quoted_addr));
|
STR(printable_quoted_addr));
|
||||||
break;
|
break;
|
||||||
case REC_TYPE_RCPT:
|
case REC_TYPE_RCPT:
|
||||||
@ -302,7 +303,8 @@ static void showq_service(VSTREAM *client, char *unused_service, char **argv)
|
|||||||
vstream_fprintf(client, "\n");
|
vstream_fprintf(client, "\n");
|
||||||
if ((qfile = mail_queue_open(qp->name, id, O_RDONLY, 0)) != 0) {
|
if ((qfile = mail_queue_open(qp->name, id, O_RDONLY, 0)) != 0) {
|
||||||
queue_size += st.st_size;
|
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))
|
if (vstream_fclose(qfile))
|
||||||
msg_warn("close file %s %s: %m", qp->name, id);
|
msg_warn("close file %s %s: %m", qp->name, id);
|
||||||
} else if (strcmp(qp->name, MAIL_QUEUE_MAILDROP) == 0) {
|
} else if (strcmp(qp->name, MAIL_QUEUE_MAILDROP) == 0) {
|
||||||
|
@ -21,10 +21,6 @@
|
|||||||
/* the destination host, sorts the list by preference, and connects
|
/* the destination host, sorts the list by preference, and connects
|
||||||
/* to each listed address until it finds a server that responds.
|
/* 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
|
/* Once the SMTP client has received the server greeting banner, no
|
||||||
/* error will cause it to proceed to the next address on the mail
|
/* error will cause it to proceed to the next address on the mail
|
||||||
/* exchanger list. Instead, the message is either bounced, or its
|
/* exchanger list. Instead, the message is either bounced, or its
|
||||||
@ -118,6 +114,9 @@
|
|||||||
/* Some SMTP servers misbehave on long lines.
|
/* Some SMTP servers misbehave on long lines.
|
||||||
/* .IP \fBsmtp_helo_name\fR
|
/* .IP \fBsmtp_helo_name\fR
|
||||||
/* The hostname to be used in HELO and EHLO commands.
|
/* 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
|
/* .IP \fBsmtp_skip_4xx_greeting\fR
|
||||||
/* Skip servers that greet us with a 4xx status code.
|
/* Skip servers that greet us with a 4xx status code.
|
||||||
/* .IP \fBsmtp_skip_5xx_greeting\fR
|
/* .IP \fBsmtp_skip_5xx_greeting\fR
|
||||||
@ -298,6 +297,7 @@ int var_smtp_pix_delay;
|
|||||||
int var_smtp_line_limit;
|
int var_smtp_line_limit;
|
||||||
char *var_smtp_helo_name;
|
char *var_smtp_helo_name;
|
||||||
char *var_smtp_host_lookup;
|
char *var_smtp_host_lookup;
|
||||||
|
int var_smtp_quote_821_env;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global variables. smtp_errno is set by the address lookup routines and by
|
* 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_NEVER_EHLO, DEF_SMTP_NEVER_EHLO, &var_smtp_never_ehlo,
|
||||||
VAR_SMTP_SASL_ENABLE, DEF_SMTP_SASL_ENABLE, &var_smtp_sasl_enable,
|
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_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,
|
0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -379,7 +379,7 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
* Macros for readability.
|
* Macros for readability.
|
||||||
*/
|
*/
|
||||||
#define REWRITE_ADDRESS(dst, mid, src) do { \
|
#define REWRITE_ADDRESS(dst, mid, src) do { \
|
||||||
if (*(src)) { \
|
if (*(src) && var_smtp_quote_821_env) { \
|
||||||
quote_821_local(mid, src); \
|
quote_821_local(mid, src); \
|
||||||
smtp_unalias_addr(dst, vstring_str(mid)); \
|
smtp_unalias_addr(dst, vstring_str(mid)); \
|
||||||
} else { \
|
} else { \
|
||||||
@ -388,7 +388,7 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define QUOTE_ADDRESS(dst, src) do { \
|
#define QUOTE_ADDRESS(dst, src) do { \
|
||||||
if (*(src)) { \
|
if (*(src) && var_smtp_quote_821_env) { \
|
||||||
quote_821_local(dst, src); \
|
quote_821_local(dst, src); \
|
||||||
} else { \
|
} else { \
|
||||||
vstring_strcpy(dst, src); \
|
vstring_strcpy(dst, src); \
|
||||||
@ -640,6 +640,7 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
if (resp->code == 552)
|
if (resp->code == 552)
|
||||||
resp->code = 452;
|
resp->code = 452;
|
||||||
#endif
|
#endif
|
||||||
|
rcpt = request->rcpt_list.info + recv_rcpt;
|
||||||
if (resp->code / 100 == 2) {
|
if (resp->code / 100 == 2) {
|
||||||
++nrcpt;
|
++nrcpt;
|
||||||
/* If trace-only, mark the recipient done. */
|
/* If trace-only, mark the recipient done. */
|
||||||
@ -654,7 +655,6 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
rcpt->offset = 0; /* in case deferred */
|
rcpt->offset = 0; /* in case deferred */
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rcpt = request->rcpt_list.info + recv_rcpt;
|
|
||||||
smtp_rcpt_fail(state, resp->code, rcpt,
|
smtp_rcpt_fail(state, resp->code, rcpt,
|
||||||
"host %s said: %s (in reply to %s)",
|
"host %s said: %s (in reply to %s)",
|
||||||
session->namaddr,
|
session->namaddr,
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
SHELL = /bin/sh
|
SHELL = /bin/sh
|
||||||
SRCS = smtpd.c smtpd_token.c smtpd_check.c smtpd_chat.c smtpd_state.c \
|
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 \
|
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 \
|
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
|
TESTSRC = smtpd_token_test.c
|
||||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||||
@ -154,6 +154,7 @@ smtpd.o: smtpd_check.h
|
|||||||
smtpd.o: smtpd_chat.h
|
smtpd.o: smtpd_chat.h
|
||||||
smtpd.o: smtpd_sasl_proto.h
|
smtpd.o: smtpd_sasl_proto.h
|
||||||
smtpd.o: smtpd_sasl_glue.h
|
smtpd.o: smtpd_sasl_glue.h
|
||||||
|
smtpd.o: smtpd_proxy.h
|
||||||
smtpd_chat.o: smtpd_chat.c
|
smtpd_chat.o: smtpd_chat.c
|
||||||
smtpd_chat.o: ../../include/sys_defs.h
|
smtpd_chat.o: ../../include/sys_defs.h
|
||||||
smtpd_chat.o: ../../include/msg.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/vstream.h
|
||||||
smtpd_peer.o: ../../include/argv.h
|
smtpd_peer.o: ../../include/argv.h
|
||||||
smtpd_peer.o: ../../include/mail_stream.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: smtpd_sasl_glue.c
|
||||||
smtpd_sasl_glue.o: ../../include/sys_defs.h
|
smtpd_sasl_glue.o: ../../include/sys_defs.h
|
||||||
smtpd_sasl_glue.o: ../../include/msg.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
|
/* Maps that specify the SASL login name that owns a MAIL FROM sender
|
||||||
/* address. Used by the \fBreject_sender_login_mismatch\fR sender
|
/* address. Used by the \fBreject_sender_login_mismatch\fR sender
|
||||||
/* anti-spoofing restriction.
|
/* 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
|
/* .SH Miscellaneous
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@ -245,6 +263,21 @@
|
|||||||
/* Restrict what domains this mail system will relay
|
/* Restrict what domains this mail system will relay
|
||||||
/* mail to. The domains are routed to the delivery agent
|
/* mail to. The domains are routed to the delivery agent
|
||||||
/* specified with the \fBrelay_transport\fR setting.
|
/* 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"
|
/* .SH "UCE control responses"
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@ -289,10 +322,11 @@
|
|||||||
/* .IP \fBunverified_recipient_reject_code\fR
|
/* .IP \fBunverified_recipient_reject_code\fR
|
||||||
/* Response code when a recipient address is known to be undeliverable.
|
/* Response code when a recipient address is known to be undeliverable.
|
||||||
/* SEE ALSO
|
/* SEE ALSO
|
||||||
/* trivial-rewrite(8) address resolver
|
|
||||||
/* cleanup(8) message canonicalization
|
/* cleanup(8) message canonicalization
|
||||||
/* master(8) process manager
|
/* master(8) process manager
|
||||||
/* syslogd(8) system logging
|
/* syslogd(8) system logging
|
||||||
|
/* trivial-rewrite(8) address resolver
|
||||||
|
/* verify(8) address verification service
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@ -368,12 +402,13 @@
|
|||||||
|
|
||||||
/* Application-specific */
|
/* Application-specific */
|
||||||
|
|
||||||
#include "smtpd_token.h"
|
#include <smtpd_token.h>
|
||||||
#include "smtpd.h"
|
#include <smtpd.h>
|
||||||
#include "smtpd_check.h"
|
#include <smtpd_check.h>
|
||||||
#include "smtpd_chat.h"
|
#include <smtpd_chat.h>
|
||||||
#include "smtpd_sasl_proto.h"
|
#include <smtpd_sasl_proto.h>
|
||||||
#include "smtpd_sasl_glue.h"
|
#include <smtpd_sasl_glue.h>
|
||||||
|
#include <smtpd_proxy.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tunable parameters. Make sure that there is some bound on the length of
|
* 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;
|
int var_relay_rcpt_code;
|
||||||
char *var_verp_clients;
|
char *var_verp_clients;
|
||||||
int var_show_unk_rcpt_table;
|
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.
|
* 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");
|
smtpd_chat_reply(state, "503 Error: send HELO/EHLO first");
|
||||||
return (-1);
|
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;
|
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||||
smtpd_chat_reply(state, "503 Error: nested MAIL command");
|
smtpd_chat_reply(state, "503 Error: nested MAIL command");
|
||||||
return (-1);
|
return (-1);
|
||||||
@ -840,6 +883,13 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
smtpd_chat_reply(state, "%s", err);
|
smtpd_chat_reply(state, "%s", err);
|
||||||
return (-1);
|
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) {
|
if ((err = smtpd_check_size(state, state->msg_size)) != 0) {
|
||||||
smtpd_chat_reply(state, "%s", err);
|
smtpd_chat_reply(state, "%s", err);
|
||||||
return (-1);
|
return (-1);
|
||||||
@ -884,6 +934,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
}
|
}
|
||||||
if (verp_delims)
|
if (verp_delims)
|
||||||
rec_fputs(state->cleanup, REC_TYPE_VERP, verp_delims);
|
rec_fputs(state->cleanup, REC_TYPE_VERP, verp_delims);
|
||||||
|
}
|
||||||
state->sender = mystrdup(argv[2].strval);
|
state->sender = mystrdup(argv[2].strval);
|
||||||
smtpd_chat_reply(state, "250 Ok");
|
smtpd_chat_reply(state, "250 Ok");
|
||||||
return (0);
|
return (0);
|
||||||
@ -918,6 +969,8 @@ static void mail_reset(SMTPD_STATE *state)
|
|||||||
smtpd_sasl_mail_reset(state);
|
smtpd_sasl_mail_reset(state);
|
||||||
#endif
|
#endif
|
||||||
state->discard = 0;
|
state->discard = 0;
|
||||||
|
if (state->proxy)
|
||||||
|
smtpd_proxy_close(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rcpt_cmd - process RCPT TO command */
|
/* 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
|
* command with a 501 response. So much for the principle of "be liberal
|
||||||
* in what you accept, be strict in what you send".
|
* 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;
|
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||||
smtpd_chat_reply(state, "503 Error: need MAIL command");
|
smtpd_chat_reply(state, "503 Error: need MAIL command");
|
||||||
return (-1);
|
return (-1);
|
||||||
@ -977,6 +1030,11 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
return (-1);
|
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.
|
* Store the recipient. Remember the first one.
|
||||||
@ -984,6 +1042,7 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
state->rcpt_count++;
|
state->rcpt_count++;
|
||||||
if (state->recipient == 0)
|
if (state->recipient == 0)
|
||||||
state->recipient = mystrdup(argv[2].strval);
|
state->recipient = mystrdup(argv[2].strval);
|
||||||
|
if (state->cleanup)
|
||||||
rec_fputs(state->cleanup, REC_TYPE_RCPT, argv[2].strval);
|
rec_fputs(state->cleanup, REC_TYPE_RCPT, argv[2].strval);
|
||||||
smtpd_chat_reply(state, "250 Ok");
|
smtpd_chat_reply(state, "250 Ok");
|
||||||
return (0);
|
return (0);
|
||||||
@ -1012,6 +1071,10 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
|||||||
int first = 1;
|
int first = 1;
|
||||||
VSTRING *why = 0;
|
VSTRING *why = 0;
|
||||||
int saved_err;
|
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
|
* 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.
|
* error.
|
||||||
*/
|
*/
|
||||||
if (state->rcpt_count == 0) {
|
if (state->rcpt_count == 0) {
|
||||||
if (state->cleanup == 0) {
|
if (!IN_MAIL_TRANSACTION(state)) {
|
||||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||||
smtpd_chat_reply(state, "503 Error: need RCPT command");
|
smtpd_chat_reply(state, "503 Error: need RCPT command");
|
||||||
} else {
|
} else {
|
||||||
@ -1036,35 +1099,61 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
|||||||
smtpd_chat_reply(state, "%s", err);
|
smtpd_chat_reply(state, "%s", err);
|
||||||
return (-1);
|
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
|
* Terminate the message envelope segment. Start the message content
|
||||||
* segment, and prepend our own Received: header. If there is only one
|
* segment, and prepend our own Received: header. If there is only one
|
||||||
* recipient, list the recipient address.
|
* recipient, list the recipient address.
|
||||||
*/
|
*/
|
||||||
|
if (state->cleanup)
|
||||||
rec_fputs(state->cleanup, REC_TYPE_MESG, "");
|
rec_fputs(state->cleanup, REC_TYPE_MESG, "");
|
||||||
rec_fprintf(state->cleanup, REC_TYPE_NORM,
|
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||||
"Received: from %s (%s [%s])",
|
"Received: from %s (%s [%s])",
|
||||||
state->helo_name ? state->helo_name : state->name,
|
state->helo_name ? state->helo_name : state->name,
|
||||||
state->name, state->addr);
|
state->name, state->addr);
|
||||||
if (state->rcpt_count == 1 && state->recipient) {
|
if (state->rcpt_count == 1 && state->recipient) {
|
||||||
rec_fprintf(state->cleanup, REC_TYPE_NORM,
|
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||||
"\tby %s (%s) with %s id %s",
|
state->cleanup ? "\tby %s (%s) with %s id %s" :
|
||||||
|
"\tby %s (%s) with %s",
|
||||||
var_myhostname, var_mail_name,
|
var_myhostname, var_mail_name,
|
||||||
state->protocol, state->queue_id);
|
state->protocol, state->queue_id);
|
||||||
quote_822_local(state->buffer, state->recipient);
|
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));
|
"\tfor <%s>; %s", STR(state->buffer), mail_date(state->time));
|
||||||
} else {
|
} else {
|
||||||
rec_fprintf(state->cleanup, REC_TYPE_NORM,
|
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||||
"\tby %s (%s) with %s",
|
state->cleanup ? "\tby %s (%s) with %s id %s;" :
|
||||||
var_myhostname, var_mail_name, state->protocol);
|
"\tby %s (%s) with %s;",
|
||||||
rec_fprintf(state->cleanup, REC_TYPE_NORM,
|
var_myhostname, var_mail_name,
|
||||||
"\tid %s; %s", state->queue_id, mail_date(state->time));
|
state->protocol, state->queue_id);
|
||||||
|
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||||
|
"\t%s", mail_date(state->time));
|
||||||
}
|
}
|
||||||
#ifdef RECEIVED_ENVELOPE_FROM
|
#ifdef RECEIVED_ENVELOPE_FROM
|
||||||
quote_822_local(state->buffer, state->sender);
|
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));
|
"\t(envelope-from %s)", STR(state->buffer));
|
||||||
#endif
|
#endif
|
||||||
smtpd_chat_reply(state, "354 End data with <CR><LF>.<CR><LF>");
|
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
|
* XXX Deal with UNIX-style From_ lines at the start of message content
|
||||||
* because sendmail permits it.
|
* 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) {
|
for (prev_rec_type = 0; /* void */ ; prev_rec_type = curr_rec_type) {
|
||||||
if (smtp_get(state->buffer, state->client, var_line_limit) == '\n')
|
if (smtp_get(state->buffer, state->client, var_line_limit) == '\n')
|
||||||
curr_rec_type = REC_TYPE_NORM;
|
curr_rec_type = REC_TYPE_NORM;
|
||||||
@ -1093,25 +1179,30 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
|||||||
len = VSTRING_LEN(state->buffer);
|
len = VSTRING_LEN(state->buffer);
|
||||||
if (first) {
|
if (first) {
|
||||||
if (strncmp(start + strspn(start, ">"), "From ", 5) == 0) {
|
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);
|
"X-Mailbox-Line: %s", start);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
first = 0;
|
first = 0;
|
||||||
if (len > 0 && IS_SPACE_TAB(start[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
|
if (prev_rec_type != REC_TYPE_CONT && *start == '.'
|
||||||
&& *start == '.' && (++start, --len) == 0)
|
&& (state->proxy == 0 ? (++start, --len) == 0 : len == 1))
|
||||||
break;
|
break;
|
||||||
if (state->err == CLEANUP_STAT_OK
|
if (state->err == CLEANUP_STAT_OK
|
||||||
&& rec_put(state->cleanup, curr_rec_type, start, len) < 0)
|
&& out_record(out_stream, curr_rec_type, start, len) < 0)
|
||||||
state->err = CLEANUP_STAT_WRITE;
|
state->err = out_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send the end-of-segment markers.
|
* Send the end-of-segment markers.
|
||||||
*/
|
*/
|
||||||
|
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 (state->err == CLEANUP_STAT_OK)
|
||||||
if (rec_fputs(state->cleanup, REC_TYPE_XTRA, "") < 0
|
if (rec_fputs(state->cleanup, REC_TYPE_XTRA, "") < 0
|
||||||
|| rec_fputs(state->cleanup, REC_TYPE_END, "") < 0
|
|| rec_fputs(state->cleanup, REC_TYPE_END, "") < 0
|
||||||
@ -1127,6 +1218,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
|||||||
mail_stream_cleanup(state->dest);
|
mail_stream_cleanup(state->dest);
|
||||||
state->dest = 0;
|
state->dest = 0;
|
||||||
state->cleanup = 0;
|
state->cleanup = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle any errors. One message may suffer from multiple errors, so
|
* 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_count = 0;
|
||||||
state->error_mask = 0;
|
state->error_mask = 0;
|
||||||
state->junk_cmds = 0;
|
state->junk_cmds = 0;
|
||||||
|
if (state->queue_id)
|
||||||
smtpd_chat_reply(state, "250 Ok: queued as %s", 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) {
|
} else if ((state->err & CLEANUP_STAT_BAD) != 0) {
|
||||||
state->error_mask |= MAIL_ERROR_SOFTWARE;
|
state->error_mask |= MAIL_ERROR_SOFTWARE;
|
||||||
smtpd_chat_reply(state, "451 Error: internal error %d", state->err);
|
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) {
|
} else if ((state->err & CLEANUP_STAT_WRITE) != 0) {
|
||||||
state->error_mask |= MAIL_ERROR_RESOURCE;
|
state->error_mask |= MAIL_ERROR_RESOURCE;
|
||||||
smtpd_chat_reply(state, "451 Error: queue file write error");
|
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 {
|
} else {
|
||||||
state->error_mask |= MAIL_ERROR_SOFTWARE;
|
state->error_mask |= MAIL_ERROR_SOFTWARE;
|
||||||
smtpd_chat_reply(state, "451 Error: internal error %d", state->err);
|
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");
|
smtpd_chat_reply(state, "503 Error: send HELO/EHLO first");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
if (state->cleanup != 0) {
|
if (IN_MAIL_TRANSACTION(state)) {
|
||||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||||
smtpd_chat_reply(state, "503 Error: MAIL transaction in progress");
|
smtpd_chat_reply(state, "503 Error: MAIL transaction in progress");
|
||||||
return (-1);
|
return (-1);
|
||||||
@ -1409,7 +1507,7 @@ typedef struct SMTPD_CMD {
|
|||||||
} SMTPD_CMD;
|
} SMTPD_CMD;
|
||||||
|
|
||||||
#define SMTPD_CMD_FLAG_LIMIT (1<<0) /* limit usage */
|
#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[] = {
|
static SMTPD_CMD smtpd_cmd_table[] = {
|
||||||
"HELO", helo_cmd, SMTPD_CMD_FLAG_LIMIT,
|
"HELO", helo_cmd, SMTPD_CMD_FLAG_LIMIT,
|
||||||
@ -1427,11 +1525,13 @@ static SMTPD_CMD smtpd_cmd_table[] = {
|
|||||||
"VRFY", vrfy_cmd, SMTPD_CMD_FLAG_LIMIT,
|
"VRFY", vrfy_cmd, SMTPD_CMD_FLAG_LIMIT,
|
||||||
"ETRN", etrn_cmd, SMTPD_CMD_FLAG_LIMIT,
|
"ETRN", etrn_cmd, SMTPD_CMD_FLAG_LIMIT,
|
||||||
"QUIT", quit_cmd, 0,
|
"QUIT", quit_cmd, 0,
|
||||||
"Received:", 0, SMTPD_CMD_FLAG_HEADER,
|
"Received:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
|
||||||
"Reply-To:", 0, SMTPD_CMD_FLAG_HEADER,
|
"Reply-To:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
|
||||||
"Message-ID:", 0, SMTPD_CMD_FLAG_HEADER,
|
"Message-ID:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
|
||||||
"Subject:", 0, SMTPD_CMD_FLAG_HEADER,
|
"Subject:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
|
||||||
"From:", 0, SMTPD_CMD_FLAG_HEADER,
|
"From:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
|
||||||
|
"CONNECT", 0, SMTPD_CMD_FLAG_FORBIDDEN,
|
||||||
|
"User-Agent:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1521,8 +1621,8 @@ static void smtpd_proto(SMTPD_STATE *state)
|
|||||||
state->error_count++;
|
state->error_count++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (cmdp->flags & SMTPD_CMD_FLAG_HEADER) {
|
if (cmdp->flags & SMTPD_CMD_FLAG_FORBIDDEN) {
|
||||||
msg_warn("%s sent %s header instead of SMTP command: %.100s",
|
msg_warn("%s sent %s instead of SMTP command: %.100s",
|
||||||
state->namaddr, cmdp->name, vstring_str(state->buffer));
|
state->namaddr, cmdp->name, vstring_str(state->buffer));
|
||||||
smtpd_chat_reply(state, "221 Error: I can break rules, too. Goodbye.");
|
smtpd_chat_reply(state, "221 Error: I can break rules, too. Goodbye.");
|
||||||
break;
|
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_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_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_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,
|
0,
|
||||||
};
|
};
|
||||||
static CONFIG_TIME_TABLE time_table[] = {
|
static CONFIG_TIME_TABLE time_table[] = {
|
||||||
VAR_SMTPD_TMOUT, DEF_SMTPD_TMOUT, &var_smtpd_tmout, 1, 0,
|
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_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,
|
0,
|
||||||
};
|
};
|
||||||
static CONFIG_BOOL_TABLE bool_table[] = {
|
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_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_VERIFY_SENDER, DEF_VERIFY_SENDER, &var_verify_sender, 0, 0,
|
||||||
VAR_VERP_CLIENTS, DEF_VERP_CLIENTS, &var_verp_clients, 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,
|
0,
|
||||||
};
|
};
|
||||||
static CONFIG_RAW_TABLE raw_table[] = {
|
static CONFIG_RAW_TABLE raw_table[] = {
|
||||||
|
@ -95,6 +95,8 @@ typedef struct SMTPD_STATE {
|
|||||||
int defer_if_permit_sender; /* force permit into warning */
|
int defer_if_permit_sender; /* force permit into warning */
|
||||||
int discard; /* discard message */
|
int discard; /* discard message */
|
||||||
VSTRING *expand_buf; /* scratch space for $name expansion */
|
VSTRING *expand_buf; /* scratch space for $name expansion */
|
||||||
|
VSTREAM *proxy; /* proxy handle */
|
||||||
|
VSTRING *proxy_buffer; /* proxy query/reply buffer */
|
||||||
} SMTPD_STATE;
|
} SMTPD_STATE;
|
||||||
|
|
||||||
extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
|
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) {
|
if (once == 0) {
|
||||||
once = 1;
|
once = 1;
|
||||||
msg_warn("the \"%s\" restriction is going away; use \"%s\" instead",
|
msg_warn("support for restriction \"%s\" will be removed from %s; "
|
||||||
CHECK_RELAY_DOMAINS, REJECT_UNAUTH_DEST);
|
"use \"%s\" instead",
|
||||||
|
CHECK_RELAY_DOMAINS, var_mail_name, REJECT_UNAUTH_DEST);
|
||||||
}
|
}
|
||||||
#endif
|
#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.
|
* 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);
|
verify_status = verify_clnt_query(addr, &rcpt_status, why);
|
||||||
if (verify_status != VRFY_STAT_OK || rcpt_status != DEL_RCPT_STAT_TODO)
|
if (verify_status != VRFY_STAT_OK || rcpt_status != DEL_RCPT_STAT_TODO)
|
||||||
break;
|
break;
|
||||||
if (count >= 2)
|
if (++count >= var_verify_poll_count)
|
||||||
break;
|
break;
|
||||||
sleep(3);
|
sleep(var_verify_poll_delay);
|
||||||
}
|
}
|
||||||
if (verify_status != VRFY_STAT_OK) {
|
if (verify_status != VRFY_STAT_OK) {
|
||||||
msg_warn("%s service failure", var_verify_service);
|
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",
|
"450 <%s>: %s rejected: address verification problem",
|
||||||
reply_name, reply_class);
|
reply_name, reply_class);
|
||||||
rqst_status = SMTPD_CHECK_DUNNO;
|
rqst_status = SMTPD_CHECK_DUNNO;
|
||||||
@ -2589,8 +2590,9 @@ static int reject_maps_rbl(SMTPD_STATE *state)
|
|||||||
|
|
||||||
if (warned == 0) {
|
if (warned == 0) {
|
||||||
warned++;
|
warned++;
|
||||||
msg_warn("restriction %s is going away. Please use %s <domain> instead",
|
msg_warn("support for restriction \"%s\" will be removed from %s; "
|
||||||
REJECT_MAPS_RBL, REJECT_RBL_CLIENT);
|
"use \"%s <domain-name>\" instead",
|
||||||
|
REJECT_MAPS_RBL, var_mail_name, REJECT_RBL_CLIENT);
|
||||||
}
|
}
|
||||||
while ((rbl_domain = mystrtok(&bp, " \t\r\n,")) != 0) {
|
while ((rbl_domain = mystrtok(&bp, " \t\r\n,")) != 0) {
|
||||||
result = reject_rbl_addr(state, rbl_domain, state->addr,
|
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++;
|
int saved_recursion = state->recursion++;
|
||||||
|
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: START", myname);
|
msg_info(">>> START %s RESTRICTIONS <<<", reply_class);
|
||||||
|
|
||||||
for (cpp = restrictions->argv; (name = *cpp) != 0; cpp++) {
|
for (cpp = restrictions->argv; (name = *cpp) != 0; cpp++) {
|
||||||
|
|
||||||
@ -2980,7 +2982,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (msg_verbose && name == 0)
|
if (msg_verbose && name == 0)
|
||||||
msg_info("%s: END", myname);
|
msg_info(">>> END %s RESTRICTIONS <<<", reply_class);
|
||||||
|
|
||||||
state->recursion = saved_recursion;
|
state->recursion = saved_recursion;
|
||||||
|
|
||||||
@ -3296,6 +3298,9 @@ static int check_rcpt_maps(SMTPD_STATE *state, const char *recipient)
|
|||||||
return (0);
|
return (0);
|
||||||
state->rcptmap_checked = 1;
|
state->rcptmap_checked = 1;
|
||||||
|
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info(">>> CHECKING RECIPIENT MAPS <<<");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Resolve the address.
|
* Resolve the address.
|
||||||
*/
|
*/
|
||||||
@ -3653,6 +3658,8 @@ int var_relay_rcpt_code;
|
|||||||
int var_virt_mailbox_code;
|
int var_virt_mailbox_code;
|
||||||
int var_virt_alias_code;
|
int var_virt_alias_code;
|
||||||
int var_show_unk_rcpt_table;
|
int var_show_unk_rcpt_table;
|
||||||
|
int var_verify_poll_count;
|
||||||
|
int var_verify_poll_delay;
|
||||||
|
|
||||||
static INT_TABLE int_table[] = {
|
static INT_TABLE int_table[] = {
|
||||||
"msg_verbose", 0, &msg_verbose,
|
"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_ALIAS_CODE, DEF_VIRT_ALIAS_CODE, &var_virt_alias_code,
|
||||||
VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_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_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,
|
0,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3803,6 +3812,14 @@ int permit_sasl_auth(SMTPD_STATE *state, int ifyes, int ifnot)
|
|||||||
|
|
||||||
#endif
|
#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 */
|
/* canon_addr_internal - stub */
|
||||||
|
|
||||||
VSTRING *canon_addr_internal(VSTRING *result, const char *addr)
|
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 */
|
/* 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;
|
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->defer_if_permit.reason = 0;
|
||||||
state->discard = 0;
|
state->discard = 0;
|
||||||
state->expand_buf = 0;
|
state->expand_buf = 0;
|
||||||
|
state->proxy = 0;
|
||||||
|
state->proxy_buffer = 0;
|
||||||
|
|
||||||
#ifdef USE_SASL_AUTH
|
#ifdef USE_SASL_AUTH
|
||||||
if (SMTPD_STAND_ALONE(state))
|
if (SMTPD_STAND_ALONE(state))
|
||||||
@ -137,6 +139,8 @@ void smtpd_state_reset(SMTPD_STATE *state)
|
|||||||
vstring_free(state->defer_if_reject.reason);
|
vstring_free(state->defer_if_reject.reason);
|
||||||
if (state->expand_buf)
|
if (state->expand_buf)
|
||||||
vstring_free(state->expand_buf);
|
vstring_free(state->expand_buf);
|
||||||
|
if (state->proxy_buffer)
|
||||||
|
vstring_free(state->proxy_buffer);
|
||||||
|
|
||||||
#ifdef USE_SASL_AUTH
|
#ifdef USE_SASL_AUTH
|
||||||
if (var_smtpd_sasl_enable)
|
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 \
|
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 \
|
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.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_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 \
|
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 \
|
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 \
|
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 \
|
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.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_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 \
|
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 \
|
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)
|
write_buf.o write_wait.o $(STRCASE)
|
||||||
HDRS = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
|
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 \
|
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_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 \
|
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 \
|
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 \
|
tests: valid_hostname_test mac_expand_test dict_test unescape_test \
|
||||||
hex_quote_test ctable_test inet_addr_list_test base64_code_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_test: valid_hostname valid_hostname.in valid_hostname.ref
|
||||||
./valid_hostname <valid_hostname.in 2>valid_hostname.tmp
|
./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
|
diff dict_regexp.ref dict_regexp.tmp
|
||||||
rm -f 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_test: host_port host_port.in host_port.ref
|
||||||
./host_port <host_port.in >host_port.tmp 2>&1
|
./host_port <host_port.in >host_port.tmp 2>&1
|
||||||
diff host_port.ref host_port.tmp
|
diff host_port.ref host_port.tmp
|
||||||
@ -529,6 +535,19 @@ dict_alloc.o: dict.h
|
|||||||
dict_alloc.o: vstream.h
|
dict_alloc.o: vstream.h
|
||||||
dict_alloc.o: vbuf.h
|
dict_alloc.o: vbuf.h
|
||||||
dict_alloc.o: argv.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: dict_db.c
|
||||||
dict_db.o: sys_defs.h
|
dict_db.o: sys_defs.h
|
||||||
dict_db.o: msg.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_pcre.h
|
||||||
dict_open.o: dict_regexp.h
|
dict_open.o: dict_regexp.h
|
||||||
dict_open.o: dict_static.h
|
dict_open.o: dict_static.h
|
||||||
|
dict_open.o: dict_cidr.h
|
||||||
dict_open.o: stringops.h
|
dict_open.o: stringops.h
|
||||||
dict_open.o: vstring.h
|
dict_open.o: vstring.h
|
||||||
dict_open.o: split_at.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 ...
|
/* If you must bind to the server, do it with this distinguished name ...
|
||||||
/* .IP \fIldapsource_\fRbind_pw
|
/* .IP \fIldapsource_\fRbind_pw
|
||||||
/* \&... and this password.
|
/* \&... and this password.
|
||||||
/* .IP \fIldapsource_\fRcache
|
/* .IP \fIldapsource_\fRcache (no longer supported)
|
||||||
/* Whether or not to turn on client-side caching.
|
/* 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.
|
/* 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.
|
/* 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
|
/* .IP \fIldapsource_\fRdereference
|
||||||
/* How to handle LDAP aliases. See ldap.h or ldap_open(3) man page.
|
/* How to handle LDAP aliases. See ldap.h or ldap_open(3) man page.
|
||||||
/* .IP \fIldapsource_\fRdebuglevel
|
/* .IP \fIldapsource_\fRdebuglevel
|
||||||
@ -152,10 +167,10 @@ typedef struct {
|
|||||||
char *bind_dn;
|
char *bind_dn;
|
||||||
char *bind_pw;
|
char *bind_pw;
|
||||||
int timeout;
|
int timeout;
|
||||||
int cache;
|
|
||||||
long cache_expiry;
|
|
||||||
long cache_size;
|
|
||||||
int dereference;
|
int dereference;
|
||||||
|
long recursion_limit;
|
||||||
|
long expansion_limit;
|
||||||
|
long size_limit;
|
||||||
int chase_referrals;
|
int chase_referrals;
|
||||||
int debuglevel;
|
int debuglevel;
|
||||||
int version;
|
int version;
|
||||||
@ -231,11 +246,6 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
|
|||||||
char *myname = "dict_ldap_connect";
|
char *myname = "dict_ldap_connect";
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
#ifdef LDAP_API_FEATURE_X_MEMCACHE
|
|
||||||
LDAPMemCache *dircache;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef LDAP_OPT_NETWORK_TIMEOUT
|
#ifdef LDAP_OPT_NETWORK_TIMEOUT
|
||||||
struct timeval mytimeval;
|
struct timeval mytimeval;
|
||||||
|
|
||||||
@ -313,6 +323,16 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
* Configure alias dereferencing for this connection. Thanks to Mike
|
||||||
* Mattice for this, and to Hery Rakotoarisoa for the v3 update.
|
* 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 ",
|
msg_info("%s: Successful bind to server %s as %s ",
|
||||||
myname, dict_ldap->server_host, dict_ldap->bind_dn);
|
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)
|
if (msg_verbose)
|
||||||
msg_info("%s: Cached connection handle for LDAP source %s",
|
msg_info("%s: Cached connection handle for LDAP source %s",
|
||||||
myname, dict_ldap->ldapsource);
|
myname, dict_ldap->ldapsource);
|
||||||
@ -426,7 +400,8 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
|
|||||||
/*
|
/*
|
||||||
* expand a filter (lookup or result)
|
* 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 *myname = "dict_ldap_expand_filter";
|
||||||
char *sub,
|
char *sub,
|
||||||
@ -461,9 +436,8 @@ static void dict_ldap_expand_filter(char *filter, char *value, VSTRING *out)
|
|||||||
vstring_strcat(out, u);
|
vstring_strcat(out, u);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
msg_warn
|
msg_warn("%s: %s: Invalid filter substitution format '%%%c'!",
|
||||||
("%s: Invalid filter substitution format '%%%c'!",
|
myname, ldapsource, *(sub + 1));
|
||||||
myname, *(sub + 1));
|
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case 's':
|
case 's':
|
||||||
vstring_strcat(out, u);
|
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,
|
static void dict_ldap_get_values(DICT_LDAP *dict_ldap, LDAPMessage * res,
|
||||||
VSTRING *result)
|
VSTRING *result)
|
||||||
{
|
{
|
||||||
|
static int recursion = 0;
|
||||||
|
static int expansion;
|
||||||
|
long entries = 0;
|
||||||
long i = 0;
|
long i = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
LDAPMessage *resloop = 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_sec = dict_ldap->timeout;
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
if (++recursion == 1)
|
||||||
|
expansion = 0;
|
||||||
|
|
||||||
if (msg_verbose)
|
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));
|
ldap_count_entries(dict_ldap->ld, res));
|
||||||
|
|
||||||
for (entry = ldap_first_entry(dict_ldap->ld, res); entry != NULL;
|
for (entry = ldap_first_entry(dict_ldap->ld, res); entry != NULL;
|
||||||
entry = ldap_next_entry(dict_ldap->ld, entry)) {
|
entry = ldap_next_entry(dict_ldap->ld, entry)) {
|
||||||
ber = NULL;
|
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);
|
for (attr = ldap_first_attribute(dict_ldap->ld, entry, &ber);
|
||||||
attr != NULL;
|
attr != NULL;
|
||||||
ldap_memfree(attr), attr = ldap_next_attribute(dict_ldap->ld,
|
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);
|
vals = ldap_get_values(dict_ldap->ld, entry, attr);
|
||||||
if (vals == NULL) {
|
if (vals == NULL) {
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: Entry doesn't have any values for %s",
|
msg_info("%s[%d]: Entry doesn't have any values for %s",
|
||||||
myname, attr);
|
myname, recursion, attr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (i = 0; dict_ldap->result_attributes->argv[i]; i++) {
|
|
||||||
if (strcasecmp(dict_ldap->result_attributes->argv[i],
|
/*
|
||||||
attr) == 0) {
|
* If we previously encountered an error, we still continue
|
||||||
if (msg_verbose)
|
* through the loop, to avoid memory leaks, but we don't waste
|
||||||
msg_info("%s: search returned %ld value(s) for requested result attribute %s", myname, i, attr);
|
* time accumulating any further results.
|
||||||
break;
|
*
|
||||||
|
* 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)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -532,21 +544,39 @@ static void dict_ldap_get_values(DICT_LDAP *dict_ldap, LDAPMessage * res,
|
|||||||
* recursing (for dn or url attributes).
|
* recursing (for dn or url attributes).
|
||||||
*/
|
*/
|
||||||
if (i < dict_ldap->num_attributes) {
|
if (i < dict_ldap->num_attributes) {
|
||||||
|
/* Ordinary result attribute */
|
||||||
for (i = 0; vals[i] != NULL; i++) {
|
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)
|
if (VSTRING_LEN(result) > 0)
|
||||||
vstring_strcat(result, ",");
|
vstring_strcat(result, ",");
|
||||||
if (dict_ldap->result_filter == NULL)
|
if (dict_ldap->result_filter == NULL)
|
||||||
vstring_strcat(result, vals[i]);
|
vstring_strcat(result, vals[i]);
|
||||||
else
|
else
|
||||||
dict_ldap_expand_filter(dict_ldap->result_filter,
|
dict_ldap_expand_filter(dict_ldap->ldapsource,
|
||||||
|
dict_ldap->result_filter,
|
||||||
vals[i], result);
|
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++) {
|
for (i = 0; vals[i] != NULL; i++) {
|
||||||
if (ldap_is_ldap_url(vals[i])) {
|
if (ldap_is_ldap_url(vals[i])) {
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: looking up URL %s", myname,
|
msg_info("%s[%d]: looking up URL %s", myname,
|
||||||
vals[i]);
|
recursion, vals[i]);
|
||||||
rc = ldap_url_parse(vals[i], &url);
|
rc = ldap_url_parse(vals[i], &url);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
rc = ldap_search_st(dict_ldap->ld, url->lud_dn,
|
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 {
|
} else {
|
||||||
if (msg_verbose)
|
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],
|
rc = ldap_search_st(dict_ldap->ld, vals[i],
|
||||||
LDAP_SCOPE_BASE, "objectclass=*",
|
LDAP_SCOPE_BASE, "objectclass=*",
|
||||||
dict_ldap->result_attributes->argv,
|
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
|
* Go ahead and treat this as though the DN existed
|
||||||
* and just didn't have any result attributes.
|
* and just didn't have any result attributes.
|
||||||
*/
|
*/
|
||||||
msg_warn("%s: DN %s not found, skipping ", myname,
|
msg_warn("%s[%d]: DN %s not found, skipping ", myname,
|
||||||
vals[i]);
|
recursion, vals[i]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
msg_warn("%s: search error %d: %s ", myname, rc,
|
msg_warn("%s[%d]: search error %d: %s ", myname,
|
||||||
ldap_err2string(rc));
|
recursion, rc, ldap_err2string(rc));
|
||||||
dict_errno = DICT_ERR_RETRY;
|
dict_errno = DICT_ERR_RETRY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resloop != 0)
|
if (resloop != 0)
|
||||||
ldap_msgfree(resloop);
|
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);
|
ldap_value_free(vals);
|
||||||
}
|
}
|
||||||
if (ber)
|
if (ber)
|
||||||
ber_free(ber, 0);
|
ber_free(ber, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg_verbose)
|
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 */
|
/* 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.
|
* No, log the fact and continue.
|
||||||
*/
|
*/
|
||||||
msg_warn("%s: Fixed query_filter %s is probably useless", myname,
|
msg_warn("%s: %s: Fixed query_filter %s is probably useless",
|
||||||
dict_ldap->query_filter);
|
myname, dict_ldap->ldapsource, dict_ldap->query_filter);
|
||||||
vstring_strcpy(filter_buf, dict_ldap->query_filter);
|
vstring_strcpy(filter_buf, dict_ldap->query_filter);
|
||||||
} else {
|
} 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);
|
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 *domainlist;
|
||||||
char *scope;
|
char *scope;
|
||||||
char *attr;
|
char *attr;
|
||||||
|
int tmp;
|
||||||
|
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: Using LDAP source %s", myname, ldapsource);
|
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
|
* get configured value of "ldapsource_cache"; default to false
|
||||||
*/
|
*/
|
||||||
vstring_sprintf(config_param, "%s_cache", ldapsource);
|
vstring_sprintf(config_param, "%s_cache", ldapsource);
|
||||||
dict_ldap->cache = get_mail_conf_bool(vstring_str(config_param), 0);
|
tmp = get_mail_conf_bool(vstring_str(config_param), 0);
|
||||||
if (msg_verbose)
|
if (tmp)
|
||||||
msg_info("%s: %s is %d", myname, vstring_str(config_param),
|
msg_warn("%s: ignoring %s", myname, vstring_str(config_param));
|
||||||
dict_ldap->cache);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get configured value of "ldapsource_cache_expiry"; default to 30
|
* get configured value of "ldapsource_cache_expiry"; default to 30
|
||||||
* seconds
|
* seconds
|
||||||
*/
|
*/
|
||||||
vstring_sprintf(config_param, "%s_cache_expiry", ldapsource);
|
vstring_sprintf(config_param, "%s_cache_expiry", ldapsource);
|
||||||
dict_ldap->cache_expiry = get_mail_conf_int(vstring_str(config_param),
|
tmp = get_mail_conf_int(vstring_str(config_param), -1, 0, 0);
|
||||||
30, 0, 0);
|
if (tmp >= 0)
|
||||||
if (msg_verbose)
|
msg_warn("%s: ignoring %s", myname, vstring_str(config_param));
|
||||||
msg_info("%s: %s is %ld", myname, vstring_str(config_param),
|
|
||||||
dict_ldap->cache_expiry);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get configured value of "ldapsource_cache_size"; default to 32k
|
* get configured value of "ldapsource_cache_size"; default to 32k
|
||||||
*/
|
*/
|
||||||
vstring_sprintf(config_param, "%s_cache_size", ldapsource);
|
vstring_sprintf(config_param, "%s_cache_size", ldapsource);
|
||||||
dict_ldap->cache_size = get_mail_conf_int(vstring_str(config_param),
|
tmp = get_mail_conf_int(vstring_str(config_param), -1, 0, 0);
|
||||||
32768, 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)
|
if (msg_verbose)
|
||||||
msg_info("%s: %s is %ld", myname, vstring_str(config_param),
|
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.
|
* Alias dereferencing suggested by Mike Mattice.
|
||||||
|
@ -178,6 +178,7 @@
|
|||||||
#include <dict_pcre.h>
|
#include <dict_pcre.h>
|
||||||
#include <dict_regexp.h>
|
#include <dict_regexp.h>
|
||||||
#include <dict_static.h>
|
#include <dict_static.h>
|
||||||
|
#include <dict_cidr.h>
|
||||||
#include <stringops.h>
|
#include <stringops.h>
|
||||||
#include <split_at.h>
|
#include <split_at.h>
|
||||||
#include <htable.h>
|
#include <htable.h>
|
||||||
@ -193,9 +194,7 @@ typedef struct {
|
|||||||
static DICT_OPEN_INFO dict_open_info[] = {
|
static DICT_OPEN_INFO dict_open_info[] = {
|
||||||
DICT_TYPE_ENVIRON, dict_env_open,
|
DICT_TYPE_ENVIRON, dict_env_open,
|
||||||
DICT_TYPE_UNIX, dict_unix_open,
|
DICT_TYPE_UNIX, dict_unix_open,
|
||||||
#if 0
|
|
||||||
DICT_TYPE_TCP, dict_tcp_open,
|
DICT_TYPE_TCP, dict_tcp_open,
|
||||||
#endif
|
|
||||||
#ifdef HAS_DBM
|
#ifdef HAS_DBM
|
||||||
DICT_TYPE_DBM, dict_dbm_open,
|
DICT_TYPE_DBM, dict_dbm_open,
|
||||||
#endif
|
#endif
|
||||||
@ -228,6 +227,7 @@ static DICT_OPEN_INFO dict_open_info[] = {
|
|||||||
DICT_TYPE_REGEXP, dict_regexp_open,
|
DICT_TYPE_REGEXP, dict_regexp_open,
|
||||||
#endif
|
#endif
|
||||||
DICT_TYPE_STATIC, dict_static_open,
|
DICT_TYPE_STATIC, dict_static_open,
|
||||||
|
DICT_TYPE_CIDR, dict_cidr_open,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
char *regexp; /* regular expression */
|
char *regexp; /* regular expression */
|
||||||
int options; /* options */
|
int options; /* options */
|
||||||
|
int match; /* positive or negative match */
|
||||||
} DICT_PCRE_REGEXP;
|
} DICT_PCRE_REGEXP;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -95,12 +96,14 @@ typedef struct {
|
|||||||
pcre *pattern; /* compiled pattern */
|
pcre *pattern; /* compiled pattern */
|
||||||
pcre_extra *hints; /* hints to speed pattern execution */
|
pcre_extra *hints; /* hints to speed pattern execution */
|
||||||
char *replacement; /* replacement string */
|
char *replacement; /* replacement string */
|
||||||
|
int match; /* positive or negative match */
|
||||||
} DICT_PCRE_MATCH_RULE;
|
} DICT_PCRE_MATCH_RULE;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
DICT_PCRE_RULE rule; /* generic members */
|
DICT_PCRE_RULE rule; /* generic members */
|
||||||
pcre *pattern; /* compiled pattern */
|
pcre *pattern; /* compiled pattern */
|
||||||
pcre_extra *hints; /* hints to speed pattern execution */
|
pcre_extra *hints; /* hints to speed pattern execution */
|
||||||
|
int match; /* positive or negative match */
|
||||||
} DICT_PCRE_IF_RULE;
|
} DICT_PCRE_IF_RULE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -132,6 +135,7 @@ typedef struct {
|
|||||||
const char *mapname; /* name of regexp map */
|
const char *mapname; /* name of regexp map */
|
||||||
int lineno; /* where in file */
|
int lineno; /* where in file */
|
||||||
int flags; /* dict_flags */
|
int flags; /* dict_flags */
|
||||||
|
size_t max_sub; /* Largest $n seen */
|
||||||
} DICT_PCRE_PRESCAN_CONTEXT;
|
} DICT_PCRE_PRESCAN_CONTEXT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -251,13 +255,23 @@ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string)
|
|||||||
lookup_string, lookup_len,
|
lookup_string, lookup_len,
|
||||||
NULL_STARTOFFSET, NULL_EXEC_OPTIONS,
|
NULL_STARTOFFSET, NULL_EXEC_OPTIONS,
|
||||||
ctxt.offsets, PCRE_MAX_CAPTURE * 3);
|
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);
|
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.
|
* 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,
|
lookup_string, lookup_len,
|
||||||
NULL_STARTOFFSET, NULL_EXEC_OPTIONS,
|
NULL_STARTOFFSET, NULL_EXEC_OPTIONS,
|
||||||
ctxt.offsets, PCRE_MAX_CAPTURE * 3);
|
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);
|
dict_pcre_exec_error(dict->name, rule->lineno, ctxt.matches);
|
||||||
continue;
|
continue; /* pcre_exec failed */
|
||||||
}
|
}
|
||||||
nesting++;
|
nesting++;
|
||||||
continue;
|
continue;
|
||||||
@ -359,6 +379,25 @@ static int dict_pcre_get_pattern(const char *mapname, int lineno, char **bufp,
|
|||||||
char *p = *bufp;
|
char *p = *bufp;
|
||||||
char re_delimiter;
|
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++;
|
re_delimiter = *p++;
|
||||||
pattern->regexp = p;
|
pattern->regexp = p;
|
||||||
|
|
||||||
@ -437,7 +476,6 @@ static int dict_pcre_prescan(int type, VSTRING *buf, char *context)
|
|||||||
ctxt->mapname, ctxt->lineno);
|
ctxt->mapname, ctxt->lineno);
|
||||||
return (MAC_PARSE_ERROR);
|
return (MAC_PARSE_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!alldig(vstring_str(buf))) {
|
if (!alldig(vstring_str(buf))) {
|
||||||
msg_warn("pcre map %s, line %d: non-numeric replacement index \"%s\"",
|
msg_warn("pcre map %s, line %d: non-numeric replacement index \"%s\"",
|
||||||
ctxt->mapname, ctxt->lineno, vstring_str(buf));
|
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));
|
ctxt->mapname, ctxt->lineno, vstring_str(buf));
|
||||||
return (MAC_PARSE_ERROR);
|
return (MAC_PARSE_ERROR);
|
||||||
}
|
}
|
||||||
|
if (n > ctxt->max_sub)
|
||||||
|
ctxt->max_sub = n;
|
||||||
}
|
}
|
||||||
return (MAC_PARSE_OK);
|
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.mapname = mapname;
|
||||||
prescan_context.lineno = lineno;
|
prescan_context.lineno = lineno;
|
||||||
prescan_context.flags = dict_flags;
|
prescan_context.flags = dict_flags;
|
||||||
|
prescan_context.max_sub = 0;
|
||||||
|
|
||||||
if (mac_parse(p, dict_pcre_prescan, (char *) &prescan_context)
|
if (mac_parse(p, dict_pcre_prescan, (char *) &prescan_context)
|
||||||
& MAC_PARSE_ERROR) {
|
& MAC_PARSE_ERROR) {
|
||||||
@ -544,6 +585,15 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno,
|
|||||||
return (0);
|
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.
|
* 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 *)
|
match_rule = (DICT_PCRE_MATCH_RULE *)
|
||||||
dict_pcre_rule_alloc(DICT_PCRE_OP_MATCH, nesting, lineno,
|
dict_pcre_rule_alloc(DICT_PCRE_OP_MATCH, nesting, lineno,
|
||||||
sizeof(DICT_PCRE_MATCH_RULE));
|
sizeof(DICT_PCRE_MATCH_RULE));
|
||||||
|
match_rule->match = regexp.match;
|
||||||
match_rule->replacement = mystrdup(p);
|
match_rule->replacement = mystrdup(p);
|
||||||
match_rule->pattern = engine.pattern;
|
match_rule->pattern = engine.pattern;
|
||||||
match_rule->hints = engine.hints;
|
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.
|
* Warn about out-of-place text.
|
||||||
*/
|
*/
|
||||||
|
while (*p && ISSPACE(*p))
|
||||||
|
++p;
|
||||||
if (*p)
|
if (*p)
|
||||||
msg_warn("pcre map %s, line %d: ignoring extra text after IF",
|
msg_warn("pcre map %s, line %d: ignoring extra text after IF",
|
||||||
mapname, lineno);
|
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 *)
|
if_rule = (DICT_PCRE_IF_RULE *)
|
||||||
dict_pcre_rule_alloc(DICT_PCRE_OP_IF, nesting, lineno,
|
dict_pcre_rule_alloc(DICT_PCRE_OP_IF, nesting, lineno,
|
||||||
sizeof(DICT_PCRE_IF_RULE));
|
sizeof(DICT_PCRE_IF_RULE));
|
||||||
|
if_rule->match = regexp.match;
|
||||||
if_rule->pattern = engine.pattern;
|
if_rule->pattern = engine.pattern;
|
||||||
if_rule->hints = engine.hints;
|
if_rule->hints = engine.hints;
|
||||||
return ((DICT_PCRE_RULE *) if_rule);
|
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.
|
* Warn about out-of-place text.
|
||||||
*/
|
*/
|
||||||
|
while (*p && ISSPACE(*p))
|
||||||
|
++p;
|
||||||
if (*p)
|
if (*p)
|
||||||
msg_warn("pcre map %s, line %d: ignoring extra text after ENDIF",
|
msg_warn("pcre map %s, line %d: ignoring extra text after ENDIF",
|
||||||
mapname, lineno);
|
mapname, lineno);
|
||||||
|
@ -8,3 +8,7 @@ get c
|
|||||||
get d
|
get d
|
||||||
get 1234
|
get 1234
|
||||||
get 123
|
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)(5)/ ($1)($2)($3)($4)($5)
|
||||||
/(1)(2)(3)(4)/ ($1)($2)($3)($4)
|
/(1)(2)(3)(4)/ ($1)($2)($3)($4)
|
||||||
/(1)(2)(3)/ ($1)($2)($3)
|
/(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 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: 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: 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
|
true: not found
|
||||||
true1=1
|
true1=1
|
||||||
true2: not found
|
true2: not found
|
||||||
@ -12,3 +13,7 @@ c=
|
|||||||
d: not found
|
d: not found
|
||||||
1234=(1)(2)(3)(4)
|
1234=(1)(2)(3)(4)
|
||||||
123=(1)(2)(3)
|
123=(1)(2)(3)
|
||||||
|
bar/find: not found
|
||||||
|
bar/whynot=Don't have a liquor license
|
||||||
|
bar/elbereth=(elbereth)
|
||||||
|
say/elbereth: not found
|
||||||
|
@ -636,6 +636,8 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno,
|
|||||||
p++;
|
p++;
|
||||||
if (!dict_regexp_get_pat(mapname, lineno, &p, &pattern))
|
if (!dict_regexp_get_pat(mapname, lineno, &p, &pattern))
|
||||||
return (0);
|
return (0);
|
||||||
|
while (*p && ISSPACE(*p))
|
||||||
|
++p;
|
||||||
if (*p)
|
if (*p)
|
||||||
msg_warn("regexp map %s, line %d: ignoring extra text after IF",
|
msg_warn("regexp map %s, line %d: ignoring extra text after IF",
|
||||||
mapname, lineno);
|
mapname, lineno);
|
||||||
@ -661,6 +663,8 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno,
|
|||||||
mapname, lineno);
|
mapname, lineno);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
while (*p && ISSPACE(*p))
|
||||||
|
++p;
|
||||||
if (*p)
|
if (*p)
|
||||||
msg_warn("regexp map %s, line %d: ignoring extra text after ENDIF",
|
msg_warn("regexp map %s, line %d: ignoring extra text after ENDIF",
|
||||||
mapname, lineno);
|
mapname, lineno);
|
||||||
|
@ -11,3 +11,7 @@ get aa
|
|||||||
get 1235
|
get 1235
|
||||||
get 1234
|
get 1234
|
||||||
get 123
|
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)(5)/ ($1)($2)($3)($4)($5)
|
||||||
/(1)(2)(3)(4)/ ($1)($2)($3)($4)
|
/(1)(2)(3)(4)/ ($1)($2)($3)($4)
|
||||||
/(1)(2)(3)/ ($1)($2)($3)
|
/(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 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 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 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
|
true: not found
|
||||||
true1=1
|
true1=1
|
||||||
true2: not found
|
true2: not found
|
||||||
@ -15,3 +16,7 @@ aa=a!b
|
|||||||
1235=(1)(2)(3)
|
1235=(1)(2)(3)
|
||||||
1234=(1)(2)(3)(4)
|
1234=(1)(2)(3)(4)
|
||||||
123=(1)(2)(3)
|
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
|
/* ENCODING
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
/* In request and reply parameters, the character % and any non-printable
|
/* In request and reply parameters, the character % and any non-printing
|
||||||
/* characters (including whitespace) are replaced by %XX, XX being the
|
/* and whitespace characters must be replaced by %XX, XX being the
|
||||||
/* corresponding ASCII hexadecimal character value. The hexadecimal codes
|
/* corresponding ASCII hexadecimal character value. The hexadecimal codes
|
||||||
/* can be specified in any case (upper, lower, mixed).
|
/* can be specified in any case (upper, lower, mixed).
|
||||||
/* REQUEST FORMAT
|
/* REQUEST FORMAT
|
||||||
@ -43,7 +43,8 @@
|
|||||||
/* REPLY FORMAT
|
/* REPLY FORMAT
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .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"
|
/* .IP "500 SPACE optional-text NEWLINE"
|
||||||
/* In case of a lookup request, the requested data does not exist.
|
/* In case of a lookup request, the requested data does not exist.
|
||||||
/* In case of an update request, the request was rejected.
|
/* In case of an update request, the request was rejected.
|
||||||
@ -83,16 +84,16 @@
|
|||||||
|
|
||||||
/* Utility library. */
|
/* Utility library. */
|
||||||
|
|
||||||
#include "msg.h"
|
#include <msg.h>
|
||||||
#include "mymalloc.h"
|
#include <mymalloc.h>
|
||||||
#include "vstring.h"
|
#include <vstring.h>
|
||||||
#include "vstream.h"
|
#include <vstream.h>
|
||||||
#include "vstring_vstream.h"
|
#include <vstring_vstream.h>
|
||||||
#include "connect.h"
|
#include <connect.h>
|
||||||
#include "hex_quote.h"
|
#include <hex_quote.h>
|
||||||
#include "dict.h"
|
#include <dict.h>
|
||||||
#include "stringops.h"
|
#include <stringops.h>
|
||||||
#include "dict_tcp.h"
|
#include <dict_tcp.h>
|
||||||
|
|
||||||
/* Application-specific. */
|
/* Application-specific. */
|
||||||
|
|
||||||
@ -103,8 +104,9 @@ typedef struct {
|
|||||||
VSTREAM *fp; /* I/O stream */
|
VSTREAM *fp; /* I/O stream */
|
||||||
} DICT_TCP;
|
} DICT_TCP;
|
||||||
|
|
||||||
#define DICT_TCP_MAXTRY 10
|
#define DICT_TCP_MAXTRY 10 /* attempts before giving up */
|
||||||
#define DICT_TCP_TMOUT 100
|
#define DICT_TCP_TMOUT 100 /* connect/read/write timeout */
|
||||||
|
#define DICT_TCP_MAXLEN 4096 /* server reply size limit */
|
||||||
|
|
||||||
#define STR(x) vstring_str(x)
|
#define STR(x) vstring_str(x)
|
||||||
|
|
||||||
@ -115,10 +117,10 @@ static int dict_tcp_connect(DICT_TCP *dict_tcp)
|
|||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Connect to the server. Enforce a time limit on read/write operations
|
* Connect to the server. Enforce a time limit on all operations so that
|
||||||
* so that we do not get stuck.
|
* 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);
|
msg_warn("connect to TCP map %s: %m", dict_tcp->dict.name);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
@ -153,6 +155,7 @@ static const char *dict_tcp_lookup(DICT *dict, const char *key)
|
|||||||
char *myname = "dict_tcp_lookup";
|
char *myname = "dict_tcp_lookup";
|
||||||
int tries;
|
int tries;
|
||||||
char *start;
|
char *start;
|
||||||
|
int last_ch;
|
||||||
|
|
||||||
#define RETURN(errval, result) { dict_errno = errval; return (result); }
|
#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);
|
hex_quote(dict_tcp->hex_buf, key);
|
||||||
vstream_fprintf(dict_tcp->fp, "get %s\n", STR(dict_tcp->hex_buf));
|
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;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disconnect from the server if it can't talk to us.
|
* Disconnect from the server if it can't talk to us.
|
||||||
*/
|
*/
|
||||||
|
if (last_ch < 0)
|
||||||
msg_warn("read TCP map reply from %s: unexpected EOF (%m)",
|
msg_warn("read TCP map reply from %s: unexpected EOF (%m)",
|
||||||
dict_tcp->dict.name);
|
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);
|
dict_tcp_disconnect(dict_tcp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,6 +206,8 @@ static const char *dict_tcp_lookup(DICT *dict, const char *key)
|
|||||||
*/
|
*/
|
||||||
sleep(1);
|
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
|
* Check the general reply syntax. If the reply is malformed, disconnect
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
/* const char *hex;
|
/* const char *hex;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* hex_quote() takes a null-terminated string and replaces non-printable
|
/* 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
|
/* The hexadecimal codes are produced as upper-case characters. The result
|
||||||
/* value is the hex argument.
|
/* value is the hex argument.
|
||||||
/*
|
/*
|
||||||
@ -61,7 +62,7 @@ VSTRING *hex_quote(VSTRING *hex, const char *raw)
|
|||||||
|
|
||||||
VSTRING_RESET(hex);
|
VSTRING_RESET(hex);
|
||||||
for (cp = raw; (ch = *(unsigned const char *) cp) != 0; cp++) {
|
for (cp = raw; (ch = *(unsigned const char *) cp) != 0; cp++) {
|
||||||
if (ch != '%' && ISPRINT(ch)) {
|
if (ch != '%' && !ISSPACE(ch) && ISPRINT(ch)) {
|
||||||
VSTRING_ADDCH(hex, ch);
|
VSTRING_ADDCH(hex, ch);
|
||||||
} else {
|
} else {
|
||||||
vstring_sprintf_append(hex, "%%%02X", ch);
|
vstring_sprintf_append(hex, "%%%02X", ch);
|
||||||
|
@ -69,7 +69,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef INADDR_NONE
|
#ifndef INADDR_NONE
|
||||||
#define INADDR_NONE 0xffffff
|
#define INADDR_NONE 0xffffffff
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Utility library. */
|
/* 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
|
* Open an existing file or create a new one, carefully. When opening
|
||||||
* an existing file, we are prepared to deal with "no file" errors
|
* 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:
|
case O_CREAT:
|
||||||
if ((fp = safe_open_exist(path, flags, st, why)) == 0)
|
fp = safe_open_exist(path, flags, st, why);
|
||||||
if (errno == ENOENT)
|
if (fp == 0 && errno == ENOENT) {
|
||||||
fp = safe_open_create(path, flags, mode, st, user, group, why);
|
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);
|
return (fp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -234,7 +234,7 @@ int valid_hostliteral(const char *addr, int gripe)
|
|||||||
msg_warn("%s: unexpected text after ']': %.100s", myname, addr);
|
msg_warn("%s: unexpected text after ']': %.100s", myname, addr);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
if (last - addr >= sizeof(buf)) {
|
if (last >= addr + sizeof(buf)) {
|
||||||
if (gripe)
|
if (gripe)
|
||||||
msg_warn("%s: too much text: %.100s", myname, addr);
|
msg_warn("%s: too much text: %.100s", myname, addr);
|
||||||
return (0);
|
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