aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_unix/pam_unix.c')
-rw-r--r--modules/pam_unix/pam_unix.c126
1 files changed, 115 insertions, 11 deletions
diff --git a/modules/pam_unix/pam_unix.c b/modules/pam_unix/pam_unix.c
index dd3c519..a14dbe6 100644
--- a/modules/pam_unix/pam_unix.c
+++ b/modules/pam_unix/pam_unix.c
@@ -1,5 +1,3 @@
-#define _XOPEN_SOURCE
-
#include <pwd.h>
#include <netdb.h>
#include <sys/types.h>
@@ -42,7 +40,10 @@
*/
#ifdef __linux__
-static int update_shadow( pam_handle_t * pamh , const char * user , const char * newhashedpwd ) ;
+static int update_shadow( pam_handle_t * pamh ,
+ const char * user , const char * newhashedpwd );
+static int update_passwd( pam_handle_t * pamh ,
+ const char * user ,const char * newhashedpwd );
static char * read_shadow(const char * user) ;
#endif
@@ -301,16 +302,17 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags,
* NIS support will be left for future implementation.
* This is standard unix passwd changing function.
*/
- struct passwd *new_pwd, *old_pwd;
+ struct passwd *old_pwd;
const char *user, *old_pass, *new_pass;
char *hashedpwd, salt[SALTSIZE+1];
#ifndef __linux__
+ struct passwd *new_pwd;
login_cap_t * lc;
int pfd, tfd;
#endif
int pam_err, retries;
-
+
/* identify user */
if (openpam_get_option(pamh, PAM_OPT_AUTH_AS_SELF)) {
@@ -352,6 +354,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags,
if (flags & PAM_PRELIM_CHECK) {
+ puts("DOING PRELIM");
PAM_LOG("Doing preliminary actions.");
if (getuid() == 0 ) {
@@ -386,7 +389,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags,
return (PAM_PERM_DENIED);
} else if ( flags & PAM_UPDATE_AUTHTOK ) {
-
+ puts("DOING UPDATE");
PAM_LOG("Doing actual update.");
pam_err= pam_get_authtok(pamh, PAM_OLDAUTHTOK ,&old_pass, NULL);
@@ -399,7 +402,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags,
retries = 0;
pam_err = PAM_AUTHTOK_ERR;
- while ((pam_err != PAM_SUCCESS) && ( retries++ < MAX_RETRIES)) {
+ while ((pam_err != PAM_SUCCESS) && ( retries++ <= MAX_RETRIES)) {
pam_err = pam_get_authtok(pamh, PAM_AUTHTOK,
&new_pass, NULL);
@@ -462,12 +465,13 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags,
pam_err = PAM_SUCCESS;
pw_fini();
- free(old_pwd);
+ //free(old_pwd);
#else
makesalt(salt);
- update_shadow( pamh ,user,crypt(new_pass, salt) );
- free(old_pwd);
/* Update shadow/passwd entries for Linux */
+ update_shadow( pamh ,user,crypt(new_pass, salt) );
+ update_passwd( pamh ,user,"x");
+ puts("done with shadow");
#endif
@@ -476,7 +480,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags,
PAM_ERROR("Unrecognized flags.");
return (pam_err);
}
-
+ puts("chauthtok successfull");
return (PAM_SUCCESS);
}
@@ -495,6 +499,7 @@ static int update_shadow( pam_handle_t * pamh , const char * user ,const char *
struct stat filestat;
+ puts("updating shadow");
if ( (pwd = getspnam(user)) == NULL)
return PAM_USER_UNKNOWN;
@@ -581,6 +586,105 @@ static int update_shadow( pam_handle_t * pamh , const char * user ,const char *
}
+/*
+ * Update /etc/passwd with new user information
+ */
+
+#define NEW_PASSWD "/etc/.passwd"
+
+static int update_passwd( pam_handle_t * pamh , const char * user ,const char * newhashedpwd ) {
+ FILE *oldpasswd, *newpasswd;
+ struct passwd *pwd,*cur_pwd;
+ struct stat filestat;
+
+
+ puts("updating passwd");
+ if ( (pwd = getpwnam(user)) == NULL)
+ return PAM_USER_UNKNOWN;
+
+ if ( (oldpasswd = fopen ("/etc/passwd", "r")) == NULL ) {
+ PAM_ERROR("Could not open /etc/passwd. Updating passwd \
+ database cancelled.");
+ return (PAM_AUTHTOK_ERR);
+ }
+
+ if ( (newpasswd = fopen (NEW_PASSWD, "w")) == NULL ) {
+ PAM_ERROR("Could not open temp file. Updating passwd \
+ database cancelled.");
+ fclose(oldpasswd);
+ return (PAM_AUTHTOK_ERR);
+ }
+
+ if (fstat(fileno(oldpasswd), &filestat) == -1 ) {
+ PAM_ERROR("Could not get stat for /etc/passwd. \
+ Updating passwd database cancelled.");
+ fclose(oldpasswd);
+ fclose(newpasswd);
+ unlink(NEW_PASSWD);
+ return (PAM_AUTHTOK_ERR);
+ }
+
+ if (fchown(fileno(newpasswd), filestat.st_uid, filestat.st_gid) == -1 ) {
+ PAM_ERROR("Could not set uid/gid for new shadwow file. \
+ Updating passwd database cancelled.");
+ fclose(oldpasswd);
+ fclose(newpasswd);
+ unlink(NEW_PASSWD);
+ return (PAM_AUTHTOK_ERR);
+ }
+
+ if (fchmod(fileno(newpasswd), filestat.st_mode) == -1 ) {
+ PAM_ERROR("Could not chmod for new passwd file. \
+ Updating passwd database cancelled.");
+ fclose(oldpasswd);
+ fclose(newpasswd);
+ unlink(NEW_PASSWD);
+ return (PAM_AUTHTOK_ERR);
+ }
+
+ while ( (cur_pwd = fgetpwent(oldpasswd)) ) {
+ if( strlen(user) == strlen(cur_pwd->pw_name)
+ && !strncmp(cur_pwd->pw_name, user, strlen(user))) {
+ cur_pwd->pw_passwd = newhashedpwd;
+ PAM_LOG("Updated password for user [%s]",user);
+ }
+
+ if(putpwent(cur_pwd, newpasswd)) {
+ PAM_ERROR("Error writing entry to new passwd file. \
+ Updating passwd database cancelled.");
+ fclose(oldpasswd);
+ fclose(newpasswd);
+ unlink(NEW_PASSWD);
+ return (PAM_AUTHTOK_ERR);
+ }
+ }
+
+ fclose(oldpasswd);
+
+ if (fclose(newpasswd)) {
+ PAM_ERROR("Error updating new passwd file.");
+ unlink(NEW_PASSWD);
+ return (PAM_AUTHTOK_ERR);
+ }
+
+ /*
+ * If program flow has come up to here, all is good
+ * and it's safe to update the passwd file.
+ */
+
+ if( rename(NEW_PASSWD, "/etc/passwd") == 0 ) {
+ PAM_LOG("Password updated successfully for user [%s]",user);
+ } else {
+ PAM_ERROR("Error updating passwd file.");
+ unlink(NEW_PASSWD);
+ return (PAM_AUTHTOK_ERR);
+ }
+
+ return (PAM_SUCCESS);
+
+}
+
+
/*
* Read hashed password for user from shadow entry.
* This is for use on Linux machines only.