test-journal-verify.c revision 143bfdaf0b890fa7acadf02d1eafacaef1b696bd
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
bb5e3b2f129cc39517b925419c22f69a378ec023eh/***
bb5e3b2f129cc39517b925419c22f69a378ec023eh This file is part of systemd.
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh Copyright 2012 Lennart Poettering
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh systemd is free software; you can redistribute it and/or modify it
bb5e3b2f129cc39517b925419c22f69a378ec023eh under the terms of the GNU Lesser General Public License as published by
bb5e3b2f129cc39517b925419c22f69a378ec023eh the Free Software Foundation; either version 2.1 of the License, or
bb5e3b2f129cc39517b925419c22f69a378ec023eh (at your option) any later version.
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh systemd is distributed in the hope that it will be useful, but
bb5e3b2f129cc39517b925419c22f69a378ec023eh WITHOUT ANY WARRANTY; without even the implied warranty of
bb5e3b2f129cc39517b925419c22f69a378ec023eh MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
bb5e3b2f129cc39517b925419c22f69a378ec023eh Lesser General Public License for more details.
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh You should have received a copy of the GNU Lesser General Public License
bb5e3b2f129cc39517b925419c22f69a378ec023eh along with systemd; If not, see <http://www.gnu.org/licenses/>.
bb5e3b2f129cc39517b925419c22f69a378ec023eh***/
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <stdio.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <unistd.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <fcntl.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include "util.h"
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include "log.h"
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include "journal-file.h"
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include "journal-verify.h"
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include "journal-authenticate.h"
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh#define N_ENTRIES 6000
bb5e3b2f129cc39517b925419c22f69a378ec023eh#define RANDOM_RANGE 77
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void bit_toggle(const char *fn, uint64_t p) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint8_t b;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ssize_t r;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int fd;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh fd = open(fn, O_RDWR|O_CLOEXEC);
bb5e3b2f129cc39517b925419c22f69a378ec023eh assert(fd >= 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh r = pread(fd, &b, 1, p/8);
bb5e3b2f129cc39517b925419c22f69a378ec023eh assert(r == 1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh b ^= 1 << (p % 8);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh r = pwrite(fd, &b, 1, p/8);
bb5e3b2f129cc39517b925419c22f69a378ec023eh assert(r == 1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng close_nointr_nofail(fd);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int raw_verify(const char *fn, const char *verification_key) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh JournalFile *f;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int r;
924f3e72988efae04c4357a6686a06ba300bab18eh
924f3e72988efae04c4357a6686a06ba300bab18eh r = journal_file_open(fn, O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, &f);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (r < 0)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return r;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh r = journal_file_verify(f, verification_key, NULL, NULL, NULL, false);
bb5e3b2f129cc39517b925419c22f69a378ec023eh journal_file_close(f);
924f3e72988efae04c4357a6686a06ba300bab18eh
924f3e72988efae04c4357a6686a06ba300bab18eh return r;
924f3e72988efae04c4357a6686a06ba300bab18eh}
924f3e72988efae04c4357a6686a06ba300bab18eh
924f3e72988efae04c4357a6686a06ba300bab18ehint main(int argc, char *argv[]) {
924f3e72988efae04c4357a6686a06ba300bab18eh char t[] = "/tmp/journal-XXXXXX";
bb5e3b2f129cc39517b925419c22f69a378ec023eh unsigned n;
bb5e3b2f129cc39517b925419c22f69a378ec023eh JournalFile *f;
bb5e3b2f129cc39517b925419c22f69a378ec023eh const char *verification_key = argv[1];
bb5e3b2f129cc39517b925419c22f69a378ec023eh usec_t from = 0, to = 0, total = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh char a[FORMAT_TIMESTAMP_MAX];
bb5e3b2f129cc39517b925419c22f69a378ec023eh char b[FORMAT_TIMESTAMP_MAX];
bb5e3b2f129cc39517b925419c22f69a378ec023eh char c[FORMAT_TIMESPAN_MAX];
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct stat st;
193974072f41a843678abf5f61979c748687e66bSherry Moore uint64_t p;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* journal_file_open requires a valid machine id */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (access("/etc/machine-id", F_OK) != 0)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return EXIT_TEST_SKIP;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh log_set_max_level(LOG_DEBUG);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh assert_se(mkdtemp(t));
bb5e3b2f129cc39517b925419c22f69a378ec023eh assert_se(chdir(t) >= 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh log_info("Generating...");
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, true, !!verification_key, NULL, NULL, NULL, &f) == 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (n = 0; n < N_ENTRIES; n++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct iovec iovec;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct dual_timestamp ts;
bb5e3b2f129cc39517b925419c22f69a378ec023eh char *test;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh dual_timestamp_get(&ts);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh assert_se(asprintf(&test, "RANDOM=%lu", random() % RANDOM_RANGE));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh iovec.iov_base = (void*) test;
bb5e3b2f129cc39517b925419c22f69a378ec023eh iovec.iov_len = strlen(test);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh free(test);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh journal_file_close(f);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh log_info("Verifying...");
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh assert_se(journal_file_open("test.journal", O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, &f) == 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* journal_file_print_header(f); */
bb5e3b2f129cc39517b925419c22f69a378ec023eh journal_file_dump(f);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh assert_se(journal_file_verify(f, verification_key, &from, &to, &total, true) >= 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (verification_key && JOURNAL_HEADER_SEALED(f->header)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh log_info("=> Validated from %s to %s, %s missing",
bb5e3b2f129cc39517b925419c22f69a378ec023eh format_timestamp(a, sizeof(a), from),
bb5e3b2f129cc39517b925419c22f69a378ec023eh format_timestamp(b, sizeof(b), to),
bb5e3b2f129cc39517b925419c22f69a378ec023eh format_timespan(c, sizeof(c), total > to ? total - to : 0, 0));
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh journal_file_close(f);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (verification_key) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh log_info("Toggling bits...");
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh assert_se(stat("test.journal", &st) >= 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (p = 38448*8+0; p < ((uint64_t) st.st_size * 8); p ++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh bit_toggle("test.journal", p);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh log_info("[ %"PRIu64"+%"PRIu64"]", p / 8, p % 8);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (raw_verify("test.journal", verification_key) >= 0)
bb5e3b2f129cc39517b925419c22f69a378ec023eh log_notice(ANSI_HIGHLIGHT_RED_ON ">>>> %"PRIu64" (bit %"PRIu64") can be toggled without detection." ANSI_HIGHLIGHT_OFF, p / 8, p % 8);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh bit_toggle("test.journal", p);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh log_info("Exiting...");
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh