mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-31 22:25:24 +00:00
postfix-2.0.16-20031214
This commit is contained in:
committed by
Viktor Dukhovni
parent
7a646f52bf
commit
0b73da41c8
@@ -8832,6 +8832,29 @@ Apologies for any names omitted.
|
|||||||
because the deliver_pass.c module was not updated for the
|
because the deliver_pass.c module was not updated for the
|
||||||
changed message delivery protocol.
|
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:
|
Open problems:
|
||||||
|
|
||||||
High: when virtual aliasing is turned off after content
|
High: when virtual aliasing is turned off after content
|
||||||
|
@@ -1,182 +1,98 @@
|
|||||||
Purpose of the XCLIENT extension to SMTP
|
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
|
1 - Access control tests. SMTP server access rules are difficult
|
||||||
to verify when decisions can be triggered only by remote clients.
|
to verify when decisions can be triggered only by remote clients.
|
||||||
In order to facilitate access rule testing, an authorized SMTP
|
In order to facilitate access rule testing, an authorized SMTP
|
||||||
client test program needs the ability to override the SMTP server's
|
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.
|
information, for the entire duration of an SMTP session.
|
||||||
|
|
||||||
2 - Logging after SMTP-based content filter. With the deployment
|
2 - Client software that downloads mail from an up-stream mail
|
||||||
of Internet->MTA1->filter->MTA2 style content filter applications,
|
server and injects it into a local MTA via SMTP. In order to take
|
||||||
remote client information is lost when MTA1 gives the mail to the
|
advantage of the local MTA's access rules, the client software
|
||||||
content filter. To simplify the interpretation of MTA2 logging,
|
needs the ability to override the SMTP server's idea of the remote
|
||||||
it would help if MTA1 could forward client information through the
|
client name, client address and other information. Such information
|
||||||
content filter to MTA2.
|
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
|
3 - Post-filter access control and logging. With Internet->filter->MTA
|
||||||
style content filter applications, the filter can be simplified if
|
style content filter applications, the filter can be simplified if
|
||||||
it can delegate decisions concerning mail relay and other access
|
it can delegate decisions concerning mail relay and other access
|
||||||
control to the MTA. As in the first example, this requires that
|
control to the MTA. This is especially useful when the filter acts
|
||||||
the filter can override the MTA's idea of the SMTP client hostname,
|
as a transparent proxy for SMTP commands. As in the first example,
|
||||||
network address, and other information, for the entire duration of
|
this requires that the filter can override the MTA's idea of the
|
||||||
an SMTP session.
|
SMTP client hostname, network address, and other information.
|
||||||
|
|
||||||
4 - Fetchmail.
|
Command syntax
|
||||||
|
==============
|
||||||
|
|
||||||
Command overview
|
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 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.
|
|
||||||
|
|
||||||
The general command syntax is described below. Upper case and
|
The general command syntax is described below. Upper case and
|
||||||
quoted strings specify terminals, lowercase strings specify meta
|
quoted strings specify terminals, lowercase strings specify meta
|
||||||
terminals, SP is whitespace, and descriptive text is enclosed in
|
terminals, and SP is whitespace. Although command and attribute
|
||||||
{}. Although command and attribute names are shown below in upper
|
names are shown in upper case, they are in fact case insensitive.
|
||||||
case, they are in fact case insensitive.
|
|
||||||
|
|
||||||
xclient-command = XCLIENT SP function SP 1*( attribute )
|
xclient-command = XCLIENT 1*( SP attribute )
|
||||||
|
|
||||||
function = ( OVERRIDE | FORWARD )
|
|
||||||
|
|
||||||
attribute = name"="value
|
attribute = name"="value
|
||||||
|
|
||||||
name = ( NAME|ADDR|CODE|PROTO|HELO )
|
name = ( NAME | ADDR | PROTO | HELO )
|
||||||
|
|
||||||
value = ( { empty } | xtext )
|
|
||||||
|
|
||||||
xtext = { attribute value encoded as per RFC 1891 }
|
|
||||||
|
|
||||||
The XCLIENT command can be sent at any time except in the middle
|
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
|
of a mail delivery transaction (i.e. between MAIL and DOT). The
|
||||||
command may be pipelined after the server EHLO reply announces
|
command may be pipelined if the server EHLO reply announces ESMTP
|
||||||
ESMTP pipelining support.
|
pipelining support.
|
||||||
|
|
||||||
The server reply codes are as follows:
|
The XCLIENT reply codes are as follows:
|
||||||
|
|
||||||
Code | Meaning
|
Code | Meaning
|
||||||
-----|------------
|
-----|------------
|
||||||
250 | success
|
250 | success
|
||||||
501 | bad command parameter
|
501 | bad command parameter syntax
|
||||||
503 | mail transaction in progress
|
503 | mail transaction in progress
|
||||||
421 | unable to proceed
|
421 | unable to proceed
|
||||||
|
|
||||||
The server must report success in case of an unrecognized attribute
|
The NAME attribute specifies an SMTP client hostname (not an SMTP
|
||||||
name, although it may log a warning.
|
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
|
The PROTO attribute specifies either SMTP or ESMTP.
|
||||||
syntax details are given in the next section.
|
|
||||||
|
|
||||||
The XCLIENT OVERRIDE request modifies remote client attributes that
|
The HELO attribute specifies a HELO parameter value, or the value
|
||||||
the MTA normally uses for access control, message headers, logging,
|
[unavailable] when the information is unavailable.
|
||||||
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 following example overrides only the client hostname and network
|
Note 1: syntactically valid NAME and HELO attributes can be up to
|
||||||
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
|
|
||||||
255 characters long. The client must not send XCLIENT commands that
|
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
|
Note 2: [UNAVAILABLE], [TEMPORARY] and IPV6: may be specified in
|
||||||
headers. The receiving MTA may substitute characters in order to
|
upper case, lower case or mixed case.
|
||||||
not violate RFC 822 or RFC 2822.
|
|
||||||
|
|
||||||
Security
|
Security
|
||||||
========
|
========
|
||||||
|
|
||||||
The XCLIENT command changes audit trails and/or client access
|
The XCLIENT command changes audit trails and/or client access
|
||||||
permissions. For these reasons, use of these commands must be
|
permissions. Use of this command must be restricted to authorized
|
||||||
restricted to authorized clients only.
|
clients.
|
||||||
|
|
||||||
The examples in this document assume that XCLIENT does not override
|
The XCLIENT should not override its own access control mechanism.
|
||||||
its own access control mechanism.
|
|
||||||
|
|
||||||
SMTP connection caching
|
SMTP connection caching
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
SMTP connection caching makes it possible to deliver multiple
|
SMTP connection caching makes it possible to deliver multiple
|
||||||
messages within the same SMTP session. Thus, one persistent SMTP
|
messages within the same SMTP session. The XCLIENT attributes are
|
||||||
session with a content filter can carry messages from unrelated
|
persistent across deliveries, and need to be reset as appropriate
|
||||||
clients. The XCLIENT FORWARD attributes are reset after the MAIL
|
in order to avoid information leakage.
|
||||||
FROM command completes, so there is no risk of 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/UUCP_README:f:root:-:644
|
||||||
$readme_directory/VERP_README:f:root:-:644
|
$readme_directory/VERP_README:f:root:-:644
|
||||||
$readme_directory/VIRTUAL_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
|
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
|
# RESOURCE AND RATE CONTROLS
|
||||||
#
|
#
|
||||||
@@ -83,6 +94,18 @@ lmtp_connect_timeout = 0s
|
|||||||
#
|
#
|
||||||
lmtp_lhlo_timeout = 300s
|
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
|
# The lmtp_mail_timeout parameter specifies the LMTP client timeout
|
||||||
# for sending the LMTP MAIL FROM command, and for receiving the server
|
# for sending the LMTP MAIL FROM command, and for receiving the server
|
||||||
# response.
|
# response.
|
||||||
|
@@ -107,6 +107,13 @@ LMTP(8) LMTP(8)
|
|||||||
server. Used as backup if the <b>lmtp</b> service is not
|
server. Used as backup if the <b>lmtp</b> service is not
|
||||||
found in <b>services</b>(4).
|
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>Authentication controls</b>
|
||||||
<b>lmtp_sasl_auth_enable</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>
|
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
|
Timeout for sending the <b>LHLO</b> command, and for
|
||||||
receiving the server response.
|
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>
|
<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.
|
receiving the server response.
|
||||||
|
|
||||||
<b>lmtp_rcpt_timeout</b>
|
<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.
|
receiving the server response.
|
||||||
|
|
||||||
<b>lmtp_data_init_timeout</b>
|
<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.
|
receiving the server response.
|
||||||
|
|
||||||
<b>lmtp_data_xfer_timeout</b>
|
<b>lmtp_data_xfer_timeout</b>
|
||||||
@@ -223,16 +234,16 @@ LMTP(8) LMTP(8)
|
|||||||
|
|
||||||
<b>lmtp_data_done_timeout</b>
|
<b>lmtp_data_done_timeout</b>
|
||||||
Timeout for sending the "<b>.</b>" command, and for
|
Timeout for sending the "<b>.</b>" command, and for
|
||||||
receiving the server response. When no response is
|
receiving the server response. When no response is
|
||||||
received, a warning is logged that the mail may be
|
received, a warning is logged that the mail may be
|
||||||
delivered multiple times.
|
delivered multiple times.
|
||||||
|
|
||||||
<b>lmtp_rset_timeout</b>
|
<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.
|
receiving the server response.
|
||||||
|
|
||||||
<b>lmtp_quit_timeout</b>
|
<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.
|
receiving the server response.
|
||||||
|
|
||||||
<b>SEE ALSO</b>
|
<b>SEE ALSO</b>
|
||||||
@@ -245,7 +256,7 @@ LMTP(8) LMTP(8)
|
|||||||
syslogd(8) system logging
|
syslogd(8) system logging
|
||||||
|
|
||||||
<b>LICENSE</b>
|
<b>LICENSE</b>
|
||||||
The Secure Mailer license must be distributed with this
|
The Secure Mailer license must be distributed with this
|
||||||
software.
|
software.
|
||||||
|
|
||||||
<b>AUTHOR(S)</b>
|
<b>AUTHOR(S)</b>
|
||||||
|
@@ -135,6 +135,13 @@ SMTP(8) SMTP(8)
|
|||||||
Numerical source network address to bind to when
|
Numerical source network address to bind to when
|
||||||
making a connection.
|
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>
|
<b>smtp_line_length_limit</b>
|
||||||
Length limit for SMTP message content lines. Zero
|
Length limit for SMTP message content lines. Zero
|
||||||
means no limit. Some SMTP servers misbehave on
|
means no limit. Some SMTP servers misbehave on
|
||||||
@@ -186,6 +193,13 @@ SMTP(8) SMTP(8)
|
|||||||
nested deeper, when converting from 8BITMIME format
|
nested deeper, when converting from 8BITMIME format
|
||||||
to 7BIT 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>Authentication controls</b>
|
||||||
<b>smtp_sasl_auth_enable</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>
|
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
|
received, a warning is logged that the mail may be
|
||||||
delivered multiple times.
|
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>
|
<b>smtp_rset_timeout</b>
|
||||||
Timeout for sending the <b>RSET</b> command.
|
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
|
.IP \fBlmtp_tcp_port\fR
|
||||||
The TCP port to be used when connecting to a LMTP server. Used as
|
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).
|
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"
|
.SH "Authentication controls"
|
||||||
.IP \fBlmtp_sasl_auth_enable\fR
|
.IP \fBlmtp_sasl_auth_enable\fR
|
||||||
Enable per-session authentication as per RFC 2554 (SASL).
|
Enable per-session authentication as per RFC 2554 (SASL).
|
||||||
@@ -185,6 +190,9 @@ is deferred.
|
|||||||
.IP \fBlmtp_lhlo_timeout\fR
|
.IP \fBlmtp_lhlo_timeout\fR
|
||||||
Timeout for sending the \fBLHLO\fR command, and for
|
Timeout for sending the \fBLHLO\fR command, and for
|
||||||
receiving the server response.
|
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
|
.IP \fBlmtp_mail_timeout\fR
|
||||||
Timeout for sending the \fBMAIL FROM\fR command, and for
|
Timeout for sending the \fBMAIL FROM\fR command, and for
|
||||||
receiving the server response.
|
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.
|
Never send EHLO at the start of a connection.
|
||||||
.IP \fBsmtp_bind_address\fR
|
.IP \fBsmtp_bind_address\fR
|
||||||
Numerical source network address to bind to when making a connection.
|
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
|
.IP \fBsmtp_line_length_limit\fR
|
||||||
Length limit for SMTP message content lines. Zero means no limit.
|
Length limit for SMTP message content lines. Zero means no limit.
|
||||||
Some SMTP servers misbehave on long lines.
|
Some SMTP servers misbehave on long lines.
|
||||||
@@ -158,6 +164,11 @@ between boundary strings that do not differ in the first
|
|||||||
The maximal nesting level of multipart mail that the MIME
|
The maximal nesting level of multipart mail that the MIME
|
||||||
processor can handle. Refuse mail that is nested deeper,
|
processor can handle. Refuse mail that is nested deeper,
|
||||||
when converting from 8BITMIME format to 7BIT format.
|
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"
|
.SH "Authentication controls"
|
||||||
.IP \fBsmtp_sasl_auth_enable\fR
|
.IP \fBsmtp_sasl_auth_enable\fR
|
||||||
Enable per-session authentication as per RFC 2554 (SASL).
|
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
|
Timeout for sending the "\fB.\fR" command, and for
|
||||||
receiving the server response. When no response is received, a
|
receiving the server response. When no response is received, a
|
||||||
warning is logged that the mail may be delivered multiple times.
|
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
|
.IP \fBsmtp_rset_timeout\fR
|
||||||
Timeout for sending the \fBRSET\fR command.
|
Timeout for sending the \fBRSET\fR command.
|
||||||
.IP \fBsmtp_quit_timeout\fR
|
.IP \fBsmtp_quit_timeout\fR
|
||||||
|
@@ -753,9 +753,9 @@ extern int var_smtp_conn_tmout;
|
|||||||
#define DEF_SMTP_HELO_TMOUT "300s"
|
#define DEF_SMTP_HELO_TMOUT "300s"
|
||||||
extern int var_smtp_helo_tmout;
|
extern int var_smtp_helo_tmout;
|
||||||
|
|
||||||
#define VAR_SMTP_XCLNT_TMOUT "smtp_xclient_timeout"
|
#define VAR_SMTP_XFWD_TMOUT "smtp_xforward_timeout"
|
||||||
#define DEF_SMTP_XCLNT_TMOUT "300s"
|
#define DEF_SMTP_XFWD_TMOUT "300s"
|
||||||
extern int var_smtp_xclnt_tmout;
|
extern int var_smtp_xfwd_tmout;
|
||||||
|
|
||||||
#define VAR_SMTP_MAIL_TMOUT "smtp_mail_timeout"
|
#define VAR_SMTP_MAIL_TMOUT "smtp_mail_timeout"
|
||||||
#define DEF_SMTP_MAIL_TMOUT "300s"
|
#define DEF_SMTP_MAIL_TMOUT "300s"
|
||||||
@@ -1032,6 +1032,10 @@ extern int var_lmtp_rset_tmout;
|
|||||||
#define DEF_LMTP_LHLO_TMOUT "300s"
|
#define DEF_LMTP_LHLO_TMOUT "300s"
|
||||||
extern int var_lmtp_lhlo_tmout;
|
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 VAR_LMTP_MAIL_TMOUT "lmtp_mail_timeout"
|
||||||
#define DEF_LMTP_MAIL_TMOUT "300s"
|
#define DEF_LMTP_MAIL_TMOUT "300s"
|
||||||
extern int var_lmtp_mail_tmout;
|
extern int var_lmtp_mail_tmout;
|
||||||
@@ -1056,6 +1060,10 @@ extern int var_lmtp_data2_tmout;
|
|||||||
#define DEF_LMTP_QUIT_TMOUT "300s"
|
#define DEF_LMTP_QUIT_TMOUT "300s"
|
||||||
extern int var_lmtp_quit_tmout;
|
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
|
* Cleanup service. Header info that exceeds $header_size_limit bytes forces
|
||||||
* the start of the message body.
|
* 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 */
|
#define MAIL_ATTR_ORG_LOCAL "local" /* local submission */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XCLIENT in SMTP.
|
* XCLIENT/XFORWARD in SMTP.
|
||||||
*/
|
*/
|
||||||
#define XCLIENT_CMD "XCLIENT" /* XCLIENT command */
|
#define XCLIENT_CMD "XCLIENT" /* XCLIENT command */
|
||||||
#define XCLIENT_NAME "NAME" /* client name */
|
#define XCLIENT_NAME "NAME" /* client name */
|
||||||
#define XCLIENT_ADDR "ADDR" /* client address */
|
#define XCLIENT_ADDR "ADDR" /* client address */
|
||||||
#define XCLIENT_PROTO "PROTO" /* client protocol */
|
#define XCLIENT_PROTO "PROTO" /* client protocol */
|
||||||
#define XCLIENT_CODE "NAME_CODE" /* client name status */
|
|
||||||
#define XCLIENT_HELO "HELO" /* client helo */
|
#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_CMD "XFORWARD" /* XFORWARD command */
|
||||||
#define XFORWARD_NAME "NAME" /* client name */
|
#define XFORWARD_NAME "NAME" /* client name */
|
||||||
#define XFORWARD_ADDR "ADDR" /* client address */
|
#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_HELO "HELO" /* client helo */
|
||||||
#define XFORWARD_IDENT "IDENT" /* message identifier */
|
#define XFORWARD_IDENT "IDENT" /* message identifier */
|
||||||
|
|
||||||
|
#define XFORWARD_UNAVAILABLE "[UNAVAILABLE]" /* attribute unavailable */
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
* Patches change the patchlevel and the release date. Snapshots change the
|
* Patches change the patchlevel and the release date. Snapshots change the
|
||||||
* release date only, unless they include the same bugfix as a patch release.
|
* release date only, unless they include the same bugfix as a patch release.
|
||||||
*/
|
*/
|
||||||
#define MAIL_RELEASE_DATE "20031213"
|
#define MAIL_RELEASE_DATE "20031214"
|
||||||
|
|
||||||
#define VAR_MAIL_VERSION "mail_version"
|
#define VAR_MAIL_VERSION "mail_version"
|
||||||
#define DEF_MAIL_VERSION "2.0.16-" MAIL_RELEASE_DATE
|
#define DEF_MAIL_VERSION "2.0.16-" MAIL_RELEASE_DATE
|
||||||
|
@@ -88,6 +88,11 @@
|
|||||||
/* .IP \fBlmtp_tcp_port\fR
|
/* .IP \fBlmtp_tcp_port\fR
|
||||||
/* The TCP port to be used when connecting to a LMTP server. Used as
|
/* 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).
|
/* 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"
|
/* .SH "Authentication controls"
|
||||||
/* .IP \fBlmtp_sasl_auth_enable\fR
|
/* .IP \fBlmtp_sasl_auth_enable\fR
|
||||||
/* Enable per-session authentication as per RFC 2554 (SASL).
|
/* Enable per-session authentication as per RFC 2554 (SASL).
|
||||||
@@ -169,6 +174,9 @@
|
|||||||
/* .IP \fBlmtp_lhlo_timeout\fR
|
/* .IP \fBlmtp_lhlo_timeout\fR
|
||||||
/* Timeout for sending the \fBLHLO\fR command, and for
|
/* Timeout for sending the \fBLHLO\fR command, and for
|
||||||
/* receiving the server response.
|
/* 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
|
/* .IP \fBlmtp_mail_timeout\fR
|
||||||
/* Timeout for sending the \fBMAIL FROM\fR command, and for
|
/* Timeout for sending the \fBMAIL FROM\fR command, and for
|
||||||
/* receiving the server response.
|
/* receiving the server response.
|
||||||
@@ -263,6 +271,7 @@ int var_lmtp_tcp_port;
|
|||||||
int var_lmtp_conn_tmout;
|
int var_lmtp_conn_tmout;
|
||||||
int var_lmtp_rset_tmout;
|
int var_lmtp_rset_tmout;
|
||||||
int var_lmtp_lhlo_tmout;
|
int var_lmtp_lhlo_tmout;
|
||||||
|
int var_lmtp_xfwd_tmout;
|
||||||
int var_lmtp_mail_tmout;
|
int var_lmtp_mail_tmout;
|
||||||
int var_lmtp_rcpt_tmout;
|
int var_lmtp_rcpt_tmout;
|
||||||
int var_lmtp_data0_tmout;
|
int var_lmtp_data0_tmout;
|
||||||
@@ -276,6 +285,7 @@ char *var_error_rcpt;
|
|||||||
char *var_lmtp_sasl_opts;
|
char *var_lmtp_sasl_opts;
|
||||||
char *var_lmtp_sasl_passwd;
|
char *var_lmtp_sasl_passwd;
|
||||||
bool var_lmtp_sasl_enable;
|
bool var_lmtp_sasl_enable;
|
||||||
|
bool var_lmtp_send_xforward;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global variables.
|
* 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_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_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_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_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_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,
|
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_PIPELINING (1<<2)
|
||||||
#define LMTP_FEATURE_SIZE (1<<3)
|
#define LMTP_FEATURE_SIZE (1<<3)
|
||||||
#define LMTP_FEATURE_AUTH (1<<5)
|
#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
|
* lmtp.c
|
||||||
|
@@ -100,6 +100,7 @@
|
|||||||
#include <vstring_vstream.h>
|
#include <vstring_vstream.h>
|
||||||
#include <stringops.h>
|
#include <stringops.h>
|
||||||
#include <mymalloc.h>
|
#include <mymalloc.h>
|
||||||
|
#include <name_code.h>
|
||||||
|
|
||||||
/* Global library. */
|
/* Global library. */
|
||||||
|
|
||||||
@@ -141,48 +142,58 @@
|
|||||||
* the existing code for exception handling and error reporting.
|
* the existing code for exception handling and error reporting.
|
||||||
*
|
*
|
||||||
* Client states that are associated with sending mail (up to and including
|
* Client states that are associated with sending mail (up to and including
|
||||||
* SMTP_STATE_DOT) must have smaller numerical values than the non-sending
|
* LMTP_STATE_DOT) must have smaller numerical values than the non-sending
|
||||||
* states (SMTP_STATE_ABORT .. SMTP_STATE_LAST).
|
* states (LMTP_STATE_ABORT .. LMTP_STATE_LAST).
|
||||||
*/
|
*/
|
||||||
#define LMTP_STATE_MAIL 0
|
#define LMTP_STATE_XFORWARD_NAME_ADDR 0
|
||||||
#define LMTP_STATE_RCPT 1
|
#define LMTP_STATE_XFORWARD_PROTO_HELO 1
|
||||||
#define LMTP_STATE_DATA 2
|
#define LMTP_STATE_MAIL 2
|
||||||
#define LMTP_STATE_DOT 3
|
#define LMTP_STATE_RCPT 3
|
||||||
#define LMTP_STATE_ABORT 4
|
#define LMTP_STATE_DATA 4
|
||||||
#define LMTP_STATE_RSET 5
|
#define LMTP_STATE_DOT 5
|
||||||
#define LMTP_STATE_QUIT 6
|
#define LMTP_STATE_ABORT 6
|
||||||
#define LMTP_STATE_LAST 7
|
#define LMTP_STATE_RSET 7
|
||||||
|
#define LMTP_STATE_QUIT 8
|
||||||
|
#define LMTP_STATE_LAST 9
|
||||||
|
|
||||||
int *xfer_timeouts[LMTP_STATE_LAST] = {
|
int *xfer_timeouts[LMTP_STATE_LAST] = {
|
||||||
|
&var_lmtp_xfwd_tmout, /* name/addr */
|
||||||
|
&var_lmtp_xfwd_tmout, /* helo/proto */
|
||||||
&var_lmtp_mail_tmout,
|
&var_lmtp_mail_tmout,
|
||||||
&var_lmtp_rcpt_tmout,
|
&var_lmtp_rcpt_tmout,
|
||||||
&var_lmtp_data0_tmout,
|
&var_lmtp_data0_tmout,
|
||||||
&var_lmtp_data2_tmout,
|
&var_lmtp_data2_tmout,
|
||||||
&var_lmtp_rset_tmout,
|
&var_lmtp_rset_tmout, /* abort */
|
||||||
&var_lmtp_rset_tmout,
|
&var_lmtp_rset_tmout, /* rset */
|
||||||
&var_lmtp_quit_tmout,
|
&var_lmtp_quit_tmout,
|
||||||
};
|
};
|
||||||
|
|
||||||
char *xfer_states[LMTP_STATE_LAST] = {
|
char *xfer_states[LMTP_STATE_LAST] = {
|
||||||
|
"sending XFORWARD name/address",
|
||||||
|
"sending XFORWARD protocol/helo_name",
|
||||||
"sending MAIL FROM",
|
"sending MAIL FROM",
|
||||||
"sending RCPT TO",
|
"sending RCPT TO",
|
||||||
"sending DATA command",
|
"sending DATA command",
|
||||||
"sending end of data -- message may be sent more than once",
|
"sending end of data -- message may be sent more than once",
|
||||||
"sending RSET",
|
"sending RSET", /* abort */
|
||||||
"sending RSET",
|
"sending RSET", /* rset */
|
||||||
"sending QUIT",
|
"sending QUIT",
|
||||||
};
|
};
|
||||||
|
|
||||||
char *xfer_request[LMTP_STATE_LAST] = {
|
char *xfer_request[LMTP_STATE_LAST] = {
|
||||||
|
"XFORWARD name/address command",
|
||||||
|
"XFORWARD helo/protocol command",
|
||||||
"MAIL FROM command",
|
"MAIL FROM command",
|
||||||
"RCPT TO command",
|
"RCPT TO command",
|
||||||
"DATA command",
|
"DATA command",
|
||||||
"end of DATA command",
|
"end of DATA command",
|
||||||
"RSET command",
|
"RSET command", /* abort */
|
||||||
"RSET command",
|
"RSET command", /* rset */
|
||||||
"QUIT command",
|
"QUIT command",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int lmtp_send_proto_helo;
|
||||||
|
|
||||||
/* lmtp_lhlo - perform initial handshake with LMTP server */
|
/* lmtp_lhlo - perform initial handshake with LMTP server */
|
||||||
|
|
||||||
int lmtp_lhlo(LMTP_STATE *state)
|
int lmtp_lhlo(LMTP_STATE *state)
|
||||||
@@ -193,6 +204,13 @@ int lmtp_lhlo(LMTP_STATE *state)
|
|||||||
char *lines;
|
char *lines;
|
||||||
char *words;
|
char *words;
|
||||||
char *word;
|
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.
|
* Prepare for disaster.
|
||||||
@@ -235,6 +253,10 @@ int lmtp_lhlo(LMTP_STATE *state)
|
|||||||
state->features |= LMTP_FEATURE_8BITMIME;
|
state->features |= LMTP_FEATURE_8BITMIME;
|
||||||
else if (strcasecmp(word, "PIPELINING") == 0)
|
else if (strcasecmp(word, "PIPELINING") == 0)
|
||||||
state->features |= LMTP_FEATURE_PIPELINING;
|
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)
|
else if (strcasecmp(word, "SIZE") == 0)
|
||||||
state->features |= LMTP_FEATURE_SIZE;
|
state->features |= LMTP_FEATURE_SIZE;
|
||||||
#ifdef USE_SASL_AUTH
|
#ifdef USE_SASL_AUTH
|
||||||
@@ -364,6 +386,40 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state)
|
|||||||
default:
|
default:
|
||||||
msg_panic("%s: bad sender state %d", myname, send_state);
|
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.
|
* Build the MAIL FROM command.
|
||||||
*/
|
*/
|
||||||
@@ -478,7 +534,7 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state)
|
|||||||
/*
|
/*
|
||||||
* Sanity check.
|
* Sanity check.
|
||||||
*/
|
*/
|
||||||
if (recv_state < LMTP_STATE_MAIL
|
if (recv_state < LMTP_STATE_XFORWARD_NAME_ADDR
|
||||||
|| recv_state > LMTP_STATE_QUIT)
|
|| recv_state > LMTP_STATE_QUIT)
|
||||||
msg_panic("%s: bad receiver state %d (sender state %d)",
|
msg_panic("%s: bad receiver state %d (sender state %d)",
|
||||||
myname, recv_state, send_state);
|
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) {
|
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
|
* Process the MAIL FROM response. When the server
|
||||||
* rejects the sender, set the mail_from_rejected flag so
|
* 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),
|
&& sent(DEL_REQ_TRACE_FLAGS(request->flags),
|
||||||
request->queue_id, rcpt->orig_addr,
|
request->queue_id, rcpt->orig_addr,
|
||||||
rcpt->address, rcpt->offset,
|
rcpt->address, rcpt->offset,
|
||||||
session->namaddr, request->arrival_time,
|
session->namaddr, request->arrival_time,
|
||||||
"%s",
|
"%s",
|
||||||
translit(resp->str, "\n", " ")) == 0) {
|
translit(resp->str, "\n", " ")) == 0) {
|
||||||
if (request->flags & DEL_REQ_FLAG_SUCCESS)
|
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)
|
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 */
|
/* 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.
|
* Sanity checks. Verify that every member has an acceptable value.
|
||||||
*/
|
*/
|
||||||
if (user == 0)
|
if (user == 0)
|
||||||
msg_fatal("missing user= attribute");
|
msg_fatal("missing user= command-line attribute");
|
||||||
if (attr->command == 0)
|
if (attr->command == 0)
|
||||||
msg_fatal("missing argv= attribute");
|
msg_fatal("missing argv= command-line attribute");
|
||||||
if (attr->uid == 0)
|
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)
|
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)
|
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)
|
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.
|
* 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/mymalloc.h
|
||||||
smtp_proto.o: ../../include/iostuff.h
|
smtp_proto.o: ../../include/iostuff.h
|
||||||
smtp_proto.o: ../../include/split_at.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/mail_params.h
|
||||||
smtp_proto.o: ../../include/smtp_stream.h
|
smtp_proto.o: ../../include/smtp_stream.h
|
||||||
smtp_proto.o: ../../include/mail_queue.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/attr.h
|
||||||
smtp_proto.o: ../../include/mime_state.h
|
smtp_proto.o: ../../include/mime_state.h
|
||||||
smtp_proto.o: ../../include/header_opts.h
|
smtp_proto.o: ../../include/header_opts.h
|
||||||
smtp_proto.o: ../../include/xtext.h
|
|
||||||
smtp_proto.o: smtp.h
|
smtp_proto.o: smtp.h
|
||||||
smtp_proto.o: ../../include/argv.h
|
smtp_proto.o: ../../include/argv.h
|
||||||
smtp_proto.o: smtp_sasl.h
|
smtp_proto.o: smtp_sasl.h
|
||||||
|
@@ -109,6 +109,12 @@
|
|||||||
/* Never send EHLO at the start of a connection.
|
/* Never send EHLO at the start of a connection.
|
||||||
/* .IP \fBsmtp_bind_address\fR
|
/* .IP \fBsmtp_bind_address\fR
|
||||||
/* Numerical source network address to bind to when making a connection.
|
/* 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
|
/* .IP \fBsmtp_line_length_limit\fR
|
||||||
/* Length limit for SMTP message content lines. Zero means no limit.
|
/* Length limit for SMTP message content lines. Zero means no limit.
|
||||||
/* Some SMTP servers misbehave on long lines.
|
/* Some SMTP servers misbehave on long lines.
|
||||||
@@ -142,6 +148,11 @@
|
|||||||
/* The maximal nesting level of multipart mail that the MIME
|
/* The maximal nesting level of multipart mail that the MIME
|
||||||
/* processor can handle. Refuse mail that is nested deeper,
|
/* processor can handle. Refuse mail that is nested deeper,
|
||||||
/* when converting from 8BITMIME format to 7BIT format.
|
/* 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"
|
/* .SH "Authentication controls"
|
||||||
/* .IP \fBsmtp_sasl_auth_enable\fR
|
/* .IP \fBsmtp_sasl_auth_enable\fR
|
||||||
/* Enable per-session authentication as per RFC 2554 (SASL).
|
/* Enable per-session authentication as per RFC 2554 (SASL).
|
||||||
@@ -212,17 +223,6 @@
|
|||||||
/* Timeout for sending the "\fB.\fR" command, and for
|
/* Timeout for sending the "\fB.\fR" command, and for
|
||||||
/* receiving the server response. When no response is received, a
|
/* receiving the server response. When no response is received, a
|
||||||
/* warning is logged that the mail may be delivered multiple times.
|
/* 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
|
/* .IP \fBsmtp_rset_timeout\fR
|
||||||
/* Timeout for sending the \fBRSET\fR command.
|
/* Timeout for sending the \fBRSET\fR command.
|
||||||
/* .IP \fBsmtp_quit_timeout\fR
|
/* .IP \fBsmtp_quit_timeout\fR
|
||||||
@@ -283,7 +283,7 @@
|
|||||||
*/
|
*/
|
||||||
int var_smtp_conn_tmout;
|
int var_smtp_conn_tmout;
|
||||||
int var_smtp_helo_tmout;
|
int var_smtp_helo_tmout;
|
||||||
int var_smtp_xclnt_tmout;
|
int var_smtp_xfwd_tmout;
|
||||||
int var_smtp_mail_tmout;
|
int var_smtp_mail_tmout;
|
||||||
int var_smtp_rcpt_tmout;
|
int var_smtp_rcpt_tmout;
|
||||||
int var_smtp_data0_tmout;
|
int var_smtp_data0_tmout;
|
||||||
@@ -502,7 +502,7 @@ int main(int argc, char **argv)
|
|||||||
static CONFIG_TIME_TABLE time_table[] = {
|
static CONFIG_TIME_TABLE time_table[] = {
|
||||||
VAR_SMTP_CONN_TMOUT, DEF_SMTP_CONN_TMOUT, &var_smtp_conn_tmout, 0, 0,
|
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_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_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_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,
|
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_PROTO (1<<9)
|
||||||
#define SMTP_FEATURE_XFORWARD_HELO (1<<10)
|
#define SMTP_FEATURE_XFORWARD_HELO (1<<10)
|
||||||
|
|
||||||
#define SMTP_FEATURE_XFORWARD_MASK \
|
#define SMTP_FEATURE_XFORWARD_NAME_ADDR \
|
||||||
(SMTP_FEATURE_XFORWARD_NAME | SMTP_FEATURE_XFORWARD_ADDR \
|
(SMTP_FEATURE_XFORWARD_NAME | SMTP_FEATURE_XFORWARD_ADDR)
|
||||||
| SMTP_FEATURE_XFORWARD_PROTO | SMTP_FEATURE_XFORWARD_HELO)
|
|
||||||
|
#define SMTP_FEATURE_XFORWARD_PROTO_HELO \
|
||||||
|
(SMTP_FEATURE_XFORWARD_PROTO | SMTP_FEATURE_XFORWARD_HELO)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* smtp.c
|
* smtp.c
|
||||||
|
@@ -104,7 +104,6 @@
|
|||||||
#include <quote_821_local.h>
|
#include <quote_821_local.h>
|
||||||
#include <mail_proto.h>
|
#include <mail_proto.h>
|
||||||
#include <mime_state.h>
|
#include <mime_state.h>
|
||||||
#include <xtext.h>
|
|
||||||
|
|
||||||
/* Application-specific. */
|
/* Application-specific. */
|
||||||
|
|
||||||
@@ -125,8 +124,8 @@
|
|||||||
* SMTP_STATE_DOT) must have smaller numerical values than the non-sending
|
* SMTP_STATE_DOT) must have smaller numerical values than the non-sending
|
||||||
* states (SMTP_STATE_ABORT .. SMTP_STATE_LAST).
|
* states (SMTP_STATE_ABORT .. SMTP_STATE_LAST).
|
||||||
*/
|
*/
|
||||||
#define SMTP_STATE_XFORWARD_ADDR 0
|
#define SMTP_STATE_XFORWARD_NAME_ADDR 0
|
||||||
#define SMTP_STATE_XFORWARD_HELO 1
|
#define SMTP_STATE_XFORWARD_PROTO_HELO 1
|
||||||
#define SMTP_STATE_MAIL 2
|
#define SMTP_STATE_MAIL 2
|
||||||
#define SMTP_STATE_RCPT 3
|
#define SMTP_STATE_RCPT 3
|
||||||
#define SMTP_STATE_DATA 4
|
#define SMTP_STATE_DATA 4
|
||||||
@@ -136,8 +135,8 @@
|
|||||||
#define SMTP_STATE_LAST 8
|
#define SMTP_STATE_LAST 8
|
||||||
|
|
||||||
int *xfer_timeouts[SMTP_STATE_LAST] = {
|
int *xfer_timeouts[SMTP_STATE_LAST] = {
|
||||||
&var_smtp_xclnt_tmout,
|
&var_smtp_xfwd_tmout, /* name/addr */
|
||||||
&var_smtp_xclnt_tmout,
|
&var_smtp_xfwd_tmout, /* helo/proto */
|
||||||
&var_smtp_mail_tmout,
|
&var_smtp_mail_tmout,
|
||||||
&var_smtp_rcpt_tmout,
|
&var_smtp_rcpt_tmout,
|
||||||
&var_smtp_data0_tmout,
|
&var_smtp_data0_tmout,
|
||||||
@@ -147,8 +146,8 @@ int *xfer_timeouts[SMTP_STATE_LAST] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
char *xfer_states[SMTP_STATE_LAST] = {
|
char *xfer_states[SMTP_STATE_LAST] = {
|
||||||
"sending XFORWARD address and name",
|
"sending XFORWARD name/address",
|
||||||
"sending XFORWARD helo_name and protocol",
|
"sending XFORWARD protocol/helo_name",
|
||||||
"sending MAIL FROM",
|
"sending MAIL FROM",
|
||||||
"sending RCPT TO",
|
"sending RCPT TO",
|
||||||
"sending DATA command",
|
"sending DATA command",
|
||||||
@@ -267,11 +266,11 @@ int smtp_helo(SMTP_STATE *state)
|
|||||||
state->features |= SMTP_FEATURE_8BITMIME;
|
state->features |= SMTP_FEATURE_8BITMIME;
|
||||||
else if (strcasecmp(word, "PIPELINING") == 0)
|
else if (strcasecmp(word, "PIPELINING") == 0)
|
||||||
state->features |= SMTP_FEATURE_PIPELINING;
|
state->features |= SMTP_FEATURE_PIPELINING;
|
||||||
else if (strcasecmp(word, "XFORWARD") == 0) {
|
else if (strcasecmp(word, "XFORWARD") == 0)
|
||||||
while ((word = mystrtok(&words, " \t")) != 0)
|
while ((word = mystrtok(&words, " \t")) != 0)
|
||||||
state->features |= name_code(xforward_features,
|
state->features |= name_code(xforward_features,
|
||||||
NAME_CODE_FLAG_NONE, word);
|
NAME_CODE_FLAG_NONE, word);
|
||||||
} else if (strcasecmp(word, "SIZE") == 0) {
|
else if (strcasecmp(word, "SIZE") == 0) {
|
||||||
state->features |= SMTP_FEATURE_SIZE;
|
state->features |= SMTP_FEATURE_SIZE;
|
||||||
if ((word = mystrtok(&words, " \t")) != 0) {
|
if ((word = mystrtok(&words, " \t")) != 0) {
|
||||||
if (!alldig(word))
|
if (!alldig(word))
|
||||||
@@ -395,6 +394,8 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
int mail_from_rejected;
|
int mail_from_rejected;
|
||||||
int downgrading;
|
int downgrading;
|
||||||
int mime_errs;
|
int mime_errs;
|
||||||
|
int send_name_addr;
|
||||||
|
int send_proto_helo;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Macros for readability.
|
* Macros for readability.
|
||||||
@@ -498,11 +499,20 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
* amount of information is available.
|
* amount of information is available.
|
||||||
*/
|
*/
|
||||||
nrcpt = 0;
|
nrcpt = 0;
|
||||||
if (var_smtp_send_xforward
|
send_name_addr =
|
||||||
&& (state->features & SMTP_FEATURE_XFORWARD_MASK)
|
(var_smtp_send_xforward
|
||||||
&& (DEL_REQ_ATTR_AVAIL(request->client_name)
|
&& (state->features & SMTP_FEATURE_XFORWARD_NAME_ADDR)
|
||||||
|| DEL_REQ_ATTR_AVAIL(request->client_addr)))
|
&& (DEL_REQ_ATTR_AVAIL(request->client_name)
|
||||||
recv_state = send_state = SMTP_STATE_XFORWARD_ADDR;
|
|| 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
|
else
|
||||||
recv_state = send_state = SMTP_STATE_MAIL;
|
recv_state = send_state = SMTP_STATE_MAIL;
|
||||||
next_rcpt = send_rcpt = recv_rcpt = 0;
|
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
|
* information, the command length stays within the 512 byte
|
||||||
* command line length limit.
|
* command line length limit.
|
||||||
*/
|
*/
|
||||||
case SMTP_STATE_XFORWARD_ADDR:
|
case SMTP_STATE_XFORWARD_NAME_ADDR:
|
||||||
vstring_strcpy(next_command, XFORWARD_CMD);
|
vstring_strcpy(next_command, XFORWARD_CMD);
|
||||||
if (state->features & SMTP_FEATURE_XFORWARD_NAME) {
|
if (state->features & SMTP_FEATURE_XFORWARD_NAME)
|
||||||
vstring_strcat(next_command, " " XCLIENT_NAME "=");
|
vstring_sprintf_append(next_command, " %s=%s",
|
||||||
if (DEL_REQ_ATTR_AVAIL(request->client_name))
|
XFORWARD_NAME, DEL_REQ_ATTR_AVAIL(request->client_name) ?
|
||||||
xtext_quote_append(next_command, request->client_name, "");
|
request->client_name : XFORWARD_UNAVAILABLE);
|
||||||
}
|
if (state->features & SMTP_FEATURE_XFORWARD_ADDR)
|
||||||
if (state->features & SMTP_FEATURE_XFORWARD_ADDR) {
|
vstring_sprintf_append(next_command, " %s=%s",
|
||||||
vstring_strcat(next_command, " " XFORWARD_ADDR "=");
|
XFORWARD_ADDR, DEL_REQ_ATTR_AVAIL(request->client_addr) ?
|
||||||
if (DEL_REQ_ATTR_AVAIL(request->client_addr))
|
request->client_addr : XFORWARD_UNAVAILABLE);
|
||||||
xtext_quote_append(next_command, request->client_addr, "");
|
if (send_proto_helo)
|
||||||
}
|
next_state = SMTP_STATE_XFORWARD_PROTO_HELO;
|
||||||
next_state = SMTP_STATE_XFORWARD_HELO;
|
else
|
||||||
|
next_state = SMTP_STATE_MAIL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SMTP_STATE_XFORWARD_HELO:
|
case SMTP_STATE_XFORWARD_PROTO_HELO:
|
||||||
vstring_strcpy(next_command, XFORWARD_CMD);
|
vstring_strcpy(next_command, XFORWARD_CMD);
|
||||||
if (state->features & SMTP_FEATURE_XFORWARD_HELO) {
|
if (state->features & SMTP_FEATURE_XFORWARD_PROTO)
|
||||||
vstring_strcat(next_command, " " XCLIENT_HELO "=");
|
vstring_sprintf_append(next_command, " %s=%s",
|
||||||
if (DEL_REQ_ATTR_AVAIL(request->client_helo))
|
XFORWARD_PROTO, DEL_REQ_ATTR_AVAIL(request->client_proto) ?
|
||||||
xtext_quote_append(next_command, request->client_helo, "");
|
request->client_proto : XFORWARD_UNAVAILABLE);
|
||||||
}
|
if (state->features & SMTP_FEATURE_XFORWARD_HELO)
|
||||||
if (state->features & SMTP_FEATURE_XFORWARD_ADDR) {
|
vstring_sprintf_append(next_command, " %s=%s",
|
||||||
vstring_strcat(next_command, " " XFORWARD_PROTO "=");
|
XFORWARD_HELO, DEL_REQ_ATTR_AVAIL(request->client_helo) ?
|
||||||
if (DEL_REQ_ATTR_AVAIL(request->client_proto))
|
request->client_helo : XFORWARD_UNAVAILABLE);
|
||||||
xtext_quote_append(next_command, request->client_proto, "");
|
|
||||||
}
|
|
||||||
next_state = SMTP_STATE_MAIL;
|
next_state = SMTP_STATE_MAIL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -665,7 +674,7 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
/*
|
/*
|
||||||
* Sanity check.
|
* Sanity check.
|
||||||
*/
|
*/
|
||||||
if (recv_state < SMTP_STATE_XFORWARD_ADDR
|
if (recv_state < SMTP_STATE_XFORWARD_NAME_ADDR
|
||||||
|| recv_state > SMTP_STATE_QUIT)
|
|| recv_state > SMTP_STATE_QUIT)
|
||||||
msg_panic("%s: bad receiver state %d (sender state %d)",
|
msg_panic("%s: bad receiver state %d (sender state %d)",
|
||||||
myname, recv_state, send_state);
|
myname, recv_state, send_state);
|
||||||
@@ -689,21 +698,24 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
/*
|
/*
|
||||||
* Process the XFORWARD response.
|
* Process the XFORWARD response.
|
||||||
*/
|
*/
|
||||||
case SMTP_STATE_XFORWARD_ADDR:
|
case SMTP_STATE_XFORWARD_NAME_ADDR:
|
||||||
if (resp->code / 100 != 2)
|
if (resp->code / 100 != 2)
|
||||||
msg_warn("host %s said: %s (in reply to %s)",
|
msg_warn("host %s said: %s (in reply to %s)",
|
||||||
session->namaddr,
|
session->namaddr,
|
||||||
translit(resp->str, "\n", " "),
|
translit(resp->str, "\n", " "),
|
||||||
xfer_request[SMTP_STATE_MAIL]);
|
xfer_request[SMTP_STATE_XFORWARD_NAME_ADDR]);
|
||||||
recv_state = SMTP_STATE_XFORWARD_HELO;
|
if (send_proto_helo)
|
||||||
|
recv_state = SMTP_STATE_XFORWARD_PROTO_HELO;
|
||||||
|
else
|
||||||
|
recv_state = SMTP_STATE_MAIL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SMTP_STATE_XFORWARD_HELO:
|
case SMTP_STATE_XFORWARD_PROTO_HELO:
|
||||||
if (resp->code / 100 != 2)
|
if (resp->code / 100 != 2)
|
||||||
msg_warn("host %s said: %s (in reply to %s)",
|
msg_warn("host %s said: %s (in reply to %s)",
|
||||||
session->namaddr,
|
session->namaddr,
|
||||||
translit(resp->str, "\n", " "),
|
translit(resp->str, "\n", " "),
|
||||||
xfer_request[SMTP_STATE_MAIL]);
|
xfer_request[SMTP_STATE_XFORWARD_PROTO_HELO]);
|
||||||
recv_state = SMTP_STATE_MAIL;
|
recv_state = SMTP_STATE_MAIL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@@ -151,7 +151,6 @@ smtpd.o: ../../include/namadr_list.h
|
|||||||
smtpd.o: ../../include/input_transp.h
|
smtpd.o: ../../include/input_transp.h
|
||||||
smtpd.o: ../../include/anvil_clnt.h
|
smtpd.o: ../../include/anvil_clnt.h
|
||||||
smtpd.o: ../../include/attr_clnt.h
|
smtpd.o: ../../include/attr_clnt.h
|
||||||
smtpd.o: ../../include/xtext.h
|
|
||||||
smtpd.o: ../../include/mail_server.h
|
smtpd.o: ../../include/mail_server.h
|
||||||
smtpd.o: smtpd_token.h
|
smtpd.o: smtpd_token.h
|
||||||
smtpd.o: smtpd.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/stringops.h
|
||||||
smtpd_proxy.o: ../../include/connect.h
|
smtpd_proxy.o: ../../include/connect.h
|
||||||
smtpd_proxy.o: ../../include/iostuff.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/mail_error.h
|
||||||
smtpd_proxy.o: ../../include/name_mask.h
|
smtpd_proxy.o: ../../include/name_mask.h
|
||||||
smtpd_proxy.o: ../../include/smtp_stream.h
|
smtpd_proxy.o: ../../include/smtp_stream.h
|
||||||
smtpd_proxy.o: ../../include/cleanup_user.h
|
smtpd_proxy.o: ../../include/cleanup_user.h
|
||||||
smtpd_proxy.o: ../../include/mail_params.h
|
smtpd_proxy.o: ../../include/mail_params.h
|
||||||
smtpd_proxy.o: ../../include/rec_type.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/mail_proto.h
|
||||||
smtpd_proxy.o: ../../include/attr.h
|
smtpd_proxy.o: ../../include/attr.h
|
||||||
smtpd_proxy.o: smtpd.h
|
smtpd_proxy.o: smtpd.h
|
||||||
|
@@ -464,7 +464,6 @@
|
|||||||
#include <namadr_list.h>
|
#include <namadr_list.h>
|
||||||
#include <input_transp.h>
|
#include <input_transp.h>
|
||||||
#include <anvil_clnt.h>
|
#include <anvil_clnt.h>
|
||||||
#include <xtext.h>
|
|
||||||
|
|
||||||
/* Single-threaded server skeleton. */
|
/* Single-threaded server skeleton. */
|
||||||
|
|
||||||
@@ -753,8 +752,7 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
if (xclient_allowed)
|
if (xclient_allowed)
|
||||||
smtpd_chat_reply(state, "250-" XCLIENT_CMD
|
smtpd_chat_reply(state, "250-" XCLIENT_CMD
|
||||||
" " XCLIENT_NAME " " XCLIENT_ADDR
|
" " XCLIENT_NAME " " XCLIENT_ADDR
|
||||||
" " XCLIENT_CODE " " XCLIENT_PROTO
|
" " XCLIENT_PROTO " " XCLIENT_HELO);
|
||||||
" " XCLIENT_HELO);
|
|
||||||
if (xforward_allowed)
|
if (xforward_allowed)
|
||||||
smtpd_chat_reply(state, "250-" XFORWARD_CMD
|
smtpd_chat_reply(state, "250-" XFORWARD_CMD
|
||||||
" " XFORWARD_NAME " " XFORWARD_ADDR
|
" " XFORWARD_NAME " " XFORWARD_ADDR
|
||||||
@@ -1723,22 +1721,21 @@ static int quit_cmd(SMTPD_STATE *state, int unused_argc, SMTPD_TOKEN *unused_arg
|
|||||||
return (0);
|
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)
|
static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||||
{
|
{
|
||||||
int arg_no;
|
SMTPD_TOKEN *argp;
|
||||||
char *attr_value;
|
char *attr_value;
|
||||||
char *attr_name;
|
char *attr_name;
|
||||||
int update_namaddr = 0;
|
int update_namaddr = 0;
|
||||||
int code;
|
int peer_code;
|
||||||
static NAME_CODE xclient_codes[] = {
|
static NAME_CODE peer_codes[] = {
|
||||||
"OK", SMTPD_PEER_CODE_OK,
|
XCLIENT_UNAVAILABLE, SMTPD_PEER_CODE_PERM,
|
||||||
"PERM", SMTPD_PEER_CODE_PERM,
|
XCLIENT_TEMPORARY, SMTPD_PEER_CODE_TEMP,
|
||||||
"TEMP", SMTPD_PEER_CODE_TEMP,
|
0, SMTPD_PEER_CODE_OK,
|
||||||
0, -1,
|
|
||||||
};
|
};
|
||||||
static NAME_CODE xclient_proto[] = {
|
static NAME_CODE proto_names[] = {
|
||||||
MAIL_PROTO_SMTP, 1,
|
MAIL_PROTO_SMTP, 1,
|
||||||
MAIL_PROTO_ESMTP, 2,
|
MAIL_PROTO_ESMTP, 2,
|
||||||
0, -1,
|
0, -1,
|
||||||
@@ -1755,7 +1752,7 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
}
|
}
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
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);
|
XCLIENT_CMD);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
@@ -1765,122 +1762,99 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
#define STREQ(x,y) (strcasecmp((x), (y)) == 0)
|
#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++) {
|
for (argp = argv + 1; argp < argv + argc; argp++) {
|
||||||
attr_name = argv[arg_no].strval;
|
attr_name = argp->strval;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For safety's sake mask non-printable characters in the raw and
|
* For safety's sake mask non-printable characters. We'll do more
|
||||||
* decoded values; we don't want to handle unexploded munitions.
|
* specific censoring later.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
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;
|
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);
|
return (-1);
|
||||||
}
|
}
|
||||||
printable(attr_value, '?');
|
printable(attr_value, '?');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NAME=hostname. Also updates the client hostname lookup status
|
* NAME=substitute SMTP client hostname. Also updates the client
|
||||||
* code. Treat a numerical hostname as an unavailable name.
|
* hostname lookup status code.
|
||||||
*/
|
*/
|
||||||
if (STREQ(attr_name, XCLIENT_NAME)) {
|
if (STREQ(attr_name, XCLIENT_NAME)) {
|
||||||
if (*attr_value && !valid_hostaddr(attr_value, DONT_GRIPE)) {
|
peer_code = name_code(peer_codes, NAME_CODE_FLAG_NONE, attr_value);
|
||||||
if (!valid_hostname(attr_value, DONT_GRIPE)) {
|
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;
|
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||||
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
||||||
XCLIENT_NAME, attr_value);
|
XCLIENT_NAME, attr_value);
|
||||||
return (-1);
|
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;
|
update_namaddr = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ADDR=client network address.
|
* ADDR=substitute SMTP client network address.
|
||||||
*/
|
*/
|
||||||
else if (STREQ(attr_name, XCLIENT_ADDR)) {
|
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)) {
|
if (!valid_hostaddr(attr_value, DONT_GRIPE)) {
|
||||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||||
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
||||||
XCLIENT_ADDR, attr_value);
|
XCLIENT_ADDR, attr_value);
|
||||||
return (-1);
|
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;
|
update_namaddr = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CODE=hostname lookup status. Reset the client hostname if the
|
* HELO=substitute SMTP client HELO parameter. Censor special
|
||||||
* hostname lookup status is not OK.
|
* characters that could mess up message headers.
|
||||||
*/
|
|
||||||
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 [].
|
|
||||||
*/
|
*/
|
||||||
else if (STREQ(attr_name, XCLIENT_HELO)) {
|
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) {
|
if (strlen(attr_value) > VALID_HOSTNAME_LEN) {
|
||||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||||
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
||||||
XCLIENT_HELO, attr_value);
|
XCLIENT_HELO, attr_value);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
neuter(attr_value, "<>()\\\";:@", '?');
|
neuter(attr_value, NEUTER_CHARACTERS, '?');
|
||||||
UPDATE_STR(state->helo_name, attr_value);
|
|
||||||
} else {
|
|
||||||
UPDATE_STR(state->helo_name, CLIENT_HELO_UNKNOWN);
|
|
||||||
}
|
}
|
||||||
|
UPDATE_STR(state->helo_name, attr_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PROTO=protocol name. Disallow characters that could mess up our
|
* PROTO=SMTP protocol name.
|
||||||
* own Received: message headers.
|
|
||||||
*/
|
*/
|
||||||
else if (STREQ(attr_name, XCLIENT_PROTO)) {
|
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;
|
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||||
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
||||||
XCLIENT_PROTO, attr_value);
|
XCLIENT_PROTO, attr_value);
|
||||||
return (-1);
|
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)
|
static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||||
{
|
{
|
||||||
int arg_no;
|
SMTPD_TOKEN *argp;
|
||||||
char *attr_value;
|
char *attr_value;
|
||||||
char *attr_name;
|
char *attr_name;
|
||||||
int updated = 0;
|
int updated = 0;
|
||||||
@@ -1934,7 +1908,7 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
}
|
}
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
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);
|
XFORWARD_CMD);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
@@ -1951,22 +1925,18 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
smtpd_xforward_preset(state);
|
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++) {
|
for (argp = argv + 1; argp < argv + argc; argp++) {
|
||||||
attr_name = argv[arg_no].strval;
|
attr_name = argp->strval;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For safety's sake mask non-printable characters in the raw and
|
* For safety's sake mask non-printable characters. We'll do more
|
||||||
* decoded values; we don't want to handle unexploded munitions.
|
* specific censoring later.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
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;
|
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);
|
return (-1);
|
||||||
}
|
}
|
||||||
printable(attr_value, '?');
|
printable(attr_value, '?');
|
||||||
@@ -1975,71 +1945,61 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
switch (flag) {
|
switch (flag) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NAME=hostname. Also updates the client hostname lookup status
|
* NAME=host name, not necessarily in the DNS. Censor special
|
||||||
* code. Treat a numerical hostname as an unavailable name.
|
* characters that could mess up message headers.
|
||||||
*/
|
*/
|
||||||
case SMTPD_XFORWARD_FLAG_NAME:
|
case SMTPD_XFORWARD_FLAG_NAME:
|
||||||
if (*attr_value && !valid_hostaddr(attr_value, DONT_GRIPE)) {
|
if (STREQ(attr_value, XFORWARD_UNAVAILABLE)) {
|
||||||
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 {
|
|
||||||
attr_value = CLIENT_NAME_UNKNOWN;
|
attr_value = CLIENT_NAME_UNKNOWN;
|
||||||
|
} else {
|
||||||
|
neuter(attr_value, NEUTER_CHARACTERS, '?');
|
||||||
}
|
}
|
||||||
UPDATE_STR(state->xforward.name, attr_value);
|
UPDATE_STR(state->xforward.name, attr_value);
|
||||||
break;
|
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:
|
case SMTPD_XFORWARD_FLAG_ADDR:
|
||||||
if (*attr_value) {
|
if (STREQ(attr_value, XFORWARD_UNAVAILABLE)) {
|
||||||
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 {
|
|
||||||
attr_value = CLIENT_ADDR_UNKNOWN;
|
attr_value = CLIENT_ADDR_UNKNOWN;
|
||||||
|
} else {
|
||||||
|
neuter(attr_value, NEUTER_CHARACTERS, '?');
|
||||||
}
|
}
|
||||||
UPDATE_STR(state->xforward.addr, attr_value);
|
UPDATE_STR(state->xforward.addr, attr_value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* HELO=hostname. Disallow characters that could mess up our own
|
* HELO=hostname that the host introduced itself with (not
|
||||||
* Received: message headers but allow [].
|
* necessarily SMTP HELO). Censor special characters that could
|
||||||
|
* mess up message headers.
|
||||||
*/
|
*/
|
||||||
case SMTPD_XFORWARD_FLAG_HELO:
|
case SMTPD_XFORWARD_FLAG_HELO:
|
||||||
if (*attr_value) {
|
if (STREQ(attr_value, XFORWARD_UNAVAILABLE)) {
|
||||||
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 {
|
|
||||||
attr_value = CLIENT_HELO_UNKNOWN;
|
attr_value = CLIENT_HELO_UNKNOWN;
|
||||||
|
} else {
|
||||||
|
neuter(attr_value, NEUTER_CHARACTERS, '?');
|
||||||
}
|
}
|
||||||
UPDATE_STR(state->xforward.helo_name, attr_value);
|
UPDATE_STR(state->xforward.helo_name, attr_value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PROTO=protocol name. Neutralize characters that could mess up
|
* PROTO=protocol name, not necessarily SMTP or ESMTP. Censor
|
||||||
* our own Received: message headers.
|
* special characters that could mess up message headers.
|
||||||
*/
|
*/
|
||||||
case SMTPD_XFORWARD_FLAG_PROTO:
|
case SMTPD_XFORWARD_FLAG_PROTO:
|
||||||
if (strlen(attr_value) > 64) {
|
if (STREQ(attr_value, XFORWARD_UNAVAILABLE)) {
|
||||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
attr_value = CLIENT_PROTO_UNKNOWN;
|
||||||
smtpd_chat_reply(state, "501 Bad %s syntax: %s",
|
} else {
|
||||||
XFORWARD_PROTO, attr_value);
|
if (strlen(attr_value) > 64) {
|
||||||
return (-1);
|
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);
|
UPDATE_STR(state->xforward.protocol, attr_value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -2063,9 +2023,10 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
if (state->xforward.namaddr)
|
if (state->xforward.namaddr)
|
||||||
myfree(state->xforward.namaddr);
|
myfree(state->xforward.namaddr);
|
||||||
state->xforward.namaddr =
|
state->xforward.namaddr =
|
||||||
|
IS_AVAIL_CLIENT_ADDR(state->xforward.addr) ?
|
||||||
concatenate(state->xforward.name, "[",
|
concatenate(state->xforward.name, "[",
|
||||||
state->xforward.addr, "]",
|
state->xforward.addr, "]",
|
||||||
(char *) 0);
|
(char *) 0) : mystrdup(state->xforward.name);
|
||||||
}
|
}
|
||||||
smtpd_chat_reply(state, "250 Ok");
|
smtpd_chat_reply(state, "250 Ok");
|
||||||
return (0);
|
return (0);
|
||||||
|
@@ -206,9 +206,8 @@ extern void smtpd_peer_reset(SMTPD_STATE *state);
|
|||||||
#define SMTPD_PROXY_XFORWARD_IDENT (1<<4) /* message identifier */
|
#define SMTPD_PROXY_XFORWARD_IDENT (1<<4) /* message identifier */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If forwarding client information, don't mix direct client information
|
* If forwarding client information, don't mix information from the current
|
||||||
* from the current SMTP session with forwarded client information from an
|
* SMTP session with forwarded information from an up-stream session.
|
||||||
* up-stream session.
|
|
||||||
*/
|
*/
|
||||||
#define FORWARD_CLIENT_ATTR(s, a) \
|
#define FORWARD_CLIENT_ATTR(s, a) \
|
||||||
(((s)->xforward.flags & SMTPD_XFORWARD_FLAG_CLIENT_MASK) ? \
|
(((s)->xforward.flags & SMTPD_XFORWARD_FLAG_CLIENT_MASK) ? \
|
||||||
|
@@ -156,7 +156,6 @@
|
|||||||
#include <cleanup_user.h>
|
#include <cleanup_user.h>
|
||||||
#include <mail_params.h>
|
#include <mail_params.h>
|
||||||
#include <rec_type.h>
|
#include <rec_type.h>
|
||||||
#include <xtext.h>
|
|
||||||
#include <mail_proto.h>
|
#include <mail_proto.h>
|
||||||
|
|
||||||
/* Application-specific. */
|
/* 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?
|
* How much space does this attribute need?
|
||||||
*/
|
*/
|
||||||
if (!value_available)
|
if (!value_available)
|
||||||
value = "";
|
value = XFORWARD_UNAVAILABLE;
|
||||||
new_len = strlen(name) + strlen(value) + 2; /* SPACE name = value */
|
new_len = strlen(name) + strlen(value) + 2; /* SPACE name = value */
|
||||||
if (new_len > PAYLOAD_LIMIT)
|
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);
|
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 \
|
username.c valid_hostname.c vbuf.c vbuf_print.c vstream.c \
|
||||||
vstream_popen.c vstring.c vstring_vstream.c watchdog.c writable.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 \
|
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 \
|
OBJS = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
|
||||||
attr_scan0.o attr_scan64.o base64_code.o basename.o binhash.o \
|
attr_scan0.o attr_scan64.o base64_code.o basename.o binhash.o \
|
||||||
chroot_uid.o clean_env.o close_on_exec.o concatenate.o ctable.o \
|
chroot_uid.o clean_env.o close_on_exec.o concatenate.o ctable.o \
|
||||||
@@ -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 \
|
username.o valid_hostname.o vbuf.o vbuf_print.o vstream.o \
|
||||||
vstream_popen.o vstring.o vstring_vstream.o watchdog.o writable.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 \
|
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 \
|
HDRS = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
|
||||||
connect.h ctable.h dict.h dict_db.h dict_dbm.h dict_env.h \
|
connect.h ctable.h dict.h dict_db.h dict_dbm.h dict_env.h \
|
||||||
dict_cidr.h dict_ht.h dict_ldap.h dict_mysql.h dict_ni.h dict_nis.h \
|
dict_cidr.h dict_ht.h dict_ldap.h dict_mysql.h dict_ni.h dict_nis.h \
|
||||||
@@ -1292,6 +1294,11 @@ unix_trigger.o: trigger.h
|
|||||||
unsafe.o: unsafe.c
|
unsafe.o: unsafe.c
|
||||||
unsafe.o: sys_defs.h
|
unsafe.o: sys_defs.h
|
||||||
unsafe.o: safe.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: username.c
|
||||||
username.o: sys_defs.h
|
username.o: sys_defs.h
|
||||||
username.o: username.h
|
username.o: username.h
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
extern char *printable(char *, int);
|
extern char *printable(char *, int);
|
||||||
extern char *neuter(char *, const char *, int);
|
extern char *neuter(char *, const char *, int);
|
||||||
extern char *lowercase(char *);
|
extern char *lowercase(char *);
|
||||||
|
extern char *uppercase(char *);
|
||||||
extern char *skipblanks(const char *);
|
extern char *skipblanks(const char *);
|
||||||
extern char *trimblanks(char *, int);
|
extern char *trimblanks(char *, int);
|
||||||
extern char *concatenate(const char *,...);
|
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);
|
||||||
|
}
|
Reference in New Issue
Block a user