2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-30 21:55:20 +00:00

postfix-2.0.16-20031128

This commit is contained in:
Wietse Venema
2003-11-28 00:00:00 -05:00
committed by Viktor Dukhovni
parent e0a1f54070
commit 196cfcd300
85 changed files with 1497 additions and 583 deletions

1
postfix/.indent.pro vendored
View File

@@ -153,6 +153,7 @@
-TSMTPD_RBL_STATE
-TSMTPD_STATE
-TSMTPD_TOKEN
-TSMTPD_XCLIENT_ATTR
-TSMTP_ADDR
-TSMTP_CMD
-TSMTP_RESP

View File

@@ -8755,6 +8755,39 @@ Apologies for any names omitted.
controls periodic logging of maximal connection counts or
rates. The default logging interval is 10 minutes.
Feature: "make makefiles WARN=stuff..." overrides the
built-in GCC warning options that are used when "make" is
invoked from within a source subdirectory. Files: makedefs,
*/Makefile.in.
20031125
Feature: qmgr logs "queueid: deleted", just like postsuper,
when it removes a message from the mail queue.
Performance: smtpd connects to the cleanup or proxy server
AFTER the first valid RCPT TO command, instead of after
the first valid MAIL FROM command. This avoid wasting
real-time proxy filter resources when mail is stopped by
the SMTP server's access blocks. File: smtpd/smtpd.c.
20031126
Bugfix: "panic: mymalloc: requested length 0" when master.cf
specified an invalid host name or address. Postfix now
logs more specific information. File: master/master_ent.c.
Reported by several people.
20031125-8
Feature: XCLIENT support to override the SMTP server's
client information for logging and/or access control. This
replaces the short-lived XADDR and XLOGINFO extensions.
Based on code by Victor Duchovni, with major simplifications.
Files: smtpd/{smtpd,smtpd_check,smtpd_proxy,smtpd_xclient}.c
smtp/smtp_smtp_proto.c, *qmgr/qmgr_message.c,
global/deliver_request.c.
Open problems:
High: when virtual aliasing is turned off after content

View File

@@ -9,7 +9,9 @@ normal mail, but are discarded instead of being deferred or bounced.
The same technique may be useful to block mail for undeliverable
recipients, for example on mail relay hosts that do not have a copy
of all the relayed recipient addresses.
of all the relayed recipient addresses. This prevents undeliverable
junk mail from entering the queue, so that Postfix doesn't have to
waste resources trying to send mailer-daemon messages back.
With address verification turned on, normal mail will suffer only
a short delay of up to 6 seconds while an address is verified for
@@ -95,6 +97,8 @@ specific domains that often appear in forged email.
/etc/postfix/main.cf:
smtpd_sender_restrictions = hash:/etc/postfix/sender_access
unverified_sender_reject_code = 550
# Be sure to read the "Caching" section below!
address_verify_map = btree:/var/mta/verify
/etc/postfix/sender_access:
aol.com reject_unverified_sender
@@ -120,6 +124,7 @@ To find out how sender address verification would affect your mail,
specify "warn_if_reject reject_unverified_sender" so that you can
see what mail would be blocked:
/etc/postfix/main.cf:
smtpd_sender_restrictions =
permit_mynetworks
...
@@ -127,6 +132,8 @@ see what mail would be blocked:
reject_unknown_sender_domain
warn_if_reject reject_unverified_sender
...
# Be sure to read the "Caching" section below!
address_verify_map = btree:/var/mta/verify
This is also a good way to populate your cache with address
verification results before you start to actually reject mail.
@@ -160,7 +167,7 @@ Caching
NOTE: By default, address verification information is not stored
in a persistent file. You have to specify one in main.cf (see
below). Persistent storage is off by default because it may need
more disk space than is available in your root file system.
more disk space than is available in your file system.
Address verification information is cached by the Postfix verify
daemon. Postfix has a bunch of parameters that control the caching
@@ -173,9 +180,9 @@ verification results. If you don't specify a file, all address
verification information is lost after "postfix reload" or "postfix
stop".
If your root file system has sufficient space, try:
If your /var file system has sufficient space, try:
address_verify_map = btree:/etc/postfix/verify
address_verify_map = btree:/var/mta/verify
NOTE: Do not put this file in a file system that fills up. When
the address verification table gets corrupted the world comes to
@@ -197,8 +204,8 @@ accepted) and for negative results (address was rejected).
Right now, no tools are provided to manage the address verification
database. If the file gets too big, or if it gets corrupted, you
can manually delete the file and run "postfix reload". The new
verify daemon process will then create a new, empty, database.
can manually rename or delete the file and run "postfix reload".
The new verify daemon process will then create a new database.
Controlling the routing of address verification probes
======================================================
@@ -249,6 +256,7 @@ for address verification probes and leave everything else alone:
/etc/postfix/main.cf:
relayhost = $mydomain
address_verify_relayhost =
...
Sites behind an address translation relay might have to use a
different SMTP client that sends the correct hostname information:

View File

@@ -233,12 +233,19 @@ one would set up the service in the Postfix master.cf file:
/etc/postfix/master.cf:
scan unix - - n - 10 smtp
# -o smtp_send_xclient_command=yes
Instead of a limit of 10 concurrent processes, use whatever process
limit is feasible for your machine. Content inspection software
can gobble up a lot of system resources, so you don't want to have
too much of it running at the same time.
Uncomment (but keep the leading white-space) the option setting:
"smtp_send_xclient_command=yes", if you would like the scan transport
to forward the original client name and IP address to the backend smtpd
so that mail transaction logs show the real client name IP address.
See sample-smtp.cf and smtp(8).
The content filter can be set up with the Postfix spawn service,
which is the Postfix equivalent of inetd. For example, to instantiate
up to 10 content filtering processes on demand:

View File

@@ -68,7 +68,7 @@ How Postfix talks to the before-queue content filter
The before-filter Postfix SMTP server connects to the content
filter, delivers one message, and disconnects. While sending mail
into the content filter, Postfix speaks ESMTP but uses no command
pipelining. Postfix generates its own EHLO, XLOGINFO (for logging
pipelining. Postfix generates its own EHLO, XCLIENT (for logging
the remote client IP address instead of localhost[127.0.0.1]), DATA
and QUIT commands, and forwards unmodified copies of all the MAIL
FROM and RCPT TO commands that the before-filter Postfix SMTP server
@@ -85,6 +85,9 @@ the connection with the after-filter Postfix SMTP server without
completing the SMTP conversation with the after-filter Postfix SMTP
server.
More details on the postfix-to-proxy interaction is at the end of
this document, in the section titled "Transparency".
Configuration parameters
========================
@@ -119,7 +122,7 @@ for testing, of course.
smtp inet n - n - - smtpd
-o smtpd_proxy_filter=26
:26 inet n - n - - smtpd
-o smtpd_authorized_xloginfo_clients=127.0.0.0/8
-o smtpd_authorized_xclient_hosts=127.0.0.0/8
-o smtpd_client_restrictions=
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
@@ -132,10 +135,10 @@ Note: do not specify spaces around the "=" or "," characters.
The ":26" causes Postfix to listen on the localhost address only.
DO NOT expose the secondary SMTP server to the Internet :-)
The smtpd_authorized_xloginfo_clients parameter allows the before
filter SMTP server to pass the remote SMTP client name and address
to the after-filter SMTP server, so that the after-filter Postfix
daemons log the remote client name and address instead of logging
The smtpd_authorized_xclient_hosts parameter allows the before
filter SMTP server to forward remote SMTP client information to
the after-filter SMTP server, so that the after-filter Postfix
daemons log the remote SMTP client information instead of logging
localhost[127.0.0.1].
The other parameter settings avoid duplication of effort that is
@@ -149,3 +152,36 @@ This configuration is sufficient for stress testing.
Other suggestions for test configurations: use the Postfix smtp-sink
command as the proxy, or something as basic as netcat.
Transparency
============
The before-filter Postfix SMTP server forwards the MAIL FROM, RCPT
TO and DATA commands that it has approved, but it does not forward
other commands such as TLS or SASL commands. It can therefore not
be transparent.
The real-time content filter, on the other hand, has to be transparent.
In order to support non-transparent real-time content filters,
Postfix would have to reconcile the before-filter Postfix ESMTP
feature set with the feature set that Postfix receives from the
real-time content filter.
- When a future Postfix version supports DSN, but the content filter
does not announce DSN support in the EHLO reply, then the before-filter
SMTP server would have to either 1) suppress the DSN feature in
its EHLO announcement, or 2) duplicate all the work that needs to
be done when delivering DSN-aware mail to a non-DSN destination.
- When the content filter does not announce 8BITMIME support in
the EHLO reply, then the before-filter SMTP server would have to
either 1) suppress the 8BITMIME feature in its EHLO announcement,
or 2) convert the content to quoted-printable before giving it to
the content filter.
- Performance: when Postfix has to suppress elements from the
before-filter EHLO reply because they are incompatible with the
real-time content filter, then Postfix has to connect to the content
filter as soon as the client sends a valid EHLO command. This wastes
a lot of resources when all the MAIL FROM or RCPT TO commands are
rejected.

View File

@@ -0,0 +1,185 @@
Purpose of the XCLIENT extension to SMTP
========================================
The XCLIENT command targets problems in the following areas:
1 - Access control tests. SMTP server access rules are difficult
to verify when decisions can be triggered only by remote clients.
In order to facilitate access rule testing, an SMTP client test
program needs the ability to override the SMTP server's idea of
the SMTP client hostname, network address, and other information.
2 - Logging after content filter. With Internet->MTA1->filter->MTA2
style content filter applications, remote client information is
lost when MTA1 gives the mail to the content filter. This complicates
the interpretation of the audit trail. In order maintain audit
trail continuity, MTA1 needs the ability to forward client information
through the content filter to MTA2.
3 - Post-filter access control and logging. With Internet->filter->MTA
style content filter applications, the content filter can be greatly
simplified if it can delegate all decisions concerning mail relay
and other access control to the MTA. This requires that the filter
can forward client information to the MTA for access control
purposes.
The preceding suggests that there is a need for two modes of
operation:
- Operation mode 1: override the SMTP server's idea of SMTP
client information for access control and audit trail purposes.
Attributes that one may want to override are:
client network address
client hostname
hostname lookup failure type (permanent or temporary)
client protocol (e.g., SMTP or ESMTP)
- Operation mode 2: forward remote client information for audit
trail purposes only. Examples of attributes are:
client network address
client hostname
client protocol (e.g., SMTP or ESMTP)
client SMTP HELO parameter
General XCLIENT command syntax
==============================
The XCLIENT command maintains one set of attributes with surrogate
client information. The general XCLIENT command syntax is described
below. Upper case and quoted strings specify terminals, lowercase
strings specify meta terminals, SP is whitespace, and descriptive
text is in {}. Although shown below in upper case, command and
attribute names are in fact case insensitive.
xclient-command = XCLIENT *( SP argument )
argument = ( request | attribute )
request = ( RST | ACL | LOG )
attribute = name"="value
name = ( CLIENT_NAME | CLIENT_ADDR | CLIENT_CODE | PROTOCOL | HELO_NAME )
value = ( { empty } | xtext )
xtext = { attribute value encoded as per RFC 1891 }
The XCLIENT command is typically sent immediately before or after
the EHLO command, may be pipelined after the server announces ESMTP
pipelining support, and must not be used in the middle of an SMTP
transaction (i.e. between MAIL and DOT).
The server reply codes are as follows:
Code | Meaning
-----|------------
250 | success
501 | command syntax error
502 | unrecognized request name
503 | command out of order (name=value without prior ACL or LOG request)
421 | unable to proceed
The server must report success in case of an unrecognized attribute
name, although it may log a warning.
Specific XCLIENT usage scenarios
================================
This section discusses the semantics of XCLIENT requests. Specific
syntax information is given in the next section.
The RST request resets all XCLIENT attributes and disables any
override of access control or audit trail attributes. Example:
XCLIENT RST
The ACL request resets all XCLIENT attributes and must be specified
before sending surrogate attributes for access control and audit
trail purposes. Attributes that are not explicitly specified will
default to their actual value. Example:
XCLIENT ACL CLIENT_NAME=spike.porcupine.org
XCLIENT CLIENT_ADDR=168.100.189.2
This overrides only the client hostname and network address, but
none of the other client attributes.
The LOG request resets all XCLIENT attributes and must be specified
before sending surrogate attributes for audit trail purposes.
Attributes that are not explicitly specified will default to the
unknown value. Example:
XCLIENT LOG CLIENT_NAME=spike.porcupine.org CLIENT_ADDR=168.100.189.2
XCLIENT HELO_NAME=spike.porcupine.org PROTOCOL=ESMTP
This overrides all client attributes that are defined in this
document, leaving none at their default unknown value.
Note 1: it is an error to specify name=value pairs without prior
ACL or LOG request.
Note 2: after an ACL or LOG request, attributes specified with
successive XCLIENT commands accumulate until the next RST, ACL or
LOG request.
Note 3: if one XCLIENT command specifies multiple requests (e.g.,
both ACL and LOG), only the last request takes effect.
XCLIENT attribute value details
===============================
Attribute values are encoded as RFC 1891 xtext strings. To explicitly
specify that an attribute value is unknown, the value must be empty;
the client is not allowed to send its own internal representation
for unknown information.
CLIENT_CODE specifies CLIENT_NAME hostname lookup status information.
Values are OK (success), TEMP (temporary lookup failure) or PERM
(permanent lookup failure). When CLIENT_CODE is set to any value
other than OK, the CLIENT_NAME attribute is set to the unknown
value.
CLIENT_NAME should specify a syntactically valid domain name and
not a numerical address. When a null client name is specified
(i.e. the client name is unknown), the CLIENT_CODE attribute is
set to PERM. When a valid domain name is specified, CLIENT_CODE is
set to OK. The server may process a syntactically invalid domain
name as if it were unknown.
CLIENT_ADDR must specify a numerical network address without [].
PROTOCOL is a string of up to 64 printable characters.
HELO_NAME should be a syntactically valid domain name.
Note 4: syntactically valid CLIENT_NAME and HELO_NAME attributes
can be up to 255 characters long. The client must not send XCLIENT
commands that exceed the 512 character limit of SMTP commands.
Note 5: attribute values may end up in Received: or other message
headers. The server may substitute any characters that are special
according to RFC 822 or RFC 2822.
Security
========
The XCLIENT command changes audit trails and changes client access
permissions. For these reasons, use of the XCLIENT command must be
restricted to authorized clients only.
The examples in this document assume that XCLIENT does not override
its own access control mechanism.
SMTP connection caching
=======================
SMTP connection caching makes it possible to deliver multiple
messages within the same SMTP session. Thus, one persistent SMTP
session with a content filter can carry messages from unrelated
clients. Attributes from one remote client should not affect the
delivery of mail from a different remote client. In order to
prevent such information leakage, use the XCLIENT RST, ACL or LOG
requests as appropriate.

View File

@@ -76,6 +76,17 @@ smtp_never_send_ehlo = no
#
smtp_defer_if_no_mx_address_found = no
# The smtp_send_xclient_command parameter controls whether the Postfix
# SMTP client will send an XCLIENT command to the SMTP server, when
# the ESMTP HELO response of the remote host indicates XCLIENT support.
# This allows an "smtp" delivery agent, used for content filter
# message injection, to forward the name, address, protocol and HELO
# name of the original client to the content filter and downstream
# queuing SMTP server. Before you change the value to yes, it is best
# to make sure your content filter supports this command.
#
smtp_send_xclient_command = no
# The smtp_line_length_limit parameter controls the length of
# message header and body lines that Postfix will send via SMTP.
# Lines that are longer are broken by inserting <CR> <LF> <SPACE>.

View File

@@ -154,13 +154,14 @@ smtpd_client_connection_limit_exceptions = $mynetworks
#
#disable_vrfy_command = no
# The smtpd_authorized_xaddr_clients parameter specifies what clients
# are allowed to specify the SMTP "XADDR client-address client-name"
# command. This command changes Postfix's idea of the client hostname
# and IP address for logging and for access control. Typical use is
# for SMTPD access testing.
# The smtpd_authorized_xclient_hosts parameter specifies what clients
# are allowed to specify the XCLIENT extension to SMTP.
#
# By default, no clients are allowed to specify XADDR.
# This command overrides SMTP client information that is used for
# logging or access control. Typical use is for SMTP-based content
# filters or for SMTP server access rule testing.
#
# By default, no clients are allowed to specify XCLIENT.
#
# Specify an explicit list of network/netmask patterns, where the
# mask specifies the number of bits in the network part of a host
@@ -171,26 +172,7 @@ smtpd_client_connection_limit_exceptions = $mynetworks
# of listing the patterns here. Specify type:table for table-based lookups
# (the value on the table right-hand side is not used).
#
smtpd_authorized_xaddr_clients =
# The smtpd_authorized_xloginfo_clients parameter specifies what
# clients are allowed to specify the SMTP "XLOGINFO client-address
# client-name" command. This command changes Postfix's idea of the
# client hostname and IP address for logging but not for access
# control. Typical use is for SMTP-based content filters.
#
# By default, no clients are allowed to specify XLOGINFO.
#
# Specify an explicit list of network/netmask patterns, where the
# mask specifies the number of bits in the network part of a host
# address. You can also specify hostnames or .domain names (the
# initial dot causes the domain to match any name below it).
#
# You can also specify the absolute pathname of a pattern file instead
# of listing the patterns here. Specify type:table for table-based lookups
# (the value on the table right-hand side is not used).
#
smtpd_authorized_xloginfo_clients =
smtpd_authorized_xclient_hosts =
# The smtpd_authorized_verp_clients parameter specifies what clients
# are allowed to specify the SMTP XVERP command. This command requests

View File

@@ -249,6 +249,10 @@ SMTP(8) SMTP(8)
Timeout for sending the <b>HELO</b> command, and for
receiving the server response.
<b>smtp_xclient_timeout</b>
Timeout for sending the <b>XCLIENT</b> command, and for
receiving the server response.
<b>smtp_mail_timeout</b>
Timeout for sending the <b>MAIL FROM</b> command, and for
receiving the server response.
@@ -277,6 +281,13 @@ SMTP(8) SMTP(8)
keep trying until a suitable MX host resolves or
until the mail is too old.
<b>smtp_send_xclient_command</b>
If the SMTP server announces XCLIENT support, send
the name, address, protocol and HELO name of the
original client. This can be used to forward client
information through a content filter to a down-
stream queuing SMTP server.
<b>smtp_rset_timeout</b>
Timeout for sending the <b>RSET</b> command.

View File

@@ -170,23 +170,13 @@ SMTPD(8) SMTPD(8)
Hostnames, domain names and/or addresses of clients
that are authorized to use the XVERP extension.
<b>smtpd_authorized_xaddr_clients</b>
<b>smtpd_authorized_xclient_hosts</b>
Hostnames, domain names and/or addresses of clients
that are authorized to use the "XADDR client-
address client-name" command. This changes Post-
fix's idea of the SMTP client IP address and host-
name for access control and for logging purposes.
<b>smtpd_authorized_xloginfo_clients</b>
Hostnames, domain names and/or addresses of clients
that are authorized to use the "XLOGINFO client-
address client-name" command. This changes the
client name and address that are used for logging,
without affecting the client IP address and host-
name that are used for access control. XLOGINFO is
typically used to propagate remote client informa-
tion through an SMTP-based content filter to the
after-filter SMTP server.
that are authorized to use the XCLIENT command.
This command changes client information for access
control and/or logging purposes, with the exception
of the <b>smtpd_authorized_xclient_hosts</b> access con-
trol itself.
<b>debug_peer_level</b>
Increment in verbose logging level when a remote

View File

@@ -6,7 +6,7 @@
# SUMMARY
# makefile configuration utility
# SYNOPSIS
# \fBmakedefs\fR
# \fBmake makefiles \fIname=value...\fR
# DESCRIPTION
# The \fBmakedefs\fR command identifies the program compilation
# environment, and emits macro definitions on the standard output
@@ -29,6 +29,9 @@
# .IP \fBOPT=\fIoptimization_level\fR
# Specifies a non-default optimization level. The default is \fB-O\fR.
# Specify \fBOPT=\fR to turn off optimization.
# .IP \fBWARN=\fIwarning_flags\fR
# Specifies non-default gcc compiler warning options for use when
# "make" is invoked in a source subdirectory only.
# LICENSE
# .ad
# .fi
@@ -320,7 +323,10 @@ case "$CC" in
*) : ${OPT='-O'};;
esac
: ${CC='gcc $(WARN)'} ${OPT='-O'} ${DEBUG='-g'} ${AWK=awk}
: ${CC='gcc $(WARN)'} ${OPT='-O'} ${DEBUG='-g'} ${AWK=awk} \
${WARN='-W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused'}
export SYSTYPE AR ARFL RANLIB SYSLIBS CC OPT DEBUG AWK OPTS
@@ -336,4 +342,5 @@ DEBUG = $DEBUG
AWK = $AWK
STRCASE = $STRCASE
EXPORT = AUXLIBS='$AUXLIBS' CCARGS='$CCARGS' OPT='$OPT' DEBUG='$DEBUG'
WARN = $WARN
EOF

View File

@@ -210,6 +210,9 @@ exchanger list.
.IP \fBsmtp_helo_timeout\fR
Timeout for sending the \fBHELO\fR command, and for
receiving the server response.
.IP \fBsmtp_xclient_timeout\fR
Timeout for sending the \fBXCLIENT\fR command, and for
receiving the server response.
.IP \fBsmtp_mail_timeout\fR
Timeout for sending the \fBMAIL FROM\fR command, and for
receiving the server response.
@@ -231,6 +234,11 @@ If no, bounce mail when no MX host resolves to an address
than the local MTA).
If yes, keep trying until a suitable MX host resolves or until
the mail is too old.
.IP \fBsmtp_send_xclient_command\fR
If the SMTP server announces XCLIENT support, send the name,
address, protocol and HELO name of the original client. This
can be used to forward client information through a content
filter to a downstream queuing SMTP server.
.IP \fBsmtp_rset_timeout\fR
Timeout for sending the \fBRSET\fR command.
.IP \fBsmtp_quit_timeout\fR

View File

@@ -157,20 +157,12 @@ anti-spoofing restriction.
.IP \fBsmtpd_authorized_verp_clients\fR
Hostnames, domain names and/or addresses of clients that are
authorized to use the XVERP extension.
.IP \fBsmtpd_authorized_xaddr_clients\fR
.IP \fBsmtpd_authorized_xclient_hosts\fR
Hostnames, domain names and/or addresses of clients that are
authorized to use the "XADDR client-address client-name" command.
This changes Postfix's
idea of the SMTP client IP address and hostname for access
control and for logging purposes.
.IP \fBsmtpd_authorized_xloginfo_clients\fR
Hostnames, domain names and/or addresses of clients that are
authorized to use the "XLOGINFO client-address client-name" command.
This changes the client
name and address that are used for logging, without affecting the
client IP address and hostname that are used for access control.
XLOGINFO is typically used to propagate remote client information
through an SMTP-based content filter to the after-filter SMTP server.
authorized to use the XCLIENT command. This command changes
client information for access control and/or logging purposes,
with the exception of the
\fBsmtpd_authorized_xclient_hosts\fR access control itself.
.IP \fBdebug_peer_level\fR
Increment in verbose logging level when a remote host matches a
pattern in the \fBdebug_peer_list\fR parameter.

View File

@@ -3,9 +3,6 @@ SRCS = anvil.c
OBJS = anvil.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -7,9 +7,6 @@ OBJS = bounce.o bounce_append_service.o bounce_notify_service.o \
bounce_one_service.o bounce_warn_service.o bounce_trace_service.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -11,9 +11,6 @@ OBJS = cleanup.o cleanup_out.o cleanup_envelope.o cleanup_message.o \
cleanup_addr.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG= cleanup_masquerade

View File

@@ -3,9 +3,6 @@ SRCS = dns_lookup.c dns_rr.c dns_strerror.c dns_strtype.c
OBJS = dns_lookup.o dns_rr.o dns_strerror.o dns_strtype.o
HDRS = dns.h
TESTSRC = test_dns_lookup.c test_alias_token.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
INCL =

View File

@@ -3,9 +3,6 @@ SRCS = error.c
OBJS = error.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -3,9 +3,6 @@ SRCS = flush.c
OBJS = flush.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -3,9 +3,6 @@ SRCS = fsstone.c
OBJS = fsstone.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -68,9 +68,6 @@ HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
trace.h log_adhoc.h verify.h dict_proxy.h mail_dict.h qmgr_user.h \
input_transp.h anvil_clnt.h
TESTSRC = rec2stream.c stream2rec.c recdump.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
INCL =

View File

@@ -22,6 +22,10 @@
/* long arrival_time;
/* RECIPIENT_LIST rcpt_list;
/* char *hop_status;
/* char *client_name;
/* char *client_addr;
/* char *client_proto;
/* char *client_helo;
/* .in -5
/* } DELIVER_REQUEST;
/*
@@ -175,6 +179,10 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
static VSTRING *address;
static VSTRING *errors_to;
static VSTRING *return_receipt;
static VSTRING *client_name;
static VSTRING *client_addr;
static VSTRING *client_proto;
static VSTRING *client_helo;
long offset;
/*
@@ -191,6 +199,10 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
address = vstring_alloc(10);
errors_to = vstring_alloc(10);
return_receipt = vstring_alloc(10);
client_name = vstring_alloc(10);
client_addr = vstring_alloc(10);
client_proto = vstring_alloc(10);
client_helo = vstring_alloc(10);
}
/*
@@ -209,7 +221,11 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
ATTR_TYPE_STR, MAIL_ATTR_ERRTO, errors_to,
ATTR_TYPE_STR, MAIL_ATTR_RRCPT, return_receipt,
ATTR_TYPE_LONG, MAIL_ATTR_TIME, &request->arrival_time,
ATTR_TYPE_END) != 11) {
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, client_name,
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, client_addr,
ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, client_proto,
ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME, client_helo,
ATTR_TYPE_END) != 15) {
msg_warn("%s: error receiving common attributes", myname);
return (-1);
}
@@ -224,6 +240,10 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
request->sender = mystrdup(vstring_str(address));
request->errors_to = mystrdup(vstring_str(errors_to));
request->return_receipt = mystrdup(vstring_str(return_receipt));
request->client_name = mystrdup(vstring_str(client_name));
request->client_addr = mystrdup(vstring_str(client_addr));
request->client_proto = mystrdup(vstring_str(client_proto));
request->client_helo = mystrdup(vstring_str(client_helo));
/*
* Extract the recipient offset and address list. Skip over any
@@ -298,6 +318,10 @@ static DELIVER_REQUEST *deliver_request_alloc(void)
request->data_size = 0;
recipient_list_init(&request->rcpt_list);
request->hop_status = 0;
request->client_name = 0;
request->client_addr = 0;
request->client_proto = 0;
request->client_helo = 0;
return (request);
}
@@ -324,6 +348,14 @@ static void deliver_request_free(DELIVER_REQUEST *request)
recipient_list_free(&request->rcpt_list);
if (request->hop_status)
myfree(request->hop_status);
if (request->client_name)
myfree(request->client_name);
if (request->client_addr)
myfree(request->client_addr);
if (request->client_proto)
myfree(request->client_proto);
if (request->client_helo)
myfree(request->client_helo);
myfree((char *) request);
}

View File

@@ -40,6 +40,10 @@ typedef struct DELIVER_REQUEST {
long arrival_time; /* arrival time */
RECIPIENT_LIST rcpt_list; /* envelope recipients */
char *hop_status; /* reason if unavailable */
char *client_name; /* client hostname */
char *client_addr; /* client address */
char *client_proto; /* client protocol */
char *client_helo; /* helo parameter */
} DELIVER_REQUEST;
#define DEL_REQ_FLAG_DEFLT (DEL_REQ_FLAG_SUCCESS | DEL_REQ_FLAG_BOUNCE)

View File

@@ -753,6 +753,10 @@ extern int var_smtp_conn_tmout;
#define DEF_SMTP_HELO_TMOUT "300s"
extern int var_smtp_helo_tmout;
#define VAR_SMTP_XCLNT_TMOUT "smtp_xclient_timeout"
#define DEF_SMTP_XCLNT_TMOUT "300s"
extern int var_smtp_xclnt_tmout;
#define VAR_SMTP_MAIL_TMOUT "smtp_mail_timeout"
#define DEF_SMTP_MAIL_TMOUT "300s"
extern int var_smtp_mail_tmout;
@@ -841,6 +845,10 @@ extern int var_smtp_pix_delay;
#define DEF_SMTP_DEFER_MXADDR 0
extern bool var_smtp_defer_mxaddr;
#define VAR_SMTP_SEND_XCLIENT "smtp_send_xclient_command"
#define DEF_SMTP_SEND_XCLIENT 0
extern bool var_smtp_send_xclient;
/*
* SMTP server. The soft error limit determines how many errors an SMTP
* client may make before we start to slow down; the hard error limit
@@ -1567,15 +1575,11 @@ extern bool var_verp_bounce_off;
extern char *var_verp_clients;
/*
* XADDR.
* XCLIENT, for rule testing and improved post-filter logging.
*/
#define VAR_XADDR_CLIENTS "smtpd_authorized_xaddr_clients"
#define DEF_XADDR_CLIENTS ""
extern char *var_xaddr_clients;
#define VAR_XLOGINFO_CLIENTS "smtpd_authorized_xloginfo_clients"
#define DEF_XLOGINFO_CLIENTS ""
extern char *var_xloginfo_clients;
#define VAR_XCLIENT_HOSTS "smtpd_authorized_xclient_hosts"
#define DEF_XCLIENT_HOSTS ""
extern char *var_xclient_hosts;
/*
* Inbound mail flow control. This allows for a stiffer coupling between

View File

@@ -15,6 +15,7 @@
* System library.
*/
#include <stdarg.h>
#include <string.h>
/*
* Utility library.
@@ -150,6 +151,24 @@ extern char *mail_pathname(const char *, const char *);
#define MAIL_ATTR_ORG_NONE "unknown" /* origin unknown */
#define MAIL_ATTR_ORG_LOCAL "local" /* local submission */
/*
* Internal forms for unknown XCLIENT information.
*/
#define CLIENT_NAME_UNKNOWN "unknown"
#define CLIENT_ADDR_UNKNOWN "unknown"
#define CLIENT_NAMADDR_UNKNOWN CLIENT_NAME_UNKNOWN "[" CLIENT_ADDR_UNKNOWN "]"
#define HELO_NAME_UNKNOWN "" /* or NULL */
#define PROTOCOL_UNKNOWN "unknown"
/*
* Internal forms: recognizing unknown XCLIENT information.
*/
#define IS_UNK_CLNT_NAME(v) (!(v) || !strcmp((v), CLIENT_NAME_UNKNOWN))
#define IS_UNK_CLNT_ADDR(v) (!(v) || !strcmp((v), CLIENT_ADDR_UNKNOWN))
#define IS_UNK_CLNT_NAMADDR(v) (!(v) || !strcmp((v), CLIENT_NAMADDR_UNKNOWN))
#define IS_UNK_HELO_NAME(v) (!(v) || !*(v))
#define IS_UNK_PROTOCOL(v) (!(v) || !strcmp((v), PROTOCOL_UNKNOWN))
/* LICENSE
/* .ad
/* .fi

View File

@@ -84,6 +84,7 @@
#include <unistd.h>
#include <errno.h>
#include <utime.h>
#include <string.h>
/* Utility library. */

View File

@@ -20,7 +20,7 @@
* Patches change the patchlevel and the release date. Snapshots change the
* release date only, unless they include the same bugfix as a patch release.
*/
#define MAIL_RELEASE_DATE "20031113"
#define MAIL_RELEASE_DATE "20031128"
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "2.0.16-" MAIL_RELEASE_DATE

View File

@@ -387,7 +387,7 @@ static MIME_ENCODING mime_encoding_map[] = { /* RFC 2045 */
* Outputs and state changes are interleaved, so we must maintain separate
* offsets for header and body segments.
*/
#define HEAD_OUT(ptr, info) do { \
#define HEAD_OUT(ptr, info, len) do { \
(ptr)->head_out((ptr)->app_context, (ptr)->curr_state, \
(info), (ptr)->output_buffer, (ptr)->head_offset); \
(ptr)->head_offset += (len) + 1; \
@@ -805,7 +805,7 @@ int mime_state_update(MIME_STATE *state, int rec_type,
|| header_info->type != HDR_CONTENT_TRANSFER_ENCODING
|| (state->static_flags & MIME_OPT_DOWNGRADE) == 0
|| state->curr_domain == MIME_ENC_7BIT)
HEAD_OUT(state, header_info);
HEAD_OUT(state, header_info, len);
state->prev_rec_type = 0;
VSTRING_RESET(state->output_buffer);
}
@@ -855,7 +855,7 @@ int mime_state_update(MIME_STATE *state, int rec_type,
cp = CU_CHAR_PTR("quoted-printable");
vstring_sprintf(state->output_buffer,
"Content-Transfer-Encoding: %s", cp);
HEAD_OUT(state, (HEADER_OPTS *) 0);
HEAD_OUT(state, (HEADER_OPTS *) 0, len);
VSTRING_RESET(state->output_buffer);
}

View File

@@ -182,6 +182,7 @@ VSTRING *rewrite_clnt_internal(const char *ruleset, const char *addr, VSTRING *r
#include <stdlib.h>
#include <string.h>
#include <msg_vstream.h>
#include <split_at.h>
#include <vstring_vstream.h>
#include <mail_conf.h>
#include <mail_params.h>
@@ -237,8 +238,8 @@ int main(int argc, char **argv)
VSTRING *buffer = vstring_alloc(1);
while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
if ((rule = strtok(STR(buffer), " \t,")) == 0
|| (addr = strtok((char *) 0, " \t,")) == 0)
if ((addr = split_at(STR(buffer), ' ')) == 0
|| *(rule = STR(buffer)) == 0)
usage(argv[0]);
rewrite(rule, addr, reply);
}

View File

@@ -2,7 +2,7 @@
/* NAME
/* xtext 3
/* SUMMARY
/* quote/unquote text, HTTP style.
/* quote/unquote text, xtext style.
/* SYNOPSIS
/* #include <xtext.h>
/*
@@ -11,6 +11,10 @@
/* const char *unquoted;
/* const char *special;
/*
/* VSTRING *xtext_unquote_append(unquoted, quoted)
/* VSTRING *unquoted;
/* const char *quoted;
/*
/* VSTRING *xtext_unquote(unquoted, quoted)
/* VSTRING *unquoted;
/* const char *quoted;
@@ -19,6 +23,9 @@
/* +, <33(10) and >126(10), as well as characters specified with "special"
/* by +XX, XX being the two-digit uppercase hexadecimal equivalent.
/*
/* xtext_quote_append() is like xtext_quote(), but appends the conversion
/* result to the result buffer.
/*
/* xtext_unquote() performs the opposite transformation. This function
/* understands lowercase, uppercase, and mixed case +XX sequences. The
/* result value is the unquoted argument in case of success, a null pointer
@@ -53,16 +60,17 @@
#define STR(x) vstring_str(x)
#define LEN(x) VSTRING_LEN(x)
/* xtext_quote - unquoted data to quoted */
/* xtext_quote_append - append unquoted data to quoted data */
VSTRING *xtext_quote(VSTRING *quoted, const char *unquoted, const char *special)
VSTRING *xtext_quote_append(VSTRING *quoted, const char *unquoted,
const char *special)
{
const char *cp;
int ch;
VSTRING_RESET(quoted);
for (cp = unquoted; (ch = *(unsigned const char *) cp) != 0; cp++) {
if (ch != '+' && ch > 32 && ch < 127 && strchr(special, ch) == 0) {
if (ch != '+' && ch > 32 && ch < 127
&& (*special == 0 || strchr(special, ch) == 0)) {
VSTRING_ADDCH(quoted, ch);
} else {
vstring_sprintf_append(quoted, "+%02X", ch);
@@ -72,6 +80,15 @@ VSTRING *xtext_quote(VSTRING *quoted, const char *unquoted, const char *special)
return (quoted);
}
/* xtext_quote - unquoted data to quoted */
VSTRING *xtext_quote(VSTRING *quoted, const char *unquoted, const char *special)
{
VSTRING_RESET(quoted);
xtext_quote_append(quoted, unquoted, special);
return (quoted);
}
/* xtext_unquote - quoted data to unquoted */
VSTRING *xtext_unquote(VSTRING *unquoted, const char *quoted)

View File

@@ -20,6 +20,7 @@
* External interface.
*/
extern VSTRING *xtext_quote(VSTRING *, const char *, const char *);
extern VSTRING *xtext_quote_append(VSTRING *, const char *, const char *);
extern VSTRING *xtext_unquote(VSTRING *, const char *);
/* LICENSE

View File

@@ -7,9 +7,6 @@ OBJS = lmtp.o lmtp_connect.o lmtp_proto.o lmtp_chat.o lmtp_session.o \
lmtp_sasl_proto.o
HDRS = lmtp.h
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -9,9 +9,6 @@ OBJS = alias.o command.o delivered.o dotforward.o file.o forward.o \
local_expand.o
HDRS = local.h
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
PROG = local

View File

@@ -10,9 +10,6 @@ LIB_OBJ = single_server.o multi_server.o trigger_server.o master_proto.o \
mail_flow.o
HDRS = mail_server.h master_proto.h mail_flow.h
INT_HDR = master.h
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
LIB = libmaster.a

View File

@@ -303,7 +303,9 @@ MASTER_SERV *get_master_ent()
MASTER_INET_ADDRLIST(serv) = (INET_ADDR_LIST *)
mymalloc(sizeof(*MASTER_INET_ADDRLIST(serv)));
inet_addr_list_init(MASTER_INET_ADDRLIST(serv));
inet_addr_host(MASTER_INET_ADDRLIST(serv), host);
if (inet_addr_host(MASTER_INET_ADDRLIST(serv), host) == 0)
msg_fatal("%s: line %d: bad hostname or network address: %s",
VSTREAM_PATH(master_fp), master_line, host);
inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv));
serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
} else if (strcasecmp(saved_interfaces, DEF_INET_INTERFACES) == 0) {

View File

@@ -9,9 +9,6 @@ OBJS = qmgr.o qmgr_active.o qmgr_transport.o qmgr_queue.o qmgr_entry.o \
qmgr_defer.o qmgr_enable.o qmgr_scan.o qmgr_bounce.o
HDRS = qmgr.h
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -276,6 +276,10 @@ struct QMGR_MESSAGE {
char *redirect_addr; /* info@spammer.tld */
long data_size; /* message content size */
long rcpt_offset; /* more recipients here */
char *client_name; /* client hostname */
char *client_addr; /* client address */
char *client_proto; /* client protocol */
char *client_helo; /* helo parameter */
QMGR_RCPT_LIST rcpt_list; /* complete addresses */
int rcpt_count; /* used recipient slots */
int rcpt_limit; /* maximum read in-core */

View File

@@ -489,8 +489,9 @@ static void qmgr_active_done_3_generic(QMGR_MESSAGE *message)
message->queue_id, message->queue_name);
msg_warn("%s: remove %s from %s: %m", myname,
message->queue_id, message->queue_name);
} else if (msg_verbose) {
msg_info("%s: remove %s", myname, message->queue_id);
} else {
/* Same format as logged by postsuper. */
msg_info("%s: removed", message->queue_id);
}
}

View File

@@ -161,6 +161,10 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
ATTR_TYPE_STR, MAIL_ATTR_ERRTO, message->errors_to,
ATTR_TYPE_STR, MAIL_ATTR_RRCPT, message->return_receipt,
ATTR_TYPE_LONG, MAIL_ATTR_TIME, message->arrival_time,
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, message->client_name,
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, message->client_addr,
ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, message->client_proto,
ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME, message->client_helo,
ATTR_TYPE_END);
if (sender_buf != 0)
vstring_free(sender_buf);

View File

@@ -168,6 +168,10 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
message->warn_time = 0;
message->rcpt_offset = 0;
message->verp_delims = 0;
message->client_name = 0;
message->client_addr = 0;
message->client_proto = 0;
message->client_helo = 0;
qmgr_rcpt_list_init(&message->rcpt_list);
message->rcpt_count = 0;
message->rcpt_limit = var_qmgr_msg_rcpt_limit;
@@ -525,6 +529,27 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
myfree(message->encoding);
message->encoding = mystrdup(value);
}
/* Original client attributes. */
if (strcmp(name, MAIL_ATTR_CLIENT_NAME) == 0) {
if (message->client_name != 0)
myfree(message->client_name);
message->client_name = mystrdup(value);
}
if (strcmp(name, MAIL_ATTR_CLIENT_ADDR) == 0) {
if (message->client_addr != 0)
myfree(message->client_addr);
message->client_addr = mystrdup(value);
}
if (strcmp(name, MAIL_ATTR_PROTO_NAME) == 0) {
if (message->client_proto != 0)
myfree(message->client_proto);
message->client_proto = mystrdup(value);
}
if (strcmp(name, MAIL_ATTR_HELO_NAME) == 0) {
if (message->client_helo != 0)
myfree(message->client_helo);
message->client_helo = mystrdup(value);
}
/* Optional tracing flags. */
else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
@@ -586,6 +611,14 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
message->return_receipt = mystrdup("");
if (message->encoding == 0)
message->encoding = mystrdup(MAIL_ATTR_ENC_NONE);
if (message->client_name == 0)
message->client_name = mystrdup(CLIENT_NAME_UNKNOWN);
if (message->client_addr == 0)
message->client_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
if (message->client_proto == 0)
message->client_proto = mystrdup(PROTOCOL_UNKNOWN);
if (message->client_helo == 0)
message->client_helo = mystrdup(HELO_NAME_UNKNOWN);
/*
* Clean up.

View File

@@ -3,9 +3,6 @@ SRCS = pickup.c
OBJS = pickup.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -3,9 +3,6 @@ SRCS = pipe.c
OBJS = pipe.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -3,9 +3,6 @@ SRCS = postalias.c
OBJS = postalias.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -3,9 +3,6 @@ SRCS = postcat.c
OBJS = postcat.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -3,9 +3,6 @@ SRCS = postconf.c
OBJS = postconf.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -3,9 +3,6 @@ SRCS = postdrop.c
OBJS = postdrop.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -3,9 +3,6 @@ SRCS = postfix.c
OBJS = postfix.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
FILES = Makefile $(SRCS) $(HDRS)

View File

@@ -3,9 +3,6 @@ SRCS = postkick.c
OBJS = postkick.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -3,9 +3,6 @@ SRCS = postlock.c
OBJS = postlock.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -3,9 +3,6 @@ SRCS = postlog.c
OBJS = postlog.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
FILES = Makefile $(SRCS) $(HDRS)

View File

@@ -3,9 +3,6 @@ SRCS = postmap.c
OBJS = postmap.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -3,9 +3,6 @@ SRCS = postqueue.c
OBJS = postqueue.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -3,9 +3,6 @@ SRCS = postsuper.c
OBJS = postsuper.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -3,9 +3,6 @@ SRCS = proxymap.c
OBJS = proxymap.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -7,9 +7,6 @@ OBJS = qmgr.o qmgr_active.o qmgr_transport.o qmgr_queue.o qmgr_entry.o \
qmgr_defer.o qmgr_enable.o qmgr_scan.o qmgr_bounce.o
HDRS = qmgr.h
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -236,6 +236,10 @@ struct QMGR_MESSAGE {
char *redirect_addr; /* info@spammer.tld */
long data_size; /* message content size */
long rcpt_offset; /* more recipients here */
char *client_name; /* client hostname */
char *client_addr; /* client address */
char *client_proto; /* client protocol */
char *client_helo; /* helo parameter */
QMGR_RCPT_LIST rcpt_list; /* complete addresses */
};

View File

@@ -489,8 +489,9 @@ static void qmgr_active_done_3_generic(QMGR_MESSAGE *message)
message->queue_id, message->queue_name);
msg_warn("%s: remove %s from %s: %m", myname,
message->queue_id, message->queue_name);
} else if (msg_verbose) {
msg_info("%s: remove %s", myname, message->queue_id);
} else {
/* Same format as logged by postsuper. */
msg_info("%s: removed", message->queue_id);
}
}

View File

@@ -156,6 +156,10 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
ATTR_TYPE_STR, MAIL_ATTR_ERRTO, message->errors_to,
ATTR_TYPE_STR, MAIL_ATTR_RRCPT, message->return_receipt,
ATTR_TYPE_LONG, MAIL_ATTR_TIME, message->arrival_time,
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, message->client_name,
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, message->client_addr,
ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, message->client_proto,
ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME, message->client_helo,
ATTR_TYPE_END);
if (sender_buf != 0)
vstring_free(sender_buf);

View File

@@ -158,6 +158,10 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
message->warn_time = 0;
message->rcpt_offset = 0;
message->verp_delims = 0;
message->client_name = 0;
message->client_addr = 0;
message->client_proto = 0;
message->client_helo = 0;
qmgr_rcpt_list_init(&message->rcpt_list);
return (message);
}
@@ -490,6 +494,27 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
myfree(message->encoding);
message->encoding = mystrdup(value);
}
/* Original client attributes. */
if (strcmp(name, MAIL_ATTR_CLIENT_NAME) == 0) {
if (message->client_name != 0)
myfree(message->client_name);
message->client_name = mystrdup(value);
}
if (strcmp(name, MAIL_ATTR_CLIENT_ADDR) == 0) {
if (message->client_addr != 0)
myfree(message->client_addr);
message->client_addr = mystrdup(value);
}
if (strcmp(name, MAIL_ATTR_PROTO_NAME) == 0) {
if (message->client_proto != 0)
myfree(message->client_proto);
message->client_proto = mystrdup(value);
}
if (strcmp(name, MAIL_ATTR_HELO_NAME) == 0) {
if (message->client_helo != 0)
myfree(message->client_helo);
message->client_helo = mystrdup(value);
}
/* Optional tracing flags. */
else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
@@ -551,6 +576,14 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
message->return_receipt = mystrdup("");
if (message->encoding == 0)
message->encoding = mystrdup(MAIL_ATTR_ENC_NONE);
if (message->client_name == 0)
message->client_name = mystrdup(CLIENT_NAME_UNKNOWN);
if (message->client_addr == 0)
message->client_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
if (message->client_proto == 0)
message->client_proto = mystrdup(PROTOCOL_UNKNOWN);
if (message->client_helo == 0)
message->client_helo = mystrdup(HELO_NAME_UNKNOWN);
/*
* Clean up.

View File

@@ -3,9 +3,6 @@ SRCS = qmqpd.c qmqpd_state.c qmqpd_peer.c
OBJS = qmqpd.o qmqpd_state.o qmqpd_peer.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -3,9 +3,6 @@ SRCS = sendmail.c
OBJS = sendmail.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -740,7 +740,7 @@ int main(int argc, char **argv)
for (fd = 0; fd < 3; fd++)
if (fstat(fd, &st) == -1
&& (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
msg_fatal_status(EX_UNAVAILABLE, "open /dev/null: %m");
msg_fatal_status(EX_OSERR, "open /dev/null: %m");
/*
* The CDE desktop calendar manager leaks a parent file descriptor into

View File

@@ -3,9 +3,6 @@ SRCS = showq.c
OBJS = showq.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -7,9 +7,6 @@ OBJS = smtp.o smtp_connect.o smtp_proto.o smtp_chat.o smtp_session.o \
smtp_sasl_proto.o smtp_sasl_glue.o
HDRS = smtp.h smtp_sasl.h
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG= smtp_unalias
@@ -176,6 +173,7 @@ smtp_proto.o: ../../include/mail_proto.h
smtp_proto.o: ../../include/attr.h
smtp_proto.o: ../../include/mime_state.h
smtp_proto.o: ../../include/header_opts.h
smtp_proto.o: ../../include/xtext.h
smtp_proto.o: smtp.h
smtp_proto.o: ../../include/argv.h
smtp_proto.o: smtp_sasl.h

View File

@@ -194,6 +194,9 @@
/* .IP \fBsmtp_helo_timeout\fR
/* Timeout for sending the \fBHELO\fR command, and for
/* receiving the server response.
/* .IP \fBsmtp_xclient_timeout\fR
/* Timeout for sending the \fBXCLIENT\fR command, and for
/* receiving the server response.
/* .IP \fBsmtp_mail_timeout\fR
/* Timeout for sending the \fBMAIL FROM\fR command, and for
/* receiving the server response.
@@ -215,6 +218,11 @@
/* than the local MTA).
/* If yes, keep trying until a suitable MX host resolves or until
/* the mail is too old.
/* .IP \fBsmtp_send_xclient_command\fR
/* If the SMTP server announces XCLIENT support, send the name,
/* address, protocol and HELO name of the original client. This
/* can be used to forward client information through a content
/* filter to a downstream queuing SMTP server.
/* .IP \fBsmtp_rset_timeout\fR
/* Timeout for sending the \fBRSET\fR command.
/* .IP \fBsmtp_quit_timeout\fR
@@ -275,6 +283,7 @@
*/
int var_smtp_conn_tmout;
int var_smtp_helo_tmout;
int var_smtp_xclnt_tmout;
int var_smtp_mail_tmout;
int var_smtp_rcpt_tmout;
int var_smtp_data0_tmout;
@@ -305,6 +314,7 @@ char *var_smtp_helo_name;
char *var_smtp_host_lookup;
bool var_smtp_quote_821_env;
bool var_smtp_defer_mxaddr;
bool var_smtp_send_xclient;
/*
* Global variables. smtp_errno is set by the address lookup routines and by
@@ -492,6 +502,7 @@ int main(int argc, char **argv)
static CONFIG_TIME_TABLE time_table[] = {
VAR_SMTP_CONN_TMOUT, DEF_SMTP_CONN_TMOUT, &var_smtp_conn_tmout, 0, 0,
VAR_SMTP_HELO_TMOUT, DEF_SMTP_HELO_TMOUT, &var_smtp_helo_tmout, 1, 0,
VAR_SMTP_XCLNT_TMOUT, DEF_SMTP_XCLNT_TMOUT, &var_smtp_xclnt_tmout, 1, 0,
VAR_SMTP_MAIL_TMOUT, DEF_SMTP_MAIL_TMOUT, &var_smtp_mail_tmout, 1, 0,
VAR_SMTP_RCPT_TMOUT, DEF_SMTP_RCPT_TMOUT, &var_smtp_rcpt_tmout, 1, 0,
VAR_SMTP_DATA0_TMOUT, DEF_SMTP_DATA0_TMOUT, &var_smtp_data0_tmout, 1, 0,
@@ -518,6 +529,7 @@ int main(int argc, char **argv)
VAR_SMTP_RAND_ADDR, DEF_SMTP_RAND_ADDR, &var_smtp_rand_addr,
VAR_SMTP_QUOTE_821_ENV, DEF_SMTP_QUOTE_821_ENV, &var_smtp_quote_821_env,
VAR_SMTP_DEFER_MXADDR, DEF_SMTP_DEFER_MXADDR, &var_smtp_defer_mxaddr,
VAR_SMTP_SEND_XCLIENT, DEF_SMTP_SEND_XCLIENT, &var_smtp_send_xclient,
0,
};

View File

@@ -64,6 +64,7 @@ typedef struct SMTP_STATE {
#define SMTP_FEATURE_STARTTLS (1<<4)
#define SMTP_FEATURE_AUTH (1<<5)
#define SMTP_FEATURE_MAYBEPIX (1<<6) /* PIX smtp fixup mode */
#define SMTP_FEATURE_XCLIENT (1<<7) /* server supports XCLIENT */
/*
* smtp.c

View File

@@ -103,6 +103,7 @@
#include <quote_821_local.h>
#include <mail_proto.h>
#include <mime_state.h>
#include <xtext.h>
/* Application-specific. */
@@ -123,15 +124,19 @@
* SMTP_STATE_DOT) must have smaller numerical values than the non-sending
* states (SMTP_STATE_ABORT .. SMTP_STATE_LAST).
*/
#define SMTP_STATE_MAIL 0
#define SMTP_STATE_RCPT 1
#define SMTP_STATE_DATA 2
#define SMTP_STATE_DOT 3
#define SMTP_STATE_ABORT 4
#define SMTP_STATE_QUIT 5
#define SMTP_STATE_LAST 6
#define SMTP_STATE_XCLIENT_ADDR 0
#define SMTP_STATE_XCLIENT_HELO 1
#define SMTP_STATE_MAIL 2
#define SMTP_STATE_RCPT 3
#define SMTP_STATE_DATA 4
#define SMTP_STATE_DOT 5
#define SMTP_STATE_ABORT 6
#define SMTP_STATE_QUIT 7
#define SMTP_STATE_LAST 8
int *xfer_timeouts[SMTP_STATE_LAST] = {
&var_smtp_xclnt_tmout,
&var_smtp_xclnt_tmout,
&var_smtp_mail_tmout,
&var_smtp_rcpt_tmout,
&var_smtp_data0_tmout,
@@ -141,6 +146,8 @@ int *xfer_timeouts[SMTP_STATE_LAST] = {
};
char *xfer_states[SMTP_STATE_LAST] = {
"sending XCLIENT address and name",
"sending XCLIENT helo_name and protocol",
"sending MAIL FROM",
"sending RCPT TO",
"sending DATA command",
@@ -150,6 +157,8 @@ char *xfer_states[SMTP_STATE_LAST] = {
};
char *xfer_request[SMTP_STATE_LAST] = {
"XCLIENT command",
"XCLIENT command",
"MAIL FROM command",
"RCPT TO command",
"DATA command",
@@ -250,6 +259,8 @@ int smtp_helo(SMTP_STATE *state)
state->features |= SMTP_FEATURE_8BITMIME;
else if (strcasecmp(word, "PIPELINING") == 0)
state->features |= SMTP_FEATURE_PIPELINING;
else if (strcasecmp(word, "XCLIENT") == 0)
state->features |= SMTP_FEATURE_XCLIENT;
else if (strcasecmp(word, "SIZE") == 0) {
state->features |= SMTP_FEATURE_SIZE;
if ((word = mystrtok(&words, " \t")) != 0) {
@@ -374,6 +385,8 @@ int smtp_xfer(SMTP_STATE *state)
int mail_from_rejected;
int downgrading;
int mime_errs;
int send_xclient_addr = 0;
int send_xclient_helo = 0;
/*
* Macros for readability.
@@ -472,8 +485,22 @@ int smtp_xfer(SMTP_STATE *state)
* receiver detects a serious problem (MAIL FROM rejected, all RCPT TO
* commands rejected, DATA rejected) it forces the sender to abort the
* SMTP dialog with RSET and QUIT.
*
* Send "XCLIENT LOG" information only if we have a surrogate remote client
* name and address, i.e. the mail was actually received from the
* network. Since "XCLIENT LOG" overrides all remote client logging
* attributes, there is no need to send helo or protocol information that
* we do not have.
*/
nrcpt = 0;
send_xclient_addr = (state->features & SMTP_FEATURE_XCLIENT)
&& !IS_UNK_CLNT_NAME(request->client_name)
&& !IS_UNK_CLNT_ADDR(request->client_addr);
if (send_xclient_addr) {
send_xclient_helo = !IS_UNK_HELO_NAME(request->client_helo)
|| !IS_UNK_PROTOCOL(request->client_proto);
recv_state = send_state = SMTP_STATE_XCLIENT_ADDR;
} else
recv_state = send_state = SMTP_STATE_MAIL;
next_rcpt = send_rcpt = recv_rcpt = 0;
mail_from_rejected = 0;
@@ -491,6 +518,41 @@ int smtp_xfer(SMTP_STATE *state)
default:
msg_panic("%s: bad sender state %d", myname, send_state);
/*
* Build the XCLIENT command. Send what we know, converting
* internal form to external form. With properly sanitized
* information, this stays within the 512 byte command line
* length limit.
*/
case SMTP_STATE_XCLIENT_ADDR:
vstring_sprintf(next_command, "XCLIENT LOG");
if (!IS_UNK_CLNT_NAME(request->client_name)) {
vstring_strcat(next_command, " CLIENT_NAME=");
xtext_quote_append(next_command, request->client_name, "");
}
if (!IS_UNK_CLNT_ADDR(request->client_addr)) {
vstring_strcat(next_command, " CLIENT_ADDR=");
xtext_quote_append(next_command, request->client_addr, "");
}
if (send_xclient_helo)
next_state = SMTP_STATE_XCLIENT_HELO;
else
next_state = SMTP_STATE_MAIL;
break;
case SMTP_STATE_XCLIENT_HELO:
vstring_sprintf(next_command, "XCLIENT");
if (!IS_UNK_HELO_NAME(request->client_helo)) {
vstring_strcat(next_command, " HELO_NAME=");
xtext_quote_append(next_command, request->client_helo, "");
}
if (!IS_UNK_PROTOCOL(request->client_proto)) {
vstring_strcat(next_command, " PROTOCOL=");
xtext_quote_append(next_command, request->client_proto, "");
}
next_state = SMTP_STATE_MAIL;
break;
/*
* Build the MAIL FROM command.
*/
@@ -600,7 +662,7 @@ int smtp_xfer(SMTP_STATE *state)
/*
* Sanity check.
*/
if (recv_state < SMTP_STATE_MAIL
if (recv_state < SMTP_STATE_XCLIENT_ADDR
|| recv_state > SMTP_STATE_QUIT)
msg_panic("%s: bad receiver state %d (sender state %d)",
myname, recv_state, send_state);
@@ -621,6 +683,20 @@ int smtp_xfer(SMTP_STATE *state)
*/
switch (recv_state) {
/*
* Ignore the XCLIENT response. No Duff device needed.
*/
case SMTP_STATE_XCLIENT_ADDR:
if (send_xclient_helo)
recv_state = SMTP_STATE_XCLIENT_HELO;
else
recv_state = SMTP_STATE_MAIL;
break;
case SMTP_STATE_XCLIENT_HELO:
recv_state = SMTP_STATE_MAIL;
break;
/*
* Process the MAIL FROM response. When the server
* rejects the sender, set the mail_from_rejected flag so

View File

@@ -1,14 +1,13 @@
SHELL = /bin/sh
SRCS = smtpd.c smtpd_token.c smtpd_check.c smtpd_chat.c smtpd_state.c \
smtpd_peer.c smtpd_sasl_proto.c smtpd_sasl_glue.c smtpd_proxy.c
smtpd_peer.c smtpd_sasl_proto.c smtpd_sasl_glue.c smtpd_proxy.c \
smtpd_xclient.c
OBJS = smtpd.o smtpd_token.o smtpd_check.o smtpd_chat.o smtpd_state.o \
smtpd_peer.o smtpd_sasl_proto.o smtpd_sasl_glue.o smtpd_proxy.o
smtpd_peer.o smtpd_sasl_proto.o smtpd_sasl_glue.o smtpd_proxy.o \
smtpd_xclient.o
HDRS = smtpd_token.h smtpd_check.h smtpd_chat.h smtpd_sasl_proto.h \
smtpd_sasl_glue.h smtpd_proxy.h
TESTSRC = smtpd_token_test.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG= smtpd_token smtpd_check
@@ -122,6 +121,7 @@ smtpd.o: ../../include/dict.h
smtpd.o: ../../include/argv.h
smtpd.o: ../../include/watchdog.h
smtpd.o: ../../include/iostuff.h
smtpd.o: ../../include/split_at.h
smtpd.o: ../../include/mail_params.h
smtpd.o: ../../include/record.h
smtpd.o: ../../include/rec_type.h
@@ -150,6 +150,7 @@ smtpd.o: ../../include/namadr_list.h
smtpd.o: ../../include/input_transp.h
smtpd.o: ../../include/anvil_clnt.h
smtpd.o: ../../include/attr_clnt.h
smtpd.o: ../../include/xtext.h
smtpd.o: ../../include/mail_server.h
smtpd.o: smtpd_token.h
smtpd.o: smtpd.h
@@ -243,8 +244,11 @@ smtpd_peer.o: ../../include/valid_hostname.h
smtpd_peer.o: ../../include/stringops.h
smtpd_peer.o: ../../include/vstring.h
smtpd_peer.o: ../../include/vbuf.h
smtpd_peer.o: smtpd.h
smtpd_peer.o: ../../include/mail_proto.h
smtpd_peer.o: ../../include/vstream.h
smtpd_peer.o: ../../include/iostuff.h
smtpd_peer.o: ../../include/attr.h
smtpd_peer.o: smtpd.h
smtpd_peer.o: ../../include/argv.h
smtpd_peer.o: ../../include/mail_stream.h
smtpd_proxy.o: smtpd_proxy.c
@@ -262,6 +266,9 @@ smtpd_proxy.o: ../../include/smtp_stream.h
smtpd_proxy.o: ../../include/cleanup_user.h
smtpd_proxy.o: ../../include/mail_params.h
smtpd_proxy.o: ../../include/rec_type.h
smtpd_proxy.o: ../../include/xtext.h
smtpd_proxy.o: ../../include/mail_proto.h
smtpd_proxy.o: ../../include/attr.h
smtpd_proxy.o: smtpd.h
smtpd_proxy.o: ../../include/argv.h
smtpd_proxy.o: ../../include/mail_stream.h
@@ -331,3 +338,16 @@ smtpd_token.o: ../../include/mvect.h
smtpd_token.o: smtpd_token.h
smtpd_token.o: ../../include/vstring.h
smtpd_token.o: ../../include/vbuf.h
smtpd_xclient.o: smtpd_xclient.c
smtpd_xclient.o: ../../include/sys_defs.h
smtpd_xclient.o: ../../include/mymalloc.h
smtpd_xclient.o: ../../include/msg.h
smtpd_xclient.o: ../../include/mail_proto.h
smtpd_xclient.o: ../../include/vstream.h
smtpd_xclient.o: ../../include/vbuf.h
smtpd_xclient.o: ../../include/iostuff.h
smtpd_xclient.o: ../../include/attr.h
smtpd_xclient.o: smtpd.h
smtpd_xclient.o: ../../include/vstring.h
smtpd_xclient.o: ../../include/argv.h
smtpd_xclient.o: ../../include/mail_stream.h

View File

@@ -143,20 +143,12 @@
/* .IP \fBsmtpd_authorized_verp_clients\fR
/* Hostnames, domain names and/or addresses of clients that are
/* authorized to use the XVERP extension.
/* .IP \fBsmtpd_authorized_xaddr_clients\fR
/* .IP \fBsmtpd_authorized_xclient_hosts\fR
/* Hostnames, domain names and/or addresses of clients that are
/* authorized to use the "XADDR client-address client-name" command.
/* This changes Postfix's
/* idea of the SMTP client IP address and hostname for access
/* control and for logging purposes.
/* .IP \fBsmtpd_authorized_xloginfo_clients\fR
/* Hostnames, domain names and/or addresses of clients that are
/* authorized to use the "XLOGINFO client-address client-name" command.
/* This changes the client
/* name and address that are used for logging, without affecting the
/* client IP address and hostname that are used for access control.
/* XLOGINFO is typically used to propagate remote client information
/* through an SMTP-based content filter to the after-filter SMTP server.
/* authorized to use the XCLIENT command. This command changes
/* client information for access control and/or logging purposes,
/* with the exception of the
/* \fBsmtpd_authorized_xclient_hosts\fR access control itself.
/* .IP \fBdebug_peer_level\fR
/* Increment in verbose logging level when a remote host matches a
/* pattern in the \fBdebug_peer_list\fR parameter.
@@ -437,6 +429,7 @@
#include <dict.h>
#include <watchdog.h>
#include <iostuff.h>
#include <split_at.h>
/* Global library. */
@@ -461,6 +454,7 @@
#include <namadr_list.h>
#include <input_transp.h>
#include <anvil_clnt.h>
#include <xtext.h>
/* Single-threaded server skeleton. */
@@ -557,8 +551,7 @@ char *var_input_transp;
int var_smtpd_policy_tmout;
int var_smtpd_policy_idle;
int var_smtpd_policy_ttl;
char *var_xaddr_clients;
char *var_xloginfo_clients;
char *var_xclient_hosts;
int var_smtpd_crate_limit;
int var_smtpd_cconn_limit;
char *var_smtpd_hoggers;
@@ -578,16 +571,9 @@ char *var_smtpd_hoggers;
static NAMADR_LIST *verp_clients;
/*
* XADDR command.
* XCLIENT command.
*/
#define XADDR_CMD "XADDR"
static NAMADR_LIST *xaddr_clients;
/*
* XLOGINFO command.
*/
static NAMADR_LIST *xloginfo_clients;
static NAMADR_LIST *xclient_hosts;
/*
* Client connection and rate limiting.
@@ -630,11 +616,10 @@ static int sasl_client_exception(SMTPD_STATE *state)
return (0);
match = namadr_list_match(sasl_exceptions_networks,
state->name, state->addr);
ACL_NAME(state), ACL_ADDR(state));
if (msg_verbose)
msg_info("sasl_exceptions: %s[%s], match=%d",
state->name, state->addr, match);
msg_info("sasl_exceptions: %s, match=%d", ACL_NAMADDR(state), match);
return (match);
}
@@ -679,6 +664,8 @@ static int helo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
mail_reset(state);
rcpt_reset(state);
state->helo_name = mystrdup(printable(argv[1].strval, '?'));
neuter(state->helo_name, "<>()\\\";:@", '?');
/* Changing the protocol name breaks the unauthorized pipelining check. */
if (strcmp(state->protocol, MAIL_PROTO_ESMTP) != 0)
state->protocol = MAIL_PROTO_SMTP;
smtpd_chat_reply(state, "250 %s", var_myhostname);
@@ -715,6 +702,7 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
mail_reset(state);
rcpt_reset(state);
state->helo_name = mystrdup(printable(argv[1].strval, '?'));
neuter(state->helo_name, "<>()\\\";:@", '?');
state->protocol = MAIL_PROTO_ESMTP;
smtpd_chat_reply(state, "250-%s", var_myhostname);
smtpd_chat_reply(state, "250-PIPELINING");
@@ -733,12 +721,11 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
smtpd_chat_reply(state, "250-AUTH=%s", state->sasl_mechanism_list);
}
#endif
if (namadr_list_match(verp_clients, state->name, state->addr))
if (namadr_list_match(verp_clients, ACL_NAME(state), ACL_ADDR(state)))
smtpd_chat_reply(state, "250-%s", VERP_CMD);
if (namadr_list_match(xaddr_clients, state->name, state->addr))
smtpd_chat_reply(state, "250-%s", XADDR_CMD);
if (namadr_list_match(xloginfo_clients, state->name, state->addr))
smtpd_chat_reply(state, "250-%s", XLOGINFO_CMD);
/* XCLIENT must not override its own access control. */
if (namadr_list_match(xclient_hosts, state->name, state->addr))
smtpd_chat_reply(state, "250-%s", XCLIENT_CMD);
smtpd_chat_reply(state, "250 8BITMIME");
return (0);
}
@@ -754,8 +741,7 @@ static void helo_reset(SMTPD_STATE *state)
/* mail_open_stream - open mail queue file or IPC stream */
static void mail_open_stream(SMTPD_STATE *state, SMTPD_TOKEN *argv,
const char *encoding, const char *verp_delims)
static void mail_open_stream(SMTPD_STATE *state, SMTPD_TOKEN *argv)
{
char *postdrop_command;
int cleanup_flags;
@@ -816,7 +802,7 @@ static void mail_open_stream(SMTPD_STATE *state, SMTPD_TOKEN *argv,
smtpd_sasl_mail_log(state);
else
#endif
msg_info("%s: client=%s", state->queue_id, state->namaddr);
msg_info("%s: client=%s", state->queue_id, LOG_NAMADDR(state));
/*
* Record the time of arrival, the sender envelope address, some session
@@ -828,24 +814,29 @@ static void mail_open_stream(SMTPD_STATE *state, SMTPD_TOKEN *argv,
rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport);
}
rec_fputs(state->cleanup, REC_TYPE_FROM, argv[2].strval);
if (encoding != 0)
if (state->encoding != 0)
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
MAIL_ATTR_ENCODING, encoding);
MAIL_ATTR_ENCODING, state->encoding);
/*
* Store the client attributes for logging purposes.
*/
if (SMTPD_STAND_ALONE(state) == 0) {
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
MAIL_ATTR_CLIENT_NAME, state->name);
MAIL_ATTR_CLIENT_NAME, LOG_NAME(state));
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
MAIL_ATTR_CLIENT_ADDR, state->addr);
MAIL_ATTR_CLIENT_ADDR, LOG_ADDR(state));
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
MAIL_ATTR_ORIGIN, state->namaddr);
if (state->helo_name != 0)
MAIL_ATTR_ORIGIN, LOG_NAMADDR(state));
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
MAIL_ATTR_HELO_NAME, state->helo_name);
MAIL_ATTR_HELO_NAME,
IS_UNK_HELO_NAME(LOG_HELO_NAME(state)) ?
HELO_NAME_UNKNOWN : LOG_HELO_NAME(state));
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
MAIL_ATTR_PROTO_NAME, state->protocol);
MAIL_ATTR_PROTO_NAME, LOG_PROTOCOL(state));
}
if (verp_delims)
rec_fputs(state->cleanup, REC_TYPE_VERP, verp_delims);
if (state->verp_delims)
rec_fputs(state->cleanup, REC_TYPE_VERP, state->verp_delims);
}
/* extract_addr - extract address from rubble */
@@ -965,8 +956,8 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
int narg;
char *arg;
char *verp_delims = 0;
char *encoding = 0;
state->encoding = 0;
state->msg_size = 0;
/*
@@ -983,7 +974,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
smtpd_chat_reply(state, "503 Error: send HELO/EHLO first");
return (-1);
}
#define IN_MAIL_TRANSACTION(state) ((state)->cleanup || (state)->proxy)
#define IN_MAIL_TRANSACTION(state) ((state)->sender != 0)
if (IN_MAIL_TRANSACTION(state)) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
@@ -998,7 +989,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
}
if (argv[2].tokval == SMTPD_TOK_ERROR) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "501 Bad address syntax");
smtpd_chat_reply(state, "501 Bad sender address syntax");
return (-1);
}
if ((err = extract_addr(state, argv + 2, PERMIT_EMPTY_ADDR, var_strict_rfc821_env)) != 0) {
@@ -1009,9 +1000,9 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
for (narg = 3; narg < argc; narg++) {
arg = argv[narg].strval;
if (strcasecmp(arg, "BODY=8BITMIME") == 0) { /* RFC 1652 */
encoding = MAIL_ATTR_ENC_8BIT;
state->encoding = MAIL_ATTR_ENC_8BIT;
} else if (strcasecmp(arg, "BODY=7BIT") == 0) { /* RFC 1652 */
encoding = MAIL_ATTR_ENC_7BIT;
state->encoding = MAIL_ATTR_ENC_7BIT;
} else if (strncasecmp(arg, "SIZE=", 5) == 0) { /* RFC 1870 */
/* Reject non-numeric size. */
if (!alldig(arg + 5)) {
@@ -1032,11 +1023,13 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
return (-1);
}
#endif
} else if (namadr_list_match(verp_clients, state->name, state->addr)) {
if (strcasecmp(arg, VERP_CMD) == 0) {
} else if (namadr_list_match(verp_clients, ACL_NAME(state),
ACL_ADDR(state))
&& strncasecmp(arg, VERP_CMD, VERP_CMD_LEN) == 0
&& (arg[VERP_CMD_LEN] == '=' || arg[VERP_CMD_LEN] == 0)) {
if (arg[VERP_CMD_LEN] == 0) {
verp_delims = var_verp_delims;
} else if (strncasecmp(arg, VERP_CMD, VERP_CMD_LEN) == 0
&& arg[VERP_CMD_LEN] == '=') {
} else {
verp_delims = arg + VERP_CMD_LEN + 1;
if (verp_delims_verify(verp_delims) != 0) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
@@ -1065,28 +1058,26 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
state->time = time((time_t *) 0);
/*
* Open connection to SMTP proxy server.
* Check the queue file space, if applicable.
*/
if (SMTPD_STAND_ALONE(state) == 0 && *var_smtpd_proxy_filt) {
if (smtpd_proxy_open(state, var_smtpd_proxy_filt, var_smtpd_proxy_tmout,
var_smtpd_proxy_ehlo, STR(state->buffer)) != 0) {
smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
#define USE_SMTPD_PROXY(state) \
(SMTPD_STAND_ALONE(state) == 0 && *var_smtpd_proxy_filt)
if (!USE_SMTPD_PROXY(state)) {
if ((err = smtpd_check_size(state, state->msg_size)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
}
}
/*
* Open queue file, or open connection to queue file writing process.
* Check for queue file space first.
* No more early returns. The mail transaction is in progress.
*/
else {
if ((err = smtpd_check_size(state, state->msg_size)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
}
mail_open_stream(state, argv, encoding, verp_delims);
}
state->sender = mystrdup(argv[2].strval);
if (verp_delims)
state->verp_delims = mystrdup(verp_delims);
if (USE_SMTPD_PROXY(state))
state->proxy_mail = mystrdup(STR(state->buffer));
smtpd_chat_reply(state, "250 Ok");
return (0);
}
@@ -1115,6 +1106,10 @@ static void mail_reset(SMTPD_STATE *state)
myfree(state->sender);
state->sender = 0;
}
if (state->verp_delims) {
myfree(state->verp_delims);
state->verp_delims = 0;
}
#ifdef USE_SASL_AUTH
if (var_smtpd_sasl_enable)
smtpd_sasl_mail_reset(state);
@@ -1129,6 +1124,10 @@ static void mail_reset(SMTPD_STATE *state)
(void) smtpd_proxy_cmd(state, SMTPD_PROX_WANT_NONE, "QUIT");
smtpd_proxy_close(state);
}
if (state->proxy_mail) {
myfree(state->proxy_mail);
state->proxy_mail = 0;
}
}
/* rcpt_cmd - process RCPT TO command */
@@ -1161,7 +1160,7 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
}
if (argv[2].tokval == SMTPD_TOK_ERROR) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "501 Bad address syntax");
smtpd_chat_reply(state, "501 Bad recipient address syntax");
return (-1);
}
if ((err = extract_addr(state, argv + 2, REJECT_EMPTY_ADDR, var_strict_rfc821_env)) != 0) {
@@ -1188,6 +1187,21 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
return (-1);
}
}
/*
* Don't access the proxy, queue file, or queue file writer process until
* we have a valid recipient address.
*/
if (state->proxy == 0 && state->proxy_mail) {
if (smtpd_proxy_open(state, var_smtpd_proxy_filt,
var_smtpd_proxy_tmout, var_smtpd_proxy_ehlo,
state->proxy_mail) != 0) {
smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
return (-1);
}
} else if (state->cleanup == 0) {
mail_open_stream(state, argv);
}
if (state->proxy && smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK,
"%s", STR(state->buffer)) != 0) {
smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
@@ -1284,9 +1298,13 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
* Terminate the message envelope segment. Start the message content
* segment, and prepend our own Received: header. If there is only one
* recipient, list the recipient address.
*
* Suppress our own Received: header in the unlikely case that we are an
* intermediate proxy.
*/
if (state->cleanup)
rec_fputs(state->cleanup, REC_TYPE_MESG, "");
if (!state->proxy || state->xclient.addr == 0) {
out_fprintf(out_stream, REC_TYPE_NORM,
"Received: from %s (%s [%s])",
state->helo_name ? state->helo_name : state->name,
@@ -1314,6 +1332,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
out_fprintf(out_stream, REC_TYPE_NORM,
"\t(envelope-from %s)", STR(state->buffer));
#endif
}
smtpd_chat_reply(state, "354 End data with <CR><LF>.<CR><LF>");
/*
@@ -1650,75 +1669,213 @@ static int quit_cmd(SMTPD_STATE *state, int unused_argc, SMTPD_TOKEN *unused_arg
return (0);
}
/* xaddr_cmd - process XADDR */
/* xclient_cmd - process XCLIENT */
static int xaddr_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
{
int arg_no;
char *raw_value;
char *cooked_value;
char *arg_val;
int update_namaddr = 0;
/*
* Sanity checks.
* Sanity checks. The XCLIENT command does not override its own access
* control.
*/
if (namadr_list_match(xaddr_clients, state->name, state->addr) == 0) {
if (namadr_list_match(xclient_hosts, state->name, state->addr) == 0) {
state->error_mask |= MAIL_ERROR_POLICY;
smtpd_chat_reply(state, "554 Error: insufficient authorization");
return (-1);
}
/* Todo: "XADDR address" to let Postfix look up the client name. */
if (argc != 3
|| !valid_hostaddr(argv[1].strval, DONT_GRIPE)
|| !valid_hostname(argv[2].strval, DONT_GRIPE)) {
#define STREQ(x,y) (strcasecmp((x), (y)) == 0)
#define UPDATE_STR(s, v) { if (s) myfree(s); s = mystrdup(v); }
/*
* Iterate over all XCLIENT arguments.
*/
for (arg_no = 1; arg_no < argc; arg_no++) {
arg_val = argv[arg_no].strval;
/*
* Request name: what should happen with the stored attributes.
* Complain about unrecognized request names. The set of requests is
* unlikely to change.
*/
if ((raw_value = split_at(arg_val, '=')) == 0) {
printable(arg_val, '?');
if (STREQ(arg_val, "RST")) { /* blow them away */
smtpd_xclient_reset(state, XCLIENT_OVER_NONE);
} else if (STREQ(arg_val, "ACL")) { /* access control and logging */
smtpd_xclient_reset(state, XCLIENT_OVER_ACL | XCLIENT_OVER_LOG);
} else if (STREQ(arg_val, "LOG")) { /* logging only */
smtpd_xclient_reset(state, XCLIENT_OVER_LOG);
} else { /* error */
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "501 Syntax: %s address hostname", XADDR_CMD);
smtpd_chat_reply(state, "501 Bad request: %s", arg_val);
return (-1);
}
}
/*
* Change peer information for logging and for access control. Change a
* numerical hostname into "unknown", to make it easy to extract client
* information from Received: headers.
* NAME=VALUE attribute. Decode the attribute and for safety's sake
* mask non-printable characters in the raw and decoded values; we
* don't want to handle unexploded munitions. Do not complain about
* unrecognized attribute names. The set of attributes may change
* over time.
*
* The client can send multiple XCLIENT attributes in a single command,
* or multiple XCLIENT commands with fewer attributes.
*
* Note: XCLIENT ACL overrides only specific logging and access control
* attributes (desirable for testing), while XCLIENT LOG overrides
* all logging attributes (for audit trail consistency).
*/
#define FIX_NUMERICAL_NAME(s) \
(valid_hostaddr((s), DONT_GRIPE) ? "unknown" : (s))
smtpd_peer_reset(state);
state->name = mystrdup(FIX_NUMERICAL_NAME(argv[2].strval));
state->addr = mystrdup(argv[1].strval);
state->namaddr =
concatenate(state->name, "[", state->addr, "]", (char *) 0);
state->peer_code = strcmp(state->name, "unknown") ? 2 : 5;
smtpd_chat_reply(state, "250 Ok");
return (0);
}
/* xloginfo_cmd - process XLOGINFO */
static int xloginfo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
{
/*
* Sanity checks.
*/
if (namadr_list_match(xloginfo_clients, state->name, state->addr) == 0) {
state->error_mask |= MAIL_ERROR_POLICY;
smtpd_chat_reply(state, "554 Error: insufficient authorization");
return (-1);
}
if (argc != 3
|| !valid_hostaddr(argv[1].strval, DONT_GRIPE)
|| !valid_hostname(argv[2].strval, DONT_GRIPE)) {
else {
if (state->xclient.mode == 0) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "501 Syntax: %s address hostname", XLOGINFO_CMD);
smtpd_chat_reply(state, "503 Error: send %s ACL or LOG first",
XCLIENT_CMD);
return (-1);
}
if (xtext_unquote(state->buffer, raw_value) == 0) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "501 Bad attribute value syntax: %s",
printable(raw_value, '?'));
return (-1);
}
cooked_value = printable(STR(state->buffer), '?');
(void) printable(raw_value, '?');
/*
* CLIENT_NAME=hostname. Also updates the client hostname lookup
* status code. Treat a numerical hostname as an unavailable
* name.
*/
if (STREQ(arg_val, "CLIENT_NAME")) {
if (*raw_value && !valid_hostaddr(cooked_value, DONT_GRIPE)) {
if (!valid_hostname(cooked_value, DONT_GRIPE)) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "501 Bad hostname syntax: %s",
cooked_value);
return (-1);
}
UPDATE_STR(state->xclient.name, cooked_value);
state->xclient.peer_code = SMTPD_PEER_CODE_OK;
} else {
UPDATE_STR(state->xclient.name, CLIENT_NAME_UNKNOWN);
state->xclient.peer_code = SMTPD_PEER_CODE_PERM;
}
update_namaddr = 1;
}
/*
* Change peer information for logging but not for access control. Change
* a numerical hostname into "unknown", for consistency with XADDR.
* CLIENT_ADDR=client network address.
*/
myfree(state->namaddr);
state->namaddr =
concatenate(FIX_NUMERICAL_NAME(argv[2].strval),
"[", argv[1].strval, "]", (char *) 0);
else if (STREQ(arg_val, "CLIENT_ADDR")) {
if (*raw_value) {
if (!valid_hostaddr(cooked_value, DONT_GRIPE)) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "501 Bad address syntax: %s",
cooked_value);
return (-1);
}
UPDATE_STR(state->xclient.addr, cooked_value);
} else {
UPDATE_STR(state->xclient.name, CLIENT_NAME_UNKNOWN);
}
update_namaddr = 1;
}
/*
* CLIENT_CODE=status. Reset the client hostname if the hostname
* lookup status is not OK.
*/
else if (STREQ(arg_val, "CLIENT_CODE")) {
if (STREQ(cooked_value, "OK")) {
state->xclient.peer_code = SMTPD_PEER_CODE_OK;
} else if (STREQ(cooked_value, "TEMP")) {
state->xclient.peer_code = SMTPD_PEER_CODE_TEMP;
UPDATE_STR(state->xclient.name, CLIENT_NAME_UNKNOWN);
update_namaddr = 1;
} else if (STREQ(cooked_value, "PERM")) {
state->xclient.peer_code = SMTPD_PEER_CODE_PERM;
UPDATE_STR(state->xclient.name, CLIENT_NAME_UNKNOWN);
update_namaddr = 1;
} else {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "501 Bad hostname status: %s",
cooked_value);
return (-1);
}
}
/*
* HELO_NAME=hostname. An empty value means the information was
* not provided by the client and that we must not fall back to
* the non-XCLIENT value. Disallow characters that could mess up
* our own Received: message headers but allow [].
*/
else if (STREQ(arg_val, "HELO_NAME")) {
if (*raw_value) {
if (strlen(cooked_value) > VALID_HOSTNAME_LEN) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "501 Bad HELO syntax: %s",
cooked_value);
return (-1);
}
neuter(cooked_value, "<>()\\\";:@", '?');
UPDATE_STR(state->xclient.helo_name, cooked_value);
} else {
UPDATE_STR(state->xclient.helo_name, HELO_NAME_UNKNOWN);
}
}
/*
* PROTOCOL=protocol name. Disallow characters that could mess up
* our own Received: message headers.
*/
else if (STREQ(arg_val, "PROTOCOL")) {
if (*raw_value) {
if (*cooked_value == 0 || strlen(cooked_value) > 64) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "501 Bad protocol syntax: %s",
cooked_value);
return (-1);
}
neuter(cooked_value, "[]<>()\\\";:@", '?');
UPDATE_STR(state->xclient.protocol, cooked_value);
} else {
UPDATE_STR(state->xclient.protocol, PROTOCOL_UNKNOWN);
}
}
/*
* Unknown attribute name. Don't complain, and log a warning.
* Logging is safe because only authorized clients can issue
* XCLIENT commands.
*/
else {
msg_warn("unknown %s attribute from %s: %s=%s",
XCLIENT_CMD, state->namaddr, arg_val, cooked_value);
}
}
}
/*
* Update the combined name and address when either has changed.
*/
#define MAYBE_OVERRIDE(state, attr) \
((state)->xclient.attr ? (state)->xclient.attr : (state)->attr)
if (update_namaddr) {
if (state->xclient.namaddr)
myfree(state->xclient.namaddr);
state->xclient.namaddr =
concatenate(MAYBE_OVERRIDE(state, name), "[",
MAYBE_OVERRIDE(state, addr), "]",
(char *) 0);
}
smtpd_chat_reply(state, "250 Ok");
return (0);
}
@@ -1774,8 +1931,7 @@ static SMTPD_CMD smtpd_cmd_table[] = {
"VRFY", vrfy_cmd, SMTPD_CMD_FLAG_LIMIT,
"ETRN", etrn_cmd, SMTPD_CMD_FLAG_LIMIT,
"QUIT", quit_cmd, 0,
"XADDR", xaddr_cmd, SMTPD_CMD_FLAG_LIMIT,
"XLOGINFO", xloginfo_cmd, SMTPD_CMD_FLAG_LIMIT,
"XCLIENT", xclient_cmd, SMTPD_CMD_FLAG_LIMIT,
"Received:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
"Reply-To:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
"Message-ID:", 0, SMTPD_CMD_FLAG_FORBIDDEN,
@@ -1835,6 +1991,12 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
break;
case 0:
/*
* XXX The client connection count/rate control uses the real client
* name/address to maintain consistency between connect and
* disconnect events.
*/
if (SMTPD_STAND_ALONE(state) == 0
&& anvil_clnt
&& !namadr_list_match(hogger_list, state->name, state->addr)
@@ -1855,6 +2017,7 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
break;
}
}
/* XXX We use the real client for connect access control. */
if (SMTPD_STAND_ALONE(state) == 0
&& var_smtpd_delay_reject == 0
&& (state->access_denied = smtpd_check_client(state)) != 0) {
@@ -1900,6 +2063,7 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
smtpd_chat_reply(state, "221 Error: I can break rules, too. Goodbye.");
break;
}
/* XXX We use the real client for connect access control. */
if (state->access_denied && cmdp->action != quit_cmd) {
smtpd_chat_reply(state, "503 Error: access denied for %s",
state->namaddr); /* RFC 2821 Sec 3.1 */
@@ -1917,6 +2081,12 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
}
break;
}
/*
* XXX The client connection count/rate control uses the real client
* name/address to maintain consistency between connect and disconnect
* events.
*/
if (SMTPD_STAND_ALONE(state) == 0
&& anvil_clnt
&& !namadr_list_match(hogger_list, state->name, state->addr))
@@ -2014,8 +2184,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
*/
smtpd_noop_cmds = string_list_init(MATCH_FLAG_NONE, var_smtpd_noop_cmds);
verp_clients = namadr_list_init(MATCH_FLAG_NONE, var_verp_clients);
xaddr_clients = namadr_list_init(MATCH_FLAG_NONE, var_xaddr_clients);
xloginfo_clients = namadr_list_init(MATCH_FLAG_NONE, var_xloginfo_clients);
xclient_hosts = namadr_list_init(MATCH_FLAG_NONE, var_xclient_hosts);
hogger_list = namadr_list_init(MATCH_FLAG_NONE, var_smtpd_hoggers);
if (getuid() == 0 || getuid() == var_owner_uid)
smtpd_check_init();
@@ -2153,8 +2322,7 @@ int main(int argc, char **argv)
VAR_SMTPD_PROXY_FILT, DEF_SMTPD_PROXY_FILT, &var_smtpd_proxy_filt, 0, 0,
VAR_SMTPD_PROXY_EHLO, DEF_SMTPD_PROXY_EHLO, &var_smtpd_proxy_ehlo, 0, 0,
VAR_INPUT_TRANSP, DEF_INPUT_TRANSP, &var_input_transp, 0, 0,
VAR_XADDR_CLIENTS, DEF_XADDR_CLIENTS, &var_xaddr_clients, 0, 0,
VAR_XLOGINFO_CLIENTS, DEF_XLOGINFO_CLIENTS, &var_xloginfo_clients, 0, 0,
VAR_XCLIENT_HOSTS, DEF_XCLIENT_HOSTS, &var_xclient_hosts, 0, 0,
VAR_SMTPD_HOGGERS, DEF_SMTPD_HOGGERS, &var_smtpd_hoggers, 0, 0,
0,
};

View File

@@ -45,6 +45,16 @@ typedef struct SMTPD_DEFER {
int class; /* error notification class */
} SMTPD_DEFER;
typedef struct SMTPD_XCLIENT_ATTR {
int mode; /* none, log, acl */
char *name; /* name for access control */
char *addr; /* address for access control */
char *namaddr; /* name[address] */
int peer_code; /* name status */
char *protocol; /* email protocol */
char *helo_name; /* helo/ehlo parameter */
} SMTPD_XCLIENT_ATTR;
typedef struct SMTPD_STATE {
int err;
VSTREAM *client;
@@ -66,6 +76,8 @@ typedef struct SMTPD_STATE {
ARGV *history;
char *reason;
char *sender;
char *encoding;
char *verp_delims;
char *recipient;
char *etrn_name;
char *protocol;
@@ -97,6 +109,9 @@ typedef struct SMTPD_STATE {
VSTRING *expand_buf; /* scratch space for $name expansion */
VSTREAM *proxy; /* proxy handle */
VSTRING *proxy_buffer; /* proxy query/reply buffer */
char *proxy_mail; /* proxy MAIL FROM command */
int proxy_features; /* proxy ESMTP features */
SMTPD_XCLIENT_ATTR xclient; /* override access control */
} SMTPD_STATE;
extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
@@ -117,22 +132,55 @@ extern void smtpd_state_reset(SMTPD_STATE *);
(state->client == VSTREAM_IN && getuid() != var_owner_uid)
/*
* SMPTD peer information lookup.
* SMTPD peer information lookup.
*/
extern void smtpd_peer_init(SMTPD_STATE *state);
extern void smtpd_peer_reset(SMTPD_STATE *state);
#define SMTPD_PEER_CODE_OK 2
#define SMTPD_PEER_CODE_TEMP 4
#define SMTPD_PEER_CODE_PERM 5
/*
* XCLIENT support to override logging and/or access control attributes. It
* makes no sense to maintain separate attribute sets for XCLIENT LOG or
* XCLIENT ACL, so we set a flag to distinguish purpose.
*/
#define XCLIENT_CMD "XCLIENT" /* XCLIENT command */
#define XCLIENT_EHLO "XCLIENT" /* ESMTP advertisement */
#define SMTPD_FEATURE_XCLIENT (1<<0) /* server supports XCLIENT */
#define XCLIENT_OVER_NONE (0) /* override reset */
#define XCLIENT_OVER_ACL (1<<0) /* override access control */
#define XCLIENT_OVER_LOG (1<<1) /* override logging */
#define XCLIENT_OVER(s, m, a) \
(((s)->xclient.mode & (m)) && (s)->xclient.a ? (s)->xclient.a : (s)->a)
#define ACL_ADDR(s) XCLIENT_OVER((s), XCLIENT_OVER_ACL, addr)
#define ACL_NAME(s) XCLIENT_OVER((s), XCLIENT_OVER_ACL, name)
#define ACL_NAMADDR(s) XCLIENT_OVER((s), XCLIENT_OVER_ACL, namaddr)
#define ACL_PEER_CODE(s) XCLIENT_OVER((s), XCLIENT_OVER_ACL, peer_code)
#define ACL_PROTOCOL(s) XCLIENT_OVER((s), XCLIENT_OVER_ACL, protocol)
#define ACL_HELO_NAME(s) XCLIENT_OVER((s), XCLIENT_OVER_ACL, helo_name)
#define LOG_ADDR(s) XCLIENT_OVER((s), XCLIENT_OVER_LOG, addr)
#define LOG_NAME(s) XCLIENT_OVER((s), XCLIENT_OVER_LOG, name)
#define LOG_NAMADDR(s) XCLIENT_OVER((s), XCLIENT_OVER_LOG, namaddr)
#define LOG_PEER_CODE(s) XCLIENT_OVER((s), XCLIENT_OVER_LOG, peer_code)
#define LOG_PROTOCOL(s) XCLIENT_OVER((s), XCLIENT_OVER_LOG, protocol)
#define LOG_HELO_NAME(s) XCLIENT_OVER((s), XCLIENT_OVER_LOG, helo_name)
extern void smtpd_xclient_init(SMTPD_STATE *state);
extern void smtpd_xclient_reset(SMTPD_STATE *state, int);
/*
* Transparency: before mail is queued, do we check for unknown recipients,
* do we allow address mapping, automatic bcc, header/body checks?
*/
extern int smtpd_input_transp_mask;
/*
* XLOGINFO command.
*/
#define XLOGINFO_CMD "XLOGINFO"
/* LICENSE
/* .ad
/* .fi

View File

@@ -809,15 +809,15 @@ static void log_whatsup(SMTPD_STATE *state, const char *whatsup,
vstring_sprintf(buf, "%s: %s: %s from %s: %s;",
state->queue_id ? state->queue_id : "NOQUEUE",
whatsup, state->where, state->namaddr, text);
whatsup, state->where, LOG_NAMADDR(state), text);
if (state->sender)
vstring_sprintf_append(buf, " from=<%s>", state->sender);
if (state->recipient)
vstring_sprintf_append(buf, " to=<%s>", state->recipient);
if (state->protocol)
vstring_sprintf_append(buf, " proto=%s", state->protocol);
if (state->helo_name)
vstring_sprintf_append(buf, " helo=<%s>", state->helo_name);
if (!IS_UNK_PROTOCOL(ACL_PROTOCOL(state)))
vstring_sprintf_append(buf, " proto=%s", ACL_PROTOCOL(state));
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state)))
vstring_sprintf_append(buf, " helo=<%s>", ACL_HELO_NAME(state));
msg_info("%s", STR(buf));
vstring_free(buf);
}
@@ -968,14 +968,14 @@ static int reject_unknown_client(SMTPD_STATE *state)
char *myname = "reject_unknown_client";
if (msg_verbose)
msg_info("%s: %s %s", myname, state->name, state->addr);
msg_info("%s: %s %s", myname, ACL_NAME(state), ACL_ADDR(state));
if (strcasecmp(state->name, "unknown") == 0)
if (IS_UNK_CLNT_NAME(ACL_NAME(state)))
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
"%d Client host rejected: cannot find your hostname, [%s]",
state->peer_code == 5 ?
ACL_PEER_CODE(state) == SMTPD_PEER_CODE_PERM ?
var_unk_client_code : 450,
state->addr));
ACL_ADDR(state)));
return (SMTPD_CHECK_DUNNO);
}
@@ -986,9 +986,9 @@ static int permit_mynetworks(SMTPD_STATE *state)
char *myname = "permit_mynetworks";
if (msg_verbose)
msg_info("%s: %s %s", myname, state->name, state->addr);
msg_info("%s: %s %s", myname, ACL_NAME(state), ACL_ADDR(state));
if (namadr_list_match(mynetworks, state->name, state->addr))
if (namadr_list_match(mynetworks, ACL_NAME(state), ACL_ADDR(state)))
return (SMTPD_CHECK_OK);
return (SMTPD_CHECK_DUNNO);
}
@@ -1207,7 +1207,7 @@ static int check_relay_domains(SMTPD_STATE *state, char *recipient,
/*
* Permit if the client matches the relay_domains list.
*/
if (domain_list_match(relay_domains, state->name))
if (domain_list_match(relay_domains, ACL_NAME(state)))
return (SMTPD_CHECK_OK);
/*
@@ -1309,7 +1309,7 @@ static int reject_unauth_pipelining(SMTPD_STATE *state,
if (state->client != 0
&& SMTPD_STAND_ALONE(state) == 0
&& vstream_peek(state->client) > 0
&& (strcasecmp(state->protocol, "ESMTP") != 0
&& (strcasecmp(ACL_PROTOCOL(state), MAIL_PROTO_ESMTP) != 0
|| strcasecmp(state->where, "DATA") == 0)) {
return (smtpd_check_reject(state, MAIL_ERROR_PROTOCOL,
"503 <%s>: %s rejected: Improper use of SMTP command pipelining",
@@ -2518,13 +2518,14 @@ static const char *smtpd_expand_lookup(const char *name, int unused_mode,
* Return NULL only for non-existent names.
*/
if (STREQ(name, MAIL_ATTR_CLIENT)) {
return (state->namaddr);
return (ACL_NAMADDR(state));
} else if (STREQ(name, MAIL_ATTR_CLIENT_ADDR)) {
return (state->addr);
return (ACL_ADDR(state));
} else if (STREQ(name, MAIL_ATTR_CLIENT_NAME)) {
return (state->name);
return (ACL_NAME(state));
} else if (STREQ(name, MAIL_ATTR_HELO_NAME)) {
return (state->helo_name ? state->helo_name : "");
return (IS_UNK_HELO_NAME(ACL_HELO_NAME(state)) ?
"" : ACL_HELO_NAME(state));
} else if (STREQN(name, MAIL_ATTR_SENDER, CONST_LEN(MAIL_ATTR_SENDER))) {
return (smtpd_expand_addr(state->expand_buf, state->sender,
name, CONST_LEN(MAIL_ATTR_SENDER)));
@@ -2820,7 +2821,7 @@ static int reject_maps_rbl(SMTPD_STATE *state)
static int warned;
if (msg_verbose)
msg_info("%s: %s", myname, state->addr);
msg_info("%s: %s", myname, ACL_ADDR(state));
if (warned == 0) {
warned++;
@@ -2829,7 +2830,7 @@ static int reject_maps_rbl(SMTPD_STATE *state)
REJECT_MAPS_RBL, var_mail_name, REJECT_RBL_CLIENT);
}
while ((rbl_domain = mystrtok(&bp, " \t\r\n,")) != 0) {
result = reject_rbl_addr(state, rbl_domain, state->addr,
result = reject_rbl_addr(state, rbl_domain, ACL_ADDR(state),
SMTPD_NAME_CLIENT);
if (result != SMTPD_CHECK_DUNNO)
break;
@@ -2906,11 +2907,12 @@ static int check_policy_service(SMTPD_STATE *state, const char *server,
ATTR_FLAG_NONE, /* Query attributes. */
ATTR_TYPE_STR, MAIL_ATTR_REQ, "smtpd_access_policy",
ATTR_TYPE_STR, MAIL_ATTR_PROTO_STATE, state->where,
ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, state->protocol,
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, state->addr,
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, state->name,
ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, ACL_PROTOCOL(state),
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, ACL_ADDR(state),
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, ACL_NAME(state),
ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME,
state->helo_name ? state->helo_name : "",
IS_UNK_HELO_NAME(ACL_HELO_NAME(state)) ?
"" : ACL_HELO_NAME(state),
ATTR_TYPE_STR, MAIL_ATTR_SENDER,
state->sender ? state->sender : "",
ATTR_TYPE_STR, MAIL_ATTR_RECIP,
@@ -3075,8 +3077,8 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
} else if (strcasecmp(name, PERMIT_MYNETWORKS) == 0) {
status = permit_mynetworks(state);
} else if (is_map_command(state, name, CHECK_CLIENT_ACL, &cpp)) {
status = check_namadr_access(state, *cpp, state->name, state->addr,
FULL, &found, state->namaddr,
status = check_namadr_access(state, *cpp, ACL_NAME(state), ACL_ADDR(state),
FULL, &found, ACL_NAMADDR(state),
SMTPD_NAME_CLIENT, def_acl);
} else if (strcasecmp(name, REJECT_MAPS_RBL) == 0) {
status = reject_maps_rbl(state);
@@ -3085,7 +3087,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
if (cpp[1] == 0)
msg_warn("restriction %s requires domain name argument", name);
else
status = reject_rbl_addr(state, *(cpp += 1), state->addr,
status = reject_rbl_addr(state, *(cpp += 1), ACL_ADDR(state),
SMTPD_NAME_CLIENT);
} else if (strcasecmp(name, REJECT_RHSBL_CLIENT) == 0) {
if (cpp[1] == 0)
@@ -3093,69 +3095,73 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
name);
else {
cpp += 1;
if (strcasecmp(state->name, "unknown") != 0)
status = reject_rbl_domain(state, *cpp, state->name,
if (!IS_UNK_CLNT_NAME(ACL_NAME(state)))
status = reject_rbl_domain(state, *cpp, ACL_NAME(state),
SMTPD_NAME_CLIENT);
}
}
/*
* HELO/EHLO parameter restrictions.
*
* XXX With XCLIENT overrides, a zero-length name means the client did
* not send a HELO/EHLO command. Do not fall back to the non-XCLIENT
* HELO/EHLO value.
*/
else if (is_map_command(state, name, CHECK_HELO_ACL, &cpp)) {
if (state->helo_name)
status = check_domain_access(state, *cpp, state->helo_name,
FULL, &found, state->helo_name,
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state)))
status = check_domain_access(state, *cpp, ACL_HELO_NAME(state),
FULL, &found, ACL_HELO_NAME(state),
SMTPD_NAME_HELO, def_acl);
} else if (strcasecmp(name, REJECT_INVALID_HOSTNAME) == 0) {
if (state->helo_name) {
if (*state->helo_name != '[')
status = reject_invalid_hostname(state, state->helo_name,
state->helo_name, SMTPD_NAME_HELO);
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
if (*ACL_HELO_NAME(state) != '[')
status = reject_invalid_hostname(state, ACL_HELO_NAME(state),
ACL_HELO_NAME(state), SMTPD_NAME_HELO);
else
status = reject_invalid_hostaddr(state, state->helo_name,
state->helo_name, SMTPD_NAME_HELO);
status = reject_invalid_hostaddr(state, ACL_HELO_NAME(state),
ACL_HELO_NAME(state), SMTPD_NAME_HELO);
}
} else if (strcasecmp(name, REJECT_UNKNOWN_HOSTNAME) == 0) {
if (state->helo_name) {
if (*state->helo_name != '[')
status = reject_unknown_hostname(state, state->helo_name,
state->helo_name, SMTPD_NAME_HELO);
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
if (*ACL_HELO_NAME(state) != '[')
status = reject_unknown_hostname(state, ACL_HELO_NAME(state),
ACL_HELO_NAME(state), SMTPD_NAME_HELO);
else
status = reject_invalid_hostaddr(state, state->helo_name,
state->helo_name, SMTPD_NAME_HELO);
status = reject_invalid_hostaddr(state, ACL_HELO_NAME(state),
ACL_HELO_NAME(state), SMTPD_NAME_HELO);
}
} else if (strcasecmp(name, PERMIT_NAKED_IP_ADDR) == 0) {
msg_warn("restriction %s is deprecated. Use %s instead",
PERMIT_NAKED_IP_ADDR, PERMIT_MYNETWORKS);
if (state->helo_name) {
if (state->helo_name[strspn(state->helo_name, "0123456789.")] == 0
&& (status = reject_invalid_hostaddr(state, state->helo_name,
state->helo_name, SMTPD_NAME_HELO)) == 0)
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
if (ACL_HELO_NAME(state)[strspn(ACL_HELO_NAME(state), "0123456789.")] == 0
&& (status = reject_invalid_hostaddr(state, ACL_HELO_NAME(state),
ACL_HELO_NAME(state), SMTPD_NAME_HELO)) == 0)
status = SMTPD_CHECK_OK;
}
} else if (is_map_command(state, name, CHECK_HELO_NS_ACL, &cpp)) {
if (state->helo_name) {
status = check_server_access(state, *cpp, state->helo_name,
T_NS, state->helo_name,
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
status = check_server_access(state, *cpp, ACL_HELO_NAME(state),
T_NS, ACL_HELO_NAME(state),
SMTPD_NAME_HELO, def_acl);
forbid_whitelist(state, name, status, state->helo_name);
forbid_whitelist(state, name, status, ACL_HELO_NAME(state));
}
} else if (is_map_command(state, name, CHECK_HELO_MX_ACL, &cpp)) {
if (state->helo_name) {
status = check_server_access(state, *cpp, state->helo_name,
T_MX, state->helo_name,
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
status = check_server_access(state, *cpp, ACL_HELO_NAME(state),
T_MX, ACL_HELO_NAME(state),
SMTPD_NAME_HELO, def_acl);
forbid_whitelist(state, name, status, state->helo_name);
forbid_whitelist(state, name, status, ACL_HELO_NAME(state));
}
} else if (strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) {
if (state->helo_name) {
if (*state->helo_name != '[')
status = reject_non_fqdn_hostname(state, state->helo_name,
state->helo_name, SMTPD_NAME_HELO);
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state))) {
if (*ACL_HELO_NAME(state) != '[')
status = reject_non_fqdn_hostname(state, ACL_HELO_NAME(state),
ACL_HELO_NAME(state), SMTPD_NAME_HELO);
else
status = reject_invalid_hostaddr(state, state->helo_name,
state->helo_name, SMTPD_NAME_HELO);
status = reject_invalid_hostaddr(state, ACL_HELO_NAME(state),
ACL_HELO_NAME(state), SMTPD_NAME_HELO);
}
} else if (strcasecmp(name, REJECT_RHSBL_HELO) == 0) {
if (cpp[1] == 0)
@@ -3163,8 +3169,8 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
name);
else {
cpp += 1;
if (state->helo_name)
status = reject_rbl_domain(state, *cpp, state->helo_name,
if (!IS_UNK_HELO_NAME(ACL_HELO_NAME(state)))
status = reject_rbl_domain(state, *cpp, ACL_HELO_NAME(state),
SMTPD_NAME_HELO);
}
}
@@ -3361,7 +3367,7 @@ char *smtpd_check_client(SMTPD_STATE *state)
/*
* Initialize.
*/
if (state->name == 0 || state->addr == 0)
if (ACL_NAME(state) == 0 || ACL_ADDR(state) == 0)
return (0);
#define SMTPD_CHECK_RESET() { \
@@ -3381,7 +3387,7 @@ char *smtpd_check_client(SMTPD_STATE *state)
SMTPD_CHECK_RESET();
status = setjmp(smtpd_check_buf);
if (status == 0 && client_restrctions->argc)
status = generic_checks(state, client_restrctions, state->namaddr,
status = generic_checks(state, client_restrctions, ACL_NAMADDR(state),
SMTPD_NAME_CLIENT, CHECK_CLIENT_ACL);
state->defer_if_permit_client = state->defer_if_permit.active;
@@ -3435,7 +3441,7 @@ char *smtpd_check_helo(SMTPD_STATE *state, char *helohost)
SMTPD_CHECK_RESET();
status = setjmp(smtpd_check_buf);
if (status == 0 && helo_restrctions->argc)
status = generic_checks(state, helo_restrctions, state->helo_name,
status = generic_checks(state, helo_restrctions, ACL_HELO_NAME(state),
SMTPD_NAME_HELO, CHECK_HELO_ACL);
state->defer_if_permit_helo = state->defer_if_permit.active;
@@ -3547,7 +3553,7 @@ char *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient)
*/
if (var_smtpd_delay_reject)
if ((err = smtpd_check_client(state)) != 0
|| (err = smtpd_check_helo(state, state->helo_name)) != 0
|| (err = smtpd_check_helo(state, ACL_HELO_NAME(state))) != 0
|| (err = smtpd_check_mail(state, state->sender)) != 0)
SMTPD_CHECK_RCPT_RETURN(err);
@@ -3616,7 +3622,7 @@ char *smtpd_check_etrn(SMTPD_STATE *state, char *domain)
*/
if (var_smtpd_delay_reject)
if ((err = smtpd_check_client(state)) != 0
|| (err = smtpd_check_helo(state, state->helo_name)) != 0)
|| (err = smtpd_check_helo(state, ACL_HELO_NAME(state))) != 0)
SMTPD_CHECK_ETRN_RETURN(err);
/*
@@ -4316,7 +4322,7 @@ int main(int argc, char **argv)
if (args->argc == 4)
state.peer_code = atoi(args->argv[3]);
else
state.peer_code = 2;
state.peer_code = SMTPD_PEER_CODE_OK;
if (state.namaddr)
myfree(state.namaddr);
state.namaddr = concatenate(state.name, "[", state.addr,

View File

@@ -93,6 +93,7 @@ static int h_errno = TRY_AGAIN;
/* Global library. */
#include <mail_proto.h>
/* Application-specific. */
@@ -124,9 +125,9 @@ void smtpd_peer_init(SMTPD_STATE *state)
* If peer went away, give up.
*/
if (errno == ECONNRESET || errno == ECONNABORTED) {
state->name = mystrdup("unknown");
state->addr = mystrdup("unknown");
state->peer_code = 5;
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
state->addr = mystrdup(CLIENT_ADDR_UNKNOWN);
state->peer_code = SMTPD_PEER_CODE_PERM;
}
/*
@@ -137,26 +138,27 @@ void smtpd_peer_init(SMTPD_STATE *state)
hp = gethostbyaddr((char *) &(sin.sin_addr),
sizeof(sin.sin_addr), AF_INET);
if (hp == 0) {
state->name = mystrdup("unknown");
state->peer_code = (h_errno == TRY_AGAIN ? 4 : 5);
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
state->peer_code = (h_errno == TRY_AGAIN ?
SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
} else if (valid_hostaddr(hp->h_name, DONT_GRIPE)) {
msg_warn("numeric result %s in address->name lookup for %s",
hp->h_name, state->addr);
state->name = mystrdup("unknown");
state->peer_code = 5;
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
state->peer_code = SMTPD_PEER_CODE_PERM;
} else if (!valid_hostname(hp->h_name, DONT_GRIPE)) {
state->name = mystrdup("unknown");
state->peer_code = 5;
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
state->peer_code = SMTPD_PEER_CODE_PERM;
} else {
state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */
state->peer_code = 2;
state->peer_code = SMTPD_PEER_CODE_OK;
/*
* Reject the hostname if it does not list the peer address.
*/
#define REJECT_PEER_NAME(state, code) { \
myfree(state->name); \
state->name = mystrdup("unknown"); \
state->name = mystrdup(CLIENT_NAME_UNKNOWN); \
state->peer_code = code; \
}
@@ -164,17 +166,18 @@ void smtpd_peer_init(SMTPD_STATE *state)
if (hp == 0) {
msg_warn("%s: hostname %s verification failed: %s",
state->addr, state->name, HSTRERROR(h_errno));
REJECT_PEER_NAME(state, (h_errno == TRY_AGAIN ? 4 : 5));
REJECT_PEER_NAME(state, (h_errno == TRY_AGAIN ?
SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM));
} else if (hp->h_length != sizeof(sin.sin_addr)) {
msg_warn("%s: hostname %s verification failed: bad address size %d",
state->addr, state->name, hp->h_length);
REJECT_PEER_NAME(state, 5);
REJECT_PEER_NAME(state, SMTPD_PEER_CODE_PERM);
} else {
for (i = 0; /* void */ ; i++) {
if (hp->h_addr_list[i] == 0) {
msg_warn("%s: address not listed for hostname %s",
state->addr, state->name);
REJECT_PEER_NAME(state, 5);
REJECT_PEER_NAME(state, SMTPD_PEER_CODE_PERM);
break;
}
if (memcmp(hp->h_addr_list[i],
@@ -193,7 +196,7 @@ void smtpd_peer_init(SMTPD_STATE *state)
else {
state->name = mystrdup("localhost");
state->addr = mystrdup("127.0.0.1"); /* XXX bogus. */
state->peer_code = 2;
state->peer_code = SMTPD_PEER_CODE_OK;
}
/*

View File

@@ -51,12 +51,12 @@
/* have the same interface as the routines that are used for non-proxied
/* mail.
/*
/* smtpd_proxy_open() should be called after receiving the MAIL FROM
/* command. It connects to the proxy service, sends EHLO, sends the
/* MAIL FROM command, and receives the reply. A non-zero result means
/* smtpd_proxy_open() connects to the proxy service, sends EHLO, sends
/* client information with the XCLIENT command if possible, sends
/* the MAIL FROM command, and receives the reply. A non-zero result means
/* trouble: either the proxy is unavailable, or it did not send the
/* expected reply.
/* All results are reported via the state->proxy_buffer field in a form
/* The result is reported via the state->proxy_buffer field in a form
/* that can be sent to the SMTP client. In case of error, the
/* state->error_mask and state->err fields are updated.
/* A state->proxy_buffer field is created automatically; this field
@@ -155,6 +155,8 @@
#include <cleanup_user.h>
#include <mail_params.h>
#include <rec_type.h>
#include <xtext.h>
#include <mail_proto.h>
/* Application-specific. */
@@ -168,7 +170,7 @@
#define LEN(x) VSTRING_LEN(x)
#define SMTPD_PROXY_CONNECT ((char *) 0)
/* smtpd_proxy_open - open proxy connection after MAIL FROM */
/* smtpd_proxy_open - open proxy connection */
int smtpd_proxy_open(SMTPD_STATE *state, const char *service,
int timeout, const char *ehlo_name,
@@ -177,6 +179,8 @@ int smtpd_proxy_open(SMTPD_STATE *state, const char *service,
int fd;
char *lines;
char *line;
VSTRING *buf;
int bad;
/*
* This buffer persists beyond the end of a proxy session so we can
@@ -205,7 +209,8 @@ int smtpd_proxy_open(SMTPD_STATE *state, const char *service,
*
* If this fails then we have a problem because the proxy should always
* accept our connection. Make up our own response instead of passing
* back the greeting banner: the client expects a MAIL FROM reply.
* back the greeting banner: the proxy open might be delayed to the point
* that the client expects a MAIL FROM or RCPT TO reply.
*/
if (smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, SMTPD_PROXY_CONNECT) != 0) {
vstring_sprintf(state->proxy_buffer,
@@ -217,8 +222,9 @@ int smtpd_proxy_open(SMTPD_STATE *state, const char *service,
/*
* Send our own EHLO command. If this fails then we have a problem
* because the proxy should always accept our EHLO command. Make up our
* own response instead of passing back the EHLO reply: the client
* expects a MAIL FROM reply.
* own response instead of passing back the EHLO reply: the proxy open
* might be delayed to the point that the client expects a MAIL FROM or
* RCPT TO reply.
*/
if (smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, "EHLO %s", ehlo_name) != 0) {
vstring_sprintf(state->proxy_buffer,
@@ -228,17 +234,46 @@ int smtpd_proxy_open(SMTPD_STATE *state, const char *service,
}
/*
* Parse the EHLO reply and see if we can forward the client hostname and
* address info for logging purposes. If the command fails, then proceed.
* It is not the end of the world.
* Parse the EHLO reply and see if we can forward logging information.
*/
state->proxy_features = 0;
lines = STR(state->proxy_buffer);
while ((line = mystrtok(&lines, "\n")) != 0)
if (ISDIGIT(line[0]) && ISDIGIT(line[1]) && ISDIGIT(line[2])
&& (line[3] == ' ' || line[3] == '-')
&& strcmp(line + 4, XLOGINFO_CMD) == 0)
(void) smtpd_proxy_cmd(state, SMTPD_PROX_WANT_ANY, "%s %s %s",
XLOGINFO_CMD, state->addr, state->name);
&& strcmp(line + 4, XCLIENT_EHLO) == 0)
state->proxy_features |= SMTPD_FEATURE_XCLIENT;
/*
* Send our XCLIENT attributes. Transform internal forms to external
* forms and encode the result as xtext.
*/
if (state->proxy_features & SMTPD_FEATURE_XCLIENT) {
buf = vstring_alloc(100);
vstring_sprintf(buf, "%s LOG CLIENT_NAME=", XCLIENT_CMD);
if (!IS_UNK_CLNT_NAME(LOG_NAME(state)))
xtext_quote_append(buf, LOG_NAME(state), "");
vstring_strcat(buf, " CLIENT_ADDR=");
if (!IS_UNK_CLNT_ADDR(LOG_ADDR(state)))
xtext_quote_append(buf, LOG_ADDR(state), "");
bad = smtpd_proxy_cmd(state, SMTPD_PROX_WANT_ANY, "%s", STR(buf));
if (bad == 0) {
vstring_sprintf(buf, "%s HELO_NAME=", XCLIENT_CMD);
if (!IS_UNK_HELO_NAME(LOG_HELO_NAME(state)))
xtext_quote_append(buf, LOG_HELO_NAME(state), "");
vstring_strcat(buf, " PROTOCOL=");
if (!IS_UNK_PROTOCOL(LOG_PROTOCOL(state)))
xtext_quote_append(buf, LOG_PROTOCOL(state), "");
bad = smtpd_proxy_cmd(state, SMTPD_PROX_WANT_ANY, "%s", STR(buf));
}
vstring_free(buf);
if (bad) {
vstring_sprintf(state->proxy_buffer,
"451 Error: queue file write error");
smtpd_proxy_close(state);
return (-1);
}
}
/*
* Pass-through the client's MAIL FROM command. If this fails, then we

View File

@@ -198,7 +198,7 @@ void smtpd_sasl_mail_log(SMTPD_STATE *state)
#define IFELSE(e1,e2,e3) ((e1) ? (e2) : (e3))
msg_info("%s: client=%s%s%s%s%s%s%s",
state->queue_id, state->namaddr,
state->queue_id, LOG_NAMADDR(state),
IFELSE(state->sasl_method, ", sasl_method=", ""),
IFELSE(state->sasl_method, state->sasl_method, ""),
IFELSE(state->sasl_username, ", sasl_username=", ""),

View File

@@ -85,6 +85,7 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
state->history = 0;
state->reason = 0;
state->sender = 0;
state->verp_delims = 0;
state->recipient = 0;
state->etrn_name = 0;
state->protocol = MAIL_PROTO_SMTP;
@@ -101,6 +102,8 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
state->expand_buf = 0;
state->proxy = 0;
state->proxy_buffer = 0;
state->proxy_mail = 0;
state->proxy_features = 0;
#ifdef USE_SASL_AUTH
if (SMTPD_STAND_ALONE(state))
@@ -114,6 +117,11 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
*/
smtpd_peer_init(state);
/*
* Initialize xclient information.
*/
smtpd_xclient_init(state);
/*
* Initialize the conversation history.
*/
@@ -133,6 +141,7 @@ void smtpd_state_reset(SMTPD_STATE *state)
if (state->buffer)
vstring_free(state->buffer);
smtpd_peer_reset(state);
smtpd_xclient_reset(state, XCLIENT_OVER_NONE);
if (state->defer_if_permit.reason)
vstring_free(state->defer_if_permit.reason);
if (state->defer_if_reject.reason)

View File

@@ -0,0 +1,116 @@
/*++
/* NAME
/* smtpd_xclient 3
/* SUMMARY
/* maintain XCLIENT information
/* SYNOPSIS
/* #include "smtpd.h"
/*
/* void smtpd_xclient_init(state)
/* SMTPD_STATE *state;
/*
/* void smtpd_xclient_reset(state, mode)
/* SMTPD_STATE *state;
/* int mode;
/* DESCRIPTION
/* smtpd_xclient_init() initializes state variables that are
/* used for storage of XCLIENT command parameters.
/* These variables override specific members of the global state
/* structure for access control or logging purposes.
/*
/* smtpd_xclient_reset() releases memory allocated after the return
/* from smtpd_xclient_init() and optionally presets the state variables
/* to defaults that are suitable for the specified mode:
/* .IP XCLIENT_OVER_NONE
/* This should be used after the XCLIENT RST request.
/* .IP XCLIENT_OVER_ACL|XCLIENT_OVER_LOG
/* This should be used after the XCLIENT ACL request.
/* .IP XCLIENT_OVER_LOG
/* This should be used after the XCLIENT LOG request.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
/* Utility library. */
#include <mymalloc.h>
#include <msg.h>
/* Global library. */
#include <mail_proto.h>
/* Application-specific. */
#include <smtpd.h>
/* smtpd_xclient_init - initialize XCLIENT attributes */
void smtpd_xclient_init(SMTPD_STATE *state)
{
state->xclient.mode = 0;
state->xclient.name = 0;
state->xclient.addr = 0;
state->xclient.namaddr = 0;
state->xclient.peer_code = 0;
state->xclient.protocol = 0;
state->xclient.helo_name = 0;
}
/* smtpd_xclient_reset - reset XCLIENT attributes */
void smtpd_xclient_reset(SMTPD_STATE *state, int mode)
{
switch (mode) {
/*
* Can't happen.
*/
default:
msg_panic("smtpd_xclient_reset: unknown mode 0x%x", mode);
/*
* Restore smtpd_xclient_init() result. Allow selective override.
* This is desirable for access rule testing.
*/
#define FREE_AND_WIPE(s) { if (s) { myfree(s); s = 0; } }
case XCLIENT_OVER_NONE:
case XCLIENT_OVER_ACL | XCLIENT_OVER_LOG:
FREE_AND_WIPE(state->xclient.name);
FREE_AND_WIPE(state->xclient.addr);
FREE_AND_WIPE(state->xclient.namaddr);
state->xclient.peer_code = 0;
FREE_AND_WIPE(state->xclient.protocol);
FREE_AND_WIPE(state->xclient.helo_name);
break;
/*
* Non-selective override. Set all attributes to "unknown". This is
* desirable to avoid polluting the audit trail with data from mixed
* origins.
*/
#define FREE_AND_DUP(s,v) { if (s) { myfree(s); s = mystrdup(v); } }
case XCLIENT_OVER_LOG:
FREE_AND_DUP(state->xclient.name, CLIENT_NAME_UNKNOWN);
FREE_AND_DUP(state->xclient.addr, CLIENT_ADDR_UNKNOWN);
FREE_AND_DUP(state->xclient.namaddr, CLIENT_NAMADDR_UNKNOWN);
state->xclient.peer_code = 0;
FREE_AND_DUP(state->xclient.protocol, PROTOCOL_UNKNOWN);
FREE_AND_DUP(state->xclient.helo_name, HELO_NAME_UNKNOWN);
break;
}
state->xclient.mode = mode;
}

View File

@@ -3,9 +3,6 @@ SRCS = smtp-source.c smtp-sink.c qmqp-source.c qmqp-sink.c
OBJS = smtp-source.o smtp-sink.o qmqp-source.o qmqp-sink.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -3,9 +3,6 @@ SRCS = spawn.c
OBJS = spawn.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -3,9 +3,6 @@ SRCS = trivial-rewrite.c rewrite.c resolve.c transport.c
OBJS = trivial-rewrite.o rewrite.o resolve.o transport.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
LIB =

View File

@@ -27,7 +27,7 @@ SRCS = alldig.c argv.c argv_split.c attr_print0.c attr_print64.c \
username.c valid_hostname.c vbuf.c vbuf_print.c vstream.c \
vstream_popen.c vstring.c vstring_vstream.c watchdog.c writable.c \
write_buf.c write_wait.c auto_clnt.c attr_clnt.c attr_scan_plain.c \
attr_print_plain.c sane_connect.c
attr_print_plain.c sane_connect.c neuter.c
OBJS = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
attr_scan0.o attr_scan64.o base64_code.o basename.o binhash.o \
chroot_uid.o clean_env.o close_on_exec.o concatenate.o ctable.o \
@@ -56,7 +56,7 @@ OBJS = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
username.o valid_hostname.o vbuf.o vbuf_print.o vstream.o \
vstream_popen.o vstring.o vstring_vstream.o watchdog.o writable.o \
write_buf.o write_wait.o auto_clnt.o attr_clnt.o attr_scan_plain.o \
attr_print_plain.o sane_connect.o $(STRCASE)
attr_print_plain.o sane_connect.o $(STRCASE) neuter.o
HDRS = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
connect.h ctable.h dict.h dict_db.h dict_dbm.h dict_env.h \
dict_cidr.h dict_ht.h dict_ldap.h dict_mysql.h dict_ni.h dict_nis.h \
@@ -78,9 +78,6 @@ HDRS = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
auto_clnt.h attr_clnt.h sane_connect.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
FILES = Makefile $(SRCS) $(HDRS)
@@ -1046,6 +1043,11 @@ netstring.o: vstream.h
netstring.o: vbuf.h
netstring.o: vstring.h
netstring.o: netstring.h
neuter.o: neuter.c
neuter.o: sys_defs.h
neuter.o: stringops.h
neuter.o: vstring.h
neuter.o: vbuf.h
non_blocking.o: non_blocking.c
non_blocking.o: sys_defs.h
non_blocking.o: msg.h

56
postfix/src/util/neuter.c Normal file
View File

@@ -0,0 +1,56 @@
/*++
/* NAME
/* neuter 3
/* SUMMARY
/* mask non-neuter characters
/* SYNOPSIS
/* #include <stringops.h>
/*
/* char *neuter(buffer, bad, replacement)
/* char *buffer;
/* const char *bad;
/* int replacement;
/* DESCRIPTION
/* neuter() replaces bad characters in its input
/* by the given replacement.
/*
/* Arguments:
/* .IP buffer
/* The null-terminated input string.
/* .IP bad
/* The null-terminated bad character string.
/* .IP replacement
/* Replacement value for characters in \fIbuffer\fR that do not
/* pass the bad character test.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <string.h>
/* Utility library. */
#include <stringops.h>
/* neuter - neutralize bad characters */
char *neuter(char *string, const char *bad, int replacement)
{
char *cp;
int ch;
for (cp = string; (ch = *(unsigned char *) cp) != 0; cp++)
if (strchr(bad, ch) != 0)
*cp = replacement;
return (string);
}

View File

@@ -20,6 +20,7 @@
* External interface.
*/
extern char *printable(char *, int);
extern char *neuter(char *, const char *, int);
extern char *lowercase(char *);
extern char *skipblanks(const char *);
extern char *trimblanks(char *, int);

View File

@@ -59,18 +59,39 @@
#define NATIVE_DAEMON_DIR "/usr/libexec/postfix"
#endif
#if defined(FREEBSD2) || defined(FREEBSD3) || defined(FREEBSD4)
#define HAS_DUPLEX_PIPE
#endif
/* __FreeBSD_version version is major+minor */
#if defined(OPENBSD2) || defined(OPENBSD3) \
|| defined(FREEBSD3) || defined(FREEBSD4)
#if __FreeBSD_version >= 200000
#define HAS_DUPLEX_PIPE
#define HAS_ISSETUGID
#endif
#if defined(NETBSD1)
#if __FreeBSD_version >= 400000
#define SOCKADDR_SIZE socklen_t
#define SOCKOPT_SIZE socklen_t
#endif
/* OpenBSD version is year+month */
#if OpenBSD >= 200000 /* XXX */
#define HAS_ISSETUGID
#endif
#if OpenBSD >= 200200 /* XXX */
#define SOCKADDR_SIZE socklen_t
#define SOCKOPT_SIZE socklen_t
#endif
/* __NetBSD_Version__ is major+minor */
#if __NetBSD_Version__ >= 103000000 /* XXX */
#undef DEF_MAILBOX_LOCK
#define DEF_MAILBOX_LOCK "flock, dotlock"
#endif
#if __NetBSD_Version__ >= 106000000 /* XXX */
#define SOCKADDR_SIZE socklen_t
#define SOCKOPT_SIZE socklen_t
#endif
/*
@@ -493,6 +514,7 @@ extern int initgroups(const char *, int);
#ifdef LINUX2
#define SUPPORTED
#include <sys/types.h>
#include <features.h>
#define USE_PATHS_H
#define HAS_FLOCK_LOCK
#define HAS_FCNTL_LOCK
@@ -516,6 +538,10 @@ extern int initgroups(const char *, int);
#define NATIVE_NEWALIAS_PATH "/usr/bin/newaliases"
#define NATIVE_COMMAND_DIR "/usr/sbin"
#define NATIVE_DAEMON_DIR "/usr/libexec/postfix"
#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
#define SOCKADDR_SIZE socklen_t
#define SOCKOPT_SIZE socklen_t
#endif
#endif
#ifdef LINUX1
@@ -908,6 +934,9 @@ extern int dup2_pass_on_exec(int oldd, int newd);
#endif
#define OPTIND (optind > 0 ? optind : 1)
/*
* Check for required but missing definitions.
*/
#if !defined(HAS_FCNTL_LOCK) && !defined(HAS_FLOCK_LOCK)
#error "define HAS_FCNTL_LOCK and/or HAS_FLOCK_LOCK"
#endif
@@ -929,7 +958,7 @@ extern int dup2_pass_on_exec(int oldd, int newd);
#endif
/*
* Defaults for normal systems.
* Defaults for systems that pre-date POSIX socklen_t.
*/
#ifndef SOCKADDR_SIZE
#define SOCKADDR_SIZE int
@@ -939,6 +968,9 @@ extern int dup2_pass_on_exec(int oldd, int newd);
#define SOCKOPT_SIZE int
#endif
/*
* Defaults for normal systems.
*/
#ifndef LOCAL_LISTEN
#define LOCAL_LISTEN unix_listen
#define LOCAL_ACCEPT unix_accept

View File

@@ -3,9 +3,6 @@ SRCS = verify.c
OBJS = verify.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=

View File

@@ -3,9 +3,6 @@ SRCS = virtual.c mailbox.c recipient.c deliver_attr.c maildir.c unknown.c
OBJS = virtual.o mailbox.o recipient.o deliver_attr.o maildir.o unknown.o
HDRS = virtual.h
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-Wunused
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
PROG = virtual