diff options
author | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2012-10-25 17:18:12 +0000 |
---|---|---|
committer | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2012-10-25 17:18:12 +0000 |
commit | d9732ccbecc3dd820e2f6496e792f5e839208312 (patch) | |
tree | b8f21a4f63875068370dbc498c5e7919a7a6ca3e /libc/crypt | |
parent | 12348b1583437f6382553bde4a32c2615216fec6 (diff) | |
download | eglibc2-d9732ccbecc3dd820e2f6496e792f5e839208312.tar.gz |
Merge changes between r21108 and r21352 from /fsf/trunk.
git-svn-id: svn://svn.eglibc.org/trunk@21353 7b3dc134-2b1b-0410-93df-9e9f96275f8d
Diffstat (limited to 'libc/crypt')
-rw-r--r-- | libc/crypt/Makefile | 2 | ||||
-rw-r--r-- | libc/crypt/badsalttest.c | 86 | ||||
-rw-r--r-- | libc/crypt/crypt-entry.c | 30 | ||||
-rw-r--r-- | libc/crypt/crypt-private.h | 3 | ||||
-rw-r--r-- | libc/crypt/crypt_util.c | 42 | ||||
-rw-r--r-- | libc/crypt/md5c-test.c | 5 |
6 files changed, 157 insertions, 11 deletions
diff --git a/libc/crypt/Makefile b/libc/crypt/Makefile index 1da12e5b4..d42e683e4 100644 --- a/libc/crypt/Makefile +++ b/libc/crypt/Makefile @@ -31,7 +31,7 @@ libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt libcrypt-routines-$(OPTION_EGLIBC_CRYPT_UFC) := crypt_util crypt libcrypt-routines += $(libcrypt-routines-y) -tests-$(OPTION_EGLIBC_CRYPT) := md5c-test sha256c-test sha512c-test +tests-$(OPTION_EGLIBC_CRYPT) := md5c-test sha256c-test sha512c-test badsalttest tests-$(OPTION_EGLIBC_CRYPT_UFC) += cert include ../Makeconfig diff --git a/libc/crypt/badsalttest.c b/libc/crypt/badsalttest.c new file mode 100644 index 000000000..e0e207bac --- /dev/null +++ b/libc/crypt/badsalttest.c @@ -0,0 +1,86 @@ +/* Test program for bad DES salt detection in crypt. + Copyright (C) 2012 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <unistd.h> +#include <sys/mman.h> +#include <crypt.h> + +static const char *tests[][2] = + { + { "no salt", "" }, + { "single char", "/" }, + { "first char bad", "!x" }, + { "second char bad", "Z%" }, + { "both chars bad", ":@" }, + { "un$upported algorithm", "$2$" }, + { "unsupported_algorithm", "_1" }, + { "end of page", NULL } + }; + +static int +do_test (void) +{ + int result = 0; + struct crypt_data cd; + size_t n = sizeof (tests) / sizeof (*tests); + size_t pagesize = (size_t) sysconf (_SC_PAGESIZE); + char *page; + + /* Check that crypt won't look at the second character if the first + one is invalid. */ + page = mmap (NULL, pagesize * 2, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (page == MAP_FAILED) + { + perror ("mmap"); + n--; + } + else + { + if (mmap (page + pagesize, pagesize, 0, + MAP_PRIVATE | MAP_ANON | MAP_FIXED, + -1, 0) != page + pagesize) + perror ("mmap 2"); + page[pagesize - 1] = '*'; + tests[n - 1][1] = &page[pagesize - 1]; + } + + for (size_t i = 0; i < n; i++) + { + if (crypt (tests[i][0], tests[i][1])) + { + result++; + printf ("%s: crypt returned non-NULL with salt \"%s\"\n", + tests[i][0], tests[i][1]); + } + + if (crypt_r (tests[i][0], tests[i][1], &cd)) + { + result++; + printf ("%s: crypt_r returned non-NULL with salt \"%s\"\n", + tests[i][0], tests[i][1]); + } + } + + return result; +} + +#define TIMEOUT 5 +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/libc/crypt/crypt-entry.c b/libc/crypt/crypt-entry.c index b6c446cd6..74a85068d 100644 --- a/libc/crypt/crypt-entry.c +++ b/libc/crypt/crypt-entry.c @@ -29,6 +29,7 @@ #include <string.h> #include <gnu/option-groups.h> #include <errno.h> +#include <fips-private.h> #ifndef STATIC #define STATIC static @@ -95,8 +96,16 @@ __crypt_r (key, salt, data) #ifdef _LIBC /* Try to find out whether we have to use MD5 encryption replacement. */ if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0) - return __md5_crypt_r (key, salt, (char *) data, - sizeof (struct crypt_data)); + { + /* FIPS rules out MD5 password encryption. */ + if (fips_enabled_p ()) + { + __set_errno (EPERM); + return NULL; + } + return __md5_crypt_r (key, salt, (char *) data, + sizeof (struct crypt_data)); + } /* Try to find out whether we have to use SHA256 encryption replacement. */ if (strncmp (sha256_salt_prefix, salt, sizeof (sha256_salt_prefix) - 1) == 0) @@ -113,7 +122,18 @@ __crypt_r (key, salt, data) /* * Hack DES tables according to salt */ - _ufc_setup_salt_r (salt, data); + if (!_ufc_setup_salt_r (salt, data)) + { + __set_errno (EINVAL); + return NULL; + } + + /* FIPS rules out DES password encryption. */ + if (fips_enabled_p ()) + { + __set_errno (EPERM); + return NULL; + } /* * Setup key schedule @@ -152,7 +172,9 @@ crypt (key, salt) { #ifdef _LIBC /* Try to find out whether we have to use MD5 encryption replacement. */ - if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0) + if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0 + /* Let __crypt_r deal with the error code if FIPS is enabled. */ + && !fips_enabled_p ()) return __md5_crypt (key, salt); /* Try to find out whether we have to use SHA256 encryption replacement. */ diff --git a/libc/crypt/crypt-private.h b/libc/crypt/crypt-private.h index b4bfa8b4a..54418fcb5 100644 --- a/libc/crypt/crypt-private.h +++ b/libc/crypt/crypt-private.h @@ -26,6 +26,7 @@ #define CRYPT_PRIVATE_H 1 #include <features.h> +#include <stdbool.h> /* crypt.c */ extern void _ufc_doit_r (ufc_long itr, struct crypt_data * __restrict __data, @@ -36,7 +37,7 @@ extern void _ufc_doit_r (ufc_long itr, struct crypt_data * __restrict __data, extern void __init_des_r (struct crypt_data * __restrict __data); extern void __init_des (void); -extern void _ufc_setup_salt_r (const char *s, +extern bool _ufc_setup_salt_r (const char *s, struct crypt_data * __restrict __data); extern void _ufc_mk_keytab_r (const char *key, struct crypt_data * __restrict __data); diff --git a/libc/crypt/crypt_util.c b/libc/crypt/crypt_util.c index a1ff88b0d..e08dd8fa9 100644 --- a/libc/crypt/crypt_util.c +++ b/libc/crypt/crypt_util.c @@ -596,23 +596,55 @@ shuffle_sb(k, saltbits) #endif /* + * Return false iff C is in the specified alphabet for crypt salt. + */ + +static bool +bad_for_salt (char c) +{ + switch (c) + { + case '0' ... '9': + case 'A' ... 'Z': + case 'a' ... 'z': + case '.': case '/': + return false; + + default: + return true; + } +} + +/* * Setup the unit for a new salt * Hopefully we'll not see a new salt in each crypt call. + * Return false if an unexpected character was found in s[0] or s[1]. */ -void +bool _ufc_setup_salt_r(s, __data) const char *s; struct crypt_data * __restrict __data; { ufc_long i, j, saltbits; + char s0, s1; if(__data->initialized == 0) __init_des_r(__data); - if(s[0] == __data->current_salt[0] && s[1] == __data->current_salt[1]) - return; - __data->current_salt[0] = s[0]; __data->current_salt[1] = s[1]; + s0 = s[0]; + if(bad_for_salt (s0)) + return false; + + s1 = s[1]; + if(bad_for_salt (s1)) + return false; + + if(s0 == __data->current_salt[0] && s1 == __data->current_salt[1]) + return true; + + __data->current_salt[0] = s0; + __data->current_salt[1] = s1; /* * This is the only crypt change to DES: @@ -646,6 +678,8 @@ _ufc_setup_salt_r(s, __data) shuffle_sb((LONGG)__data->sb3, __data->current_saltbits ^ saltbits); __data->current_saltbits = saltbits; + + return true; } void diff --git a/libc/crypt/md5c-test.c b/libc/crypt/md5c-test.c index f56d0eb4a..c80e40202 100644 --- a/libc/crypt/md5c-test.c +++ b/libc/crypt/md5c-test.c @@ -9,7 +9,10 @@ main (int argc, char *argv[]) int result = 0; cp = crypt ("Hello world!", salt); - result |= strcmp ("$1$saltstri$YMyguxXMBpd2TEZ.vS/3q1", cp); + + /* MD5 is disabled in FIPS mode. */ + if (cp) + result |= strcmp ("$1$saltstri$YMyguxXMBpd2TEZ.vS/3q1", cp); return result; } |