From ecdac9bb770ec5f76fd04ce0528daad10c221b13 Mon Sep 17 00:00:00 2001 From: Seraphim Mellos Date: Mon, 16 Jun 2008 22:57:28 +0300 Subject: Added logging/debug msgs in pam_unix --- Make.defs~ | 13 - modules/pam_nologin/pam_nologin.c~ | 20 - modules/pam_rootok/Makefile~ | 41 -- modules/pam_rootok/pam_rootok.c~ | 31 -- modules/pam_securetty/Makefile~ | 41 -- modules/pam_securetty/pam_securetty.c~ | 70 --- modules/pam_unix/pam_unix.c~ | 806 --------------------------------- 7 files changed, 1022 deletions(-) delete mode 100644 Make.defs~ delete mode 100644 modules/pam_nologin/pam_nologin.c~ delete mode 100644 modules/pam_rootok/Makefile~ delete mode 100644 modules/pam_rootok/pam_rootok.c~ delete mode 100644 modules/pam_securetty/Makefile~ delete mode 100644 modules/pam_securetty/pam_securetty.c~ delete mode 100644 modules/pam_unix/pam_unix.c~ diff --git a/Make.defs~ b/Make.defs~ deleted file mode 100644 index cbaea77..0000000 --- a/Make.defs~ +++ /dev/null @@ -1,13 +0,0 @@ -# -## Copyright (c) 2008 by Seraphim Mellos. See LICENSE. -# - -CC = gcc -LD = $(CC) -RM = rm -f -MKDIR = mkdir -p -INSTALL = install -c -CFLAGS = -Wall -g -fPIC -I../../include -I/opt/local/include -O2 -D_XOPEN_SOURCE=500 -D_SVID_SOURCE -fno-stack-protector -LDFLAGS = -shared -L/opt/local/lib # -Wl,$(LINKEROPTS) -LINKEROPTS = -LDLIBS = -lpam -lcrypt diff --git a/modules/pam_nologin/pam_nologin.c~ b/modules/pam_nologin/pam_nologin.c~ deleted file mode 100644 index db95fbe..0000000 --- a/modules/pam_nologin/pam_nologin.c~ +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#ifndef __linux__ -#include -#endif - -#define PAM_SM_AUTH - -#include -#include -#include - -#define NOLOGIN_FILE "/etc/nologin" - diff --git a/modules/pam_rootok/Makefile~ b/modules/pam_rootok/Makefile~ deleted file mode 100644 index 4285e98..0000000 --- a/modules/pam_rootok/Makefile~ +++ /dev/null @@ -1,41 +0,0 @@ -# -## Copyright (c) 2008 by Seraphim Mellos. See LICENSE. -# - -include ../../Make.defs - -TITLE = pam_rootok -PAM_SO_SUFFIX = -LIBSHARED = $(TITLE).so$(PAM_SO_SUFFIX) -SHLIBMODE = 755 -MAN8 = $(TITLE).8 -MANMODE = 644 -#SECUREDIR = /lib/security -#MANDIR = /usr/share/man -#DESTDIR = - - - -PROJ = $(LIBSHARED) -OBJS = pam_unix.o - -all: - case "`uname -s`" in \ - Linux) $(MAKE) CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" \ - LDLIBS="$(LDLIBS)" $(PROJ);;\ - FreeBSD) echo "Not yet supported.";;\ - *) echo "OS not supported.";;\ - esac - -$(LIBSHARED): $(OBJS) - $(LD) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(LIBSHARED) - -.c.o: - $(CC) $(CFLAGS) -c $*.c - - -clean: - $(RM) $(PROJ) *.o - - - diff --git a/modules/pam_rootok/pam_rootok.c~ b/modules/pam_rootok/pam_rootok.c~ deleted file mode 100644 index 9adec8c..0000000 --- a/modules/pam_rootok/pam_rootok.c~ +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include -#include -#include - -#define PAM_SM_AUTH - -#include -#include -#include - -PAM_EXTERN int -pam_sm_authenticate(pam_handle_t *pamh, int flags , - int argc , const char *argv[] ) -{ - - if (getuid() == 0) - return (PAM_SUCCESS); - - PAM_ERROR("User is not superuser"); - - return (PAM_AUTH_ERR); -} - -PAM_EXTERN int -pam_sm_setcred(pam_handle_t *pamh, int flags, - int argc , const char *argv[] ) -{ - - return (PAM_SUCCESS); -} diff --git a/modules/pam_securetty/Makefile~ b/modules/pam_securetty/Makefile~ deleted file mode 100644 index 6115401..0000000 --- a/modules/pam_securetty/Makefile~ +++ /dev/null @@ -1,41 +0,0 @@ -# -## Copyright (c) 2008 by Seraphim Mellos. See LICENSE. -# - -include ../../Make.defs - -TITLE = pam_rootok -PAM_SO_SUFFIX = -LIBSHARED = $(TITLE).so$(PAM_SO_SUFFIX) -SHLIBMODE = 755 -MAN8 = $(TITLE).8 -MANMODE = 644 -#SECUREDIR = /lib/security -#MANDIR = /usr/share/man -#DESTDIR = - - - -PROJ = $(LIBSHARED) -OBJS = pam_rootok.o - -all: - case "`uname -s`" in \ - Linux) $(MAKE) CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" \ - LDLIBS="$(LDLIBS)" $(PROJ);;\ - FreeBSD) echo "Not yet supported.";;\ - *) echo "OS not supported.";;\ - esac - -$(LIBSHARED): $(OBJS) - $(LD) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(LIBSHARED) - -.c.o: - $(CC) $(CFLAGS) -c $*.c - - -clean: - $(RM) $(PROJ) *.o - - - diff --git a/modules/pam_securetty/pam_securetty.c~ b/modules/pam_securetty/pam_securetty.c~ deleted file mode 100644 index bd81ea5..0000000 --- a/modules/pam_securetty/pam_securetty.c~ +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include -#include -#include -#include - - -#define PAM_SM_ACCOUNT - -#include -#include -#include - -#define TTY_PREFIX "/dev/" - - -PAM_EXTERN int -pam_sm_acct_mgmt(pam_handle_t * pamh, int flags, - int argc, const char * argv[]) -{ - struct passwd *pwd; - struct ttyent *ttyinfo; - const char *user; - const char *tty; - int pam_err; - - if ( ( (pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS ) - || ( user == NULL ) ) { - PAM_ERROR("Error recovering username."); - return (pam_err); - } - - if ( (pwd = getpwnam(user)) == NULL ) { - PAM_ERROR("Could not get passwd entry for user [%s]",user); - return (PAM_SERVICE_ERR); - } - - if ( pwd->pw_uid != 0 ) { - /* secure tty applies only to root */ - return (PAM_SUCCESS); - } - - if ( (pam_err = pam_get_item(pamh, PAM_TTY,(void *) &tty) ) != PAM_SUCCESS ) { - return (pam_err); - } - - if (tty != NULL && strncmp(TTY_PREFIX, tty, sizeof(TTY_PREFIX)) == 0) { - PAM_LOG("tty starts with " TTY_PREFIX); - /* skip prefix */ - tty = (const char *)tty + sizeof(TTY_PREFIX) - 1; - } - - /* - * Linux-PAM, before checking the actual tty, - * opens /etc/securettys to check if it's world - * writable or not a normal file and only continues - * if neither is correct. Sounds like a good idea - - * maybe it should be done here as well... - */ - - - if ( tty != NULL && (ttyinfo = getttynam(tty)) != NULL && - (ttyinfo->ty_status & TTY_SECURE) != 0) - return (PAM_SUCCESS); - - PAM_ERROR("Access denied: tty %s is not secure", tty); - return (PAM_AUTH_ERR); -} - -PAM_MODULE_ENTRY("pam_securetty"); diff --git a/modules/pam_unix/pam_unix.c~ b/modules/pam_unix/pam_unix.c~ deleted file mode 100644 index ea1b75d..0000000 --- a/modules/pam_unix/pam_unix.c~ +++ /dev/null @@ -1,806 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#ifndef MAXHOSTNAMELEN -# define MAXHOSTNAMELEN 256 -#endif - -#define PAM_SM_AUTH -#define PAM_SM_ACCOUNT -#define PAM_SM_PASSWORD -#define PAM_SM_SESSION - -#ifndef __linux__ -#include /* for BSD login classes */ -#include /* libutil functions */ -#else -#include -#endif - -#define PASSWORD_HASH "md5" -#define MAX_RETRIES 3 -#define DEFAULT_WARN (2L * 7L * 86400L) /* two weeks */ -#define SALTSIZE 32 - - -#include -#include -#include -#include - - -/* - * Helper functions for internal use - */ - -#ifdef __linux__ -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 - -static void to64(char *s, long v, int n); -void makesalt(char salt[SALTSIZE]); - -/* - * User authentication - */ - -PAM_EXTERN int -pam_sm_authenticate(pam_handle_t *pamh, int flags, - int argc , const char *argv[] ) { - -#ifndef __linux__ - login_cap_t *lc; -#endif - struct passwd *pwd; - const char *pass, *crypt_pass, *real_hash, *user; - int pam_err; - - /* identify user */ - - if (openpam_get_option(pamh, PAM_OPT_AUTH_AS_SELF)) { - PAM_LOG("Authenticating as self."); - pwd = getpwnam(getlogin()); - } else { - if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) { - PAM_ERROR("Authenticating with uname [%s] failed.", user); - return (pam_err); - } - - pwd = getpwnam(user); - } - puts("authenticating as user:"); - puts(user); - PAM_LOG("Authenticating user: [%s]", user); - - /* get password */ - - if (pwd != NULL) { - PAM_LOG("Doing real authentication"); - pass = pwd->pw_passwd; - if (pass[0] == '\0') { - if (!(flags & PAM_DISALLOW_NULL_AUTHTOK) && - openpam_get_option(pamh, PAM_OPT_NULLOK)){ - PAM_LOG("User [%s] has empty password. \ - Authentication succesfull.", user); - return (PAM_SUCCESS); - } - - real_hash = "*"; - } - -#ifndef __linux__ - lc = login_getpwclass(pwd); -#endif - } else { - PAM_LOG("Doing dummy authentication."); - 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); - login_close(lc); -#else - pam_err = pam_get_authtok(pamh, PAM_AUTHTOK, (const char **) &pass, NULL); -#endif - PAM_LOG("Got password for user [%s]", user); - - if (pam_err == PAM_CONV_ERR) - return (pam_err); - if (pam_err != PAM_SUCCESS) - return (PAM_AUTH_ERR); - - - /* 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."); - pam_err = PAM_SUCCESS; - } - - return (pam_err); -} - -PAM_EXTERN int -pam_sm_setcred(pam_handle_t *pamh , int flags , - int argc , const char *argv[] ) { - - /* - * This functions takes care of renewing/initializing - * user credentials as well as gid/uids. Someday, it - * will be completed. For now, it's not very urgent. - */ - - return (PAM_SUCCESS); -} - - -/* - * Account Management - */ - -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 - - struct spwd *pwd; - int pam_err; - const char *user; - time_t curtime; - -#ifndef __linux__ - const void *rhost, *tty; - char rhostip[MAXHOSTNAMELEN] = ""; -#endif - - /* Sanity checks for uname,pwd,tty,host etc */ - - pam_err = pam_get_user(pamh, &user, NULL); - - if (pam_err != PAM_SUCCESS) - return (pam_err); - - if (user == NULL || (pwd = getpwnam(user)) == NULL) - return (PAM_SERVICE_ERR); - - - PAM_LOG("Got user [%s]" , user ); -#ifndef __linux__ - - /* - * tty/host info are provided by login classes - * and cannot be used out of the box under Linux - * for sanity checking (BSD only). May need to - * be ported/rewritten to work on Linux as well. - * Time will tell... - */ - pam_err = pam_get_item(pamh, PAM_RHOST, &rhost); - - if (pam_err != PAM_SUCCESS) - return (pam_err); - - pam_err = pam_get_item(pamh, PAM_TTY, &tty); - - if (pam_err != PAM_SUCCESS) - return (pam_err); -#endif - if (*pwd->sp_pwdp == '\0' && - (flags & PAM_DISALLOW_NULL_AUTHTOK) != 0) - return (PAM_NEW_AUTHTOK_REQD); - -#ifndef __linux__ - lc = login_getpwclass(pwd); - - if (lc == NULL) { - PAM_ERROR("Unable to get login class for user [%s]"); - return (PAM_SERVICE_ERR); - } -#endif - /* Check if pw_lstchg or sp_expire is set */ -/* - if (pwd->sp_lstchg || pwd->sp_expire) - curtime = time(NULL) / (60 * 60 * 24); - puts("before all"); - if (pwd->sp_expire) { - puts(ctime(&(pwd->sp_expire))); - puts(ctime(&curtime)); - if ( (curtime > pwd->sp_expire ) && ( pwd->sp_expire != -1 ) ) { -#ifndef __linux__ - login_close(lc); -#endif - puts("expire 1"); - PAM_ERROR("Account has expired!"); - return (PAM_ACCT_EXPIRED); - } else if ( ( pwd->sp_expire - curtime < DEFAULT_WARN) ) { - puts("expire 2"); - PAM_ERROR("Warning: your account expires on %s", - ctime(&pwd->sp_expire)); - } - } - - if (pwd->sp_lstchg == 0 ) { - return (PAM_NEW_AUTHTOK_REQD); - } - puts("before tcb OK!"); - * check all other possibilities (mostly stolen from pam_tcb) * - - if ((curtime > (pwd->sp_lstchg + pwd->sp_max + pwd->sp_inact)) && - (pwd->sp_max != -1) && (pwd->sp_inact != -1) && - (pwd->sp_lstchg != 0)) { - PAM_ERROR("Account has expired!"); - return (PAM_ACCT_EXPIRED); - } - puts("after 1"); - - if (((pwd->sp_lstchg + pwd->sp_max) < curtime) && - (pwd->sp_max != -1)) { - PAM_ERROR("Account has expired!"); - return (PAM_ACCT_EXPIRED); - } - puts("after 2"); - - if ((curtime - pwd->sp_lstchg > pwd->sp_max) - && (curtime - pwd->sp_lstchg > pwd->sp_inact) - && (curtime - pwd->sp_lstchg > pwd->sp_max + pwd->sp_inact) - && (pwd->sp_max != -1) && (pwd->sp_inact != -1)) { - PAM_ERROR("Account has expired!"); - return (PAM_ACCT_EXPIRED); - } - - puts("after 3"); -*/ pam_err = (PAM_SUCCESS); - -#ifndef __linux__ - - /* validate tty/host/time */ - - if (!auth_hostok(lc, rhost, rhostip) || - !auth_ttyok(lc, tty) || - !auth_timeok(lc, time(NULL))) - pam_err = PAM_AUTH_ERR; - - - login_close(lc); -#endif - - return (pam_err); - -} - -/* - * Password Management - */ - -PAM_EXTERN int -pam_sm_chauthtok(pam_handle_t *pamh, int flags, - int argc, const char *argv[]) -{ - - /* - * NIS support will be left for future implementation. - * This is standard unix passwd changing function. - */ - 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)) { - PAM_LOG("Authenticating as self."); - 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); - return (pam_err); - } - - old_pwd = getpwnam(user); - } - - PAM_LOG("Got user: [%s]", user); - - if (old_pwd == NULL) { - PAM_ERROR("User [%s] either has a corrupted passwd entry or \ - is not in the selected database", user); - return (PAM_AUTHTOK_RECOVERY_ERR); - } - - /* - * When looking through the LinuxPAM code, I came across this : - * - * ` Various libraries at various times have had bugs related to - * '+' or '-' as the first character of a user name. Don't - * allow them. ` - * - * I don't know if the problem is still around but just in case... - */ - - if (user == NULL || user[0] == '-' || user[0] == '+' ) { - PAM_ERROR("Bad username [%s]", user); - return (PAM_USER_UNKNOWN); - } - - - - if (flags & PAM_PRELIM_CHECK) { - puts("DOING PRELIM"); - PAM_LOG("Doing preliminary actions."); - - if (getuid() == 0 ) { - /* root doesn't need old passwd */ - return (pam_set_item(pamh, PAM_OLDAUTHTOK, "")); - } - - if ( (old_pwd->pw_passwd[0] == '\0' ) && - ( openpam_get_option(pamh, PAM_OPT_NULLOK) ) && - !(flags & PAM_DISALLOW_NULL_AUTHTOK) ) { - /* - * Something funny could happen here since we don't - * ask for a password. - */ - old_pass = ""; - } else { - pam_err = pam_get_authtok(pamh,PAM_OLDAUTHTOK, - &old_pass, NULL); - if (pam_err != PAM_SUCCESS ) - return (pam_err); - - } - - PAM_LOG("Got old token for user [%s].",user); - - hashedpwd = crypt(old_pass, old_pwd->pw_passwd); - - if (old_pass[0] == '\0' && !openpam_get_option(pamh, PAM_OPT_NULLOK)) - return (PAM_PERM_DENIED); - - if (strcmp(hashedpwd, old_pwd->pw_passwd) != 0) - 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); - - if (pam_err != PAM_SUCCESS) - return (pam_err); - - PAM_LOG("Got old password"); - - retries = 0; - pam_err = PAM_AUTHTOK_ERR; - - while ((pam_err != PAM_SUCCESS) && ( retries++ <= MAX_RETRIES)) { - - pam_err = pam_get_authtok(pamh, PAM_AUTHTOK, - &new_pass, NULL); - - PAM_ERROR("Unable to get new passwd. Please \ - try again"); - - } - - if (pam_err != PAM_SUCCESS) { - PAM_ERROR("Unable to get new password!"); - return (pam_err); - } - - PAM_LOG("Got new password"); - - /* - * checking has to be done (?) for the new passwd to - * verify it's not weak. - */ - - if (getuid() != 0 && new_pass[0] == '\0' && - !openpam_get_option(pamh, PAM_OPT_NULLOK)) - return (PAM_PERM_DENIED); - -#ifndef __linux__ - - /* - * The BSD way to update the passwd entry. Taken as is - * from the freebsd-lib module pam_unix. Unfortunately, - * the following won't work under Linux. - */ - - if ((new_pwd = pw_dup(old_pwd)) == NULL) - return (PAM_BUF_ERR); - - new_pwd->pw_change = 0; - lc = login_getclass(new_pwd->pw_class); - if (login_setcryptfmt(lc, password_hash, NULL) == NULL) - openpam_log(PAM_LOG_ERROR, - "can't set password cipher, relying on default"); - - login_close(lc); - makesalt(salt); - new_pwd->pw_passwd = crypt(new_pass, salt); - - - pam_err = PAM_SERVICE_ERR; - if (pw_init(NULL, NULL)) - openpam_log(PAM_LOG_ERROR, "pw_init() failed"); - else if ((pfd = pw_lock()) == -1) - openpam_log(PAM_LOG_ERROR, "pw_lock() failed"); - else if ((tfd = pw_tmp(-1)) == -1) - openpam_log(PAM_LOG_ERROR, "pw_tmp() failed"); - else if (pw_copy(pfd, tfd, new_pwd, old_pwd) == -1) - openpam_log(PAM_LOG_ERROR, "pw_copy() failed"); - else if (pw_mkdb(new_pwd->pw_name) == -1) - openpam_log(PAM_LOG_ERROR, "pw_mkdb() failed"); - else - pam_err = PAM_SUCCESS; - pw_fini(); - - //free(old_pwd); -#else - makesalt(salt); - /* Update shadow/passwd entries for Linux */ - update_shadow( pamh ,user,crypt(new_pass, salt) ); - update_passwd( pamh ,user,"x"); - puts("done with shadow"); - -#endif - - } else { - pam_err = PAM_ABORT; - PAM_ERROR("Unrecognized flags."); - return (pam_err); - } - puts("chauthtok successfull"); - return (PAM_SUCCESS); -} - - -PAM_EXTERN int -pam_sm_open_session( pam_handle_t * pamh, int flags, - int argc, const char * argv[]) -{ - - char *user, *service; - int pam_err; - - pam_err = pam_get_item(pamh, PAM_USER, (void *) &user); - if ( pam_err != PAM_SUCCESS || user == NULL || *user == '\0') { - PAM_ERROR("Open session - Error recovering username"); - return (PAM_SESSION_ERR); - } - - pam_err = pam_get_item(pamh, PAM_SERVICE, (void *) &service); - if ( pam_err != PAM_SUCCESS || service == NULL || *service == '\0') { - PAM_ERROR("Open session - Error recovering service"); - return (PAM_SESSION_ERR); - } - - PAM_LOG("Opened session for user [%s] by %s(uid=%lu)", user, getlogin(), - (unsigned long) getuid()); - - return PAM_SUCCESS; - -} - -PAM_EXTERN int -pam_sm_close_session( pam_handle_t * pamh, int flags, - int argc, const char * argv[]) -{ - char *user, *service; - int pam_err; - - pam_err = pam_get_item(pamh, PAM_USER, (void *) &user); - if ( pam_err != PAM_SUCCESS || user == NULL || *user == '\0') { - PAM_ERROR("Close session - Error recovering username"); - return (PAM_SESSION_ERR); - } - - pam_err = pam_get_item(pamh, PAM_SERVICE, (void *) &service); - if ( pam_err != PAM_SUCCESS || service == NULL || *service == '\0') { - PAM_ERROR("Close session - Error recovering service"); - return (PAM_SESSION_ERR); - } - - PAM_LOG("Closed session for user [%s]", user); - - return PAM_SUCCESS; -} - -#ifdef __linux__ - -#define NEW_SHADOW "/etc/.shadow" -/* - * Update shadow with new user password - */ - -static int update_shadow( pam_handle_t * pamh , const char * user, - const char * newhashedpwd ) { - FILE *oldshadow, *newshadow; - struct spwd *pwd,*cur_pwd; - struct stat filestat; - - - puts("updating shadow"); - if ( (pwd = getspnam(user)) == NULL) - return PAM_USER_UNKNOWN; - - if ( (oldshadow = fopen ("/etc/shadow", "r")) == NULL ) { - PAM_ERROR("Could not open /etc/shadow. Updating shadow \ - database cancelled."); - return (PAM_AUTHTOK_ERR); - } - - if ( (newshadow = fopen (NEW_SHADOW, "w")) == NULL ) { - PAM_ERROR("Could not open temp file. Updating shadow \ - database cancelled."); - fclose(oldshadow); - return (PAM_AUTHTOK_ERR); - } - - if (fstat(fileno(oldshadow), &filestat) == -1 ) { - PAM_ERROR("Could not get stat for /etc/shadow. \ - Updating shadow database cancelled."); - fclose(oldshadow); - fclose(newshadow); - unlink(NEW_SHADOW); - return (PAM_AUTHTOK_ERR); - } - - if (fchown(fileno(newshadow), filestat.st_uid, filestat.st_gid) == -1 ) { - PAM_ERROR("Could not set uid/gid for new shadwow file. \ - Updating shadow database cancelled."); - fclose(oldshadow); - fclose(newshadow); - unlink(NEW_SHADOW); - return (PAM_AUTHTOK_ERR); - } - - if (fchmod(fileno(newshadow), filestat.st_mode) == -1 ) { - PAM_ERROR("Could not chmod for new shadow file. \ - Updating shadow database cancelled."); - fclose(oldshadow); - fclose(newshadow); - unlink(NEW_SHADOW); - return (PAM_AUTHTOK_ERR); - } - - while ( (cur_pwd = fgetspent(oldshadow)) ) { - if( strlen(user) == strlen(cur_pwd->sp_namp) - && !strncmp(cur_pwd->sp_namp, user, strlen(user))) { - cur_pwd->sp_pwdp = newhashedpwd; - cur_pwd->sp_lstchg = time(NULL) / (60 * 60 * 24); - PAM_LOG("Updated password for user [%s]",user); - } - - if(putspent(cur_pwd, newshadow)) { - PAM_ERROR("Error writing entry to new shadow file. \ - Updating shadow database cancelled."); - fclose(oldshadow); - fclose(newshadow); - unlink(NEW_SHADOW); - return (PAM_AUTHTOK_ERR); - } - } - - fclose(oldshadow); - - if (fclose(newshadow)) { - PAM_ERROR("Error updating new shadow file."); - unlink(NEW_SHADOW); - return (PAM_AUTHTOK_ERR); - } - - /* - * If program flow has come up to here, all is good - * and it's safe to update the shadow file. - */ - - if( rename(NEW_SHADOW, "/etc/shadow") == 0 ) { - PAM_LOG("Password updated successfully for user [%s]",user); - } else { - PAM_ERROR("Error updating shadow file."); - unlink(NEW_SHADOW); - return (PAM_AUTHTOK_ERR); - } - - return (PAM_SUCCESS); - -} - -/* - * 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. - */ -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); -} - - -#endif - -/* - * Mostly stolen from freebsd-lib's pam_unix module which was mostly - * stolen from passwd(1)'s local_passwd.c - * - * Good ideas are meant to be reused ;) - */ - -static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ - "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - -static void to64(char *s, long v, int n) { - while (--n >= 0) { - *s++ = itoa64[v&0x3f]; - v >>= 6; - } -} - -/* Salt suitable for traditional DES and MD5 */ -void -makesalt(char salt[SALTSIZE]) { - int i; - /* These are not really random numbers, they are just - * numbers that change to thwart construction of a - * dictionary. This is exposed to the public. - */ - - for (i = 0; i < SALTSIZE; i += 4) - -#ifndef __linux__ - to64(&salt[i], arc4random(), 4); -#else - to64(&salt[i], random(), 4); -#endif - - salt[SALTSIZE] = '\0'; -} -PAM_MODULE_ENTRY("pam_unix") -- cgit v1.2.3-65-gdbad