diff -urN shadow-4.0.3/acconfig.h shadow-4.0.3-blowfish/acconfig.h --- shadow-4.0.3/acconfig.h 2001-07-27 15:26:04.000000000 +0200 +++ shadow-4.0.3-blowfish/acconfig.h 2004-12-26 20:46:20.000000000 +0100 @@ -41,6 +41,9 @@ /* Define as 1 if you have catgets and don't want to use GNU gettext. */ #undef HAVE_CATGETS +/* Do we have the Openwall-patched glibc? */ +#undef HAVE_CRYPT_GENSALT + /* Define as 1 if you have gettext and don't want to use GNU gettext. */ #undef HAVE_GETTEXT @@ -101,6 +104,9 @@ /* Define if the compiler understands function prototypes. */ #undef PROTOTYPES +/* Where is /dev/urandom or a /dev/urandom-alike. */ +#undef RANDOM_FILE + /* Define if login should support the -r flag for rlogind. */ #undef RLOGIN diff -urN shadow-4.0.3/config.h.in shadow-4.0.3-blowfish/config.h.in --- shadow-4.0.3/config.h.in 2002-01-06 15:46:07.000000000 +0100 +++ shadow-4.0.3-blowfish/config.h.in 2004-12-26 20:46:20.000000000 +0100 @@ -42,6 +42,9 @@ /* Define as 1 if you have catgets and don't want to use GNU gettext. */ #undef HAVE_CATGETS +/* Do we have the Openwall-patched glibc? */ +#undef HAVE_CRYPT_GENSALT + /* Define as 1 if you have gettext and don't want to use GNU gettext. */ #undef HAVE_GETTEXT @@ -102,6 +105,9 @@ /* Define if the compiler understands function prototypes. */ #undef PROTOTYPES +/* Where is /dev/urandom or a /dev/urandom-alike. */ +#undef RANDOM_FILE + /* Define if login should support the -r flag for rlogind. */ #undef RLOGIN diff -urN shadow-4.0.3/configure.in shadow-4.0.3-blowfish/configure.in --- shadow-4.0.3/configure.in 2002-03-13 09:36:40.000000000 +0100 +++ shadow-4.0.3-blowfish/configure.in 2004-12-26 20:46:20.000000000 +0100 @@ -211,6 +211,22 @@ AC_ARG_WITH(libpam, [ --with-libpam use libpam for PAM support]) AC_ARG_WITH(libskey, [ --with-libskey use libskey for S/Key support]) AC_ARG_WITH(libtcfs, [ --with-libtcfs use libtcfs for TCFS support]) +AC_ARG_WITH(random, + [ --with-random=FILE read randomness from FILE (default=/dev/urandom)], + [ RANDOM_FILE="$withval" ], + [ + dnl Check for random device + AC_CHECK_FILE("/dev/urandom", + [ + RANDOM_FILE="/dev/urandom"; + ] + ) + ] +) +if test -n "$RANDOM_FILE" ; then + AC_SUBST(RANDOM_FILE) + AC_DEFINE_UNQUOTED(RANDOM_FILE, "$RANDOM_FILE") +fi dnl Check for some functions in libc first, only if not found check for dnl other libraries. This should prevent linking libnsl if not really @@ -236,6 +252,7 @@ AC_SUBST(LIBCRYPT) if test "$with_libcrypt" != "no"; then AC_CHECK_LIB(crypt, crypt, [AC_DEFINE(HAVE_LIBCRYPT) LIBCRYPT=-lcrypt]) + AC_CHECK_LIB(crypt, crypt_gensalt, AC_DEFINE(HAVE_CRYPT_GENSALT)) fi AC_SUBST(LIBCRACK) diff -urN shadow-4.0.3/etc/login.defs.linux shadow-4.0.3-blowfish/etc/login.defs.linux --- shadow-4.0.3/etc/login.defs.linux 2004-12-26 20:45:17.000000000 +0100 +++ shadow-4.0.3-blowfish/etc/login.defs.linux 2004-12-26 20:46:20.000000000 +0100 @@ -265,13 +265,6 @@ PASS_ALWAYS_WARN yes # -# Number of significant characters in the password for crypt(). -# Default is 8, don't change unless your crypt() is better. -# Ignored if MD5_CRYPT_ENAB set to "yes". -# -#PASS_MAX_LEN 8 - -# # Require password before chfn/chsh can make any changes. # CHFN_AUTH yes @@ -292,14 +285,62 @@ #LOGIN_STRING "%s's Password: " # -# Only works if compiled with MD5_CRYPT defined: -# If set to "yes", new passwords will be encrypted using the MD5-based -# algorithm compatible with the one used by recent releases of FreeBSD. -# It supports passwords of unlimited length and longer salt strings. -# Set to "no" if you need to copy encrypted passwords to other systems -# which don't understand the new algorithm. Default is "no". +# Each password entry contains a prefix that specifies the hashing algorithm +# used to create the remaining characters/bytes. Use this setting to specify +# which hashing algorithm is used to create new passwords. +# +# The default here is to use the Blowfish-based algorithm, (which currently +# requires you to be running a patched version of glibc). To use the slightly +# more compatible MD5-based algorithm, you would set this to $1$. To be +# completely backwards compatible and use the traditional DES-based hashing, +# you should set this value to an empty string, but be warned, passwords using +# this algorithm offer very little security. +# +CRYPT_PREFIX "$2a$" + +# +# For hashing algorithms that can alter their complexity, use this setting to +# achieve a balance between the security of the password and performance on the +# host system. +# +# This value is interpreted by each algorithm in specific ways. With the +# Blowfish algorithm, it specifies the number of rounds as a base-2 logarithm +# of the actual iteration count, so 12 actually refers to 2^12. Altering the +# value to 11 would therefore halve the number of iterations used to 2^11. +# +# Make sure that if you alter the above setting, this setting is also +# appropriate. For algorithms that have fixed iteration counts, or to +# enforce the use of a low default value, use a setting of 0. +# +CRYPT_ROUNDS 12 + +# +# All algorithms require varying amounts of random bytes known as salt. For +# example the DES-based algorithm requires only 12-bits, (1½ bytes), whereas +# the Blowfish-based algorithm requires 128-bits, (16 bytes). +# +# If an algorithm doesn't receive enough salt, more will be collected from +# /dev/urandom, a byte at a time until it's satisfied. If you know how much +# is enough to satisfy even the most hungry of algorithms locally available, +# setting it here will speed up the generation of passwords. +# +# A maximum is also provided to enforce an upper limit on this to prevent a +# wayward algorithm munching all the randomness unnecessarily. +# +CRYPT_MINSALT 16 +CRYPT_MAXSALT 32 + +# +# Number of significant characters in the password for crypt(). MD5 can +# effectively cope with unlimited length passwords, but a limit of ~127 is +# reasonable. Blowfish can handle up to 72 characters, and the DES algorithm +# can only handle 8. +# +# This setting is used in some of the obscure checks, and also to inform the +# user on how big their new password should be, so it should be set in +# accordance to the choice of algorithm. # -MD5_CRYPT_ENAB yes +PASS_MAX_LEN 72 # # List of groups to add to the user's supplementary group set diff -urN shadow-4.0.3/lib/getdef.c shadow-4.0.3-blowfish/lib/getdef.c --- shadow-4.0.3/lib/getdef.c 2002-01-06 15:08:00.000000000 +0100 +++ shadow-4.0.3-blowfish/lib/getdef.c 2004-12-26 20:46:20.000000000 +0100 @@ -62,6 +62,12 @@ { "CONSOLE_GROUPS", NULL }, { "CRACKLIB_DICTPATH", NULL }, { "CREATE_HOME", NULL }, +#ifdef HAVE_CRYPT_GENSALT + { "CRYPT_MAXSALT", NULL }, + { "CRYPT_MINSALT", NULL }, + { "CRYPT_PREFIX", NULL }, + { "CRYPT_ROUNDS", NULL }, +#endif /* HAVE_CRYPT_GENSALT */ { "DEFAULT_HOME", NULL }, { "DIALUPS_CHECK_ENAB", NULL }, { "ENVIRON_FILE", NULL }, @@ -90,7 +96,9 @@ { "MAIL_CHECK_ENAB", NULL }, { "MAIL_DIR", NULL }, { "MAIL_FILE", NULL }, +#ifndef HAVE_CRYPT_GENSALT { "MD5_CRYPT_ENAB", NULL }, +#endif /* ! HAVE_CRYPT_GENSALT */ { "MOTD_FILE", NULL }, { "NOLOGINS_FILE", NULL }, { "NOLOGIN_STR", NULL }, diff -urN shadow-4.0.3/libmisc/obscure.c shadow-4.0.3-blowfish/libmisc/obscure.c --- shadow-4.0.3/libmisc/obscure.c 1999-03-07 20:14:40.000000000 +0100 +++ shadow-4.0.3-blowfish/libmisc/obscure.c 2004-12-26 20:46:20.000000000 +0100 @@ -241,8 +241,10 @@ Example: "password$%^&*123". So check it again, this time truncated to the maximum length. Idea from npasswd. --marekm */ +#ifndef HAVE_CRYPT_GENSALT if (getdef_bool("MD5_CRYPT_ENAB")) return NULL; /* unlimited password length */ +#endif maxlen = getdef_num("PASS_MAX_LEN", 8); if (oldlen <= maxlen && newlen <= maxlen) diff -urN shadow-4.0.3/libmisc/salt.c shadow-4.0.3-blowfish/libmisc/salt.c --- shadow-4.0.3/libmisc/salt.c 1997-12-08 00:27:09.000000000 +0100 +++ shadow-4.0.3-blowfish/libmisc/salt.c 2004-12-26 20:46:20.000000000 +0100 @@ -3,8 +3,12 @@ * * Written by Marek Michalkiewicz , * public domain. + * + * Broken by Matt Dainty */ +#define _OW_SOURCE + #include #include "rcsid.h" @@ -14,7 +18,94 @@ #include "defines.h" #include -#if 1 +#ifdef HAVE_CRYPT_GENSALT +#include +#include +#include +#include +#include +#include "getdef.h" + +/* Soopa-doopa salt generation function. There isn't anything algorithm + * specific in here, although it does require the Openwall-patched glibc to + * provide the crypt_gensalt() function, as well as make use of Blowfish-based + * hashing. + * + * All parameters can be customised from the /etc/login.defs file + * + * Written by Matt Dainty + */ +char * +crypt_make_salt(void) +{ + char *result, *salt; + int fd, offset, minsalt, maxsalt, count; + + minsalt = getdef_num( "CRYPT_MINSALT", 16 ); + maxsalt = getdef_num( "CRYPT_MAXSALT", 32 ); + + if( minsalt > maxsalt ) { + fprintf( stderr, "Check the CRYPT_MINSALT and CRYPT_MAXSALT settings!\n" ); + exit(1); + } + + if( ( salt = ( char * ) malloc( maxsalt ) ) == NULL ) { + fprintf( stderr, "Can't allocate %d bytes of memory\n", maxsalt ); + exit(1); + } + + if( ( fd = open( RANDOM_FILE, O_RDONLY ) ) < 0 ) { + fprintf( stderr, "Can't open %s for reading\n", RANDOM_FILE ); + free( salt ); + exit(1); + } + + offset = 0; + result = NULL; + + while( !result ) { + while( offset < minsalt ) { + count = read( fd, &salt[offset], minsalt - offset ); + if( count <= 0 ) { + if( errno == EINTR ) + continue; + goto finish; + } + offset += count; + } + result = crypt_gensalt( getdef_str( "CRYPT_PREFIX" ), + getdef_num( "CRYPT_ROUNDS", 0 ), + salt, minsalt ); + + if( !result && errno == EINVAL ) { + if( minsalt < maxsalt ) { + minsalt++; + } else { + fprintf( stderr, "CRYPT_PREFIX or CRYPT_ROUNDS is set incorrectly\n" ); + goto finish; + } + } + } + +finish: + if( salt ) + free( salt ); + if( fd ) + close( fd ); + + /* XXX If we return the salt string as NULL, crypt will currently + * segfault, so if have we a NULL salt string, exit here. + * Otherwise, every invocation of crypt_make_salt() will have to + * check for a NULL return value. + * + * This way, I don't muck up any more code! :-) + */ + if( result ) + return result; + + exit(1); +} +#elif 1 /* HAVE_CRYPT_GENSALT */ #include "getdef.h" extern char *l64a(); diff -urN shadow-4.0.3/src/passwd.c shadow-4.0.3-blowfish/src/passwd.c --- shadow-4.0.3/src/passwd.c 2002-01-05 16:41:43.000000000 +0100 +++ shadow-4.0.3-blowfish/src/passwd.c 2004-12-26 20:46:20.000000000 +0100 @@ -324,9 +324,11 @@ * for initial login passwords. */ +#ifndef HAVE_CRYPT_GENSALT if (getdef_bool ("MD5_CRYPT_ENAB")) pass_max_len = 127; else +#endif pass_max_len = getdef_num ("PASS_MAX_LEN", 8); if (!qflg)