]> granicus.if.org Git - linux-pam/commitdiff
Relevant BUGIDs:
authorThorsten Kukuk <kukuk@thkukuk.de>
Mon, 1 Dec 2008 12:40:40 +0000 (12:40 +0000)
committerThorsten Kukuk <kukuk@thkukuk.de>
Mon, 1 Dec 2008 12:40:40 +0000 (12:40 +0000)
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>

ChangeLog
NEWS
configure.in
modules/pam_unix/pam_unix.8.xml
modules/pam_unix/pam_unix_passwd.c
modules/pam_unix/passverify.c
modules/pam_unix/passverify.h
modules/pam_unix/support.c
modules/pam_unix/support.h

index 5f452a1b127faca40ed90f5ec19971d9c3a128ba..fb585bcd0cc05ccdfd64abcfed43ef0fd59ea574 100644 (file)
--- 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 e3f5623c41a7c8b61ee607f3fe720537b71c5cac..a480eeb1c7ba94aecd63234029b0c14a7f7d6957 100644 (file)
--- 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
 
index e16bd44f926870dc14de69b813b50e3bf19ece51..ff14401c3bbc679dd9b66f3ca2c302cfafd71ce8 100644 (file)
@@ -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
index e08edfcc9b0e6b04671a263f2772c963ecf592f3..cc3affd9fec07a02603f21844ffeb86c98d611b5 100644 (file)
           <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>
           <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>
         </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>
index 240caddb18d3a50366ec3de69911b861a503e825..b8da991388c8d68d091e50f928ccaed538c163b3 100644 (file)
@@ -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");
index eae1e24cfb7dc7296bec3c59b89397cb957dd62a..281716e09c42ee1743840fec109976165bf746ed 100644 (file)
@@ -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;
index 21bb9232cf2346ab3b0f0f03e280cbf13e43921a..3de67593621c3caafa99a8b980ff86824e78893c 100644 (file)
@@ -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.
index db630f517b5c7d332535bd2487d650e134997146..faec20dc4c879e92c5163eb00e947e2f8767c802 100644 (file)
@@ -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 */
 
index a33dadaa98644ce3a35eac564e85c86ce1400f89..86575ff01c882001a7693b4ff359e4b4c22e3e2c 100644 (file)
@@ -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)