From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1IHl19-0004kx-Dl for mharc-grub-devel@gnu.org; Sun, 05 Aug 2007 14:39:55 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1IHl16-0004iL-UZ for grub-devel@gnu.org; Sun, 05 Aug 2007 14:39:53 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1IHl10-0004ZQ-Fs for grub-devel@gnu.org; Sun, 05 Aug 2007 14:39:52 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1IHl10-0004ZD-94 for grub-devel@gnu.org; Sun, 05 Aug 2007 14:39:46 -0400 Received: from [66.249.92.168] (helo=ug-out-1314.google.com) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1IHl0x-00067r-QS for grub-devel@gnu.org; Sun, 05 Aug 2007 14:39:45 -0400 Received: by ug-out-1314.google.com with SMTP id 34so709887ugf for ; Sun, 05 Aug 2007 11:39:15 -0700 (PDT) DKIM-Signature: a=rsa-sha1; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:disposition-notification-to:date:from:user-agent:mime-version:to:subject:content-type; b=k8Jb7lxzxFISG3aBudJierrXa98s+9qIi2dccH30VYK1X4dOTYmQLCHvkN+q0pWQeqAI7Nzr0CIIEYkLyMCBgjNvKxyo2sQw3mdhbvHGm0XPtnkjQFeJrM37Nz8O7EzPlWhaSx4pfOq8VwQ0ly4Z/kOXHVVJyT4XUm+IkDUSmZ8= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:disposition-notification-to:date:from:user-agent:mime-version:to:subject:content-type; b=Tp3yBG3ieKZ5qYn0hcZidVAEQxlpzQMYeGUgAI7AToYyht2D9o5WPiL7YUONlqSZw7XYErYdCJqh/t58pqdttuaPK5DASTmTiPxrku9U7rUVYcp4ePYgphI78RY745MU8uT6C/V5fVbTv/LAhrKaFRWTQ84TDbuYOPZ4awhl1II= Received: by 10.67.15.17 with SMTP id s17mr4583813ugi.1186339154792; Sun, 05 Aug 2007 11:39:14 -0700 (PDT) Received: from ?192.168.2.3? ( [88.176.208.48]) by mx.google.com with ESMTPS id r38sm2661622ugc.2007.08.05.11.39.09 (version=TLSv1/SSLv3 cipher=RC4-MD5); Sun, 05 Aug 2007 11:39:10 -0700 (PDT) Message-ID: <46B6193D.4010403@gmail.com> Date: Sun, 05 Aug 2007 20:38:53 +0200 From: Julien RANC User-Agent: Thunderbird 1.5.0.12 (X11/20070604) MIME-Version: 1.0 To: grub-devel@gnu.org, julien.ranc@gmail.com Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------ms000808070701090601060607" X-Detected-Kernel: Linux 2.4-2.6 (Google crawlbot) Cc: Subject: [PATCH] password command implementation X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: The development of GRUB 2 List-Id: The development of GRUB 2 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 05 Aug 2007 18:39:53 -0000 This is a cryptographically signed message in MIME format. --------------ms000808070701090601060607 Content-Type: multipart/mixed; boundary="------------090005000105040609060007" This is a multi-part message in MIME format. --------------090005000105040609060007 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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 julien.ranc@gmail.com --------------090005000105040609060007 Content-Type: text/plain; name="patch_1.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="patch_1.txt" --- 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 . + */ + +/* See RFC 1321 for a description of the MD5 algorithm. */ + +#include +#include +#include + +/* 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 +#include +#include /* for error codes */ +#include /* for memory mngt */ +#include /* for string manipulation */ +#include +#include + +/** + * 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 . + */ + + +/* 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 + +/* 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 */ + --------------090005000105040609060007 Content-Type: text/plain; name="patch_2.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="patch_2.txt" 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 #include #include +#include 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 #include #include +#include + +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) --------------090005000105040609060007-- --------------ms000808070701090601060607 Content-Type: application/x-pkcs7-signature; name="smime.p7s" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="smime.p7s" Content-Description: S/MIME Cryptographic Signature MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIJBzCC At4wggJHoAMCAQICECWevNWjd1IbZbVZVG6t+Y0wDQYJKoZIhvcNAQEFBQAwYjELMAkGA1UE BhMCWkExJTAjBgNVBAoTHFRoYXd0ZSBDb25zdWx0aW5nIChQdHkpIEx0ZC4xLDAqBgNVBAMT I1RoYXd0ZSBQZXJzb25hbCBGcmVlbWFpbCBJc3N1aW5nIENBMB4XDTA3MDIxNzEyNTg1OFoX DTA4MDIxNzEyNTg1OFowgZ8xDTALBgNVBAQTBFJBTkMxDzANBgNVBCoTBkp1bGllbjEUMBIG A1UEAxMLSnVsaWVuIFJBTkMxITAfBgkqhkiG9w0BCQEWEmoucmFuY0BsYXBvc3RlLm5ldDEe MBwGCSqGSIb3DQEJARYPanJhbmNAanJhbmMuY29tMSQwIgYJKoZIhvcNAQkBFhVqdWxpZW4u cmFuY0BnbWFpbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPKyCb2ym6Zt1hwj YnQEyF/gBoYBqPtbjMFr/iZA9oKPKOXJ20BkSEg0TOYT4q6dDf2SvKWH+7FVon7uslSgKumc k2PVb6FoEtWuyR8CgMDCCBdcJ5Frm471DftT+zxyTEzSaEZgGb0bQxujGOBDYPSVF+VDi4IQ AzlivxvyZvSxAgMBAAGjVzBVMEUGA1UdEQQ+MDyBEmoucmFuY0BsYXBvc3RlLm5ldIEPanJh bmNAanJhbmMuY29tgRVqdWxpZW4ucmFuY0BnbWFpbC5jb20wDAYDVR0TAQH/BAIwADANBgkq hkiG9w0BAQUFAAOBgQALvbQR35RcTVb8O7vWqXzJtvT/75tnZHVgf6kibuzolcDnba42GfY2 RmeCX8n2Fwu3AEWDn3CiHxi9Ino29oYnx4Qamhoz0RxOay3ESSZMjpiyoejHtr5OYersQjJo 6X0ZfMTASdkMkyYwcwQCF7tTGDoKwRzEY/QrNnzpF+s0azCCAt4wggJHoAMCAQICECWevNWj d1IbZbVZVG6t+Y0wDQYJKoZIhvcNAQEFBQAwYjELMAkGA1UEBhMCWkExJTAjBgNVBAoTHFRo YXd0ZSBDb25zdWx0aW5nIChQdHkpIEx0ZC4xLDAqBgNVBAMTI1RoYXd0ZSBQZXJzb25hbCBG cmVlbWFpbCBJc3N1aW5nIENBMB4XDTA3MDIxNzEyNTg1OFoXDTA4MDIxNzEyNTg1OFowgZ8x DTALBgNVBAQTBFJBTkMxDzANBgNVBCoTBkp1bGllbjEUMBIGA1UEAxMLSnVsaWVuIFJBTkMx ITAfBgkqhkiG9w0BCQEWEmoucmFuY0BsYXBvc3RlLm5ldDEeMBwGCSqGSIb3DQEJARYPanJh bmNAanJhbmMuY29tMSQwIgYJKoZIhvcNAQkBFhVqdWxpZW4ucmFuY0BnbWFpbC5jb20wgZ8w DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPKyCb2ym6Zt1hwjYnQEyF/gBoYBqPtbjMFr/iZA 9oKPKOXJ20BkSEg0TOYT4q6dDf2SvKWH+7FVon7uslSgKumck2PVb6FoEtWuyR8CgMDCCBdc J5Frm471DftT+zxyTEzSaEZgGb0bQxujGOBDYPSVF+VDi4IQAzlivxvyZvSxAgMBAAGjVzBV MEUGA1UdEQQ+MDyBEmoucmFuY0BsYXBvc3RlLm5ldIEPanJhbmNAanJhbmMuY29tgRVqdWxp ZW4ucmFuY0BnbWFpbC5jb20wDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQUFAAOBgQALvbQR 35RcTVb8O7vWqXzJtvT/75tnZHVgf6kibuzolcDnba42GfY2RmeCX8n2Fwu3AEWDn3CiHxi9 Ino29oYnx4Qamhoz0RxOay3ESSZMjpiyoejHtr5OYersQjJo6X0ZfMTASdkMkyYwcwQCF7tT GDoKwRzEY/QrNnzpF+s0azCCAz8wggKooAMCAQICAQ0wDQYJKoZIhvcNAQEFBQAwgdExCzAJ BgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEa MBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2Vy dmljZXMgRGl2aXNpb24xJDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBGcmVlbWFpbCBDQTEr MCkGCSqGSIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhhd3RlLmNvbTAeFw0wMzA3MTcw MDAwMDBaFw0xMzA3MTYyMzU5NTlaMGIxCzAJBgNVBAYTAlpBMSUwIwYDVQQKExxUaGF3dGUg Q29uc3VsdGluZyAoUHR5KSBMdGQuMSwwKgYDVQQDEyNUaGF3dGUgUGVyc29uYWwgRnJlZW1h aWwgSXNzdWluZyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxKY8VXNV+065ypla HmjAdQRwnd/p/6Me7L3N9VvyGna9fww6YfK/Uc4B1OVQCjDXAmNaLIkVcI7dyfArhVqqP3FW y688Cwfn8R+RNiQqE88r1fOCdz0Dviv+uxg+B79AgAJk16emu59l0cUqVIUPSAR/p7bRPGEE QB5kGXJgt/sCAwEAAaOBlDCBkTASBgNVHRMBAf8ECDAGAQH/AgEAMEMGA1UdHwQ8MDowOKA2 oDSGMmh0dHA6Ly9jcmwudGhhd3RlLmNvbS9UaGF3dGVQZXJzb25hbEZyZWVtYWlsQ0EuY3Js MAsGA1UdDwQEAwIBBjApBgNVHREEIjAgpB4wHDEaMBgGA1UEAxMRUHJpdmF0ZUxhYmVsMi0x MzgwDQYJKoZIhvcNAQEFBQADgYEASIzRUIPqCy7MDaNmrGcPf6+svsIXoUOWlJ1/TCG4+DYf qi2fNi/A9BxQIJNwPP2t4WFiw9k6GX6EsZkbAMUaC4J0niVQlGLH2ydxVyWN3amcOY6MIE9l X5Xa9/eH1sYITq726jTlEBpbNU1341YheILcIRk13iSx0x1G/11fZU8xggLjMIIC3wIBATB2 MGIxCzAJBgNVBAYTAlpBMSUwIwYDVQQKExxUaGF3dGUgQ29uc3VsdGluZyAoUHR5KSBMdGQu MSwwKgYDVQQDEyNUaGF3dGUgUGVyc29uYWwgRnJlZW1haWwgSXNzdWluZyBDQQIQJZ681aN3 UhtltVlUbq35jTAJBgUrDgMCGgUAoIIBwzAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwG CSqGSIb3DQEJBTEPFw0wNzA4MDUxODM5MDFaMCMGCSqGSIb3DQEJBDEWBBSp5X36++sUmg/R fkJ8mqnqwFz8dDBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqGSIb3DQMHMA4GCCqGSIb3DQMCAgIA gDANBggqhkiG9w0DAgIBQDAHBgUrDgMCBzANBggqhkiG9w0DAgIBKDCBhQYJKwYBBAGCNxAE MXgwdjBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg THRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVtYWlsIElzc3VpbmcgQ0ECECWe vNWjd1IbZbVZVG6t+Y0wgYcGCyqGSIb3DQEJEAILMXigdjBiMQswCQYDVQQGEwJaQTElMCMG A1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBl cnNvbmFsIEZyZWVtYWlsIElzc3VpbmcgQ0ECECWevNWjd1IbZbVZVG6t+Y0wDQYJKoZIhvcN AQEBBQAEgYAJ1WRrPUgDvWxQ+PmZXqWHMmGVF/8KhTse1hUVP/Qq4eanvT00v0KRAG9iJsAK NBD/lzx6hGgcB/xT8xWdw3PKDW5sD61LqG65AsyRZeh9qb0RJpCjMB0RvLm0dRbd8ba8iF60 5hxHaOwwQbPN5qdz5xb8QXfpEIkW3tv6roHBOAAAAAAAAA== --------------ms000808070701090601060607--