* Exim - an Internet mail transport agent *
*************************************************/
+/* Copyright (c) The Exim Maintainers 2020 - 2022 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
-/* Copyright (c) The Exim Maintainers 2020 - 2021 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for handling an incoming SMTP call. */
if (recipients_count > 0)
{
- raw_recipients = store_get(recipients_count * sizeof(uschar *), FALSE);
+ raw_recipients = store_get(recipients_count * sizeof(uschar *), GET_UNTAINTED);
for (int i = 0; i < recipients_count; i++)
raw_recipients[i] = recipients_list[i].address;
raw_recipients_count = recipients_count;
}
bdat_pop_receive_functions();
-
-if (chunking_state != CHUNKING_LAST)
- {
- chunking_state = CHUNKING_OFFERED;
- DEBUG(D_receive) debug_printf("chunking state %d\n", (int)chunking_state);
- }
+chunking_state = CHUNKING_OFFERED;
+DEBUG(D_receive) debug_printf("chunking state %d\n", (int)chunking_state);
}
yield = !! string_vformat(&gs, SVFMT_TAINT_NOCHK, format, ap);
string_from_gstring(&gs);
-DEBUG(D_receive)
- {
- uschar *msg_copy, *cr, *end;
- msg_copy = string_copy(gs.s);
- end = msg_copy + gs.ptr;
- while ((cr = Ustrchr(msg_copy, '\r')) != NULL) /* lose CRs */
- memmove(cr, cr + 1, (end--) - cr);
- debug_printf("SMTP>> %s", msg_copy);
- }
+DEBUG(D_receive) for (const uschar * t, * s = gs.s;
+ s && (t = Ustrchr(s, '\r'));
+ s = t + 2) /* \r\n */
+ debug_printf("%s %.*s\n",
+ s == gs.s ? "SMTP>>" : " ",
+ (int)(t - s), s);
if (!yield)
{
if (fl.rcpt_in_progress)
{
- if (rcpt_smtp_response == NULL)
+ if (!rcpt_smtp_response)
rcpt_smtp_response = string_copy(big_buffer);
else if (fl.rcpt_smtp_response_same &&
Ustrcmp(rcpt_smtp_response, big_buffer) != 0)
*/
void
-smtp_closedown(uschar *message)
+smtp_closedown(uschar * message)
{
if (!smtp_in || smtp_batched_input) return;
receive_swallow_smtp();
/* Allow for trailing 0 in the command and data buffers. Tainted. */
-smtp_cmd_buffer = store_get_perm(2*SMTP_CMD_BUFFER_SIZE + 2, TRUE);
+smtp_cmd_buffer = store_get_perm(2*SMTP_CMD_BUFFER_SIZE + 2, GET_TAINTED);
smtp_cmd_buffer[0] = 0;
smtp_data_buffer = smtp_cmd_buffer + SMTP_CMD_BUFFER_SIZE + 1;
{
#if OPTSTYLE == 1
EXIM_SOCKLEN_T optlen = sizeof(struct ip_options) + MAX_IPOPTLEN;
- struct ip_options *ipopt = store_get(optlen, FALSE);
+ struct ip_options *ipopt = store_get(optlen, GET_UNTAINTED);
#elif OPTSTYLE == 2
struct ip_opts ipoptblock;
struct ip_opts *ipopt = &ipoptblock;
static int
-smtp_in_auth(auth_instance *au, uschar ** s, uschar ** ss)
+smtp_in_auth(auth_instance *au, uschar ** smtp_resp, uschar ** errmsg)
{
const uschar *set_id = NULL;
int rc;
+/* Set up globals for error messages */
+
+authenticator_name = au->name;
+driver_srcfile = au->srcfile;
+driver_srcline = au->srcline;
+
/* Run the checking code, passing the remainder of the command line as
data. Initials the $auth<n> variables as empty. Initialize $0 empty and set
it as the only set numerical variable. The authenticator may set $auth<n>
if (au->set_id) set_id = expand_string(au->set_id);
expand_nmax = -1; /* Reset numeric variables */
for (int i = 0; i < AUTH_VARS; i++) auth_vars[i] = NULL; /* Reset $auth<n> */
+driver_srcfile = authenticator_name = NULL; driver_srcline = 0;
/* The value of authenticated_id is stored in the spool file and printed in
log lines. It must not contain binary zeros or newline characters. In
received_protocol =
(sender_host_address ? protocols : protocols_local)
[pextend + pauthed + (tls_in.active.sock >= 0 ? pcrpted:0)];
- *s = *ss = US"235 Authentication succeeded";
+ *smtp_resp = *errmsg = US"235 Authentication succeeded";
authenticated_by = au;
break;
}
case DEFER:
if (set_id) authenticated_fail_id = string_copy_perm(set_id, TRUE);
- *s = string_sprintf("435 Unable to authenticate at present%s",
+ *smtp_resp = string_sprintf("435 Unable to authenticate at present%s",
auth_defer_user_msg);
- *ss = string_sprintf("435 Unable to authenticate at present%s: %s",
+ *errmsg = string_sprintf("435 Unable to authenticate at present%s: %s",
set_id, auth_defer_msg);
break;
case BAD64:
- *s = *ss = US"501 Invalid base64 data";
+ *smtp_resp = *errmsg = US"501 Invalid base64 data";
break;
case CANCELLED:
- *s = *ss = US"501 Authentication cancelled";
+ *smtp_resp = *errmsg = US"501 Authentication cancelled";
break;
case UNEXPECTED:
- *s = *ss = US"553 Initial data not expected";
+ *smtp_resp = *errmsg = US"553 Initial data not expected";
break;
case FAIL:
if (set_id) authenticated_fail_id = string_copy_perm(set_id, TRUE);
- *s = US"535 Incorrect authentication data";
- *ss = string_sprintf("535 Incorrect authentication data%s", set_id);
+ *smtp_resp = US"535 Incorrect authentication data";
+ *errmsg = string_sprintf("535 Incorrect authentication data%s", set_id);
break;
default:
if (set_id) authenticated_fail_id = string_copy_perm(set_id, TRUE);
- *s = US"435 Internal error";
- *ss = string_sprintf("435 Internal error%s: return %d from authentication "
+ *smtp_resp = US"435 Internal error";
+ *errmsg = string_sprintf("435 Internal error%s: return %d from authentication "
"check", set_id, rc);
break;
}
incomplete_transaction_log(US"RSET");
smtp_printf("250 Reset OK\r\n", FALSE);
cmd_list[CMD_LIST_RSET].is_mail_cmd = FALSE;
+if (chunking_state > CHUNKING_OFFERED)
+ chunking_state = CHUNKING_OFFERED;
}
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"); }
+ {
+ DEBUG(D_auth) debug_printf("tls auth not succeeded\n");
+#ifndef DISABLE_EVENT
+ {
+ uschar * save_name = sender_host_authenticated, * logmsg;
+ sender_host_authenticated = au->name;
+ if ((logmsg = event_raise(event_action, US"auth:fail", s, NULL)))
+ log_write(0, LOG_MAIN, "%s", logmsg);
+ sender_host_authenticated = save_name;
+ }
+#endif
+ }
}
break;
}
{
auth_instance * au;
+ uschar * smtp_resp, * errmsg;
+
for (au = auths; au; au = au->next)
if (strcmpic(s, au->public_name) == 0 && au->server &&
(au->advertised || f.allow_auth_unadvertised))
if (au)
{
- c = smtp_in_auth(au, &s, &ss);
+ int rc = smtp_in_auth(au, &smtp_resp, &errmsg);
- smtp_printf("%s\r\n", FALSE, s);
- if (c != OK)
- log_write(0, LOG_MAIN|LOG_REJECT, "%s authenticator failed for %s: %s",
- au->name, host_and_ident(FALSE), ss);
+ smtp_printf("%s\r\n", FALSE, smtp_resp);
+ if (rc != OK)
+ {
+ uschar * logmsg = NULL;
+#ifndef DISABLE_EVENT
+ {uschar * save_name = sender_host_authenticated;
+ sender_host_authenticated = au->name;
+ logmsg = event_raise(event_action, US"auth:fail", smtp_resp, NULL);
+ sender_host_authenticated = save_name;
+ }
+#endif
+ if (logmsg)
+ log_write(0, LOG_MAIN|LOG_REJECT, "%s", logmsg);
+ else
+ log_write(0, LOG_MAIN|LOG_REJECT, "%s authenticator failed for %s: %s",
+ au->name, host_and_ident(FALSE), errmsg);
+ }
}
else
done = synprot_error(L_smtp_protocol_error, 504, NULL,
if (!user_msg)
{
/* sender_host_name below will be tainted, so save on copy when we hit it */
- g = string_get_tainted(24, TRUE);
+ g = string_get_tainted(24, GET_TAINTED);
g = string_fmt_append(g, "%.3s %s Hello %s%s%s",
smtp_code,
smtp_active_hostname,
else
{
- char *ss;
+ char * ss;
int codelen = 4;
smtp_message_code(&smtp_code, &codelen, &user_msg, NULL, TRUE);
s = string_sprintf("%.*s%s", codelen, smtp_code, user_msg);
#endif
(void) fwrite(g->s, 1, g->ptr, smtp_out);
- DEBUG(D_receive)
- {
- uschar *cr;
-
- (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);
- }
+ 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;
/* Reset the protocol and the state, abandoning any previous message. */
count this as a protocol error. Reset was_rej_mail so that further RCPTs
get the same treatment. */
- if (sender_address == NULL)
+ if (!sender_address)
{
if (f.smtp_in_pipelining_advertised && last_was_rej_mail)
{
/* Check for an operand */
- if (smtp_cmd_data[0] == 0)
+ if (!smtp_cmd_data[0])
{
done = synprot_error(L_smtp_syntax_error, 501, NULL,
US"RCPT must have an address operand");
#endif
if (!discarded && recipients_count <= 0)
{
- if (fl.rcpt_smtp_response_same && rcpt_smtp_response != NULL)
+ if (fl.rcpt_smtp_response_same && rcpt_smtp_response)
{
uschar *code = US"503";
int len = Ustrlen(rcpt_smtp_response);
etrn_command = smtp_etrn_command;
deliver_domain = smtp_cmd_data;
rc = transport_set_up_command(&argv, smtp_etrn_command, TRUE, 0, NULL,
- US"ETRN processing", &error);
+ FALSE, US"ETRN processing", &error);
deliver_domain = NULL;
if (!rc)
{
{
DEBUG(D_exec) debug_print_argv(argv);
exim_nullstd(); /* Ensure std{in,out,err} exist */
+ /* argv[0] should be untainted, from child_exec_exim() */
execv(CS argv[0], (char *const *)argv);
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "exec of \"%s\" (ETRN) failed: %s",
etrn_command, strerror(errno));
COMMAND_LOOP:
last_was_rej_mail = was_rej_mail; /* Remember some last commands for */
last_was_rcpt = was_rcpt; /* protocol error handling */
- continue;
}
return done - 2; /* Convert yield values */