mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
journal: make libgcrypt dependency optional
This commit is contained in:
parent
8088cbd3cf
commit
feb12d3ed2
@ -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
1
README
@ -42,6 +42,7 @@ REQUIREMENTS:
|
||||
libcap
|
||||
PAM >= 1.1.2 (optional)
|
||||
libcryptsetup (optional)
|
||||
libgcrypt (optional)
|
||||
libaudit (optional)
|
||||
libacl (optional)
|
||||
libselinux (optional)
|
||||
|
6
TODO
6
TODO
@ -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
|
||||
|
@ -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 ;;
|
||||
|
@ -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_
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 ++;
|
||||
|
@ -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),
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user