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