]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
user-record: add recovery key fields to user record
authorLennart Poettering <lennart@poettering.net>
Mon, 17 Aug 2020 12:28:14 +0000 (14:28 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 25 Aug 2020 15:58:02 +0000 (17:58 +0200)
src/shared/user-record-show.c
src/shared/user-record.c
src/shared/user-record.h

index 84ededd86e95b719dd211b8a1908af23399fe8a1..6aeb6bd33008d98f8a4a58d2e6018a9fe5f49be9 100644 (file)
@@ -479,6 +479,9 @@ void user_record_show(UserRecord *hr, bool show_full_group_info) {
         if (hr->n_fido2_hmac_credential > 0)
                 printf(" FIDO2 Token: %zu\n", hr->n_fido2_hmac_credential);
 
+        if (!strv_isempty(hr->recovery_key_type))
+                printf("Recovery Key: %zu\n", strv_length(hr->recovery_key_type));
+
         k = strv_length(hr->hashed_password);
         if (k == 0)
                 printf("   Passwords: %snone%s\n",
index 5d9fe84061d9cb002ffa792678ce1937e18539d9..e04df4d78b41f52af7187a2800785c0081dfb445 100644 (file)
@@ -112,6 +112,14 @@ static void fido2_hmac_salt_done(Fido2HmacSalt *s) {
         erase_and_free(s->hashed_password);
 }
 
+static void recovery_key_done(RecoveryKey *k) {
+        if (!k)
+                return;
+
+        free(k->type);
+        erase_and_free(k->hashed_password);
+}
+
 static UserRecord* user_record_free(UserRecord *h) {
         if (!h)
                 return NULL;
@@ -169,6 +177,10 @@ static UserRecord* user_record_free(UserRecord *h) {
         for (size_t i = 0; i < h->n_fido2_hmac_salt; i++)
                 fido2_hmac_salt_done(h->fido2_hmac_salt + i);
 
+        strv_free(h->recovery_key_type);
+        for (size_t i = 0; i < h->n_recovery_key; i++)
+                recovery_key_done(h->recovery_key + i);
+
         json_variant_unref(h->json);
 
         return mfree(h);
@@ -924,6 +936,46 @@ static int dispatch_fido2_hmac_salt(const char *name, JsonVariant *variant, Json
         return 0;
 }
 
+static int dispatch_recovery_key(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
+        UserRecord *h = userdata;
+        JsonVariant *e;
+        int r;
+
+        if (!json_variant_is_array(variant))
+                return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an array of objects.", strna(name));
+
+        JSON_VARIANT_ARRAY_FOREACH(e, variant) {
+                RecoveryKey *array, *k;
+
+                static const JsonDispatch recovery_key_dispatch_table[] = {
+                        { "type",           JSON_VARIANT_STRING, json_dispatch_string, 0,                                      JSON_MANDATORY },
+                        { "hashedPassword", JSON_VARIANT_STRING, json_dispatch_string, offsetof(RecoveryKey, hashed_password), JSON_MANDATORY },
+                        {},
+                };
+
+                if (!json_variant_is_object(e))
+                        return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL), "JSON array element is not an object.");
+
+                array = reallocarray(h->recovery_key, h->n_recovery_key + 1, sizeof(RecoveryKey));
+                if (!array)
+                        return log_oom();
+
+                h->recovery_key = array;
+                k = h->recovery_key + h->n_recovery_key;
+                *k = (RecoveryKey) {};
+
+                r = json_dispatch(e, recovery_key_dispatch_table, NULL, flags, k);
+                if (r < 0) {
+                        recovery_key_done(k);
+                        return r;
+                }
+
+                h->n_recovery_key++;
+        }
+
+        return 0;
+}
+
 static int dispatch_privileged(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
 
         static const JsonDispatch privileged_dispatch_table[] = {
@@ -932,6 +984,7 @@ static int dispatch_privileged(const char *name, JsonVariant *variant, JsonDispa
                 { "sshAuthorizedKeys",  _JSON_VARIANT_TYPE_INVALID, json_dispatch_strv,       offsetof(UserRecord, ssh_authorized_keys),  0         },
                 { "pkcs11EncryptedKey", JSON_VARIANT_ARRAY,         dispatch_pkcs11_key,      0,                                          0         },
                 { "fido2HmacSalt",      JSON_VARIANT_ARRAY,         dispatch_fido2_hmac_salt, 0,                                          0         },
+                { "recoveryKey",        JSON_VARIANT_ARRAY,         dispatch_recovery_key,    0,                                          0         },
                 {},
         };
 
@@ -1475,6 +1528,7 @@ int user_record_load(UserRecord *h, JsonVariant *v, UserRecordLoadFlags load_fla
                 { "passwordChangeNow",          JSON_VARIANT_BOOLEAN,       json_dispatch_tristate,               offsetof(UserRecord, password_change_now),           0         },
                 { "pkcs11TokenUri",             JSON_VARIANT_ARRAY,         dispatch_pkcs11_uri_array,            offsetof(UserRecord, pkcs11_token_uri),              0         },
                 { "fido2HmacCredential",        JSON_VARIANT_ARRAY,         dispatch_fido2_hmac_credential_array, 0,                                                   0         },
+                { "recoveryKeyType",            JSON_VARIANT_ARRAY,         json_dispatch_strv,                   offsetof(UserRecord, recovery_key_type),             0         },
 
                 { "secret",                     JSON_VARIANT_OBJECT,        dispatch_secret,                      0,                                                   0         },
                 { "privileged",                 JSON_VARIANT_OBJECT,        dispatch_privileged,                  0,                                                   0         },
index 39580b6b76a807d2ae756e1656d900ecf9e8769f..bbcb2201e8a8f7e9a5c55509bdf3c2d0e1cb3cbf 100644 (file)
@@ -206,6 +206,14 @@ typedef struct Fido2HmacSalt {
         char *hashed_password;
 } Fido2HmacSalt;
 
+typedef struct RecoveryKey {
+        /* The type of recovery key, must be "modhex64" right now */
+        char *type;
+
+        /* A UNIX pasword hash of the normalized form of modhex64 */
+        char *hashed_password;
+} RecoveryKey;
+
 typedef struct UserRecord {
         /* The following three fields are not part of the JSON record */
         unsigned n_ref;
@@ -332,6 +340,10 @@ typedef struct UserRecord {
         size_t n_fido2_hmac_salt;
         int fido2_user_presence_permitted;
 
+        char **recovery_key_type;
+        RecoveryKey *recovery_key;
+        size_t n_recovery_key;
+
         JsonVariant *json;
 } UserRecord;