diff --git a/ChangeLog b/ChangeLog index e00524932..dc1699e97 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2013-11-12 Vladimir Serbinenko + + * grub-core/tests/legacy_password_test.c: New test. + * grub-core/commands/legacycfg.c: Remove variable length arrays. + 2013-11-12 Vladimir Serbinenko * grub-core/lib/pbkdf2.c: Remove variable length arrays. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 8df80a616..1d98a8ecb 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1921,6 +1921,11 @@ module = { common = tests/pbkdf2_test.c; }; +module = { + name = legacy_password_test; + common = tests/legacy_password_test.c; +}; + module = { name = div_test; common = tests/div_test.c; diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index 103380754..4443341b4 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -553,8 +553,13 @@ check_password_md5_real (const char *entered, grub_size_t enteredlen = grub_strlen (entered); unsigned char alt_result[MD5_HASHLEN]; unsigned char *digest; - grub_uint8_t ctx[GRUB_MD_MD5->contextsize]; + grub_uint8_t *ctx; grub_size_t i; + int ret; + + ctx = grub_zalloc (GRUB_MD_MD5->contextsize); + if (!ctx) + return 0; GRUB_MD_MD5->init (ctx); GRUB_MD_MD5->write (ctx, entered, enteredlen); @@ -600,7 +605,9 @@ check_password_md5_real (const char *entered, GRUB_MD_MD5->final (ctx); } - return (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0); + ret = (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0); + grub_free (ctx); + return ret; } static grub_err_t @@ -723,18 +730,11 @@ grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)), NULL); } -static grub_err_t -grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unused)), - int argc, char **args) +int +grub_legacy_check_md5_password (int argc, char **args, + char *entered) { struct legacy_md5_password *pw = NULL; - char entered[GRUB_AUTH_MAX_PASSLEN]; - - if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); - grub_puts_ (N_("Enter password: ")); - if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) - return GRUB_ACCESS_DENIED; if (args[0][0] != '-' || args[0][1] != '-') { @@ -743,17 +743,31 @@ grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unuse grub_memset (correct, 0, sizeof (correct)); grub_strncpy (correct, args[0], sizeof (correct)); - if (grub_crypto_memcmp (entered, correct, GRUB_AUTH_MAX_PASSLEN) != 0) - return GRUB_ACCESS_DENIED; - return GRUB_ERR_NONE; + return grub_crypto_memcmp (entered, correct, GRUB_AUTH_MAX_PASSLEN) == 0; } pw = parse_legacy_md5 (argc, args); if (!pw) + return 0; + + return check_password_md5_real (entered, pw); +} + +static grub_err_t +grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + char entered[GRUB_AUTH_MAX_PASSLEN]; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + grub_puts_ (N_("Enter password: ")); + if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) return GRUB_ACCESS_DENIED; - if (!check_password_md5_real (entered, pw)) + if (!grub_legacy_check_md5_password (argc, args, + entered)) return GRUB_ACCESS_DENIED; return GRUB_ERR_NONE; diff --git a/grub-core/tests/legacy_password_test.c b/grub-core/tests/legacy_password_test.c new file mode 100644 index 000000000..7427f6a7b --- /dev/null +++ b/grub-core/tests/legacy_password_test.c @@ -0,0 +1,68 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct +{ + char **args; + int argc; + char entered[GRUB_AUTH_MAX_PASSLEN]; + int exp; +} vectors[] = { + { (char * []) { (char *) "hello", NULL }, 1, "hello", 1 }, + { (char * []) { (char *) "hello", NULL }, 1, "hi", 0 }, + { (char * []) { (char *) "hello", NULL }, 1, "hillo", 0 }, + { (char * []) { (char *) "hello", NULL }, 1, "hellw", 0 }, + { (char * []) { (char *) "hello", NULL }, 1, "hell", 0 }, + { (char * []) { (char *) "hello", NULL }, 1, "h", 0 }, + { (char * []) { (char *) "--md5", (char *) "$1$maL$OKEF0PD2k6eQ0Po8u4Gjr/", + NULL }, 2, "hello", 1 }, + { (char * []) { (char *) "--md5", (char *) "$1$maL$OKEF0PD2k6eQ0Po8u4Gjr/", + NULL }, 2, "hell", 0 }, + { (char * []) { (char *) "--md5", (char *) "$1$naL$BaFO8zGgmss1E76GsrAec1", + NULL }, 2, "hello", 1 }, + { (char * []) { (char *) "--md5", (char *) "$1$naL$BaFO8zGgmss1E76GsrAec1", + NULL }, 2, "hell", 0 }, + { (char * []) { (char *) "--md5", (char *) "$1$oaL$eyrazuM7TkxVkKgBim1WH1", + NULL }, 2, "hi", 1 }, + { (char * []) { (char *) "--md5", (char *) "$1$oaL$eyrazuM7TkxVkKgBim1WH1", + NULL }, 2, "hello", 0 }, +}; + +static void +legacy_password_test (void) +{ + grub_size_t i; + + for (i = 0; i < ARRAY_SIZE (vectors); i++) + grub_test_assert (grub_legacy_check_md5_password (vectors[i].argc, + vectors[i].args, + vectors[i].entered) + == vectors[i].exp, "Bad password check (%d)", (int) i); +} + +/* Register example_test method as a functional test. */ +GRUB_FUNCTIONAL_TEST (legacy_password_test, legacy_password_test); diff --git a/grub-core/tests/lib/functional_test.c b/grub-core/tests/lib/functional_test.c index 6b849f5ae..65ff69c33 100644 --- a/grub-core/tests/lib/functional_test.c +++ b/grub-core/tests/lib/functional_test.c @@ -61,6 +61,7 @@ grub_functional_all_tests (grub_extcmd_context_t ctxt __attribute__ ((unused)), grub_dl_load ("div_test"); grub_dl_load ("xnu_uuid_test"); grub_dl_load ("pbkdf2_test"); + grub_dl_load ("legacy_password_test"); FOR_LIST_ELEMENTS (test, grub_test_list) ok = !grub_test_run (test) && ok; diff --git a/include/grub/legacy_parse.h b/include/grub/legacy_parse.h index a5e67a071..751950590 100644 --- a/include/grub/legacy_parse.h +++ b/include/grub/legacy_parse.h @@ -24,4 +24,9 @@ char *grub_legacy_parse (const char *buf, char **entryname, char **suffix); char *grub_legacy_escape (const char *in, grub_size_t len); +/* Entered has to be GRUB_AUTH_MAX_PASSLEN long, zero-padded. */ +int +grub_legacy_check_md5_password (int argc, char **args, + char *entered); + #endif