aboutsummaryrefslogtreecommitdiff
path: root/modules/pam_pwhistory/opasswd.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_pwhistory/opasswd.c')
-rw-r--r--modules/pam_pwhistory/opasswd.c168
1 files changed, 70 insertions, 98 deletions
diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c
index 859b3da4..512688d1 100644
--- a/modules/pam_pwhistory/opasswd.c
+++ b/modules/pam_pwhistory/opasswd.c
@@ -34,9 +34,7 @@
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#if defined(HAVE_CONFIG_H)
#include <config.h>
-#endif
#include <pwd.h>
#include <shadow.h>
@@ -76,9 +74,7 @@
#define RANDOM_DEVICE "/dev/urandom"
#endif
-#define DEFAULT_OLD_PASSWORDS_FILE SCONFIGDIR "/opasswd"
-
-#define DEFAULT_BUFLEN 4096
+#define DEFAULT_OLD_PASSWORDS_FILE SCONFIG_DIR "/opasswd"
typedef struct {
char *user;
@@ -88,7 +84,6 @@ typedef struct {
} opwd;
#ifdef HELPER_COMPILE
-PAM_FORMAT((printf, 2, 3))
void
helper_log_err(int err, const char *format, ...)
{
@@ -124,23 +119,32 @@ parse_entry (char *line, opwd *data)
return 0;
}
+/* Return 1 if the passwords are equal, 0 if they are not, and -1 on error. */
static int
compare_password(const char *newpass, const char *oldpass)
{
char *outval;
-#ifdef HAVE_CRYPT_R
- struct crypt_data output;
int retval;
+#ifdef HAVE_CRYPT_R
+ struct crypt_data *cdata;
- output.initialized = 0;
+ cdata = calloc(1, sizeof(*cdata));
+ if (!cdata)
+ return -1;
- outval = crypt_r (newpass, oldpass, &output);
+ outval = crypt_r (newpass, oldpass, cdata);
#else
outval = crypt (newpass, oldpass);
#endif
retval = outval != NULL && strcmp(outval, oldpass) == 0;
+
+#ifdef HAVE_CRYPT_R
+ pam_overwrite_object(cdata);
+ free(cdata);
+#else
pam_overwrite_string(outval);
+#endif
return retval;
}
@@ -172,46 +176,20 @@ check_old_pass, const char *user, const char *newpass, const char *filename, int
while (!feof (oldpf))
{
- char *cp, *tmp;
-#if defined(HAVE_GETLINE)
ssize_t n = getline (&buf, &buflen, oldpf);
-#elif defined (HAVE_GETDELIM)
- ssize_t n = getdelim (&buf, &buflen, '\n', oldpf);
-#else
- ssize_t n;
-
- if (buf == NULL)
- {
- buflen = DEFAULT_BUFLEN;
- buf = malloc (buflen);
- if (buf == NULL)
- return PAM_BUF_ERR;
- }
- buf[0] = '\0';
- fgets (buf, buflen - 1, oldpf);
- n = strlen (buf);
-#endif /* HAVE_GETLINE / HAVE_GETDELIM */
- cp = buf;
if (n < 1)
break;
- tmp = strchr (cp, '#'); /* remove comments */
- if (tmp)
- *tmp = '\0';
- while (isspace ((int)*cp)) /* remove spaces and tabs */
- ++cp;
- if (*cp == '\0') /* ignore empty lines */
+ buf[strcspn(buf, "\n")] = '\0';
+ if (buf[0] == '\0') /* ignore empty lines */
continue;
- if (cp[strlen (cp) - 1] == '\n')
- cp[strlen (cp) - 1] = '\0';
-
- if (strncmp (cp, user, strlen (user)) == 0 &&
- cp[strlen (user)] == ':')
+ if (strncmp (buf, user, strlen (user)) == 0 &&
+ buf[strlen (user)] == ':')
{
/* We found the line we needed */
- if (parse_entry (cp, &entry) == 0)
+ if (parse_entry (buf, &entry) == 0)
{
found = 1;
break;
@@ -231,13 +209,19 @@ check_old_pass, const char *user, const char *newpass, const char *filename, int
do {
oldpass = strsep (&running, delimiters);
- if (oldpass && strlen (oldpass) > 0 &&
- compare_password(newpass, oldpass) )
- {
- if (debug)
- pam_syslog (pamh, LOG_DEBUG, "New password already used");
- retval = PAM_AUTHTOK_ERR;
- break;
+ if (oldpass && strlen (oldpass) > 0) {
+ int rc;
+
+ rc = compare_password(newpass, oldpass);
+ if (rc) {
+ if (rc < 0)
+ pam_syslog (pamh, LOG_ERR, "Cannot allocate crypt data");
+ else if (debug)
+ pam_syslog (pamh, LOG_DEBUG, "New password already used");
+
+ retval = PAM_AUTHTOK_ERR;
+ break;
+ }
}
} while (oldpass != NULL);
}
@@ -265,22 +249,30 @@ save_old_pass, const char *user, int howmany, const char *filename, int debug UN
/* Define opasswd file and temp file for opasswd */
const char *opasswd_file =
(filename != NULL ? filename : DEFAULT_OLD_PASSWORDS_FILE);
- char opasswd_tmp[PATH_MAX];
+ char *opasswd_tmp;
- if ((size_t) snprintf (opasswd_tmp, sizeof (opasswd_tmp), "%s.tmpXXXXXX",
- opasswd_file) >= sizeof (opasswd_tmp))
+ if (asprintf (&opasswd_tmp, "%s.tmpXXXXXX", opasswd_file) < 0)
return PAM_BUF_ERR;
pwd = pam_modutil_getpwnam (pamh, user);
if (pwd == NULL)
- return PAM_USER_UNKNOWN;
+ {
+ free (opasswd_tmp);
+ return PAM_USER_UNKNOWN;
+ }
if (howmany <= 0)
- return PAM_SUCCESS;
+ {
+ free (opasswd_tmp);
+ return PAM_SUCCESS;
+ }
#ifndef HELPER_COMPILE
if (SELINUX_ENABLED)
- return PAM_PWHISTORY_RUN_HELPER;
+ {
+ free (opasswd_tmp);
+ return PAM_PWHISTORY_RUN_HELPER;
+ }
#endif
if ((strcmp(pwd->pw_passwd, "x") == 0) ||
@@ -291,14 +283,20 @@ save_old_pass, const char *user, int howmany, const char *filename, int debug UN
struct spwd *spw = pam_modutil_getspnam (pamh, user);
if (spw == NULL)
- return PAM_USER_UNKNOWN;
+ {
+ free (opasswd_tmp);
+ return PAM_USER_UNKNOWN;
+ }
oldpass = spw->sp_pwdp;
}
else
oldpass = pwd->pw_passwd;
if (oldpass == NULL || *oldpass == '\0')
- return PAM_SUCCESS;
+ {
+ free (opasswd_tmp);
+ return PAM_SUCCESS;
+ }
if ((oldpf = fopen (opasswd_file, "r")) == NULL)
{
@@ -310,6 +308,7 @@ save_old_pass, const char *user, int howmany, const char *filename, int debug UN
else
{
pam_syslog (pamh, LOG_ERR, "Cannot open %s: %m", opasswd_file);
+ free (opasswd_tmp);
return PAM_AUTHTOK_ERR;
}
}
@@ -317,6 +316,7 @@ save_old_pass, const char *user, int howmany, const char *filename, int debug UN
{
pam_syslog (pamh, LOG_ERR, "Cannot stat %s: %m", opasswd_file);
fclose (oldpf);
+ free (opasswd_tmp);
return PAM_AUTHTOK_ERR;
}
@@ -328,6 +328,7 @@ save_old_pass, const char *user, int howmany, const char *filename, int debug UN
opasswd_file);
if (oldpf)
fclose (oldpf);
+ free (opasswd_tmp);
return PAM_AUTHTOK_ERR;
}
if (do_create)
@@ -362,35 +363,12 @@ save_old_pass, const char *user, int howmany, const char *filename, int debug UN
if (!do_create)
while (!feof (oldpf))
{
- char *cp, *tmp, *save;
-#if defined(HAVE_GETLINE)
+ char *save;
ssize_t n = getline (&buf, &buflen, oldpf);
-#elif defined (HAVE_GETDELIM)
- ssize_t n = getdelim (&buf, &buflen, '\n', oldpf);
-#else
- ssize_t n;
-
- if (buf == NULL)
- {
- buflen = DEFAULT_BUFLEN;
- buf = malloc (buflen);
- if (buf == NULL)
- {
- fclose (oldpf);
- fclose (newpf);
- retval = PAM_BUF_ERR;
- goto error_opasswd;
- }
- }
- buf[0] = '\0';
- fgets (buf, buflen - 1, oldpf);
- n = strlen (buf);
-#endif /* HAVE_GETLINE / HAVE_GETDELIM */
if (n < 1)
break;
- cp = buf;
save = strdup (buf); /* Copy to write the original data back. */
if (save == NULL)
{
@@ -400,24 +378,17 @@ save_old_pass, const char *user, int howmany, const char *filename, int debug UN
goto error_opasswd;
}
- tmp = strchr (cp, '#'); /* remove comments */
- if (tmp)
- *tmp = '\0';
- while (isspace ((int)*cp)) /* remove spaces and tabs */
- ++cp;
- if (*cp == '\0') /* ignore empty lines */
+ buf[strcspn(buf, "\n")] = '\0';
+ if (buf[0] == '\0') /* ignore empty lines */
goto write_old_data;
- if (cp[strlen (cp) - 1] == '\n')
- cp[strlen (cp) - 1] = '\0';
-
- if (strncmp (cp, user, strlen (user)) == 0 &&
- cp[strlen (user)] == ':')
+ if (strncmp (buf, user, strlen (user)) == 0 &&
+ buf[strlen (user)] == ':')
{
/* We found the line we needed */
opwd entry;
- if (parse_entry (cp, &entry) == 0)
+ if (parse_entry (buf, &entry) == 0)
{
char *out = NULL;
@@ -426,9 +397,9 @@ save_old_pass, const char *user, int howmany, const char *filename, int debug UN
/* Don't save the current password twice */
if (entry.old_passwords && entry.old_passwords[0] != '\0')
{
- char *last = entry.old_passwords;
+ char *cp = entry.old_passwords;
+ char *last = cp;
- cp = entry.old_passwords;
entry.count = 1; /* Don't believe the count */
while ((cp = strchr (cp, ',')) != NULL)
{
@@ -446,7 +417,7 @@ save_old_pass, const char *user, int howmany, const char *filename, int debug UN
/* increase count. */
entry.count++;
- /* check that we don't remember to many passwords. */
+ /* check that we don't remember too many passwords. */
while (entry.count > howmany && entry.count > 1)
{
char *p = strpbrk (entry.old_passwords, ",");
@@ -561,9 +532,8 @@ save_old_pass, const char *user, int howmany, const char *filename, int debug UN
goto error_opasswd;
}
- char opasswd_backup[PATH_MAX];
- if ((size_t) snprintf (opasswd_backup, sizeof (opasswd_backup), "%s.old",
- opasswd_file) >= sizeof (opasswd_backup))
+ char *opasswd_backup;
+ if (asprintf (&opasswd_backup, "%s.old", opasswd_file) < 0)
{
retval = PAM_BUF_ERR;
goto error_opasswd;
@@ -575,8 +545,10 @@ save_old_pass, const char *user, int howmany, const char *filename, int debug UN
pam_syslog (pamh, LOG_ERR, "Cannot create backup file of %s: %m",
opasswd_file);
rename (opasswd_tmp, opasswd_file);
+ free (opasswd_backup);
error_opasswd:
unlink (opasswd_tmp);
+ free (opasswd_tmp);
pam_overwrite_n(buf, buflen);
free (buf);