diff options
Diffstat (limited to '')
-rw-r--r-- | lib/password.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/lib/password.c b/lib/password.c new file mode 100644 index 0000000..7457878 --- /dev/null +++ b/lib/password.c @@ -0,0 +1,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); +} |