git://git.exim.org
/
exim.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
typo
[exim.git]
/
src
/
src
/
smtp_in.c
diff --git
a/src/src/smtp_in.c
b/src/src/smtp_in.c
index 93d5cece38525c40dfaaf1d3e32955f1c030c658..ee248c5173e4c1ac0ab81524532b47f40f7c73c2 100644
(file)
--- a/
src/src/smtp_in.c
+++ b/
src/src/smtp_in.c
@@
-139,7
+139,7
@@
static struct {
#endif
BOOL dsn_advertised :1;
BOOL esmtp :1;
#endif
BOOL dsn_advertised :1;
BOOL esmtp :1;
- BOOL helo_
required
:1;
+ BOOL helo_
verify_required
:1;
BOOL helo_verify :1;
BOOL helo_seen :1;
BOOL helo_accept_junk :1;
BOOL helo_verify :1;
BOOL helo_seen :1;
BOOL helo_accept_junk :1;
@@
-153,7
+153,7
@@
static struct {
BOOL smtputf8_advertised :1;
#endif
} fl = {
BOOL smtputf8_advertised :1;
#endif
} fl = {
- .helo_required = FALSE,
+ .helo_
verify_
required = FALSE,
.helo_verify = FALSE,
.smtp_exit_function_called = FALSE,
};
.helo_verify = FALSE,
.smtp_exit_function_called = FALSE,
};
@@
-794,15
+794,22
@@
else
}
receive_getc = bdat_getc;
}
receive_getc = bdat_getc;
+receive_getbuf = bdat_getbuf;
receive_ungetc = bdat_ungetc;
}
static inline void
bdat_pop_receive_functions(void)
{
receive_ungetc = bdat_ungetc;
}
static inline void
bdat_pop_receive_functions(void)
{
+if (lwr_receive_getc == NULL)
+ {
+ DEBUG(D_receive) debug_printf("chunking double-pop receive functions\n");
+ return;
+ }
receive_getc = lwr_receive_getc;
receive_getbuf = lwr_receive_getbuf;
receive_ungetc = lwr_receive_ungetc;
receive_getc = lwr_receive_getc;
receive_getbuf = lwr_receive_getbuf;
receive_ungetc = lwr_receive_ungetc;
+
lwr_receive_getc = NULL;
lwr_receive_getbuf = NULL;
lwr_receive_ungetc = NULL;
lwr_receive_getc = NULL;
lwr_receive_getbuf = NULL;
lwr_receive_ungetc = NULL;
@@
-824,6
+831,9
@@
Returns: the character
int
smtp_ungetc(int ch)
{
int
smtp_ungetc(int ch)
{
+if (smtp_inptr <= smtp_inbuffer)
+ log_write(0, LOG_MAIN|LOG_PANIC_DIE, "buffer underflow in smtp_ungetc");
+
*--smtp_inptr = ch;
return ch;
}
*--smtp_inptr = ch;
return ch;
}
@@
-833,6
+843,7
@@
int
bdat_ungetc(int ch)
{
chunking_data_left++;
bdat_ungetc(int ch)
{
chunking_data_left++;
+bdat_push_receive_functions(); /* we're not done yet, calling push is safe, because it checks the state before pushing anything */
return lwr_receive_ungetc(ch);
}
return lwr_receive_ungetc(ch);
}
@@
-1996,30
+2007,35
@@
static BOOL
extract_option(uschar **name, uschar **value)
{
uschar *n;
extract_option(uschar **name, uschar **value)
{
uschar *n;
-uschar *v = smtp_cmd_data + Ustrlen(smtp_cmd_data) - 1;
-while (isspace(*v)) v--;
-v[1] = '\0';
+uschar *v;
+if (Ustrlen(smtp_cmd_data) <= 0) return FALSE;
+v = smtp_cmd_data + Ustrlen(smtp_cmd_data) - 1;
+while (v > smtp_cmd_data && isspace(*v)) v--;
+v[1] = 0;
+
while (v > smtp_cmd_data && *v != '=' && !isspace(*v))
{
/* Take care to not stop at a space embedded in a quoted local-part */
while (v > smtp_cmd_data && *v != '=' && !isspace(*v))
{
/* Take care to not stop at a space embedded in a quoted local-part */
-
- if ((*v == '"') && (v > smtp_cmd_data + 1))
- do v--; while (*v != '"' && v > smtp_cmd_data+1);
+ if (*v == '"')
+ {
+ do v--; while (v > smtp_cmd_data && *v != '"');
+ if (v <= smtp_cmd_data) return FALSE;
+ }
v--;
}
v--;
}
+if (v <= smtp_cmd_data) return FALSE;
n = v;
if (*v == '=')
{
n = v;
if (*v == '=')
{
- while
(
isalpha(n[-1])) n--;
+ while
(n > smtp_cmd_data &&
isalpha(n[-1])) n--;
/* RFC says SP, but TAB seen in wild and other major MTAs accept it */
/* RFC says SP, but TAB seen in wild and other major MTAs accept it */
- if (!isspace(n[-1])) return FALSE;
+ if (
n <= smtp_cmd_data ||
!isspace(n[-1])) return FALSE;
n[-1] = 0;
}
else
{
n++;
n[-1] = 0;
}
else
{
n++;
- if (v == smtp_cmd_data) return FALSE;
}
*v++ = 0;
*name = n;
}
*v++ = 0;
*name = n;
@@
-2920,8
+2936,8
@@
if (!f.sender_host_unknown)
/* Determine whether HELO/EHLO is required for this host. The requirement
can be hard or soft. */
/* Determine whether HELO/EHLO is required for this host. The requirement
can be hard or soft. */
- fl.helo_required = verify_check_host(&helo_verify_hosts) == OK;
- if (!fl.helo_required)
+ fl.helo_
verify_
required = verify_check_host(&helo_verify_hosts) == OK;
+ if (!fl.helo_
verify_
required)
fl.helo_verify = verify_check_host(&helo_try_verify_hosts) == OK;
/* Determine whether this hosts is permitted to send syntactic junk
fl.helo_verify = verify_check_host(&helo_try_verify_hosts) == OK;
/* Determine whether this hosts is permitted to send syntactic junk
@@
-2999,7
+3015,7
@@
else
p = s + Ustrlen(s);
while (p > s && isspace(p[-1])) p--;
p = s + Ustrlen(s);
while (p > s && isspace(p[-1])) p--;
-
*p = 0
;
+
s = string_copyn(s, p-s)
;
/* It seems that CC:Mail is braindead, and assumes that the greeting message
is all contained in a single IP packet. The original code wrote out the
/* It seems that CC:Mail is braindead, and assumes that the greeting message
is all contained in a single IP packet. The original code wrote out the
@@
-3179,7
+3195,7
@@
which sometimes uses smtp_printf() and sometimes smtp_respond(). */
if (fl.rcpt_in_progress)
{
if (fl.rcpt_in_progress)
{
- if (
rcpt_smtp_response == NULL
)
+ if (
!rcpt_smtp_response
)
rcpt_smtp_response = string_copy(msg);
else if (fl.rcpt_smtp_response_same &&
Ustrcmp(rcpt_smtp_response, msg) != 0)
rcpt_smtp_response = string_copy(msg);
else if (fl.rcpt_smtp_response_same &&
Ustrcmp(rcpt_smtp_response, msg) != 0)
@@
-3194,7
+3210,7
@@
not the whole MAIL/RCPT/DATA response set. */
for (;;)
{
uschar *nl = Ustrchr(msg, '\n');
for (;;)
{
uschar *nl = Ustrchr(msg, '\n');
- if (
nl == NULL
)
+ if (
!nl
)
{
smtp_printf("%.3s%c%.*s%s\r\n", !final, code, final ? ' ':'-', esclen, esc, msg);
return;
{
smtp_printf("%.3s%c%.*s%s\r\n", !final, code, final ? ' ':'-', esclen, esc, msg);
return;
@@
-3965,7
+3981,6
@@
int
smtp_setup_msg(void)
{
int done = 0;
smtp_setup_msg(void)
{
int done = 0;
-int mailmax = -1;
BOOL toomany = FALSE;
BOOL discarded = FALSE;
BOOL last_was_rej_mail = FALSE;
BOOL toomany = FALSE;
BOOL discarded = FALSE;
BOOL last_was_rej_mail = FALSE;
@@
-4235,7
+4250,7
@@
while (done <= 0)
/* If sender_host_unknown is true, we have got here via the -bs interface,
not called from inetd. Otherwise, we are running an IP connection and the
host address will be set. If the helo name is the primary name of this
/* If sender_host_unknown is true, we have got here via the -bs interface,
not called from inetd. Otherwise, we are running an IP connection and the
host address will be set. If the helo name is the primary name of this
- host and we haven't done a reverse lookup, force one now. If helo_required
+ host and we haven't done a reverse lookup, force one now. If helo_
verify_
required
is set, ensure that the HELO name matches the actual host. If helo_verify
is set, do the same check, but softly. */
is set, ensure that the HELO name matches the actual host. If helo_verify
is set, do the same check, but softly. */
@@
-4263,19
+4278,19
@@
while (done <= 0)
tls_in.active.sock >= 0 ? " TLS" : "", host_and_ident(FALSE));
/* Verify if configured. This doesn't give much security, but it does
tls_in.active.sock >= 0 ? " TLS" : "", host_and_ident(FALSE));
/* Verify if configured. This doesn't give much security, but it does
- make some people happy to be able to do it. If helo_required is set,
+ make some people happy to be able to do it. If helo_
verify_
required is set,
(host matches helo_verify_hosts) failure forces rejection. If helo_verify
is set (host matches helo_try_verify_hosts), it does not. This is perhaps
now obsolescent, since the verification can now be requested selectively
at ACL time. */
f.helo_verified = f.helo_verify_failed = sender_helo_dnssec = FALSE;
(host matches helo_verify_hosts) failure forces rejection. If helo_verify
is set (host matches helo_try_verify_hosts), it does not. This is perhaps
now obsolescent, since the verification can now be requested selectively
at ACL time. */
f.helo_verified = f.helo_verify_failed = sender_helo_dnssec = FALSE;
- if (fl.helo_required || fl.helo_verify)
+ if (fl.helo_
verify_
required || fl.helo_verify)
{
BOOL tempfail = !smtp_verify_helo();
if (!f.helo_verified)
{
{
BOOL tempfail = !smtp_verify_helo();
if (!f.helo_verified)
{
- if (fl.helo_required)
+ if (fl.helo_
verify_
required)
{
smtp_printf("%d %s argument does not match calling host\r\n", FALSE,
tempfail? 451 : 550, hello);
{
smtp_printf("%d %s argument does not match calling host\r\n", FALSE,
tempfail? 451 : 550, hello);
@@
-4332,7
+4347,7
@@
while (done <= 0)
#endif
/* Expand the per-connection message count limit option */
#endif
/* Expand the per-connection message count limit option */
-
mail
max = expand_mailmax(smtp_accept_max_per_connection);
+
smtp_mailcmd_
max = expand_mailmax(smtp_accept_max_per_connection);
smtp_code = US"250 "; /* Default response code plus space*/
if (!user_msg)
smtp_code = US"250 "; /* Default response code plus space*/
if (!user_msg)
@@
-4394,12
+4409,12
@@
while (done <= 0)
}
#ifdef EXPERIMENTAL_ESMTP_LIMITS
}
#ifdef EXPERIMENTAL_ESMTP_LIMITS
- if ( (
mail
max > 0 || recipients_max)
+ if ( (
smtp_mailcmd_
max > 0 || recipients_max)
&& verify_check_host(&limits_advertise_hosts) == OK)
{
g = string_fmt_append(g, "%.3s-LIMITS", smtp_code);
&& verify_check_host(&limits_advertise_hosts) == OK)
{
g = string_fmt_append(g, "%.3s-LIMITS", smtp_code);
- if (
mail
max > 0)
- g = string_fmt_append(g, " MAILMAX=%d",
mail
max);
+ if (
smtp_mailcmd_
max > 0)
+ g = string_fmt_append(g, " MAILMAX=%d",
smtp_mailcmd_
max);
if (recipients_max)
g = string_fmt_append(g, " RCPTMAX=%d", recipients_max);
g = string_catn(g, US"\r\n", 2);
if (recipients_max)
g = string_fmt_append(g, " RCPTMAX=%d", recipients_max);
g = string_catn(g, US"\r\n", 2);
@@
-4623,15
+4638,16
@@
while (done <= 0)
env_mail_type_t * mail_args; /* Sanity check & validate args */
if (!fl.helo_seen)
env_mail_type_t * mail_args; /* Sanity check & validate args */
if (!fl.helo_seen)
- if (fl.helo_required)
+ if ( fl.helo_verify_required
+ || verify_check_host(&hosts_require_helo) == OK)
{
smtp_printf("503 HELO or EHLO required\r\n", FALSE);
log_write(0, LOG_MAIN|LOG_REJECT, "rejected MAIL from %s: no "
"HELO/EHLO given", host_and_ident(FALSE));
break;
}
{
smtp_printf("503 HELO or EHLO required\r\n", FALSE);
log_write(0, LOG_MAIN|LOG_REJECT, "rejected MAIL from %s: no "
"HELO/EHLO given", host_and_ident(FALSE));
break;
}
- else if (
mail
max < 0)
-
mail
max = expand_mailmax(smtp_accept_max_per_connection);
+ else if (
smtp_mailcmd_
max < 0)
+
smtp_mailcmd_
max = expand_mailmax(smtp_accept_max_per_connection);
if (sender_address)
{
if (sender_address)
{
@@
-4650,7
+4666,7
@@
while (done <= 0)
/* Check to see if the limit for messages per connection would be
exceeded by accepting further messages. */
/* Check to see if the limit for messages per connection would be
exceeded by accepting further messages. */
- if (
mailmax > 0 && smtp_mailcmd_count > mail
max)
+ if (
smtp_mailcmd_max > 0 && smtp_mailcmd_count > smtp_mailcmd_
max)
{
smtp_printf("421 too many messages in this connection\r\n", FALSE);
log_write(0, LOG_MAIN|LOG_REJECT, "rejected MAIL command %s: too many "
{
smtp_printf("421 too many messages in this connection\r\n", FALSE);
log_write(0, LOG_MAIN|LOG_REJECT, "rejected MAIL command %s: too many "
@@
-5036,6
+5052,10
@@
while (done <= 0)
case RCPT_CMD:
HAD(SCH_RCPT);
case RCPT_CMD:
HAD(SCH_RCPT);
+ /* We got really to many recipients. A check against configured
+ limits is done later */
+ if (rcpt_count < 0 || rcpt_count >= INT_MAX/2)
+ log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Too many recipients: %d", rcpt_count);
rcpt_count++;
was_rcpt = fl.rcpt_in_progress = TRUE;
rcpt_count++;
was_rcpt = fl.rcpt_in_progress = TRUE;
@@
-5192,7
+5212,7
@@
while (done <= 0)
/* Check maximum allowed */
/* Check maximum allowed */
- if (rcpt_count > recipients_max && recipients_max > 0)
+ if (rcpt_count
+1 < 0 || rcpt_count
> recipients_max && recipients_max > 0)
{
if (recipients_max_reject)
{
{
if (recipients_max_reject)
{
@@
-5337,7
+5357,7
@@
while (done <= 0)
DEBUG(D_receive) debug_printf("chunking state %d, %d bytes\n",
(int)chunking_state, chunking_data_left);
DEBUG(D_receive) debug_printf("chunking state %d, %d bytes\n",
(int)chunking_state, chunking_data_left);
- f.bdat_readers_wanted = TRUE;
+ f.bdat_readers_wanted = TRUE;
/* FIXME: redundant vs chunking_state? */
f.dot_ends = FALSE;
goto DATA_BDAT;
f.dot_ends = FALSE;
goto DATA_BDAT;
@@
-5387,6
+5407,12
@@
while (done <= 0)
sender_address = NULL; /* This will allow a new MAIL without RSET */
sender_address_unrewritten = NULL;
smtp_printf("554 Too many recipients\r\n", FALSE);
sender_address = NULL; /* This will allow a new MAIL without RSET */
sender_address_unrewritten = NULL;
smtp_printf("554 Too many recipients\r\n", FALSE);
+
+ if (chunking_state > CHUNKING_OFFERED)
+ {
+ bdat_push_receive_functions();
+ bdat_flush_data();
+ }
break;
}
break;
}