--- grub-2.02-orig/grub-core/kern/list.c +++ grub-2.02/grub-core/kern/list.c @@ -21,6 +21,31 @@ #include #include +static struct grub_passwd_list *passwd_list = NULL; + +grub_err_t +grub_push_passwd (const char *passwd) +{ + struct grub_passwd_list *cur; + cur = grub_zalloc (sizeof (*cur)); + if (!cur) + return grub_errno; + cur->passwd = grub_strdup (passwd); + if (!cur->passwd) + { + grub_free (cur); + return grub_errno; + } + grub_list_push (GRUB_AS_LIST_P (&passwd_list), GRUB_AS_LIST (cur)); + return GRUB_ERR_NONE; +} + +struct grub_passwd_list * +grub_first_passwd (void) +{ + return passwd_list; +} + void * grub_named_list_find (grub_named_list_t head, const char *name) { --- grub-2.02-orig/include/grub/list.h +++ grub-2.02/include/grub/list.h @@ -84,4 +84,14 @@ void * EXPORT_FUNC(grub_named_list_find) && GRUB_FIELD_MATCH (*pptr, grub_named_list_t, name))? \ (grub_named_list_t *) (void *) pptr : (grub_named_list_t *) grub_bad_type_cast ()) +struct grub_passwd_list +{ + struct grub_passwd_list *next; + struct grub_passwd_list **prev; + char *passwd; +}; + +grub_err_t EXPORT_FUNC(grub_push_passwd) (const char *passwd); +struct grub_passwd_list * EXPORT_FUNC(grub_first_passwd) (void); + #endif /* ! GRUB_LIST_HEADER */ --- grub-2.02/grub-core/loader/i386/linux.c.ORIG +++ grub-2.02/grub-core/loader/i386/linux.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -686,6 +687,11 @@ grub_cmd_linux (grub_command_t cmd __att grub_size_t align, min_align; int relocatable; grub_uint64_t preferred_address = GRUB_LINUX_BZIMAGE_ADDR; + struct grub_passwd_list *passwd_list = NULL; + struct grub_passwd_list *passwd_cur; + int pass_passwd = 0; + int pwargc; + char **pwargv; grub_dl_ref (my_mod); @@ -1002,6 +1008,10 @@ grub_cmd_linux (grub_command_t cmd __att linux_mem_size <<= shift; } } + else if (grub_memcmp (argv[i], "grub.pass_password", sizeof ("grub.pass_password") - 1) == 0) + { + pass_passwd = 1; + } else if (grub_memcmp (argv[i], "quiet", sizeof ("quiet") - 1) == 0) { linux_params.loadflags |= GRUB_LINUX_FLAG_QUIET; @@ -1018,6 +1028,33 @@ grub_cmd_linux (grub_command_t cmd __att maximal_cmdline_size - (sizeof (LINUX_IMAGE) - 1)); + if (pass_passwd) + { + passwd_list = grub_first_passwd(); + if (passwd_list) + { + pwargc = 1; + FOR_LIST_ELEMENTS (passwd_cur, passwd_list) + ++pwargc; + pwargv = grub_zalloc (pwargc * sizeof (*pwargv)); + pwargv[0] = grub_strdup ("hdn"); /* signature: NUL hdn SPC */ + i = 0; + FOR_LIST_ELEMENTS (passwd_cur, passwd_list) + { + ++i; + len = grub_strlen(passwd_cur->passwd); + pwargv[i] = grub_zalloc (len + sizeof ("pwd=")); + grub_memcpy (pwargv[i], "pwd=", sizeof ("pwd=") - 1); + grub_memcpy (pwargv[i] + sizeof ("pwd=") - 1, passwd_cur->passwd, len + 1); + } + len = grub_strlen(linux_cmdline); + grub_create_loader_cmdline (pwargc, pwargv, linux_cmdline + len + 1, maximal_cmdline_size - len - 1); + for (i = 0; i < pwargc; ++i) + grub_free(pwargv[i]); + grub_free(pwargv); + } + } + len = prot_file_size; if (grub_file_read (file, prot_mode_mem, len) != len && !grub_errno) grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), --- grub-2.02-orig/grub-core/disk/luks.c +++ grub-2.02/grub-core/disk/luks.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -32,6 +33,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define MAX_PASSPHRASE 256 #define LUKS_KEY_ENABLED 0x00AC71F3 +#define LUKS_ATTEMPTS 3 /* On disk LUKS header */ struct grub_luks_phdr @@ -321,6 +323,7 @@ luks_recover_key (grub_disk_t source, grub_err_t err; grub_size_t max_stripes = 1; char *tmp; + unsigned attempts = LUKS_ATTEMPTS; err = grub_disk_read (source, 0, 0, sizeof (header), &header); if (err) @@ -340,6 +343,8 @@ luks_recover_key (grub_disk_t source, if (!split_key) return grub_errno; +while (attempts) { + /* Get the passphrase from the user. */ tmp = NULL; if (source->partition) @@ -460,9 +465,22 @@ luks_recover_key (grub_disk_t source, grub_free (split_key); + grub_push_passwd(passphrase); + return GRUB_ERR_NONE; } + grub_printf_ (N_("Failed to decrypt master key.\n")); + if (--attempts) + { + if (attempts == 1) + grub_printf_ (N_("1 attempt remaining.\n")); + else + grub_printf_ (N_("%u attempts remaining.\n"), attempts); + + } +} + grub_free (split_key); return GRUB_ACCESS_DENIED; }