summaryrefslogtreecommitdiff
path: root/modules/pam_pwhistory
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_pwhistory')
-rw-r--r--modules/pam_pwhistory/opasswd.c57
-rw-r--r--modules/pam_pwhistory/pam_pwhistory.8.xml4
-rw-r--r--modules/pam_pwhistory/pam_pwhistory.c21
3 files changed, 44 insertions, 38 deletions
diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c
index f045555f..738483ac 100644
--- a/modules/pam_pwhistory/opasswd.c
+++ b/modules/pam_pwhistory/opasswd.c
@@ -181,15 +181,13 @@ check_old_password (pam_handle_t *pamh, const char *user,
fclose (oldpf);
- if (found)
+ if (found && entry.old_passwords)
{
const char delimiters[] = ",";
char *running;
char *oldpass;
- running = strdupa (entry.old_passwords);
- if (running == NULL)
- return PAM_BUF_ERR;
+ running = entry.old_passwords;
do {
oldpass = strsep (&running, delimiters);
@@ -311,8 +309,12 @@ save_old_password (pam_handle_t *pamh, const char *user, uid_t uid,
buflen = DEFAULT_BUFLEN;
buf = malloc (buflen);
if (buf == NULL)
- return PAM_BUF_ERR;
-
+ {
+ fclose (oldpf);
+ fclose (newpf);
+ retval = PAM_BUF_ERR;
+ goto error_opasswd;
+ }
}
buf[0] = '\0';
fgets (buf, buflen - 1, oldpf);
@@ -322,7 +324,12 @@ save_old_password (pam_handle_t *pamh, const char *user, uid_t uid,
cp = buf;
save = strdup (buf); /* Copy to write the original data back. */
if (save == NULL)
- return PAM_BUF_ERR;
+ {
+ fclose (oldpf);
+ fclose (newpf);
+ retval = PAM_BUF_ERR;
+ goto error_opasswd;
+ }
if (n < 1)
break;
@@ -351,31 +358,30 @@ save_old_password (pam_handle_t *pamh, const char *user, uid_t uid,
found = 1;
/* Don't save the current password twice */
- if (entry.old_passwords)
+ if (entry.old_passwords && entry.old_passwords[0] != '\0')
{
- /* there is only one password */
- if (strcmp (entry.old_passwords, oldpass) == 0)
- goto write_old_data;
- else
+ char *last = entry.old_passwords;
+
+ cp = entry.old_passwords;
+ entry.count = 1; /* Don't believe the count */
+ while ((cp = strchr (cp, ',')) != NULL)
{
- /* check last entry */
- cp = strstr (entry.old_passwords, oldpass);
-
- if (cp && strcmp (cp, oldpass) == 0)
- { /* the end is the same, check that there
- is a "," before. */
- --cp;
- if (*cp == ',')
- goto write_old_data;
- }
+ entry.count++;
+ last = ++cp;
}
+
+ /* compare the last password */
+ if (strcmp (last, oldpass) == 0)
+ goto write_old_data;
}
+ else
+ entry.count = 0;
/* increase count. */
entry.count++;
/* check that we don't remember to many passwords. */
- while (entry.count > howmany)
+ while (entry.count > howmany && entry.count > 1)
{
char *p = strpbrk (entry.old_passwords, ",");
if (p != NULL)
@@ -383,12 +389,13 @@ save_old_password (pam_handle_t *pamh, const char *user, uid_t uid,
entry.count--;
}
- if (entry.old_passwords == NULL)
+ if (entry.count == 1)
{
if (asprintf (&out, "%s:%s:%d:%s\n",
entry.user, entry.uid, entry.count,
oldpass) < 0)
{
+ free (save);
retval = PAM_AUTHTOK_ERR;
fclose (oldpf);
fclose (newpf);
@@ -401,6 +408,7 @@ save_old_password (pam_handle_t *pamh, const char *user, uid_t uid,
entry.user, entry.uid, entry.count,
entry.old_passwords, oldpass) < 0)
{
+ free (save);
retval = PAM_AUTHTOK_ERR;
fclose (oldpf);
fclose (newpf);
@@ -493,6 +501,7 @@ save_old_password (pam_handle_t *pamh, const char *user, uid_t uid,
rename (opasswd_tmp, OLD_PASSWORDS_FILE);
error_opasswd:
unlink (opasswd_tmp);
+ free (buf);
return retval;
}
diff --git a/modules/pam_pwhistory/pam_pwhistory.8.xml b/modules/pam_pwhistory/pam_pwhistory.8.xml
index 7696353f..9e1056b2 100644
--- a/modules/pam_pwhistory/pam_pwhistory.8.xml
+++ b/modules/pam_pwhistory/pam_pwhistory.8.xml
@@ -105,7 +105,9 @@
<para>
The last <replaceable>N</replaceable> passwords for each
user are saved in <filename>/etc/security/opasswd</filename>.
- The default is <emphasis>10</emphasis>.
+ The default is <emphasis>10</emphasis>. Value of
+ <emphasis>0</emphasis> makes the module to keep the existing
+ contents of the <filename>opasswd</filename> file unchanged.
</para>
</listitem>
</varlistentry>
diff --git a/modules/pam_pwhistory/pam_pwhistory.c b/modules/pam_pwhistory/pam_pwhistory.c
index 0f6ffca3..9b588958 100644
--- a/modules/pam_pwhistory/pam_pwhistory.c
+++ b/modules/pam_pwhistory/pam_pwhistory.c
@@ -187,12 +187,13 @@ pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv)
{
retval = pam_get_authtok (pamh, PAM_AUTHTOK, &newpass, NULL);
if (retval != PAM_SUCCESS && retval != PAM_TRY_AGAIN)
- return retval;
+ {
+ if (retval == PAM_CONV_AGAIN)
+ retval = PAM_INCOMPLETE;
+ return retval;
+ }
tries++;
- if (newpass == NULL || retval == PAM_TRY_AGAIN)
- continue;
-
if (options.debug)
{
if (newpass)
@@ -201,12 +202,8 @@ pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv)
pam_syslog (pamh, LOG_DEBUG, "got no auth token");
}
- if (retval != PAM_SUCCESS || newpass == NULL)
- {
- if (retval == PAM_CONV_AGAIN)
- retval = PAM_INCOMPLETE;
- return retval;
- }
+ if (newpass == NULL || retval == PAM_TRY_AGAIN)
+ continue;
if (options.debug)
pam_syslog (pamh, LOG_DEBUG, "check against old password file");
@@ -219,7 +216,6 @@ pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv)
newpass = NULL;
/* Remove password item, else following module will use it */
pam_set_item (pamh, PAM_AUTHTOK, (void *) NULL);
- continue;
}
}
@@ -230,8 +226,7 @@ pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv)
return PAM_MAXTRIES;
}
- /* Remember new password */
- return pam_set_item (pamh, PAM_AUTHTOK, newpass);
+ return PAM_SUCCESS;
}