chiark / gitweb /
journal: verify compressed objects
[elogind.git] / src / journal / journal-verify.c
index f3182e876ea1bfef14bd732626cce9d2b25966e8..8ef91ce4854fdb337c256af2771aec0421f6b5f8 100644 (file)
 #include "journal-file.h"
 #include "journal-authenticate.h"
 #include "journal-verify.h"
+#include "lookup3.h"
+#include "compress.h"
+
+/* FIXME:
+ *
+ * - follow all chains
+ * - check for unreferenced objects
+ * - verify FSPRG
+ * - Allow building without libgcrypt
+ *
+ * */
 
 static int journal_file_object_verify(JournalFile *f, Object *o) {
         assert(f);
@@ -38,15 +49,43 @@ static int journal_file_object_verify(JournalFile *f, Object *o) {
          * possible field values. It does not follow any references to
          * other objects. */
 
+        if ((o->object.flags & OBJECT_COMPRESSED) &&
+            o->object.type != OBJECT_DATA)
+                return -EBADMSG;
+
         switch (o->object.type) {
-        case OBJECT_DATA:
+
+        case OBJECT_DATA: {
+                uint64_t h1, h2;
+
                 if (le64toh(o->data.entry_offset) <= 0 ||
                     le64toh(o->data.n_entries) <= 0)
                         return -EBADMSG;
 
                 if (le64toh(o->object.size) - offsetof(DataObject, payload) <= 0)
                         return -EBADMSG;
+
+                h1 = le64toh(o->data.hash);
+
+                if (o->object.flags & OBJECT_COMPRESSED) {
+                        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))
+                                return -EBADMSG;
+
+                        h2 = hash64(b, b_size);
+                        free(b);
+                } else
+                        h2 = hash64(o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload));
+
+                if (h1 != h2)
+                        return -EBADMSG;
+
                 break;
+        }
 
         case OBJECT_FIELD:
                 if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0)
@@ -251,12 +290,6 @@ int journal_file_verify(JournalFile *f, const char *key) {
                         goto fail;
                 }
 
-                r = journal_file_hmac_put_object(f, -1, p);
-                if (r < 0) {
-                        log_error("Failed to calculate HMAC at %llu", (unsigned long long) p);
-                        goto fail;
-                }
-
                 if (o->object.flags & OBJECT_COMPRESSED &&
                     !(le32toh(f->header->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED)) {
                         log_error("Compressed object without compression at %llu", (unsigned long long) p);
@@ -264,10 +297,9 @@ int journal_file_verify(JournalFile *f, const char *key) {
                         goto fail;
                 }
 
-                if (o->object.flags & OBJECT_COMPRESSED &&
-                    o->object.type != OBJECT_DATA) {
-                        log_error("Compressed non-data object at %llu", (unsigned long long) p);
-                        r = -EBADMSG;
+                r = journal_file_hmac_put_object(f, -1, p);
+                if (r < 0) {
+                        log_error("Failed to calculate HMAC at %llu", (unsigned long long) p);
                         goto fail;
                 }