]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
homectl: don't use cached passwords when re-requesting password because wrong
authorLennart Poettering <lennart@poettering.net>
Fri, 23 Apr 2021 12:53:32 +0000 (14:53 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 23 Apr 2021 21:18:43 +0000 (23:18 +0200)
Asking repeatedly for a password is pointless if we always use the same
cached one. Let's thus disable cache use whenever we failed already
once.

src/home/homectl.c

index a187a75d863c9dc1c0492e09d84a9a133a05944b..34363c4f703b51e98790284508f6a80d648d83fa 100644 (file)
@@ -190,7 +190,12 @@ static int list_homes(int argc, char *argv[], void *userdata) {
         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_free_ char *question = NULL;
         char *e;
@@ -212,7 +217,7 @@ static int acquire_existing_password(const char *user_name, UserRecord *hr, bool
                 string_erase(e);
                 assert_se(unsetenv("PASSWORD") == 0);
 
-                return 0;
+                return 1;
         }
 
         if (asprintf(&question, emphasize_current ?
@@ -221,7 +226,14 @@ static int acquire_existing_password(const char *user_name, UserRecord *hr, bool
                      user_name) < 0)
                 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 < 0)
                 return log_error_errno(r, "Failed to acquire password: %m");
 
@@ -229,10 +241,14 @@ static int acquire_existing_password(const char *user_name, UserRecord *hr, bool
         if (r < 0)
                 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_free_ char *question = NULL;
         char *e;
@@ -250,14 +266,21 @@ static int acquire_token_pin(const char *user_name, UserRecord *hr) {
                 string_erase(e);
                 assert_se(unsetenv("PIN") == 0);
 
-                return 0;
+                return 1;
         }
 
         if (asprintf(&question, "Please enter security token PIN for user %s:", user_name) < 0)
                 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(question, "user-home", NULL, "token-pin", "home.token-pin", USEC_INFINITY, 0, &pin);
+        r = ask_password_auto(
+                        question,
+                        /* icon= */ "user-home",
+                        NULL,
+                        /* key_name= */ "token-pin",
+                        /* credential_name= */ "home.token-pin",
+                        USEC_INFINITY,
+                        flags,
+                        &pin);
         if (r < 0)
                 return log_error_errno(r, "Failed to acquire security token PIN: %m");
 
@@ -265,7 +288,7 @@ static int acquire_token_pin(const char *user_name, UserRecord *hr) {
         if (r < 0)
                 return log_error_errno(r, "Failed to store security token PIN: %m");
 
-        return 0;
+        return 1;
 }
 
 static int handle_generic_user_record_error(
@@ -292,7 +315,13 @@ static int handle_generic_user_record_error(
                 if (!strv_isempty(hr->password))
                         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)
                         return r;
 
@@ -303,13 +332,21 @@ static int handle_generic_user_record_error(
                 else
                         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)
                         return r;
 
         } 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)
                         return r;
 
@@ -340,7 +377,11 @@ static int handle_generic_user_record_error(
 
                 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)
                         return r;
 
@@ -348,7 +389,10 @@ static int handle_generic_user_record_error(
 
                 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)
                         return r;
 
@@ -356,7 +400,10 @@ static int handle_generic_user_record_error(
 
                 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)
                         return r;
         } else
@@ -399,7 +446,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);
                         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 (ret == 0)
                                                 ret = r;
@@ -1010,7 +1057,15 @@ static int acquire_new_password(
                 if (asprintf(&question, "Please enter new password for user %s:", user_name) < 0)
                         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)
                         return log_error_errno(r, "Failed to acquire password: %m");
 
@@ -1018,7 +1073,15 @@ static int acquire_new_password(
                 if (asprintf(&question, "Please enter new password for user %s (repeat):", user_name) < 0)
                         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)
                         return log_error_errno(r, "Failed to acquire password: %m");
 
@@ -1106,7 +1169,11 @@ static int create_home(int argc, char *argv[], void *userdata) {
                                 return log_error_errno(r, "Failed to hash password: %m");
                 } else {
                         /* 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)
                                 return r;
                 }