1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
35 #include <sys/ioctl.h>
38 #include <systemd/sd-journal.h>
42 #include "path-util.h"
45 #include "logs-show.h"
47 #include "journal-internal.h"
48 #include "journal-def.h"
49 #include "journal-verify.h"
50 #include "journal-authenticate.h"
51 #include "journal-qrcode.h"
53 #include "unit-name.h"
56 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
58 static OutputMode arg_output = OUTPUT_SHORT;
59 static bool arg_follow = false;
60 static bool arg_full = false;
61 static bool arg_all = false;
62 static bool arg_no_pager = false;
63 static int arg_lines = -1;
64 static bool arg_no_tail = false;
65 static bool arg_quiet = false;
66 static bool arg_merge = false;
67 static bool arg_this_boot = false;
68 static const char *arg_cursor = NULL;
69 static const char *arg_directory = NULL;
70 static int arg_priorities = 0xFF;
71 static const char *arg_verify_key = NULL;
73 static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
75 static usec_t arg_since, arg_until;
76 static bool arg_since_set = false, arg_until_set = false;
77 static const char *arg_unit = NULL;
78 static const char *arg_field = NULL;
79 static bool arg_catalog = false;
90 } arg_action = ACTION_SHOW;
92 static int help(void) {
94 printf("%s [OPTIONS...] [MATCHES...]\n\n"
95 "Query the journal.\n\n"
97 " --since=DATE Start showing entries newer or of the specified date\n"
98 " --until=DATE Stop showing entries older or of the specified date\n"
99 " -c --cursor=CURSOR Start showing entries from specified cursor\n"
100 " -b --this-boot Show data only from current boot\n"
101 " -u --unit=UNIT Show data only from the specified unit\n"
102 " -p --priority=RANGE Show only messages within the specified priority range\n"
103 " -f --follow Follow journal\n"
104 " -n --lines[=INTEGER] Number of journal entries to show\n"
105 " --no-tail Show all lines, even in follow mode\n"
106 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
107 " verbose, export, json, json-pretty, json-sse, cat)\n"
108 " -x --catalog Add message explanations where available\n"
109 " --full Do not ellipsize fields\n"
110 " -a --all Show all fields, including long and unprintable\n"
111 " -q --quiet Don't show privilege warning\n"
112 " --no-pager Do not pipe output into a pager\n"
113 " -m --merge Show entries from all available journals\n"
114 " -D --directory=PATH Show journal files from directory\n"
116 " --interval=TIME Time interval for changing the FSS sealing key\n"
117 " --verify-key=KEY Specify FSS verification key\n"
120 " -h --help Show this help\n"
121 " --version Show package version\n"
122 " --new-id128 Generate a new 128 Bit ID\n"
123 " --header Show journal header information\n"
124 " --disk-usage Show total disk usage\n"
125 " -F --field=FIELD List all values a certain field takes\n"
126 " --list-catalog Show message IDs of all entries in the message catalog\n"
127 " --update-catalog Update the message catalog database\n"
129 " --setup-keys Generate new FSS key pair\n"
130 " --verify Verify journal file consistency\n"
132 , program_invocation_short_name);
137 static int parse_argv(int argc, char *argv[]) {
157 static const struct option options[] = {
158 { "help", no_argument, NULL, 'h' },
159 { "version" , no_argument, NULL, ARG_VERSION },
160 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
161 { "follow", no_argument, NULL, 'f' },
162 { "output", required_argument, NULL, 'o' },
163 { "all", no_argument, NULL, 'a' },
164 { "full", no_argument, NULL, ARG_FULL },
165 { "lines", optional_argument, NULL, 'n' },
166 { "no-tail", no_argument, NULL, ARG_NO_TAIL },
167 { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
168 { "quiet", no_argument, NULL, 'q' },
169 { "merge", no_argument, NULL, 'm' },
170 { "this-boot", no_argument, NULL, 'b' },
171 { "directory", required_argument, NULL, 'D' },
172 { "header", no_argument, NULL, ARG_HEADER },
173 { "priority", required_argument, NULL, 'p' },
174 { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
175 { "interval", required_argument, NULL, ARG_INTERVAL },
176 { "verify", no_argument, NULL, ARG_VERIFY },
177 { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
178 { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
179 { "cursor", required_argument, NULL, 'c' },
180 { "since", required_argument, NULL, ARG_SINCE },
181 { "until", required_argument, NULL, ARG_UNTIL },
182 { "unit", required_argument, NULL, 'u' },
183 { "field", required_argument, NULL, 'F' },
184 { "catalog", no_argument, NULL, 'x' },
185 { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG },
186 { "update-catalog",no_argument, NULL, ARG_UPDATE_CATALOG },
195 while ((c = getopt_long(argc, argv, "hfo:an::qmbD:p:c:u:F:x", options, NULL)) >= 0) {
204 puts(PACKAGE_STRING);
205 puts(SYSTEMD_FEATURES);
217 arg_output = output_mode_from_string(optarg);
218 if (arg_output < 0) {
219 log_error("Unknown output format '%s'.", optarg);
223 if (arg_output == OUTPUT_EXPORT ||
224 arg_output == OUTPUT_JSON ||
225 arg_output == OUTPUT_JSON_PRETTY ||
226 arg_output == OUTPUT_JSON_SSE ||
227 arg_output == OUTPUT_CAT)
242 r = safe_atoi(optarg, &arg_lines);
243 if (r < 0 || arg_lines < 0) {
244 log_error("Failed to parse lines '%s'", optarg);
250 /* Hmm, no argument? Maybe the next
251 * word on the command line is
252 * supposed to be the argument? Let's
253 * see if there is one, and is
254 * parsable as a positive
258 safe_atoi(argv[optind], &n) >= 0 &&
274 arg_action = ACTION_NEW_ID128;
286 arg_this_boot = true;
290 arg_directory = optarg;
298 arg_action = ACTION_PRINT_HEADER;
302 arg_action = ACTION_VERIFY;
306 arg_action = ACTION_DISK_USAGE;
311 arg_action = ACTION_SETUP_KEYS;
316 arg_action = ACTION_VERIFY;
317 arg_verify_key = optarg;
322 r = parse_usec(optarg, &arg_interval);
323 if (r < 0 || arg_interval <= 0) {
324 log_error("Failed to parse sealing key change interval: %s", optarg);
332 log_error("Forward-secure sealing not available.");
339 dots = strstr(optarg, "..");
345 a = strndup(optarg, dots - optarg);
349 from = log_level_from_string(a);
350 to = log_level_from_string(dots + 2);
353 if (from < 0 || to < 0) {
354 log_error("Failed to parse log level range %s", optarg);
361 for (i = from; i <= to; i++)
362 arg_priorities |= 1 << i;
364 for (i = to; i <= from; i++)
365 arg_priorities |= 1 << i;
371 p = log_level_from_string(optarg);
373 log_error("Unknown log level %s", optarg);
379 for (i = 0; i <= p; i++)
380 arg_priorities |= 1 << i;
387 r = parse_timestamp(optarg, &arg_since);
389 log_error("Failed to parse timestamp: %s", optarg);
392 arg_since_set = true;
396 r = parse_timestamp(optarg, &arg_until);
398 log_error("Failed to parse timestamp: %s", optarg);
401 arg_until_set = true;
419 case ARG_LIST_CATALOG:
420 arg_action = ACTION_LIST_CATALOG;
423 case ARG_UPDATE_CATALOG:
424 arg_action = ACTION_UPDATE_CATALOG;
428 log_error("Unknown option code %c", c);
433 if (arg_follow && !arg_no_tail && arg_lines < 0)
436 if (arg_since_set && arg_until_set && arg_since > arg_until) {
437 log_error("--since= must be before --until=.");
441 if (arg_cursor && arg_since_set) {
442 log_error("Please specify either --since= or --cursor=, not both.");
449 static int generate_new_id128(void) {
454 r = sd_id128_randomize(&id);
456 log_error("Failed to generate ID: %s", strerror(-r));
460 printf("As string:\n"
461 SD_ID128_FORMAT_STR "\n\n"
463 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
465 "#define MESSAGE_XYZ SD_ID128_MAKE(",
466 SD_ID128_FORMAT_VAL(id),
467 SD_ID128_FORMAT_VAL(id));
468 for (i = 0; i < 16; i++)
469 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
470 fputs(")\n\n", stdout);
472 printf("As Python constant:\n"
474 ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
475 SD_ID128_FORMAT_VAL(id));
480 static int add_matches(sd_journal *j, char **args) {
486 STRV_FOREACH(i, args) {
489 r = sd_journal_add_disjunction(j);
490 else if (path_is_absolute(*i)) {
495 p = canonicalize_file_name(*i);
498 if (stat(path, &st) < 0) {
500 log_error("Couldn't stat file: %m");
504 if (S_ISREG(st.st_mode) && (0111 & st.st_mode))
505 t = strappend("_EXE=", path);
506 else if (S_ISCHR(st.st_mode))
507 asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
508 else if (S_ISBLK(st.st_mode))
509 asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
512 log_error("File is not a device node, regular file or is not executable: %s", *i);
521 r = sd_journal_add_match(j, t, 0);
524 r = sd_journal_add_match(j, *i, 0);
527 log_error("Failed to add match '%s': %s", *i, strerror(-r));
535 static int add_this_boot(sd_journal *j) {
536 char match[9+32+1] = "_BOOT_ID=";
545 r = sd_id128_get_boot(&boot_id);
547 log_error("Failed to get boot id: %s", strerror(-r));
551 sd_id128_to_string(boot_id, match + 9);
552 r = sd_journal_add_match(j, match, strlen(match));
554 log_error("Failed to add match: %s", strerror(-r));
561 static int add_unit(sd_journal *j) {
562 _cleanup_free_ char *m = NULL, *u = NULL;
567 if (isempty(arg_unit))
570 u = unit_name_mangle(arg_unit);
574 m = strappend("_SYSTEMD_UNIT=", u);
578 r = sd_journal_add_match(j, m, strlen(m));
580 log_error("Failed to add match: %s", strerror(-r));
587 static int add_priorities(sd_journal *j) {
588 char match[] = "PRIORITY=0";
593 if (arg_priorities == 0xFF)
596 for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
597 if (arg_priorities & (1 << i)) {
598 match[sizeof(match)-2] = '0' + i;
600 r = sd_journal_add_match(j, match, strlen(match));
602 log_error("Failed to add match: %s", strerror(-r));
610 static int setup_keys(void) {
612 size_t mpk_size, seed_size, state_size, i;
613 uint8_t *mpk, *seed, *state;
615 int fd = -1, r, attr = 0;
616 sd_id128_t machine, boot;
617 char *p = NULL, *k = NULL;
621 r = sd_id128_get_machine(&machine);
623 log_error("Failed to get machine ID: %s", strerror(-r));
627 r = sd_id128_get_boot(&boot);
629 log_error("Failed to get boot ID: %s", strerror(-r));
633 if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
634 SD_ID128_FORMAT_VAL(machine)) < 0)
637 if (access(p, F_OK) >= 0) {
638 log_error("Sealing key file %s exists already.", p);
643 if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
644 SD_ID128_FORMAT_VAL(machine)) < 0) {
649 mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
650 mpk = alloca(mpk_size);
652 seed_size = FSPRG_RECOMMENDED_SEEDLEN;
653 seed = alloca(seed_size);
655 state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
656 state = alloca(state_size);
658 fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
660 log_error("Failed to open /dev/random: %m");
665 log_info("Generating seed...");
666 l = loop_read(fd, seed, seed_size, true);
667 if (l < 0 || (size_t) l != seed_size) {
668 log_error("Failed to read random seed: %s", strerror(EIO));
673 log_info("Generating key pair...");
674 FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
676 log_info("Generating sealing key...");
677 FSPRG_GenState0(state, mpk, seed, seed_size);
679 assert(arg_interval > 0);
681 n = now(CLOCK_REALTIME);
684 close_nointr_nofail(fd);
685 fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
687 log_error("Failed to open %s: %m", k);
692 /* Enable secure remove, exclusion from dump, synchronous
693 * writing and in-place updating */
694 if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
695 log_warning("FS_IOC_GETFLAGS failed: %m");
697 attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
699 if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
700 log_warning("FS_IOC_SETFLAGS failed: %m");
703 memcpy(h.signature, "KSHHRHLP", 8);
704 h.machine_id = machine;
706 h.header_size = htole64(sizeof(h));
707 h.start_usec = htole64(n * arg_interval);
708 h.interval_usec = htole64(arg_interval);
709 h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
710 h.fsprg_state_size = htole64(state_size);
712 l = loop_write(fd, &h, sizeof(h), false);
713 if (l < 0 || (size_t) l != sizeof(h)) {
714 log_error("Failed to write header: %s", strerror(EIO));
719 l = loop_write(fd, state, state_size, false);
720 if (l < 0 || (size_t) l != state_size) {
721 log_error("Failed to write state: %s", strerror(EIO));
726 if (link(k, p) < 0) {
727 log_error("Failed to link file: %m");
735 "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
736 "the following local file. This key file is automatically updated when the\n"
737 "sealing key is advanced. It should not be used on multiple hosts.\n"
741 "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
742 "at a safe location and should not be saved locally on disk.\n"
743 "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
746 for (i = 0; i < seed_size; i++) {
747 if (i > 0 && i % 3 == 0)
749 printf("%02x", ((uint8_t*) seed)[i]);
752 printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
755 char tsb[FORMAT_TIMESPAN_MAX], *hn;
758 ANSI_HIGHLIGHT_OFF "\n"
759 "The sealing key is automatically changed every %s.\n",
760 format_timespan(tsb, sizeof(tsb), arg_interval));
762 hn = gethostname_malloc();
765 hostname_cleanup(hn);
766 fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
768 fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
771 /* If this is not an UTF-8 system don't print any QR codes */
772 if (is_locale_utf8()) {
773 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
774 print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
784 close_nointr_nofail(fd);
795 log_error("Forward-secure sealing not available.");
800 static int verify(sd_journal *j) {
807 log_show_color(true);
809 HASHMAP_FOREACH(f, j->files, i) {
811 usec_t first, validated, last;
814 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
815 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
818 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
820 /* If the key was invalid give up right-away. */
823 log_warning("FAIL: %s (%s)", f->path, strerror(-k));
826 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
827 log_info("PASS: %s", f->path);
829 if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
831 log_info("=> Validated from %s to %s, final %s entries not sealed.",
832 format_timestamp(a, sizeof(a), first),
833 format_timestamp(b, sizeof(b), validated),
834 format_timespan(c, sizeof(c), last > validated ? last - validated : 0));
836 log_info("=> No sealing yet, %s of entries not sealed.",
837 format_timespan(c, sizeof(c), last - first));
839 log_info("=> No sealing yet, no entries in file.");
847 static int access_check(void) {
850 if (access("/var/log/journal", F_OK) < 0 && geteuid() != 0 && in_group("adm") <= 0) {
851 log_error("Unprivileged users can't see messages unless persistent log storage is enabled. Users in the group 'adm' can always see messages.");
855 if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0)
856 log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this notice off.");
858 if (geteuid() != 0 && in_group("adm") <= 0) {
859 log_error("No access to messages. Only users in the group 'adm' can see messages.");
867 int main(int argc, char *argv[]) {
869 sd_journal *j = NULL;
870 bool need_seek = false;
871 sd_id128_t previous_boot_id;
872 bool previous_boot_id_valid = false, first_line = true;
875 setlocale(LC_ALL, "");
876 log_parse_environment();
879 r = parse_argv(argc, argv);
883 signal(SIGWINCH, columns_lines_cache_reset);
885 if (arg_action == ACTION_NEW_ID128) {
886 r = generate_new_id128();
890 if (arg_action == ACTION_SETUP_KEYS) {
895 if (arg_action == ACTION_LIST_CATALOG) {
896 r = catalog_list(stdout);
898 log_error("Failed to list catalog: %s", strerror(-r));
902 if (arg_action == ACTION_UPDATE_CATALOG) {
903 r = catalog_update();
912 r = sd_journal_open_directory(&j, arg_directory, 0);
914 r = sd_journal_open(&j, arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY);
916 log_error("Failed to open journal: %s", strerror(-r));
920 if (arg_action == ACTION_VERIFY) {
925 if (arg_action == ACTION_PRINT_HEADER) {
926 journal_print_header(j);
931 if (arg_action == ACTION_DISK_USAGE) {
933 char sbytes[FORMAT_BYTES_MAX];
935 r = sd_journal_get_usage(j, &bytes);
939 printf("Journals take up %s on disk.\n", format_bytes(sbytes, sizeof(sbytes), bytes));
944 r = add_this_boot(j);
952 r = add_matches(j, argv + optind);
956 r = add_priorities(j);
960 /* Opening the fd now means the first sd_journal_wait() will actually wait */
961 r = sd_journal_get_fd(j);
969 r = sd_journal_query_unique(j, arg_field);
971 log_error("Failed to query unique data objects: %s", strerror(-r));
975 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
978 if (arg_lines >= 0 && n_shown >= arg_lines)
981 eq = memchr(data, '=', size);
983 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
985 printf("%.*s\n", (int) size, (const char*) data);
995 r = sd_journal_seek_cursor(j, arg_cursor);
997 log_error("Failed to seek to cursor: %s", strerror(-r));
1001 r = sd_journal_next(j);
1003 } else if (arg_since_set) {
1004 r = sd_journal_seek_realtime_usec(j, arg_since);
1006 log_error("Failed to seek to date: %s", strerror(-r));
1009 r = sd_journal_next(j);
1011 } else if (arg_lines >= 0) {
1012 r = sd_journal_seek_tail(j);
1014 log_error("Failed to seek to tail: %s", strerror(-r));
1018 r = sd_journal_previous_skip(j, arg_lines);
1021 r = sd_journal_seek_head(j);
1023 log_error("Failed to seek to head: %s", strerror(-r));
1027 r = sd_journal_next(j);
1031 log_error("Failed to iterate through journal: %s", strerror(-r));
1035 if (!arg_no_pager && !arg_follow)
1040 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1042 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1044 log_error("Failed to get cutoff: %s", strerror(-r));
1050 printf("-- Logs begin at %s. --\n",
1051 format_timestamp(start_buf, sizeof(start_buf), start));
1053 printf("-- Logs begin at %s, end at %s. --\n",
1054 format_timestamp(start_buf, sizeof(start_buf), start),
1055 format_timestamp(end_buf, sizeof(end_buf), end));
1060 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1064 r = sd_journal_next(j);
1066 log_error("Failed to iterate through journal: %s", strerror(-r));
1074 if (arg_until_set) {
1077 r = sd_journal_get_realtime_usec(j, &usec);
1079 log_error("Failed to determine timestamp: %s", strerror(-r));
1082 if (usec > arg_until)
1089 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1091 if (previous_boot_id_valid &&
1092 !sd_id128_equal(boot_id, previous_boot_id))
1093 printf(ANSI_HIGHLIGHT_ON "-- Reboot --" ANSI_HIGHLIGHT_OFF "\n");
1095 previous_boot_id = boot_id;
1096 previous_boot_id_valid = true;
1101 arg_all * OUTPUT_SHOW_ALL |
1102 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
1103 on_tty() * OUTPUT_COLOR |
1104 arg_catalog * OUTPUT_CATALOG;
1106 r = output_journal(stdout, j, arg_output, 0, flags);
1107 if (r < 0 || ferror(stdout))
1117 r = sd_journal_wait(j, (uint64_t) -1);
1119 log_error("Couldn't wait for journal event: %s", strerror(-r));
1128 sd_journal_close(j);
1132 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;