* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <security/_pam_aconf.h>
+#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#define PAM_SM_PASSWORD
#include <security/pam_modules.h>
-
-#ifndef LINUX_PAM
-#include <security/pam_appl.h>
-#endif /* LINUX_PAM */
-
-#include <security/_pam_modutil.h>
+#include <security/pam_ext.h>
+#include <security/pam_modutil.h>
#include "yppasswd.h"
#include "md5.h"
* password changing module.
*/
-#ifdef NEED_LCKPWDF
+#if defined(USE_LCKPWDF) && !defined(HAVE_LCKPWDF)
# include "./lckpwdf.-c"
#endif
#define PW_TMPFILE "/etc/npasswd"
#define SH_TMPFILE "/etc/nshadow"
#ifndef CRACKLIB_DICTS
-#define CRACKLIB_DICTS "/usr/share/dict/cracklib_dict"
+#define CRACKLIB_DICTS NULL
#endif
#define OPW_TMPFILE "/etc/security/nopasswd"
#define OLD_PASSWORDS_FILE "/etc/security/opasswd"
int port, err;
if ((err = yp_get_default_domain(&domainname)) != 0) {
- _log_err(LOG_WARNING, pamh, "can't get local yp domain: %s\n",
+ pam_syslog(pamh, LOG_WARNING, "can't get local yp domain: %s",
yperr_string(err));
return NULL;
}
if ((err = yp_master(domainname, "passwd.byname", &master)) != 0) {
- _log_err(LOG_WARNING, pamh, "can't find the master ypserver: %s\n",
+ pam_syslog(pamh, LOG_WARNING, "can't find the master ypserver: %s",
yperr_string(err));
return NULL;
}
port = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP);
if (port == 0) {
- _log_err(LOG_WARNING, pamh,
- "yppasswdd not running on NIS master host\n");
+ pam_syslog(pamh, LOG_WARNING,
+ "yppasswdd not running on NIS master host");
return NULL;
}
if (port >= IPPORT_RESERVED) {
- _log_err(LOG_WARNING, pamh,
- "yppasswd daemon running on illegal port.\n");
+ pam_syslog(pamh, LOG_WARNING,
+ "yppasswd daemon running on illegal port");
return NULL;
}
return master;
/* fork */
child = fork();
if (child == 0) {
- int i=0;
+ size_t i=0;
struct rlimit rlim;
static char *envp[] = { NULL };
char *args[] = { NULL, NULL, NULL, NULL };
if (getrlimit(RLIMIT_NOFILE,&rlim)==0) {
for (i=2; i < rlim.rlim_max; i++) {
- if (fds[0] != i)
+ if ((unsigned int)fds[0] != i)
close(i);
}
}
+
+ if (SELINUX_ENABLED && geteuid() == 0) {
+ /* must set the real uid to 0 so the helper will not error
+ out if pam is called from setuid binary (su, sudo...) */
+ setuid(0);
+ }
+
/* exec binary helper */
args[0] = x_strdup(CHKPWD_HELPER);
args[1] = x_strdup(user);
/* if the stored password is NULL */
int rc=0;
if (fromwhat)
- _pammodutil_write(fds[1], fromwhat, strlen(fromwhat)+1);
+ pam_modutil_write(fds[1], fromwhat, strlen(fromwhat)+1);
else
- _pammodutil_write(fds[1], "", 1);
+ pam_modutil_write(fds[1], "", 1);
if (towhat) {
- _pammodutil_write(fds[1], towhat, strlen(towhat)+1);
+ pam_modutil_write(fds[1], towhat, strlen(towhat)+1);
}
else
- _pammodutil_write(fds[1], "", 1);
+ pam_modutil_write(fds[1], "", 1);
close(fds[0]); /* close here to avoid possible SIGPIPE above */
close(fds[1]);
rc=waitpid(child, &retval, 0); /* wait for helper to complete */
if (rc<0) {
- _log_err(LOG_ERR, pamh, "unix_chkpwd waitpid returned %d: %s", rc, strerror(errno));
+ pam_syslog(pamh, LOG_ERR, "unix_chkpwd waitpid returned %d: %m", rc);
retval = PAM_AUTH_ERR;
} else {
retval = WEXITSTATUS(retval);
fclose(opwfile);
if (!found) {
- pwd = _pammodutil_getpwnam(pamh, forwho);
+ pwd = pam_modutil_getpwnam(pamh, forwho);
if (pwd == NULL) {
err = 1;
} else {
done:
if (!err) {
if (!rename(PW_TMPFILE, "/etc/passwd"))
- _log_err(LOG_NOTICE, pamh, "password changed for %s", forwho);
+ pam_syslog(pamh, LOG_NOTICE, "password changed for %s", forwho);
else
err = 1;
}
done:
if (!err) {
if (!rename(SH_TMPFILE, "/etc/shadow"))
- _log_err(LOG_NOTICE, pamh, "password changed for %s", forwho);
+ pam_syslog(pamh, LOG_NOTICE, "password changed for %s", forwho);
else
err = 1;
}
}
}
-static int _do_setpass(pam_handle_t* pamh, const char *forwho, char *fromwhat,
+static int _do_setpass(pam_handle_t* pamh, const char *forwho,
+ const char *fromwhat,
char *towhat, unsigned int ctrl, int remember)
{
struct passwd *pwd = NULL;
retval = PAM_AUTHTOK_ERR;
goto done;
}
-
+
if (on(UNIX_NIS, ctrl) && _unix_comesfromsource(pamh, forwho, 0, 1)) {
if ((master=getNISserver(pamh)) != NULL) {
struct timeval timeout;
yppwd.newpw.pw_gecos = pwd->pw_gecos;
yppwd.newpw.pw_dir = pwd->pw_dir;
yppwd.newpw.pw_shell = pwd->pw_shell;
- yppwd.oldpass = fromwhat ? fromwhat : "";
+ yppwd.oldpass = fromwhat ? strdup (fromwhat) : strdup ("");
yppwd.newpw.pw_passwd = towhat;
D(("Set password %s for %s", yppwd.newpw.pw_passwd, forwho));
(xdrproc_t) xdr_int, (char *) &status,
timeout);
+ free (yppwd.oldpass);
+
if (err) {
_make_remark(pamh, ctrl, PAM_TEXT_INFO,
clnt_sperrno(err));
}
D(("The password has%s been changed on %s.",
(err || status) ? " not" : "", master));
- _log_err(LOG_NOTICE, pamh, "password%s changed for %s on %s",
+ pam_syslog(pamh, LOG_NOTICE, "password%s changed for %s on %s",
(err || status) ? " not" : "", pwd->pw_name, master);
auth_destroy(clnt->cl_auth);
clnt_destroy(clnt);
if (err || status) {
_make_remark(pamh, ctrl, PAM_TEXT_INFO,
- "NIS password could not be changed.");
+ _("NIS password could not be changed."));
retval = PAM_TRY_AGAIN;
}
#ifdef DEBUG
}
-done:
+done:
#ifdef USE_LCKPWDF
ulckpwdf();
#endif
if (off(UNIX__IAMROOT, ctrl)) {
/* Get the current number of days since 1970 */
curdays = time(NULL) / (60 * 60 * 24);
- if ((curdays < (spwdent->sp_lstchg + spwdent->sp_min))
- && (spwdent->sp_min != -1))
+ if (curdays < spwdent->sp_lstchg) {
+ pam_syslog(pamh, LOG_DEBUG,
+ "account %s has password changed in future",
+ user);
+ curdays = spwdent->sp_lstchg;
+ }
+ if ((curdays - spwdent->sp_lstchg < spwdent->sp_min)
+ && (spwdent->sp_min != -1))
+ /*
+ * The last password change was too recent.
+ */
retval = PAM_AUTHTOK_ERR;
- else if ((curdays > (spwdent->sp_lstchg + spwdent->sp_max + spwdent->sp_inact))
+ else if ((curdays - spwdent->sp_lstchg > spwdent->sp_max)
+ && (curdays - spwdent->sp_lstchg > spwdent->sp_inact)
+ && (curdays - spwdent->sp_lstchg >
+ spwdent->sp_max + spwdent->sp_inact)
&& (spwdent->sp_max != -1) && (spwdent->sp_inact != -1)
&& (spwdent->sp_lstchg != 0))
/*
,const char *pass_old
,const char *pass_new)
{
- const char *user;
+ const void *user;
const char *remark = NULL;
int retval = PAM_SUCCESS;
if (pass_new == NULL || (pass_old && !strcmp(pass_old, pass_new))) {
if (on(UNIX_DEBUG, ctrl)) {
- _log_err(LOG_DEBUG, pamh, "bad authentication token");
+ pam_syslog(pamh, LOG_DEBUG, "bad authentication token");
}
_make_remark(pamh, ctrl, PAM_ERROR_MSG, pass_new == NULL ?
- "No password supplied" : "Password unchanged");
+ _("No password supplied") : _("Password unchanged"));
return PAM_AUTHTOK_ERR;
}
/*
* checking this would be the place - AGM
*/
- retval = pam_get_item(pamh, PAM_USER, (const void **) &user);
+ retval = pam_get_item(pamh, PAM_USER, &user);
if (retval != PAM_SUCCESS) {
if (on(UNIX_DEBUG, ctrl)) {
- _log_err(LOG_ERR, pamh, "Can not get username");
+ pam_syslog(pamh, LOG_ERR, "Can not get username");
return PAM_AUTHTOK_ERR;
}
}
if (off(UNIX__IAMROOT, ctrl)) {
#ifdef USE_CRACKLIB
- remark = FascistCheck(pass_new, CRACKLIB_DICTS);
+ remark = FascistCheck (pass_new, CRACKLIB_DICTS);
D(("called cracklib [%s]", remark));
#else
if (strlen(pass_new) < 6)
- remark = "You must choose a longer password";
+ remark = _("You must choose a longer password");
D(("length check [%s]", remark));
#endif
if (on(UNIX_REMEMBER_PASSWD, ctrl)) {
if ((retval = check_old_password(user, pass_new)) == PAM_AUTHTOK_ERR)
- remark = "Password has been already used. Choose another.";
+ remark = _("Password has been already used. Choose another.");
if (retval == PAM_ABORT) {
- _log_err(LOG_ERR, pamh, "can't open %s file to check old passwords",
+ pam_syslog(pamh, LOG_ERR, "can't open %s file to check old passwords",
OLD_PASSWORDS_FILE);
return retval;
}
/* <DO NOT free() THESE> */
const char *user;
- char *pass_old, *pass_new;
+ const void *pass_old, *pass_new;
/* </DO NOT free() THESE> */
D(("called."));
* alphanumeric character.
*/
if (user == NULL || !isalnum(*user)) {
- _log_err(LOG_ERR, pamh, "bad username [%s]", user);
+ pam_syslog(pamh, LOG_ERR, "bad username [%s]", user);
return PAM_USER_UNKNOWN;
}
if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl))
- _log_err(LOG_DEBUG, pamh, "username [%s] obtained",
+ pam_syslog(pamh, LOG_DEBUG, "username [%s] obtained",
user);
} else {
if (on(UNIX_DEBUG, ctrl))
- _log_err(LOG_DEBUG, pamh,
+ pam_syslog(pamh, LOG_DEBUG,
"password - could not identify user");
return retval;
}
* getpwnam() doesn't tell you *where* the information it gives you
* came from, nor should it. That's our job.
*/
- if (_unix_comesfromsource(pamh, user, 1, 1) == 0) {
- _log_err(LOG_DEBUG, pamh,
- "user \"%s\" does not exist in /etc/passwd or NIS",
- user);
+ if (_unix_comesfromsource(pamh, user, 1, on(UNIX_NIS, ctrl)) == 0) {
+ pam_syslog(pamh, LOG_DEBUG,
+ "user \"%s\" does not exist in /etc/passwd%s",
+ user, on(UNIX_NIS, ctrl) ? " or NIS" : "");
return PAM_USER_UNKNOWN;
} else {
struct passwd *pwd;
_unix_getpwnam(pamh, user, 1, 1, &pwd);
if (pwd == NULL) {
- _log_err(LOG_DEBUG, pamh,
+ pam_syslog(pamh, LOG_DEBUG,
"user \"%s\" has corrupted passwd entry",
user);
return PAM_USER_UNKNOWN;
}
if (!_unix_shadowed(pwd) &&
(strchr(pwd->pw_passwd, '*') != NULL)) {
- _log_err(LOG_DEBUG, pamh,
+ pam_syslog(pamh, LOG_DEBUG,
"user \"%s\" does not have modifiable password",
user);
return PAM_USER_UNKNOWN;
#define greeting "Changing password for "
Announce = (char *) malloc(sizeof(greeting) + strlen(user));
if (Announce == NULL) {
- _log_err(LOG_CRIT, pamh,
+ pam_syslog(pamh, LOG_CRIT,
"password - out of memory");
return PAM_BUF_ERR;
}
set(UNIX__OLD_PASSWD, lctrl);
retval = _unix_read_password(pamh, lctrl
,Announce
- ,"(current) UNIX password: "
+ ,_("(current) UNIX password: ")
,NULL
,_UNIX_OLD_AUTHTOK
- ,(const char **) &pass_old);
+ ,&pass_old);
free(Announce);
if (retval != PAM_SUCCESS) {
- _log_err(LOG_NOTICE, pamh
- ,"password - (old) token not obtained");
+ pam_syslog(pamh, LOG_NOTICE,
+ "password - (old) token not obtained");
return retval;
}
/* verify that this is the password for this user */
retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old);
pass_old = NULL;
if (retval != PAM_SUCCESS) {
- _log_err(LOG_CRIT, pamh,
+ pam_syslog(pamh, LOG_CRIT,
"failed to set PAM_OLDAUTHTOK");
}
retval = _unix_verify_shadow(pamh,user, ctrl);
if (retval == PAM_AUTHTOK_ERR) {
if (off(UNIX__IAMROOT, ctrl))
_make_remark(pamh, ctrl, PAM_ERROR_MSG,
- "You must wait longer to change your password");
+ _("You must wait longer to change your password"));
else
retval = PAM_SUCCESS;
}
if (off(UNIX_NOT_SET_PASS, ctrl)) {
retval = pam_get_item(pamh, PAM_OLDAUTHTOK
- ,(const void **) &pass_old);
+ ,&pass_old);
} else {
retval = pam_get_data(pamh, _UNIX_OLD_AUTHTOK
- ,(const void **) &pass_old);
+ ,&pass_old);
if (retval == PAM_NO_MODULE_DATA) {
retval = PAM_SUCCESS;
pass_old = NULL;
D(("pass_old [%s]", pass_old));
if (retval != PAM_SUCCESS) {
- _log_err(LOG_NOTICE, pamh, "user not authenticated");
+ pam_syslog(pamh, LOG_NOTICE, "user not authenticated");
return retval;
}
retval = _unix_read_password(pamh, lctrl
,NULL
- ,"Enter new UNIX password: "
- ,"Retype new UNIX password: "
+ ,_("Enter new UNIX password: ")
+ ,_("Retype new UNIX password: ")
,_UNIX_NEW_AUTHTOK
- ,(const char **) &pass_new);
+ ,&pass_new);
if (retval != PAM_SUCCESS) {
if (on(UNIX_DEBUG, ctrl)) {
- _log_err(LOG_ALERT, pamh
- ,"password - new password not obtained");
+ pam_syslog(pamh, LOG_ALERT,
+ "password - new password not obtained");
}
pass_old = NULL; /* tidy up */
return retval;
* password is acceptable.
*/
- if (pass_new[0] == '\0') { /* "\0" password = NULL */
+ if (*(const char *)pass_new == '\0') { /* "\0" password = NULL */
pass_new = NULL;
}
retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new);
}
if (retval != PAM_SUCCESS) {
- _log_err(LOG_NOTICE, pamh,
+ pam_syslog(pamh, LOG_NOTICE,
"new password not acceptable");
pass_new = pass_old = NULL; /* tidy up */
return retval;
if (pass_old) {
retval = _unix_verify_password(pamh, user, pass_old, ctrl);
if (retval != PAM_SUCCESS) {
- _log_err(LOG_NOTICE, pamh, "user password changed by another process");
+ pam_syslog(pamh, LOG_NOTICE, "user password changed by another process");
#ifdef USE_LCKPWDF
ulckpwdf();
#endif
retval = _unix_verify_shadow(pamh, user, ctrl);
if (retval != PAM_SUCCESS) {
- _log_err(LOG_NOTICE, pamh, "user not authenticated 2");
+ pam_syslog(pamh, LOG_NOTICE, "user not authenticated 2");
#ifdef USE_LCKPWDF
ulckpwdf();
#endif
retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new);
if (retval != PAM_SUCCESS) {
- _log_err(LOG_NOTICE, pamh,
+ pam_syslog(pamh, LOG_NOTICE,
"new password not acceptable 2");
pass_new = pass_old = NULL; /* tidy up */
#ifdef USE_LCKPWDF
char *temp = malloc(9);
if (temp == NULL) {
- _log_err(LOG_CRIT, pamh,
+ pam_syslog(pamh, LOG_CRIT,
"out of memory for password");
pass_new = pass_old = NULL; /* tidy up */
#ifdef USE_LCKPWDF
_pam_delete(tpass);
pass_old = pass_new = NULL;
} else { /* something has broken with the module */
- _log_err(LOG_ALERT, pamh,
+ pam_syslog(pamh, LOG_ALERT,
"password received unknown request");
retval = PAM_ABORT;
}