]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Support legacy_check_password
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Wed, 15 Sep 2010 11:51:02 +0000 (13:51 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Wed, 15 Sep 2010 11:51:02 +0000 (13:51 +0200)
grub-core/commands/legacycfg.c
grub-core/lib/legacy_parse.c

index bea608b9ebe070a89ded5411e3f737883e849016..46329781077675315d331f41ce1d4be3ea698217 100644 (file)
@@ -603,19 +603,14 @@ ib64t (char c)
   return -1;
 }
 
-static grub_err_t
-grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)),
-                         int argc, char **args)
+static struct legacy_md5_password *
+parse_legacy_md5 (int argc, char **args)
 {
   const char *salt, *saltend;
-  const char *p;
   struct legacy_md5_password *pw = NULL;
   int i;
+  const char *p;
 
-  if (argc == 0)
-    return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected");
-  if (args[0][0] != '-' || args[0][1] != '-')
-    return grub_normal_set_password ("legacy", args[0]);
   if (grub_memcmp (args[0], "--md5", sizeof ("--md5")) != 0)
     goto fail;
   if (argc == 1)
@@ -667,21 +662,76 @@ grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)),
   if (!pw->salt)
     goto fail;
 
-  return grub_auth_register_authentication ("legacy", check_password_md5, pw);
+  return pw;
 
  fail:
   grub_free (pw);
-  /* This is to imitate minor difference between grub-legacy in GRUB2.
-     If 2 password commands are executed in a row and second one fails
-     on GRUB2 the password of first one is used, whereas in grub-legacy
-     authenthication is denied. In case of no password command was executed
-     early both versions deny any access.  */
-  return grub_auth_register_authentication ("legacy", check_password_deny,
-                                           NULL);
+  return NULL;
+}
+
+static grub_err_t
+grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)),
+                         int argc, char **args)
+{
+  struct legacy_md5_password *pw = NULL;
+
+  if (argc == 0)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected");
+  if (args[0][0] != '-' || args[0][1] != '-')
+    return grub_normal_set_password ("legacy", args[0]);
+
+  pw = parse_legacy_md5 (argc, args);
+
+  if (pw)
+    return grub_auth_register_authentication ("legacy", check_password_md5, pw);
+  else
+    /* This is to imitate minor difference between grub-legacy in GRUB2.
+       If 2 password commands are executed in a row and second one fails
+       on GRUB2 the password of first one is used, whereas in grub-legacy
+       authenthication is denied. In case of no password command was executed
+       early both versions deny any access.  */
+    return grub_auth_register_authentication ("legacy", check_password_deny,
+                                             NULL);
+}
+
+static grub_err_t
+grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unused)),
+                               int argc, char **args)
+{
+  struct legacy_md5_password *pw = NULL;
+  char entered[GRUB_AUTH_MAX_PASSLEN];
+
+  if (argc == 0)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected");
+  grub_printf ("Enter password:");
+  if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN))
+    return GRUB_ACCESS_DENIED;
+
+  if (args[0][0] != '-' || args[0][1] != '-')
+    {
+      char correct[GRUB_AUTH_MAX_PASSLEN];
+
+      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;
+    }
+
+  pw = parse_legacy_md5 (argc, args);
+
+  if (!pw)
+    return GRUB_ACCESS_DENIED;
+
+  if (!check_password_md5_real (entered, pw))
+    return GRUB_ACCESS_DENIED;
+
+  return GRUB_ERR_NONE;
 }
 
 static grub_command_t cmd_source, cmd_configfile, cmd_kernel, cmd_initrd;
-static grub_command_t cmd_password, cmd_initrdnounzip;
+static grub_command_t cmd_password, cmd_check_password, cmd_initrdnounzip;
 
 GRUB_MOD_INIT(legacycfg)
 {
@@ -711,6 +761,12 @@ GRUB_MOD_INIT(legacycfg)
                                        grub_cmd_legacy_password,
                                        N_("[--md5] PASSWD [FILE]"),
                                        N_("Simulate grub-legacy password command"));
+
+  cmd_check_password = grub_register_command ("legacy_check_password",
+                                             grub_cmd_legacy_check_password,
+                                             N_("[--md5] PASSWD [FILE]"),
+                                             N_("Simulate grub-legacy password command in menuentry mode"));
+
 }
 
 GRUB_MOD_FINI(legacycfg)
@@ -721,4 +777,5 @@ GRUB_MOD_FINI(legacycfg)
   grub_unregister_command (cmd_initrd);
   grub_unregister_command (cmd_initrdnounzip);
   grub_unregister_command (cmd_password);
+  grub_unregister_command (cmd_check_password);
 }
index 024d425e89f619602513205a6b9417e0afedce67..e5014cdc789bbfc00d8adff39f251f1d0527cbb7 100644 (file)
@@ -49,6 +49,8 @@ struct legacy_command
     FLAG_FALLBACK_AVAILABLE =  4,
     FLAG_FALLBACK           =  8,
     FLAG_COLOR_INVERT       = 16,
+    FLAG_NO_MENUENTRY       = 32,
+    FLAG_MENUENTRY_ONLY     = 64,
   } flags;
   const char *shortdesc;
   const char *longdesc;
@@ -189,12 +191,12 @@ struct legacy_command legacy_commands[] =
     {"parttype", "parttool '%s' type=%s\n", NULL, 0,
      2, {TYPE_PARTITION, TYPE_INT}, 0,
      "PART TYPE", "Change the type of the partition PART to TYPE."},
-    /* FIXME: support usage in menuentry.  */
     {"password", "if [ \"$superusers\" = "" ]; then superusers=legacy; fi;\n"
-     "legacy_password %s '%s'",
+     "legacy_password %s '%s'\n",
      "menuentry \"Superuser menu\" --users \"legacy\" { configfile '%s'; }\n",
      2, 3, {TYPE_OPTION, TYPE_VERBATIM, TYPE_FILE},
-     FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE, "[--md5] PASSWD [FILE]",
+     FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE | FLAG_NO_MENUENTRY,
+     "[--md5] PASSWD [FILE]",
      "If used in the first section of a menu file, disable all"
      " interactive editing control (menu entry editor and"
      " command line). If the password PASSWD is entered, it loads the"
@@ -205,8 +207,15 @@ struct legacy_command legacy_commands[] =
      " The option --md5 tells GRUB that PASSWD is encrypted with"
      " md5crypt."},
     {"password", "if [ \"$superusers\" = "" ]; then superusers=legacy; fi;\n"
-     "legacy_password %s '%s'", NULL, 0, 2, {TYPE_OPTION, TYPE_VERBATIM},
-     FLAG_IGNORE_REST | FLAG_FALLBACK, NULL, NULL},
+     "legacy_password %s '%s'\n", NULL, 0, 2, {TYPE_OPTION, TYPE_VERBATIM},
+     FLAG_IGNORE_REST | FLAG_FALLBACK | FLAG_NO_MENUENTRY, NULL, NULL},
+    {"password", "if legacy_check_password %s '%s'; then configfile '%s'; "
+     "else return; fi\n", NULL, 2, 3, {TYPE_OPTION, TYPE_VERBATIM, TYPE_FILE},
+     FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE | FLAG_MENUENTRY_ONLY,
+     NULL, NULL},
+    {"password", "if ! legacy_check_password %s '%s'; then return fi;\n",
+     NULL, 0, 2, {TYPE_OPTION, TYPE_VERBATIM},
+     FLAG_IGNORE_REST | FLAG_FALLBACK | FLAG_MENUENTRY_ONLY, NULL, NULL},
     /* NOTE: GRUB2 has a design principle of not eternally waiting for user
        input. 60 seconds should be enough.
      */
@@ -442,7 +451,11 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix)
 
   for (cmdnum = 0; cmdnum < ARRAY_SIZE (legacy_commands); cmdnum++)
     if (grub_strncmp (legacy_commands[cmdnum].name, cmdname, ptr - cmdname) == 0
-       && legacy_commands[cmdnum].name[ptr - cmdname] == 0)
+       && legacy_commands[cmdnum].name[ptr - cmdname] == 0
+       && (!(*entryname != NULL && (legacy_commands[cmdnum].flags
+                                    & FLAG_NO_MENUENTRY)))
+       && (!(*entryname == NULL && (legacy_commands[cmdnum].flags
+                                    & FLAG_MENUENTRY_ONLY))))
       break;
   if (cmdnum == ARRAY_SIZE (legacy_commands))
     return grub_xasprintf ("# Unsupported legacy command: %s\n", buf);