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