chkpw.c (1778B)
- // checkpassword-ng: Uniform password checking interface for applications
- // Copyright © 2021 checkpassword-ng Authors <https://hacktivis.me/git/checkpassword-ng>
- // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
- #define _POSIX_C_SOURCE 200809L
- #include "chkpw.h"
- #include <assert.h> /* assert */
- #include <errno.h> /* errno */
- #include <pwd.h> /* getpwnam */
- #include <stdio.h> /* sprintf() */
- #include <string.h> /* strerror, strcmp */
- #include <unistd.h> /* crypt, sleep */
- #ifdef __GLIBC__
- // GNU's Not POSIX
- #include <crypt.h>
- #endif
- #ifdef __linux__
- // I love linux extensions (no)
- #include <shadow.h> /* getspnam */
- #endif
- char strerror_buf[1024];
- struct chkpw_extra
- {
- // intentionally left blank
- } chkpw_extra;
- static void
- safe_strerror(char *desc, int errnum)
- {
- char *err = strerror(errnum);
- snprintf(strerror_buf, 1024, "%s: %s", desc, err);
- }
- char *
- chkpw(const char *username, const char *password, struct chkpw_extra *chkpw_extra)
- {
- (void)chkpw_extra;
- char *pw_hash = "";
- struct passwd *pwent = getpwnam(username);
- if(!pwent)
- {
- safe_strerror("getpwnam", errno);
- return strerror_buf;
- }
- assert(pwent->pw_passwd);
- pw_hash = pwent->pw_passwd;
- if(strcmp(pw_hash, "") == 0)
- {
- return CHKPW_EMPTY;
- }
- if(strcmp(pw_hash, "x") == 0)
- {
- #ifdef __linux__
- struct spwd *swent = getspnam(username);
- if(!swent)
- {
- safe_strerror("getspnam", errno);
- return strerror_buf;
- }
- pw_hash = swent->sp_pwdp;
- #else /* __linux__ */
- return "Invalid password entry";
- #endif
- }
- char *chk_hash = crypt(password, pw_hash);
- if(chk_hash == NULL)
- {
- safe_strerror("crypt", errno);
- return strerror_buf;
- }
- if(strcmp(chk_hash, pw_hash) == 0)
- {
- return CHKPW_VALID;
- }
- else
- {
- sleep(2);
- return CHKPW_INVALID;
- }
- assert(1);
- }