chiark / gitweb /
Add ugly CMP_F_TYPE() macro
[elogind.git] / src / journal / journal-verify.c
index 6afeab9a80bb939e34dd3b6e9775093c1309b5cf..ed28b457372813e689a09ad0cc9ed4244d6420c3 100644 (file)
@@ -22,6 +22,7 @@
 #include <unistd.h>
 #include <sys/mman.h>
 #include <fcntl.h>
+#include <stddef.h>
 
 #include "util.h"
 #include "macro.h"
 #include "compress.h"
 #include "fsprg.h"
 
-/* FIXME:
- *
- * - evolve key even if nothing happened in regular intervals
- *
- * - Allow building without libgcrypt
- * - check with sparse
- * - 64bit conversions
- *
- * */
-
 static int journal_file_object_verify(JournalFile *f, Object *o) {
         uint64_t i;
 
@@ -72,16 +63,20 @@ static int journal_file_object_verify(JournalFile *f, Object *o) {
                 h1 = le64toh(o->data.hash);
 
                 if (o->object.flags & OBJECT_COMPRESSED) {
+#ifdef HAVE_XZ
                         void *b = NULL;
                         uint64_t alloc = 0, b_size;
 
                         if (!uncompress_blob(o->data.payload,
                                              le64toh(o->object.size) - offsetof(Object, data.payload),
-                                             &b, &alloc, &b_size))
+                                             &b, &alloc, &b_size, 0))
                                 return -EBADMSG;
 
                         h2 = hash64(b, b_size);
                         free(b);
+#else
+                        return -EPROTONOSUPPORT;
+#endif
                 } else
                         h2 = hash64(o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload));
 
@@ -183,7 +178,7 @@ static void draw_progress(uint64_t p, usec_t *last_usec) {
         unsigned n, i, j, k;
         usec_t z, x;
 
-        if (!isatty(STDOUT_FILENO))
+        if (!on_tty())
                 return;
 
         z = now(CLOCK_MONOTONIC);
@@ -217,7 +212,7 @@ static void draw_progress(uint64_t p, usec_t *last_usec) {
 static void flush_progress(void) {
         unsigned n, i;
 
-        if (!isatty(STDOUT_FILENO))
+        if (!on_tty())
                 return;
 
         n = (3 * columns()) / 4;
@@ -258,7 +253,7 @@ static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) {
 
                 c = (a + b) / 2;
 
-                r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, c * sizeof(uint64_t), sizeof(uint64_t), (void **) &z);
+                r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z);
                 if (r < 0)
                         return r;
 
@@ -270,9 +265,8 @@ static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) {
 
                 if (p < *z)
                         b = c;
-                else {
+                else
                         a = c;
-                }
         }
 
         return 0;
@@ -318,22 +312,46 @@ static int entry_points_to_data(
          * main entry array has already been verified we can rely on
          * its consistency.*/
 
+        i = 0;
         n = le64toh(f->header->n_entries);
         a = le64toh(f->header->entry_array_offset);
-        i = 0;
 
         while (i < n) {
-                uint64_t m, j;
+                uint64_t m, u;
 
                 r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
                 if (r < 0)
                         return r;
 
                 m = journal_file_entry_array_n_items(o);
-                for (j = 0; i < n && j < m; i++, j++)
-                        if (le64toh(o->entry_array.items[j]) == entry_p)
-                                return 0;
+                u = MIN(n - i, m);
 
+                if (entry_p <= le64toh(o->entry_array.items[u-1])) {
+                        uint64_t x, y, z;
+
+                        x = 0;
+                        y = u;
+
+                        while (x < y) {
+                                z = (x + y) / 2;
+
+                                if (le64toh(o->entry_array.items[z]) == entry_p)
+                                        return 0;
+
+                                if (x + 1 >= y)
+                                        break;
+
+                                if (entry_p < le64toh(o->entry_array.items[z]))
+                                        y = z;
+                                else
+                                        x = z;
+                        }
+
+                        log_error("Entry object doesn't exist in main entry array at %llu", (unsigned long long) entry_p);
+                        return -EBADMSG;
+                }
+
+                i += u;
                 a = le64toh(o->entry_array.next_entry_array_offset);
         }
 
@@ -645,70 +663,15 @@ static int verify_entry_array(
         return 0;
 }
 
-static int journal_file_parse_verification_key(JournalFile *f, const char *key) {
-        uint8_t *seed;
-        size_t seed_size, c;
-        const char *k;
-        int r;
-        unsigned long long start, interval;
-
-        seed_size = FSPRG_RECOMMENDED_SEEDLEN;
-        seed = malloc(seed_size);
-        if (!seed)
-                return -ENOMEM;
-
-        k = key;
-        for (c = 0; c < seed_size; c++) {
-                int x, y;
-
-                while (*k == '-')
-                        k++;
-
-                x = unhexchar(*k);
-                if (x < 0) {
-                        free(seed);
-                        return -EINVAL;
-                }
-                k++;
-                y = unhexchar(*k);
-                if (y < 0) {
-                        free(seed);
-                        return -EINVAL;
-                }
-                k++;
-
-                seed[c] = (uint8_t) (x * 16 + y);
-        }
-
-        if (*k != '/') {
-                free(seed);
-                return -EINVAL;
-        }
-        k++;
-
-        r = sscanf(k, "%llx-%llx", &start, &interval);
-        if (r != 2) {
-                free(seed);
-                return -EINVAL;
-        }
-
-        f->fsprg_seed = seed;
-        f->fsprg_seed_size = seed_size;
-
-        f->fss_start_usec = start * interval;
-        f->fss_interval_usec = interval;
-
-        return 0;
-}
-
 int journal_file_verify(
                 JournalFile *f,
                 const char *key,
-                usec_t *first_validated, usec_t *last_validated, usec_t *last_contained,
+                usec_t *first_contained, usec_t *last_validated, usec_t *last_contained,
                 bool show_progress) {
         int r;
         Object *o;
-        uint64_t p = 0, last_tag = 0, last_epoch = 0, last_tag_realtime = 0, last_sealed_realtime = 0;
+        uint64_t p = 0, last_epoch = 0, last_tag_realtime = 0, last_sealed_realtime = 0;
+
         uint64_t entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0;
         sd_id128_t entry_boot_id;
         bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false;
@@ -720,15 +683,21 @@ int journal_file_verify(
                 entry_array_path[] = "/var/tmp/journal-entry-array-XXXXXX";
         unsigned i;
         bool found_last;
-
+#ifdef HAVE_GCRYPT
+        uint64_t last_tag = 0;
+#endif
         assert(f);
 
         if (key) {
+#ifdef HAVE_GCRYPT
                 r = journal_file_parse_verification_key(f, key);
                 if (r < 0) {
                         log_error("Failed to parse seed.");
                         return r;
                 }
+#else
+                return -ENOTSUP;
+#endif
         } else if (f->seal)
                 return -ENOKEY;
 
@@ -936,9 +905,7 @@ int journal_file_verify(
                         n_entry_arrays++;
                         break;
 
-                case OBJECT_TAG: {
-                        uint64_t q, rt;
-
+                case OBJECT_TAG:
                         if (!JOURNAL_HEADER_SEALED(f->header)) {
                                 log_error("Tag object in file without sealing at %llu", (unsigned long long) p);
                                 r = -EBADMSG;
@@ -957,7 +924,10 @@ int journal_file_verify(
                                 goto fail;
                         }
 
+#ifdef HAVE_GCRYPT
                         if (f->seal) {
+                                uint64_t q, rt;
+
                                 log_debug("Checking tag %llu..", (unsigned long long) le64toh(o->tag.seqnum));
 
                                 rt = f->fss_start_usec + o->tag.epoch * f->fss_interval_usec;
@@ -992,7 +962,7 @@ int journal_file_verify(
                                         if (r < 0)
                                                 goto fail;
 
-                                        r = journal_file_hmac_put_object(f, -1, q);
+                                        r = journal_file_hmac_put_object(f, -1, o, q);
                                         if (r < 0)
                                                 goto fail;
 
@@ -1016,11 +986,12 @@ int journal_file_verify(
                         }
 
                         last_tag = p + ALIGN64(le64toh(o->object.size));
+#endif
+
                         last_epoch = le64toh(o->tag.epoch);
 
                         n_tags ++;
                         break;
-                }
 
                 default:
                         n_weird ++;
@@ -1154,8 +1125,8 @@ int journal_file_verify(
         close_nointr_nofail(entry_fd);
         close_nointr_nofail(entry_array_fd);
 
-        if (first_validated)
-                *first_validated = last_tag_realtime ? le64toh(f->header->head_entry_realtime) : 0;
+        if (first_contained)
+                *first_contained = le64toh(f->header->head_entry_realtime);
         if (last_validated)
                 *last_validated = last_sealed_realtime;
         if (last_contained)