chiark / gitweb /
hostnamectl: fix parsing of --no-ask-password
[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 <sys/poll.h>
31 #include <time.h>
32 #include <getopt.h>
33 #include <signal.h>
34 #include <sys/stat.h>
35 #include <sys/ioctl.h>
36 #include <linux/fs.h>
37
38 #include <systemd/sd-journal.h>
39
40 #include "log.h"
41 #include "util.h"
42 #include "path-util.h"
43 #include "build.h"
44 #include "pager.h"
45 #include "logs-show.h"
46 #include "strv.h"
47 #include "journal-internal.h"
48 #include "journal-def.h"
49 #include "journal-verify.h"
50 #include "journal-authenticate.h"
51 #include "journal-qrcode.h"
52 #include "fsprg.h"
53 #include "unit-name.h"
54
55 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
56
57 static OutputMode arg_output = OUTPUT_SHORT;
58 static bool arg_follow = false;
59 static bool arg_all = false;
60 static bool arg_no_pager = false;
61 static unsigned arg_lines = 0;
62 static bool arg_no_tail = false;
63 static bool arg_quiet = false;
64 static bool arg_merge = false;
65 static bool arg_this_boot = false;
66 static const char *arg_cursor = NULL;
67 static const char *arg_directory = NULL;
68 static int arg_priorities = 0xFF;
69 static const char *arg_verify_key = NULL;
70 #ifdef HAVE_GCRYPT
71 static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
72 #endif
73 static usec_t arg_since, arg_until;
74 static bool arg_since_set = false, arg_until_set = false;
75 static const char *arg_unit = NULL;
76 static const char *arg_field = NULL;
77
78 static enum {
79         ACTION_SHOW,
80         ACTION_NEW_ID128,
81         ACTION_PRINT_HEADER,
82         ACTION_SETUP_KEYS,
83         ACTION_VERIFY,
84         ACTION_DISK_USAGE,
85 } arg_action = ACTION_SHOW;
86
87 static int help(void) {
88
89         printf("%s [OPTIONS...] [MATCHES...]\n\n"
90                "Query the journal.\n\n"
91                "Flags:\n"
92                "     --since=DATE        Start showing entries newer or of the specified date\n"
93                "     --until=DATE        Stop showing entries older or of the specified date\n"
94                "  -c --cursor=CURSOR     Start showing entries from specified cursor\n"
95                "  -b --this-boot         Show data only from current boot\n"
96                "  -u --unit=UNIT         Show data only from the specified unit\n"
97                "  -p --priority=RANGE    Show only messages within the specified priority range\n"
98                "  -f --follow            Follow journal\n"
99                "  -n --lines[=INTEGER]   Number of journal entries to show\n"
100                "     --no-tail           Show all lines, even in follow mode\n"
101                "  -o --output=STRING     Change journal output mode (short, short-monotonic,\n"
102                "                         verbose, export, json, json-pretty, json-sse, cat)\n"
103                "  -a --all               Show all fields, including long and unprintable\n"
104                "  -q --quiet             Don't show privilege warning\n"
105                "     --no-pager          Do not pipe output into a pager\n"
106                "  -m --merge             Show entries from all available journals\n"
107                "  -D --directory=PATH    Show journal files from directory\n"
108 #ifdef HAVE_GCRYPT
109                "     --interval=TIME     Time interval for changing the FSS sealing key\n"
110                "     --verify-key=KEY    Specify FSS verification key\n"
111 #endif
112                "\nCommands:\n"
113                "  -h --help              Show this help\n"
114                "     --version           Show package version\n"
115                "     --new-id128         Generate a new 128 Bit ID\n"
116                "     --header            Show journal header information\n"
117                "     --disk-usage        Show total disk usage\n"
118                "  -F --field=FIELD       List all values a certain field takes\n"
119 #ifdef HAVE_GCRYPT
120                "     --setup-keys        Generate new FSS key pair\n"
121                "     --verify            Verify journal file consistency\n"
122 #endif
123                , program_invocation_short_name);
124
125         return 0;
126 }
127
128 static int parse_argv(int argc, char *argv[]) {
129
130         enum {
131                 ARG_VERSION = 0x100,
132                 ARG_NO_PAGER,
133                 ARG_NO_TAIL,
134                 ARG_NEW_ID128,
135                 ARG_HEADER,
136                 ARG_SETUP_KEYS,
137                 ARG_INTERVAL,
138                 ARG_VERIFY,
139                 ARG_VERIFY_KEY,
140                 ARG_DISK_USAGE,
141                 ARG_SINCE,
142                 ARG_UNTIL
143         };
144
145         static const struct option options[] = {
146                 { "help",         no_argument,       NULL, 'h'              },
147                 { "version" ,     no_argument,       NULL, ARG_VERSION      },
148                 { "no-pager",     no_argument,       NULL, ARG_NO_PAGER     },
149                 { "follow",       no_argument,       NULL, 'f'              },
150                 { "output",       required_argument, NULL, 'o'              },
151                 { "all",          no_argument,       NULL, 'a'              },
152                 { "lines",        optional_argument, NULL, 'n'              },
153                 { "no-tail",      no_argument,       NULL, ARG_NO_TAIL      },
154                 { "new-id128",    no_argument,       NULL, ARG_NEW_ID128    },
155                 { "quiet",        no_argument,       NULL, 'q'              },
156                 { "merge",        no_argument,       NULL, 'm'              },
157                 { "this-boot",    no_argument,       NULL, 'b'              },
158                 { "directory",    required_argument, NULL, 'D'              },
159                 { "header",       no_argument,       NULL, ARG_HEADER       },
160                 { "priority",     required_argument, NULL, 'p'              },
161                 { "setup-keys",   no_argument,       NULL, ARG_SETUP_KEYS   },
162                 { "interval",     required_argument, NULL, ARG_INTERVAL     },
163                 { "verify",       no_argument,       NULL, ARG_VERIFY       },
164                 { "verify-key",   required_argument, NULL, ARG_VERIFY_KEY   },
165                 { "disk-usage",   no_argument,       NULL, ARG_DISK_USAGE   },
166                 { "cursor",       required_argument, NULL, 'c'              },
167                 { "since",        required_argument, NULL, ARG_SINCE        },
168                 { "until",        required_argument, NULL, ARG_UNTIL        },
169                 { "unit",         required_argument, NULL, 'u'              },
170                 { "field",        required_argument, NULL, 'F'              },
171                 { NULL,           0,                 NULL, 0                }
172         };
173
174         int c, r;
175
176         assert(argc >= 0);
177         assert(argv);
178
179         while ((c = getopt_long(argc, argv, "hfo:an::qmbD:p:c:u:F:", options, NULL)) >= 0) {
180
181                 switch (c) {
182
183                 case 'h':
184                         help();
185                         return 0;
186
187                 case ARG_VERSION:
188                         puts(PACKAGE_STRING);
189                         puts(DISTRIBUTION);
190                         puts(SYSTEMD_FEATURES);
191                         return 0;
192
193                 case ARG_NO_PAGER:
194                         arg_no_pager = true;
195                         break;
196
197                 case 'f':
198                         arg_follow = true;
199                         break;
200
201                 case 'o':
202                         arg_output = output_mode_from_string(optarg);
203                         if (arg_output < 0) {
204                                 log_error("Unknown output format '%s'.", optarg);
205                                 return -EINVAL;
206                         }
207
208                         if (arg_output == OUTPUT_EXPORT ||
209                             arg_output == OUTPUT_JSON ||
210                             arg_output == OUTPUT_JSON_PRETTY ||
211                             arg_output == OUTPUT_JSON_SSE ||
212                             arg_output == OUTPUT_CAT)
213                                 arg_quiet = true;
214
215                         break;
216
217                 case 'a':
218                         arg_all = true;
219                         break;
220
221                 case 'n':
222                         if (optarg) {
223                                 r = safe_atou(optarg, &arg_lines);
224                                 if (r < 0 || arg_lines <= 0) {
225                                         log_error("Failed to parse lines '%s'", optarg);
226                                         return -EINVAL;
227                                 }
228                         } else
229                                 arg_lines = 10;
230
231                         break;
232
233                 case ARG_NO_TAIL:
234                         arg_no_tail = true;
235                         break;
236
237                 case ARG_NEW_ID128:
238                         arg_action = ACTION_NEW_ID128;
239                         break;
240
241                 case 'q':
242                         arg_quiet = true;
243                         break;
244
245                 case 'm':
246                         arg_merge = true;
247                         break;
248
249                 case 'b':
250                         arg_this_boot = true;
251                         break;
252
253                 case 'D':
254                         arg_directory = optarg;
255                         break;
256
257                 case 'c':
258                         arg_cursor = optarg;
259                         break;
260
261                 case ARG_HEADER:
262                         arg_action = ACTION_PRINT_HEADER;
263                         break;
264
265                 case ARG_VERIFY:
266                         arg_action = ACTION_VERIFY;
267                         break;
268
269                 case ARG_DISK_USAGE:
270                         arg_action = ACTION_DISK_USAGE;
271                         break;
272
273 #ifdef HAVE_GCRYPT
274                 case ARG_SETUP_KEYS:
275                         arg_action = ACTION_SETUP_KEYS;
276                         break;
277
278
279                 case ARG_VERIFY_KEY:
280                         arg_action = ACTION_VERIFY;
281                         arg_verify_key = optarg;
282                         arg_merge = false;
283                         break;
284
285                 case ARG_INTERVAL:
286                         r = parse_usec(optarg, &arg_interval);
287                         if (r < 0 || arg_interval <= 0) {
288                                 log_error("Failed to parse sealing key change interval: %s", optarg);
289                                 return -EINVAL;
290                         }
291                         break;
292 #else
293                 case ARG_SETUP_KEYS:
294                 case ARG_VERIFY_KEY:
295                 case ARG_INTERVAL:
296                         log_error("Forward-secure sealing not available.");
297                         return -ENOTSUP;
298 #endif
299
300                 case 'p': {
301                         const char *dots;
302
303                         dots = strstr(optarg, "..");
304                         if (dots) {
305                                 char *a;
306                                 int from, to, i;
307
308                                 /* a range */
309                                 a = strndup(optarg, dots - optarg);
310                                 if (!a)
311                                         return log_oom();
312
313                                 from = log_level_from_string(a);
314                                 to = log_level_from_string(dots + 2);
315                                 free(a);
316
317                                 if (from < 0 || to < 0) {
318                                         log_error("Failed to parse log level range %s", optarg);
319                                         return -EINVAL;
320                                 }
321
322                                 arg_priorities = 0;
323
324                                 if (from < to) {
325                                         for (i = from; i <= to; i++)
326                                                 arg_priorities |= 1 << i;
327                                 } else {
328                                         for (i = to; i <= from; i++)
329                                                 arg_priorities |= 1 << i;
330                                 }
331
332                         } else {
333                                 int p, i;
334
335                                 p = log_level_from_string(optarg);
336                                 if (p < 0) {
337                                         log_error("Unknown log level %s", optarg);
338                                         return -EINVAL;
339                                 }
340
341                                 arg_priorities = 0;
342
343                                 for (i = 0; i <= p; i++)
344                                         arg_priorities |= 1 << i;
345                         }
346
347                         break;
348                 }
349
350                 case ARG_SINCE:
351                         r = parse_timestamp(optarg, &arg_since);
352                         if (r < 0) {
353                                 log_error("Failed to parse timestamp: %s", optarg);
354                                 return -EINVAL;
355                         }
356                         arg_since_set = true;
357                         break;
358
359                 case ARG_UNTIL:
360                         r = parse_timestamp(optarg, &arg_until);
361                         if (r < 0) {
362                                 log_error("Failed to parse timestamp: %s", optarg);
363                                 return -EINVAL;
364                         }
365                         arg_until_set = true;
366                         break;
367
368                 case 'u':
369                         arg_unit = optarg;
370                         break;
371
372                 case '?':
373                         return -EINVAL;
374
375                 case 'F':
376                         arg_field = optarg;
377                         break;
378
379                 default:
380                         log_error("Unknown option code %c", c);
381                         return -EINVAL;
382                 }
383         }
384
385         if (arg_follow && !arg_no_tail && arg_lines <= 0)
386                 arg_lines = 10;
387
388         if (arg_since_set && arg_until_set && arg_since_set > arg_until_set) {
389                 log_error("--since= must be before --until=.");
390                 return -EINVAL;
391         }
392
393         if (arg_cursor && arg_since_set) {
394                 log_error("Please specify either --since= or --cursor=, not both.");
395                 return -EINVAL;
396         }
397
398         return 1;
399 }
400
401 static int generate_new_id128(void) {
402         sd_id128_t id;
403         int r;
404         unsigned i;
405
406         r = sd_id128_randomize(&id);
407         if (r < 0) {
408                 log_error("Failed to generate ID: %s", strerror(-r));
409                 return r;
410         }
411
412         printf("As string:\n"
413                SD_ID128_FORMAT_STR "\n\n"
414                "As UUID:\n"
415                "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
416                "As macro:\n"
417               "#define MESSAGE_XYZ SD_ID128_MAKE(",
418                SD_ID128_FORMAT_VAL(id),
419                SD_ID128_FORMAT_VAL(id));
420
421         for (i = 0; i < 16; i++)
422                 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
423
424         fputs(")\n", stdout);
425
426         return 0;
427 }
428
429 static int add_matches(sd_journal *j, char **args) {
430         char **i;
431         int r;
432
433         assert(j);
434
435         STRV_FOREACH(i, args) {
436
437                 if (streq(*i, "+"))
438                         r = sd_journal_add_disjunction(j);
439                 else if (path_is_absolute(*i)) {
440                         char *p, *t = NULL;
441                         const char *path;
442                         struct stat st;
443
444                         p = canonicalize_file_name(*i);
445                         path = p ? p : *i;
446
447                         if (stat(path, &st) < 0)  {
448                                 free(p);
449                                 log_error("Couldn't stat file: %m");
450                                 return -errno;
451                         }
452
453                         if (S_ISREG(st.st_mode) && (0111 & st.st_mode))
454                                 t = strappend("_EXE=", path);
455                         else if (S_ISCHR(st.st_mode))
456                                 asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
457                         else if (S_ISBLK(st.st_mode))
458                                 asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
459                         else {
460                                 free(p);
461                                 log_error("File is not a device node, regular file or is not executable: %s", *i);
462                                 return -EINVAL;
463                         }
464
465                         free(p);
466
467                         if (!t)
468                                 return log_oom();
469
470                         r = sd_journal_add_match(j, t, 0);
471                         free(t);
472                 } else
473                         r = sd_journal_add_match(j, *i, 0);
474
475                 if (r < 0) {
476                         log_error("Failed to add match '%s': %s", *i, strerror(-r));
477                         return r;
478                 }
479         }
480
481         return 0;
482 }
483
484 static int add_this_boot(sd_journal *j) {
485         char match[9+32+1] = "_BOOT_ID=";
486         sd_id128_t boot_id;
487         int r;
488
489         assert(j);
490
491         if (!arg_this_boot)
492                 return 0;
493
494         r = sd_id128_get_boot(&boot_id);
495         if (r < 0) {
496                 log_error("Failed to get boot id: %s", strerror(-r));
497                 return r;
498         }
499
500         sd_id128_to_string(boot_id, match + 9);
501         r = sd_journal_add_match(j, match, strlen(match));
502         if (r < 0) {
503                 log_error("Failed to add match: %s", strerror(-r));
504                 return r;
505         }
506
507         return 0;
508 }
509
510 static int add_unit(sd_journal *j) {
511         _cleanup_free_ char *m = NULL, *u = NULL;
512         int r;
513
514         assert(j);
515
516         if (isempty(arg_unit))
517                 return 0;
518
519         u = unit_name_mangle(arg_unit);
520         if (!u)
521                 return log_oom();
522
523         m = strappend("_SYSTEMD_UNIT=", u);
524         if (!m)
525                 return log_oom();
526
527         r = sd_journal_add_match(j, m, strlen(m));
528         if (r < 0) {
529                 log_error("Failed to add match: %s", strerror(-r));
530                 return r;
531         }
532
533         return 0;
534 }
535
536 static int add_priorities(sd_journal *j) {
537         char match[] = "PRIORITY=0";
538         int i, r;
539
540         assert(j);
541
542         if (arg_priorities == 0xFF)
543                 return 0;
544
545         for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
546                 if (arg_priorities & (1 << i)) {
547                         match[sizeof(match)-2] = '0' + i;
548
549                         r = sd_journal_add_match(j, match, strlen(match));
550                         if (r < 0) {
551                                 log_error("Failed to add match: %s", strerror(-r));
552                                 return r;
553                         }
554                 }
555
556         return 0;
557 }
558
559 static int setup_keys(void) {
560 #ifdef HAVE_GCRYPT
561         size_t mpk_size, seed_size, state_size, i;
562         uint8_t *mpk, *seed, *state;
563         ssize_t l;
564         int fd = -1, r, attr = 0;
565         sd_id128_t machine, boot;
566         char *p = NULL, *k = NULL;
567         struct FSSHeader h;
568         uint64_t n;
569
570         r = sd_id128_get_machine(&machine);
571         if (r < 0) {
572                 log_error("Failed to get machine ID: %s", strerror(-r));
573                 return r;
574         }
575
576         r = sd_id128_get_boot(&boot);
577         if (r < 0) {
578                 log_error("Failed to get boot ID: %s", strerror(-r));
579                 return r;
580         }
581
582         if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
583                      SD_ID128_FORMAT_VAL(machine)) < 0)
584                 return log_oom();
585
586         if (access(p, F_OK) >= 0) {
587                 log_error("Sealing key file %s exists already.", p);
588                 r = -EEXIST;
589                 goto finish;
590         }
591
592         if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
593                      SD_ID128_FORMAT_VAL(machine)) < 0) {
594                 r = log_oom();
595                 goto finish;
596         }
597
598         mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
599         mpk = alloca(mpk_size);
600
601         seed_size = FSPRG_RECOMMENDED_SEEDLEN;
602         seed = alloca(seed_size);
603
604         state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
605         state = alloca(state_size);
606
607         fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
608         if (fd < 0) {
609                 log_error("Failed to open /dev/random: %m");
610                 r = -errno;
611                 goto finish;
612         }
613
614         log_info("Generating seed...");
615         l = loop_read(fd, seed, seed_size, true);
616         if (l < 0 || (size_t) l != seed_size) {
617                 log_error("Failed to read random seed: %s", strerror(EIO));
618                 r = -EIO;
619                 goto finish;
620         }
621
622         log_info("Generating key pair...");
623         FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
624
625         log_info("Generating sealing key...");
626         FSPRG_GenState0(state, mpk, seed, seed_size);
627
628         assert(arg_interval > 0);
629
630         n = now(CLOCK_REALTIME);
631         n /= arg_interval;
632
633         close_nointr_nofail(fd);
634         fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
635         if (fd < 0) {
636                 log_error("Failed to open %s: %m", k);
637                 r = -errno;
638                 goto finish;
639         }
640
641         /* Enable secure remove, exclusion from dump, synchronous
642          * writing and in-place updating */
643         if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
644                 log_warning("FS_IOC_GETFLAGS failed: %m");
645
646         attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
647
648         if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
649                 log_warning("FS_IOC_SETFLAGS failed: %m");
650
651         zero(h);
652         memcpy(h.signature, "KSHHRHLP", 8);
653         h.machine_id = machine;
654         h.boot_id = boot;
655         h.header_size = htole64(sizeof(h));
656         h.start_usec = htole64(n * arg_interval);
657         h.interval_usec = htole64(arg_interval);
658         h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
659         h.fsprg_state_size = htole64(state_size);
660
661         l = loop_write(fd, &h, sizeof(h), false);
662         if (l < 0 || (size_t) l != sizeof(h)) {
663                 log_error("Failed to write header: %s", strerror(EIO));
664                 r = -EIO;
665                 goto finish;
666         }
667
668         l = loop_write(fd, state, state_size, false);
669         if (l < 0 || (size_t) l != state_size) {
670                 log_error("Failed to write state: %s", strerror(EIO));
671                 r = -EIO;
672                 goto finish;
673         }
674
675         if (link(k, p) < 0) {
676                 log_error("Failed to link file: %m");
677                 r = -errno;
678                 goto finish;
679         }
680
681         if (on_tty()) {
682                 fprintf(stderr,
683                         "\n"
684                         "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
685                         "the following local file. This key file is automatically updated when the\n"
686                         "sealing key is advanced. It should not be used on multiple hosts.\n"
687                         "\n"
688                         "\t%s\n"
689                         "\n"
690                         "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
691                         "at a safe location and should not be saved locally on disk.\n"
692                         "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
693                 fflush(stderr);
694         }
695         for (i = 0; i < seed_size; i++) {
696                 if (i > 0 && i % 3 == 0)
697                         putchar('-');
698                 printf("%02x", ((uint8_t*) seed)[i]);
699         }
700
701         printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
702
703         if (on_tty()) {
704                 char tsb[FORMAT_TIMESPAN_MAX], *hn;
705
706                 fprintf(stderr,
707                         ANSI_HIGHLIGHT_OFF "\n"
708                         "The sealing key is automatically changed every %s.\n",
709                         format_timespan(tsb, sizeof(tsb), arg_interval));
710
711                 hn = gethostname_malloc();
712
713                 if (hn) {
714                         hostname_cleanup(hn);
715                         fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
716                 } else
717                         fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
718
719 #ifdef HAVE_QRENCODE
720                 /* If this is not an UTF-8 system don't print any QR codes */
721                 if (is_locale_utf8()) {
722                         fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
723                         print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
724                 }
725 #endif
726                 free(hn);
727         }
728
729         r = 0;
730
731 finish:
732         if (fd >= 0)
733                 close_nointr_nofail(fd);
734
735         if (k) {
736                 unlink(k);
737                 free(k);
738         }
739
740         free(p);
741
742         return r;
743 #else
744         log_error("Forward-secure sealing not available.");
745         return -ENOTSUP;
746 #endif
747 }
748
749 static int verify(sd_journal *j) {
750         int r = 0;
751         Iterator i;
752         JournalFile *f;
753
754         assert(j);
755
756         log_show_color(true);
757
758         HASHMAP_FOREACH(f, j->files, i) {
759                 int k;
760                 usec_t first, validated, last;
761
762 #ifdef HAVE_GCRYPT
763                 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
764                         log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
765 #endif
766
767                 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
768                 if (k == -EINVAL) {
769                         /* If the key was invalid give up right-away. */
770                         return k;
771                 } else if (k < 0) {
772                         log_warning("FAIL: %s (%s)", f->path, strerror(-k));
773                         r = k;
774                 } else {
775                         char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
776                         log_info("PASS: %s", f->path);
777
778                         if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
779                                 if (validated > 0) {
780                                         log_info("=> Validated from %s to %s, final %s entries not sealed.",
781                                                  format_timestamp(a, sizeof(a), first),
782                                                  format_timestamp(b, sizeof(b), validated),
783                                                  format_timespan(c, sizeof(c), last > validated ? last - validated : 0));
784                                 } else if (last > 0)
785                                         log_info("=> No sealing yet, %s of entries not sealed.",
786                                                  format_timespan(c, sizeof(c), last - first));
787                                 else
788                                         log_info("=> No sealing yet, no entries in file.");
789                         }
790                 }
791         }
792
793         return r;
794 }
795
796 static int access_check(void) {
797
798 #ifdef HAVE_ACL
799         if (access("/var/log/journal", F_OK) < 0 && geteuid() != 0 && in_group("adm") <= 0) {
800                 log_error("Unprivileged users can't see messages unless persistent log storage is enabled. Users in the group 'adm' can always see messages.");
801                 return -EACCES;
802         }
803
804         if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0)
805                 log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this notice off.");
806 #else
807         if (geteuid() != 0 && in_group("adm") <= 0) {
808                 log_error("No access to messages. Only users in the group 'adm' can see messages.");
809                 return -EACCES;
810         }
811 #endif
812
813         return 0;
814 }
815
816 int main(int argc, char *argv[]) {
817         int r;
818         sd_journal *j = NULL;
819         bool need_seek = false;
820         sd_id128_t previous_boot_id;
821         bool previous_boot_id_valid = false;
822         unsigned n_shown = 0;
823
824         setlocale(LC_ALL, "");
825         log_parse_environment();
826         log_open();
827
828         r = parse_argv(argc, argv);
829         if (r <= 0)
830                 goto finish;
831
832         signal(SIGWINCH, columns_lines_cache_reset);
833
834         if (arg_action == ACTION_NEW_ID128) {
835                 r = generate_new_id128();
836                 goto finish;
837         }
838
839         if (arg_action == ACTION_SETUP_KEYS) {
840                 r = setup_keys();
841                 goto finish;
842         }
843
844         r = access_check();
845         if (r < 0)
846                 goto finish;
847
848         if (arg_directory)
849                 r = sd_journal_open_directory(&j, arg_directory, 0);
850         else
851                 r = sd_journal_open(&j, arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY);
852         if (r < 0) {
853                 log_error("Failed to open journal: %s", strerror(-r));
854                 goto finish;
855         }
856
857         if (arg_action == ACTION_VERIFY) {
858                 r = verify(j);
859                 goto finish;
860         }
861
862         if (arg_action == ACTION_PRINT_HEADER) {
863                 journal_print_header(j);
864                 r = 0;
865                 goto finish;
866         }
867
868         if (arg_action == ACTION_DISK_USAGE) {
869                 uint64_t bytes;
870                 char sbytes[FORMAT_BYTES_MAX];
871
872                 r = sd_journal_get_usage(j, &bytes);
873                 if (r < 0)
874                         goto finish;
875
876                 printf("Journals take up %s on disk.\n", format_bytes(sbytes, sizeof(sbytes), bytes));
877                 r = 0;
878                 goto finish;
879         }
880
881         r = add_this_boot(j);
882         if (r < 0)
883                 goto finish;
884
885         r = add_unit(j);
886         if (r < 0)
887                 goto finish;
888
889         r = add_matches(j, argv + optind);
890         if (r < 0)
891                 goto finish;
892
893         r = add_priorities(j);
894         if (r < 0)
895                 goto finish;
896
897         if (arg_field) {
898                 const void *data;
899                 size_t size;
900
901                 r = sd_journal_query_unique(j, arg_field);
902                 if (r < 0) {
903                         log_error("Failed to query unique data objects: %s", strerror(-r));
904                         goto finish;
905                 }
906
907                 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
908                         const void *eq;
909
910                         if (arg_lines > 0 && n_shown >= arg_lines)
911                                 break;
912
913                         eq = memchr(data, '=', size);
914                         if (eq)
915                                 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
916                         else
917                                 printf("%.*s\n", (int) size, (const char*) data);
918
919                         n_shown ++;
920                 }
921
922                 r = 0;
923                 goto finish;
924         }
925
926         if (arg_cursor) {
927                 r = sd_journal_seek_cursor(j, arg_cursor);
928                 if (r < 0) {
929                         log_error("Failed to seek to cursor: %s", strerror(-r));
930                         goto finish;
931                 }
932
933                 r = sd_journal_next(j);
934
935         } else if (arg_since_set) {
936                 r = sd_journal_seek_realtime_usec(j, arg_since);
937                 if (r < 0) {
938                         log_error("Failed to seek to date: %s", strerror(-r));
939                         goto finish;
940                 }
941                 r = sd_journal_next(j);
942
943         } else if (arg_lines > 0) {
944                 r = sd_journal_seek_tail(j);
945                 if (r < 0) {
946                         log_error("Failed to seek to tail: %s", strerror(-r));
947                         goto finish;
948                 }
949
950                 r = sd_journal_previous_skip(j, arg_lines);
951
952         } else {
953                 r = sd_journal_seek_head(j);
954                 if (r < 0) {
955                         log_error("Failed to seek to head: %s", strerror(-r));
956                         goto finish;
957                 }
958
959                 r = sd_journal_next(j);
960         }
961
962         if (r < 0) {
963                 log_error("Failed to iterate through journal: %s", strerror(-r));
964                 goto finish;
965         }
966
967         if (!arg_no_pager && !arg_follow)
968                 pager_open();
969
970         if (!arg_quiet) {
971                 usec_t start, end;
972                 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
973
974                 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
975                 if (r < 0) {
976                         log_error("Failed to get cutoff: %s", strerror(-r));
977                         goto finish;
978                 }
979
980                 if (r > 0) {
981                         if (arg_follow)
982                                 printf("-- Logs begin at %s. --\n",
983                                        format_timestamp(start_buf, sizeof(start_buf), start));
984                         else
985                                 printf("-- Logs begin at %s, end at %s. --\n",
986                                        format_timestamp(start_buf, sizeof(start_buf), start),
987                                        format_timestamp(end_buf, sizeof(end_buf), end));
988                 }
989         }
990
991         for (;;) {
992                 while (arg_lines == 0 || arg_follow || n_shown < arg_lines) {
993                         int flags;
994
995                         if (need_seek) {
996                                 r = sd_journal_next(j);
997                                 if (r < 0) {
998                                         log_error("Failed to iterate through journal: %s", strerror(-r));
999                                         goto finish;
1000                                 }
1001                         }
1002
1003                         if (r == 0)
1004                                 break;
1005
1006                         if (arg_until_set) {
1007                                 usec_t usec;
1008
1009                                 r = sd_journal_get_realtime_usec(j, &usec);
1010                                 if (r < 0) {
1011                                         log_error("Failed to determine timestamp: %s", strerror(-r));
1012                                         goto finish;
1013                                 }
1014                         }
1015
1016                         if (!arg_merge) {
1017                                 sd_id128_t boot_id;
1018
1019                                 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1020                                 if (r >= 0) {
1021                                         if (previous_boot_id_valid &&
1022                                             !sd_id128_equal(boot_id, previous_boot_id))
1023                                                 printf(ANSI_HIGHLIGHT_ON "-- Reboot --" ANSI_HIGHLIGHT_OFF "\n");
1024
1025                                         previous_boot_id = boot_id;
1026                                         previous_boot_id_valid = true;
1027                                 }
1028                         }
1029
1030                         flags =
1031                                 arg_all * OUTPUT_SHOW_ALL |
1032                                 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
1033                                 on_tty() * OUTPUT_COLOR;
1034
1035                         r = output_journal(stdout, j, arg_output, 0, flags);
1036                         if (r < 0)
1037                                 goto finish;
1038
1039                         need_seek = true;
1040                         n_shown++;
1041                 }
1042
1043                 if (!arg_follow)
1044                         break;
1045
1046                 r = sd_journal_wait(j, (uint64_t) -1);
1047                 if (r < 0) {
1048                         log_error("Couldn't wait for journal event: %s", strerror(-r));
1049                         goto finish;
1050                 }
1051         }
1052
1053 finish:
1054         if (j)
1055                 sd_journal_close(j);
1056
1057         pager_close();
1058
1059         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1060 }