Hello,

I want to use grub-mkpasswd inside of a ansible playbook, therefore a 
idempotency or check feature is required.
Without it, there is no posibility to verify, that the configuration is already 
inplace.
Therefore I want to suggest implementing the attached changes.
The simplest one I was thinking of, is grub-mkpasswd allowing to specify a salt 
and comparing the results.
My patch also introduces a quiet mode, that basically suppresses all prompts 
and only expects the password to be entered/piped in once. It also changes the 
output slightly to not inlcude the `PBKDF2 hash of your password is `-part.

The patch is attached to this mail.

Best,
Klaus Frank
>From d289bbb5f5dffbbed2c871989f55e48b756e9ae2 Mon Sep 17 00:00:00 2001
From: Klaus Frank <g...@frank.fyi>
Date: Tue, 25 Dec 2018 06:17:38 +0100
Subject: [PATCH] Implement salt-value and quiet parameter for
 grub-mkpasswd-pbkdf2

---
 util/grub-mkpasswd-pbkdf2.c | 103 ++++++++++++++++++++++++++++++------
 1 file changed, 88 insertions(+), 15 deletions(-)

diff --git a/util/grub-mkpasswd-pbkdf2.c b/util/grub-mkpasswd-pbkdf2.c
index 5805f3c10..018715bf3 100644
--- a/util/grub-mkpasswd-pbkdf2.c
+++ b/util/grub-mkpasswd-pbkdf2.c
@@ -42,10 +42,15 @@
 
 #include "progname.h"
 
+static int dec_from_hex(const int); // Converts the charcode into an integer representation of the representing hex value.
+int unhexify(grub_uint8_t*, const char*);
+
 static struct argp_option options[] = {
   {"iteration-count",  'c', N_("NUM"), 0, N_("Number of PBKDF2 iterations"), 0},
   {"buflen",  'l', N_("NUM"), 0, N_("Length of generated hash"), 0},
   {"salt",  's', N_("NUM"), 0, N_("Length of salt"), 0},
+  {"salt-value", 'v', N_("STR"), 0, N_("Salt"), 0},
+  {"quiet", 'q', 0, 0, N_("Only output hash, suppress other output, indended for pipes"), 0},
   { 0, 0, 0, 0, 0, 0 }
 };
 
@@ -54,6 +59,8 @@ struct arguments
   unsigned int count;
   unsigned int buflen;
   unsigned int saltlen;
+  char *value;
+  unsigned char quiet;
 };
 
 static error_t
@@ -76,6 +83,15 @@ argp_parser (int key, char *arg, struct argp_state *state)
     case 's':
       arguments->saltlen = strtoul (arg, NULL, 0);
       break;
+
+    case 'v':
+      arguments->value = arg;
+      break;
+
+    case 'q':
+      arguments->quiet = 1;
+      break;
+
     default:
       return ARGP_ERR_UNKNOWN;
     }
@@ -94,29 +110,70 @@ hexify (char *hex, grub_uint8_t *bin, grub_size_t n)
 {
   while (n--)
     {
-      if (((*bin & 0xf0) >> 4) < 10)
-	*hex = ((*bin & 0xf0) >> 4) + '0';
-      else
-	*hex = ((*bin & 0xf0) >> 4) + 'A' - 10;
+      if (((*bin & 0xf0) >> 4) < 10) {
+        *hex = ((*bin & 0xf0) >> 4) + '0';
+      } else {
+        *hex = ((*bin & 0xf0) >> 4) + 'A' - 10;
+      }
       hex++;
 
       if ((*bin & 0xf) < 10)
-	*hex = (*bin & 0xf) + '0';
+        *hex = (*bin & 0xf) + '0';
       else
-	*hex = (*bin & 0xf) + 'A' - 10;
+        *hex = (*bin & 0xf) + 'A' - 10;
       hex++;
       bin++;
     }
   *hex = 0;
 }
 
+static int
+dec_from_hex(const int hex) {
+  if (48 <= hex && hex <= 57) {
+    return hex - 48;
+  } else if (65 <= hex && hex <= 90) {
+    return hex - 65 + 10;
+  } else if (97 <= hex && hex <= 122) {
+    return hex - 97 + 10;
+  } else {
+    exit(1);
+  }
+}
+
+int
+unhexify(grub_uint8_t* output, const char* hexstring) {
+  // sizeof(output) == (sizeof(hexstring) - 1) / 2 + 1
+  if (sizeof(output) < (sizeof(hexstring) - 1) / 2 + 1) {
+    return -1;
+  }
+  char *output_ptr = NULL;
+  output_ptr = (char*)output;
+  int CharCodeInDecimal = 0;
+  void *HexDigits = xmalloc(sizeof("FF"));
+  char *HexDigitOne = HexDigits;
+  char *HexDigitTwo = (char*)HexDigits + 1;
+  char *HexString_ptr = NULL;
+  HexString_ptr = (char*)hexstring;
+  while(*HexString_ptr) {
+    memcpy (HexDigitOne, HexString_ptr++, sizeof (char));
+    memcpy (HexDigitTwo, HexString_ptr++, sizeof (char));
+    
+    CharCodeInDecimal = dec_from_hex((int)*HexDigitOne) * 16 + dec_from_hex((int)*HexDigitTwo);
+    *output_ptr++ = (char)CharCodeInDecimal;
+  }
+  output_ptr = '\0';
+  return 0;
+}
+
 int
 main (int argc, char *argv[])
 {
   struct arguments arguments = {
     .count = 10000,
     .buflen = 64,
-    .saltlen = 64
+    .saltlen = 64,
+    .value = NULL,
+    .quiet = 0
   };
   char *result, *ptr;
   gcry_err_code_t gcry_err;
@@ -136,22 +193,25 @@ main (int argc, char *argv[])
   buf = xmalloc (arguments.buflen);
   salt = xmalloc (arguments.saltlen);
   
-  printf ("%s", _("Enter password: "));
+  if (!arguments.quiet) {
+    printf ("%s", _("Enter password: "));
+  }
   if (!grub_password_get (pass1, GRUB_AUTH_MAX_PASSLEN))
     {
       free (buf);
       free (salt);
       grub_util_error ("%s", _("failure to read password"));
     }
-  printf ("%s", _("Reenter password: "));
-  if (!grub_password_get (pass2, GRUB_AUTH_MAX_PASSLEN))
+  if (!arguments.quiet) {
+    printf ("%s", _("Reenter password: "));
+    if (!grub_password_get (pass2, GRUB_AUTH_MAX_PASSLEN))
     {
       free (buf);
       free (salt);
       grub_util_error ("%s", _("failure to read password"));
     }
 
-  if (strcmp (pass1, pass2) != 0)
+    if (strcmp (pass1, pass2) != 0)
     {
       memset (pass1, 0, sizeof (pass1));
       memset (pass2, 0, sizeof (pass2));
@@ -159,15 +219,25 @@ main (int argc, char *argv[])
       free (salt);
       grub_util_error ("%s", _("passwords don't match"));
     }
-  memset (pass2, 0, sizeof (pass2));
+    memset (pass2, 0, sizeof (pass2));
+  }
 
-  if (grub_get_random (salt, arguments.saltlen))
+  if (arguments.value) {
+    if (unhexify(salt, arguments.value)) {
+      memset(pass1, 0, sizeof(pass1));
+      free(buf);
+      free(salt);
+      grub_util_error("%s", _("couldn't convert hexstring into salt"));
+    }
+  } else {
+    if (grub_get_random (salt, arguments.saltlen))
     {
       memset (pass1, 0, sizeof (pass1));
       free (buf);
       free (salt);
       grub_util_error ("%s", _("couldn't retrieve random data for salt"));
     }
+  }
 
   gcry_err = grub_crypto_pbkdf2 (GRUB_MD_SHA512,
 				 (grub_uint8_t *) pass1, strlen (pass1),
@@ -200,11 +270,14 @@ main (int argc, char *argv[])
   ptr += arguments.buflen * 2;
   *ptr = '\0';
 
-  printf (_("PBKDF2 hash of your password is %s\n"), result);
+  if (arguments.quiet) {
+    printf ("%s\n", result);
+  } else {
+    printf (_("PBKDF2 hash of your password is %s\n"), result);
+  }
   memset (buf, 0, arguments.buflen);
   free (buf);
   memset (salt, 0, arguments.saltlen);
   free (salt);
-
   return 0;
 }
-- 
2.20.1

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to