-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathauth_shadow.c
77 lines (64 loc) · 1.63 KB
/
auth_shadow.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/*
* The /etc/shadow authentication routine. This one is really tricky,
* in order to make sure we don't have an /etc/shadow fd or sensitive
* data in our address space after we drop the root privileges. It is
* arguable whether this was worth the extra code and the performance
* penalty or not, but such discussions are outside of the scope of a
* comment like this. ;^)
*/
#include "params.h"
#if AUTH_SHADOW && !VIRTUAL_ONLY
#define _XOPEN_SOURCE 4
#define _XOPEN_SOURCE_EXTENDED
#define _XOPEN_VERSION 4
#define _XPG4_2
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pwd.h>
#include <shadow.h>
#include <sys/wait.h>
#include <sys/types.h>
extern int log_error(char *s);
struct passwd *auth_userpass(char *user, char *pass, int *known)
{
int channel[2];
struct passwd *pw;
struct spwd *spw;
char result;
if ((*known = (pw = getpwnam(user)) != NULL))
memset(pw->pw_passwd, 0, strlen(pw->pw_passwd));
endpwent();
result = 0;
if (pipe(channel)) {
log_error("pipe");
return NULL;
}
switch (fork()) {
case -1:
log_error("fork");
return NULL;
case 0:
close(channel[0]);
if (!(spw = getspnam(user)) || !pw || !*spw->sp_pwdp ||
*spw->sp_pwdp == '*' || *spw->sp_pwdp == '!')
crypt(pass, AUTH_DUMMY_SALT);
else {
char *hash = crypt(pass, spw->sp_pwdp);
if (hash && !strcmp(hash, spw->sp_pwdp))
result = 1;
}
write(channel[1], &result, 1);
exit(0);
}
if (close(channel[1]))
pw = NULL;
else {
if (read(channel[0], &result, 1) != 1) pw = NULL;
if (result != 1) pw = NULL;
if (close(channel[0])) pw = NULL;
}
wait(NULL);
return result == 1 ? pw : NULL;
}
#endif