chiark / gitweb /
journal: after verification output validated time range
authorLennart Poettering <lennart@poettering.net>
Fri, 17 Aug 2012 01:30:22 +0000 (03:30 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 17 Aug 2012 01:30:22 +0000 (03:30 +0200)
src/journal/journal-verify.c
src/journal/journal-verify.h
src/journal/journalctl.c
src/journal/test-journal-verify.c

index 598fc9beadf2f86c4f2c8acc317478685a9c28bc..f9a930e42eac05d4f08cbf8549e7cf615e27220f 100644 (file)
@@ -36,8 +36,6 @@
 /* FIXME:
  *
  * - write bit mucking test
- * - tag timestamps should be between entry timestamps
- * - output validated time ranges
  * - evolve key even if nothing happened in regular intervals
  *
  * - Allow building without libgcrypt
@@ -652,7 +650,10 @@ static int journal_file_parse_verification_key(JournalFile *f, const char *key)
         return 0;
 }
 
-int journal_file_verify(JournalFile *f, const char *key) {
+int journal_file_verify(
+                JournalFile *f,
+                const char *key,
+                usec_t *first_validated, usec_t *last_validated, usec_t *last_contained) {
         int r;
         Object *o;
         uint64_t p = 0, last_tag = 0, last_epoch = 0, last_tag_realtime = 0;
@@ -749,6 +750,12 @@ int journal_file_verify(JournalFile *f, const char *key) {
                         break;
 
                 case OBJECT_ENTRY:
+                        if ((le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_SEALED) && n_tags <= 0) {
+                                log_error("First entry before first tag at %llu", (unsigned long long) p);
+                                r = -EBADMSG;
+                                goto fail;
+                        }
+
                         r = write_uint64(entry_fd, p);
                         if (r < 0)
                                 goto fail;
@@ -854,7 +861,7 @@ int journal_file_verify(JournalFile *f, const char *key) {
                         break;
 
                 case OBJECT_TAG: {
-                        uint64_t q;
+                        uint64_t q, rt;
 
                         if (!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_SEALED)) {
                                 log_error("Tag object in file without sealing at %llu", (unsigned long long) p);
@@ -876,8 +883,8 @@ int journal_file_verify(JournalFile *f, const char *key) {
                                 goto fail;
                         }
 
-                        last_tag_realtime = (o->tag.epoch + 1) * f->fss_interval_usec + f->fss_start_usec;
-                        if (entry_realtime_set && entry_realtime >= last_tag_realtime) {
+                        rt = (o->tag.epoch + 1) * f->fss_interval_usec + f->fss_start_usec;
+                        if (entry_realtime_set && entry_realtime >= rt) {
                                 log_error("Tag/entry realtime timestamp out of synchronization at %llu", (unsigned long long) p);
                                 r = -EBADMSG;
                                 goto fail;
@@ -929,6 +936,8 @@ int journal_file_verify(JournalFile *f, const char *key) {
                         f->hmac_running = false;
 
                         last_tag = p + ALIGN64(le64toh(o->object.size));
+                        last_tag_realtime = rt;
+
                         n_tags ++;
                         break;
                 }
@@ -1056,6 +1065,13 @@ int journal_file_verify(JournalFile *f, const char *key) {
         close_nointr_nofail(entry_fd);
         close_nointr_nofail(entry_array_fd);
 
+        if (first_validated)
+                *first_validated = le64toh(f->header->head_entry_realtime);
+        if (last_validated)
+                *last_validated = last_tag_realtime;
+        if (last_contained)
+                *last_contained = le64toh(f->header->tail_entry_realtime);
+
         return 0;
 
 fail:
index 3ebdd5e7f228065a66628bb0260c92acbb1da590..e4449c6ad73a941d1426959e20b230cf0bebdf8f 100644 (file)
@@ -23,4 +23,4 @@
 
 #include "journal-file.h"
 
-int journal_file_verify(JournalFile *f, const char *key);
+int journal_file_verify(JournalFile *f, const char *key, usec_t *first_validated, usec_t *last_validated, usec_t *last_contained);
index 0df8ce57fd78cae0486f90eade54f1eeaa59ec15..5c21ab0adffd7dbeaf50041da32787b26b3ff797 100644 (file)
@@ -618,21 +618,30 @@ static int verify(sd_journal *j) {
 
         HASHMAP_FOREACH(f, j->files, i) {
                 int k;
+                usec_t from, to, total;
 
 #ifdef HAVE_GCRYPT
                 if (!arg_verify_key && journal_file_fss_enabled(f))
                         log_warning("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
 #endif
 
-                k = journal_file_verify(f, arg_verify_key);
+                k = journal_file_verify(f, arg_verify_key, &from, &to, &total);
                 if (k == -EINVAL) {
                         /* If the key was invalid give up right-away. */
                         return k;
                 } else if (k < 0) {
                         log_warning("FAIL: %s (%s)", f->path, strerror(-k));
                         r = k;
-                } else
+                } else {
+                        char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
                         log_info("PASS: %s", f->path);
+
+                        if (journal_file_fss_enabled(f))
+                                log_info("=> Validated from %s to %s, %s missing",
+                                         format_timestamp(a, sizeof(a), from),
+                                         format_timestamp(b, sizeof(b), to),
+                                         format_timespan(c, sizeof(c), total > to ? total - to : 0));
+                }
         }
 
         return r;
index 9a99bcba4b5ef35a787403fa4364d74f0b014cef..df0a5ddef937965f042409b01f483e206728a615 100644 (file)
@@ -36,6 +36,10 @@ int main(int argc, char *argv[]) {
         unsigned n;
         JournalFile *f;
         const char *verification_key = argv[1];
+        usec_t from, to, total;
+        char a[FORMAT_TIMESTAMP_MAX];
+        char b[FORMAT_TIMESTAMP_MAX];
+        char c[FORMAT_TIMESPAN_MAX];
 
         log_set_max_level(LOG_DEBUG);
 
@@ -71,7 +75,13 @@ int main(int argc, char *argv[]) {
 
         journal_file_print_header(f);
 
-        assert_se(journal_file_verify(f, verification_key) >= 0);
+        assert_se(journal_file_verify(f, verification_key, &from, &to, &total) >= 0);
+
+        log_info("=> Validated from %s to %s, %s missing",
+                 format_timestamp(a, sizeof(a), from),
+                 format_timestamp(b, sizeof(b), to),
+                 format_timespan(c, sizeof(c), total > to ? total - to : 0));
+
         journal_file_close(f);
 
         log_info("Exiting...");