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