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