journald-audit.c revision 78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering/***
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering This file is part of systemd.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Copyright 2014 Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering systemd is free software; you can redistribute it and/or modify it
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering under the terms of the GNU Lesser General Public License as published by
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering (at your option) any later version.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering systemd is distributed in the hope that it will be useful, but
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Lesser General Public License for more details.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering You should have received a copy of the GNU Lesser General Public License
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering***/
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "missing.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "journald-audit.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringtypedef struct MapField {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const char *audit_field;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const char *journal_field;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int (*map)(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering} MapField;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int map_simple_field(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_free_ char *c = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering size_t l = 0, allocated = 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const char *e;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(field);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(p);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(iov);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(n_iov);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering l = strlen(field);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering allocated = l + 1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering c = malloc(allocated);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!c)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -ENOMEM;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering memcpy(c, field, l);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering for (e = *p; *e != ' ' && *e != 0; e++) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!GREEDY_REALLOC(c, allocated, l+2))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -ENOMEM;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering c[l++] = *e;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering c[l] = 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!GREEDY_REALLOC(*iov, *n_iov_allocated, *n_iov + 1))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -ENOMEM;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering (*iov)[*n_iov].iov_base = c;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering (*iov)[*n_iov].iov_len = l;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering (*n_iov) ++;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering *p = e;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering c = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poetteringstatic int map_string_field_internal(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov, bool filter_printable) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_free_ char *c = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const char *s, *e;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering size_t l;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(field);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(p);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(iov);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(n_iov);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* The kernel formats string fields in one of two formats. */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (**p == '"') {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Normal quoted syntax */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering s = *p + 1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering e = strchr(s, '"');
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!e)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering l = strlen(field) + (e - s);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering c = malloc(l+1);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!c)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -ENOMEM;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering *((char*) mempcpy(stpcpy(c, field), s, e - s)) = 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering e += 1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering } else if (unhexchar(**p) >= 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Hexadecimal escaping */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering size_t allocated = 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering l = strlen(field);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering allocated = l + 2;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering c = malloc(allocated);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!c)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -ENOMEM;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering memcpy(c, field, l);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering for (e = *p; *e != ' ' && *e != 0; e += 2) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int a, b;
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering uint8_t x;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering a = unhexchar(e[0]);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (a < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering b = unhexchar(e[1]);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (b < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering x = ((uint8_t) a << 4 | (uint8_t) b);
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering if (filter_printable && x < (uint8_t) ' ')
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering x = (uint8_t) ' ';
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!GREEDY_REALLOC(c, allocated, l+2))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -ENOMEM;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering c[l++] = (char) x;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering c[l] = 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering } else
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!GREEDY_REALLOC(*iov, *n_iov_allocated, *n_iov + 1))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -ENOMEM;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering (*iov)[*n_iov].iov_base = c;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering (*iov)[*n_iov].iov_len = l;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering (*n_iov) ++;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering *p = e;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering c = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poetteringstatic int map_string_field(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov) {
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering return map_string_field_internal(field, p, iov, n_iov_allocated, n_iov, false);
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering}
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poetteringstatic int map_string_field_printable(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov) {
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering return map_string_field_internal(field, p, iov, n_iov_allocated, n_iov, true);
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering}
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int map_generic_field(const char *prefix, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const char *e, *f;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering char *c, *t;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Implements fallback mappings for all fields we don't know */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering for (e = *p; e < *p + 16; e++) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (*e == 0 || *e == ' ')
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (*e == '=')
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!((*e >= 'a' && *e <= 'z') ||
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering (*e >= 'A' && *e <= 'Z') ||
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering (*e >= '0' && *e <= '9') ||
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering (*e == '_')))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (e <= *p || e >= *p + 16)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering c = alloca(strlen(prefix) + (e - *p) + 2);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering t = stpcpy(c, prefix);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering for (f = *p; f < e; f++)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering *(t++) = *f >= 'a' && *f <= 'z' ? ((*f - 'a') + 'A') : *f;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering strcpy(t, "=");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering e ++;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = map_simple_field(c, &e, iov, n_iov_allocated, n_iov);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering *p = e;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering/* Kernel fields are those occuring in the audit string before
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering * msg='. All of these fields are trusted, hence carry the "_" prefix.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering * We try to translate the fields we know into our native names. The
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering * other's are generically mapped to _AUDIT_FIELD_XYZ= */
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic const MapField map_fields_kernel[] = {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* First, we map certain well-known audit fields into native
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering * well-known fields */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "pid=", "_PID=", map_simple_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "ppid=", "_PPID=", map_simple_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "uid=", "_UID=", map_simple_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "euid=", "_EUID=", map_simple_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "fsuid=", "_FSUID=", map_simple_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "gid=", "_GID=", map_simple_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "egid=", "_EGID=", map_simple_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "fsgid=", "_FSGID=", map_simple_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "tty=", "_TTY=", map_simple_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "ses=", "_AUDIT_SESSION=", map_simple_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "auid=", "_AUDIT_LOGINUID=", map_simple_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "subj=", "_SELINUX_CONTEXT=", map_simple_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "comm=", "_COMM=", map_string_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "exe=", "_EXE=", map_string_field },
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering { "proctitle=", "_CMDLINE=", map_string_field_printable },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Some fields don't map to native well-known fields. However,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering * we know that they are string fields, hence let's undo
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering * string field escaping for them, though we stick to the
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering * generic field names. */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "path=", "_AUDIT_FIELD_PATH=", map_string_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "dev=", "_AUDIT_FIELD_DEV=", map_string_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "name=", "_AUDIT_FIELD_NAME=", map_string_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering {}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering};
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering/* Userspace fields are thos occuring in the audit string after
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering * msg='. All of these fields are untrusted, hence carry no "_"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering * prefix. We map the fields we don't know to AUDIT_FIELD_XYZ= */
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic const MapField map_fields_userspace[] = {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "cwd=", "AUDIT_FIELD_CWD=", map_string_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "cmd=", "AUDIT_FIELD_CMD=", map_string_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "acct=", "AUDIT_FIELD_ACCT=", map_string_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "exe=", "AUDIT_FIELD_EXE=", map_string_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering { "comm=", "AUDIT_FIELD_COMM=", map_string_field },
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering {}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering};
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int map_all_fields(
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const char *p,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const MapField map_fields[],
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const char *prefix,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering bool handle_msg,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering struct iovec **iov,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering size_t *n_iov_allocated,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering unsigned *n_iov) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(p);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(iov);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(n_iov_allocated);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(n_iov);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering for (;;) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering bool mapped = false;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const MapField *m;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const char *v;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering p += strspn(p, WHITESPACE);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (*p == 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (handle_msg) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering v = startswith(p, "msg='");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (v) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const char *e;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering char *c;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Userspace message. It's enclosed in
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering simple quotation marks, is not
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering escaped, but the last field in the
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering line, hence let's remove the
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering quotation mark, and apply the
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering userspace mapping instead of the
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering kernel mapping. */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering e = endswith(v, "'");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!e)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0; /* don't continue splitting up if the final quotation mark is missing */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering c = strndupa(v, e - v);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return map_all_fields(c, map_fields_userspace, "AUDIT_FIELD_", false, iov, n_iov_allocated, n_iov);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Try to map the kernel fields to our own names */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering for (m = map_fields; m->audit_field; m++) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering v = startswith(p, m->audit_field);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!v)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering continue;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = m->map(m->journal_field, &v, iov, n_iov_allocated, n_iov);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_debug("Failed to parse audit array: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r > 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering mapped = true;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering p = v;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!mapped) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = map_generic_field(prefix, &p, iov, n_iov_allocated, n_iov);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_debug("Failed to parse audit array: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r == 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Couldn't process as generic field, let's just skip over it */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering p += strcspn(p, WHITESPACE);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic void process_audit_string(Server *s, int type, const char *data, size_t size, const struct timeval *tv) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_free_ struct iovec *iov = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering size_t n_iov_allocated = 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering unsigned n_iov = 0, k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering uint64_t seconds, msec, id;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const char *p;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering unsigned z;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering char id_field[sizeof("_AUDIT_ID=") + DECIMAL_STR_MAX(uint64_t)],
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering type_field[sizeof("_AUDIT_TYPE=") + DECIMAL_STR_MAX(int)],
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering source_time_field[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)];
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const char *m;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(s);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (size <= 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!data)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Note that the input buffer is NUL terminated, but let's
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering * check whether there is a spurious NUL byte */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (memchr(data, 0, size))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering p = startswith(data, "audit");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!p)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (sscanf(p, "(%" PRIi64 ".%" PRIi64 ":%" PRIi64 "): %n",
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering &seconds,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering &msec,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering &id,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering &k) != 3)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering p += k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering n_iov_allocated = N_IOVEC_META_FIELDS + 5;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering iov = new(struct iovec, n_iov_allocated);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!iov) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_oom();
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering IOVEC_SET_STRING(iov[n_iov++], "_TRANSPORT=audit");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sprintf(source_time_field, "_SOURCE_REALTIME_TIMESTAMP=%" PRIu64,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering (usec_t) seconds * USEC_PER_SEC + (usec_t) msec * USEC_PER_MSEC);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering IOVEC_SET_STRING(iov[n_iov++], source_time_field);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sprintf(type_field, "_AUDIT_TYPE=%i", type);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering IOVEC_SET_STRING(iov[n_iov++], type_field);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sprintf(id_field, "_AUDIT_ID=%" PRIu64, id);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering IOVEC_SET_STRING(iov[n_iov++], id_field);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering m = strappenda("MESSAGE=", data);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering IOVEC_SET_STRING(iov[n_iov++], m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering z = n_iov;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering map_all_fields(p, map_fields_kernel, "_AUDIT_FIELD_", true, &iov, &n_iov_allocated, &n_iov);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!GREEDY_REALLOC(iov, n_iov_allocated, n_iov + N_IOVEC_META_FIELDS)) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_oom();
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering server_dispatch_message(s, iov, n_iov, n_iov_allocated, NULL, tv, NULL, 0, NULL, LOG_NOTICE, 0);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringfinish:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* free() all entries that map_all_fields() added. All others
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering * are allocated on the stack or are constant. */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering for (; z < n_iov; z++)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(iov[z].iov_base);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringvoid server_process_audit_message(
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Server *s,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const void *buffer,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering size_t buffer_size,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const struct ucred *ucred,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const struct timeval *tv,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const union sockaddr_union *sa,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering socklen_t salen) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const struct nlmsghdr *nl = buffer;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(s);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (buffer_size < ALIGN(sizeof(struct nlmsghdr)))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(buffer);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Filter out fake data */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!sa ||
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering salen != sizeof(struct sockaddr_nl) ||
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sa->nl.nl_family != AF_NETLINK ||
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sa->nl.nl_pid != 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_debug("Audit netlink message from invalid sender.");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!ucred || ucred->pid != 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_debug("Audit netlink message with invalid credentials.");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!NLMSG_OK(nl, buffer_size)) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Audit netlink message truncated.");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Ignore special Netlink messages */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (IN_SET(nl->nlmsg_type, NLMSG_NOOP, NLMSG_ERROR))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Below AUDIT_FIRST_USER_MSG theer are only control messages, let's ignore those */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (nl->nlmsg_type < AUDIT_FIRST_USER_MSG)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering process_audit_string(s, nl->nlmsg_type, NLMSG_DATA(nl), nl->nlmsg_len - ALIGN(sizeof(struct nlmsghdr)), tv);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poetteringstatic int enable_audit(int fd, bool b) {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering struct {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering union {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering struct nlmsghdr header;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering uint8_t header_space[NLMSG_HDRLEN];
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering };
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering struct audit_status body;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering } _packed_ request = {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering .header.nlmsg_len = NLMSG_LENGTH(sizeof(struct audit_status)),
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering .header.nlmsg_type = AUDIT_SET,
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering .header.nlmsg_flags = NLM_F_REQUEST,
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering .header.nlmsg_seq = 1,
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering .header.nlmsg_pid = 0,
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering .body.mask = AUDIT_STATUS_ENABLED,
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering .body.enabled = b,
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering };
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering union sockaddr_union sa = {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering .nl.nl_family = AF_NETLINK,
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering .nl.nl_pid = 0,
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering };
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering struct iovec iovec = {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering .iov_base = &request,
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering .iov_len = NLMSG_LENGTH(sizeof(struct audit_status)),
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering };
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering struct msghdr mh = {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering .msg_iov = &iovec,
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering .msg_iovlen = 1,
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering .msg_name = &sa.sa,
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering .msg_namelen = sizeof(sa.nl),
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering };
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering ssize_t n;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering n = sendmsg(fd, &mh, MSG_NOSIGNAL);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (n < 0)
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return -errno;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (n != NLMSG_LENGTH(sizeof(struct audit_status)))
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return -EIO;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering /* We don't wait for the result here, we can't do anything
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering * about it anyway */
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return 0;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering}
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint server_open_audit(Server *s) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering static const int one = 1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (s->audit_fd < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering static const union sockaddr_union sa = {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering .nl.nl_family = AF_NETLINK,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering .nl.nl_pid = 0,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering .nl.nl_groups = AUDIT_NLGRP_READLOG,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering };
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering s->audit_fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_AUDIT);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (s->audit_fd < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_debug("Audit not supported in the kernel.");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering else
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_warning("Failed to create audit socket, ignoring: %m");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = bind(s->audit_fd, &sa.sa, sizeof(sa.nl));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to join audit multicast group: %m");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -errno;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering } else
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fd_nonblock(s->audit_fd, 1);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = setsockopt(s->audit_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to set SO_PASSCRED on audit socket: %m");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -errno;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_event_add_io(s->event, &s->audit_event_source, s->audit_fd, EPOLLIN, process_datagram, s);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to add audit fd to event loop: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering /* We are listening now, try to enable audit */
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering r = enable_audit(s->audit_fd, true);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (r < 0)
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering log_warning("Failed to issue audit enable call: %s", strerror(-r));
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}