summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThorsten Kukuk <kukuk@thkukuk.de>2008-12-01 12:40:40 +0000
committerThorsten Kukuk <kukuk@thkukuk.de>2008-12-01 12:40:40 +0000
commit090693e116fc6ea0dfb649e11a01af08e19b33d9 (patch)
tree1d3cde1416515bc7136e604d58e96e90caa510be
parent1395ff30321ce605ab2ca79b1301cd93f51a5ca1 (diff)
Relevant BUGIDs:
Purpose of commit: new feature Commit summary: --------------- 2008-12-01 Thorsten Kukuk <kukuk@thkukuk.de> * modules/pam_unix/pam_unix.8.xml: Document blowfish option. * configure.in: Check for crypt_gensalt_rn. * modules/pam_unix/pam_unix_passwd.c: Pass pamh to create_password_hash function. * modules/pam_unix/passverify.c (create_password_hash): Add blowfish support. * modules/pam_unix/passverify.h: Adjust create_password_hash prototype. * modules/pam_unix/support.c: Add support for blowfish option. * modules/pam_unix/support.h: Add defines for blowfish option. Patch from Diego Flameeyes Pettenò <flameeyes@gmail.com>
-rw-r--r--ChangeLog15
-rw-r--r--NEWS1
-rw-r--r--configure.in2
-rw-r--r--modules/pam_unix/pam_unix.8.xml28
-rw-r--r--modules/pam_unix/pam_unix_passwd.c2
-rw-r--r--modules/pam_unix/passverify.c107
-rw-r--r--modules/pam_unix/passverify.h51
-rw-r--r--modules/pam_unix/support.c32
-rw-r--r--modules/pam_unix/support.h4
9 files changed, 130 insertions, 112 deletions
diff --git a/ChangeLog b/ChangeLog
index 5f452a1b..fb585bcd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2008-12-01 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * modules/pam_unix/pam_unix.8.xml: Document blowfish option.
+
+ * configure.in: Check for crypt_gensalt_rn.
+ * modules/pam_unix/pam_unix_passwd.c: Pass pamh to
+ create_password_hash function.
+ * modules/pam_unix/passverify.c (create_password_hash): Add
+ blowfish support.
+ * modules/pam_unix/passverify.h: Adjust create_password_hash
+ prototype.
+ * modules/pam_unix/support.c: Add support for blowfish option.
+ * modules/pam_unix/support.h: Add defines for blowfish option.
+ Patch from Diego Flameeyes Pettenò <flameeyes@gmail.com>
+
2008-12-01 Tomas Mraz <t8m@centrum.cz>
* modules/pam_access/pam_access.8.xml: Fix description of nodefgroup
diff --git a/NEWS b/NEWS
index e3f5623c..a480eeb1 100644
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,7 @@ Release 1.0.90
* Make libpam not log missing module if its type is prepended with '-'
* New pam_timestamp module for authentication based on recent successful
login.
+* Add blowfish support to pam_unix.
Release 1.0.2
diff --git a/configure.in b/configure.in
index e16bd44f..ff14401c 100644
--- a/configure.in
+++ b/configure.in
@@ -363,7 +363,7 @@ AM_CONDITIONAL([HAVE_AUDIT_TTY_STATUS],
AC_CHECK_HEADERS(xcrypt.h crypt.h)
BACKUP_LIBS=$LIBS
AC_SEARCH_LIBS([crypt],[xcrypt crypt], LIBCRYPT="-l$ac_lib", LIBCRYPT="")
-AC_CHECK_FUNCS(crypt_r)
+AC_CHECK_FUNCS(crypt_r crypt_gensalt_rn)
LIBS=$BACKUP_LIBS
AC_SUBST(LIBCRYPT)
if test "$LIBCRYPT" = "-lxcrypt" -a "$ac_cv_header_xcrypt_h" = "yes" ; then
diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml
index e08edfcc..cc3affd9 100644
--- a/modules/pam_unix/pam_unix.8.xml
+++ b/modules/pam_unix/pam_unix.8.xml
@@ -266,7 +266,9 @@
<para>
When a user changes their password next,
encrypt it with the SHA256 algorithm. If the
- SHA256 algorithm is not known to the libcrypt,
+ SHA256 algorithm is not known to the <citerefentry>
+ <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry> function,
fall back to MD5.
</para>
</listitem>
@@ -279,7 +281,24 @@
<para>
When a user changes their password next,
encrypt it with the SHA512 algorithm. If the
- SHA512 algorithm is not known to the libcrypt,
+ SHA512 algorithm is not known to the <citerefentry>
+ <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry> function,
+ fall back to MD5.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <option>blowfish</option>
+ </term>
+ <listitem>
+ <para>
+ When a user changes their password next,
+ encrypt it with the blowfish algorithm. If the
+ SHA512 algorithm is not known to the <citerefentry>
+ <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry> function,
fall back to MD5.
</para>
</listitem>
@@ -290,8 +309,9 @@
</term>
<listitem>
<para>
- Set the optional number of rounds of the SHA256 and SHA512
- password hashing algorithms to <replaceable>n</replaceable>.
+ Set the optional number of rounds of the SHA256, SHA512
+ and blowfish password hashing algorithms to
+ <replaceable>n</replaceable>.
</para>
</listitem>
</varlistentry>
diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c
index 240caddb..b8da9913 100644
--- a/modules/pam_unix/pam_unix_passwd.c
+++ b/modules/pam_unix/pam_unix_passwd.c
@@ -749,7 +749,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
* First we encrypt the new password.
*/
- tpass = create_password_hash(pass_new, ctrl, rounds);
+ tpass = create_password_hash(pamh, pass_new, ctrl, rounds);
if (tpass == NULL) {
pam_syslog(pamh, LOG_CRIT,
"out of memory for password");
diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
index eae1e24c..281716e0 100644
--- a/modules/pam_unix/passverify.c
+++ b/modules/pam_unix/passverify.c
@@ -151,15 +151,8 @@ is_pwd_shadowed(const struct passwd *pwd)
return 0;
}
-#ifdef HELPER_COMPILE
-int
-get_account_info(const char *name,
- struct passwd **pwd, struct spwd **spwdent)
-#else
-int
-get_account_info(pam_handle_t *pamh, const char *name,
- struct passwd **pwd, struct spwd **spwdent)
-#endif
+PAMH_ARG_DECL(int get_account_info,
+ const char *name, struct passwd **pwd, struct spwd **spwdent)
{
/* UNIX passwords area */
*pwd = pam_modutil_getpwnam(pamh, name); /* Get password file entry... */
@@ -219,24 +212,13 @@ get_account_info(pam_handle_t *pamh, const char *name,
return PAM_SUCCESS;
}
-#ifdef HELPER_COMPILE
-int
-get_pwd_hash(const char *name,
- struct passwd **pwd, char **hash)
-#else
-int
-get_pwd_hash(pam_handle_t *pamh, const char *name,
- struct passwd **pwd, char **hash)
-#endif
+PAMH_ARG_DECL(int get_pwd_hash,
+ const char *name, struct passwd **pwd, char **hash)
{
int retval;
struct spwd *spwdent = NULL;
-#ifdef HELPER_COMPILE
- retval = get_account_info(name, pwd, &spwdent);
-#else
- retval = get_account_info(pamh, name, pwd, &spwdent);
-#endif
+ retval = get_account_info(PAMH_ARG(name, pwd, &spwdent));
if (retval != PAM_SUCCESS) {
return retval;
}
@@ -251,13 +233,8 @@ get_pwd_hash(pam_handle_t *pamh, const char *name,
return PAM_SUCCESS;
}
-#ifdef HELPER_COMPILE
-int
-check_shadow_expiry(struct spwd *spent, int *daysleft)
-#else
-int
-check_shadow_expiry(pam_handle_t *pamh, struct spwd *spent, int *daysleft)
-#endif
+PAMH_ARG_DECL(int check_shadow_expiry,
+ struct spwd *spent, int *daysleft)
{
long int curdays;
*daysleft = -1;
@@ -386,17 +363,19 @@ crypt_md5_wrapper(const char *pass_new)
return cp;
}
-char *
-create_password_hash(const char *password, unsigned int ctrl, int rounds)
+PAMH_ARG_DECL(char * create_password_hash,
+ const char *password, unsigned int ctrl, int rounds)
{
const char *algoid;
char salt[64]; /* contains rounds number + max 16 bytes of salt + algo id */
char *sp;
if (on(UNIX_MD5_PASS, ctrl)) {
+ /* algoid = "$1" */
return crypt_md5_wrapper(password);
- }
- if (on(UNIX_SHA256_PASS, ctrl)) {
+ } else if (on(UNIX_BLOWFISH_PASS, ctrl)) {
+ algoid = "$2a$";
+ } else if (on(UNIX_SHA256_PASS, ctrl)) {
algoid = "$5$";
} else if (on(UNIX_SHA512_PASS, ctrl)) {
algoid = "$6$";
@@ -416,17 +395,35 @@ create_password_hash(const char *password, unsigned int ctrl, int rounds)
return crypted;
}
- sp = stpcpy(salt, algoid);
- if (on(UNIX_ALGO_ROUNDS, ctrl)) {
- sp += snprintf(sp, sizeof(salt) - 3, "rounds=%u$", rounds);
+#ifdef HAVE_CRYPT_GENSALT_RN
+ if (on(UNIX_BLOWFISH_PASS, ctrl)) {
+ char entropy[17];
+ crypt_make_salt(entropy, sizeof(entropy) - 1);
+ sp = crypt_gensalt_rn(algoid, rounds,
+ entropy, sizeof(entropy),
+ salt, sizeof(salt));
+ } else {
+#endif
+ sp = stpcpy(salt, algoid);
+ if (on(UNIX_ALGO_ROUNDS, ctrl)) {
+ sp += snprintf(sp, sizeof(salt) - 3, "rounds=%u$", rounds);
+ }
+ crypt_make_salt(sp, 8);
+ /* For now be conservative so the resulting hashes
+ * are not too long. 8 bytes of salt prevents dictionary
+ * attacks well enough. */
+#ifdef HAVE_CRYPT_GENSALT_RN
}
- crypt_make_salt(sp, 8);
- /* For now be conservative so the resulting hashes
- * are not too long. 8 bytes of salt prevents dictionary
- * attacks well enough. */
+#endif
sp = crypt(password, salt);
if (strncmp(algoid, sp, strlen(algoid)) != 0) {
- /* libc doesn't know the algorithm, use MD5 */
+ /* libxcrypt/libc doesn't know the algorithm, use MD5 */
+ pam_syslog(pamh, LOG_ERR,
+ "Algo %s not supported by the crypto backend, "
+ "falling back to MD5\n",
+ on(UNIX_BLOWFISH_PASS, ctrl) ? "blowfish" :
+ on(UNIX_SHA256_PASS, ctrl) ? "sha256" :
+ on(UNIX_SHA512_PASS, ctrl) ? "sha512" : algoid);
memset(sp, '\0', strlen(sp));
return crypt_md5_wrapper(password);
}
@@ -703,13 +700,8 @@ done:
}
}
-#ifdef HELPER_COMPILE
-int
-unix_update_passwd(const char *forwho, const char *towhat)
-#else
-int
-unix_update_passwd(pam_handle_t *pamh, const char *forwho, const char *towhat)
-#endif
+PAMH_ARG_DECL(int unix_update_passwd,
+ const char *forwho, const char *towhat)
{
struct passwd *tmpent = NULL;
struct stat st;
@@ -803,11 +795,7 @@ unix_update_passwd(pam_handle_t *pamh, const char *forwho, const char *towhat)
done:
if (!err) {
if (!rename(PW_TMPFILE, "/etc/passwd"))
-#ifdef HELPER_COMPILE
- helper_log_err(
-#else
pam_syslog(pamh,
-#endif
LOG_NOTICE, "password changed for %s", forwho);
else
err = 1;
@@ -830,13 +818,8 @@ done:
}
}
-#ifdef HELPER_COMPILE
-int
-unix_update_shadow(const char *forwho, char *towhat)
-#else
-int
-unix_update_shadow(pam_handle_t *pamh, const char *forwho, char *towhat)
-#endif
+PAMH_ARG_DECL(int unix_update_shadow,
+ const char *forwho, char *towhat)
{
struct spwd *spwdent = NULL, *stmpent = NULL;
struct stat st;
@@ -933,11 +916,7 @@ unix_update_shadow(pam_handle_t *pamh, const char *forwho, char *towhat)
done:
if (!err) {
if (!rename(SH_TMPFILE, "/etc/shadow"))
-#ifdef HELPER_COMPILE
- helper_log_err(
-#else
pam_syslog(pamh,
-#endif
LOG_NOTICE, "password changed for %s", forwho);
else
err = 1;
diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h
index 21bb9232..3de67593 100644
--- a/modules/pam_unix/passverify.h
+++ b/modules/pam_unix/passverify.h
@@ -21,9 +21,6 @@ is_pwd_shadowed(const struct passwd *pwd);
char *
crypt_md5_wrapper(const char *pass_new);
-char *
-create_password_hash(const char *password, unsigned int ctrl, int rounds);
-
int
unix_selinux_confined(void);
@@ -58,41 +55,33 @@ getuidname(uid_t uid);
int
read_passwords(int fd, int npass, char **passwords);
+#endif
-int
-get_account_info(const char *name,
- struct passwd **pwd, struct spwd **spwdent);
-
-int
-get_pwd_hash(const char *name,
- struct passwd **pwd, char **hash);
-
-int
-check_shadow_expiry(struct spwd *spent, int *daysleft);
+#ifdef HELPER_COMPILE
+#define PAMH_ARG_DECL(fname, ...) fname(__VA_ARGS__)
+#define PAMH_ARG(...) __VA_ARGS__
+#else
+#define PAMH_ARG_DECL(fname, ...) fname(pam_handle_t *pamh, __VA_ARGS__)
+#define PAMH_ARG(...) pamh, __VA_ARGS__
+#endif
-int
-unix_update_passwd(const char *forwho, const char *towhat);
+PAMH_ARG_DECL(char * create_password_hash,
+ const char *password, unsigned int ctrl, int rounds);
-int
-unix_update_shadow(const char *forwho, char *towhat);
-#else
-int
-get_account_info(pam_handle_t *pamh, const char *name,
- struct passwd **pwd, struct spwd **spwdent);
+PAMH_ARG_DECL(int get_account_info,
+ const char *name, struct passwd **pwd, struct spwd **spwdent);
-int
-get_pwd_hash(pam_handle_t *pamh, const char *name,
- struct passwd **pwd, char **hash);
+PAMH_ARG_DECL(int get_pwd_hash,
+ const char *name, struct passwd **pwd, char **hash);
-int
-check_shadow_expiry(pam_handle_t *pamh, struct spwd *spent, int *daysleft);
+PAMH_ARG_DECL(int check_shadow_expiry,
+ struct spwd *spent, int *daysleft);
-int
-unix_update_passwd(pam_handle_t *pamh, const char *forwho, const char *towhat);
+PAMH_ARG_DECL(int unix_update_passwd,
+ const char *forwho, const char *towhat);
-int
-unix_update_shadow(pam_handle_t *pamh, const char *forwho, char *towhat);
-#endif
+PAMH_ARG_DECL(int unix_update_shadow,
+ const char *forwho, char *towhat);
/* ****************************************************************** *
* Copyright (c) Red Hat, Inc. 2007.
diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c
index db630f51..faec20dc 100644
--- a/modules/pam_unix/support.c
+++ b/modules/pam_unix/support.c
@@ -109,16 +109,8 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds,
*remember = 400;
}
}
- if (rounds != NULL) {
- if (j == UNIX_ALGO_ROUNDS) {
- *rounds = strtol(*argv + 7, NULL, 10);
- if ((*rounds < 1000) || (*rounds == INT_MAX))
- /* don't care about bogus values */
- unset(UNIX_ALGO_ROUNDS, ctrl);
- if (*rounds >= 10000000)
- *rounds = 9999999;
- }
- }
+ if (rounds != NULL && j == UNIX_ALGO_ROUNDS)
+ *rounds = strtol(*argv + 7, NULL, 10);
}
++argv; /* step to next argument */
@@ -128,6 +120,26 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds,
D(("DISALLOW_NULL_AUTHTOK"));
set(UNIX__NONULL, ctrl);
}
+
+ /* Set default rounds for blowfish */
+ if (on(UNIX_BLOWFISH_PASS, ctrl) && off(UNIX_ALGO_ROUNDS, ctrl)) {
+ *rounds = 5;
+ set(UNIX_ALGO_ROUNDS, ctrl);
+ }
+
+ /* Enforce sane "rounds" values */
+ if (on(UNIX_ALGO_ROUNDS, ctrl)) {
+ if (on(UNIX_BLOWFISH_PASS, ctrl)) {
+ if (*rounds < 4 || *rounds > 31)
+ *rounds = 5;
+ } else if (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl)) {
+ if ((*rounds < 1000) || (*rounds == INT_MAX))
+ /* don't care about bogus values */
+ unset(UNIX_ALGO_ROUNDS, ctrl);
+ if (*rounds >= 10000000)
+ *rounds = 9999999;
+ }
+ }
/* auditing is a more sensitive version of debug */
diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h
index a33dadaa..86575ff0 100644
--- a/modules/pam_unix/support.h
+++ b/modules/pam_unix/support.h
@@ -88,8 +88,9 @@ typedef struct {
#define UNIX_SHA512_PASS 24 /* new password hashes will use SHA512 */
#define UNIX_ALGO_ROUNDS 25 /* optional number of rounds for new
password hash algorithms */
+#define UNIX_BLOWFISH_PASS 26 /* new password hashes will use blowfish */
/* -------------- */
-#define UNIX_CTRLS_ 26 /* number of ctrl arguments defined */
+#define UNIX_CTRLS_ 27 /* number of ctrl arguments defined */
static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
{
@@ -122,6 +123,7 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(040420000), 020000000},
/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(020420000), 040000000},
/* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000},
+/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(060420000),0200000000},
};
#define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag)