journal: store the original syslog input as SYSLOG_RAW=

This allows the original stream to be recreated and/or verified. The new field
is written if any stripping was done or if the input message contained embeded
NULs.

$ printf '<13>Sep 15 15:07:58 HOST: x\0y' | nc -w1 -u -U /run/systemd/journal/dev-log

$ journalctl -o json-pretty ...
{
  ...
  "MESSAGE" : "x",
  "SYSLOG_RAW" : [ 60, 49, 51, 62, 83, 101, 112, 32, 49, 53, 32, 49, 53, 58, 48, 55, 58, 53, 56, 32, 72, 79, 83, 84, 58, 32, 120, 0, 121 ]
}

$ journalctl -o export ... | cat -v
...
MESSAGE=x
SYSLOG_RAW
^]^@^@^@^@^@^@^@<13>Sep 15 15:07:58 HOST: x^@y

This mostly fixes #4863.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2018-06-08 13:52:22 +02:00
parent c3950a9bbe
commit df8701a3f2
2 changed files with 33 additions and 3 deletions

View File

@ -112,7 +112,22 @@
see
<citerefentry project='die-net'><refentrytitle>program_invocation_short_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>.)</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>SYSLOG_RAW=</varname></term>
<listitem>
<para>The original contents of the syslog line as received in the syslog
datagram. This field is only included if the <varname>MESSAGE=</varname>
field was modified compared to the original payload. This happens when the
message contains leading or trailing whitespace (trailing and leading
whitespace is stripped), or it contains an embedded
<constant>NUL</constant> byte (the <constant>NUL</constant> byte and
anything after it is not included). Thus, the original syslog line is
either stored as <varname>SYSLOG_RAW=</varname> or it can be recreated
based on the stored priority, timestamp, hostname, and the message payload
stored in <varname>MESSAGE=</varname>.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -311,6 +311,7 @@ void server_process_syslog_message(
ClientContext *context = NULL;
struct iovec *iovec;
size_t n = 0, m, i, leading_ws;
bool store_raw;
assert(s);
assert(buf);
@ -345,6 +346,10 @@ void server_process_syslog_message(
t[i - leading_ws] = 0;
}
/* We will add the SYSLOG_RAW= field when we stripped anything
* _or_ if the input message contained NUL bytes. */
store_raw = msg != buf || strlen(msg) != raw_len;
syslog_parse_priority(&msg, &priority, true);
if (!client_context_test_priority(context, priority))
@ -365,7 +370,7 @@ void server_process_syslog_message(
if (s->forward_to_wall)
server_forward_wall(s, priority, identifier, msg, ucred);
m = N_IOVEC_META_FIELDS + 6 + client_context_extra_fields_n_iovec(context);
m = N_IOVEC_META_FIELDS + 7 + client_context_extra_fields_n_iovec(context);
iovec = newa(struct iovec, m);
iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=syslog");
@ -389,8 +394,18 @@ void server_process_syslog_message(
}
message = strjoina("MESSAGE=", msg);
if (message)
iovec[n++] = IOVEC_MAKE_STRING(message);
iovec[n++] = IOVEC_MAKE_STRING(message);
if (store_raw) {
const size_t hlen = strlen("SYSLOG_RAW=");
char *t;
t = newa(char, hlen + raw_len);
memcpy(t, "SYSLOG_RAW=", hlen);
memcpy(t + hlen, buf, raw_len);
iovec[n++] = IOVEC_MAKE(t, hlen + raw_len);
}
server_dispatch_message(s, iovec, n, m, context, tv, priority, 0);
}