]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/user-util.c
Merge pull request #7767 from poettering/fork-wait
[thirdparty/systemd.git] / src / basic / user-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <alloca.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <grp.h>
25 #include <pwd.h>
26 #include <stddef.h>
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/stat.h>
32 #include <unistd.h>
33 #include <utmp.h>
34
35 #include "alloc-util.h"
36 #include "fd-util.h"
37 #include "fileio.h"
38 #include "format-util.h"
39 #include "macro.h"
40 #include "missing.h"
41 #include "parse-util.h"
42 #include "path-util.h"
43 #include "string-util.h"
44 #include "strv.h"
45 #include "user-util.h"
46 #include "utf8.h"
47
48 bool uid_is_valid(uid_t uid) {
49
50 /* Also see POSIX IEEE Std 1003.1-2008, 2016 Edition, 3.436. */
51
52 /* Some libc APIs use UID_INVALID as special placeholder */
53 if (uid == (uid_t) UINT32_C(0xFFFFFFFF))
54 return false;
55
56 /* A long time ago UIDs where 16bit, hence explicitly avoid the 16bit -1 too */
57 if (uid == (uid_t) UINT32_C(0xFFFF))
58 return false;
59
60 return true;
61 }
62
63 int parse_uid(const char *s, uid_t *ret) {
64 uint32_t uid = 0;
65 int r;
66
67 assert(s);
68
69 assert_cc(sizeof(uid_t) == sizeof(uint32_t));
70 r = safe_atou32(s, &uid);
71 if (r < 0)
72 return r;
73
74 if (!uid_is_valid(uid))
75 return -ENXIO; /* we return ENXIO instead of EINVAL
76 * here, to make it easy to distuingish
77 * invalid numeric uids from invalid
78 * strings. */
79
80 if (ret)
81 *ret = uid;
82
83 return 0;
84 }
85
86 char* getlogname_malloc(void) {
87 uid_t uid;
88 struct stat st;
89
90 if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
91 uid = st.st_uid;
92 else
93 uid = getuid();
94
95 return uid_to_name(uid);
96 }
97
98 char *getusername_malloc(void) {
99 const char *e;
100
101 e = getenv("USER");
102 if (e)
103 return strdup(e);
104
105 return uid_to_name(getuid());
106 }
107
108 int get_user_creds(
109 const char **username,
110 uid_t *uid, gid_t *gid,
111 const char **home,
112 const char **shell) {
113
114 struct passwd *p;
115 uid_t u;
116
117 assert(username);
118 assert(*username);
119
120 /* We enforce some special rules for uid=0 and uid=65534: in order to avoid NSS lookups for root we hardcode
121 * their user record data. */
122
123 if (STR_IN_SET(*username, "root", "0")) {
124 *username = "root";
125
126 if (uid)
127 *uid = 0;
128 if (gid)
129 *gid = 0;
130
131 if (home)
132 *home = "/root";
133
134 if (shell)
135 *shell = "/bin/sh";
136
137 return 0;
138 }
139
140 if (STR_IN_SET(*username, NOBODY_USER_NAME, "65534")) {
141 *username = NOBODY_USER_NAME;
142
143 if (uid)
144 *uid = UID_NOBODY;
145 if (gid)
146 *gid = GID_NOBODY;
147
148 if (home)
149 *home = "/";
150
151 if (shell)
152 *shell = "/sbin/nologin";
153
154 return 0;
155 }
156
157 if (parse_uid(*username, &u) >= 0) {
158 errno = 0;
159 p = getpwuid(u);
160
161 /* If there are multiple users with the same id, make
162 * sure to leave $USER to the configured value instead
163 * of the first occurrence in the database. However if
164 * the uid was configured by a numeric uid, then let's
165 * pick the real username from /etc/passwd. */
166 if (p)
167 *username = p->pw_name;
168 } else {
169 errno = 0;
170 p = getpwnam(*username);
171 }
172
173 if (!p)
174 return errno > 0 ? -errno : -ESRCH;
175
176 if (uid) {
177 if (!uid_is_valid(p->pw_uid))
178 return -EBADMSG;
179
180 *uid = p->pw_uid;
181 }
182
183 if (gid) {
184 if (!gid_is_valid(p->pw_gid))
185 return -EBADMSG;
186
187 *gid = p->pw_gid;
188 }
189
190 if (home)
191 *home = p->pw_dir;
192
193 if (shell)
194 *shell = p->pw_shell;
195
196 return 0;
197 }
198
199 int get_user_creds_clean(
200 const char **username,
201 uid_t *uid, gid_t *gid,
202 const char **home,
203 const char **shell) {
204
205 int r;
206
207 /* Like get_user_creds(), but resets home/shell to NULL if they don't contain anything relevant. */
208
209 r = get_user_creds(username, uid, gid, home, shell);
210 if (r < 0)
211 return r;
212
213 if (shell &&
214 (isempty(*shell) || PATH_IN_SET(*shell,
215 "/bin/nologin",
216 "/sbin/nologin",
217 "/usr/bin/nologin",
218 "/usr/sbin/nologin")))
219 *shell = NULL;
220
221 if (home &&
222 (isempty(*home) || path_equal(*home, "/")))
223 *home = NULL;
224
225 return 0;
226 }
227
228 int get_group_creds(const char **groupname, gid_t *gid) {
229 struct group *g;
230 gid_t id;
231
232 assert(groupname);
233
234 /* We enforce some special rules for gid=0: in order to avoid
235 * NSS lookups for root we hardcode its data. */
236
237 if (STR_IN_SET(*groupname, "root", "0")) {
238 *groupname = "root";
239
240 if (gid)
241 *gid = 0;
242
243 return 0;
244 }
245
246 if (STR_IN_SET(*groupname, NOBODY_GROUP_NAME, "65534")) {
247 *groupname = NOBODY_GROUP_NAME;
248
249 if (gid)
250 *gid = GID_NOBODY;
251
252 return 0;
253 }
254
255 if (parse_gid(*groupname, &id) >= 0) {
256 errno = 0;
257 g = getgrgid(id);
258
259 if (g)
260 *groupname = g->gr_name;
261 } else {
262 errno = 0;
263 g = getgrnam(*groupname);
264 }
265
266 if (!g)
267 return errno > 0 ? -errno : -ESRCH;
268
269 if (gid) {
270 if (!gid_is_valid(g->gr_gid))
271 return -EBADMSG;
272
273 *gid = g->gr_gid;
274 }
275
276 return 0;
277 }
278
279 char* uid_to_name(uid_t uid) {
280 char *ret;
281 int r;
282
283 /* Shortcut things to avoid NSS lookups */
284 if (uid == 0)
285 return strdup("root");
286 if (uid == UID_NOBODY)
287 return strdup(NOBODY_USER_NAME);
288
289 if (uid_is_valid(uid)) {
290 long bufsize;
291
292 bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
293 if (bufsize <= 0)
294 bufsize = 4096;
295
296 for (;;) {
297 struct passwd pwbuf, *pw = NULL;
298 _cleanup_free_ char *buf = NULL;
299
300 buf = malloc(bufsize);
301 if (!buf)
302 return NULL;
303
304 r = getpwuid_r(uid, &pwbuf, buf, (size_t) bufsize, &pw);
305 if (r == 0 && pw)
306 return strdup(pw->pw_name);
307 if (r != ERANGE)
308 break;
309
310 bufsize *= 2;
311 }
312 }
313
314 if (asprintf(&ret, UID_FMT, uid) < 0)
315 return NULL;
316
317 return ret;
318 }
319
320 char* gid_to_name(gid_t gid) {
321 char *ret;
322 int r;
323
324 if (gid == 0)
325 return strdup("root");
326 if (gid == GID_NOBODY)
327 return strdup(NOBODY_GROUP_NAME);
328
329 if (gid_is_valid(gid)) {
330 long bufsize;
331
332 bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
333 if (bufsize <= 0)
334 bufsize = 4096;
335
336 for (;;) {
337 struct group grbuf, *gr = NULL;
338 _cleanup_free_ char *buf = NULL;
339
340 buf = malloc(bufsize);
341 if (!buf)
342 return NULL;
343
344 r = getgrgid_r(gid, &grbuf, buf, (size_t) bufsize, &gr);
345 if (r == 0 && gr)
346 return strdup(gr->gr_name);
347 if (r != ERANGE)
348 break;
349
350 bufsize *= 2;
351 }
352 }
353
354 if (asprintf(&ret, GID_FMT, gid) < 0)
355 return NULL;
356
357 return ret;
358 }
359
360 int in_gid(gid_t gid) {
361 long ngroups_max;
362 gid_t *gids;
363 int r, i;
364
365 if (getgid() == gid)
366 return 1;
367
368 if (getegid() == gid)
369 return 1;
370
371 if (!gid_is_valid(gid))
372 return -EINVAL;
373
374 ngroups_max = sysconf(_SC_NGROUPS_MAX);
375 assert(ngroups_max > 0);
376
377 gids = newa(gid_t, ngroups_max);
378
379 r = getgroups(ngroups_max, gids);
380 if (r < 0)
381 return -errno;
382
383 for (i = 0; i < r; i++)
384 if (gids[i] == gid)
385 return 1;
386
387 return 0;
388 }
389
390 int in_group(const char *name) {
391 int r;
392 gid_t gid;
393
394 r = get_group_creds(&name, &gid);
395 if (r < 0)
396 return r;
397
398 return in_gid(gid);
399 }
400
401 int get_home_dir(char **_h) {
402 struct passwd *p;
403 const char *e;
404 char *h;
405 uid_t u;
406
407 assert(_h);
408
409 /* Take the user specified one */
410 e = secure_getenv("HOME");
411 if (e && path_is_absolute(e)) {
412 h = strdup(e);
413 if (!h)
414 return -ENOMEM;
415
416 *_h = h;
417 return 0;
418 }
419
420 /* Hardcode home directory for root and nobody to avoid NSS */
421 u = getuid();
422 if (u == 0) {
423 h = strdup("/root");
424 if (!h)
425 return -ENOMEM;
426
427 *_h = h;
428 return 0;
429 }
430 if (u == UID_NOBODY) {
431 h = strdup("/");
432 if (!h)
433 return -ENOMEM;
434
435 *_h = h;
436 return 0;
437 }
438
439 /* Check the database... */
440 errno = 0;
441 p = getpwuid(u);
442 if (!p)
443 return errno > 0 ? -errno : -ESRCH;
444
445 if (!path_is_absolute(p->pw_dir))
446 return -EINVAL;
447
448 h = strdup(p->pw_dir);
449 if (!h)
450 return -ENOMEM;
451
452 *_h = h;
453 return 0;
454 }
455
456 int get_shell(char **_s) {
457 struct passwd *p;
458 const char *e;
459 char *s;
460 uid_t u;
461
462 assert(_s);
463
464 /* Take the user specified one */
465 e = getenv("SHELL");
466 if (e) {
467 s = strdup(e);
468 if (!s)
469 return -ENOMEM;
470
471 *_s = s;
472 return 0;
473 }
474
475 /* Hardcode shell for root and nobody to avoid NSS */
476 u = getuid();
477 if (u == 0) {
478 s = strdup("/bin/sh");
479 if (!s)
480 return -ENOMEM;
481
482 *_s = s;
483 return 0;
484 }
485 if (u == UID_NOBODY) {
486 s = strdup("/sbin/nologin");
487 if (!s)
488 return -ENOMEM;
489
490 *_s = s;
491 return 0;
492 }
493
494 /* Check the database... */
495 errno = 0;
496 p = getpwuid(u);
497 if (!p)
498 return errno > 0 ? -errno : -ESRCH;
499
500 if (!path_is_absolute(p->pw_shell))
501 return -EINVAL;
502
503 s = strdup(p->pw_shell);
504 if (!s)
505 return -ENOMEM;
506
507 *_s = s;
508 return 0;
509 }
510
511 int reset_uid_gid(void) {
512 int r;
513
514 r = maybe_setgroups(0, NULL);
515 if (r < 0)
516 return r;
517
518 if (setresgid(0, 0, 0) < 0)
519 return -errno;
520
521 if (setresuid(0, 0, 0) < 0)
522 return -errno;
523
524 return 0;
525 }
526
527 int take_etc_passwd_lock(const char *root) {
528
529 struct flock flock = {
530 .l_type = F_WRLCK,
531 .l_whence = SEEK_SET,
532 .l_start = 0,
533 .l_len = 0,
534 };
535
536 const char *path;
537 int fd, r;
538
539 /* This is roughly the same as lckpwdf(), but not as awful. We
540 * don't want to use alarm() and signals, hence we implement
541 * our own trivial version of this.
542 *
543 * Note that shadow-utils also takes per-database locks in
544 * addition to lckpwdf(). However, we don't given that they
545 * are redundant as they invoke lckpwdf() first and keep
546 * it during everything they do. The per-database locks are
547 * awfully racy, and thus we just won't do them. */
548
549 if (root)
550 path = prefix_roota(root, "/etc/.pwd.lock");
551 else
552 path = "/etc/.pwd.lock";
553
554 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
555 if (fd < 0)
556 return -errno;
557
558 r = fcntl(fd, F_SETLKW, &flock);
559 if (r < 0) {
560 safe_close(fd);
561 return -errno;
562 }
563
564 return fd;
565 }
566
567 bool valid_user_group_name(const char *u) {
568 const char *i;
569 long sz;
570
571 /* Checks if the specified name is a valid user/group name. Also see POSIX IEEE Std 1003.1-2008, 2016 Edition,
572 * 3.437. We are a bit stricter here however. Specifically we deviate from POSIX rules:
573 *
574 * - We don't allow any dots (this would break chown syntax which permits dots as user/group name separator)
575 * - We require that names fit into the appropriate utmp field
576 * - We don't allow empty user names
577 *
578 * Note that other systems are even more restrictive, and don't permit underscores or uppercase characters.
579 */
580
581 if (isempty(u))
582 return false;
583
584 if (!(u[0] >= 'a' && u[0] <= 'z') &&
585 !(u[0] >= 'A' && u[0] <= 'Z') &&
586 u[0] != '_')
587 return false;
588
589 for (i = u+1; *i; i++) {
590 if (!(*i >= 'a' && *i <= 'z') &&
591 !(*i >= 'A' && *i <= 'Z') &&
592 !(*i >= '0' && *i <= '9') &&
593 !IN_SET(*i, '_', '-'))
594 return false;
595 }
596
597 sz = sysconf(_SC_LOGIN_NAME_MAX);
598 assert_se(sz > 0);
599
600 if ((size_t) (i-u) > (size_t) sz)
601 return false;
602
603 if ((size_t) (i-u) > UT_NAMESIZE - 1)
604 return false;
605
606 return true;
607 }
608
609 bool valid_user_group_name_or_id(const char *u) {
610
611 /* Similar as above, but is also fine with numeric UID/GID specifications, as long as they are in the right
612 * range, and not the invalid user ids. */
613
614 if (isempty(u))
615 return false;
616
617 if (valid_user_group_name(u))
618 return true;
619
620 return parse_uid(u, NULL) >= 0;
621 }
622
623 bool valid_gecos(const char *d) {
624
625 if (!d)
626 return false;
627
628 if (!utf8_is_valid(d))
629 return false;
630
631 if (string_has_cc(d, NULL))
632 return false;
633
634 /* Colons are used as field separators, and hence not OK */
635 if (strchr(d, ':'))
636 return false;
637
638 return true;
639 }
640
641 bool valid_home(const char *p) {
642
643 if (isempty(p))
644 return false;
645
646 if (!utf8_is_valid(p))
647 return false;
648
649 if (string_has_cc(p, NULL))
650 return false;
651
652 if (!path_is_absolute(p))
653 return false;
654
655 if (!path_is_normalized(p))
656 return false;
657
658 /* Colons are used as field separators, and hence not OK */
659 if (strchr(p, ':'))
660 return false;
661
662 return true;
663 }
664
665 int maybe_setgroups(size_t size, const gid_t *list) {
666 int r;
667
668 /* Check if setgroups is allowed before we try to drop all the auxiliary groups */
669 if (size == 0) { /* Dropping all aux groups? */
670 _cleanup_free_ char *setgroups_content = NULL;
671 bool can_setgroups;
672
673 r = read_one_line_file("/proc/self/setgroups", &setgroups_content);
674 if (r == -ENOENT)
675 /* Old kernels don't have /proc/self/setgroups, so assume we can use setgroups */
676 can_setgroups = true;
677 else if (r < 0)
678 return r;
679 else
680 can_setgroups = streq(setgroups_content, "allow");
681
682 if (!can_setgroups) {
683 log_debug("Skipping setgroups(), /proc/self/setgroups is set to 'deny'");
684 return 0;
685 }
686 }
687
688 if (setgroups(size, list) < 0)
689 return -errno;
690
691 return 0;
692 }