From b848c8582e597287af9a72488737e672b95e3aa2 Mon Sep 17 00:00:00 2001 From: Seraphim Mellos Date: Fri, 20 Jun 2008 12:49:48 +0300 Subject: Completed update_passwd function for pam_unix --- Make.defs | 2 +- modules/pam_unix/pam_unix.c | 126 +++++++++++++++++++++++++++++++++++++---- modules/pam_unix/pam_unix.c~ | 130 +++++++++++++++++++++++++++++++++++++++---- 3 files changed, 234 insertions(+), 24 deletions(-) diff --git a/Make.defs b/Make.defs index 465c9e1..c39353d 100644 --- a/Make.defs +++ b/Make.defs @@ -7,7 +7,7 @@ LD = $(CC) RM = rm -f MKDIR = mkdir -p INSTALL = install -c -CFLAGS = -Wall -g -fPIC -I../../include -I/opt/local/include -O2 +CFLAGS = -Wall -g -fPIC -I../../include -I/opt/local/include -O2 -D_XOPEN_SOURCE=500 -D_SVID_SOURCE LDFLAGS = -shared -L/opt/local/lib # -Wl,$(LINKEROPTS) LINKEROPTS = LDLIBS = -lpam -lcrypt 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 #include #include @@ -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. diff --git a/modules/pam_unix/pam_unix.c~ b/modules/pam_unix/pam_unix.c~ index dd3c519..d1410c9 100644 --- a/modules/pam_unix/pam_unix.c~ +++ b/modules/pam_unix/pam_unix.c~ @@ -1,5 +1,3 @@ -#define _XOPEN_SOURCE - #include #include #include @@ -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,15 +302,18 @@ 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; + + int tmpflags = flags | PAM_UPDATE_AUTHTOK; /* identify user */ @@ -351,7 +355,8 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, - if (flags & PAM_PRELIM_CHECK) { + if (tmpflags & PAM_PRELIM_CHECK) { + puts("DOING PRELIM"); PAM_LOG("Doing preliminary actions."); if (getuid() == 0 ) { @@ -385,8 +390,8 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, if (strcmp(hashedpwd, old_pwd->pw_passwd) != 0) return (PAM_PERM_DENIED); - } else if ( flags & PAM_UPDATE_AUTHTOK ) { - + } else if ( tmpflags & PAM_UPDATE_AUTHTOK ) { + puts("DOING UPDATE"); PAM_LOG("Doing actual update."); pam_err= pam_get_authtok(pamh, PAM_OLDAUTHTOK ,&old_pass, NULL); @@ -399,7 +404,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 +467,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 +482,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 +501,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 +588,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. -- cgit v1.2.3-65-gdbad