All of lore.kernel.org
 help / color / mirror / Atom feed
* 'password' command in GRUB 2?
@ 2009-06-05 17:36 Colin Watson
  2009-06-05 17:55 ` Vladimir 'phcoder' Serbinenko
  0 siblings, 1 reply; 22+ messages in thread
From: Colin Watson @ 2009-06-05 17:36 UTC (permalink / raw)
  To: grub-devel

Hi,

I was asked today whether GRUB 2 had a 'password' command yet, as it's
more or less the last major feature regression from GRUB Legacy from our
point of view. I see from the Subversion repository that it doesn't yet,
but there have been a number of attempts in the past. Rather than
reinventing the wheel, if we were to look at pushing this up the hill to
inclusion, where would be the best place to start?

Previous attempts I have found:

  http://lists.gnu.org/archive/html/grub-devel/2007-08/msg00034.html
    "[PATCH] password command implementation", Julien RANC, August 2007
  http://lists.gnu.org/archive/html/grub-devel/2008-05/msg00135.html
    "[RFC] Grub2 lock and password implementation", Julien Ranc, May 2008
  http://lists.gnu.org/archive/html/grub-devel/2008-08/msg00308.html
    "Idea: implementation of the password command", Bean, August 2008
  http://lists.gnu.org/archive/html/grub-devel/2009-02/msg00376.html
    "Menu locks / password authentication", Robert Millan, February 2009

I agreed with Robert in the last link above that it would be best to
implement lock/password first and worry about something more extensible
later if required (on the "you ain't gonna need it" principle), but the
threads on the subject have mostly seemed to end up in interface design
discussions rather than just emulating the working design from GRUB
Legacy (modulo using a non-broken hash function) for now.

Is there still substantial disagreement among the GRUB developers about
this, or would it be worthwhile pursuing something that basically just
does what the GRUB Legacy code did? In that case, it seems that Julien's
code in
http://lists.gnu.org/archive/html/grub-devel/2007-08/msg00034.html, with
the review comments incorporated, would be a reasonable place to start?

Thanks,

-- 
Colin Watson                                       [cjwatson@ubuntu.com]



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: 'password' command in GRUB 2?
  2009-06-05 17:36 'password' command in GRUB 2? Colin Watson
@ 2009-06-05 17:55 ` Vladimir 'phcoder' Serbinenko
  2009-06-05 18:17   ` Re[2]: " Julien RANC
  0 siblings, 1 reply; 22+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-06-05 17:55 UTC (permalink / raw)
  To: The development of GRUB 2

On Fri, Jun 5, 2009 at 7:36 PM, Colin Watson<cjwatson@ubuntu.com> wrote:
> Hi,
>
> I was asked today whether GRUB 2 had a 'password' command yet, as it's
> more or less the last major feature regression from GRUB Legacy from our
> point of view. I see from the Subversion repository that it doesn't yet,
> but there have been a number of attempts in the past. Rather than
> reinventing the wheel, if we were to look at pushing this up the hill to
> inclusion, where would be the best place to start?
Once I merge savedefault password protection is the last feature
needed for debian to migrate (according to Robert Millan)
>
> Previous attempts I have found:
>
>  http://lists.gnu.org/archive/html/grub-devel/2007-08/msg00034.html
>    "[PATCH] password command implementation", Julien RANC, August 2007
>  http://lists.gnu.org/archive/html/grub-devel/2008-05/msg00135.html
>    "[RFC] Grub2 lock and password implementation", Julien Ranc, May 2008
I don't know if he has copyright assignment. If he doesn't, copyright
assignment takes a lot of time
>  http://lists.gnu.org/archive/html/grub-devel/2008-08/msg00308.html
>    "Idea: implementation of the password command", Bean, August 2008
>  http://lists.gnu.org/archive/html/grub-devel/2009-02/msg00376.html
>    "Menu locks / password authentication", Robert Millan, February 2009
>
> I agreed with Robert in the last link above that it would be best to
> implement lock/password first and worry about something more extensible
> later if required (on the "you ain't gonna need it" principle),
Yes but I'm uncomfortable with authntication handled in scripts. We
all know SQL injection problems. The main question is whether we want
something simple to use or something very extendable. My approach
would be:
http://lists.gnu.org/archive/html/grub-devel/2009-03/msg00156.html
> Thanks,
>
> --
> Colin Watson                                       [cjwatson@ubuntu.com]
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>



-- 
Regards
Vladimir 'phcoder' Serbinenko



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re[2]: 'password' command in GRUB 2?
  2009-06-05 17:55 ` Vladimir 'phcoder' Serbinenko
@ 2009-06-05 18:17   ` Julien RANC
  2009-07-26 14:40     ` Felix Zielcke
  0 siblings, 1 reply; 22+ messages in thread
From: Julien RANC @ 2009-06-05 18:17 UTC (permalink / raw)
  To: Vladimir 'phcoder' Serbinenko; +Cc: The development of GRUB 2

Hello,

>> Previous attempts I have found:
>>
>>  http://lists.gnu.org/archive/html/grub-devel/2007-08/msg00034.html
>>    "[PATCH] password command implementation", Julien RANC, August 2007
>>  http://lists.gnu.org/archive/html/grub-devel/2008-05/msg00135.html
>>    "[RFC] Grub2 lock and password implementation", Julien Ranc, May 2008
> I don't know if he has copyright assignment. If he doesn't, copyright
> assignment takes a lot of time

I have no copyright assignment. If there is anything I can do to help
integrating that feature, please tell me, as I see no problem in that,
and I have currently no plan to continue this work.

If I remember correctly, I had improved on the first patch to include
most of the remarks. I'll have a look if I can find back the modified
patch, and send it to the list for anyone to have it.

-- 
Julien RANC.




^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-06-05 18:17   ` Re[2]: " Julien RANC
@ 2009-07-26 14:40     ` Felix Zielcke
  2009-07-26 16:20       ` Vladimir 'phcoder' Serbinenko
  0 siblings, 1 reply; 22+ messages in thread
From: Felix Zielcke @ 2009-07-26 14:40 UTC (permalink / raw)
  To: The development of GRUB 2

Am Freitag, den 05.06.2009, 20:17 +0200 schrieb Julien RANC:
> Hello,
> 
> >> Previous attempts I have found:
> >>
> >>  http://lists.gnu.org/archive/html/grub-devel/2007-08/msg00034.html
> >>    "[PATCH] password command implementation", Julien RANC, August 2007
> >>  http://lists.gnu.org/archive/html/grub-devel/2008-05/msg00135.html
> >>    "[RFC] Grub2 lock and password implementation", Julien Ranc, May 2008
> > I don't know if he has copyright assignment. If he doesn't, copyright
> > assignment takes a lot of time
> 
> I have no copyright assignment. If there is anything I can do to help
> integrating that feature, please tell me, as I see no problem in that,
> and I have currently no plan to continue this work.
> 
> If I remember correctly, I had improved on the first patch to include
> most of the remarks. I'll have a look if I can find back the modified
> patch, and send it to the list for anyone to have it.
> 

What is with his patch? Shouldn't we just send him an assigment?
Adrian (the author of SGD) just mentioned on IRC that everyone tells him
grub2 won't be used widely by distros without password support.

So it seems this is important to people.
I try to look into this but I have the feeling that I'm not really the
right person for this. Especially when we want something complete and
extensible etc.

-- 
Felix Zielcke
Proud Debian Maintainer




^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-07-26 14:40     ` Felix Zielcke
@ 2009-07-26 16:20       ` Vladimir 'phcoder' Serbinenko
  2009-07-26 21:29         ` Vladimir 'phcoder' Serbinenko
  2009-08-19 15:08         ` Robert Millan
  0 siblings, 2 replies; 22+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-07-26 16:20 UTC (permalink / raw)
  To: The development of GRUB 2

>> If I remember correctly, I had improved on the first patch to include
>> most of the remarks. I'll have a look if I can find back the modified
>> patch, and send it to the list for anyone to have it.
>>
>
> What is with his patch? Shouldn't we just send him an assigment?
> Adrian (the author of SGD) just mentioned on IRC that everyone tells him
> grub2 won't be used widely by distros without password support.
Yes. It's important. Quick look shows that this patch mainly deals
with passwords and totally neglects authentication framework. While it
already does password protection if later we want to extend support to
new primitives or even just. Once we have the framework implementing
particular authentication will be easy
>
> So it seems this is important to people.
> I try to look into this but I have the feeling that I'm not really the
> right person for this. Especially when we want something complete and
> extensible etc.
>
I think you underestimate yourself. Especially if we agree on function
propotypes you are completely able to implement. Discussing on IRC I
formulated 3 criteria which our system must satisfy:
(1) you can't access shell without authenticating as "superuser".
(2) boot some entries without authenticating as one of users (list of
allowed users may differ per menuentry)
(3) new autentication schemes (e.g. ssh keys) should be implementable as modules

I propose following implementation guidelines:
Syntax:
set superusers=root,gnu
password root "GRUB"
md5_password operator $MD5$MD5$MD5
fingeprint gnu /gnu.fp
menuentry "single mode" --users root,operator {
  ....
}

Wher user tries to authenticate GRUB2 will ask him login and then call
a function from module

Prototypes:
grub_err_t grub_auth_register_authentication (const char *user,
grub_err_t (*callback) (const char*, void *), void *arg);
this will ask to call callback if login is USER.
grub_err_t grub_auth_authenticate (const char *user);
grub_err_t grub_auth_deauthenticate (const char *user);
grub_err_t grub_auth_check_authentication (const char *userlist);

grub_auth_check_authentication will output login prompt if no user
from userlist is already authenticated
> --
> Felix Zielcke
> Proud Debian Maintainer
>
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>



-- 
Regards
Vladimir 'phcoder' Serbinenko

Personal git repository: http://repo.or.cz/w/grub2/phcoder.git



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-07-26 16:20       ` Vladimir 'phcoder' Serbinenko
@ 2009-07-26 21:29         ` Vladimir 'phcoder' Serbinenko
  2009-08-20 16:44           ` Robert Millan
  2009-08-19 15:08         ` Robert Millan
  1 sibling, 1 reply; 22+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-07-26 21:29 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 2936 bytes --]

On Sun, Jul 26, 2009 at 6:20 PM, Vladimir 'phcoder'
Serbinenko<phcoder@gmail.com> wrote:
>>> If I remember correctly, I had improved on the first patch to include
>>> most of the remarks. I'll have a look if I can find back the modified
>>> patch, and send it to the list for anyone to have it.
>>>
>>
>> What is with his patch? Shouldn't we just send him an assigment?
>> Adrian (the author of SGD) just mentioned on IRC that everyone tells him
>> grub2 won't be used widely by distros without password support.
> Yes. It's important. Quick look shows that this patch mainly deals
> with passwords and totally neglects authentication framework. While it
> already does password protection if later we want to extend support to
> new primitives or even just. Once we have the framework implementing
> particular authentication will be easy
>>
>> So it seems this is important to people.
>> I try to look into this but I have the feeling that I'm not really the
>> right person for this. Especially when we want something complete and
>> extensible etc.
>>
> I think you underestimate yourself. Especially if we agree on function
> propotypes you are completely able to implement. Discussing on IRC I
> formulated 3 criteria which our system must satisfy:
> (1) you can't access shell without authenticating as "superuser".
> (2) boot some entries without authenticating as one of users (list of
> allowed users may differ per menuentry)
> (3) new autentication schemes (e.g. ssh keys) should be implementable as modules
>
> I propose following implementation guidelines:
> Syntax:
> set superusers=root,gnu
> password root "GRUB"
> md5_password operator $MD5$MD5$MD5
> fingeprint gnu /gnu.fp
> menuentry "single mode" --users root,operator {
>  ....
> }
>
> Wher user tries to authenticate GRUB2 will ask him login and then call
> a function from module
>
> Prototypes:
> grub_err_t grub_auth_register_authentication (const char *user,
> grub_err_t (*callback) (const char*, void *), void *arg);
> this will ask to call callback if login is USER.
> grub_err_t grub_auth_authenticate (const char *user);
> grub_err_t grub_auth_deauthenticate (const char *user);
> grub_err_t grub_auth_check_authentication (const char *userlist);
>
> grub_auth_check_authentication will output login prompt if no user
> from userlist is already authenticated
As agreed with Felix I implemented the framework. See attached patch
>> --
>> Felix Zielcke
>> Proud Debian Maintainer
>>
>>
>>
>> _______________________________________________
>> Grub-devel mailing list
>> Grub-devel@gnu.org
>> http://lists.gnu.org/mailman/listinfo/grub-devel
>>
>
>
>
> --
> Regards
> Vladimir 'phcoder' Serbinenko
>
> Personal git repository: http://repo.or.cz/w/grub2/phcoder.git
>



-- 
Regards
Vladimir 'phcoder' Serbinenko

Personal git repository: http://repo.or.cz/w/grub2/phcoder.git

[-- Attachment #2: auth.diff --]
[-- Type: text/plain, Size: 18165 bytes --]

diff --git a/conf/common.rmk b/conf/common.rmk
index 032517f..f5843a7 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -503,7 +503,7 @@ probe_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # For normal.mod.
 normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \
-	normal/autofs.c normal/handler.c \
+	normal/auth.c normal/autofs.c normal/handler.c \
 	normal/color.c normal/completion.c normal/datetime.c normal/menu.c \
 	normal/menu_entry.c normal/menu_text.c normal/menu_viewer.c \
 	normal/misc.c
diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
index 7ba5737..6be465b 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -127,7 +127,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	kern/partition.c kern/reader.c kern/term.c			\
 	kern/rescue_reader.c kern/rescue_parser.c                       \
 	lib/arg.c normal/cmdline.c normal/misc.c			\
-	normal/handler.c normal/autofs.c				\
+	normal/handler.c normal/auth.c normal/autofs.c				\
 	normal/completion.c normal/datetime.c normal/main.c 		\
 	normal/menu_text.c						\
 	normal/menu.c normal/menu_entry.c normal/menu_viewer.c		\
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index 9177b9d..47b4508 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -54,7 +54,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	kern/partition.c kern/reader.c kern/term.c			\
 	kern/rescue_reader.c kern/rescue_parser.c                       \
 	lib/arg.c normal/cmdline.c normal/command.c normal/datetime.c 	\
-	normal/autofs.c							\
+	normal/auth.c normal/autofs.c							\
 	normal/completion.c normal/context.c normal/main.c		\
 	normal/menu.c normal/menu_entry.c normal/menu_viewer.c		\
 	normal/menu_text.c						\
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
index 0321979..9543a65 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -82,7 +82,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	kern/partition.c kern/reader.c kern/term.c			\
 	kern/rescue_reader.c kern/rescue_parser.c 			\
 	lib/arg.c normal/cmdline.c normal/datetime.c normal/misc.c	\
-	normal/handler.c normal/autofs.c				\
+	normal/handler.c normal/auth.c normal/autofs.c				\
 	normal/completion.c normal/main.c normal/menu_text.c		\
 	normal/menu.c normal/menu_entry.c normal/menu_viewer.c		\
 	normal/color.c							\
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 798aee2..6b827e3 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -136,7 +136,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	kern/partition.c kern/reader.c kern/term.c			\
 	kern/rescue_reader.c kern/rescue_parser.c			\
 	lib/arg.c normal/cmdline.c normal/datetime.c normal/misc.c	\
-	normal/handler.c normal/autofs.c				\
+	normal/handler.c normal/auth.c normal/autofs.c				\
 	normal/completion.c normal/main.c normal/color.c		\
 	normal/menu.c normal/menu_entry.c normal/menu_viewer.c		\
 	normal/menu_text.c						\
diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk
index af29d23..08c73b0 100644
--- a/conf/powerpc-ieee1275.rmk
+++ b/conf/powerpc-ieee1275.rmk
@@ -62,7 +62,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	kern/command.c kern/corecmd.c commands/extcmd.c			\
 	lib/arg.c normal/cmdline.c normal/datetime.c 			\
 	normal/completion.c normal/misc.c		 		\
-	normal/handler.c normal/autofs.c normal/main.c			\
+	normal/handler.c normal/auth.c normal/autofs.c normal/main.c			\
 	normal/menu.c 							\
 	normal/menu_text.c						\
 	normal/menu_entry.c normal/menu_viewer.c 	 		\
diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk
index aabccee..d61e97c 100644
--- a/conf/sparc64-ieee1275.rmk
+++ b/conf/sparc64-ieee1275.rmk
@@ -119,7 +119,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	kern/command.c kern/corecmd.c commands/extcmd.c			\
 	lib/arg.c normal/cmdline.c normal/datetime.c 			\
 	normal/completion.c normal/misc.c		 		\
-	normal/handler.c normal/autofs.c normal/main.c			\
+	normal/handler.c normal/auth.c normal/autofs.c normal/main.c			\
 	normal/menu.c 							\
 	normal/menu_text.c						\
 	normal/menu_entry.c normal/menu_viewer.c 	 		\
diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
index 21da0e1..57254c0 100644
--- a/conf/x86_64-efi.rmk
+++ b/conf/x86_64-efi.rmk
@@ -50,7 +50,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	kern/command.c kern/corecmd.c commands/extcmd.c kern/file.c 	\
 	kern/fs.c commands/boot.c kern/main.c kern/misc.c kern/parser.c	\
 	kern/partition.c kern/readerescue.c kern/term.c			\
-	lib/arg.c normal/cmdline.c normal/misc.c normal/autofs.c	\
+	lib/arg.c normal/cmdline.c normal/misc.c normal/auth.c normal/autofs.c	\
 	normal/completion.c normal/datetime.c normal/context.c 		\
 	normal/main.c		\
 	normal/menu.c normal/menu_entry.c normal/menu_viewer.c		\
diff --git a/include/grub/auth.h b/include/grub/auth.h
new file mode 100644
index 0000000..6a5d0b6
--- /dev/null
+++ b/include/grub/auth.h
@@ -0,0 +1,34 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  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 <http://www.gnu.org/licenses/>.
+ */
+#ifndef GRUB_AURH_HEADER
+#define GRUB_AUTH_HEADER	1
+
+#include <grub/err.h>
+
+typedef grub_err_t (*grub_auth_callback_t) (const char*, void *);
+
+grub_err_t grub_auth_register_authentication (const char *user,
+					      grub_auth_callback_t callback,
+					      void *arg);
+grub_err_t grub_auth_unregister_authentication (const char *user);
+
+grub_err_t grub_auth_authenticate (const char *user);
+grub_err_t grub_auth_deauthenticate (const char *user);
+grub_err_t grub_auth_check_authentication (const char *userlist);
+
+#endif /* ! GRUB_AUTH_HEADER */
diff --git a/include/grub/err.h b/include/grub/err.h
index 3435fb7..7a5ce1a 100644
--- a/include/grub/err.h
+++ b/include/grub/err.h
@@ -53,7 +53,8 @@ typedef enum
     GRUB_ERR_BAD_GZIP_DATA,
     GRUB_ERR_MENU,
     GRUB_ERR_TIMEOUT,
-    GRUB_ERR_IO
+    GRUB_ERR_IO,
+    GRUB_ERR_ACCESS_DENIED
   }
 grub_err_t;
 
diff --git a/include/grub/menu.h b/include/grub/menu.h
index 3bd25e8..70aa7fd 100644
--- a/include/grub/menu.h
+++ b/include/grub/menu.h
@@ -32,6 +32,9 @@ struct grub_menu_entry
   /* The title name.  */
   const char *title;
 
+  /* Allowed users. NULL means 'everybody'.  */
+  const char *users;
+
   /* The classes associated with the menu entry:
      used to choose an icon or other style attributes.
      This is a dummy head node for the linked list, so for an entry E,
diff --git a/include/grub/normal.h b/include/grub/normal.h
index 7d8122a..feebc85 100644
--- a/include/grub/normal.h
+++ b/include/grub/normal.h
@@ -56,7 +56,7 @@ void grub_cmdline_run (int nested);
 
 /* Defined in `cmdline.c'.  */
 int grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
-		      int echo_char, int readline);
+		      int echo_char, int readline, int history);
 grub_err_t grub_set_history (int newsize);
 
 /* Defined in `completion.c'.  */
diff --git a/normal/auth.c b/normal/auth.c
new file mode 100644
index 0000000..8633006
--- /dev/null
+++ b/normal/auth.c
@@ -0,0 +1,184 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/auth.h>
+#include <grub/list.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/normal.h>
+
+struct grub_auth_user
+{
+  struct grub_auth_user *next;
+  char *name;
+  grub_auth_callback_t callback;
+  void *arg;
+  int authenticated;
+};
+
+struct grub_auth_user *users = 0;
+
+grub_err_t 
+grub_auth_register_authentication (const char *user,
+				   grub_auth_callback_t callback,
+				   void *arg)
+{
+  struct grub_auth_user *cur;
+
+  cur = grub_named_list_find (GRUB_AS_NAMED_LIST (users), user);
+  if (!cur)
+    cur = grub_zalloc (sizeof (*cur));
+  if (!cur)
+    return grub_errno;
+  cur->callback = callback;
+  cur->arg = arg;
+  if (! cur->name)
+    {
+      cur->name = grub_strdup (user);
+      if (!cur->name)
+	{
+	  grub_free (cur);
+	  return grub_errno;
+	}
+      grub_list_push (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur));
+    }
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t 
+grub_auth_unregister_authentication (const char *user)
+{
+  struct grub_auth_user *cur;
+  cur = grub_named_list_find (GRUB_AS_NAMED_LIST (users), user);
+  if (!cur)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "user '%s' not found", user);
+  if (!cur->authenticated)
+    {
+      grub_free (cur->name);
+      grub_list_remove (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur));
+      grub_free (cur);
+    }
+  else
+    {
+      cur->callback = 0;
+      cur->arg = 0;
+    }
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t 
+grub_auth_authenticate (const char *user)
+{
+  struct grub_auth_user *cur;
+
+  cur = grub_named_list_find (GRUB_AS_NAMED_LIST (users), user);
+  if (!cur)
+    cur = grub_zalloc (sizeof (*cur));
+  if (!cur)
+    return grub_errno;
+
+  cur->authenticated = 1;
+
+  if (! cur->name)
+    {
+      cur->name = grub_strdup (user);
+      if (!cur->name)
+	{
+	  grub_free (cur);
+	  return grub_errno;
+	}
+      grub_list_push (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur));
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t 
+grub_auth_deauthenticate (const char *user)
+{
+  struct grub_auth_user *cur;
+  cur = grub_named_list_find (GRUB_AS_NAMED_LIST (users), user);
+  if (!cur)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "user '%s' not found", user);
+  if (!cur->callback)
+    {
+      grub_free (cur->name);
+      grub_list_remove (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur));
+      grub_free (cur);
+    }
+  else
+    cur->authenticated = 0;
+  return GRUB_ERR_NONE;
+}
+
+static int
+is_authenticated (const char *userlist)
+{
+  const char *superusers;
+
+  auto int hook (grub_list_t item);
+  int hook (grub_list_t item)
+  {
+    return (userlist && grub_strword (userlist,
+				      ((struct grub_auth_user *) item)->name))
+      || grub_strword (superusers, ((struct grub_auth_user *) item)->name);
+  }
+
+  superusers = grub_env_get ("superusers");
+  
+  if (!superusers)
+    return GRUB_ERR_NONE;
+
+  return grub_list_iterate (GRUB_AS_LIST (users), hook);
+}
+
+grub_err_t 
+grub_auth_check_authentication (const char *userlist)
+{
+  char login[1024] = {0};
+  struct grub_auth_user *cur = 0;
+  grub_err_t err;
+
+  auto int hook (grub_list_t item);
+  int hook (grub_list_t item)
+  {
+    if (grub_strcmp (login, ((struct grub_auth_user *) item)->name) == 0)
+      {
+	cur = (struct grub_auth_user *) item;
+	return 1;
+      }
+    return 0;
+  }
+
+  if (is_authenticated (userlist))
+    return GRUB_ERR_NONE;
+
+  if (!grub_cmdline_get ("Enter username: ", login, sizeof (login) - 1, 0, 0, 0))
+    return grub_error (GRUB_ERR_ACCESS_DENIED, "login aborted");
+
+  if (!grub_list_iterate (GRUB_AS_LIST (users), hook) || ! cur->callback)
+    {
+      /* XXX Show a fake password prompt*/
+      return grub_error (GRUB_ERR_ACCESS_DENIED, "password incorrect");      
+    }
+  err = cur->callback (login, cur->arg);
+  if (is_authenticated (userlist))
+    return GRUB_ERR_NONE;
+  return grub_error (GRUB_ERR_ACCESS_DENIED, "access denied");
+}
diff --git a/normal/cmdline.c b/normal/cmdline.c
index 9a07d7d..56f8921 100644
--- a/normal/cmdline.c
+++ b/normal/cmdline.c
@@ -181,7 +181,7 @@ print_completion (const char *item, grub_completion_type_t type, int count)
 /* FIXME: The dumb interface is not supported yet.  */
 int
 grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
-		  int echo_char, int readline)
+		  int echo_char, int readline, int history)
 {
   unsigned xpos, ypos, ystart;
   grub_size_t lpos, llen;
@@ -280,7 +280,7 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
 
   cl_insert (cmdline);
 
-  if (hist_used == 0)
+  if (history && hist_used == 0)
     grub_history_add (buf);
 
   while ((key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && key != '\r')
@@ -468,11 +468,14 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
     while (buf[lpos] == ' ')
       lpos++;
 
-  histpos = 0;
-  if (grub_strlen (buf) > 0)
+  if (history)
     {
-      grub_history_replace (histpos, buf);
-      grub_history_add ("");
+      histpos = 0;
+      if (grub_strlen (buf) > 0)
+	{
+	  grub_history_replace (histpos, buf);
+	  grub_history_add ("");
+	}
     }
 
   grub_memcpy (cmdline, buf + lpos, llen - lpos + 1);
diff --git a/normal/main.c b/normal/main.c
index 66d8418..b2029ce 100644
--- a/normal/main.c
+++ b/normal/main.c
@@ -28,6 +28,7 @@
 #include <grub/parser.h>
 #include <grub/reader.h>
 #include <grub/menu_viewer.h>
+#include <grub/auth.h>
 
 #define GRUB_DEFAULT_HISTORY_SIZE	50
 
@@ -164,6 +165,7 @@ grub_normal_add_menu_entry (int argc, const char **args,
   int i;
   struct grub_menu_entry_class *classes_head;  /* Dummy head node for list.  */
   struct grub_menu_entry_class *classes_tail;
+  char *users = 0;
 
   /* Allocate dummy head node for class list.  */
   classes_head = grub_zalloc (sizeof (struct grub_menu_entry_class));
@@ -218,6 +220,18 @@ grub_normal_add_menu_entry (int argc, const char **args,
 	      classes_tail = new_class;
 	      continue;
 	    }
+	  else if (grub_strcmp(arg, "users") == 0)
+	    {
+	      i++;
+	      users = grub_strdup (args[i]);
+	      if (! users)
+		{
+		  failed = 1;
+		  break;
+		}
+
+	      continue;
+	    }
 	  else
 	    {
 	      /* Handle invalid argument.  */
@@ -275,6 +289,7 @@ grub_normal_add_menu_entry (int argc, const char **args,
 
   (*last)->title = menutitle;
   (*last)->classes = classes_head;
+  (*last)->users = users;
   (*last)->sourcecode = menusourcecode;
 
   menu->size++;
@@ -465,7 +480,19 @@ quit:
 void
 grub_cmdline_run (int nested)
 {
-  grub_reader_t reader = grub_reader_get_current ();
+  grub_reader_t reader;
+  grub_err_t err = GRUB_ERR_NONE;
+
+  err = grub_auth_check_authentication (0);
+
+  if (err)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+      return;
+    }
+
+  reader = grub_reader_get_current ();
 
   reader_nested = nested;
   if (reader->init)
@@ -501,7 +528,7 @@ grub_normal_read_line (char **line, int cont)
   while (1)
     {
       cmdline[0] = 0;
-      if (grub_cmdline_get (prompt, cmdline, sizeof (cmdline), 0, 1))
+      if (grub_cmdline_get (prompt, cmdline, sizeof (cmdline), 0, 1, 1))
 	break;
 
       if ((reader_nested) || (cont))
diff --git a/normal/menu.c b/normal/menu.c
index 59ad83f..b9b7763 100644
--- a/normal/menu.c
+++ b/normal/menu.c
@@ -26,6 +26,7 @@
 #include <grub/menu_viewer.h>
 #include <grub/command.h>
 #include <grub/parser.h>
+#include <grub/auth.h>
 
 /* Get a menu entry by its index in the entry list.  */
 grub_menu_entry_t
@@ -124,6 +125,18 @@ get_and_remove_first_entry_number (const char *name)
 void
 grub_menu_execute_entry(grub_menu_entry_t entry)
 {
+  grub_err_t err = GRUB_ERR_NONE;
+
+  if (entry->users)
+    err = grub_auth_check_authentication (entry->users);
+
+  if (err)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+      return;
+    }
+
   grub_parser_execute ((char *) entry->sourcecode);
 
   if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
diff --git a/normal/menu_entry.c b/normal/menu_entry.c
index f7662ff..9505df0 100644
--- a/normal/menu_entry.c
+++ b/normal/menu_entry.c
@@ -23,6 +23,7 @@
 #include <grub/loader.h>
 #include <grub/command.h>
 #include <grub/parser.h>
+#include <grub/auth.h>
 
 enum update_mode
   {
@@ -1026,6 +1027,16 @@ grub_menu_entry_run (grub_menu_entry_t entry)
 {
   struct screen *screen;
   int prev_c;
+  grub_err_t err = GRUB_ERR_NONE;
+
+  err = grub_auth_check_authentication (0);
+
+  if (err)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+      return;
+    }
 
   screen = make_screen (entry);
   if (! screen)
diff --git a/normal/menu_viewer.c b/normal/menu_viewer.c
index 37d317b..ef715c9 100644
--- a/normal/menu_viewer.c
+++ b/normal/menu_viewer.c
@@ -21,6 +21,7 @@
 #include <grub/env.h>
 #include <grub/menu_viewer.h>
 #include <grub/menu.h>
+#include <grub/auth.h>
 
 /* The list of menu viewers.  */
 static grub_menu_viewer_t menu_viewer_list;
@@ -55,9 +56,24 @@ grub_err_t
 grub_menu_viewer_show_menu (grub_menu_t menu, int nested)
 {
   grub_menu_viewer_t cur = get_current_menu_viewer ();
+  grub_err_t err1, err2;
   if (!cur)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "No menu viewer available.");
 
-  return cur->show_menu (menu, nested);
+  while (1)
+    {
+      err1 = cur->show_menu (menu, nested);
+      grub_print_error ();
+
+      err2 = grub_auth_check_authentication (0);
+      if (err2)
+	{
+	  grub_print_error ();
+	  grub_errno = GRUB_ERR_NONE;
+	  continue;
+	}
+    }
+ 
+  return err1;
 }
 

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-07-26 16:20       ` Vladimir 'phcoder' Serbinenko
  2009-07-26 21:29         ` Vladimir 'phcoder' Serbinenko
@ 2009-08-19 15:08         ` Robert Millan
  2009-08-19 15:17           ` Vladimir 'phcoder' Serbinenko
  1 sibling, 1 reply; 22+ messages in thread
From: Robert Millan @ 2009-08-19 15:08 UTC (permalink / raw)
  To: The development of GRUB 2

On Sun, Jul 26, 2009 at 06:20:03PM +0200, Vladimir 'phcoder' Serbinenko wrote:
> I think you underestimate yourself. Especially if we agree on function
> propotypes you are completely able to implement. Discussing on IRC I
> formulated 3 criteria which our system must satisfy:
> (1) you can't access shell without authenticating as "superuser".
> (2) boot some entries without authenticating as one of users (list of
> allowed users may differ per menuentry)
> (3) new autentication schemes (e.g. ssh keys) should be implementable as modules
> 
> I propose following implementation guidelines:
> Syntax:
> set superusers=root,gnu
> password root "GRUB"
> md5_password operator $MD5$MD5$MD5
> fingeprint gnu /gnu.fp
> menuentry "single mode" --users root,operator {
>   ....
> }
> 
> Wher user tries to authenticate GRUB2 will ask him login and then call
> a function from module
> 
> Prototypes:
> grub_err_t grub_auth_register_authentication (const char *user,
> grub_err_t (*callback) (const char*, void *), void *arg);
> this will ask to call callback if login is USER.
> grub_err_t grub_auth_authenticate (const char *user);
> grub_err_t grub_auth_deauthenticate (const char *user);
> grub_err_t grub_auth_check_authentication (const char *userlist);
> 
> grub_auth_check_authentication will output login prompt if no user
> from userlist is already authenticated

I agree with this proposal in general.  Except with the concept of "users",
which I think might be overkill.  GRUB is not a Un*x with its /home and
per-user settings.  These passwords just protect resources, so I'm not sure
if there's a point in managing users as an intermediate layer between
passwords and the restricted resource.

What does everyone else think?

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-08-19 15:08         ` Robert Millan
@ 2009-08-19 15:17           ` Vladimir 'phcoder' Serbinenko
  2009-08-20 16:32             ` Robert Millan
  0 siblings, 1 reply; 22+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-08-19 15:17 UTC (permalink / raw)
  To: The development of GRUB 2

On Wed, Aug 19, 2009 at 5:08 PM, Robert Millan<rmh@aybabtu.com> wrote:
>
> I agree with this proposal in general.  Except with the concept of "users",
> which I think might be overkill.  GRUB is not a Un*x with its /home and
> per-user settings.  These passwords just protect resources, so I'm not sure
> if there's a point in managing users as an intermediate layer between
> passwords and the restricted resource.
The concept of users allows to use other authentication methods then
password. Consider a possibility of fingerprint authentications. 2
users needing superuser privilegies can share the same password but
have trouble sharing fingerprints. Another possibility is LUKS
authentication - user is considered ok if his password unlocks the
slot number N. If we ask users to share the same keyslot on luks we
get in the way of luks keyphrase revocation.
Additionally this simplifies the configuration as you don't need to
write password at every menuentry directive.
While the concept of users isn't strictly necessary it allows easy
management of multiple authentication methods and is really helpful
even  for just managing multiple passwords
>
> What does everyone else think?
>
> --
> Robert Millan
>
>  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
>  how) you may access your data; but nobody's threatening your freedom: we
>  still allow you to remove your data and not access it at all."
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>



-- 
Regards
Vladimir 'phcoder' Serbinenko

Personal git repository: http://repo.or.cz/w/grub2/phcoder.git



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-08-19 15:17           ` Vladimir 'phcoder' Serbinenko
@ 2009-08-20 16:32             ` Robert Millan
  0 siblings, 0 replies; 22+ messages in thread
From: Robert Millan @ 2009-08-20 16:32 UTC (permalink / raw)
  To: The development of GRUB 2

On Wed, Aug 19, 2009 at 05:17:13PM +0200, Vladimir 'phcoder' Serbinenko wrote:
> On Wed, Aug 19, 2009 at 5:08 PM, Robert Millan<rmh@aybabtu.com> wrote:
> >
> > I agree with this proposal in general.  Except with the concept of "users",
> > which I think might be overkill.  GRUB is not a Un*x with its /home and
> > per-user settings.  These passwords just protect resources, so I'm not sure
> > if there's a point in managing users as an intermediate layer between
> > passwords and the restricted resource.
> The concept of users allows to use other authentication methods then
> password. Consider a possibility of fingerprint authentications. 2
> users needing superuser privilegies can share the same password but
> have trouble sharing fingerprints. Another possibility is LUKS
> authentication - user is considered ok if his password unlocks the
> slot number N. If we ask users to share the same keyslot on luks we
> get in the way of luks keyphrase revocation.
> Additionally this simplifies the configuration as you don't need to
> write password at every menuentry directive.
> While the concept of users isn't strictly necessary it allows easy
> management of multiple authentication methods and is really helpful
> even  for just managing multiple passwords

Ok.  Then it might be a good thing to have those in our current model, even
if we don't support fingerprints yet.

I'm fine with the proposed design.

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-07-26 21:29         ` Vladimir 'phcoder' Serbinenko
@ 2009-08-20 16:44           ` Robert Millan
  2009-08-21 11:30             ` Vladimir 'phcoder' Serbinenko
  0 siblings, 1 reply; 22+ messages in thread
From: Robert Millan @ 2009-08-20 16:44 UTC (permalink / raw)
  To: The development of GRUB 2

On Sun, Jul 26, 2009 at 11:29:01PM +0200, Vladimir 'phcoder' Serbinenko wrote:
> +  /* Allowed users. NULL means 'everybody'.  */
> +  const char *users;

This sounds dangerous: it is easy to make a mistake in code that e.g.
removes a user from this list.

The "natural" meaning of an empty OR list is false.  Why not make NULL
mean `nobody' instead?

> +grub_err_t 
> +grub_auth_check_authentication (const char *userlist)
> +{
> +  char login[1024] = {0};

Please avoid arbitrary limits.  If the grub_cmdline_get() API is enforcing
them, then this function is wrong and should be using malloc() instead (like,
say, getline() or asprintf() do).

> +  if (!grub_cmdline_get ("Enter username: ", login, sizeof (login) - 1, 0, 0, 0))
> +    return grub_error (GRUB_ERR_ACCESS_DENIED, "login aborted");
> +
> +  if (!grub_list_iterate (GRUB_AS_LIST (users), hook) || ! cur->callback)
> +    {
> +      /* XXX Show a fake password prompt*/
> +      return grub_error (GRUB_ERR_ACCESS_DENIED, "password incorrect");      
> +    }
> +  err = cur->callback (login, cur->arg);
> +  if (is_authenticated (userlist))
> +    return GRUB_ERR_NONE;
> +  return grub_error (GRUB_ERR_ACCESS_DENIED, "access denied");

Please capitalize user messages.

> @@ -164,6 +165,7 @@ grub_normal_add_menu_entry (int argc, const char **args,
>    int i;
>    struct grub_menu_entry_class *classes_head;  /* Dummy head node for list.  */
>    struct grub_menu_entry_class *classes_tail;
> +  char *users = 0;

Please use `NULL' for pointers (see below).

> +  err = grub_auth_check_authentication (0);
> [...]
> +    err = grub_auth_check_authentication (entry->users);

This is an example on why using 0 for pointers is confusing.  When I read
the first line, since I didn't know the declaration of
grub_auth_check_authentication(), this lead me to think its parameter is some
sort of boolean or enum.  Had `NULL' been used instead, I'd inmediately notice
it's actually a data structure.

When you're already familiar with the code, it doesn't matter, but for everyone
else it makes things easier to figure out (which helps lowering the entry
barrier to GRUB hacking).

>  grub_menu_viewer_show_menu (grub_menu_t menu, int nested)
>  {
>    grub_menu_viewer_t cur = get_current_menu_viewer ();
> +  grub_err_t err1, err2;
>    if (!cur)
>      return grub_error (GRUB_ERR_BAD_ARGUMENT, "No menu viewer available.");
>  
> -  return cur->show_menu (menu, nested);
> +  while (1)
> +    {
> +      err1 = cur->show_menu (menu, nested);
> +      grub_print_error ();
> +
> +      err2 = grub_auth_check_authentication (0);
> +      if (err2)
> +	{
> +	  grub_print_error ();
> +	  grub_errno = GRUB_ERR_NONE;
> +	  continue;
> +	}
> +    }
> + 
> +  return err1;
>  }

How do you exit this loop?  Or is it intentional that it can't be exitted?
(in the latter case, a comment would help).

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-08-20 16:44           ` Robert Millan
@ 2009-08-21 11:30             ` Vladimir 'phcoder' Serbinenko
  2009-08-22 19:47               ` Vladimir 'phcoder' Serbinenko
  2009-08-23 10:14               ` Robert Millan
  0 siblings, 2 replies; 22+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-08-21 11:30 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 726 bytes --]

>
>> +grub_err_t
>> +grub_auth_check_authentication (const char *userlist)
>> +{
>> +  char login[1024] = {0};
>
> Please avoid arbitrary limits.  If the grub_cmdline_get() API is enforcing
> them, then this function is wrong and should be using malloc() instead (like,
> say, getline() or asprintf() do).
>

If user has a username longer than 1K it can mean only that he is
trying to execute buffer overflow.

New patch. This time with password command (plaintext).
Beware that I haven't reread patch myself yet and until I do so AND
it's reviewed by other people it can't pretend to be secure.

-- 
Regards
Vladimir 'phcoder' Serbinenko

Personal git repository: http://repo.or.cz/w/grub2/phcoder.git

[-- Attachment #2: auth.diff --]
[-- Type: text/plain, Size: 25430 bytes --]

diff --git a/commands/password.c b/commands/password.c
new file mode 100644
index 0000000..0c0cd6c
--- /dev/null
+++ b/commands/password.c
@@ -0,0 +1,84 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/auth.h>
+#include <grub/list.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+
+static grub_dl_t my_mod;
+
+static grub_err_t
+check_password (const char *user,
+		void *password)
+{
+  char entered[1024] = {0};
+
+  if (!GRUB_GET_PASSWORD (entered, sizeof (entered) - 1))
+    return GRUB_ACCESS_DENIED;
+
+  if (grub_auth_strcmp (entered, password) != 0)
+    return GRUB_ACCESS_DENIED;
+
+  grub_auth_authenticate (user);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
+		   int argc, char **args)
+{
+  grub_err_t err;
+  char *pass;
+
+  if (argc != 2)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Two arguments expected.");
+
+  pass = grub_strdup (args[1]);
+  if (!pass)
+    return grub_errno;
+
+  err = grub_auth_register_authentication (args[0], check_password, pass);
+  if (err)
+    {
+      grub_free (pass);
+      return err;
+    }
+  grub_dl_ref (my_mod);
+  return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd;
+\f
+GRUB_MOD_INIT(password)
+{
+  my_mod = mod;
+  cmd = grub_register_command ("password", grub_cmd_password,
+			       "password USER PASSWORD",
+			       "Set user password (plaintext). "
+			       "Unrecommended and insecure.");
+}
+
+GRUB_MOD_FINI(password)
+{
+  grub_unregister_command (cmd);
+}
diff --git a/conf/common.rmk b/conf/common.rmk
index b0d3785..db7fa1a 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -364,7 +364,12 @@ pkglib_MODULES += minicmd.mod extcmd.mod hello.mod handler.mod	\
 	terminfo.mod test.mod blocklist.mod hexdump.mod		\
 	read.mod sleep.mod loadenv.mod crc.mod parttool.mod	\
 	pcpart.mod memrw.mod normal.mod sh.mod lua.mod	\
-	gptsync.mod true.mod probe.mod
+	gptsync.mod true.mod probe.mod password.mod
+
+# For password.mod.
+password_mod_SOURCES = commands/password.c
+password_mod_CFLAGS = $(COMMON_CFLAGS)
+password_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # For gptsync.mod.
 gptsync_mod_SOURCES = commands/gptsync.c
@@ -508,7 +513,7 @@ probe_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # For normal.mod.
 normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \
-	normal/autofs.c normal/handler.c \
+	normal/auth.c normal/autofs.c normal/handler.c \
 	normal/color.c normal/completion.c normal/datetime.c normal/menu.c \
 	normal/menu_entry.c normal/menu_text.c normal/menu_viewer.c \
 	normal/misc.c
diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
index ce2576b..74f8217 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -110,6 +110,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	commands/handler.c commands/ls.c commands/test.c 		\
 	commands/search.c commands/blocklist.c commands/hexdump.c	\
 	commands/gptsync.c commands/probe.c commands/xnu_uuid.c		\
+	commands/password.c						\
 	lib/hexdump.c commands/i386/cpuid.c				\
 	disk/host.c disk/loopback.c					\
 	\
@@ -127,7 +128,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	kern/partition.c kern/reader.c kern/term.c			\
 	kern/rescue_reader.c kern/rescue_parser.c                       \
 	lib/arg.c normal/cmdline.c normal/misc.c			\
-	normal/handler.c normal/autofs.c				\
+	normal/handler.c normal/auth.c normal/autofs.c			\
 	normal/completion.c normal/datetime.c normal/main.c 		\
 	normal/menu_text.c						\
 	normal/menu.c normal/menu_entry.c normal/menu_viewer.c		\
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index 6e3cbcf..9b8819f 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -39,6 +39,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	commands/search.c commands/hexdump.c lib/hexdump.c		\
 	commands/halt.c commands/reboot.c				\
 	commands/i386/cpuid.c						\
+	commands/password.c						\
 	disk/loopback.c							\
 	\
 	fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c			\
@@ -54,7 +55,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	kern/partition.c kern/reader.c kern/term.c			\
 	kern/rescue_reader.c kern/rescue_parser.c                       \
 	lib/arg.c normal/cmdline.c normal/command.c normal/datetime.c 	\
-	normal/autofs.c							\
+	normal/auth.c normal/autofs.c					\
 	normal/completion.c normal/context.c normal/main.c		\
 	normal/menu.c normal/menu_entry.c normal/menu_viewer.c		\
 	normal/menu_text.c						\
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
index 65d1c6b..7858df7 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -66,6 +66,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	lib/hexdump.c commands/halt.c commands/reboot.c			\
 	commands/gptsync.c commands/probe.c  commands/xnu_uuid.c	\
 	commands/i386/cpuid.c	\
+	commands/password.c						\
 	disk/host.c disk/loopback.c					\
 	\
 	fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c			\
@@ -82,7 +83,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	kern/partition.c kern/reader.c kern/term.c			\
 	kern/rescue_reader.c kern/rescue_parser.c 			\
 	lib/arg.c normal/cmdline.c normal/datetime.c normal/misc.c	\
-	normal/handler.c normal/autofs.c				\
+	normal/handler.c normal/auth.c normal/autofs.c			\
 	normal/completion.c normal/main.c normal/menu_text.c		\
 	normal/menu.c normal/menu_entry.c normal/menu_viewer.c		\
 	normal/color.c							\
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 0ef5e47..2655772 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -123,6 +123,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	lib/hexdump.c commands/i386/pc/halt.c commands/reboot.c		\
 	commands/gptsync.c commands/probe.c commands/xnu_uuid.c		\
 	commands/i386/cpuid.c	\
+	commands/password.c						\
 	disk/host.c disk/loopback.c disk/scsi.c				\
 	fs/fshelp.c 	\
 	\
@@ -134,7 +135,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	kern/partition.c kern/reader.c kern/term.c			\
 	kern/rescue_reader.c kern/rescue_parser.c			\
 	lib/arg.c normal/cmdline.c normal/datetime.c normal/misc.c	\
-	normal/handler.c normal/autofs.c				\
+	normal/handler.c normal/auth.c normal/autofs.c				\
 	normal/completion.c normal/main.c normal/color.c		\
 	normal/menu.c normal/menu_entry.c normal/menu_viewer.c		\
 	normal/menu_text.c						\
diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk
index c30f61a..10935cb 100644
--- a/conf/powerpc-ieee1275.rmk
+++ b/conf/powerpc-ieee1275.rmk
@@ -46,6 +46,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	commands/ls.c commands/blocklist.c commands/hexdump.c		\
 	lib/hexdump.c commands/halt.c commands/reboot.c 		\
 	commands/gptsync.c commands/probe.c commands/xnu_uuid.c		\
+	commands/password.c						\
 	disk/loopback.c							\
 	\
 	fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c			\
@@ -62,7 +63,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	kern/command.c kern/corecmd.c commands/extcmd.c			\
 	lib/arg.c normal/cmdline.c normal/datetime.c 			\
 	normal/completion.c normal/misc.c		 		\
-	normal/handler.c normal/autofs.c normal/main.c			\
+	normal/handler.c normal/auth.c normal/autofs.c normal/main.c	\
 	normal/menu.c 							\
 	normal/menu_text.c						\
 	normal/menu_entry.c normal/menu_viewer.c 	 		\
diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk
index b26496d..c90f305 100644
--- a/conf/sparc64-ieee1275.rmk
+++ b/conf/sparc64-ieee1275.rmk
@@ -103,6 +103,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	commands/ls.c commands/blocklist.c commands/hexdump.c		\
 	lib/hexdump.c commands/halt.c commands/reboot.c 		\
 	commands/gptsync.c commands/probe.c commands/xnu_uuid.c		\
+	commands/password.c						\
 	disk/loopback.c							\
 	\
 	fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c			\
@@ -119,7 +120,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	kern/command.c kern/corecmd.c commands/extcmd.c			\
 	lib/arg.c normal/cmdline.c normal/datetime.c 			\
 	normal/completion.c normal/misc.c		 		\
-	normal/handler.c normal/autofs.c normal/main.c			\
+	normal/handler.c normal/auth.c normal/autofs.c normal/main.c	\
 	normal/menu.c 							\
 	normal/menu_text.c						\
 	normal/menu_entry.c normal/menu_viewer.c 	 		\
diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
index 71a90ce..1fd9407 100644
--- a/conf/x86_64-efi.rmk
+++ b/conf/x86_64-efi.rmk
@@ -37,6 +37,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	commands/search.c commands/hexdump.c lib/hexdump.c		\
 	commands/halt.c commands/reboot.c				\
 	commands/i386/cpuid.c						\
+	commands/password.c						\
 	disk/loopback.c							\
 	\
 	fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c			\
@@ -50,7 +51,8 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	kern/command.c kern/corecmd.c commands/extcmd.c kern/file.c 	\
 	kern/fs.c commands/boot.c kern/main.c kern/misc.c kern/parser.c	\
 	kern/partition.c kern/readerescue.c kern/term.c			\
-	lib/arg.c normal/cmdline.c normal/misc.c normal/autofs.c	\
+	lib/arg.c normal/cmdline.c normal/misc.c normal/auth.c		\
+	normal/autofs.c	\
 	normal/completion.c normal/datetime.c normal/context.c 		\
 	normal/main.c		\
 	normal/menu.c normal/menu_entry.c normal/menu_viewer.c		\
diff --git a/include/grub/auth.h b/include/grub/auth.h
new file mode 100644
index 0000000..da930ee
--- /dev/null
+++ b/include/grub/auth.h
@@ -0,0 +1,45 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  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 <http://www.gnu.org/licenses/>.
+ */
+#ifndef GRUB_AURH_HEADER
+#define GRUB_AUTH_HEADER	1
+
+#include <grub/err.h>
+
+/* Macros for indistinguishibility.  */
+#define GRUB_ACCESS_DENIED grub_error (GRUB_ERR_ACCESS_DENIED, "Access denied.")
+#define GRUB_GET_PASSWORD(string, len) grub_cmdline_get ("Enter password: ", \
+							 string, len,	\
+							 '*', 0, 0)
+
+/* Like strcmp but untimeable. Accepts NULL as second argument.  */
+int grub_auth_strcmp (const char *user_input, const char *template);
+/* Like strcmp but untimeable and ignores commas in needle.  */
+int grub_auth_strword (const char *haystack, const char *needle);
+
+typedef grub_err_t (*grub_auth_callback_t) (const char*, void *);
+
+grub_err_t grub_auth_register_authentication (const char *user,
+					      grub_auth_callback_t callback,
+					      void *arg);
+grub_err_t grub_auth_unregister_authentication (const char *user);
+
+grub_err_t grub_auth_authenticate (const char *user);
+grub_err_t grub_auth_deauthenticate (const char *user);
+grub_err_t grub_auth_check_authentication (const char *userlist);
+
+#endif /* ! GRUB_AUTH_HEADER */
diff --git a/include/grub/err.h b/include/grub/err.h
index 3435fb7..7a5ce1a 100644
--- a/include/grub/err.h
+++ b/include/grub/err.h
@@ -53,7 +53,8 @@ typedef enum
     GRUB_ERR_BAD_GZIP_DATA,
     GRUB_ERR_MENU,
     GRUB_ERR_TIMEOUT,
-    GRUB_ERR_IO
+    GRUB_ERR_IO,
+    GRUB_ERR_ACCESS_DENIED
   }
 grub_err_t;
 
diff --git a/include/grub/menu.h b/include/grub/menu.h
index 3bd25e8..c7114a9 100644
--- a/include/grub/menu.h
+++ b/include/grub/menu.h
@@ -32,6 +32,12 @@ struct grub_menu_entry
   /* The title name.  */
   const char *title;
 
+  /* If set means not everybody is allowed to boot this entry.  */
+  int restricted;
+
+  /* Allowed users.  */
+  const char *users;
+
   /* The classes associated with the menu entry:
      used to choose an icon or other style attributes.
      This is a dummy head node for the linked list, so for an entry E,
diff --git a/include/grub/normal.h b/include/grub/normal.h
index 7d8122a..feebc85 100644
--- a/include/grub/normal.h
+++ b/include/grub/normal.h
@@ -56,7 +56,7 @@ void grub_cmdline_run (int nested);
 
 /* Defined in `cmdline.c'.  */
 int grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
-		      int echo_char, int readline);
+		      int echo_char, int readline, int history);
 grub_err_t grub_set_history (int newsize);
 
 /* Defined in `completion.c'.  */
diff --git a/normal/auth.c b/normal/auth.c
new file mode 100644
index 0000000..5431d58
--- /dev/null
+++ b/normal/auth.c
@@ -0,0 +1,254 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/auth.h>
+#include <grub/list.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/normal.h>
+
+struct grub_auth_user
+{
+  struct grub_auth_user *next;
+  char *name;
+  grub_auth_callback_t callback;
+  void *arg;
+  int authenticated;
+};
+
+struct grub_auth_user *users = NULL;
+
+int
+grub_auth_strcmp (const char *user_input, const char *template)
+{
+  int ok = 1;
+  const char *ptr1, *ptr2;
+  for (ptr1 = user_input, ptr2 = template; *ptr1; ptr1++)
+    if (*ptr1 == (ptr2 ? *ptr2 : ptr1[1]) && ok && ptr2 != NULL)
+      ptr2++;
+    else
+      ok = 0;
+
+  return !ok;
+}
+
+int
+grub_auth_strword (const char *haystack, const char *needle)
+{
+  const char *n_pos = needle;
+  int found = 0;
+
+  while (grub_iswordseparator (*haystack))
+    haystack++;
+
+  while (*haystack)
+    {
+      int ok = 1;
+      /* Crawl both the needle and the haystack word we're on.  */
+      while(*haystack && !grub_iswordseparator (*haystack))
+        {
+	  if (*haystack == *n_pos && ok)
+	    n_pos++;
+	  else
+	    ok = 0;
+
+          haystack++;
+        }
+
+      if (ok)
+	found = 1;
+    }
+
+  return found;
+}
+
+grub_err_t
+grub_auth_register_authentication (const char *user,
+				   grub_auth_callback_t callback,
+				   void *arg)
+{
+  struct grub_auth_user *cur;
+
+  cur = grub_named_list_find (GRUB_AS_NAMED_LIST (users), user);
+  if (!cur)
+    cur = grub_zalloc (sizeof (*cur));
+  if (!cur)
+    return grub_errno;
+  cur->callback = callback;
+  cur->arg = arg;
+  if (! cur->name)
+    {
+      cur->name = grub_strdup (user);
+      if (!cur->name)
+	{
+	  grub_free (cur);
+	  return grub_errno;
+	}
+      grub_list_push (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur));
+    }
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_auth_unregister_authentication (const char *user)
+{
+  struct grub_auth_user *cur;
+  cur = grub_named_list_find (GRUB_AS_NAMED_LIST (users), user);
+  if (!cur)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "user '%s' not found", user);
+  if (!cur->authenticated)
+    {
+      grub_free (cur->name);
+      grub_list_remove (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur));
+      grub_free (cur);
+    }
+  else
+    {
+      cur->callback = NULL;
+      cur->arg = NULL;
+    }
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_auth_authenticate (const char *user)
+{
+  struct grub_auth_user *cur;
+
+  cur = grub_named_list_find (GRUB_AS_NAMED_LIST (users), user);
+  if (!cur)
+    cur = grub_zalloc (sizeof (*cur));
+  if (!cur)
+    return grub_errno;
+
+  cur->authenticated = 1;
+
+  if (! cur->name)
+    {
+      cur->name = grub_strdup (user);
+      if (!cur->name)
+	{
+	  grub_free (cur);
+	  return grub_errno;
+	}
+      grub_list_push (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur));
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_auth_deauthenticate (const char *user)
+{
+  struct grub_auth_user *cur;
+  cur = grub_named_list_find (GRUB_AS_NAMED_LIST (users), user);
+  if (!cur)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "user '%s' not found", user);
+  if (!cur->callback)
+    {
+      grub_free (cur->name);
+      grub_list_remove (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur));
+      grub_free (cur);
+    }
+  else
+    cur->authenticated = 0;
+  return GRUB_ERR_NONE;
+}
+
+static int
+is_authenticated (const char *userlist)
+{
+  const char *superusers;
+
+  auto int hook (grub_list_t item);
+  int hook (grub_list_t item)
+  {
+    const char *name;
+    if (!((struct grub_auth_user *) item)->authenticated)
+      return 0;
+    name = ((struct grub_auth_user *) item)->name;
+
+    return (userlist && grub_auth_strword (userlist, name))
+      || grub_auth_strword (superusers, name);
+  }
+
+  superusers = grub_env_get ("superusers");
+
+  if (!superusers)
+    return GRUB_ERR_NONE;
+
+  return grub_list_iterate (GRUB_AS_LIST (users), hook);
+}
+
+grub_err_t
+grub_auth_check_authentication (const char *userlist)
+{
+  char login[1024] = {0};
+  struct grub_auth_user *cur = NULL;
+  grub_err_t err;
+
+  auto int hook (grub_list_t item);
+  int hook (grub_list_t item)
+  {
+    if (grub_auth_strcmp (login, ((struct grub_auth_user *) item)->name) == 0)
+      {
+	cur = (struct grub_auth_user *) item;
+	return 1;
+      }
+    return 0;
+  }
+
+  auto int hook_any (grub_list_t item);
+  int hook_any (grub_list_t item)
+  {
+    if (((struct grub_auth_user *) item)->callback)
+      {
+	cur = (struct grub_auth_user *) item;
+	return 1;
+      }
+    return 0;
+  }
+
+  if (is_authenticated (userlist))
+    return GRUB_ERR_NONE;
+
+  if (!grub_cmdline_get ("Enter username: ", login, sizeof (login) - 1,
+			 0, 0, 0))
+    return GRUB_ACCESS_DENIED;
+
+  grub_list_iterate (GRUB_AS_LIST (users), hook);
+
+  if (!cur || ! cur->callback)
+    {
+      grub_list_iterate (GRUB_AS_LIST (users), hook_any);
+
+      /* No users present at all.  */
+      if (!cur)
+	return GRUB_ACCESS_DENIED;
+
+      /* Display any of available authentication schemes.  */
+      err = cur->callback (login, 0);
+
+      return GRUB_ACCESS_DENIED;
+    }
+  err = cur->callback (login, cur->arg);
+  if (is_authenticated (userlist))
+    return GRUB_ERR_NONE;
+  return GRUB_ACCESS_DENIED;
+}
diff --git a/normal/cmdline.c b/normal/cmdline.c
index 9a07d7d..56f8921 100644
--- a/normal/cmdline.c
+++ b/normal/cmdline.c
@@ -181,7 +181,7 @@ print_completion (const char *item, grub_completion_type_t type, int count)
 /* FIXME: The dumb interface is not supported yet.  */
 int
 grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
-		  int echo_char, int readline)
+		  int echo_char, int readline, int history)
 {
   unsigned xpos, ypos, ystart;
   grub_size_t lpos, llen;
@@ -280,7 +280,7 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
 
   cl_insert (cmdline);
 
-  if (hist_used == 0)
+  if (history && hist_used == 0)
     grub_history_add (buf);
 
   while ((key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && key != '\r')
@@ -468,11 +468,14 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
     while (buf[lpos] == ' ')
       lpos++;
 
-  histpos = 0;
-  if (grub_strlen (buf) > 0)
+  if (history)
     {
-      grub_history_replace (histpos, buf);
-      grub_history_add ("");
+      histpos = 0;
+      if (grub_strlen (buf) > 0)
+	{
+	  grub_history_replace (histpos, buf);
+	  grub_history_add ("");
+	}
     }
 
   grub_memcpy (cmdline, buf + lpos, llen - lpos + 1);
diff --git a/normal/main.c b/normal/main.c
index 66d8418..748eef8 100644
--- a/normal/main.c
+++ b/normal/main.c
@@ -28,6 +28,7 @@
 #include <grub/parser.h>
 #include <grub/reader.h>
 #include <grub/menu_viewer.h>
+#include <grub/auth.h>
 
 #define GRUB_DEFAULT_HISTORY_SIZE	50
 
@@ -164,6 +165,7 @@ grub_normal_add_menu_entry (int argc, const char **args,
   int i;
   struct grub_menu_entry_class *classes_head;  /* Dummy head node for list.  */
   struct grub_menu_entry_class *classes_tail;
+  char *users = NULL;
 
   /* Allocate dummy head node for class list.  */
   classes_head = grub_zalloc (sizeof (struct grub_menu_entry_class));
@@ -218,6 +220,18 @@ grub_normal_add_menu_entry (int argc, const char **args,
 	      classes_tail = new_class;
 	      continue;
 	    }
+	  else if (grub_strcmp(arg, "users") == 0)
+	    {
+	      i++;
+	      users = grub_strdup (args[i]);
+	      if (! users)
+		{
+		  failed = 1;
+		  break;
+		}
+
+	      continue;
+	    }
 	  else
 	    {
 	      /* Handle invalid argument.  */
@@ -275,6 +289,9 @@ grub_normal_add_menu_entry (int argc, const char **args,
 
   (*last)->title = menutitle;
   (*last)->classes = classes_head;
+  if (users)
+    (*last)->restricted = 1;
+  (*last)->users = users;
   (*last)->sourcecode = menusourcecode;
 
   menu->size++;
@@ -465,7 +482,19 @@ quit:
 void
 grub_cmdline_run (int nested)
 {
-  grub_reader_t reader = grub_reader_get_current ();
+  grub_reader_t reader;
+  grub_err_t err = GRUB_ERR_NONE;
+
+  err = grub_auth_check_authentication (NULL);
+
+  if (err)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+      return;
+    }
+
+  reader = grub_reader_get_current ();
 
   reader_nested = nested;
   if (reader->init)
@@ -501,7 +530,7 @@ grub_normal_read_line (char **line, int cont)
   while (1)
     {
       cmdline[0] = 0;
-      if (grub_cmdline_get (prompt, cmdline, sizeof (cmdline), 0, 1))
+      if (grub_cmdline_get (prompt, cmdline, sizeof (cmdline), 0, 1, 1))
 	break;
 
       if ((reader_nested) || (cont))
diff --git a/normal/menu.c b/normal/menu.c
index 59ad83f..8ee7d1c 100644
--- a/normal/menu.c
+++ b/normal/menu.c
@@ -26,6 +26,7 @@
 #include <grub/menu_viewer.h>
 #include <grub/command.h>
 #include <grub/parser.h>
+#include <grub/auth.h>
 
 /* Get a menu entry by its index in the entry list.  */
 grub_menu_entry_t
@@ -124,6 +125,18 @@ get_and_remove_first_entry_number (const char *name)
 void
 grub_menu_execute_entry(grub_menu_entry_t entry)
 {
+  grub_err_t err = GRUB_ERR_NONE;
+
+  if (entry->restricted)
+    err = grub_auth_check_authentication (entry->users);
+
+  if (err)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+      return;
+    }
+
   grub_parser_execute ((char *) entry->sourcecode);
 
   if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
diff --git a/normal/menu_entry.c b/normal/menu_entry.c
index f7662ff..75a6377 100644
--- a/normal/menu_entry.c
+++ b/normal/menu_entry.c
@@ -23,6 +23,7 @@
 #include <grub/loader.h>
 #include <grub/command.h>
 #include <grub/parser.h>
+#include <grub/auth.h>
 
 enum update_mode
   {
@@ -1026,6 +1027,16 @@ grub_menu_entry_run (grub_menu_entry_t entry)
 {
   struct screen *screen;
   int prev_c;
+  grub_err_t err = GRUB_ERR_NONE;
+
+  err = grub_auth_check_authentication (NULL);
+
+  if (err)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+      return;
+    }
 
   screen = make_screen (entry);
   if (! screen)
diff --git a/normal/menu_viewer.c b/normal/menu_viewer.c
index 37d317b..1bd271a 100644
--- a/normal/menu_viewer.c
+++ b/normal/menu_viewer.c
@@ -21,6 +21,7 @@
 #include <grub/env.h>
 #include <grub/menu_viewer.h>
 #include <grub/menu.h>
+#include <grub/auth.h>
 
 /* The list of menu viewers.  */
 static grub_menu_viewer_t menu_viewer_list;
@@ -55,9 +56,26 @@ grub_err_t
 grub_menu_viewer_show_menu (grub_menu_t menu, int nested)
 {
   grub_menu_viewer_t cur = get_current_menu_viewer ();
+  grub_err_t err1, err2;
   if (!cur)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "No menu viewer available.");
 
-  return cur->show_menu (menu, nested);
+  while (1)
+    {
+      err1 = cur->show_menu (menu, nested);
+      grub_print_error ();
+
+      err2 = grub_auth_check_authentication (NULL);
+      if (err2)
+	{
+	  grub_print_error ();
+	  grub_errno = GRUB_ERR_NONE;
+	  continue;
+	}
+
+      break;
+    }
+
+  return err1;
 }
 

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-08-21 11:30             ` Vladimir 'phcoder' Serbinenko
@ 2009-08-22 19:47               ` Vladimir 'phcoder' Serbinenko
  2009-08-23 10:14               ` Robert Millan
  1 sibling, 0 replies; 22+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-08-22 19:47 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 1030 bytes --]

Updated. one bug fixed and now compileable with Apple's CC

On Fri, Aug 21, 2009 at 1:30 PM, Vladimir 'phcoder'
Serbinenko<phcoder@gmail.com> wrote:
>>
>>> +grub_err_t
>>> +grub_auth_check_authentication (const char *userlist)
>>> +{
>>> +  char login[1024] = {0};
>>
>> Please avoid arbitrary limits.  If the grub_cmdline_get() API is enforcing
>> them, then this function is wrong and should be using malloc() instead (like,
>> say, getline() or asprintf() do).
>>
>
> If user has a username longer than 1K it can mean only that he is
> trying to execute buffer overflow.
>
> New patch. This time with password command (plaintext).
> Beware that I haven't reread patch myself yet and until I do so AND
> it's reviewed by other people it can't pretend to be secure.
>
> --
> Regards
> Vladimir 'phcoder' Serbinenko
>
> Personal git repository: http://repo.or.cz/w/grub2/phcoder.git
>



-- 
Regards
Vladimir 'phcoder' Serbinenko

Personal git repository: http://repo.or.cz/w/grub2/phcoder.git

[-- Attachment #2: auth.diff --]
[-- Type: text/plain, Size: 25500 bytes --]

diff --git a/commands/password.c b/commands/password.c
new file mode 100644
index 0000000..0e04879
--- /dev/null
+++ b/commands/password.c
@@ -0,0 +1,86 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/auth.h>
+#include <grub/list.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+
+static grub_dl_t my_mod;
+
+static grub_err_t
+check_password (const char *user,
+		void *password)
+{
+  char entered[1024];
+
+  grub_memset (entered, 0, sizeof (entered));
+
+  if (!GRUB_GET_PASSWORD (entered, sizeof (entered) - 1))
+    return GRUB_ACCESS_DENIED;
+
+  if (grub_auth_strcmp (entered, password) != 0)
+    return GRUB_ACCESS_DENIED;
+
+  grub_auth_authenticate (user);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
+		   int argc, char **args)
+{
+  grub_err_t err;
+  char *pass;
+
+  if (argc != 2)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Two arguments expected.");
+
+  pass = grub_strdup (args[1]);
+  if (!pass)
+    return grub_errno;
+
+  err = grub_auth_register_authentication (args[0], check_password, pass);
+  if (err)
+    {
+      grub_free (pass);
+      return err;
+    }
+  grub_dl_ref (my_mod);
+  return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd;
+\f
+GRUB_MOD_INIT(password)
+{
+  my_mod = mod;
+  cmd = grub_register_command ("password", grub_cmd_password,
+			       "password USER PASSWORD",
+			       "Set user password (plaintext). "
+			       "Unrecommended and insecure.");
+}
+
+GRUB_MOD_FINI(password)
+{
+  grub_unregister_command (cmd);
+}
diff --git a/conf/common.rmk b/conf/common.rmk
index b0d3785..db7fa1a 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -364,7 +364,12 @@ pkglib_MODULES += minicmd.mod extcmd.mod hello.mod handler.mod	\
 	terminfo.mod test.mod blocklist.mod hexdump.mod		\
 	read.mod sleep.mod loadenv.mod crc.mod parttool.mod	\
 	pcpart.mod memrw.mod normal.mod sh.mod lua.mod	\
-	gptsync.mod true.mod probe.mod
+	gptsync.mod true.mod probe.mod password.mod
+
+# For password.mod.
+password_mod_SOURCES = commands/password.c
+password_mod_CFLAGS = $(COMMON_CFLAGS)
+password_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # For gptsync.mod.
 gptsync_mod_SOURCES = commands/gptsync.c
@@ -508,7 +513,7 @@ probe_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # For normal.mod.
 normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \
-	normal/autofs.c normal/handler.c \
+	normal/auth.c normal/autofs.c normal/handler.c \
 	normal/color.c normal/completion.c normal/datetime.c normal/menu.c \
 	normal/menu_entry.c normal/menu_text.c normal/menu_viewer.c \
 	normal/misc.c
diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
index ce2576b..74f8217 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -110,6 +110,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	commands/handler.c commands/ls.c commands/test.c 		\
 	commands/search.c commands/blocklist.c commands/hexdump.c	\
 	commands/gptsync.c commands/probe.c commands/xnu_uuid.c		\
+	commands/password.c						\
 	lib/hexdump.c commands/i386/cpuid.c				\
 	disk/host.c disk/loopback.c					\
 	\
@@ -127,7 +128,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	kern/partition.c kern/reader.c kern/term.c			\
 	kern/rescue_reader.c kern/rescue_parser.c                       \
 	lib/arg.c normal/cmdline.c normal/misc.c			\
-	normal/handler.c normal/autofs.c				\
+	normal/handler.c normal/auth.c normal/autofs.c			\
 	normal/completion.c normal/datetime.c normal/main.c 		\
 	normal/menu_text.c						\
 	normal/menu.c normal/menu_entry.c normal/menu_viewer.c		\
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index 6e3cbcf..9b8819f 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -39,6 +39,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	commands/search.c commands/hexdump.c lib/hexdump.c		\
 	commands/halt.c commands/reboot.c				\
 	commands/i386/cpuid.c						\
+	commands/password.c						\
 	disk/loopback.c							\
 	\
 	fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c			\
@@ -54,7 +55,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	kern/partition.c kern/reader.c kern/term.c			\
 	kern/rescue_reader.c kern/rescue_parser.c                       \
 	lib/arg.c normal/cmdline.c normal/command.c normal/datetime.c 	\
-	normal/autofs.c							\
+	normal/auth.c normal/autofs.c					\
 	normal/completion.c normal/context.c normal/main.c		\
 	normal/menu.c normal/menu_entry.c normal/menu_viewer.c		\
 	normal/menu_text.c						\
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
index 65d1c6b..7858df7 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -66,6 +66,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	lib/hexdump.c commands/halt.c commands/reboot.c			\
 	commands/gptsync.c commands/probe.c  commands/xnu_uuid.c	\
 	commands/i386/cpuid.c	\
+	commands/password.c						\
 	disk/host.c disk/loopback.c					\
 	\
 	fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c			\
@@ -82,7 +83,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	kern/partition.c kern/reader.c kern/term.c			\
 	kern/rescue_reader.c kern/rescue_parser.c 			\
 	lib/arg.c normal/cmdline.c normal/datetime.c normal/misc.c	\
-	normal/handler.c normal/autofs.c				\
+	normal/handler.c normal/auth.c normal/autofs.c			\
 	normal/completion.c normal/main.c normal/menu_text.c		\
 	normal/menu.c normal/menu_entry.c normal/menu_viewer.c		\
 	normal/color.c							\
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 0ef5e47..2655772 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -123,6 +123,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	lib/hexdump.c commands/i386/pc/halt.c commands/reboot.c		\
 	commands/gptsync.c commands/probe.c commands/xnu_uuid.c		\
 	commands/i386/cpuid.c	\
+	commands/password.c						\
 	disk/host.c disk/loopback.c disk/scsi.c				\
 	fs/fshelp.c 	\
 	\
@@ -134,7 +135,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	kern/partition.c kern/reader.c kern/term.c			\
 	kern/rescue_reader.c kern/rescue_parser.c			\
 	lib/arg.c normal/cmdline.c normal/datetime.c normal/misc.c	\
-	normal/handler.c normal/autofs.c				\
+	normal/handler.c normal/auth.c normal/autofs.c				\
 	normal/completion.c normal/main.c normal/color.c		\
 	normal/menu.c normal/menu_entry.c normal/menu_viewer.c		\
 	normal/menu_text.c						\
diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk
index c30f61a..10935cb 100644
--- a/conf/powerpc-ieee1275.rmk
+++ b/conf/powerpc-ieee1275.rmk
@@ -46,6 +46,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	commands/ls.c commands/blocklist.c commands/hexdump.c		\
 	lib/hexdump.c commands/halt.c commands/reboot.c 		\
 	commands/gptsync.c commands/probe.c commands/xnu_uuid.c		\
+	commands/password.c						\
 	disk/loopback.c							\
 	\
 	fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c			\
@@ -62,7 +63,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	kern/command.c kern/corecmd.c commands/extcmd.c			\
 	lib/arg.c normal/cmdline.c normal/datetime.c 			\
 	normal/completion.c normal/misc.c		 		\
-	normal/handler.c normal/autofs.c normal/main.c			\
+	normal/handler.c normal/auth.c normal/autofs.c normal/main.c	\
 	normal/menu.c 							\
 	normal/menu_text.c						\
 	normal/menu_entry.c normal/menu_viewer.c 	 		\
diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk
index b26496d..c90f305 100644
--- a/conf/sparc64-ieee1275.rmk
+++ b/conf/sparc64-ieee1275.rmk
@@ -103,6 +103,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	commands/ls.c commands/blocklist.c commands/hexdump.c		\
 	lib/hexdump.c commands/halt.c commands/reboot.c 		\
 	commands/gptsync.c commands/probe.c commands/xnu_uuid.c		\
+	commands/password.c						\
 	disk/loopback.c							\
 	\
 	fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c			\
@@ -119,7 +120,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	kern/command.c kern/corecmd.c commands/extcmd.c			\
 	lib/arg.c normal/cmdline.c normal/datetime.c 			\
 	normal/completion.c normal/misc.c		 		\
-	normal/handler.c normal/autofs.c normal/main.c			\
+	normal/handler.c normal/auth.c normal/autofs.c normal/main.c	\
 	normal/menu.c 							\
 	normal/menu_text.c						\
 	normal/menu_entry.c normal/menu_viewer.c 	 		\
diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
index 71a90ce..1fd9407 100644
--- a/conf/x86_64-efi.rmk
+++ b/conf/x86_64-efi.rmk
@@ -37,6 +37,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	commands/search.c commands/hexdump.c lib/hexdump.c		\
 	commands/halt.c commands/reboot.c				\
 	commands/i386/cpuid.c						\
+	commands/password.c						\
 	disk/loopback.c							\
 	\
 	fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c			\
@@ -50,7 +51,8 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	kern/command.c kern/corecmd.c commands/extcmd.c kern/file.c 	\
 	kern/fs.c commands/boot.c kern/main.c kern/misc.c kern/parser.c	\
 	kern/partition.c kern/readerescue.c kern/term.c			\
-	lib/arg.c normal/cmdline.c normal/misc.c normal/autofs.c	\
+	lib/arg.c normal/cmdline.c normal/misc.c normal/auth.c		\
+	normal/autofs.c	\
 	normal/completion.c normal/datetime.c normal/context.c 		\
 	normal/main.c		\
 	normal/menu.c normal/menu_entry.c normal/menu_viewer.c		\
diff --git a/include/grub/auth.h b/include/grub/auth.h
new file mode 100644
index 0000000..da930ee
--- /dev/null
+++ b/include/grub/auth.h
@@ -0,0 +1,45 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  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 <http://www.gnu.org/licenses/>.
+ */
+#ifndef GRUB_AURH_HEADER
+#define GRUB_AUTH_HEADER	1
+
+#include <grub/err.h>
+
+/* Macros for indistinguishibility.  */
+#define GRUB_ACCESS_DENIED grub_error (GRUB_ERR_ACCESS_DENIED, "Access denied.")
+#define GRUB_GET_PASSWORD(string, len) grub_cmdline_get ("Enter password: ", \
+							 string, len,	\
+							 '*', 0, 0)
+
+/* Like strcmp but untimeable. Accepts NULL as second argument.  */
+int grub_auth_strcmp (const char *user_input, const char *template);
+/* Like strcmp but untimeable and ignores commas in needle.  */
+int grub_auth_strword (const char *haystack, const char *needle);
+
+typedef grub_err_t (*grub_auth_callback_t) (const char*, void *);
+
+grub_err_t grub_auth_register_authentication (const char *user,
+					      grub_auth_callback_t callback,
+					      void *arg);
+grub_err_t grub_auth_unregister_authentication (const char *user);
+
+grub_err_t grub_auth_authenticate (const char *user);
+grub_err_t grub_auth_deauthenticate (const char *user);
+grub_err_t grub_auth_check_authentication (const char *userlist);
+
+#endif /* ! GRUB_AUTH_HEADER */
diff --git a/include/grub/err.h b/include/grub/err.h
index 3435fb7..7a5ce1a 100644
--- a/include/grub/err.h
+++ b/include/grub/err.h
@@ -53,7 +53,8 @@ typedef enum
     GRUB_ERR_BAD_GZIP_DATA,
     GRUB_ERR_MENU,
     GRUB_ERR_TIMEOUT,
-    GRUB_ERR_IO
+    GRUB_ERR_IO,
+    GRUB_ERR_ACCESS_DENIED
   }
 grub_err_t;
 
diff --git a/include/grub/menu.h b/include/grub/menu.h
index 3bd25e8..c7114a9 100644
--- a/include/grub/menu.h
+++ b/include/grub/menu.h
@@ -32,6 +32,12 @@ struct grub_menu_entry
   /* The title name.  */
   const char *title;
 
+  /* If set means not everybody is allowed to boot this entry.  */
+  int restricted;
+
+  /* Allowed users.  */
+  const char *users;
+
   /* The classes associated with the menu entry:
      used to choose an icon or other style attributes.
      This is a dummy head node for the linked list, so for an entry E,
diff --git a/include/grub/normal.h b/include/grub/normal.h
index 7d8122a..feebc85 100644
--- a/include/grub/normal.h
+++ b/include/grub/normal.h
@@ -56,7 +56,7 @@ void grub_cmdline_run (int nested);
 
 /* Defined in `cmdline.c'.  */
 int grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
-		      int echo_char, int readline);
+		      int echo_char, int readline, int history);
 grub_err_t grub_set_history (int newsize);
 
 /* Defined in `completion.c'.  */
diff --git a/normal/auth.c b/normal/auth.c
new file mode 100644
index 0000000..65245c8
--- /dev/null
+++ b/normal/auth.c
@@ -0,0 +1,256 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/auth.h>
+#include <grub/list.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/normal.h>
+
+struct grub_auth_user
+{
+  struct grub_auth_user *next;
+  char *name;
+  grub_auth_callback_t callback;
+  void *arg;
+  int authenticated;
+};
+
+struct grub_auth_user *users = NULL;
+
+int
+grub_auth_strcmp (const char *user_input, const char *template)
+{
+  int ok = 1;
+  const char *ptr1, *ptr2;
+  for (ptr1 = user_input, ptr2 = template; *ptr1; ptr1++)
+    if (*ptr1 == (ptr2 ? *ptr2 : ptr1[1]) && ok && ptr2 != NULL)
+      ptr2++;
+    else
+      ok = 0;
+
+  return !ok;
+}
+
+int
+grub_auth_strword (const char *haystack, const char *needle)
+{
+  const char *n_pos = needle;
+  int found = 0;
+
+  while (grub_iswordseparator (*haystack))
+    haystack++;
+
+  while (*haystack)
+    {
+      int ok = 1;
+      /* Crawl both the needle and the haystack word we're on.  */
+      while(*haystack && !grub_iswordseparator (*haystack))
+        {
+	  if (*haystack == *n_pos && ok)
+	    n_pos++;
+	  else
+	    ok = 0;
+
+          haystack++;
+        }
+
+      if (ok)
+	found = 1;
+    }
+
+  return found;
+}
+
+grub_err_t
+grub_auth_register_authentication (const char *user,
+				   grub_auth_callback_t callback,
+				   void *arg)
+{
+  struct grub_auth_user *cur;
+
+  cur = grub_named_list_find (GRUB_AS_NAMED_LIST (users), user);
+  if (!cur)
+    cur = grub_zalloc (sizeof (*cur));
+  if (!cur)
+    return grub_errno;
+  cur->callback = callback;
+  cur->arg = arg;
+  if (! cur->name)
+    {
+      cur->name = grub_strdup (user);
+      if (!cur->name)
+	{
+	  grub_free (cur);
+	  return grub_errno;
+	}
+      grub_list_push (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur));
+    }
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_auth_unregister_authentication (const char *user)
+{
+  struct grub_auth_user *cur;
+  cur = grub_named_list_find (GRUB_AS_NAMED_LIST (users), user);
+  if (!cur)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "user '%s' not found", user);
+  if (!cur->authenticated)
+    {
+      grub_free (cur->name);
+      grub_list_remove (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur));
+      grub_free (cur);
+    }
+  else
+    {
+      cur->callback = NULL;
+      cur->arg = NULL;
+    }
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_auth_authenticate (const char *user)
+{
+  struct grub_auth_user *cur;
+
+  cur = grub_named_list_find (GRUB_AS_NAMED_LIST (users), user);
+  if (!cur)
+    cur = grub_zalloc (sizeof (*cur));
+  if (!cur)
+    return grub_errno;
+
+  cur->authenticated = 1;
+
+  if (! cur->name)
+    {
+      cur->name = grub_strdup (user);
+      if (!cur->name)
+	{
+	  grub_free (cur);
+	  return grub_errno;
+	}
+      grub_list_push (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur));
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_auth_deauthenticate (const char *user)
+{
+  struct grub_auth_user *cur;
+  cur = grub_named_list_find (GRUB_AS_NAMED_LIST (users), user);
+  if (!cur)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "user '%s' not found", user);
+  if (!cur->callback)
+    {
+      grub_free (cur->name);
+      grub_list_remove (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur));
+      grub_free (cur);
+    }
+  else
+    cur->authenticated = 0;
+  return GRUB_ERR_NONE;
+}
+
+static int
+is_authenticated (const char *userlist)
+{
+  const char *superusers;
+
+  auto int hook (grub_list_t item);
+  int hook (grub_list_t item)
+  {
+    const char *name;
+    if (!((struct grub_auth_user *) item)->authenticated)
+      return 0;
+    name = ((struct grub_auth_user *) item)->name;
+
+    return (userlist && grub_auth_strword (userlist, name))
+      || grub_auth_strword (superusers, name);
+  }
+
+  superusers = grub_env_get ("superusers");
+
+  if (!superusers)
+    return 1;
+
+  return grub_list_iterate (GRUB_AS_LIST (users), hook);
+}
+
+grub_err_t
+grub_auth_check_authentication (const char *userlist)
+{
+  char login[1024];
+  struct grub_auth_user *cur = NULL;
+  grub_err_t err;
+
+  auto int hook (grub_list_t item);
+  int hook (grub_list_t item)
+  {
+    if (grub_auth_strcmp (login, ((struct grub_auth_user *) item)->name) == 0)
+      {
+	cur = (struct grub_auth_user *) item;
+	return 1;
+      }
+    return 0;
+  }
+
+  auto int hook_any (grub_list_t item);
+  int hook_any (grub_list_t item)
+  {
+    if (((struct grub_auth_user *) item)->callback)
+      {
+	cur = (struct grub_auth_user *) item;
+	return 1;
+      }
+    return 0;
+  }
+
+  grub_memset (login, 0, sizeof (login));
+
+  if (is_authenticated (userlist))
+    return GRUB_ERR_NONE;
+
+  if (!grub_cmdline_get ("Enter username: ", login, sizeof (login) - 1,
+			 0, 0, 0))
+    return GRUB_ACCESS_DENIED;
+
+  grub_list_iterate (GRUB_AS_LIST (users), hook);
+
+  if (!cur || ! cur->callback)
+    {
+      grub_list_iterate (GRUB_AS_LIST (users), hook_any);
+
+      /* No users present at all.  */
+      if (!cur)
+	return GRUB_ACCESS_DENIED;
+
+      /* Display any of available authentication schemes.  */
+      err = cur->callback (login, 0);
+
+      return GRUB_ACCESS_DENIED;
+    }
+  err = cur->callback (login, cur->arg);
+  if (is_authenticated (userlist))
+    return GRUB_ERR_NONE;
+  return GRUB_ACCESS_DENIED;
+}
diff --git a/normal/cmdline.c b/normal/cmdline.c
index 9a07d7d..56f8921 100644
--- a/normal/cmdline.c
+++ b/normal/cmdline.c
@@ -181,7 +181,7 @@ print_completion (const char *item, grub_completion_type_t type, int count)
 /* FIXME: The dumb interface is not supported yet.  */
 int
 grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
-		  int echo_char, int readline)
+		  int echo_char, int readline, int history)
 {
   unsigned xpos, ypos, ystart;
   grub_size_t lpos, llen;
@@ -280,7 +280,7 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
 
   cl_insert (cmdline);
 
-  if (hist_used == 0)
+  if (history && hist_used == 0)
     grub_history_add (buf);
 
   while ((key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && key != '\r')
@@ -468,11 +468,14 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
     while (buf[lpos] == ' ')
       lpos++;
 
-  histpos = 0;
-  if (grub_strlen (buf) > 0)
+  if (history)
     {
-      grub_history_replace (histpos, buf);
-      grub_history_add ("");
+      histpos = 0;
+      if (grub_strlen (buf) > 0)
+	{
+	  grub_history_replace (histpos, buf);
+	  grub_history_add ("");
+	}
     }
 
   grub_memcpy (cmdline, buf + lpos, llen - lpos + 1);
diff --git a/normal/main.c b/normal/main.c
index 66d8418..748eef8 100644
--- a/normal/main.c
+++ b/normal/main.c
@@ -28,6 +28,7 @@
 #include <grub/parser.h>
 #include <grub/reader.h>
 #include <grub/menu_viewer.h>
+#include <grub/auth.h>
 
 #define GRUB_DEFAULT_HISTORY_SIZE	50
 
@@ -164,6 +165,7 @@ grub_normal_add_menu_entry (int argc, const char **args,
   int i;
   struct grub_menu_entry_class *classes_head;  /* Dummy head node for list.  */
   struct grub_menu_entry_class *classes_tail;
+  char *users = NULL;
 
   /* Allocate dummy head node for class list.  */
   classes_head = grub_zalloc (sizeof (struct grub_menu_entry_class));
@@ -218,6 +220,18 @@ grub_normal_add_menu_entry (int argc, const char **args,
 	      classes_tail = new_class;
 	      continue;
 	    }
+	  else if (grub_strcmp(arg, "users") == 0)
+	    {
+	      i++;
+	      users = grub_strdup (args[i]);
+	      if (! users)
+		{
+		  failed = 1;
+		  break;
+		}
+
+	      continue;
+	    }
 	  else
 	    {
 	      /* Handle invalid argument.  */
@@ -275,6 +289,9 @@ grub_normal_add_menu_entry (int argc, const char **args,
 
   (*last)->title = menutitle;
   (*last)->classes = classes_head;
+  if (users)
+    (*last)->restricted = 1;
+  (*last)->users = users;
   (*last)->sourcecode = menusourcecode;
 
   menu->size++;
@@ -465,7 +482,19 @@ quit:
 void
 grub_cmdline_run (int nested)
 {
-  grub_reader_t reader = grub_reader_get_current ();
+  grub_reader_t reader;
+  grub_err_t err = GRUB_ERR_NONE;
+
+  err = grub_auth_check_authentication (NULL);
+
+  if (err)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+      return;
+    }
+
+  reader = grub_reader_get_current ();
 
   reader_nested = nested;
   if (reader->init)
@@ -501,7 +530,7 @@ grub_normal_read_line (char **line, int cont)
   while (1)
     {
       cmdline[0] = 0;
-      if (grub_cmdline_get (prompt, cmdline, sizeof (cmdline), 0, 1))
+      if (grub_cmdline_get (prompt, cmdline, sizeof (cmdline), 0, 1, 1))
 	break;
 
       if ((reader_nested) || (cont))
diff --git a/normal/menu.c b/normal/menu.c
index 59ad83f..8ee7d1c 100644
--- a/normal/menu.c
+++ b/normal/menu.c
@@ -26,6 +26,7 @@
 #include <grub/menu_viewer.h>
 #include <grub/command.h>
 #include <grub/parser.h>
+#include <grub/auth.h>
 
 /* Get a menu entry by its index in the entry list.  */
 grub_menu_entry_t
@@ -124,6 +125,18 @@ get_and_remove_first_entry_number (const char *name)
 void
 grub_menu_execute_entry(grub_menu_entry_t entry)
 {
+  grub_err_t err = GRUB_ERR_NONE;
+
+  if (entry->restricted)
+    err = grub_auth_check_authentication (entry->users);
+
+  if (err)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+      return;
+    }
+
   grub_parser_execute ((char *) entry->sourcecode);
 
   if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
diff --git a/normal/menu_entry.c b/normal/menu_entry.c
index f7662ff..75a6377 100644
--- a/normal/menu_entry.c
+++ b/normal/menu_entry.c
@@ -23,6 +23,7 @@
 #include <grub/loader.h>
 #include <grub/command.h>
 #include <grub/parser.h>
+#include <grub/auth.h>
 
 enum update_mode
   {
@@ -1026,6 +1027,16 @@ grub_menu_entry_run (grub_menu_entry_t entry)
 {
   struct screen *screen;
   int prev_c;
+  grub_err_t err = GRUB_ERR_NONE;
+
+  err = grub_auth_check_authentication (NULL);
+
+  if (err)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+      return;
+    }
 
   screen = make_screen (entry);
   if (! screen)
diff --git a/normal/menu_viewer.c b/normal/menu_viewer.c
index 37d317b..1bd271a 100644
--- a/normal/menu_viewer.c
+++ b/normal/menu_viewer.c
@@ -21,6 +21,7 @@
 #include <grub/env.h>
 #include <grub/menu_viewer.h>
 #include <grub/menu.h>
+#include <grub/auth.h>
 
 /* The list of menu viewers.  */
 static grub_menu_viewer_t menu_viewer_list;
@@ -55,9 +56,26 @@ grub_err_t
 grub_menu_viewer_show_menu (grub_menu_t menu, int nested)
 {
   grub_menu_viewer_t cur = get_current_menu_viewer ();
+  grub_err_t err1, err2;
   if (!cur)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "No menu viewer available.");
 
-  return cur->show_menu (menu, nested);
+  while (1)
+    {
+      err1 = cur->show_menu (menu, nested);
+      grub_print_error ();
+
+      err2 = grub_auth_check_authentication (NULL);
+      if (err2)
+	{
+	  grub_print_error ();
+	  grub_errno = GRUB_ERR_NONE;
+	  continue;
+	}
+
+      break;
+    }
+
+  return err1;
 }
 

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-08-21 11:30             ` Vladimir 'phcoder' Serbinenko
  2009-08-22 19:47               ` Vladimir 'phcoder' Serbinenko
@ 2009-08-23 10:14               ` Robert Millan
  2009-08-24 22:36                 ` Robert Millan
  1 sibling, 1 reply; 22+ messages in thread
From: Robert Millan @ 2009-08-23 10:14 UTC (permalink / raw)
  To: The development of GRUB 2

On Fri, Aug 21, 2009 at 01:30:14PM +0200, Vladimir 'phcoder' Serbinenko wrote:
> >
> >> +grub_err_t
> >> +grub_auth_check_authentication (const char *userlist)
> >> +{
> >> +  char login[1024] = {0};
> >
> > Please avoid arbitrary limits.  If the grub_cmdline_get() API is enforcing
> > them, then this function is wrong and should be using malloc() instead (like,
> > say, getline() or asprintf() do).
> >
> 
> If user has a username longer than 1K it can mean only that he is
> trying to execute buffer overflow.

Maybe.  Or maybe it's just 8 bytes and we're claiming 1K of stack
unnecessarily.

In any case, GCS mandates that we avoid arbitrary length limits:

  http://www.gnu.org/prep/standards/standards.html#Semantics

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-08-23 10:14               ` Robert Millan
@ 2009-08-24 22:36                 ` Robert Millan
  2009-08-24 23:58                   ` Vladimir 'phcoder' Serbinenko
  0 siblings, 1 reply; 22+ messages in thread
From: Robert Millan @ 2009-08-24 22:36 UTC (permalink / raw)
  To: The development of GRUB 2


I had a look at grub_cmdline_get(), and it would need some restructuring in
order not to enforce static allocation.  I admit it doesn't make sense to
put this patch on hold because of it.

Vladimir, please go ahead with your latest patch.  I will try to change
grub_cmdline_get() semantics later if I get some time.

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-08-24 22:36                 ` Robert Millan
@ 2009-08-24 23:58                   ` Vladimir 'phcoder' Serbinenko
  2009-08-25 14:35                     ` Felix Zielcke
  0 siblings, 1 reply; 22+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-08-24 23:58 UTC (permalink / raw)
  To: The development of GRUB 2

On Tue, Aug 25, 2009 at 12:36 AM, Robert Millan<rmh@aybabtu.com> wrote:
>
> I had a look at grub_cmdline_get(), and it would need some restructuring in
> order not to enforce static allocation.  I admit it doesn't make sense to
> put this patch on hold because of it.
>
> Vladimir, please go ahead with your latest patch.  I will try to change
> grub_cmdline_get() semantics later if I get some time.
>
Comitted. Beware that it needs more review and testing before
considering it somewhat secure (well we don't really need to be more
secure than firmware password unless we're firmware).
Additionally using plaintext support (currently the only supported) is
a bad practise. I'll look if I have time to implement a form of
cryptographic password (e.g. scrypt) before 1.97 freeze.
> --
> Robert Millan
>
>  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
>  how) you may access your data; but nobody's threatening your freedom: we
>  still allow you to remove your data and not access it at all."
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>



-- 
Regards
Vladimir 'phcoder' Serbinenko

Personal git repository: http://repo.or.cz/w/grub2/phcoder.git



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-08-24 23:58                   ` Vladimir 'phcoder' Serbinenko
@ 2009-08-25 14:35                     ` Felix Zielcke
  2009-08-25 14:50                       ` Vladimir 'phcoder' Serbinenko
  0 siblings, 1 reply; 22+ messages in thread
From: Felix Zielcke @ 2009-08-25 14:35 UTC (permalink / raw)
  To: The development of GRUB 2

Am Dienstag, den 25.08.2009, 01:58 +0200 schrieb Vladimir 'phcoder'
Serbinenko:
> On Tue, Aug 25, 2009 at 12:36 AM, Robert Millan<rmh@aybabtu.com>
> wrote:
> >
> > I had a look at grub_cmdline_get(), and it would need some
> restructuring in
> > order not to enforce static allocation.  I admit it doesn't make
> sense to
> > put this patch on hold because of it.
> >
> > Vladimir, please go ahead with your latest patch.  I will try to
> change
> > grub_cmdline_get() semantics later if I get some time.
> >
> Comitted. Beware that it needs more review and testing before
> considering it somewhat secure (well we don't really need to be more
> secure than firmware password unless we're firmware).
> Additionally using plaintext support (currently the only supported) is
> a bad practise. I'll look if I have time to implement a form of
> cryptographic password (e.g. scrypt) before 1.97 freeze. 

Does it has the same problem as CVE-2008-3896 published for grub-legacy?

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-3896

-- 
Felix Zielcke
Proud Debian Maintainer




^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-08-25 14:35                     ` Felix Zielcke
@ 2009-08-25 14:50                       ` Vladimir 'phcoder' Serbinenko
  2009-08-25 18:55                         ` Michal Suchanek
  0 siblings, 1 reply; 22+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-08-25 14:50 UTC (permalink / raw)
  To: The development of GRUB 2

> Does it has the same problem as CVE-2008-3896 published for grub-legacy?
It's completely different concern. Actually BIOS keyboard buffer
shouldn't be a problem since only root can read raw memory and if user
is a root he can just kexec any kernel he wants.
I could add keyboard buffer wiping to my sendkey work but it only
offsets the problem since same info is stored in RAM by grb anyway.
The only solution I see for second problem is to make grub_free shred
the memory and ensuring all sensitive fields are dynamically allocated
and free'ed before boot (last part makes code cleaner too). Actually I
have done some experiments with replacing grub_sprintf with
grub_asprintf which revealed many spot of suboptimal code too.
After all I think this is worth to do (wiping keyboard buffer and
making grub_free wipe the memory). But it doesn't destroy the info
which was in memory before grub booted. Doing so may take significant
booting time (to be tested) but may be desirable in some cases.
>
> http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-3896
>
> --
> Felix Zielcke
> Proud Debian Maintainer
>
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>



-- 
Regards
Vladimir 'phcoder' Serbinenko

Personal git repository: http://repo.or.cz/w/grub2/phcoder.git



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-08-25 14:50                       ` Vladimir 'phcoder' Serbinenko
@ 2009-08-25 18:55                         ` Michal Suchanek
  2009-08-25 19:54                           ` Vladimir 'phcoder' Serbinenko
  0 siblings, 1 reply; 22+ messages in thread
From: Michal Suchanek @ 2009-08-25 18:55 UTC (permalink / raw)
  To: The development of GRUB 2

2009/8/25 Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>:
>> Does it has the same problem as CVE-2008-3896 published for grub-legacy?
> It's completely different concern. Actually BIOS keyboard buffer
> shouldn't be a problem since only root can read raw memory and if user
> is a root he can just kexec any kernel he wants.
> I could add keyboard buffer wiping to my sendkey work but it only
> offsets the problem since same info is stored in RAM by grb anyway.
> The only solution I see for second problem is to make grub_free shred
> the memory and ensuring all sensitive fields are dynamically allocated
> and free'ed before boot (last part makes code cleaner too). Actually I
> have done some experiments with replacing grub_sprintf with
> grub_asprintf which revealed many spot of suboptimal code too.
> After all I think this is worth to do (wiping keyboard buffer and
> making grub_free wipe the memory). But it doesn't destroy the info
> which was in memory before grub booted. Doing so may take significant
> booting time (to be tested) but may be desirable in some cases.

Ever tried memtest?

Depending on the speed of the memory bus and memory size I would
expect doing a single write over the whole ram would take seconds to a
few tens of seconds.

Not unreasonable if you don't boot often but unless it's in the range
of seconds I probably would not use such feature.

However, that CVE is about grub leaving its passwords in memory.
Wiping memory used by grub should be fast - orders of magnitude faster
than loading the OS kernel for example.

Thanks

Michal

Thanks

Michal



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-08-25 18:55                         ` Michal Suchanek
@ 2009-08-25 19:54                           ` Vladimir 'phcoder' Serbinenko
  2009-08-26 11:51                             ` Michal Suchanek
  0 siblings, 1 reply; 22+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-08-25 19:54 UTC (permalink / raw)
  To: The development of GRUB 2

> However, that CVE is about grub leaving its passwords in memory.
> Wiping memory used by grub should be fast - orders of magnitude faster
> than loading the OS kernel for example.
Actually this specific report is about BIOS leaving its keyboard
buffer - you can find BIOS password there too. As BIOS is proprietary
firmware whatever we do we can never ensure it being secure. Even the
task to just wipe grub's memory would take time to implement. I'll do
it but probably timeframe before release freeze is too short.
>
> Thanks
>
> Michal
>
> Thanks
>
> Michal
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>



-- 
Regards
Vladimir 'phcoder' Serbinenko

Personal git repository: http://repo.or.cz/w/grub2/phcoder.git



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-08-25 19:54                           ` Vladimir 'phcoder' Serbinenko
@ 2009-08-26 11:51                             ` Michal Suchanek
  2009-08-26 17:32                               ` Vladimir 'phcoder' Serbinenko
  0 siblings, 1 reply; 22+ messages in thread
From: Michal Suchanek @ 2009-08-26 11:51 UTC (permalink / raw)
  To: The development of GRUB 2

2009/8/25 Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>:
>> However, that CVE is about grub leaving its passwords in memory.
>> Wiping memory used by grub should be fast - orders of magnitude faster
>> than loading the OS kernel for example.
> Actually this specific report is about BIOS leaving its keyboard
> buffer - you can find BIOS password there too. As BIOS is proprietary
> firmware whatever we do we can never ensure it being secure. Even the

Even if many BIOSes leave their password there it's not reason to be as sloppy.

I am not particularly concerned about this issue but the BIOS
typically requires a reboot after typing the password so if it is
half-decently implemented it clears the buffer during initialization.
If it does not it's not grub's concern, it should do its part by
clearing its own sensitive data (if any).

Thanks

Michal



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-08-26 11:51                             ` Michal Suchanek
@ 2009-08-26 17:32                               ` Vladimir 'phcoder' Serbinenko
  2009-08-28 12:37                                 ` Robert Millan
  0 siblings, 1 reply; 22+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-08-26 17:32 UTC (permalink / raw)
  To: The development of GRUB 2

On Wed, Aug 26, 2009 at 1:51 PM, Michal Suchanek<hramrach@centrum.cz> wrote:
> 2009/8/25 Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>:
>>> However, that CVE is about grub leaving its passwords in memory.
>>> Wiping memory used by grub should be fast - orders of magnitude faster
>>> than loading the OS kernel for example.
>> Actually this specific report is about BIOS leaving its keyboard
>> buffer - you can find BIOS password there too. As BIOS is proprietary
>> firmware whatever we do we can never ensure it being secure. Even the
>
> Even if many BIOSes leave their password there it's not reason to be as sloppy.
>
Let me clarify my position:
1) If someone submits a patch with clean (E.g. shredding grub_free,
ensure there is no memory leak and a shredder for BIOS buffer) then I
would recomment to merge this patch
2) This is a considerable amount of work and not a priority.
3) It's not a reason to hold the release
> I am not particularly concerned about this issue but the BIOS
> typically requires a reboot after typing the password so if it is
> half-decently implemented it clears the buffer during initialization.
> If it does not it's not grub's concern, it should do its part by
> clearing its own sensitive data (if any).
Actually what was described in original link is exactly BIOS leaving data behind
>
> Thanks
>
> Michal
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>



-- 
Regards
Vladimir 'phcoder' Serbinenko

Personal git repository: http://repo.or.cz/w/grub2/phcoder.git



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Re[2]: 'password' command in GRUB 2?
  2009-08-26 17:32                               ` Vladimir 'phcoder' Serbinenko
@ 2009-08-28 12:37                                 ` Robert Millan
  0 siblings, 0 replies; 22+ messages in thread
From: Robert Millan @ 2009-08-28 12:37 UTC (permalink / raw)
  To: The development of GRUB 2

On Wed, Aug 26, 2009 at 07:32:37PM +0200, Vladimir 'phcoder' Serbinenko wrote:
> On Wed, Aug 26, 2009 at 1:51 PM, Michal Suchanek<hramrach@centrum.cz> wrote:
> > 2009/8/25 Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>:
> >>> However, that CVE is about grub leaving its passwords in memory.
> >>> Wiping memory used by grub should be fast - orders of magnitude faster
> >>> than loading the OS kernel for example.
> >> Actually this specific report is about BIOS leaving its keyboard
> >> buffer - you can find BIOS password there too. As BIOS is proprietary
> >> firmware whatever we do we can never ensure it being secure. Even the
> >
> > Even if many BIOSes leave their password there it's not reason to be as sloppy.
> >
> Let me clarify my position:
> 1) If someone submits a patch with clean (E.g. shredding grub_free,
> ensure there is no memory leak and a shredder for BIOS buffer) then I
> would recomment to merge this patch
> 2) This is a considerable amount of work and not a priority.
> 3) It's not a reason to hold the release

root's ability to read GRUB password from physical memory is already obvious
by the fact that it is stored in clear text in grub.cfg.

When we support password hashing, this should be contemplated as well.

But for now, I agree with Vladimir that this isn't a reason to hold the
release.

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."



^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2009-08-28 12:38 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-05 17:36 'password' command in GRUB 2? Colin Watson
2009-06-05 17:55 ` Vladimir 'phcoder' Serbinenko
2009-06-05 18:17   ` Re[2]: " Julien RANC
2009-07-26 14:40     ` Felix Zielcke
2009-07-26 16:20       ` Vladimir 'phcoder' Serbinenko
2009-07-26 21:29         ` Vladimir 'phcoder' Serbinenko
2009-08-20 16:44           ` Robert Millan
2009-08-21 11:30             ` Vladimir 'phcoder' Serbinenko
2009-08-22 19:47               ` Vladimir 'phcoder' Serbinenko
2009-08-23 10:14               ` Robert Millan
2009-08-24 22:36                 ` Robert Millan
2009-08-24 23:58                   ` Vladimir 'phcoder' Serbinenko
2009-08-25 14:35                     ` Felix Zielcke
2009-08-25 14:50                       ` Vladimir 'phcoder' Serbinenko
2009-08-25 18:55                         ` Michal Suchanek
2009-08-25 19:54                           ` Vladimir 'phcoder' Serbinenko
2009-08-26 11:51                             ` Michal Suchanek
2009-08-26 17:32                               ` Vladimir 'phcoder' Serbinenko
2009-08-28 12:37                                 ` Robert Millan
2009-08-19 15:08         ` Robert Millan
2009-08-19 15:17           ` Vladimir 'phcoder' Serbinenko
2009-08-20 16:32             ` Robert Millan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.