2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-29 21:27:57 +00:00

postfix-2.3-20050726

This commit is contained in:
Wietse Venema 2005-07-26 00:00:00 -05:00 committed by Viktor Dukhovni
parent 01c5f58c4b
commit 3fb1ad8ad5
14 changed files with 210 additions and 126 deletions

View File

@ -11050,6 +11050,18 @@ Apologies for any names omitted.
client IP address). Files: global/mail_params.h,
smtpd/smtpd_peer.c, smtpd/smtpd.c, smtpd/smtpd_check.c.
20050726
Horror: total rewrite of DNS client error handling because
some misguided proposal attempts to give special meaning
to some syntactically invalid MX hostname lookup result.
Not only that, people expect sensible results with
reject_unknown_sender_domain etc. Files: dns/dns_lookup.c,
smtp/smtp_addr.c smtpd/smtpd_check.c, lmtp/lmtp_addr.c.
Cleanup: HOLD action executes only once, to reduce noise
in the logfile. Files: cleanup/cleanup_message.c, smtpd/smtpd.c.
Open problems:
Med: when the cleanup server bounces local mail that should

View File

@ -17,7 +17,32 @@ Incompatibility with Postfix 2.1 and earlier
If you upgrade from Postfix 2.1 or earlier, read RELEASE_NOTES-2.2
before proceeding.
Incompatibility with snapshot 20050715
Incompatibility with snapshot 20050726
======================================
Name server replies that contain a malformed hostname are now flagged
as permanent errors instead of transient errors. This change works
around a questionable proposal to use syntactically invalid hostnames
in MX records.
Major changes with snapshot 20050724
====================================
SMTPD Access control based on the existence of an address->name
mapping, with reject_unknown_reverse_client_hostname. There is
no corresponding access table lookup feature, because the name
is not validated in any way (except that it has proper syntax).
Several confusing SMTPD access restrictions were renamed:
reject_unknown_client -> reject_unknown_client_hostname,
reject_unknown_hostname -> reject_unknown_helo_hostname,
reject_invalid_hostname -> reject_invalid_helo_hostname,
reject_non_fqdn_hostname -> reject_non_fqdn_helo_hostname.
The old names are still recognized and documented.
Incompatibility with snapshot 20050716
======================================
Internal interfaces have changed; this may break third-party patches
@ -40,7 +65,7 @@ report "(unsigned) int" versus "(s)size_t" format string argument
mis-matches on 32-bit systems; they can be found only on 64-bit
systems.
Major changes with snapshot 20050715
Major changes with snapshot 20050716
====================================
Improved portability to LP64 systems, by converting the type of

View File

@ -8132,11 +8132,13 @@ code for rejected requests (default: 554). </dd>
<dt><b><a name="reject_unknown_recipient_domain">reject_unknown_recipient_domain</a></b></dt>
<dd>Reject the request when the RCPT TO address has no DNS A or MX
record and Postfix is not final destination for the recipient
address. <br> The <a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> parameter specifies
the response code for rejected requests (default: 450). The response
is always 450 in case of a temporary DNS error.</dd>
<dd>Reject the request when Postfix is not final destination for
the recipient address, and the RCPT TO address has no DNS A or MX
record, or when it has a malformed MX record such as a record with
a zero-length MX hostname (Postfix 2.3 and later). <br> The
<a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> parameter specifies the response code
for rejected requests (default: 450). The response is always 450
in case of a temporary DNS error.</dd>
<dt><b><a name="reject_unlisted_recipient">reject_unlisted_recipient</a></b> (with Postfix 2.0: check_recipient_maps)</dt>
@ -8602,11 +8604,13 @@ Postfix version 2.1 and later. </dd>
<dt><b><a name="reject_unknown_sender_domain">reject_unknown_sender_domain</a></b></dt>
<dd>Reject the request when the MAIL FROM address has no DNS A or
MX record and Postfix is not final destination for the sender
address. <br> The <a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> parameter specifies
the response code for rejected requests (default: 450). The response
is always 450 in case of a temporary DNS error. </dd>
<dd>Reject the request when Postfix is not final destination for
the sender address, and the MAIL FROM address has no DNS A or MX
record, or when it has a malformed MX record such as a record with
a zero-length MX hostname (Postfix 2.3 and later). <br> The
<a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> parameter specifies the response code
for rejected requests (default: 450). The response is always 450
in case of a temporary DNS error. </dd>
<dt><b><a name="reject_unlisted_sender">reject_unlisted_sender</a></b></dt>

View File

@ -4648,13 +4648,15 @@ no sender-specified routing (user@elsewhere@domain).
The relay_domains_reject_code parameter specifies the response
code for rejected requests (default: 554).
.IP "\fBreject_unknown_recipient_domain\fR"
Reject the request when the RCPT TO address has no DNS A or MX
record and Postfix is not final destination for the recipient
address.
Reject the request when Postfix is not final destination for
the recipient address, and the RCPT TO address has no DNS A or MX
record, or when it has a malformed MX record such as a record with
a zero-length MX hostname (Postfix 2.3 and later).
.br
The unknown_address_reject_code parameter specifies
the response code for rejected requests (default: 450). The response
is always 450 in case of a temporary DNS error.
The
unknown_address_reject_code parameter specifies the response code
for rejected requests (default: 450). The response is always 450
in case of a temporary DNS error.
.IP "\fBreject_unlisted_recipient\fR (with Postfix 2.0: check_recipient_maps)"
Reject the request when the RCPT TO address is not listed in
the list of valid recipients for its domain class. See the
@ -4953,13 +4955,15 @@ Enforces the reject_sender_login_mismatch restriction for
unauthenticated clients only. This feature is available in
Postfix version 2.1 and later.
.IP "\fBreject_unknown_sender_domain\fR"
Reject the request when the MAIL FROM address has no DNS A or
MX record and Postfix is not final destination for the sender
address.
Reject the request when Postfix is not final destination for
the sender address, and the MAIL FROM address has no DNS A or MX
record, or when it has a malformed MX record such as a record with
a zero-length MX hostname (Postfix 2.3 and later).
.br
The unknown_address_reject_code parameter specifies
the response code for rejected requests (default: 450). The response
is always 450 in case of a temporary DNS error.
The
unknown_address_reject_code parameter specifies the response code
for rejected requests (default: 450). The response is always 450
in case of a temporary DNS error.
.IP "\fBreject_unlisted_sender\fR"
Reject the request when the MAIL FROM address is not listed in
the list of valid recipients for its domain class. See the

View File

@ -5150,11 +5150,13 @@ code for rejected requests (default: 554). </dd>
<dt><b><a name="reject_unknown_recipient_domain">reject_unknown_recipient_domain</a></b></dt>
<dd>Reject the request when the RCPT TO address has no DNS A or MX
record and Postfix is not final destination for the recipient
address. <br> The unknown_address_reject_code parameter specifies
the response code for rejected requests (default: 450). The response
is always 450 in case of a temporary DNS error.</dd>
<dd>Reject the request when Postfix is not final destination for
the recipient address, and the RCPT TO address has no DNS A or MX
record, or when it has a malformed MX record such as a record with
a zero-length MX hostname (Postfix 2.3 and later). <br> The
unknown_address_reject_code parameter specifies the response code
for rejected requests (default: 450). The response is always 450
in case of a temporary DNS error.</dd>
<dt><b><a name="reject_unlisted_recipient">reject_unlisted_recipient</a></b> (with Postfix 2.0: check_recipient_maps)</dt>
@ -5488,11 +5490,13 @@ Postfix version 2.1 and later. </dd>
<dt><b><a name="reject_unknown_sender_domain">reject_unknown_sender_domain</a></b></dt>
<dd>Reject the request when the MAIL FROM address has no DNS A or
MX record and Postfix is not final destination for the sender
address. <br> The unknown_address_reject_code parameter specifies
the response code for rejected requests (default: 450). The response
is always 450 in case of a temporary DNS error. </dd>
<dd>Reject the request when Postfix is not final destination for
the sender address, and the MAIL FROM address has no DNS A or MX
record, or when it has a malformed MX record such as a record with
a zero-length MX hostname (Postfix 2.3 and later). <br> The
unknown_address_reject_code parameter specifies the response code
for rejected requests (default: 450). The response is always 450
in case of a temporary DNS error. </dd>
<dt><b><a name="reject_unlisted_sender">reject_unlisted_sender</a></b></dt>

View File

@ -316,8 +316,8 @@ static const char *cleanup_act(CLEANUP_STATE *state, char *context,
if (*optional_text) {
state->reason = dsn_prepend("5.7.1", optional_text);
if (*state->reason != '4' && *state->reason != '5') {
msg_warn("bad DSN action in %s -- need 4.x.x or 5.x.x",
optional_text);
msg_warn("bad DSN action in %s -- need 4.x.x or 5.x.x",
optional_text);
*state->reason = '4';
}
} else {
@ -356,8 +356,10 @@ static const char *cleanup_act(CLEANUP_STATE *state, char *context,
return (buf);
}
if (STREQUAL(value, "HOLD", command_len)) {
cleanup_act_log(state, "hold", context, buf, optional_text);
state->flags |= CLEANUP_FLAG_HOLD;
if ((state->flags & CLEANUP_FLAG_HOLD) == 0) {
cleanup_act_log(state, "hold", context, buf, optional_text);
state->flags |= CLEANUP_FLAG_HOLD;
}
return (buf);
}
if (STREQUAL(value, "PREPEND", command_len)) {

View File

@ -157,13 +157,15 @@ extern int dns_lookup_v(const char *, unsigned, DNS_RR **, VSTRING *,
/*
* Request flags.
*/
#define DNS_REQ_FLAG_ANY (1<<0)
#define DNS_REQ_FLAG_ALL (1<<1)
#define DNS_REQ_FLAG_STOP_OK (1<<0)
#define DNS_REQ_FLAG_STOP_INVAL (1<<1)
#define DNS_REQ_FLAG_NONE (0)
/*
* Status codes. Failures must have negative codes so they will not collide
* with valid counts of answer records etc.
*/
#define DNS_INVAL (-5) /* query ok, malformed reply */
#define DNS_FAIL (-4) /* query failed, don't retry */
#define DNS_NOTFOUND (-3) /* query ok, data not found */
#define DNS_RETRY (-2) /* query failed, try again */

View File

@ -37,7 +37,8 @@
/* number of CNAME indirections. All result names (including
/* null terminator) will fit a buffer of size DNS_NAME_LEN.
/* All name results are validated by \fIvalid_hostname\fR();
/* an invalid name is reported as a transient error.
/* an invalid name is reported as a DNS_INVAL result, while
/* malformed replies are reported as transient errors.
/*
/* dns_lookup_l() and dns_lookup_v() allow the user to specify
/* a list of resource types.
@ -46,6 +47,8 @@
/* .fi
/* .IP name
/* The name to be looked up in the domain name system.
/* This name must pass the valid_hostname() test; it
/* must not be an IP address.
/* .IP type
/* The resource record type to be looked up (T_A, T_MX etc.).
/* .IP rflags
@ -59,16 +62,18 @@
/* Append local domain to unqualified names.
/* .RE
/* .IP lflags
/* Multi-type request control for dns_lookup_l() and
/* dns_lookup_v(). This is one of the following:
/* Multi-type request control for dns_lookup_l() and dns_lookup_v().
/* For convenience, DNS_REQ_FLAG_NONE requests no special
/* processing. Invoke dns_lookup() for all specified resource
/* record types in the specified order, and merge their results.
/* Otherwise, specify one or more of the following:
/* .RS
/* .IP DNS_REQ_FLAG_ANY
/* Call dns_lookup() for each specified resource record type
/* in the specified order, until the list is exhausted or
/* until some result is DNS_OK.
/* .IP DNS_REQ_FLAG_ALL
/* Call dns_lookup() for all specified resource record types
/* in the specified order, and merge their results.
/* .IP DNS_REQ_FLAG_STOP_INVAL
/* Invoke dns_lookup() for the resource types in the order as
/* specified, and return when dns_lookup() returns DNS_INVAL.
/* .IP DNS_REQ_FLAG_STOP_OK
/* Invoke dns_lookup() for the resource types in the order as
/* specified, and return when dns_lookup() returns DNS_OK.
/* .RE
/* .IP ltype
/* The resource record types to be looked up. In the case of
@ -93,8 +98,11 @@
/* The DNS query succeeded.
/* .IP DNS_NOTFOUND
/* The DNS query succeeded; the requested information was not found.
/* .IP DNS_INVAL
/* The DNS query succeeded; the result failed the valid_hostname() test.
/* .IP DNS_RETRY
/* The query failed; the problem is transient.
/* The query failed, or the reply was malformed.
/* The problem is considered transient.
/* .IP DNS_FAIL
/* The query failed.
/* BUGS
@ -142,8 +150,8 @@
/*
* Structure to keep track of things while decoding a name server reply.
*/
#define DEF_DNS_REPLY_SIZE 4096 /* in case we're using TCP */
#define MAX_DNS_REPLY_SIZE 32768 /* in case we're using TCP */
#define DEF_DNS_REPLY_SIZE 4096 /* in case we're using TCP */
#define MAX_DNS_REPLY_SIZE 32768 /* in case we're using TCP */
typedef struct DNS_REPLY {
unsigned char *buf; /* raw reply data */
@ -341,8 +349,8 @@ static int valid_rr_name(const char *name, const char *location,
/* dns_get_rr - extract resource record from name server reply */
static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos,
char *rr_name, DNS_FIXED *fixed)
static int dns_get_rr(DNS_RR **list, DNS_REPLY *reply, unsigned char *pos,
char *rr_name, DNS_FIXED *fixed)
{
char temp[DNS_NAME_LEN];
ssize_t data_len;
@ -353,8 +361,9 @@ static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos,
#define MIN2(a, b) ((unsigned)(a) < (unsigned)(b) ? (a) : (b))
*list = 0;
if (pos + fixed->length > reply->end)
return (0);
return (DNS_RETRY);
switch (fixed->type) {
default:
@ -367,23 +376,23 @@ static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos,
case T_NS:
case T_PTR:
if (dn_expand(reply->buf, reply->end, pos, temp, sizeof(temp)) < 0)
return (0);
return (DNS_RETRY);
if (!valid_rr_name(temp, "resource data", fixed->type, reply))
return (0);
return (DNS_INVAL);
data_len = strlen(temp) + 1;
break;
case T_MX:
GETSHORT(pref, pos);
if (dn_expand(reply->buf, reply->end, pos, temp, sizeof(temp)) < 0)
return (0);
return (DNS_RETRY);
if (!valid_rr_name(temp, "resource data", fixed->type, reply))
return (0);
return (DNS_INVAL);
data_len = strlen(temp) + 1;
break;
case T_A:
if (fixed->length != INET_ADDR_LEN) {
msg_warn("extract_answer: bad address length: %d", fixed->length);
return (0);
return (DNS_RETRY);
}
if (fixed->length > sizeof(temp))
msg_panic("dns_get_rr: length %d > DNS_NAME_LEN",
@ -395,7 +404,7 @@ static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos,
case T_AAAA:
if (fixed->length != INET6_ADDR_LEN) {
msg_warn("extract_answer: bad address length: %d", fixed->length);
return (0);
return (DNS_RETRY);
}
if (fixed->length > sizeof(temp))
msg_panic("dns_get_rr: length %d > DNS_NAME_LEN",
@ -414,8 +423,9 @@ static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos,
*dst = 0;
break;
}
return (dns_rr_create(rr_name, fixed->type, fixed->class, fixed->ttl,
pref, temp, data_len));
*list = dns_rr_create(rr_name, fixed->type, fixed->class, fixed->ttl,
pref, temp, data_len);
return (DNS_OK);
}
/* dns_get_alias - extract CNAME from name server reply */
@ -428,7 +438,7 @@ static int dns_get_alias(DNS_REPLY *reply, unsigned char *pos,
if (dn_expand(reply->buf, reply->end, pos, cname, c_len) < 0)
return (DNS_RETRY);
if (!valid_rr_name(cname, "resource data", fixed->type, reply))
return (DNS_RETRY);
return (DNS_INVAL);
return (DNS_OK);
}
@ -445,14 +455,15 @@ static int dns_get_answer(DNS_REPLY *reply, int type,
DNS_RR *rr;
int resource_found = 0;
int cname_found = 0;
int not_found_status = DNS_NOTFOUND;
int not_found_status = DNS_RETRY; /* can't happen */
int status;
/*
* Initialize. Skip over the name server query if we haven't yet.
*/
if (reply->answer_start == 0)
if (dns_skip_query(reply) < 0)
return (DNS_RETRY);
if ((status = dns_skip_query(reply)) < 0)
return (status);
pos = reply->answer_start;
if (rrlist)
*rrlist = 0;
@ -461,12 +472,12 @@ static int dns_get_answer(DNS_REPLY *reply, int type,
* Either this, or use a GOTO for emergency exits. The purpose is to
* prevent incomplete answers from being passed back to the caller.
*/
#define CORRUPT { \
#define CORRUPT(status) { \
if (rrlist && *rrlist) { \
dns_rr_free(*rrlist); \
*rrlist = 0; \
} \
return (DNS_RETRY); \
return (status); \
}
/*
@ -478,21 +489,21 @@ static int dns_get_answer(DNS_REPLY *reply, int type,
* Optionally extract the fully-qualified domain name.
*/
if (pos >= reply->end)
CORRUPT;
CORRUPT(DNS_RETRY);
len = dn_expand(reply->buf, reply->end, pos, rr_name, DNS_NAME_LEN);
if (len < 0)
CORRUPT;
CORRUPT(DNS_RETRY);
pos += len;
/*
* Extract the fixed reply data: type, class, ttl, length.
*/
if (pos + RRFIXEDSZ > reply->end)
CORRUPT;
if (dns_get_fixed(pos, &fixed) != DNS_OK)
CORRUPT;
CORRUPT(DNS_RETRY);
if ((status = dns_get_fixed(pos, &fixed)) != DNS_OK)
CORRUPT(status);
if (!valid_rr_name(rr_name, "resource name", fixed.type, reply))
CORRUPT;
CORRUPT(DNS_INVAL);
if (fqdn)
vstring_strcpy(fqdn, rr_name);
if (msg_verbose)
@ -504,21 +515,21 @@ static int dns_get_answer(DNS_REPLY *reply, int type,
* Optionally extract the requested resource or CNAME data.
*/
if (pos + fixed.length > reply->end)
CORRUPT;
CORRUPT(DNS_RETRY);
if (type == fixed.type || type == T_ANY) { /* requested type */
if (rrlist) {
if ((rr = dns_get_rr(reply, pos, rr_name, &fixed)) != 0) {
if ((status = dns_get_rr(&rr, reply, pos, rr_name, &fixed)) == DNS_OK) {
resource_found++;
*rrlist = dns_rr_append(*rrlist, rr);
} else
not_found_status = DNS_RETRY;
} else if (not_found_status != DNS_RETRY)
not_found_status = status;
} else
resource_found++;
} else if (fixed.type == T_CNAME) { /* cname resource */
cname_found++;
if (cname && c_len > 0)
if (dns_get_alias(reply, pos, &fixed, cname, c_len) != DNS_OK)
CORRUPT;
if ((status = dns_get_alias(reply, pos, &fixed, cname, c_len)) != DNS_OK)
CORRUPT(status);
}
pos += fixed.length;
}
@ -591,10 +602,9 @@ int dns_lookup(const char *name, unsigned type, unsigned flags,
default:
if (why)
vstring_sprintf(why, "Name service error for name=%s type=%s: "
"Malformed name server reply",
"Malformed or unexpected name server reply",
name, dns_strtype(type));
case DNS_OK:
case DNS_NOTFOUND:
return (status);
case DNS_RECURSE:
if (msg_verbose)
@ -633,7 +643,10 @@ int dns_lookup_l(const char *name, unsigned flags, DNS_RR **rrlist,
non_err = 1;
if (rrlist)
*rrlist = dns_rr_append(*rrlist, rr);
if (lflags == DNS_REQ_FLAG_ANY)
if (lflags & DNS_REQ_FLAG_STOP_OK)
break;
} else if (status == DNS_INVAL) {
if (lflags & DNS_REQ_FLAG_STOP_INVAL)
break;
} else if (status == DNS_RETRY) {
soft_err = 1;
@ -667,7 +680,10 @@ int dns_lookup_v(const char *name, unsigned flags, DNS_RR **rrlist,
non_err = 1;
if (rrlist)
*rrlist = dns_rr_append(*rrlist, rr);
if (lflags == DNS_REQ_FLAG_ANY)
if (lflags & DNS_REQ_FLAG_STOP_OK)
break;
} else if (status == DNS_INVAL) {
if (lflags & DNS_REQ_FLAG_STOP_INVAL)
break;
} else if (status == DNS_RETRY) {
soft_err = 1;

View File

@ -100,7 +100,7 @@ int main(int argc, char **argv)
name = argv[2];
msg_verbose = 1;
switch (dns_lookup_v(name, RES_DEFNAMES | RES_DEBUG, &rr, fqdn, why,
DNS_REQ_FLAG_ALL, types)) {
DNS_REQ_FLAG_NONE, types)) {
default:
msg_fatal("%s", vstring_str(why));
case DNS_OK:

View File

@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
#define MAIL_RELEASE_DATE "20050724"
#define MAIL_RELEASE_DATE "20050726"
#define MAIL_VERSION_NUMBER "2.3"
#ifdef SNAPSHOT

View File

@ -191,7 +191,7 @@ static DNS_RR *lmtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
* Append the addresses for this host to the address list.
*/
switch (dns_lookup_v(host, RES_DEFNAMES, &addr, (VSTRING *) 0, why->reason,
DNS_REQ_FLAG_ALL, proto_info->dns_atype_list)) {
DNS_REQ_FLAG_NONE, proto_info->dns_atype_list)) {
case DNS_OK:
for (rr = addr; rr; rr = rr->next)
rr->pref = pref;
@ -207,6 +207,7 @@ static DNS_RR *lmtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
"5.4.3", 550, "550 Name server failure");
lmtp_errno = LMTP_FAIL;
break;
case DNS_INVAL:
case DNS_NOTFOUND:
lmtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
"5.4.4", 550, "550 Host not found");

View File

@ -162,7 +162,7 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
*/
if (smtp_host_lookup_mask & SMTP_HOST_FLAG_DNS) {
switch (dns_lookup_v(host, RES_DEFNAMES, &addr, (VSTRING *) 0,
why->reason, DNS_REQ_FLAG_ALL,
why->reason, DNS_REQ_FLAG_NONE,
proto_info->dns_atype_list)) {
case DNS_OK:
for (rr = addr; rr; rr = rr->next)
@ -180,6 +180,7 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
if (smtp_errno != SMTP_ERR_RETRY)
smtp_errno = SMTP_ERR_FAIL;
return (addr_list);
case DNS_INVAL:
case DNS_NOTFOUND:
smtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
"5.4.4", 550, "550 Host not found");
@ -474,6 +475,11 @@ DNS_RR *smtp_domain_addr(char *name, int misc_flags, DSN_BUF *why,
addr_list = dns_rr_sort(addr_list, smtp_compare_pref);
}
break;
case DNS_INVAL:
smtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
"5.4.4", 550, "550 Host not found");
smtp_errno = SMTP_ERR_FAIL;
break;
case DNS_NOTFOUND:
addr_list = smtp_host_addr(name, misc_flags, why);
break;

View File

@ -86,7 +86,7 @@ const char *smtp_unalias_name(const char *name)
if ((result = htable_find(cache, name)) == 0) {
fqdn = vstring_alloc(10);
if (dns_lookup_l(name, smtp_unalias_flags, (DNS_RR **) 0, fqdn,
(VSTRING *) 0, DNS_REQ_FLAG_ANY, T_MX, T_A,
(VSTRING *) 0, DNS_REQ_FLAG_NONE, T_MX, T_A,
#ifdef HAS_IPV6
T_AAAA,
#endif

View File

@ -966,7 +966,7 @@ static int reject_unknown_client(SMTPD_STATE *state)
if (state->name_status != SMTPD_PEER_CODE_OK)
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
state->name_status == SMTPD_PEER_CODE_PERM ?
state->name_status == SMTPD_PEER_CODE_PERM ?
var_unk_client_code : 450, "4.7.1",
"Client host rejected: cannot find your hostname, [%s]",
state->addr));
@ -1155,18 +1155,20 @@ static int reject_unknown_hostname(SMTPD_STATE *state, char *name,
#endif
dns_status = dns_lookup_l(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
(VSTRING *) 0, DNS_REQ_FLAG_ANY,
(VSTRING *) 0, DNS_REQ_FLAG_STOP_OK,
RR_ADDR_TYPES, T_MX, 0);
if (dns_status == DNS_NOTFOUND)
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
var_unk_name_code, "4.7.1",
"<%s>: %s rejected: Host not found",
reply_name, reply_class));
else if (dns_status != DNS_OK)
DEFER_IF_PERMIT2(state, MAIL_ERROR_POLICY,
450, "4.7.1",
"<%s>: %s rejected: Host not found",
reply_name, reply_class);
if (dns_status != DNS_OK) { /* incl. DNS_INVAL */
if (dns_status != DNS_RETRY)
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
var_unk_name_code, "4.7.1",
"<%s>: %s rejected: Host not found",
reply_name, reply_class));
else
DEFER_IF_PERMIT2(state, MAIL_ERROR_POLICY,
450, "4.7.1",
"<%s>: %s rejected: Host not found",
reply_name, reply_class);
}
return (SMTPD_CHECK_DUNNO);
}
@ -1181,22 +1183,26 @@ static int reject_unknown_mailhost(SMTPD_STATE *state, const char *name,
if (msg_verbose)
msg_info("%s: %s", myname, name);
#define MAILHOST_LOOKUP_FLAGS (DNS_REQ_FLAG_STOP_OK | DNS_REQ_FLAG_STOP_INVAL)
dns_status = dns_lookup_l(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
(VSTRING *) 0, DNS_REQ_FLAG_ANY,
RR_ADDR_TYPES, T_MX, 0);
if (dns_status == DNS_NOTFOUND)
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
var_unk_addr_code,
(VSTRING *) 0, MAILHOST_LOOKUP_FLAGS,
T_MX, RR_ADDR_TYPES, 0);
if (dns_status != DNS_OK) { /* incl. DNS_INVAL */
if (dns_status != DNS_RETRY)
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
var_unk_addr_code,
strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
"4.1.8" : "4.1.2",
"<%s>: %s rejected: Domain not found",
reply_name, reply_class));
else if (dns_status != DNS_OK)
DEFER_IF_PERMIT2(state, MAIL_ERROR_POLICY,
450, strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
"4.1.8" : "4.1.2",
"<%s>: %s rejected: Domain not found",
reply_name, reply_class);
"4.1.8" : "4.1.2",
"<%s>: %s rejected: Domain not found",
reply_name, reply_class));
else
DEFER_IF_PERMIT2(state, MAIL_ERROR_POLICY,
450, strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
"4.1.8" : "4.1.2",
"<%s>: %s rejected: Domain not found",
reply_name, reply_class);
}
return (SMTPD_CHECK_DUNNO);
}
@ -1395,8 +1401,8 @@ static int all_auth_mx_addr(SMTPD_STATE *state, char *host,
* Verify that all host addresses are within permit_mx_backup_networks.
*/
dns_status = dns_lookup_v(host, 0, &addr_list, (VSTRING *) 0, (VSTRING *) 0,
DNS_REQ_FLAG_ALL, inet_proto_info()->dns_atype_list);
if (dns_status != DNS_OK) {
DNS_REQ_FLAG_NONE, inet_proto_info()->dns_atype_list);
if (dns_status != DNS_OK) { /* incl. DNS_INVAL */
DEFER_IF_REJECT3(state, MAIL_ERROR_POLICY,
450, "4.4.4",
"<%s>: %s rejected: Unable to look up host %s as mail exchanger",
@ -1622,11 +1628,12 @@ static int permit_mx_backup(SMTPD_STATE *state, const char *recipient,
if (dns_status == DNS_NOTFOUND)
return (has_my_addr(state, domain, reply_name, reply_class) ?
SMTPD_CHECK_OK : SMTPD_CHECK_DUNNO);
if (dns_status != DNS_OK) {
DEFER_IF_REJECT2(state, MAIL_ERROR_POLICY,
450, "4.4.4",
"<%s>: %s rejected: Unable to look up mail exchanger information",
reply_name, reply_class);
if (dns_status != DNS_OK) { /* incl. DNS_INVAL */
if (dns_status == DNS_RETRY)
DEFER_IF_REJECT2(state, MAIL_ERROR_POLICY,
450, "4.4.4",
"<%s>: %s rejected: Unable to look up mail exchanger information",
reply_name, reply_class);
return (SMTPD_CHECK_DUNNO);
}
@ -1961,7 +1968,8 @@ static int check_table_result(SMTPD_STATE *state, const char *table,
*/
if (STREQUAL(value, "HOLD", cmd_len)) {
#ifndef TEST
if (can_delegate_action(state, table, "HOLD", reply_class) == 0)
if (can_delegate_action(state, table, "HOLD", reply_class) == 0
|| (state->saved_flags & CLEANUP_FLAG_HOLD))
return (SMTPD_CHECK_DUNNO);
#endif
vstring_sprintf(error_text, "<%s>: %s %s", reply_name, reply_class,
@ -3502,7 +3510,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
forbid_whitelist(state, name, status, state->helo_name);
}
} else if (strcasecmp(name, REJECT_NON_FQDN_HELO_HOSTNAME) == 0
||strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) {
|| strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) {
if (state->helo_name) {
if (*state->helo_name != '[')
status = reject_non_fqdn_hostname(state, state->helo_name,