From 9337945233ce174ab924e81e1beba5d3df1a4a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 23 Oct 2020 20:19:05 +0200 Subject: [PATCH 1/4] meson: sort include dirs Our headers should have unique names, so the sort order shouldn't matter. --- meson.build | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/meson.build b/meson.build index 7c2d4e8b10..8cf76c61b5 100644 --- a/meson.build +++ b/meson.build @@ -1561,21 +1561,11 @@ meson_apply_m4 = find_program('tools/meson-apply-m4.sh') includes = include_directories('src/basic', 'src/boot', + 'src/core', 'src/home', - 'src/shared', - 'src/systemd', 'src/journal', 'src/journal-remote', - 'src/nspawn', - 'src/resolve', - 'src/timesync', - 'src/time-wait-sync', - 'src/login', - 'src/udev', - 'src/libudev', - 'src/core', - 'src/shutdown', - 'src/xdg-autostart-generator', + 'src/libsystemd-network', 'src/libsystemd/sd-bus', 'src/libsystemd/sd-device', 'src/libsystemd/sd-event', @@ -1584,7 +1574,17 @@ includes = include_directories('src/basic', 'src/libsystemd/sd-netlink', 'src/libsystemd/sd-network', 'src/libsystemd/sd-resolve', - 'src/libsystemd-network', + 'src/libudev', + 'src/login', + 'src/nspawn', + 'src/resolve', + 'src/shared', + 'src/shutdown', + 'src/systemd', + 'src/time-wait-sync', + 'src/timesync', + 'src/udev', + 'src/xdg-autostart-generator', '.') add_project_arguments('-include', 'config.h', language : 'c') From c9e9a57fce214b24d250921654b101ff433962e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 23 Oct 2020 20:35:47 +0200 Subject: [PATCH 2/4] shared/qrcode-util: reduce scope of iterator variables --- src/shared/qrcode-util.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/shared/qrcode-util.c b/src/shared/qrcode-util.c index a545daaef3..99995eb893 100644 --- a/src/shared/qrcode-util.c +++ b/src/shared/qrcode-util.c @@ -4,13 +4,11 @@ #define ANSI_WHITE_ON_BLACK "\033[40;37;1m" static void print_border(FILE *output, unsigned width) { - unsigned x, y; - /* Four rows of border */ - for (y = 0; y < 4; y += 2) { + for (unsigned y = 0; y < 4; y += 2) { fputs(ANSI_WHITE_ON_BLACK, output); - for (x = 0; x < 4 + width + 4; x++) + for (unsigned x = 0; x < 4 + width + 4; x++) fputs("\342\226\210", output); fputs(ANSI_NORMAL "\n", output); @@ -18,8 +16,6 @@ static void print_border(FILE *output, unsigned width) { } void write_qrcode(FILE *output, QRcode *qr) { - unsigned x, y; - assert(qr); if (!output) @@ -27,17 +23,15 @@ void write_qrcode(FILE *output, QRcode *qr) { print_border(output, qr->width); - for (y = 0; y < (unsigned) qr->width; y += 2) { - const uint8_t *row1, *row2; - - row1 = qr->data + qr->width * y; - row2 = row1 + qr->width; + for (unsigned y = 0; y < (unsigned) qr->width; y += 2) { + const uint8_t *row1 = qr->data + qr->width * y; + const uint8_t *row2 = row1 + qr->width; fputs(ANSI_WHITE_ON_BLACK, output); - for (x = 0; x < 4; x++) + for (unsigned x = 0; x < 4; x++) fputs("\342\226\210", output); - for (x = 0; x < (unsigned) qr->width; x ++) { + for (unsigned x = 0; x < (unsigned) qr->width; x++) { bool a, b; a = row1[x] & 1; @@ -53,7 +47,7 @@ void write_qrcode(FILE *output, QRcode *qr) { fputs("\342\226\210", output); } - for (x = 0; x < 4; x++) + for (unsigned x = 0; x < 4; x++) fputs("\342\226\210", output); fputs(ANSI_NORMAL "\n", output); } From f1b823596f8a4dc6b1f76206b7473bac71e3840b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 25 Oct 2020 12:11:21 +0100 Subject: [PATCH 3/4] journal,homectl: unify implementations of libqrencode loading and fss key printing We had two of each: both homectl and journalctl had the whole dlopen() wrapper, and journalctl had two implementations (slightly different) of the code to print the fss:// pattern. print_qrcode() now returns -EOPNOTSUPP when compiled with qrcode support. Both callers ignore the return value, so this changes nothing. No functional change. --- src/home/homectl-recovery-key.c | 51 +---------------- src/journal/journal-qrcode.c | 97 --------------------------------- src/journal/journal-qrcode.h | 9 --- src/journal/journalctl.c | 75 ++++++++++++++++++++----- src/journal/meson.build | 5 -- src/shared/meson.build | 9 +-- src/shared/qrcode-util.c | 50 ++++++++++++++++- src/shared/qrcode-util.h | 12 ++-- 8 files changed, 123 insertions(+), 185 deletions(-) delete mode 100644 src/journal/journal-qrcode.c delete mode 100644 src/journal/journal-qrcode.h diff --git a/src/home/homectl-recovery-key.c b/src/home/homectl-recovery-key.c index c63d3415f4..3311205db5 100644 --- a/src/home/homectl-recovery-key.c +++ b/src/home/homectl-recovery-key.c @@ -1,17 +1,12 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -#if HAVE_QRENCODE -#include -#include "qrcode-util.h" -#endif - -#include "dlfcn-util.h" #include "errno-util.h" #include "homectl-recovery-key.h" #include "libcrypt-util.h" #include "locale-util.h" #include "memory-util.h" #include "modhex.h" +#include "qrcode-util.h" #include "random-util.h" #include "strv.h" #include "terminal-util.h" @@ -140,48 +135,6 @@ static int add_secret(JsonVariant **v, const char *password) { return 0; } -static int print_qr_code(const char *secret) { -#if HAVE_QRENCODE - QRcode* (*sym_QRcode_encodeString)(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); - void (*sym_QRcode_free)(QRcode *qrcode); - _cleanup_(dlclosep) void *dl = NULL; - QRcode* qr; - int r; - - /* 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; - - qr = sym_QRcode_encodeString(secret, 0, QR_ECLEVEL_L, QR_MODE_8, 0); - if (!qr) - return -ENOMEM; - - fprintf(stderr, "\nYou may optionally scan the recovery key off screen:\n\n"); - - write_qrcode(stderr, qr); - - fputc('\n', stderr); - - sym_QRcode_free(qr); -#endif - return 0; -} - int identity_add_recovery_key(JsonVariant **v) { _cleanup_(erase_and_freep) char *password = NULL, *hashed = NULL; int r; @@ -240,7 +193,7 @@ int identity_add_recovery_key(JsonVariant **v) { "whenever authentication is requested.\n", stderr); fflush(stderr); - print_qr_code(password); + (void) print_qrcode(stderr, "You may optionally scan the recovery key off screen", password); return 0; } diff --git a/src/journal/journal-qrcode.c b/src/journal/journal-qrcode.c deleted file mode 100644 index e8a7655316..0000000000 --- a/src/journal/journal-qrcode.c +++ /dev/null @@ -1,97 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ - -#include -#include -#include -#include -#include - -#include "alloc-util.h" -#include "dlfcn-util.h" -#include "fd-util.h" -#include "fileio.h" -#include "journal-qrcode.h" -#include "locale-util.h" -#include "macro.h" -#include "qrcode-util.h" -#include "terminal-util.h" - -int print_qr_code( - FILE *output, - const char *prefix_text, - const void *seed, - size_t seed_size, - uint64_t start, - uint64_t interval, - const char *hn, - sd_id128_t machine) { - - QRcode* (*sym_QRcode_encodeString)(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); - 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; - QRcode* qr; - int r; - - assert(seed); - 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); - if (!f) - return -ENOMEM; - - fputs("fss://", f); - - for (size_t i = 0; i < seed_size; i++) { - if (i > 0 && i % 3 == 0) - fputc('-', f); - fprintf(f, "%02x", ((uint8_t*) seed)[i]); - } - - fprintf(f, "/%"PRIx64"-%"PRIx64"?machine=" SD_ID128_FORMAT_STR, - start, - interval, - SD_ID128_FORMAT_VAL(machine)); - - if (hn) - fprintf(f, ";hostname=%s", hn); - - r = fflush_and_check(f); - if (r < 0) - return r; - - f = safe_fclose(f); - - qr = sym_QRcode_encodeString(url, 0, QR_ECLEVEL_L, QR_MODE_8, 1); - if (!qr) - return -ENOMEM; - - if (prefix_text) - fputs(prefix_text, output); - - write_qrcode(output, qr); - - sym_QRcode_free(qr); - return 0; -} diff --git a/src/journal/journal-qrcode.h b/src/journal/journal-qrcode.h deleted file mode 100644 index 24ae9d32ee..0000000000 --- a/src/journal/journal-qrcode.h +++ /dev/null @@ -1,9 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ -#pragma once - -#include -#include - -#include "sd-id128.h" - -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); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index e43e9d1afa..4014b8aad2 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -43,7 +43,6 @@ #include "io-util.h" #include "journal-def.h" #include "journal-internal.h" -#include "journal-qrcode.h" #include "journal-util.h" #include "journal-vacuum.h" #include "journal-verify.h" @@ -60,6 +59,7 @@ #include "path-util.h" #include "pcre2-dlopen.h" #include "pretty-print.h" +#include "qrcode-util.h" #include "random-util.h" #include "rlimit-util.h" #include "set.h" @@ -1779,6 +1779,53 @@ static int add_syslog_identifier(sd_journal *j) { return 0; } +static int format_journal_url( + const void *seed, + size_t seed_size, + uint64_t start, + uint64_t interval, + const char *hn, + sd_id128_t machine, + bool full, + char **ret_url) { + _cleanup_free_ char *url = NULL; + _cleanup_fclose_ FILE *f = NULL; + size_t url_size = 0; + int r; + + assert(seed); + assert(seed_size > 0); + + f = open_memstream_unlocked(&url, &url_size); + if (!f) + return -ENOMEM; + + if (full) + fputs("fss://", f); + + for (size_t i = 0; i < seed_size; i++) { + if (i > 0 && i % 3 == 0) + fputc('-', f); + fprintf(f, "%02x", ((uint8_t*) seed)[i]); + } + + fprintf(f, "/%"PRIx64"-%"PRIx64, start, interval); + + if (full) { + fprintf(f, "?machine=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(machine)); + if (hn) + fprintf(f, ";hostname=%s", hn); + } + + r = fflush_and_check(f); + if (r < 0) + return r; + + f = safe_fclose(f); + *ret_url = TAKE_PTR(url); + return 0; +} + static int setup_keys(void) { #if HAVE_GCRYPT size_t mpk_size, seed_size, state_size; @@ -1893,7 +1940,11 @@ static int setup_keys(void) { k = mfree(k); - _cleanup_free_ char *hn = NULL; + _cleanup_free_ char *hn = NULL, *key = NULL; + + r = format_journal_url(seed, seed_size, n, arg_interval, hn, machine, false, &key); + if (r < 0) + return r; if (on_tty()) { hn = gethostname_malloc(); @@ -1925,21 +1976,19 @@ static int setup_keys(void) { fflush(stderr); } - for (size_t i = 0; i < seed_size; i++) { - if (i > 0 && i % 3 == 0) - putchar('-'); - printf("%02x", ((uint8_t*) seed)[i]); - } - printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval); + puts(key); if (on_tty()) { fprintf(stderr, "%s", ansi_normal()); #if HAVE_QRENCODE - (void) print_qr_code(stderr, - "\nTo transfer the verification key to your phone scan the QR code below:\n", - seed, seed_size, - n, arg_interval, - hn, machine); + _cleanup_free_ char *url = NULL; + r = format_journal_url(seed, seed_size, n, arg_interval, hn, machine, true, &url); + if (r < 0) + return r; + + (void) print_qrcode(stderr, + "To transfer the verification key to your phone scan the QR code below", + url); #endif } diff --git a/src/journal/meson.build b/src/journal/meson.build index 3a590bdc6c..215ba949e7 100644 --- a/src/journal/meson.build +++ b/src/journal/meson.build @@ -107,11 +107,6 @@ journalctl_sources = files(''' pcre2-dlopen.h '''.split()) -if conf.get('HAVE_QRENCODE') == 1 - journalctl_sources += files('journal-qrcode.c', - 'journal-qrcode.h') -endif - install_data('journald.conf', install_dir : pkgsysconfdir) diff --git a/src/shared/meson.build b/src/shared/meson.build index 0ed216f1aa..260ee5a8b6 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -195,6 +195,8 @@ shared_sources = files(''' ptyfwd.h pwquality-util.c pwquality-util.h + qrcode-util.c + qrcode-util.h reboot-util.c reboot-util.h resize-fs.c @@ -304,13 +306,6 @@ if conf.get('HAVE_PAM') == 1 '''.split()) endif -if conf.get('HAVE_QRENCODE') == 1 - shared_sources += files(''' - qrcode-util.c - qrcode-util.h -'''.split()) -endif - generate_ip_protocol_list = find_program('generate-ip-protocol-list.sh') ip_protocol_list_txt = custom_target( 'ip-protocol-list.txt', diff --git a/src/shared/qrcode-util.c b/src/shared/qrcode-util.c index 99995eb893..4094c4ff3b 100644 --- a/src/shared/qrcode-util.c +++ b/src/shared/qrcode-util.c @@ -1,4 +1,10 @@ #include "qrcode-util.h" + +#if HAVE_QRENCODE +#include + +#include "dlfcn-util.h" +#include "locale-util.h" #include "terminal-util.h" #define ANSI_WHITE_ON_BLACK "\033[40;37;1m" @@ -15,7 +21,7 @@ static void print_border(FILE *output, unsigned width) { } } -void write_qrcode(FILE *output, QRcode *qr) { +static void write_qrcode(FILE *output, QRcode *qr) { assert(qr); if (!output) @@ -55,3 +61,45 @@ void write_qrcode(FILE *output, QRcode *qr) { print_border(output, qr->width); fflush(output); } + +int print_qrcode(FILE *out, const char *header, const char *string) { + QRcode* (*sym_QRcode_encodeString)(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); + void (*sym_QRcode_free)(QRcode *qrcode); + _cleanup_(dlclosep) void *dl = NULL; + QRcode* qr; + int r; + + /* 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; + + qr = sym_QRcode_encodeString(string, 0, QR_ECLEVEL_L, QR_MODE_8, 0); + if (!qr) + return -ENOMEM; + + if (header) + fprintf(out, "\n%s:\n\n", header); + + write_qrcode(out, qr); + + fputc('\n', out); + + sym_QRcode_free(qr); + return 0; +} +#endif diff --git a/src/shared/qrcode-util.h b/src/shared/qrcode-util.h index 9a21ffd7fe..036c3f7f90 100644 --- a/src/shared/qrcode-util.h +++ b/src/shared/qrcode-util.h @@ -1,9 +1,13 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ + #pragma once +#include +#include #if HAVE_QRENCODE -#include -#include - -void write_qrcode(FILE *output, QRcode *qr); +int print_qrcode(FILE *out, const char *header, const char *string); +#else +static inline int print_qrcode(FILE *out, const char *header, const char *string) { + return -EOPNOTSUPP; +} #endif From 158b28313f5ff978b98ea2006608ff8e6bb695c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 25 Oct 2020 12:20:38 +0100 Subject: [PATCH 4/4] test: add a simple test for the qr printing code Ideally, we'd read back what we wrote, but that would have been much more complicated. But just writing stuff is useful to test under valgrind or manually. --- src/test/meson.build | 4 ++++ src/test/test-qrcode-util.c | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/test/test-qrcode-util.c diff --git a/src/test/meson.build b/src/test/meson.build index ac1182e37a..71f3e12178 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -808,6 +808,10 @@ tests += [ [['src/test/test-psi-util.c'], [], []], + + [['src/test/test-qrcode-util.c'], + [libshared], + [libdl]], ] ############################################################ diff --git a/src/test/test-qrcode-util.c b/src/test/test-qrcode-util.c new file mode 100644 index 0000000000..c4e2894eb7 --- /dev/null +++ b/src/test/test-qrcode-util.c @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "locale-util.h" +#include "main-func.h" +#include "qrcode-util.h" +#include "tests.h" + +static int run(int argc, char **argv) { + int r; + + test_setup_logging(LOG_DEBUG); + + assert_se(setenv("SYSTEMD_COLORS", "1", 1) == 0); /* Force the qrcode to be printed */ + + r = print_qrcode(stdout, "This should say \"TEST\"", "TEST"); + if (r == -EOPNOTSUPP) + return log_tests_skipped("not supported"); + if (r < 0) + return log_error_errno(r, "Failed to print QR code: %m"); + return 0; +} + +DEFINE_MAIN_FUNCTION(run);