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