/src/systemd/src/shared/user-record.h
Line | Count | Source |
1 | | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | | #pragma once |
3 | | |
4 | | #include <time.h> |
5 | | |
6 | | #include "sd-id128.h" |
7 | | |
8 | | #include "bitfield.h" |
9 | | #include "forward.h" |
10 | | #include "pkcs11-padding.h" |
11 | | #include "rlimit-util.h" |
12 | | |
13 | | typedef enum UserDisposition { |
14 | | USER_INTRINSIC, /* root and nobody */ |
15 | | USER_SYSTEM, /* statically allocated users for system services */ |
16 | | USER_DYNAMIC, /* dynamically allocated users for system services */ |
17 | | USER_REGULAR, /* regular (typically human users) */ |
18 | | USER_CONTAINER, /* UID ranges allocated for container uses */ |
19 | | USER_FOREIGN, /* UID range allocated for foreign OS images */ |
20 | | USER_RESERVED, /* Range above 2^31 */ |
21 | | _USER_DISPOSITION_MAX, |
22 | | _USER_DISPOSITION_INVALID = -EINVAL, |
23 | | } UserDisposition; |
24 | | |
25 | | typedef enum UserStorage { |
26 | | USER_CLASSIC, |
27 | | USER_LUKS, |
28 | | USER_DIRECTORY, /* A directory, and a .identity file in it, which USER_CLASSIC lacks */ |
29 | | USER_SUBVOLUME, |
30 | | USER_FSCRYPT, |
31 | | USER_CIFS, |
32 | | _USER_STORAGE_MAX, |
33 | | _USER_STORAGE_INVALID = -EINVAL, |
34 | | } UserStorage; |
35 | | |
36 | | typedef enum UserRecordMask { |
37 | | /* The various sections an identity record may have, as bit mask */ |
38 | | USER_RECORD_REGULAR = 1U << 0, |
39 | | USER_RECORD_SECRET = 1U << 1, |
40 | | USER_RECORD_PRIVILEGED = 1U << 2, |
41 | | USER_RECORD_PER_MACHINE = 1U << 3, |
42 | | USER_RECORD_BINDING = 1U << 4, |
43 | | USER_RECORD_STATUS = 1U << 5, |
44 | | USER_RECORD_SIGNATURE = 1U << 6, |
45 | | _USER_RECORD_MASK_MAX = (1U << 7)-1 |
46 | | } UserRecordMask; |
47 | | |
48 | | typedef enum UserRecordLoadFlags { |
49 | | /* A set of flags used while loading a user record from JSON data. We leave the lower 6 bits free, |
50 | | * just as a safety precaution so that we can detect borked conversions between UserRecordMask and |
51 | | * UserRecordLoadFlags. */ |
52 | | |
53 | | /* What to require */ |
54 | | USER_RECORD_REQUIRE_REGULAR = USER_RECORD_REGULAR << 7, |
55 | | USER_RECORD_REQUIRE_SECRET = USER_RECORD_SECRET << 7, |
56 | | USER_RECORD_REQUIRE_PRIVILEGED = USER_RECORD_PRIVILEGED << 7, |
57 | | USER_RECORD_REQUIRE_PER_MACHINE = USER_RECORD_PER_MACHINE << 7, |
58 | | USER_RECORD_REQUIRE_BINDING = USER_RECORD_BINDING << 7, |
59 | | USER_RECORD_REQUIRE_STATUS = USER_RECORD_STATUS << 7, |
60 | | USER_RECORD_REQUIRE_SIGNATURE = USER_RECORD_SIGNATURE << 7, |
61 | | |
62 | | /* What to allow */ |
63 | | USER_RECORD_ALLOW_REGULAR = USER_RECORD_REGULAR << 14, |
64 | | USER_RECORD_ALLOW_SECRET = USER_RECORD_SECRET << 14, |
65 | | USER_RECORD_ALLOW_PRIVILEGED = USER_RECORD_PRIVILEGED << 14, |
66 | | USER_RECORD_ALLOW_PER_MACHINE = USER_RECORD_PER_MACHINE << 14, |
67 | | USER_RECORD_ALLOW_BINDING = USER_RECORD_BINDING << 14, |
68 | | USER_RECORD_ALLOW_STATUS = USER_RECORD_STATUS << 14, |
69 | | USER_RECORD_ALLOW_SIGNATURE = USER_RECORD_SIGNATURE << 14, |
70 | | |
71 | | /* What to strip */ |
72 | | USER_RECORD_STRIP_REGULAR = USER_RECORD_REGULAR << 21, |
73 | | USER_RECORD_STRIP_SECRET = USER_RECORD_SECRET << 21, |
74 | | USER_RECORD_STRIP_PRIVILEGED = USER_RECORD_PRIVILEGED << 21, |
75 | | USER_RECORD_STRIP_PER_MACHINE = USER_RECORD_PER_MACHINE << 21, |
76 | | USER_RECORD_STRIP_BINDING = USER_RECORD_BINDING << 21, |
77 | | USER_RECORD_STRIP_STATUS = USER_RECORD_STATUS << 21, |
78 | | USER_RECORD_STRIP_SIGNATURE = USER_RECORD_SIGNATURE << 21, |
79 | | |
80 | | /* Some special combinations that deserve explicit names */ |
81 | | USER_RECORD_LOAD_FULL = USER_RECORD_REQUIRE_REGULAR | |
82 | | USER_RECORD_ALLOW_SECRET | |
83 | | USER_RECORD_ALLOW_PRIVILEGED | |
84 | | USER_RECORD_ALLOW_PER_MACHINE | |
85 | | USER_RECORD_ALLOW_BINDING | |
86 | | USER_RECORD_ALLOW_STATUS | |
87 | | USER_RECORD_ALLOW_SIGNATURE, |
88 | | |
89 | | USER_RECORD_LOAD_REFUSE_SECRET = USER_RECORD_REQUIRE_REGULAR | |
90 | | USER_RECORD_ALLOW_PRIVILEGED | |
91 | | USER_RECORD_ALLOW_PER_MACHINE | |
92 | | USER_RECORD_ALLOW_BINDING | |
93 | | USER_RECORD_ALLOW_STATUS | |
94 | | USER_RECORD_ALLOW_SIGNATURE, |
95 | | |
96 | | USER_RECORD_LOAD_MASK_SECRET = USER_RECORD_REQUIRE_REGULAR | |
97 | | USER_RECORD_ALLOW_PRIVILEGED | |
98 | | USER_RECORD_ALLOW_PER_MACHINE | |
99 | | USER_RECORD_ALLOW_BINDING | |
100 | | USER_RECORD_ALLOW_STATUS | |
101 | | USER_RECORD_ALLOW_SIGNATURE | |
102 | | USER_RECORD_STRIP_SECRET, |
103 | | |
104 | | USER_RECORD_EXTRACT_SECRET = USER_RECORD_REQUIRE_SECRET | |
105 | | USER_RECORD_STRIP_REGULAR | |
106 | | USER_RECORD_STRIP_PRIVILEGED | |
107 | | USER_RECORD_STRIP_PER_MACHINE | |
108 | | USER_RECORD_STRIP_BINDING | |
109 | | USER_RECORD_STRIP_STATUS | |
110 | | USER_RECORD_STRIP_SIGNATURE, |
111 | | |
112 | | USER_RECORD_LOAD_SIGNABLE = USER_RECORD_REQUIRE_REGULAR | |
113 | | USER_RECORD_ALLOW_PRIVILEGED | |
114 | | USER_RECORD_ALLOW_PER_MACHINE, |
115 | | |
116 | | USER_RECORD_EXTRACT_SIGNABLE = USER_RECORD_LOAD_SIGNABLE | |
117 | | USER_RECORD_STRIP_SECRET | |
118 | | USER_RECORD_STRIP_BINDING | |
119 | | USER_RECORD_STRIP_STATUS | |
120 | | USER_RECORD_STRIP_SIGNATURE, |
121 | | |
122 | | USER_RECORD_LOAD_EMBEDDED = USER_RECORD_REQUIRE_REGULAR | |
123 | | USER_RECORD_ALLOW_PRIVILEGED | |
124 | | USER_RECORD_ALLOW_PER_MACHINE | |
125 | | USER_RECORD_ALLOW_SIGNATURE, |
126 | | |
127 | | USER_RECORD_EXTRACT_EMBEDDED = USER_RECORD_LOAD_EMBEDDED | |
128 | | USER_RECORD_STRIP_SECRET | |
129 | | USER_RECORD_STRIP_BINDING | |
130 | | USER_RECORD_STRIP_STATUS, |
131 | | |
132 | | USER_RECORD_LOAD_MASK_PRIVILEGED = USER_RECORD_REQUIRE_REGULAR| |
133 | | USER_RECORD_STRIP_PRIVILEGED| |
134 | | USER_RECORD_ALLOW_PER_MACHINE| |
135 | | USER_RECORD_ALLOW_BINDING| |
136 | | USER_RECORD_ALLOW_STATUS| |
137 | | USER_RECORD_ALLOW_SIGNATURE, |
138 | | |
139 | | USER_RECORD_EXTRACT_PRIVILEGED = USER_RECORD_STRIP_REGULAR| |
140 | | USER_RECORD_ALLOW_PRIVILEGED| |
141 | | USER_RECORD_STRIP_PER_MACHINE| |
142 | | USER_RECORD_STRIP_BINDING| |
143 | | USER_RECORD_STRIP_STATUS| |
144 | | USER_RECORD_STRIP_SIGNATURE, |
145 | | |
146 | | /* Whether to log about loader errors beyond LOG_DEBUG */ |
147 | | USER_RECORD_LOG = 1U << 28, |
148 | | |
149 | | /* Whether to ignore errors and load what we can */ |
150 | | USER_RECORD_PERMISSIVE = 1U << 29, |
151 | | |
152 | | /* Whether an empty record is OK */ |
153 | | USER_RECORD_EMPTY_OK = 1U << 30, |
154 | | } UserRecordLoadFlags; |
155 | | |
156 | 0 | static inline UserRecordLoadFlags USER_RECORD_REQUIRE(UserRecordMask m) { |
157 | 0 | assert((m & ~_USER_RECORD_MASK_MAX) == 0); |
158 | 0 | return m << 7; |
159 | 0 | } Unexecuted instantiation: udev-rules.c:USER_RECORD_REQUIRE Unexecuted instantiation: tuntap.c:USER_RECORD_REQUIRE Unexecuted instantiation: fuzz-user-record.c:USER_RECORD_REQUIRE Unexecuted instantiation: group-record.c:USER_RECORD_REQUIRE Unexecuted instantiation: machine-bind-user.c:USER_RECORD_REQUIRE Unexecuted instantiation: pcrextend-util.c:USER_RECORD_REQUIRE Unexecuted instantiation: user-record-nss.c:USER_RECORD_REQUIRE Unexecuted instantiation: user-record-show.c:USER_RECORD_REQUIRE Unexecuted instantiation: user-record.c:USER_RECORD_REQUIRE Unexecuted instantiation: userdb-dropin.c:USER_RECORD_REQUIRE Unexecuted instantiation: userdb.c:USER_RECORD_REQUIRE |
160 | | |
161 | 0 | static inline UserRecordLoadFlags USER_RECORD_ALLOW(UserRecordMask m) { |
162 | 0 | assert((m & ~_USER_RECORD_MASK_MAX) == 0); |
163 | 0 | return m << 14; |
164 | 0 | } Unexecuted instantiation: udev-rules.c:USER_RECORD_ALLOW Unexecuted instantiation: tuntap.c:USER_RECORD_ALLOW Unexecuted instantiation: fuzz-user-record.c:USER_RECORD_ALLOW Unexecuted instantiation: group-record.c:USER_RECORD_ALLOW Unexecuted instantiation: machine-bind-user.c:USER_RECORD_ALLOW Unexecuted instantiation: pcrextend-util.c:USER_RECORD_ALLOW Unexecuted instantiation: user-record-nss.c:USER_RECORD_ALLOW Unexecuted instantiation: user-record-show.c:USER_RECORD_ALLOW Unexecuted instantiation: user-record.c:USER_RECORD_ALLOW Unexecuted instantiation: userdb-dropin.c:USER_RECORD_ALLOW Unexecuted instantiation: userdb.c:USER_RECORD_ALLOW |
165 | | |
166 | 0 | static inline UserRecordLoadFlags USER_RECORD_STRIP(UserRecordMask m) { |
167 | 0 | assert((m & ~_USER_RECORD_MASK_MAX) == 0); |
168 | 0 | return m << 21; |
169 | 0 | } Unexecuted instantiation: udev-rules.c:USER_RECORD_STRIP Unexecuted instantiation: tuntap.c:USER_RECORD_STRIP Unexecuted instantiation: fuzz-user-record.c:USER_RECORD_STRIP Unexecuted instantiation: group-record.c:USER_RECORD_STRIP Unexecuted instantiation: machine-bind-user.c:USER_RECORD_STRIP Unexecuted instantiation: pcrextend-util.c:USER_RECORD_STRIP Unexecuted instantiation: user-record-nss.c:USER_RECORD_STRIP Unexecuted instantiation: user-record-show.c:USER_RECORD_STRIP Unexecuted instantiation: user-record.c:USER_RECORD_STRIP Unexecuted instantiation: userdb-dropin.c:USER_RECORD_STRIP Unexecuted instantiation: userdb.c:USER_RECORD_STRIP |
170 | | |
171 | 177k | static inline UserRecordMask USER_RECORD_REQUIRE_MASK(UserRecordLoadFlags f) { |
172 | 177k | return (f >> 7) & _USER_RECORD_MASK_MAX; |
173 | 177k | } Unexecuted instantiation: udev-rules.c:USER_RECORD_REQUIRE_MASK Unexecuted instantiation: tuntap.c:USER_RECORD_REQUIRE_MASK Unexecuted instantiation: fuzz-user-record.c:USER_RECORD_REQUIRE_MASK group-record.c:USER_RECORD_REQUIRE_MASK Line | Count | Source | 171 | 4.37k | static inline UserRecordMask USER_RECORD_REQUIRE_MASK(UserRecordLoadFlags f) { | 172 | 4.37k | return (f >> 7) & _USER_RECORD_MASK_MAX; | 173 | 4.37k | } |
Unexecuted instantiation: machine-bind-user.c:USER_RECORD_REQUIRE_MASK Unexecuted instantiation: pcrextend-util.c:USER_RECORD_REQUIRE_MASK Unexecuted instantiation: user-record-nss.c:USER_RECORD_REQUIRE_MASK Unexecuted instantiation: user-record-show.c:USER_RECORD_REQUIRE_MASK user-record.c:USER_RECORD_REQUIRE_MASK Line | Count | Source | 171 | 173k | static inline UserRecordMask USER_RECORD_REQUIRE_MASK(UserRecordLoadFlags f) { | 172 | 173k | return (f >> 7) & _USER_RECORD_MASK_MAX; | 173 | 173k | } |
Unexecuted instantiation: userdb-dropin.c:USER_RECORD_REQUIRE_MASK Unexecuted instantiation: userdb.c:USER_RECORD_REQUIRE_MASK |
174 | | |
175 | 27.9k | static inline UserRecordMask USER_RECORD_ALLOW_MASK(UserRecordLoadFlags f) { |
176 | 27.9k | return ((f >> 14) & _USER_RECORD_MASK_MAX) | USER_RECORD_REQUIRE_MASK(f); |
177 | 27.9k | } Unexecuted instantiation: udev-rules.c:USER_RECORD_ALLOW_MASK Unexecuted instantiation: tuntap.c:USER_RECORD_ALLOW_MASK Unexecuted instantiation: fuzz-user-record.c:USER_RECORD_ALLOW_MASK Unexecuted instantiation: group-record.c:USER_RECORD_ALLOW_MASK Unexecuted instantiation: machine-bind-user.c:USER_RECORD_ALLOW_MASK Unexecuted instantiation: pcrextend-util.c:USER_RECORD_ALLOW_MASK Unexecuted instantiation: user-record-nss.c:USER_RECORD_ALLOW_MASK Unexecuted instantiation: user-record-show.c:USER_RECORD_ALLOW_MASK user-record.c:USER_RECORD_ALLOW_MASK Line | Count | Source | 175 | 27.9k | static inline UserRecordMask USER_RECORD_ALLOW_MASK(UserRecordLoadFlags f) { | 176 | 27.9k | return ((f >> 14) & _USER_RECORD_MASK_MAX) | USER_RECORD_REQUIRE_MASK(f); | 177 | 27.9k | } |
Unexecuted instantiation: userdb-dropin.c:USER_RECORD_ALLOW_MASK Unexecuted instantiation: userdb.c:USER_RECORD_ALLOW_MASK |
178 | | |
179 | 173k | static inline UserRecordMask USER_RECORD_STRIP_MASK(UserRecordLoadFlags f) { |
180 | 173k | return (f >> 21) & _USER_RECORD_MASK_MAX; |
181 | 173k | } Unexecuted instantiation: udev-rules.c:USER_RECORD_STRIP_MASK Unexecuted instantiation: tuntap.c:USER_RECORD_STRIP_MASK Unexecuted instantiation: fuzz-user-record.c:USER_RECORD_STRIP_MASK Unexecuted instantiation: group-record.c:USER_RECORD_STRIP_MASK Unexecuted instantiation: machine-bind-user.c:USER_RECORD_STRIP_MASK Unexecuted instantiation: pcrextend-util.c:USER_RECORD_STRIP_MASK Unexecuted instantiation: user-record-nss.c:USER_RECORD_STRIP_MASK Unexecuted instantiation: user-record-show.c:USER_RECORD_STRIP_MASK user-record.c:USER_RECORD_STRIP_MASK Line | Count | Source | 179 | 173k | static inline UserRecordMask USER_RECORD_STRIP_MASK(UserRecordLoadFlags f) { | 180 | 173k | return (f >> 21) & _USER_RECORD_MASK_MAX; | 181 | 173k | } |
Unexecuted instantiation: userdb-dropin.c:USER_RECORD_STRIP_MASK Unexecuted instantiation: userdb.c:USER_RECORD_STRIP_MASK |
182 | | |
183 | | sd_json_dispatch_flags_t USER_RECORD_LOAD_FLAGS_TO_JSON_DISPATCH_FLAGS(UserRecordLoadFlags flags) _const_; |
184 | | |
185 | | typedef struct Pkcs11EncryptedKey { |
186 | | /* The encrypted passphrase, which can be decrypted with the private key indicated below */ |
187 | | void *data; |
188 | | size_t size; |
189 | | |
190 | | /* Where to find the private key to decrypt the encrypted passphrase above */ |
191 | | char *uri; |
192 | | |
193 | | /* Which RSA padding scheme was used to wrap the encrypted passphrase. Defaults to PKCS#1 v1.5 for |
194 | | * legacy records that omit the field; new enrollments use RSA-OAEP with SHA-256 or SHA-1. */ |
195 | | Pkcs11RsaPadding padding; |
196 | | |
197 | | /* What to test the decrypted passphrase against to allow access (classic UNIX password hash). Note |
198 | | * that the decrypted passphrase is also used for unlocking LUKS and fscrypt, and if the account is |
199 | | * backed by LUKS or fscrypt the hashed password is only an additional layer of authentication, not |
200 | | * the only. */ |
201 | | char *hashed_password; |
202 | | } Pkcs11EncryptedKey; |
203 | | |
204 | | typedef struct Fido2HmacCredential { |
205 | | void *id; |
206 | | size_t size; |
207 | | } Fido2HmacCredential; |
208 | | |
209 | | typedef struct Fido2HmacSalt { |
210 | | /* The FIDO2 Cridential ID to use */ |
211 | | Fido2HmacCredential credential; |
212 | | |
213 | | /* The FIDO2 salt value */ |
214 | | void *salt; |
215 | | size_t salt_size; |
216 | | |
217 | | /* What to test the hashed salt value against, usually UNIX password hash here. */ |
218 | | char *hashed_password; |
219 | | |
220 | | /* Whether the 'up', 'uv', 'clientPin' features are enabled. */ |
221 | | int uv, up, client_pin; |
222 | | } Fido2HmacSalt; |
223 | | |
224 | | typedef struct RecoveryKey { |
225 | | /* The type of recovery key, must be "modhex64" right now */ |
226 | | char *type; |
227 | | |
228 | | /* A UNIX password hash of the normalized form of modhex64 */ |
229 | | char *hashed_password; |
230 | | } RecoveryKey; |
231 | | |
232 | | typedef enum AutoResizeMode { |
233 | | AUTO_RESIZE_OFF, /* no automatic grow/shrink */ |
234 | | AUTO_RESIZE_GROW, /* grow at login */ |
235 | | AUTO_RESIZE_SHRINK_AND_GROW, /* shrink at logout + grow at login */ |
236 | | _AUTO_RESIZE_MODE_MAX, |
237 | | _AUTO_RESIZE_MODE_INVALID = -EINVAL, |
238 | | } AutoResizeMode; |
239 | | |
240 | 227 | #define REBALANCE_WEIGHT_OFF UINT64_C(0) |
241 | 0 | #define REBALANCE_WEIGHT_DEFAULT UINT64_C(100) |
242 | | #define REBALANCE_WEIGHT_BACKING UINT64_C(20) |
243 | 927 | #define REBALANCE_WEIGHT_MIN UINT64_C(1) |
244 | 700 | #define REBALANCE_WEIGHT_MAX UINT64_C(10000) |
245 | 29.3k | #define REBALANCE_WEIGHT_UNSET UINT64_MAX |
246 | | |
247 | | typedef struct TmpfsLimit { |
248 | | /* Absolute and relative tmpfs limits */ |
249 | | uint64_t limit; |
250 | | uint32_t limit_scale; |
251 | | bool is_set; |
252 | | } TmpfsLimit; |
253 | | |
254 | | #define TMPFS_LIMIT_NULL \ |
255 | 58.6k | (TmpfsLimit) { \ |
256 | 58.6k | .limit = UINT64_MAX, \ |
257 | 58.6k | .limit_scale = UINT32_MAX, \ |
258 | 58.6k | } \ |
259 | | |
260 | | typedef struct UserRecord { |
261 | | /* The following three fields are not part of the JSON record */ |
262 | | unsigned n_ref; |
263 | | UserRecordMask mask; |
264 | | bool incomplete; /* incomplete due to security restrictions. */ |
265 | | |
266 | | char *user_name; |
267 | | char *realm; |
268 | | char *user_name_and_realm_auto; /* the user_name field concatenated with '@' and the realm, if the latter is defined */ |
269 | | char **aliases; |
270 | | sd_id128_t uuid; |
271 | | char *real_name; |
272 | | char *email_address; |
273 | | char *password_hint; |
274 | | char *icon_name; |
275 | | char *location; |
276 | | struct tm birth_date; |
277 | | |
278 | | char *blob_directory; |
279 | | Hashmap *blob_manifest; |
280 | | |
281 | | UserDisposition disposition; |
282 | | uint64_t last_change_usec; |
283 | | uint64_t last_password_change_usec; |
284 | | |
285 | | char *shell; |
286 | | mode_t umask; |
287 | | char **environment; |
288 | | char *time_zone; |
289 | | char *preferred_language; |
290 | | char **additional_languages; |
291 | | int nice_level; |
292 | | struct rlimit *rlimits[_RLIMIT_MAX]; |
293 | | |
294 | | int locked; /* prohibit activation in general */ |
295 | | uint64_t not_before_usec; /* prohibit activation before this unix time */ |
296 | | uint64_t not_after_usec; /* prohibit activation after this unix time */ |
297 | | |
298 | | UserStorage storage; |
299 | | uint64_t disk_size; |
300 | | uint64_t disk_size_relative; /* Disk size, relative to the free bytes of the medium, normalized to UINT32_MAX = 100% */ |
301 | | char *skeleton_directory; |
302 | | mode_t access_mode; |
303 | | AutoResizeMode auto_resize_mode; |
304 | | uint64_t rebalance_weight; |
305 | | |
306 | | uint64_t tasks_max; |
307 | | uint64_t memory_high; |
308 | | uint64_t memory_max; |
309 | | uint64_t cpu_weight; |
310 | | uint64_t io_weight; |
311 | | |
312 | | bool nosuid; |
313 | | bool nodev; |
314 | | bool noexec; |
315 | | |
316 | | char **hashed_password; |
317 | | char **ssh_authorized_keys; |
318 | | char **password; |
319 | | char **token_pin; |
320 | | |
321 | | char *cifs_domain; |
322 | | char *cifs_user_name; |
323 | | char *cifs_service; |
324 | | char *cifs_extra_mount_options; |
325 | | |
326 | | char *image_path; |
327 | | char *image_path_auto; /* when none is configured explicitly, this is where we place the implicit image */ |
328 | | char *home_directory; |
329 | | char *home_directory_auto; /* when none is set explicitly, this is where we place the implicit home directory */ |
330 | | |
331 | | /* fallback shell and home dir */ |
332 | | char *fallback_shell; |
333 | | char *fallback_home_directory; |
334 | | |
335 | | uid_t uid; |
336 | | gid_t gid; |
337 | | |
338 | | char **member_of; |
339 | | |
340 | | char *file_system_type; |
341 | | sd_id128_t partition_uuid; |
342 | | sd_id128_t luks_uuid; |
343 | | sd_id128_t file_system_uuid; |
344 | | |
345 | | int luks_discard; |
346 | | int luks_offline_discard; |
347 | | char *luks_cipher; |
348 | | char *luks_cipher_mode; |
349 | | uint64_t luks_volume_key_size; |
350 | | char *luks_pbkdf_hash_algorithm; |
351 | | char *luks_pbkdf_type; |
352 | | uint64_t luks_pbkdf_force_iterations; |
353 | | uint64_t luks_pbkdf_time_cost_usec; |
354 | | uint64_t luks_pbkdf_memory_cost; |
355 | | uint64_t luks_pbkdf_parallel_threads; |
356 | | uint64_t luks_sector_size; |
357 | | char *luks_extra_mount_options; |
358 | | |
359 | | uint64_t disk_usage; |
360 | | uint64_t disk_free; |
361 | | uint64_t disk_ceiling; |
362 | | uint64_t disk_floor; |
363 | | |
364 | | bool use_fallback; /* if true → use fallback_shell + fallback_home_directory instead of the regular ones */ |
365 | | |
366 | | char *state; |
367 | | char *service; |
368 | | int signed_locally; |
369 | | |
370 | | uint64_t good_authentication_counter; |
371 | | uint64_t bad_authentication_counter; |
372 | | uint64_t last_good_authentication_usec; |
373 | | uint64_t last_bad_authentication_usec; |
374 | | |
375 | | uint64_t ratelimit_begin_usec; |
376 | | uint64_t ratelimit_count; |
377 | | uint64_t ratelimit_interval_usec; |
378 | | uint64_t ratelimit_burst; |
379 | | |
380 | | int removable; |
381 | | int enforce_password_policy; |
382 | | int auto_login; |
383 | | int drop_caches; |
384 | | |
385 | | char *preferred_session_type; |
386 | | char *preferred_session_launcher; |
387 | | |
388 | | uint64_t stop_delay_usec; /* How long to leave systemd --user around on log-out */ |
389 | | int kill_processes; /* Whether to kill user processes forcibly on log-out */ |
390 | | |
391 | | /* The following exist mostly so that we can cover the full /etc/shadow set of fields */ |
392 | | uint64_t password_change_min_usec; /* maps to .sp_min */ |
393 | | uint64_t password_change_max_usec; /* maps to .sp_max */ |
394 | | uint64_t password_change_warn_usec; /* maps to .sp_warn */ |
395 | | uint64_t password_change_inactive_usec; /* maps to .sp_inact */ |
396 | | int password_change_now; /* Require a password change immediately on next login (.sp_lstchg = 0) */ |
397 | | |
398 | | char **pkcs11_token_uri; |
399 | | Pkcs11EncryptedKey *pkcs11_encrypted_key; |
400 | | size_t n_pkcs11_encrypted_key; |
401 | | int pkcs11_protected_authentication_path_permitted; |
402 | | |
403 | | Fido2HmacCredential *fido2_hmac_credential; |
404 | | size_t n_fido2_hmac_credential; |
405 | | Fido2HmacSalt *fido2_hmac_salt; |
406 | | size_t n_fido2_hmac_salt; |
407 | | int fido2_user_presence_permitted; |
408 | | int fido2_user_verification_permitted; |
409 | | |
410 | | char **recovery_key_type; |
411 | | RecoveryKey *recovery_key; |
412 | | size_t n_recovery_key; |
413 | | |
414 | | char **capability_bounding_set; |
415 | | char **capability_ambient_set; |
416 | | |
417 | | char **self_modifiable_fields; /* fields a user can change about themself w/o auth */ |
418 | | char **self_modifiable_blobs; |
419 | | char **self_modifiable_privileged; |
420 | | |
421 | | TmpfsLimit tmp_limit, dev_shm_limit; |
422 | | |
423 | | char *default_area; |
424 | | |
425 | | sd_json_variant *json; |
426 | | } UserRecord; |
427 | | |
428 | | UserRecord* user_record_new(void); |
429 | | DECLARE_TRIVIAL_REF_UNREF_FUNC(UserRecord, user_record); |
430 | | |
431 | | DEFINE_TRIVIAL_CLEANUP_FUNC(UserRecord*, user_record_unref); |
432 | | |
433 | | int user_record_load(UserRecord *h, sd_json_variant *v, UserRecordLoadFlags flags); |
434 | | int user_record_build(UserRecord **ret, ...); |
435 | | #define user_record_buildo(ret, ...) \ |
436 | 6.94k | user_record_build((ret), SD_JSON_BUILD_OBJECT(__VA_ARGS__)) |
437 | | |
438 | | const char* user_record_user_name_and_realm(UserRecord *h); |
439 | | UserStorage user_record_storage(UserRecord *h); |
440 | | const char* user_record_file_system_type(UserRecord *h); |
441 | | const char* user_record_skeleton_directory(UserRecord *h); |
442 | | mode_t user_record_access_mode(UserRecord *h); |
443 | | const char* user_record_home_directory(UserRecord *h); |
444 | | const char* user_record_image_path(UserRecord *h); |
445 | | unsigned long user_record_mount_flags(UserRecord *h); |
446 | | const char* user_record_cifs_user_name(UserRecord *h); |
447 | | const char* user_record_shell(UserRecord *h); |
448 | | const char* user_record_real_name(UserRecord *h); |
449 | | bool user_record_luks_discard(UserRecord *h); |
450 | | bool user_record_luks_offline_discard(UserRecord *h); |
451 | | const char* user_record_luks_cipher(UserRecord *h); |
452 | | const char* user_record_luks_cipher_mode(UserRecord *h); |
453 | | uint64_t user_record_luks_volume_key_size(UserRecord *h); |
454 | | const char* user_record_luks_pbkdf_type(UserRecord *h); |
455 | | uint64_t user_record_luks_pbkdf_force_iterations(UserRecord *h); |
456 | | usec_t user_record_luks_pbkdf_time_cost_usec(UserRecord *h); |
457 | | uint64_t user_record_luks_pbkdf_memory_cost(UserRecord *h); |
458 | | uint64_t user_record_luks_pbkdf_parallel_threads(UserRecord *h); |
459 | | uint64_t user_record_luks_sector_size(UserRecord *h); |
460 | | const char* user_record_luks_pbkdf_hash_algorithm(UserRecord *h); |
461 | | gid_t user_record_gid(UserRecord *h); |
462 | | UserDisposition user_record_disposition(UserRecord *h); |
463 | | int user_record_removable(UserRecord *h); |
464 | | usec_t user_record_ratelimit_interval_usec(UserRecord *h); |
465 | | uint64_t user_record_ratelimit_burst(UserRecord *h); |
466 | | bool user_record_can_authenticate(UserRecord *h); |
467 | | bool user_record_drop_caches(UserRecord *h); |
468 | | AutoResizeMode user_record_auto_resize_mode(UserRecord *h); |
469 | | uint64_t user_record_rebalance_weight(UserRecord *h); |
470 | | uint64_t user_record_capability_bounding_set(UserRecord *h); |
471 | | uint64_t user_record_capability_ambient_set(UserRecord *h); |
472 | | int user_record_languages(UserRecord *h, char ***ret); |
473 | | uint32_t user_record_tmp_limit_scale(UserRecord *h); |
474 | | uint32_t user_record_dev_shm_limit_scale(UserRecord *h); |
475 | | |
476 | | const char **user_record_self_modifiable_fields(UserRecord *h); |
477 | | const char **user_record_self_modifiable_blobs(UserRecord *h); |
478 | | const char **user_record_self_modifiable_privileged(UserRecord *h); |
479 | | int user_record_self_changes_allowed(UserRecord *current, UserRecord *incoming); |
480 | | |
481 | | int user_record_build_image_path(UserStorage storage, const char *user_name_and_realm, char **ret); |
482 | | |
483 | | bool user_record_equal(UserRecord *a, UserRecord *b); |
484 | | bool user_record_compatible(UserRecord *a, UserRecord *b); |
485 | | int user_record_compare_last_change(UserRecord *a, UserRecord *b); |
486 | | |
487 | | usec_t user_record_ratelimit_next_try(UserRecord *h); |
488 | | |
489 | | int user_record_clone(UserRecord *h, UserRecordLoadFlags flags, UserRecord **ret); |
490 | | int user_record_masked_equal(UserRecord *a, UserRecord *b, UserRecordMask mask); |
491 | | |
492 | | int user_record_test_blocked(UserRecord *h); |
493 | | int user_record_test_password_change_required(UserRecord *h); |
494 | | |
495 | | bool user_record_is_root(const UserRecord *u); |
496 | | bool user_record_is_nobody(const UserRecord *u); |
497 | | |
498 | | /* The following six are user by group-record.c, that's why we export them here */ |
499 | | int json_dispatch_realm(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); |
500 | | int json_dispatch_gecos(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); |
501 | | int json_dispatch_user_group_list(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); |
502 | | int json_dispatch_user_disposition(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); |
503 | | |
504 | | int per_machine_id_match(sd_json_variant *ids, sd_json_dispatch_flags_t flags); |
505 | | int per_machine_hostname_match(sd_json_variant *hns, sd_json_dispatch_flags_t flags); |
506 | | int per_machine_match(sd_json_variant *entry, sd_json_dispatch_flags_t flags); |
507 | | int user_group_record_mangle(sd_json_variant *v, UserRecordLoadFlags load_flags, sd_json_variant **ret_variant, UserRecordMask *ret_mask); |
508 | | |
509 | | #define BLOB_DIR_MAX_SIZE (UINT64_C(64) * U64_MB) |
510 | | int suitable_blob_filename(const char *name); |
511 | | |
512 | | typedef struct UserDBMatch { |
513 | | char **fuzzy_names; |
514 | | uint64_t disposition_mask; |
515 | | union { |
516 | | uid_t uid_min; |
517 | | gid_t gid_min; |
518 | | }; |
519 | | union { |
520 | | uid_t uid_max; |
521 | | gid_t gid_max; |
522 | | }; |
523 | | sd_id128_t uuid; |
524 | | } UserDBMatch; |
525 | | |
526 | | #define USER_DISPOSITION_MASK_ALL ((UINT64_C(1) << _USER_DISPOSITION_MAX) - UINT64_C(1)) |
527 | | |
528 | | #define USERDB_MATCH_NULL \ |
529 | | (const UserDBMatch) { \ |
530 | | .disposition_mask = USER_DISPOSITION_MASK_ALL, \ |
531 | | .uid_min = 0, \ |
532 | | .uid_max = UID_INVALID-1, \ |
533 | | .uuid = SD_ID128_NULL, \ |
534 | | } |
535 | | |
536 | | /* Maybe useful when we want to resolve root and system user/group but want to refuse nobody user/group. */ |
537 | | #define USERDB_MATCH_ROOT_AND_SYSTEM \ |
538 | | (const UserDBMatch) { \ |
539 | | .disposition_mask = \ |
540 | | INDEXES_TO_MASK(uint64_t, USER_INTRINSIC, USER_SYSTEM), \ |
541 | | .uid_min = 0, \ |
542 | | .uid_max = UID_NOBODY - 1, \ |
543 | | } |
544 | | |
545 | | bool userdb_match_is_set(const UserDBMatch *match) _pure_; |
546 | | |
547 | | void userdb_match_done(UserDBMatch *match); |
548 | | |
549 | | bool record_name_matches_alias_realm(const char *name, char * const *aliases, const char *realm); |
550 | | bool user_name_fuzzy_match(const char *names[], size_t n_names, char **matches); |
551 | | bool user_record_match(UserRecord *u, const UserDBMatch *match); |
552 | | |
553 | | bool user_record_matches_user_name(const UserRecord *u, const char *username); |
554 | | |
555 | | int json_dispatch_dispositions_mask(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); |
556 | | |
557 | | DECLARE_STRING_TABLE_LOOKUP(user_storage, UserStorage); |
558 | | |
559 | | DECLARE_STRING_TABLE_LOOKUP(user_disposition, UserDisposition); |
560 | | |
561 | | DECLARE_STRING_TABLE_LOOKUP(auto_resize_mode, AutoResizeMode); |