diff --git a/ChangeLog b/ChangeLog index ca6d2e02..541e3982 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2007-11-19 Nicolas François + + * NEWS, libmisc/obscure.c, libmisc/salt.c, src/passwd.c, + lib/getdef.c, etc/login.defs: Add support for SHA256 and SHA512 + encrypt methods. Apply RedHat's patch shadow-4.0.18.1-sha256.patch. + Thanks to Peter Vrabec. Hardly no changes except re-indent and + changes related to recent modifications (max_salt_len in + crypt_make_salt). Changes in lib/defines.h not applied (definition + of ENCRYPTMETHOD_SELECT). I will add a configure check or flag. + 2007-11-19 Nicolas François * man/de/Makefile.am: Add su.1 to the generated manpages. diff --git a/NEWS b/NEWS index 1f6316ce..ec519be6 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ $Id$ shadow-4.0.18.1 -> shadow-4.0.18.2 UNRELEASED *** general: +- Add support for SHA256 and SHA512 encrypt methods (supported by new + libc). - useradd: Allow non numerical group identifier to be specified with useradd's -g option. - chgpasswd, chpasswd: Fix chpasswd and chgpasswd stack overflow. diff --git a/etc/login.defs b/etc/login.defs index d31cbed4..04d20aa3 100644 --- a/etc/login.defs +++ b/etc/login.defs @@ -278,6 +278,16 @@ CHFN_RESTRICT rwh # #MD5_CRYPT_ENAB no +# +# Only works if compiled with ENCRYPTMETHOD_SELECT defined: +# If set to MD5 , MD5-based algorithm will be used for encrypting password +# If set to SHA256, SHA256-based algorithm will be used for encrypting password +# If set to SHA512, SHA512-based algorithm will be used for encrypting password +# If set to DES, DES-based algorithm will be used for encrypting password (default) +# Overrides the MD5_CRYPT_ENAB option +# +#ENCRYPT_METHOD DES + # # List of groups to add to the user's supplementary group set # when logging in on the console (as determined by the CONSOLE diff --git a/lib/getdef.c b/lib/getdef.c index b2dd4716..93546b9d 100644 --- a/lib/getdef.c +++ b/lib/getdef.c @@ -84,6 +84,7 @@ static struct itemdef def_table[] = { {"CHFN_AUTH", NULL}, {"CHSH_AUTH", NULL}, {"CRACKLIB_DICTPATH", NULL}, + {"ENCRYPT_METHOD", NULL}, {"ENV_HZ", NULL}, {"ENVIRON_FILE", NULL}, {"ENV_TZ", NULL}, diff --git a/libmisc/obscure.c b/libmisc/obscure.c index b3345af7..d45b084f 100644 --- a/libmisc/obscure.c +++ b/libmisc/obscure.c @@ -210,6 +210,9 @@ static const char *password_check (const char *old, const char *new, int maxlen, oldlen, newlen; char *new1, *old1; const char *msg; +#ifdef ENCRYPTMETHOD_SELECT + char *result; +#endif oldlen = strlen (old); newlen = strlen (new); @@ -227,15 +230,28 @@ static const char *password_check (const char *old, const char *new, if (msg) return msg; +#ifdef ENCRYPTMETHOD_SELECT + if ((result = getdef_str ("ENCRYPT_METHOD")) == NULL) { +#endif /* The traditional crypt() truncates passwords to 8 chars. It is possible to circumvent the above checks by choosing an easy 8-char password and adding some random characters to it... Example: "password$%^&*123". So check it again, this time truncated to the maximum length. Idea from npasswd. --marekm */ - if (getdef_bool ("MD5_CRYPT_ENAB")) - return NULL; /* unlimited password length */ + if (getdef_bool ("MD5_CRYPT_ENAB")) + return NULL; +#ifdef ENCRYPTMETHOD_SELECT + } else { + + if (!strncmp (result, "MD5" , 3) || + !strncmp (result, "SHA256", 6) || + !strncmp (result, "SHA512", 6)) + return NULL; + + } +#endif maxlen = getdef_num ("PASS_MAX_LEN", 8); if (oldlen <= maxlen && newlen <= maxlen) return NULL; diff --git a/libmisc/salt.c b/libmisc/salt.c index 4ccf36cc..9e78a767 100644 --- a/libmisc/salt.c +++ b/libmisc/salt.c @@ -58,20 +58,44 @@ char *l64a(long value) * (magic) and pw_encrypt() will execute the MD5-based FreeBSD-compatible * version of crypt() instead of the standard one. */ + +#define MAGNUM(array,ch) (array)[0]= (array)[2] = '$',(array)[1]=(ch) + char *crypt_make_salt (void) { struct timeval tv; static char result[40]; int max_salt_len = 8; + char *method; - result[0] = '\0'; #ifndef USE_PAM - if (getdef_bool ("MD5_CRYPT_ENAB")) { - strcpy (result, "$1$"); /* magic for the new MD5 crypt() */ max_salt_len += 3; - } +#ifdef ENCRYPTMETHOD_SELECT + if ((method = getdef_str ("ENCRYPT_METHOD")) == NULL) { #endif - + if (getdef_bool ("MD5_CRYPT_ENAB")) { + MAGNUM(result,'1'); + max_salt_len = 11; + } else + result[0] = '\0'; +#ifdef ENCRYPTMETHOD_SELECT + } else { + if (!strncmp (method, "MD5", 3)) { + MAGNUM(result, '1'); + max_salt_len = 11; + } else if (!strncmp (method, "SHA256", 6)) { + MAGNUM(result, '5'); + max_salt_len = 11; /* XXX: should not be fixed */ + } else if (!strncmp (method, "SHA512", 6)) { + MAGNUM(result, '6'); + max_salt_len = 11; /* XXX: should not be fixed */ + } else if (!strncmp (method, "DES", 3)) + result[0] = '\0'; + else + result[0] = '\0'; + } +#endif /* ENCRYPTMETHOD_SELECT */ +#endif /* USE_PAM */ /* * Generate 8 chars of salt, the old crypt() will use only first 2. */ diff --git a/src/passwd.c b/src/passwd.c index 8775e87c..1f57e705 100644 --- a/src/passwd.c +++ b/src/passwd.c @@ -190,7 +190,10 @@ static int new_password (const struct passwd *pw) char pass[200]; /* New password */ int i; /* Counter for retries */ int warned; - int pass_max_len; + int pass_max_len = -1; +#ifdef ENCRYPTMETHOD_SELECT + char *method; +#endif #ifdef HAVE_LIBCRACK_HIST int HistUpdate (const char *, const char *); @@ -228,15 +231,34 @@ static int new_password (const struct passwd *pw) * for strength, unless it is the root user. This provides an escape * for initial login passwords. */ - if (getdef_bool ("MD5_CRYPT_ENAB")) - pass_max_len = 127; - else - pass_max_len = getdef_num ("PASS_MAX_LEN", 8); - - if (!qflg) - printf (_("\ -Enter the new password (minimum of %d, maximum of %d characters)\n\ -Please use a combination of upper and lower case letters and numbers.\n"), getdef_num ("PASS_MIN_LEN", 5), pass_max_len); +#ifdef ENCRYPTMETHOD_SELECT + if ((method = getdef_str ("ENCRYPT_METHOD")) == NULL) { +#endif + if (!getdef_bool ("MD5_CRYPT_ENAB")) + pass_max_len = getdef_num ("PASS_MAX_LEN", 8); +#ifdef ENCRYPTMETHOD_SELECT + } else { + if (!strncmp (method, "MD5" , 3) || + !strncmp (method, "SHA256", 6) || + !strncmp (method, "SHA512", 6)) + pass_max_len = -1; + else + pass_max_len = getdef_num ("PASS_MAX_LEN", 8); + } +#endif + if (!qflg) { + if (pass_max_len == -1) { + printf (_( +"Enter the new password (minimum of %d characters)\n" +"Please use a combination of upper and lower case letters and numbers.\n"), + getdef_num ("PASS_MIN_LEN", 5)); + } else { + printf (_( +"Enter the new password (minimum of %d, maximum of %d characters)\n" +"Please use a combination of upper and lower case letters and numbers.\n"), + getdef_num ("PASS_MIN_LEN", 5), pass_max_len); + } + } warned = 0; for (i = getdef_num ("PASS_CHANGE_TRIES", 5); i > 0; i--) {