journal: make libgcrypt dependency optional

This commit is contained in:
Lennart Poettering 2012-08-20 16:51:46 +02:00
parent 8088cbd3cf
commit feb12d3ed2
12 changed files with 134 additions and 86 deletions

View File

@ -2402,8 +2402,6 @@ libsystemd_journal_la_SOURCES = \
src/journal/journal-vacuum.h \
src/journal/journal-verify.c \
src/journal/journal-verify.h \
src/journal/journal-authenticate.c \
src/journal/journal-authenticate.h \
src/journal/lookup3.c \
src/journal/lookup3.h \
src/journal/journal-send.c \
@ -2455,6 +2453,8 @@ endif
if HAVE_GCRYPT
libsystemd_journal_la_SOURCES += \
src/journal/journal-authenticate.c \
src/journal/journal-authenticate.h \
src/journal/fsprg.c \
src/journal/fsprg.h

1
README
View File

@ -42,6 +42,7 @@ REQUIREMENTS:
libcap
PAM >= 1.1.2 (optional)
libcryptsetup (optional)
libgcrypt (optional)
libaudit (optional)
libacl (optional)
libselinux (optional)

6
TODO
View File

@ -254,8 +254,6 @@ Features:
* cleanup syslog 'priority' vs. 'level' wording
* journal: if mmap() fails for mapping window try to unmap a a few older maps
* dbus upstream still refers to dbus.target and shouldn't
* when a service has the same env var set twice we actually store it twice and return that in systemctl show -p... We should only show the last setting
@ -300,8 +298,6 @@ Features:
* journal: message catalog
* journal: forward-secure signatures
* document the exit codes when services fail before they are exec()ed
* systemctl journal command
@ -503,6 +499,4 @@ Scheduled for removal (or fixing):
* xxxOverridable dependencies
* journald.conf: ImportKernel=
* prefdm.service

View File

@ -302,7 +302,7 @@ AC_SUBST(ACL_LIBS)
AM_CONDITIONAL([HAVE_ACL], [test "x$have_acl" != xno])
# ------------------------------------------------------------------------------
AC_ARG_ENABLE([],
AC_ARG_ENABLE([gcrypt],
AS_HELP_STRING([--disable-gcrypt],[Disable optional GCRYPT support]),
[case "${enableval}" in
yes) have_gcrypt=yes ;;

View File

@ -63,4 +63,22 @@
#define _LIBCRYPTSETUP_FEATURE_ "-LIBCRYPTSETUP"
#endif
#define SYSTEMD_FEATURES _PAM_FEATURE_ " " _LIBWRAP_FEATURE_ " " _AUDIT_FEATURE_ " " _SELINUX_FEATURE_ " " _IMA_FEATURE_ " " _SYSVINIT_FEATURE_ " " _LIBCRYPTSETUP_FEATURE_
#ifdef HAVE_GCRYPT
#define _GCRYPT_FEATURE_ "+GCRYPT"
#else
#define _GCRYPT_FEATURE_ "-GCRYPT"
#endif
#ifdef HAVE_ACL
#define _ACL_FEATURE_ "+ACL"
#else
#define _ACL_FEATURE_ "-ACL"
#endif
#ifdef HAVE_XZ
#define _XZ_FEATURE_ "+XZ"
#else
#define _XZ_FEATURE_ "-XZ"
#endif
#define SYSTEMD_FEATURES _PAM_FEATURE_ " " _LIBWRAP_FEATURE_ " " _AUDIT_FEATURE_ " " _SELINUX_FEATURE_ " " _IMA_FEATURE_ " " _SYSVINIT_FEATURE_ " " _LIBCRYPTSETUP_FEATURE_ " " _GCRYPT_FEATURE_ " " _ACL_FEATURE_ " " _XZ_FEATURE_

View File

@ -461,8 +461,59 @@ int journal_file_append_first_tag(JournalFile *f) {
return 0;
}
bool journal_file_fss_enabled(JournalFile *f) {
assert(f);
return JOURNAL_HEADER_SEALED(f->header);
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;
}

View File

@ -36,7 +36,7 @@ int journal_file_hmac_put_header(JournalFile *f);
int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p);
int journal_file_fss_load(JournalFile *f);
bool journal_file_fss_enabled(JournalFile *f);
int journal_file_parse_verification_key(JournalFile *f, const char *key);
int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime);
int journal_file_fsprg_seek(JournalFile *f, uint64_t epoch);

View File

@ -64,9 +64,11 @@
void journal_file_close(JournalFile *f) {
assert(f);
#ifdef HAVE_GCRYPT
/* Write the final tag */
if (f->seal && f->writable)
journal_file_append_tag(f);
#endif
/* Sync everything to disk, before we mark the file offline */
if (f->mmap && f->fd >= 0)
@ -764,9 +766,11 @@ static int journal_file_append_data(
if (r < 0)
return r;
#ifdef HAVE_GCRYPT
r = journal_file_hmac_put_object(f, OBJECT_DATA, p);
if (r < 0)
return r;
#endif
/* The linking might have altered the window, so let's
* refresh our pointer */
@ -852,9 +856,11 @@ static int link_entry_into_array(JournalFile *f,
if (r < 0)
return r;
#ifdef HAVE_GCRYPT
r = journal_file_hmac_put_object(f, OBJECT_ENTRY_ARRAY, q);
if (r < 0)
return r;
#endif
o->entry_array.items[i] = htole64(p);
@ -996,9 +1002,11 @@ static int journal_file_append_entry_internal(
o->entry.xor_hash = htole64(xor_hash);
o->entry.boot_id = f->header->boot_id;
#ifdef HAVE_GCRYPT
r = journal_file_hmac_put_object(f, OBJECT_ENTRY, np);
if (r < 0)
return r;
#endif
r = journal_file_link_entry(f, o, np);
if (r < 0)
@ -1049,9 +1057,11 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st
ts->monotonic < le64toh(f->header->tail_entry_monotonic))
return -EINVAL;
#ifdef HAVE_GCRYPT
r = journal_file_maybe_append_tag(f, ts->realtime);
if (r < 0)
return r;
#endif
/* alloca() can't take 0, hence let's allocate at least one */
items = alloca(sizeof(EntryItem) * MAX(1, n_iovec));
@ -2030,11 +2040,13 @@ int journal_file_open(
if (f->last_stat.st_size == 0 && f->writable) {
newly_created = true;
#ifdef HAVE_GCRYPT
/* Try to load the FSPRG state, and if we can't, then
* just don't do sealing */
r = journal_file_fss_load(f);
if (r < 0)
f->seal = false;
#endif
r = journal_file_init_header(f, template);
if (r < 0)
@ -2064,11 +2076,13 @@ int journal_file_open(
goto fail;
}
#ifdef HAVE_GCRYPT
if (!newly_created && f->writable) {
r = journal_file_fss_load(f);
if (r < 0)
goto fail;
}
#endif
if (f->writable) {
if (metrics) {
@ -2082,9 +2096,11 @@ int journal_file_open(
goto fail;
}
#ifdef HAVE_GCRYPT
r = journal_file_hmac_setup(f);
if (r < 0)
goto fail;
#endif
if (newly_created) {
r = journal_file_setup_field_hash_table(f);
@ -2095,9 +2111,11 @@ int journal_file_open(
if (r < 0)
goto fail;
#ifdef HAVE_GCRYPT
r = journal_file_append_first_tag(f);
if (r < 0)
goto fail;
#endif
}
r = journal_file_map_field_hash_table(f);

View File

@ -22,6 +22,7 @@
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stddef.h>
#include "util.h"
#include "macro.h"
@ -37,7 +38,6 @@
*
* - evolve key even if nothing happened in regular intervals
*
* - Allow building without libgcrypt
* - check with sparse
* - 64bit conversions
*
@ -645,62 +645,6 @@ 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,
@ -724,11 +668,15 @@ int journal_file_verify(
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 +884,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 +903,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;
@ -1014,13 +963,13 @@ int journal_file_verify(
last_tag_realtime = rt;
last_sealed_realtime = entry_realtime;
}
#endif
last_tag = p + ALIGN64(le64toh(o->object.size));
last_epoch = le64toh(o->tag.epoch);
n_tags ++;
break;
}
default:
n_weird ++;

View File

@ -62,7 +62,9 @@ static bool arg_this_boot = false;
static const char *arg_directory = NULL;
static int arg_priorities = 0xFF;
static const char *arg_verify_key = NULL;
#ifdef HAVE_GCRYPT
static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
#endif
static enum {
ACTION_SHOW,
@ -93,11 +95,13 @@ static int help(void) {
"Commands:\n"
" --new-id128 Generate a new 128 Bit ID\n"
" --header Show journal header information\n"
#ifdef HAVE_GCRYPT
" --setup-keys Generate new FSS key pair\n"
" --interval=TIME Time interval for changing the FSS sealing key\n"
" --verify Verify journal file consistency\n"
" --verify-key=KEY Specify FSS verification key\n",
program_invocation_short_name);
" --verify-key=KEY Specify FSS verification key\n"
#endif
, program_invocation_short_name);
return 0;
}
@ -215,13 +219,15 @@ static int parse_argv(int argc, char *argv[]) {
arg_action = ACTION_PRINT_HEADER;
break;
case ARG_VERIFY:
arg_action = ACTION_VERIFY;
break;
#ifdef HAVE_GCRYPT
case ARG_SETUP_KEYS:
arg_action = ACTION_SETUP_KEYS;
break;
case ARG_VERIFY:
arg_action = ACTION_VERIFY;
break;
case ARG_VERIFY_KEY:
arg_action = ACTION_VERIFY;
@ -235,6 +241,13 @@ static int parse_argv(int argc, char *argv[]) {
return -EINVAL;
}
break;
#else
case ARG_SETUP_KEYS:
case ARG_VERIFY_KEY:
case ARG_INTERVAL:
log_error("Forward-secure sealing not available.");
return -ENOTSUP;
#endif
case 'p': {
const char *dots;
@ -617,7 +630,8 @@ finish:
return r;
#else
log_error("Forward-secure journal verification not available.");
log_error("Forward-secure sealing not available.");
return -ENOTSUP;
#endif
}
@ -633,7 +647,7 @@ static int verify(sd_journal *j) {
usec_t from, to, total;
#ifdef HAVE_GCRYPT
if (!arg_verify_key && journal_file_fss_enabled(f))
if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
log_warning("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
#endif
@ -648,7 +662,7 @@ static int verify(sd_journal *j) {
char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
log_info("PASS: %s", f->path);
if (arg_verify_key && journal_file_fss_enabled(f))
if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
log_info("=> Validated from %s to %s, %s missing",
format_timestamp(a, sizeof(a), from),
format_timestamp(b, sizeof(b), to),

View File

@ -55,7 +55,7 @@ static int raw_verify(const char *fn, const char *verification_key) {
JournalFile *f;
int r;
r = journal_file_open(fn, O_RDONLY, 0666, true, true, NULL, NULL, NULL, &f);
r = journal_file_open(fn, O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, &f);
if (r < 0)
return r;
@ -107,18 +107,19 @@ int main(int argc, char *argv[]) {
log_info("Verifying...");
assert_se(journal_file_open("test.journal", O_RDONLY, 0666, true, true, NULL, NULL, NULL, &f) == 0);
assert_se(journal_file_open("test.journal", O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, &f) == 0);
/* journal_file_print_header(f); */
journal_file_dump(f);
assert_se(journal_file_verify(f, verification_key, &from, &to, &total, true) >= 0);
if (verification_key && journal_file_fss_enabled(f)) {
if (verification_key && JOURNAL_HEADER_SEALED(f->header)) {
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);
if (verification_key) {

View File

@ -59,7 +59,9 @@ int main(int argc, char *argv[]) {
iovec.iov_len = strlen(test);
assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
#ifdef HAVE_GCRYPT
journal_file_append_tag(f);
#endif
journal_file_dump(f);
assert(journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, &o, &p) == 1);