From cbae575e0f63b47ed3809ce6c68d385a66a4ca5e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 2 Nov 2021 18:20:12 +0100 Subject: keyring-util: add new keyring-util.h helpers This adds to new helpers: keyring_read() for reading a key data from a keyring entry, and TAKE_KEY_SERIAL which is what TAKE_FD is for fds, but for key_serial_t. The former is immediately used by ask-password-api.c --- src/shared/ask-password-api.c | 32 ++++++++------------------------ src/shared/keyring-util.c | 38 ++++++++++++++++++++++++++++++++++++++ src/shared/keyring-util.h | 17 +++++++++++++++++ src/shared/meson.build | 2 ++ 4 files changed, 65 insertions(+), 24 deletions(-) create mode 100644 src/shared/keyring-util.c create mode 100644 src/shared/keyring-util.h diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index a60ccee4d8..367c1df240 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -28,6 +28,7 @@ #include "fs-util.h" #include "glyph-util.h" #include "io-util.h" +#include "keyring-util.h" #include "log.h" #include "macro.h" #include "memory-util.h" @@ -62,35 +63,18 @@ static int lookup_key(const char *keyname, key_serial_t *ret) { } static int retrieve_key(key_serial_t serial, char ***ret) { - size_t nfinal, m = 100; + _cleanup_(erase_and_freep) void *p = NULL; char **l; - _cleanup_(erase_and_freep) char *pfinal = NULL; + size_t n; + int r; assert(ret); - for (;;) { - _cleanup_(erase_and_freep) char *p = NULL; - long n; - - p = new(char, m); - if (!p) - return -ENOMEM; - - n = keyctl(KEYCTL_READ, (unsigned long) serial, (unsigned long) p, (unsigned long) m, 0); - if (n < 0) - return -errno; - if ((size_t) n <= m) { - nfinal = (size_t) n; - pfinal = TAKE_PTR(p); - break; - } - - if (m > LONG_MAX / 2) /* overflow check */ - return -ENOMEM; - m *= 2; - } + r = keyring_read(serial, &p, &n); + if (r < 0) + return r; - l = strv_parse_nulstr(pfinal, nfinal); + l = strv_parse_nulstr(p, n); if (!l) return -ENOMEM; diff --git a/src/shared/keyring-util.c b/src/shared/keyring-util.c new file mode 100644 index 0000000000..655cf5241d --- /dev/null +++ b/src/shared/keyring-util.c @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "keyring-util.h" +#include "memory-util.h" +#include "missing_syscall.h" + +int keyring_read(key_serial_t serial, void **ret, size_t *ret_size) { + size_t m = 100; + + for (;;) { + _cleanup_(erase_and_freep) uint8_t *p = NULL; + long n; + + p = new(uint8_t, m+1); + if (!p) + return -ENOMEM; + + n = keyctl(KEYCTL_READ, (unsigned long) serial, (unsigned long) p, (unsigned long) m, 0); + if (n < 0) + return -errno; + + if ((size_t) n <= m) { + p[n] = 0; /* NUL terminate, just in case */ + + if (ret) + *ret = TAKE_PTR(p); + if (ret_size) + *ret_size = n; + + return 0; + } + + if (m > (SIZE_MAX-1) / 2) /* overflow check */ + return -ENOMEM; + + m *= 2; + } +} diff --git a/src/shared/keyring-util.h b/src/shared/keyring-util.h new file mode 100644 index 0000000000..838e990b80 --- /dev/null +++ b/src/shared/keyring-util.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include + +#include "missing_keyctl.h" + +/* TAKE_FD but for key_serial_t instead of fds */ +#define TAKE_KEY_SERIAL(key_serial) \ + ({ \ + key_serial_t *_key_serialp_ = &(key_serial); \ + key_serial_t _key_serial_ = *_key_serialp_; \ + *_key_serialp_ = -1; \ + _key_serial_; \ + }) + +int keyring_read(key_serial_t serial, void **ret, size_t *ret_size); diff --git a/src/shared/meson.build b/src/shared/meson.build index a23d43ce09..229e58beba 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -173,6 +173,8 @@ shared_sources = files(''' json.h kbd-util.c kbd-util.h + keyring-util.h + keyring-util.c killall.c killall.h label.c -- cgit v1.2.1