mirror of
https://github.com/systemd/systemd
synced 2025-10-09 13:44:44 +02:00
Compare commits
4 Commits
43ed3d294a
...
be8fc0ef2e
Author | SHA1 | Date | |
---|---|---|---|
![]() |
be8fc0ef2e | ||
![]() |
57bb9bcba5 | ||
![]() |
7bdbafc261 | ||
![]() |
ea086f0610 |
@ -1072,3 +1072,16 @@ int fgetsgent_sane(FILE *stream, struct sgrp **sg) {
|
|||||||
return !!s;
|
return !!s;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int is_this_me(const char *username) {
|
||||||
|
uid_t uid;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* Checks if the specified username is our current one. Passed string might be a UID or a user name. */
|
||||||
|
|
||||||
|
r = get_user_creds(&username, &uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return uid == getuid();
|
||||||
|
}
|
||||||
|
@ -109,3 +109,5 @@ int putsgent_sane(const struct sgrp *sg, FILE *stream);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool is_nologin_shell(const char *shell);
|
bool is_nologin_shell(const char *shell);
|
||||||
|
|
||||||
|
int is_this_me(const char *username);
|
||||||
|
@ -190,7 +190,12 @@ static int list_homes(int argc, char *argv[], void *userdata) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int acquire_existing_password(const char *user_name, UserRecord *hr, bool emphasize_current) {
|
static int acquire_existing_password(
|
||||||
|
const char *user_name,
|
||||||
|
UserRecord *hr,
|
||||||
|
bool emphasize_current,
|
||||||
|
AskPasswordFlags flags) {
|
||||||
|
|
||||||
_cleanup_(strv_free_erasep) char **password = NULL;
|
_cleanup_(strv_free_erasep) char **password = NULL;
|
||||||
_cleanup_free_ char *question = NULL;
|
_cleanup_free_ char *question = NULL;
|
||||||
char *e;
|
char *e;
|
||||||
@ -212,16 +217,32 @@ static int acquire_existing_password(const char *user_name, UserRecord *hr, bool
|
|||||||
string_erase(e);
|
string_erase(e);
|
||||||
assert_se(unsetenv("PASSWORD") == 0);
|
assert_se(unsetenv("PASSWORD") == 0);
|
||||||
|
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If this is not our own user, then don't use the password cache */
|
||||||
|
if (is_this_me(user_name) <= 0)
|
||||||
|
SET_FLAG(flags, ASK_PASSWORD_ACCEPT_CACHED|ASK_PASSWORD_PUSH_CACHE, false);
|
||||||
|
|
||||||
if (asprintf(&question, emphasize_current ?
|
if (asprintf(&question, emphasize_current ?
|
||||||
"Please enter current password for user %s:" :
|
"Please enter current password for user %s:" :
|
||||||
"Please enter password for user %s:",
|
"Please enter password for user %s:",
|
||||||
user_name) < 0)
|
user_name) < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = ask_password_auto(question, "user-home", NULL, "home-password", "home.password", USEC_INFINITY, ASK_PASSWORD_ACCEPT_CACHED|ASK_PASSWORD_PUSH_CACHE, &password);
|
r = ask_password_auto(question,
|
||||||
|
/* icon= */ "user-home",
|
||||||
|
NULL,
|
||||||
|
/* key_name= */ "home-password",
|
||||||
|
/* credential_name= */ "home.password",
|
||||||
|
USEC_INFINITY,
|
||||||
|
flags,
|
||||||
|
&password);
|
||||||
|
if (r == -EUNATCH) { /* EUNATCH is returned if no password was found and asking interactively was
|
||||||
|
* disabled via the flags. Not an error for us. */
|
||||||
|
log_debug_errno(r, "No passwords acquired.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to acquire password: %m");
|
return log_error_errno(r, "Failed to acquire password: %m");
|
||||||
|
|
||||||
@ -229,10 +250,14 @@ static int acquire_existing_password(const char *user_name, UserRecord *hr, bool
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to store password: %m");
|
return log_error_errno(r, "Failed to store password: %m");
|
||||||
|
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int acquire_token_pin(const char *user_name, UserRecord *hr) {
|
static int acquire_token_pin(
|
||||||
|
const char *user_name,
|
||||||
|
UserRecord *hr,
|
||||||
|
AskPasswordFlags flags) {
|
||||||
|
|
||||||
_cleanup_(strv_free_erasep) char **pin = NULL;
|
_cleanup_(strv_free_erasep) char **pin = NULL;
|
||||||
_cleanup_free_ char *question = NULL;
|
_cleanup_free_ char *question = NULL;
|
||||||
char *e;
|
char *e;
|
||||||
@ -250,14 +275,30 @@ static int acquire_token_pin(const char *user_name, UserRecord *hr) {
|
|||||||
string_erase(e);
|
string_erase(e);
|
||||||
assert_se(unsetenv("PIN") == 0);
|
assert_se(unsetenv("PIN") == 0);
|
||||||
|
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If this is not our own user, then don't use the password cache */
|
||||||
|
if (is_this_me(user_name) <= 0)
|
||||||
|
SET_FLAG(flags, ASK_PASSWORD_ACCEPT_CACHED|ASK_PASSWORD_PUSH_CACHE, false);
|
||||||
|
|
||||||
if (asprintf(&question, "Please enter security token PIN for user %s:", user_name) < 0)
|
if (asprintf(&question, "Please enter security token PIN for user %s:", user_name) < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
/* We never cache or use cached PINs, since usually there are only very few attempts allowed before the PIN is blocked */
|
r = ask_password_auto(
|
||||||
r = ask_password_auto(question, "user-home", NULL, "token-pin", "home.token-pin", USEC_INFINITY, 0, &pin);
|
question,
|
||||||
|
/* icon= */ "user-home",
|
||||||
|
NULL,
|
||||||
|
/* key_name= */ "token-pin",
|
||||||
|
/* credential_name= */ "home.token-pin",
|
||||||
|
USEC_INFINITY,
|
||||||
|
flags,
|
||||||
|
&pin);
|
||||||
|
if (r == -EUNATCH) { /* EUNATCH is returned if no PIN was found and asking interactively was disabled
|
||||||
|
* via the flags. Not an error for us. */
|
||||||
|
log_debug_errno(r, "No security token PINs acquired.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to acquire security token PIN: %m");
|
return log_error_errno(r, "Failed to acquire security token PIN: %m");
|
||||||
|
|
||||||
@ -265,7 +306,7 @@ static int acquire_token_pin(const char *user_name, UserRecord *hr) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to store security token PIN: %m");
|
return log_error_errno(r, "Failed to store security token PIN: %m");
|
||||||
|
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_generic_user_record_error(
|
static int handle_generic_user_record_error(
|
||||||
@ -292,7 +333,13 @@ static int handle_generic_user_record_error(
|
|||||||
if (!strv_isempty(hr->password))
|
if (!strv_isempty(hr->password))
|
||||||
log_notice("Password incorrect or not sufficient, please try again.");
|
log_notice("Password incorrect or not sufficient, please try again.");
|
||||||
|
|
||||||
r = acquire_existing_password(user_name, hr, emphasize_current_password);
|
/* Don't consume cache entries or credentials here, we already tried that unsuccessfully. But
|
||||||
|
* let's push what we acquire here into the cache */
|
||||||
|
r = acquire_existing_password(
|
||||||
|
user_name,
|
||||||
|
hr,
|
||||||
|
emphasize_current_password,
|
||||||
|
ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_NO_CREDENTIAL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -303,13 +350,21 @@ static int handle_generic_user_record_error(
|
|||||||
else
|
else
|
||||||
log_notice("Password incorrect or not sufficient, and configured security token not inserted, please try again.");
|
log_notice("Password incorrect or not sufficient, and configured security token not inserted, please try again.");
|
||||||
|
|
||||||
r = acquire_existing_password(user_name, hr, emphasize_current_password);
|
r = acquire_existing_password(
|
||||||
|
user_name,
|
||||||
|
hr,
|
||||||
|
emphasize_current_password,
|
||||||
|
ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_NO_CREDENTIAL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
} else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_PIN_NEEDED)) {
|
} else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_PIN_NEEDED)) {
|
||||||
|
|
||||||
r = acquire_token_pin(user_name, hr);
|
/* First time the PIN is requested, let's accept cached data, and allow using credential store */
|
||||||
|
r = acquire_token_pin(
|
||||||
|
user_name,
|
||||||
|
hr,
|
||||||
|
ASK_PASSWORD_ACCEPT_CACHED | ASK_PASSWORD_PUSH_CACHE);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -340,7 +395,11 @@ static int handle_generic_user_record_error(
|
|||||||
|
|
||||||
log_notice("Security token PIN incorrect, please try again.");
|
log_notice("Security token PIN incorrect, please try again.");
|
||||||
|
|
||||||
r = acquire_token_pin(user_name, hr);
|
/* If the previous PIN was wrong don't accept cached info anymore, but add to cache. Also, don't use the credential data */
|
||||||
|
r = acquire_token_pin(
|
||||||
|
user_name,
|
||||||
|
hr,
|
||||||
|
ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_NO_CREDENTIAL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -348,7 +407,10 @@ static int handle_generic_user_record_error(
|
|||||||
|
|
||||||
log_notice("Security token PIN incorrect, please try again (only a few tries left!).");
|
log_notice("Security token PIN incorrect, please try again (only a few tries left!).");
|
||||||
|
|
||||||
r = acquire_token_pin(user_name, hr);
|
r = acquire_token_pin(
|
||||||
|
user_name,
|
||||||
|
hr,
|
||||||
|
ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_NO_CREDENTIAL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -356,7 +418,10 @@ static int handle_generic_user_record_error(
|
|||||||
|
|
||||||
log_notice("Security token PIN incorrect, please try again (only one try left!).");
|
log_notice("Security token PIN incorrect, please try again (only one try left!).");
|
||||||
|
|
||||||
r = acquire_token_pin(user_name, hr);
|
r = acquire_token_pin(
|
||||||
|
user_name,
|
||||||
|
hr,
|
||||||
|
ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_NO_CREDENTIAL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
} else
|
} else
|
||||||
@ -365,6 +430,39 @@ static int handle_generic_user_record_error(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int acquire_passed_secrets(const char *user_name, UserRecord **ret) {
|
||||||
|
_cleanup_(user_record_unrefp) UserRecord *secret = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
/* Generates an initial secret objects that contains passwords supplied via $PASSWORD, the password
|
||||||
|
* cache or the credentials subsystem, but excluding any interactive stuff. If nothing is passed,
|
||||||
|
* returns an empty secret object. */
|
||||||
|
|
||||||
|
secret = user_record_new();
|
||||||
|
if (!secret)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
r = acquire_existing_password(
|
||||||
|
user_name,
|
||||||
|
secret,
|
||||||
|
/* emphasize_current_password = */ false,
|
||||||
|
ASK_PASSWORD_ACCEPT_CACHED | ASK_PASSWORD_NO_TTY | ASK_PASSWORD_NO_AGENT);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = acquire_token_pin(
|
||||||
|
user_name,
|
||||||
|
secret,
|
||||||
|
ASK_PASSWORD_ACCEPT_CACHED | ASK_PASSWORD_NO_TTY | ASK_PASSWORD_NO_AGENT);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
*ret = TAKE_PTR(secret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int activate_home(int argc, char *argv[], void *userdata) {
|
static int activate_home(int argc, char *argv[], void *userdata) {
|
||||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||||
int r, ret = 0;
|
int r, ret = 0;
|
||||||
@ -377,9 +475,9 @@ static int activate_home(int argc, char *argv[], void *userdata) {
|
|||||||
STRV_FOREACH(i, strv_skip(argv, 1)) {
|
STRV_FOREACH(i, strv_skip(argv, 1)) {
|
||||||
_cleanup_(user_record_unrefp) UserRecord *secret = NULL;
|
_cleanup_(user_record_unrefp) UserRecord *secret = NULL;
|
||||||
|
|
||||||
secret = user_record_new();
|
r = acquire_passed_secrets(*i, &secret);
|
||||||
if (!secret)
|
if (r < 0)
|
||||||
return log_oom();
|
return r;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||||
@ -399,7 +497,7 @@ static int activate_home(int argc, char *argv[], void *userdata) {
|
|||||||
|
|
||||||
r = sd_bus_call(bus, m, HOME_SLOW_BUS_CALL_TIMEOUT_USEC, &error, NULL);
|
r = sd_bus_call(bus, m, HOME_SLOW_BUS_CALL_TIMEOUT_USEC, &error, NULL);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
r = handle_generic_user_record_error(*i, secret, &error, r, false);
|
r = handle_generic_user_record_error(*i, secret, &error, r, /* emphasize_current_password= */ false);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
ret = r;
|
ret = r;
|
||||||
@ -603,9 +701,9 @@ static int authenticate_home(int argc, char *argv[], void *userdata) {
|
|||||||
STRV_FOREACH(i, items) {
|
STRV_FOREACH(i, items) {
|
||||||
_cleanup_(user_record_unrefp) UserRecord *secret = NULL;
|
_cleanup_(user_record_unrefp) UserRecord *secret = NULL;
|
||||||
|
|
||||||
secret = user_record_new();
|
r = acquire_passed_secrets(*i, &secret);
|
||||||
if (!secret)
|
if (r < 0)
|
||||||
return log_oom();
|
return r;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||||
@ -1010,7 +1108,15 @@ static int acquire_new_password(
|
|||||||
if (asprintf(&question, "Please enter new password for user %s:", user_name) < 0)
|
if (asprintf(&question, "Please enter new password for user %s:", user_name) < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = ask_password_auto(question, "user-home", NULL, "home-password", "home.new-password", USEC_INFINITY, 0, &first);
|
r = ask_password_auto(
|
||||||
|
question,
|
||||||
|
/* icon= */ "user-home",
|
||||||
|
NULL,
|
||||||
|
/* key_name= */ "home-password",
|
||||||
|
/* credential_name= */ "home.new-password",
|
||||||
|
USEC_INFINITY,
|
||||||
|
0, /* no caching, we want to collect a new password here after all */
|
||||||
|
&first);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to acquire password: %m");
|
return log_error_errno(r, "Failed to acquire password: %m");
|
||||||
|
|
||||||
@ -1018,7 +1124,15 @@ static int acquire_new_password(
|
|||||||
if (asprintf(&question, "Please enter new password for user %s (repeat):", user_name) < 0)
|
if (asprintf(&question, "Please enter new password for user %s (repeat):", user_name) < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = ask_password_auto(question, "user-home", NULL, "home-password", "home.new-password", USEC_INFINITY, 0, &second);
|
r = ask_password_auto(
|
||||||
|
question,
|
||||||
|
/* icon= */ "user-home",
|
||||||
|
NULL,
|
||||||
|
/* key_name= */ "home-password",
|
||||||
|
/* credential_name= */ "home.new-password",
|
||||||
|
USEC_INFINITY,
|
||||||
|
0, /* no caching */
|
||||||
|
&second);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to acquire password: %m");
|
return log_error_errno(r, "Failed to acquire password: %m");
|
||||||
|
|
||||||
@ -1106,7 +1220,11 @@ static int create_home(int argc, char *argv[], void *userdata) {
|
|||||||
return log_error_errno(r, "Failed to hash password: %m");
|
return log_error_errno(r, "Failed to hash password: %m");
|
||||||
} else {
|
} else {
|
||||||
/* There's a hash password set in the record, acquire the unhashed version of it. */
|
/* There's a hash password set in the record, acquire the unhashed version of it. */
|
||||||
r = acquire_existing_password(hr->user_name, hr, /* emphasize_current= */ false);
|
r = acquire_existing_password(
|
||||||
|
hr->user_name,
|
||||||
|
hr,
|
||||||
|
/* emphasize_current= */ false,
|
||||||
|
ASK_PASSWORD_ACCEPT_CACHED | ASK_PASSWORD_PUSH_CACHE);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -1585,9 +1703,9 @@ static int resize_home(int argc, char *argv[], void *userdata) {
|
|||||||
ds = arg_disk_size;
|
ds = arg_disk_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
secret = user_record_new();
|
r = acquire_passed_secrets(argv[1], &secret);
|
||||||
if (!secret)
|
if (r < 0)
|
||||||
return log_oom();
|
return r;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||||
@ -1661,9 +1779,9 @@ static int unlock_home(int argc, char *argv[], void *userdata) {
|
|||||||
STRV_FOREACH(i, strv_skip(argv, 1)) {
|
STRV_FOREACH(i, strv_skip(argv, 1)) {
|
||||||
_cleanup_(user_record_unrefp) UserRecord *secret = NULL;
|
_cleanup_(user_record_unrefp) UserRecord *secret = NULL;
|
||||||
|
|
||||||
secret = user_record_new();
|
r = acquire_passed_secrets(*i, &secret);
|
||||||
if (!secret)
|
if (r < 0)
|
||||||
return log_oom();
|
return r;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||||
@ -1727,9 +1845,9 @@ static int with_home(int argc, char *argv[], void *userdata) {
|
|||||||
if (!cmdline)
|
if (!cmdline)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
secret = user_record_new();
|
r = acquire_passed_secrets(argv[1], &secret);
|
||||||
if (!secret)
|
if (r < 0)
|
||||||
return log_oom();
|
return r;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
r = bus_message_new_method_call(bus, &m, bus_mgr, "AcquireHome");
|
r = bus_message_new_method_call(bus, &m, bus_mgr, "AcquireHome");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user