summaryrefslogtreecommitdiff
path: root/lib/password.c
blob: 74578784f2ffd0cfb9c1014a3ef18ee1cea2ff29 (plain)
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
#include "lslib.h"

#include <errno.h>
#include <pwd.h>
#include <shadow.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define SHADOW_BUFSIZE 256

static const char* get_passwd(const struct passwd* pw) {
	const char *pass;

	if (!pw)
		return "aa"; /* "aa" will never match */

	pass = pw->pw_passwd;

	if ((pass[0] == 'x' || pass[0] == '*') && !pass[1]) {
		struct spwd* result;

        errno = 0;
		result = getspnam(pw->pw_name);
        
        if (errno == EACCES) {
            errno = 0;
            error("binary not properly installed");
        }

		pass = (result == NULL) ? "aa" : result->sp_pwdp;
	}

	return pass;
}

int check_password(const struct passwd *pw, char* plaintext) {
	char* encrypted;
    char* salt;
    char* p;
	const char *pw_pass;
	int r;

	pw_pass = get_passwd(pw);
	if (!pw_pass[0]) {
		return PASSWORD_EMPTY;
	}

    salt = strdup(pw_pass);
    if (salt == NULL) die();
    p = strchr(salt + 1, '$');
    if (p == NULL) die();
    p = strchr(p + 1, '$');
    if (p == NULL) die();
    p[1] = 0;

    encrypted = crypt(plaintext, salt);
	r = (strcmp(encrypted, pw_pass) == 0);

    nuke_str(plaintext); 
    free(salt);

	return r;
}

int prompt_password(const struct passwd *pw, char* prompt) {
    char* plaintext = getpass(prompt);
	return check_password(pw, plaintext);
}