]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/user-util.c
Merge pull request #8552 from keszybz/test-improvements
[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 (synthesize_nobody() &&
141 STR_IN_SET(*username, NOBODY_USER_NAME, "65534")) {
142 *username = NOBODY_USER_NAME;
143
144 if (uid)
145 *uid = UID_NOBODY;
146 if (gid)
147 *gid = GID_NOBODY;
148
149 if (home)
150 *home = "/";
151
152 if (shell)
153 *shell = "/sbin/nologin";
154
155 return 0;
156 }
157
158 if (parse_uid(*username, &u) >= 0) {
159 errno = 0;
160 p = getpwuid(u);
161
162 /* If there are multiple users with the same id, make
163 * sure to leave $USER to the configured value instead
164 * of the first occurrence in the database. However if
165 * the uid was configured by a numeric uid, then let's
166 * pick the real username from /etc/passwd. */
167 if (p)
168 *username = p->pw_name;
169 } else {
170 errno = 0;
171 p = getpwnam(*username);
172 }
173
174 if (!p)
175 return errno > 0 ? -errno : -ESRCH;
176
177 if (uid) {
178 if (!uid_is_valid(p->pw_uid))
179 return -EBADMSG;
180
181 *uid = p->pw_uid;
182 }
183
184 if (gid) {
185 if (!gid_is_valid(p->pw_gid))
186 return -EBADMSG;
187
188 *gid = p->pw_gid;
189 }
190
191 if (home)
192 *home = p->pw_dir;
193
194 if (shell)
195 *shell = p->pw_shell;
196
197 return 0;
198 }
199
200 static inline bool is_nologin_shell(const char *shell) {
201
202 return PATH_IN_SET(shell,
203 /* 'nologin' is the friendliest way to disable logins for a user account. It prints a nice
204 * message and exits. Different distributions place the binary at different places though,
205 * hence let's list them all. */
206 "/bin/nologin",
207 "/sbin/nologin",
208 "/usr/bin/nologin",
209 "/usr/sbin/nologin",
210 /* 'true' and 'false' work too for the same purpose, but are less friendly as they don't do
211 * any message printing. Different distributions place the binary at various places but at
212 * least not in the 'sbin' directory. */
213 "/bin/false",
214 "/usr/bin/false",
215 "/bin/true",
216 "/usr/bin/true");
217 }
218
219 int get_user_creds_clean(
220 const char **username,
221 uid_t *uid, gid_t *gid,
222 const char **home,
223 const char **shell) {
224
225 int r;
226
227 /* Like get_user_creds(), but resets home/shell to NULL if they don't contain anything relevant. */
228
229 r = get_user_creds(username, uid, gid, home, shell);
230 if (r < 0)
231 return r;
232
233 if (shell &&
234 (isempty(*shell) || is_nologin_shell(*shell)))
235 *shell = NULL;
236
237 if (home &&
238 (isempty(*home) || path_equal(*home, "/")))
239 *home = NULL;
240
241 return 0;
242 }
243
244 int get_group_creds(const char **groupname, gid_t *gid) {
245 struct group *g;
246 gid_t id;
247
248 assert(groupname);
249
250 /* We enforce some special rules for gid=0: in order to avoid
251 * NSS lookups for root we hardcode its data. */
252
253 if (STR_IN_SET(*groupname, "root", "0")) {
254 *groupname = "root";
255
256 if (gid)
257 *gid = 0;
258
259 return 0;
260 }
261
262 if (synthesize_nobody() &&
263 STR_IN_SET(*groupname, NOBODY_GROUP_NAME, "65534")) {
264 *groupname = NOBODY_GROUP_NAME;
265
266 if (gid)
267 *gid = GID_NOBODY;
268
269 return 0;
270 }
271
272 if (parse_gid(*groupname, &id) >= 0) {
273 errno = 0;
274 g = getgrgid(id);
275
276 if (g)
277 *groupname = g->gr_name;
278 } else {
279 errno = 0;
280 g = getgrnam(*groupname);
281 }
282
283 if (!g)
284 return errno > 0 ? -errno : -ESRCH;
285
286 if (gid) {
287 if (!gid_is_valid(g->gr_gid))
288 return -EBADMSG;
289
290 *gid = g->gr_gid;
291 }
292
293 return 0;
294 }
295
296 char* uid_to_name(uid_t uid) {
297 char *ret;
298 int r;
299
300 /* Shortcut things to avoid NSS lookups */
301 if (uid == 0)
302 return strdup("root");
303 if (synthesize_nobody() &&
304 uid == UID_NOBODY)
305 return strdup(NOBODY_USER_NAME);
306
307 if (uid_is_valid(uid)) {
308 long bufsize;
309
310 bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
311 if (bufsize <= 0)
312 bufsize = 4096;
313
314 for (;;) {
315 struct passwd pwbuf, *pw = NULL;
316 _cleanup_free_ char *buf = NULL;
317
318 buf = malloc(bufsize);
319 if (!buf)
320 return NULL;
321
322 r = getpwuid_r(uid, &pwbuf, buf, (size_t) bufsize, &pw);
323 if (r == 0 && pw)
324 return strdup(pw->pw_name);
325 if (r != ERANGE)
326 break;
327
328 bufsize *= 2;
329 }
330 }
331
332 if (asprintf(&ret, UID_FMT, uid) < 0)
333 return NULL;
334
335 return ret;
336 }
337
338 char* gid_to_name(gid_t gid) {
339 char *ret;
340 int r;
341
342 if (gid == 0)
343 return strdup("root");
344 if (synthesize_nobody() &&
345 gid == GID_NOBODY)
346 return strdup(NOBODY_GROUP_NAME);
347
348 if (gid_is_valid(gid)) {
349 long bufsize;
350
351 bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
352 if (bufsize <= 0)
353 bufsize = 4096;
354
355 for (;;) {
356 struct group grbuf, *gr = NULL;
357 _cleanup_free_ char *buf = NULL;
358
359 buf = malloc(bufsize);
360 if (!buf)
361 return NULL;
362
363 r = getgrgid_r(gid, &grbuf, buf, (size_t) bufsize, &gr);
364 if (r == 0 && gr)
365 return strdup(gr->gr_name);
366 if (r != ERANGE)
367 break;
368
369 bufsize *= 2;
370 }
371 }
372
373 if (asprintf(&ret, GID_FMT, gid) < 0)
374 return NULL;
375
376 return ret;
377 }
378
379 int in_gid(gid_t gid) {
380 long ngroups_max;
381 gid_t *gids;
382 int r, i;
383
384 if (getgid() == gid)
385 return 1;
386
387 if (getegid() == gid)
388 return 1;
389
390 if (!gid_is_valid(gid))
391 return -EINVAL;
392
393 ngroups_max = sysconf(_SC_NGROUPS_MAX);
394 assert(ngroups_max > 0);
395
396 gids = newa(gid_t, ngroups_max);
397
398 r = getgroups(ngroups_max, gids);
399 if (r < 0)
400 return -errno;
401
402 for (i = 0; i < r; i++)
403 if (gids[i] == gid)
404 return 1;
405
406 return 0;
407 }
408
409 int in_group(const char *name) {
410 int r;
411 gid_t gid;
412
413 r = get_group_creds(&name, &gid);
414 if (r < 0)
415 return r;
416
417 return in_gid(gid);
418 }
419
420 int get_home_dir(char **_h) {
421 struct passwd *p;
422 const char *e;
423 char *h;
424 uid_t u;
425
426 assert(_h);
427
428 /* Take the user specified one */
429 e = secure_getenv("HOME");
430 if (e && path_is_absolute(e)) {
431 h = strdup(e);
432 if (!h)
433 return -ENOMEM;
434
435 *_h = h;
436 return 0;
437 }
438
439 /* Hardcode home directory for root and nobody to avoid NSS */
440 u = getuid();
441 if (u == 0) {
442 h = strdup("/root");
443 if (!h)
444 return -ENOMEM;
445
446 *_h = h;
447 return 0;
448 }
449 if (synthesize_nobody() &&
450 u == UID_NOBODY) {
451 h = strdup("/");
452 if (!h)
453 return -ENOMEM;
454
455 *_h = h;
456 return 0;
457 }
458
459 /* Check the database... */
460 errno = 0;
461 p = getpwuid(u);
462 if (!p)
463 return errno > 0 ? -errno : -ESRCH;
464
465 if (!path_is_absolute(p->pw_dir))
466 return -EINVAL;
467
468 h = strdup(p->pw_dir);
469 if (!h)
470 return -ENOMEM;
471
472 *_h = h;
473 return 0;
474 }
475
476 int get_shell(char **_s) {
477 struct passwd *p;
478 const char *e;
479 char *s;
480 uid_t u;
481
482 assert(_s);
483
484 /* Take the user specified one */
485 e = getenv("SHELL");
486 if (e) {
487 s = strdup(e);
488 if (!s)
489 return -ENOMEM;
490
491 *_s = s;
492 return 0;
493 }
494
495 /* Hardcode shell for root and nobody to avoid NSS */
496 u = getuid();
497 if (u == 0) {
498 s = strdup("/bin/sh");
499 if (!s)
500 return -ENOMEM;
501
502 *_s = s;
503 return 0;
504 }
505 if (synthesize_nobody() &&
506 u == UID_NOBODY) {
507 s = strdup("/sbin/nologin");
508 if (!s)
509 return -ENOMEM;
510
511 *_s = s;
512 return 0;
513 }
514
515 /* Check the database... */
516 errno = 0;
517 p = getpwuid(u);
518 if (!p)
519 return errno > 0 ? -errno : -ESRCH;
520
521 if (!path_is_absolute(p->pw_shell))
522 return -EINVAL;
523
524 s = strdup(p->pw_shell);
525 if (!s)
526 return -ENOMEM;
527
528 *_s = s;
529 return 0;
530 }
531
532 int reset_uid_gid(void) {
533 int r;
534
535 r = maybe_setgroups(0, NULL);
536 if (r < 0)
537 return r;
538
539 if (setresgid(0, 0, 0) < 0)
540 return -errno;
541
542 if (setresuid(0, 0, 0) < 0)
543 return -errno;
544
545 return 0;
546 }
547
548 int take_etc_passwd_lock(const char *root) {
549
550 struct flock flock = {
551 .l_type = F_WRLCK,
552 .l_whence = SEEK_SET,
553 .l_start = 0,
554 .l_len = 0,
555 };
556
557 const char *path;
558 int fd, r;
559
560 /* This is roughly the same as lckpwdf(), but not as awful. We
561 * don't want to use alarm() and signals, hence we implement
562 * our own trivial version of this.
563 *
564 * Note that shadow-utils also takes per-database locks in
565 * addition to lckpwdf(). However, we don't given that they
566 * are redundant as they invoke lckpwdf() first and keep
567 * it during everything they do. The per-database locks are
568 * awfully racy, and thus we just won't do them. */
569
570 if (root)
571 path = prefix_roota(root, ETC_PASSWD_LOCK_PATH);
572 else
573 path = ETC_PASSWD_LOCK_PATH;
574
575 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
576 if (fd < 0)
577 return log_debug_errno(errno, "Cannot open %s: %m", path);
578
579 r = fcntl(fd, F_SETLKW, &flock);
580 if (r < 0) {
581 safe_close(fd);
582 return log_debug_errno(errno, "Locking %s failed: %m", path);
583 }
584
585 return fd;
586 }
587
588 bool valid_user_group_name(const char *u) {
589 const char *i;
590 long sz;
591
592 /* Checks if the specified name is a valid user/group name. Also see POSIX IEEE Std 1003.1-2008, 2016 Edition,
593 * 3.437. We are a bit stricter here however. Specifically we deviate from POSIX rules:
594 *
595 * - We don't allow any dots (this would break chown syntax which permits dots as user/group name separator)
596 * - We require that names fit into the appropriate utmp field
597 * - We don't allow empty user names
598 *
599 * Note that other systems are even more restrictive, and don't permit underscores or uppercase characters.
600 */
601
602 if (isempty(u))
603 return false;
604
605 if (!(u[0] >= 'a' && u[0] <= 'z') &&
606 !(u[0] >= 'A' && u[0] <= 'Z') &&
607 u[0] != '_')
608 return false;
609
610 for (i = u+1; *i; i++) {
611 if (!(*i >= 'a' && *i <= 'z') &&
612 !(*i >= 'A' && *i <= 'Z') &&
613 !(*i >= '0' && *i <= '9') &&
614 !IN_SET(*i, '_', '-'))
615 return false;
616 }
617
618 sz = sysconf(_SC_LOGIN_NAME_MAX);
619 assert_se(sz > 0);
620
621 if ((size_t) (i-u) > (size_t) sz)
622 return false;
623
624 if ((size_t) (i-u) > UT_NAMESIZE - 1)
625 return false;
626
627 return true;
628 }
629
630 bool valid_user_group_name_or_id(const char *u) {
631
632 /* Similar as above, but is also fine with numeric UID/GID specifications, as long as they are in the right
633 * range, and not the invalid user ids. */
634
635 if (isempty(u))
636 return false;
637
638 if (valid_user_group_name(u))
639 return true;
640
641 return parse_uid(u, NULL) >= 0;
642 }
643
644 bool valid_gecos(const char *d) {
645
646 if (!d)
647 return false;
648
649 if (!utf8_is_valid(d))
650 return false;
651
652 if (string_has_cc(d, NULL))
653 return false;
654
655 /* Colons are used as field separators, and hence not OK */
656 if (strchr(d, ':'))
657 return false;
658
659 return true;
660 }
661
662 bool valid_home(const char *p) {
663 /* Note that this function is also called by valid_shell(), any
664 * changes must account for that. */
665
666 if (isempty(p))
667 return false;
668
669 if (!utf8_is_valid(p))
670 return false;
671
672 if (string_has_cc(p, NULL))
673 return false;
674
675 if (!path_is_absolute(p))
676 return false;
677
678 if (!path_is_normalized(p))
679 return false;
680
681 /* Colons are used as field separators, and hence not OK */
682 if (strchr(p, ':'))
683 return false;
684
685 return true;
686 }
687
688 int maybe_setgroups(size_t size, const gid_t *list) {
689 int r;
690
691 /* Check if setgroups is allowed before we try to drop all the auxiliary groups */
692 if (size == 0) { /* Dropping all aux groups? */
693 _cleanup_free_ char *setgroups_content = NULL;
694 bool can_setgroups;
695
696 r = read_one_line_file("/proc/self/setgroups", &setgroups_content);
697 if (r == -ENOENT)
698 /* Old kernels don't have /proc/self/setgroups, so assume we can use setgroups */
699 can_setgroups = true;
700 else if (r < 0)
701 return r;
702 else
703 can_setgroups = streq(setgroups_content, "allow");
704
705 if (!can_setgroups) {
706 log_debug("Skipping setgroups(), /proc/self/setgroups is set to 'deny'");
707 return 0;
708 }
709 }
710
711 if (setgroups(size, list) < 0)
712 return -errno;
713
714 return 0;
715 }
716
717 bool synthesize_nobody(void) {
718
719 #ifdef NOLEGACY
720 return true;
721 #else
722 /* Returns true when we shall synthesize the "nobody" user (which we do by default). This can be turned off by
723 * touching /etc/systemd/dont-synthesize-nobody in order to provide upgrade compatibility with legacy systems
724 * that used the "nobody" user name and group name for other UIDs/GIDs than 65534.
725 *
726 * Note that we do not employ any kind of synchronization on the following caching variable. If the variable is
727 * accessed in multi-threaded programs in the worst case it might happen that we initialize twice, but that
728 * shouldn't matter as each initialization should come to the same result. */
729 static int cache = -1;
730
731 if (cache < 0)
732 cache = access("/etc/systemd/dont-synthesize-nobody", F_OK) < 0;
733
734 return cache;
735 #endif
736 }
737
738 int putpwent_sane(const struct passwd *pw, FILE *stream) {
739 assert(pw);
740 assert(stream);
741
742 errno = 0;
743 if (putpwent(pw, stream) != 0)
744 return errno > 0 ? -errno : -EIO;
745
746 return 0;
747 }
748
749 int putspent_sane(const struct spwd *sp, FILE *stream) {
750 assert(sp);
751 assert(stream);
752
753 errno = 0;
754 if (putspent(sp, stream) != 0)
755 return errno > 0 ? -errno : -EIO;
756
757 return 0;
758 }
759
760 int putgrent_sane(const struct group *gr, FILE *stream) {
761 assert(gr);
762 assert(stream);
763
764 errno = 0;
765 if (putgrent(gr, stream) != 0)
766 return errno > 0 ? -errno : -EIO;
767
768 return 0;
769 }
770
771 #if ENABLE_GSHADOW
772 int putsgent_sane(const struct sgrp *sg, FILE *stream) {
773 assert(sg);
774 assert(stream);
775
776 errno = 0;
777 if (putsgent(sg, stream) != 0)
778 return errno > 0 ? -errno : -EIO;
779
780 return 0;
781 }
782 #endif
783
784 int fgetpwent_sane(FILE *stream, struct passwd **pw) {
785 struct passwd *p;
786
787 assert(pw);
788 assert(stream);
789
790 errno = 0;
791 p = fgetpwent(stream);
792 if (p == NULL) {
793 if (errno == ENOENT)
794 return false;
795 return errno > 0 ? -errno : -EIO;
796 }
797
798 *pw = p;
799 return true;
800 }
801
802 int fgetspent_sane(FILE *stream, struct spwd **sp) {
803 struct spwd *s;
804
805 assert(sp);
806 assert(stream);
807
808 errno = 0;
809 s = fgetspent(stream);
810 if (s == NULL) {
811 if (errno == ENOENT)
812 return false;
813 return errno > 0 ? -errno : -EIO;
814 }
815
816 *sp = s;
817 return true;
818 }
819
820 int fgetgrent_sane(FILE *stream, struct group **gr) {
821 struct group *g;
822
823 assert(gr);
824 assert(stream);
825
826 errno = 0;
827 g = fgetgrent(stream);
828 if (g == NULL) {
829 if (errno == ENOENT)
830 return false;
831 return errno > 0 ? -errno : -EIO;
832 }
833
834 *gr = g;
835 return true;
836 }
837
838 #if ENABLE_GSHADOW
839 int fgetsgent_sane(FILE *stream, struct sgrp **sg) {
840 struct sgrp *s;
841
842 assert(sg);
843 assert(stream);
844
845 errno = 0;
846 s = fgetsgent(stream);
847 if (s == NULL) {
848 if (errno == ENOENT)
849 return false;
850 return errno > 0 ? -errno : -EIO;
851 }
852
853 *sg = s;
854 return true;
855 }
856 #endif