summaryrefslogtreecommitdiff
path: root/modules/pam_unix
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_unix')
-rw-r--r--modules/pam_unix/pam_unix.8.xml7
-rw-r--r--modules/pam_unix/support.c106
-rw-r--r--modules/pam_unix/support.h63
3 files changed, 146 insertions, 30 deletions
diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml
index 0a42d7a3..9ce084e3 100644
--- a/modules/pam_unix/pam_unix.8.xml
+++ b/modules/pam_unix/pam_unix.8.xml
@@ -81,7 +81,9 @@
<para>
The password component of this module performs the task of updating
- the user's password.
+ the user's password. The default encryption hash is taken from the
+ <emphasis remap='B'>ENCRYPT_METHOD</emphasis> variable from
+ <emphasis>/etc/login.defs</emphasis>
</para>
<para>
@@ -393,6 +395,9 @@ session required pam_unix.so
<title>SEE ALSO</title>
<para>
<citerefentry>
+ <refentrytitle>login.defs</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citerefentry>
<refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
</citerefentry>,
<citerefentry>
diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c
index ab04535f..f36786e4 100644
--- a/modules/pam_unix/support.c
+++ b/modules/pam_unix/support.c
@@ -37,6 +37,80 @@
#define SELINUX_ENABLED 0
#endif
+static char *
+search_key (const char *key, const char *filename)
+{
+ FILE *fp;
+ char *buf = NULL;
+ size_t buflen = 0;
+ char *retval = NULL;
+
+ fp = fopen (filename, "r");
+ if (NULL == fp)
+ return NULL;
+
+ while (!feof (fp))
+ {
+ char *tmp, *cp;
+#if defined(HAVE_GETLINE)
+ ssize_t n = getline (&buf, &buflen, fp);
+#elif defined (HAVE_GETDELIM)
+ ssize_t n = getdelim (&buf, &buflen, '\n', fp);
+#else
+ ssize_t n;
+
+ if (buf == NULL)
+ {
+ buflen = BUF_SIZE;
+ buf = malloc (buflen);
+ if (buf == NULL) {
+ fclose (fp);
+ return NULL;
+ }
+ }
+ buf[0] = '\0';
+ if (fgets (buf, buflen - 1, fp) == NULL)
+ break;
+ else if (buf != NULL)
+ n = strlen (buf);
+ else
+ n = 0;
+#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 */
+ continue;
+
+ if (cp[strlen (cp) - 1] == '\n')
+ cp[strlen (cp) - 1] = '\0';
+
+ tmp = strsep (&cp, " \t=");
+ if (cp != NULL)
+ while (isspace ((int)*cp) || *cp == '=')
+ ++cp;
+
+ if (strcasecmp (tmp, key) == 0)
+ {
+ retval = strdup (cp);
+ break;
+ }
+ }
+ fclose (fp);
+
+ free (buf);
+
+ return retval;
+}
+
+
/* this is a front-end for module-application conversations */
int _make_remark(pam_handle_t * pamh, unsigned int ctrl,
@@ -58,6 +132,8 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds,
int *pass_min_len, int argc, const char **argv)
{
unsigned int ctrl;
+ char *val;
+ int j;
D(("called."));
@@ -81,10 +157,38 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds,
D(("SILENT"));
set(UNIX__QUIET, ctrl);
}
+
+ /* preset encryption method with value from /etc/login.defs */
+ val = search_key ("ENCRYPT_METHOD", LOGIN_DEFS);
+ if (val) {
+ for (j = 0; j < UNIX_CTRLS_; ++j) {
+ if (unix_args[j].token && unix_args[j].is_hash_algo
+ && !strncasecmp(val, unix_args[j].token, strlen(unix_args[j].token))) {
+ break;
+ }
+ }
+ if (j >= UNIX_CTRLS_) {
+ pam_syslog(pamh, LOG_WARNING, "unrecognized ENCRYPT_METHOD value [%s]", val);
+ } else {
+ ctrl &= unix_args[j].mask; /* for turning things off */
+ ctrl |= unix_args[j].flag; /* for turning things on */
+ }
+ free (val);
+
+ /* read number of rounds for crypt algo */
+ if (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl)) {
+ val=search_key ("SHA_CRYPT_MAX_ROUNDS", LOGIN_DEFS);
+
+ if (val) {
+ *rounds = strtol(val, NULL, 10);
+ free (val);
+ }
+ }
+ }
+
/* now parse the arguments to this module */
for (; argc-- > 0; ++argv) {
- int j;
D(("pam_unix arg: %s", *argv));
diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h
index db4cd953..65759384 100644
--- a/modules/pam_unix/support.h
+++ b/modules/pam_unix/support.h
@@ -8,6 +8,12 @@
#include <pwd.h>
/*
+ * File to read value of ENCRYPT_METHOD from.
+ */
+#define LOGIN_DEFS "/etc/login.defs"
+
+
+/*
* here is the string to inform the user that the new passwords they
* typed were not the same.
*/
@@ -20,6 +26,7 @@ typedef struct {
const char *token;
unsigned int mask; /* shall assume 32 bits of flags */
unsigned int flag;
+ unsigned int is_hash_algo;
} UNIX_Ctrls;
/*
@@ -100,34 +107,34 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
/* symbol token name ctrl mask ctrl *
* ----------------------- ------------------- --------------------- -------- */
-/* UNIX__OLD_PASSWD */ {NULL, _ALL_ON_, 01},
-/* UNIX__VERIFY_PASSWD */ {NULL, _ALL_ON_, 02},
-/* UNIX__IAMROOT */ {NULL, _ALL_ON_, 04},
-/* UNIX_AUDIT */ {"audit", _ALL_ON_, 010},
-/* UNIX_USE_FIRST_PASS */ {"use_first_pass", _ALL_ON_^(060), 020},
-/* UNIX_TRY_FIRST_PASS */ {"try_first_pass", _ALL_ON_^(060), 040},
-/* UNIX_NOT_SET_PASS */ {"not_set_pass", _ALL_ON_, 0100},
-/* UNIX__PRELIM */ {NULL, _ALL_ON_^(0600), 0200},
-/* UNIX__UPDATE */ {NULL, _ALL_ON_^(0600), 0400},
-/* UNIX__NONULL */ {NULL, _ALL_ON_, 01000},
-/* UNIX__QUIET */ {NULL, _ALL_ON_, 02000},
-/* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000},
-/* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000},
-/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(0260420000), 020000},
-/* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000), 0},
-/* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000},
-/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000},
-/* UNIX_NIS */ {"nis", _ALL_ON_, 0200000},
-/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(0260420000), 0400000},
-/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000},
-/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000},
-/* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000},
-/* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000},
-/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(0260420000), 020000000},
-/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(0260420000), 040000000},
-/* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000},
-/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(0260420000), 0200000000},
-/* UNIX_MIN_PASS_LEN */ {"minlen=", _ALL_ON_, 0400000000},
+/* UNIX__OLD_PASSWD */ {NULL, _ALL_ON_, 01, 0},
+/* UNIX__VERIFY_PASSWD */ {NULL, _ALL_ON_, 02, 0},
+/* UNIX__IAMROOT */ {NULL, _ALL_ON_, 04, 0},
+/* UNIX_AUDIT */ {"audit", _ALL_ON_, 010, 0},
+/* UNIX_USE_FIRST_PASS */ {"use_first_pass", _ALL_ON_^(060), 020, 0},
+/* UNIX_TRY_FIRST_PASS */ {"try_first_pass", _ALL_ON_^(060), 040, 0},
+/* UNIX_NOT_SET_PASS */ {"not_set_pass", _ALL_ON_, 0100, 0},
+/* UNIX__PRELIM */ {NULL, _ALL_ON_^(0600), 0200, 0},
+/* UNIX__UPDATE */ {NULL, _ALL_ON_^(0600), 0400, 0},
+/* UNIX__NONULL */ {NULL, _ALL_ON_, 01000, 0},
+/* UNIX__QUIET */ {NULL, _ALL_ON_, 02000, 0},
+/* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000, 0},
+/* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000, 0},
+/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(0260420000), 020000, 1},
+/* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000), 0, 0},
+/* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000, 0},
+/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000, 0},
+/* UNIX_NIS */ {"nis", _ALL_ON_, 0200000, 0},
+/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(0260420000), 0400000, 1},
+/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000, 0},
+/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000, 0},
+/* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000, 0},
+/* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000, 0},
+/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(0260420000), 020000000, 1},
+/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(0260420000), 040000000, 1},
+/* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000, 0},
+/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(0260420000), 0200000000, 1},
+/* UNIX_MIN_PASS_LEN */ {"minlen=", _ALL_ON_, 0400000000, 0},
};
#define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag)