summaryrefslogtreecommitdiff
path: root/lib/password.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lib/password.c70
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);
+}