]> git.armaanb.net Git - opendoas.git/blob - shadow.c
64cc1f740d0172172072b3bf90b0befe7cdf12e0
[opendoas.git] / shadow.c
1 #if HAVE_CRYPT_H
2 #       include <crypt.h>
3 #endif
4 #include <err.h>
5 #include <errno.h>
6 #include <limits.h>
7 #include <pwd.h>
8 #ifdef HAVE_READPASSPHRASE_H
9 #       include <readpassphrase.h>
10 #else
11 #       include "readpassphrase.h"
12 #endif
13 #include <shadow.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <syslog.h>
17 #include <unistd.h>
18
19 #include "openbsd.h"
20
21 #ifndef HOST_NAME_MAX
22 #define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
23 #endif
24
25 void
26 shadowauth(const char *myname, int persist)
27 {
28         const char *hash;
29         char *encrypted;
30         struct passwd *pw;
31         char *challenge, *response, rbuf[1024], cbuf[128];
32
33 #ifdef USE_TIMESTAMP
34         int fd = -1;
35         int valid = 0;
36
37         if (persist)
38                 fd = timestamp_open(&valid, 5 * 60);
39         if (fd != -1 && valid == 1)
40                 goto good;
41 #else
42         (void) persist;
43 #endif
44
45         if ((pw = getpwnam(myname)) == NULL)
46                 err(1, "getpwnam");
47
48         hash = pw->pw_passwd;
49         if (hash[0] == 'x' && hash[1] == '\0') {
50                 struct spwd *sp;
51                 if ((sp = getspnam(myname)) == NULL)
52                         errx(1, "Authorization failed");
53                 hash = sp->sp_pwdp;
54         } else if (hash[0] != '*') {
55                 errx(1, "Authorization failed");
56         }
57
58         char host[HOST_NAME_MAX + 1];
59         if (gethostname(host, sizeof(host)))
60                 snprintf(host, sizeof(host), "?");
61         snprintf(cbuf, sizeof(cbuf),
62                         "\rdoas (%.32s@%.32s) password: ", myname, host);
63         challenge = cbuf;
64
65         response = readpassphrase(challenge, rbuf, sizeof(rbuf), RPP_REQUIRE_TTY);
66         if (response == NULL && errno == ENOTTY) {
67                 syslog(LOG_AUTHPRIV | LOG_NOTICE,
68                         "tty required for %s", myname);
69                 errx(1, "a tty is required");
70         }
71         if (response == NULL)
72                 err(1, "readpassphrase");
73         if ((encrypted = crypt(response, hash)) == NULL) {
74                 explicit_bzero(rbuf, sizeof(rbuf));
75                 errx(1, "Authorization failed");
76         }
77         explicit_bzero(rbuf, sizeof(rbuf));
78         if (strcmp(encrypted, hash) != 0) {
79                 syslog(LOG_AUTHPRIV | LOG_NOTICE, "failed auth for %s", myname);
80                 errx(1, "Authorization failed");
81         }
82
83 #ifdef USE_TIMESTAMP
84 good:
85         if (fd != -1) {
86                 timestamp_set(fd, 5 * 60);
87                 close(fd);
88         }
89 #endif
90 }