mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 05:38:06 +00:00
postfix-2.0.16-20031128
This commit is contained in:
parent
e0a1f54070
commit
196cfcd300
1
postfix/.indent.pro
vendored
1
postfix/.indent.pro
vendored
@ -153,6 +153,7 @@
|
||||
-TSMTPD_RBL_STATE
|
||||
-TSMTPD_STATE
|
||||
-TSMTPD_TOKEN
|
||||
-TSMTPD_XCLIENT_ATTR
|
||||
-TSMTP_ADDR
|
||||
-TSMTP_CMD
|
||||
-TSMTP_RESP
|
||||
|
@ -8755,6 +8755,39 @@ Apologies for any names omitted.
|
||||
controls periodic logging of maximal connection counts or
|
||||
rates. The default logging interval is 10 minutes.
|
||||
|
||||
Feature: "make makefiles WARN=stuff..." overrides the
|
||||
built-in GCC warning options that are used when "make" is
|
||||
invoked from within a source subdirectory. Files: makedefs,
|
||||
*/Makefile.in.
|
||||
|
||||
20031125
|
||||
|
||||
Feature: qmgr logs "queueid: deleted", just like postsuper,
|
||||
when it removes a message from the mail queue.
|
||||
|
||||
Performance: smtpd connects to the cleanup or proxy server
|
||||
AFTER the first valid RCPT TO command, instead of after
|
||||
the first valid MAIL FROM command. This avoid wasting
|
||||
real-time proxy filter resources when mail is stopped by
|
||||
the SMTP server's access blocks. File: smtpd/smtpd.c.
|
||||
|
||||
20031126
|
||||
|
||||
Bugfix: "panic: mymalloc: requested length 0" when master.cf
|
||||
specified an invalid host name or address. Postfix now
|
||||
logs more specific information. File: master/master_ent.c.
|
||||
Reported by several people.
|
||||
|
||||
20031125-8
|
||||
|
||||
Feature: XCLIENT support to override the SMTP server's
|
||||
client information for logging and/or access control. This
|
||||
replaces the short-lived XADDR and XLOGINFO extensions.
|
||||
Based on code by Victor Duchovni, with major simplifications.
|
||||
Files: smtpd/{smtpd,smtpd_check,smtpd_proxy,smtpd_xclient}.c
|
||||
smtp/smtp_smtp_proto.c, *qmgr/qmgr_message.c,
|
||||
global/deliver_request.c.
|
||||
|
||||
Open problems:
|
||||
|
||||
High: when virtual aliasing is turned off after content
|
||||
|
@ -9,7 +9,9 @@ normal mail, but are discarded instead of being deferred or bounced.
|
||||
|
||||
The same technique may be useful to block mail for undeliverable
|
||||
recipients, for example on mail relay hosts that do not have a copy
|
||||
of all the relayed recipient addresses.
|
||||
of all the relayed recipient addresses. This prevents undeliverable
|
||||
junk mail from entering the queue, so that Postfix doesn't have to
|
||||
waste resources trying to send mailer-daemon messages back.
|
||||
|
||||
With address verification turned on, normal mail will suffer only
|
||||
a short delay of up to 6 seconds while an address is verified for
|
||||
@ -95,6 +97,8 @@ specific domains that often appear in forged email.
|
||||
/etc/postfix/main.cf:
|
||||
smtpd_sender_restrictions = hash:/etc/postfix/sender_access
|
||||
unverified_sender_reject_code = 550
|
||||
# Be sure to read the "Caching" section below!
|
||||
address_verify_map = btree:/var/mta/verify
|
||||
|
||||
/etc/postfix/sender_access:
|
||||
aol.com reject_unverified_sender
|
||||
@ -120,6 +124,7 @@ To find out how sender address verification would affect your mail,
|
||||
specify "warn_if_reject reject_unverified_sender" so that you can
|
||||
see what mail would be blocked:
|
||||
|
||||
/etc/postfix/main.cf:
|
||||
smtpd_sender_restrictions =
|
||||
permit_mynetworks
|
||||
...
|
||||
@ -127,6 +132,8 @@ see what mail would be blocked:
|
||||
reject_unknown_sender_domain
|
||||
warn_if_reject reject_unverified_sender
|
||||
...
|
||||
# Be sure to read the "Caching" section below!
|
||||
address_verify_map = btree:/var/mta/verify
|
||||
|
||||
This is also a good way to populate your cache with address
|
||||
verification results before you start to actually reject mail.
|
||||
@ -160,7 +167,7 @@ Caching
|
||||
NOTE: By default, address verification information is not stored
|
||||
in a persistent file. You have to specify one in main.cf (see
|
||||
below). Persistent storage is off by default because it may need
|
||||
more disk space than is available in your root file system.
|
||||
more disk space than is available in your file system.
|
||||
|
||||
Address verification information is cached by the Postfix verify
|
||||
daemon. Postfix has a bunch of parameters that control the caching
|
||||
@ -173,9 +180,9 @@ verification results. If you don't specify a file, all address
|
||||
verification information is lost after "postfix reload" or "postfix
|
||||
stop".
|
||||
|
||||
If your root file system has sufficient space, try:
|
||||
If your /var file system has sufficient space, try:
|
||||
|
||||
address_verify_map = btree:/etc/postfix/verify
|
||||
address_verify_map = btree:/var/mta/verify
|
||||
|
||||
NOTE: Do not put this file in a file system that fills up. When
|
||||
the address verification table gets corrupted the world comes to
|
||||
@ -197,8 +204,8 @@ accepted) and for negative results (address was rejected).
|
||||
|
||||
Right now, no tools are provided to manage the address verification
|
||||
database. If the file gets too big, or if it gets corrupted, you
|
||||
can manually delete the file and run "postfix reload". The new
|
||||
verify daemon process will then create a new, empty, database.
|
||||
can manually rename or delete the file and run "postfix reload".
|
||||
The new verify daemon process will then create a new database.
|
||||
|
||||
Controlling the routing of address verification probes
|
||||
======================================================
|
||||
@ -249,6 +256,7 @@ for address verification probes and leave everything else alone:
|
||||
/etc/postfix/main.cf:
|
||||
relayhost = $mydomain
|
||||
address_verify_relayhost =
|
||||
...
|
||||
|
||||
Sites behind an address translation relay might have to use a
|
||||
different SMTP client that sends the correct hostname information:
|
||||
|
@ -233,12 +233,19 @@ one would set up the service in the Postfix master.cf file:
|
||||
|
||||
/etc/postfix/master.cf:
|
||||
scan unix - - n - 10 smtp
|
||||
# -o smtp_send_xclient_command=yes
|
||||
|
||||
Instead of a limit of 10 concurrent processes, use whatever process
|
||||
limit is feasible for your machine. Content inspection software
|
||||
can gobble up a lot of system resources, so you don't want to have
|
||||
too much of it running at the same time.
|
||||
|
||||
Uncomment (but keep the leading white-space) the option setting:
|
||||
"smtp_send_xclient_command=yes", if you would like the scan transport
|
||||
to forward the original client name and IP address to the backend smtpd
|
||||
so that mail transaction logs show the real client name IP address.
|
||||
See sample-smtp.cf and smtp(8).
|
||||
|
||||
The content filter can be set up with the Postfix spawn service,
|
||||
which is the Postfix equivalent of inetd. For example, to instantiate
|
||||
up to 10 content filtering processes on demand:
|
||||
|
@ -68,7 +68,7 @@ How Postfix talks to the before-queue content filter
|
||||
The before-filter Postfix SMTP server connects to the content
|
||||
filter, delivers one message, and disconnects. While sending mail
|
||||
into the content filter, Postfix speaks ESMTP but uses no command
|
||||
pipelining. Postfix generates its own EHLO, XLOGINFO (for logging
|
||||
pipelining. Postfix generates its own EHLO, XCLIENT (for logging
|
||||
the remote client IP address instead of localhost[127.0.0.1]), DATA
|
||||
and QUIT commands, and forwards unmodified copies of all the MAIL
|
||||
FROM and RCPT TO commands that the before-filter Postfix SMTP server
|
||||
@ -85,6 +85,9 @@ the connection with the after-filter Postfix SMTP server without
|
||||
completing the SMTP conversation with the after-filter Postfix SMTP
|
||||
server.
|
||||
|
||||
More details on the postfix-to-proxy interaction is at the end of
|
||||
this document, in the section titled "Transparency".
|
||||
|
||||
Configuration parameters
|
||||
========================
|
||||
|
||||
@ -119,7 +122,7 @@ for testing, of course.
|
||||
smtp inet n - n - - smtpd
|
||||
-o smtpd_proxy_filter=26
|
||||
:26 inet n - n - - smtpd
|
||||
-o smtpd_authorized_xloginfo_clients=127.0.0.0/8
|
||||
-o smtpd_authorized_xclient_hosts=127.0.0.0/8
|
||||
-o smtpd_client_restrictions=
|
||||
-o smtpd_helo_restrictions=
|
||||
-o smtpd_sender_restrictions=
|
||||
@ -132,10 +135,10 @@ Note: do not specify spaces around the "=" or "," characters.
|
||||
The ":26" causes Postfix to listen on the localhost address only.
|
||||
DO NOT expose the secondary SMTP server to the Internet :-)
|
||||
|
||||
The smtpd_authorized_xloginfo_clients parameter allows the before
|
||||
filter SMTP server to pass the remote SMTP client name and address
|
||||
to the after-filter SMTP server, so that the after-filter Postfix
|
||||
daemons log the remote client name and address instead of logging
|
||||
The smtpd_authorized_xclient_hosts parameter allows the before
|
||||
filter SMTP server to forward remote SMTP client information to
|
||||
the after-filter SMTP server, so that the after-filter Postfix
|
||||
daemons log the remote SMTP client information instead of logging
|
||||
localhost[127.0.0.1].
|
||||
|
||||
The other parameter settings avoid duplication of effort that is
|
||||
@ -149,3 +152,36 @@ This configuration is sufficient for stress testing.
|
||||
|
||||
Other suggestions for test configurations: use the Postfix smtp-sink
|
||||
command as the proxy, or something as basic as netcat.
|
||||
|
||||
Transparency
|
||||
============
|
||||
|
||||
The before-filter Postfix SMTP server forwards the MAIL FROM, RCPT
|
||||
TO and DATA commands that it has approved, but it does not forward
|
||||
other commands such as TLS or SASL commands. It can therefore not
|
||||
be transparent.
|
||||
|
||||
The real-time content filter, on the other hand, has to be transparent.
|
||||
In order to support non-transparent real-time content filters,
|
||||
Postfix would have to reconcile the before-filter Postfix ESMTP
|
||||
feature set with the feature set that Postfix receives from the
|
||||
real-time content filter.
|
||||
|
||||
- When a future Postfix version supports DSN, but the content filter
|
||||
does not announce DSN support in the EHLO reply, then the before-filter
|
||||
SMTP server would have to either 1) suppress the DSN feature in
|
||||
its EHLO announcement, or 2) duplicate all the work that needs to
|
||||
be done when delivering DSN-aware mail to a non-DSN destination.
|
||||
|
||||
- When the content filter does not announce 8BITMIME support in
|
||||
the EHLO reply, then the before-filter SMTP server would have to
|
||||
either 1) suppress the 8BITMIME feature in its EHLO announcement,
|
||||
or 2) convert the content to quoted-printable before giving it to
|
||||
the content filter.
|
||||
|
||||
- Performance: when Postfix has to suppress elements from the
|
||||
before-filter EHLO reply because they are incompatible with the
|
||||
real-time content filter, then Postfix has to connect to the content
|
||||
filter as soon as the client sends a valid EHLO command. This wastes
|
||||
a lot of resources when all the MAIL FROM or RCPT TO commands are
|
||||
rejected.
|
||||
|
185
postfix/README_FILES/XCLIENT_README
Normal file
185
postfix/README_FILES/XCLIENT_README
Normal file
@ -0,0 +1,185 @@
|
||||
Purpose of the XCLIENT extension to SMTP
|
||||
========================================
|
||||
|
||||
The XCLIENT command targets problems in the following areas:
|
||||
|
||||
1 - Access control tests. SMTP server access rules are difficult
|
||||
to verify when decisions can be triggered only by remote clients.
|
||||
In order to facilitate access rule testing, an SMTP client test
|
||||
program needs the ability to override the SMTP server's idea of
|
||||
the SMTP client hostname, network address, and other information.
|
||||
|
||||
2 - Logging after content filter. With Internet->MTA1->filter->MTA2
|
||||
style content filter applications, remote client information is
|
||||
lost when MTA1 gives the mail to the content filter. This complicates
|
||||
the interpretation of the audit trail. In order maintain audit
|
||||
trail continuity, MTA1 needs the ability to forward client information
|
||||
through the content filter to MTA2.
|
||||
|
||||
3 - Post-filter access control and logging. With Internet->filter->MTA
|
||||
style content filter applications, the content filter can be greatly
|
||||
simplified if it can delegate all decisions concerning mail relay
|
||||
and other access control to the MTA. This requires that the filter
|
||||
can forward client information to the MTA for access control
|
||||
purposes.
|
||||
|
||||
The preceding suggests that there is a need for two modes of
|
||||
operation:
|
||||
|
||||
- Operation mode 1: override the SMTP server's idea of SMTP
|
||||
client information for access control and audit trail purposes.
|
||||
Attributes that one may want to override are:
|
||||
|
||||
client network address
|
||||
client hostname
|
||||
hostname lookup failure type (permanent or temporary)
|
||||
client protocol (e.g., SMTP or ESMTP)
|
||||
|
||||
- Operation mode 2: forward remote client information for audit
|
||||
trail purposes only. Examples of attributes are:
|
||||
|
||||
client network address
|
||||
client hostname
|
||||
client protocol (e.g., SMTP or ESMTP)
|
||||
client SMTP HELO parameter
|
||||
|
||||
General XCLIENT command syntax
|
||||
==============================
|
||||
|
||||
The XCLIENT command maintains one set of attributes with surrogate
|
||||
client information. The general XCLIENT command syntax is described
|
||||
below. Upper case and quoted strings specify terminals, lowercase
|
||||
strings specify meta terminals, SP is whitespace, and descriptive
|
||||
text is in {}. Although shown below in upper case, command and
|
||||
attribute names are in fact case insensitive.
|
||||
|
||||
xclient-command = XCLIENT *( SP argument )
|
||||
|
||||
argument = ( request | attribute )
|
||||
|
||||
request = ( RST | ACL | LOG )
|
||||
|
||||
attribute = name"="value
|
||||
|
||||
name = ( CLIENT_NAME | CLIENT_ADDR | CLIENT_CODE | PROTOCOL | HELO_NAME )
|
||||
|
||||
value = ( { empty } | xtext )
|
||||
|
||||
xtext = { attribute value encoded as per RFC 1891 }
|
||||
|
||||
The XCLIENT command is typically sent immediately before or after
|
||||
the EHLO command, may be pipelined after the server announces ESMTP
|
||||
pipelining support, and must not be used in the middle of an SMTP
|
||||
transaction (i.e. between MAIL and DOT).
|
||||
|
||||
The server reply codes are as follows:
|
||||
|
||||
Code | Meaning
|
||||
-----|------------
|
||||
250 | success
|
||||
501 | command syntax error
|
||||
502 | unrecognized request name
|
||||
503 | command out of order (name=value without prior ACL or LOG request)
|
||||
421 | unable to proceed
|
||||
|
||||
The server must report success in case of an unrecognized attribute
|
||||
name, although it may log a warning.
|
||||
|
||||
Specific XCLIENT usage scenarios
|
||||
================================
|
||||
|
||||
This section discusses the semantics of XCLIENT requests. Specific
|
||||
syntax information is given in the next section.
|
||||
|
||||
The RST request resets all XCLIENT attributes and disables any
|
||||
override of access control or audit trail attributes. Example:
|
||||
|
||||
XCLIENT RST
|
||||
|
||||
The ACL request resets all XCLIENT attributes and must be specified
|
||||
before sending surrogate attributes for access control and audit
|
||||
trail purposes. Attributes that are not explicitly specified will
|
||||
default to their actual value. Example:
|
||||
|
||||
XCLIENT ACL CLIENT_NAME=spike.porcupine.org
|
||||
XCLIENT CLIENT_ADDR=168.100.189.2
|
||||
|
||||
This overrides only the client hostname and network address, but
|
||||
none of the other client attributes.
|
||||
|
||||
The LOG request resets all XCLIENT attributes and must be specified
|
||||
before sending surrogate attributes for audit trail purposes.
|
||||
Attributes that are not explicitly specified will default to the
|
||||
unknown value. Example:
|
||||
|
||||
XCLIENT LOG CLIENT_NAME=spike.porcupine.org CLIENT_ADDR=168.100.189.2
|
||||
XCLIENT HELO_NAME=spike.porcupine.org PROTOCOL=ESMTP
|
||||
|
||||
This overrides all client attributes that are defined in this
|
||||
document, leaving none at their default unknown value.
|
||||
|
||||
Note 1: it is an error to specify name=value pairs without prior
|
||||
ACL or LOG request.
|
||||
|
||||
Note 2: after an ACL or LOG request, attributes specified with
|
||||
successive XCLIENT commands accumulate until the next RST, ACL or
|
||||
LOG request.
|
||||
|
||||
Note 3: if one XCLIENT command specifies multiple requests (e.g.,
|
||||
both ACL and LOG), only the last request takes effect.
|
||||
|
||||
XCLIENT attribute value details
|
||||
===============================
|
||||
|
||||
Attribute values are encoded as RFC 1891 xtext strings. To explicitly
|
||||
specify that an attribute value is unknown, the value must be empty;
|
||||
the client is not allowed to send its own internal representation
|
||||
for unknown information.
|
||||
|
||||
CLIENT_CODE specifies CLIENT_NAME hostname lookup status information.
|
||||
Values are OK (success), TEMP (temporary lookup failure) or PERM
|
||||
(permanent lookup failure). When CLIENT_CODE is set to any value
|
||||
other than OK, the CLIENT_NAME attribute is set to the unknown
|
||||
value.
|
||||
|
||||
CLIENT_NAME should specify a syntactically valid domain name and
|
||||
not a numerical address. When a null client name is specified
|
||||
(i.e. the client name is unknown), the CLIENT_CODE attribute is
|
||||
set to PERM. When a valid domain name is specified, CLIENT_CODE is
|
||||
set to OK. The server may process a syntactically invalid domain
|
||||
name as if it were unknown.
|
||||
|
||||
CLIENT_ADDR must specify a numerical network address without [].
|
||||
|
||||
PROTOCOL is a string of up to 64 printable characters.
|
||||
|
||||
HELO_NAME should be a syntactically valid domain name.
|
||||
|
||||
Note 4: syntactically valid CLIENT_NAME and HELO_NAME attributes
|
||||
can be up to 255 characters long. The client must not send XCLIENT
|
||||
commands that exceed the 512 character limit of SMTP commands.
|
||||
|
||||
Note 5: attribute values may end up in Received: or other message
|
||||
headers. The server may substitute any characters that are special
|
||||
according to RFC 822 or RFC 2822.
|
||||
|
||||
Security
|
||||
========
|
||||
|
||||
The XCLIENT command changes audit trails and changes client access
|
||||
permissions. For these reasons, use of the XCLIENT command must be
|
||||
restricted to authorized clients only.
|
||||
|
||||
The examples in this document assume that XCLIENT does not override
|
||||
its own access control mechanism.
|
||||
|
||||
SMTP connection caching
|
||||
=======================
|
||||
|
||||
SMTP connection caching makes it possible to deliver multiple
|
||||
messages within the same SMTP session. Thus, one persistent SMTP
|
||||
session with a content filter can carry messages from unrelated
|
||||
clients. Attributes from one remote client should not affect the
|
||||
delivery of mail from a different remote client. In order to
|
||||
prevent such information leakage, use the XCLIENT RST, ACL or LOG
|
||||
requests as appropriate.
|
@ -76,6 +76,17 @@ smtp_never_send_ehlo = no
|
||||
#
|
||||
smtp_defer_if_no_mx_address_found = no
|
||||
|
||||
# The smtp_send_xclient_command parameter controls whether the Postfix
|
||||
# SMTP client will send an XCLIENT command to the SMTP server, when
|
||||
# the ESMTP HELO response of the remote host indicates XCLIENT support.
|
||||
# This allows an "smtp" delivery agent, used for content filter
|
||||
# message injection, to forward the name, address, protocol and HELO
|
||||
# name of the original client to the content filter and downstream
|
||||
# queuing SMTP server. Before you change the value to yes, it is best
|
||||
# to make sure your content filter supports this command.
|
||||
#
|
||||
smtp_send_xclient_command = no
|
||||
|
||||
# The smtp_line_length_limit parameter controls the length of
|
||||
# message header and body lines that Postfix will send via SMTP.
|
||||
# Lines that are longer are broken by inserting <CR> <LF> <SPACE>.
|
||||
|
@ -154,13 +154,14 @@ smtpd_client_connection_limit_exceptions = $mynetworks
|
||||
#
|
||||
#disable_vrfy_command = no
|
||||
|
||||
# The smtpd_authorized_xaddr_clients parameter specifies what clients
|
||||
# are allowed to specify the SMTP "XADDR client-address client-name"
|
||||
# command. This command changes Postfix's idea of the client hostname
|
||||
# and IP address for logging and for access control. Typical use is
|
||||
# for SMTPD access testing.
|
||||
# The smtpd_authorized_xclient_hosts parameter specifies what clients
|
||||
# are allowed to specify the XCLIENT extension to SMTP.
|
||||
#
|
||||
# By default, no clients are allowed to specify XADDR.
|
||||
# This command overrides SMTP client information that is used for
|
||||
# logging or access control. Typical use is for SMTP-based content
|
||||
# filters or for SMTP server access rule testing.
|
||||
#
|
||||
# By default, no clients are allowed to specify XCLIENT.
|
||||
#
|
||||
# Specify an explicit list of network/netmask patterns, where the
|
||||
# mask specifies the number of bits in the network part of a host
|
||||
@ -171,26 +172,7 @@ smtpd_client_connection_limit_exceptions = $mynetworks
|
||||
# of listing the patterns here. Specify type:table for table-based lookups
|
||||
# (the value on the table right-hand side is not used).
|
||||
#
|
||||
smtpd_authorized_xaddr_clients =
|
||||
|
||||
# The smtpd_authorized_xloginfo_clients parameter specifies what
|
||||
# clients are allowed to specify the SMTP "XLOGINFO client-address
|
||||
# client-name" command. This command changes Postfix's idea of the
|
||||
# client hostname and IP address for logging but not for access
|
||||
# control. Typical use is for SMTP-based content filters.
|
||||
#
|
||||
# By default, no clients are allowed to specify XLOGINFO.
|
||||
#
|
||||
# Specify an explicit list of network/netmask patterns, where the
|
||||
# mask specifies the number of bits in the network part of a host
|
||||
# address. You can also specify hostnames or .domain names (the
|
||||
# initial dot causes the domain to match any name below it).
|
||||
#
|
||||
# You can also specify the absolute pathname of a pattern file instead
|
||||
# of listing the patterns here. Specify type:table for table-based lookups
|
||||
# (the value on the table right-hand side is not used).
|
||||
#
|
||||
smtpd_authorized_xloginfo_clients =
|
||||
smtpd_authorized_xclient_hosts =
|
||||
|
||||
# The smtpd_authorized_verp_clients parameter specifies what clients
|
||||
# are allowed to specify the SMTP XVERP command. This command requests
|
||||
|
@ -249,16 +249,20 @@ SMTP(8) SMTP(8)
|
||||
Timeout for sending the <b>HELO</b> command, and for
|
||||
receiving the server response.
|
||||
|
||||
<b>smtp_xclient_timeout</b>
|
||||
Timeout for sending the <b>XCLIENT</b> command, and for
|
||||
receiving the server response.
|
||||
|
||||
<b>smtp_mail_timeout</b>
|
||||
Timeout for sending the <b>MAIL FROM</b> command, and for
|
||||
Timeout for sending the <b>MAIL FROM</b> command, and for
|
||||
receiving the server response.
|
||||
|
||||
<b>smtp_rcpt_timeout</b>
|
||||
Timeout for sending the <b>RCPT TO</b> command, and for
|
||||
Timeout for sending the <b>RCPT TO</b> command, and for
|
||||
receiving the server response.
|
||||
|
||||
<b>smtp_data_init_timeout</b>
|
||||
Timeout for sending the <b>DATA</b> command, and for
|
||||
Timeout for sending the <b>DATA</b> command, and for
|
||||
receiving the server response.
|
||||
|
||||
<b>smtp_data_xfer_timeout</b>
|
||||
@ -266,22 +270,29 @@ SMTP(8) SMTP(8)
|
||||
|
||||
<b>smtp_data_done_timeout</b>
|
||||
Timeout for sending the "<b>.</b>" command, and for
|
||||
receiving the server response. When no response is
|
||||
received, a warning is logged that the mail may be
|
||||
receiving the server response. When no response is
|
||||
received, a warning is logged that the mail may be
|
||||
delivered multiple times.
|
||||
|
||||
<b>smtp_defer_if_no_mx_address_found</b>
|
||||
If no, bounce mail when no MX host resolves to an
|
||||
If no, bounce mail when no MX host resolves to an
|
||||
address (Postfix always ignores MX hosts with equal
|
||||
or worse preference than the local MTA). If yes,
|
||||
keep trying until a suitable MX host resolves or
|
||||
or worse preference than the local MTA). If yes,
|
||||
keep trying until a suitable MX host resolves or
|
||||
until the mail is too old.
|
||||
|
||||
<b>smtp_send_xclient_command</b>
|
||||
If the SMTP server announces XCLIENT support, send
|
||||
the name, address, protocol and HELO name of the
|
||||
original client. This can be used to forward client
|
||||
information through a content filter to a down-
|
||||
stream queuing SMTP server.
|
||||
|
||||
<b>smtp_rset_timeout</b>
|
||||
Timeout for sending the <b>RSET</b> command.
|
||||
|
||||
<b>smtp_quit_timeout</b>
|
||||
Timeout for sending the <b>QUIT</b> command, and for
|
||||
Timeout for sending the <b>QUIT</b> command, and for
|
||||
receiving the server response.
|
||||
|
||||
<b>SEE ALSO</b>
|
||||
@ -291,7 +302,7 @@ SMTP(8) SMTP(8)
|
||||
syslogd(8) system logging
|
||||
|
||||
<b>LICENSE</b>
|
||||
The Secure Mailer license must be distributed with this
|
||||
The Secure Mailer license must be distributed with this
|
||||
software.
|
||||
|
||||
<b>AUTHOR(S)</b>
|
||||
|
@ -170,42 +170,32 @@ SMTPD(8) SMTPD(8)
|
||||
Hostnames, domain names and/or addresses of clients
|
||||
that are authorized to use the XVERP extension.
|
||||
|
||||
<b>smtpd_authorized_xaddr_clients</b>
|
||||
<b>smtpd_authorized_xclient_hosts</b>
|
||||
Hostnames, domain names and/or addresses of clients
|
||||
that are authorized to use the "XADDR client-
|
||||
address client-name" command. This changes Post-
|
||||
fix's idea of the SMTP client IP address and host-
|
||||
name for access control and for logging purposes.
|
||||
|
||||
<b>smtpd_authorized_xloginfo_clients</b>
|
||||
Hostnames, domain names and/or addresses of clients
|
||||
that are authorized to use the "XLOGINFO client-
|
||||
address client-name" command. This changes the
|
||||
client name and address that are used for logging,
|
||||
without affecting the client IP address and host-
|
||||
name that are used for access control. XLOGINFO is
|
||||
typically used to propagate remote client informa-
|
||||
tion through an SMTP-based content filter to the
|
||||
after-filter SMTP server.
|
||||
that are authorized to use the XCLIENT command.
|
||||
This command changes client information for access
|
||||
control and/or logging purposes, with the exception
|
||||
of the <b>smtpd_authorized_xclient_hosts</b> access con-
|
||||
trol itself.
|
||||
|
||||
<b>debug_peer_level</b>
|
||||
Increment in verbose logging level when a remote
|
||||
Increment in verbose logging level when a remote
|
||||
host matches a pattern in the <b>debug_peer_list</b>
|
||||
parameter.
|
||||
|
||||
<b>debug_peer_list</b>
|
||||
List of domain or network patterns. When a remote
|
||||
host matches a pattern, increase the verbose log-
|
||||
ging level by the amount specified in the
|
||||
List of domain or network patterns. When a remote
|
||||
host matches a pattern, increase the verbose log-
|
||||
ging level by the amount specified in the
|
||||
<b>debug_peer_level</b> parameter.
|
||||
|
||||
<b>default_verp_delimiters</b>
|
||||
The default VERP delimiter characters that are used
|
||||
when the XVERP command is specified without
|
||||
when the XVERP command is specified without
|
||||
explicit delimiters.
|
||||
|
||||
<b>error_notice_recipient</b>
|
||||
Recipient of protocol/policy/resource/software
|
||||
Recipient of protocol/policy/resource/software
|
||||
error notices.
|
||||
|
||||
<b>hopcount_limit</b>
|
||||
@ -214,18 +204,18 @@ SMTPD(8) SMTPD(8)
|
||||
<b>notify_classes</b>
|
||||
List of error classes. Of special interest are:
|
||||
|
||||
<b>policy</b> When a client violates any policy, mail a
|
||||
<b>policy</b> When a client violates any policy, mail a
|
||||
transcript of the entire SMTP session to the
|
||||
postmaster.
|
||||
|
||||
<b>protocol</b>
|
||||
When a client violates the SMTP protocol or
|
||||
When a client violates the SMTP protocol or
|
||||
issues an unimplemented command, mail a
|
||||
transcript of the entire SMTP session to the
|
||||
postmaster.
|
||||
|
||||
<b>smtpd_banner</b>
|
||||
Text that follows the <b>220</b> status code in the SMTP
|
||||
Text that follows the <b>220</b> status code in the SMTP
|
||||
greeting banner.
|
||||
|
||||
<b>smtpd_expansion_filter</b>
|
||||
@ -233,57 +223,57 @@ SMTPD(8) SMTPD(8)
|
||||
expansion of rbl template responses and other text.
|
||||
|
||||
<b>smtpd_recipient_limit</b>
|
||||
Restrict the number of recipients that the SMTP
|
||||
Restrict the number of recipients that the SMTP
|
||||
server accepts per message delivery.
|
||||
|
||||
<b>smtpd_timeout</b>
|
||||
Limit the time to send a server response and to
|
||||
Limit the time to send a server response and to
|
||||
receive a client request.
|
||||
|
||||
<b>soft_bounce</b>
|
||||
Change hard (5xx) reject responses into soft (4xx)
|
||||
reject responses. This can be useful for testing
|
||||
Change hard (5xx) reject responses into soft (4xx)
|
||||
reject responses. This can be useful for testing
|
||||
purposes.
|
||||
|
||||
<b>verp_delimiter_filter</b>
|
||||
The characters that Postfix accepts as VERP delim-
|
||||
The characters that Postfix accepts as VERP delim-
|
||||
iter characters.
|
||||
|
||||
<b>Known versus unknown recipients</b>
|
||||
<b>show_user_unknown_table_name</b>
|
||||
Whether or not to reveal the table name in the
|
||||
"User unknown" responses. The extra detail makes
|
||||
trouble shooting easier but also reveals informa-
|
||||
Whether or not to reveal the table name in the
|
||||
"User unknown" responses. The extra detail makes
|
||||
trouble shooting easier but also reveals informa-
|
||||
tion that is nobody elses business.
|
||||
|
||||
<b>unknown_local_recipient_reject_code</b>
|
||||
The response code when a client specifies a recipi-
|
||||
ent whose domain matches <b>$mydestination</b> or
|
||||
ent whose domain matches <b>$mydestination</b> or
|
||||
<b>$inet_interfaces</b>, while <b>$local_recipient_maps</b> is
|
||||
non-empty and does not list the recipient address
|
||||
non-empty and does not list the recipient address
|
||||
or address local-part.
|
||||
|
||||
<b>unknown_relay_recipient_reject_code</b>
|
||||
The response code when a client specifies a recipi-
|
||||
ent whose domain matches <b>$relay_domains</b>, while
|
||||
<b>$relay_recipient_maps</b> is non-empty and does not
|
||||
<b>$relay_recipient_maps</b> is non-empty and does not
|
||||
list the recipient address.
|
||||
|
||||
<b>unknown_virtual_alias_reject_code</b>
|
||||
The response code when a client specifies a recipi-
|
||||
ent whose domain matches <b>$virtual_alias_domains</b>,
|
||||
while the recipient is not listed in <b>$vir-</b>
|
||||
ent whose domain matches <b>$virtual_alias_domains</b>,
|
||||
while the recipient is not listed in <b>$vir-</b>
|
||||
<b>tual_alias_maps</b>.
|
||||
|
||||
<b>unknown_virtual_mailbox_reject_code</b>
|
||||
The response code when a client specifies a recipi-
|
||||
ent whose domain matches <b>$virtual_mailbox_domains</b>,
|
||||
ent whose domain matches <b>$virtual_mailbox_domains</b>,
|
||||
while the recipient is not listed in <b>$virtual_mail-</b>
|
||||
<b>box_maps</b>.
|
||||
|
||||
<b>Resource controls</b>
|
||||
<b>line_length_limit</b>
|
||||
Limit the amount of memory in bytes used for the
|
||||
Limit the amount of memory in bytes used for the
|
||||
handling of partial input lines.
|
||||
|
||||
<b>message_size_limit</b>
|
||||
@ -291,9 +281,9 @@ SMTPD(8) SMTPD(8)
|
||||
ing on-disk storage for envelope information.
|
||||
|
||||
<b>queue_minfree</b>
|
||||
Minimal amount of free space in bytes in the queue
|
||||
file system for the SMTP server to accept any mail
|
||||
at all (default: twice the <b>message_size_limit</b>
|
||||
Minimal amount of free space in bytes in the queue
|
||||
file system for the SMTP server to accept any mail
|
||||
at all (default: twice the <b>message_size_limit</b>
|
||||
value).
|
||||
|
||||
<b>smtpd_history_flush_threshold</b>
|
||||
@ -303,21 +293,21 @@ SMTPD(8) SMTPD(8)
|
||||
|
||||
<b>smtpd_client_connection_count_limit</b>
|
||||
The maximal number of simultaneous connections that
|
||||
any client is allowed to make to this service.
|
||||
When a client exceeds the limit, the SMTP server
|
||||
any client is allowed to make to this service.
|
||||
When a client exceeds the limit, the SMTP server
|
||||
logs a warning with the client name/address and the
|
||||
service name as configured in master.cf.
|
||||
|
||||
<b>smtpd_client_connection_rate_limit</b>
|
||||
The maximal number of connections per unit time
|
||||
The maximal number of connections per unit time
|
||||
(specified with <b>connection_rate_time_unit</b>) that any
|
||||
client is allowed to make to this service. When a
|
||||
client exceeds the limit, the SMTP server logs a
|
||||
warning with the client name/address and the ser-
|
||||
client is allowed to make to this service. When a
|
||||
client exceeds the limit, the SMTP server logs a
|
||||
warning with the client name/address and the ser-
|
||||
vice name as configured in master.cf.
|
||||
|
||||
<b>smtpd_client_connection_limit_exceptions</b>
|
||||
Hostnames, .domain names and/or network address
|
||||
Hostnames, .domain names and/or network address
|
||||
blocks of clients that are excluded from connection
|
||||
count or rate limits.
|
||||
|
||||
@ -328,17 +318,17 @@ SMTPD(8) SMTPD(8)
|
||||
|
||||
<b>smtpd_soft_error_limit</b>
|
||||
When an SMTP client has made this number of errors,
|
||||
wait <i>error</i><b>_</b><i>count</i> seconds before responding to any
|
||||
wait <i>error</i><b>_</b><i>count</i> seconds before responding to any
|
||||
client request.
|
||||
|
||||
<b>smtpd_hard_error_limit</b>
|
||||
Disconnect after a client has made this number of
|
||||
Disconnect after a client has made this number of
|
||||
errors.
|
||||
|
||||
<b>smtpd_junk_command_limit</b>
|
||||
Limit the number of times a client can issue a junk
|
||||
command such as NOOP, VRFY, ETRN or RSET in one
|
||||
SMTP session before it is penalized with tarpit
|
||||
command such as NOOP, VRFY, ETRN or RSET in one
|
||||
SMTP session before it is penalized with tarpit
|
||||
delays.
|
||||
|
||||
<b>Delegated policy</b>
|
||||
@ -347,17 +337,17 @@ SMTPD(8) SMTPD(8)
|
||||
receiving from a delegated SMTPD policy server.
|
||||
|
||||
<b>smtpd_policy_service_max_idle</b>
|
||||
Time after which an unused SMTPD policy service
|
||||
Time after which an unused SMTPD policy service
|
||||
connection is closed.
|
||||
|
||||
<b>smtpd_policy_service_timeout</b>
|
||||
Time after which an active SMTPD policy service
|
||||
Time after which an active SMTPD policy service
|
||||
connection is closed.
|
||||
|
||||
<b>UCE control restrictions</b>
|
||||
<b>parent_domain_matches_subdomains</b>
|
||||
List of Postfix features that use <i>domain.tld</i> pat-
|
||||
terns to match <i>sub.domain.tld</i> (as opposed to
|
||||
List of Postfix features that use <i>domain.tld</i> pat-
|
||||
terns to match <i>sub.domain.tld</i> (as opposed to
|
||||
requiring <i>.domain.tld</i> patterns).
|
||||
|
||||
<b>smtpd_client_restrictions</b>
|
||||
@ -365,19 +355,19 @@ SMTPD(8) SMTPD(8)
|
||||
tem.
|
||||
|
||||
<b>smtpd_helo_required</b>
|
||||
Require that clients introduce themselves at the
|
||||
Require that clients introduce themselves at the
|
||||
beginning of an SMTP session.
|
||||
|
||||
<b>smtpd_helo_restrictions</b>
|
||||
Restrict what client hostnames are allowed in <b>HELO</b>
|
||||
Restrict what client hostnames are allowed in <b>HELO</b>
|
||||
and <b>EHLO</b> commands.
|
||||
|
||||
<b>smtpd_sender_restrictions</b>
|
||||
Restrict what sender addresses are allowed in <b>MAIL</b>
|
||||
Restrict what sender addresses are allowed in <b>MAIL</b>
|
||||
<b>FROM</b> commands.
|
||||
|
||||
<b>smtpd_recipient_restrictions</b>
|
||||
Restrict what recipient addresses are allowed in
|
||||
Restrict what recipient addresses are allowed in
|
||||
<b>RCPT TO</b> commands.
|
||||
|
||||
<b>smtpd_etrn_restrictions</b>
|
||||
@ -385,96 +375,96 @@ SMTPD(8) SMTPD(8)
|
||||
mands, and what clients may issue <b>ETRN</b> commands.
|
||||
|
||||
<b>smtpd_data_restrictions</b>
|
||||
Restrictions on the <b>DATA</b> command. Currently, the
|
||||
only restriction that makes sense here is
|
||||
Restrictions on the <b>DATA</b> command. Currently, the
|
||||
only restriction that makes sense here is
|
||||
<b>reject_unauth_pipelining</b>.
|
||||
|
||||
<b>allow_untrusted_routing</b>
|
||||
Allow untrusted clients to specify addresses with
|
||||
sender-specified routing. Enabling this opens up
|
||||
nasty relay loopholes involving trusted backup MX
|
||||
Allow untrusted clients to specify addresses with
|
||||
sender-specified routing. Enabling this opens up
|
||||
nasty relay loopholes involving trusted backup MX
|
||||
hosts.
|
||||
|
||||
<b>smtpd_restriction_classes</b>
|
||||
Declares the name of zero or more parameters that
|
||||
contain a list of UCE restrictions. The names of
|
||||
these parameters can then be used instead of the
|
||||
Declares the name of zero or more parameters that
|
||||
contain a list of UCE restrictions. The names of
|
||||
these parameters can then be used instead of the
|
||||
restriction lists that they represent.
|
||||
|
||||
<b>smtpd_null_access_lookup_key</b>
|
||||
The lookup key to be used in SMTPD access tables
|
||||
instead of the null sender address. A null sender
|
||||
The lookup key to be used in SMTPD access tables
|
||||
instead of the null sender address. A null sender
|
||||
address cannot be looked up.
|
||||
|
||||
<b>maps_rbl_domains</b> (deprecated)
|
||||
List of DNS domains that publish the addresses of
|
||||
List of DNS domains that publish the addresses of
|
||||
blacklisted hosts. This is used with the deprecated
|
||||
<b>reject_maps_rbl</b> restriction.
|
||||
|
||||
<b>permit_mx_backup_networks</b>
|
||||
Only domains whose primary MX hosts match the
|
||||
listed networks are eligible for the <b>per-</b>
|
||||
Only domains whose primary MX hosts match the
|
||||
listed networks are eligible for the <b>per-</b>
|
||||
<b>mit_mx_backup</b> feature.
|
||||
|
||||
<b>relay_domains</b>
|
||||
Restrict what domains this mail system will relay
|
||||
mail to. The domains are routed to the delivery
|
||||
Restrict what domains this mail system will relay
|
||||
mail to. The domains are routed to the delivery
|
||||
agent specified with the <b>relay_transport</b> setting.
|
||||
|
||||
<b>Sender/recipient address 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-
|
||||
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_verify_poll_count</b>
|
||||
How many times to query the address verification
|
||||
service for completion of an address verification
|
||||
request. Specify 1 to implement a simple form of
|
||||
greylisting, that is, always defer the request for
|
||||
How many times to query the address verification
|
||||
service for completion of an address verification
|
||||
request. Specify 1 to implement a simple form of
|
||||
greylisting, that is, always defer the request for
|
||||
a new sender or recipient address.
|
||||
|
||||
<b>address_verify_poll_delay</b>
|
||||
Time to wait after querying the address verifica-
|
||||
Time to wait after querying the address verifica-
|
||||
tion service for completion of an address verifica-
|
||||
tion request.
|
||||
|
||||
<b>UCE control responses</b>
|
||||
<b>access_map_reject_code</b>
|
||||
Response code when a client violates an access
|
||||
Response code when a client violates an access
|
||||
database restriction.
|
||||
|
||||
<b>default_rbl_reply</b>
|
||||
Default template reply when a request is RBL black-
|
||||
listed. This template is used by the <b>reject_rbl_*</b>
|
||||
and <b>reject_rhsbl_*</b> restrictions. See also:
|
||||
listed. This template is used by the <b>reject_rbl_*</b>
|
||||
and <b>reject_rhsbl_*</b> restrictions. See also:
|
||||
<b>rbl_reply_maps</b> and <b>smtpd_expansion_filter</b>.
|
||||
|
||||
<b>defer_code</b>
|
||||
Response code when a client request is rejected by
|
||||
Response code when a client request is rejected by
|
||||
the <b>defer</b> restriction.
|
||||
|
||||
<b>invalid_hostname_reject_code</b>
|
||||
Response code when a client violates the
|
||||
Response code when a client violates the
|
||||
<b>reject_invalid_hostname</b> restriction.
|
||||
|
||||
<b>maps_rbl_reject_code</b>
|
||||
Response code when a request is RBL blacklisted.
|
||||
|
||||
<b>multi_recipient_bounce_reject_code</b>
|
||||
Response code when a multi-recipient bounce is
|
||||
Response code when a multi-recipient bounce is
|
||||
blocked.
|
||||
|
||||
<b>rbl_reply_maps</b>
|
||||
Table with template responses for RBL blacklisted
|
||||
requests, indexed by RBL domain name. These tem-
|
||||
Table with template responses for RBL blacklisted
|
||||
requests, indexed by RBL domain name. These tem-
|
||||
plates are used by the <b>reject_rbl_*</b> and
|
||||
<b>reject_rhsbl_*</b> restrictions. See also:
|
||||
<b>reject_rhsbl_*</b> restrictions. See also:
|
||||
<b>default_rbl_reply</b> and <b>smtpd_expansion_filter</b>.
|
||||
|
||||
<b>reject_code</b>
|
||||
Response code when the client matches a <b>reject</b>
|
||||
Response code when the client matches a <b>reject</b>
|
||||
restriction.
|
||||
|
||||
<b>relay_domains_reject_code</b>
|
||||
@ -482,7 +472,7 @@ SMTPD(8) SMTPD(8)
|
||||
mail relay policy.
|
||||
|
||||
<b>unknown_address_reject_code</b>
|
||||
Response code when a client violates the
|
||||
Response code when a client violates the
|
||||
<b>reject_unknown_address</b> restriction.
|
||||
|
||||
<b>unknown_client_reject_code</b>
|
||||
@ -491,15 +481,15 @@ SMTPD(8) SMTPD(8)
|
||||
tion.
|
||||
|
||||
<b>unknown_hostname_reject_code</b>
|
||||
Response code when a client violates the
|
||||
Response code when a client violates the
|
||||
<b>reject_unknown_hostname</b> restriction.
|
||||
|
||||
<b>unverified_sender_reject_code</b>
|
||||
Response code when a sender address is known to be
|
||||
Response code when a sender address is known to be
|
||||
undeliverable.
|
||||
|
||||
<b>unverified_recipient_reject_code</b>
|
||||
Response code when a recipient address is known to
|
||||
Response code when a recipient address is known to
|
||||
be undeliverable.
|
||||
|
||||
<b>SEE ALSO</b>
|
||||
@ -510,7 +500,7 @@ SMTPD(8) SMTPD(8)
|
||||
<a href="verify.8.html">verify(8)</a> address verification service
|
||||
|
||||
<b>LICENSE</b>
|
||||
The Secure Mailer license must be distributed with this
|
||||
The Secure Mailer license must be distributed with this
|
||||
software.
|
||||
|
||||
<b>AUTHOR(S)</b>
|
||||
|
@ -6,7 +6,7 @@
|
||||
# SUMMARY
|
||||
# makefile configuration utility
|
||||
# SYNOPSIS
|
||||
# \fBmakedefs\fR
|
||||
# \fBmake makefiles \fIname=value...\fR
|
||||
# DESCRIPTION
|
||||
# The \fBmakedefs\fR command identifies the program compilation
|
||||
# environment, and emits macro definitions on the standard output
|
||||
@ -29,6 +29,9 @@
|
||||
# .IP \fBOPT=\fIoptimization_level\fR
|
||||
# Specifies a non-default optimization level. The default is \fB-O\fR.
|
||||
# Specify \fBOPT=\fR to turn off optimization.
|
||||
# .IP \fBWARN=\fIwarning_flags\fR
|
||||
# Specifies non-default gcc compiler warning options for use when
|
||||
# "make" is invoked in a source subdirectory only.
|
||||
# LICENSE
|
||||
# .ad
|
||||
# .fi
|
||||
@ -320,7 +323,10 @@ case "$CC" in
|
||||
*) : ${OPT='-O'};;
|
||||
esac
|
||||
|
||||
: ${CC='gcc $(WARN)'} ${OPT='-O'} ${DEBUG='-g'} ${AWK=awk}
|
||||
: ${CC='gcc $(WARN)'} ${OPT='-O'} ${DEBUG='-g'} ${AWK=awk} \
|
||||
${WARN='-W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused'}
|
||||
|
||||
export SYSTYPE AR ARFL RANLIB SYSLIBS CC OPT DEBUG AWK OPTS
|
||||
|
||||
@ -336,4 +342,5 @@ DEBUG = $DEBUG
|
||||
AWK = $AWK
|
||||
STRCASE = $STRCASE
|
||||
EXPORT = AUXLIBS='$AUXLIBS' CCARGS='$CCARGS' OPT='$OPT' DEBUG='$DEBUG'
|
||||
WARN = $WARN
|
||||
EOF
|
||||
|
@ -210,6 +210,9 @@ exchanger list.
|
||||
.IP \fBsmtp_helo_timeout\fR
|
||||
Timeout for sending the \fBHELO\fR command, and for
|
||||
receiving the server response.
|
||||
.IP \fBsmtp_xclient_timeout\fR
|
||||
Timeout for sending the \fBXCLIENT\fR command, and for
|
||||
receiving the server response.
|
||||
.IP \fBsmtp_mail_timeout\fR
|
||||
Timeout for sending the \fBMAIL FROM\fR command, and for
|
||||
receiving the server response.
|
||||
@ -231,6 +234,11 @@ If no, bounce mail when no MX host resolves to an address
|
||||
than the local MTA).
|
||||
If yes, keep trying until a suitable MX host resolves or until
|
||||
the mail is too old.
|
||||
.IP \fBsmtp_send_xclient_command\fR
|
||||
If the SMTP server announces XCLIENT support, send the name,
|
||||
address, protocol and HELO name of the original client. This
|
||||
can be used to forward client information through a content
|
||||
filter to a downstream queuing SMTP server.
|
||||
.IP \fBsmtp_rset_timeout\fR
|
||||
Timeout for sending the \fBRSET\fR command.
|
||||
.IP \fBsmtp_quit_timeout\fR
|
||||
|
@ -157,20 +157,12 @@ anti-spoofing restriction.
|
||||
.IP \fBsmtpd_authorized_verp_clients\fR
|
||||
Hostnames, domain names and/or addresses of clients that are
|
||||
authorized to use the XVERP extension.
|
||||
.IP \fBsmtpd_authorized_xaddr_clients\fR
|
||||
.IP \fBsmtpd_authorized_xclient_hosts\fR
|
||||
Hostnames, domain names and/or addresses of clients that are
|
||||
authorized to use the "XADDR client-address client-name" command.
|
||||
This changes Postfix's
|
||||
idea of the SMTP client IP address and hostname for access
|
||||
control and for logging purposes.
|
||||
.IP \fBsmtpd_authorized_xloginfo_clients\fR
|
||||
Hostnames, domain names and/or addresses of clients that are
|
||||
authorized to use the "XLOGINFO client-address client-name" command.
|
||||
This changes the client
|
||||
name and address that are used for logging, without affecting the
|
||||
client IP address and hostname that are used for access control.
|
||||
XLOGINFO is typically used to propagate remote client information
|
||||
through an SMTP-based content filter to the after-filter SMTP server.
|
||||
authorized to use the XCLIENT command. This command changes
|
||||
client information for access control and/or logging purposes,
|
||||
with the exception of the
|
||||
\fBsmtpd_authorized_xclient_hosts\fR access control itself.
|
||||
.IP \fBdebug_peer_level\fR
|
||||
Increment in verbose logging level when a remote host matches a
|
||||
pattern in the \fBdebug_peer_list\fR parameter.
|
||||
|
@ -3,9 +3,6 @@ SRCS = anvil.c
|
||||
OBJS = anvil.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -7,9 +7,6 @@ OBJS = bounce.o bounce_append_service.o bounce_notify_service.o \
|
||||
bounce_one_service.o bounce_warn_service.o bounce_trace_service.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -11,9 +11,6 @@ OBJS = cleanup.o cleanup_out.o cleanup_envelope.o cleanup_message.o \
|
||||
cleanup_addr.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG= cleanup_masquerade
|
||||
|
@ -3,9 +3,6 @@ SRCS = dns_lookup.c dns_rr.c dns_strerror.c dns_strtype.c
|
||||
OBJS = dns_lookup.o dns_rr.o dns_strerror.o dns_strtype.o
|
||||
HDRS = dns.h
|
||||
TESTSRC = test_dns_lookup.c test_alias_token.c
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
INCL =
|
||||
|
@ -3,9 +3,6 @@ SRCS = error.c
|
||||
OBJS = error.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -3,9 +3,6 @@ SRCS = flush.c
|
||||
OBJS = flush.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -3,9 +3,6 @@ SRCS = fsstone.c
|
||||
OBJS = fsstone.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -68,9 +68,6 @@ HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
|
||||
trace.h log_adhoc.h verify.h dict_proxy.h mail_dict.h qmgr_user.h \
|
||||
input_transp.h anvil_clnt.h
|
||||
TESTSRC = rec2stream.c stream2rec.c recdump.c
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
INCL =
|
||||
|
@ -22,6 +22,10 @@
|
||||
/* long arrival_time;
|
||||
/* RECIPIENT_LIST rcpt_list;
|
||||
/* char *hop_status;
|
||||
/* char *client_name;
|
||||
/* char *client_addr;
|
||||
/* char *client_proto;
|
||||
/* char *client_helo;
|
||||
/* .in -5
|
||||
/* } DELIVER_REQUEST;
|
||||
/*
|
||||
@ -175,6 +179,10 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
|
||||
static VSTRING *address;
|
||||
static VSTRING *errors_to;
|
||||
static VSTRING *return_receipt;
|
||||
static VSTRING *client_name;
|
||||
static VSTRING *client_addr;
|
||||
static VSTRING *client_proto;
|
||||
static VSTRING *client_helo;
|
||||
long offset;
|
||||
|
||||
/*
|
||||
@ -191,6 +199,10 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
|
||||
address = vstring_alloc(10);
|
||||
errors_to = vstring_alloc(10);
|
||||
return_receipt = vstring_alloc(10);
|
||||
client_name = vstring_alloc(10);
|
||||
client_addr = vstring_alloc(10);
|
||||
client_proto = vstring_alloc(10);
|
||||
client_helo = vstring_alloc(10);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -209,7 +221,11 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
|
||||
ATTR_TYPE_STR, MAIL_ATTR_ERRTO, errors_to,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_RRCPT, return_receipt,
|
||||
ATTR_TYPE_LONG, MAIL_ATTR_TIME, &request->arrival_time,
|
||||
ATTR_TYPE_END) != 11) {
|
||||
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, client_name,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, client_addr,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, client_proto,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME, client_helo,
|
||||
ATTR_TYPE_END) != 15) {
|
||||
msg_warn("%s: error receiving common attributes", myname);
|
||||
return (-1);
|
||||
}
|
||||
@ -224,6 +240,10 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
|
||||
request->sender = mystrdup(vstring_str(address));
|
||||
request->errors_to = mystrdup(vstring_str(errors_to));
|
||||
request->return_receipt = mystrdup(vstring_str(return_receipt));
|
||||
request->client_name = mystrdup(vstring_str(client_name));
|
||||
request->client_addr = mystrdup(vstring_str(client_addr));
|
||||
request->client_proto = mystrdup(vstring_str(client_proto));
|
||||
request->client_helo = mystrdup(vstring_str(client_helo));
|
||||
|
||||
/*
|
||||
* Extract the recipient offset and address list. Skip over any
|
||||
@ -298,6 +318,10 @@ static DELIVER_REQUEST *deliver_request_alloc(void)
|
||||
request->data_size = 0;
|
||||
recipient_list_init(&request->rcpt_list);
|
||||
request->hop_status = 0;
|
||||
request->client_name = 0;
|
||||
request->client_addr = 0;
|
||||
request->client_proto = 0;
|
||||
request->client_helo = 0;
|
||||
return (request);
|
||||
}
|
||||
|
||||
@ -324,6 +348,14 @@ static void deliver_request_free(DELIVER_REQUEST *request)
|
||||
recipient_list_free(&request->rcpt_list);
|
||||
if (request->hop_status)
|
||||
myfree(request->hop_status);
|
||||
if (request->client_name)
|
||||
myfree(request->client_name);
|
||||
if (request->client_addr)
|
||||
myfree(request->client_addr);
|
||||
if (request->client_proto)
|
||||
myfree(request->client_proto);
|
||||
if (request->client_helo)
|
||||
myfree(request->client_helo);
|
||||
myfree((char *) request);
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,10 @@ typedef struct DELIVER_REQUEST {
|
||||
long arrival_time; /* arrival time */
|
||||
RECIPIENT_LIST rcpt_list; /* envelope recipients */
|
||||
char *hop_status; /* reason if unavailable */
|
||||
char *client_name; /* client hostname */
|
||||
char *client_addr; /* client address */
|
||||
char *client_proto; /* client protocol */
|
||||
char *client_helo; /* helo parameter */
|
||||
} DELIVER_REQUEST;
|
||||
|
||||
#define DEL_REQ_FLAG_DEFLT (DEL_REQ_FLAG_SUCCESS | DEL_REQ_FLAG_BOUNCE)
|
||||
|
@ -753,6 +753,10 @@ extern int var_smtp_conn_tmout;
|
||||
#define DEF_SMTP_HELO_TMOUT "300s"
|
||||
extern int var_smtp_helo_tmout;
|
||||
|
||||
#define VAR_SMTP_XCLNT_TMOUT "smtp_xclient_timeout"
|
||||
#define DEF_SMTP_XCLNT_TMOUT "300s"
|
||||
extern int var_smtp_xclnt_tmout;
|
||||
|
||||
#define VAR_SMTP_MAIL_TMOUT "smtp_mail_timeout"
|
||||
#define DEF_SMTP_MAIL_TMOUT "300s"
|
||||
extern int var_smtp_mail_tmout;
|
||||
@ -841,6 +845,10 @@ extern int var_smtp_pix_delay;
|
||||
#define DEF_SMTP_DEFER_MXADDR 0
|
||||
extern bool var_smtp_defer_mxaddr;
|
||||
|
||||
#define VAR_SMTP_SEND_XCLIENT "smtp_send_xclient_command"
|
||||
#define DEF_SMTP_SEND_XCLIENT 0
|
||||
extern bool var_smtp_send_xclient;
|
||||
|
||||
/*
|
||||
* SMTP server. The soft error limit determines how many errors an SMTP
|
||||
* client may make before we start to slow down; the hard error limit
|
||||
@ -1567,15 +1575,11 @@ extern bool var_verp_bounce_off;
|
||||
extern char *var_verp_clients;
|
||||
|
||||
/*
|
||||
* XADDR.
|
||||
* XCLIENT, for rule testing and improved post-filter logging.
|
||||
*/
|
||||
#define VAR_XADDR_CLIENTS "smtpd_authorized_xaddr_clients"
|
||||
#define DEF_XADDR_CLIENTS ""
|
||||
extern char *var_xaddr_clients;
|
||||
|
||||
#define VAR_XLOGINFO_CLIENTS "smtpd_authorized_xloginfo_clients"
|
||||
#define DEF_XLOGINFO_CLIENTS ""
|
||||
extern char *var_xloginfo_clients;
|
||||
#define VAR_XCLIENT_HOSTS "smtpd_authorized_xclient_hosts"
|
||||
#define DEF_XCLIENT_HOSTS ""
|
||||
extern char *var_xclient_hosts;
|
||||
|
||||
/*
|
||||
* Inbound mail flow control. This allows for a stiffer coupling between
|
||||
|
@ -15,6 +15,7 @@
|
||||
* System library.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Utility library.
|
||||
@ -150,6 +151,24 @@ extern char *mail_pathname(const char *, const char *);
|
||||
#define MAIL_ATTR_ORG_NONE "unknown" /* origin unknown */
|
||||
#define MAIL_ATTR_ORG_LOCAL "local" /* local submission */
|
||||
|
||||
/*
|
||||
* Internal forms for unknown XCLIENT information.
|
||||
*/
|
||||
#define CLIENT_NAME_UNKNOWN "unknown"
|
||||
#define CLIENT_ADDR_UNKNOWN "unknown"
|
||||
#define CLIENT_NAMADDR_UNKNOWN CLIENT_NAME_UNKNOWN "[" CLIENT_ADDR_UNKNOWN "]"
|
||||
#define HELO_NAME_UNKNOWN "" /* or NULL */
|
||||
#define PROTOCOL_UNKNOWN "unknown"
|
||||
|
||||
/*
|
||||
* Internal forms: recognizing unknown XCLIENT information.
|
||||
*/
|
||||
#define IS_UNK_CLNT_NAME(v) (!(v) || !strcmp((v), CLIENT_NAME_UNKNOWN))
|
||||
#define IS_UNK_CLNT_ADDR(v) (!(v) || !strcmp((v), CLIENT_ADDR_UNKNOWN))
|
||||
#define IS_UNK_CLNT_NAMADDR(v) (!(v) || !strcmp((v), CLIENT_NAMADDR_UNKNOWN))
|
||||
#define IS_UNK_HELO_NAME(v) (!(v) || !*(v))
|
||||
#define IS_UNK_PROTOCOL(v) (!(v) || !strcmp((v), PROTOCOL_UNKNOWN))
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
|
@ -84,6 +84,7 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <utime.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
* Patches change the patchlevel and the release date. Snapshots change the
|
||||
* release date only, unless they include the same bugfix as a patch release.
|
||||
*/
|
||||
#define MAIL_RELEASE_DATE "20031113"
|
||||
#define MAIL_RELEASE_DATE "20031128"
|
||||
|
||||
#define VAR_MAIL_VERSION "mail_version"
|
||||
#define DEF_MAIL_VERSION "2.0.16-" MAIL_RELEASE_DATE
|
||||
|
@ -387,7 +387,7 @@ static MIME_ENCODING mime_encoding_map[] = { /* RFC 2045 */
|
||||
* Outputs and state changes are interleaved, so we must maintain separate
|
||||
* offsets for header and body segments.
|
||||
*/
|
||||
#define HEAD_OUT(ptr, info) do { \
|
||||
#define HEAD_OUT(ptr, info, len) do { \
|
||||
(ptr)->head_out((ptr)->app_context, (ptr)->curr_state, \
|
||||
(info), (ptr)->output_buffer, (ptr)->head_offset); \
|
||||
(ptr)->head_offset += (len) + 1; \
|
||||
@ -805,7 +805,7 @@ int mime_state_update(MIME_STATE *state, int rec_type,
|
||||
|| header_info->type != HDR_CONTENT_TRANSFER_ENCODING
|
||||
|| (state->static_flags & MIME_OPT_DOWNGRADE) == 0
|
||||
|| state->curr_domain == MIME_ENC_7BIT)
|
||||
HEAD_OUT(state, header_info);
|
||||
HEAD_OUT(state, header_info, len);
|
||||
state->prev_rec_type = 0;
|
||||
VSTRING_RESET(state->output_buffer);
|
||||
}
|
||||
@ -855,7 +855,7 @@ int mime_state_update(MIME_STATE *state, int rec_type,
|
||||
cp = CU_CHAR_PTR("quoted-printable");
|
||||
vstring_sprintf(state->output_buffer,
|
||||
"Content-Transfer-Encoding: %s", cp);
|
||||
HEAD_OUT(state, (HEADER_OPTS *) 0);
|
||||
HEAD_OUT(state, (HEADER_OPTS *) 0, len);
|
||||
VSTRING_RESET(state->output_buffer);
|
||||
}
|
||||
|
||||
|
@ -182,6 +182,7 @@ VSTRING *rewrite_clnt_internal(const char *ruleset, const char *addr, VSTRING *r
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <msg_vstream.h>
|
||||
#include <split_at.h>
|
||||
#include <vstring_vstream.h>
|
||||
#include <mail_conf.h>
|
||||
#include <mail_params.h>
|
||||
@ -237,8 +238,8 @@ int main(int argc, char **argv)
|
||||
VSTRING *buffer = vstring_alloc(1);
|
||||
|
||||
while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
|
||||
if ((rule = strtok(STR(buffer), " \t,")) == 0
|
||||
|| (addr = strtok((char *) 0, " \t,")) == 0)
|
||||
if ((addr = split_at(STR(buffer), ' ')) == 0
|
||||
|| *(rule = STR(buffer)) == 0)
|
||||
usage(argv[0]);
|
||||
rewrite(rule, addr, reply);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
/* NAME
|
||||
/* xtext 3
|
||||
/* SUMMARY
|
||||
/* quote/unquote text, HTTP style.
|
||||
/* quote/unquote text, xtext style.
|
||||
/* SYNOPSIS
|
||||
/* #include <xtext.h>
|
||||
/*
|
||||
@ -11,6 +11,10 @@
|
||||
/* const char *unquoted;
|
||||
/* const char *special;
|
||||
/*
|
||||
/* VSTRING *xtext_unquote_append(unquoted, quoted)
|
||||
/* VSTRING *unquoted;
|
||||
/* const char *quoted;
|
||||
/*
|
||||
/* VSTRING *xtext_unquote(unquoted, quoted)
|
||||
/* VSTRING *unquoted;
|
||||
/* const char *quoted;
|
||||
@ -19,6 +23,9 @@
|
||||
/* +, <33(10) and >126(10), as well as characters specified with "special"
|
||||
/* by +XX, XX being the two-digit uppercase hexadecimal equivalent.
|
||||
/*
|
||||
/* xtext_quote_append() is like xtext_quote(), but appends the conversion
|
||||
/* result to the result buffer.
|
||||
/*
|
||||
/* 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
|
||||
@ -53,16 +60,17 @@
|
||||
#define STR(x) vstring_str(x)
|
||||
#define LEN(x) VSTRING_LEN(x)
|
||||
|
||||
/* xtext_quote - unquoted data to quoted */
|
||||
/* xtext_quote_append - append unquoted data to quoted data */
|
||||
|
||||
VSTRING *xtext_quote(VSTRING *quoted, const char *unquoted, const char *special)
|
||||
VSTRING *xtext_quote_append(VSTRING *quoted, const char *unquoted,
|
||||
const char *special)
|
||||
{
|
||||
const char *cp;
|
||||
int ch;
|
||||
|
||||
VSTRING_RESET(quoted);
|
||||
for (cp = unquoted; (ch = *(unsigned const char *) cp) != 0; cp++) {
|
||||
if (ch != '+' && ch > 32 && ch < 127 && strchr(special, ch) == 0) {
|
||||
if (ch != '+' && ch > 32 && ch < 127
|
||||
&& (*special == 0 || strchr(special, ch) == 0)) {
|
||||
VSTRING_ADDCH(quoted, ch);
|
||||
} else {
|
||||
vstring_sprintf_append(quoted, "+%02X", ch);
|
||||
@ -72,6 +80,15 @@ VSTRING *xtext_quote(VSTRING *quoted, const char *unquoted, const char *special)
|
||||
return (quoted);
|
||||
}
|
||||
|
||||
/* xtext_quote - unquoted data to quoted */
|
||||
|
||||
VSTRING *xtext_quote(VSTRING *quoted, const char *unquoted, const char *special)
|
||||
{
|
||||
VSTRING_RESET(quoted);
|
||||
xtext_quote_append(quoted, unquoted, special);
|
||||
return (quoted);
|
||||
}
|
||||
|
||||
/* xtext_unquote - quoted data to unquoted */
|
||||
|
||||
VSTRING *xtext_unquote(VSTRING *unquoted, const char *quoted)
|
||||
|
@ -13,13 +13,14 @@
|
||||
|
||||
/*
|
||||
* Utility library.
|
||||
*/
|
||||
*/
|
||||
#include <vstring.h>
|
||||
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
extern VSTRING *xtext_quote(VSTRING *, const char *, const char *);
|
||||
extern VSTRING *xtext_quote_append(VSTRING *, const char *, const char *);
|
||||
extern VSTRING *xtext_unquote(VSTRING *, const char *);
|
||||
|
||||
/* LICENSE
|
||||
|
@ -7,9 +7,6 @@ OBJS = lmtp.o lmtp_connect.o lmtp_proto.o lmtp_chat.o lmtp_session.o \
|
||||
lmtp_sasl_proto.o
|
||||
HDRS = lmtp.h
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -9,9 +9,6 @@ OBJS = alias.o command.o delivered.o dotforward.o file.o forward.o \
|
||||
local_expand.o
|
||||
HDRS = local.h
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
PROG = local
|
||||
|
@ -10,9 +10,6 @@ LIB_OBJ = single_server.o multi_server.o trigger_server.o master_proto.o \
|
||||
mail_flow.o
|
||||
HDRS = mail_server.h master_proto.h mail_flow.h
|
||||
INT_HDR = master.h
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
LIB = libmaster.a
|
||||
|
@ -303,7 +303,9 @@ MASTER_SERV *get_master_ent()
|
||||
MASTER_INET_ADDRLIST(serv) = (INET_ADDR_LIST *)
|
||||
mymalloc(sizeof(*MASTER_INET_ADDRLIST(serv)));
|
||||
inet_addr_list_init(MASTER_INET_ADDRLIST(serv));
|
||||
inet_addr_host(MASTER_INET_ADDRLIST(serv), host);
|
||||
if (inet_addr_host(MASTER_INET_ADDRLIST(serv), host) == 0)
|
||||
msg_fatal("%s: line %d: bad hostname or network address: %s",
|
||||
VSTREAM_PATH(master_fp), master_line, host);
|
||||
inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv));
|
||||
serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
|
||||
} else if (strcasecmp(saved_interfaces, DEF_INET_INTERFACES) == 0) {
|
||||
|
@ -9,9 +9,6 @@ OBJS = qmgr.o qmgr_active.o qmgr_transport.o qmgr_queue.o qmgr_entry.o \
|
||||
qmgr_defer.o qmgr_enable.o qmgr_scan.o qmgr_bounce.o
|
||||
HDRS = qmgr.h
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -276,6 +276,10 @@ struct QMGR_MESSAGE {
|
||||
char *redirect_addr; /* info@spammer.tld */
|
||||
long data_size; /* message content size */
|
||||
long rcpt_offset; /* more recipients here */
|
||||
char *client_name; /* client hostname */
|
||||
char *client_addr; /* client address */
|
||||
char *client_proto; /* client protocol */
|
||||
char *client_helo; /* helo parameter */
|
||||
QMGR_RCPT_LIST rcpt_list; /* complete addresses */
|
||||
int rcpt_count; /* used recipient slots */
|
||||
int rcpt_limit; /* maximum read in-core */
|
||||
|
@ -489,8 +489,9 @@ static void qmgr_active_done_3_generic(QMGR_MESSAGE *message)
|
||||
message->queue_id, message->queue_name);
|
||||
msg_warn("%s: remove %s from %s: %m", myname,
|
||||
message->queue_id, message->queue_name);
|
||||
} else if (msg_verbose) {
|
||||
msg_info("%s: remove %s", myname, message->queue_id);
|
||||
} else {
|
||||
/* Same format as logged by postsuper. */
|
||||
msg_info("%s: removed", message->queue_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,6 +161,10 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
|
||||
ATTR_TYPE_STR, MAIL_ATTR_ERRTO, message->errors_to,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_RRCPT, message->return_receipt,
|
||||
ATTR_TYPE_LONG, MAIL_ATTR_TIME, message->arrival_time,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, message->client_name,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, message->client_addr,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, message->client_proto,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME, message->client_helo,
|
||||
ATTR_TYPE_END);
|
||||
if (sender_buf != 0)
|
||||
vstring_free(sender_buf);
|
||||
|
@ -168,6 +168,10 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
|
||||
message->warn_time = 0;
|
||||
message->rcpt_offset = 0;
|
||||
message->verp_delims = 0;
|
||||
message->client_name = 0;
|
||||
message->client_addr = 0;
|
||||
message->client_proto = 0;
|
||||
message->client_helo = 0;
|
||||
qmgr_rcpt_list_init(&message->rcpt_list);
|
||||
message->rcpt_count = 0;
|
||||
message->rcpt_limit = var_qmgr_msg_rcpt_limit;
|
||||
@ -525,6 +529,27 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
|
||||
myfree(message->encoding);
|
||||
message->encoding = mystrdup(value);
|
||||
}
|
||||
/* Original client attributes. */
|
||||
if (strcmp(name, MAIL_ATTR_CLIENT_NAME) == 0) {
|
||||
if (message->client_name != 0)
|
||||
myfree(message->client_name);
|
||||
message->client_name = mystrdup(value);
|
||||
}
|
||||
if (strcmp(name, MAIL_ATTR_CLIENT_ADDR) == 0) {
|
||||
if (message->client_addr != 0)
|
||||
myfree(message->client_addr);
|
||||
message->client_addr = mystrdup(value);
|
||||
}
|
||||
if (strcmp(name, MAIL_ATTR_PROTO_NAME) == 0) {
|
||||
if (message->client_proto != 0)
|
||||
myfree(message->client_proto);
|
||||
message->client_proto = mystrdup(value);
|
||||
}
|
||||
if (strcmp(name, MAIL_ATTR_HELO_NAME) == 0) {
|
||||
if (message->client_helo != 0)
|
||||
myfree(message->client_helo);
|
||||
message->client_helo = mystrdup(value);
|
||||
}
|
||||
/* Optional tracing flags. */
|
||||
else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
|
||||
message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
|
||||
@ -586,6 +611,14 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
|
||||
message->return_receipt = mystrdup("");
|
||||
if (message->encoding == 0)
|
||||
message->encoding = mystrdup(MAIL_ATTR_ENC_NONE);
|
||||
if (message->client_name == 0)
|
||||
message->client_name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||
if (message->client_addr == 0)
|
||||
message->client_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
|
||||
if (message->client_proto == 0)
|
||||
message->client_proto = mystrdup(PROTOCOL_UNKNOWN);
|
||||
if (message->client_helo == 0)
|
||||
message->client_helo = mystrdup(HELO_NAME_UNKNOWN);
|
||||
|
||||
/*
|
||||
* Clean up.
|
||||
|
@ -3,9 +3,6 @@ SRCS = pickup.c
|
||||
OBJS = pickup.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -3,9 +3,6 @@ SRCS = pipe.c
|
||||
OBJS = pipe.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -3,9 +3,6 @@ SRCS = postalias.c
|
||||
OBJS = postalias.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -3,9 +3,6 @@ SRCS = postcat.c
|
||||
OBJS = postcat.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -3,9 +3,6 @@ SRCS = postconf.c
|
||||
OBJS = postconf.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -3,9 +3,6 @@ SRCS = postdrop.c
|
||||
OBJS = postdrop.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -3,9 +3,6 @@ SRCS = postfix.c
|
||||
OBJS = postfix.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
FILES = Makefile $(SRCS) $(HDRS)
|
||||
|
@ -3,9 +3,6 @@ SRCS = postkick.c
|
||||
OBJS = postkick.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -3,9 +3,6 @@ SRCS = postlock.c
|
||||
OBJS = postlock.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -3,9 +3,6 @@ SRCS = postlog.c
|
||||
OBJS = postlog.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
FILES = Makefile $(SRCS) $(HDRS)
|
||||
|
@ -3,9 +3,6 @@ SRCS = postmap.c
|
||||
OBJS = postmap.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -3,9 +3,6 @@ SRCS = postqueue.c
|
||||
OBJS = postqueue.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -3,9 +3,6 @@ SRCS = postsuper.c
|
||||
OBJS = postsuper.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -3,9 +3,6 @@ SRCS = proxymap.c
|
||||
OBJS = proxymap.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -7,9 +7,6 @@ OBJS = qmgr.o qmgr_active.o qmgr_transport.o qmgr_queue.o qmgr_entry.o \
|
||||
qmgr_defer.o qmgr_enable.o qmgr_scan.o qmgr_bounce.o
|
||||
HDRS = qmgr.h
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -236,6 +236,10 @@ struct QMGR_MESSAGE {
|
||||
char *redirect_addr; /* info@spammer.tld */
|
||||
long data_size; /* message content size */
|
||||
long rcpt_offset; /* more recipients here */
|
||||
char *client_name; /* client hostname */
|
||||
char *client_addr; /* client address */
|
||||
char *client_proto; /* client protocol */
|
||||
char *client_helo; /* helo parameter */
|
||||
QMGR_RCPT_LIST rcpt_list; /* complete addresses */
|
||||
};
|
||||
|
||||
|
@ -489,8 +489,9 @@ static void qmgr_active_done_3_generic(QMGR_MESSAGE *message)
|
||||
message->queue_id, message->queue_name);
|
||||
msg_warn("%s: remove %s from %s: %m", myname,
|
||||
message->queue_id, message->queue_name);
|
||||
} else if (msg_verbose) {
|
||||
msg_info("%s: remove %s", myname, message->queue_id);
|
||||
} else {
|
||||
/* Same format as logged by postsuper. */
|
||||
msg_info("%s: removed", message->queue_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,6 +156,10 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
|
||||
ATTR_TYPE_STR, MAIL_ATTR_ERRTO, message->errors_to,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_RRCPT, message->return_receipt,
|
||||
ATTR_TYPE_LONG, MAIL_ATTR_TIME, message->arrival_time,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, message->client_name,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, message->client_addr,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, message->client_proto,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME, message->client_helo,
|
||||
ATTR_TYPE_END);
|
||||
if (sender_buf != 0)
|
||||
vstring_free(sender_buf);
|
||||
|
@ -158,6 +158,10 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
|
||||
message->warn_time = 0;
|
||||
message->rcpt_offset = 0;
|
||||
message->verp_delims = 0;
|
||||
message->client_name = 0;
|
||||
message->client_addr = 0;
|
||||
message->client_proto = 0;
|
||||
message->client_helo = 0;
|
||||
qmgr_rcpt_list_init(&message->rcpt_list);
|
||||
return (message);
|
||||
}
|
||||
@ -490,6 +494,27 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
|
||||
myfree(message->encoding);
|
||||
message->encoding = mystrdup(value);
|
||||
}
|
||||
/* Original client attributes. */
|
||||
if (strcmp(name, MAIL_ATTR_CLIENT_NAME) == 0) {
|
||||
if (message->client_name != 0)
|
||||
myfree(message->client_name);
|
||||
message->client_name = mystrdup(value);
|
||||
}
|
||||
if (strcmp(name, MAIL_ATTR_CLIENT_ADDR) == 0) {
|
||||
if (message->client_addr != 0)
|
||||
myfree(message->client_addr);
|
||||
message->client_addr = mystrdup(value);
|
||||
}
|
||||
if (strcmp(name, MAIL_ATTR_PROTO_NAME) == 0) {
|
||||
if (message->client_proto != 0)
|
||||
myfree(message->client_proto);
|
||||
message->client_proto = mystrdup(value);
|
||||
}
|
||||
if (strcmp(name, MAIL_ATTR_HELO_NAME) == 0) {
|
||||
if (message->client_helo != 0)
|
||||
myfree(message->client_helo);
|
||||
message->client_helo = mystrdup(value);
|
||||
}
|
||||
/* Optional tracing flags. */
|
||||
else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
|
||||
message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
|
||||
@ -551,6 +576,14 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
|
||||
message->return_receipt = mystrdup("");
|
||||
if (message->encoding == 0)
|
||||
message->encoding = mystrdup(MAIL_ATTR_ENC_NONE);
|
||||
if (message->client_name == 0)
|
||||
message->client_name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||
if (message->client_addr == 0)
|
||||
message->client_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
|
||||
if (message->client_proto == 0)
|
||||
message->client_proto = mystrdup(PROTOCOL_UNKNOWN);
|
||||
if (message->client_helo == 0)
|
||||
message->client_helo = mystrdup(HELO_NAME_UNKNOWN);
|
||||
|
||||
/*
|
||||
* Clean up.
|
||||
|
@ -3,9 +3,6 @@ SRCS = qmqpd.c qmqpd_state.c qmqpd_peer.c
|
||||
OBJS = qmqpd.o qmqpd_state.o qmqpd_peer.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -3,9 +3,6 @@ SRCS = sendmail.c
|
||||
OBJS = sendmail.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -740,7 +740,7 @@ int main(int argc, char **argv)
|
||||
for (fd = 0; fd < 3; fd++)
|
||||
if (fstat(fd, &st) == -1
|
||||
&& (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
|
||||
msg_fatal_status(EX_UNAVAILABLE, "open /dev/null: %m");
|
||||
msg_fatal_status(EX_OSERR, "open /dev/null: %m");
|
||||
|
||||
/*
|
||||
* The CDE desktop calendar manager leaks a parent file descriptor into
|
||||
|
@ -3,9 +3,6 @@ SRCS = showq.c
|
||||
OBJS = showq.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -7,9 +7,6 @@ OBJS = smtp.o smtp_connect.o smtp_proto.o smtp_chat.o smtp_session.o \
|
||||
smtp_sasl_proto.o smtp_sasl_glue.o
|
||||
HDRS = smtp.h smtp_sasl.h
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG= smtp_unalias
|
||||
@ -176,6 +173,7 @@ smtp_proto.o: ../../include/mail_proto.h
|
||||
smtp_proto.o: ../../include/attr.h
|
||||
smtp_proto.o: ../../include/mime_state.h
|
||||
smtp_proto.o: ../../include/header_opts.h
|
||||
smtp_proto.o: ../../include/xtext.h
|
||||
smtp_proto.o: smtp.h
|
||||
smtp_proto.o: ../../include/argv.h
|
||||
smtp_proto.o: smtp_sasl.h
|
||||
|
@ -194,6 +194,9 @@
|
||||
/* .IP \fBsmtp_helo_timeout\fR
|
||||
/* Timeout for sending the \fBHELO\fR command, and for
|
||||
/* receiving the server response.
|
||||
/* .IP \fBsmtp_xclient_timeout\fR
|
||||
/* Timeout for sending the \fBXCLIENT\fR command, and for
|
||||
/* receiving the server response.
|
||||
/* .IP \fBsmtp_mail_timeout\fR
|
||||
/* Timeout for sending the \fBMAIL FROM\fR command, and for
|
||||
/* receiving the server response.
|
||||
@ -215,6 +218,11 @@
|
||||
/* than the local MTA).
|
||||
/* If yes, keep trying until a suitable MX host resolves or until
|
||||
/* the mail is too old.
|
||||
/* .IP \fBsmtp_send_xclient_command\fR
|
||||
/* If the SMTP server announces XCLIENT support, send the name,
|
||||
/* address, protocol and HELO name of the original client. This
|
||||
/* can be used to forward client information through a content
|
||||
/* filter to a downstream queuing SMTP server.
|
||||
/* .IP \fBsmtp_rset_timeout\fR
|
||||
/* Timeout for sending the \fBRSET\fR command.
|
||||
/* .IP \fBsmtp_quit_timeout\fR
|
||||
@ -275,6 +283,7 @@
|
||||
*/
|
||||
int var_smtp_conn_tmout;
|
||||
int var_smtp_helo_tmout;
|
||||
int var_smtp_xclnt_tmout;
|
||||
int var_smtp_mail_tmout;
|
||||
int var_smtp_rcpt_tmout;
|
||||
int var_smtp_data0_tmout;
|
||||
@ -305,6 +314,7 @@ char *var_smtp_helo_name;
|
||||
char *var_smtp_host_lookup;
|
||||
bool var_smtp_quote_821_env;
|
||||
bool var_smtp_defer_mxaddr;
|
||||
bool var_smtp_send_xclient;
|
||||
|
||||
/*
|
||||
* Global variables. smtp_errno is set by the address lookup routines and by
|
||||
@ -492,6 +502,7 @@ int main(int argc, char **argv)
|
||||
static CONFIG_TIME_TABLE time_table[] = {
|
||||
VAR_SMTP_CONN_TMOUT, DEF_SMTP_CONN_TMOUT, &var_smtp_conn_tmout, 0, 0,
|
||||
VAR_SMTP_HELO_TMOUT, DEF_SMTP_HELO_TMOUT, &var_smtp_helo_tmout, 1, 0,
|
||||
VAR_SMTP_XCLNT_TMOUT, DEF_SMTP_XCLNT_TMOUT, &var_smtp_xclnt_tmout, 1, 0,
|
||||
VAR_SMTP_MAIL_TMOUT, DEF_SMTP_MAIL_TMOUT, &var_smtp_mail_tmout, 1, 0,
|
||||
VAR_SMTP_RCPT_TMOUT, DEF_SMTP_RCPT_TMOUT, &var_smtp_rcpt_tmout, 1, 0,
|
||||
VAR_SMTP_DATA0_TMOUT, DEF_SMTP_DATA0_TMOUT, &var_smtp_data0_tmout, 1, 0,
|
||||
@ -518,6 +529,7 @@ int main(int argc, char **argv)
|
||||
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,
|
||||
VAR_SMTP_DEFER_MXADDR, DEF_SMTP_DEFER_MXADDR, &var_smtp_defer_mxaddr,
|
||||
VAR_SMTP_SEND_XCLIENT, DEF_SMTP_SEND_XCLIENT, &var_smtp_send_xclient,
|
||||
0,
|
||||
};
|
||||
|
||||
|
@ -64,6 +64,7 @@ typedef struct SMTP_STATE {
|
||||
#define SMTP_FEATURE_STARTTLS (1<<4)
|
||||
#define SMTP_FEATURE_AUTH (1<<5)
|
||||
#define SMTP_FEATURE_MAYBEPIX (1<<6) /* PIX smtp fixup mode */
|
||||
#define SMTP_FEATURE_XCLIENT (1<<7) /* server supports XCLIENT */
|
||||
|
||||
/*
|
||||
* smtp.c
|
||||
|
@ -103,6 +103,7 @@
|
||||
#include <quote_821_local.h>
|
||||
#include <mail_proto.h>
|
||||
#include <mime_state.h>
|
||||
#include <xtext.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@ -123,15 +124,19 @@
|
||||
* SMTP_STATE_DOT) must have smaller numerical values than the non-sending
|
||||
* states (SMTP_STATE_ABORT .. SMTP_STATE_LAST).
|
||||
*/
|
||||
#define SMTP_STATE_MAIL 0
|
||||
#define SMTP_STATE_RCPT 1
|
||||
#define SMTP_STATE_DATA 2
|
||||
#define SMTP_STATE_DOT 3
|
||||
#define SMTP_STATE_ABORT 4
|
||||
#define SMTP_STATE_QUIT 5
|
||||
#define SMTP_STATE_LAST 6
|
||||
#define SMTP_STATE_XCLIENT_ADDR 0
|
||||
#define SMTP_STATE_XCLIENT_HELO 1
|
||||
#define SMTP_STATE_MAIL 2
|
||||
#define SMTP_STATE_RCPT 3
|
||||
#define SMTP_STATE_DATA 4
|
||||
#define SMTP_STATE_DOT 5
|
||||
#define SMTP_STATE_ABORT 6
|
||||
#define SMTP_STATE_QUIT 7
|
||||
#define SMTP_STATE_LAST 8
|
||||
|
||||
int *xfer_timeouts[SMTP_STATE_LAST] = {
|
||||
&var_smtp_xclnt_tmout,
|
||||
&var_smtp_xclnt_tmout,
|
||||
&var_smtp_mail_tmout,
|
||||
&var_smtp_rcpt_tmout,
|
||||
&var_smtp_data0_tmout,
|
||||
@ -141,6 +146,8 @@ int *xfer_timeouts[SMTP_STATE_LAST] = {
|
||||
};
|
||||
|
||||
char *xfer_states[SMTP_STATE_LAST] = {
|
||||
"sending XCLIENT address and name",
|
||||
"sending XCLIENT helo_name and protocol",
|
||||
"sending MAIL FROM",
|
||||
"sending RCPT TO",
|
||||
"sending DATA command",
|
||||
@ -150,6 +157,8 @@ char *xfer_states[SMTP_STATE_LAST] = {
|
||||
};
|
||||
|
||||
char *xfer_request[SMTP_STATE_LAST] = {
|
||||
"XCLIENT command",
|
||||
"XCLIENT command",
|
||||
"MAIL FROM command",
|
||||
"RCPT TO command",
|
||||
"DATA command",
|
||||
@ -250,6 +259,8 @@ int smtp_helo(SMTP_STATE *state)
|
||||
state->features |= SMTP_FEATURE_8BITMIME;
|
||||
else if (strcasecmp(word, "PIPELINING") == 0)
|
||||
state->features |= SMTP_FEATURE_PIPELINING;
|
||||
else if (strcasecmp(word, "XCLIENT") == 0)
|
||||
state->features |= SMTP_FEATURE_XCLIENT;
|
||||
else if (strcasecmp(word, "SIZE") == 0) {
|
||||
state->features |= SMTP_FEATURE_SIZE;
|
||||
if ((word = mystrtok(&words, " \t")) != 0) {
|
||||
@ -374,6 +385,8 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
int mail_from_rejected;
|
||||
int downgrading;
|
||||
int mime_errs;
|
||||
int send_xclient_addr = 0;
|
||||
int send_xclient_helo = 0;
|
||||
|
||||
/*
|
||||
* Macros for readability.
|
||||
@ -472,9 +485,23 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
* receiver detects a serious problem (MAIL FROM rejected, all RCPT TO
|
||||
* commands rejected, DATA rejected) it forces the sender to abort the
|
||||
* SMTP dialog with RSET and QUIT.
|
||||
*
|
||||
* Send "XCLIENT LOG" information only if we have a surrogate remote client
|
||||
* name and address, i.e. the mail was actually received from the
|
||||
* network. Since "XCLIENT LOG" overrides all remote client logging
|
||||
* attributes, there is no need to send helo or protocol information that
|
||||
* we do not have.
|
||||
*/
|
||||
nrcpt = 0;
|
||||
recv_state = send_state = SMTP_STATE_MAIL;
|
||||
send_xclient_addr = (state->features & SMTP_FEATURE_XCLIENT)
|
||||
&& !IS_UNK_CLNT_NAME(request->client_name)
|
||||
&& !IS_UNK_CLNT_ADDR(request->client_addr);
|
||||
if (send_xclient_addr) {
|
||||
send_xclient_helo = !IS_UNK_HELO_NAME(request->client_helo)
|
||||
|| !IS_UNK_PROTOCOL(request->client_proto);
|
||||
recv_state = send_state = SMTP_STATE_XCLIENT_ADDR;
|
||||
} else
|
||||
recv_state = send_state = SMTP_STATE_MAIL;
|
||||
next_rcpt = send_rcpt = recv_rcpt = 0;
|
||||
mail_from_rejected = 0;
|
||||
|
||||
@ -491,6 +518,41 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
default:
|
||||
msg_panic("%s: bad sender state %d", myname, send_state);
|
||||
|
||||
/*
|
||||
* Build the XCLIENT command. Send what we know, converting
|
||||
* internal form to external form. With properly sanitized
|
||||
* information, this stays within the 512 byte command line
|
||||
* length limit.
|
||||
*/
|
||||
case SMTP_STATE_XCLIENT_ADDR:
|
||||
vstring_sprintf(next_command, "XCLIENT LOG");
|
||||
if (!IS_UNK_CLNT_NAME(request->client_name)) {
|
||||
vstring_strcat(next_command, " CLIENT_NAME=");
|
||||
xtext_quote_append(next_command, request->client_name, "");
|
||||
}
|
||||
if (!IS_UNK_CLNT_ADDR(request->client_addr)) {
|
||||
vstring_strcat(next_command, " CLIENT_ADDR=");
|
||||
xtext_quote_append(next_command, request->client_addr, "");
|
||||
}
|
||||
if (send_xclient_helo)
|
||||
next_state = SMTP_STATE_XCLIENT_HELO;
|
||||
else
|
||||
next_state = SMTP_STATE_MAIL;
|
||||
break;
|
||||
|
||||
case SMTP_STATE_XCLIENT_HELO:
|
||||
vstring_sprintf(next_command, "XCLIENT");
|
||||
if (!IS_UNK_HELO_NAME(request->client_helo)) {
|
||||
vstring_strcat(next_command, " HELO_NAME=");
|
||||
xtext_quote_append(next_command, request->client_helo, "");
|
||||
}
|
||||
if (!IS_UNK_PROTOCOL(request->client_proto)) {
|
||||
vstring_strcat(next_command, " PROTOCOL=");
|
||||
xtext_quote_append(next_command, request->client_proto, "");
|
||||
}
|
||||
next_state = SMTP_STATE_MAIL;
|
||||
break;
|
||||
|
||||
/*
|
||||
* Build the MAIL FROM command.
|
||||
*/
|
||||
@ -600,7 +662,7 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
/*
|
||||
* Sanity check.
|
||||
*/
|
||||
if (recv_state < SMTP_STATE_MAIL
|
||||
if (recv_state < SMTP_STATE_XCLIENT_ADDR
|
||||
|| recv_state > SMTP_STATE_QUIT)
|
||||
msg_panic("%s: bad receiver state %d (sender state %d)",
|
||||
myname, recv_state, send_state);
|
||||
@ -621,6 +683,20 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
*/
|
||||
switch (recv_state) {
|
||||
|
||||
/*
|
||||
* Ignore the XCLIENT response. No Duff device needed.
|
||||
*/
|
||||
case SMTP_STATE_XCLIENT_ADDR:
|
||||
if (send_xclient_helo)
|
||||
recv_state = SMTP_STATE_XCLIENT_HELO;
|
||||
else
|
||||
recv_state = SMTP_STATE_MAIL;
|
||||
break;
|
||||
|
||||
case SMTP_STATE_XCLIENT_HELO:
|
||||
recv_state = SMTP_STATE_MAIL;
|
||||
break;
|
||||
|
||||
/*
|
||||
* Process the MAIL FROM response. When the server
|
||||
* rejects the sender, set the mail_from_rejected flag so
|
||||
|
@ -1,14 +1,13 @@
|
||||
SHELL = /bin/sh
|
||||
SRCS = smtpd.c smtpd_token.c smtpd_check.c smtpd_chat.c smtpd_state.c \
|
||||
smtpd_peer.c smtpd_sasl_proto.c smtpd_sasl_glue.c smtpd_proxy.c
|
||||
smtpd_peer.c smtpd_sasl_proto.c smtpd_sasl_glue.c smtpd_proxy.c \
|
||||
smtpd_xclient.c
|
||||
OBJS = smtpd.o smtpd_token.o smtpd_check.o smtpd_chat.o smtpd_state.o \
|
||||
smtpd_peer.o smtpd_sasl_proto.o smtpd_sasl_glue.o smtpd_proxy.o
|
||||
smtpd_peer.o smtpd_sasl_proto.o smtpd_sasl_glue.o smtpd_proxy.o \
|
||||
smtpd_xclient.o
|
||||
HDRS = smtpd_token.h smtpd_check.h smtpd_chat.h smtpd_sasl_proto.h \
|
||||
smtpd_sasl_glue.h smtpd_proxy.h
|
||||
TESTSRC = smtpd_token_test.c
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG= smtpd_token smtpd_check
|
||||
@ -122,6 +121,7 @@ smtpd.o: ../../include/dict.h
|
||||
smtpd.o: ../../include/argv.h
|
||||
smtpd.o: ../../include/watchdog.h
|
||||
smtpd.o: ../../include/iostuff.h
|
||||
smtpd.o: ../../include/split_at.h
|
||||
smtpd.o: ../../include/mail_params.h
|
||||
smtpd.o: ../../include/record.h
|
||||
smtpd.o: ../../include/rec_type.h
|
||||
@ -150,6 +150,7 @@ smtpd.o: ../../include/namadr_list.h
|
||||
smtpd.o: ../../include/input_transp.h
|
||||
smtpd.o: ../../include/anvil_clnt.h
|
||||
smtpd.o: ../../include/attr_clnt.h
|
||||
smtpd.o: ../../include/xtext.h
|
||||
smtpd.o: ../../include/mail_server.h
|
||||
smtpd.o: smtpd_token.h
|
||||
smtpd.o: smtpd.h
|
||||
@ -243,8 +244,11 @@ smtpd_peer.o: ../../include/valid_hostname.h
|
||||
smtpd_peer.o: ../../include/stringops.h
|
||||
smtpd_peer.o: ../../include/vstring.h
|
||||
smtpd_peer.o: ../../include/vbuf.h
|
||||
smtpd_peer.o: smtpd.h
|
||||
smtpd_peer.o: ../../include/mail_proto.h
|
||||
smtpd_peer.o: ../../include/vstream.h
|
||||
smtpd_peer.o: ../../include/iostuff.h
|
||||
smtpd_peer.o: ../../include/attr.h
|
||||
smtpd_peer.o: smtpd.h
|
||||
smtpd_peer.o: ../../include/argv.h
|
||||
smtpd_peer.o: ../../include/mail_stream.h
|
||||
smtpd_proxy.o: smtpd_proxy.c
|
||||
@ -262,6 +266,9 @@ 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: ../../include/xtext.h
|
||||
smtpd_proxy.o: ../../include/mail_proto.h
|
||||
smtpd_proxy.o: ../../include/attr.h
|
||||
smtpd_proxy.o: smtpd.h
|
||||
smtpd_proxy.o: ../../include/argv.h
|
||||
smtpd_proxy.o: ../../include/mail_stream.h
|
||||
@ -331,3 +338,16 @@ smtpd_token.o: ../../include/mvect.h
|
||||
smtpd_token.o: smtpd_token.h
|
||||
smtpd_token.o: ../../include/vstring.h
|
||||
smtpd_token.o: ../../include/vbuf.h
|
||||
smtpd_xclient.o: smtpd_xclient.c
|
||||
smtpd_xclient.o: ../../include/sys_defs.h
|
||||
smtpd_xclient.o: ../../include/mymalloc.h
|
||||
smtpd_xclient.o: ../../include/msg.h
|
||||
smtpd_xclient.o: ../../include/mail_proto.h
|
||||
smtpd_xclient.o: ../../include/vstream.h
|
||||
smtpd_xclient.o: ../../include/vbuf.h
|
||||
smtpd_xclient.o: ../../include/iostuff.h
|
||||
smtpd_xclient.o: ../../include/attr.h
|
||||
smtpd_xclient.o: smtpd.h
|
||||
smtpd_xclient.o: ../../include/vstring.h
|
||||
smtpd_xclient.o: ../../include/argv.h
|
||||
smtpd_xclient.o: ../../include/mail_stream.h
|
||||
|
@ -143,20 +143,12 @@
|
||||
/* .IP \fBsmtpd_authorized_verp_clients\fR
|
||||
/* Hostnames, domain names and/or addresses of clients that are
|
||||
/* authorized to use the XVERP extension.
|
||||
/* .IP \fBsmtpd_authorized_xaddr_clients\fR
|
||||
/* .IP \fBsmtpd_authorized_xclient_hosts\fR
|
||||
/* Hostnames, domain names and/or addresses of clients that are
|
||||
/* authorized to use the "XADDR client-address client-name" command.
|
||||
/* This changes Postfix's
|
||||
/* idea of the SMTP client IP address and hostname for access
|
||||
/* control and for logging purposes.
|
||||
/* .IP \fBsmtpd_authorized_xloginfo_clients\fR
|
||||
/* Hostnames, domain names and/or addresses of clients that are
|
||||
/* authorized to use the "XLOGINFO client-address client-name" command.
|
||||
/* This changes the client
|
||||
/* name and address that are used for logging, without affecting the
|
||||
/* client IP address and hostname that are used for access control.
|
||||
/* XLOGINFO is typically used to propagate remote client information
|
||||
/* through an SMTP-based content filter to the after-filter SMTP server.
|
||||
/* authorized to use the XCLIENT command. This command changes
|
||||
/* client information for access control and/or logging purposes,
|
||||
/* with the exception of the
|
||||
/* \fBsmtpd_authorized_xclient_hosts\fR access control itself.
|
||||
/* .IP \fBdebug_peer_level\fR
|
||||
/* Increment in verbose logging level when a remote host matches a
|
||||
/* pattern in the \fBdebug_peer_list\fR parameter.
|
||||
@ -437,6 +429,7 @@
|
||||
#include <dict.h>
|
||||
#include <watchdog.h>
|
||||
#include <iostuff.h>
|
||||
#include <split_at.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
@ -461,6 +454,7 @@
|
||||
#include <namadr_list.h>
|
||||
#include <input_transp.h>
|
||||
#include <anvil_clnt.h>
|
||||
#include <xtext.h>
|
||||
|
||||
/* Single-threaded server skeleton. */
|
||||
|
||||
@ -557,8 +551,7 @@ char *var_input_transp;
|
||||
int var_smtpd_policy_tmout;
|
||||
int var_smtpd_policy_idle;
|
||||
int var_smtpd_policy_ttl;
|
||||
char *var_xaddr_clients;
|
||||
char *var_xloginfo_clients;
|
||||
char *var_xclient_hosts;
|
||||
int var_smtpd_crate_limit;
|
||||
int var_smtpd_cconn_limit;
|
||||
char *var_smtpd_hoggers;
|
||||
@ -578,16 +571,9 @@ char *var_smtpd_hoggers;
|
||||
static NAMADR_LIST *verp_clients;
|
||||
|
||||
/*
|
||||
* XADDR command.
|
||||
* XCLIENT command.
|
||||
*/
|
||||
#define XADDR_CMD "XADDR"
|
||||
|
||||
static NAMADR_LIST *xaddr_clients;
|
||||
|
||||
/*
|
||||
* XLOGINFO command.
|
||||
*/
|
||||
static NAMADR_LIST *xloginfo_clients;
|
||||
static NAMADR_LIST *xclient_hosts;
|
||||
|
||||
/*
|
||||
* Client connection and rate limiting.
|
||||
@ -630,11 +616,10 @@ static int sasl_client_exception(SMTPD_STATE *state)
|
||||
return (0);
|
||||
|
||||
match = namadr_list_match(sasl_exceptions_networks,
|
||||
state->name, state->addr);
|
||||
ACL_NAME(state), ACL_ADDR(state));
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("sasl_exceptions: %s[%s], match=%d",
|
||||
state->name, state->addr, match);
|
||||
msg_info("sasl_exceptions: %s, match=%d", ACL_NAMADDR(state), match);
|
||||
|
||||
return (match);
|
||||
}
|
||||
@ -679,6 +664,8 @@ static int helo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
mail_reset(state);
|
||||
rcpt_reset(state);
|
||||
state->helo_name = mystrdup(printable(argv[1].strval, '?'));
|
||||
neuter(state->helo_name, "<>()\\\";:@", '?');
|
||||
/* Changing the protocol name breaks the unauthorized pipelining check. */
|
||||
if (strcmp(state->protocol, MAIL_PROTO_ESMTP) != 0)
|
||||
state->protocol = MAIL_PROTO_SMTP;
|
||||
smtpd_chat_reply(state, "250 %s", var_myhostname);
|
||||
@ -715,6 +702,7 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
mail_reset(state);
|
||||
rcpt_reset(state);
|
||||
state->helo_name = mystrdup(printable(argv[1].strval, '?'));
|
||||
neuter(state->helo_name, "<>()\\\";:@", '?');
|
||||
state->protocol = MAIL_PROTO_ESMTP;
|
||||
smtpd_chat_reply(state, "250-%s", var_myhostname);
|
||||
smtpd_chat_reply(state, "250-PIPELINING");
|
||||
@ -733,12 +721,11 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
smtpd_chat_reply(state, "250-AUTH=%s", state->sasl_mechanism_list);
|
||||
}
|
||||
#endif
|
||||
if (namadr_list_match(verp_clients, state->name, state->addr))
|
||||
if (namadr_list_match(verp_clients, ACL_NAME(state), ACL_ADDR(state)))
|
||||
smtpd_chat_reply(state, "250-%s", VERP_CMD);
|
||||
if (namadr_list_match(xaddr_clients, state->name, state->addr))
|
||||
smtpd_chat_reply(state, "250-%s", XADDR_CMD);
|
||||
if (namadr_list_match(xloginfo_clients, state->name, state->addr))
|
||||
smtpd_chat_reply(state, "250-%s", XLOGINFO_CMD);
|
||||
/* XCLIENT must not override its own access control. */
|
||||
if (namadr_list_match(xclient_hosts, state->name, state->addr))
|
||||
smtpd_chat_reply(state, "250-%s", XCLIENT_CMD);
|
||||
smtpd_chat_reply(state, "250 8BITMIME");
|
||||
return (0);
|
||||
}
|
||||
@ -754,8 +741,7 @@ static void helo_reset(SMTPD_STATE *state)
|
||||
|
||||
/* mail_open_stream - open mail queue file or IPC stream */
|
||||
|
||||
static void mail_open_stream(SMTPD_STATE *state, SMTPD_TOKEN *argv,
|
||||
const char *encoding, const char *verp_delims)
|
||||
static void mail_open_stream(SMTPD_STATE *state, SMTPD_TOKEN *argv)
|
||||
{
|
||||
char *postdrop_command;
|
||||
int cleanup_flags;
|
||||
@ -816,7 +802,7 @@ static void mail_open_stream(SMTPD_STATE *state, SMTPD_TOKEN *argv,
|
||||
smtpd_sasl_mail_log(state);
|
||||
else
|
||||
#endif
|
||||
msg_info("%s: client=%s", state->queue_id, state->namaddr);
|
||||
msg_info("%s: client=%s", state->queue_id, LOG_NAMADDR(state));
|
||||
|
||||
/*
|
||||
* Record the time of arrival, the sender envelope address, some session
|
||||
@ -828,24 +814,29 @@ static void mail_open_stream(SMTPD_STATE *state, SMTPD_TOKEN *argv,
|
||||
rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport);
|
||||
}
|
||||
rec_fputs(state->cleanup, REC_TYPE_FROM, argv[2].strval);
|
||||
if (encoding != 0)
|
||||
if (state->encoding != 0)
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_ENCODING, encoding);
|
||||
MAIL_ATTR_ENCODING, state->encoding);
|
||||
|
||||
/*
|
||||
* Store the client attributes for logging purposes.
|
||||
*/
|
||||
if (SMTPD_STAND_ALONE(state) == 0) {
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_CLIENT_NAME, state->name);
|
||||
MAIL_ATTR_CLIENT_NAME, LOG_NAME(state));
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_CLIENT_ADDR, state->addr);
|
||||
MAIL_ATTR_CLIENT_ADDR, LOG_ADDR(state));
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_ORIGIN, state->namaddr);
|
||||
if (state->helo_name != 0)
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_HELO_NAME, state->helo_name);
|
||||
MAIL_ATTR_ORIGIN, LOG_NAMADDR(state));
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_PROTO_NAME, state->protocol);
|
||||
MAIL_ATTR_HELO_NAME,
|
||||
IS_UNK_HELO_NAME(LOG_HELO_NAME(state)) ?
|
||||
HELO_NAME_UNKNOWN : LOG_HELO_NAME(state));
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_PROTO_NAME, LOG_PROTOCOL(state));
|
||||
}
|
||||
if (verp_delims)
|
||||
rec_fputs(state->cleanup, REC_TYPE_VERP, verp_delims);
|
||||
if (state->verp_delims)
|
||||
rec_fputs(state->cleanup, REC_TYPE_VERP, state->verp_delims);
|
||||
}
|
||||
|
||||
/* extract_addr - extract address from rubble */
|
||||
@ -965,8 +956,8 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
int narg;
|
||||
char *arg;
|
||||
char *verp_delims = 0;
|
||||
char *encoding = 0;
|
||||
|
||||
state->encoding = 0;
|
||||
state->msg_size = 0;
|
||||
|
||||
/*
|
||||
@ -983,7 +974,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
smtpd_chat_reply(state, "503 Error: send HELO/EHLO first");
|
||||
return (-1);
|
||||
}
|
||||
#define IN_MAIL_TRANSACTION(state) ((state)->cleanup || (state)->proxy)
|
||||
#define IN_MAIL_TRANSACTION(state) ((state)->sender != 0)
|
||||
|
||||
if (IN_MAIL_TRANSACTION(state)) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
@ -998,7 +989,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
}
|
||||
if (argv[2].tokval == SMTPD_TOK_ERROR) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad address syntax");
|
||||
smtpd_chat_reply(state, "501 Bad sender address syntax");
|
||||
return (-1);
|
||||
}
|
||||
if ((err = extract_addr(state, argv + 2, PERMIT_EMPTY_ADDR, var_strict_rfc821_env)) != 0) {
|
||||
@ -1009,9 +1000,9 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
for (narg = 3; narg < argc; narg++) {
|
||||
arg = argv[narg].strval;
|
||||
if (strcasecmp(arg, "BODY=8BITMIME") == 0) { /* RFC 1652 */
|
||||
encoding = MAIL_ATTR_ENC_8BIT;
|
||||
state->encoding = MAIL_ATTR_ENC_8BIT;
|
||||
} else if (strcasecmp(arg, "BODY=7BIT") == 0) { /* RFC 1652 */
|
||||
encoding = MAIL_ATTR_ENC_7BIT;
|
||||
state->encoding = MAIL_ATTR_ENC_7BIT;
|
||||
} else if (strncasecmp(arg, "SIZE=", 5) == 0) { /* RFC 1870 */
|
||||
/* Reject non-numeric size. */
|
||||
if (!alldig(arg + 5)) {
|
||||
@ -1032,11 +1023,13 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
} else if (namadr_list_match(verp_clients, state->name, state->addr)) {
|
||||
if (strcasecmp(arg, VERP_CMD) == 0) {
|
||||
} else if (namadr_list_match(verp_clients, ACL_NAME(state),
|
||||
ACL_ADDR(state))
|
||||
&& strncasecmp(arg, VERP_CMD, VERP_CMD_LEN) == 0
|
||||
&& (arg[VERP_CMD_LEN] == '=' || arg[VERP_CMD_LEN] == 0)) {
|
||||
if (arg[VERP_CMD_LEN] == 0) {
|
||||
verp_delims = var_verp_delims;
|
||||
} else if (strncasecmp(arg, VERP_CMD, VERP_CMD_LEN) == 0
|
||||
&& arg[VERP_CMD_LEN] == '=') {
|
||||
} else {
|
||||
verp_delims = arg + VERP_CMD_LEN + 1;
|
||||
if (verp_delims_verify(verp_delims) != 0) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
@ -1065,28 +1058,26 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
state->time = time((time_t *) 0);
|
||||
|
||||
/*
|
||||
* Open connection to SMTP proxy server.
|
||||
* Check the queue file space, if applicable.
|
||||
*/
|
||||
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));
|
||||
#define USE_SMTPD_PROXY(state) \
|
||||
(SMTPD_STAND_ALONE(state) == 0 && *var_smtpd_proxy_filt)
|
||||
|
||||
if (!USE_SMTPD_PROXY(state)) {
|
||||
if ((err = smtpd_check_size(state, state->msg_size)) != 0) {
|
||||
smtpd_chat_reply(state, "%s", err);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Open queue file, or open connection to queue file writing process.
|
||||
* Check for queue file space first.
|
||||
* No more early returns. The mail transaction is in progress.
|
||||
*/
|
||||
else {
|
||||
if ((err = smtpd_check_size(state, state->msg_size)) != 0) {
|
||||
smtpd_chat_reply(state, "%s", err);
|
||||
return (-1);
|
||||
}
|
||||
mail_open_stream(state, argv, encoding, verp_delims);
|
||||
}
|
||||
state->sender = mystrdup(argv[2].strval);
|
||||
if (verp_delims)
|
||||
state->verp_delims = mystrdup(verp_delims);
|
||||
if (USE_SMTPD_PROXY(state))
|
||||
state->proxy_mail = mystrdup(STR(state->buffer));
|
||||
smtpd_chat_reply(state, "250 Ok");
|
||||
return (0);
|
||||
}
|
||||
@ -1115,6 +1106,10 @@ static void mail_reset(SMTPD_STATE *state)
|
||||
myfree(state->sender);
|
||||
state->sender = 0;
|
||||
}
|
||||
if (state->verp_delims) {
|
||||
myfree(state->verp_delims);
|
||||
state->verp_delims = 0;
|
||||
}
|
||||
#ifdef USE_SASL_AUTH
|
||||
if (var_smtpd_sasl_enable)
|
||||
smtpd_sasl_mail_reset(state);
|
||||
@ -1129,6 +1124,10 @@ static void mail_reset(SMTPD_STATE *state)
|
||||
(void) smtpd_proxy_cmd(state, SMTPD_PROX_WANT_NONE, "QUIT");
|
||||
smtpd_proxy_close(state);
|
||||
}
|
||||
if (state->proxy_mail) {
|
||||
myfree(state->proxy_mail);
|
||||
state->proxy_mail = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* rcpt_cmd - process RCPT TO command */
|
||||
@ -1161,7 +1160,7 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
}
|
||||
if (argv[2].tokval == SMTPD_TOK_ERROR) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad address syntax");
|
||||
smtpd_chat_reply(state, "501 Bad recipient address syntax");
|
||||
return (-1);
|
||||
}
|
||||
if ((err = extract_addr(state, argv + 2, REJECT_EMPTY_ADDR, var_strict_rfc821_env)) != 0) {
|
||||
@ -1188,6 +1187,21 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't access the proxy, queue file, or queue file writer process until
|
||||
* we have a valid recipient address.
|
||||
*/
|
||||
if (state->proxy == 0 && state->proxy_mail) {
|
||||
if (smtpd_proxy_open(state, var_smtpd_proxy_filt,
|
||||
var_smtpd_proxy_tmout, var_smtpd_proxy_ehlo,
|
||||
state->proxy_mail) != 0) {
|
||||
smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
|
||||
return (-1);
|
||||
}
|
||||
} else if (state->cleanup == 0) {
|
||||
mail_open_stream(state, argv);
|
||||
}
|
||||
if (state->proxy && smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK,
|
||||
"%s", STR(state->buffer)) != 0) {
|
||||
smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
|
||||
@ -1284,36 +1298,41 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
||||
* Terminate the message envelope segment. Start the message content
|
||||
* segment, and prepend our own Received: header. If there is only one
|
||||
* recipient, list the recipient address.
|
||||
*
|
||||
* Suppress our own Received: header in the unlikely case that we are an
|
||||
* intermediate proxy.
|
||||
*/
|
||||
if (state->cleanup)
|
||||
rec_fputs(state->cleanup, REC_TYPE_MESG, "");
|
||||
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||
"Received: from %s (%s [%s])",
|
||||
state->helo_name ? state->helo_name : state->name,
|
||||
state->name, state->addr);
|
||||
if (state->rcpt_count == 1 && state->recipient) {
|
||||
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||
state->cleanup ? "\tby %s (%s) with %s id %s" :
|
||||
"\tby %s (%s) with %s",
|
||||
var_myhostname, var_mail_name,
|
||||
state->protocol, state->queue_id);
|
||||
quote_822_local(state->buffer, state->recipient);
|
||||
if (!state->proxy || state->xclient.addr == 0) {
|
||||
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||
"Received: from %s (%s [%s])",
|
||||
state->helo_name ? state->helo_name : state->name,
|
||||
state->name, state->addr);
|
||||
if (state->rcpt_count == 1 && state->recipient) {
|
||||
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||
state->cleanup ? "\tby %s (%s) with %s id %s" :
|
||||
"\tby %s (%s) with %s",
|
||||
var_myhostname, var_mail_name,
|
||||
state->protocol, state->queue_id);
|
||||
quote_822_local(state->buffer, state->recipient);
|
||||
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||
"\tfor <%s>; %s", STR(state->buffer), mail_date(state->time));
|
||||
} else {
|
||||
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||
state->cleanup ? "\tby %s (%s) with %s id %s;" :
|
||||
"\tby %s (%s) with %s;",
|
||||
var_myhostname, var_mail_name,
|
||||
state->protocol, state->queue_id);
|
||||
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||
"\t%s", mail_date(state->time));
|
||||
}
|
||||
} else {
|
||||
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||
state->cleanup ? "\tby %s (%s) with %s id %s;" :
|
||||
"\tby %s (%s) with %s;",
|
||||
var_myhostname, var_mail_name,
|
||||
state->protocol, state->queue_id);
|
||||
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||
"\t%s", mail_date(state->time));
|
||||
}
|
||||
#ifdef RECEIVED_ENVELOPE_FROM
|
||||
quote_822_local(state->buffer, state->sender);
|
||||
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||
"\t(envelope-from %s)", STR(state->buffer));
|
||||
quote_822_local(state->buffer, state->sender);
|
||||
out_fprintf(out_stream, REC_TYPE_NORM,
|
||||
"\t(envelope-from %s)", STR(state->buffer));
|
||||
#endif
|
||||
}
|
||||
smtpd_chat_reply(state, "354 End data with <CR><LF>.<CR><LF>");
|
||||
|
||||
/*
|
||||
@ -1650,75 +1669,213 @@ static int quit_cmd(SMTPD_STATE *state, int unused_argc, SMTPD_TOKEN *unused_arg
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* xaddr_cmd - process XADDR */
|
||||
/* xclient_cmd - process XCLIENT */
|
||||
|
||||
static int xaddr_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
{
|
||||
int arg_no;
|
||||
char *raw_value;
|
||||
char *cooked_value;
|
||||
char *arg_val;
|
||||
int update_namaddr = 0;
|
||||
|
||||
/*
|
||||
* Sanity checks.
|
||||
* Sanity checks. The XCLIENT command does not override its own access
|
||||
* control.
|
||||
*/
|
||||
if (namadr_list_match(xaddr_clients, state->name, state->addr) == 0) {
|
||||
if (namadr_list_match(xclient_hosts, state->name, state->addr) == 0) {
|
||||
state->error_mask |= MAIL_ERROR_POLICY;
|
||||
smtpd_chat_reply(state, "554 Error: insufficient authorization");
|
||||
return (-1);
|
||||
}
|
||||
/* Todo: "XADDR address" to let Postfix look up the client name. */
|
||||
if (argc != 3
|
||||
|| !valid_hostaddr(argv[1].strval, DONT_GRIPE)
|
||||
|| !valid_hostname(argv[2].strval, DONT_GRIPE)) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Syntax: %s address hostname", XADDR_CMD);
|
||||
return (-1);
|
||||
#define STREQ(x,y) (strcasecmp((x), (y)) == 0)
|
||||
#define UPDATE_STR(s, v) { if (s) myfree(s); s = mystrdup(v); }
|
||||
|
||||
/*
|
||||
* Iterate over all XCLIENT arguments.
|
||||
*/
|
||||
for (arg_no = 1; arg_no < argc; arg_no++) {
|
||||
arg_val = argv[arg_no].strval;
|
||||
|
||||
/*
|
||||
* Request name: what should happen with the stored attributes.
|
||||
* Complain about unrecognized request names. The set of requests is
|
||||
* unlikely to change.
|
||||
*/
|
||||
if ((raw_value = split_at(arg_val, '=')) == 0) {
|
||||
printable(arg_val, '?');
|
||||
if (STREQ(arg_val, "RST")) { /* blow them away */
|
||||
smtpd_xclient_reset(state, XCLIENT_OVER_NONE);
|
||||
} else if (STREQ(arg_val, "ACL")) { /* access control and logging */
|
||||
smtpd_xclient_reset(state, XCLIENT_OVER_ACL | XCLIENT_OVER_LOG);
|
||||
} else if (STREQ(arg_val, "LOG")) { /* logging only */
|
||||
smtpd_xclient_reset(state, XCLIENT_OVER_LOG);
|
||||
} else { /* error */
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad request: %s", arg_val);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME=VALUE attribute. Decode the attribute and for safety's sake
|
||||
* mask non-printable characters in the raw and decoded values; we
|
||||
* don't want to handle unexploded munitions. Do not complain about
|
||||
* unrecognized attribute names. The set of attributes may change
|
||||
* over time.
|
||||
*
|
||||
* The client can send multiple XCLIENT attributes in a single command,
|
||||
* or multiple XCLIENT commands with fewer attributes.
|
||||
*
|
||||
* Note: XCLIENT ACL overrides only specific logging and access control
|
||||
* attributes (desirable for testing), while XCLIENT LOG overrides
|
||||
* all logging attributes (for audit trail consistency).
|
||||
*/
|
||||
else {
|
||||
if (state->xclient.mode == 0) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "503 Error: send %s ACL or LOG first",
|
||||
XCLIENT_CMD);
|
||||
return (-1);
|
||||
}
|
||||
if (xtext_unquote(state->buffer, raw_value) == 0) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad attribute value syntax: %s",
|
||||
printable(raw_value, '?'));
|
||||
return (-1);
|
||||
}
|
||||
cooked_value = printable(STR(state->buffer), '?');
|
||||
(void) printable(raw_value, '?');
|
||||
|
||||
/*
|
||||
* CLIENT_NAME=hostname. Also updates the client hostname lookup
|
||||
* status code. Treat a numerical hostname as an unavailable
|
||||
* name.
|
||||
*/
|
||||
if (STREQ(arg_val, "CLIENT_NAME")) {
|
||||
if (*raw_value && !valid_hostaddr(cooked_value, DONT_GRIPE)) {
|
||||
if (!valid_hostname(cooked_value, DONT_GRIPE)) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad hostname syntax: %s",
|
||||
cooked_value);
|
||||
return (-1);
|
||||
}
|
||||
UPDATE_STR(state->xclient.name, cooked_value);
|
||||
state->xclient.peer_code = SMTPD_PEER_CODE_OK;
|
||||
} else {
|
||||
UPDATE_STR(state->xclient.name, CLIENT_NAME_UNKNOWN);
|
||||
state->xclient.peer_code = SMTPD_PEER_CODE_PERM;
|
||||
}
|
||||
update_namaddr = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* CLIENT_ADDR=client network address.
|
||||
*/
|
||||
else if (STREQ(arg_val, "CLIENT_ADDR")) {
|
||||
if (*raw_value) {
|
||||
if (!valid_hostaddr(cooked_value, DONT_GRIPE)) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad address syntax: %s",
|
||||
cooked_value);
|
||||
return (-1);
|
||||
}
|
||||
UPDATE_STR(state->xclient.addr, cooked_value);
|
||||
} else {
|
||||
UPDATE_STR(state->xclient.name, CLIENT_NAME_UNKNOWN);
|
||||
}
|
||||
update_namaddr = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* CLIENT_CODE=status. Reset the client hostname if the hostname
|
||||
* lookup status is not OK.
|
||||
*/
|
||||
else if (STREQ(arg_val, "CLIENT_CODE")) {
|
||||
if (STREQ(cooked_value, "OK")) {
|
||||
state->xclient.peer_code = SMTPD_PEER_CODE_OK;
|
||||
} else if (STREQ(cooked_value, "TEMP")) {
|
||||
state->xclient.peer_code = SMTPD_PEER_CODE_TEMP;
|
||||
UPDATE_STR(state->xclient.name, CLIENT_NAME_UNKNOWN);
|
||||
update_namaddr = 1;
|
||||
} else if (STREQ(cooked_value, "PERM")) {
|
||||
state->xclient.peer_code = SMTPD_PEER_CODE_PERM;
|
||||
UPDATE_STR(state->xclient.name, CLIENT_NAME_UNKNOWN);
|
||||
update_namaddr = 1;
|
||||
} else {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad hostname status: %s",
|
||||
cooked_value);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* HELO_NAME=hostname. An empty value means the information was
|
||||
* not provided by the client and that we must not fall back to
|
||||
* the non-XCLIENT value. Disallow characters that could mess up
|
||||
* our own Received: message headers but allow [].
|
||||
*/
|
||||
else if (STREQ(arg_val, "HELO_NAME")) {
|
||||
if (*raw_value) {
|
||||
if (strlen(cooked_value) > VALID_HOSTNAME_LEN) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad HELO syntax: %s",
|
||||
cooked_value);
|
||||
return (-1);
|
||||
}
|
||||
neuter(cooked_value, "<>()\\\";:@", '?');
|
||||
UPDATE_STR(state->xclient.helo_name, cooked_value);
|
||||
} else {
|
||||
UPDATE_STR(state->xclient.helo_name, HELO_NAME_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* PROTOCOL=protocol name. Disallow characters that could mess up
|
||||
* our own Received: message headers.
|
||||
*/
|
||||
else if (STREQ(arg_val, "PROTOCOL")) {
|
||||
if (*raw_value) {
|
||||
if (*cooked_value == 0 || strlen(cooked_value) > 64) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad protocol syntax: %s",
|
||||
cooked_value);
|
||||
return (-1);
|
||||
}
|
||||
neuter(cooked_value, "[]<>()\\\";:@", '?');
|
||||
UPDATE_STR(state->xclient.protocol, cooked_value);
|
||||
} else {
|
||||
UPDATE_STR(state->xclient.protocol, PROTOCOL_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Unknown attribute name. Don't complain, and log a warning.
|
||||
* Logging is safe because only authorized clients can issue
|
||||
* XCLIENT commands.
|
||||
*/
|
||||
else {
|
||||
msg_warn("unknown %s attribute from %s: %s=%s",
|
||||
XCLIENT_CMD, state->namaddr, arg_val, cooked_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Change peer information for logging and for access control. Change a
|
||||
* numerical hostname into "unknown", to make it easy to extract client
|
||||
* information from Received: headers.
|
||||
* Update the combined name and address when either has changed.
|
||||
*/
|
||||
#define FIX_NUMERICAL_NAME(s) \
|
||||
(valid_hostaddr((s), DONT_GRIPE) ? "unknown" : (s))
|
||||
#define MAYBE_OVERRIDE(state, attr) \
|
||||
((state)->xclient.attr ? (state)->xclient.attr : (state)->attr)
|
||||
|
||||
smtpd_peer_reset(state);
|
||||
state->name = mystrdup(FIX_NUMERICAL_NAME(argv[2].strval));
|
||||
state->addr = mystrdup(argv[1].strval);
|
||||
state->namaddr =
|
||||
concatenate(state->name, "[", state->addr, "]", (char *) 0);
|
||||
state->peer_code = strcmp(state->name, "unknown") ? 2 : 5;
|
||||
smtpd_chat_reply(state, "250 Ok");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* xloginfo_cmd - process XLOGINFO */
|
||||
|
||||
static int xloginfo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
{
|
||||
|
||||
/*
|
||||
* Sanity checks.
|
||||
*/
|
||||
if (namadr_list_match(xloginfo_clients, state->name, state->addr) == 0) {
|
||||
state->error_mask |= MAIL_ERROR_POLICY;
|
||||
smtpd_chat_reply(state, "554 Error: insufficient authorization");
|
||||
return (-1);
|
||||
if (update_namaddr) {
|
||||
if (state->xclient.namaddr)
|
||||
myfree(state->xclient.namaddr);
|
||||
state->xclient.namaddr =
|
||||
concatenate(MAYBE_OVERRIDE(state, name), "[",
|
||||
MAYBE_OVERRIDE(state, addr), "]",
|
||||
(char *) 0);
|
||||
}
|
||||
if (argc != 3
|
||||
|| !valid_hostaddr(argv[1].strval, DONT_GRIPE)
|
||||
|| !valid_hostname(argv[2].strval, DONT_GRIPE)) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Syntax: %s address hostname", XLOGINFO_CMD);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change peer information for logging but not for access control. Change
|
||||
* a numerical hostname into "unknown", for consistency with XADDR.
|
||||
*/
|
||||
myfree(state->namaddr);
|
||||
state->namaddr =
|
||||
concatenate(FIX_NUMERICAL_NAME(argv[2].strval),
|
||||
"[", argv[1].strval, "]", (char *) 0);
|
||||
smtpd_chat_reply(state, "250 Ok");
|
||||
return (0);
|
||||
}
|
||||
@ -1774,8 +1931,7 @@ static SMTPD_CMD smtpd_cmd_table[] = {
|
||||
"VRFY", vrfy_cmd, SMTPD_CMD_FLAG_LIMIT,
|
||||
"ETRN", etrn_cmd, SMTPD_CMD_FLAG_LIMIT,
|
||||
"QUIT", quit_cmd, 0,
|
||||
"XADDR", xaddr_cmd, SMTPD_CMD_FLAG_LIMIT,
|
||||
"XLOGINFO", xloginfo_cmd, SMTPD_CMD_FLAG_LIMIT,
|
||||
"XCLIENT", xclient_cmd, SMTPD_CMD_FLAG_LIMIT,
|
||||
"Received:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
|
||||
"Reply-To:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
|
||||
"Message-ID:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
|
||||
@ -1835,6 +1991,12 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
|
||||
break;
|
||||
|
||||
case 0:
|
||||
|
||||
/*
|
||||
* XXX The client connection count/rate control uses the real client
|
||||
* name/address to maintain consistency between connect and
|
||||
* disconnect events.
|
||||
*/
|
||||
if (SMTPD_STAND_ALONE(state) == 0
|
||||
&& anvil_clnt
|
||||
&& !namadr_list_match(hogger_list, state->name, state->addr)
|
||||
@ -1855,6 +2017,7 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* XXX We use the real client for connect access control. */
|
||||
if (SMTPD_STAND_ALONE(state) == 0
|
||||
&& var_smtpd_delay_reject == 0
|
||||
&& (state->access_denied = smtpd_check_client(state)) != 0) {
|
||||
@ -1900,6 +2063,7 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
|
||||
smtpd_chat_reply(state, "221 Error: I can break rules, too. Goodbye.");
|
||||
break;
|
||||
}
|
||||
/* XXX We use the real client for connect access control. */
|
||||
if (state->access_denied && cmdp->action != quit_cmd) {
|
||||
smtpd_chat_reply(state, "503 Error: access denied for %s",
|
||||
state->namaddr); /* RFC 2821 Sec 3.1 */
|
||||
@ -1917,6 +2081,12 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX The client connection count/rate control uses the real client
|
||||
* name/address to maintain consistency between connect and disconnect
|
||||
* events.
|
||||
*/
|
||||
if (SMTPD_STAND_ALONE(state) == 0
|
||||
&& anvil_clnt
|
||||
&& !namadr_list_match(hogger_list, state->name, state->addr))
|
||||
@ -2014,8 +2184,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
|
||||
*/
|
||||
smtpd_noop_cmds = string_list_init(MATCH_FLAG_NONE, var_smtpd_noop_cmds);
|
||||
verp_clients = namadr_list_init(MATCH_FLAG_NONE, var_verp_clients);
|
||||
xaddr_clients = namadr_list_init(MATCH_FLAG_NONE, var_xaddr_clients);
|
||||
xloginfo_clients = namadr_list_init(MATCH_FLAG_NONE, var_xloginfo_clients);
|
||||
xclient_hosts = namadr_list_init(MATCH_FLAG_NONE, var_xclient_hosts);
|
||||
hogger_list = namadr_list_init(MATCH_FLAG_NONE, var_smtpd_hoggers);
|
||||
if (getuid() == 0 || getuid() == var_owner_uid)
|
||||
smtpd_check_init();
|
||||
@ -2153,8 +2322,7 @@ int main(int argc, char **argv)
|
||||
VAR_SMTPD_PROXY_FILT, DEF_SMTPD_PROXY_FILT, &var_smtpd_proxy_filt, 0, 0,
|
||||
VAR_SMTPD_PROXY_EHLO, DEF_SMTPD_PROXY_EHLO, &var_smtpd_proxy_ehlo, 0, 0,
|
||||
VAR_INPUT_TRANSP, DEF_INPUT_TRANSP, &var_input_transp, 0, 0,
|
||||
VAR_XADDR_CLIENTS, DEF_XADDR_CLIENTS, &var_xaddr_clients, 0, 0,
|
||||
VAR_XLOGINFO_CLIENTS, DEF_XLOGINFO_CLIENTS, &var_xloginfo_clients, 0, 0,
|
||||
VAR_XCLIENT_HOSTS, DEF_XCLIENT_HOSTS, &var_xclient_hosts, 0, 0,
|
||||
VAR_SMTPD_HOGGERS, DEF_SMTPD_HOGGERS, &var_smtpd_hoggers, 0, 0,
|
||||
0,
|
||||
};
|
||||
|
@ -45,6 +45,16 @@ typedef struct SMTPD_DEFER {
|
||||
int class; /* error notification class */
|
||||
} SMTPD_DEFER;
|
||||
|
||||
typedef struct SMTPD_XCLIENT_ATTR {
|
||||
int mode; /* none, log, acl */
|
||||
char *name; /* name for access control */
|
||||
char *addr; /* address for access control */
|
||||
char *namaddr; /* name[address] */
|
||||
int peer_code; /* name status */
|
||||
char *protocol; /* email protocol */
|
||||
char *helo_name; /* helo/ehlo parameter */
|
||||
} SMTPD_XCLIENT_ATTR;
|
||||
|
||||
typedef struct SMTPD_STATE {
|
||||
int err;
|
||||
VSTREAM *client;
|
||||
@ -66,6 +76,8 @@ typedef struct SMTPD_STATE {
|
||||
ARGV *history;
|
||||
char *reason;
|
||||
char *sender;
|
||||
char *encoding;
|
||||
char *verp_delims;
|
||||
char *recipient;
|
||||
char *etrn_name;
|
||||
char *protocol;
|
||||
@ -97,6 +109,9 @@ typedef struct SMTPD_STATE {
|
||||
VSTRING *expand_buf; /* scratch space for $name expansion */
|
||||
VSTREAM *proxy; /* proxy handle */
|
||||
VSTRING *proxy_buffer; /* proxy query/reply buffer */
|
||||
char *proxy_mail; /* proxy MAIL FROM command */
|
||||
int proxy_features; /* proxy ESMTP features */
|
||||
SMTPD_XCLIENT_ATTR xclient; /* override access control */
|
||||
} SMTPD_STATE;
|
||||
|
||||
extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
|
||||
@ -117,22 +132,55 @@ extern void smtpd_state_reset(SMTPD_STATE *);
|
||||
(state->client == VSTREAM_IN && getuid() != var_owner_uid)
|
||||
|
||||
/*
|
||||
* SMPTD peer information lookup.
|
||||
* SMTPD peer information lookup.
|
||||
*/
|
||||
extern void smtpd_peer_init(SMTPD_STATE *state);
|
||||
extern void smtpd_peer_reset(SMTPD_STATE *state);
|
||||
|
||||
#define SMTPD_PEER_CODE_OK 2
|
||||
#define SMTPD_PEER_CODE_TEMP 4
|
||||
#define SMTPD_PEER_CODE_PERM 5
|
||||
|
||||
/*
|
||||
* XCLIENT support to override logging and/or access control attributes. It
|
||||
* makes no sense to maintain separate attribute sets for XCLIENT LOG or
|
||||
* XCLIENT ACL, so we set a flag to distinguish purpose.
|
||||
*/
|
||||
#define XCLIENT_CMD "XCLIENT" /* XCLIENT command */
|
||||
#define XCLIENT_EHLO "XCLIENT" /* ESMTP advertisement */
|
||||
|
||||
#define SMTPD_FEATURE_XCLIENT (1<<0) /* server supports XCLIENT */
|
||||
|
||||
#define XCLIENT_OVER_NONE (0) /* override reset */
|
||||
#define XCLIENT_OVER_ACL (1<<0) /* override access control */
|
||||
#define XCLIENT_OVER_LOG (1<<1) /* override logging */
|
||||
|
||||
#define XCLIENT_OVER(s, m, a) \
|
||||
(((s)->xclient.mode & (m)) && (s)->xclient.a ? (s)->xclient.a : (s)->a)
|
||||
|
||||
#define ACL_ADDR(s) XCLIENT_OVER((s), XCLIENT_OVER_ACL, addr)
|
||||
#define ACL_NAME(s) XCLIENT_OVER((s), XCLIENT_OVER_ACL, name)
|
||||
#define ACL_NAMADDR(s) XCLIENT_OVER((s), XCLIENT_OVER_ACL, namaddr)
|
||||
#define ACL_PEER_CODE(s) XCLIENT_OVER((s), XCLIENT_OVER_ACL, peer_code)
|
||||
#define ACL_PROTOCOL(s) XCLIENT_OVER((s), XCLIENT_OVER_ACL, protocol)
|
||||
#define ACL_HELO_NAME(s) XCLIENT_OVER((s), XCLIENT_OVER_ACL, helo_name)
|
||||
|
||||
#define LOG_ADDR(s) XCLIENT_OVER((s), XCLIENT_OVER_LOG, addr)
|
||||
#define LOG_NAME(s) XCLIENT_OVER((s), XCLIENT_OVER_LOG, name)
|
||||
#define LOG_NAMADDR(s) XCLIENT_OVER((s), XCLIENT_OVER_LOG, namaddr)
|
||||
#define LOG_PEER_CODE(s) XCLIENT_OVER((s), XCLIENT_OVER_LOG, peer_code)
|
||||
#define LOG_PROTOCOL(s) XCLIENT_OVER((s), XCLIENT_OVER_LOG, protocol)
|
||||
#define LOG_HELO_NAME(s) XCLIENT_OVER((s), XCLIENT_OVER_LOG, helo_name)
|
||||
|
||||
extern void smtpd_xclient_init(SMTPD_STATE *state);
|
||||
extern void smtpd_xclient_reset(SMTPD_STATE *state, int);
|
||||
|
||||
/*
|
||||
* Transparency: before mail is queued, do we check for unknown recipients,
|
||||
* do we allow address mapping, automatic bcc, header/body checks?
|
||||
*/
|
||||
extern int smtpd_input_transp_mask;
|
||||
|
||||
/*
|
||||
* XLOGINFO command.
|
||||
*/
|
||||
#define XLOGINFO_CMD "XLOGINFO"
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
|
@ -809,15 +809,15 @@ static void log_whatsup(SMTPD_STATE *state, const char *whatsup,
|
||||
|
||||
vstring_sprintf(buf, "%s: %s: %s from %s: %s;",
|
||||
state->queue_id ? state->queue_id : "NOQUEUE",
|
||||
whatsup, state->where, state->namaddr, text);
|
||||
whatsup, state->where, LOG_NAMADDR(state), text);
|
||||
if (state->sender)
|
||||
vstring_sprintf_append(buf, " from=<%s>", state->sender);
|
||||
if (state->recipient)
|
||||
vstring_sprintf_append(buf, " to=<%s>", state->recipient);
|
||||
if (state->protocol)
|
||||
vstring_sprintf_append(buf, " proto=%s", state->protocol);
|
||||
if (state->helo_name)
|
||||
vstring_sprintf_append(buf, " helo=<%s>", state->helo_name);
|
||||
if (!IS_UNK_PROTOCOL(ACL_PROTOCOL(state)))
|
||||
vstring_sprintf_append(buf, " proto=%s", ACL_PROTOCOL(state));
|
||||
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state)))
|
||||
vstring_sprintf_append(buf, " helo=<%s>", ACL_HELO_NAME(state));
|
||||
msg_info("%s", STR(buf));
|
||||
vstring_free(buf);
|
||||
}
|
||||
@ -968,14 +968,14 @@ static int reject_unknown_client(SMTPD_STATE *state)
|
||||
char *myname = "reject_unknown_client";
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s %s", myname, state->name, state->addr);
|
||||
msg_info("%s: %s %s", myname, ACL_NAME(state), ACL_ADDR(state));
|
||||
|
||||
if (strcasecmp(state->name, "unknown") == 0)
|
||||
if (IS_UNK_CLNT_NAME(ACL_NAME(state)))
|
||||
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
|
||||
"%d Client host rejected: cannot find your hostname, [%s]",
|
||||
state->peer_code == 5 ?
|
||||
ACL_PEER_CODE(state) == SMTPD_PEER_CODE_PERM ?
|
||||
var_unk_client_code : 450,
|
||||
state->addr));
|
||||
ACL_ADDR(state)));
|
||||
return (SMTPD_CHECK_DUNNO);
|
||||
}
|
||||
|
||||
@ -986,9 +986,9 @@ static int permit_mynetworks(SMTPD_STATE *state)
|
||||
char *myname = "permit_mynetworks";
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s %s", myname, state->name, state->addr);
|
||||
msg_info("%s: %s %s", myname, ACL_NAME(state), ACL_ADDR(state));
|
||||
|
||||
if (namadr_list_match(mynetworks, state->name, state->addr))
|
||||
if (namadr_list_match(mynetworks, ACL_NAME(state), ACL_ADDR(state)))
|
||||
return (SMTPD_CHECK_OK);
|
||||
return (SMTPD_CHECK_DUNNO);
|
||||
}
|
||||
@ -1207,7 +1207,7 @@ static int check_relay_domains(SMTPD_STATE *state, char *recipient,
|
||||
/*
|
||||
* Permit if the client matches the relay_domains list.
|
||||
*/
|
||||
if (domain_list_match(relay_domains, state->name))
|
||||
if (domain_list_match(relay_domains, ACL_NAME(state)))
|
||||
return (SMTPD_CHECK_OK);
|
||||
|
||||
/*
|
||||
@ -1309,7 +1309,7 @@ static int reject_unauth_pipelining(SMTPD_STATE *state,
|
||||
if (state->client != 0
|
||||
&& SMTPD_STAND_ALONE(state) == 0
|
||||
&& vstream_peek(state->client) > 0
|
||||
&& (strcasecmp(state->protocol, "ESMTP") != 0
|
||||
&& (strcasecmp(ACL_PROTOCOL(state), MAIL_PROTO_ESMTP) != 0
|
||||
|| strcasecmp(state->where, "DATA") == 0)) {
|
||||
return (smtpd_check_reject(state, MAIL_ERROR_PROTOCOL,
|
||||
"503 <%s>: %s rejected: Improper use of SMTP command pipelining",
|
||||
@ -2518,13 +2518,14 @@ static const char *smtpd_expand_lookup(const char *name, int unused_mode,
|
||||
* Return NULL only for non-existent names.
|
||||
*/
|
||||
if (STREQ(name, MAIL_ATTR_CLIENT)) {
|
||||
return (state->namaddr);
|
||||
return (ACL_NAMADDR(state));
|
||||
} else if (STREQ(name, MAIL_ATTR_CLIENT_ADDR)) {
|
||||
return (state->addr);
|
||||
return (ACL_ADDR(state));
|
||||
} else if (STREQ(name, MAIL_ATTR_CLIENT_NAME)) {
|
||||
return (state->name);
|
||||
return (ACL_NAME(state));
|
||||
} else if (STREQ(name, MAIL_ATTR_HELO_NAME)) {
|
||||
return (state->helo_name ? state->helo_name : "");
|
||||
return (IS_UNK_HELO_NAME(ACL_HELO_NAME(state)) ?
|
||||
"" : ACL_HELO_NAME(state));
|
||||
} else if (STREQN(name, MAIL_ATTR_SENDER, CONST_LEN(MAIL_ATTR_SENDER))) {
|
||||
return (smtpd_expand_addr(state->expand_buf, state->sender,
|
||||
name, CONST_LEN(MAIL_ATTR_SENDER)));
|
||||
@ -2820,7 +2821,7 @@ static int reject_maps_rbl(SMTPD_STATE *state)
|
||||
static int warned;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s", myname, state->addr);
|
||||
msg_info("%s: %s", myname, ACL_ADDR(state));
|
||||
|
||||
if (warned == 0) {
|
||||
warned++;
|
||||
@ -2829,7 +2830,7 @@ static int reject_maps_rbl(SMTPD_STATE *state)
|
||||
REJECT_MAPS_RBL, var_mail_name, REJECT_RBL_CLIENT);
|
||||
}
|
||||
while ((rbl_domain = mystrtok(&bp, " \t\r\n,")) != 0) {
|
||||
result = reject_rbl_addr(state, rbl_domain, state->addr,
|
||||
result = reject_rbl_addr(state, rbl_domain, ACL_ADDR(state),
|
||||
SMTPD_NAME_CLIENT);
|
||||
if (result != SMTPD_CHECK_DUNNO)
|
||||
break;
|
||||
@ -2906,11 +2907,12 @@ static int check_policy_service(SMTPD_STATE *state, const char *server,
|
||||
ATTR_FLAG_NONE, /* Query attributes. */
|
||||
ATTR_TYPE_STR, MAIL_ATTR_REQ, "smtpd_access_policy",
|
||||
ATTR_TYPE_STR, MAIL_ATTR_PROTO_STATE, state->where,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, state->protocol,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, state->addr,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, state->name,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, ACL_PROTOCOL(state),
|
||||
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, ACL_ADDR(state),
|
||||
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, ACL_NAME(state),
|
||||
ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME,
|
||||
state->helo_name ? state->helo_name : "",
|
||||
IS_UNK_HELO_NAME(ACL_HELO_NAME(state)) ?
|
||||
"" : ACL_HELO_NAME(state),
|
||||
ATTR_TYPE_STR, MAIL_ATTR_SENDER,
|
||||
state->sender ? state->sender : "",
|
||||
ATTR_TYPE_STR, MAIL_ATTR_RECIP,
|
||||
@ -3075,8 +3077,8 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
|
||||
} else if (strcasecmp(name, PERMIT_MYNETWORKS) == 0) {
|
||||
status = permit_mynetworks(state);
|
||||
} else if (is_map_command(state, name, CHECK_CLIENT_ACL, &cpp)) {
|
||||
status = check_namadr_access(state, *cpp, state->name, state->addr,
|
||||
FULL, &found, state->namaddr,
|
||||
status = check_namadr_access(state, *cpp, ACL_NAME(state), ACL_ADDR(state),
|
||||
FULL, &found, ACL_NAMADDR(state),
|
||||
SMTPD_NAME_CLIENT, def_acl);
|
||||
} else if (strcasecmp(name, REJECT_MAPS_RBL) == 0) {
|
||||
status = reject_maps_rbl(state);
|
||||
@ -3085,7 +3087,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
|
||||
if (cpp[1] == 0)
|
||||
msg_warn("restriction %s requires domain name argument", name);
|
||||
else
|
||||
status = reject_rbl_addr(state, *(cpp += 1), state->addr,
|
||||
status = reject_rbl_addr(state, *(cpp += 1), ACL_ADDR(state),
|
||||
SMTPD_NAME_CLIENT);
|
||||
} else if (strcasecmp(name, REJECT_RHSBL_CLIENT) == 0) {
|
||||
if (cpp[1] == 0)
|
||||
@ -3093,69 +3095,73 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
|
||||
name);
|
||||
else {
|
||||
cpp += 1;
|
||||
if (strcasecmp(state->name, "unknown") != 0)
|
||||
status = reject_rbl_domain(state, *cpp, state->name,
|
||||
if (!IS_UNK_CLNT_NAME(ACL_NAME(state)))
|
||||
status = reject_rbl_domain(state, *cpp, ACL_NAME(state),
|
||||
SMTPD_NAME_CLIENT);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* HELO/EHLO parameter restrictions.
|
||||
*
|
||||
* XXX With XCLIENT overrides, a zero-length name means the client did
|
||||
* not send a HELO/EHLO command. Do not fall back to the non-XCLIENT
|
||||
* HELO/EHLO value.
|
||||
*/
|
||||
else if (is_map_command(state, name, CHECK_HELO_ACL, &cpp)) {
|
||||
if (state->helo_name)
|
||||
status = check_domain_access(state, *cpp, state->helo_name,
|
||||
FULL, &found, state->helo_name,
|
||||
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state)))
|
||||
status = check_domain_access(state, *cpp, ACL_HELO_NAME(state),
|
||||
FULL, &found, ACL_HELO_NAME(state),
|
||||
SMTPD_NAME_HELO, def_acl);
|
||||
} else if (strcasecmp(name, REJECT_INVALID_HOSTNAME) == 0) {
|
||||
if (state->helo_name) {
|
||||
if (*state->helo_name != '[')
|
||||
status = reject_invalid_hostname(state, state->helo_name,
|
||||
state->helo_name, SMTPD_NAME_HELO);
|
||||
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
|
||||
if (*ACL_HELO_NAME(state) != '[')
|
||||
status = reject_invalid_hostname(state, ACL_HELO_NAME(state),
|
||||
ACL_HELO_NAME(state), SMTPD_NAME_HELO);
|
||||
else
|
||||
status = reject_invalid_hostaddr(state, state->helo_name,
|
||||
state->helo_name, SMTPD_NAME_HELO);
|
||||
status = reject_invalid_hostaddr(state, ACL_HELO_NAME(state),
|
||||
ACL_HELO_NAME(state), SMTPD_NAME_HELO);
|
||||
}
|
||||
} else if (strcasecmp(name, REJECT_UNKNOWN_HOSTNAME) == 0) {
|
||||
if (state->helo_name) {
|
||||
if (*state->helo_name != '[')
|
||||
status = reject_unknown_hostname(state, state->helo_name,
|
||||
state->helo_name, SMTPD_NAME_HELO);
|
||||
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
|
||||
if (*ACL_HELO_NAME(state) != '[')
|
||||
status = reject_unknown_hostname(state, ACL_HELO_NAME(state),
|
||||
ACL_HELO_NAME(state), SMTPD_NAME_HELO);
|
||||
else
|
||||
status = reject_invalid_hostaddr(state, state->helo_name,
|
||||
state->helo_name, SMTPD_NAME_HELO);
|
||||
status = reject_invalid_hostaddr(state, ACL_HELO_NAME(state),
|
||||
ACL_HELO_NAME(state), SMTPD_NAME_HELO);
|
||||
}
|
||||
} else if (strcasecmp(name, PERMIT_NAKED_IP_ADDR) == 0) {
|
||||
msg_warn("restriction %s is deprecated. Use %s instead",
|
||||
PERMIT_NAKED_IP_ADDR, PERMIT_MYNETWORKS);
|
||||
if (state->helo_name) {
|
||||
if (state->helo_name[strspn(state->helo_name, "0123456789.")] == 0
|
||||
&& (status = reject_invalid_hostaddr(state, state->helo_name,
|
||||
state->helo_name, SMTPD_NAME_HELO)) == 0)
|
||||
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
|
||||
if (ACL_HELO_NAME(state)[strspn(ACL_HELO_NAME(state), "0123456789.")] == 0
|
||||
&& (status = reject_invalid_hostaddr(state, ACL_HELO_NAME(state),
|
||||
ACL_HELO_NAME(state), SMTPD_NAME_HELO)) == 0)
|
||||
status = SMTPD_CHECK_OK;
|
||||
}
|
||||
} else if (is_map_command(state, name, CHECK_HELO_NS_ACL, &cpp)) {
|
||||
if (state->helo_name) {
|
||||
status = check_server_access(state, *cpp, state->helo_name,
|
||||
T_NS, state->helo_name,
|
||||
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
|
||||
status = check_server_access(state, *cpp, ACL_HELO_NAME(state),
|
||||
T_NS, ACL_HELO_NAME(state),
|
||||
SMTPD_NAME_HELO, def_acl);
|
||||
forbid_whitelist(state, name, status, state->helo_name);
|
||||
forbid_whitelist(state, name, status, ACL_HELO_NAME(state));
|
||||
}
|
||||
} else if (is_map_command(state, name, CHECK_HELO_MX_ACL, &cpp)) {
|
||||
if (state->helo_name) {
|
||||
status = check_server_access(state, *cpp, state->helo_name,
|
||||
T_MX, state->helo_name,
|
||||
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
|
||||
status = check_server_access(state, *cpp, ACL_HELO_NAME(state),
|
||||
T_MX, ACL_HELO_NAME(state),
|
||||
SMTPD_NAME_HELO, def_acl);
|
||||
forbid_whitelist(state, name, status, state->helo_name);
|
||||
forbid_whitelist(state, name, status, ACL_HELO_NAME(state));
|
||||
}
|
||||
} else if (strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) {
|
||||
if (state->helo_name) {
|
||||
if (*state->helo_name != '[')
|
||||
status = reject_non_fqdn_hostname(state, state->helo_name,
|
||||
state->helo_name, SMTPD_NAME_HELO);
|
||||
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
|
||||
if (*ACL_HELO_NAME(state) != '[')
|
||||
status = reject_non_fqdn_hostname(state, ACL_HELO_NAME(state),
|
||||
ACL_HELO_NAME(state), SMTPD_NAME_HELO);
|
||||
else
|
||||
status = reject_invalid_hostaddr(state, state->helo_name,
|
||||
state->helo_name, SMTPD_NAME_HELO);
|
||||
status = reject_invalid_hostaddr(state, ACL_HELO_NAME(state),
|
||||
ACL_HELO_NAME(state), SMTPD_NAME_HELO);
|
||||
}
|
||||
} else if (strcasecmp(name, REJECT_RHSBL_HELO) == 0) {
|
||||
if (cpp[1] == 0)
|
||||
@ -3163,8 +3169,8 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
|
||||
name);
|
||||
else {
|
||||
cpp += 1;
|
||||
if (state->helo_name)
|
||||
status = reject_rbl_domain(state, *cpp, state->helo_name,
|
||||
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state)))
|
||||
status = reject_rbl_domain(state, *cpp, ACL_HELO_NAME(state),
|
||||
SMTPD_NAME_HELO);
|
||||
}
|
||||
}
|
||||
@ -3361,7 +3367,7 @@ char *smtpd_check_client(SMTPD_STATE *state)
|
||||
/*
|
||||
* Initialize.
|
||||
*/
|
||||
if (state->name == 0 || state->addr == 0)
|
||||
if (ACL_NAME(state) == 0 || ACL_ADDR(state) == 0)
|
||||
return (0);
|
||||
|
||||
#define SMTPD_CHECK_RESET() { \
|
||||
@ -3381,7 +3387,7 @@ char *smtpd_check_client(SMTPD_STATE *state)
|
||||
SMTPD_CHECK_RESET();
|
||||
status = setjmp(smtpd_check_buf);
|
||||
if (status == 0 && client_restrctions->argc)
|
||||
status = generic_checks(state, client_restrctions, state->namaddr,
|
||||
status = generic_checks(state, client_restrctions, ACL_NAMADDR(state),
|
||||
SMTPD_NAME_CLIENT, CHECK_CLIENT_ACL);
|
||||
state->defer_if_permit_client = state->defer_if_permit.active;
|
||||
|
||||
@ -3435,7 +3441,7 @@ char *smtpd_check_helo(SMTPD_STATE *state, char *helohost)
|
||||
SMTPD_CHECK_RESET();
|
||||
status = setjmp(smtpd_check_buf);
|
||||
if (status == 0 && helo_restrctions->argc)
|
||||
status = generic_checks(state, helo_restrctions, state->helo_name,
|
||||
status = generic_checks(state, helo_restrctions, ACL_HELO_NAME(state),
|
||||
SMTPD_NAME_HELO, CHECK_HELO_ACL);
|
||||
state->defer_if_permit_helo = state->defer_if_permit.active;
|
||||
|
||||
@ -3547,7 +3553,7 @@ char *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient)
|
||||
*/
|
||||
if (var_smtpd_delay_reject)
|
||||
if ((err = smtpd_check_client(state)) != 0
|
||||
|| (err = smtpd_check_helo(state, state->helo_name)) != 0
|
||||
|| (err = smtpd_check_helo(state, ACL_HELO_NAME(state))) != 0
|
||||
|| (err = smtpd_check_mail(state, state->sender)) != 0)
|
||||
SMTPD_CHECK_RCPT_RETURN(err);
|
||||
|
||||
@ -3616,7 +3622,7 @@ char *smtpd_check_etrn(SMTPD_STATE *state, char *domain)
|
||||
*/
|
||||
if (var_smtpd_delay_reject)
|
||||
if ((err = smtpd_check_client(state)) != 0
|
||||
|| (err = smtpd_check_helo(state, state->helo_name)) != 0)
|
||||
|| (err = smtpd_check_helo(state, ACL_HELO_NAME(state))) != 0)
|
||||
SMTPD_CHECK_ETRN_RETURN(err);
|
||||
|
||||
/*
|
||||
@ -4316,7 +4322,7 @@ int main(int argc, char **argv)
|
||||
if (args->argc == 4)
|
||||
state.peer_code = atoi(args->argv[3]);
|
||||
else
|
||||
state.peer_code = 2;
|
||||
state.peer_code = SMTPD_PEER_CODE_OK;
|
||||
if (state.namaddr)
|
||||
myfree(state.namaddr);
|
||||
state.namaddr = concatenate(state.name, "[", state.addr,
|
||||
|
@ -93,6 +93,7 @@ static int h_errno = TRY_AGAIN;
|
||||
|
||||
/* Global library. */
|
||||
|
||||
#include <mail_proto.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@ -124,9 +125,9 @@ void smtpd_peer_init(SMTPD_STATE *state)
|
||||
* If peer went away, give up.
|
||||
*/
|
||||
if (errno == ECONNRESET || errno == ECONNABORTED) {
|
||||
state->name = mystrdup("unknown");
|
||||
state->addr = mystrdup("unknown");
|
||||
state->peer_code = 5;
|
||||
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||
state->addr = mystrdup(CLIENT_ADDR_UNKNOWN);
|
||||
state->peer_code = SMTPD_PEER_CODE_PERM;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -137,26 +138,27 @@ void smtpd_peer_init(SMTPD_STATE *state)
|
||||
hp = gethostbyaddr((char *) &(sin.sin_addr),
|
||||
sizeof(sin.sin_addr), AF_INET);
|
||||
if (hp == 0) {
|
||||
state->name = mystrdup("unknown");
|
||||
state->peer_code = (h_errno == TRY_AGAIN ? 4 : 5);
|
||||
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||
state->peer_code = (h_errno == TRY_AGAIN ?
|
||||
SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
|
||||
} else if (valid_hostaddr(hp->h_name, DONT_GRIPE)) {
|
||||
msg_warn("numeric result %s in address->name lookup for %s",
|
||||
hp->h_name, state->addr);
|
||||
state->name = mystrdup("unknown");
|
||||
state->peer_code = 5;
|
||||
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||
state->peer_code = SMTPD_PEER_CODE_PERM;
|
||||
} else if (!valid_hostname(hp->h_name, DONT_GRIPE)) {
|
||||
state->name = mystrdup("unknown");
|
||||
state->peer_code = 5;
|
||||
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||
state->peer_code = SMTPD_PEER_CODE_PERM;
|
||||
} else {
|
||||
state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */
|
||||
state->peer_code = 2;
|
||||
state->peer_code = SMTPD_PEER_CODE_OK;
|
||||
|
||||
/*
|
||||
* Reject the hostname if it does not list the peer address.
|
||||
*/
|
||||
#define REJECT_PEER_NAME(state, code) { \
|
||||
myfree(state->name); \
|
||||
state->name = mystrdup("unknown"); \
|
||||
state->name = mystrdup(CLIENT_NAME_UNKNOWN); \
|
||||
state->peer_code = code; \
|
||||
}
|
||||
|
||||
@ -164,17 +166,18 @@ void smtpd_peer_init(SMTPD_STATE *state)
|
||||
if (hp == 0) {
|
||||
msg_warn("%s: hostname %s verification failed: %s",
|
||||
state->addr, state->name, HSTRERROR(h_errno));
|
||||
REJECT_PEER_NAME(state, (h_errno == TRY_AGAIN ? 4 : 5));
|
||||
REJECT_PEER_NAME(state, (h_errno == TRY_AGAIN ?
|
||||
SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM));
|
||||
} else if (hp->h_length != sizeof(sin.sin_addr)) {
|
||||
msg_warn("%s: hostname %s verification failed: bad address size %d",
|
||||
state->addr, state->name, hp->h_length);
|
||||
REJECT_PEER_NAME(state, 5);
|
||||
REJECT_PEER_NAME(state, SMTPD_PEER_CODE_PERM);
|
||||
} else {
|
||||
for (i = 0; /* void */ ; i++) {
|
||||
if (hp->h_addr_list[i] == 0) {
|
||||
msg_warn("%s: address not listed for hostname %s",
|
||||
state->addr, state->name);
|
||||
REJECT_PEER_NAME(state, 5);
|
||||
REJECT_PEER_NAME(state, SMTPD_PEER_CODE_PERM);
|
||||
break;
|
||||
}
|
||||
if (memcmp(hp->h_addr_list[i],
|
||||
@ -193,7 +196,7 @@ void smtpd_peer_init(SMTPD_STATE *state)
|
||||
else {
|
||||
state->name = mystrdup("localhost");
|
||||
state->addr = mystrdup("127.0.0.1"); /* XXX bogus. */
|
||||
state->peer_code = 2;
|
||||
state->peer_code = SMTPD_PEER_CODE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -51,12 +51,12 @@
|
||||
/* 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
|
||||
/* smtpd_proxy_open() connects to the proxy service, sends EHLO, sends
|
||||
/* client information with the XCLIENT command if possible, 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_buffer field in a form
|
||||
/* The result is reported via the state->proxy_buffer field in a form
|
||||
/* that can be sent to the SMTP client. In case of error, the
|
||||
/* state->error_mask and state->err fields are updated.
|
||||
/* A state->proxy_buffer field is created automatically; this field
|
||||
@ -155,6 +155,8 @@
|
||||
#include <cleanup_user.h>
|
||||
#include <mail_params.h>
|
||||
#include <rec_type.h>
|
||||
#include <xtext.h>
|
||||
#include <mail_proto.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@ -168,7 +170,7 @@
|
||||
#define LEN(x) VSTRING_LEN(x)
|
||||
#define SMTPD_PROXY_CONNECT ((char *) 0)
|
||||
|
||||
/* smtpd_proxy_open - open proxy connection after MAIL FROM */
|
||||
/* smtpd_proxy_open - open proxy connection */
|
||||
|
||||
int smtpd_proxy_open(SMTPD_STATE *state, const char *service,
|
||||
int timeout, const char *ehlo_name,
|
||||
@ -177,6 +179,8 @@ int smtpd_proxy_open(SMTPD_STATE *state, const char *service,
|
||||
int fd;
|
||||
char *lines;
|
||||
char *line;
|
||||
VSTRING *buf;
|
||||
int bad;
|
||||
|
||||
/*
|
||||
* This buffer persists beyond the end of a proxy session so we can
|
||||
@ -205,7 +209,8 @@ int smtpd_proxy_open(SMTPD_STATE *state, const char *service,
|
||||
*
|
||||
* If this fails then we have a problem because the proxy should always
|
||||
* accept our connection. Make up our own response instead of passing
|
||||
* back the greeting banner: the client expects a MAIL FROM reply.
|
||||
* back the greeting banner: the proxy open might be delayed to the point
|
||||
* that the client expects a MAIL FROM or RCPT TO reply.
|
||||
*/
|
||||
if (smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, SMTPD_PROXY_CONNECT) != 0) {
|
||||
vstring_sprintf(state->proxy_buffer,
|
||||
@ -217,8 +222,9 @@ int smtpd_proxy_open(SMTPD_STATE *state, const char *service,
|
||||
/*
|
||||
* Send our own EHLO command. If this fails then we have a problem
|
||||
* because the proxy should always accept our EHLO command. Make up our
|
||||
* own response instead of passing back the EHLO reply: the client
|
||||
* expects a MAIL FROM reply.
|
||||
* own response instead of passing back the EHLO reply: the proxy open
|
||||
* might be delayed to the point that the client expects a MAIL FROM or
|
||||
* RCPT TO reply.
|
||||
*/
|
||||
if (smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, "EHLO %s", ehlo_name) != 0) {
|
||||
vstring_sprintf(state->proxy_buffer,
|
||||
@ -228,17 +234,46 @@ int smtpd_proxy_open(SMTPD_STATE *state, const char *service,
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the EHLO reply and see if we can forward the client hostname and
|
||||
* address info for logging purposes. If the command fails, then proceed.
|
||||
* It is not the end of the world.
|
||||
* Parse the EHLO reply and see if we can forward logging information.
|
||||
*/
|
||||
state->proxy_features = 0;
|
||||
lines = STR(state->proxy_buffer);
|
||||
while ((line = mystrtok(&lines, "\n")) != 0)
|
||||
if (ISDIGIT(line[0]) && ISDIGIT(line[1]) && ISDIGIT(line[2])
|
||||
&& (line[3] == ' ' || line[3] == '-')
|
||||
&& strcmp(line + 4, XLOGINFO_CMD) == 0)
|
||||
(void) smtpd_proxy_cmd(state, SMTPD_PROX_WANT_ANY, "%s %s %s",
|
||||
XLOGINFO_CMD, state->addr, state->name);
|
||||
&& strcmp(line + 4, XCLIENT_EHLO) == 0)
|
||||
state->proxy_features |= SMTPD_FEATURE_XCLIENT;
|
||||
|
||||
/*
|
||||
* Send our XCLIENT attributes. Transform internal forms to external
|
||||
* forms and encode the result as xtext.
|
||||
*/
|
||||
if (state->proxy_features & SMTPD_FEATURE_XCLIENT) {
|
||||
buf = vstring_alloc(100);
|
||||
vstring_sprintf(buf, "%s LOG CLIENT_NAME=", XCLIENT_CMD);
|
||||
if (!IS_UNK_CLNT_NAME(LOG_NAME(state)))
|
||||
xtext_quote_append(buf, LOG_NAME(state), "");
|
||||
vstring_strcat(buf, " CLIENT_ADDR=");
|
||||
if (!IS_UNK_CLNT_ADDR(LOG_ADDR(state)))
|
||||
xtext_quote_append(buf, LOG_ADDR(state), "");
|
||||
bad = smtpd_proxy_cmd(state, SMTPD_PROX_WANT_ANY, "%s", STR(buf));
|
||||
if (bad == 0) {
|
||||
vstring_sprintf(buf, "%s HELO_NAME=", XCLIENT_CMD);
|
||||
if (!IS_UNK_HELO_NAME(LOG_HELO_NAME(state)))
|
||||
xtext_quote_append(buf, LOG_HELO_NAME(state), "");
|
||||
vstring_strcat(buf, " PROTOCOL=");
|
||||
if (!IS_UNK_PROTOCOL(LOG_PROTOCOL(state)))
|
||||
xtext_quote_append(buf, LOG_PROTOCOL(state), "");
|
||||
bad = smtpd_proxy_cmd(state, SMTPD_PROX_WANT_ANY, "%s", STR(buf));
|
||||
}
|
||||
vstring_free(buf);
|
||||
if (bad) {
|
||||
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 this fails, then we
|
||||
|
@ -198,7 +198,7 @@ void smtpd_sasl_mail_log(SMTPD_STATE *state)
|
||||
#define IFELSE(e1,e2,e3) ((e1) ? (e2) : (e3))
|
||||
|
||||
msg_info("%s: client=%s%s%s%s%s%s%s",
|
||||
state->queue_id, state->namaddr,
|
||||
state->queue_id, LOG_NAMADDR(state),
|
||||
IFELSE(state->sasl_method, ", sasl_method=", ""),
|
||||
IFELSE(state->sasl_method, state->sasl_method, ""),
|
||||
IFELSE(state->sasl_username, ", sasl_username=", ""),
|
||||
|
@ -85,6 +85,7 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
|
||||
state->history = 0;
|
||||
state->reason = 0;
|
||||
state->sender = 0;
|
||||
state->verp_delims = 0;
|
||||
state->recipient = 0;
|
||||
state->etrn_name = 0;
|
||||
state->protocol = MAIL_PROTO_SMTP;
|
||||
@ -101,6 +102,8 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
|
||||
state->expand_buf = 0;
|
||||
state->proxy = 0;
|
||||
state->proxy_buffer = 0;
|
||||
state->proxy_mail = 0;
|
||||
state->proxy_features = 0;
|
||||
|
||||
#ifdef USE_SASL_AUTH
|
||||
if (SMTPD_STAND_ALONE(state))
|
||||
@ -114,6 +117,11 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
|
||||
*/
|
||||
smtpd_peer_init(state);
|
||||
|
||||
/*
|
||||
* Initialize xclient information.
|
||||
*/
|
||||
smtpd_xclient_init(state);
|
||||
|
||||
/*
|
||||
* Initialize the conversation history.
|
||||
*/
|
||||
@ -133,6 +141,7 @@ void smtpd_state_reset(SMTPD_STATE *state)
|
||||
if (state->buffer)
|
||||
vstring_free(state->buffer);
|
||||
smtpd_peer_reset(state);
|
||||
smtpd_xclient_reset(state, XCLIENT_OVER_NONE);
|
||||
if (state->defer_if_permit.reason)
|
||||
vstring_free(state->defer_if_permit.reason);
|
||||
if (state->defer_if_reject.reason)
|
||||
|
116
postfix/src/smtpd/smtpd_xclient.c
Normal file
116
postfix/src/smtpd/smtpd_xclient.c
Normal file
@ -0,0 +1,116 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* smtpd_xclient 3
|
||||
/* SUMMARY
|
||||
/* maintain XCLIENT information
|
||||
/* SYNOPSIS
|
||||
/* #include "smtpd.h"
|
||||
/*
|
||||
/* void smtpd_xclient_init(state)
|
||||
/* SMTPD_STATE *state;
|
||||
/*
|
||||
/* void smtpd_xclient_reset(state, mode)
|
||||
/* SMTPD_STATE *state;
|
||||
/* int mode;
|
||||
/* DESCRIPTION
|
||||
/* smtpd_xclient_init() initializes state variables that are
|
||||
/* used for storage of XCLIENT command parameters.
|
||||
/* These variables override specific members of the global state
|
||||
/* structure for access control or logging purposes.
|
||||
/*
|
||||
/* smtpd_xclient_reset() releases memory allocated after the return
|
||||
/* from smtpd_xclient_init() and optionally presets the state variables
|
||||
/* to defaults that are suitable for the specified mode:
|
||||
/* .IP XCLIENT_OVER_NONE
|
||||
/* This should be used after the XCLIENT RST request.
|
||||
/* .IP XCLIENT_OVER_ACL|XCLIENT_OVER_LOG
|
||||
/* This should be used after the XCLIENT ACL request.
|
||||
/* .IP XCLIENT_OVER_LOG
|
||||
/* This should be used after the XCLIENT LOG request.
|
||||
/* 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>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <mymalloc.h>
|
||||
#include <msg.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
#include <mail_proto.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include <smtpd.h>
|
||||
|
||||
/* smtpd_xclient_init - initialize XCLIENT attributes */
|
||||
|
||||
void smtpd_xclient_init(SMTPD_STATE *state)
|
||||
{
|
||||
state->xclient.mode = 0;
|
||||
state->xclient.name = 0;
|
||||
state->xclient.addr = 0;
|
||||
state->xclient.namaddr = 0;
|
||||
state->xclient.peer_code = 0;
|
||||
state->xclient.protocol = 0;
|
||||
state->xclient.helo_name = 0;
|
||||
}
|
||||
|
||||
/* smtpd_xclient_reset - reset XCLIENT attributes */
|
||||
|
||||
void smtpd_xclient_reset(SMTPD_STATE *state, int mode)
|
||||
{
|
||||
switch (mode) {
|
||||
|
||||
/*
|
||||
* Can't happen.
|
||||
*/
|
||||
default:
|
||||
msg_panic("smtpd_xclient_reset: unknown mode 0x%x", mode);
|
||||
|
||||
/*
|
||||
* Restore smtpd_xclient_init() result. Allow selective override.
|
||||
* This is desirable for access rule testing.
|
||||
*/
|
||||
#define FREE_AND_WIPE(s) { if (s) { myfree(s); s = 0; } }
|
||||
|
||||
case XCLIENT_OVER_NONE:
|
||||
case XCLIENT_OVER_ACL | XCLIENT_OVER_LOG:
|
||||
FREE_AND_WIPE(state->xclient.name);
|
||||
FREE_AND_WIPE(state->xclient.addr);
|
||||
FREE_AND_WIPE(state->xclient.namaddr);
|
||||
state->xclient.peer_code = 0;
|
||||
FREE_AND_WIPE(state->xclient.protocol);
|
||||
FREE_AND_WIPE(state->xclient.helo_name);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Non-selective override. Set all attributes to "unknown". This is
|
||||
* desirable to avoid polluting the audit trail with data from mixed
|
||||
* origins.
|
||||
*/
|
||||
#define FREE_AND_DUP(s,v) { if (s) { myfree(s); s = mystrdup(v); } }
|
||||
|
||||
case XCLIENT_OVER_LOG:
|
||||
FREE_AND_DUP(state->xclient.name, CLIENT_NAME_UNKNOWN);
|
||||
FREE_AND_DUP(state->xclient.addr, CLIENT_ADDR_UNKNOWN);
|
||||
FREE_AND_DUP(state->xclient.namaddr, CLIENT_NAMADDR_UNKNOWN);
|
||||
state->xclient.peer_code = 0;
|
||||
FREE_AND_DUP(state->xclient.protocol, PROTOCOL_UNKNOWN);
|
||||
FREE_AND_DUP(state->xclient.helo_name, HELO_NAME_UNKNOWN);
|
||||
break;
|
||||
}
|
||||
state->xclient.mode = mode;
|
||||
}
|
@ -3,9 +3,6 @@ SRCS = smtp-source.c smtp-sink.c qmqp-source.c qmqp-sink.c
|
||||
OBJS = smtp-source.o smtp-sink.o qmqp-source.o qmqp-sink.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -3,9 +3,6 @@ SRCS = spawn.c
|
||||
OBJS = spawn.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -3,9 +3,6 @@ SRCS = trivial-rewrite.c rewrite.c resolve.c transport.c
|
||||
OBJS = trivial-rewrite.o rewrite.o resolve.o transport.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
LIB =
|
||||
|
@ -27,7 +27,7 @@ SRCS = alldig.c argv.c argv_split.c attr_print0.c attr_print64.c \
|
||||
username.c valid_hostname.c vbuf.c vbuf_print.c vstream.c \
|
||||
vstream_popen.c vstring.c vstring_vstream.c watchdog.c writable.c \
|
||||
write_buf.c write_wait.c auto_clnt.c attr_clnt.c attr_scan_plain.c \
|
||||
attr_print_plain.c sane_connect.c
|
||||
attr_print_plain.c sane_connect.c neuter.c
|
||||
OBJS = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
|
||||
attr_scan0.o attr_scan64.o base64_code.o basename.o binhash.o \
|
||||
chroot_uid.o clean_env.o close_on_exec.o concatenate.o ctable.o \
|
||||
@ -56,7 +56,7 @@ OBJS = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
|
||||
username.o valid_hostname.o vbuf.o vbuf_print.o vstream.o \
|
||||
vstream_popen.o vstring.o vstring_vstream.o watchdog.o writable.o \
|
||||
write_buf.o write_wait.o auto_clnt.o attr_clnt.o attr_scan_plain.o \
|
||||
attr_print_plain.o sane_connect.o $(STRCASE)
|
||||
attr_print_plain.o sane_connect.o $(STRCASE) neuter.o
|
||||
HDRS = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
|
||||
connect.h ctable.h dict.h dict_db.h dict_dbm.h dict_env.h \
|
||||
dict_cidr.h dict_ht.h dict_ldap.h dict_mysql.h dict_ni.h dict_nis.h \
|
||||
@ -78,9 +78,6 @@ HDRS = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
|
||||
auto_clnt.h attr_clnt.h sane_connect.h
|
||||
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
|
||||
stream_test.c dup2_pass_on_exec.c
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
FILES = Makefile $(SRCS) $(HDRS)
|
||||
@ -1046,6 +1043,11 @@ netstring.o: vstream.h
|
||||
netstring.o: vbuf.h
|
||||
netstring.o: vstring.h
|
||||
netstring.o: netstring.h
|
||||
neuter.o: neuter.c
|
||||
neuter.o: sys_defs.h
|
||||
neuter.o: stringops.h
|
||||
neuter.o: vstring.h
|
||||
neuter.o: vbuf.h
|
||||
non_blocking.o: non_blocking.c
|
||||
non_blocking.o: sys_defs.h
|
||||
non_blocking.o: msg.h
|
||||
|
56
postfix/src/util/neuter.c
Normal file
56
postfix/src/util/neuter.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* neuter 3
|
||||
/* SUMMARY
|
||||
/* mask non-neuter characters
|
||||
/* SYNOPSIS
|
||||
/* #include <stringops.h>
|
||||
/*
|
||||
/* char *neuter(buffer, bad, replacement)
|
||||
/* char *buffer;
|
||||
/* const char *bad;
|
||||
/* int replacement;
|
||||
/* DESCRIPTION
|
||||
/* neuter() replaces bad characters in its input
|
||||
/* by the given replacement.
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP buffer
|
||||
/* The null-terminated input string.
|
||||
/* .IP bad
|
||||
/* The null-terminated bad character string.
|
||||
/* .IP replacement
|
||||
/* Replacement value for characters in \fIbuffer\fR that do not
|
||||
/* pass the bad character test.
|
||||
/* 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 <string.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <stringops.h>
|
||||
|
||||
/* neuter - neutralize bad characters */
|
||||
|
||||
char *neuter(char *string, const char *bad, int replacement)
|
||||
{
|
||||
char *cp;
|
||||
int ch;
|
||||
|
||||
for (cp = string; (ch = *(unsigned char *) cp) != 0; cp++)
|
||||
if (strchr(bad, ch) != 0)
|
||||
*cp = replacement;
|
||||
return (string);
|
||||
}
|
@ -20,6 +20,7 @@
|
||||
* External interface.
|
||||
*/
|
||||
extern char *printable(char *, int);
|
||||
extern char *neuter(char *, const char *, int);
|
||||
extern char *lowercase(char *);
|
||||
extern char *skipblanks(const char *);
|
||||
extern char *trimblanks(char *, int);
|
||||
|
@ -59,18 +59,39 @@
|
||||
#define NATIVE_DAEMON_DIR "/usr/libexec/postfix"
|
||||
#endif
|
||||
|
||||
#if defined(FREEBSD2) || defined(FREEBSD3) || defined(FREEBSD4)
|
||||
#define HAS_DUPLEX_PIPE
|
||||
#endif
|
||||
/* __FreeBSD_version version is major+minor */
|
||||
|
||||
#if defined(OPENBSD2) || defined(OPENBSD3) \
|
||||
|| defined(FREEBSD3) || defined(FREEBSD4)
|
||||
#if __FreeBSD_version >= 200000
|
||||
#define HAS_DUPLEX_PIPE
|
||||
#define HAS_ISSETUGID
|
||||
#endif
|
||||
|
||||
#if defined(NETBSD1)
|
||||
#if __FreeBSD_version >= 400000
|
||||
#define SOCKADDR_SIZE socklen_t
|
||||
#define SOCKOPT_SIZE socklen_t
|
||||
#endif
|
||||
|
||||
/* OpenBSD version is year+month */
|
||||
|
||||
#if OpenBSD >= 200000 /* XXX */
|
||||
#define HAS_ISSETUGID
|
||||
#endif
|
||||
|
||||
#if OpenBSD >= 200200 /* XXX */
|
||||
#define SOCKADDR_SIZE socklen_t
|
||||
#define SOCKOPT_SIZE socklen_t
|
||||
#endif
|
||||
|
||||
/* __NetBSD_Version__ is major+minor */
|
||||
|
||||
#if __NetBSD_Version__ >= 103000000 /* XXX */
|
||||
#undef DEF_MAILBOX_LOCK
|
||||
#define DEF_MAILBOX_LOCK "flock, dotlock"
|
||||
#endif
|
||||
|
||||
#if __NetBSD_Version__ >= 106000000 /* XXX */
|
||||
#define SOCKADDR_SIZE socklen_t
|
||||
#define SOCKOPT_SIZE socklen_t
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -493,6 +514,7 @@ extern int initgroups(const char *, int);
|
||||
#ifdef LINUX2
|
||||
#define SUPPORTED
|
||||
#include <sys/types.h>
|
||||
#include <features.h>
|
||||
#define USE_PATHS_H
|
||||
#define HAS_FLOCK_LOCK
|
||||
#define HAS_FCNTL_LOCK
|
||||
@ -516,6 +538,10 @@ extern int initgroups(const char *, int);
|
||||
#define NATIVE_NEWALIAS_PATH "/usr/bin/newaliases"
|
||||
#define NATIVE_COMMAND_DIR "/usr/sbin"
|
||||
#define NATIVE_DAEMON_DIR "/usr/libexec/postfix"
|
||||
#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
|
||||
#define SOCKADDR_SIZE socklen_t
|
||||
#define SOCKOPT_SIZE socklen_t
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef LINUX1
|
||||
@ -908,6 +934,9 @@ extern int dup2_pass_on_exec(int oldd, int newd);
|
||||
#endif
|
||||
#define OPTIND (optind > 0 ? optind : 1)
|
||||
|
||||
/*
|
||||
* Check for required but missing definitions.
|
||||
*/
|
||||
#if !defined(HAS_FCNTL_LOCK) && !defined(HAS_FLOCK_LOCK)
|
||||
#error "define HAS_FCNTL_LOCK and/or HAS_FLOCK_LOCK"
|
||||
#endif
|
||||
@ -929,7 +958,7 @@ extern int dup2_pass_on_exec(int oldd, int newd);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Defaults for normal systems.
|
||||
* Defaults for systems that pre-date POSIX socklen_t.
|
||||
*/
|
||||
#ifndef SOCKADDR_SIZE
|
||||
#define SOCKADDR_SIZE int
|
||||
@ -939,6 +968,9 @@ extern int dup2_pass_on_exec(int oldd, int newd);
|
||||
#define SOCKOPT_SIZE int
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Defaults for normal systems.
|
||||
*/
|
||||
#ifndef LOCAL_LISTEN
|
||||
#define LOCAL_LISTEN unix_listen
|
||||
#define LOCAL_ACCEPT unix_accept
|
||||
|
@ -3,9 +3,6 @@ SRCS = verify.c
|
||||
OBJS = verify.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
TESTPROG=
|
||||
|
@ -3,9 +3,6 @@ SRCS = virtual.c mailbox.c recipient.c deliver_attr.c maildir.c unknown.c
|
||||
OBJS = virtual.o mailbox.o recipient.o deliver_attr.o maildir.o unknown.o
|
||||
HDRS = virtual.h
|
||||
TESTSRC =
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||
-Wunused
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
PROG = virtual
|
||||
|
Loading…
x
Reference in New Issue
Block a user