]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/home/home-util.c
Merge pull request #15703 from poettering/homed-tweak-default-storage
[thirdparty/systemd.git] / src / home / home-util.c
CommitLineData
70a5db58
LP
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include "dns-domain.h"
4#include "errno-util.h"
5#include "home-util.h"
6#include "libcrypt-util.h"
7#include "memory-util.h"
8#include "path-util.h"
9#include "string-util.h"
10#include "strv.h"
11#include "user-util.h"
12
13bool suitable_user_name(const char *name) {
14
3e93027b 15 /* Checks whether the specified name is suitable for management via homed. Note that client-side
18143cd7 16 * we usually validate with the simple valid_user_group_name(), while server-side we are a bit more
2a4be3c5
ZJS
17 * restrictive, so that we can change the rules server-side without having to update things
18 * client-side too. */
70a5db58 19
7a8867ab 20 if (!valid_user_group_name(name, 0))
70a5db58
LP
21 return false;
22
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. */
25 if (STR_IN_SET(name,
26 "root",
27 "nobody",
28 NOBODY_USER_NAME, NOBODY_GROUP_NAME))
29 return false;
30
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-", "_"))
34 return false;
35
36 return true;
37}
38
39int suitable_realm(const char *realm) {
40 _cleanup_free_ char *normalized = NULL;
41 int r;
42
43 /* Similar to the above: let's validate the realm a bit stricter server-side than client side */
44
45 r = dns_name_normalize(realm, 0, &normalized); /* this also checks general validity */
46 if (r == -EINVAL)
47 return 0;
48 if (r < 0)
49 return r;
50
51 if (!streq(realm, normalized)) /* is this normalized? */
52 return false;
53
54 if (dns_name_is_root(realm)) /* Don't allow top level domain */
55 return false;
56
57 return true;
58}
59
60int suitable_image_path(const char *path) {
61
62 return !empty_or_root(path) &&
63 path_is_valid(path) &&
64 path_is_absolute(path);
65}
66
c07bf7a4
LP
67bool supported_fstype(const char *fstype) {
68 /* Limit the set of supported file systems a bit, as protection against little tested kernel file
69 * systems. Also, we only support the resize ioctls for these file systems. */
70 return STR_IN_SET(fstype, "ext4", "btrfs", "xfs");
71}
72
70a5db58
LP
73int split_user_name_realm(const char *t, char **ret_user_name, char **ret_realm) {
74 _cleanup_free_ char *user_name = NULL, *realm = NULL;
75 const char *c;
76 int r;
77
78 assert(t);
79 assert(ret_user_name);
80 assert(ret_realm);
81
82 c = strchr(t, '@');
83 if (!c) {
84 user_name = strdup(t);
85 if (!user_name)
86 return -ENOMEM;
87 } else {
88 user_name = strndup(t, c - t);
89 if (!user_name)
90 return -ENOMEM;
91
92 realm = strdup(c + 1);
93 if (!realm)
94 return -ENOMEM;
95 }
96
97 if (!suitable_user_name(user_name))
98 return -EINVAL;
99
100 if (realm) {
101 r = suitable_realm(realm);
102 if (r < 0)
103 return r;
104 if (r == 0)
105 return -EINVAL;
106 }
107
108 *ret_user_name = TAKE_PTR(user_name);
109 *ret_realm = TAKE_PTR(realm);
110
111 return 0;
112}
113
114int bus_message_append_secret(sd_bus_message *m, UserRecord *secret) {
115 _cleanup_(erase_and_freep) char *formatted = NULL;
116 JsonVariant *v;
117 int r;
118
119 assert(m);
120 assert(secret);
121
122 if (!FLAGS_SET(secret->mask, USER_RECORD_SECRET))
123 return sd_bus_message_append(m, "s", "{}");
124
125 v = json_variant_by_key(secret->json, "secret");
126 if (!v)
127 return -EINVAL;
128
129 r = json_variant_format(v, 0, &formatted);
130 if (r < 0)
131 return r;
132
2ffee2c9
LP
133 (void) sd_bus_message_sensitive(m);
134
70a5db58
LP
135 return sd_bus_message_append(m, "s", formatted);
136}
137
138int test_password_one(const char *hashed_password, const char *password) {
139 struct crypt_data cc = {};
140 const char *k;
141 bool b;
142
143 errno = 0;
144 k = crypt_r(password, hashed_password, &cc);
145 if (!k) {
146 explicit_bzero_safe(&cc, sizeof(cc));
147 return errno_or_else(EINVAL);
148 }
149
150 b = streq(k, hashed_password);
151 explicit_bzero_safe(&cc, sizeof(cc));
152 return b;
153}
154
155int test_password_many(char **hashed_password, const char *password) {
156 char **hpw;
157 int r;
158
159 STRV_FOREACH(hpw, hashed_password) {
160 r = test_password_one(*hpw, password);
161 if (r < 0)
162 return r;
163 if (r > 0)
164 return true;
165 }
166
167 return false;
168}