chiark / gitweb /
journalctl: add --verify-seed= switch to specify seed value
[elogind.git] / src / journal / journalctl.c
index 138bf09d48082124bb3dd96f35c5728b459652ee..3d274c8eb5e64a172ff9c41f1f7b7e9e24f2ab20 100644 (file)
 #include "logs-show.h"
 #include "strv.h"
 #include "journal-internal.h"
-#include "fsprg.h"
 #include "journal-def.h"
+#include "journal-verify.h"
+#include "journal-authenticate.h"
+#include "fsprg.h"
 
 #define DEFAULT_FSPRG_INTERVAL_USEC (15*USEC_PER_MINUTE)
 
@@ -57,36 +59,40 @@ static bool arg_local = false;
 static bool arg_this_boot = false;
 static const char *arg_directory = NULL;
 static int arg_priorities = 0xFF;
+static const char *arg_verify_seed = NULL;
 
 static enum {
         ACTION_SHOW,
         ACTION_NEW_ID128,
         ACTION_PRINT_HEADER,
-        ACTION_SETUP_KEYS
+        ACTION_SETUP_KEYS,
+        ACTION_VERIFY
 } arg_action = ACTION_SHOW;
 
 static int help(void) {
 
         printf("%s [OPTIONS...] [MATCH]\n\n"
                "Send control commands to or query the journal.\n\n"
-               "  -h --help           Show this help\n"
-               "     --version        Show package version\n"
-               "     --no-pager       Do not pipe output into a pager\n"
-               "  -a --all            Show all fields, including long and unprintable\n"
-               "  -f --follow         Follow journal\n"
-               "  -n --lines=INTEGER  Journal entries to show\n"
-               "     --no-tail        Show all lines, even in follow mode\n"
-               "  -o --output=STRING  Change journal output mode (short, short-monotonic,\n"
-               "                      verbose, export, json, cat)\n"
-               "  -q --quiet          Don't show privilege warning\n"
-               "  -l --local          Only local entries\n"
-               "  -b --this-boot      Show data only from current boot\n"
-               "  -D --directory=PATH Show journal files from directory\n"
-               "  -p --priority=RANGE Show only messages within the specified priority range\n\n"
+               "  -h --help              Show this help\n"
+               "     --version           Show package version\n"
+               "     --no-pager          Do not pipe output into a pager\n"
+               "  -a --all               Show all fields, including long and unprintable\n"
+               "  -f --follow            Follow journal\n"
+               "  -n --lines=INTEGER     Journal entries to show\n"
+               "     --no-tail           Show all lines, even in follow mode\n"
+               "  -o --output=STRING     Change journal output mode (short, short-monotonic,\n"
+               "                         verbose, export, json, cat)\n"
+               "  -q --quiet             Don't show privilege warning\n"
+               "  -l --local             Only local entries\n"
+               "  -b --this-boot         Show data only from current boot\n"
+               "  -D --directory=PATH    Show journal files from directory\n"
+               "  -p --priority=RANGE    Show only messages within the specified priority range\n\n"
                "Commands:\n"
-               "     --new-id128      Generate a new 128 Bit id\n"
-               "     --header         Show journal header information\n"
-               "     --setup-keys     Generate new FSPRG key pair\n",
+               "     --new-id128         Generate a new 128 Bit ID\n"
+               "     --header            Show journal header information\n"
+               "     --verify            Verify journal file consistency\n"
+               "     --verify-seed=SEED  Specify FSPRG seed for verification\n"
+               "     --setup-keys        Generate new FSPRG key and seed\n",
                program_invocation_short_name);
 
         return 0;
@@ -100,27 +106,31 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_NO_TAIL,
                 ARG_NEW_ID128,
                 ARG_HEADER,
-                ARG_SETUP_KEYS
+                ARG_SETUP_KEYS,
+                ARG_VERIFY,
+                ARG_VERIFY_SEED
         };
 
         static const struct option options[] = {
-                { "help",      no_argument,       NULL, 'h'           },
-                { "version" ,  no_argument,       NULL, ARG_VERSION   },
-                { "no-pager",  no_argument,       NULL, ARG_NO_PAGER  },
-                { "follow",    no_argument,       NULL, 'f'           },
-                { "output",    required_argument, NULL, 'o'           },
-                { "all",       no_argument,       NULL, 'a'           },
-                { "lines",     required_argument, NULL, 'n'           },
-                { "no-tail",   no_argument,       NULL, ARG_NO_TAIL   },
-                { "new-id128", no_argument,       NULL, ARG_NEW_ID128 },
-                { "quiet",     no_argument,       NULL, 'q'           },
-                { "local",     no_argument,       NULL, 'l'           },
-                { "this-boot", no_argument,       NULL, 'b'           },
-                { "directory", required_argument, NULL, 'D'           },
-                { "header",    no_argument,       NULL, ARG_HEADER    },
-                { "priority",  no_argument,       NULL, 'p'           },
-                { "setup-keys",no_argument,       NULL, ARG_SETUP_KEYS},
-                { NULL,        0,                 NULL, 0             }
+                { "help",        no_argument,       NULL, 'h'             },
+                { "version" ,    no_argument,       NULL, ARG_VERSION     },
+                { "no-pager",    no_argument,       NULL, ARG_NO_PAGER    },
+                { "follow",      no_argument,       NULL, 'f'             },
+                { "output",      required_argument, NULL, 'o'             },
+                { "all",         no_argument,       NULL, 'a'             },
+                { "lines",       required_argument, NULL, 'n'             },
+                { "no-tail",     no_argument,       NULL, ARG_NO_TAIL     },
+                { "new-id128",   no_argument,       NULL, ARG_NEW_ID128   },
+                { "quiet",       no_argument,       NULL, 'q'             },
+                { "local",       no_argument,       NULL, 'l'             },
+                { "this-boot",   no_argument,       NULL, 'b'             },
+                { "directory",   required_argument, NULL, 'D'             },
+                { "header",      no_argument,       NULL, ARG_HEADER      },
+                { "priority",    no_argument,       NULL, 'p'             },
+                { "setup-keys",  no_argument,       NULL, ARG_SETUP_KEYS  },
+                { "verify",      no_argument,       NULL, ARG_VERIFY      },
+                { "verify-seed", required_argument, NULL, ARG_VERIFY_SEED },
+                { NULL,          0,                 NULL, 0               }
         };
 
         int c, r;
@@ -203,6 +213,15 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_action = ACTION_SETUP_KEYS;
                         break;
 
+                case ARG_VERIFY:
+                        arg_action = ACTION_VERIFY;
+                        break;
+
+                case ARG_VERIFY_SEED:
+                        arg_action = ACTION_VERIFY;
+                        arg_verify_seed = optarg;
+                        break;
+
                 case 'p': {
                         const char *dots;
 
@@ -532,8 +551,8 @@ static int setup_keys(void) {
                 fprintf(stderr,
                         "\n"
                         "The new key pair has been generated. The evolving key has been written to the\n"
-                        "following file. It will be used to protect local journal files. This file does\n"
-                        "not need to be kept secret. It should not be used on multiple hosts.\n"
+                        "following file. It will be used to protect local journal files. This file\n"
+                        "should be kept secret. It should not be used on multiple hosts.\n"
                         "\n"
                         "\t%s\n"
                         "\n"
@@ -572,6 +591,30 @@ finish:
 #endif
 }
 
+static int verify(sd_journal *j) {
+        int r = 0;
+        Iterator i;
+        JournalFile *f;
+
+        assert(j);
+
+        HASHMAP_FOREACH(f, j->files, i) {
+                int k;
+
+                if (!arg_verify_seed && journal_file_fsprg_enabled(f))
+                        log_warning("Journal file %s has authentication enabled but verification seed has not been passed using --verify-seed=.", f->path);
+
+                k = journal_file_verify(f, arg_verify_seed);
+                if (k < 0) {
+                        log_warning("FAIL: %s (%s)", f->path, strerror(-k));
+                        r = -r;
+                } else
+                        log_info("PASS: %s", f->path);
+        }
+
+        return r;
+}
+
 int main(int argc, char *argv[]) {
         int r;
         sd_journal *j = NULL;
@@ -598,11 +641,6 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-#ifdef HAVE_ACL
-        if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0)
-                log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this message off.");
-#endif
-
         if (arg_directory)
                 r = sd_journal_open_directory(&j, arg_directory, 0);
         else
@@ -613,12 +651,22 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
+        if (arg_action == ACTION_VERIFY) {
+                r = verify(j);
+                goto finish;
+        }
+
         if (arg_action == ACTION_PRINT_HEADER) {
                 journal_print_header(j);
                 r = 0;
                 goto finish;
         }
 
+#ifdef HAVE_ACL
+        if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0)
+                log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this message off.");
+#endif
+
         r = add_this_boot(j);
         if (r < 0)
                 goto finish;