mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-29 13:18:12 +00:00
postfix-2.0.16-20031201
This commit is contained in:
parent
edb9945f66
commit
e0c65a2f44
@ -8778,13 +8778,13 @@ Apologies for any names omitted.
|
||||
logs more specific information. File: master/master_ent.c.
|
||||
Reported by several people.
|
||||
|
||||
20031125-8
|
||||
20031125-20031201
|
||||
|
||||
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
|
||||
Remotely based on code by Victor Duchovni. Files:
|
||||
smtpd/{smtpd,smtpd_check,smtpd_proxy,smtpd_xclient}.c
|
||||
smtp/smtp_smtp_proto.c, *qmgr/qmgr_message.c,
|
||||
global/deliver_request.c.
|
||||
|
||||
|
@ -3,49 +3,42 @@ 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.
|
||||
1 - Access control tests. SMTP server access rules can be difficult
|
||||
to verify when decisions can be triggered by remote clients only.
|
||||
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.
|
||||
the SMTP client hostname, network address, and other information,
|
||||
for the entire duration of an SMTP session.
|
||||
|
||||
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. To simplify
|
||||
the interpretation of MTA2 logging, it would help if MTA1 could
|
||||
forward client information through the content filter to MTA2.
|
||||
forward client information through the content filter to MTA2, for
|
||||
a single message delivery.
|
||||
|
||||
3 - Post-filter access control and logging. With Internet->filter->MTA
|
||||
style content filter applications, the filter can be simplified if
|
||||
it can delegate decisions concerning mail relay and other access
|
||||
control to the MTA. As in the first example, this requires that
|
||||
the filter can override the MTA's idea of the SMTP client hostname,
|
||||
network address, and other information.
|
||||
|
||||
The preceding suggests that there is a need for two functions:
|
||||
|
||||
1 - Override the MTA's idea of SMTP client information for access
|
||||
control and other purposes. This function is generally useful
|
||||
for trouble shooting. The implementation can be relatively
|
||||
straightforward because it updates already existing attributes.
|
||||
|
||||
2 - Forward remote client information for logging purposes. This
|
||||
function is limited mainly to environments that use SMTP-based
|
||||
content filters. The implementation requires more invasive
|
||||
changes to the MTA to store the additional attributes and to
|
||||
choose between the normal attributes and the forwarded ones.
|
||||
network address, and other information, for the entire duration of
|
||||
an SMTP session.
|
||||
|
||||
Command overview
|
||||
================
|
||||
|
||||
The EHLO keyword associated with this extension is XCLIENT.
|
||||
XCLIENT is an extension to SMTP. The EHLO keyword associated with
|
||||
this extension is XCLIENT.
|
||||
|
||||
The XCLIENT OVERRIDE command updates the remote client attributes
|
||||
that the MTA normally uses for access control, message headers,
|
||||
logging and so on, while the XCLIENT FORWARD command maintains an
|
||||
additional set of attributes that is meant to be used for logging
|
||||
purposes. In the absence of forwarded attributes the MTA must use
|
||||
the normal remote client attribute values.
|
||||
logging and so on, for the duration of an entire SMTP session.
|
||||
|
||||
The XCLIENT FORWARD command maintains an additional set of attributes
|
||||
that concern only one message delivery attempt. In the absence of
|
||||
forwarded attributes the MTA must use the normal remote client
|
||||
attribute values.
|
||||
|
||||
The general command syntax is described below. Upper case and
|
||||
quoted strings specify terminals, lowercase strings specify meta
|
||||
@ -59,7 +52,7 @@ case, they are in fact case insensitive.
|
||||
|
||||
attribute = name"="value
|
||||
|
||||
name = ( CLIENT_NAME | CLIENT_ADDR | CLIENT_CODE | PROTOCOL | HELO_NAME )
|
||||
name = ( CLIENT_NAME|CLIENT_ADDR|CLIENT_CODE|CLIENT_PROTO|CLIENT_HELO )
|
||||
|
||||
value = ( { empty } | xtext )
|
||||
|
||||
@ -88,10 +81,11 @@ Specific usage scenarios
|
||||
This section discusses the semantics of XCLIENT requests. Specific
|
||||
syntax details are given in the next section.
|
||||
|
||||
The XCLIENT OVERRIDE request modifies the attributes that the MTA
|
||||
normally uses for access control, message headers, logging, and
|
||||
for other purposes. Attributes that are not specified in XCLIENT
|
||||
OVERRIDE requests are not modified.
|
||||
The XCLIENT OVERRIDE request modifies remote client attributes that
|
||||
the MTA normally uses for access control, message headers, logging,
|
||||
and for other purposes, for the duraction of the entire SMTP session.
|
||||
Attributes that are not specified in XCLIENT OVERRIDE requests are
|
||||
not modified.
|
||||
|
||||
The following example overrides only the client hostname and network
|
||||
address, leaving unchanged all other client attributes such as the
|
||||
@ -100,21 +94,23 @@ mail protocol or the hostname given in the HELO command:
|
||||
XCLIENT OVERRIDE CLIENT_NAME=spike.porcupine.org
|
||||
XCLIENT OVERRIDE CLIENT_ADDR=168.100.189.2
|
||||
|
||||
The XCLIENT FORWARD request specifies surrogate client attributes for
|
||||
logging purposes. In the absence of any XCLIENT FORWARD attributes, the
|
||||
MTA must use the normal client attributes.
|
||||
The XCLIENT FORWARD request specifies remote client attributes
|
||||
concerning only one message delivery attempt. The attributes are
|
||||
discarded after the next MAIL FROM transaction finishes. In the
|
||||
absence of any XCLIENT FORWARD attributes, the MTA must use the
|
||||
normal client attributes.
|
||||
|
||||
If only a subset of all possible XCLIENT FORWARD attributes is
|
||||
specified, the unspecified attributes must either not be logged at
|
||||
all, or they must be logged as if they are unknown. This avoids
|
||||
the logging of attributes from mixed origins.
|
||||
specified, the unspecified attributes must be treated as if they
|
||||
are unknown. The implementation must not replace missing XCLIENT
|
||||
FORWARD attributes by normal attributes.
|
||||
|
||||
The following example updates all forwarded client attributes that
|
||||
are defined in this document, leaving none at their default unknown
|
||||
value:
|
||||
|
||||
XCLIENT FORWARD CLIENT_NAME=spike.porcupine.org CLIENT_ADDR=168.100.189.2
|
||||
XCLIENT FORWARD HELO_NAME=spike.porcupine.org PROTOCOL=ESMTP
|
||||
XCLIENT FORWARD CLIENT_HELO=spike.porcupine.org CLIENT_PROTO=ESMTP
|
||||
|
||||
Note 1: attributes specified with successive XCLIENT commands
|
||||
accumulate.
|
||||
@ -126,34 +122,36 @@ 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 must not send its own internal representation of unknown
|
||||
information.
|
||||
specify that an attribute value is unavailable, the value must be
|
||||
empty; the client must not send its own internal representation of
|
||||
unavailable 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 automatically set to
|
||||
the unknown value.
|
||||
The CLIENT_CODE attribute 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
|
||||
automatically 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
|
||||
implicitly set to PERM. When a valid domain name is specified,
|
||||
CLIENT_CODE is implicitly set to OK. The server may process a
|
||||
syntactically invalid domain name as if it were unknown.
|
||||
The CLIENT_NAME attribute 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 implicitly set to PERM. When a valid domain name is
|
||||
specified, CLIENT_CODE is implicitly 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 [].
|
||||
The CLIENT_ADDR attribute must specify a numerical network address
|
||||
without [].
|
||||
|
||||
PROTOCOL is a string of up to 64 printable characters, where
|
||||
printable is defined by the ANSI C isascii() and isprint() predicates.
|
||||
The CLIENT_PROTO attribute should be a string of up to 64 printable
|
||||
characters, where printable is defined by the ANSI C isascii() and
|
||||
isprint() predicates.
|
||||
|
||||
HELO_NAME should be a syntactically valid HELO parameter value.
|
||||
The CLIENT_HELO attribute should be a syntactically valid HELO
|
||||
parameter value.
|
||||
|
||||
Note 3: syntactically valid CLIENT_NAME and HELO_NAME attributes
|
||||
can be up to 255 characters long. The client must not send XCLIENT OVERRIDE
|
||||
or XCLIENT FORWARD commands that exceed the 512 character limit of SMTP
|
||||
commands.
|
||||
Note 3: syntactically valid CLIENT_NAME and CLIENT_HELO attributes
|
||||
can be up to 255 characters long. The client must not send XCLIENT
|
||||
commands that exceed the 512 character limit of SMTP commands.
|
||||
|
||||
Note 4: attribute values may end up in Received: or other message
|
||||
headers. The receiving MTA may substitute characters in order to
|
||||
@ -175,6 +173,5 @@ 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. Applications should ensure that XCLIENT information from
|
||||
one remote client is properly updated before commencing delivery
|
||||
of mail from a different remote client.
|
||||
clients. The XCLIENT FORWARD attributes are reset after the MAIL
|
||||
FROM command completes, so there is no risk of information leakage.
|
||||
|
@ -1,4 +1,4 @@
|
||||
<html> <head> </head> <body> <pre>
|
||||
<html> <body> <pre>
|
||||
QMQPD(8) QMQPD(8)
|
||||
|
||||
<b>NAME</b>
|
||||
@ -44,72 +44,72 @@ QMQPD(8) QMQPD(8)
|
||||
command after a configuration change.
|
||||
|
||||
<b>Miscellaneous</b>
|
||||
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>level</b>
|
||||
<b>debug_peer_level</b>
|
||||
Increment in verbose logging level when a remote
|
||||
host matches a pattern in the <b>debug</b><i>_</i><b>peer</b><i>_</i><b>list</b>
|
||||
host matches a pattern in the <b>debug_peer_list</b>
|
||||
parameter.
|
||||
|
||||
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>list</b>
|
||||
<b>debug_peer_list</b>
|
||||
List of domain or network patterns. When a remote
|
||||
host matches a pattern, increase the verbose log-
|
||||
ging level by the amount specified in the
|
||||
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>level</b> parameter.
|
||||
<b>debug_peer_level</b> parameter.
|
||||
|
||||
<b>hopcount</b><i>_</i><b>limit</b>
|
||||
<b>hopcount_limit</b>
|
||||
Limit the number of <b>Received:</b> message headers.
|
||||
|
||||
<b>qmqpd</b><i>_</i><b>authorized</b><i>_</i><b>clients</b>
|
||||
<b>qmqpd_authorized_clients</b>
|
||||
A list of domain or network patterns that specifies
|
||||
what clients are allowed to use the service.
|
||||
|
||||
<b>qmqpd</b><i>_</i><b>timeout</b>
|
||||
<b>qmqpd_timeout</b>
|
||||
Limit the time to send a server response and to
|
||||
receive a client request.
|
||||
|
||||
<b>soft</b><i>_</i><b>bounce</b>
|
||||
<b>soft_bounce</b>
|
||||
Change hard (D) reject responses into soft (Z)
|
||||
reject responses. This can be useful for testing
|
||||
purposes.
|
||||
|
||||
<b>Content inspection controls</b>
|
||||
<b>content</b><i>_</i><b>filter</b>
|
||||
<b>content_filter</b>
|
||||
The name of a mail delivery transport that filters
|
||||
mail and that either bounces mail or re-injects the
|
||||
result back into Postfix. This parameter uses the
|
||||
same syntax as the right-hand side of a Postfix
|
||||
transport table.
|
||||
|
||||
<b>receive</b><i>_</i><b>override</b><i>_</i><b>options</b>
|
||||
<b>receive_override_options</b>
|
||||
The following options override <b>main.cf</b> settings.
|
||||
The options are passed on to the downstream cleanup
|
||||
server.
|
||||
|
||||
<b>no</b><i>_</i><b>address</b><i>_</i><b>mappings</b>
|
||||
<b>no_address_mappings</b>
|
||||
Disable canonical address mapping, virtual
|
||||
alias map expansion, address masquerading,
|
||||
and automatic BCC recipients. Specify this
|
||||
if address mapping etc. are to be done <b>after</b>
|
||||
an external content filter.
|
||||
|
||||
<b>no</b><i>_</i><b>header</b><i>_</i><b>body</b><i>_</i><b>checks</b>
|
||||
<b>no_header_body_checks</b>
|
||||
Disable header/body_checks. Specify this if
|
||||
header/body_checks are to be done <b>after</b> an
|
||||
external content filter.
|
||||
|
||||
<b>Resource controls</b>
|
||||
<b>line</b><i>_</i><b>length</b><i>_</i><b>limit</b>
|
||||
<b>line_length_limit</b>
|
||||
Limit the amount of memory in bytes used for the
|
||||
handling of partial input lines, and the length of
|
||||
sender and recipient addresses that are received
|
||||
from client.
|
||||
|
||||
<b>message</b><i>_</i><b>size</b><i>_</i><b>limit</b>
|
||||
<b>message_size_limit</b>
|
||||
Limit the total size in bytes of a message, includ-
|
||||
ing on-disk storage for sender and recipient
|
||||
address information.
|
||||
|
||||
<b>Tarpitting</b>
|
||||
<b>qmqpd</b><i>_</i><b>error</b><i>_</i><b>delay</b>
|
||||
<b>qmqpd_error_delay</b>
|
||||
Time to wait in seconds before informing the client
|
||||
of a problem. This slows down run-away errors.
|
||||
|
||||
|
@ -46,6 +46,15 @@ typedef struct DELIVER_REQUEST {
|
||||
char *client_helo; /* helo parameter */
|
||||
} DELIVER_REQUEST;
|
||||
|
||||
/*
|
||||
* Since we can't send null pointers, null strings represent unavailable
|
||||
* attributes instead. They're less likely to explode in our face, too.
|
||||
*/
|
||||
#define DEL_REQ_ATTR_UNAVAIL(a) (*(a))
|
||||
|
||||
/*
|
||||
* How to deliver, really?
|
||||
*/
|
||||
#define DEL_REQ_FLAG_DEFLT (DEL_REQ_FLAG_SUCCESS | DEL_REQ_FLAG_BOUNCE)
|
||||
#define DEL_REQ_FLAG_SUCCESS (1<<0) /* delete successful recipients */
|
||||
#define DEL_REQ_FLAG_BOUNCE (1<<1) /* unimplemented */
|
||||
|
@ -159,27 +159,33 @@ extern char *mail_pathname(const char *, const char *);
|
||||
#define XCLIENT_FORWARD "FORWARD" /* forward function */
|
||||
#define XCLIENT_NAME "CLIENT_NAME" /* client name */
|
||||
#define XCLIENT_ADDR "CLIENT_ADDR" /* client address */
|
||||
#define XCLIENT_PROTO "PROTOCOL" /* client protocol */
|
||||
#define XCLIENT_PROTO "CLIENT_PROTO" /* client protocol */
|
||||
#define XCLIENT_CODE "CLIENT_CODE" /* client name status */
|
||||
#define XCLIENT_HELO "HELO_NAME" /* client helo */
|
||||
#define XCLIENT_HELO "CLIENT_HELO" /* client helo */
|
||||
|
||||
/*
|
||||
* Internal forms for unknown XCLIENT information.
|
||||
* This is how Postfix represents unknown client information within smtpd or
|
||||
* qmqpd processes.
|
||||
*
|
||||
* This is not the representation that Postfix uses in queue files, in queue
|
||||
* manager delivery requests, nor is it the representation of information in
|
||||
* XCLIENT commands!
|
||||
*/
|
||||
#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"
|
||||
#define CLIENT_ATTR_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))
|
||||
#define CLIENT_NAME_UNKNOWN CLIENT_ATTR_UNKNOWN
|
||||
#define CLIENT_ADDR_UNKNOWN CLIENT_ATTR_UNKNOWN
|
||||
#define CLIENT_NAMADDR_UNKNOWN CLIENT_ATTR_UNKNOWN
|
||||
#define CLIENT_HELO_UNKNOWN 0
|
||||
#define CLIENT_PROTO_UNKNOWN CLIENT_ATTR_UNKNOWN
|
||||
|
||||
#define IS_UNK_CLIENT_ATTR(v) (!(v) || !strcmp((v), CLIENT_ATTR_UNKNOWN))
|
||||
|
||||
#define IS_UNK_CLIENT_NAME(v) IS_UNK_CLIENT_ATTR(v)
|
||||
#define IS_UNK_CLIENT_ADDR(v) IS_UNK_CLIENT_ATTR(v)
|
||||
#define IS_UNK_CLIENT_NAMADDR(v) IS_UNK_CLIENT_ATTR(v)
|
||||
#define IS_UNK_CLIENT_HELO(v) (!(v))
|
||||
#define IS_UNK_CLIENT_PROTO(v) IS_UNK_CLIENT_ATTR(v)
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
|
@ -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 "20031130"
|
||||
#define MAIL_RELEASE_DATE "20031201"
|
||||
|
||||
#define VAR_MAIL_VERSION "mail_version"
|
||||
#define DEF_MAIL_VERSION "2.0.16-" MAIL_RELEASE_DATE
|
||||
|
@ -612,13 +612,13 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
|
||||
if (message->encoding == 0)
|
||||
message->encoding = mystrdup(MAIL_ATTR_ENC_NONE);
|
||||
if (message->client_name == 0)
|
||||
message->client_name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||
message->client_name = mystrdup("");
|
||||
if (message->client_addr == 0)
|
||||
message->client_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
|
||||
message->client_addr = mystrdup("");
|
||||
if (message->client_proto == 0)
|
||||
message->client_proto = mystrdup(PROTOCOL_UNKNOWN);
|
||||
message->client_proto = mystrdup("");
|
||||
if (message->client_helo == 0)
|
||||
message->client_helo = mystrdup(HELO_NAME_UNKNOWN);
|
||||
message->client_helo = mystrdup("");
|
||||
|
||||
/*
|
||||
* Clean up.
|
||||
@ -1130,6 +1130,14 @@ void qmgr_message_free(QMGR_MESSAGE *message)
|
||||
myfree(message->inspect_xport);
|
||||
if (message->redirect_addr)
|
||||
myfree(message->redirect_addr);
|
||||
if (message->client_name)
|
||||
myfree(message->client_name);
|
||||
if (message->client_addr)
|
||||
myfree(message->client_addr);
|
||||
if (message->client_proto)
|
||||
myfree(message->client_proto);
|
||||
if (message->client_helo)
|
||||
myfree(message->client_helo);
|
||||
qmgr_rcpt_list_free(&message->rcpt_list);
|
||||
qmgr_message_count--;
|
||||
myfree((char *) message);
|
||||
|
@ -577,13 +577,13 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
|
||||
if (message->encoding == 0)
|
||||
message->encoding = mystrdup(MAIL_ATTR_ENC_NONE);
|
||||
if (message->client_name == 0)
|
||||
message->client_name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||
message->client_name = mystrdup("");
|
||||
if (message->client_addr == 0)
|
||||
message->client_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
|
||||
message->client_addr = mystrdup("");
|
||||
if (message->client_proto == 0)
|
||||
message->client_proto = mystrdup(PROTOCOL_UNKNOWN);
|
||||
message->client_proto = mystrdup("");
|
||||
if (message->client_helo == 0)
|
||||
message->client_helo = mystrdup(HELO_NAME_UNKNOWN);
|
||||
message->client_helo = mystrdup("");
|
||||
|
||||
/*
|
||||
* Clean up.
|
||||
@ -1024,6 +1024,14 @@ void qmgr_message_free(QMGR_MESSAGE *message)
|
||||
myfree(message->inspect_xport);
|
||||
if (message->redirect_addr)
|
||||
myfree(message->redirect_addr);
|
||||
if (message->client_name)
|
||||
myfree(message->client_name);
|
||||
if (message->client_addr)
|
||||
myfree(message->client_addr);
|
||||
if (message->client_proto)
|
||||
myfree(message->client_proto);
|
||||
if (message->client_helo)
|
||||
myfree(message->client_helo);
|
||||
qmgr_rcpt_list_free(&message->rcpt_list);
|
||||
qmgr_message_count--;
|
||||
myfree((char *) message);
|
||||
|
@ -285,10 +285,12 @@ static void qmqpd_copy_sender(QMQPD_STATE *state)
|
||||
|
||||
static void qmqpd_write_attributes(QMQPD_STATE *state)
|
||||
{
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_CLIENT_NAME, state->name);
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_CLIENT_ADDR, state->addr);
|
||||
if (!IS_UNK_CLIENT_NAME(state->name))
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_CLIENT_NAME, state->name);
|
||||
if (!IS_UNK_CLIENT_ADDR(state->addr))
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_CLIENT_ADDR, state->addr);
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_ORIGIN, state->namaddr);
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
|
@ -484,11 +484,14 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
* commands rejected, DATA rejected) it forces the sender to abort the
|
||||
* SMTP dialog with RSET and QUIT.
|
||||
*
|
||||
* Update the server's remote client information to avoid leakage of past
|
||||
* client attributes into an unrelated mail delivery.
|
||||
* Use the XCLIENT command to forward client attributes only when a minimal
|
||||
* amount of information is available.
|
||||
*/
|
||||
nrcpt = 0;
|
||||
if (var_smtp_send_xclient && (state->features & SMTP_FEATURE_XCLIENT))
|
||||
if (var_smtp_send_xclient
|
||||
&& (state->features & SMTP_FEATURE_XCLIENT)
|
||||
&& !DEL_REQ_ATTR_UNAVAIL(request->client_name)
|
||||
&& !DEL_REQ_ATTR_UNAVAIL(request->client_addr))
|
||||
recv_state = send_state = SMTP_STATE_XCLIENT_ADDR;
|
||||
else
|
||||
recv_state = send_state = SMTP_STATE_MAIL;
|
||||
@ -516,10 +519,10 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
case SMTP_STATE_XCLIENT_ADDR:
|
||||
vstring_strcpy(next_command,
|
||||
XCLIENT_CMD " " XCLIENT_FORWARD " " XCLIENT_NAME "=");
|
||||
if (!IS_UNK_CLNT_NAME(request->client_name))
|
||||
if (!DEL_REQ_ATTR_UNAVAIL(request->client_name))
|
||||
xtext_quote_append(next_command, request->client_name, "");
|
||||
vstring_strcat(next_command, " " XCLIENT_ADDR "=");
|
||||
if (!IS_UNK_CLNT_ADDR(request->client_addr))
|
||||
if (!DEL_REQ_ATTR_UNAVAIL(request->client_addr))
|
||||
xtext_quote_append(next_command, request->client_addr, "");
|
||||
next_state = SMTP_STATE_XCLIENT_HELO;
|
||||
break;
|
||||
@ -527,10 +530,10 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
case SMTP_STATE_XCLIENT_HELO:
|
||||
vstring_strcpy(next_command,
|
||||
XCLIENT_CMD " " XCLIENT_FORWARD " " XCLIENT_HELO "=");
|
||||
if (!IS_UNK_HELO_NAME(request->client_helo))
|
||||
if (!DEL_REQ_ATTR_UNAVAIL(request->client_helo))
|
||||
xtext_quote_append(next_command, request->client_helo, "");
|
||||
vstring_strcat(next_command, " " XCLIENT_PROTO "=");
|
||||
if (!IS_UNK_PROTOCOL(request->client_proto))
|
||||
if (!DEL_REQ_ATTR_UNAVAIL(request->client_proto))
|
||||
xtext_quote_append(next_command, request->client_proto, "");
|
||||
next_state = SMTP_STATE_MAIL;
|
||||
break;
|
||||
|
@ -667,9 +667,12 @@ static int helo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
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;
|
||||
/* Downgrading the protocol name breaks the unauthorized pipelining test. */
|
||||
if (strcasecmp(state->protocol, MAIL_PROTO_ESMTP) != 0
|
||||
&& strcasecmp(state->protocol, MAIL_PROTO_SMTP) != 0) {
|
||||
myfree(state->protocol);
|
||||
state->protocol = mystrdup(MAIL_PROTO_SMTP);
|
||||
}
|
||||
smtpd_chat_reply(state, "250 %s", var_myhostname);
|
||||
return (0);
|
||||
}
|
||||
@ -705,7 +708,10 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
rcpt_reset(state);
|
||||
state->helo_name = mystrdup(printable(argv[1].strval, '?'));
|
||||
neuter(state->helo_name, "<>()\\\";:@", '?');
|
||||
state->protocol = MAIL_PROTO_ESMTP;
|
||||
if (strcasecmp(state->protocol, MAIL_PROTO_ESMTP) != 0) {
|
||||
myfree(state->protocol);
|
||||
state->protocol = mystrdup(MAIL_PROTO_ESMTP);
|
||||
}
|
||||
smtpd_chat_reply(state, "250-%s", var_myhostname);
|
||||
smtpd_chat_reply(state, "250-PIPELINING");
|
||||
if (var_message_limit)
|
||||
@ -743,7 +749,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)
|
||||
static void mail_open_stream(SMTPD_STATE *state)
|
||||
{
|
||||
char *postdrop_command;
|
||||
int cleanup_flags;
|
||||
@ -815,7 +821,7 @@ static void mail_open_stream(SMTPD_STATE *state, SMTPD_TOKEN *argv)
|
||||
if (*var_filter_xport)
|
||||
rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport);
|
||||
}
|
||||
rec_fputs(state->cleanup, REC_TYPE_FROM, argv[2].strval);
|
||||
rec_fputs(state->cleanup, REC_TYPE_FROM, state->sender);
|
||||
if (state->encoding != 0)
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_ENCODING, state->encoding);
|
||||
@ -824,18 +830,21 @@ static void mail_open_stream(SMTPD_STATE *state, SMTPD_TOKEN *argv)
|
||||
* 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, FORWARD_NAME(state));
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_CLIENT_ADDR, FORWARD_ADDR(state));
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_ORIGIN, FORWARD_NAMADDR(state));
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_HELO_NAME,
|
||||
IS_UNK_HELO_NAME(FORWARD_HELO(state)) ?
|
||||
HELO_NAME_UNKNOWN : FORWARD_HELO(state));
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_PROTO_NAME, FORWARD_PROTO(state));
|
||||
if (!IS_UNK_CLIENT_NAME(FORWARD_NAME(state)))
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_CLIENT_NAME, FORWARD_NAME(state));
|
||||
if (!IS_UNK_CLIENT_ADDR(FORWARD_ADDR(state)))
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_CLIENT_ADDR, FORWARD_ADDR(state));
|
||||
if (!IS_UNK_CLIENT_NAMADDR(FORWARD_NAMADDR(state)))
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_ORIGIN, FORWARD_NAMADDR(state));
|
||||
if (!IS_UNK_CLIENT_HELO(FORWARD_HELO(state)))
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_HELO_NAME, FORWARD_HELO(state));
|
||||
if (!IS_UNK_CLIENT_PROTO(FORWARD_PROTO(state)))
|
||||
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
|
||||
MAIL_ATTR_PROTO_NAME, FORWARD_PROTO(state));
|
||||
}
|
||||
if (state->verp_delims)
|
||||
rec_fputs(state->cleanup, REC_TYPE_VERP, state->verp_delims);
|
||||
@ -1129,6 +1138,8 @@ static void mail_reset(SMTPD_STATE *state)
|
||||
myfree(state->proxy_mail);
|
||||
state->proxy_mail = 0;
|
||||
}
|
||||
if (state->xclient.used)
|
||||
smtpd_xclient_reset(state);
|
||||
}
|
||||
|
||||
/* rcpt_cmd - process RCPT TO command */
|
||||
@ -1201,7 +1212,7 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
return (-1);
|
||||
}
|
||||
} else if (state->cleanup == 0) {
|
||||
mail_open_stream(state, argv);
|
||||
mail_open_stream(state);
|
||||
}
|
||||
if (state->proxy && smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK,
|
||||
"%s", STR(state->buffer)) != 0) {
|
||||
@ -1702,13 +1713,19 @@ static const struct attr_offset attr_offset = {
|
||||
#define STR_ATTR(state, func, attr) *((char **) PTR_ATTR(state, func, attr))
|
||||
#define INT_ATTR(state, func, attr) *((int *) PTR_ATTR(state, func, attr))
|
||||
|
||||
#define UPDATE_STR(state, func, attr, value) { \
|
||||
#define RST_STR_ATTR(state, func, attr) { \
|
||||
if (STR_ATTR(state, func, attr)) \
|
||||
myfree(STR_ATTR(state, func, attr)); \
|
||||
STR_ATTR(state, func, attr) = 0; \
|
||||
}
|
||||
|
||||
#define UPD_STR_ATTR(state, func, attr, value) { \
|
||||
if (STR_ATTR(state, func, attr)) \
|
||||
myfree(STR_ATTR(state, func, attr)); \
|
||||
STR_ATTR(state, func, attr) = mystrdup(value); \
|
||||
}
|
||||
|
||||
#define UPDATE_INT(state, func, attr, value) { \
|
||||
#define UPD_INT_ATTR(state, func, attr, value) { \
|
||||
INT_ATTR(state, func, attr) = (value); \
|
||||
}
|
||||
|
||||
@ -1755,7 +1772,8 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
function = FUNC_OVERRIDE;
|
||||
} else if (STREQ(arg_val, XCLIENT_FORWARD)) {
|
||||
function = FUNC_FORWARD;
|
||||
state->xclient.used = 1;
|
||||
if (state->xclient.used == 0)
|
||||
smtpd_xclient_preset(state);
|
||||
} else { /* error */
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad %s function: %s",
|
||||
@ -1764,7 +1782,9 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over all NAME=VALUE attributes.
|
||||
* Iterate over all NAME=VALUE attributes. An empty value means the
|
||||
* information was not provided by the client and that we must not fall
|
||||
* back to the non-XCLIENT value.
|
||||
*/
|
||||
for (arg_no = 2; arg_no < argc; arg_no++) {
|
||||
arg_val = argv[arg_no].strval;
|
||||
@ -1810,11 +1830,11 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
cooked_value);
|
||||
return (-1);
|
||||
}
|
||||
UPDATE_STR(state, function, name, cooked_value);
|
||||
UPDATE_INT(state, function, peer_code, SMTPD_PEER_CODE_OK);
|
||||
UPD_STR_ATTR(state, function, name, cooked_value);
|
||||
UPD_INT_ATTR(state, function, peer_code, SMTPD_PEER_CODE_OK);
|
||||
} else {
|
||||
UPDATE_STR(state, function, name, CLIENT_NAME_UNKNOWN);
|
||||
UPDATE_INT(state, function, peer_code, SMTPD_PEER_CODE_PERM);
|
||||
UPD_STR_ATTR(state, function, name, CLIENT_NAME_UNKNOWN);
|
||||
UPD_INT_ATTR(state, function, peer_code, SMTPD_PEER_CODE_PERM);
|
||||
}
|
||||
update_namaddr = 1;
|
||||
}
|
||||
@ -1822,7 +1842,7 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
/*
|
||||
* CLIENT_ADDR=client network address.
|
||||
*/
|
||||
else if (STREQ(arg_val, "CLIENT_ADDR")) {
|
||||
else if (STREQ(arg_val, XCLIENT_ADDR)) {
|
||||
if (*raw_value) {
|
||||
if (!valid_hostaddr(cooked_value, DONT_GRIPE)) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
@ -1830,9 +1850,9 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
cooked_value);
|
||||
return (-1);
|
||||
}
|
||||
UPDATE_STR(state, function, addr, cooked_value);
|
||||
UPD_STR_ATTR(state, function, addr, cooked_value);
|
||||
} else {
|
||||
UPDATE_STR(state, function, name, CLIENT_ADDR_UNKNOWN);
|
||||
UPD_STR_ATTR(state, function, addr, CLIENT_ADDR_UNKNOWN);
|
||||
}
|
||||
update_namaddr = 1;
|
||||
}
|
||||
@ -1841,16 +1861,16 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
* CLIENT_CODE=status. Reset the client hostname if the hostname
|
||||
* lookup status is not OK.
|
||||
*/
|
||||
else if (STREQ(arg_val, "CLIENT_CODE")) {
|
||||
else if (STREQ(arg_val, XCLIENT_CODE)) {
|
||||
if (STREQ(cooked_value, "OK")) {
|
||||
UPDATE_INT(state, function, peer_code, SMTPD_PEER_CODE_OK);
|
||||
UPD_INT_ATTR(state, function, peer_code, SMTPD_PEER_CODE_OK);
|
||||
} else if (STREQ(cooked_value, "TEMP")) {
|
||||
UPDATE_INT(state, function, peer_code, SMTPD_PEER_CODE_TEMP);
|
||||
UPDATE_STR(state, function, name, CLIENT_NAME_UNKNOWN);
|
||||
UPD_INT_ATTR(state, function, peer_code, SMTPD_PEER_CODE_TEMP);
|
||||
UPD_STR_ATTR(state, function, name, CLIENT_NAME_UNKNOWN);
|
||||
update_namaddr = 1;
|
||||
} else if (STREQ(cooked_value, "PERM")) {
|
||||
UPDATE_INT(state, function, peer_code, SMTPD_PEER_CODE_PERM);
|
||||
UPDATE_STR(state, function, name, CLIENT_NAME_UNKNOWN);
|
||||
UPD_INT_ATTR(state, function, peer_code, SMTPD_PEER_CODE_PERM);
|
||||
UPD_STR_ATTR(state, function, name, CLIENT_NAME_UNKNOWN);
|
||||
update_namaddr = 1;
|
||||
} else {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
@ -1861,12 +1881,10 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 [].
|
||||
* CLIENT_HELO=hostname. Disallow characters that could mess up our
|
||||
* own Received: message headers but allow [].
|
||||
*/
|
||||
else if (STREQ(arg_val, "HELO_NAME")) {
|
||||
else if (STREQ(arg_val, XCLIENT_HELO)) {
|
||||
if (*raw_value) {
|
||||
if (strlen(cooked_value) > VALID_HOSTNAME_LEN) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
@ -1875,17 +1893,17 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
return (-1);
|
||||
}
|
||||
neuter(cooked_value, "<>()\\\";:@", '?');
|
||||
UPDATE_STR(state, function, helo_name, cooked_value);
|
||||
UPD_STR_ATTR(state, function, helo_name, cooked_value);
|
||||
} else {
|
||||
UPDATE_STR(state, function, helo_name, HELO_NAME_UNKNOWN);
|
||||
RST_STR_ATTR(state, function, helo_name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* PROTOCOL=protocol name. Disallow characters that could mess up our
|
||||
* own Received: message headers.
|
||||
* CLIENT_PROTO=protocol name. Disallow characters that could mess up
|
||||
* our own Received: message headers.
|
||||
*/
|
||||
else if (STREQ(arg_val, "PROTOCOL")) {
|
||||
else if (STREQ(arg_val, XCLIENT_PROTO)) {
|
||||
if (*raw_value) {
|
||||
if (*cooked_value == 0 || strlen(cooked_value) > 64) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
@ -1894,9 +1912,9 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
return (-1);
|
||||
}
|
||||
neuter(cooked_value, "[]<>()\\\";:@", '?');
|
||||
UPDATE_STR(state, function, protocol, cooked_value);
|
||||
UPD_STR_ATTR(state, function, protocol, cooked_value);
|
||||
} else {
|
||||
UPDATE_STR(state, function, protocol, PROTOCOL_UNKNOWN);
|
||||
UPD_STR_ATTR(state, function, protocol, CLIENT_PROTO_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2039,11 +2057,13 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
|
||||
case 0:
|
||||
|
||||
/*
|
||||
* XXX The client connection count/rate control uses the real client
|
||||
* name/address to maintain consistency between connect and
|
||||
* disconnect events.
|
||||
* XXX The client connection count/rate control must be consistent in
|
||||
* its use of client address information in connect and disconnect
|
||||
* events. For now we exclude xclient authorized hosts from
|
||||
* connection count/rate control.
|
||||
*/
|
||||
if (SMTPD_STAND_ALONE(state) == 0
|
||||
&& !xclient_allowed
|
||||
&& anvil_clnt
|
||||
&& !namadr_list_match(hogger_list, state->name, state->addr)
|
||||
&& anvil_clnt_connect(anvil_clnt, service, state->addr,
|
||||
@ -2129,11 +2149,13 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX The client connection count/rate control uses the real client
|
||||
* name/address to maintain consistency between connect and disconnect
|
||||
* events.
|
||||
* XXX The client connection count/rate control must be consistent in its
|
||||
* use of client address information in connect and disconnect events.
|
||||
* For now we exclude xclient authorized hosts from connection count/rate
|
||||
* control.
|
||||
*/
|
||||
if (SMTPD_STAND_ALONE(state) == 0
|
||||
&& !xclient_allowed
|
||||
&& anvil_clnt
|
||||
&& !namadr_list_match(hogger_list, state->name, state->addr))
|
||||
anvil_clnt_disconnect(anvil_clnt, service, state->addr);
|
||||
|
@ -142,9 +142,7 @@ extern void smtpd_peer_reset(SMTPD_STATE *state);
|
||||
#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.
|
||||
* Choose between normal or forwarded attributes.
|
||||
*/
|
||||
#define SMTPD_FEATURE_XCLIENT (1<<0) /* XCLIENT supported */
|
||||
|
||||
@ -159,6 +157,7 @@ extern void smtpd_peer_reset(SMTPD_STATE *state);
|
||||
#define FORWARD_HELO(s) MAYBE_FORWARD((s), helo_name)
|
||||
|
||||
extern void smtpd_xclient_init(SMTPD_STATE *state);
|
||||
extern void smtpd_xclient_preset(SMTPD_STATE *state);
|
||||
extern void smtpd_xclient_reset(SMTPD_STATE *state);
|
||||
|
||||
/*
|
||||
|
@ -970,7 +970,7 @@ static int reject_unknown_client(SMTPD_STATE *state)
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s %s", myname, state->name, state->addr);
|
||||
|
||||
if (IS_UNK_CLNT_NAME(state->name))
|
||||
if (strcasecmp(state->name, "unknown") == 0)
|
||||
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
|
||||
"%d Client host rejected: cannot find your hostname, [%s]",
|
||||
state->peer_code == SMTPD_PEER_CODE_PERM ?
|
||||
@ -2524,7 +2524,7 @@ static const char *smtpd_expand_lookup(const char *name, int unused_mode,
|
||||
} else if (STREQ(name, MAIL_ATTR_CLIENT_NAME)) {
|
||||
return (state->name);
|
||||
} else if (STREQ(name, MAIL_ATTR_HELO_NAME)) {
|
||||
return (state->helo_name ? state->helo_name : "");
|
||||
return (state->helo_name ? state->helo_name : "");
|
||||
} 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)));
|
||||
@ -2910,7 +2910,7 @@ static int check_policy_service(SMTPD_STATE *state, const char *server,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, state->addr,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, state->name,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME,
|
||||
state->helo_name ? state->helo_name : "",
|
||||
state->helo_name ? state->helo_name : "",
|
||||
ATTR_TYPE_STR, MAIL_ATTR_SENDER,
|
||||
state->sender ? state->sender : "",
|
||||
ATTR_TYPE_STR, MAIL_ATTR_RECIP,
|
||||
@ -3093,7 +3093,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
|
||||
name);
|
||||
else {
|
||||
cpp += 1;
|
||||
if (!IS_UNK_CLNT_NAME(state->name))
|
||||
if (strcasecmp(state->name, "unknown") != 0)
|
||||
status = reject_rbl_domain(state, *cpp, state->name,
|
||||
SMTPD_NAME_CLIENT);
|
||||
}
|
||||
|
@ -245,26 +245,29 @@ int smtpd_proxy_open(SMTPD_STATE *state, const char *service,
|
||||
state->proxy_features |= SMTPD_FEATURE_XCLIENT;
|
||||
|
||||
/*
|
||||
* Send all XCLIENT attributes. Transform internal forms to external
|
||||
* Send all XCLIENT attributes, but only if we have some minimal amount
|
||||
* of remote client information. Transform internal forms to external
|
||||
* forms and encode the result as xtext.
|
||||
*/
|
||||
if (state->proxy_features & SMTPD_FEATURE_XCLIENT) {
|
||||
if ((state->proxy_features & SMTPD_FEATURE_XCLIENT)
|
||||
&& (!IS_UNK_CLIENT_NAME(FORWARD_NAME(state))
|
||||
|| !IS_UNK_CLIENT_ADDR(FORWARD_ADDR(state)))) {
|
||||
buf = vstring_alloc(100);
|
||||
vstring_strcpy(buf, XCLIENT_CMD " " XCLIENT_FORWARD
|
||||
" " XCLIENT_NAME "=");
|
||||
if (!IS_UNK_CLNT_NAME(FORWARD_NAME(state)))
|
||||
if (!IS_UNK_CLIENT_NAME(FORWARD_NAME(state)))
|
||||
xtext_quote_append(buf, FORWARD_NAME(state), "");
|
||||
vstring_strcat(buf, " " XCLIENT_ADDR "=");
|
||||
if (!IS_UNK_CLNT_ADDR(FORWARD_ADDR(state)))
|
||||
if (!IS_UNK_CLIENT_ADDR(FORWARD_ADDR(state)))
|
||||
xtext_quote_append(buf, FORWARD_ADDR(state), "");
|
||||
bad = smtpd_proxy_cmd(state, SMTPD_PROX_WANT_ANY, "%s", STR(buf));
|
||||
if (bad == 0) {
|
||||
vstring_strcpy(buf, XCLIENT_CMD " " XCLIENT_FORWARD
|
||||
" " XCLIENT_HELO "=");
|
||||
if (!IS_UNK_HELO_NAME(FORWARD_HELO(state)))
|
||||
if (!IS_UNK_CLIENT_HELO(FORWARD_HELO(state)))
|
||||
xtext_quote_append(buf, FORWARD_HELO(state), "");
|
||||
vstring_strcat(buf, " " XCLIENT_PROTO "=");
|
||||
if (!IS_UNK_PROTOCOL(FORWARD_PROTO(state)))
|
||||
if (!IS_UNK_CLIENT_PROTO(FORWARD_PROTO(state)))
|
||||
xtext_quote_append(buf, FORWARD_PROTO(state), "");
|
||||
bad = smtpd_proxy_cmd(state, SMTPD_PROX_WANT_ANY, "%s", STR(buf));
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
|
||||
state->verp_delims = 0;
|
||||
state->recipient = 0;
|
||||
state->etrn_name = 0;
|
||||
state->protocol = MAIL_PROTO_SMTP;
|
||||
state->protocol = mystrdup(MAIL_PROTO_SMTP);
|
||||
state->where = SMTPD_AFTER_CONNECT;
|
||||
state->recursion = 0;
|
||||
state->msg_size = 0;
|
||||
@ -140,6 +140,8 @@ void smtpd_state_reset(SMTPD_STATE *state)
|
||||
*/
|
||||
if (state->buffer)
|
||||
vstring_free(state->buffer);
|
||||
if (state->protocol)
|
||||
myfree(state->protocol);
|
||||
smtpd_peer_reset(state);
|
||||
smtpd_xclient_reset(state);
|
||||
if (state->defer_if_permit.reason)
|
||||
|
@ -12,13 +12,14 @@
|
||||
/* void smtpd_xclient_reset(state)
|
||||
/* SMTPD_STATE *state;
|
||||
/* 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_init() zeroes the attributes for storage of XCLIENT
|
||||
/* FORWARD command parameters.
|
||||
/*
|
||||
/* smtpd_xclient_reset() releases memory allocated after the return
|
||||
/* from smtpd_xclient_init().
|
||||
/* smtpd_xclient_preset() takes the result from smtpd_xclient_init()
|
||||
/* and sets all fields to the same "unknown" value that regular
|
||||
/* client attributes would have.
|
||||
*/
|
||||
/* smtpd_xclient_reset() restores the state from smtpd_xclient_init().
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
@ -52,21 +53,42 @@
|
||||
void smtpd_xclient_init(SMTPD_STATE *state)
|
||||
{
|
||||
state->xclient.used = 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_preset - set xclient attributes to "unknown" */
|
||||
|
||||
void smtpd_xclient_preset(SMTPD_STATE *state)
|
||||
{
|
||||
|
||||
/*
|
||||
* This is a temporary solution. Unknown forwarded attributes get the
|
||||
* same values as unknown normal attributes, so that we don't break
|
||||
* assumptions in pre-existing code.
|
||||
*/
|
||||
state->xclient.used = 1;
|
||||
state->xclient.name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||
state->xclient.addr = mystrdup(CLIENT_ADDR_UNKNOWN);
|
||||
state->xclient.namaddr = mystrdup(CLIENT_NAMADDR_UNKNOWN);
|
||||
state->xclient.peer_code = 0;
|
||||
state->xclient.protocol = mystrdup(PROTOCOL_UNKNOWN);
|
||||
state->xclient.helo_name = mystrdup(HELO_NAME_UNKNOWN);
|
||||
state->xclient.protocol = mystrdup(CLIENT_PROTO_UNKNOWN);
|
||||
}
|
||||
|
||||
/* smtpd_xclient_reset - reset XCLIENT attributes */
|
||||
|
||||
void smtpd_xclient_reset(SMTPD_STATE *state)
|
||||
{
|
||||
myfree(state->xclient.name);
|
||||
myfree(state->xclient.addr);
|
||||
myfree(state->xclient.namaddr);
|
||||
myfree(state->xclient.protocol);
|
||||
myfree(state->xclient.helo_name);
|
||||
#define FREE_AND_WIPE(s) { if (s) myfree(s); s = 0; }
|
||||
|
||||
state->xclient.used = 0;
|
||||
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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user