2 This file is part of systemd.
4 Copyright 2014 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include "alloc-util.h"
21 #include "audit-type.h"
23 #include "hexdecoct.h"
25 #include "journald-audit.h"
27 #include "string-util.h"
29 typedef struct MapField
{
30 const char *audit_field
;
31 const char *journal_field
;
32 int (*map
)(const char *field
, const char **p
, struct iovec
**iov
, size_t *n_iov_allocated
, unsigned *n_iov
);
35 static int map_simple_field(const char *field
, const char **p
, struct iovec
**iov
, size_t *n_iov_allocated
, unsigned *n_iov
) {
36 _cleanup_free_
char *c
= NULL
;
37 size_t l
= 0, allocated
= 0;
47 c
= malloc(allocated
);
52 for (e
= *p
; *e
!= ' ' && *e
!= 0; e
++) {
53 if (!GREEDY_REALLOC(c
, allocated
, l
+2))
61 if (!GREEDY_REALLOC(*iov
, *n_iov_allocated
, *n_iov
+ 1))
64 (*iov
)[*n_iov
].iov_base
= c
;
65 (*iov
)[*n_iov
].iov_len
= l
;
74 static 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
) {
75 _cleanup_free_
char *c
= NULL
;
84 /* The kernel formats string fields in one of two formats. */
87 /* Normal quoted syntax */
93 l
= strlen(field
) + (e
- s
);
98 *((char*) mempcpy(stpcpy(c
, field
), s
, e
- s
)) = 0;
102 } else if (unhexchar(**p
) >= 0) {
103 /* Hexadecimal escaping */
104 size_t allocated
= 0;
108 c
= malloc(allocated
);
113 for (e
= *p
; *e
!= ' ' && *e
!= 0; e
+= 2) {
125 x
= ((uint8_t) a
<< 4 | (uint8_t) b
);
127 if (filter_printable
&& x
< (uint8_t) ' ')
130 if (!GREEDY_REALLOC(c
, allocated
, l
+2))
140 if (!GREEDY_REALLOC(*iov
, *n_iov_allocated
, *n_iov
+ 1))
143 (*iov
)[*n_iov
].iov_base
= c
;
144 (*iov
)[*n_iov
].iov_len
= l
;
153 static int map_string_field(const char *field
, const char **p
, struct iovec
**iov
, size_t *n_iov_allocated
, unsigned *n_iov
) {
154 return map_string_field_internal(field
, p
, iov
, n_iov_allocated
, n_iov
, false);
157 static int map_string_field_printable(const char *field
, const char **p
, struct iovec
**iov
, size_t *n_iov_allocated
, unsigned *n_iov
) {
158 return map_string_field_internal(field
, p
, iov
, n_iov_allocated
, n_iov
, true);
161 static int map_generic_field(const char *prefix
, const char **p
, struct iovec
**iov
, size_t *n_iov_allocated
, unsigned *n_iov
) {
166 /* Implements fallback mappings for all fields we don't know */
168 for (e
= *p
; e
< *p
+ 16; e
++) {
170 if (*e
== 0 || *e
== ' ')
176 if (!((*e
>= 'a' && *e
<= 'z') ||
177 (*e
>= 'A' && *e
<= 'Z') ||
178 (*e
>= '0' && *e
<= '9') ||
179 *e
== '_' || *e
== '-'))
183 if (e
<= *p
|| e
>= *p
+ 16)
186 c
= alloca(strlen(prefix
) + (e
- *p
) + 2);
188 t
= stpcpy(c
, prefix
);
189 for (f
= *p
; f
< e
; f
++) {
192 if (*f
>= 'a' && *f
<= 'z')
193 x
= (*f
- 'a') + 'A'; /* uppercase */
195 x
= '_'; /* dashes → underscores */
205 r
= map_simple_field(c
, &e
, iov
, n_iov_allocated
, n_iov
);
213 /* Kernel fields are those occurring in the audit string before
214 * msg='. All of these fields are trusted, hence carry the "_" prefix.
215 * We try to translate the fields we know into our native names. The
216 * other's are generically mapped to _AUDIT_FIELD_XYZ= */
217 static const MapField map_fields_kernel
[] = {
219 /* First, we map certain well-known audit fields into native
220 * well-known fields */
221 { "pid=", "_PID=", map_simple_field
},
222 { "ppid=", "_PPID=", map_simple_field
},
223 { "uid=", "_UID=", map_simple_field
},
224 { "euid=", "_EUID=", map_simple_field
},
225 { "fsuid=", "_FSUID=", map_simple_field
},
226 { "gid=", "_GID=", map_simple_field
},
227 { "egid=", "_EGID=", map_simple_field
},
228 { "fsgid=", "_FSGID=", map_simple_field
},
229 { "tty=", "_TTY=", map_simple_field
},
230 { "ses=", "_AUDIT_SESSION=", map_simple_field
},
231 { "auid=", "_AUDIT_LOGINUID=", map_simple_field
},
232 { "subj=", "_SELINUX_CONTEXT=", map_simple_field
},
233 { "comm=", "_COMM=", map_string_field
},
234 { "exe=", "_EXE=", map_string_field
},
235 { "proctitle=", "_CMDLINE=", map_string_field_printable
},
237 /* Some fields don't map to native well-known fields. However,
238 * we know that they are string fields, hence let's undo
239 * string field escaping for them, though we stick to the
240 * generic field names. */
241 { "path=", "_AUDIT_FIELD_PATH=", map_string_field
},
242 { "dev=", "_AUDIT_FIELD_DEV=", map_string_field
},
243 { "name=", "_AUDIT_FIELD_NAME=", map_string_field
},
247 /* Userspace fields are those occurring in the audit string after
248 * msg='. All of these fields are untrusted, hence carry no "_"
249 * prefix. We map the fields we don't know to AUDIT_FIELD_XYZ= */
250 static const MapField map_fields_userspace
[] = {
251 { "cwd=", "AUDIT_FIELD_CWD=", map_string_field
},
252 { "cmd=", "AUDIT_FIELD_CMD=", map_string_field
},
253 { "acct=", "AUDIT_FIELD_ACCT=", map_string_field
},
254 { "exe=", "AUDIT_FIELD_EXE=", map_string_field
},
255 { "comm=", "AUDIT_FIELD_COMM=", map_string_field
},
259 static int map_all_fields(
261 const MapField map_fields
[],
265 size_t *n_iov_allocated
,
272 assert(n_iov_allocated
);
280 p
+= strspn(p
, WHITESPACE
);
286 v
= startswith(p
, "msg='");
291 /* Userspace message. It's enclosed in
292 simple quotation marks, is not
293 escaped, but the last field in the
294 line, hence let's remove the
295 quotation mark, and apply the
296 userspace mapping instead of the
299 e
= endswith(v
, "'");
301 return 0; /* don't continue splitting up if the final quotation mark is missing */
303 c
= strndupa(v
, e
- v
);
304 return map_all_fields(c
, map_fields_userspace
, "AUDIT_FIELD_", false, iov
, n_iov_allocated
, n_iov
);
308 /* Try to map the kernel fields to our own names */
309 for (m
= map_fields
; m
->audit_field
; m
++) {
310 v
= startswith(p
, m
->audit_field
);
314 r
= m
->map(m
->journal_field
, &v
, iov
, n_iov_allocated
, n_iov
);
316 return log_debug_errno(r
, "Failed to parse audit array: %m");
326 r
= map_generic_field(prefix
, &p
, iov
, n_iov_allocated
, n_iov
);
328 return log_debug_errno(r
, "Failed to parse audit array: %m");
331 /* Couldn't process as generic field, let's just skip over it */
332 p
+= strcspn(p
, WHITESPACE
);
337 static void process_audit_string(Server
*s
, int type
, const char *data
, size_t size
) {
338 _cleanup_free_
struct iovec
*iov
= NULL
;
339 size_t n_iov_allocated
= 0;
340 unsigned n_iov
= 0, k
;
341 uint64_t seconds
, msec
, id
;
342 const char *p
, *type_name
;
344 char id_field
[sizeof("_AUDIT_ID=") + DECIMAL_STR_MAX(uint64_t)],
345 type_field
[sizeof("_AUDIT_TYPE=") + DECIMAL_STR_MAX(int)],
346 source_time_field
[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t
)];
357 /* Note that the input buffer is NUL terminated, but let's
358 * check whether there is a spurious NUL byte */
359 if (memchr(data
, 0, size
))
362 p
= startswith(data
, "audit");
366 if (sscanf(p
, "(%" PRIu64
".%" PRIu64
":%" PRIu64
"):%n",
374 p
+= strspn(p
, WHITESPACE
);
379 n_iov_allocated
= N_IOVEC_META_FIELDS
+ 7;
380 iov
= new(struct iovec
, n_iov_allocated
);
386 IOVEC_SET_STRING(iov
[n_iov
++], "_TRANSPORT=audit");
388 sprintf(source_time_field
, "_SOURCE_REALTIME_TIMESTAMP=%" PRIu64
,
389 (usec_t
) seconds
* USEC_PER_SEC
+ (usec_t
) msec
* USEC_PER_MSEC
);
390 IOVEC_SET_STRING(iov
[n_iov
++], source_time_field
);
392 sprintf(type_field
, "_AUDIT_TYPE=%i", type
);
393 IOVEC_SET_STRING(iov
[n_iov
++], type_field
);
395 sprintf(id_field
, "_AUDIT_ID=%" PRIu64
, id
);
396 IOVEC_SET_STRING(iov
[n_iov
++], id_field
);
398 assert_cc(4 == LOG_FAC(LOG_AUTH
));
399 IOVEC_SET_STRING(iov
[n_iov
++], "SYSLOG_FACILITY=4");
400 IOVEC_SET_STRING(iov
[n_iov
++], "SYSLOG_IDENTIFIER=audit");
402 type_name
= audit_type_name_alloca(type
);
404 m
= strjoina("MESSAGE=", type_name
, " ", p
);
405 IOVEC_SET_STRING(iov
[n_iov
++], m
);
409 map_all_fields(p
, map_fields_kernel
, "_AUDIT_FIELD_", true, &iov
, &n_iov_allocated
, &n_iov
);
411 if (!GREEDY_REALLOC(iov
, n_iov_allocated
, n_iov
+ N_IOVEC_META_FIELDS
)) {
416 server_dispatch_message(s
, iov
, n_iov
, n_iov_allocated
, NULL
, NULL
, NULL
, 0, NULL
, LOG_NOTICE
, 0);
419 /* free() all entries that map_all_fields() added. All others
420 * are allocated on the stack or are constant. */
422 for (; z
< n_iov
; z
++)
423 free(iov
[z
].iov_base
);
426 void server_process_audit_message(
430 const struct ucred
*ucred
,
431 const union sockaddr_union
*sa
,
434 const struct nlmsghdr
*nl
= buffer
;
438 if (buffer_size
< ALIGN(sizeof(struct nlmsghdr
)))
443 /* Filter out fake data */
445 salen
!= sizeof(struct sockaddr_nl
) ||
446 sa
->nl
.nl_family
!= AF_NETLINK
||
447 sa
->nl
.nl_pid
!= 0) {
448 log_debug("Audit netlink message from invalid sender.");
452 if (!ucred
|| ucred
->pid
!= 0) {
453 log_debug("Audit netlink message with invalid credentials.");
457 if (!NLMSG_OK(nl
, buffer_size
)) {
458 log_error("Audit netlink message truncated.");
462 /* Ignore special Netlink messages */
463 if (IN_SET(nl
->nlmsg_type
, NLMSG_NOOP
, NLMSG_ERROR
))
466 /* Below AUDIT_FIRST_USER_MSG theer are only control messages, let's ignore those */
467 if (nl
->nlmsg_type
< AUDIT_FIRST_USER_MSG
)
470 process_audit_string(s
, nl
->nlmsg_type
, NLMSG_DATA(nl
), nl
->nlmsg_len
- ALIGN(sizeof(struct nlmsghdr
)));
473 static int enable_audit(int fd
, bool b
) {
476 struct nlmsghdr header
;
477 uint8_t header_space
[NLMSG_HDRLEN
];
479 struct audit_status body
;
480 } _packed_ request
= {
481 .header
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct audit_status
)),
482 .header
.nlmsg_type
= AUDIT_SET
,
483 .header
.nlmsg_flags
= NLM_F_REQUEST
,
484 .header
.nlmsg_seq
= 1,
485 .header
.nlmsg_pid
= 0,
486 .body
.mask
= AUDIT_STATUS_ENABLED
,
489 union sockaddr_union sa
= {
490 .nl
.nl_family
= AF_NETLINK
,
493 struct iovec iovec
= {
494 .iov_base
= &request
,
495 .iov_len
= NLMSG_LENGTH(sizeof(struct audit_status
)),
501 .msg_namelen
= sizeof(sa
.nl
),
506 n
= sendmsg(fd
, &mh
, MSG_NOSIGNAL
);
509 if (n
!= NLMSG_LENGTH(sizeof(struct audit_status
)))
512 /* We don't wait for the result here, we can't do anything
518 int server_open_audit(Server
*s
) {
519 static const int one
= 1;
522 if (s
->audit_fd
< 0) {
523 static const union sockaddr_union sa
= {
524 .nl
.nl_family
= AF_NETLINK
,
526 .nl
.nl_groups
= AUDIT_NLGRP_READLOG
,
529 s
->audit_fd
= socket(AF_NETLINK
, SOCK_RAW
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, NETLINK_AUDIT
);
530 if (s
->audit_fd
< 0) {
531 if (errno
== EAFNOSUPPORT
|| errno
== EPROTONOSUPPORT
)
532 log_debug("Audit not supported in the kernel.");
534 log_warning_errno(errno
, "Failed to create audit socket, ignoring: %m");
539 if (bind(s
->audit_fd
, &sa
.sa
, sizeof(sa
.nl
)) < 0) {
540 log_warning_errno(errno
,
541 "Failed to join audit multicast group. "
542 "The kernel is probably too old or multicast reading is not supported. "
544 s
->audit_fd
= safe_close(s
->audit_fd
);
548 fd_nonblock(s
->audit_fd
, 1);
550 r
= setsockopt(s
->audit_fd
, SOL_SOCKET
, SO_PASSCRED
, &one
, sizeof(one
));
552 return log_error_errno(errno
, "Failed to set SO_PASSCRED on audit socket: %m");
554 r
= sd_event_add_io(s
->event
, &s
->audit_event_source
, s
->audit_fd
, EPOLLIN
, server_process_datagram
, s
);
556 return log_error_errno(r
, "Failed to add audit fd to event loop: %m");
558 /* We are listening now, try to enable audit */
559 r
= enable_audit(s
->audit_fd
, true);
561 log_warning_errno(r
, "Failed to issue audit enable call: %m");