* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2017 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for handling an incoming SMTP call. */
{ "auth", sizeof("auth")-1, AUTH_CMD, TRUE, TRUE },
#ifdef SUPPORT_TLS
{ "starttls", sizeof("starttls")-1, STARTTLS_CMD, FALSE, FALSE },
- { "tls_auth", 0, TLS_AUTH_CMD, FALSE, TRUE },
+ { "tls_auth", 0, TLS_AUTH_CMD, FALSE, FALSE },
#endif
/* If you change anything above here, also fix the definitions below. */
incomplete_transaction_log(US"sync failure");
log_write(0, LOG_MAIN|LOG_REJECT, "SMTP protocol synchronization error "
"(next input sent too soon: pipelining was not advertised): "
- "rejected \"%s\" %s next input=\"%s\"",
+ "rejected \"%s\" %s next input=\"%s\"%s",
smtp_cmd_buffer, host_and_ident(TRUE),
- string_printing(string_copyn(smtp_inptr, n)));
- (void) synprot_error(L_smtp_protocol_error, 554, NULL,
- US"SMTP synchronization error");
+ string_printing(string_copyn(smtp_inptr, n)),
+ smtp_inend - smtp_inptr > n ? "..." : "");
+ (void) synprot_error(L_smtp_protocol_error, 554, NULL,
+ US"SMTP synchronization error");
goto repeat_until_rset;
}
void
bdat_flush_data(void)
{
-unsigned n = chunking_data_left;
-(void) bdat_getbuf(&n);
+while (chunking_data_left)
+ {
+ unsigned n = chunking_data_left;
+ (void) bdat_getbuf(&n);
+ }
receive_getc = lwr_receive_getc;
receive_getbuf = lwr_receive_getbuf;
{
log_write(0, LOG_MAIN|LOG_PANIC, "string too large in smtp_printf()");
smtp_closedown(US"Unexpected error");
- exim_exit(EXIT_FAILURE);
+ exim_exit(EXIT_FAILURE, NULL);
}
/* If this is the first output for a (non-batch) RCPT command, see if all RCPTs
moan_smtp_batch(NULL, "421 SMTP command timeout"); /* Does not return */
smtp_notquit_exit(US"command-timeout", US"421",
US"%s: SMTP command timeout - closing connection", smtp_active_hostname);
-exim_exit(EXIT_FAILURE);
+exim_exit(EXIT_FAILURE, US"receiving");
}
moan_smtp_batch(NULL, "421 SIGTERM received"); /* Does not return */
smtp_notquit_exit(US"signal-exit", US"421",
US"%s: Service not available - closing connection", smtp_active_hostname);
-exim_exit(EXIT_FAILURE);
+exim_exit(EXIT_FAILURE, US"receiving");
}
void
smtp_closedown(uschar *message)
{
-if (smtp_in == NULL || smtp_batched_input) return;
+if (!smtp_in || smtp_batched_input) return;
receive_swallow_smtp();
smtp_printf("421 %s\r\n", FALSE, message);
for (;;) switch(smtp_read_command(FALSE, GETC_BUFFER_UNLIMITED))
{
case EOF_CMD:
- return;
+ return;
case QUIT_CMD:
- smtp_printf("221 %s closing connection\r\n", FALSE, smtp_active_hostname);
- mac_smtp_fflush();
- return;
+ smtp_printf("221 %s closing connection\r\n", FALSE, smtp_active_hostname);
+ mac_smtp_fflush();
+ return;
case RSET_CMD:
- smtp_printf("250 Reset OK\r\n", FALSE);
- break;
+ smtp_printf("250 Reset OK\r\n", FALSE);
+ break;
default:
- smtp_printf("421 %s\r\n", FALSE, message);
- break;
+ smtp_printf("421 %s\r\n", FALSE, message);
+ break;
}
}
/* Append TLS-related information to a log line
Arguments:
- s String under construction: allocated string to extend, or NULL
- sizep Pointer to current allocation size (update on return), or NULL
- ptrp Pointer to index for new entries in string (update on return), or NULL
+ g String under construction: allocated string to extend, or NULL
Returns: Allocated string or NULL
*/
-static uschar *
-s_tlslog(uschar * s, int * sizep, int * ptrp)
+static gstring *
+s_tlslog(gstring * g)
{
- int size = sizep ? *sizep : 0;
- int ptr = ptrp ? *ptrp : 0;
-
- if (LOGGING(tls_cipher) && tls_in.cipher != NULL)
- s = string_append(s, &size, &ptr, 2, US" X=", tls_in.cipher);
- if (LOGGING(tls_certificate_verified) && tls_in.cipher != NULL)
- s = string_append(s, &size, &ptr, 2, US" CV=",
- tls_in.certificate_verified? "yes":"no");
- if (LOGGING(tls_peerdn) && tls_in.peerdn != NULL)
- s = string_append(s, &size, &ptr, 3, US" DN=\"",
- string_printing(tls_in.peerdn), US"\"");
- if (LOGGING(tls_sni) && tls_in.sni != NULL)
- s = string_append(s, &size, &ptr, 3, US" SNI=\"",
- string_printing(tls_in.sni), US"\"");
-
- if (s)
- {
- s[ptr] = '\0';
- if (sizep) *sizep = size;
- if (ptrp) *ptrp = ptr;
- }
- return s;
+if (LOGGING(tls_cipher) && tls_in.cipher)
+ g = string_append(g, 2, US" X=", tls_in.cipher);
+if (LOGGING(tls_certificate_verified) && tls_in.cipher)
+ g = string_append(g, 2, US" CV=", tls_in.certificate_verified? "yes":"no");
+if (LOGGING(tls_peerdn) && tls_in.peerdn)
+ g = string_append(g, 3, US" DN=\"", string_printing(tls_in.peerdn), US"\"");
+if (LOGGING(tls_sni) && tls_in.sni)
+ g = string_append(g, 3, US" SNI=\"", string_printing(tls_in.sni), US"\"");
+return g;
}
#endif
void
smtp_log_no_mail(void)
{
-int size, ptr, i;
-uschar *s, *sep;
+int i;
+uschar * sep, * s;
+gstring * g = NULL;
if (smtp_mailcmd_count > 0 || !LOGGING(smtp_no_mail))
return;
-s = NULL;
-size = ptr = 0;
-
-if (sender_host_authenticated != NULL)
+if (sender_host_authenticated)
{
- s = string_append(s, &size, &ptr, 2, US" A=", sender_host_authenticated);
- if (authenticated_id != NULL)
- s = string_append(s, &size, &ptr, 2, US":", authenticated_id);
+ g = string_append(g, 2, US" A=", sender_host_authenticated);
+ if (authenticated_id) g = string_append(g, 2, US":", authenticated_id);
}
#ifdef SUPPORT_TLS
-s = s_tlslog(s, &size, &ptr);
+g = s_tlslog(g);
#endif
-sep = (smtp_connection_had[SMTP_HBUFF_SIZE-1] != SCH_NONE)?
- US" C=..." : US" C=";
+sep = smtp_connection_had[SMTP_HBUFF_SIZE-1] != SCH_NONE ? US" C=..." : US" C=";
+
for (i = smtp_ch_index; i < SMTP_HBUFF_SIZE; i++)
- {
if (smtp_connection_had[i] != SCH_NONE)
{
- s = string_append(s, &size, &ptr, 2, sep,
- smtp_names[smtp_connection_had[i]]);
+ g = string_append(g, 2, sep, smtp_names[smtp_connection_had[i]]);
sep = US",";
}
- }
for (i = 0; i < smtp_ch_index; i++)
{
- s = string_append(s, &size, &ptr, 2, sep, smtp_names[smtp_connection_had[i]]);
+ g = string_append(g, 2, sep, smtp_names[smtp_connection_had[i]]);
sep = US",";
}
-if (s) s[ptr] = 0; else s = US"";
+if (!(s = string_from_gstring(g))) s = US"";
+
log_write(0, LOG_MAIN, "no MAIL in %sSMTP connection from %s D=%s%s",
tcp_in_fastopen ? US"TFO " : US"",
host_and_ident(FALSE), string_timesince(&smtp_connection_start), s);
uschar *
smtp_cmd_hist(void)
{
-uschar * list = NULL;
-int size = 0, len = 0, i;
+int i;
+gstring * list = NULL;
+uschar * s;
for (i = smtp_ch_index; i < SMTP_HBUFF_SIZE; i++)
if (smtp_connection_had[i] != SCH_NONE)
- list = string_append_listele(list, &size, &len, ',',
- smtp_names[smtp_connection_had[i]]);
+ list = string_append_listele(list, ',', smtp_names[smtp_connection_had[i]]);
+
for (i = 0; i < smtp_ch_index; i++)
- list = string_append_listele(list, &size, &len, ',',
- smtp_names[smtp_connection_had[i]]);
-return list ? list : US"";
+ list = string_append_listele(list, ',', smtp_names[smtp_connection_had[i]]);
+
+s = string_from_gstring(list);
+return s ? s : US"";
}
/* Skip tests if junk is permitted. */
if (!yield)
- {
+
/* Allow the new standard form for IPv6 address literals, namely,
[IPv6:....], and because someone is bound to use it, allow an equivalent
IPv4 form. Allow plain addresses as well. */
/* Non-literals must be alpha, dot, hyphen, plus any non-valid chars
that have been configured (usually underscore - sigh). */
- else if (*s != 0)
- {
- yield = TRUE;
- while (*s != 0)
- {
+ else if (*s)
+ for (yield = TRUE; *s; s++)
if (!isalnum(*s) && *s != '.' && *s != '-' &&
Ustrchr(helo_allow_chars, *s) == NULL)
{
yield = FALSE;
break;
}
- s++;
- }
- }
- }
/* Save argument if OK */
#ifndef DISABLE_PRDR
prdr_requested = FALSE;
#endif
-#ifdef EXPERIMENTAL_SPF
+#ifdef SUPPORT_SPF
spf_header_comment = NULL;
spf_received = NULL;
spf_result = NULL;
case HELO_CMD:
case EHLO_CMD:
- check_helo(smtp_cmd_data);
- /* Fall through */
+ check_helo(smtp_cmd_data);
+ /* Fall through */
case RSET_CMD:
- cancel_cutthrough_connection(TRUE, US"RSET received");
- smtp_reset(reset_point);
- bsmtp_transaction_linecount = receive_linecount;
- break;
+ cancel_cutthrough_connection(TRUE, US"RSET received");
+ smtp_reset(reset_point);
+ bsmtp_transaction_linecount = receive_linecount;
+ break;
/* The MAIL FROM command requires an address as an operand. All we
it is the canonical extracted address which is all that is kept. */
case MAIL_CMD:
- smtp_mailcmd_count++; /* Count for no-mail log */
- if (sender_address != NULL)
- /* The function moan_smtp_batch() does not return. */
- moan_smtp_batch(smtp_cmd_buffer, "503 Sender already given");
+ smtp_mailcmd_count++; /* Count for no-mail log */
+ if (sender_address != NULL)
+ /* The function moan_smtp_batch() does not return. */
+ moan_smtp_batch(smtp_cmd_buffer, "503 Sender already given");
- if (smtp_cmd_data[0] == 0)
- /* The function moan_smtp_batch() does not return. */
- moan_smtp_batch(smtp_cmd_buffer, "501 MAIL FROM must have an address operand");
+ if (smtp_cmd_data[0] == 0)
+ /* The function moan_smtp_batch() does not return. */
+ moan_smtp_batch(smtp_cmd_buffer, "501 MAIL FROM must have an address operand");
- /* Reset to start of message */
+ /* Reset to start of message */
- cancel_cutthrough_connection(TRUE, US"MAIL received");
- smtp_reset(reset_point);
+ cancel_cutthrough_connection(TRUE, US"MAIL received");
+ smtp_reset(reset_point);
- /* Apply SMTP rewrite */
+ /* Apply SMTP rewrite */
- raw_sender = ((rewrite_existflags & rewrite_smtp) != 0)?
- rewrite_one(smtp_cmd_data, rewrite_smtp|rewrite_smtp_sender, NULL, FALSE,
- US"", global_rewrite_rules) : smtp_cmd_data;
+ raw_sender = ((rewrite_existflags & rewrite_smtp) != 0)?
+ rewrite_one(smtp_cmd_data, rewrite_smtp|rewrite_smtp_sender, NULL, FALSE,
+ US"", global_rewrite_rules) : smtp_cmd_data;
- /* Extract the address; the TRUE flag allows <> as valid */
+ /* Extract the address; the TRUE flag allows <> as valid */
- raw_sender =
- parse_extract_address(raw_sender, &errmess, &start, &end, &sender_domain,
- TRUE);
+ raw_sender =
+ parse_extract_address(raw_sender, &errmess, &start, &end, &sender_domain,
+ TRUE);
- if (raw_sender == NULL)
- /* The function moan_smtp_batch() does not return. */
- moan_smtp_batch(smtp_cmd_buffer, "501 %s", errmess);
+ if (!raw_sender)
+ /* The function moan_smtp_batch() does not return. */
+ moan_smtp_batch(smtp_cmd_buffer, "501 %s", errmess);
- sender_address = string_copy(raw_sender);
+ sender_address = string_copy(raw_sender);
- /* Qualify unqualified sender addresses if permitted to do so. */
+ /* Qualify unqualified sender addresses if permitted to do so. */
- if (sender_domain == 0 && sender_address[0] != 0 && sender_address[0] != '@')
- {
- if (allow_unqualified_sender)
- {
- sender_address = rewrite_address_qualify(sender_address, FALSE);
- DEBUG(D_receive) debug_printf("unqualified address %s accepted "
- "and rewritten\n", raw_sender);
- }
- /* The function moan_smtp_batch() does not return. */
- else moan_smtp_batch(smtp_cmd_buffer, "501 sender address must contain "
- "a domain");
- }
- break;
+ if ( !sender_domain
+ && sender_address[0] != 0 && sender_address[0] != '@')
+ if (allow_unqualified_sender)
+ {
+ sender_address = rewrite_address_qualify(sender_address, FALSE);
+ DEBUG(D_receive) debug_printf("unqualified address %s accepted "
+ "and rewritten\n", raw_sender);
+ }
+ /* The function moan_smtp_batch() does not return. */
+ else
+ moan_smtp_batch(smtp_cmd_buffer, "501 sender address must contain "
+ "a domain");
+ break;
/* The RCPT TO command requires an address as an operand. All we do
extracted address. */
case RCPT_CMD:
- if (sender_address == NULL)
- /* The function moan_smtp_batch() does not return. */
- moan_smtp_batch(smtp_cmd_buffer, "503 No sender yet given");
+ if (!sender_address)
+ /* The function moan_smtp_batch() does not return. */
+ moan_smtp_batch(smtp_cmd_buffer, "503 No sender yet given");
- if (smtp_cmd_data[0] == 0)
- /* The function moan_smtp_batch() does not return. */
- moan_smtp_batch(smtp_cmd_buffer, "501 RCPT TO must have an address operand");
+ if (smtp_cmd_data[0] == 0)
+ /* The function moan_smtp_batch() does not return. */
+ moan_smtp_batch(smtp_cmd_buffer,
+ "501 RCPT TO must have an address operand");
- /* Check maximum number allowed */
+ /* Check maximum number allowed */
- if (recipients_max > 0 && recipients_count + 1 > recipients_max)
- /* The function moan_smtp_batch() does not return. */
- moan_smtp_batch(smtp_cmd_buffer, "%s too many recipients",
- recipients_max_reject? "552": "452");
+ if (recipients_max > 0 && recipients_count + 1 > recipients_max)
+ /* The function moan_smtp_batch() does not return. */
+ moan_smtp_batch(smtp_cmd_buffer, "%s too many recipients",
+ recipients_max_reject? "552": "452");
- /* Apply SMTP rewrite, then extract address. Don't allow "<>" as a
- recipient address */
+ /* Apply SMTP rewrite, then extract address. Don't allow "<>" as a
+ recipient address */
- recipient = rewrite_existflags & rewrite_smtp
- ? rewrite_one(smtp_cmd_data, rewrite_smtp, NULL, FALSE, US"",
- global_rewrite_rules)
- : smtp_cmd_data;
+ recipient = rewrite_existflags & rewrite_smtp
+ ? rewrite_one(smtp_cmd_data, rewrite_smtp, NULL, FALSE, US"",
+ global_rewrite_rules)
+ : smtp_cmd_data;
- recipient = parse_extract_address(recipient, &errmess, &start, &end,
- &recipient_domain, FALSE);
+ recipient = parse_extract_address(recipient, &errmess, &start, &end,
+ &recipient_domain, FALSE);
- if (!recipient)
- /* The function moan_smtp_batch() does not return. */
- moan_smtp_batch(smtp_cmd_buffer, "501 %s", errmess);
+ if (!recipient)
+ /* The function moan_smtp_batch() does not return. */
+ moan_smtp_batch(smtp_cmd_buffer, "501 %s", errmess);
- /* If the recipient address is unqualified, qualify it if permitted. Then
- add it to the list of recipients. */
+ /* If the recipient address is unqualified, qualify it if permitted. Then
+ add it to the list of recipients. */
- if (recipient_domain == 0)
- {
- if (allow_unqualified_recipient)
- {
- DEBUG(D_receive) debug_printf("unqualified address %s accepted\n",
- recipient);
- recipient = rewrite_address_qualify(recipient, TRUE);
- }
- /* The function moan_smtp_batch() does not return. */
- else moan_smtp_batch(smtp_cmd_buffer, "501 recipient address must contain "
- "a domain");
- }
- receive_add_recipient(recipient, -1);
- break;
+ if (!recipient_domain)
+ if (allow_unqualified_recipient)
+ {
+ DEBUG(D_receive) debug_printf("unqualified address %s accepted\n",
+ recipient);
+ recipient = rewrite_address_qualify(recipient, TRUE);
+ }
+ /* The function moan_smtp_batch() does not return. */
+ else
+ moan_smtp_batch(smtp_cmd_buffer,
+ "501 recipient address must contain a domain");
+
+ receive_add_recipient(recipient, -1);
+ break;
/* The DATA command is legal only if it follows successful MAIL FROM
command is encountered. */
case DATA_CMD:
- if (sender_address == NULL || recipients_count <= 0)
- {
- /* The function moan_smtp_batch() does not return. */
- if (sender_address == NULL)
- moan_smtp_batch(smtp_cmd_buffer,
- "503 MAIL FROM:<sender> command must precede DATA");
+ if (!sender_address || recipients_count <= 0)
+ /* The function moan_smtp_batch() does not return. */
+ if (!sender_address)
+ moan_smtp_batch(smtp_cmd_buffer,
+ "503 MAIL FROM:<sender> command must precede DATA");
+ else
+ moan_smtp_batch(smtp_cmd_buffer,
+ "503 RCPT TO:<recipient> must precede DATA");
else
- moan_smtp_batch(smtp_cmd_buffer,
- "503 RCPT TO:<recipient> must precede DATA");
- }
- else
- {
- done = 3; /* DATA successfully achieved */
- message_ended = END_NOTENDED; /* Indicate in middle of message */
- }
- break;
+ {
+ done = 3; /* DATA successfully achieved */
+ message_ended = END_NOTENDED; /* Indicate in middle of message */
+ }
+ break;
/* The VRFY, EXPN, HELP, ETRN, and NOOP commands are ignored. */
case HELP_CMD:
case NOOP_CMD:
case ETRN_CMD:
- bsmtp_transaction_linecount = receive_linecount;
- break;
+ bsmtp_transaction_linecount = receive_linecount;
+ break;
case EOF_CMD:
case QUIT_CMD:
- done = 2;
- break;
+ done = 2;
+ break;
case BADARG_CMD:
- /* The function moan_smtp_batch() does not return. */
- moan_smtp_batch(smtp_cmd_buffer, "501 Unexpected argument data");
- break;
+ /* The function moan_smtp_batch() does not return. */
+ moan_smtp_batch(smtp_cmd_buffer, "501 Unexpected argument data");
+ break;
case BADCHAR_CMD:
- /* The function moan_smtp_batch() does not return. */
- moan_smtp_batch(smtp_cmd_buffer, "501 Unexpected NULL in SMTP command");
- break;
+ /* The function moan_smtp_batch() does not return. */
+ moan_smtp_batch(smtp_cmd_buffer, "501 Unexpected NULL in SMTP command");
+ break;
default:
- /* The function moan_smtp_batch() does not return. */
- moan_smtp_batch(smtp_cmd_buffer, "500 Command unrecognized");
- break;
+ /* The function moan_smtp_batch() does not return. */
+ moan_smtp_batch(smtp_cmd_buffer, "500 Command unrecognized");
+ break;
}
}
BOOL
smtp_start_session(void)
{
-int size = 256;
-int ptr, esclen;
+int esclen;
uschar *user_msg, *log_msg;
uschar *code, *esc;
-uschar *p, *s, *ss;
+uschar *p, *s;
+gstring * ss;
gettimeofday(&smtp_connection_start, NULL);
for (smtp_ch_index = 0; smtp_ch_index < SMTP_HBUFF_SIZE; smtp_ch_index++)
/* Set up the message size limit; this may be host-specific */
thismessage_size_limit = expand_string_integer(message_size_limit, TRUE);
-if (expand_string_message != NULL)
+if (expand_string_message)
{
if (thismessage_size_limit == -1)
log_write(0, LOG_MAIN|LOG_PANIC, "unable to expand message_size_limit: "
smtps port for use with older style SSL MTAs. */
#ifdef SUPPORT_TLS
- if (tls_in.on_connect && tls_server_start(tls_require_ciphers, &user_msg) != OK)
- return smtp_log_tls_fail(user_msg);
+ if (tls_in.on_connect)
+ {
+ if (tls_server_start(tls_require_ciphers, &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 */
first, and output it in one fell swoop. This gives a better chance of it
ending up as a single packet. */
-ss = store_get(size);
-ptr = 0;
+ss = string_get(256);
p = s;
do /* At least once, in case we have an empty string */
{
int len;
uschar *linebreak = Ustrchr(p, '\n');
- ss = string_catn(ss, &size, &ptr, code, 3);
- if (linebreak == NULL)
+ ss = string_catn(ss, code, 3);
+ if (!linebreak)
{
len = Ustrlen(p);
- ss = string_catn(ss, &size, &ptr, US" ", 1);
+ ss = string_catn(ss, US" ", 1);
}
else
{
len = linebreak - p;
- ss = string_catn(ss, &size, &ptr, US"-", 1);
+ ss = string_catn(ss, US"-", 1);
}
- ss = string_catn(ss, &size, &ptr, esc, esclen);
- ss = string_catn(ss, &size, &ptr, p, len);
- ss = string_catn(ss, &size, &ptr, US"\r\n", 2);
+ ss = string_catn(ss, esc, esclen);
+ ss = string_catn(ss, p, len);
+ ss = string_catn(ss, US"\r\n", 2);
p += len;
- if (linebreak != NULL) p++;
+ if (linebreak) p++;
}
-while (*p != 0);
-
-ss[ptr] = 0; /* string_cat leaves room for this */
+while (*p);
/* Before we write the banner, check that there is no input pending, unless
this synchronisation check is disabled. */
/* Now output the banner */
-smtp_printf("%s", FALSE, ss);
+smtp_printf("%s", FALSE, string_from_gstring(ss));
/* Attempt to see if we sent the banner before the last ACK of the 3-way
handshake arrived. If so we must have managed a TFO. */
/* This function is called when acl_check() fails. As well as calls from within
this module, it is called from receive.c for an ACL after DATA. It sorts out
-logging the incident, and sets up the error response. A message containing
+logging the incident, and sends the error response. A message containing
newlines is turned into a multiline SMTP response, but for logging, only the
first line is used.
if (log_reject_target != 0)
{
#ifdef SUPPORT_TLS
- uschar * tls = s_tlslog(NULL, NULL, NULL);
+ gstring * g = s_tlslog(NULL);
+ uschar * tls = string_from_gstring(g);
if (!tls) tls = US"";
#else
uschar * tls = US"";
HDEBUG(D_receive) debug_printf("getting IP address for %s\n",
sender_helo_name);
- rc = host_find_bydns(&h, NULL, HOST_FIND_BY_A,
+ rc = host_find_bydns(&h, NULL, HOST_FIND_BY_A | HOST_FIND_BY_AAAA,
NULL, NULL, NULL, &d, NULL, NULL);
if (rc == HOST_FOUND || rc == HOST_FOUND_LOCAL)
for (hh = &h; hh; hh = hh->next)
cmd_list[CMD_LIST_EHLO].is_mail_cmd = TRUE;
#ifdef SUPPORT_TLS
cmd_list[CMD_LIST_STARTTLS].is_mail_cmd = TRUE;
-cmd_list[CMD_LIST_TLS_AUTH].is_mail_cmd = TRUE;
#endif
/* Set the local signal handler for SIGTERM - it tries to end off tidily */
void (*oldsignal)(int);
pid_t pid;
int start, end, sender_domain, recipient_domain;
- int ptr, size, rc;
+ int rc;
int c;
auth_instance *au;
uschar *orcpt = NULL;
int flags;
+ gstring * g;
#ifdef AUTH_TLS
/* Check once per STARTTLS or SSL-on-connect for a TLS AUTH */
)
{
cmd_list[CMD_LIST_TLS_AUTH].is_mail_cmd = FALSE;
- if ( acl_smtp_auth
- && (rc = acl_check(ACL_WHERE_AUTH, NULL, acl_smtp_auth,
- &user_msg, &log_msg)) != OK
- )
- {
- done = smtp_handle_acl_fail(ACL_WHERE_AUTH, rc, user_msg, log_msg);
- continue;
- }
for (au = auths; au; au = au->next)
if (strcmpic(US"tls", au->driver_name) == 0)
{
- smtp_cmd_data = NULL;
-
- if (smtp_in_auth(au, &s, &ss) == OK)
- { DEBUG(D_auth) debug_printf("tls auth succeeded\n"); }
+ if ( acl_smtp_auth
+ && (rc = acl_check(ACL_WHERE_AUTH, NULL, acl_smtp_auth,
+ &user_msg, &log_msg)) != OK
+ )
+ done = smtp_handle_acl_fail(ACL_WHERE_AUTH, rc, user_msg, log_msg);
else
- { DEBUG(D_auth) debug_printf("tls auth not succeeded\n"); }
+ {
+ smtp_cmd_data = NULL;
+
+ if (smtp_in_auth(au, &s, &ss) == OK)
+ { DEBUG(D_auth) debug_printf("tls auth succeeded\n"); }
+ else
+ { DEBUG(D_auth) debug_printf("tls auth not succeeded\n"); }
+ }
break;
}
}
}
}
-#ifdef EXPERIMENTAL_SPF
+#ifdef SUPPORT_SPF
/* set up SPF context */
spf_init(sender_helo_name, sender_host_address);
#endif
sender_ident ? sender_ident : US"",
sender_ident ? US" at " : US"",
sender_host_name ? sender_host_name : sender_helo_name);
-
- ptr = Ustrlen(s);
- size = ptr + 1;
+ g = string_cat(NULL, s);
if (sender_host_address)
{
- s = string_catn(s, &size, &ptr, US" [", 2);
- s = string_cat (s, &size, &ptr, sender_host_address);
- s = string_catn(s, &size, &ptr, US"]", 1);
+ g = string_catn(g, US" [", 2);
+ g = string_cat (g, sender_host_address);
+ g = string_catn(g, US"]", 1);
}
}
"newlines: message truncated: %s", string_printing(s));
*ss = 0;
}
- ptr = Ustrlen(s);
- size = ptr + 1;
+ g = string_cat(NULL, s);
}
- s = string_catn(s, &size, &ptr, US"\r\n", 2);
+ g = string_catn(g, US"\r\n", 2);
/* If we received EHLO, we must create a multiline response which includes
the functions supported. */
if (esmtp)
{
- s[3] = '-';
+ g->s[3] = '-';
/* 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
{
sprintf(CS big_buffer, "%.3s-SIZE %d\r\n", smtp_code,
thismessage_size_limit);
- s = string_cat(s, &size, &ptr, big_buffer);
+ g = string_cat(g, big_buffer);
}
else
{
- s = string_catn(s, &size, &ptr, smtp_code, 3);
- s = string_catn(s, &size, &ptr, US"-SIZE\r\n", 7);
+ g = string_catn(g, smtp_code, 3);
+ g = string_catn(g, US"-SIZE\r\n", 7);
}
/* Exim does not do protocol conversion or data conversion. It is 8-bit
if (accept_8bitmime)
{
- s = string_catn(s, &size, &ptr, smtp_code, 3);
- s = string_catn(s, &size, &ptr, US"-8BITMIME\r\n", 11);
+ g = string_catn(g, smtp_code, 3);
+ g = string_catn(g, US"-8BITMIME\r\n", 11);
}
/* Advertise DSN support if configured to do so. */
if (verify_check_host(&dsn_advertise_hosts) != FAIL)
{
- s = string_catn(s, &size, &ptr, smtp_code, 3);
- s = string_catn(s, &size, &ptr, US"-DSN\r\n", 6);
+ g = string_catn(g, smtp_code, 3);
+ g = string_catn(g, US"-DSN\r\n", 6);
dsn_advertised = TRUE;
}
if (acl_smtp_etrn)
{
- s = string_catn(s, &size, &ptr, smtp_code, 3);
- s = string_catn(s, &size, &ptr, US"-ETRN\r\n", 7);
+ g = string_catn(g, smtp_code, 3);
+ g = string_catn(g, US"-ETRN\r\n", 7);
}
if (acl_smtp_vrfy)
{
- s = string_catn(s, &size, &ptr, smtp_code, 3);
- s = string_catn(s, &size, &ptr, US"-VRFY\r\n", 7);
+ g = string_catn(g, smtp_code, 3);
+ g = string_catn(g, US"-VRFY\r\n", 7);
}
if (acl_smtp_expn)
{
- s = string_catn(s, &size, &ptr, smtp_code, 3);
- s = string_catn(s, &size, &ptr, US"-EXPN\r\n", 7);
+ g = string_catn(g, smtp_code, 3);
+ g = string_catn(g, US"-EXPN\r\n", 7);
}
/* Exim is quite happy with pipelining, so let the other end know that
if (pipelining_enable &&
verify_check_host(&pipelining_advertise_hosts) == OK)
{
- s = string_catn(s, &size, &ptr, smtp_code, 3);
- s = string_catn(s, &size, &ptr, US"-PIPELINING\r\n", 13);
+ g = string_catn(g, smtp_code, 3);
+ g = string_catn(g, US"-PIPELINING\r\n", 13);
sync_cmd_limit = NON_SYNC_CMD_PIPELINING;
pipelining_advertised = TRUE;
}
int saveptr;
if (first)
{
- s = string_catn(s, &size, &ptr, smtp_code, 3);
- s = string_catn(s, &size, &ptr, US"-AUTH", 5);
+ g = string_catn(g, smtp_code, 3);
+ g = string_catn(g, US"-AUTH", 5);
first = FALSE;
auth_advertised = TRUE;
}
- saveptr = ptr;
- s = string_catn(s, &size, &ptr, US" ", 1);
- s = string_cat (s, &size, &ptr, au->public_name);
- while (++saveptr < ptr) s[saveptr] = toupper(s[saveptr]);
+ saveptr = g->ptr;
+ g = string_catn(g, US" ", 1);
+ g = string_cat (g, au->public_name);
+ while (++saveptr < g->ptr) g->s[saveptr] = toupper(g->s[saveptr]);
au->advertised = TRUE;
}
}
}
- if (!first) s = string_catn(s, &size, &ptr, US"\r\n", 2);
+ if (!first) g = string_catn(g, US"\r\n", 2);
}
/* RFC 3030 CHUNKING */
if (verify_check_host(&chunking_advertise_hosts) != FAIL)
{
- s = string_catn(s, &size, &ptr, smtp_code, 3);
- s = string_catn(s, &size, &ptr, US"-CHUNKING\r\n", 11);
+ g = string_catn(g, smtp_code, 3);
+ g = string_catn(g, US"-CHUNKING\r\n", 11);
chunking_offered = TRUE;
chunking_state = CHUNKING_OFFERED;
}
if (tls_in.active < 0 &&
verify_check_host(&tls_advertise_hosts) != FAIL)
{
- s = string_catn(s, &size, &ptr, smtp_code, 3);
- s = string_catn(s, &size, &ptr, US"-STARTTLS\r\n", 11);
+ g = string_catn(g, smtp_code, 3);
+ g = string_catn(g, US"-STARTTLS\r\n", 11);
tls_advertised = TRUE;
}
#endif
/* Per Recipient Data Response, draft by Eric A. Hall extending RFC */
if (prdr_enable)
{
- s = string_catn(s, &size, &ptr, smtp_code, 3);
- s = string_catn(s, &size, &ptr, US"-PRDR\r\n", 7);
+ g = string_catn(g, smtp_code, 3);
+ g = string_catn(g, US"-PRDR\r\n", 7);
}
#endif
if ( accept_8bitmime
&& verify_check_host(&smtputf8_advertise_hosts) != FAIL)
{
- s = string_catn(s, &size, &ptr, smtp_code, 3);
- s = string_catn(s, &size, &ptr, US"-SMTPUTF8\r\n", 11);
+ g = string_catn(g, smtp_code, 3);
+ g = string_catn(g, US"-SMTPUTF8\r\n", 11);
smtputf8_advertised = TRUE;
}
#endif
/* Finish off the multiline reply with one that is always available. */
- s = string_catn(s, &size, &ptr, smtp_code, 3);
- s = string_catn(s, &size, &ptr, US" HELP\r\n", 7);
+ g = string_catn(g, smtp_code, 3);
+ g = string_catn(g, US" HELP\r\n", 7);
}
/* Terminate the string (for debug), write it, and note that HELO/EHLO
has been seen. */
- s[ptr] = 0;
-
#ifdef SUPPORT_TLS
- if (tls_in.active >= 0) (void)tls_write(TRUE, s, ptr, FALSE); else
+ if (tls_in.active >= 0) (void)tls_write(TRUE, g->s, g->ptr, FALSE); else
#endif
{
- int i = fwrite(s, 1, ptr, smtp_out); i = i; /* compiler quietening */
+ int i = fwrite(g->s, 1, g->ptr, smtp_out); i = i; /* compiler quietening */
}
DEBUG(D_receive)
{
uschar *cr;
- while ((cr = Ustrchr(s, '\r')) != NULL) /* lose CRs */
- memmove(cr, cr + 1, (ptr--) - (cr - s));
- debug_printf("SMTP>> %s", s);
+
+ (void) string_from_gstring(g);
+ while ((cr = Ustrchr(g->s, '\r')) != NULL) /* lose CRs */
+ memmove(cr, cr + 1, (g->ptr--) - (cr - g->s));
+ debug_printf("SMTP>> %s", g->s);
}
helo_seen = TRUE;
DEBUG(D_receive) debug_printf("chunking state %d, %d bytes\n",
(int)chunking_state, chunking_data_left);
+ /* 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. */
lwr_receive_getc = receive_getc;
lwr_receive_getbuf = receive_getbuf;
lwr_receive_ungetc = receive_ungetc;
+
receive_getc = bdat_getc;
receive_ungetc = bdat_ungetc;
+ dot_ends = FALSE;
+
goto DATA_BDAT;
}
case DATA_CMD:
HAD(SCH_DATA);
+ dot_ends = TRUE;
DATA_BDAT: /* Common code for DATA and BDAT */
if (!discarded && recipients_count <= 0)