*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for writing log files. The code for maintaining datestamped
US"Negotiation failed for proxy configured host",
US"Authenticator 'other' failure",
US"target not supporting SMTPUTF8",
- US"",
+ US"host is local",
+ US"tainted filename",
US"Not time for routing",
US"Not time for local delivery",
}
if (f.receive_call_bombout) receive_bomb_out(NULL, s2); /* does not return */
if (smtp_input) smtp_closedown(s2);
-exim_exit(EXIT_FAILURE, NULL);
+exim_exit(EXIT_FAILURE);
}
int
log_create_as_exim(uschar *name)
{
-pid_t pid = fork();
+pid_t pid = exim_fork(US"logfile-create");
int status = 1;
int fd = -1;
will be compared. The static slot for saving it is the same size as buffer,
and the text has been checked above to fit, so this use of strcpy() is OK. */
-if (type == lt_main && string_datestamp_offset >= 0)
+if (type == lt_main)
{
Ustrcpy(mainlog_name, buffer);
- mainlog_datestamp = mainlog_name + string_datestamp_offset;
+ if (string_datestamp_offset > 0)
+ mainlog_datestamp = mainlog_name + string_datestamp_offset;
}
/* Ditto for the reject log */
-else if (type == lt_reject && string_datestamp_offset >= 0)
+else if (type == lt_reject)
{
Ustrcpy(rejectlog_name, buffer);
- rejectlog_datestamp = rejectlog_name + string_datestamp_offset;
+ if (string_datestamp_offset > 0)
+ rejectlog_datestamp = rejectlog_name + string_datestamp_offset;
}
/* and deal with the debug log (which keeps the datestamp, but does not
just bombing out, force the log to stderr and carry on if stderr is available.
*/
-if (euid != root_uid && euid != exim_uid && log_stderr != NULL)
+if (euid != root_uid && euid != exim_uid && log_stderr)
{
*fd = fileno(log_stderr);
return;
/* Otherwise this is a disaster. This call is deliberately ONLY to the panic
log. If possible, save a copy of the original line that was being logged. If we
are recursing (can't open the panic log either), the pointer will already be
-set. */
+set. Also, when we had to use a subprocess for the create we didn't retrieve
+errno from it, so get the error from the open attempt above (which is often
+meaningful enough, so leave it). */
if (!panic_save_buffer)
if ((panic_save_buffer = US malloc(LOG_BUFFER_SIZE)))
if (!(log_buffer = US malloc(LOG_BUFFER_SIZE)))
{
fprintf(stderr, "exim: failed to get store for log buffer\n");
- exim_exit(EXIT_FAILURE, NULL);
+ exim_exit(EXIT_FAILURE);
}
/* If we haven't already done so, inspect the setting of log_file_path to
if (flags & LOG_CONFIG) g = log_config_info(g, flags);
+ /* We want to be able to log tainted info, but log_buffer is directly
+ malloc'd. So use deliberately taint-nonchecking routines to build into
+ it, trusting that we will never expand the results. */
+
va_start(ap, format);
i = g->ptr;
- if (!string_vformat(g, FALSE, format, ap))
+ if (!string_vformat(g, SVFMT_TAINT_NOCHK, format, ap))
{
g->ptr = i;
g = string_cat(g, US"**** log string overflowed log buffer ****");
va_start(ap, format);
{
int i = g->ptr;
- if (!string_vformat(g, FALSE, format, ap))
+
+ /* We want to be able to log tainted info, but log_buffer is directly
+ malloc'd. So use deliberately taint-nonchecking routines to build into
+ it, trusting that we will never expand the results. */
+
+ if (!string_vformat(g, SVFMT_TAINT_NOCHK, format, ap))
{
g->ptr = i;
g = string_cat(g, US"**** log string overflowed log buffer ****\n");
if ( flags & LOG_SENDER
&& g->ptr < LOG_BUFFER_SIZE - 10 - Ustrlen(raw_sender))
- g = string_fmt_append(g, " from <%s>", raw_sender);
+ g = string_fmt_append_f(g, SVFMT_TAINT_NOCHK, " from <%s>", raw_sender);
/* Add list of recipients to the message if required; the raw list,
before rewriting, was saved in raw_recipients. There may be none, if an ACL
&& raw_recipients_count > 0)
{
int i;
- g = string_fmt_append(g, " for");
+ g = string_fmt_append_f(g, SVFMT_TAINT_NOCHK, " for", NULL);
for (i = 0; i < raw_recipients_count; i++)
{
uschar * s = raw_recipients[i];
if (LOG_BUFFER_SIZE - g->ptr < Ustrlen(s) + 3) break;
- g = string_fmt_append(g, " %s", s);
+ g = string_fmt_append_f(g, SVFMT_TAINT_NOCHK, " %s", s);
}
}
else
fprintf(log_stderr, "%s", CS log_buffer);
- if ((flags & LOG_PANIC_DIE) == LOG_PANIC_DIE) exim_exit(EXIT_FAILURE, US"");
+ if ((flags & LOG_PANIC_DIE) == LOG_PANIC_DIE) exim_exit(EXIT_FAILURE);
return;
}
{
if (header_list && LOGGING(rejected_header))
{
- uschar * p = g->s + g->ptr;
+ gstring * g2;
int i;
if (recipients_count > 0)
{
/* List the sender */
- string_format(p, LOG_BUFFER_SIZE - g->ptr,
- "Envelope-from: <%s>\n", sender_address);
- while (*p) p++;
- g->ptr = p - g->s;
+ g2 = string_fmt_append_f(g, SVFMT_TAINT_NOCHK,
+ "Envelope-from: <%s>\n", sender_address);
+ if (g2) g = g2;
/* List up to 5 recipients */
- string_format(p, LOG_BUFFER_SIZE - g->ptr,
- "Envelope-to: <%s>\n", recipients_list[0].address);
- while (*p) p++;
- g->ptr = p - g->s;
+ g2 = string_fmt_append_f(g, SVFMT_TAINT_NOCHK,
+ "Envelope-to: <%s>\n", recipients_list[0].address);
+ if (g2) g = g2;
for (i = 1; i < recipients_count && i < 5; i++)
{
- string_format(p, LOG_BUFFER_SIZE - g->ptr, " <%s>\n",
- recipients_list[i].address);
- while (*p) p++;
- g->ptr = p - g->s;
+ g2 = string_fmt_append_f(g, SVFMT_TAINT_NOCHK,
+ " <%s>\n", recipients_list[i].address);
+ if (g2) g = g2;
}
if (i < recipients_count)
{
- string_format(p, LOG_BUFFER_SIZE - g->ptr,
- " ...\n");
- while (*p) p++;
- g->ptr = p - g->s;
+ g2 = string_fmt_append_f(g, SVFMT_TAINT_NOCHK, " ...\n", NULL);
+ if (g2) g = g2;
}
}
for (header_line * h = header_list; h; h = h->next) if (h->text)
{
- BOOL fitted = string_format(p, LOG_BUFFER_SIZE - g->ptr,
- "%c %s", h->type, h->text);
- while (*p) p++;
- g->ptr = p - g->s;
- if (!fitted) /* Buffer is full; truncate */
+ g2 = string_fmt_append_f(g, SVFMT_TAINT_NOCHK,
+ "%c %s", h->type, h->text);
+ if (g2)
+ g = g2;
+ else /* Buffer is full; truncate */
{
g->ptr -= 100; /* For message and separator */
if (g->s[g->ptr-1] == '\n') g->ptr--;
panic_recurseflag = FALSE;
if (panic_save_buffer)
- {
- int i = write(paniclogfd, panic_save_buffer, Ustrlen(panic_save_buffer));
- i = i; /* compiler quietening */
- }
+ (void) write(paniclogfd, panic_save_buffer, Ustrlen(panic_save_buffer));
written_len = write_to_fd_buf(paniclogfd, g->s, g->ptr);
if (written_len != g->ptr)
uschar *string, bit_table *options, int count, uschar *which, int flags)
{
uschar *errmsg;
-if (string == NULL) return;
+if (!string) return;
if (*string == '=')
{
char *end; /* Not uschar */
memset(selector, 0, sizeof(*selector)*selsize);
*selector = strtoul(CS string+1, &end, 0);
- if (*end == 0) return;
+ if (!*end) return;
errmsg = string_sprintf("malformed numeric %s_selector setting: %s", which,
string);
goto ERROR_RETURN;
int len;
bit_table *start, *end;
- while (isspace(*string)) string++;
- if (*string == 0) return;
+ Uskip_whitespace(&string);
+ if (!*string) return;
if (*string != '+' && *string != '-')
{
bit_table *middle = start + (end - start)/2;
int c = Ustrncmp(s, middle->name, len);
if (c == 0)
- {
if (middle->name[len] != 0) c = -1; else
{
unsigned int bit = middle->bit;
break; /* Out of loop to match selector name */
}
- }
if (c < 0) end = middle; else start = middle + 1;
} /* Loop to match selector name */