Compare commits
20 Commits
5e258d734a
...
d2841d563e
Author | SHA1 | Date |
---|---|---|
Anita Zhang | d2841d563e | |
Lennart Poettering | 1817be807f | |
Lennart Poettering | 3f440b13b7 | |
Lennart Poettering | 10e8a60baa | |
Lennart Poettering | 335d2eadca | |
Lennart Poettering | 2fef50cd9e | |
Lennart Poettering | 554c4beb47 | |
Lennart Poettering | efe4266240 | |
Zbigniew Jędrzejewski-Szmek | 5d3fe6f78d | |
Zbigniew Jędrzejewski-Szmek | bd99297bd3 | |
Zbigniew Jędrzejewski-Szmek | 35e22827a9 | |
Zbigniew Jędrzejewski-Szmek | 9de324c3c9 | |
Zbigniew Jędrzejewski-Szmek | 2b49f0ca83 | |
Zbigniew Jędrzejewski-Szmek | e8644a414a | |
Zbigniew Jędrzejewski-Szmek | 83764f8d00 | |
Zbigniew Jędrzejewski-Szmek | 999b49c818 | |
Zbigniew Jędrzejewski-Szmek | 6016b4b0ba | |
Zbigniew Jędrzejewski-Szmek | 2ae297fe0d | |
Zbigniew Jędrzejewski-Szmek | a937ce2d85 | |
Zbigniew Jędrzejewski-Szmek | 0e98d17e77 |
23
TODO
23
TODO
|
@ -20,11 +20,23 @@ Janitorial Clean-ups:
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
|
||||||
* nss-systemd: also synthesize shadow records for users/groups
|
* add wrapper for mount() that uses O_PATH on the destination and than mounts
|
||||||
|
to /proc/self/fd/xxx so that we basically have a mount() with O_NOFOLLOW like
|
||||||
|
behaviour. (in case of bind mounts do it on both source and target)
|
||||||
|
|
||||||
* nspawn: move "incoming mount" directory to /run/host, move "inaccessible"
|
* add root=tmpfs that mounts a tmpfs to /sysroot (to be used in combination
|
||||||
nodes to /run/host, move notify socket (for sd_notify() between payload and
|
with usr=…, for a similar effect as systemd.volatile=yes but without the
|
||||||
container manager)
|
"hide-out" effect). Also, add root=gpt-auto-late support or so, that is like
|
||||||
|
root=gpt-auto but initially mounts a tmpfs to /sysroot, and then revisits
|
||||||
|
later after systemd-repart ran. Usecase: let's ship images with only /usr
|
||||||
|
partition, then on first boot create the root partition. In this case we want
|
||||||
|
to read the repart data from /usr before the root partition exists. Add
|
||||||
|
usr=gpt-auto that automatically finds a /usr partition.
|
||||||
|
|
||||||
|
* homed: keep an fd to the homedir open at all times, to keep the fs pinned
|
||||||
|
(autofs and such) while user is loged in.
|
||||||
|
|
||||||
|
* nss-systemd: also synthesize shadow records for users/groups
|
||||||
|
|
||||||
* make use of new glibc 2.32 APIs sigabbrev_np() and strerrorname_np().
|
* make use of new glibc 2.32 APIs sigabbrev_np() and strerrorname_np().
|
||||||
|
|
||||||
|
@ -65,9 +77,6 @@ Features:
|
||||||
often for one, let's turn it off entirely for a while. Use that for the
|
often for one, let's turn it off entirely for a while. Use that for the
|
||||||
/proc/self/mountinfo logic.
|
/proc/self/mountinfo logic.
|
||||||
|
|
||||||
* move our systemd-user PAM snippet to /usr/, which PAM appears to support
|
|
||||||
these days
|
|
||||||
|
|
||||||
* nspawn: support time namespaces
|
* nspawn: support time namespaces
|
||||||
|
|
||||||
* systemd-firstboot: make sure to always use chase_symlinks() before
|
* systemd-firstboot: make sure to always use chase_symlinks() before
|
||||||
|
|
|
@ -1370,15 +1370,18 @@
|
||||||
|
|
||||||
<listitem><para>Configures how to set up standard input, output and error output for the container
|
<listitem><para>Configures how to set up standard input, output and error output for the container
|
||||||
payload, as well as the <filename>/dev/console</filename> device for the container. Takes one of
|
payload, as well as the <filename>/dev/console</filename> device for the container. Takes one of
|
||||||
<option>interactive</option>, <option>read-only</option>, <option>passive</option>, or
|
<option>interactive</option>, <option>read-only</option>, <option>passive</option>,
|
||||||
<option>pipe</option>. If <option>interactive</option>, a pseudo-TTY is allocated and made available
|
<option>pipe</option> or <option>autopipe</option>. If <option>interactive</option>, a pseudo-TTY is
|
||||||
as <filename>/dev/console</filename> in the container. It is then bi-directionally connected to the
|
allocated and made available as <filename>/dev/console</filename> in the container. It is then
|
||||||
standard input and output passed to <command>systemd-nspawn</command>. <option>read-only</option> is
|
bi-directionally connected to the standard input and output passed to
|
||||||
similar but only the output of the container is propagated and no input from the caller is read. If
|
<command>systemd-nspawn</command>. <option>read-only</option> is similar but only the output of the
|
||||||
<option>passive</option>, a pseudo TTY is allocated, but it is not connected anywhere. Finally, in
|
container is propagated and no input from the caller is read. If <option>passive</option>, a pseudo
|
||||||
<option>pipe</option> mode no pseudo TTY is allocated, but the standard input, output and error
|
TTY is allocated, but it is not connected anywhere. In <option>pipe</option> mode no pseudo TTY is
|
||||||
output file descriptors passed to <command>systemd-nspawn</command> are passed on — as they are — to
|
allocated, but the standard input, output and error output file descriptors passed to
|
||||||
the container payload, see the following paragraph. Defaults to <option>interactive</option> if
|
<command>systemd-nspawn</command> are passed on — as they are — to the container payload, see the
|
||||||
|
following paragraph. Finally, <option>autopipe</option> mode operates like
|
||||||
|
<option>interactive</option> when <command>systemd-nspawn</command> is invoked on a terminal, and
|
||||||
|
like <option>pipe</option> otherwise. Defaults to <option>interactive</option> if
|
||||||
<command>systemd-nspawn</command> is invoked from a terminal, and <option>read-only</option>
|
<command>systemd-nspawn</command> is invoked from a terminal, and <option>read-only</option>
|
||||||
otherwise.</para>
|
otherwise.</para>
|
||||||
|
|
||||||
|
|
11
meson.build
11
meson.build
|
@ -882,6 +882,17 @@ libm = cc.find_library('m')
|
||||||
libdl = cc.find_library('dl')
|
libdl = cc.find_library('dl')
|
||||||
libcrypt = cc.find_library('crypt')
|
libcrypt = cc.find_library('crypt')
|
||||||
|
|
||||||
|
crypt_header = conf.get('HAVE_CRYPT_H') == 1 ? \
|
||||||
|
'''#include <crypt.h>''' : '''#include <unistd.h>'''
|
||||||
|
foreach ident : [
|
||||||
|
['crypt_ra', crypt_header],
|
||||||
|
['crypt_gensalt_ra', crypt_header]]
|
||||||
|
|
||||||
|
have = cc.has_function(ident[0], prefix : ident[1], args : '-D_GNU_SOURCE',
|
||||||
|
dependencies : libcrypt)
|
||||||
|
conf.set10('HAVE_' + ident[0].to_upper(), have)
|
||||||
|
endforeach
|
||||||
|
|
||||||
libcap = dependency('libcap', required : false)
|
libcap = dependency('libcap', required : false)
|
||||||
if not libcap.found()
|
if not libcap.found()
|
||||||
# Compat with Ubuntu 14.04 which ships libcap w/o .pc file
|
# Compat with Ubuntu 14.04 which ships libcap w/o .pc file
|
||||||
|
|
|
@ -802,7 +802,7 @@ static int write_root_shadow(const char *shadow_path, const char *hashed_passwor
|
||||||
|
|
||||||
static int process_root_args(void) {
|
static int process_root_args(void) {
|
||||||
_cleanup_close_ int lock = -1;
|
_cleanup_close_ int lock = -1;
|
||||||
struct crypt_data cd = {};
|
_cleanup_(erase_and_freep) char *_hashed_password = NULL;
|
||||||
const char *password, *hashed_password;
|
const char *password, *hashed_password;
|
||||||
const char *etc_passwd, *etc_shadow;
|
const char *etc_passwd, *etc_shadow;
|
||||||
int r;
|
int r;
|
||||||
|
@ -866,20 +866,13 @@ static int process_root_args(void) {
|
||||||
password = "x";
|
password = "x";
|
||||||
hashed_password = arg_root_password;
|
hashed_password = arg_root_password;
|
||||||
} else if (arg_root_password) {
|
} else if (arg_root_password) {
|
||||||
_cleanup_free_ char *salt = NULL;
|
r = hash_password(arg_root_password, &_hashed_password);
|
||||||
/* hashed_password points inside cd after crypt_r returns so cd has function scope. */
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to hash password: %m");
|
||||||
|
|
||||||
password = "x";
|
password = "x";
|
||||||
|
hashed_password = _hashed_password;
|
||||||
|
|
||||||
r = make_salt(&salt);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to get salt: %m");
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
hashed_password = crypt_r(arg_root_password, salt, &cd);
|
|
||||||
if (!hashed_password)
|
|
||||||
return log_error_errno(errno == 0 ? SYNTHETIC_ERRNO(EINVAL) : errno,
|
|
||||||
"Failed to encrypt password: %m");
|
|
||||||
} else if (arg_delete_root_password)
|
} else if (arg_delete_root_password)
|
||||||
password = hashed_password = "";
|
password = hashed_password = "";
|
||||||
else
|
else
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
|
||||||
#include "dns-domain.h"
|
#include "dns-domain.h"
|
||||||
#include "errno-util.h"
|
|
||||||
#include "home-util.h"
|
#include "home-util.h"
|
||||||
#include "libcrypt-util.h"
|
#include "libcrypt-util.h"
|
||||||
#include "memory-util.h"
|
#include "memory-util.h"
|
||||||
|
@ -134,35 +133,3 @@ int bus_message_append_secret(sd_bus_message *m, UserRecord *secret) {
|
||||||
|
|
||||||
return sd_bus_message_append(m, "s", formatted);
|
return sd_bus_message_append(m, "s", formatted);
|
||||||
}
|
}
|
||||||
|
|
||||||
int test_password_one(const char *hashed_password, const char *password) {
|
|
||||||
struct crypt_data cc = {};
|
|
||||||
const char *k;
|
|
||||||
bool b;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
k = crypt_r(password, hashed_password, &cc);
|
|
||||||
if (!k) {
|
|
||||||
explicit_bzero_safe(&cc, sizeof(cc));
|
|
||||||
return errno_or_else(EINVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
b = streq(k, hashed_password);
|
|
||||||
explicit_bzero_safe(&cc, sizeof(cc));
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
int test_password_many(char **hashed_password, const char *password) {
|
|
||||||
char **hpw;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
STRV_FOREACH(hpw, hashed_password) {
|
|
||||||
r = test_password_one(*hpw, password);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
if (r > 0)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,6 +21,3 @@ int bus_message_append_secret(sd_bus_message *m, UserRecord *secret);
|
||||||
/* Many of our operations might be slow due to crypto, fsck, recursive chown() and so on. For these
|
/* Many of our operations might be slow due to crypto, fsck, recursive chown() and so on. For these
|
||||||
* operations permit a *very* long timeout */
|
* operations permit a *very* long timeout */
|
||||||
#define HOME_SLOW_BUS_CALL_TIMEOUT_USEC (2*USEC_PER_MINUTE)
|
#define HOME_SLOW_BUS_CALL_TIMEOUT_USEC (2*USEC_PER_MINUTE)
|
||||||
|
|
||||||
int test_password_one(const char *hashed_password, const char *password);
|
|
||||||
int test_password_many(char **hashed_password, const char *password);
|
|
||||||
|
|
|
@ -70,31 +70,23 @@ static int add_fido2_salt(
|
||||||
size_t secret_size) {
|
size_t secret_size) {
|
||||||
|
|
||||||
_cleanup_(json_variant_unrefp) JsonVariant *l = NULL, *w = NULL, *e = NULL;
|
_cleanup_(json_variant_unrefp) JsonVariant *l = NULL, *w = NULL, *e = NULL;
|
||||||
_cleanup_(erase_and_freep) char *base64_encoded = NULL;
|
_cleanup_(erase_and_freep) char *base64_encoded = NULL, *hashed = NULL;
|
||||||
_cleanup_free_ char *unix_salt = NULL;
|
|
||||||
struct crypt_data cd = {};
|
|
||||||
char *k;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = make_salt(&unix_salt);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to generate salt: %m");
|
|
||||||
|
|
||||||
/* Before using UNIX hashing on the supplied key we base64 encode it, since crypt_r() and friends
|
/* Before using UNIX hashing on the supplied key we base64 encode it, since crypt_r() and friends
|
||||||
* expect a NUL terminated string, and we use a binary key */
|
* expect a NUL terminated string, and we use a binary key */
|
||||||
r = base64mem(secret, secret_size, &base64_encoded);
|
r = base64mem(secret, secret_size, &base64_encoded);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to base64 encode secret key: %m");
|
return log_error_errno(r, "Failed to base64 encode secret key: %m");
|
||||||
|
|
||||||
errno = 0;
|
r = hash_password(base64_encoded, &hashed);
|
||||||
k = crypt_r(base64_encoded, unix_salt, &cd);
|
if (r < 0)
|
||||||
if (!k)
|
|
||||||
return log_error_errno(errno_or_else(EINVAL), "Failed to UNIX hash secret key: %m");
|
return log_error_errno(errno_or_else(EINVAL), "Failed to UNIX hash secret key: %m");
|
||||||
|
|
||||||
r = json_build(&e, JSON_BUILD_OBJECT(
|
r = json_build(&e, JSON_BUILD_OBJECT(
|
||||||
JSON_BUILD_PAIR("credential", JSON_BUILD_BASE64(cid, cid_size)),
|
JSON_BUILD_PAIR("credential", JSON_BUILD_BASE64(cid, cid_size)),
|
||||||
JSON_BUILD_PAIR("salt", JSON_BUILD_BASE64(fido2_salt, fido2_salt_size)),
|
JSON_BUILD_PAIR("salt", JSON_BUILD_BASE64(fido2_salt, fido2_salt_size)),
|
||||||
JSON_BUILD_PAIR("hashedPassword", JSON_BUILD_STRING(k))));
|
JSON_BUILD_PAIR("hashedPassword", JSON_BUILD_STRING(hashed))));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to build FIDO2 salt JSON key object: %m");
|
return log_error_errno(r, "Failed to build FIDO2 salt JSON key object: %m");
|
||||||
|
|
||||||
|
|
|
@ -134,10 +134,7 @@ static int add_pkcs11_encrypted_key(
|
||||||
const void *decrypted_key, size_t decrypted_key_size) {
|
const void *decrypted_key, size_t decrypted_key_size) {
|
||||||
|
|
||||||
_cleanup_(json_variant_unrefp) JsonVariant *l = NULL, *w = NULL, *e = NULL;
|
_cleanup_(json_variant_unrefp) JsonVariant *l = NULL, *w = NULL, *e = NULL;
|
||||||
_cleanup_(erase_and_freep) char *base64_encoded = NULL;
|
_cleanup_(erase_and_freep) char *base64_encoded = NULL, *hashed = NULL;
|
||||||
_cleanup_free_ char *salt = NULL;
|
|
||||||
struct crypt_data cd = {};
|
|
||||||
char *k;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(v);
|
assert(v);
|
||||||
|
@ -147,25 +144,20 @@ static int add_pkcs11_encrypted_key(
|
||||||
assert(decrypted_key);
|
assert(decrypted_key);
|
||||||
assert(decrypted_key_size > 0);
|
assert(decrypted_key_size > 0);
|
||||||
|
|
||||||
r = make_salt(&salt);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to generate salt: %m");
|
|
||||||
|
|
||||||
/* Before using UNIX hashing on the supplied key we base64 encode it, since crypt_r() and friends
|
/* Before using UNIX hashing on the supplied key we base64 encode it, since crypt_r() and friends
|
||||||
* expect a NUL terminated string, and we use a binary key */
|
* expect a NUL terminated string, and we use a binary key */
|
||||||
r = base64mem(decrypted_key, decrypted_key_size, &base64_encoded);
|
r = base64mem(decrypted_key, decrypted_key_size, &base64_encoded);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to base64 encode secret key: %m");
|
return log_error_errno(r, "Failed to base64 encode secret key: %m");
|
||||||
|
|
||||||
errno = 0;
|
r = hash_password(base64_encoded, &hashed);
|
||||||
k = crypt_r(base64_encoded, salt, &cd);
|
if (r < 0)
|
||||||
if (!k)
|
|
||||||
return log_error_errno(errno_or_else(EINVAL), "Failed to UNIX hash secret key: %m");
|
return log_error_errno(errno_or_else(EINVAL), "Failed to UNIX hash secret key: %m");
|
||||||
|
|
||||||
r = json_build(&e, JSON_BUILD_OBJECT(
|
r = json_build(&e, JSON_BUILD_OBJECT(
|
||||||
JSON_BUILD_PAIR("uri", JSON_BUILD_STRING(uri)),
|
JSON_BUILD_PAIR("uri", JSON_BUILD_STRING(uri)),
|
||||||
JSON_BUILD_PAIR("data", JSON_BUILD_BASE64(encrypted_key, encrypted_key_size)),
|
JSON_BUILD_PAIR("data", JSON_BUILD_BASE64(encrypted_key, encrypted_key_size)),
|
||||||
JSON_BUILD_PAIR("hashedPassword", JSON_BUILD_STRING(k))));
|
JSON_BUILD_PAIR("hashedPassword", JSON_BUILD_STRING(hashed))));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to build encrypted JSON key object: %m");
|
return log_error_errno(r, "Failed to build encrypted JSON key object: %m");
|
||||||
|
|
||||||
|
|
|
@ -183,9 +183,7 @@ static int print_qr_code(const char *secret) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int identity_add_recovery_key(JsonVariant **v) {
|
int identity_add_recovery_key(JsonVariant **v) {
|
||||||
_cleanup_(erase_and_freep) char *unix_salt = NULL, *password = NULL;
|
_cleanup_(erase_and_freep) char *password = NULL, *hashed = NULL;
|
||||||
struct crypt_data cd = {};
|
|
||||||
char *k;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(v);
|
assert(v);
|
||||||
|
@ -196,17 +194,12 @@ int identity_add_recovery_key(JsonVariant **v) {
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* Let's UNIX hash it */
|
/* Let's UNIX hash it */
|
||||||
r = make_salt(&unix_salt);
|
r = hash_password(password, &hashed);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to generate salt: %m");
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
k = crypt_r(password, unix_salt, &cd);
|
|
||||||
if (!k)
|
|
||||||
return log_error_errno(errno_or_else(EINVAL), "Failed to UNIX hash secret key: %m");
|
return log_error_errno(errno_or_else(EINVAL), "Failed to UNIX hash secret key: %m");
|
||||||
|
|
||||||
/* Let's now add the "privileged" version of the recovery key */
|
/* Let's now add the "privileged" version of the recovery key */
|
||||||
r = add_privileged(v, k);
|
r = add_privileged(v, hashed);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "homework-mount.h"
|
#include "homework-mount.h"
|
||||||
#include "homework-pkcs11.h"
|
#include "homework-pkcs11.h"
|
||||||
#include "homework.h"
|
#include "homework.h"
|
||||||
|
#include "libcrypt-util.h"
|
||||||
#include "main-func.h"
|
#include "main-func.h"
|
||||||
#include "memory-util.h"
|
#include "memory-util.h"
|
||||||
#include "missing_magic.h"
|
#include "missing_magic.h"
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "bus-common-errors.h"
|
#include "bus-common-errors.h"
|
||||||
#include "errno-util.h"
|
#include "errno-util.h"
|
||||||
#include "home-util.h"
|
#include "home-util.h"
|
||||||
|
#include "libcrypt-util.h"
|
||||||
#include "pwquality-util.h"
|
#include "pwquality-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "user-record-pwquality.h"
|
#include "user-record-pwquality.h"
|
||||||
|
|
|
@ -806,20 +806,13 @@ int user_record_make_hashed_password(UserRecord *h, char **secret, bool extend)
|
||||||
}
|
}
|
||||||
|
|
||||||
STRV_FOREACH(i, secret) {
|
STRV_FOREACH(i, secret) {
|
||||||
_cleanup_free_ char *salt = NULL;
|
_cleanup_(erase_and_freep) char *hashed = NULL;
|
||||||
struct crypt_data cd = {};
|
|
||||||
char *k;
|
|
||||||
|
|
||||||
r = make_salt(&salt);
|
r = hash_password(*i, &hashed);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
errno = 0;
|
r = strv_consume(&np, TAKE_PTR(hashed));
|
||||||
k = crypt_r(*i, salt, &cd);
|
|
||||||
if (!k)
|
|
||||||
return errno_or_else(EINVAL);
|
|
||||||
|
|
||||||
r = strv_extend(&np, k);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,12 +53,6 @@ int stub_pid1(sd_id128_t uuid) {
|
||||||
assert_se(sigfillset(&fullmask) >= 0);
|
assert_se(sigfillset(&fullmask) >= 0);
|
||||||
assert_se(sigprocmask(SIG_BLOCK, &fullmask, &oldmask) >= 0);
|
assert_se(sigprocmask(SIG_BLOCK, &fullmask, &oldmask) >= 0);
|
||||||
|
|
||||||
/* Surrender the terminal this stub may control so that child processes can have a controlling terminal
|
|
||||||
* without resorting to setsid hacks. */
|
|
||||||
r = ioctl(STDIN_FILENO, TIOCNOTTY);
|
|
||||||
if (r < 0 && errno != ENOTTY)
|
|
||||||
return log_error_errno(errno, "Failed to surrender controlling terminal: %m");
|
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
return log_error_errno(errno, "Failed to fork child pid: %m");
|
return log_error_errno(errno, "Failed to fork child pid: %m");
|
||||||
|
@ -66,7 +60,10 @@ int stub_pid1(sd_id128_t uuid) {
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
/* Return in the child */
|
/* Return in the child */
|
||||||
assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) >= 0);
|
assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) >= 0);
|
||||||
setsid();
|
|
||||||
|
if (setsid() < 0)
|
||||||
|
return log_error_errno(errno, "Failed to become session leader in payload process: %m");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +73,12 @@ int stub_pid1(sd_id128_t uuid) {
|
||||||
(void) close_all_fds(NULL, 0);
|
(void) close_all_fds(NULL, 0);
|
||||||
log_open();
|
log_open();
|
||||||
|
|
||||||
|
if (ioctl(STDIN_FILENO, TIOCNOTTY) < 0) {
|
||||||
|
if (errno != ENOTTY)
|
||||||
|
log_warning_errno(errno, "Unexpected error from TIOCNOTTY ioctl in init stub process, ignoring: %m");
|
||||||
|
} else
|
||||||
|
log_warning("Expected TIOCNOTTY to fail, but it succeeded in init stub process, ignoring.");
|
||||||
|
|
||||||
/* Flush out /proc/self/environ, so that we don't leak the environment from the host into the container. Also,
|
/* Flush out /proc/self/environ, so that we don't leak the environment from the host into the container. Also,
|
||||||
* set $container= and $container_uuid= so that clients in the container that query it from /proc/1/environ
|
* set $container= and $container_uuid= so that clients in the container that query it from /proc/1/environ
|
||||||
* find them set. */
|
* find them set. */
|
||||||
|
|
|
@ -11,10 +11,12 @@
|
||||||
#endif
|
#endif
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <sys/personality.h>
|
#include <sys/personality.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "sd-bus.h"
|
#include "sd-bus.h"
|
||||||
|
@ -254,10 +256,11 @@ STATIC_DESTRUCTOR_REGISTER(arg_sysctl, strv_freep);
|
||||||
|
|
||||||
static int handle_arg_console(const char *arg) {
|
static int handle_arg_console(const char *arg) {
|
||||||
if (streq(arg, "help")) {
|
if (streq(arg, "help")) {
|
||||||
puts("interactive\n"
|
puts("autopipe\n"
|
||||||
"read-only\n"
|
"interactive\n"
|
||||||
"passive\n"
|
"passive\n"
|
||||||
"pipe");
|
"pipe\n"
|
||||||
|
"read-only");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,9 +270,20 @@ static int handle_arg_console(const char *arg) {
|
||||||
arg_console_mode = CONSOLE_READ_ONLY;
|
arg_console_mode = CONSOLE_READ_ONLY;
|
||||||
else if (streq(arg, "passive"))
|
else if (streq(arg, "passive"))
|
||||||
arg_console_mode = CONSOLE_PASSIVE;
|
arg_console_mode = CONSOLE_PASSIVE;
|
||||||
else if (streq(arg, "pipe"))
|
else if (streq(arg, "pipe")) {
|
||||||
|
if (isatty(STDIN_FILENO) > 0 && isatty(STDOUT_FILENO) > 0)
|
||||||
|
log_full(arg_quiet ? LOG_DEBUG : LOG_NOTICE,
|
||||||
|
"Console mode 'pipe' selected, but standard input/output are connected to an interactive TTY. "
|
||||||
|
"Most likely you want to use 'interactive' console mode for proper interactivity and shell job control. "
|
||||||
|
"Proceeding anyway.");
|
||||||
|
|
||||||
arg_console_mode = CONSOLE_PIPE;
|
arg_console_mode = CONSOLE_PIPE;
|
||||||
|
} else if (streq(arg, "autopipe")) {
|
||||||
|
if (isatty(STDIN_FILENO) > 0 && isatty(STDOUT_FILENO) > 0)
|
||||||
|
arg_console_mode = CONSOLE_INTERACTIVE;
|
||||||
else
|
else
|
||||||
|
arg_console_mode = CONSOLE_PIPE;
|
||||||
|
} else
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown console mode: %s", optarg);
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown console mode: %s", optarg);
|
||||||
|
|
||||||
arg_settings_mask |= SETTING_CONSOLE_MODE;
|
arg_settings_mask |= SETTING_CONSOLE_MODE;
|
||||||
|
@ -2269,10 +2283,12 @@ static int setup_pts(const char *dest) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int setup_stdio_as_dev_console(void) {
|
static int setup_stdio_as_dev_console(void) {
|
||||||
int terminal;
|
_cleanup_close_ int terminal = -1;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
terminal = open_terminal("/dev/console", O_RDWR);
|
/* We open the TTY in O_NOCTTY mode, so that we do not become controller yet. We'll do that later
|
||||||
|
* explicitly, if we are configured to. */
|
||||||
|
terminal = open_terminal("/dev/console", O_RDWR|O_NOCTTY);
|
||||||
if (terminal < 0)
|
if (terminal < 0)
|
||||||
return log_error_errno(terminal, "Failed to open console: %m");
|
return log_error_errno(terminal, "Failed to open console: %m");
|
||||||
|
|
||||||
|
@ -2284,6 +2300,7 @@ static int setup_stdio_as_dev_console(void) {
|
||||||
|
|
||||||
/* invalidates 'terminal' on success and failure */
|
/* invalidates 'terminal' on success and failure */
|
||||||
r = rearrange_stdio(terminal, terminal, terminal);
|
r = rearrange_stdio(terminal, terminal, terminal);
|
||||||
|
TAKE_FD(terminal);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to move console to stdin/stdout/stderr: %m");
|
return log_error_errno(r, "Failed to move console to stdin/stdout/stderr: %m");
|
||||||
|
|
||||||
|
@ -3366,8 +3383,7 @@ static int inner_child(
|
||||||
* wait until the parent is ready with the
|
* wait until the parent is ready with the
|
||||||
* setup, too... */
|
* setup, too... */
|
||||||
if (!barrier_place_and_sync(barrier)) /* #5 */
|
if (!barrier_place_and_sync(barrier)) /* #5 */
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(ESRCH),
|
return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "Parent died too early");
|
||||||
"Parent died too early");
|
|
||||||
|
|
||||||
if (arg_chdir)
|
if (arg_chdir)
|
||||||
if (chdir(arg_chdir) < 0)
|
if (chdir(arg_chdir) < 0)
|
||||||
|
@ -3379,6 +3395,13 @@ static int inner_child(
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arg_console_mode != CONSOLE_PIPE) {
|
||||||
|
/* So far our pty wasn't controlled by any process. Finally, it's time to change that, if we
|
||||||
|
* are configured for that. Acquire it as controlling tty. */
|
||||||
|
if (ioctl(STDIN_FILENO, TIOCSCTTY) < 0)
|
||||||
|
return log_error_errno(errno, "Failed to acquire controlling TTY: %m");
|
||||||
|
}
|
||||||
|
|
||||||
log_debug("Inner child completed, invoking payload.");
|
log_debug("Inner child completed, invoking payload.");
|
||||||
|
|
||||||
/* Now, explicitly close the log, so that we then can close all remaining fds. Closing the log explicitly first
|
/* Now, explicitly close the log, so that we then can close all remaining fds. Closing the log explicitly first
|
||||||
|
|
|
@ -1,12 +1,29 @@
|
||||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
|
||||||
|
#if HAVE_CRYPT_H
|
||||||
|
/* libxcrypt is a replacement for glibc's libcrypt, and libcrypt might be
|
||||||
|
* removed from glibc at some point. As part of the removal, defines for
|
||||||
|
* crypt(3) are dropped from unistd.h, and we must include crypt.h instead.
|
||||||
|
*
|
||||||
|
* Newer versions of glibc (v2.0+) already ship crypt.h with a definition
|
||||||
|
* of crypt(3) as well, so we simply include it if it is present. MariaDB,
|
||||||
|
* MySQL, PostgreSQL, Perl and some other wide-spread packages do it the
|
||||||
|
* same way since ages without any problems.
|
||||||
|
*/
|
||||||
|
# include <crypt.h>
|
||||||
|
#else
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
|
#include "errno-util.h"
|
||||||
#include "libcrypt-util.h"
|
#include "libcrypt-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
|
#include "memory-util.h"
|
||||||
#include "missing_stdlib.h"
|
#include "missing_stdlib.h"
|
||||||
#include "random-util.h"
|
#include "random-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
|
@ -14,12 +31,12 @@
|
||||||
|
|
||||||
int make_salt(char **ret) {
|
int make_salt(char **ret) {
|
||||||
|
|
||||||
#ifdef XCRYPT_VERSION_MAJOR
|
#if HAVE_CRYPT_GENSALT_RA
|
||||||
const char *e;
|
const char *e;
|
||||||
char *salt;
|
char *salt;
|
||||||
|
|
||||||
/* If we have libxcrypt we default to the "preferred method" (i.e. usually yescrypt), and generate it
|
/* If we have crypt_gensalt_ra() we default to the "preferred method" (i.e. usually yescrypt).
|
||||||
* with crypt_gensalt_ra(). */
|
* crypt_gensalt_ra() is usually provided by libxcrypt. */
|
||||||
|
|
||||||
e = secure_getenv("SYSTEMD_CRYPT_PREFIX");
|
e = secure_getenv("SYSTEMD_CRYPT_PREFIX");
|
||||||
if (!e)
|
if (!e)
|
||||||
|
@ -34,8 +51,7 @@ int make_salt(char **ret) {
|
||||||
*ret = salt;
|
*ret = salt;
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
/* If libxcrypt is not used, we use SHA512 and generate the salt on our own since crypt_gensalt_ra()
|
/* If crypt_gensalt_ra() is not available, we use SHA512 and generate the salt on our own. */
|
||||||
* is not available. */
|
|
||||||
|
|
||||||
static const char table[] =
|
static const char table[] =
|
||||||
"abcdefghijklmnopqrstuvwxyz"
|
"abcdefghijklmnopqrstuvwxyz"
|
||||||
|
@ -53,6 +69,8 @@ int make_salt(char **ret) {
|
||||||
|
|
||||||
assert_cc(sizeof(table) == 64U + 1U);
|
assert_cc(sizeof(table) == 64U + 1U);
|
||||||
|
|
||||||
|
log_debug("Generating fallback salt for hash prefix: $6$");
|
||||||
|
|
||||||
/* Insist on the best randomness by setting RANDOM_BLOCK, this is about keeping passwords secret after all. */
|
/* Insist on the best randomness by setting RANDOM_BLOCK, this is about keeping passwords secret after all. */
|
||||||
r = genuine_random_bytes(raw, sizeof(raw), RANDOM_BLOCK);
|
r = genuine_random_bytes(raw, sizeof(raw), RANDOM_BLOCK);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -74,6 +92,73 @@ int make_salt(char **ret) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAVE_CRYPT_RA
|
||||||
|
# define CRYPT_RA_NAME "crypt_ra"
|
||||||
|
#else
|
||||||
|
# define CRYPT_RA_NAME "crypt_r"
|
||||||
|
|
||||||
|
/* Provide a poor man's fallback that uses a fixed size buffer. */
|
||||||
|
|
||||||
|
static char* systemd_crypt_ra(const char *phrase, const char *setting, void **data, int *size) {
|
||||||
|
assert(data);
|
||||||
|
assert(size);
|
||||||
|
|
||||||
|
/* We allocate the buffer because crypt(3) says: struct crypt_data may be quite large (32kB in this
|
||||||
|
* implementation of libcrypt; over 128kB in some other implementations). This is large enough that
|
||||||
|
* it may be unwise to allocate it on the stack. */
|
||||||
|
|
||||||
|
if (!*data) {
|
||||||
|
*data = new0(struct crypt_data, 1);
|
||||||
|
if (!*data) {
|
||||||
|
errno = -ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*size = (int) (sizeof(struct crypt_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
char *t = crypt_r(phrase, setting, *data);
|
||||||
|
if (!t)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* crypt_r may return a pointer to an invalid hashed password on error. Our callers expect NULL on
|
||||||
|
* error, so let's just return that. */
|
||||||
|
if (t[0] == '*')
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define crypt_ra systemd_crypt_ra
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int hash_password_full(const char *password, void **cd_data, int *cd_size, char **ret) {
|
||||||
|
_cleanup_free_ char *salt = NULL;
|
||||||
|
_cleanup_(erase_and_freep) void *_cd_data = NULL;
|
||||||
|
char *p;
|
||||||
|
int r, _cd_size = 0;
|
||||||
|
|
||||||
|
assert(!!cd_data == !!cd_size);
|
||||||
|
|
||||||
|
r = make_salt(&salt);
|
||||||
|
if (r < 0)
|
||||||
|
return log_debug_errno(r, "Failed to generate salt: %m");
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
p = crypt_ra(password, salt, cd_data ?: &_cd_data, cd_size ?: &_cd_size);
|
||||||
|
if (!p)
|
||||||
|
return log_debug_errno(errno_or_else(SYNTHETIC_ERRNO(EINVAL)),
|
||||||
|
CRYPT_RA_NAME "() failed: %m");
|
||||||
|
|
||||||
|
p = strdup(p);
|
||||||
|
if (!p)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
*ret = p;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool looks_like_hashed_password(const char *s) {
|
bool looks_like_hashed_password(const char *s) {
|
||||||
/* Returns false if the specified string is certainly not a hashed UNIX password. crypt(5) lists
|
/* Returns false if the specified string is certainly not a hashed UNIX password. crypt(5) lists
|
||||||
* various hashing methods. We only reject (return false) strings which are documented to have
|
* various hashing methods. We only reject (return false) strings which are documented to have
|
||||||
|
@ -89,3 +174,35 @@ bool looks_like_hashed_password(const char *s) {
|
||||||
|
|
||||||
return !STR_IN_SET(s, "x", "*");
|
return !STR_IN_SET(s, "x", "*");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int test_password_one(const char *hashed_password, const char *password) {
|
||||||
|
_cleanup_(erase_and_freep) void *cd_data = NULL;
|
||||||
|
int cd_size = 0;
|
||||||
|
const char *k;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
k = crypt_ra(password, hashed_password, &cd_data, &cd_size);
|
||||||
|
if (!k) {
|
||||||
|
if (errno == ENOMEM)
|
||||||
|
return -ENOMEM;
|
||||||
|
/* Unknown or unavailable hashing method or string too short */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return streq(k, hashed_password);
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_password_many(char **hashed_password, const char *password) {
|
||||||
|
char **hpw;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
STRV_FOREACH(hpw, hashed_password) {
|
||||||
|
r = test_password_one(*hpw, password);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r > 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -1,22 +1,13 @@
|
||||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if HAVE_CRYPT_H
|
|
||||||
/* libxcrypt is a replacement for glibc's libcrypt, and libcrypt might be
|
|
||||||
* removed from glibc at some point. As part of the removal, defines for
|
|
||||||
* crypt(3) are dropped from unistd.h, and we must include crypt.h instead.
|
|
||||||
*
|
|
||||||
* Newer versions of glibc (v2.0+) already ship crypt.h with a definition
|
|
||||||
* of crypt(3) as well, so we simply include it if it is present. MariaDB,
|
|
||||||
* MySQL, PostgreSQL, Perl and some other wide-spread packages do it the
|
|
||||||
* same way since ages without any problems.
|
|
||||||
*/
|
|
||||||
#include <crypt.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
int make_salt(char **ret);
|
int make_salt(char **ret);
|
||||||
|
int hash_password_full(const char *password, void **cd_data, int *cd_size, char **ret);
|
||||||
|
static inline int hash_password(const char *password, char **ret) {
|
||||||
|
return hash_password_full(password, NULL, NULL, ret);
|
||||||
|
}
|
||||||
bool looks_like_hashed_password(const char *s);
|
bool looks_like_hashed_password(const char *s);
|
||||||
|
int test_password_one(const char *hashed_password, const char *password);
|
||||||
|
int test_password_many(char **hashed_password, const char *password);
|
||||||
|
|
|
@ -301,6 +301,10 @@ tests += [
|
||||||
[],
|
[],
|
||||||
[]],
|
[]],
|
||||||
|
|
||||||
|
[['src/test/test-libcrypt-util.c'],
|
||||||
|
[],
|
||||||
|
[]],
|
||||||
|
|
||||||
[['src/test/test-offline-passwd.c',
|
[['src/test/test-offline-passwd.c',
|
||||||
'src/shared/offline-passwd.c',
|
'src/shared/offline-passwd.c',
|
||||||
'src/shared/offline-passwd.h'],
|
'src/shared/offline-passwd.h'],
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
|
||||||
|
#if HAVE_CRYPT_H
|
||||||
|
# include <crypt.h>
|
||||||
|
#else
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "strv.h"
|
||||||
|
#include "tests.h"
|
||||||
|
#include "libcrypt-util.h"
|
||||||
|
|
||||||
|
static int test_hash_password(void) {
|
||||||
|
log_info("/* %s */", __func__);
|
||||||
|
|
||||||
|
/* As a warmup exercise, check if we can hash passwords. */
|
||||||
|
|
||||||
|
bool have_sane_hash = false;
|
||||||
|
const char *hash;
|
||||||
|
|
||||||
|
FOREACH_STRING(hash,
|
||||||
|
"ew3bU1.hoKk4o",
|
||||||
|
"$1$gc5rWpTB$wK1aul1PyBn9AX1z93stk1",
|
||||||
|
"$2b$12$BlqcGkB/7BFvNMXKGxDea.5/8D6FTny.cbNcHW/tqcrcyo6ZJd8u2",
|
||||||
|
"$5$lGhDrcrao9zb5oIK$05KlOVG3ocknx/ThreqXE/gk.XzFFBMTksc4t2CPDUD",
|
||||||
|
"$6$c7wB/3GiRk0VHf7e$zXJ7hN0aLZapE.iO4mn/oHu6.prsXTUG/5k1AxpgR85ELolyAcaIGRgzfwJs3isTChMDBjnthZyaMCfCNxo9I.",
|
||||||
|
"$y$j9T$$9cKOWsAm4m97WiYk61lPPibZpy3oaGPIbsL4koRe/XD") {
|
||||||
|
int b;
|
||||||
|
|
||||||
|
b = test_password_one(hash, "ppp");
|
||||||
|
log_info("%s: %s", hash, yes_no(b));
|
||||||
|
#if defined(XCRYPT_VERSION_MAJOR)
|
||||||
|
/* xcrypt is supposed to always implement all methods. */
|
||||||
|
assert_se(b);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (b && IN_SET(hash[1], '6', 'y'))
|
||||||
|
have_sane_hash = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return have_sane_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_hash_password_full(void) {
|
||||||
|
log_info("/* %s */", __func__);
|
||||||
|
|
||||||
|
_cleanup_free_ void *cd_data = NULL;
|
||||||
|
const char *i;
|
||||||
|
int cd_size = 0;
|
||||||
|
|
||||||
|
log_info("sizeof(struct crypt_data): %zu bytes", sizeof(struct crypt_data));
|
||||||
|
|
||||||
|
for (unsigned c = 0; c < 2; c++)
|
||||||
|
FOREACH_STRING(i, "abc123", "h⸿sło") {
|
||||||
|
_cleanup_free_ char *hashed;
|
||||||
|
|
||||||
|
if (c == 0)
|
||||||
|
assert_se(hash_password_full(i, &cd_data, &cd_size, &hashed) == 0);
|
||||||
|
else
|
||||||
|
assert_se(hash_password_full(i, NULL, NULL, &hashed) == 0);
|
||||||
|
log_debug("\"%s\" → \"%s\"", i, hashed);
|
||||||
|
log_info("crypt_r[a] buffer size: %i bytes", cd_size);
|
||||||
|
|
||||||
|
assert_se(test_password_one(hashed, i) == true);
|
||||||
|
assert_se(test_password_one(i, hashed) <= 0); /* We get an error for non-utf8 */
|
||||||
|
assert_se(test_password_one(hashed, "foobar") == false);
|
||||||
|
assert_se(test_password_many(STRV_MAKE(hashed), i) == true);
|
||||||
|
assert_se(test_password_many(STRV_MAKE(hashed), "foobar") == false);
|
||||||
|
assert_se(test_password_many(STRV_MAKE(hashed, hashed, hashed), "foobar") == false);
|
||||||
|
assert_se(test_password_many(STRV_MAKE("$y$j9T$dlCXwkX0GC5L6B8Gf.4PN/$VCyEH",
|
||||||
|
hashed,
|
||||||
|
"$y$j9T$SAayASazWZIQeJd9AS02m/$"),
|
||||||
|
i) == true);
|
||||||
|
assert_se(test_password_many(STRV_MAKE("$W$j9T$dlCXwkX0GC5L6B8Gf.4PN/$VCyEH", /* no such method exists... */
|
||||||
|
hashed,
|
||||||
|
"$y$j9T$SAayASazWZIQeJd9AS02m/$"),
|
||||||
|
i) == true);
|
||||||
|
assert_se(test_password_many(STRV_MAKE("$y$j9T$dlCXwkX0GC5L6B8Gf.4PN/$VCyEH",
|
||||||
|
hashed,
|
||||||
|
"$y$j9T$SAayASazWZIQeJd9AS02m/$"),
|
||||||
|
"") == false);
|
||||||
|
assert_se(test_password_many(STRV_MAKE("$W$j9T$dlCXwkX0GC5L6B8Gf.4PN/$VCyEH", /* no such method exists... */
|
||||||
|
hashed,
|
||||||
|
"$y$j9T$SAayASazWZIQeJd9AS02m/$"),
|
||||||
|
"") == false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
test_setup_logging(LOG_DEBUG);
|
||||||
|
|
||||||
|
#if defined(__powerpc__) && !defined(XCRYPT_VERSION_MAJOR)
|
||||||
|
return log_tests_skipped("crypt_r() causes a buffer overflow on ppc64el, see https://github.com/systemd/systemd/pull/16981#issuecomment-691203787");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!test_hash_password())
|
||||||
|
return log_tests_skipped("crypt doesn't support yescrypt or sha512crypt");
|
||||||
|
|
||||||
|
test_hash_password_full();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue