Hi all,Here is my first patch for Grub2, so I hope it won't be too bad, and by advance, all my apologies for the probable errors ;-) So, please, comment gently...
These 2 patch add support for the 'password' command, with the syntax I proposed in my mail from August 1st.
Just a few remarks:1. if you use several 'password' commands in the grub.cfg, only the last one will be valid. 2. To use MD5 passwords, you _MUST_ put quotes around the password. For example:
password --md5 '$1$WAso4$Z93ELTjxbgLaXvhSF/7cZ/' --> This works fine password --md5 $1$WAso4$Z93ELTjxbgLaXvhSF/7cZ/ --> no quotes, don't work 3. passwords are limited to 64 chars.The first patch (patch_1.txt) contains the implementation itself of password management, and MD5 routines (based on the MD5 routines from Grub Legacy)
The second patch (patch_2.txt) contains modifications to the module normal to take into account the new command:
- register the command on startup - add relevant checks and actions in menu.c It also patches the .rmk files to compile.I will let you comment on this, and start working on implementing the 'lock' command in the meanwhile. I hope I'll be able to send a first patch for the lock command by the end of the week.
-- Julien RANC [EMAIL PROTECTED]
--- vanilla_grub2/normal/md5.c 1970-01-01 01:00:00.000000000 +0100 +++ grub2/normal/md5.c 2007-08-04 12:26:22.000000000 +0200 @@ -0,0 +1,303 @@ +/* md5.c - an implementation of the MD5 algorithm and MD5 crypt */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2005,2006,2007 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/>. + */ + +/* See RFC 1321 for a description of the MD5 algorithm. */ + +#include <grub/md5.h> +#include <grub/types.h> +#include <grub/misc.h> + +/* F, G, H and I are basic MD5 functions. */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x >> (32 - (n))))) + +static grub_uint32_t initstate[4] = +{ + 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 +}; + +static char s1[4] = { 7, 12, 17, 22 }; +static char s2[4] = { 5, 9, 14, 20 }; +static char s3[4] = { 4, 11, 16, 23 }; +static char s4[4] = { 6, 10, 15, 21 }; + +static grub_uint32_t T[64] = +{ + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 +}; + +static const char *b64t = +"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static grub_uint32_t state[4]; +static unsigned int length; +static unsigned char buffer[64]; + +static void +md5_transform (const unsigned char block[64]) +{ + int i, j; + grub_uint32_t a,b,c,d,tmp; + const grub_uint32_t *x = (grub_uint32_t *) block; + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + + /* Round 1 */ + for (i = 0; i < 16; i++) + { + tmp = a + F (b, c, d) + grub_le_to_cpu32 (x[i]) + T[i]; + tmp = ROTATE_LEFT (tmp, s1[i & 3]); + tmp += b; + a = d; d = c; c = b; b = tmp; + } + /* Round 2 */ + for (i = 0, j = 1; i < 16; i++, j += 5) + { + tmp = a + G (b, c, d) + grub_le_to_cpu32 (x[j & 15]) + T[i+16]; + tmp = ROTATE_LEFT (tmp, s2[i & 3]); + tmp += b; + a = d; d = c; c = b; b = tmp; + } + /* Round 3 */ + for (i = 0, j = 5; i < 16; i++, j += 3) + { + tmp = a + H (b, c, d) + grub_le_to_cpu32 (x[j & 15]) + T[i+32]; + tmp = ROTATE_LEFT (tmp, s3[i & 3]); + tmp += b; + a = d; d = c; c = b; b = tmp; + } + /* Round 4 */ + for (i = 0, j = 0; i < 16; i++, j += 7) + { + tmp = a + I (b, c, d) + grub_le_to_cpu32 (x[j & 15]) + T[i+48]; + tmp = ROTATE_LEFT (tmp, s4[i & 3]); + tmp += b; + a = d; d = c; c = b; b = tmp; + } + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; +} + +static void +md5_init(void) +{ + grub_memcpy ((char *) state, (char *) initstate, sizeof (initstate)); + length = 0; +} + +static void +md5_update (const char *input, int inputlen) +{ + int buflen = length & 63; + length += inputlen; + if (buflen + inputlen < 64) + { + grub_memcpy (buffer + buflen, input, inputlen); + buflen += inputlen; + return; + } + + grub_memcpy (buffer + buflen, input, 64 - buflen); + md5_transform (buffer); + input += 64 - buflen; + inputlen -= 64 - buflen; + while (inputlen >= 64) + { + md5_transform ((const unsigned char*) input); + input += 64; + inputlen -= 64; + } + grub_memcpy (buffer, input, inputlen); + buflen = inputlen; +} + +static unsigned char * +md5_final( void ) +{ + int i, buflen = length & 63; + + buffer[buflen++] = 0x80; + + grub_memset (buffer+buflen, 0, 64 - buflen); + if (buflen > 56) + { + md5_transform (buffer); + grub_memset (buffer, 0, 64); + buflen = 0; + } + + *(grub_uint32_t *) (buffer + 56) = grub_cpu_to_le32 (8 * length); + *(grub_uint32_t *) (buffer + 60) = 0; + md5_transform (buffer); + + for (i = 0; i < 4; i++) + state[i] = grub_cpu_to_le32 (state[i]); + return (unsigned char *) state; +} + +/* If CHECK is true, check a password for correctness. Returns 0 + if password was correct, and a value != 0 for error, similarly + to strcmp. + If CHECK is false, crypt KEY and save the result in CRYPTED. + CRYPTED must have a salt. */ +int +grub_md5_password (const char *key, char *crypted, int check) +{ + int keylen = grub_strlen (key); + char *salt = crypted + 3; /* skip $1$ header */ + char *p; + int saltlen; + int i, n; + unsigned char alt_result[16]; + unsigned char *digest; + + if (check) + { + /* If our crypted password isn't 3 chars, then it can't be md5 + crypted. So, they don't match. */ + if (grub_strlen(crypted) <= 3) + return 1; + + saltlen = grub_strstr (salt, "$") - salt; + } + else + { + char *end = grub_strstr (salt, "$"); + if (end && end - salt < 8) + saltlen = end - salt; + else + saltlen = 8; + + salt[saltlen] = '$'; + } + + md5_init (); + md5_update (key, keylen); + md5_update (salt, saltlen); + md5_update (key, keylen); + digest = md5_final (); + grub_memcpy (alt_result, digest, 16); + + grub_memcpy ((char *) state, (char *) initstate, sizeof (initstate)); + length = 0; + md5_update (key, keylen); + md5_update (crypted, 3 + saltlen); /* include the $1$ header */ + for (i = keylen; i > 16; i -= 16) + md5_update ((char *) alt_result, 16); + md5_update ((char *) alt_result, i); + + for (i = keylen; i > 0; i >>= 1) + md5_update ((char*) (key + ((i & 1) ? keylen : 0)), 1); + digest = md5_final (); + + for (i = 0; i < 1000; i++) + { + grub_memcpy (alt_result, digest, 16); + + grub_memcpy ((char *) state, (char *) initstate, sizeof (initstate)); + length = 0; + if ((i & 1) != 0) + md5_update (key, keylen); + else + md5_update ((char *) alt_result, 16); + + if (i % 3 != 0) + md5_update (salt, saltlen); + + if (i % 7 != 0) + md5_update (key, keylen); + + if ((i & 1) != 0) + md5_update ((char *) alt_result, 16); + else + md5_update (key, keylen); + digest = md5_final (); + } + + p = salt + saltlen + 1; + for (i = 0; i < 5; i++) + { + unsigned int w = + digest[i == 4 ? 5 : 12+i] | (digest[6+i] << 8) | (digest[i] << 16); + for (n = 4; n-- > 0;) + { + if (check) + { + if (*p++ != b64t[w & 0x3f]) + return 1; + } + else + { + *p++ = b64t[w & 0x3f]; + } + + w >>= 6; + } + } + { + unsigned int w = digest[11]; + for (n = 2; n-- > 0;) + { + if (check) + { + if (*p++ != b64t[w & 0x3f]) + return 1; + } + else + { + *p++ = b64t[w & 0x3f]; + } + + w >>= 6; + } + } + + if (! check) + *p = '\0'; + + return *p; +} + + --- vanilla_grub2/normal/password.c 1970-01-01 01:00:00.000000000 +0100 +++ grub2/normal/password.c 2007-08-05 16:48:31.000000000 +0200 @@ -0,0 +1,249 @@ +/* password.c - Password helper function for other modules */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2004,2005,2006 Free Software Foundation, Inc. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <grub/dl.h> +#include <grub/password.h> +#include <grub/err.h> /* for error codes */ +#include <grub/mm.h> /* for memory mngt */ +#include <grub/misc.h> /* for string manipulation */ +#include <grub/normal.h> +#include <grub/md5.h> + +/** + * The global password, used as default. + */ +static grub_password_t global_password = 0; + + +/* Declare private functions */ +int check_plain_text(const char *entered, const char *correct); +int check_md5(const char *entered, const char *correct); + +grub_err_t +grub_password_command(struct grub_arg_list *state, + int argc, + char **args) +{ + if (argc <= 0) + goto fail; /* too few arguments */ + + if (argc > 2) + goto fail; /* too many arguments */ + + if (global_password == 0) + { + global_password = grub_malloc(sizeof(global_password)); + global_password->password = 0; + global_password->type = GRUB_PASSWORD_TYPE_UNSUPPORTED; + global_password->next_file = 0; + global_password->authenticated = 0; + } + + /* Set the new password */ + if ( global_password->password != 0) + grub_free(global_password->password); + global_password->password = grub_strdup(args[0]); + + /* set the next file to load */ + if ( global_password->next_file != 0) + grub_free(global_password->next_file); + if ( argc > 1) + global_password->next_file = grub_strdup(args[1]); + else + global_password->next_file = 0; + + /* set the password type */ + if (state[0].set) + global_password->type = GRUB_PASSWORD_TYPE_MD5; + else + global_password->type = GRUB_PASSWORD_TYPE_PLAIN_TEXT; + + global_password->authenticated = 0; + + /* OK, done */ + return GRUB_ERR_NONE; + + + fail: + return GRUB_ERR_INVALID_COMMAND; +} + + + +grub_password_t +grub_password_create_password(grub_password_type_t type, + const char *password, + const char *next_file) +{ + if ( password == 0 ) + goto fail; + + if ( next_file == 0 ) + goto fail; + + if ( type == GRUB_PASSWORD_TYPE_UNSUPPORTED ) + goto fail; + + grub_password_t passwd; + passwd = grub_malloc( sizeof(passwd) ); + passwd->type = type; + passwd->password = grub_strdup(password); + passwd->next_file = grub_strdup(next_file); + passwd->authenticated = 0; + + return passwd; + + fail: + return 0; +} + +void +grub_password_free_password(grub_password_t password) +{ + if (password == 0) + goto finished; + + if (password->password != 0) + grub_free(password->password); + + if (password->next_file != 0) + grub_free(password->next_file); + + grub_free(password); + + finished: + return; +} + +int +grub_password_is_password_set(void) +{ + return (global_password != 0); +} + +int +grub_password_is_user_authenticated(grub_password_t password) +{ + grub_password_t passwd; + int result; + + if ( password != 0 ) + passwd = password; + else + passwd = global_password; + + if ( passwd == 0 ) + { + /* No password set : let's say it is OK */ + result = 1; + } + else + { + result = passwd->authenticated; + } + + return result; +} + +int +grub_password_check_password(const char *entered, + grub_password_t password) +{ + int check_result = -1; + grub_password_t checked_passwd; + + /* Sets the password we check against */ + if ( password != 0 ) + checked_passwd = password; + else + checked_passwd = global_password; + + /* If no password set nor passed, OK */ + if (checked_passwd == 0) { + check_result = 0; + goto end_check; + } + + /* Perform actual check */ + switch ( checked_passwd->type ) + { + case (GRUB_PASSWORD_TYPE_PLAIN_TEXT): + check_result = check_plain_text(entered, + checked_passwd->password); + break; + + case (GRUB_PASSWORD_TYPE_MD5): + check_result = check_md5(entered, + checked_passwd->password); + break; + + default: + /* Unknown password type, or unsupported */ + check_result = -1; + } + + if (check_result == 0) + checked_passwd->authenticated = 1; + + + end_check: + return check_result; +} + +char* +grub_password_get_next_file(void) +{ + if (global_password == 0) + return 0; + + if (grub_password_is_user_authenticated(0) == 0) + return 0; + + if (global_password->next_file == 0) + return 0; + + return grub_strdup(global_password->next_file); +} + +/* Start of private functions */ + +int +check_plain_text(const char *entered, + const char *correct) +{ + int result; + result = grub_strcmp(entered, correct); + if (result != 0) + result = -1; + + return result; +} + +int +check_md5(const char *entered, + const char *correct) +{ + int result; + result = grub_md5_check_password(entered, correct); + return result; +} + + + --- vanilla_grub2/include/grub/md5.h 1970-01-01 01:00:00.000000000 +0100 +++ grub2/include/grub/md5.h 2007-08-04 12:44:46.000000000 +0200 @@ -0,0 +1,30 @@ +/* md5.c - an implementation of the MD5 algorithm and MD5 crypt */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2005,2006,2007 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/>. + */ + + +/* If CHECK is true, check a password for correctness. Returns 0 + if password was correct, and a value != 0 for error, similarly + to strcmp. + If CHECK is false, crypt KEY and save the result in CRYPTED. + CRYPTED must have a salt. */ +extern int grub_md5_password (const char *key, char *crypted, int check); + +/* For convenience. */ +#define grub_md5_check_password(key,crypted) grub_md5_password((key), (crypted), 1) +#define grub_md5_make_password(key,crypted) grub_md5_password((key), (crypted), 0) --- vanilla_grub2/include/grub/password.h 1970-01-01 01:00:00.000000000 +0100 +++ grub2/include/grub/password.h 2007-08-05 16:49:06.000000000 +0200 @@ -0,0 +1,147 @@ +/* password.h - Header file for password management */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2005 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 2 of the License, or + * (at your option) any later version. + * + * This program 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef GRUB_PASSWORD_H +#define GRUB_PASSWORD_H 1 + + +#include <grub/arg.h> + +/* The max length of the password, in chars */ +#define GRUB_PASSWORD_MAX_LENGTH 64 + +/* the password types */ +enum grub_password_type + { + GRUB_PASSWORD_TYPE_UNSUPPORTED, + GRUB_PASSWORD_TYPE_PLAIN_TEXT, + GRUB_PASSWORD_TYPE_MD5 + }; +typedef enum grub_password_type grub_password_type_t; + + +/* structure holding a password */ +struct grub_password +{ + char *password; /* The password. */ + grub_password_type_t type; /* The type. */ + char *next_file; /* The file to jump after auth */ + int authenticated; /* Flag for passwd verification status */ +}; +typedef struct grub_password *grub_password_t; + +/* The options available for the 'password' command */ +static const struct grub_arg_option grub_password_arg_options[] = + { + {"md5", 'm', GRUB_ARG_OPTION_OPTIONAL, "indicates the password is encrypted with MD5", 0, ARG_TYPE_NONE}, + {0, 0, 0, 0, 0, 0} + }; + +/* Helper functions */ + +/** + * @brief The 'password' command itself + * + * This is the callback to execute a 'password' command from a + * script. + * See normal.h for information on the parameters + */ +grub_err_t +grub_password_command(struct grub_arg_list *state, + int argc, + char **args); + +/** + * @bried Create a grub_password_t structure based on entered params + * + * This function is helpful for the 'lock' command to generate the + * password against which the user password will be checked. + * + * @param[in] type the password type + * @param[in] password the password + * + * @returns a grub_password_t object properly filled + * @returns 0 is invalid params are passed + */ +grub_password_t +grub_password_create_password(grub_password_type_t type, + const char *password, + const char *next_file); + +/** + * @bried Free a grub_password_t structure + * + * @param[in] password the password + */ +void +grub_password_free_password(grub_password_t password); + + +/** + * @brief Check is a global password is set + * + * @returns 0 if no password is set + * @returns 1 if a password is set + */ +int +grub_password_is_password_set(void); + +/** + * @brief Check if the user has correctly authentificated with a given password + * + * @param[in] password : the password to check. If set to 0, the global + * password is used instead. + * + * @returns 0 if user is not authenticated + * @returns 1 if user is authenticated + * @returns 1 if no password passed and no global password is set + */ +int +grub_password_is_user_authenticated(grub_password_t password); + +/** + * @brief Check a user password + * + * @param[in] entered the user entered password + * @param[in] password the password agains which the user input + * will be checked. If set to 0, the global password, if set, will + * be used. + * + * @returns 0 if the user entered password is correct, or if no password + * had been set AND no password had been specified. + * @returns -1 if the user password is wrong. + */ +int +grub_password_check_password(const char *entered, + grub_password_t password); + + +/** + * @brief get the next file specified with the global password + * + * @returns the next file to jump to. The buffer needs to be freed + * after use... + * @returns 0 if user is not authenticated, or no file given + */ +char* +grub_password_get_next_file(void); + +#endif /* !GRUB_PASSWORD_H */ +
Index: conf/i386-efi.rmk =================================================================== RCS file: /sources/grub/grub2/conf/i386-efi.rmk,v retrieving revision 1.19 diff -u -p -r1.19 i386-efi.rmk --- conf/i386-efi.rmk 2 Aug 2007 19:12:52 -0000 1.19 +++ conf/i386-efi.rmk 5 Aug 2007 15:18:51 -0000 @@ -109,6 +109,7 @@ normal_mod_SOURCES = normal/arg.c normal normal/completion.c normal/execute.c \ normal/function.c normal/lexer.c normal/main.c normal/menu.c \ normal/menu_entry.c normal/misc.c grub_script.tab.c \ + normal/password.c normal/md5.c \ normal/script.c normal/i386/setjmp.S normal_mod_CFLAGS = $(COMMON_CFLAGS) normal_mod_ASFLAGS = $(COMMON_ASFLAGS) Index: conf/i386-pc.rmk =================================================================== RCS file: /sources/grub/grub2/conf/i386-pc.rmk,v retrieving revision 1.86 diff -u -p -r1.86 i386-pc.rmk --- conf/i386-pc.rmk 2 Aug 2007 19:12:52 -0000 1.86 +++ conf/i386-pc.rmk 5 Aug 2007 15:18:52 -0000 @@ -157,6 +157,7 @@ normal_mod_SOURCES = normal/arg.c normal normal/completion.c normal/execute.c \ normal/function.c normal/lexer.c normal/main.c normal/menu.c \ normal/menu_entry.c normal/misc.c grub_script.tab.c \ + normal/password.c normal/md5.c \ normal/script.c normal/i386/setjmp.S normal_mod_CFLAGS = $(COMMON_CFLAGS) normal_mod_ASFLAGS = $(COMMON_ASFLAGS) Index: conf/powerpc-ieee1275.rmk =================================================================== RCS file: /sources/grub/grub2/conf/powerpc-ieee1275.rmk,v retrieving revision 1.69 diff -u -p -r1.69 powerpc-ieee1275.rmk --- conf/powerpc-ieee1275.rmk 2 Aug 2007 19:12:52 -0000 1.69 +++ conf/powerpc-ieee1275.rmk 5 Aug 2007 15:18:52 -0000 @@ -124,6 +124,7 @@ normal_mod_SOURCES = normal/arg.c normal normal/completion.c normal/execute.c \ normal/function.c normal/lexer.c normal/main.c normal/menu.c \ normal/menu_entry.c normal/misc.c grub_script.tab.c \ + normal/password.c normal/md5.c \ normal/script.c normal/powerpc/setjmp.S normal_mod_CFLAGS = $(COMMON_CFLAGS) normal_mod_LDFLAGS = $(COMMON_LDFLAGS) Index: conf/sparc64-ieee1275.rmk =================================================================== RCS file: /sources/grub/grub2/conf/sparc64-ieee1275.rmk,v retrieving revision 1.17 diff -u -p -r1.17 sparc64-ieee1275.rmk --- conf/sparc64-ieee1275.rmk 2 Jul 2007 20:38:01 -0000 1.17 +++ conf/sparc64-ieee1275.rmk 5 Aug 2007 15:18:52 -0000 @@ -156,6 +156,7 @@ normal_mod_SOURCES = normal/arg.c normal normal/completion.c normal/execute.c \ normal/function.c normal/lexer.c normal/main.c normal/menu.c \ normal/menu_entry.c normal/misc.c normal/script.c \ + normal/password.c normal/md5.c \ normal/sparc64/setjmp.S \ grub_script.tab.c normal_mod_CFLAGS = $(COMMON_CFLAGS) Index: normal/command.c =================================================================== RCS file: /sources/grub/grub2/normal/command.c,v retrieving revision 1.19 diff -u -p -r1.19 command.c --- normal/command.c 21 Jul 2007 23:32:29 -0000 1.19 +++ normal/command.c 5 Aug 2007 15:18:52 -0000 @@ -25,6 +25,7 @@ #include <grub/dl.h> #include <grub/parser.h> #include <grub/script.h> +#include <grub/password.h> static grub_command_t grub_command_list; @@ -391,4 +392,8 @@ grub_command_init (void) grub_register_command ("lsmod", lsmod_command, GRUB_COMMAND_FLAG_BOTH, "lsmod", "Show loaded modules.", 0); + + grub_register_command ("password", grub_password_command, GRUB_COMMAND_FLAG_MENU, + "password [--MD5] PASSWORD [NEXT_FILE]", "Set a password", + grub_password_arg_options); } Index: normal/menu.c =================================================================== RCS file: /sources/grub/grub2/normal/menu.c,v retrieving revision 1.18 diff -u -p -r1.18 menu.c --- normal/menu.c 21 Jul 2007 23:32:29 -0000 1.18 +++ normal/menu.c 5 Aug 2007 15:18:52 -0000 @@ -24,6 +24,9 @@ #include <grub/machine/time.h> #include <grub/env.h> #include <grub/script.h> +#include <grub/password.h> + +int ask_and_check_password(void); static void draw_border (void) @@ -76,9 +79,18 @@ print_message (int nested, int edit) grub_printf ("\n\ Use the %C and %C keys to select which entry is highlighted.\n", (grub_uint32_t) GRUB_TERM_DISP_UP, (grub_uint32_t) GRUB_TERM_DISP_DOWN); - grub_printf ("\ + if ( grub_password_is_user_authenticated(0) == 1 ) + { + grub_printf ("\ Press enter to boot the selected OS, \'e\' to edit the\n\ commands before booting or \'c\' for a command-line."); + } + else + { + grub_printf ("\ + Press \'p\' to enter password and unlock command-line and\n\ + menu entry edition."); + } if (nested) grub_printf ("\n\ ESC to return previous menu."); @@ -408,13 +420,46 @@ run_menu (grub_menu_t menu, int nested) break; case 'c': + if ( grub_password_is_user_authenticated(0) != 1 ) + { + if (ask_and_check_password() == 0) + goto proceed_cmdline; + goto refresh; + } + + proceed_cmdline: grub_cmdline_run (1); goto refresh; case 'e': + if ( grub_password_is_user_authenticated(0) != 1 ) + { + if (ask_and_check_password() == 0) + goto proceed_edition; + goto refresh; + } + + proceed_edition: grub_menu_entry_run (get_entry (menu, first + offset)); goto refresh; - + + case 'p': + /* Authenticate voluntarily and go to next file is any */ + if ( grub_password_is_password_set() != 0 ) + { + if (ask_and_check_password() == 0) + { + /* Check if there is a next file specified... */ + char *next_file = grub_password_get_next_file(); + if (next_file == 0) + goto refresh; + + grub_normal_execute( (const char*) next_file, 1); + goto refresh; + } + } + goto refresh; + default: break; } @@ -427,6 +472,38 @@ run_menu (grub_menu_t menu, int nested) return -1; } +int +ask_and_check_password(void) +{ + int ret; + int cmdline_ret; + char entered[GRUB_PASSWORD_MAX_LENGTH + 1]; + grub_memset(entered, 0, sizeof(entered)); + + /* Clear password zone, and prompt for password*/ + grub_gotoxy (0, GRUB_TERM_HEIGHT - 3); + grub_printf ("\ + "); + grub_gotoxy (0, GRUB_TERM_HEIGHT - 3); + cmdline_ret = grub_cmdline_get(" Password : ", + entered, + GRUB_PASSWORD_MAX_LENGTH, + '*', + 0); + if (cmdline_ret == 0) + goto failed; /* User taped ESC */ + + if (grub_password_check_password(entered, 0) == 0) + goto success; + + failed: + return -1; + + success: + return 0; + +} + /* Run a menu entry. */ static void run_menu_entry (grub_menu_entry_t entry)
smime.p7s
Description: S/MIME Cryptographic Signature
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel