]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/home/homectl.c
user-record: rename JSON field "pkcs11Pin" to "tokenPin"
[thirdparty/systemd.git] / src / home / homectl.c
index d35034ac08e6c22de71eb682738a3545cc9ac25e..e69fa63fa32c6011ecad5789af868071e366297c 100644 (file)
@@ -8,7 +8,7 @@
 #include "ask-password-api.h"
 #include "bus-common-errors.h"
 #include "bus-error.h"
-#include "bus-util.h"
+#include "bus-locator.h"
 #include "cgroup-util.h"
 #include "dns-domain.h"
 #include "env-util.h"
@@ -116,15 +116,7 @@ static int list_homes(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
-        r = sd_bus_call_method(
-                        bus,
-                        "org.freedesktop.home1",
-                        "/org/freedesktop/home1",
-                        "org.freedesktop.home1.Manager",
-                        "ListHomes",
-                        &error,
-                        &reply,
-                        NULL);
+        r = bus_call_method(bus, bus_home_mgr, "ListHomes", &error, &reply, NULL);
         if (r < 0)
                 return log_error_errno(r, "Failed to list homes: %s", bus_error_message(&error, r));
 
@@ -192,9 +184,9 @@ static int list_homes(int argc, char *argv[], void *userdata) {
 
         if (arg_legend && !arg_json) {
                 if (table_get_rows(table) > 1)
-                        printf("\n%zu homes listed.\n", table_get_rows(table) - 1);
+                        printf("\n%zu home areas listed.\n", table_get_rows(table) - 1);
                 else
-                        printf("No homes.\n");
+                        printf("No home areas.\n");
         }
 
         return 0;
@@ -244,7 +236,7 @@ static int acquire_existing_password(const char *user_name, UserRecord *hr, bool
         return 0;
 }
 
-static int acquire_pkcs11_pin(const char *user_name, UserRecord *hr) {
+static int acquire_token_pin(const char *user_name, UserRecord *hr) {
         _cleanup_(strv_free_erasep) char **pin = NULL;
         _cleanup_free_ char *question = NULL;
         char *e;
@@ -255,9 +247,9 @@ static int acquire_pkcs11_pin(const char *user_name, UserRecord *hr) {
 
         e = getenv("PIN");
         if (e) {
-                r = user_record_set_pkcs11_pin(hr, STRV_MAKE(e), false);
+                r = user_record_set_token_pin(hr, STRV_MAKE(e), false);
                 if (r < 0)
-                        return log_error_errno(r, "Failed to store PKCS#11 PIN: %m");
+                        return log_error_errno(r, "Failed to store token PIN: %m");
 
                 string_erase(e);
 
@@ -271,11 +263,11 @@ static int acquire_pkcs11_pin(const char *user_name, UserRecord *hr) {
                 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, "pkcs11-pin", USEC_INFINITY, 0, &pin);
+        r = ask_password_auto(question, "user-home", NULL, "token-pin", USEC_INFINITY, 0, &pin);
         if (r < 0)
                 return log_error_errno(r, "Failed to acquire security token PIN: %m");
 
-        r = user_record_set_pkcs11_pin(hr, pin, false);
+        r = user_record_set_token_pin(hr, pin, false);
         if (r < 0)
                 return log_error_errno(r, "Failed to store security token PIN: %m");
 
@@ -295,7 +287,7 @@ static int handle_generic_user_record_error(
 
         if (sd_bus_error_has_name(error, BUS_ERROR_HOME_ABSENT))
                 return log_error_errno(SYNTHETIC_ERRNO(EREMOTE),
-                                       "Home of user %s is currently absent, please plug in the necessary stroage device or backing file system.", user_name);
+                                       "Home of user %s is currently absent, please plug in the necessary storage device or backing file system.", user_name);
 
         else if (sd_bus_error_has_name(error, BUS_ERROR_AUTHENTICATION_LIMIT_HIT))
                 return log_error_errno(SYNTHETIC_ERRNO(ETOOMANYREFS),
@@ -323,7 +315,7 @@ static int handle_generic_user_record_error(
 
         } else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_PIN_NEEDED)) {
 
-                r = acquire_pkcs11_pin(user_name, hr);
+                r = acquire_token_pin(user_name, hr);
                 if (r < 0)
                         return r;
 
@@ -342,7 +334,7 @@ static int handle_generic_user_record_error(
 
                 log_notice("Security token PIN incorrect, please try again.");
 
-                r = acquire_pkcs11_pin(user_name, hr);
+                r = acquire_token_pin(user_name, hr);
                 if (r < 0)
                         return r;
 
@@ -350,7 +342,7 @@ static int handle_generic_user_record_error(
 
                 log_notice("Security token PIN incorrect, please try again (only a few tries left!).");
 
-                r = acquire_pkcs11_pin(user_name, hr);
+                r = acquire_token_pin(user_name, hr);
                 if (r < 0)
                         return r;
 
@@ -358,7 +350,7 @@ static int handle_generic_user_record_error(
 
                 log_notice("Security token PIN incorrect, please try again (only one try left!).");
 
-                r = acquire_pkcs11_pin(user_name, hr);
+                r = acquire_token_pin(user_name, hr);
                 if (r < 0)
                         return r;
         } else
@@ -387,13 +379,7 @@ static int activate_home(int argc, char *argv[], void *userdata) {
                         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 
-                        r = sd_bus_message_new_method_call(
-                                        bus,
-                                        &m,
-                                        "org.freedesktop.home1",
-                                        "/org/freedesktop/home1",
-                                        "org.freedesktop.home1.Manager",
-                                        "ActivateHome");
+                        r = bus_message_new_method_call(bus, &m, bus_home_mgr, "ActivateHome");
                         if (r < 0)
                                 return bus_log_create_error(r);
 
@@ -435,13 +421,7 @@ static int deactivate_home(int argc, char *argv[], void *userdata) {
                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 
-                r = sd_bus_message_new_method_call(
-                                bus,
-                                &m,
-                                "org.freedesktop.home1",
-                                "/org/freedesktop/home1",
-                                "org.freedesktop.home1.Manager",
-                                "DeactivateHome");
+                r = bus_message_new_method_call(bus, &m, bus_home_mgr, "DeactivateHome");
                 if (r < 0)
                         return bus_log_create_error(r);
 
@@ -540,7 +520,7 @@ static int inspect_home(int argc, char *argv[], void *userdata) {
 
                 r = parse_uid(*i, &uid);
                 if (r < 0) {
-                        if (!valid_user_group_name(*i)) {
+                        if (!valid_user_group_name(*i, 0)) {
                                 log_error("Invalid user name '%s'.", *i);
                                 if (ret == 0)
                                         ret = -EINVAL;
@@ -548,28 +528,9 @@ static int inspect_home(int argc, char *argv[], void *userdata) {
                                 continue;
                         }
 
-                        r = sd_bus_call_method(
-                                        bus,
-                                        "org.freedesktop.home1",
-                                        "/org/freedesktop/home1",
-                                        "org.freedesktop.home1.Manager",
-                                        "GetUserRecordByName",
-                                        &error,
-                                        &reply,
-                                        "s",
-                                        *i);
-                } else {
-                        r = sd_bus_call_method(
-                                        bus,
-                                        "org.freedesktop.home1",
-                                        "/org/freedesktop/home1",
-                                        "org.freedesktop.home1.Manager",
-                                        "GetUserRecordByUID",
-                                        &error,
-                                        &reply,
-                                        "u",
-                                        (uint32_t) uid);
-                }
+                        r = bus_call_method(bus, bus_home_mgr, "GetUserRecordByName", &error, &reply, "s", *i);
+                } else
+                        r = bus_call_method(bus, bus_home_mgr, "GetUserRecordByUID", &error, &reply, "u", (uint32_t) uid);
 
                 if (r < 0) {
                         log_error_errno(r, "Failed to inspect home: %s", bus_error_message(&error, r));
@@ -643,13 +604,7 @@ static int authenticate_home(int argc, char *argv[], void *userdata) {
                         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 
-                        r = sd_bus_message_new_method_call(
-                                        bus,
-                                        &m,
-                                        "org.freedesktop.home1",
-                                        "/org/freedesktop/home1",
-                                        "org.freedesktop.home1.Manager",
-                                        "AuthenticateHome");
+                        r = bus_message_new_method_call(bus, &m, bus_home_mgr, "AuthenticateHome");
                         if (r < 0)
                                 return bus_log_create_error(r);
 
@@ -1050,7 +1005,7 @@ static int encrypt_bytes(
         return 0;
 }
 
-static int add_pkcs11_pin(JsonVariant **v, const char *pin) {
+static int add_token_pin(JsonVariant **v, const char *pin) {
         _cleanup_(json_variant_unrefp) JsonVariant *w = NULL, *l = NULL;
         _cleanup_(strv_free_erasep) char **pins = NULL;
         int r;
@@ -1061,7 +1016,7 @@ static int add_pkcs11_pin(JsonVariant **v, const char *pin) {
                 return 0;
 
         w = json_variant_ref(json_variant_by_key(*v, "secret"));
-        l = json_variant_ref(json_variant_by_key(w, "pkcs11Pin"));
+        l = json_variant_ref(json_variant_by_key(w, "tokenPin"));
 
         r = json_variant_strv(l, &pins);
         if (r < 0)
@@ -1084,7 +1039,7 @@ static int add_pkcs11_pin(JsonVariant **v, const char *pin) {
 
         json_variant_sensitive(l);
 
-        r = json_variant_set_field(&w, "pkcs11Pin", l);
+        r = json_variant_set_field(&w, "tokenPin", l);
         if (r < 0)
                 return log_error_errno(r, "Failed to update PIN field: %m");
 
@@ -1207,7 +1162,7 @@ static int add_pkcs11_key_data(JsonVariant **v, const char *uri) {
 
         pkey = X509_get0_pubkey(cert);
         if (!pkey)
-                return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to exract public key from X.509 certificate.");
+                return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to extract public key from X.509 certificate.");
 
         if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA)
                 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "X.509 certificate does not refer to RSA key.");
@@ -1257,7 +1212,7 @@ static int add_pkcs11_key_data(JsonVariant **v, const char *uri) {
         /* If we acquired the PIN also include it in the secret section of the record, so that systemd-homed
          * can use it if it needs to, given that it likely needs to decrypt the key again to pass to LUKS or
          * fscrypt. */
-        r = add_pkcs11_pin(v, pin);
+        r = add_token_pin(v, pin);
         if (r < 0)
                 return r;
 
@@ -1338,7 +1293,7 @@ static int acquire_new_password(
                 string_erase(e);
 
                 if (unsetenv("NEWPASSWORD") < 0)
-                        return log_error_errno(errno, "Failed to unse $NEWPASSWORD: %m");
+                        return log_error_errno(errno, "Failed to unset $NEWPASSWORD: %m");
 
                 return 0;
         }
@@ -1376,7 +1331,7 @@ static int acquire_new_password(
                         return 0;
                 }
 
-                log_error("Password didn't mach, try again.");
+                log_error("Password didn't match, try again.");
         }
 }
 
@@ -1395,7 +1350,7 @@ static int create_home(int argc, char *argv[], void *userdata) {
         if (argc >= 2) {
                 /* If a username was specified, use it */
 
-                if (valid_user_group_name(argv[1]))
+                if (valid_user_group_name(argv[1], 0))
                         r = json_variant_set_field_string(&arg_identity_extra, "userName", argv[1]);
                 else {
                         _cleanup_free_ char *un = NULL, *rr = NULL;
@@ -1425,7 +1380,7 @@ static int create_home(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
-        /* Remember the original hashed paswords before we add our own, so that we can return to them later,
+        /* Remember the original hashed passwords before we add our own, so that we can return to them later,
          * should the entered password turn out not to be acceptable. */
         original_hashed_passwords = strv_copy(hr->hashed_password);
         if (!original_hashed_passwords)
@@ -1468,18 +1423,14 @@ static int create_home(int argc, char *argv[], void *userdata) {
 
                 r = json_variant_format(hr->json, 0, &formatted);
                 if (r < 0)
-                        return r;
+                        return log_error_errno(r, "Failed to format user record: %m");
 
-                r = sd_bus_message_new_method_call(
-                                bus,
-                                &m,
-                                "org.freedesktop.home1",
-                                "/org/freedesktop/home1",
-                                "org.freedesktop.home1.Manager",
-                                "CreateHome");
+                r = bus_message_new_method_call(bus, &m, bus_home_mgr, "CreateHome");
                 if (r < 0)
                         return bus_log_create_error(r);
 
+                (void) sd_bus_message_sensitive(m);
+
                 r = sd_bus_message_append(m, "s", formatted);
                 if (r < 0)
                         return bus_log_create_error(r);
@@ -1525,13 +1476,7 @@ static int remove_home(int argc, char *argv[], void *userdata) {
                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 
-                r = sd_bus_message_new_method_call(
-                                bus,
-                                &m,
-                                "org.freedesktop.home1",
-                                "/org/freedesktop/home1",
-                                "org.freedesktop.home1.Manager",
-                                "RemoveHome");
+                r = bus_message_new_method_call(bus, &m, bus_home_mgr, "RemoveHome");
                 if (r < 0)
                         return bus_log_create_error(r);
 
@@ -1594,16 +1539,7 @@ static int acquire_updated_home_record(
                 if (!identity_properties_specified())
                         return log_error_errno(SYNTHETIC_ERRNO(EALREADY), "No field to change specified.");
 
-                r = sd_bus_call_method(
-                                bus,
-                                "org.freedesktop.home1",
-                                "/org/freedesktop/home1",
-                                "org.freedesktop.home1.Manager",
-                                "GetUserRecordByName",
-                                &error,
-                                &reply,
-                                "s",
-                                username);
+                r = bus_call_method(bus, bus_home_mgr, "GetUserRecordByName", &error, &reply, "s", username);
                 if (r < 0)
                         return log_error_errno(r, "Failed to acquire user home record: %s", bus_error_message(&error, r));
 
@@ -1689,19 +1625,15 @@ static int update_home(int argc, char *argv[], void *userdata) {
                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
                 _cleanup_free_ char *formatted = NULL;
 
-                r = sd_bus_message_new_method_call(
-                                bus,
-                                &m,
-                                "org.freedesktop.home1",
-                                "/org/freedesktop/home1",
-                                "org.freedesktop.home1.Manager",
-                                "UpdateHome");
+                r = bus_message_new_method_call(bus, &m, bus_home_mgr, "UpdateHome");
                 if (r < 0)
                         return bus_log_create_error(r);
 
                 r = json_variant_format(hr->json, 0, &formatted);
                 if (r < 0)
-                        return r;
+                        return log_error_errno(r, "Failed to format user record: %m");
+
+                (void) sd_bus_message_sensitive(m);
 
                 r = sd_bus_message_append(m, "s", formatted);
                 if (r < 0)
@@ -1730,13 +1662,7 @@ static int update_home(int argc, char *argv[], void *userdata) {
 
                 log_debug("Resizing");
 
-                r = sd_bus_message_new_method_call(
-                                bus,
-                                &m,
-                                "org.freedesktop.home1",
-                                "/org/freedesktop/home1",
-                                "org.freedesktop.home1.Manager",
-                                "ResizeHome");
+                r = bus_message_new_method_call(bus, &m, bus_home_mgr, "ResizeHome");
                 if (r < 0)
                         return bus_log_create_error(r);
 
@@ -1769,13 +1695,7 @@ static int update_home(int argc, char *argv[], void *userdata) {
 
                 log_debug("Propagating password");
 
-                r = sd_bus_message_new_method_call(
-                                bus,
-                                &m,
-                                "org.freedesktop.home1",
-                                "/org/freedesktop/home1",
-                                "org.freedesktop.home1.Manager",
-                                "ChangePasswordHome");
+                r = bus_message_new_method_call(bus, &m, bus_home_mgr, "ChangePasswordHome");
                 if (r < 0)
                         return bus_log_create_error(r);
 
@@ -1847,13 +1767,7 @@ static int passwd_home(int argc, char *argv[], void *userdata) {
                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 
-                r = sd_bus_message_new_method_call(
-                                bus,
-                                &m,
-                                "org.freedesktop.home1",
-                                "/org/freedesktop/home1",
-                                "org.freedesktop.home1.Manager",
-                                "ChangePasswordHome");
+                r = bus_message_new_method_call(bus, &m, bus_home_mgr, "ChangePasswordHome");
                 if (r < 0)
                         return bus_log_create_error(r);
 
@@ -1932,13 +1846,7 @@ static int resize_home(int argc, char *argv[], void *userdata) {
                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 
-                r = sd_bus_message_new_method_call(
-                                bus,
-                                &m,
-                                "org.freedesktop.home1",
-                                "/org/freedesktop/home1",
-                                "org.freedesktop.home1.Manager",
-                                "ResizeHome");
+                r = bus_message_new_method_call(bus, &m, bus_home_mgr, "ResizeHome");
                 if (r < 0)
                         return bus_log_create_error(r);
 
@@ -1975,13 +1883,7 @@ static int lock_home(int argc, char *argv[], void *userdata) {
                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 
-                r = sd_bus_message_new_method_call(
-                                bus,
-                                &m,
-                                "org.freedesktop.home1",
-                                "/org/freedesktop/home1",
-                                "org.freedesktop.home1.Manager",
-                                "LockHome");
+                r = bus_message_new_method_call(bus, &m, bus_home_mgr, "LockHome");
                 if (r < 0)
                         return bus_log_create_error(r);
 
@@ -2020,13 +1922,7 @@ static int unlock_home(int argc, char *argv[], void *userdata) {
                         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 
-                        r = sd_bus_message_new_method_call(
-                                        bus,
-                                        &m,
-                                        "org.freedesktop.home1",
-                                        "/org/freedesktop/home1",
-                                        "org.freedesktop.home1.Manager",
-                                        "UnlockHome");
+                        r = bus_message_new_method_call(bus, &m, bus_home_mgr, "UnlockHome");
                         if (r < 0)
                                 return bus_log_create_error(r);
 
@@ -2089,13 +1985,7 @@ static int with_home(int argc, char *argv[], void *userdata) {
                 return log_oom();
 
         for (;;) {
-                r = sd_bus_message_new_method_call(
-                                bus,
-                                &m,
-                                "org.freedesktop.home1",
-                                "/org/freedesktop/home1",
-                                "org.freedesktop.home1.Manager",
-                                "AcquireHome");
+                r = bus_message_new_method_call(bus, &m, bus_home_mgr, "AcquireHome");
                 if (r < 0)
                         return bus_log_create_error(r);
 
@@ -2135,16 +2025,7 @@ static int with_home(int argc, char *argv[], void *userdata) {
                 }
         }
 
-        r = sd_bus_call_method(
-                        bus,
-                        "org.freedesktop.home1",
-                        "/org/freedesktop/home1",
-                        "org.freedesktop.home1.Manager",
-                        "GetHomeByName",
-                        &error,
-                        &reply,
-                        "s",
-                        argv[1]);
+        r = bus_call_method(bus, bus_home_mgr, "GetHomeByName", &error, &reply, "s", argv[1]);
         if (r < 0)
                 return log_error_errno(r, "Failed to inspect home: %s", bus_error_message(&error, r));
 
@@ -2171,13 +2052,7 @@ static int with_home(int argc, char *argv[], void *userdata) {
         /* Close the fd that pings the home now. */
         acquired_fd = safe_close(acquired_fd);
 
-        r = sd_bus_message_new_method_call(
-                        bus,
-                        &m,
-                        "org.freedesktop.home1",
-                        "/org/freedesktop/home1",
-                        "org.freedesktop.home1.Manager",
-                        "ReleaseHome");
+        r = bus_message_new_method_call(bus, &m, bus_home_mgr, "ReleaseHome");
         if (r < 0)
                 return bus_log_create_error(r);
 
@@ -2206,13 +2081,7 @@ static int lock_all_homes(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
-        r = sd_bus_message_new_method_call(
-                        bus,
-                        &m,
-                        "org.freedesktop.home1",
-                        "/org/freedesktop/home1",
-                        "org.freedesktop.home1.Manager",
-                        "LockAllHomes");
+        r = bus_message_new_method_call(bus, &m, bus_home_mgr, "LockAllHomes");
         if (r < 0)
                 return bus_log_create_error(r);
 
@@ -2263,20 +2132,20 @@ static int help(int argc, char *argv[], void *userdata) {
         printf("%1$s [OPTIONS...] COMMAND ...\n\n"
                "%2$sCreate, manipulate or inspect home directories.%3$s\n"
                "\n%4$sCommands:%5$s\n"
-               "  list                        List homes\n"
-               "  activate USER…              Activate home\n"
-               "  deactivate USER…            Deactivate home\n"
-               "  inspect USER…               Inspect home\n"
-               "  authenticate USER…          Authenticate home\n"
+               "  list                        List home areas\n"
+               "  activate USER…              Activate a home area\n"
+               "  deactivate USER…            Deactivate a home area\n"
+               "  inspect USER…               Inspect a home area\n"
+               "  authenticate USER…          Authenticate a home area\n"
                "  create USER                 Create a home area\n"
                "  remove USER…                Remove a home area\n"
                "  update USER                 Update a home area\n"
                "  passwd USER                 Change password of a home area\n"
                "  resize USER SIZE            Resize a home area\n"
-               "  lock USER…                  Temporarily lock an active home\n"
-               "  unlock USER…                Unlock a temporarily locked home\n"
-               "  lock-all                    Lock all suitable homes\n"
-               "  with USER [COMMAND…]        Run shell or command with access to home\n"
+               "  lock USER…                  Temporarily lock an active home area\n"
+               "  unlock USER…                Unlock a temporarily locked home area\n"
+               "  lock-all                    Lock all suitable home areas\n"
+               "  with USER [COMMAND…]        Run shell or command with access to a home area\n"
                "\n%4$sOptions:%5$s\n"
                "  -h --help                   Show this help\n"
                "     --version                Show package version\n"
@@ -2302,7 +2171,7 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --location=LOCATION      Set location of user on earth\n"
                "     --icon-name=NAME         Icon name for user\n"
                "  -d --home-dir=PATH          Home directory\n"
-               "     --uid=UID                Numeric UID for user\n"
+               "  -u --uid=UID                Numeric UID for user\n"
                "  -G --member-of=GROUP        Add user to group\n"
                "     --skel=PATH              Skeleton directory to use\n"
                "     --shell=PATH             Shell for account\n"
@@ -2357,6 +2226,9 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --fs-type=TYPE           File system type to use in case of luks\n"
                "                              storage (ext4, xfs, btrfs)\n"
                "     --luks-discard=BOOL      Whether to use 'discard' feature of file system\n"
+               "                              when activated (mounted)\n"
+               "     --luks-offline-discard=BOOL\n"
+               "                              Whether to trim file on logout\n"
                "     --luks-cipher=CIPHER     Cipher to use for LUKS encryption\n"
                "     --luks-cipher-mode=MODE  Cipher mode to use for LUKS encryption\n"
                "     --luks-volume-key-size=BITS\n"
@@ -2377,7 +2249,7 @@ static int help(int argc, char *argv[], void *userdata) {
                "\n%4$sCIFS User Record Properties:%5$s\n"
                "     --cifs-domain=DOMAIN     CIFS (Windows) domain\n"
                "     --cifs-user-name=USER    CIFS (Windows) user name\n"
-               "     --cifs-service=SERVICE   CIFS (Windows) service to mount as home\n"
+               "     --cifs-service=SERVICE   CIFS (Windows) service to mount as home area\n"
                "\n%4$sLogin Behaviour User Record Properties:%5$s\n"
                "     --stop-delay=SECS        How long to leave user services running after\n"
                "                              logout\n"
@@ -2410,6 +2282,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_IMAGE_PATH,
                 ARG_UMASK,
                 ARG_LUKS_DISCARD,
+                ARG_LUKS_OFFLINE_DISCARD,
                 ARG_JSON,
                 ARG_SETENV,
                 ARG_TIMEZONE,
@@ -2503,6 +2376,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "image-path",                  required_argument, NULL, ARG_IMAGE_PATH                  },
                 { "fs-type",                     required_argument, NULL, ARG_FS_TYPE                     },
                 { "luks-discard",                required_argument, NULL, ARG_LUKS_DISCARD                },
+                { "luks-offline-discard",        required_argument, NULL, ARG_LUKS_OFFLINE_DISCARD        },
                 { "luks-cipher",                 required_argument, NULL, ARG_LUKS_CIPHER                 },
                 { "luks-cipher-mode",            required_argument, NULL, ARG_LUKS_CIPHER_MODE            },
                 { "luks-volume-key-size",        required_argument, NULL, ARG_LUKS_VOLUME_KEY_SIZE        },
@@ -2896,7 +2770,7 @@ static int parse_argv(int argc, char *argv[]) {
 
                         r = json_variant_set_field(&arg_identity_extra, "environment", ne);
                         if (r < 0)
-                                return log_error_errno(r, "Failed to set environent list: %m");
+                                return log_error_errno(r, "Failed to set environment list: %m");
 
                         break;
                 }
@@ -2932,6 +2806,9 @@ static int parse_argv(int argc, char *argv[]) {
                         if (!locale_is_valid(optarg))
                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Locale '%s' is not valid.", optarg);
 
+                        if (locale_is_installed(optarg) <= 0)
+                                log_warning("Locale '%s' is not installed, accepting anyway.", optarg);
+
                         r = json_variant_set_field_string(&arg_identity_extra, "preferredLanguage", optarg);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to set preferredLanguage field: %m");
@@ -3072,6 +2949,25 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
 
+                case ARG_LUKS_OFFLINE_DISCARD:
+                        if (isempty(optarg)) {
+                                r = drop_from_identity("luksOfflineDiscard");
+                                if (r < 0)
+                                        return r;
+
+                                break;
+                        }
+
+                        r = parse_boolean(optarg);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse --luks-offline-discard= parameter: %s", optarg);
+
+                        r = json_variant_set_field_boolean(&arg_identity_extra, "luksOfflineDiscard", r);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to set offline discard field: %m");
+
+                        break;
+
                 case ARG_LUKS_VOLUME_KEY_SIZE:
                 case ARG_LUKS_PBKDF_PARALLEL_THREADS:
                 case ARG_RATE_LIMIT_BURST: {
@@ -3148,7 +3044,7 @@ static int parse_argv(int argc, char *argv[]) {
 
                                         r = read_line(f, LONG_LINE_MAX, &line);
                                         if (r < 0)
-                                                return log_error_errno(r, "Faile dto read from '%s': %m", optarg+1);
+                                                return log_error_errno(r, "Faileto read from '%s': %m", optarg+1);
                                         if (r == 0)
                                                 break;
 
@@ -3357,7 +3253,7 @@ static int parse_argv(int argc, char *argv[]) {
                                 if (r == 0)
                                         break;
 
-                                if (!valid_user_group_name(word))
+                                if (!valid_user_group_name(word, 0))
                                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid group name %s.", word);
 
                                 mo = json_variant_ref(json_variant_by_key(arg_identity_extra, "memberOf"));
@@ -3593,9 +3489,7 @@ static int run(int argc, char *argv[]) {
 
         int r;
 
-        log_show_color(true);
-        log_parse_environment();
-        log_open();
+        log_setup_cli();
 
         r = parse_argv(argc, argv);
         if (r <= 0)