On Sat, 27 Apr 2024 17:48:31 -0700 Forest <fores...@nom.one> wrote: > Give the user a chance to re-enter their cryptodisk passphrase after a typo, > rather than immediately failing (and likely dumping them into a grub shell). > > By default, we allow 3 tries before giving up. A value in the > cryptodisk_passphrase_tries environment variable will override this default. > > The user can give up early by entering an empty passphrase, just as they > could before this patch. > > Signed-off-by: Forest <fores...@nom.one> > --- > Note: This is identical to the v3 patch. The change I had in mind proved > unviable.
LGTM. Reviewed-by: Glenn Washburn <developm...@efficientek.com> Glenn > > docs/grub.texi | 9 +++++ > grub-core/disk/cryptodisk.c | 74 +++++++++++++++++++++++++++++-------- > 2 files changed, 67 insertions(+), 16 deletions(-) > > diff --git a/docs/grub.texi b/docs/grub.texi > index a225f9a88..6ac603a32 100644 > --- a/docs/grub.texi > +++ b/docs/grub.texi > @@ -3277,6 +3277,7 @@ These variables have special meaning to GRUB. > * color_normal:: > * config_directory:: > * config_file:: > +* cryptodisk_passphrase_tries:: > * debug:: > * default:: > * fallback:: > @@ -3441,6 +3442,14 @@ processed by commands @command{configfile} > (@pxref{configfile}) or @command{norm > (@pxref{normal}). It is restored to the previous value when command > completes. > > > +@node cryptodisk_passphrase_tries > +@subsection cryptodisk_passphrase_tries > + > +When prompting the user for a cryptodisk passphrase, allow this many attempts > +before giving up. The default is @samp{3}. (The user can give up early by > +entering an empty passphrase.) > + > + > @node debug > @subsection debug > > diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c > index 2246af51b..4fa7dc58d 100644 > --- a/grub-core/disk/cryptodisk.c > +++ b/grub-core/disk/cryptodisk.c > @@ -17,6 +17,7 @@ > */ > > #include <grub/cryptodisk.h> > +#include <grub/env.h> > #include <grub/mm.h> > #include <grub/misc.h> > #include <grub/dl.h> > @@ -1063,6 +1064,8 @@ grub_cryptodisk_scan_device_real (const char *name, > grub_cryptodisk_dev_t cr; > struct cryptodisk_read_hook_ctx read_hook_data = {0}; > int askpass = 0; > + unsigned long tries = 3; > + const char *tries_env; > char *part = NULL; > > dev = grub_cryptodisk_get_by_source_disk (source); > @@ -1114,32 +1117,71 @@ grub_cryptodisk_scan_device_real (const char *name, > if (!dev) > continue; > > - if (!cargs->key_len) > + if (cargs->key_len) > + { > + ret = cr->recover_key (source, dev, cargs); > + if (ret != GRUB_ERR_NONE) > + goto error; > + } > + else > { > /* Get the passphrase from the user, if no key data. */ > askpass = 1; > - part = grub_partition_get_name (source->partition); > - grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name, > - source->partition != NULL ? "," : "", > - part != NULL ? part : N_("UNKNOWN"), > - dev->uuid); > - grub_free (part); > - > cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE); > if (cargs->key_data == NULL) > goto error_no_close; > > - if (!grub_password_get ((char *) cargs->key_data, > GRUB_CRYPTODISK_MAX_PASSPHRASE)) > + tries_env = grub_env_get ("cryptodisk_passphrase_tries"); > + if (tries_env != NULL && tries_env[0] != '\0') > { > - grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied"); > - goto error; > + const char *p = NULL; > + tries = grub_strtoul (tries_env, &p, 0); > + if (*p != '\0') > + { > + /* Account for grub_strtoul() ignoring trailing text. */ > + grub_err_t err = grub_errno; > + if (p > tries_env && tries != ~0UL) > + err = GRUB_ERR_BAD_NUMBER; > + > + grub_error (err, > + N_("non-numeric or invalid value for > cryptodisk_passphrase_tries: `%s'"), > + tries_env); > + goto error; > + } > } > - cargs->key_len = grub_strlen ((char *) cargs->key_data); > - } > > - ret = cr->recover_key (source, dev, cargs); > - if (ret != GRUB_ERR_NONE) > - goto error; > + for (; tries > 0; tries--) > + { > + part = grub_partition_get_name (source->partition); > + grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), > source->name, > + source->partition != NULL ? "," : "", > + part != NULL ? part : N_("UNKNOWN"), > + dev->uuid); > + grub_free (part); > + > + if (!grub_password_get ((char *) cargs->key_data, > GRUB_CRYPTODISK_MAX_PASSPHRASE)) > + { > + grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied"); > + goto error; > + } > + cargs->key_len = grub_strlen ((char *) cargs->key_data); > + > + ret = cr->recover_key (source, dev, cargs); > + if (ret == GRUB_ERR_NONE) > + break; > + if (ret != GRUB_ERR_ACCESS_DENIED || tries == 1) > + goto error; > + grub_puts_ (N_("Invalid passphrase.")); > + > + /* > + * Since recover_key() calls a function that returns grub_errno, > + * a leftover error value from a previously rejected passphrase > + * will trigger a phantom failure. We therefore clear it before > + * trying a new passphrase. > + */ > + grub_errno = GRUB_ERR_NONE; > + } > + } > > ret = grub_cryptodisk_insert (dev, name, source); > if (ret != GRUB_ERR_NONE) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel