From 0d40a5b03d76ad60e6346117a28ecb191ef315f1 Mon Sep 17 00:00:00 2001 From: Seraphim Mellos Date: Wed, 18 Jun 2008 15:33:32 +0300 Subject: Fixed a bug with dummy authentication in pam_unix --- modules/pam_unix/pam_unix.c | 67 ++++++++++++++++++++++++++++---------- modules/pam_unix/pam_unix.c~ | 77 +++++++++++++++++++++++++++++++++----------- 2 files changed, 108 insertions(+), 36 deletions(-) diff --git a/modules/pam_unix/pam_unix.c b/modules/pam_unix/pam_unix.c index 0443a5a..2be7e75 100644 --- a/modules/pam_unix/pam_unix.c +++ b/modules/pam_unix/pam_unix.c @@ -2,7 +2,6 @@ #include #include -#include #include #include #include @@ -18,10 +17,11 @@ #define PAM_PASSWORD #ifndef __linux__ -#include +#include /* for BSD login classes */ +#else +#include /* for linux boxes */ #endif - #define PASSWORD_HASH "md5" #define MAX_RETRIES 3 #define DEFAULT_WARN (2L * 7L * 86400L) /* two weeks */ @@ -32,6 +32,7 @@ #include #include +static char * read_shadow(const char * user) ; /* * User authentication */ @@ -44,7 +45,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, login_cap_t *lc; #endif struct passwd *pwd; - const char *pass, *crypt_pass, *user; + const char *pass, *crypt_pass, *real_hash, *user; int pam_err; /* identify user */ @@ -63,6 +64,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, PAM_LOG("Authenticating user: [%s]", user); + puts("USER GOT"); /* get password */ if (pwd != NULL) { @@ -71,23 +73,26 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, if (pass[0] == '\0') { if (!(flags & PAM_DISALLOW_NULL_AUTHTOK) && openpam_get_option(pamh, PAM_OPT_NULLOK)){ - PAM_ERROR("Authentication failed. Empty passwd not allowed."); + PAM_LOG("User [%s] has empty password. Authentication succesfull."); return (PAM_SUCCESS); } - pass = "*"; + real_hash = "*"; } + #ifndef __linux__ lc = login_getpwclass(pwd); -#endif +#endif } else { PAM_LOG("Doing dummy authentication."); - pass = "*"; -#ifndef __linux__ + real_hash = "*"; + +#ifndef __linux__ lc = login_getpwclass(NULL); #endif } + #ifndef __linux__ prompt = login_getcapstr(lc, "passwd_prompt", NULL, NULL); pam_err = pam_get_authtok(pamh, PAM_AUTHTOK, &pass, prompt); @@ -102,14 +107,24 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, if (pam_err != PAM_SUCCESS) return (PAM_AUTH_ERR); - /* check passwd entry */ - crypt_pass = crypt(pass, pwd->pw_passwd); - if ( strcmp(crypt_pass, pwd->pw_passwd) != 0 ) { + /* check passwd entry */ + + if ( strncmp(real_hash, "*", sizeof(char)) !=0 ) { +#ifndef __linux__ + real_hash = pwd->pw_passwd; +#else + real_hash = read_shadow(user); +#endif + } + + crypt_pass = crypt(pass,real_hash); + if ( strcmp(crypt_pass, real_hash) != 0 ) { PAM_ERROR("Wrong password. Authentication failed."); pam_err = PAM_AUTH_ERR; } else { PAM_LOG("Authentication completed succesfully."); + puts("SUCCESS!"); pam_err = PAM_SUCCESS; } @@ -138,8 +153,6 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags , int argc , const char *argv[] ) { - - #ifndef __linux__ login_cap_t *lc; #endif @@ -209,7 +222,7 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags , PAM_ERROR("Account has expired!"); return (PAM_ACCT_EXPIRED); } else if ( ( pwd->sp_expire - curtime < DEFAULT_WARN) ) { - PAM_ERROR(pamh, "Warning: your account expires on %s", + PAM_ERROR("Warning: your account expires on %s", ctime(&pwd->sp_expire)); } } @@ -285,7 +298,8 @@ pam_sm_chautok(pam_handle_t *pamh, int flags, if (openpam_get_option(pamh, PAM_OPT_AUTH_AS_SELF)) { PAM_LOG("Authenticating as self."); - old_pwd = getpwnam(getlogin()); + user=getlogin(); + old_pwd = getpwnam(user); } else { if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) { PAM_ERROR("Authenticating with uname [%s] failed.", user); @@ -454,6 +468,25 @@ pam_sm_chautok(pam_handle_t *pamh, int flags, } +/* + * Read hashed password for user from shadow entry. + * This is for use on Linux machines only. + */ +static char * read_shadow(const char * user) { + + struct spwd * pwd; + /* + * No error checking. Everything has been tested prior to + * calling this function. Nothing can go wrong, right? + */ + pwd = getspnam(user); + + return (pwd->sp_pwdp); +} + + + +#ifndef __linux__ /* * Mostly stolen from freebsd-lib's pam_unix module which was mostly * stolen from passwd(1)'s local_passwd.c @@ -484,5 +517,5 @@ makesalt(char salt[SALTSIZE]) { // to64(&salt[i], arc4random(), 4); salt[SALTSIZE] = '\0'; } - +#endif PAM_MODULE_ENTRY("pam_unix") diff --git a/modules/pam_unix/pam_unix.c~ b/modules/pam_unix/pam_unix.c~ index d70693d..601aa89 100644 --- a/modules/pam_unix/pam_unix.c~ +++ b/modules/pam_unix/pam_unix.c~ @@ -2,7 +2,6 @@ #include #include -#include #include #include #include @@ -18,10 +17,11 @@ #define PAM_PASSWORD #ifndef __linux__ -#include +#include /* for BSD login classes */ +#else +#include /* for linux boxes */ #endif - #define PASSWORD_HASH "md5" #define MAX_RETRIES 3 #define DEFAULT_WARN (2L * 7L * 86400L) /* two weeks */ @@ -32,6 +32,7 @@ #include #include +static char * read_shadow(const char * user) ; /* * User authentication */ @@ -44,7 +45,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, login_cap_t *lc; #endif struct passwd *pwd; - const char *pass, *crypt_pass, *user; + const char *pass, *crypt_pass, *real_hash, *user; int pam_err; /* identify user */ @@ -63,6 +64,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, PAM_LOG("Authenticating user: [%s]", user); + puts("USER GOT"); /* get password */ if (pwd != NULL) { @@ -71,23 +73,32 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, if (pass[0] == '\0') { if (!(flags & PAM_DISALLOW_NULL_AUTHTOK) && openpam_get_option(pamh, PAM_OPT_NULLOK)){ - PAM_ERROR("Authentication failed. Empty passwd not allowed."); + PAM_LOG("User [%s] has empty password. Authentication succesfull."); return (PAM_SUCCESS); } - pass = "*"; + real_hash = "*"; } -#ifndef __linux__ + + /* + * Dummy authentication is something that the freebsd-lib + * people have implemented. Not sure whether it's needed on + * Linux -or BSD- but it'll be left as is for compatibiity + * issues. Need to be checked! + */ + lc = login_getpwclass(pwd); -#endif + } else { PAM_LOG("Doing dummy authentication."); - pass = "*"; -#ifndef __linux__ + real_hash = "*"; + +#ifndef __linux__ lc = login_getpwclass(NULL); #endif } + #ifndef __linux__ prompt = login_getcapstr(lc, "passwd_prompt", NULL, NULL); pam_err = pam_get_authtok(pamh, PAM_AUTHTOK, &pass, prompt); @@ -102,14 +113,24 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, if (pam_err != PAM_SUCCESS) return (PAM_AUTH_ERR); - /* check passwd entry */ - crypt_pass = crypt(pass, pwd->pw_passwd); - if ( strcmp(crypt_pass, pwd->pw_passwd) != 0 ) { + /* check passwd entry */ + + if ( strncmp(real_hash, "*", sizeof(char)) !=0 ) { +#ifndef __linux__ + real_hash = pwd->pw_passwd; +#else + real_hash = read_shadow(user); +#endif + } + + crypt_pass = crypt(pass,real_hash); + if ( strcmp(crypt_pass, real_hash) != 0 ) { PAM_ERROR("Wrong password. Authentication failed."); pam_err = PAM_AUTH_ERR; } else { PAM_LOG("Authentication completed succesfully."); + puts("SUCCESS!"); pam_err = PAM_SUCCESS; } @@ -138,8 +159,6 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags , int argc , const char *argv[] ) { - - #ifndef __linux__ login_cap_t *lc; #endif @@ -209,7 +228,7 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags , PAM_ERROR("Account has expired!"); return (PAM_ACCT_EXPIRED); } else if ( ( pwd->sp_expire - curtime < DEFAULT_WARN) ) { - PAM_ERROR(pamh, "Warning: your account expires on %s", + PAM_ERROR("Warning: your account expires on %s", ctime(&pwd->sp_expire)); } } @@ -285,7 +304,8 @@ pam_sm_chautok(pam_handle_t *pamh, int flags, if (openpam_get_option(pamh, PAM_OPT_AUTH_AS_SELF)) { PAM_LOG("Authenticating as self."); - old_pwd = getpwnam(getlogin()); + user=getlogin(); + old_pwd = getpwnam(user); } else { if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) { PAM_ERROR("Authenticating with uname [%s] failed.", user); @@ -454,6 +474,25 @@ pam_sm_chautok(pam_handle_t *pamh, int flags, } +/* + * Read hashed password for user from shadow entry. + * This is for use on Linux machines only. + */ +static char * read_shadow(const char * user) { + + struct spwd * pwd; + /* + * No error checking. Everything has been tested prior to + * calling this function. Nothing can go wrong, right? + */ + pwd = getspnam(user); + + return (pwd->sp_pwdp); +} + + + +#ifndef __linux__ /* * Mostly stolen from freebsd-lib's pam_unix module which was mostly * stolen from passwd(1)'s local_passwd.c @@ -481,8 +520,8 @@ makesalt(char salt[SALTSIZE]) { */ for (i = 0; i < SALTSIZE; i += 4) - to64(&salt[i], arc4random(), 4); +// to64(&salt[i], arc4random(), 4); salt[SALTSIZE] = '\0'; } - +#endif PAM_MODULE_ENTRY("pam_unix") -- cgit v1.2.3