empty item in a list. */
if (*p == 0) p = US":";
+ /* should never be a tainted list */
while ((path = string_nextinlist(&p, &sep, buffer, sizeof(buffer))))
if (Ustrcmp(path, "syslog") != 0)
break;
{
recipient_item *oldlist = recipients_list;
int oldmax = recipients_list_max;
+
+ const int safe_recipients_limit = INT_MAX / 2 / sizeof(recipient_item);
+ if (recipients_list_max < 0 || recipients_list_max >= safe_recipients_limit)
+ {
+ log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Too many recipients: %d", recipients_list_max);
+ }
+
recipients_list_max = recipients_list_max ? 2*recipients_list_max : 50;
recipients_list = store_get(recipients_list_max * sizeof(recipient_item), FALSE);
- if (oldlist != NULL)
+ if (oldlist)
memcpy(recipients_list, oldlist, oldmax * sizeof(recipient_item));
}
const uschar * list = acl_removed_headers;
int sep = ':'; /* This is specified as a colon-separated list */
uschar *s;
- uschar buffer[128];
- while ((s = string_nextinlist(&list, &sep, buffer, sizeof(buffer))))
+ while ((s = string_nextinlist(&list, &sep, NULL, 0)))
if (header_testname(h, s, Ustrlen(s), FALSE))
{
h->type = htype_old;
void
received_header_gen(void)
{
-uschar *received;
-uschar *timestamp;
-header_line *received_header= header_list;
+uschar * received;
+uschar * timestamp = expand_string(US"${tod_full}");
+header_line * received_header= header_list;
-timestamp = expand_string(US"${tod_full}");
if (recipients_count == 1) received_for = recipients_list[0].address;
received = expand_string(received_header_text);
received_for = NULL;
the result of the expansion is an empty string, we leave the header marked as
"old" so as to refrain from adding a Received header. */
-if (received[0] == 0)
+if (!received[0])
{
received_header->text = string_sprintf("Received: ; %s\n", timestamp);
received_header->type = htype_old;
}
else
{
- received_header->text = string_sprintf("%s; %s\n", received, timestamp);
+ received_header->text = string_sprintf("%s;\n\t%s\n", received, timestamp);
received_header->type = htype_received;
}
ids, and fractions of a second are required. See the comments that precede the
message id creation below. */
-(void)gettimeofday(&message_id_tv, NULL);
+exim_gettime(&message_id_tv);
/* For other uses of the received time we can operate with granularity of one
second, and for that we use the global variable received_time. This is for
if (newsender)
{
if (domain == 0 && newsender[0] != 0)
- newsender = rewrite_address_qualify(newsender, FALSE);
+ /* deconst ok as newsender was not const */
+ newsender = US rewrite_address_qualify(newsender, FALSE);
if (filter_test != FTEST_NONE || receive_check_set_sender(newsender))
{
{
while (recipients_count-- > 0)
{
- uschar *s = rewrite_address(recipients_list[recipients_count].address,
+ const uschar * s = rewrite_address(recipients_list[recipients_count].address,
TRUE, TRUE, global_rewrite_rules, rewrite_existflags);
tree_add_nonrecipient(s);
}
&domain, FALSE);
#ifdef SUPPORT_I18N
- if (string_is_utf8(recipient))
- message_smtputf8 = TRUE;
- else
- allow_utf8_domains = b;
+ if (recipient)
+ if (string_is_utf8(recipient)) message_smtputf8 = TRUE;
+ else allow_utf8_domains = b;
}
+#else
+ ;
#endif
/* Keep a list of all the bad addresses so we can send a single
recipient is TRUE). */
for (int i = 0; i < recipients_count; i++)
- recipients_list[i].address =
- rewrite_address(recipients_list[i].address, TRUE, TRUE,
+ recipients_list[i].address = /* deconst ok as src was not cont */
+ US rewrite_address(recipients_list[i].address, TRUE, TRUE,
global_rewrite_rules, rewrite_existflags);
/* If there is no From: header, generate one for local (without
if ( !from_header
&& ((!sender_host_address && !f.suppress_local_fixups) || f.submission_mode))
{
- uschar *oname = US"";
+ const uschar * oname = US"";
/* Use the originator_name if this is a locally submitted message and the
caller is not trusted. For trusted callers, use it only if -F was used to
if (global_rewrite_rules && !sender_address_unrewritten && *sender_address)
{
- sender_address = rewrite_address(sender_address, FALSE, TRUE,
+ /* deconst ok as src was not const */
+ sender_address = US rewrite_address(sender_address, FALSE, TRUE,
global_rewrite_rules, rewrite_existflags);
DEBUG(D_receive|D_rewrite)
debug_printf("rewritten sender = %s\n", sender_address);
/* No I/O errors were encountered while writing the data file. */
DEBUG(D_receive) debug_printf("Data file written for message %s\n", message_id);
-if (LOGGING(receive_time)) timesince(&received_time_taken, &received_time);
+gettimeofday(&received_time_complete, NULL);
/* If there were any bad addresses extracted by -t, or there were no recipients
if (LOGGING(tls_cipher) && tls_in.cipher)
{
g = string_append(g, 2, US" X=", tls_in.cipher);
-# ifdef EXPERIMENTAL_TLS_RESUME
+# ifndef DISABLE_TLS_RESUME
if (LOGGING(tls_resumption) && tls_in.resumption & RESUME_USED)
g = string_catn(g, US"*", 1);
# endif
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"\"");
+ g = string_append(g, 2, US" SNI=", string_printing2(tls_in.sni, SP_TAB|SP_SPACE));
#endif
if (sender_host_authenticated)
#endif
if (LOGGING(receive_time))
- g = string_append(g, 2, US" RT=", string_timediff(&received_time_taken));
+ {
+ struct timeval diff = received_time_complete;
+ timediff(&diff, &received_time);
+ g = string_append(g, 2, US" RT=", string_timediff(&diff));
+ }
if (*queue_name)
g = string_append(g, 2, US" Q=", queue_name);
if (smtp_input && sender_host_address && !f.sender_host_notsocket &&
!receive_smtp_buffered())
{
- struct timeval tv;
+ struct timeval tv = {.tv_sec = 0, .tv_usec = 0};
fd_set select_check;
FD_ZERO(&select_check);
FD_SET(fileno(smtp_in), &select_check);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
if (select(fileno(smtp_in) + 1, &select_check, NULL, NULL, &tv) != 0)
{
else if (chunking_state > CHUNKING_OFFERED)
{
- smtp_printf("250- %u byte chunk, total %d\r\n250 OK id=%s\r\n", FALSE,
+ /* If there is more input waiting, no need to flush (probably the client
+ pipelined QUIT after data). We check only the in-process buffer, not
+ the socket. */
+
+ smtp_printf("250- %u byte chunk, total %d\r\n250 OK id=%s\r\n",
+ receive_smtp_buffered(),
chunking_datasize, message_size+message_linecount, message_id);
chunking_state = CHUNKING_OFFERED;
}
else
- smtp_printf("250 OK id=%s\r\n", FALSE, message_id);
+ smtp_printf("250 OK id=%s\r\n", receive_smtp_buffered(), message_id);
if (host_checking)
fprintf(stdout,