diff options
Diffstat (limited to 'modules/pam_unix/unix_chkpwd.c')
-rw-r--r-- | modules/pam_unix/unix_chkpwd.c | 277 |
1 files changed, 17 insertions, 260 deletions
diff --git a/modules/pam_unix/unix_chkpwd.c b/modules/pam_unix/unix_chkpwd.c index b6508b87..11ac3aac 100644 --- a/modules/pam_unix/unix_chkpwd.c +++ b/modules/pam_unix/unix_chkpwd.c @@ -24,61 +24,12 @@ #include <shadow.h> #include <signal.h> #include <time.h> -#ifdef WITH_SELINUX -#include <selinux/selinux.h> -#define SELINUX_ENABLED (selinux_enabled!=-1 ? selinux_enabled : (selinux_enabled=is_selinux_enabled()>0)) -static security_context_t prev_context=NULL; -static int selinux_enabled=-1; -#else -#define SELINUX_ENABLED 0 -#endif - -#define MAXPASS 200 /* the maximum length of a password */ #include <security/_pam_types.h> #include <security/_pam_macros.h> #include "passverify.h" -/* syslogging function for errors and other information */ - -static void su_sighandler(int sig) -{ -#ifndef SA_RESETHAND - /* emulate the behaviour of the SA_RESETHAND flag */ - if ( sig == SIGILL || sig == SIGTRAP || sig == SIGBUS || sig = SIGSERV ) - signal(sig, SIG_DFL); -#endif - if (sig > 0) { - helper_log_err(LOG_NOTICE, "caught signal %d.", sig); - exit(sig); - } -} - -static void setup_signals(void) -{ - struct sigaction action; /* posix signal structure */ - - /* - * Setup signal handlers - */ - (void) memset((void *) &action, 0, sizeof(action)); - action.sa_handler = su_sighandler; -#ifdef SA_RESETHAND - action.sa_flags = SA_RESETHAND; -#endif - (void) sigaction(SIGILL, &action, NULL); - (void) sigaction(SIGTRAP, &action, NULL); - (void) sigaction(SIGBUS, &action, NULL); - (void) sigaction(SIGSEGV, &action, NULL); - action.sa_handler = SIG_IGN; - action.sa_flags = 0; - (void) sigaction(SIGTERM, &action, NULL); - (void) sigaction(SIGHUP, &action, NULL); - (void) sigaction(SIGINT, &action, NULL); - (void) sigaction(SIGQUIT, &action, NULL); -} - static int _check_expiry(const char *uname) { struct spwd *spent; @@ -103,190 +54,15 @@ static int _check_expiry(const char *uname) return retval; } -static char *getuidname(uid_t uid) -{ - struct passwd *pw; - static char username[32]; - - pw = getpwuid(uid); - if (pw == NULL) - return NULL; - - strncpy(username, pw->pw_name, sizeof(username)); - username[sizeof(username) - 1] = '\0'; - - return username; -} - -#define SH_TMPFILE "/etc/nshadow" -static int _update_shadow(const char *forwho) -{ - struct spwd *spwdent = NULL, *stmpent = NULL; - FILE *pwfile, *opwfile; - int err = 1; - int oldmask; - struct stat st; - char pass[MAXPASS + 1]; - char towhat[MAXPASS + 1]; - int npass=0; - - /* read the password from stdin (a pipe from the pam_unix module) */ - - npass = read(STDIN_FILENO, pass, MAXPASS); - - if (npass < 0) { /* is it a valid password? */ - - helper_log_err(LOG_DEBUG, "no password supplied"); - return PAM_AUTHTOK_ERR; - - } else if (npass >= MAXPASS) { - - helper_log_err(LOG_DEBUG, "password too long"); - return PAM_AUTHTOK_ERR; - - } else { - /* does pass agree with the official one? */ - int retval=0; - pass[npass] = '\0'; /* NUL terminate */ - retval = helper_verify_password(forwho, pass, 0); - if (retval != PAM_SUCCESS) { - return retval; - } - } - - /* read the password from stdin (a pipe from the pam_unix module) */ - - npass = read(STDIN_FILENO, towhat, MAXPASS); - - if (npass < 0) { /* is it a valid password? */ - - helper_log_err(LOG_DEBUG, "no new password supplied"); - return PAM_AUTHTOK_ERR; - - } else if (npass >= MAXPASS) { - - helper_log_err(LOG_DEBUG, "new password too long"); - return PAM_AUTHTOK_ERR; - - } - - towhat[npass] = '\0'; /* NUL terminate */ - spwdent = getspnam(forwho); - if (spwdent == NULL) { - return PAM_USER_UNKNOWN; - } - oldmask = umask(077); - -#ifdef WITH_SELINUX - if (SELINUX_ENABLED) { - security_context_t shadow_context=NULL; - if (getfilecon("/etc/shadow",&shadow_context)<0) { - return PAM_AUTHTOK_ERR; - }; - if (getfscreatecon(&prev_context)<0) { - freecon(shadow_context); - return PAM_AUTHTOK_ERR; - } - if (setfscreatecon(shadow_context)) { - freecon(shadow_context); - freecon(prev_context); - return PAM_AUTHTOK_ERR; - } - freecon(shadow_context); - } -#endif - pwfile = fopen(SH_TMPFILE, "w"); - umask(oldmask); - if (pwfile == NULL) { - err = 1; - goto done; - } - - opwfile = fopen("/etc/shadow", "r"); - if (opwfile == NULL) { - fclose(pwfile); - err = 1; - goto done; - } - - if (fstat(fileno(opwfile), &st) == -1) { - fclose(opwfile); - fclose(pwfile); - err = 1; - goto done; - } - - if (fchown(fileno(pwfile), st.st_uid, st.st_gid) == -1) { - fclose(opwfile); - fclose(pwfile); - err = 1; - goto done; - } - if (fchmod(fileno(pwfile), st.st_mode) == -1) { - fclose(opwfile); - fclose(pwfile); - err = 1; - goto done; - } - - stmpent = fgetspent(opwfile); - while (stmpent) { - - if (!strcmp(stmpent->sp_namp, forwho)) { - stmpent->sp_pwdp = towhat; - stmpent->sp_lstchg = time(NULL) / (60 * 60 * 24); - err = 0; - D(("Set password %s for %s", stmpent->sp_pwdp, forwho)); - } - - if (putspent(stmpent, pwfile)) { - D(("error writing entry to shadow file: %m")); - err = 1; - break; - } - - stmpent = fgetspent(opwfile); - } - fclose(opwfile); - - if (fclose(pwfile)) { - D(("error writing entries to shadow file: %m")); - err = 1; - } - - done: - if (!err) { - if (rename(SH_TMPFILE, "/etc/shadow")) - err = 1; - } - -#ifdef WITH_SELINUX - if (SELINUX_ENABLED) { - if (setfscreatecon(prev_context)) { - err = 1; - } - if (prev_context) - freecon(prev_context); - prev_context=NULL; - } -#endif - - if (!err) { - return PAM_SUCCESS; - } else { - unlink(SH_TMPFILE); - return PAM_AUTHTOK_ERR; - } -} - int main(int argc, char *argv[]) { char pass[MAXPASS + 1]; char *option; int npass, nullok; - int blankpass; + int blankpass = 0; int retval = PAM_AUTH_ERR; char *user; + char *passwords[] = { pass }; /* * Catch or ignore as many signal as possible. @@ -331,51 +107,32 @@ int main(int argc, char *argv[]) option=argv[2]; - if (strncmp(argv[2], "chkexpiry", 8) == 0) { + if (strcmp(option, "chkexpiry") == 0) /* Check account information from the shadow file */ - return _check_expiry(argv[1]); - - } - - if (strncmp(option, "shadow", 8) == 0) { - /* Attempting to change the password */ - return _update_shadow(argv[1]); - } - + return _check_expiry(argv[1]); /* read the nullok/nonull option */ - if (strncmp(option, "nullok", 8) == 0) + else if (strcmp(option, "nullok") == 0) nullok = 1; - else + else if (strcmp(option, "nonull") == 0) nullok = 0; + else + return PAM_SYSTEM_ERR; /* read the password from stdin (a pipe from the pam_unix module) */ - npass = read(STDIN_FILENO, pass, MAXPASS); - - if (npass < 0) { /* is it a valid password? */ + npass = read_passwords(STDIN_FILENO, 1, passwords); + if (npass != 1) { /* is it a valid password? */ helper_log_err(LOG_DEBUG, "no password supplied"); + *pass = '\0'; + } - } else if (npass >= MAXPASS) { - - helper_log_err(LOG_DEBUG, "password too long"); - - } else { - if (npass == 0) { - /* the password is NULL */ - blankpass = 1; - retval = helper_verify_password(user, NULL, nullok); - - } else { - /* does pass agree with the official one? */ - if (pass[0] == '\0') - blankpass = 1; - pass[npass] = '\0'; /* NUL terminate */ - retval = helper_verify_password(user, pass, nullok); - - } + if (*pass == '\0') { + blankpass = 1; } + retval = helper_verify_password(user, pass, nullok); + memset(pass, '\0', MAXPASS); /* clear memory of the password */ /* return pass or fail */ @@ -392,7 +149,7 @@ int main(int argc, char *argv[]) /* * Copyright (c) Andrew G. Morgan, 1996. All rights reserved - * Copyright (c) Red Hat, Inc., 2007. All rights reserved + * Copyright (c) Red Hat, Inc., 2007,2008. All rights reserved * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions |