Hi,
I find it very disturbing, that you need to manual maintain the used encryption hash in /etc/login.defs for shadow and as pam_unix.so argument. Since we have already two modules reading /etc/login.defs, I made a small change to pam_unix.so:
The default encryption hash is taken from /etc/login.defs and can be overwritten with the pam_unix.so argument. If there is no entry in /etc/login.defs and no argument DES is still the default.
So this change should be pretty backward compatible.
Any opinions? Most of the code is from the other PAM modules, maybe we should add the /etc/login.defs parsing functions to libpam itself sometimes.
2013-02-05 Thorsten Kukuk kukuk@thkukuk.de
Use hash from /etc/login.defs as default if no other one is specified as argument.
* modules/pam_unix/support.c: Add search_key, call from __set_ctrl * modules/pam_unix/support.h: Add define for /etc/login.defs * modules/pam_unix/pam_unix.8.xml: Document new behavior.
--- modules/pam_unix/support.c +++ modules/pam_unix/support.c @@ -37,6 +37,76 @@ #define SELINUX_ENABLED 0 #endif
+static char * +search_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); + } + 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, "ENCRYPT_METHOD") == 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 +128,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 +153,27 @@ 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 (LOGIN_DEFS); + if (val) { + for (j = 0; j < UNIX_CTRLS_; ++j) { + if (unix_args[j].token + && !strncasecmp(val, unix_args[j].token, strlen(unix_args[j].token))) { + break; + } + } + if (j >= UNIX_CTRLS_) { + pam_syslog(pamh, LOG_WARNING, "unrecognized ENCRYPTION_METHOD value [%s]", val); + } else { + ctrl &= unix_args[j].mask; /* for turning things off */ + ctrl |= unix_args[j].flag; /* for turning things on */ + } + } + /* now parse the arguments to this module */
for (; argc-- > 0; ++argv) { - int j;
D(("pam_unix arg: %s", *argv));
--- modules/pam_unix/support.h +++ 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. */ --- modules/pam_unix/pam_unix.8.xml +++ 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'>ENCYPTION_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>