chiark / gitweb /
systemctl: limit logs in status to current boot
[elogind.git] / src / journal / journalctl.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2011 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <locale.h>
23 #include <fcntl.h>
24 #include <errno.h>
25 #include <stddef.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <time.h>
31 #include <getopt.h>
32 #include <signal.h>
33 #include <sys/stat.h>
34 #include <sys/ioctl.h>
35 #include <linux/fs.h>
36
37 #ifdef HAVE_ACL
38 #include <sys/acl.h>
39 #include "acl-util.h"
40 #endif
41
42 #include <systemd/sd-journal.h>
43
44 #include "log.h"
45 #include "logs-show.h"
46 #include "util.h"
47 #include "path-util.h"
48 #include "build.h"
49 #include "pager.h"
50 #include "logs-show.h"
51 #include "strv.h"
52 #include "journal-internal.h"
53 #include "journal-def.h"
54 #include "journal-verify.h"
55 #include "journal-authenticate.h"
56 #include "journal-qrcode.h"
57 #include "fsprg.h"
58 #include "unit-name.h"
59 #include "catalog.h"
60
61 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
62
63 static OutputMode arg_output = OUTPUT_SHORT;
64 static bool arg_pager_end = false;
65 static bool arg_follow = false;
66 static bool arg_full = false;
67 static bool arg_all = false;
68 static bool arg_no_pager = false;
69 static int arg_lines = -1;
70 static bool arg_no_tail = false;
71 static bool arg_quiet = false;
72 static bool arg_merge = false;
73 static bool arg_this_boot = false;
74 static bool arg_dmesg = false;
75 static const char *arg_cursor = NULL;
76 static const char *arg_directory = NULL;
77 static int arg_priorities = 0xFF;
78 static const char *arg_verify_key = NULL;
79 #ifdef HAVE_GCRYPT
80 static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
81 #endif
82 static usec_t arg_since, arg_until;
83 static bool arg_since_set = false, arg_until_set = false;
84 static char **arg_system_units = NULL;
85 static char **arg_user_units = NULL;
86 static const char *arg_field = NULL;
87 static bool arg_catalog = false;
88 static bool arg_reverse = false;
89 static const char *arg_root = NULL;
90
91 static enum {
92         ACTION_SHOW,
93         ACTION_NEW_ID128,
94         ACTION_PRINT_HEADER,
95         ACTION_SETUP_KEYS,
96         ACTION_VERIFY,
97         ACTION_DISK_USAGE,
98         ACTION_LIST_CATALOG,
99         ACTION_DUMP_CATALOG,
100         ACTION_UPDATE_CATALOG
101 } arg_action = ACTION_SHOW;
102
103 static int help(void) {
104
105         printf("%s [OPTIONS...] [MATCHES...]\n\n"
106                "Query the journal.\n\n"
107                "Flags:\n"
108                "     --since=DATE        Start showing entries newer or of the specified date\n"
109                "     --until=DATE        Stop showing entries older or of the specified date\n"
110                "  -c --cursor=CURSOR     Start showing entries from specified cursor\n"
111                "  -b --this-boot         Show data only from current boot\n"
112                "  -k --dmesg             Show kmsg log from current boot\n"
113                "  -u --unit=UNIT         Show data only from the specified unit\n"
114                "     --user-unit=UNIT    Show data only from the specified user session unit\n"
115                "  -p --priority=RANGE    Show only messages within the specified priority range\n"
116                "  -e --pager-end         Immediately jump to end of the journal in the pager\n"
117                "  -f --follow            Follow journal\n"
118                "  -n --lines[=INTEGER]   Number of journal entries to show\n"
119                "     --no-tail           Show all lines, even in follow mode\n"
120                "  -r --reverse           Show the newest entries first\n"
121                "  -o --output=STRING     Change journal output mode (short, short-monotonic,\n"
122                "                         verbose, export, json, json-pretty, json-sse, cat)\n"
123                "  -x --catalog           Add message explanations where available\n"
124                "     --full              Do not ellipsize fields\n"
125                "  -a --all               Show all fields, including long and unprintable\n"
126                "  -q --quiet             Don't show privilege warning\n"
127                "     --no-pager          Do not pipe output into a pager\n"
128                "  -m --merge             Show entries from all available journals\n"
129                "  -D --directory=PATH    Show journal files from directory\n"
130                "     --root=ROOT         Operate on catalog files underneath the root ROOT\n"
131 #ifdef HAVE_GCRYPT
132                "     --interval=TIME     Time interval for changing the FSS sealing key\n"
133                "     --verify-key=KEY    Specify FSS verification key\n"
134 #endif
135                "\nCommands:\n"
136                "  -h --help              Show this help\n"
137                "     --version           Show package version\n"
138                "     --new-id128         Generate a new 128 Bit ID\n"
139                "     --header            Show journal header information\n"
140                "     --disk-usage        Show total disk usage\n"
141                "  -F --field=FIELD       List all values a certain field takes\n"
142                "     --list-catalog      Show message IDs of all entries in the message catalog\n"
143                "     --dump-catalog      Show entries in the message catalog\n"
144                "     --update-catalog    Update the message catalog database\n"
145 #ifdef HAVE_GCRYPT
146                "     --setup-keys        Generate new FSS key pair\n"
147                "     --verify            Verify journal file consistency\n"
148 #endif
149                , program_invocation_short_name);
150
151         return 0;
152 }
153
154 static int parse_argv(int argc, char *argv[]) {
155
156         enum {
157                 ARG_VERSION = 0x100,
158                 ARG_NO_PAGER,
159                 ARG_NO_TAIL,
160                 ARG_NEW_ID128,
161                 ARG_ROOT,
162                 ARG_HEADER,
163                 ARG_FULL,
164                 ARG_SETUP_KEYS,
165                 ARG_INTERVAL,
166                 ARG_VERIFY,
167                 ARG_VERIFY_KEY,
168                 ARG_DISK_USAGE,
169                 ARG_SINCE,
170                 ARG_UNTIL,
171                 ARG_USER_UNIT,
172                 ARG_LIST_CATALOG,
173                 ARG_DUMP_CATALOG,
174                 ARG_UPDATE_CATALOG
175         };
176
177         static const struct option options[] = {
178                 { "help",         no_argument,       NULL, 'h'              },
179                 { "version" ,     no_argument,       NULL, ARG_VERSION      },
180                 { "no-pager",     no_argument,       NULL, ARG_NO_PAGER     },
181                 { "pager-end",    no_argument,       NULL, 'e'              },
182                 { "follow",       no_argument,       NULL, 'f'              },
183                 { "output",       required_argument, NULL, 'o'              },
184                 { "all",          no_argument,       NULL, 'a'              },
185                 { "full",         no_argument,       NULL, ARG_FULL         },
186                 { "lines",        optional_argument, NULL, 'n'              },
187                 { "no-tail",      no_argument,       NULL, ARG_NO_TAIL      },
188                 { "new-id128",    no_argument,       NULL, ARG_NEW_ID128    },
189                 { "quiet",        no_argument,       NULL, 'q'              },
190                 { "merge",        no_argument,       NULL, 'm'              },
191                 { "this-boot",    no_argument,       NULL, 'b'              },
192                 { "dmesg",        no_argument,       NULL, 'k'              },
193                 { "directory",    required_argument, NULL, 'D'              },
194                 { "root",         required_argument, NULL, ARG_ROOT         },
195                 { "header",       no_argument,       NULL, ARG_HEADER       },
196                 { "priority",     required_argument, NULL, 'p'              },
197                 { "setup-keys",   no_argument,       NULL, ARG_SETUP_KEYS   },
198                 { "interval",     required_argument, NULL, ARG_INTERVAL     },
199                 { "verify",       no_argument,       NULL, ARG_VERIFY       },
200                 { "verify-key",   required_argument, NULL, ARG_VERIFY_KEY   },
201                 { "disk-usage",   no_argument,       NULL, ARG_DISK_USAGE   },
202                 { "cursor",       required_argument, NULL, 'c'              },
203                 { "since",        required_argument, NULL, ARG_SINCE        },
204                 { "until",        required_argument, NULL, ARG_UNTIL        },
205                 { "unit",         required_argument, NULL, 'u'              },
206                 { "user-unit",    required_argument, NULL, ARG_USER_UNIT    },
207                 { "field",        required_argument, NULL, 'F'              },
208                 { "catalog",      no_argument,       NULL, 'x'              },
209                 { "list-catalog", no_argument,       NULL, ARG_LIST_CATALOG },
210                 { "dump-catalog", no_argument,       NULL, ARG_DUMP_CATALOG },
211                 { "update-catalog",no_argument,      NULL, ARG_UPDATE_CATALOG },
212                 { "reverse",      no_argument,       NULL, 'r'              },
213                 { NULL,           0,                 NULL, 0                }
214         };
215
216         int c, r;
217
218         assert(argc >= 0);
219         assert(argv);
220
221         while ((c = getopt_long(argc, argv, "hefo:an::qmbkD:p:c:u:F:xr", options, NULL)) >= 0) {
222
223                 switch (c) {
224
225                 case 'h':
226                         help();
227                         return 0;
228
229                 case ARG_VERSION:
230                         puts(PACKAGE_STRING);
231                         puts(SYSTEMD_FEATURES);
232                         return 0;
233
234                 case ARG_NO_PAGER:
235                         arg_no_pager = true;
236                         break;
237
238                 case 'e':
239                         arg_pager_end = true;
240
241                         if (arg_lines < 0)
242                                 arg_lines = 1000;
243
244                         break;
245
246                 case 'f':
247                         arg_follow = true;
248                         break;
249
250                 case 'o':
251                         arg_output = output_mode_from_string(optarg);
252                         if (arg_output < 0) {
253                                 log_error("Unknown output format '%s'.", optarg);
254                                 return -EINVAL;
255                         }
256
257                         if (arg_output == OUTPUT_EXPORT ||
258                             arg_output == OUTPUT_JSON ||
259                             arg_output == OUTPUT_JSON_PRETTY ||
260                             arg_output == OUTPUT_JSON_SSE ||
261                             arg_output == OUTPUT_CAT)
262                                 arg_quiet = true;
263
264                         break;
265
266                 case ARG_FULL:
267                         arg_full = true;
268                         break;
269
270                 case 'a':
271                         arg_all = true;
272                         break;
273
274                 case 'n':
275                         if (optarg) {
276                                 r = safe_atoi(optarg, &arg_lines);
277                                 if (r < 0 || arg_lines < 0) {
278                                         log_error("Failed to parse lines '%s'", optarg);
279                                         return -EINVAL;
280                                 }
281                         } else {
282                                 int n;
283
284                                 /* Hmm, no argument? Maybe the next
285                                  * word on the command line is
286                                  * supposed to be the argument? Let's
287                                  * see if there is one, and is
288                                  * parsable as a positive
289                                  * integer... */
290
291                                 if (optind < argc &&
292                                     safe_atoi(argv[optind], &n) >= 0 &&
293                                     n >= 0) {
294
295                                         arg_lines = n;
296                                         optind++;
297                                 } else
298                                         arg_lines = 10;
299                         }
300
301                         break;
302
303                 case ARG_NO_TAIL:
304                         arg_no_tail = true;
305                         break;
306
307                 case ARG_NEW_ID128:
308                         arg_action = ACTION_NEW_ID128;
309                         break;
310
311                 case 'q':
312                         arg_quiet = true;
313                         break;
314
315                 case 'm':
316                         arg_merge = true;
317                         break;
318
319                 case 'b':
320                         arg_this_boot = true;
321                         break;
322
323                 case 'k':
324                         arg_this_boot = arg_dmesg = true;
325                         break;
326
327                 case 'D':
328                         arg_directory = optarg;
329                         break;
330
331                 case ARG_ROOT:
332                         arg_root = optarg;
333                         break;
334
335                 case 'c':
336                         arg_cursor = optarg;
337                         break;
338
339                 case ARG_HEADER:
340                         arg_action = ACTION_PRINT_HEADER;
341                         break;
342
343                 case ARG_VERIFY:
344                         arg_action = ACTION_VERIFY;
345                         break;
346
347                 case ARG_DISK_USAGE:
348                         arg_action = ACTION_DISK_USAGE;
349                         break;
350
351 #ifdef HAVE_GCRYPT
352                 case ARG_SETUP_KEYS:
353                         arg_action = ACTION_SETUP_KEYS;
354                         break;
355
356
357                 case ARG_VERIFY_KEY:
358                         arg_action = ACTION_VERIFY;
359                         arg_verify_key = optarg;
360                         arg_merge = false;
361                         break;
362
363                 case ARG_INTERVAL:
364                         r = parse_sec(optarg, &arg_interval);
365                         if (r < 0 || arg_interval <= 0) {
366                                 log_error("Failed to parse sealing key change interval: %s", optarg);
367                                 return -EINVAL;
368                         }
369                         break;
370 #else
371                 case ARG_SETUP_KEYS:
372                 case ARG_VERIFY_KEY:
373                 case ARG_INTERVAL:
374                         log_error("Forward-secure sealing not available.");
375                         return -ENOTSUP;
376 #endif
377
378                 case 'p': {
379                         const char *dots;
380
381                         dots = strstr(optarg, "..");
382                         if (dots) {
383                                 char *a;
384                                 int from, to, i;
385
386                                 /* a range */
387                                 a = strndup(optarg, dots - optarg);
388                                 if (!a)
389                                         return log_oom();
390
391                                 from = log_level_from_string(a);
392                                 to = log_level_from_string(dots + 2);
393                                 free(a);
394
395                                 if (from < 0 || to < 0) {
396                                         log_error("Failed to parse log level range %s", optarg);
397                                         return -EINVAL;
398                                 }
399
400                                 arg_priorities = 0;
401
402                                 if (from < to) {
403                                         for (i = from; i <= to; i++)
404                                                 arg_priorities |= 1 << i;
405                                 } else {
406                                         for (i = to; i <= from; i++)
407                                                 arg_priorities |= 1 << i;
408                                 }
409
410                         } else {
411                                 int p, i;
412
413                                 p = log_level_from_string(optarg);
414                                 if (p < 0) {
415                                         log_error("Unknown log level %s", optarg);
416                                         return -EINVAL;
417                                 }
418
419                                 arg_priorities = 0;
420
421                                 for (i = 0; i <= p; i++)
422                                         arg_priorities |= 1 << i;
423                         }
424
425                         break;
426                 }
427
428                 case ARG_SINCE:
429                         r = parse_timestamp(optarg, &arg_since);
430                         if (r < 0) {
431                                 log_error("Failed to parse timestamp: %s", optarg);
432                                 return -EINVAL;
433                         }
434                         arg_since_set = true;
435                         break;
436
437                 case ARG_UNTIL:
438                         r = parse_timestamp(optarg, &arg_until);
439                         if (r < 0) {
440                                 log_error("Failed to parse timestamp: %s", optarg);
441                                 return -EINVAL;
442                         }
443                         arg_until_set = true;
444                         break;
445
446                 case 'u':
447                         r = strv_extend(&arg_system_units, optarg);
448                         if (r < 0)
449                                 return log_oom();
450                         break;
451
452                 case ARG_USER_UNIT:
453                         r = strv_extend(&arg_user_units, optarg);
454                         if (r < 0)
455                                 return log_oom();
456                         break;
457
458                 case '?':
459                         return -EINVAL;
460
461                 case 'F':
462                         arg_field = optarg;
463                         break;
464
465                 case 'x':
466                         arg_catalog = true;
467                         break;
468
469                 case ARG_LIST_CATALOG:
470                         arg_action = ACTION_LIST_CATALOG;
471                         break;
472
473                 case ARG_DUMP_CATALOG:
474                         arg_action = ACTION_DUMP_CATALOG;
475                         break;
476
477                 case ARG_UPDATE_CATALOG:
478                         arg_action = ACTION_UPDATE_CATALOG;
479                         break;
480
481                 case 'r':
482                         arg_reverse = true;
483                         break;
484
485                 default:
486                         log_error("Unknown option code %c", c);
487                         return -EINVAL;
488                 }
489         }
490
491         if (arg_follow && !arg_no_tail && arg_lines < 0)
492                 arg_lines = 10;
493
494         if (arg_since_set && arg_until_set && arg_since > arg_until) {
495                 log_error("--since= must be before --until=.");
496                 return -EINVAL;
497         }
498
499         if (arg_cursor && arg_since_set) {
500                 log_error("Please specify either --since= or --cursor=, not both.");
501                 return -EINVAL;
502         }
503
504         if (arg_follow && arg_reverse) {
505                 log_error("Please specify either --reverse= or --follow=, not both.");
506                 return -EINVAL;
507         }
508
509         return 1;
510 }
511
512 static int generate_new_id128(void) {
513         sd_id128_t id;
514         int r;
515         unsigned i;
516
517         r = sd_id128_randomize(&id);
518         if (r < 0) {
519                 log_error("Failed to generate ID: %s", strerror(-r));
520                 return r;
521         }
522
523         printf("As string:\n"
524                SD_ID128_FORMAT_STR "\n\n"
525                "As UUID:\n"
526                "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
527                "As macro:\n"
528                "#define MESSAGE_XYZ SD_ID128_MAKE(",
529                SD_ID128_FORMAT_VAL(id),
530                SD_ID128_FORMAT_VAL(id));
531         for (i = 0; i < 16; i++)
532                 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
533         fputs(")\n\n", stdout);
534
535         printf("As Python constant:\n"
536                ">>> import uuid\n"
537                ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
538                SD_ID128_FORMAT_VAL(id));
539
540         return 0;
541 }
542
543 static int add_matches(sd_journal *j, char **args) {
544         char **i;
545
546         assert(j);
547
548         STRV_FOREACH(i, args) {
549                 int r;
550
551                 if (streq(*i, "+"))
552                         r = sd_journal_add_disjunction(j);
553                 else if (path_is_absolute(*i)) {
554                         _cleanup_free_ char *p, *t = NULL;
555                         const char *path;
556                         struct stat st;
557
558                         p = canonicalize_file_name(*i);
559                         path = p ? p : *i;
560
561                         if (stat(path, &st) < 0)  {
562                                 log_error("Couldn't stat file: %m");
563                                 return -errno;
564                         }
565
566                         if (S_ISREG(st.st_mode) && (0111 & st.st_mode))
567                                 t = strappend("_EXE=", path);
568                         else if (S_ISCHR(st.st_mode))
569                                 asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
570                         else if (S_ISBLK(st.st_mode))
571                                 asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
572                         else {
573                                 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
574                                 return -EINVAL;
575                         }
576
577                         if (!t)
578                                 return log_oom();
579
580                         r = sd_journal_add_match(j, t, 0);
581                 } else
582                         r = sd_journal_add_match(j, *i, 0);
583
584                 if (r < 0) {
585                         log_error("Failed to add match '%s': %s", *i, strerror(-r));
586                         return r;
587                 }
588         }
589
590         return 0;
591 }
592
593 static int add_this_boot(sd_journal *j) {
594         if (!arg_this_boot)
595                 return 0;
596
597         return add_match_this_boot(j);
598 }
599
600 static int add_dmesg(sd_journal *j) {
601         int r;
602         assert(j);
603
604         if (!arg_dmesg)
605                 return 0;
606
607         r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
608         if (r < 0) {
609                 log_error("Failed to add match: %s", strerror(-r));
610                 return r;
611         }
612
613         r = sd_journal_add_conjunction(j);
614         if (r < 0)
615                 return r;
616
617         return 0;
618 }
619
620 static int add_units(sd_journal *j) {
621         _cleanup_free_ char *u = NULL;
622         int r;
623         char **i;
624
625         assert(j);
626
627         STRV_FOREACH(i, arg_system_units) {
628                 u = unit_name_mangle(*i);
629                 if (!u)
630                         return log_oom();
631                 r = add_matches_for_unit(j, u);
632                 if (r < 0)
633                         return r;
634                 r = sd_journal_add_disjunction(j);
635                 if (r < 0)
636                         return r;
637         }
638
639         STRV_FOREACH(i, arg_user_units) {
640                 u = unit_name_mangle(*i);
641                 if (!u)
642                         return log_oom();
643
644                 r = add_matches_for_user_unit(j, u, getuid());
645                 if (r < 0)
646                         return r;
647
648                 r = sd_journal_add_disjunction(j);
649                 if (r < 0)
650                         return r;
651
652         }
653
654         r = sd_journal_add_conjunction(j);
655         if (r < 0)
656                 return r;
657
658         return 0;
659 }
660
661 static int add_priorities(sd_journal *j) {
662         char match[] = "PRIORITY=0";
663         int i, r;
664         assert(j);
665
666         if (arg_priorities == 0xFF)
667                 return 0;
668
669         for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
670                 if (arg_priorities & (1 << i)) {
671                         match[sizeof(match)-2] = '0' + i;
672
673                         r = sd_journal_add_match(j, match, strlen(match));
674                         if (r < 0) {
675                                 log_error("Failed to add match: %s", strerror(-r));
676                                 return r;
677                         }
678                 }
679
680         r = sd_journal_add_conjunction(j);
681         if (r < 0)
682                 return r;
683
684         return 0;
685 }
686
687 static int setup_keys(void) {
688 #ifdef HAVE_GCRYPT
689         size_t mpk_size, seed_size, state_size, i;
690         uint8_t *mpk, *seed, *state;
691         ssize_t l;
692         int fd = -1, r, attr = 0;
693         sd_id128_t machine, boot;
694         char *p = NULL, *k = NULL;
695         struct FSSHeader h;
696         uint64_t n;
697
698         r = sd_id128_get_machine(&machine);
699         if (r < 0) {
700                 log_error("Failed to get machine ID: %s", strerror(-r));
701                 return r;
702         }
703
704         r = sd_id128_get_boot(&boot);
705         if (r < 0) {
706                 log_error("Failed to get boot ID: %s", strerror(-r));
707                 return r;
708         }
709
710         if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
711                      SD_ID128_FORMAT_VAL(machine)) < 0)
712                 return log_oom();
713
714         if (access(p, F_OK) >= 0) {
715                 log_error("Sealing key file %s exists already.", p);
716                 r = -EEXIST;
717                 goto finish;
718         }
719
720         if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
721                      SD_ID128_FORMAT_VAL(machine)) < 0) {
722                 r = log_oom();
723                 goto finish;
724         }
725
726         mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
727         mpk = alloca(mpk_size);
728
729         seed_size = FSPRG_RECOMMENDED_SEEDLEN;
730         seed = alloca(seed_size);
731
732         state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
733         state = alloca(state_size);
734
735         fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
736         if (fd < 0) {
737                 log_error("Failed to open /dev/random: %m");
738                 r = -errno;
739                 goto finish;
740         }
741
742         log_info("Generating seed...");
743         l = loop_read(fd, seed, seed_size, true);
744         if (l < 0 || (size_t) l != seed_size) {
745                 log_error("Failed to read random seed: %s", strerror(EIO));
746                 r = -EIO;
747                 goto finish;
748         }
749
750         log_info("Generating key pair...");
751         FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
752
753         log_info("Generating sealing key...");
754         FSPRG_GenState0(state, mpk, seed, seed_size);
755
756         assert(arg_interval > 0);
757
758         n = now(CLOCK_REALTIME);
759         n /= arg_interval;
760
761         close_nointr_nofail(fd);
762         fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
763         if (fd < 0) {
764                 log_error("Failed to open %s: %m", k);
765                 r = -errno;
766                 goto finish;
767         }
768
769         /* Enable secure remove, exclusion from dump, synchronous
770          * writing and in-place updating */
771         if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
772                 log_warning("FS_IOC_GETFLAGS failed: %m");
773
774         attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
775
776         if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
777                 log_warning("FS_IOC_SETFLAGS failed: %m");
778
779         zero(h);
780         memcpy(h.signature, "KSHHRHLP", 8);
781         h.machine_id = machine;
782         h.boot_id = boot;
783         h.header_size = htole64(sizeof(h));
784         h.start_usec = htole64(n * arg_interval);
785         h.interval_usec = htole64(arg_interval);
786         h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
787         h.fsprg_state_size = htole64(state_size);
788
789         l = loop_write(fd, &h, sizeof(h), false);
790         if (l < 0 || (size_t) l != sizeof(h)) {
791                 log_error("Failed to write header: %s", strerror(EIO));
792                 r = -EIO;
793                 goto finish;
794         }
795
796         l = loop_write(fd, state, state_size, false);
797         if (l < 0 || (size_t) l != state_size) {
798                 log_error("Failed to write state: %s", strerror(EIO));
799                 r = -EIO;
800                 goto finish;
801         }
802
803         if (link(k, p) < 0) {
804                 log_error("Failed to link file: %m");
805                 r = -errno;
806                 goto finish;
807         }
808
809         if (on_tty()) {
810                 fprintf(stderr,
811                         "\n"
812                         "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
813                         "the following local file. This key file is automatically updated when the\n"
814                         "sealing key is advanced. It should not be used on multiple hosts.\n"
815                         "\n"
816                         "\t%s\n"
817                         "\n"
818                         "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
819                         "at a safe location and should not be saved locally on disk.\n"
820                         "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
821                 fflush(stderr);
822         }
823         for (i = 0; i < seed_size; i++) {
824                 if (i > 0 && i % 3 == 0)
825                         putchar('-');
826                 printf("%02x", ((uint8_t*) seed)[i]);
827         }
828
829         printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
830
831         if (on_tty()) {
832                 char tsb[FORMAT_TIMESPAN_MAX], *hn;
833
834                 fprintf(stderr,
835                         ANSI_HIGHLIGHT_OFF "\n"
836                         "The sealing key is automatically changed every %s.\n",
837                         format_timespan(tsb, sizeof(tsb), arg_interval, 0));
838
839                 hn = gethostname_malloc();
840
841                 if (hn) {
842                         hostname_cleanup(hn, false);
843                         fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
844                 } else
845                         fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
846
847 #ifdef HAVE_QRENCODE
848                 /* If this is not an UTF-8 system don't print any QR codes */
849                 if (is_locale_utf8()) {
850                         fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
851                         print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
852                 }
853 #endif
854                 free(hn);
855         }
856
857         r = 0;
858
859 finish:
860         if (fd >= 0)
861                 close_nointr_nofail(fd);
862
863         if (k) {
864                 unlink(k);
865                 free(k);
866         }
867
868         free(p);
869
870         return r;
871 #else
872         log_error("Forward-secure sealing not available.");
873         return -ENOTSUP;
874 #endif
875 }
876
877 static int verify(sd_journal *j) {
878         int r = 0;
879         Iterator i;
880         JournalFile *f;
881
882         assert(j);
883
884         log_show_color(true);
885
886         HASHMAP_FOREACH(f, j->files, i) {
887                 int k;
888                 usec_t first, validated, last;
889
890 #ifdef HAVE_GCRYPT
891                 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
892                         log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
893 #endif
894
895                 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
896                 if (k == -EINVAL) {
897                         /* If the key was invalid give up right-away. */
898                         return k;
899                 } else if (k < 0) {
900                         log_warning("FAIL: %s (%s)", f->path, strerror(-k));
901                         r = k;
902                 } else {
903                         char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
904                         log_info("PASS: %s", f->path);
905
906                         if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
907                                 if (validated > 0) {
908                                         log_info("=> Validated from %s to %s, final %s entries not sealed.",
909                                                  format_timestamp(a, sizeof(a), first),
910                                                  format_timestamp(b, sizeof(b), validated),
911                                                  format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
912                                 } else if (last > 0)
913                                         log_info("=> No sealing yet, %s of entries not sealed.",
914                                                  format_timespan(c, sizeof(c), last - first, 0));
915                                 else
916                                         log_info("=> No sealing yet, no entries in file.");
917                         }
918                 }
919         }
920
921         return r;
922 }
923
924 #ifdef HAVE_ACL
925 static int access_check_var_log_journal(sd_journal *j) {
926         _cleanup_strv_free_ char **g = NULL;
927         bool have_access;
928         int r;
929
930         assert(j);
931
932         have_access = in_group("systemd-journal") > 0;
933
934         if (!have_access) {
935                 /* Let's enumerate all groups from the default ACL of
936                  * the directory, which generally should allow access
937                  * to most journal files too */
938                 r = search_acl_groups(&g, "/var/log/journal/", &have_access);
939                 if (r < 0)
940                         return r;
941         }
942
943         if (!have_access) {
944
945                 if (strv_isempty(g))
946                         log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
947                                    "      Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
948                                    "      turn off this notice.");
949                 else {
950                         _cleanup_free_ char *s = NULL;
951
952                         r = strv_extend(&g, "systemd-journal");
953                         if (r < 0)
954                                 return log_oom();
955
956                         strv_sort(g);
957                         strv_uniq(g);
958
959                         s = strv_join(g, "', '");
960                         if (!s)
961                                 return log_oom();
962
963                         log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
964                                    "      Users in the groups '%s' can see all messages.\n"
965                                    "      Pass -q to turn off this notice.", s);
966                 }
967         }
968
969         return 0;
970 }
971 #endif
972
973 static int access_check(sd_journal *j) {
974         Iterator it;
975         void *code;
976         int r = 0;
977
978         assert(j);
979
980         if (set_isempty(j->errors)) {
981                 if (hashmap_isempty(j->files))
982                         log_notice("No journal files were found.");
983                 return 0;
984         }
985
986         if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
987 #ifdef HAVE_ACL
988                 /* If /var/log/journal doesn't even exist,
989                  * unprivileged users have no access at all */
990                 if (access("/var/log/journal", F_OK) < 0 &&
991                     geteuid() != 0 &&
992                     in_group("systemd-journal") <= 0) {
993                         log_error("Unprivileged users cannot access messages, unless persistent log storage is\n"
994                                   "enabled. Users in the 'systemd-journal' group may always access messages.");
995                         return -EACCES;
996                 }
997
998                 /* If /var/log/journal exists, try to pring a nice
999                    notice if the user lacks access to it */
1000                 if (!arg_quiet && geteuid() != 0) {
1001                         r = access_check_var_log_journal(j);
1002                         if (r < 0)
1003                                 return r;
1004                 }
1005 #else
1006                 if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
1007                         log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
1008                                   "group may access messages.");
1009                         return -EACCES;
1010                 }
1011 #endif
1012
1013                 if (hashmap_isempty(j->files)) {
1014                         log_error("No journal files were opened due to insufficient permissions.");
1015                         r = -EACCES;
1016                 }
1017         }
1018
1019         SET_FOREACH(code, j->errors, it) {
1020                 int err;
1021
1022                 err = -PTR_TO_INT(code);
1023                 assert(err > 0);
1024
1025                 if (err != EACCES)
1026                         log_warning("Error was encountered while opening journal files: %s",
1027                                     strerror(err));
1028         }
1029
1030         return r;
1031 }
1032
1033 int main(int argc, char *argv[]) {
1034         int r;
1035         _cleanup_journal_close_ sd_journal*j = NULL;
1036         bool need_seek = false;
1037         sd_id128_t previous_boot_id;
1038         bool previous_boot_id_valid = false, first_line = true;
1039         int n_shown = 0;
1040
1041         setlocale(LC_ALL, "");
1042         log_parse_environment();
1043         log_open();
1044
1045         r = parse_argv(argc, argv);
1046         if (r <= 0)
1047                 goto finish;
1048
1049         signal(SIGWINCH, columns_lines_cache_reset);
1050
1051         if (arg_action == ACTION_NEW_ID128) {
1052                 r = generate_new_id128();
1053                 goto finish;
1054         }
1055
1056         if (arg_action == ACTION_SETUP_KEYS) {
1057                 r = setup_keys();
1058                 goto finish;
1059         }
1060
1061         if (arg_action == ACTION_UPDATE_CATALOG ||
1062             arg_action == ACTION_LIST_CATALOG ||
1063             arg_action == ACTION_DUMP_CATALOG) {
1064
1065                 const char* database = CATALOG_DATABASE;
1066                 _cleanup_free_ char *copy = NULL;
1067                 if (arg_root) {
1068                         copy = strjoin(arg_root, "/", CATALOG_DATABASE, NULL);
1069                         if (!copy) {
1070                                 r = log_oom();
1071                                 goto finish;
1072                         }
1073                         path_kill_slashes(copy);
1074                         database = copy;
1075                 }
1076
1077                 if (arg_action == ACTION_UPDATE_CATALOG) {
1078                         r = catalog_update(database, arg_root, catalog_file_dirs);
1079                         if (r < 0)
1080                                 log_error("Failed to list catalog: %s", strerror(-r));
1081                 } else {
1082                         bool oneline = arg_action == ACTION_LIST_CATALOG;
1083
1084                         if (optind < argc)
1085                                 r = catalog_list_items(stdout, database,
1086                                                        oneline, argv + optind);
1087                         else
1088                                 r = catalog_list(stdout, database, oneline);
1089                         if (r < 0)
1090                                 log_error("Failed to list catalog: %s", strerror(-r));
1091                 }
1092
1093                 goto finish;
1094         }
1095
1096         if (arg_directory)
1097                 r = sd_journal_open_directory(&j, arg_directory, 0);
1098         else
1099                 r = sd_journal_open(&j, arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY);
1100         if (r < 0) {
1101                 log_error("Failed to open journal: %s", strerror(-r));
1102                 return EXIT_FAILURE;
1103         }
1104
1105         r = access_check(j);
1106         if (r < 0)
1107                 return EXIT_FAILURE;
1108
1109         if (arg_action == ACTION_VERIFY) {
1110                 r = verify(j);
1111                 goto finish;
1112         }
1113
1114         if (arg_action == ACTION_PRINT_HEADER) {
1115                 journal_print_header(j);
1116                 return EXIT_SUCCESS;
1117         }
1118
1119         if (arg_action == ACTION_DISK_USAGE) {
1120                 uint64_t bytes;
1121                 char sbytes[FORMAT_BYTES_MAX];
1122
1123                 r = sd_journal_get_usage(j, &bytes);
1124                 if (r < 0)
1125                         return EXIT_FAILURE;
1126
1127                 printf("Journals take up %s on disk.\n",
1128                        format_bytes(sbytes, sizeof(sbytes), bytes));
1129                 return EXIT_SUCCESS;
1130         }
1131
1132         r = add_this_boot(j);
1133         if (r < 0)
1134                 return EXIT_FAILURE;
1135
1136         r = add_dmesg(j);
1137         if (r < 0)
1138                 return EXIT_FAILURE;
1139
1140         r = add_units(j);
1141         strv_free(arg_system_units);
1142         strv_free(arg_user_units);
1143
1144         if (r < 0)
1145                 return EXIT_FAILURE;
1146
1147         r = add_priorities(j);
1148         if (r < 0)
1149                 return EXIT_FAILURE;
1150
1151         r = add_matches(j, argv + optind);
1152         if (r < 0)
1153                 return EXIT_FAILURE;
1154
1155         /* Opening the fd now means the first sd_journal_wait() will actually wait */
1156         r = sd_journal_get_fd(j);
1157         if (r < 0)
1158                 return EXIT_FAILURE;
1159
1160         if (arg_field) {
1161                 const void *data;
1162                 size_t size;
1163
1164                 r = sd_journal_set_data_threshold(j, 0);
1165                 if (r < 0) {
1166                         log_error("Failed to unset data size threshold");
1167                         return EXIT_FAILURE;
1168                 }
1169
1170                 r = sd_journal_query_unique(j, arg_field);
1171                 if (r < 0) {
1172                         log_error("Failed to query unique data objects: %s", strerror(-r));
1173                         return EXIT_FAILURE;
1174                 }
1175
1176                 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1177                         const void *eq;
1178
1179                         if (arg_lines >= 0 && n_shown >= arg_lines)
1180                                 break;
1181
1182                         eq = memchr(data, '=', size);
1183                         if (eq)
1184                                 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
1185                         else
1186                                 printf("%.*s\n", (int) size, (const char*) data);
1187
1188                         n_shown ++;
1189                 }
1190
1191                 return EXIT_SUCCESS;
1192         }
1193
1194         if (arg_cursor) {
1195                 r = sd_journal_seek_cursor(j, arg_cursor);
1196                 if (r < 0) {
1197                         log_error("Failed to seek to cursor: %s", strerror(-r));
1198                         return EXIT_FAILURE;
1199                 }
1200                 if (!arg_reverse)
1201                         r = sd_journal_next(j);
1202                 else
1203                         r = sd_journal_previous(j);
1204
1205         } else if (arg_since_set && !arg_reverse) {
1206                 r = sd_journal_seek_realtime_usec(j, arg_since);
1207                 if (r < 0) {
1208                         log_error("Failed to seek to date: %s", strerror(-r));
1209                         return EXIT_FAILURE;
1210                 }
1211                 r = sd_journal_next(j);
1212
1213         } else if (arg_until_set && arg_reverse) {
1214                 r = sd_journal_seek_realtime_usec(j, arg_until);
1215                 if (r < 0) {
1216                         log_error("Failed to seek to date: %s", strerror(-r));
1217                         return EXIT_FAILURE;
1218                 }
1219                 r = sd_journal_previous(j);
1220
1221         } else if (arg_lines >= 0) {
1222                 r = sd_journal_seek_tail(j);
1223                 if (r < 0) {
1224                         log_error("Failed to seek to tail: %s", strerror(-r));
1225                         return EXIT_FAILURE;
1226                 }
1227
1228                 r = sd_journal_previous_skip(j, arg_lines);
1229
1230         } else if (arg_reverse) {
1231                 r = sd_journal_seek_tail(j);
1232                 if (r < 0) {
1233                         log_error("Failed to seek to tail: %s", strerror(-r));
1234                         return EXIT_FAILURE;
1235                 }
1236
1237                 r = sd_journal_previous(j);
1238
1239         } else {
1240                 r = sd_journal_seek_head(j);
1241                 if (r < 0) {
1242                         log_error("Failed to seek to head: %s", strerror(-r));
1243                         return EXIT_FAILURE;
1244                 }
1245
1246                 r = sd_journal_next(j);
1247         }
1248
1249         if (r < 0) {
1250                 log_error("Failed to iterate through journal: %s", strerror(-r));
1251                 return EXIT_FAILURE;
1252         }
1253
1254         if (!arg_no_pager && !arg_follow)
1255                 pager_open(arg_pager_end);
1256
1257         if (!arg_quiet) {
1258                 usec_t start, end;
1259                 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1260
1261                 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1262                 if (r < 0) {
1263                         log_error("Failed to get cutoff: %s", strerror(-r));
1264                         goto finish;
1265                 }
1266
1267                 if (r > 0) {
1268                         if (arg_follow)
1269                                 printf("-- Logs begin at %s. --\n",
1270                                        format_timestamp(start_buf, sizeof(start_buf), start));
1271                         else
1272                                 printf("-- Logs begin at %s, end at %s. --\n",
1273                                        format_timestamp(start_buf, sizeof(start_buf), start),
1274                                        format_timestamp(end_buf, sizeof(end_buf), end));
1275                 }
1276         }
1277
1278         for (;;) {
1279                 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1280                         int flags;
1281
1282                         if (need_seek) {
1283                                 if (!arg_reverse)
1284                                         r = sd_journal_next(j);
1285                                 else
1286                                         r = sd_journal_previous(j);
1287                                 if (r < 0) {
1288                                         log_error("Failed to iterate through journal: %s", strerror(-r));
1289                                         goto finish;
1290                                 }
1291                         }
1292
1293                         if (r == 0)
1294                                 break;
1295
1296                         if (arg_until_set && !arg_reverse) {
1297                                 usec_t usec;
1298
1299                                 r = sd_journal_get_realtime_usec(j, &usec);
1300                                 if (r < 0) {
1301                                         log_error("Failed to determine timestamp: %s", strerror(-r));
1302                                         goto finish;
1303                                 }
1304                                 if (usec > arg_until)
1305                                         goto finish;
1306                         }
1307
1308                         if (arg_since_set && arg_reverse) {
1309                                 usec_t usec;
1310
1311                                 r = sd_journal_get_realtime_usec(j, &usec);
1312                                 if (r < 0) {
1313                                         log_error("Failed to determine timestamp: %s", strerror(-r));
1314                                         goto finish;
1315                                 }
1316                                 if (usec < arg_since)
1317                                         goto finish;
1318                         }
1319
1320                         if (!arg_merge) {
1321                                 sd_id128_t boot_id;
1322
1323                                 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1324                                 if (r >= 0) {
1325                                         if (previous_boot_id_valid &&
1326                                             !sd_id128_equal(boot_id, previous_boot_id))
1327                                                 printf(ANSI_HIGHLIGHT_ON "-- Reboot --" ANSI_HIGHLIGHT_OFF "\n");
1328
1329                                         previous_boot_id = boot_id;
1330                                         previous_boot_id_valid = true;
1331                                 }
1332                         }
1333
1334                         flags =
1335                                 arg_all * OUTPUT_SHOW_ALL |
1336                                 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
1337                                 on_tty() * OUTPUT_COLOR |
1338                                 arg_catalog * OUTPUT_CATALOG;
1339
1340                         r = output_journal(stdout, j, arg_output, 0, flags);
1341                         if (r < 0 || ferror(stdout))
1342                                 goto finish;
1343
1344                         need_seek = true;
1345                         n_shown++;
1346                 }
1347
1348                 if (!arg_follow)
1349                         break;
1350
1351                 r = sd_journal_wait(j, (uint64_t) -1);
1352                 if (r < 0) {
1353                         log_error("Couldn't wait for journal event: %s", strerror(-r));
1354                         goto finish;
1355                 }
1356
1357                 first_line = false;
1358         }
1359
1360 finish:
1361         pager_close();
1362
1363         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1364 }