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