tls_auth is a pseudo-command, never expected in input. It is activated
on TLS startup and looks for a tls authenticator. */
+enum { CL_RSET, CL_HELO, CL_EHLO, CL_AUTH,
+#ifndef DISABLE_TLS
+ CL_STLS, CL_TLAU,
+#endif
+};
+
static smtp_cmd_list cmd_list[] = {
/* name len cmd has_arg is_mail_cmd */
- { "rset", sizeof("rset")-1, RSET_CMD, FALSE, FALSE }, /* First */
- { "helo", sizeof("helo")-1, HELO_CMD, TRUE, FALSE },
- { "ehlo", sizeof("ehlo")-1, EHLO_CMD, TRUE, FALSE },
- { "auth", sizeof("auth")-1, AUTH_CMD, TRUE, TRUE },
+ [CL_RSET] = { "rset", sizeof("rset")-1, RSET_CMD, FALSE, FALSE }, /* First */
+ [CL_HELO] = { "helo", sizeof("helo")-1, HELO_CMD, TRUE, FALSE },
+ [CL_EHLO] = { "ehlo", sizeof("ehlo")-1, EHLO_CMD, TRUE, FALSE },
+ [CL_AUTH] = { "auth", sizeof("auth")-1, AUTH_CMD, TRUE, TRUE },
#ifndef DISABLE_TLS
- { "starttls", sizeof("starttls")-1, STARTTLS_CMD, FALSE, FALSE },
- { "tls_auth", 0, TLS_AUTH_CMD, FALSE, FALSE },
+ [CL_STLS] = { "starttls", sizeof("starttls")-1, STARTTLS_CMD, FALSE, FALSE },
+ [CL_TLAU] = { "tls_auth", 0, TLS_AUTH_CMD, FALSE, FALSE },
#endif
/* If you change anything above here, also fix the definitions below. */
{ "help", sizeof("help")-1, HELP_CMD, TRUE, FALSE }
};
-static smtp_cmd_list *cmd_list_end =
- cmd_list + sizeof(cmd_list)/sizeof(smtp_cmd_list);
-
-#define CMD_LIST_RSET 0
-#define CMD_LIST_HELO 1
-#define CMD_LIST_EHLO 2
-#define CMD_LIST_AUTH 3
-#define CMD_LIST_STARTTLS 4
-#define CMD_LIST_TLS_AUTH 5
-
-/* This list of names is used for performing the smtp_no_mail logging action.
-It must be kept in step with the SCH_xxx enumerations. */
+/* This list of names is used for performing the smtp_no_mail logging action. */
uschar * smtp_names[] =
{
- US"NONE", US"AUTH", US"DATA", US"BDAT", US"EHLO", US"ETRN", US"EXPN",
- US"HELO", US"HELP", US"MAIL", US"NOOP", US"QUIT", US"RCPT", US"RSET",
- US"STARTTLS", US"VRFY" };
+ [SCH_NONE] = US"NONE",
+ [SCH_AUTH] = US"AUTH",
+ [SCH_DATA] = US"DATA",
+ [SCH_BDAT] = US"BDAT",
+ [SCH_EHLO] = US"EHLO",
+ [SCH_ETRN] = US"ETRN",
+ [SCH_EXPN] = US"EXPN",
+ [SCH_HELO] = US"HELO",
+ [SCH_HELP] = US"HELP",
+ [SCH_MAIL] = US"MAIL",
+ [SCH_NOOP] = US"NOOP",
+ [SCH_QUIT] = US"QUIT",
+ [SCH_RCPT] = US"RCPT",
+ [SCH_RSET] = US"RSET",
+ [SCH_STARTTLS] = US"STARTTLS",
+ [SCH_VRFY] = US"VRFY",
+ };
static uschar *protocols_local[] = {
US"local-smtp", /* HELO */
*/
static void
-incomplete_transaction_log(uschar *what)
+incomplete_transaction_log(uschar * what)
{
if (!sender_address /* No transaction in progress */
|| !LOGGING(smtp_incomplete_transaction))
+static void
+log_close_event(const uschar * reason)
+{
+log_write(L_smtp_connection, LOG_MAIN, "%s D=%s closed %s",
+ smtp_get_connection_info(), string_timesince(&smtp_connection_start), reason);
+}
+
void
smtp_command_timeout_exit(void)
{
log_write(L_lost_incoming_connection,
- LOG_MAIN, "SMTP command timeout on%s connection from %s",
- tls_in.active.sock >= 0 ? " TLS" : "", host_and_ident(FALSE));
+ LOG_MAIN, "SMTP command timeout on%s connection from %s D=%s",
+ tls_in.active.sock >= 0 ? " TLS" : "", host_and_ident(FALSE),
+ string_timesince(&smtp_connection_start));
if (smtp_batched_input)
moan_smtp_batch(NULL, "421 SMTP command timeout"); /* Does not return */
smtp_notquit_exit(US"command-timeout", US"421",
void
smtp_command_sigterm_exit(void)
{
-log_write(0, LOG_MAIN, "%s closed after SIGTERM", smtp_get_connection_info());
+log_close_event(US"after SIGTERM");
if (smtp_batched_input)
moan_smtp_batch(NULL, "421 SIGTERM received"); /* Does not return */
smtp_notquit_exit(US"signal-exit", US"421",
void
smtp_data_timeout_exit(void)
{
-log_write(L_lost_incoming_connection,
- LOG_MAIN, "SMTP data timeout (message abandoned) on connection from %s F=<%s>",
- sender_fullhost ? sender_fullhost : US"local process", sender_address);
+log_write(L_lost_incoming_connection, LOG_MAIN,
+ "SMTP data timeout (message abandoned) on connection from %s F=<%s> D=%s",
+ sender_fullhost ? sender_fullhost : US"local process", sender_address,
+ string_timesince(&smtp_connection_start));
receive_bomb_out(US"data-timeout", US"SMTP incoming data timeout");
/* Does not return */
}
void
smtp_data_sigint_exit(void)
{
-log_write(0, LOG_MAIN, "%s closed after %s",
- smtp_get_connection_info(), had_data_sigint == SIGTERM ? "SIGTERM":"SIGINT");
+log_close_event(had_data_sigint == SIGTERM ? US"SIGTERM":US"SIGINT");
receive_bomb_out(US"signal-exit",
US"Service not available - SIGTERM or SIGINT received");
/* Does not return */
return -1;
}
+
+static void
+proxy_debug(uschar * buf, unsigned start, unsigned end)
+{
+debug_printf("PROXY<<");
+while (start < end) debug_printf(" %02x", buf[start++]);
+debug_printf("\n");
+}
+
+
/*************************************************
* Setup host for proxy protocol *
*************************************************/
we have to do a minimum of 3 read calls, not 1. Eww.
*/
-#define PROXY_INITIAL_READ 14
-#define PROXY_V2_HEADER_SIZE 16
-#if PROXY_INITIAL_READ > PROXY_V2_HEADER_SIZE
-# error Code bug in sizes of data to read for proxy usage
-#endif
+# define PROXY_INITIAL_READ 14
+# define PROXY_V2_HEADER_SIZE 16
+# if PROXY_INITIAL_READ > PROXY_V2_HEADER_SIZE
+# error Code bug in sizes of data to read for proxy usage
+# endif
int get_ok = 0;
int size, ret;
"safe". Can't take it all because TLS-on-connect clients follow
immediately with TLS handshake. */
ret = read(fd, &hdr, PROXY_INITIAL_READ);
- }
- while (ret == -1 && errno == EINTR && !had_command_timeout);
+ } while (ret == -1 && errno == EINTR && !had_command_timeout);
if (ret == -1)
goto proxyfail;
+DEBUG(D_receive) proxy_debug(US &hdr, 0, ret);
/* For v2, handle reading the length, and then the rest. */
if ((ret == PROXY_INITIAL_READ) && (memcmp(&hdr.v2, v2sig, sizeof(v2sig)) == 0))
int retmore;
uint8_t ver;
+ DEBUG(D_receive) debug_printf("v2\n");
+
/* First get the length fields. */
do
{
} while (retmore == -1 && errno == EINTR && !had_command_timeout);
if (retmore == -1)
goto proxyfail;
+ DEBUG(D_receive) proxy_debug(US &hdr, ret, ret + retmore);
+
ret += retmore;
ver = (hdr.v2.ver_cmd & 0xf0) >> 4;
} while (retmore == -1 && errno == EINTR && !had_command_timeout);
if (retmore == -1)
goto proxyfail;
+ DEBUG(D_receive) proxy_debug(US &hdr, ret, ret + retmore);
ret += retmore;
DEBUG(D_receive) debug_printf("PROXYv2: have %d/%d required octets\n", ret, size);
} while (ret < size);
ALARM(0);
return;
}
-#endif
+#endif /*SUPPORT_PROXY*/
/*************************************************
* Read one command line *
to the start of the actual data characters. Check for SMTP synchronization
if required. */
-for (smtp_cmd_list * p = cmd_list; p < cmd_list_end; p++)
+for (smtp_cmd_list * p = cmd_list; p < cmd_list + nelem(cmd_list); p++)
{
#ifdef SUPPORT_PROXY
/* Only allow QUIT command if Proxy Protocol parsing failed */
#endif
+static void
+log_connect_tls_drop(const uschar * what, const uschar * log_msg)
+{
+gstring * g = s_tlslog(NULL);
+uschar * tls = string_from_gstring(g);
+
+log_write(L_connection_reject,
+ log_reject_target, "%s%s%s dropped by %s%s%s",
+ LOGGING(dnssec) && sender_host_dnssec ? US" DS" : US"",
+ host_and_ident(TRUE),
+ tls ? tls : US"",
+ what,
+ log_msg ? US": " : US"", log_msg);
+}
+
+
/*************************************************
* Start an SMTP session *
*************************************************/
#if !HAVE_IPV6 && !defined(NO_IP_OPTIONS)
- #ifdef GLIBC_IP_OPTIONS
- #if (!defined __GLIBC__) || (__GLIBC__ < 2)
- #define OPTSTYLE 1
- #else
- #define OPTSTYLE 2
- #endif
- #elif defined DARWIN_IP_OPTIONS
- #define OPTSTYLE 2
- #else
- #define OPTSTYLE 3
- #endif
+# ifdef GLIBC_IP_OPTIONS
+# if (!defined __GLIBC__) || (__GLIBC__ < 2)
+# define OPTSTYLE 1
+# else
+# define OPTSTYLE 2
+# endif
+# elif defined DARWIN_IP_OPTIONS
+# define OPTSTYLE 2
+# else
+# define OPTSTYLE 3
+# endif
if (!host_checking && !f.sender_host_notsocket)
{
- #if OPTSTYLE == 1
+# if OPTSTYLE == 1
EXIM_SOCKLEN_T optlen = sizeof(struct ip_options) + MAX_IPOPTLEN;
struct ip_options *ipopt = store_get(optlen, GET_UNTAINTED);
- #elif OPTSTYLE == 2
+# elif OPTSTYLE == 2
struct ip_opts ipoptblock;
struct ip_opts *ipopt = &ipoptblock;
EXIM_SOCKLEN_T optlen = sizeof(ipoptblock);
- #else
+# else
struct ipoption ipoptblock;
struct ipoption *ipopt = &ipoptblock;
EXIM_SOCKLEN_T optlen = sizeof(ipoptblock);
- #endif
+# endif
/* Occasional genuine failures of getsockopt() have been seen - for
example, "reset by peer". Therefore, just log and give up on this
else if (optlen > 0)
{
- uschar *p = big_buffer;
- uschar *pend = big_buffer + big_buffer_size;
- uschar *adptr;
+ uschar * p = big_buffer;
+ uschar * pend = big_buffer + big_buffer_size;
+ uschar * adptr;
int optcount;
struct in_addr addr;
- #if OPTSTYLE == 1
- uschar *optstart = US (ipopt->__data);
- #elif OPTSTYLE == 2
- uschar *optstart = US (ipopt->ip_opts);
- #else
- uschar *optstart = US (ipopt->ipopt_list);
- #endif
+# if OPTSTYLE == 1
+ uschar * optstart = US (ipopt->__data);
+# elif OPTSTYLE == 2
+ uschar * optstart = US (ipopt->ip_opts);
+# else
+ uschar * optstart = US (ipopt->ipopt_list);
+# endif
DEBUG(D_receive) debug_printf("IP options exist\n");
switch (*opt)
{
case IPOPT_EOL:
- opt = NULL;
- break;
+ opt = NULL;
+ break;
case IPOPT_NOP:
- opt++;
- break;
+ opt++;
+ break;
case IPOPT_SSRR:
case IPOPT_LSRR:
- if (!string_format(p, pend-p, " %s [@%s",
- (*opt == IPOPT_SSRR)? "SSRR" : "LSRR",
- #if OPTSTYLE == 1
- inet_ntoa(*((struct in_addr *)(&(ipopt->faddr))))))
- #elif OPTSTYLE == 2
- inet_ntoa(ipopt->ip_dst)))
- #else
- inet_ntoa(ipopt->ipopt_dst)))
- #endif
- {
- opt = NULL;
- break;
- }
+ if (!
+# if OPTSTYLE == 1
+ string_format(p, pend-p, " %s [@%s",
+ (*opt == IPOPT_SSRR)? "SSRR" : "LSRR",
+ inet_ntoa(*((struct in_addr *)(&(ipopt->faddr)))))
+# elif OPTSTYLE == 2
+ string_format(p, pend-p, " %s [@%s",
+ (*opt == IPOPT_SSRR)? "SSRR" : "LSRR",
+ inet_ntoa(ipopt->ip_dst))
+# else
+ string_format(p, pend-p, " %s [@%s",
+ (*opt == IPOPT_SSRR)? "SSRR" : "LSRR",
+ inet_ntoa(ipopt->ipopt_dst))
+# endif
+ )
+ {
+ opt = NULL;
+ break;
+ }
- p += Ustrlen(p);
- optcount = (opt[1] - 3) / sizeof(struct in_addr);
- adptr = opt + 3;
- while (optcount-- > 0)
- {
- memcpy(&addr, adptr, sizeof(addr));
- if (!string_format(p, pend - p - 1, "%s%s",
- (optcount == 0)? ":" : "@", inet_ntoa(addr)))
- {
- opt = NULL;
- break;
- }
- p += Ustrlen(p);
- adptr += sizeof(struct in_addr);
- }
- *p++ = ']';
- opt += opt[1];
- break;
+ p += Ustrlen(p);
+ optcount = (opt[1] - 3) / sizeof(struct in_addr);
+ adptr = opt + 3;
+ while (optcount-- > 0)
+ {
+ memcpy(&addr, adptr, sizeof(addr));
+ if (!string_format(p, pend - p - 1, "%s%s",
+ (optcount == 0)? ":" : "@", inet_ntoa(addr)))
+ {
+ opt = NULL;
+ break;
+ }
+ p += Ustrlen(p);
+ adptr += sizeof(struct in_addr);
+ }
+ *p++ = ']';
+ opt += opt[1];
+ break;
default:
- {
- if (pend - p < 4 + 3*opt[1]) { opt = NULL; break; }
- Ustrcat(p, "[ ");
- p += 2;
- for (int i = 0; i < opt[1]; i++)
- p += sprintf(CS p, "%2.2x ", opt[i]);
- *p++ = ']';
- }
- opt += opt[1];
- break;
+ {
+ if (pend - p < 4 + 3*opt[1]) { opt = NULL; break; }
+ Ustrcat(p, "[ ");
+ p += 2;
+ for (int i = 0; i < opt[1]; i++)
+ p += sprintf(CS p, "%2.2x ", opt[i]);
+ *p++ = ']';
+ }
+ opt += opt[1];
+ break;
}
*p = 0;
{
log_write(L_connection_reject, LOG_MAIN|LOG_REJECT, "refused connection "
"from %s (host_reject_connection)", host_and_ident(FALSE));
- smtp_printf("554 SMTP service not available\r\n", FALSE);
+#ifndef DISABLE_TLS
+ if (!tls_in.on_connect)
+#endif
+ smtp_printf("554 SMTP service not available\r\n", FALSE);
return FALSE;
}
setup_proxy_protocol_host();
#endif
-/* Start up TLS if tls_on_connect is set. This is for supporting the legacy
-smtps port for use with older style SSL MTAs. */
-
-#ifndef DISABLE_TLS
-if (tls_in.on_connect)
- {
- if (tls_server_start(&user_msg) != OK)
- return smtp_log_tls_fail(user_msg);
- cmd_list[CMD_LIST_TLS_AUTH].is_mail_cmd = TRUE;
- }
-#endif
-
/* Run the connect ACL if it exists */
user_msg = NULL;
if ((rc = acl_check(ACL_WHERE_CONNECT, NULL, acl_smtp_connect, &user_msg,
&log_msg)) != OK)
{
- (void) smtp_handle_acl_fail(ACL_WHERE_CONNECT, rc, user_msg, log_msg);
+#ifndef DISABLE_TLS
+ if (tls_in.on_connect)
+ log_connect_tls_drop(US"'connect' ACL", log_msg);
+ else
+#endif
+ (void) smtp_handle_acl_fail(ACL_WHERE_CONNECT, rc, user_msg, log_msg);
return FALSE;
}
}
+/* Start up TLS if tls_on_connect is set. This is for supporting the legacy
+smtps port for use with older style SSL MTAs. */
+
+#ifndef DISABLE_TLS
+if (tls_in.on_connect)
+ {
+ if (tls_server_start(&user_msg) != OK)
+ return smtp_log_tls_fail(user_msg);
+ cmd_list[CL_TLAU].is_mail_cmd = TRUE;
+ }
+#endif
+
/* Output the initial message for a two-way SMTP connection. It may contain
newlines, which then cause a multi-line response to be given. */
esc = US""; /* Default extended status code */
esclen = 0; /* Length of esc */
-if (!user_msg)
- {
- if (!(s = expand_string(smtp_banner)))
- log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Expansion of \"%s\" (smtp_banner) "
- "failed: %s", smtp_banner, expand_string_message);
- }
-else
+if (user_msg)
{
int codelen = 3;
s = user_msg;
esclen = codelen - 4;
}
}
+else if (!(s = expand_string(smtp_banner)))
+ {
+ log_write(0, f.expand_string_forcedfail ? LOG_MAIN : LOG_MAIN|LOG_PANIC_DIE,
+ "Expansion of \"%s\" (smtp_banner) failed: %s",
+ smtp_banner, expand_string_message);
+ /* for force-fail */
+#ifndef DISABLE_TLS
+ if (tls_in.on_connect) tls_close(NULL, TLS_SHUTDOWN_WAIT);
+#endif
+ return FALSE;
+ }
/* Remove any terminating newlines; might as well remove trailing space too */
if (!drop) return 0;
-log_write(L_smtp_connection, LOG_MAIN, "%s closed by DROP in ACL",
- smtp_get_connection_info());
+log_close_event(US"by DROP in ACL");
/* Run the not-quit ACL, but without any custom messages. This should not be a
problem, because we get here only if some other ACL has issued "drop", and
in that case, *its* custom messages will have been used above. */
smtp_notquit_exit(US"acl-drop", NULL, NULL);
+
+/* An overenthusiastic fail2ban/iptables implimentation has been seen to result
+in the TCP conn staying open, and retrying, despite this process exiting. A
+malicious client could possibly do the same, tying up server netowrking
+resources. Close the socket explicitly to try to avoid that (there's a note in
+the Linux socket(7) manpage, SO_LINGER para, to the effect that exim() without
+close() results in the socket always lingering). */
+
+(void) poll_one_fd(fileno(smtp_in), POLLIN, 200);
+DEBUG(D_any) debug_printf_indent("SMTP(close)>>\n");
+(void) fclose(smtp_in);
+(void) fclose(smtp_out);
+
return 2;
}
tls_close(NULL, TLS_SHUTDOWN_NOWAIT);
# endif
-log_write(L_smtp_connection, LOG_MAIN, "%s closed by QUIT",
- smtp_get_connection_info());
+log_close_event(US"by QUIT");
#else
# ifndef DISABLE_TLS
tls_close(NULL, TLS_SHUTDOWN_WAIT);
# endif
-log_write(L_smtp_connection, LOG_MAIN, "%s closed by QUIT",
- smtp_get_connection_info());
+log_close_event(US"by QUIT");
/* Pause, hoping client will FIN first so that they get the TIME_WAIT.
The socket should become readble (though with no data) */
HAD(SCH_RSET);
incomplete_transaction_log(US"RSET");
smtp_printf("250 Reset OK\r\n", FALSE);
-cmd_list[CMD_LIST_RSET].is_mail_cmd = FALSE;
+cmd_list[CL_RSET].is_mail_cmd = FALSE;
if (chunking_state > CHUNKING_OFFERED)
chunking_state = CHUNKING_OFFERED;
}
chunking_state = f.chunking_offered ? CHUNKING_OFFERED : CHUNKING_NOT_OFFERED;
-cmd_list[CMD_LIST_RSET].is_mail_cmd = TRUE;
-cmd_list[CMD_LIST_HELO].is_mail_cmd = TRUE;
-cmd_list[CMD_LIST_EHLO].is_mail_cmd = TRUE;
+cmd_list[CL_RSET].is_mail_cmd = TRUE;
+cmd_list[CL_HELO].is_mail_cmd = TRUE;
+cmd_list[CL_EHLO].is_mail_cmd = TRUE;
#ifndef DISABLE_TLS
-cmd_list[CMD_LIST_STARTTLS].is_mail_cmd = TRUE;
+cmd_list[CL_STLS].is_mail_cmd = TRUE;
#endif
if (lwr_receive_getc != NULL)
if ( tls_in.active.sock >= 0
&& tls_in.peercert
&& tls_in.certificate_verified
- && cmd_list[CMD_LIST_TLS_AUTH].is_mail_cmd
+ && cmd_list[CL_TLAU].is_mail_cmd
)
{
- cmd_list[CMD_LIST_TLS_AUTH].is_mail_cmd = FALSE;
+ cmd_list[CL_TLAU].is_mail_cmd = FALSE;
for (auth_instance * au = auths; au; au = au->next)
if (strcmpic(US"tls", au->driver_name) == 0)
case AUTH_CMD:
HAD(SCH_AUTH);
authentication_failed = TRUE;
- cmd_list[CMD_LIST_AUTH].is_mail_cmd = FALSE;
+ cmd_list[CL_AUTH].is_mail_cmd = FALSE;
if (!fl.auth_advertised && !f.allow_auth_unadvertised)
{
fl.esmtp = TRUE;
HELO_EHLO: /* Common code for HELO and EHLO */
- cmd_list[CMD_LIST_HELO].is_mail_cmd = FALSE;
- cmd_list[CMD_LIST_EHLO].is_mail_cmd = FALSE;
+ cmd_list[CL_HELO].is_mail_cmd = FALSE;
+ cmd_list[CL_EHLO].is_mail_cmd = FALSE;
/* Reject the HELO if its argument was invalid or non-existent. A
successful check causes the argument to be saved in malloc store. */
if (fl.esmtp)
{
- g->s[3] = '-';
+ g->s[3] = '-'; /* overwrite the space after the SMTP response code */
/* I'm not entirely happy with this, as an MTA is supposed to check
that it has enough room to accept a message of maximum size before
first = FALSE;
fl.auth_advertised = TRUE;
}
- saveptr = g->ptr;
+ saveptr = gstring_length(g);
g = string_catn(g, US" ", 1);
- g = string_cat (g, au->public_name);
+ g = string_cat(g, au->public_name);
while (++saveptr < g->ptr) g->s[saveptr] = toupper(g->s[saveptr]);
au->advertised = TRUE;
}
/* Terminate the string (for debug), write it, and note that HELO/EHLO
has been seen. */
+ {
+ uschar * ehlo_resp;
+ int len = len_string_from_gstring(g, &ehlo_resp);
#ifndef DISABLE_TLS
- if (tls_in.active.sock >= 0)
- (void)tls_write(NULL, g->s, g->ptr,
+ if (tls_in.active.sock >= 0)
+ (void) tls_write(NULL, ehlo_resp, len,
# ifndef DISABLE_PIPE_CONNECT
- fl.pipe_connect_acceptable && pipeline_connect_sends());
+ fl.pipe_connect_acceptable && pipeline_connect_sends());
# else
- FALSE);
+ FALSE);
# endif
- else
+ else
#endif
- (void) fwrite(g->s, 1, g->ptr, smtp_out);
+ (void) fwrite(ehlo_resp, 1, len, smtp_out);
- DEBUG(D_receive) for (const uschar * t, * s = string_from_gstring(g);
- s && (t = Ustrchr(s, '\r'));
- s = t + 2) /* \r\n */
- debug_printf("%s %.*s\n",
- s == g->s ? "SMTP>>" : " ",
- (int)(t - s), s);
- fl.helo_seen = TRUE;
+ DEBUG(D_receive) for (const uschar * t, * s = ehlo_resp;
+ s && (t = Ustrchr(s, '\r'));
+ s = t + 2) /* \r\n */
+ debug_printf("%s %.*s\n",
+ s == g->s ? "SMTP>>" : " ",
+ (int)(t - s), s);
+ fl.helo_seen = TRUE;
+ }
/* Reset the protocol and the state, abandoning any previous message. */
received_protocol =
cancel_cutthrough_connection(TRUE, US"STARTTLS received");
reset_point = smtp_reset(reset_point);
toomany = FALSE;
- cmd_list[CMD_LIST_STARTTLS].is_mail_cmd = FALSE;
+ cmd_list[CL_STLS].is_mail_cmd = FALSE;
/* There's an attack where more data is read in past the STARTTLS command
before TLS is negotiated, then assumed to be part of the secure session
{
if (!tls_remember_esmtp)
fl.helo_seen = fl.esmtp = fl.auth_advertised = f.smtp_in_pipelining_advertised = FALSE;
- cmd_list[CMD_LIST_EHLO].is_mail_cmd = TRUE;
- cmd_list[CMD_LIST_AUTH].is_mail_cmd = TRUE;
- cmd_list[CMD_LIST_TLS_AUTH].is_mail_cmd = TRUE;
+ cmd_list[CL_EHLO].is_mail_cmd = TRUE;
+ cmd_list[CL_AUTH].is_mail_cmd = TRUE;
+ cmd_list[CL_TLAU].is_mail_cmd = TRUE;
if (sender_helo_name)
{
sender_helo_name = NULL;
while (done <= 0) switch(smtp_read_command(FALSE, GETC_BUFFER_UNLIMITED))
{
case EOF_CMD:
- log_write(L_smtp_connection, LOG_MAIN, "%s closed by EOF",
- smtp_get_connection_info());
+ log_close_event(US"by EOF");
smtp_notquit_exit(US"tls-failed", NULL, NULL);
done = 2;
break;
smtp_respond(US"221", 3, TRUE, user_msg);
else
smtp_printf("221 %s closing connection\r\n", FALSE, smtp_active_hostname);
- log_write(L_smtp_connection, LOG_MAIN, "%s closed by QUIT",
- smtp_get_connection_info());
+ log_close_event(US"by QUIT");
done = 2;
break;
case HELP_CMD:
HAD(SCH_HELP);
- smtp_printf("214-Commands supported:\r\n", TRUE);
- {
- uschar buffer[256];
- buffer[0] = 0;
- Ustrcat(buffer, US" AUTH");
- #ifndef DISABLE_TLS
- if (tls_in.active.sock < 0 &&
- verify_check_host(&tls_advertise_hosts) != FAIL)
- Ustrcat(buffer, US" STARTTLS");
- #endif
- Ustrcat(buffer, US" HELO EHLO MAIL RCPT DATA BDAT");
- Ustrcat(buffer, US" NOOP QUIT RSET HELP");
- if (acl_smtp_etrn) Ustrcat(buffer, US" ETRN");
- if (acl_smtp_expn) Ustrcat(buffer, US" EXPN");
- if (acl_smtp_vrfy) Ustrcat(buffer, US" VRFY");
- smtp_printf("214%s\r\n", FALSE, buffer);
- }
+ smtp_printf("214-Commands supported:\r\n214", TRUE);
+ smtp_printf(" AUTH", TRUE);
+#ifndef DISABLE_TLS
+ if (tls_in.active.sock < 0 &&
+ verify_check_host(&tls_advertise_hosts) != FAIL)
+ smtp_printf(" STARTTLS", TRUE);
+#endif
+ smtp_printf(" HELO EHLO MAIL RCPT DATA BDAT", TRUE);
+ smtp_printf(" NOOP QUIT RSET HELP", TRUE);
+ if (acl_smtp_etrn) smtp_printf(" ETRN", TRUE);
+ if (acl_smtp_expn) smtp_printf(" EXPN", TRUE);
+ if (acl_smtp_vrfy) smtp_printf(" VRFY", TRUE);
+ smtp_printf("\r\n", FALSE);
break;