]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/home/home-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #include "dns-domain.h"
4 #include "errno-util.h"
6 #include "libcrypt-util.h"
7 #include "memory-util.h"
9 #include "string-util.h"
11 #include "user-util.h"
13 bool suitable_user_name(const char *name
) {
15 /* Checks whether the specified name is suitable for management via homed. Note that client-side
16 * we usually validate with the simple valid_user_group_name(), while server-side we are a bit more
17 * restrictive, so that we can change the rules server-side without having to update things
20 if (!valid_user_group_name(name
, 0))
23 /* We generally rely on NSS to tell us which users not to care for, but let's filter out some
24 * particularly well-known users. */
28 NOBODY_USER_NAME
, NOBODY_GROUP_NAME
))
31 /* Let's also defend our own namespace, as well as Debian's (unwritten?) logic of prefixing system
32 * users with underscores. */
33 if (STARTSWITH_SET(name
, "systemd-", "_"))
39 int suitable_realm(const char *realm
) {
40 _cleanup_free_
char *normalized
= NULL
;
43 /* Similar to the above: let's validate the realm a bit stricter server-side than client side */
45 r
= dns_name_normalize(realm
, 0, &normalized
); /* this also checks general validity */
51 if (!streq(realm
, normalized
)) /* is this normalized? */
54 if (dns_name_is_root(realm
)) /* Don't allow top level domain */
60 int suitable_image_path(const char *path
) {
62 return !empty_or_root(path
) &&
63 path_is_valid(path
) &&
64 path_is_absolute(path
);
67 int split_user_name_realm(const char *t
, char **ret_user_name
, char **ret_realm
) {
68 _cleanup_free_
char *user_name
= NULL
, *realm
= NULL
;
73 assert(ret_user_name
);
78 user_name
= strdup(t
);
82 user_name
= strndup(t
, c
- t
);
86 realm
= strdup(c
+ 1);
91 if (!suitable_user_name(user_name
))
95 r
= suitable_realm(realm
);
102 *ret_user_name
= TAKE_PTR(user_name
);
103 *ret_realm
= TAKE_PTR(realm
);
108 int bus_message_append_secret(sd_bus_message
*m
, UserRecord
*secret
) {
109 _cleanup_(erase_and_freep
) char *formatted
= NULL
;
116 if (!FLAGS_SET(secret
->mask
, USER_RECORD_SECRET
))
117 return sd_bus_message_append(m
, "s", "{}");
119 v
= json_variant_by_key(secret
->json
, "secret");
123 r
= json_variant_format(v
, 0, &formatted
);
127 return sd_bus_message_append(m
, "s", formatted
);
130 int test_password_one(const char *hashed_password
, const char *password
) {
131 struct crypt_data cc
= {};
136 k
= crypt_r(password
, hashed_password
, &cc
);
138 explicit_bzero_safe(&cc
, sizeof(cc
));
139 return errno_or_else(EINVAL
);
142 b
= streq(k
, hashed_password
);
143 explicit_bzero_safe(&cc
, sizeof(cc
));
147 int test_password_many(char **hashed_password
, const char *password
) {
151 STRV_FOREACH(hpw
, hashed_password
) {
152 r
= test_password_one(*hpw
, password
);