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
Avoid calling gettimeofday(), select() per char for cmdline message submission. ...
[exim.git]
/
src
/
src
/
smtp_in.c
diff --git
a/src/src/smtp_in.c
b/src/src/smtp_in.c
index 6d23397702dc2d8ac2a609ab2bd0eff04694dc3a..c1aa5867cde8b4281179e5ab249835b656b40c13 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,
};
@@
-563,6
+563,12
@@
if (smtp_inptr >= smtp_inend)
return *smtp_inptr++;
}
return *smtp_inptr++;
}
+BOOL
+smtp_hasc(void)
+{
+return smtp_inptr < smtp_inend;
+}
+
uschar *
smtp_getbuf(unsigned * len)
{
uschar *
smtp_getbuf(unsigned * len)
{
@@
-581,12
+587,12
@@
return buf;
}
void
}
void
-smtp_get_cache(
void
)
+smtp_get_cache(
unsigned lim
)
{
#ifndef DISABLE_DKIM
int n = smtp_inend - smtp_inptr;
{
#ifndef DISABLE_DKIM
int n = smtp_inend - smtp_inptr;
-if (
chunking_state == CHUNKING_LAST && chunking_data_left < n
)
- n =
chunking_data_left
;
+if (
n > lim
)
+ n =
lim
;
if (n > 0)
dkim_exim_verify_feed(smtp_inptr, n);
#endif
if (n > 0)
dkim_exim_verify_feed(smtp_inptr, n);
#endif
@@
-661,7
+667,9
@@
for(;;)
if (chunking_state == CHUNKING_LAST)
{
#ifndef DISABLE_DKIM
if (chunking_state == CHUNKING_LAST)
{
#ifndef DISABLE_DKIM
+ dkim_collect_input = dkim_save;
dkim_exim_verify_feed(NULL, 0); /* notify EOD */
dkim_exim_verify_feed(NULL, 0); /* notify EOD */
+ dkim_collect_input = 0;
#endif
return EOD;
}
#endif
return EOD;
}
@@
-743,6
+751,14
@@
next_cmd:
}
}
}
}
+BOOL
+bdat_hasc(void)
+{
+if (chunking_data_left > 0)
+ return lwr_receive_hasc();
+return TRUE;
+}
+
uschar *
bdat_getbuf(unsigned * len)
{
uschar *
bdat_getbuf(unsigned * len)
{
@@
-782,10
+798,11
@@
bdat_push_receive_functions(void)
/* push the current receive_* function on the "stack", and
replace them by bdat_getc(), which in turn will use the lwr_receive_*
functions to do the dirty work. */
/* push the current receive_* function on the "stack", and
replace them by bdat_getc(), which in turn will use the lwr_receive_*
functions to do the dirty work. */
-if (
lwr_receive_getc == NULL
)
+if (
!lwr_receive_getc
)
{
lwr_receive_getc = receive_getc;
lwr_receive_getbuf = receive_getbuf;
{
lwr_receive_getc = receive_getc;
lwr_receive_getbuf = receive_getbuf;
+ lwr_receive_hasc = receive_hasc;
lwr_receive_ungetc = receive_ungetc;
}
else
lwr_receive_ungetc = receive_ungetc;
}
else
@@
-795,23
+812,26
@@
else
receive_getc = bdat_getc;
receive_getbuf = bdat_getbuf;
receive_getc = bdat_getc;
receive_getbuf = bdat_getbuf;
+receive_hasc = bdat_hasc;
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
)
+if (
!lwr_receive_getc
)
{
DEBUG(D_receive) debug_printf("chunking double-pop receive functions\n");
return;
}
receive_getc = lwr_receive_getc;
receive_getbuf = lwr_receive_getbuf;
{
DEBUG(D_receive) debug_printf("chunking double-pop receive functions\n");
return;
}
receive_getc = lwr_receive_getc;
receive_getbuf = lwr_receive_getbuf;
+receive_hasc = lwr_receive_hasc;
receive_ungetc = lwr_receive_ungetc;
lwr_receive_getc = NULL;
lwr_receive_getbuf = NULL;
receive_ungetc = lwr_receive_ungetc;
lwr_receive_getc = NULL;
lwr_receive_getbuf = NULL;
+lwr_receive_hasc = NULL;
lwr_receive_ungetc = NULL;
}
lwr_receive_ungetc = NULL;
}
@@
-831,6
+851,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;
}
@@
-840,6
+863,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);
}
@@
-2003,30
+2027,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;
@@
-2565,12
+2594,14
@@
smtp_inbuffer[IN_BUFFER_SIZE-1] = '\0';
receive_getc = smtp_getc;
receive_getbuf = smtp_getbuf;
receive_get_cache = smtp_get_cache;
receive_getc = smtp_getc;
receive_getbuf = smtp_getbuf;
receive_get_cache = smtp_get_cache;
+receive_hasc = smtp_hasc;
receive_ungetc = smtp_ungetc;
receive_feof = smtp_feof;
receive_ferror = smtp_ferror;
receive_smtp_buffered = smtp_buffered;
lwr_receive_getc = NULL;
lwr_receive_getbuf = NULL;
receive_ungetc = smtp_ungetc;
receive_feof = smtp_feof;
receive_ferror = smtp_ferror;
receive_smtp_buffered = smtp_buffered;
lwr_receive_getc = NULL;
lwr_receive_getbuf = NULL;
+lwr_receive_hasc = NULL;
lwr_receive_ungetc = NULL;
smtp_inptr = smtp_inend = smtp_inbuffer;
smtp_had_eof = smtp_had_error = 0;
lwr_receive_ungetc = NULL;
smtp_inptr = smtp_inend = smtp_inbuffer;
smtp_had_eof = smtp_had_error = 0;
@@
-2927,8
+2958,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
@@
-3006,7
+3037,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
@@
-3186,7
+3217,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)
@@
-3201,7
+3232,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;
@@
-3257,27
+3288,26
@@
void
smtp_message_code(uschar **code, int *codelen, uschar **msg, uschar **log_msg,
BOOL check_valid)
{
smtp_message_code(uschar **code, int *codelen, uschar **msg, uschar **log_msg,
BOOL check_valid)
{
-
int n
;
-int
ovector[3]
;
+
uschar * match
;
+int
len
;
-if (!msg || !*msg) return;
-
-if ((n = pcre_exec(regex_smtp_code, NULL, CS *msg, Ustrlen(*msg), 0,
- PCRE_EOPT, ovector, sizeof(ovector)/sizeof(int))) < 0) return;
+if (!msg || !*msg || !regex_match(regex_smtp_code, *msg, -1, &match))
+ return;
+len = Ustrlen(match);
if (check_valid && (*msg)[0] != (*code)[0])
{
log_write(0, LOG_MAIN|LOG_PANIC, "configured error code starts with "
"incorrect digit (expected %c) in \"%s\"", (*code)[0], *msg);
if (check_valid && (*msg)[0] != (*code)[0])
{
log_write(0, LOG_MAIN|LOG_PANIC, "configured error code starts with "
"incorrect digit (expected %c) in \"%s\"", (*code)[0], *msg);
- if (log_msg
!= NULL
&& *log_msg == *msg)
- *log_msg = string_sprintf("%s %s", *code, *log_msg +
ovector[1]
);
+ if (log_msg && *log_msg == *msg)
+ *log_msg = string_sprintf("%s %s", *code, *log_msg +
len
);
}
else
{
*code = *msg;
}
else
{
*code = *msg;
- *codelen =
ovector[1]
; /* Includes final space */
+ *codelen =
len
; /* Includes final space */
}
}
-*msg +=
ovector[1]
; /* Chop the code off the message */
+*msg +=
len
; /* Chop the code off the message */
return;
}
return;
}
@@
-3972,7
+4002,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;
@@
-4242,7
+4271,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. */
@@
-4270,19
+4299,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);
@@
-4339,7
+4368,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)
@@
-4401,12
+4430,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);
@@
-4630,15
+4659,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)
{
@@
-4657,7
+4687,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 "