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
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "alloc-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "audit-type.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "fd-util.h"
afc5dbf37fd2399d37976388d9dd9ab470ecf446Lennart Poettering#include "hexdecoct.h"
afc5dbf37fd2399d37976388d9dd9ab470ecf446Lennart Poettering#include "io-util.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "journald-audit.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "missing.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "string-util.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') ||
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering *e == '_' || *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);
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering for (f = *p; f < e; f++) {
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering char x;
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering if (*f >= 'a' && *f <= 'z')
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering x = (*f - 'a') + 'A'; /* uppercase */
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering else if (*f == '-')
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering x = '_'; /* dashes → underscores */
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering else
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering x = *f;
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering *(t++) = x;
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering }
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
f131770b1465fbf423881f16ba85523a05f846feVeres Lajos/* Kernel fields are those occurring 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
f131770b1465fbf423881f16ba85523a05f846feVeres Lajos/* Userspace fields are those occurring 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);
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt if (r < 0)
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt return log_debug_errno(r, "Failed to parse audit array: %m");
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);
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt if (r < 0)
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt return log_debug_errno(r, "Failed to parse audit array: %m");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
ece174c5439021e32ebcc858842de9586072c006Lennart 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
0b97208d8c39131f8a7cfcfccb5c40b86af44ee5Lennart Poetteringstatic void process_audit_string(Server *s, int type, const char *data, size_t size) {
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;
8bb3626dac93c0157989fb87afe0212958d7dbb4Zbigniew Jędrzejewski-Szmek const char *p, *type_name;
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)];
25b3245fb483e52766867dfe33ce271011caaca9Lennart Poettering 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
1fa2f38f0f011010bf57522b42fcc168856a7003Zbigniew Jędrzejewski-Szmek if (sscanf(p, "(%" PRIu64 ".%" PRIu64 ":%" PRIu64 "):%n",
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering &seconds,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering &msec,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering &id,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering &k) != 3)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering p += k;
5034c7bcdfc4493ed3c30722e9d897c8da78fedeLennart Poettering p += strspn(p, WHITESPACE);
5034c7bcdfc4493ed3c30722e9d897c8da78fedeLennart Poettering
5034c7bcdfc4493ed3c30722e9d897c8da78fedeLennart Poettering if (isempty(p))
5034c7bcdfc4493ed3c30722e9d897c8da78fedeLennart Poettering return;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
cd556b6ca8aec8dd371806afedec45f852f8f724Zbigniew Jędrzejewski-Szmek n_iov_allocated = N_IOVEC_META_FIELDS + 7;
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
d6f4302b66fb8847dd79cdf7ea35b9eeccac8affLennart Poettering assert_cc(4 == LOG_FAC(LOG_AUTH));
d6f4302b66fb8847dd79cdf7ea35b9eeccac8affLennart Poettering IOVEC_SET_STRING(iov[n_iov++], "SYSLOG_FACILITY=4");
cd556b6ca8aec8dd371806afedec45f852f8f724Zbigniew Jędrzejewski-Szmek IOVEC_SET_STRING(iov[n_iov++], "SYSLOG_IDENTIFIER=audit");
cd556b6ca8aec8dd371806afedec45f852f8f724Zbigniew Jędrzejewski-Szmek
8bb3626dac93c0157989fb87afe0212958d7dbb4Zbigniew Jędrzejewski-Szmek type_name = audit_type_name_alloca(type);
8bb3626dac93c0157989fb87afe0212958d7dbb4Zbigniew Jędrzejewski-Szmek
8bb3626dac93c0157989fb87afe0212958d7dbb4Zbigniew Jędrzejewski-Szmek m = strjoina("MESSAGE=", type_name, " ", p);
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
0b97208d8c39131f8a7cfcfccb5c40b86af44ee5Lennart Poettering server_dispatch_message(s, iov, n_iov, n_iov_allocated, NULL, NULL, 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 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
0b97208d8c39131f8a7cfcfccb5c40b86af44ee5Lennart Poettering process_audit_string(s, nl->nlmsg_type, NLMSG_DATA(nl), nl->nlmsg_len - ALIGN(sizeof(struct nlmsghdr)));
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
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt log_warning_errno(errno, "Failed to create audit socket, ignoring: %m");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
417a7fdc418ec76cc4c321c9a07ec15c72b3ac7dLennart Poettering if (bind(s->audit_fd, &sa.sa, sizeof(sa.nl)) < 0) {
417a7fdc418ec76cc4c321c9a07ec15c72b3ac7dLennart Poettering log_warning_errno(errno,
417a7fdc418ec76cc4c321c9a07ec15c72b3ac7dLennart Poettering "Failed to join audit multicast group. "
417a7fdc418ec76cc4c321c9a07ec15c72b3ac7dLennart Poettering "The kernel is probably too old or multicast reading is not supported. "
417a7fdc418ec76cc4c321c9a07ec15c72b3ac7dLennart Poettering "Ignoring: %m");
417a7fdc418ec76cc4c321c9a07ec15c72b3ac7dLennart Poettering s->audit_fd = safe_close(s->audit_fd);
417a7fdc418ec76cc4c321c9a07ec15c72b3ac7dLennart Poettering return 0;
417a7fdc418ec76cc4c321c9a07ec15c72b3ac7dLennart 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));
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt if (r < 0)
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt return log_error_errno(errno, "Failed to set SO_PASSCRED on audit socket: %m");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
8531ae707d4d0203e83304d4af948b8169a5fce1Lennart Poettering r = sd_event_add_io(s->event, &s->audit_event_source, s->audit_fd, EPOLLIN, server_process_datagram, s);
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt if (r < 0)
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt return log_error_errno(r, "Failed to add audit fd to event loop: %m");
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)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_warning_errno(r, "Failed to issue audit enable call: %m");
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}