mirror of
https://github.com/systemd/systemd.git
synced 2025-08-25 13:49:55 +03:00
Merge pull request #16145 from poettering/qrcode-dlopen
journalctl: make libqrencode a weak (dlopen() style) dependency
This commit is contained in:
@ -1799,7 +1799,7 @@ public_programs += executable(
|
|||||||
include_directories : includes,
|
include_directories : includes,
|
||||||
link_with : [libshared],
|
link_with : [libshared],
|
||||||
dependencies : [threads,
|
dependencies : [threads,
|
||||||
libqrencode,
|
libdl,
|
||||||
libxz,
|
libxz,
|
||||||
liblz4,
|
liblz4,
|
||||||
libpcre2,
|
libpcre2,
|
||||||
|
40
src/basic/dlfcn-util.c
Normal file
40
src/basic/dlfcn-util.c
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
|
||||||
|
#include "dlfcn-util.h"
|
||||||
|
|
||||||
|
int dlsym_many_and_warn(void *dl, int level, ...) {
|
||||||
|
va_list ap;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* Tries to resolve a bunch of function symbols, and logs errors about the ones it cannot
|
||||||
|
* resolve. Note that this function possibly modifies the supplied function pointers if the whole
|
||||||
|
* operation fails */
|
||||||
|
|
||||||
|
va_start(ap, level);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
void (**fn)(void);
|
||||||
|
void (*tfn)(void);
|
||||||
|
const char *symbol;
|
||||||
|
|
||||||
|
fn = va_arg(ap, typeof(fn));
|
||||||
|
if (!fn)
|
||||||
|
break;
|
||||||
|
|
||||||
|
symbol = va_arg(ap, typeof(symbol));
|
||||||
|
|
||||||
|
tfn = (typeof(tfn)) dlsym(dl, symbol);
|
||||||
|
if (!tfn) {
|
||||||
|
r = log_full_errno(level,
|
||||||
|
SYNTHETIC_ERRNO(ELIBBAD),
|
||||||
|
"Can't find symbol %s: %s", symbol, dlerror());
|
||||||
|
va_end(ap);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
*fn = tfn;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
return 0;
|
||||||
|
}
|
@ -6,3 +6,5 @@
|
|||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
|
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(void*, dlclose);
|
DEFINE_TRIVIAL_CLEANUP_FUNC(void*, dlclose);
|
||||||
|
|
||||||
|
int dlsym_many_and_warn(void *dl, int level, ...);
|
||||||
|
@ -39,6 +39,7 @@ basic_sources = files('''
|
|||||||
device-nodes.h
|
device-nodes.h
|
||||||
dirent-util.c
|
dirent-util.c
|
||||||
dirent-util.h
|
dirent-util.h
|
||||||
|
dlfcn-util.c
|
||||||
dlfcn-util.h
|
dlfcn-util.h
|
||||||
efivars.c
|
efivars.c
|
||||||
efivars.h
|
efivars.h
|
||||||
|
@ -6,29 +6,34 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "alloc-util.h"
|
||||||
|
#include "dlfcn-util.h"
|
||||||
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "journal-qrcode.h"
|
#include "journal-qrcode.h"
|
||||||
|
#include "locale-util.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
|
#include "terminal-util.h"
|
||||||
|
|
||||||
#define WHITE_ON_BLACK "\033[40;37;1m"
|
#define ANSI_WHITE_ON_BLACK "\033[40;37;1m"
|
||||||
#define NORMAL "\033[0m"
|
|
||||||
|
|
||||||
static void print_border(FILE *output, unsigned width) {
|
static void print_border(FILE *output, unsigned width) {
|
||||||
unsigned x, y;
|
unsigned x, y;
|
||||||
|
|
||||||
/* Four rows of border */
|
/* Four rows of border */
|
||||||
for (y = 0; y < 4; y += 2) {
|
for (y = 0; y < 4; y += 2) {
|
||||||
fputs(WHITE_ON_BLACK, output);
|
fputs(ANSI_WHITE_ON_BLACK, output);
|
||||||
|
|
||||||
for (x = 0; x < 4 + width + 4; x++)
|
for (x = 0; x < 4 + width + 4; x++)
|
||||||
fputs("\342\226\210", output);
|
fputs("\342\226\210", output);
|
||||||
|
|
||||||
fputs(NORMAL "\n", output);
|
fputs(ANSI_NORMAL "\n", output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_qr_code(
|
int print_qr_code(
|
||||||
FILE *output,
|
FILE *output,
|
||||||
|
const char *prefix_text,
|
||||||
const void *seed,
|
const void *seed,
|
||||||
size_t seed_size,
|
size_t seed_size,
|
||||||
uint64_t start,
|
uint64_t start,
|
||||||
@ -36,15 +41,38 @@ int print_qr_code(
|
|||||||
const char *hn,
|
const char *hn,
|
||||||
sd_id128_t machine) {
|
sd_id128_t machine) {
|
||||||
|
|
||||||
FILE *f;
|
QRcode* (*sym_QRcode_encodeString)(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
|
||||||
char *url = NULL;
|
void (*sym_QRcode_free)(QRcode *qrcode);
|
||||||
|
_cleanup_(dlclosep) void *dl = NULL;
|
||||||
|
_cleanup_free_ char *url = NULL;
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
size_t url_size = 0, i;
|
size_t url_size = 0, i;
|
||||||
QRcode* qr;
|
|
||||||
unsigned x, y;
|
unsigned x, y;
|
||||||
|
QRcode* qr;
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(seed);
|
assert(seed);
|
||||||
assert(seed_size > 0);
|
assert(seed_size > 0);
|
||||||
|
|
||||||
|
/* If this is not an UTF-8 system or ANSI colors aren't supported/disabled don't print any QR
|
||||||
|
* codes */
|
||||||
|
if (!is_locale_utf8() || !colors_enabled())
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
dl = dlopen("libqrencode.so.4", RTLD_LAZY);
|
||||||
|
if (!dl)
|
||||||
|
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||||
|
"QRCODE support is not installed: %s", dlerror());
|
||||||
|
|
||||||
|
r = dlsym_many_and_warn(
|
||||||
|
dl,
|
||||||
|
LOG_DEBUG,
|
||||||
|
&sym_QRcode_encodeString, "QRcode_encodeString",
|
||||||
|
&sym_QRcode_free, "QRcode_free",
|
||||||
|
NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
f = open_memstream_unlocked(&url, &url_size);
|
f = open_memstream_unlocked(&url, &url_size);
|
||||||
if (!f)
|
if (!f)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -65,20 +93,19 @@ int print_qr_code(
|
|||||||
if (hn)
|
if (hn)
|
||||||
fprintf(f, ";hostname=%s", hn);
|
fprintf(f, ";hostname=%s", hn);
|
||||||
|
|
||||||
if (ferror(f)) {
|
r = fflush_and_check(f);
|
||||||
fclose(f);
|
if (r < 0)
|
||||||
free(url);
|
return r;
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(f);
|
f = safe_fclose(f);
|
||||||
|
|
||||||
qr = QRcode_encodeString(url, 0, QR_ECLEVEL_L, QR_MODE_8, 1);
|
|
||||||
free(url);
|
|
||||||
|
|
||||||
|
qr = sym_QRcode_encodeString(url, 0, QR_ECLEVEL_L, QR_MODE_8, 1);
|
||||||
if (!qr)
|
if (!qr)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (prefix_text)
|
||||||
|
fputs(prefix_text, output);
|
||||||
|
|
||||||
print_border(output, qr->width);
|
print_border(output, qr->width);
|
||||||
|
|
||||||
for (y = 0; y < (unsigned) qr->width; y += 2) {
|
for (y = 0; y < (unsigned) qr->width; y += 2) {
|
||||||
@ -87,7 +114,7 @@ int print_qr_code(
|
|||||||
row1 = qr->data + qr->width * y;
|
row1 = qr->data + qr->width * y;
|
||||||
row2 = row1 + qr->width;
|
row2 = row1 + qr->width;
|
||||||
|
|
||||||
fputs(WHITE_ON_BLACK, output);
|
fputs(ANSI_WHITE_ON_BLACK, output);
|
||||||
for (x = 0; x < 4; x++)
|
for (x = 0; x < 4; x++)
|
||||||
fputs("\342\226\210", output);
|
fputs("\342\226\210", output);
|
||||||
|
|
||||||
@ -109,11 +136,11 @@ int print_qr_code(
|
|||||||
|
|
||||||
for (x = 0; x < 4; x++)
|
for (x = 0; x < 4; x++)
|
||||||
fputs("\342\226\210", output);
|
fputs("\342\226\210", output);
|
||||||
fputs(NORMAL "\n", output);
|
fputs(ANSI_NORMAL "\n", output);
|
||||||
}
|
}
|
||||||
|
|
||||||
print_border(output, qr->width);
|
print_border(output, qr->width);
|
||||||
|
|
||||||
QRcode_free(qr);
|
sym_QRcode_free(qr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -6,4 +6,4 @@
|
|||||||
|
|
||||||
#include "sd-id128.h"
|
#include "sd-id128.h"
|
||||||
|
|
||||||
int print_qr_code(FILE *f, const void *seed, size_t seed_size, uint64_t start, uint64_t interval, const char *hn, sd_id128_t machine);
|
int print_qr_code(FILE *f, const char *prefix_text, const void *seed, size_t seed_size, uint64_t start, uint64_t interval, const char *hn, sd_id128_t machine);
|
||||||
|
@ -57,12 +57,13 @@
|
|||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "pretty-print.h"
|
#include "pretty-print.h"
|
||||||
|
#include "random-util.h"
|
||||||
#include "rlimit-util.h"
|
#include "rlimit-util.h"
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
#include "sigbus.h"
|
#include "sigbus.h"
|
||||||
|
#include "stdio-util.h"
|
||||||
#include "string-table.h"
|
#include "string-table.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "stdio-util.h"
|
|
||||||
#include "syslog-util.h"
|
#include "syslog-util.h"
|
||||||
#include "terminal-util.h"
|
#include "terminal-util.h"
|
||||||
#include "tmpfile-util.h"
|
#include "tmpfile-util.h"
|
||||||
@ -1774,12 +1775,14 @@ static int add_syslog_identifier(sd_journal *j) {
|
|||||||
static int setup_keys(void) {
|
static int setup_keys(void) {
|
||||||
#if HAVE_GCRYPT
|
#if HAVE_GCRYPT
|
||||||
size_t mpk_size, seed_size, state_size, i;
|
size_t mpk_size, seed_size, state_size, i;
|
||||||
|
_cleanup_(unlink_and_freep) char *k = NULL;
|
||||||
|
_cleanup_free_ char *p = NULL;
|
||||||
uint8_t *mpk, *seed, *state;
|
uint8_t *mpk, *seed, *state;
|
||||||
int fd = -1, r;
|
_cleanup_close_ int fd = -1;
|
||||||
sd_id128_t machine, boot;
|
sd_id128_t machine, boot;
|
||||||
char *p = NULL, *k = NULL;
|
|
||||||
uint64_t n;
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
uint64_t n;
|
||||||
|
int r;
|
||||||
|
|
||||||
r = stat("/var/log/journal", &st);
|
r = stat("/var/log/journal", &st);
|
||||||
if (r < 0 && !IN_SET(errno, ENOENT, ENOTDIR))
|
if (r < 0 && !IN_SET(errno, ENOENT, ENOTDIR))
|
||||||
@ -1805,21 +1808,15 @@ static int setup_keys(void) {
|
|||||||
|
|
||||||
if (arg_force) {
|
if (arg_force) {
|
||||||
r = unlink(p);
|
r = unlink(p);
|
||||||
if (r < 0 && errno != ENOENT) {
|
if (r < 0 && errno != ENOENT)
|
||||||
r = log_error_errno(errno, "unlink(\"%s\") failed: %m", p);
|
return log_error_errno(errno, "unlink(\"%s\") failed: %m", p);
|
||||||
goto finish;
|
} else if (access(p, F_OK) >= 0)
|
||||||
}
|
return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
|
||||||
} else if (access(p, F_OK) >= 0) {
|
"Sealing key file %s exists already. Use --force to recreate.", p);
|
||||||
log_error("Sealing key file %s exists already. Use --force to recreate.", p);
|
|
||||||
r = -EEXIST;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
|
if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
|
||||||
SD_ID128_FORMAT_VAL(machine)) < 0) {
|
SD_ID128_FORMAT_VAL(machine)) < 0)
|
||||||
r = log_oom();
|
return log_oom();
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
|
mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
|
||||||
mpk = alloca(mpk_size);
|
mpk = alloca(mpk_size);
|
||||||
@ -1830,18 +1827,10 @@ static int setup_keys(void) {
|
|||||||
state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
|
state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
|
||||||
state = alloca(state_size);
|
state = alloca(state_size);
|
||||||
|
|
||||||
fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
|
||||||
if (fd < 0) {
|
|
||||||
r = log_error_errno(errno, "Failed to open /dev/random: %m");
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_info("Generating seed...");
|
log_info("Generating seed...");
|
||||||
r = loop_read_exact(fd, seed, seed_size, true);
|
r = genuine_random_bytes(seed, seed_size, RANDOM_BLOCK);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
log_error_errno(r, "Failed to read random seed: %m");
|
return log_error_errno(r, "Failed to acquire random seed: %m");
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_info("Generating key pair...");
|
log_info("Generating key pair...");
|
||||||
FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
|
FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
|
||||||
@ -1856,18 +1845,25 @@ static int setup_keys(void) {
|
|||||||
|
|
||||||
safe_close(fd);
|
safe_close(fd);
|
||||||
fd = mkostemp_safe(k);
|
fd = mkostemp_safe(k);
|
||||||
if (fd < 0) {
|
if (fd < 0)
|
||||||
r = log_error_errno(fd, "Failed to open %s: %m", k);
|
return log_error_errno(fd, "Failed to open %s: %m", k);
|
||||||
goto finish;
|
|
||||||
|
/* Enable secure remove, exclusion from dump, synchronous writing and in-place updating */
|
||||||
|
static const unsigned chattr_flags[] = {
|
||||||
|
FS_SECRM_FL,
|
||||||
|
FS_NODUMP_FL,
|
||||||
|
FS_SYNC_FL,
|
||||||
|
FS_NOCOW_FL,
|
||||||
|
};
|
||||||
|
for (size_t j = 0; j < ELEMENTSOF(chattr_flags); j++) {
|
||||||
|
r = chattr_fd(fd, chattr_flags[j], chattr_flags[j], NULL);
|
||||||
|
if (r < 0)
|
||||||
|
log_full_errno(ERRNO_IS_NOT_SUPPORTED(r) ? LOG_DEBUG : LOG_WARNING, r,
|
||||||
|
"Failed to set file attribute 0x%x: %m", chattr_flags[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable secure remove, exclusion from dump, synchronous
|
|
||||||
* writing and in-place updating */
|
|
||||||
r = chattr_fd(fd, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, NULL);
|
|
||||||
if (r < 0)
|
|
||||||
log_warning_errno(r, "Failed to set file attributes: %m");
|
|
||||||
|
|
||||||
struct FSSHeader h = {
|
struct FSSHeader h = {
|
||||||
|
.signature = { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' },
|
||||||
.machine_id = machine,
|
.machine_id = machine,
|
||||||
.boot_id = boot,
|
.boot_id = boot,
|
||||||
.header_size = htole64(sizeof(h)),
|
.header_size = htole64(sizeof(h)),
|
||||||
@ -1877,24 +1873,18 @@ static int setup_keys(void) {
|
|||||||
.fsprg_state_size = htole64(state_size),
|
.fsprg_state_size = htole64(state_size),
|
||||||
};
|
};
|
||||||
|
|
||||||
memcpy(h.signature, "KSHHRHLP", 8);
|
|
||||||
|
|
||||||
r = loop_write(fd, &h, sizeof(h), false);
|
r = loop_write(fd, &h, sizeof(h), false);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
log_error_errno(r, "Failed to write header: %m");
|
return log_error_errno(r, "Failed to write header: %m");
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = loop_write(fd, state, state_size, false);
|
r = loop_write(fd, state, state_size, false);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
log_error_errno(r, "Failed to write state: %m");
|
return log_error_errno(r, "Failed to write state: %m");
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (link(k, p) < 0) {
|
if (rename(k, p) < 0)
|
||||||
r = log_error_errno(errno, "Failed to link file: %m");
|
return log_error_errno(errno, "Failed to link file: %m");
|
||||||
goto finish;
|
|
||||||
}
|
k = mfree(k);
|
||||||
|
|
||||||
if (on_tty()) {
|
if (on_tty()) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@ -1923,7 +1913,8 @@ static int setup_keys(void) {
|
|||||||
printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
|
printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
|
||||||
|
|
||||||
if (on_tty()) {
|
if (on_tty()) {
|
||||||
char tsb[FORMAT_TIMESPAN_MAX], *hn;
|
_cleanup_free_ char *hn = NULL;
|
||||||
|
char tsb[FORMAT_TIMESPAN_MAX];
|
||||||
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s\n"
|
"%s\n"
|
||||||
@ -1932,7 +1923,6 @@ static int setup_keys(void) {
|
|||||||
format_timespan(tsb, sizeof(tsb), arg_interval, 0));
|
format_timespan(tsb, sizeof(tsb), arg_interval, 0));
|
||||||
|
|
||||||
hn = gethostname_malloc();
|
hn = gethostname_malloc();
|
||||||
|
|
||||||
if (hn) {
|
if (hn) {
|
||||||
hostname_cleanup(hn);
|
hostname_cleanup(hn);
|
||||||
fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
|
fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
|
||||||
@ -1940,28 +1930,15 @@ static int setup_keys(void) {
|
|||||||
fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
|
fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
|
||||||
|
|
||||||
#if HAVE_QRENCODE
|
#if HAVE_QRENCODE
|
||||||
/* If this is not an UTF-8 system don't print any QR codes */
|
(void) print_qr_code(stderr,
|
||||||
if (is_locale_utf8()) {
|
"\nTo transfer the verification key to your phone please scan the QR code below:\n\n",
|
||||||
fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
|
seed, seed_size,
|
||||||
print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
|
n, arg_interval,
|
||||||
}
|
hn, machine);
|
||||||
#endif
|
#endif
|
||||||
free(hn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r = 0;
|
return 0;
|
||||||
|
|
||||||
finish:
|
|
||||||
safe_close(fd);
|
|
||||||
|
|
||||||
if (k) {
|
|
||||||
(void) unlink(k);
|
|
||||||
free(k);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(p);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
#else
|
#else
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||||
"Forward-secure sealing not available.");
|
"Forward-secure sealing not available.");
|
||||||
|
Reference in New Issue
Block a user