user-record: add support for alias user names to user record

This commit is contained in:
Lennart Poettering
2025-01-16 14:15:52 +01:00
parent 8aacf0fee1
commit e2e1f38f5a
4 changed files with 29 additions and 1 deletions

View File

@@ -226,6 +226,14 @@ This field is optional, when unset the user should not be considered part of any
A user record with a realm set is never compatible (for the purpose of updates,
see above) with a user record without one set, even if the `userName` field matches.
`aliases` → An array of strings, each being a valid UNIX user name. If
specified, a list of additional UNIX user names this record shall be known
under. These are *alias* names only, the name in `userName` is always the
primary name. Typically, a user record that carries this field shall be
retrievable and resolvable under every name listed here, pretty much everywhere
the primary user name is. If logging in is attempted via an alias name it
should be normalized to the primary name.
`blobDirectory` → The absolute path to a world-readable copy of the user's blob
directory. See [Blob Directories](/USER_RECORD_BLOB_DIRS) for more details.

View File

@@ -65,6 +65,13 @@ void user_record_show(UserRecord *hr, bool show_full_group_info) {
printf(" User name: %s\n",
user_record_user_name_and_realm(hr));
if (!strv_isempty(hr->aliases)) {
STRV_FOREACH(i, hr->aliases)
printf(i == hr->aliases ?
" Alias: %s" : ", %s", *i);
putchar('\n');
}
if (hr->state) {
const char *color;

View File

@@ -140,6 +140,7 @@ static UserRecord* user_record_free(UserRecord *h) {
free(h->user_name);
free(h->realm);
free(h->user_name_and_realm_auto);
strv_free(h->aliases);
free(h->real_name);
free(h->email_address);
erase_and_free(h->password_hint);
@@ -1538,6 +1539,7 @@ int user_record_load(UserRecord *h, sd_json_variant *v, UserRecordLoadFlags load
static const sd_json_dispatch_field user_dispatch_table[] = {
{ "userName", SD_JSON_VARIANT_STRING, json_dispatch_user_group_name, offsetof(UserRecord, user_name), SD_JSON_RELAX },
{ "aliases", SD_JSON_VARIANT_ARRAY, json_dispatch_user_group_list, offsetof(UserRecord, aliases), SD_JSON_RELAX },
{ "realm", SD_JSON_VARIANT_STRING, json_dispatch_realm, offsetof(UserRecord, realm), 0 },
{ "blobDirectory", SD_JSON_VARIANT_STRING, json_dispatch_path, offsetof(UserRecord, blob_directory), SD_JSON_STRICT },
{ "blobManifest", SD_JSON_VARIANT_OBJECT, dispatch_blob_manifest, offsetof(UserRecord, blob_manifest), 0 },
@@ -2635,6 +2637,15 @@ bool user_record_matches_user_name(const UserRecord *u, const char *user_name) {
if (streq_ptr(u->user_name_and_realm_auto, user_name))
return true;
if (strv_contains(u->aliases, user_name))
return true;
const char *realm = strrchr(user_name, '@');
if (realm && streq_ptr(realm+1, u->realm))
STRV_FOREACH(a, u->aliases)
if (startswith(user_name, *a) == realm)
return true;
return false;
}
@@ -2704,7 +2715,8 @@ int user_record_match(UserRecord *u, const UserDBMatch *match) {
u->cifs_user_name,
};
if (!user_name_fuzzy_match(names, ELEMENTSOF(names), match->fuzzy_names))
if (!user_name_fuzzy_match(names, ELEMENTSOF(names), match->fuzzy_names) &&
!user_name_fuzzy_match((const char**) u->aliases, strv_length(u->aliases), match->fuzzy_names))
return false;
}

View File

@@ -239,6 +239,7 @@ typedef struct UserRecord {
char *user_name;
char *realm;
char *user_name_and_realm_auto; /* the user_name field concatenated with '@' and the realm, if the latter is defined */
char **aliases;
char *real_name;
char *email_address;
char *password_hint;