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