]>
Commit | Line | Data |
---|---|---|
70a5db58 LP |
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
2 | ||
3 | #include "dns-domain.h" | |
70a5db58 LP |
4 | #include "home-util.h" |
5 | #include "libcrypt-util.h" | |
6 | #include "memory-util.h" | |
7 | #include "path-util.h" | |
8 | #include "string-util.h" | |
9 | #include "strv.h" | |
10 | #include "user-util.h" | |
11 | ||
12 | bool suitable_user_name(const char *name) { | |
13 | ||
3e93027b | 14 | /* Checks whether the specified name is suitable for management via homed. Note that client-side |
18143cd7 | 15 | * we usually validate with the simple valid_user_group_name(), while server-side we are a bit more |
2a4be3c5 ZJS |
16 | * restrictive, so that we can change the rules server-side without having to update things |
17 | * client-side too. */ | |
70a5db58 | 18 | |
7a8867ab | 19 | if (!valid_user_group_name(name, 0)) |
70a5db58 LP |
20 | return false; |
21 | ||
22 | /* We generally rely on NSS to tell us which users not to care for, but let's filter out some | |
23 | * particularly well-known users. */ | |
24 | if (STR_IN_SET(name, | |
25 | "root", | |
26 | "nobody", | |
27 | NOBODY_USER_NAME, NOBODY_GROUP_NAME)) | |
28 | return false; | |
29 | ||
30 | /* Let's also defend our own namespace, as well as Debian's (unwritten?) logic of prefixing system | |
31 | * users with underscores. */ | |
32 | if (STARTSWITH_SET(name, "systemd-", "_")) | |
33 | return false; | |
34 | ||
35 | return true; | |
36 | } | |
37 | ||
38 | int suitable_realm(const char *realm) { | |
39 | _cleanup_free_ char *normalized = NULL; | |
40 | int r; | |
41 | ||
42 | /* Similar to the above: let's validate the realm a bit stricter server-side than client side */ | |
43 | ||
44 | r = dns_name_normalize(realm, 0, &normalized); /* this also checks general validity */ | |
45 | if (r == -EINVAL) | |
46 | return 0; | |
47 | if (r < 0) | |
48 | return r; | |
49 | ||
50 | if (!streq(realm, normalized)) /* is this normalized? */ | |
51 | return false; | |
52 | ||
53 | if (dns_name_is_root(realm)) /* Don't allow top level domain */ | |
54 | return false; | |
55 | ||
56 | return true; | |
57 | } | |
58 | ||
59 | int suitable_image_path(const char *path) { | |
60 | ||
61 | return !empty_or_root(path) && | |
62 | path_is_valid(path) && | |
63 | path_is_absolute(path); | |
64 | } | |
65 | ||
c07bf7a4 LP |
66 | bool supported_fstype(const char *fstype) { |
67 | /* Limit the set of supported file systems a bit, as protection against little tested kernel file | |
68 | * systems. Also, we only support the resize ioctls for these file systems. */ | |
69 | return STR_IN_SET(fstype, "ext4", "btrfs", "xfs"); | |
70 | } | |
71 | ||
70a5db58 LP |
72 | int split_user_name_realm(const char *t, char **ret_user_name, char **ret_realm) { |
73 | _cleanup_free_ char *user_name = NULL, *realm = NULL; | |
74 | const char *c; | |
75 | int r; | |
76 | ||
77 | assert(t); | |
78 | assert(ret_user_name); | |
79 | assert(ret_realm); | |
80 | ||
81 | c = strchr(t, '@'); | |
82 | if (!c) { | |
83 | user_name = strdup(t); | |
84 | if (!user_name) | |
85 | return -ENOMEM; | |
86 | } else { | |
87 | user_name = strndup(t, c - t); | |
88 | if (!user_name) | |
89 | return -ENOMEM; | |
90 | ||
91 | realm = strdup(c + 1); | |
92 | if (!realm) | |
93 | return -ENOMEM; | |
94 | } | |
95 | ||
96 | if (!suitable_user_name(user_name)) | |
97 | return -EINVAL; | |
98 | ||
99 | if (realm) { | |
100 | r = suitable_realm(realm); | |
101 | if (r < 0) | |
102 | return r; | |
103 | if (r == 0) | |
104 | return -EINVAL; | |
105 | } | |
106 | ||
107 | *ret_user_name = TAKE_PTR(user_name); | |
108 | *ret_realm = TAKE_PTR(realm); | |
109 | ||
110 | return 0; | |
111 | } | |
112 | ||
113 | int bus_message_append_secret(sd_bus_message *m, UserRecord *secret) { | |
114 | _cleanup_(erase_and_freep) char *formatted = NULL; | |
115 | JsonVariant *v; | |
116 | int r; | |
117 | ||
118 | assert(m); | |
119 | assert(secret); | |
120 | ||
121 | if (!FLAGS_SET(secret->mask, USER_RECORD_SECRET)) | |
122 | return sd_bus_message_append(m, "s", "{}"); | |
123 | ||
124 | v = json_variant_by_key(secret->json, "secret"); | |
125 | if (!v) | |
126 | return -EINVAL; | |
127 | ||
128 | r = json_variant_format(v, 0, &formatted); | |
129 | if (r < 0) | |
130 | return r; | |
131 | ||
2ffee2c9 LP |
132 | (void) sd_bus_message_sensitive(m); |
133 | ||
70a5db58 LP |
134 | return sd_bus_message_append(m, "s", formatted); |
135 | } |