mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 13:48:06 +00:00
postfix-2.0.16-20031214
This commit is contained in:
parent
7a646f52bf
commit
0b73da41c8
@ -8832,6 +8832,29 @@ Apologies for any names omitted.
|
||||
because the deliver_pass.c module was not updated for the
|
||||
changed message delivery protocol.
|
||||
|
||||
20031211
|
||||
|
||||
Safety: in dynamically growing data structures, update the
|
||||
length info after (instead of before) updating the data
|
||||
size. Files: util/argv.c, util/inet_addrlist.c, util/intv.c,
|
||||
util/mvect.c, util/vstring.c, global/recipient_list.c,
|
||||
*qmgr/qmgr_rcpt_list.c.
|
||||
|
||||
20031212
|
||||
|
||||
Cleanup: separate extensions XCLIENT (impersonate SMTP
|
||||
client) and XFORWARD (down-stream logging of up-stream
|
||||
session information, not necessarily SMTP related). The
|
||||
protocol is extensible: the server advertises what attributes
|
||||
XCLIENT or XFORWARD will accept. The requirement for xtext
|
||||
encoding is dropped as no attribute currently needs it.
|
||||
All errors are reported by the server and are logged by
|
||||
the client. See also: XCLIENT_README and XFORWARD_README.
|
||||
|
||||
20031214
|
||||
|
||||
Feature: XCLIENT and XFORWARD support in the LMTP client.
|
||||
|
||||
Open problems:
|
||||
|
||||
High: when virtual aliasing is turned off after content
|
||||
|
@ -1,182 +1,98 @@
|
||||
Purpose of the XCLIENT extension to SMTP
|
||||
========================================
|
||||
|
||||
The XCLIENT command targets problems in the following areas:
|
||||
The XCLIENT command targets the following problems:
|
||||
|
||||
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 authorized SMTP
|
||||
client test program needs the ability to override the SMTP server's
|
||||
idea of the SMTP client hostname, network address, and other
|
||||
idea of the SMTP client hostname, network address, and other client
|
||||
information, for the entire duration of an SMTP session.
|
||||
|
||||
2 - Logging after SMTP-based content filter. With the deployment
|
||||
of Internet->MTA1->filter->MTA2 style content filter applications,
|
||||
remote client information is lost when MTA1 gives the mail to the
|
||||
content filter. To simplify the interpretation of MTA2 logging,
|
||||
it would help if MTA1 could forward client information through the
|
||||
content filter to MTA2.
|
||||
2 - Client software that downloads mail from an up-stream mail
|
||||
server and injects it into a local MTA via SMTP. In order to take
|
||||
advantage of the local MTA's access rules, the client software
|
||||
needs the ability to override the SMTP server's idea of the remote
|
||||
client name, client address and other information. Such information
|
||||
can typically be extracted from the up-stream mail server's Received:
|
||||
message header.
|
||||
|
||||
3 - Post-filter access control and logging. With Internet->filter->MTA
|
||||
style content filter applications, the filter can be simplified if
|
||||
it can delegate decisions concerning mail relay and other access
|
||||
control to the MTA. As in the first example, this requires that
|
||||
the filter can override the MTA's idea of the SMTP client hostname,
|
||||
network address, and other information, for the entire duration of
|
||||
an SMTP session.
|
||||
control to the MTA. This is especially useful when the filter acts
|
||||
as a transparent proxy for SMTP commands. As in the first example,
|
||||
this requires that the filter can override the MTA's idea of the
|
||||
SMTP client hostname, network address, and other information.
|
||||
|
||||
4 - Fetchmail.
|
||||
Command syntax
|
||||
==============
|
||||
|
||||
Command overview
|
||||
================
|
||||
|
||||
The EHLO keyword associated with this extension is XCLIENT. In EHLO
|
||||
replies, XCLIENT is followed by the names of the supported XCLIENT
|
||||
functions.
|
||||
|
||||
The XCLIENT OVERRIDE function updates remote client attributes that
|
||||
the MTA normally uses for access control, message headers, logging
|
||||
and so on, for the duration of an entire SMTP session.
|
||||
|
||||
The XCLIENT FORWARD function updates temporary remote client
|
||||
attributes that the MTA uses for transaction logging. These attributes
|
||||
are valid for only one message delivery attempt. In the absence
|
||||
of forwarded attributes the MTA must use the normal remote client
|
||||
attribute values.
|
||||
In SMTP server EHLO replies, the keyword associated with this
|
||||
extension is XCLIENT. It is followed by the names of the attributes
|
||||
that the XCLIENT implementation supports.
|
||||
|
||||
The general command syntax is described below. Upper case and
|
||||
quoted strings specify terminals, lowercase strings specify meta
|
||||
terminals, SP is whitespace, and descriptive text is enclosed in
|
||||
{}. Although command and attribute names are shown below in upper
|
||||
case, they are in fact case insensitive.
|
||||
terminals, and SP is whitespace. Although command and attribute
|
||||
names are shown in upper case, they are in fact case insensitive.
|
||||
|
||||
xclient-command = XCLIENT SP function SP 1*( attribute )
|
||||
|
||||
function = ( OVERRIDE | FORWARD )
|
||||
xclient-command = XCLIENT 1*( SP attribute )
|
||||
|
||||
attribute = name"="value
|
||||
|
||||
name = ( NAME|ADDR|CODE|PROTO|HELO )
|
||||
|
||||
value = ( { empty } | xtext )
|
||||
|
||||
xtext = { attribute value encoded as per RFC 1891 }
|
||||
name = ( NAME | ADDR | PROTO | HELO )
|
||||
|
||||
The XCLIENT command can be sent at any time except in the middle
|
||||
of a mail delivery transaction (i.e. between MAIL and DOT). The
|
||||
command may be pipelined after the server EHLO reply announces
|
||||
ESMTP pipelining support.
|
||||
command may be pipelined if the server EHLO reply announces ESMTP
|
||||
pipelining support.
|
||||
|
||||
The server reply codes are as follows:
|
||||
The XCLIENT reply codes are as follows:
|
||||
|
||||
Code | Meaning
|
||||
-----|------------
|
||||
250 | success
|
||||
501 | bad command parameter
|
||||
501 | bad command parameter syntax
|
||||
503 | mail transaction in progress
|
||||
421 | unable to proceed
|
||||
|
||||
The server must report success in case of an unrecognized attribute
|
||||
name, although it may log a warning.
|
||||
The NAME attribute specifies an SMTP client hostname (not an SMTP
|
||||
client address), [unavailable] when client hostname lookup failed
|
||||
due to a permanent error, or [temporary] when the lookup error
|
||||
condition was transient.
|
||||
|
||||
Specific usage scenarios
|
||||
========================
|
||||
The ADDR attribute specifies an SMTP client numerical IPv4 network
|
||||
address, an IPv6 address prefixed with IPV6:, or [unavailable]
|
||||
when the address information is unavailable. Address information
|
||||
is not enclosed with [].
|
||||
|
||||
This section discusses the semantics of XCLIENT requests. Specific
|
||||
syntax details are given in the next section.
|
||||
The PROTO attribute specifies either SMTP or ESMTP.
|
||||
|
||||
The XCLIENT OVERRIDE request modifies remote client attributes that
|
||||
the MTA normally uses for access control, message headers, logging,
|
||||
and for other purposes, for the duraction of the entire SMTP session.
|
||||
Attributes that are not specified in XCLIENT OVERRIDE requests are
|
||||
not modified.
|
||||
The HELO attribute specifies a HELO parameter value, or the value
|
||||
[unavailable] when the information is unavailable.
|
||||
|
||||
The following example overrides only the client hostname and network
|
||||
address, leaving unchanged all other client attributes such as the
|
||||
mail protocol or the hostname given in the HELO command:
|
||||
|
||||
XCLIENT OVERRIDE NAME=spike.porcupine.org
|
||||
XCLIENT OVERRIDE ADDR=168.100.189.2
|
||||
|
||||
The XCLIENT FORWARD request specifies remote client attributes that
|
||||
are logged with one message delivery attempt. The attributes are
|
||||
discarded after the MAIL FROM transaction finishes. In the absence
|
||||
of any XCLIENT FORWARD attributes, the MTA must use the normal
|
||||
client attributes.
|
||||
|
||||
If only a subset of all possible XCLIENT FORWARD attributes is
|
||||
specified, the unspecified attributes must be treated as if they
|
||||
are unknown. The implementation must not replace missing XCLIENT
|
||||
FORWARD attributes by normal attributes.
|
||||
|
||||
The following example updates all forwarded client attributes that
|
||||
are defined in this document, leaving none at their default unknown
|
||||
value:
|
||||
|
||||
XCLIENT FORWARD NAME=spike.porcupine.org ADDR=168.100.189.2
|
||||
XCLIENT FORWARD HELO=spike.porcupine.org PROTO=ESMTP
|
||||
|
||||
Note 1: attributes specified with successive XCLIENT commands
|
||||
accumulate.
|
||||
|
||||
Note 2: XCLIENT FORWARD attributes take precedence over XCLIENT
|
||||
OVERRIDE attributes.
|
||||
|
||||
Attribute value details
|
||||
=======================
|
||||
|
||||
Attribute values are encoded as RFC 1891 xtext strings. To explicitly
|
||||
specify that an attribute value is unavailable, the value must be
|
||||
empty; the client must not send its own internal representation of
|
||||
unavailable information.
|
||||
|
||||
The NAME_CODE attribute specifies NAME hostname lookup status
|
||||
information. Values are OK (success), TEMP (temporary lookup
|
||||
failure) or PERM (permanent lookup failure). When CODE is set to
|
||||
any value other than OK, the NAME attribute is automatically set
|
||||
to the unknown value.
|
||||
|
||||
The NAME attribute specifies a name space (typically, DNS) and
|
||||
an MTA name within that name space.
|
||||
and not a numerical address. When a null client name is specified
|
||||
(i.e. the client name is unknown), the CODE attribute is implicitly
|
||||
set to PERM. When a valid domain name is specified, CODE is implicitly
|
||||
set to OK. The server may process a syntactically invalid domain
|
||||
name as if it were unknown.
|
||||
|
||||
The ADDR attribute must specify a numerical network address without
|
||||
[].
|
||||
|
||||
The PROTO attribute should be a string of up to 64 printable
|
||||
characters, where printable is defined by the ANSI C isascii() and
|
||||
isprint() predicates.
|
||||
|
||||
The HELO attribute should be a syntactically valid HELO
|
||||
parameter value.
|
||||
|
||||
Note 3: syntactically valid NAME and HELO attributes can be up to
|
||||
Note 1: syntactically valid NAME and HELO attributes can be up to
|
||||
255 characters long. The client must not send XCLIENT commands that
|
||||
exceed the 512 character limit of SMTP commands.
|
||||
exceed the 512 character limit for SMTP commands.
|
||||
|
||||
Note 4: attribute values may end up in Received: or other message
|
||||
headers. The receiving MTA may substitute characters in order to
|
||||
not violate RFC 822 or RFC 2822.
|
||||
Note 2: [UNAVAILABLE], [TEMPORARY] and IPV6: may be specified in
|
||||
upper case, lower case or mixed case.
|
||||
|
||||
Security
|
||||
========
|
||||
|
||||
The XCLIENT command changes audit trails and/or client access
|
||||
permissions. For these reasons, use of these commands must be
|
||||
restricted to authorized clients only.
|
||||
permissions. Use of this command must be restricted to authorized
|
||||
clients.
|
||||
|
||||
The examples in this document assume that XCLIENT does not override
|
||||
its own access control mechanism.
|
||||
The XCLIENT should 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. The XCLIENT FORWARD attributes are reset after the MAIL
|
||||
FROM command completes, so there is no risk of information leakage.
|
||||
messages within the same SMTP session. The XCLIENT attributes are
|
||||
persistent across deliveries, and need to be reset as appropriate
|
||||
in order to avoid information leakage.
|
||||
|
95
postfix/README_FILES/XFORWARD_README
Normal file
95
postfix/README_FILES/XFORWARD_README
Normal file
@ -0,0 +1,95 @@
|
||||
Purpose of the XFORWARD extension to SMTP
|
||||
========================================
|
||||
|
||||
The XFORWARD command targets the following problem:
|
||||
|
||||
- Logging after SMTP-based content filter. With the deployment of
|
||||
Internet->MTA1->filter->MTA2 style content filter applications,
|
||||
the logging of client and message identifying information changes
|
||||
when MTA1 gives the mail to the content filter. To simplify the
|
||||
interpretation of MTA2 logging, it would help if MTA1 could forward
|
||||
remote client and/or message identifying information through the
|
||||
content filter to MTA2, so that the information could be logged as
|
||||
part of mail handling transactions.
|
||||
|
||||
Command syntax
|
||||
==============
|
||||
|
||||
In SMTP server EHLO replies, the keyword associated with this
|
||||
extension is XFORWARD. The keyword is followed by the names of the
|
||||
attributes that the XFORWARD implementation supports.
|
||||
|
||||
The general command syntax is described below. Upper case and
|
||||
quoted strings specify terminals, lowercase strings specify meta
|
||||
terminals, and SP is whitespace. Although command and attribute
|
||||
names are shown in upper case, they are in fact case insensitive.
|
||||
|
||||
xclient-command = XFORWARD 1*( SP attribute )
|
||||
|
||||
attribute = name"="value
|
||||
|
||||
name = ( NAME | ADDR | PROTO | HELO | IDENT )
|
||||
|
||||
The XFORWARD command can be sent at any time except in the middle
|
||||
of a mail delivery transaction (i.e. between MAIL and DOT). The
|
||||
command may be pipelined if the server EHLO reply announces ESMTP
|
||||
pipelining support.
|
||||
|
||||
The XFORWARD reply codes are as follows:
|
||||
|
||||
Code | Meaning
|
||||
-----|------------
|
||||
250 | success
|
||||
501 | bad command parameter syntax
|
||||
503 | mail transaction in progress
|
||||
421 | unable to proceed
|
||||
|
||||
The information specified with XFORWARD attribues is not limited
|
||||
to DNS hostnames, IP addresses or SMTP protocol names. Attribute
|
||||
values may contain arbitrary text, but must not contain control
|
||||
characters, non-ASCII characters, whitespace, or other characters
|
||||
that are special in message headers.
|
||||
|
||||
The NAME attribute specifies an up-stream client hostname, or
|
||||
[UNAVAILABLE] when the information is unavailable. The hostname
|
||||
may be a non-DNS hostname.
|
||||
|
||||
The ADDR attribute specifies an up-stream client network address,
|
||||
or [UNAVAILABLE] when the information is unavailable. Address
|
||||
information is not enclosed with []. The address may be a non-IP
|
||||
address.
|
||||
|
||||
The PROTO attribute specifies the mail protocol that was used by
|
||||
the up-stream client. This may be an SMTP non-SMTP protocol name
|
||||
of up to 64 characters, or [UNAVAILABLE] when the information is
|
||||
unavailable.
|
||||
|
||||
The HELO attribute specifies the hostname that the up-stream client
|
||||
host introduced itself with (for example, via the SMTP HELO command),
|
||||
or [UNAVAILABLE] when the information is unavailable. The hostname
|
||||
may be a non-DNS hostname.
|
||||
|
||||
Note 1: DNS hostnames can be up to 255 characters long. The XFORWARD
|
||||
client implementation must not send XFORWARD commands that exceed
|
||||
the 512 character limit for SMTP commands.
|
||||
|
||||
Note 2: [UNAVAILABLE] may be specified in upper case, lower case
|
||||
or mixed case.
|
||||
|
||||
Note 3: the XFORWARD server implementation must not mix information
|
||||
from the current SMTP session with forwarded information from an
|
||||
up-stream session.
|
||||
|
||||
Security
|
||||
========
|
||||
|
||||
The XFORWARD command changes audit trails. Use of this command
|
||||
must be restricted to authorized clients.
|
||||
|
||||
SMTP connection caching
|
||||
=======================
|
||||
|
||||
SMTP connection caching makes it possible to deliver multiple
|
||||
messages within the same SMTP session. The XFORWARD attributes are
|
||||
reset after the MAIL FROM command completes, so there is no risk
|
||||
of information leakage.
|
@ -217,3 +217,5 @@ $readme_directory/ULTRIX_README:f:root:-:644
|
||||
$readme_directory/UUCP_README:f:root:-:644
|
||||
$readme_directory/VERP_README:f:root:-:644
|
||||
$readme_directory/VIRTUAL_README:f:root:-:644
|
||||
$readme_directory/XCLIENT_README:f:root:-:644
|
||||
$readme_directory/XFORWARD_README:f:root:-:644
|
||||
|
@ -21,6 +21,17 @@ lmtp_skip_quit_response = yes
|
||||
#
|
||||
lmtp_tcp_port = 24
|
||||
|
||||
# The lmtp_send_xforward_command parameter controls whether the Postfix
|
||||
# LMTP client will send an XFORWARD command to the SMTP server, when
|
||||
# the ELMTP HELO response of the remote host indicates XFORWARD 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 LMTP server. Before you change the value to yes, it is best
|
||||
# to make sure your content filter supports this command.
|
||||
#
|
||||
lmtp_send_xforward_command = no
|
||||
|
||||
#
|
||||
# RESOURCE AND RATE CONTROLS
|
||||
#
|
||||
@ -83,6 +94,18 @@ lmtp_connect_timeout = 0s
|
||||
#
|
||||
lmtp_lhlo_timeout = 300s
|
||||
|
||||
# The lmtp_xforward_timeout parameter specifies the LMTP client timeout
|
||||
# for sending the LMTP XFORWARD command, and for receiving the server
|
||||
# response.
|
||||
#
|
||||
# In case of problems the client does NOT try the next address on
|
||||
# the mail exchanger list.
|
||||
#
|
||||
# Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
|
||||
# The default time unit is s (seconds).
|
||||
#
|
||||
lmtp_xforward_timeout = 300s
|
||||
|
||||
# The lmtp_mail_timeout parameter specifies the LMTP client timeout
|
||||
# for sending the LMTP MAIL FROM command, and for receiving the server
|
||||
# response.
|
||||
|
@ -107,6 +107,13 @@ LMTP(8) LMTP(8)
|
||||
server. Used as backup if the <b>lmtp</b> service is not
|
||||
found in <b>services</b>(4).
|
||||
|
||||
<b>lmtp_send_xforward_command</b>
|
||||
If the LMTP server announces XFORWARD 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 LMTP server.
|
||||
|
||||
<b>Authentication controls</b>
|
||||
<b>lmtp_sasl_auth_enable</b>
|
||||
Enable per-session authentication as per <a href="http://www.faqs.org/rfcs/rfc2554.html">RFC 2554</a>
|
||||
@ -206,16 +213,20 @@ LMTP(8) LMTP(8)
|
||||
Timeout for sending the <b>LHLO</b> command, and for
|
||||
receiving the server response.
|
||||
|
||||
<b>lmtp_xforward_timeout</b>
|
||||
Timeout for sending the <b>XFORWARD</b> command, and for
|
||||
receiving the server response.
|
||||
|
||||
<b>lmtp_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>lmtp_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>lmtp_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>lmtp_data_xfer_timeout</b>
|
||||
@ -223,16 +234,16 @@ LMTP(8) LMTP(8)
|
||||
|
||||
<b>lmtp_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>lmtp_rset_timeout</b>
|
||||
Timeout for sending the <b>RSET</b> command, and for
|
||||
Timeout for sending the <b>RSET</b> command, and for
|
||||
receiving the server response.
|
||||
|
||||
<b>lmtp_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>
|
||||
@ -245,7 +256,7 @@ LMTP(8) LMTP(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>
|
||||
|
@ -135,6 +135,13 @@ SMTP(8) SMTP(8)
|
||||
Numerical source network address to bind to when
|
||||
making a connection.
|
||||
|
||||
<b>smtp_defer_if_no_mx_address_found</b>
|
||||
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
|
||||
until the mail is too old.
|
||||
|
||||
<b>smtp_line_length_limit</b>
|
||||
Length limit for SMTP message content lines. Zero
|
||||
means no limit. Some SMTP servers misbehave on
|
||||
@ -186,6 +193,13 @@ SMTP(8) SMTP(8)
|
||||
nested deeper, when converting from 8BITMIME format
|
||||
to 7BIT format.
|
||||
|
||||
<b>smtp_send_xforward_command</b>
|
||||
If the SMTP server announces XFORWARD 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>Authentication controls</b>
|
||||
<b>smtp_sasl_auth_enable</b>
|
||||
Enable per-session authentication as per <a href="http://www.faqs.org/rfcs/rfc2554.html">RFC 2554</a>
|
||||
@ -274,20 +288,6 @@ SMTP(8) SMTP(8)
|
||||
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
|
||||
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
|
||||
until the mail is too old.
|
||||
|
||||
<b>smtp_send_xforward_command</b>
|
||||
If the SMTP server announces XFORWARD 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.
|
||||
|
||||
|
@ -104,6 +104,11 @@ Do not wait for the server response after sending QUIT.
|
||||
.IP \fBlmtp_tcp_port\fR
|
||||
The TCP port to be used when connecting to a LMTP server. Used as
|
||||
backup if the \fBlmtp\fR service is not found in \fBservices\fR(4).
|
||||
.IP \fBlmtp_send_xforward_command\fR
|
||||
If the LMTP server announces XFORWARD 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 LMTP server.
|
||||
.SH "Authentication controls"
|
||||
.IP \fBlmtp_sasl_auth_enable\fR
|
||||
Enable per-session authentication as per RFC 2554 (SASL).
|
||||
@ -185,6 +190,9 @@ is deferred.
|
||||
.IP \fBlmtp_lhlo_timeout\fR
|
||||
Timeout for sending the \fBLHLO\fR command, and for
|
||||
receiving the server response.
|
||||
.IP \fBlmtp_xforward_timeout\fR
|
||||
Timeout for sending the \fBXFORWARD\fR command, and for
|
||||
receiving the server response.
|
||||
.IP \fBlmtp_mail_timeout\fR
|
||||
Timeout for sending the \fBMAIL FROM\fR command, and for
|
||||
receiving the server response.
|
||||
|
@ -125,6 +125,12 @@ Always send EHLO at the start of a connection.
|
||||
Never send EHLO at the start of a connection.
|
||||
.IP \fBsmtp_bind_address\fR
|
||||
Numerical source network address to bind to when making a connection.
|
||||
.IP \fBsmtp_defer_if_no_mx_address_found\fR
|
||||
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 until
|
||||
the mail is too old.
|
||||
.IP \fBsmtp_line_length_limit\fR
|
||||
Length limit for SMTP message content lines. Zero means no limit.
|
||||
Some SMTP servers misbehave on long lines.
|
||||
@ -158,6 +164,11 @@ between boundary strings that do not differ in the first
|
||||
The maximal nesting level of multipart mail that the MIME
|
||||
processor can handle. Refuse mail that is nested deeper,
|
||||
when converting from 8BITMIME format to 7BIT format.
|
||||
.IP \fBsmtp_send_xforward_command\fR
|
||||
If the SMTP server announces XFORWARD 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.
|
||||
.SH "Authentication controls"
|
||||
.IP \fBsmtp_sasl_auth_enable\fR
|
||||
Enable per-session authentication as per RFC 2554 (SASL).
|
||||
@ -228,17 +239,6 @@ Timeout for sending the message content.
|
||||
Timeout for sending the "\fB.\fR" command, and for
|
||||
receiving the server response. When no response is received, a
|
||||
warning is logged that the mail may be delivered multiple times.
|
||||
.IP \fBsmtp_defer_if_no_mx_address_found\fR
|
||||
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 until
|
||||
the mail is too old.
|
||||
.IP \fBsmtp_send_xforward_command\fR
|
||||
If the SMTP server announces XFORWARD 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
|
||||
|
@ -753,9 +753,9 @@ 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_XFWD_TMOUT "smtp_xforward_timeout"
|
||||
#define DEF_SMTP_XFWD_TMOUT "300s"
|
||||
extern int var_smtp_xfwd_tmout;
|
||||
|
||||
#define VAR_SMTP_MAIL_TMOUT "smtp_mail_timeout"
|
||||
#define DEF_SMTP_MAIL_TMOUT "300s"
|
||||
@ -1032,6 +1032,10 @@ extern int var_lmtp_rset_tmout;
|
||||
#define DEF_LMTP_LHLO_TMOUT "300s"
|
||||
extern int var_lmtp_lhlo_tmout;
|
||||
|
||||
#define VAR_LMTP_XFWD_TMOUT "lmtp_xforward_timeout"
|
||||
#define DEF_LMTP_XFWD_TMOUT "300s"
|
||||
extern int var_lmtp_xfwd_tmout;
|
||||
|
||||
#define VAR_LMTP_MAIL_TMOUT "lmtp_mail_timeout"
|
||||
#define DEF_LMTP_MAIL_TMOUT "300s"
|
||||
extern int var_lmtp_mail_tmout;
|
||||
@ -1056,6 +1060,10 @@ extern int var_lmtp_data2_tmout;
|
||||
#define DEF_LMTP_QUIT_TMOUT "300s"
|
||||
extern int var_lmtp_quit_tmout;
|
||||
|
||||
#define VAR_LMTP_SEND_XFORWARD "lmtp_send_xforward_command"
|
||||
#define DEF_LMTP_SEND_XFORWARD 0
|
||||
extern bool var_lmtp_send_xforward;
|
||||
|
||||
/*
|
||||
* Cleanup service. Header info that exceeds $header_size_limit bytes forces
|
||||
* the start of the message body.
|
||||
|
@ -152,15 +152,17 @@ extern char *mail_pathname(const char *, const char *);
|
||||
#define MAIL_ATTR_ORG_LOCAL "local" /* local submission */
|
||||
|
||||
/*
|
||||
* XCLIENT in SMTP.
|
||||
* XCLIENT/XFORWARD in SMTP.
|
||||
*/
|
||||
#define XCLIENT_CMD "XCLIENT" /* XCLIENT command */
|
||||
#define XCLIENT_NAME "NAME" /* client name */
|
||||
#define XCLIENT_ADDR "ADDR" /* client address */
|
||||
#define XCLIENT_PROTO "PROTO" /* client protocol */
|
||||
#define XCLIENT_CODE "NAME_CODE" /* client name status */
|
||||
#define XCLIENT_HELO "HELO" /* client helo */
|
||||
|
||||
#define XCLIENT_UNAVAILABLE "[UNAVAILABLE]" /* permanently unavailable */
|
||||
#define XCLIENT_TEMPORARY "[TEMPUNAVAIL]" /* temporarily unavailable */
|
||||
|
||||
#define XFORWARD_CMD "XFORWARD" /* XFORWARD command */
|
||||
#define XFORWARD_NAME "NAME" /* client name */
|
||||
#define XFORWARD_ADDR "ADDR" /* client address */
|
||||
@ -168,6 +170,8 @@ extern char *mail_pathname(const char *, const char *);
|
||||
#define XFORWARD_HELO "HELO" /* client helo */
|
||||
#define XFORWARD_IDENT "IDENT" /* message identifier */
|
||||
|
||||
#define XFORWARD_UNAVAILABLE "[UNAVAILABLE]" /* attribute unavailable */
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
|
@ -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 "20031213"
|
||||
#define MAIL_RELEASE_DATE "20031214"
|
||||
|
||||
#define VAR_MAIL_VERSION "mail_version"
|
||||
#define DEF_MAIL_VERSION "2.0.16-" MAIL_RELEASE_DATE
|
||||
|
@ -88,6 +88,11 @@
|
||||
/* .IP \fBlmtp_tcp_port\fR
|
||||
/* The TCP port to be used when connecting to a LMTP server. Used as
|
||||
/* backup if the \fBlmtp\fR service is not found in \fBservices\fR(4).
|
||||
/* .IP \fBlmtp_send_xforward_command\fR
|
||||
/* If the LMTP server announces XFORWARD 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 LMTP server.
|
||||
/* .SH "Authentication controls"
|
||||
/* .IP \fBlmtp_sasl_auth_enable\fR
|
||||
/* Enable per-session authentication as per RFC 2554 (SASL).
|
||||
@ -169,6 +174,9 @@
|
||||
/* .IP \fBlmtp_lhlo_timeout\fR
|
||||
/* Timeout for sending the \fBLHLO\fR command, and for
|
||||
/* receiving the server response.
|
||||
/* .IP \fBlmtp_xforward_timeout\fR
|
||||
/* Timeout for sending the \fBXFORWARD\fR command, and for
|
||||
/* receiving the server response.
|
||||
/* .IP \fBlmtp_mail_timeout\fR
|
||||
/* Timeout for sending the \fBMAIL FROM\fR command, and for
|
||||
/* receiving the server response.
|
||||
@ -263,6 +271,7 @@ int var_lmtp_tcp_port;
|
||||
int var_lmtp_conn_tmout;
|
||||
int var_lmtp_rset_tmout;
|
||||
int var_lmtp_lhlo_tmout;
|
||||
int var_lmtp_xfwd_tmout;
|
||||
int var_lmtp_mail_tmout;
|
||||
int var_lmtp_rcpt_tmout;
|
||||
int var_lmtp_data0_tmout;
|
||||
@ -276,6 +285,7 @@ char *var_error_rcpt;
|
||||
char *var_lmtp_sasl_opts;
|
||||
char *var_lmtp_sasl_passwd;
|
||||
bool var_lmtp_sasl_enable;
|
||||
bool var_lmtp_send_xforward;
|
||||
|
||||
/*
|
||||
* Global variables.
|
||||
@ -538,6 +548,7 @@ int main(int argc, char **argv)
|
||||
VAR_LMTP_CONN_TMOUT, DEF_LMTP_CONN_TMOUT, &var_lmtp_conn_tmout, 0, 0,
|
||||
VAR_LMTP_RSET_TMOUT, DEF_LMTP_RSET_TMOUT, &var_lmtp_rset_tmout, 1, 0,
|
||||
VAR_LMTP_LHLO_TMOUT, DEF_LMTP_LHLO_TMOUT, &var_lmtp_lhlo_tmout, 1, 0,
|
||||
VAR_LMTP_XFWD_TMOUT, DEF_LMTP_XFWD_TMOUT, &var_lmtp_xfwd_tmout, 1, 0,
|
||||
VAR_LMTP_MAIL_TMOUT, DEF_LMTP_MAIL_TMOUT, &var_lmtp_mail_tmout, 1, 0,
|
||||
VAR_LMTP_RCPT_TMOUT, DEF_LMTP_RCPT_TMOUT, &var_lmtp_rcpt_tmout, 1, 0,
|
||||
VAR_LMTP_DATA0_TMOUT, DEF_LMTP_DATA0_TMOUT, &var_lmtp_data0_tmout, 1, 0,
|
||||
|
@ -61,6 +61,16 @@ typedef struct LMTP_STATE {
|
||||
#define LMTP_FEATURE_PIPELINING (1<<2)
|
||||
#define LMTP_FEATURE_SIZE (1<<3)
|
||||
#define LMTP_FEATURE_AUTH (1<<5)
|
||||
#define LMTP_FEATURE_XFORWARD_NAME (1<<6)
|
||||
#define LMTP_FEATURE_XFORWARD_ADDR (1<<7)
|
||||
#define LMTP_FEATURE_XFORWARD_PROTO (1<<8)
|
||||
#define LMTP_FEATURE_XFORWARD_HELO (1<<9)
|
||||
|
||||
#define LMTP_FEATURE_XFORWARD_NAME_ADDR \
|
||||
(LMTP_FEATURE_XFORWARD_NAME | LMTP_FEATURE_XFORWARD_ADDR)
|
||||
|
||||
#define LMTP_FEATURE_XFORWARD_PROTO_HELO \
|
||||
(LMTP_FEATURE_XFORWARD_PROTO | LMTP_FEATURE_XFORWARD_HELO)
|
||||
|
||||
/*
|
||||
* lmtp.c
|
||||
|
@ -100,6 +100,7 @@
|
||||
#include <vstring_vstream.h>
|
||||
#include <stringops.h>
|
||||
#include <mymalloc.h>
|
||||
#include <name_code.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
@ -141,48 +142,58 @@
|
||||
* the existing code for exception handling and error reporting.
|
||||
*
|
||||
* Client states that are associated with sending mail (up to and including
|
||||
* SMTP_STATE_DOT) must have smaller numerical values than the non-sending
|
||||
* states (SMTP_STATE_ABORT .. SMTP_STATE_LAST).
|
||||
* LMTP_STATE_DOT) must have smaller numerical values than the non-sending
|
||||
* states (LMTP_STATE_ABORT .. LMTP_STATE_LAST).
|
||||
*/
|
||||
#define LMTP_STATE_MAIL 0
|
||||
#define LMTP_STATE_RCPT 1
|
||||
#define LMTP_STATE_DATA 2
|
||||
#define LMTP_STATE_DOT 3
|
||||
#define LMTP_STATE_ABORT 4
|
||||
#define LMTP_STATE_RSET 5
|
||||
#define LMTP_STATE_QUIT 6
|
||||
#define LMTP_STATE_LAST 7
|
||||
#define LMTP_STATE_XFORWARD_NAME_ADDR 0
|
||||
#define LMTP_STATE_XFORWARD_PROTO_HELO 1
|
||||
#define LMTP_STATE_MAIL 2
|
||||
#define LMTP_STATE_RCPT 3
|
||||
#define LMTP_STATE_DATA 4
|
||||
#define LMTP_STATE_DOT 5
|
||||
#define LMTP_STATE_ABORT 6
|
||||
#define LMTP_STATE_RSET 7
|
||||
#define LMTP_STATE_QUIT 8
|
||||
#define LMTP_STATE_LAST 9
|
||||
|
||||
int *xfer_timeouts[LMTP_STATE_LAST] = {
|
||||
&var_lmtp_xfwd_tmout, /* name/addr */
|
||||
&var_lmtp_xfwd_tmout, /* helo/proto */
|
||||
&var_lmtp_mail_tmout,
|
||||
&var_lmtp_rcpt_tmout,
|
||||
&var_lmtp_data0_tmout,
|
||||
&var_lmtp_data2_tmout,
|
||||
&var_lmtp_rset_tmout,
|
||||
&var_lmtp_rset_tmout,
|
||||
&var_lmtp_rset_tmout, /* abort */
|
||||
&var_lmtp_rset_tmout, /* rset */
|
||||
&var_lmtp_quit_tmout,
|
||||
};
|
||||
|
||||
char *xfer_states[LMTP_STATE_LAST] = {
|
||||
"sending XFORWARD name/address",
|
||||
"sending XFORWARD protocol/helo_name",
|
||||
"sending MAIL FROM",
|
||||
"sending RCPT TO",
|
||||
"sending DATA command",
|
||||
"sending end of data -- message may be sent more than once",
|
||||
"sending RSET",
|
||||
"sending RSET",
|
||||
"sending RSET", /* abort */
|
||||
"sending RSET", /* rset */
|
||||
"sending QUIT",
|
||||
};
|
||||
|
||||
char *xfer_request[LMTP_STATE_LAST] = {
|
||||
"XFORWARD name/address command",
|
||||
"XFORWARD helo/protocol command",
|
||||
"MAIL FROM command",
|
||||
"RCPT TO command",
|
||||
"DATA command",
|
||||
"end of DATA command",
|
||||
"RSET command",
|
||||
"RSET command",
|
||||
"RSET command", /* abort */
|
||||
"RSET command", /* rset */
|
||||
"QUIT command",
|
||||
};
|
||||
|
||||
static int lmtp_send_proto_helo;
|
||||
|
||||
/* lmtp_lhlo - perform initial handshake with LMTP server */
|
||||
|
||||
int lmtp_lhlo(LMTP_STATE *state)
|
||||
@ -193,6 +204,13 @@ int lmtp_lhlo(LMTP_STATE *state)
|
||||
char *lines;
|
||||
char *words;
|
||||
char *word;
|
||||
static NAME_CODE xforward_features[] = {
|
||||
XFORWARD_NAME, LMTP_FEATURE_XFORWARD_NAME,
|
||||
XFORWARD_ADDR, LMTP_FEATURE_XFORWARD_ADDR,
|
||||
XFORWARD_PROTO, LMTP_FEATURE_XFORWARD_PROTO,
|
||||
XFORWARD_HELO, LMTP_FEATURE_XFORWARD_HELO,
|
||||
0, 0,
|
||||
};
|
||||
|
||||
/*
|
||||
* Prepare for disaster.
|
||||
@ -235,6 +253,10 @@ int lmtp_lhlo(LMTP_STATE *state)
|
||||
state->features |= LMTP_FEATURE_8BITMIME;
|
||||
else if (strcasecmp(word, "PIPELINING") == 0)
|
||||
state->features |= LMTP_FEATURE_PIPELINING;
|
||||
else if (strcasecmp(word, "XFORWARD") == 0)
|
||||
while ((word = mystrtok(&words, " \t")) != 0)
|
||||
state->features |= name_code(xforward_features,
|
||||
NAME_CODE_FLAG_NONE, word);
|
||||
else if (strcasecmp(word, "SIZE") == 0)
|
||||
state->features |= LMTP_FEATURE_SIZE;
|
||||
#ifdef USE_SASL_AUTH
|
||||
@ -364,6 +386,40 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state)
|
||||
default:
|
||||
msg_panic("%s: bad sender state %d", myname, send_state);
|
||||
|
||||
/*
|
||||
* Build the XFORWARD command. With properly sanitized
|
||||
* information, the command length stays within the 512 byte
|
||||
* command line length limit.
|
||||
*/
|
||||
case LMTP_STATE_XFORWARD_NAME_ADDR:
|
||||
vstring_strcpy(next_command, XFORWARD_CMD);
|
||||
if (state->features & LMTP_FEATURE_XFORWARD_NAME)
|
||||
vstring_sprintf_append(next_command, " %s=%s",
|
||||
XFORWARD_NAME, DEL_REQ_ATTR_AVAIL(request->client_name) ?
|
||||
request->client_name : XFORWARD_UNAVAILABLE);
|
||||
if (state->features & LMTP_FEATURE_XFORWARD_ADDR)
|
||||
vstring_sprintf_append(next_command, " %s=%s",
|
||||
XFORWARD_ADDR, DEL_REQ_ATTR_AVAIL(request->client_addr) ?
|
||||
request->client_addr : XFORWARD_UNAVAILABLE);
|
||||
if (lmtp_send_proto_helo)
|
||||
next_state = LMTP_STATE_XFORWARD_PROTO_HELO;
|
||||
else
|
||||
next_state = LMTP_STATE_MAIL;
|
||||
break;
|
||||
|
||||
case LMTP_STATE_XFORWARD_PROTO_HELO:
|
||||
vstring_strcpy(next_command, XFORWARD_CMD);
|
||||
if (state->features & LMTP_FEATURE_XFORWARD_PROTO)
|
||||
vstring_sprintf_append(next_command, " %s=%s",
|
||||
XFORWARD_PROTO, DEL_REQ_ATTR_AVAIL(request->client_proto) ?
|
||||
request->client_proto : XFORWARD_UNAVAILABLE);
|
||||
if (state->features & LMTP_FEATURE_XFORWARD_HELO)
|
||||
vstring_sprintf_append(next_command, " %s=%s",
|
||||
XFORWARD_HELO, DEL_REQ_ATTR_AVAIL(request->client_helo) ?
|
||||
request->client_helo : XFORWARD_UNAVAILABLE);
|
||||
next_state = LMTP_STATE_MAIL;
|
||||
break;
|
||||
|
||||
/*
|
||||
* Build the MAIL FROM command.
|
||||
*/
|
||||
@ -478,7 +534,7 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state)
|
||||
/*
|
||||
* Sanity check.
|
||||
*/
|
||||
if (recv_state < LMTP_STATE_MAIL
|
||||
if (recv_state < LMTP_STATE_XFORWARD_NAME_ADDR
|
||||
|| recv_state > LMTP_STATE_QUIT)
|
||||
msg_panic("%s: bad receiver state %d (sender state %d)",
|
||||
myname, recv_state, send_state);
|
||||
@ -499,6 +555,30 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state)
|
||||
*/
|
||||
switch (recv_state) {
|
||||
|
||||
/*
|
||||
* Process the XFORWARD response.
|
||||
*/
|
||||
case LMTP_STATE_XFORWARD_NAME_ADDR:
|
||||
if (resp->code / 100 != 2)
|
||||
msg_warn("host %s said: %s (in reply to %s)",
|
||||
session->namaddr,
|
||||
translit(resp->str, "\n", " "),
|
||||
xfer_request[LMTP_STATE_XFORWARD_NAME_ADDR]);
|
||||
if (lmtp_send_proto_helo)
|
||||
recv_state = LMTP_STATE_XFORWARD_PROTO_HELO;
|
||||
else
|
||||
recv_state = LMTP_STATE_MAIL;
|
||||
break;
|
||||
|
||||
case LMTP_STATE_XFORWARD_PROTO_HELO:
|
||||
if (resp->code / 100 != 2)
|
||||
msg_warn("host %s said: %s (in reply to %s)",
|
||||
session->namaddr,
|
||||
translit(resp->str, "\n", " "),
|
||||
xfer_request[LMTP_STATE_XFORWARD_PROTO_HELO]);
|
||||
recv_state = LMTP_STATE_MAIL;
|
||||
break;
|
||||
|
||||
/*
|
||||
* Process the MAIL FROM response. When the server
|
||||
* rejects the sender, set the mail_from_rejected flag so
|
||||
@ -546,7 +626,7 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state)
|
||||
&& sent(DEL_REQ_TRACE_FLAGS(request->flags),
|
||||
request->queue_id, rcpt->orig_addr,
|
||||
rcpt->address, rcpt->offset,
|
||||
session->namaddr, request->arrival_time,
|
||||
session->namaddr, request->arrival_time,
|
||||
"%s",
|
||||
translit(resp->str, "\n", " ")) == 0) {
|
||||
if (request->flags & DEL_REQ_FLAG_SUCCESS)
|
||||
@ -746,7 +826,31 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state)
|
||||
|
||||
int lmtp_xfer(LMTP_STATE *state)
|
||||
{
|
||||
return (lmtp_loop(state, LMTP_STATE_MAIL, LMTP_STATE_MAIL));
|
||||
DELIVER_REQUEST *request = state->request;
|
||||
int start;
|
||||
int send_name_addr;
|
||||
|
||||
/*
|
||||
* Use the XFORWARD command to forward client attributes only when a
|
||||
* minimal amount of information is available.
|
||||
*/
|
||||
send_name_addr =
|
||||
(var_lmtp_send_xforward
|
||||
&& (state->features & LMTP_FEATURE_XFORWARD_NAME_ADDR)
|
||||
&& (DEL_REQ_ATTR_AVAIL(request->client_name)
|
||||
|| DEL_REQ_ATTR_AVAIL(request->client_addr)));
|
||||
lmtp_send_proto_helo =
|
||||
(var_lmtp_send_xforward
|
||||
&& (state->features & LMTP_FEATURE_XFORWARD_PROTO_HELO)
|
||||
&& (DEL_REQ_ATTR_AVAIL(request->client_proto)
|
||||
|| DEL_REQ_ATTR_AVAIL(request->client_helo)));
|
||||
if (send_name_addr)
|
||||
start = LMTP_STATE_XFORWARD_NAME_ADDR;
|
||||
else if (lmtp_send_proto_helo)
|
||||
start = LMTP_STATE_XFORWARD_PROTO_HELO;
|
||||
else
|
||||
start = LMTP_STATE_MAIL;
|
||||
return (lmtp_loop(state, start, start));
|
||||
}
|
||||
|
||||
/* lmtp_rset - send a lone RSET command and wait for response */
|
||||
|
@ -698,17 +698,19 @@ static void get_service_attr(PIPE_ATTR *attr, char **argv)
|
||||
* Sanity checks. Verify that every member has an acceptable value.
|
||||
*/
|
||||
if (user == 0)
|
||||
msg_fatal("missing user= attribute");
|
||||
msg_fatal("missing user= command-line attribute");
|
||||
if (attr->command == 0)
|
||||
msg_fatal("missing argv= attribute");
|
||||
msg_fatal("missing argv= command-line attribute");
|
||||
if (attr->uid == 0)
|
||||
msg_fatal("request to deliver as root");
|
||||
msg_fatal("user= command-line attribute specifies root privileges");
|
||||
if (attr->uid == var_owner_uid)
|
||||
msg_fatal("request to deliver as mail system owner");
|
||||
msg_fatal("user= command-line attribute specifies mail system owner %s",
|
||||
var_mail_owner);
|
||||
if (attr->gid == 0)
|
||||
msg_fatal("request to use privileged group id %ld", (long) attr->gid);
|
||||
msg_fatal("user= command-line attribute specifies privileged group id 0");
|
||||
if (attr->gid == var_owner_gid)
|
||||
msg_fatal("request to use mail system owner group id %ld", (long) attr->gid);
|
||||
msg_fatal("user= command-line attribute specifies mail system owner %s group id %ld",
|
||||
var_mail_owner, (long) attr->gid);
|
||||
|
||||
/*
|
||||
* Give the poor tester a clue of what is going on.
|
||||
|
@ -154,6 +154,7 @@ smtp_proto.o: ../../include/stringops.h
|
||||
smtp_proto.o: ../../include/mymalloc.h
|
||||
smtp_proto.o: ../../include/iostuff.h
|
||||
smtp_proto.o: ../../include/split_at.h
|
||||
smtp_proto.o: ../../include/name_code.h
|
||||
smtp_proto.o: ../../include/mail_params.h
|
||||
smtp_proto.o: ../../include/smtp_stream.h
|
||||
smtp_proto.o: ../../include/mail_queue.h
|
||||
@ -173,7 +174,6 @@ 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
|
||||
|
@ -109,6 +109,12 @@
|
||||
/* Never send EHLO at the start of a connection.
|
||||
/* .IP \fBsmtp_bind_address\fR
|
||||
/* Numerical source network address to bind to when making a connection.
|
||||
/* .IP \fBsmtp_defer_if_no_mx_address_found\fR
|
||||
/* 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 until
|
||||
/* the mail is too old.
|
||||
/* .IP \fBsmtp_line_length_limit\fR
|
||||
/* Length limit for SMTP message content lines. Zero means no limit.
|
||||
/* Some SMTP servers misbehave on long lines.
|
||||
@ -142,6 +148,11 @@
|
||||
/* The maximal nesting level of multipart mail that the MIME
|
||||
/* processor can handle. Refuse mail that is nested deeper,
|
||||
/* when converting from 8BITMIME format to 7BIT format.
|
||||
/* .IP \fBsmtp_send_xforward_command\fR
|
||||
/* If the SMTP server announces XFORWARD 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.
|
||||
/* .SH "Authentication controls"
|
||||
/* .IP \fBsmtp_sasl_auth_enable\fR
|
||||
/* Enable per-session authentication as per RFC 2554 (SASL).
|
||||
@ -212,17 +223,6 @@
|
||||
/* Timeout for sending the "\fB.\fR" command, and for
|
||||
/* receiving the server response. When no response is received, a
|
||||
/* warning is logged that the mail may be delivered multiple times.
|
||||
/* .IP \fBsmtp_defer_if_no_mx_address_found\fR
|
||||
/* 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 until
|
||||
/* the mail is too old.
|
||||
/* .IP \fBsmtp_send_xforward_command\fR
|
||||
/* If the SMTP server announces XFORWARD 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
|
||||
@ -283,7 +283,7 @@
|
||||
*/
|
||||
int var_smtp_conn_tmout;
|
||||
int var_smtp_helo_tmout;
|
||||
int var_smtp_xclnt_tmout;
|
||||
int var_smtp_xfwd_tmout;
|
||||
int var_smtp_mail_tmout;
|
||||
int var_smtp_rcpt_tmout;
|
||||
int var_smtp_data0_tmout;
|
||||
@ -502,7 +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_XFWD_TMOUT, DEF_SMTP_XFWD_TMOUT, &var_smtp_xfwd_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,
|
||||
|
@ -69,9 +69,11 @@ typedef struct SMTP_STATE {
|
||||
#define SMTP_FEATURE_XFORWARD_PROTO (1<<9)
|
||||
#define SMTP_FEATURE_XFORWARD_HELO (1<<10)
|
||||
|
||||
#define SMTP_FEATURE_XFORWARD_MASK \
|
||||
(SMTP_FEATURE_XFORWARD_NAME | SMTP_FEATURE_XFORWARD_ADDR \
|
||||
| SMTP_FEATURE_XFORWARD_PROTO | SMTP_FEATURE_XFORWARD_HELO)
|
||||
#define SMTP_FEATURE_XFORWARD_NAME_ADDR \
|
||||
(SMTP_FEATURE_XFORWARD_NAME | SMTP_FEATURE_XFORWARD_ADDR)
|
||||
|
||||
#define SMTP_FEATURE_XFORWARD_PROTO_HELO \
|
||||
(SMTP_FEATURE_XFORWARD_PROTO | SMTP_FEATURE_XFORWARD_HELO)
|
||||
|
||||
/*
|
||||
* smtp.c
|
||||
|
@ -104,7 +104,6 @@
|
||||
#include <quote_821_local.h>
|
||||
#include <mail_proto.h>
|
||||
#include <mime_state.h>
|
||||
#include <xtext.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@ -125,8 +124,8 @@
|
||||
* SMTP_STATE_DOT) must have smaller numerical values than the non-sending
|
||||
* states (SMTP_STATE_ABORT .. SMTP_STATE_LAST).
|
||||
*/
|
||||
#define SMTP_STATE_XFORWARD_ADDR 0
|
||||
#define SMTP_STATE_XFORWARD_HELO 1
|
||||
#define SMTP_STATE_XFORWARD_NAME_ADDR 0
|
||||
#define SMTP_STATE_XFORWARD_PROTO_HELO 1
|
||||
#define SMTP_STATE_MAIL 2
|
||||
#define SMTP_STATE_RCPT 3
|
||||
#define SMTP_STATE_DATA 4
|
||||
@ -136,8 +135,8 @@
|
||||
#define SMTP_STATE_LAST 8
|
||||
|
||||
int *xfer_timeouts[SMTP_STATE_LAST] = {
|
||||
&var_smtp_xclnt_tmout,
|
||||
&var_smtp_xclnt_tmout,
|
||||
&var_smtp_xfwd_tmout, /* name/addr */
|
||||
&var_smtp_xfwd_tmout, /* helo/proto */
|
||||
&var_smtp_mail_tmout,
|
||||
&var_smtp_rcpt_tmout,
|
||||
&var_smtp_data0_tmout,
|
||||
@ -147,8 +146,8 @@ int *xfer_timeouts[SMTP_STATE_LAST] = {
|
||||
};
|
||||
|
||||
char *xfer_states[SMTP_STATE_LAST] = {
|
||||
"sending XFORWARD address and name",
|
||||
"sending XFORWARD helo_name and protocol",
|
||||
"sending XFORWARD name/address",
|
||||
"sending XFORWARD protocol/helo_name",
|
||||
"sending MAIL FROM",
|
||||
"sending RCPT TO",
|
||||
"sending DATA command",
|
||||
@ -267,11 +266,11 @@ 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, "XFORWARD") == 0) {
|
||||
else if (strcasecmp(word, "XFORWARD") == 0)
|
||||
while ((word = mystrtok(&words, " \t")) != 0)
|
||||
state->features |= name_code(xforward_features,
|
||||
NAME_CODE_FLAG_NONE, word);
|
||||
} else if (strcasecmp(word, "SIZE") == 0) {
|
||||
else if (strcasecmp(word, "SIZE") == 0) {
|
||||
state->features |= SMTP_FEATURE_SIZE;
|
||||
if ((word = mystrtok(&words, " \t")) != 0) {
|
||||
if (!alldig(word))
|
||||
@ -395,6 +394,8 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
int mail_from_rejected;
|
||||
int downgrading;
|
||||
int mime_errs;
|
||||
int send_name_addr;
|
||||
int send_proto_helo;
|
||||
|
||||
/*
|
||||
* Macros for readability.
|
||||
@ -498,11 +499,20 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
* amount of information is available.
|
||||
*/
|
||||
nrcpt = 0;
|
||||
if (var_smtp_send_xforward
|
||||
&& (state->features & SMTP_FEATURE_XFORWARD_MASK)
|
||||
&& (DEL_REQ_ATTR_AVAIL(request->client_name)
|
||||
|| DEL_REQ_ATTR_AVAIL(request->client_addr)))
|
||||
recv_state = send_state = SMTP_STATE_XFORWARD_ADDR;
|
||||
send_name_addr =
|
||||
(var_smtp_send_xforward
|
||||
&& (state->features & SMTP_FEATURE_XFORWARD_NAME_ADDR)
|
||||
&& (DEL_REQ_ATTR_AVAIL(request->client_name)
|
||||
|| DEL_REQ_ATTR_AVAIL(request->client_addr)));
|
||||
send_proto_helo =
|
||||
(var_smtp_send_xforward
|
||||
&& (state->features & SMTP_FEATURE_XFORWARD_PROTO_HELO)
|
||||
&& (DEL_REQ_ATTR_AVAIL(request->client_proto)
|
||||
|| DEL_REQ_ATTR_AVAIL(request->client_helo)));
|
||||
if (send_name_addr)
|
||||
recv_state = send_state = SMTP_STATE_XFORWARD_NAME_ADDR;
|
||||
else if (send_proto_helo)
|
||||
recv_state = send_state = SMTP_STATE_XFORWARD_PROTO_HELO;
|
||||
else
|
||||
recv_state = send_state = SMTP_STATE_MAIL;
|
||||
next_rcpt = send_rcpt = recv_rcpt = 0;
|
||||
@ -526,33 +536,32 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
* information, the command length stays within the 512 byte
|
||||
* command line length limit.
|
||||
*/
|
||||
case SMTP_STATE_XFORWARD_ADDR:
|
||||
case SMTP_STATE_XFORWARD_NAME_ADDR:
|
||||
vstring_strcpy(next_command, XFORWARD_CMD);
|
||||
if (state->features & SMTP_FEATURE_XFORWARD_NAME) {
|
||||
vstring_strcat(next_command, " " XCLIENT_NAME "=");
|
||||
if (DEL_REQ_ATTR_AVAIL(request->client_name))
|
||||
xtext_quote_append(next_command, request->client_name, "");
|
||||
}
|
||||
if (state->features & SMTP_FEATURE_XFORWARD_ADDR) {
|
||||
vstring_strcat(next_command, " " XFORWARD_ADDR "=");
|
||||
if (DEL_REQ_ATTR_AVAIL(request->client_addr))
|
||||
xtext_quote_append(next_command, request->client_addr, "");
|
||||
}
|
||||
next_state = SMTP_STATE_XFORWARD_HELO;
|
||||
if (state->features & SMTP_FEATURE_XFORWARD_NAME)
|
||||
vstring_sprintf_append(next_command, " %s=%s",
|
||||
XFORWARD_NAME, DEL_REQ_ATTR_AVAIL(request->client_name) ?
|
||||
request->client_name : XFORWARD_UNAVAILABLE);
|
||||
if (state->features & SMTP_FEATURE_XFORWARD_ADDR)
|
||||
vstring_sprintf_append(next_command, " %s=%s",
|
||||
XFORWARD_ADDR, DEL_REQ_ATTR_AVAIL(request->client_addr) ?
|
||||
request->client_addr : XFORWARD_UNAVAILABLE);
|
||||
if (send_proto_helo)
|
||||
next_state = SMTP_STATE_XFORWARD_PROTO_HELO;
|
||||
else
|
||||
next_state = SMTP_STATE_MAIL;
|
||||
break;
|
||||
|
||||
case SMTP_STATE_XFORWARD_HELO:
|
||||
case SMTP_STATE_XFORWARD_PROTO_HELO:
|
||||
vstring_strcpy(next_command, XFORWARD_CMD);
|
||||
if (state->features & SMTP_FEATURE_XFORWARD_HELO) {
|
||||
vstring_strcat(next_command, " " XCLIENT_HELO "=");
|
||||
if (DEL_REQ_ATTR_AVAIL(request->client_helo))
|
||||
xtext_quote_append(next_command, request->client_helo, "");
|
||||
}
|
||||
if (state->features & SMTP_FEATURE_XFORWARD_ADDR) {
|
||||
vstring_strcat(next_command, " " XFORWARD_PROTO "=");
|
||||
if (DEL_REQ_ATTR_AVAIL(request->client_proto))
|
||||
xtext_quote_append(next_command, request->client_proto, "");
|
||||
}
|
||||
if (state->features & SMTP_FEATURE_XFORWARD_PROTO)
|
||||
vstring_sprintf_append(next_command, " %s=%s",
|
||||
XFORWARD_PROTO, DEL_REQ_ATTR_AVAIL(request->client_proto) ?
|
||||
request->client_proto : XFORWARD_UNAVAILABLE);
|
||||
if (state->features & SMTP_FEATURE_XFORWARD_HELO)
|
||||
vstring_sprintf_append(next_command, " %s=%s",
|
||||
XFORWARD_HELO, DEL_REQ_ATTR_AVAIL(request->client_helo) ?
|
||||
request->client_helo : XFORWARD_UNAVAILABLE);
|
||||
next_state = SMTP_STATE_MAIL;
|
||||
break;
|
||||
|
||||
@ -665,7 +674,7 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
/*
|
||||
* Sanity check.
|
||||
*/
|
||||
if (recv_state < SMTP_STATE_XFORWARD_ADDR
|
||||
if (recv_state < SMTP_STATE_XFORWARD_NAME_ADDR
|
||||
|| recv_state > SMTP_STATE_QUIT)
|
||||
msg_panic("%s: bad receiver state %d (sender state %d)",
|
||||
myname, recv_state, send_state);
|
||||
@ -689,21 +698,24 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
/*
|
||||
* Process the XFORWARD response.
|
||||
*/
|
||||
case SMTP_STATE_XFORWARD_ADDR:
|
||||
case SMTP_STATE_XFORWARD_NAME_ADDR:
|
||||
if (resp->code / 100 != 2)
|
||||
msg_warn("host %s said: %s (in reply to %s)",
|
||||
session->namaddr,
|
||||
translit(resp->str, "\n", " "),
|
||||
xfer_request[SMTP_STATE_MAIL]);
|
||||
recv_state = SMTP_STATE_XFORWARD_HELO;
|
||||
xfer_request[SMTP_STATE_XFORWARD_NAME_ADDR]);
|
||||
if (send_proto_helo)
|
||||
recv_state = SMTP_STATE_XFORWARD_PROTO_HELO;
|
||||
else
|
||||
recv_state = SMTP_STATE_MAIL;
|
||||
break;
|
||||
|
||||
case SMTP_STATE_XFORWARD_HELO:
|
||||
case SMTP_STATE_XFORWARD_PROTO_HELO:
|
||||
if (resp->code / 100 != 2)
|
||||
msg_warn("host %s said: %s (in reply to %s)",
|
||||
session->namaddr,
|
||||
translit(resp->str, "\n", " "),
|
||||
xfer_request[SMTP_STATE_MAIL]);
|
||||
xfer_request[SMTP_STATE_XFORWARD_PROTO_HELO]);
|
||||
recv_state = SMTP_STATE_MAIL;
|
||||
break;
|
||||
|
||||
|
@ -151,7 +151,6 @@ 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
|
||||
@ -261,13 +260,13 @@ smtpd_proxy.o: ../../include/vstring.h
|
||||
smtpd_proxy.o: ../../include/stringops.h
|
||||
smtpd_proxy.o: ../../include/connect.h
|
||||
smtpd_proxy.o: ../../include/iostuff.h
|
||||
smtpd_proxy.o: ../../include/name_code.h
|
||||
smtpd_proxy.o: ../../include/mail_error.h
|
||||
smtpd_proxy.o: ../../include/name_mask.h
|
||||
smtpd_proxy.o: ../../include/smtp_stream.h
|
||||
smtpd_proxy.o: ../../include/cleanup_user.h
|
||||
smtpd_proxy.o: ../../include/mail_params.h
|
||||
smtpd_proxy.o: ../../include/rec_type.h
|
||||
smtpd_proxy.o: ../../include/xtext.h
|
||||
smtpd_proxy.o: ../../include/mail_proto.h
|
||||
smtpd_proxy.o: ../../include/attr.h
|
||||
smtpd_proxy.o: smtpd.h
|
||||
|
@ -464,7 +464,6 @@
|
||||
#include <namadr_list.h>
|
||||
#include <input_transp.h>
|
||||
#include <anvil_clnt.h>
|
||||
#include <xtext.h>
|
||||
|
||||
/* Single-threaded server skeleton. */
|
||||
|
||||
@ -753,8 +752,7 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
if (xclient_allowed)
|
||||
smtpd_chat_reply(state, "250-" XCLIENT_CMD
|
||||
" " XCLIENT_NAME " " XCLIENT_ADDR
|
||||
" " XCLIENT_CODE " " XCLIENT_PROTO
|
||||
" " XCLIENT_HELO);
|
||||
" " XCLIENT_PROTO " " XCLIENT_HELO);
|
||||
if (xforward_allowed)
|
||||
smtpd_chat_reply(state, "250-" XFORWARD_CMD
|
||||
" " XFORWARD_NAME " " XFORWARD_ADDR
|
||||
@ -1723,22 +1721,21 @@ static int quit_cmd(SMTPD_STATE *state, int unused_argc, SMTPD_TOKEN *unused_arg
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* xclient_cmd - override client attributes */
|
||||
/* xclient_cmd - override SMTP client attributes */
|
||||
|
||||
static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
{
|
||||
int arg_no;
|
||||
SMTPD_TOKEN *argp;
|
||||
char *attr_value;
|
||||
char *attr_name;
|
||||
int update_namaddr = 0;
|
||||
int code;
|
||||
static NAME_CODE xclient_codes[] = {
|
||||
"OK", SMTPD_PEER_CODE_OK,
|
||||
"PERM", SMTPD_PEER_CODE_PERM,
|
||||
"TEMP", SMTPD_PEER_CODE_TEMP,
|
||||
0, -1,
|
||||
int peer_code;
|
||||
static NAME_CODE peer_codes[] = {
|
||||
XCLIENT_UNAVAILABLE, SMTPD_PEER_CODE_PERM,
|
||||
XCLIENT_TEMPORARY, SMTPD_PEER_CODE_TEMP,
|
||||
0, SMTPD_PEER_CODE_OK,
|
||||
};
|
||||
static NAME_CODE xclient_proto[] = {
|
||||
static NAME_CODE proto_names[] = {
|
||||
MAIL_PROTO_SMTP, 1,
|
||||
MAIL_PROTO_ESMTP, 2,
|
||||
0, -1,
|
||||
@ -1755,7 +1752,7 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
}
|
||||
if (argc < 2) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Syntax: %s name=value...",
|
||||
smtpd_chat_reply(state, "501 Syntax: %s attribute=value...",
|
||||
XCLIENT_CMD);
|
||||
return (-1);
|
||||
}
|
||||
@ -1765,122 +1762,99 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
return (-1);
|
||||
}
|
||||
#define STREQ(x,y) (strcasecmp((x), (y)) == 0)
|
||||
#define UPDATE_STR(s, v) do { if (s) myfree(s); s = (v) ? mystrdup(v) : 0; } while(0)
|
||||
#define UPDATE_STR(s, v) do { \
|
||||
if (s) myfree(s); \
|
||||
s = (v) ? mystrdup(v) : 0; \
|
||||
} while(0)
|
||||
#define NEUTER_CHARACTERS "<>()\\\";:@"
|
||||
|
||||
/*
|
||||
* Iterate over all NAME=VALUE attributes.
|
||||
* Iterate over all attribute=value elements.
|
||||
*/
|
||||
for (arg_no = 1; arg_no < argc; arg_no++) {
|
||||
attr_name = argv[arg_no].strval;
|
||||
for (argp = argv + 1; argp < argv + argc; argp++) {
|
||||
attr_name = argp->strval;
|
||||
|
||||
/*
|
||||
* For safety's sake mask non-printable characters in the raw and
|
||||
* decoded values; we don't want to handle unexploded munitions.
|
||||
* Complain when they send an attribute that we didn't announce.
|
||||
*
|
||||
* An implementation must allow clients to send XCLIENT before the
|
||||
* HELO/EHLO greeting.
|
||||
*
|
||||
* The client can send multiple XCLIENT attributes in a single command,
|
||||
* or multiple XCLIENT commands with fewer attributes.
|
||||
* For safety's sake mask non-printable characters. We'll do more
|
||||
* specific censoring later.
|
||||
*/
|
||||
if ((attr_value = split_at(attr_name, '=')) == 0) {
|
||||
if ((attr_value = split_at(attr_name, '=')) == 0 || *attr_value == 0) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Error: name=value expected");
|
||||
smtpd_chat_reply(state, "501 Error: attribute=value expected");
|
||||
return (-1);
|
||||
}
|
||||
printable(attr_value, '?');
|
||||
|
||||
/*
|
||||
* NAME=hostname. Also updates the client hostname lookup status
|
||||
* code. Treat a numerical hostname as an unavailable name.
|
||||
* NAME=substitute SMTP client hostname. Also updates the client
|
||||
* hostname lookup status code.
|
||||
*/
|
||||
if (STREQ(attr_name, XCLIENT_NAME)) {
|
||||
if (*attr_value && !valid_hostaddr(attr_value, DONT_GRIPE)) {
|
||||
if (!valid_hostname(attr_value, DONT_GRIPE)) {
|
||||
peer_code = name_code(peer_codes, NAME_CODE_FLAG_NONE, attr_value);
|
||||
if (peer_code != SMTPD_PEER_CODE_OK) {
|
||||
attr_value = CLIENT_NAME_UNKNOWN;
|
||||
} else {
|
||||
if (!valid_hostname(attr_value, DONT_GRIPE)
|
||||
|| valid_hostaddr(attr_value, DONT_GRIPE)) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
||||
XCLIENT_NAME, attr_value);
|
||||
return (-1);
|
||||
}
|
||||
UPDATE_STR(state->name, attr_value);
|
||||
state->peer_code = SMTPD_PEER_CODE_OK;
|
||||
} else {
|
||||
UPDATE_STR(state->name, CLIENT_NAME_UNKNOWN);
|
||||
state->peer_code = SMTPD_PEER_CODE_PERM;
|
||||
}
|
||||
state->peer_code = peer_code;
|
||||
UPDATE_STR(state->name, attr_value);
|
||||
update_namaddr = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* ADDR=client network address.
|
||||
* ADDR=substitute SMTP client network address.
|
||||
*/
|
||||
else if (STREQ(attr_name, XCLIENT_ADDR)) {
|
||||
if (*attr_value) {
|
||||
if (STREQ(attr_value, XCLIENT_UNAVAILABLE)) {
|
||||
attr_value = CLIENT_ADDR_UNKNOWN;
|
||||
} else {
|
||||
if (!valid_hostaddr(attr_value, DONT_GRIPE)) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
||||
XCLIENT_ADDR, attr_value);
|
||||
return (-1);
|
||||
}
|
||||
UPDATE_STR(state->addr, attr_value);
|
||||
} else {
|
||||
UPDATE_STR(state->addr, CLIENT_ADDR_UNKNOWN);
|
||||
}
|
||||
UPDATE_STR(state->addr, attr_value);
|
||||
update_namaddr = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* CODE=hostname lookup status. Reset the client hostname if the
|
||||
* hostname lookup status is not OK.
|
||||
*/
|
||||
else if (STREQ(attr_name, XCLIENT_CODE)) {
|
||||
if (*attr_value) {
|
||||
if ((code = name_code(xclient_codes, NAME_CODE_FLAG_NONE, attr_value)) < 0) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad %s value: %s",
|
||||
XCLIENT_CODE, attr_value);
|
||||
return (-1);
|
||||
}
|
||||
state->peer_code = code;
|
||||
if (code != SMTPD_PEER_CODE_OK) {
|
||||
UPDATE_STR(state->name, CLIENT_NAME_UNKNOWN);
|
||||
update_namaddr = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* HELO=hostname. Disallow characters that could mess up our own
|
||||
* Received: message headers but allow [].
|
||||
* HELO=substitute SMTP client HELO parameter. Censor special
|
||||
* characters that could mess up message headers.
|
||||
*/
|
||||
else if (STREQ(attr_name, XCLIENT_HELO)) {
|
||||
if (*attr_value) {
|
||||
if (STREQ(attr_value, XCLIENT_UNAVAILABLE)) {
|
||||
attr_value = CLIENT_HELO_UNKNOWN;
|
||||
} else {
|
||||
if (strlen(attr_value) > VALID_HOSTNAME_LEN) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
||||
XCLIENT_HELO, attr_value);
|
||||
return (-1);
|
||||
}
|
||||
neuter(attr_value, "<>()\\\";:@", '?');
|
||||
UPDATE_STR(state->helo_name, attr_value);
|
||||
} else {
|
||||
UPDATE_STR(state->helo_name, CLIENT_HELO_UNKNOWN);
|
||||
neuter(attr_value, NEUTER_CHARACTERS, '?');
|
||||
}
|
||||
UPDATE_STR(state->helo_name, attr_value);
|
||||
}
|
||||
|
||||
/*
|
||||
* PROTO=protocol name. Disallow characters that could mess up our
|
||||
* own Received: message headers.
|
||||
* PROTO=SMTP protocol name.
|
||||
*/
|
||||
else if (STREQ(attr_name, XCLIENT_PROTO)) {
|
||||
if (name_code(xclient_proto, NAME_CODE_FLAG_NONE, attr_value) < 0) {
|
||||
if (name_code(proto_names, NAME_CODE_FLAG_NONE, attr_value) < 0) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
||||
XCLIENT_PROTO, attr_value);
|
||||
return (-1);
|
||||
}
|
||||
UPDATE_STR(state->protocol, attr_value);
|
||||
UPDATE_STR(state->protocol, uppercase(attr_value));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1911,7 +1885,7 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
|
||||
static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
{
|
||||
int arg_no;
|
||||
SMTPD_TOKEN *argp;
|
||||
char *attr_value;
|
||||
char *attr_name;
|
||||
int updated = 0;
|
||||
@ -1934,7 +1908,7 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
}
|
||||
if (argc < 2) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Syntax: %s name=value...",
|
||||
smtpd_chat_reply(state, "501 Syntax: %s attribute=value...",
|
||||
XFORWARD_CMD);
|
||||
return (-1);
|
||||
}
|
||||
@ -1951,22 +1925,18 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
smtpd_xforward_preset(state);
|
||||
|
||||
/*
|
||||
* Iterate over all NAME=VALUE attributes.
|
||||
* Iterate over all attribute=value elements.
|
||||
*/
|
||||
for (arg_no = 1; arg_no < argc; arg_no++) {
|
||||
attr_name = argv[arg_no].strval;
|
||||
for (argp = argv + 1; argp < argv + argc; argp++) {
|
||||
attr_name = argp->strval;
|
||||
|
||||
/*
|
||||
* For safety's sake mask non-printable characters in the raw and
|
||||
* decoded values; we don't want to handle unexploded munitions.
|
||||
* Complain when they send an attribute that we didn't announce.
|
||||
*
|
||||
* The client can send multiple XFORWARD attributes in a single command,
|
||||
* or multiple XFORWARD commands with fewer attributes.
|
||||
* For safety's sake mask non-printable characters. We'll do more
|
||||
* specific censoring later.
|
||||
*/
|
||||
if ((attr_value = split_at(attr_name, '=')) == 0) {
|
||||
if ((attr_value = split_at(attr_name, '=')) == 0 || *attr_value == 0) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Error: name=value expected");
|
||||
smtpd_chat_reply(state, "501 Error: attribute=value expected");
|
||||
return (-1);
|
||||
}
|
||||
printable(attr_value, '?');
|
||||
@ -1975,71 +1945,61 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
switch (flag) {
|
||||
|
||||
/*
|
||||
* NAME=hostname. Also updates the client hostname lookup status
|
||||
* code. Treat a numerical hostname as an unavailable name.
|
||||
* NAME=host name, not necessarily in the DNS. Censor special
|
||||
* characters that could mess up message headers.
|
||||
*/
|
||||
case SMTPD_XFORWARD_FLAG_NAME:
|
||||
if (*attr_value && !valid_hostaddr(attr_value, DONT_GRIPE)) {
|
||||
if (!valid_hostname(attr_value, DONT_GRIPE)) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
||||
XFORWARD_NAME, attr_value);
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
if (STREQ(attr_value, XFORWARD_UNAVAILABLE)) {
|
||||
attr_value = CLIENT_NAME_UNKNOWN;
|
||||
} else {
|
||||
neuter(attr_value, NEUTER_CHARACTERS, '?');
|
||||
}
|
||||
UPDATE_STR(state->xforward.name, attr_value);
|
||||
break;
|
||||
|
||||
/*
|
||||
* ADDR=client network address.
|
||||
* ADDR=host network address, not necessarily on the Internet.
|
||||
* Censor special characters that could mess up message headers.
|
||||
*/
|
||||
case SMTPD_XFORWARD_FLAG_ADDR:
|
||||
if (*attr_value) {
|
||||
if (!valid_hostaddr(attr_value, DONT_GRIPE)) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
||||
XFORWARD_ADDR, attr_value);
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
if (STREQ(attr_value, XFORWARD_UNAVAILABLE)) {
|
||||
attr_value = CLIENT_ADDR_UNKNOWN;
|
||||
} else {
|
||||
neuter(attr_value, NEUTER_CHARACTERS, '?');
|
||||
}
|
||||
UPDATE_STR(state->xforward.addr, attr_value);
|
||||
break;
|
||||
|
||||
/*
|
||||
* HELO=hostname. Disallow characters that could mess up our own
|
||||
* Received: message headers but allow [].
|
||||
* HELO=hostname that the host introduced itself with (not
|
||||
* necessarily SMTP HELO). Censor special characters that could
|
||||
* mess up message headers.
|
||||
*/
|
||||
case SMTPD_XFORWARD_FLAG_HELO:
|
||||
if (*attr_value) {
|
||||
if (strlen(attr_value) > VALID_HOSTNAME_LEN) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
||||
XFORWARD_HELO, attr_value);
|
||||
return (-1);
|
||||
}
|
||||
neuter(attr_value, "<>()\\\";:@", '?');
|
||||
} else {
|
||||
if (STREQ(attr_value, XFORWARD_UNAVAILABLE)) {
|
||||
attr_value = CLIENT_HELO_UNKNOWN;
|
||||
} else {
|
||||
neuter(attr_value, NEUTER_CHARACTERS, '?');
|
||||
}
|
||||
UPDATE_STR(state->xforward.helo_name, attr_value);
|
||||
break;
|
||||
|
||||
/*
|
||||
* PROTO=protocol name. Neutralize characters that could mess up
|
||||
* our own Received: message headers.
|
||||
* PROTO=protocol name, not necessarily SMTP or ESMTP. Censor
|
||||
* special characters that could mess up message headers.
|
||||
*/
|
||||
case SMTPD_XFORWARD_FLAG_PROTO:
|
||||
if (strlen(attr_value) > 64) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
||||
XFORWARD_PROTO, attr_value);
|
||||
return (-1);
|
||||
if (STREQ(attr_value, XFORWARD_UNAVAILABLE)) {
|
||||
attr_value = CLIENT_PROTO_UNKNOWN;
|
||||
} else {
|
||||
if (strlen(attr_value) > 64) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
||||
XFORWARD_PROTO, attr_value);
|
||||
return (-1);
|
||||
}
|
||||
neuter(attr_value, NEUTER_CHARACTERS, '?');
|
||||
}
|
||||
neuter(attr_value, "<>()\\\";:@", '?');
|
||||
UPDATE_STR(state->xforward.protocol, attr_value);
|
||||
break;
|
||||
|
||||
@ -2063,9 +2023,10 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
if (state->xforward.namaddr)
|
||||
myfree(state->xforward.namaddr);
|
||||
state->xforward.namaddr =
|
||||
IS_AVAIL_CLIENT_ADDR(state->xforward.addr) ?
|
||||
concatenate(state->xforward.name, "[",
|
||||
state->xforward.addr, "]",
|
||||
(char *) 0);
|
||||
(char *) 0) : mystrdup(state->xforward.name);
|
||||
}
|
||||
smtpd_chat_reply(state, "250 Ok");
|
||||
return (0);
|
||||
|
@ -206,9 +206,8 @@ extern void smtpd_peer_reset(SMTPD_STATE *state);
|
||||
#define SMTPD_PROXY_XFORWARD_IDENT (1<<4) /* message identifier */
|
||||
|
||||
/*
|
||||
* If forwarding client information, don't mix direct client information
|
||||
* from the current SMTP session with forwarded client information from an
|
||||
* up-stream session.
|
||||
* If forwarding client information, don't mix information from the current
|
||||
* SMTP session with forwarded information from an up-stream session.
|
||||
*/
|
||||
#define FORWARD_CLIENT_ATTR(s, a) \
|
||||
(((s)->xforward.flags & SMTPD_XFORWARD_FLAG_CLIENT_MASK) ? \
|
||||
|
@ -156,7 +156,6 @@
|
||||
#include <cleanup_user.h>
|
||||
#include <mail_params.h>
|
||||
#include <rec_type.h>
|
||||
#include <xtext.h>
|
||||
#include <mail_proto.h>
|
||||
|
||||
/* Application-specific. */
|
||||
@ -201,10 +200,10 @@ static int smtpd_xforward(SMTPD_STATE *state, VSTRING *buf, const char *name,
|
||||
* How much space does this attribute need?
|
||||
*/
|
||||
if (!value_available)
|
||||
value = "";
|
||||
value = XFORWARD_UNAVAILABLE;
|
||||
new_len = strlen(name) + strlen(value) + 2; /* SPACE name = value */
|
||||
if (new_len > PAYLOAD_LIMIT)
|
||||
msg_warn("%s payload %s=%.10s... exceeds SMTP protocol limit",
|
||||
msg_warn("%s command payload %s=%.10s... exceeds SMTP protocol limit",
|
||||
XFORWARD_CMD, name, value);
|
||||
|
||||
/*
|
||||
|
@ -27,7 +27,8 @@ 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 neuter.c name_code.c
|
||||
attr_print_plain.c sane_connect.c neuter.c name_code.c \
|
||||
uppercase.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 +57,8 @@ 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) neuter.o name_code.o
|
||||
attr_print_plain.o sane_connect.o $(STRCASE) neuter.o name_code.o \
|
||||
uppercase.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 \
|
||||
@ -1292,6 +1294,11 @@ unix_trigger.o: trigger.h
|
||||
unsafe.o: unsafe.c
|
||||
unsafe.o: sys_defs.h
|
||||
unsafe.o: safe.h
|
||||
uppercase.o: uppercase.c
|
||||
uppercase.o: sys_defs.h
|
||||
uppercase.o: stringops.h
|
||||
uppercase.o: vstring.h
|
||||
uppercase.o: vbuf.h
|
||||
username.o: username.c
|
||||
username.o: sys_defs.h
|
||||
username.o: username.h
|
||||
|
@ -22,6 +22,7 @@
|
||||
extern char *printable(char *, int);
|
||||
extern char *neuter(char *, const char *, int);
|
||||
extern char *lowercase(char *);
|
||||
extern char *uppercase(char *);
|
||||
extern char *skipblanks(const char *);
|
||||
extern char *trimblanks(char *, int);
|
||||
extern char *concatenate(const char *,...);
|
||||
|
43
postfix/src/util/uppercase.c
Normal file
43
postfix/src/util/uppercase.c
Normal file
@ -0,0 +1,43 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* uppercase 3
|
||||
/* SUMMARY
|
||||
/* map lowercase characters to uppercase
|
||||
/* SYNOPSIS
|
||||
/* #include <stringops.h>
|
||||
/*
|
||||
/* char *uppercase(buf)
|
||||
/* char *buf;
|
||||
/* DESCRIPTION
|
||||
/* uppercase() replaces lowercase characters in its null-terminated
|
||||
/* input by their uppercase equivalent.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include "sys_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include "stringops.h"
|
||||
|
||||
char *uppercase(char *string)
|
||||
{
|
||||
char *cp;
|
||||
int ch;
|
||||
|
||||
for (cp = string; (ch = *cp) != 0; cp++)
|
||||
if (ISLOWER(ch))
|
||||
*cp = TOUPPER(ch);
|
||||
return (string);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user