summaryrefslogtreecommitdiffstats
path: root/src/smtp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/smtp/smtp_addr.c13
-rw-r--r--src/smtpd/smtpd.c19
-rw-r--r--src/smtpd/smtpd_check.c10
-rw-r--r--src/smtpd/smtpd_sasl_glue.c10
4 files changed, 46 insertions, 6 deletions
diff --git a/src/smtp/smtp_addr.c b/src/smtp/smtp_addr.c
index 2b5c126..fa0af4e 100644
--- a/src/smtp/smtp_addr.c
+++ b/src/smtp/smtp_addr.c
@@ -154,7 +154,7 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, const char *host, int res_opt,
msg_fatal("host %s: conversion error for address family "
"%d: %m", host, res0->ai_addr->sa_family);
addr_list = dns_rr_append(addr_list, addr);
- if (msg_verbose)
+ if (msg_verbose && !DNS_RR_IS_TRUNCATED(addr_list))
msg_info("%s: using numerical host %s", myname, host);
freeaddrinfo(res0);
return (addr_list);
@@ -232,6 +232,8 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, const char *host, int res_opt,
msg_fatal("host %s: conversion error for address family "
"%d: %m", host, res0->ai_addr->sa_family);
addr_list = dns_rr_append(addr_list, addr);
+ if (DNS_RR_IS_TRUNCATED(addr_list))
+ break;
if (msg_verbose) {
MAI_HOSTADDR_STR hostaddr_str;
@@ -297,6 +299,8 @@ static DNS_RR *smtp_addr_list(DNS_RR *mx_names, DSN_BUF *why)
msg_panic("smtp_addr_list: bad resource type: %d", rr->type);
addr_list = smtp_addr_one(addr_list, (char *) rr->data, res_opt,
rr->pref, why);
+ if (addr_list && DNS_RR_IS_TRUNCATED(addr_list))
+ break;
}
return (addr_list);
}
@@ -391,6 +395,13 @@ static DNS_RR *smtp_balance_inet_proto(DNS_RR *addr_list, int misc_flags,
*/
/*
+ * Ensure that dns_rr_append() won't interfere with the protocol
+ * balancing goals.
+ */
+ if (addr_limit > var_dns_rr_list_limit)
+ addr_limit = var_dns_rr_list_limit;
+
+ /*
* Count the number of IPv6 and IPv4 addresses.
*/
for (v4_count = v6_count = 0, rr = addr_list; rr != 0; rr = rr->next) {
diff --git a/src/smtpd/smtpd.c b/src/smtpd/smtpd.c
index 4f4aedd..c2aa428 100644
--- a/src/smtpd/smtpd.c
+++ b/src/smtpd/smtpd.c
@@ -4114,14 +4114,31 @@ static int bdat_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
/*
* Read lines from the fragment. The last line may continue in the
* next fragment, or in the next chunk.
+ *
+ * If smtp_get_noexcept() stopped after var_line_limit bytes and did not
+ * emit a queue file record, then that means smtp_get_noexcept()
+ * stopped after CR and hit EOF as it tried to find out if the next
+ * byte is LF. In that case, read the first byte from the next
+ * fragment or chunk, and if that first byte is LF, then
+ * smtp_get_noexcept() strips off the trailing CRLF and returns '\n'
+ * as it always does after reading a complete line.
*/
do {
+ int can_read = var_line_limit - LEN(state->bdat_get_buffer);
+
if (smtp_get_noexcept(state->bdat_get_buffer,
state->bdat_get_stream,
- var_line_limit,
+ can_read > 0 ? can_read : 1, /* Peek one */
SMTP_GET_FLAG_APPEND) == '\n') {
/* Stopped at end-of-line. */
curr_rec_type = REC_TYPE_NORM;
+ } else if (LEN(state->bdat_get_buffer) > var_line_limit) {
+ /* Undo peeking, and output the buffer as REC_TYPE_CONT. */
+ vstream_ungetc(state->bdat_get_stream,
+ vstring_end(state->bdat_get_buffer)[-1]);
+ vstring_truncate(state->bdat_get_buffer,
+ LEN(state->bdat_get_buffer) - 1);
+ curr_rec_type = REC_TYPE_CONT;
} else if (!vstream_feof(state->bdat_get_stream)) {
/* Stopped at var_line_limit. */
curr_rec_type = REC_TYPE_CONT;
diff --git a/src/smtpd/smtpd_check.c b/src/smtpd/smtpd_check.c
index 996a19e..513652d 100644
--- a/src/smtpd/smtpd_check.c
+++ b/src/smtpd/smtpd_check.c
@@ -2993,6 +2993,7 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
struct addrinfo *res;
int status;
const INET_PROTO_INFO *proto_info;
+ int server_addr_count = 0;
/*
* Sanity check.
@@ -3144,6 +3145,15 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
msg_info("%s: %s host address check: %s",
myname, dns_strtype(type), (char *) server->data);
for (res = res0; res != 0; res = res->ai_next) {
+ server_addr_count += 1;
+ if (server_addr_count > var_dns_rr_list_limit) {
+ msg_warn("%s: %s server address count limit (%d) exceeded"
+ " for %s %s -- ignoring the remainder", myname,
+ dns_strtype(type), var_dns_rr_list_limit,
+ reply_class, reply_name);
+ freeaddrinfo(res0);
+ CHECK_SERVER_RETURN(SMTPD_CHECK_DUNNO);
+ }
if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
if (msg_verbose)
msg_info("skipping address family %d for host %s",
diff --git a/src/smtpd/smtpd_sasl_glue.c b/src/smtpd/smtpd_sasl_glue.c
index 2dc6aad..d9db7b0 100644
--- a/src/smtpd/smtpd_sasl_glue.c
+++ b/src/smtpd/smtpd_sasl_glue.c
@@ -340,18 +340,20 @@ int smtpd_sasl_authenticate(SMTPD_STATE *state,
}
}
if (status != XSASL_AUTH_DONE) {
+ const char *reason = (*STR(state->sasl_reply) ? STR(state->sasl_reply) :
+ "(reason unavailable)");
+
sasl_username = xsasl_server_get_username(state->sasl_server);
msg_warn("%s: SASL %.100s authentication failed: %s, sasl_username=%.100s",
- state->namaddr, sasl_method, *STR(state->sasl_reply) ?
- STR(state->sasl_reply) : "(reason unavailable)",
+ state->namaddr, sasl_method, reason,
sasl_username ? sasl_username : "(unavailable)");
/* RFC 4954 Section 6. */
if (status == XSASL_AUTH_TEMP)
smtpd_chat_reply(state, "454 4.7.0 Temporary authentication failure: %s",
- STR(state->sasl_reply));
+ reason);
else
smtpd_chat_reply(state, "535 5.7.8 Error: authentication failed: %s",
- STR(state->sasl_reply));
+ reason);
return (-1);
}
/* RFC 4954 Section 6. */