From 2315cb466cac63ed80159ccd32f0141e578525ae Mon Sep 17 00:00:00 2001 From: jochen Date: Tue, 17 Oct 2000 13:37:27 +0000 Subject: [PATCH] Added MD5 passwords and extended the password command. --- AUTHORS | 2 +- ChangeLog | 32 +++++ NEWS | 3 + configure | 179 +++++++++++++------------ configure.in | 5 + docs/tutorial.texi | 17 ++- docs/user-ref.texi | 21 +-- stage2/Makefile.am | 4 +- stage2/Makefile.in | 55 ++++++-- stage2/builtins.c | 98 +++++++++++--- stage2/cmdline.c | 10 +- stage2/md5.c | 327 +++++++++++++++++++++++++++++++++++++++++++++ stage2/md5.h | 34 +++++ stage2/shared.h | 14 ++ stage2/stage2.c | 4 +- 15 files changed, 672 insertions(+), 133 deletions(-) create mode 100644 stage2/md5.c create mode 100644 stage2/md5.h diff --git a/AUTHORS b/AUTHORS index 202cd70a7..0115da208 100644 --- a/AUTHORS +++ b/AUTHORS @@ -29,7 +29,7 @@ Klaus Reichl wrote stage2/fsys_minix.c. Per Lundberg added graphics support to the Multiboot Specification. Jochen Hoenicke rewrote stage2/fsys_fat.c and wrote -stage2/fsys_reiserfs.c. +stage2/fsys_reiserfs.c and stage2/md5.c. Christoph Plattner added support for Net Boot Image Proposal. diff --git a/ChangeLog b/ChangeLog index 1e05cf828..6d80f71cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2000-10-17 Jochen Hoenicke + + Added MD5 passwords and extended password command: + + * configure.in (--disable-md5password): New option. + * stage2/Makefile.am (libgrub_a_SOURCES): Added md5.c. + (pre_stage2_exec_SOURCES): Likewise. + * stage2/md5.c: New file. + * stage2/shared.h (password_t): New type. + (password_type): New variable. + (BUILTIN_HIDDEN): New flag, describing that a command should not + be printed when booting the entry. + (check_password): New function. + * stage2/cmdline.c (run_script): Don't show commands that have + the hidden attribute. + * stage2/buildins.c (password_type): New variable. + (check_password): New function. + (password_func): Handle the --md5 option and set password_type. + Check if in CMDLINE or SCRIPT mode and ask password immediately. + (builtin_password): Also allow passwords in CMDLINE mode, make + it hidden, so the user wont see the password he should enter. + Changed command description. + (builtin_pause): Make the command hidden. + (pause_func): Print argument, since the command is now hidden. + * stage2/stage2.c (run_menu): Call check_password to check password. + * docs/tutorial.texi (Security): Describe the new features of the + password commands. + * docs/user-ref.texi (Menu-specific commands): password command + moved ... + (Command-line and menu commands): ... to here. New features + doumented. + 2000-10-17 OKUJI Yoshinori * stage2/builtins.c (setkey_func): Clear the all elements of diff --git a/NEWS b/NEWS index 69ab0de7b..a452d6e51 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,9 @@ New in 1.0 - XXXX-XX-XX: * The utility ``grub-install'' accepts a new option, `--recheck'. If this option is specified, probe a device map, even if it already exists. You should use this option whenever you add/remove a disk. +* The command "password" supports md5 passwords if the option `--md5' + is given. This command can now also be used to protect specific menu + items with their own password. New in 0.5.96 - 2000-10-04: * New commands, "reboot" and "halt". diff --git a/configure b/configure index a72467567..662a27df2 100644 --- a/configure +++ b/configure @@ -33,6 +33,8 @@ ac_help="$ac_help --disable-reiserfs disable ReiserFS support in Stage 2" ac_help="$ac_help --disable-gunzip disable decompression in Stage 2" +ac_help="$ac_help + --disable-md5password disable MD5 passwords in Stage 2" ac_help="$ac_help --disable-packet-retransmission turn off packet retransmission" @@ -660,7 +662,7 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:664: checking for a BSD compatible install" >&5 +echo "configure:666: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -713,7 +715,7 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 -echo "configure:717: checking whether build environment is sane" >&5 +echo "configure:719: checking whether build environment is sane" >&5 # Just in case sleep 1 echo timestamp > conftestfile @@ -780,12 +782,12 @@ else echo "configure: warning: ${am_backtick}missing' script is too old or missing" 1>&2 fi -for ac_prog in gawk mawk nawk awk +for ac_prog in mawk gawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:789: checking for $ac_word" >&5 +echo "configure:791: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -815,7 +817,7 @@ test -n "$AWK" && break done echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -echo "configure:819: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo "configure:821: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -941,7 +943,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:945: checking host system type" >&5 +echo "configure:947: checking host system type" >&5 host_alias=$host case "$host_alias" in @@ -975,7 +977,7 @@ esac # echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 -echo "configure:979: checking whether to enable maintainer-specific portions of Makefiles" >&5 +echo "configure:981: checking whether to enable maintainer-specific portions of Makefiles" >&5 # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then enableval="$enable_maintainer_mode" @@ -1001,7 +1003,7 @@ if test "x$enable_maintainer_mode" = xyes; then # Extract the first word of "perl", so it can be a program name with args. set dummy perl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1005: checking for $ac_word" >&5 +echo "configure:1007: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1048,7 +1050,7 @@ fi # echo $ac_n "checking build system type""... $ac_c" 1>&6 -echo "configure:1052: checking build system type" >&5 +echo "configure:1054: checking build system type" >&5 build_alias=$build case "$build_alias" in @@ -1074,7 +1076,7 @@ fi # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1078: checking for $ac_word" >&5 +echo "configure:1080: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1106,7 +1108,7 @@ fi # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1110: checking for $ac_word" >&5 +echo "configure:1112: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1136,7 +1138,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1140: checking for $ac_word" >&5 +echo "configure:1142: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1187,7 +1189,7 @@ fi # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1191: checking for $ac_word" >&5 +echo "configure:1193: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1219,7 +1221,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1223: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:1225: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -1230,12 +1232,12 @@ cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 1234 "configure" +#line 1236 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:1239: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1241: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -1261,12 +1263,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1265: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:1267: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:1270: checking whether we are using GNU C" >&5 +echo "configure:1272: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1275,7 +1277,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1279: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1281: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -1294,7 +1296,7 @@ ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:1298: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:1300: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1327,7 +1329,7 @@ fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1331: checking how to run the C preprocessor" >&5 +echo "configure:1333: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -1342,13 +1344,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1352: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1354: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1359,13 +1361,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1369: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1371: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1376,13 +1378,13 @@ else rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1386: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1388: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1415,7 +1417,7 @@ echo "$ac_t""$CPP" 1>&6 depcc="$CC" depcpp="$CPP" echo $ac_n "checking dependency style of $depcc""... $ac_c" 1>&6 -echo "configure:1419: checking dependency style of $depcc" >&5 +echo "configure:1421: checking dependency style of $depcc" >&5 if eval "test \"`echo '$''{'am_cv_CC_dependencies_compiler_type'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1471,7 +1473,7 @@ if test "x$with_binutils" != x; then # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1475: checking for $ac_word" >&5 +echo "configure:1477: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1508,7 +1510,7 @@ else # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1512: checking for $ac_word" >&5 +echo "configure:1514: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1548,7 +1550,7 @@ if test "x$ac_cv_prog_gcc" = xyes; then STAGE1_CFLAGS="-O2" GRUB_CFLAGS="-O2" echo $ac_n "checking whether optimization for size works""... $ac_c" 1>&6 -echo "configure:1552: checking whether optimization for size works" >&5 +echo "configure:1554: checking whether optimization for size works" >&5 if eval "test \"`echo '$''{'size_flag'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1556,14 +1558,14 @@ else saved_CFLAGS=$CFLAGS CFLAGS="-Os -g" cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1569: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* size_flag=yes else @@ -1595,7 +1597,7 @@ CPPFLAGS="$CPPFLAGS -Wall -Wmissing-prototypes -Wunused -Wshadow" CPPFLAGS="$CPPFLAGS -Wpointer-arith" echo $ac_n "checking whether -Wundef works""... $ac_c" 1>&6 -echo "configure:1599: checking whether -Wundef works" >&5 +echo "configure:1601: checking whether -Wundef works" >&5 if eval "test \"`echo '$''{'undef_flag'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1603,14 +1605,14 @@ else saved_CPPFLAGS=$CPPFLAGS CPPFLAGS="-Wundef" cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1616: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* undef_flag=yes else @@ -1637,7 +1639,7 @@ if test "x$with_binutils" != x; then # Extract the first word of "objcopy", so it can be a program name with args. set dummy objcopy; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1641: checking for $ac_word" >&5 +echo "configure:1643: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_OBJCOPY'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1673,7 +1675,7 @@ else # Extract the first word of "${ac_tool_prefix}objcopy", so it can be a program name with args. set dummy ${ac_tool_prefix}objcopy; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1677: checking for $ac_word" >&5 +echo "configure:1679: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_OBJCOPY'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1707,7 +1709,7 @@ fi # Defined in acinclude.m4. echo $ac_n "checking if C symbols get an underscore after compilation""... $ac_c" 1>&6 -echo "configure:1711: checking if C symbols get an underscore after compilation" >&5 +echo "configure:1713: checking if C symbols get an underscore after compilation" >&5 if eval "test \"`echo '$''{'grub_cv_asm_uscore'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1720,7 +1722,7 @@ func (int *list) } EOF -if { ac_try='${CC-cc} ${CFLAGS} -S conftest.c'; { (eval echo configure:1724: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.s; then +if { ac_try='${CC-cc} ${CFLAGS} -S conftest.c'; { (eval echo configure:1726: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.s; then true else { echo "configure: error: ${CC-cc} failed to produce assembly code" 1>&2; exit 1; } @@ -1746,7 +1748,7 @@ fi echo "$ac_t""$grub_cv_asm_uscore" 1>&6 echo $ac_n "checking whether ${OBJCOPY} works for absolute addresses""... $ac_c" 1>&6 -echo "configure:1750: checking whether ${OBJCOPY} works for absolute addresses" >&5 +echo "configure:1752: checking whether ${OBJCOPY} works for absolute addresses" >&5 if eval "test \"`echo '$''{'grub_cv_prog_objcopy_absolute'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1758,21 +1760,21 @@ cmain (void) } EOF -if { (eval echo configure:1762: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.o; then : +if { (eval echo configure:1764: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.o; then : else { echo "configure: error: ${CC-cc} cannot compile C source code" 1>&2; exit 1; } fi grub_cv_prog_objcopy_absolute=yes for link_addr in 2000 8000 7C00; do - if { ac_try='${CC-cc} ${CFLAGS} -nostdlib -Wl,-N -Wl,-Ttext -Wl,$link_addr conftest.o -o conftest.exec'; { (eval echo configure:1768: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then : + if { ac_try='${CC-cc} ${CFLAGS} -nostdlib -Wl,-N -Wl,-Ttext -Wl,$link_addr conftest.o -o conftest.exec'; { (eval echo configure:1770: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then : else { echo "configure: error: ${CC-cc} cannot link at address $link_addr" 1>&2; exit 1; } fi - if { ac_try='${OBJCOPY-objcopy} -O binary conftest.exec conftest'; { (eval echo configure:1772: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then : + if { ac_try='${OBJCOPY-objcopy} -O binary conftest.exec conftest'; { (eval echo configure:1774: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then : else { echo "configure: error: ${OBJCOPY-objcopy} cannot create binary files" 1>&2; exit 1; } fi - if test ! -f conftest.old || { ac_try='cmp -s conftest.old conftest'; { (eval echo configure:1776: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + if test ! -f conftest.old || { ac_try='cmp -s conftest.old conftest'; { (eval echo configure:1778: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then mv -f conftest conftest.old else grub_cv_prog_objcopy_absolute=no @@ -1789,7 +1791,7 @@ fi echo $ac_n "checking whether addr32 must be in the same line as the instruction""... $ac_c" 1>&6 -echo "configure:1793: checking whether addr32 must be in the same line as the instruction" >&5 +echo "configure:1795: checking whether addr32 must be in the same line as the instruction" >&5 if eval "test \"`echo '$''{'grub_cv_asm_prefix_requirement'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1798,7 +1800,7 @@ else l1: addr32 movb %al, l1 EOF -if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'; { (eval echo configure:1802: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then +if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'; { (eval echo configure:1804: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then grub_cv_asm_prefix_requirement=yes else grub_cv_asm_prefix_requirement=no @@ -1830,7 +1832,7 @@ echo "$ac_t""$grub_cv_asm_prefix_requirement" 1>&6 echo $ac_n "checking for .code16 addr32 assembler support""... $ac_c" 1>&6 -echo "configure:1834: checking for .code16 addr32 assembler support" >&5 +echo "configure:1836: checking for .code16 addr32 assembler support" >&5 if eval "test \"`echo '$''{'grub_cv_asm_addr32'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1845,7 +1847,7 @@ else sed -e s/@ADDR32@/addr32\;/ < conftest.s.in > conftest.s fi -if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'; { (eval echo configure:1849: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then +if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'; { (eval echo configure:1851: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then grub_cv_asm_addr32=yes else grub_cv_asm_addr32=no @@ -1862,7 +1864,7 @@ fi echo $ac_n "checking whether an absolute indirect call/jump must not be prefixed with an asterisk""... $ac_c" 1>&6 -echo "configure:1866: checking whether an absolute indirect call/jump must not be prefixed with an asterisk" >&5 +echo "configure:1868: checking whether an absolute indirect call/jump must not be prefixed with an asterisk" >&5 if eval "test \"`echo '$''{'grub_cv_asm_absolute_without_asterisk'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1873,7 +1875,7 @@ offset: .word 0 EOF -if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'; { (eval echo configure:1877: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then +if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'; { (eval echo configure:1879: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then grub_cv_asm_absolute_without_asterisk=no else grub_cv_asm_absolute_without_asterisk=yes @@ -1894,19 +1896,19 @@ echo "$ac_t""$grub_cv_asm_absolute_without_asterisk" 1>&6 echo $ac_n "checking if start is defined by the compiler""... $ac_c" 1>&6 -echo "configure:1898: checking if start is defined by the compiler" >&5 +echo "configure:1900: checking if start is defined by the compiler" >&5 if eval "test \"`echo '$''{'grub_cv_check_start_symbol'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1912: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* grub_cv_check_start_symbol=yes else @@ -1930,19 +1932,19 @@ echo "$ac_t""$grub_cv_check_start_symbol" 1>&6 echo $ac_n "checking if _start is defined by the compiler""... $ac_c" 1>&6 -echo "configure:1934: checking if _start is defined by the compiler" >&5 +echo "configure:1936: checking if _start is defined by the compiler" >&5 if eval "test \"`echo '$''{'grub_cv_check_uscore_start_symbol'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1948: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* grub_cv_check_uscore_start_symbol=yes else @@ -1971,19 +1973,19 @@ fi echo $ac_n "checking if __bss_start is defined by the compiler""... $ac_c" 1>&6 -echo "configure:1975: checking if __bss_start is defined by the compiler" >&5 +echo "configure:1977: checking if __bss_start is defined by the compiler" >&5 if eval "test \"`echo '$''{'grub_cv_check_uscore_uscore_bss_start_symbol'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1989: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* grub_cv_check_uscore_uscore_bss_start_symbol=yes else @@ -2007,19 +2009,19 @@ echo "$ac_t""$grub_cv_check_uscore_uscore_bss_start_symbol" 1>&6 echo $ac_n "checking if _edata is defined by the compiler""... $ac_c" 1>&6 -echo "configure:2011: checking if _edata is defined by the compiler" >&5 +echo "configure:2013: checking if _edata is defined by the compiler" >&5 if eval "test \"`echo '$''{'grub_cv_check_uscore_edata_symbol'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2025: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* grub_cv_check_uscore_edata_symbol=yes else @@ -2043,19 +2045,19 @@ echo "$ac_t""$grub_cv_check_uscore_edata_symbol" 1>&6 echo $ac_n "checking if edata is defined by the compiler""... $ac_c" 1>&6 -echo "configure:2047: checking if edata is defined by the compiler" >&5 +echo "configure:2049: checking if edata is defined by the compiler" >&5 if eval "test \"`echo '$''{'grub_cv_check_edata_symbol'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2061: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* grub_cv_check_edata_symbol=yes else @@ -2085,19 +2087,19 @@ fi echo $ac_n "checking if end is defined by the compiler""... $ac_c" 1>&6 -echo "configure:2089: checking if end is defined by the compiler" >&5 +echo "configure:2091: checking if end is defined by the compiler" >&5 if eval "test \"`echo '$''{'grub_cv_check_end_symbol'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2103: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* grub_cv_check_end_symbol=yes else @@ -2121,19 +2123,19 @@ echo "$ac_t""$grub_cv_check_end_symbol" 1>&6 echo $ac_n "checking if _end is defined by the compiler""... $ac_c" 1>&6 -echo "configure:2125: checking if _end is defined by the compiler" >&5 +echo "configure:2127: checking if _end is defined by the compiler" >&5 if eval "test \"`echo '$''{'grub_cv_check_uscore_end_symbol'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2139: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* grub_cv_check_uscore_end_symbol=yes else @@ -2171,7 +2173,7 @@ fi # Get the filename or the whole disk and open it. # Known to work on NetBSD. echo $ac_n "checking for opendisk in -lutil""... $ac_c" 1>&6 -echo "configure:2175: checking for opendisk in -lutil" >&5 +echo "configure:2177: checking for opendisk in -lutil" >&5 ac_lib_var=`echo util'_'opendisk | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2179,7 +2181,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lutil $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2196: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2218,7 +2220,7 @@ fi # Unless the user specify --without-curses, check for curses. if test "x$with_curses" != "xno"; then echo $ac_n "checking for wgetch in -lncurses""... $ac_c" 1>&6 -echo "configure:2222: checking for wgetch in -lncurses" >&5 +echo "configure:2224: checking for wgetch in -lncurses" >&5 ac_lib_var=`echo ncurses'_'wgetch | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2226,7 +2228,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lncurses $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2243: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2260,7 +2262,7 @@ EOF else echo "$ac_t""no" 1>&6 echo $ac_n "checking for wgetch in -lcurses""... $ac_c" 1>&6 -echo "configure:2264: checking for wgetch in -lcurses" >&5 +echo "configure:2266: checking for wgetch in -lcurses" >&5 ac_lib_var=`echo curses'_'wgetch | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2268,7 +2270,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lcurses $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2285: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2314,17 +2316,17 @@ for ac_hdr in string.h strings.h ncurses/curses.h ncurses.h curses.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2318: checking for $ac_hdr" >&5 +echo "configure:2320: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2328: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2330: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2421,6 +2423,15 @@ if test x"$enable_gunzip" = xno; then FSYS_CFLAGS="$FSYS_CFLAGS -DNO_DECOMPRESSION=1" fi +# Check whether --enable-md5password or --disable-md5password was given. +if test "${enable_md5password+set}" = set; then + enableval="$enable_md5password" + : +fi + +if test "x$enable_md5password" != xno; then + CFLAGS="$CFLAGS -DUSE_MD5_PASSWORDS=1" +fi # Check whether --enable-packet-retransmission or --disable-packet-retransmission was given. if test "${enable_packet_retransmission+set}" = set; then diff --git a/configure.in b/configure.in index 0660768dd..5649e2f17 100644 --- a/configure.in +++ b/configure.in @@ -230,6 +230,11 @@ if test x"$enable_gunzip" = xno; then FSYS_CFLAGS="$FSYS_CFLAGS -DNO_DECOMPRESSION=1" fi +AC_ARG_ENABLE(md5password, + [ --disable-md5password disable MD5 passwords in Stage 2]) +if test "x$enable_md5password" != xno; then + CFLAGS="$CFLAGS -DUSE_MD5_PASSWORDS=1" +fi dnl The netboot support. dnl General options. diff --git a/docs/tutorial.texi b/docs/tutorial.texi index 9f0ef6bf9..0bf0c01e3 100644 --- a/docs/tutorial.texi +++ b/docs/tutorial.texi @@ -979,11 +979,13 @@ run the command @command{password} in your configuration file, like this: @example -password PASSWORD +password --md5 PASSWORD @end example If this is specified, GRUB disallows any interactive control, until you -press the key @key{p} and enter @samp{PASSWORD}. +press the key @key{p} and enter @samp{PASSWORD}. The option +@option{--md5} tells GRUB that @samp{PASSWORD} is in md5 format. If it +is omitted grub assumes the @samp{PASSWORD} is in clear text. Also, you can specify an optional argument to @command{password}. See this example: @@ -1000,9 +1002,8 @@ menu entry. Usually, this wouldn't be problematic, but you might want to permit only administrators to run some of your menu entries, such as an entry for booting an insecure OS like DOS. -The solution used by GRUB is the command @command{lock}. This command -always fails until you enter a valid password, so you can use it, like -this: +GRUB provides the command @command{lock}. This command always fails +until you enter a valid password, so you can use it, like this: @example @group @@ -1017,3 +1018,9 @@ chainload +1 You should insert @command{lock} right after @command{title}, because any user can execute commands in an entry, until GRUB encounters @command{lock}. + +You can also use the command @command{password} instead of +@command{lock}. In this case the boot process will ask for the password +and stop if it was entered incorrectly. Since the @command{password} +takes its own @samp{PASSWORD} argument this is useful if you want +different passwords for different entries. diff --git a/docs/user-ref.texi b/docs/user-ref.texi index c2b00f9ab..0b45cd958 100644 --- a/docs/user-ref.texi +++ b/docs/user-ref.texi @@ -553,15 +553,6 @@ menu to be displayed by pressing @key{ESC} before the timeout expires. @end deffn -@deffn Command password passwd [new-config-file] -Disable all interactive editing control (menu entry editor and -command line) and entries protected by the command @command{lock}. If -the password @var{passwd} is entered, it loads the @var{new-config-file} -as a new config file and restarts the GRUB Stage 2, if -@var{new-config-file} is specified. Otherwise, GRUB will just unlock the -privileged instructions. -@end deffn - @deffn Command timeout sec Set a timeout, in @var{sec} seconds, before automatically booting the default entry (normally the first entry defined). @@ -704,6 +695,18 @@ specification in GRUB syntax (@pxref{Naming convention}); @var{type} is the new partition type and must be a number in the range 0-0xff. @end deffn +@deffn Command password [@option{--md5}] passwd [new-config-file] +If used in the first section of a menu file, disable all interactive +editing control (menu entry editor and command line) and entries +protected by the command @command{lock}. If the password @var{passwd} is +entered, it loads the @var{new-config-file} as a new config file and +restarts the GRUB Stage 2, if @var{new-config-file} is +specified. Otherwise, GRUB will just unlock the privileged instructions. +You can also use this command in the script section, in which case it +will ask for the password, before continueing. The option +@option{--md5} tells GRUB that @var{passwd} is encrypted with md5crypt. +@end deffn + @deffn Command rarp Initialize a network device via the @dfn{RARP} protocol. This command is only available if GRUB is compiled with netboot support. diff --git a/stage2/Makefile.am b/stage2/Makefile.am index e1240e46e..53a1750b8 100644 --- a/stage2/Makefile.am +++ b/stage2/Makefile.am @@ -16,7 +16,7 @@ INCLUDES = -I$(top_srcdir)/stage1 noinst_LIBRARIES = libgrub.a libgrub_a_SOURCES = boot.c builtins.c common.c char_io.c cmdline.c \ disk_io.c gunzip.c fsys_ffs.c fsys_ext2fs.c fsys_fat.c \ - fsys_minix.c fsys_reiserfs.c stage2.c + fsys_minix.c fsys_reiserfs.c stage2.c md5.c libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \ -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \ -DFSYS_MINIX=1 -DFSYS_REISERFS=1 -DSUPPORT_SERIAL \ @@ -72,7 +72,7 @@ STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1 pre_stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c common.c \ char_io.c cmdline.c disk_io.c gunzip.c fsys_ext2fs.c \ fsys_fat.c fsys_ffs.c fsys_minix.c fsys_reiserfs.c serial.c \ - smp-imps.c stage2.c + smp-imps.c stage2.c md5.c pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK) diff --git a/stage2/Makefile.in b/stage2/Makefile.in index 9a3405957..6f4004951 100644 --- a/stage2/Makefile.in +++ b/stage2/Makefile.in @@ -105,7 +105,7 @@ INCLUDES = -I$(top_srcdir)/stage1 noinst_LIBRARIES = libgrub.a libgrub_a_SOURCES = boot.c builtins.c common.c char_io.c cmdline.c \ disk_io.c gunzip.c fsys_ffs.c fsys_ext2fs.c fsys_fat.c \ - fsys_minix.c fsys_reiserfs.c stage2.c + fsys_minix.c fsys_reiserfs.c stage2.c md5.c libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \ -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \ @@ -152,7 +152,7 @@ STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1 pre_stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c common.c \ char_io.c cmdline.c disk_io.c gunzip.c fsys_ext2fs.c \ fsys_fat.c fsys_ffs.c fsys_minix.c fsys_reiserfs.c serial.c \ - smp-imps.c stage2.c + smp-imps.c stage2.c md5.c pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK) @@ -247,7 +247,7 @@ am_libgrub_a_OBJECTS = libgrub_a-boot.o libgrub_a-builtins.o \ libgrub_a-common.o libgrub_a-char_io.o libgrub_a-cmdline.o \ libgrub_a-disk_io.o libgrub_a-gunzip.o libgrub_a-fsys_ffs.o \ libgrub_a-fsys_ext2fs.o libgrub_a-fsys_fat.o libgrub_a-fsys_minix.o \ -libgrub_a-fsys_reiserfs.o libgrub_a-stage2.o +libgrub_a-fsys_reiserfs.o libgrub_a-stage2.o libgrub_a-md5.o libgrub_a_OBJECTS = $(am_libgrub_a_OBJECTS) AR = ar PROGRAMS = $(noinst_PROGRAMS) @@ -258,7 +258,8 @@ diskless_exec-char_io.o diskless_exec-cmdline.o diskless_exec-disk_io.o \ diskless_exec-gunzip.o diskless_exec-fsys_ext2fs.o \ diskless_exec-fsys_fat.o diskless_exec-fsys_ffs.o \ diskless_exec-fsys_minix.o diskless_exec-fsys_reiserfs.o \ -diskless_exec-serial.o diskless_exec-smp-imps.o diskless_exec-stage2.o +diskless_exec-serial.o diskless_exec-smp-imps.o diskless_exec-stage2.o \ +diskless_exec-md5.o diskless_exec_OBJECTS = $(am_diskless_exec_OBJECTS) diskless_exec_DEPENDENCIES = ../netboot/libdrivers.a am_e2fs_stage1_5_exec_OBJECTS = e2fs_stage1_5_exec-start.o \ @@ -305,7 +306,8 @@ pre_stage2_exec-disk_io.o pre_stage2_exec-gunzip.o \ pre_stage2_exec-fsys_ext2fs.o pre_stage2_exec-fsys_fat.o \ pre_stage2_exec-fsys_ffs.o pre_stage2_exec-fsys_minix.o \ pre_stage2_exec-fsys_reiserfs.o pre_stage2_exec-serial.o \ -pre_stage2_exec-smp-imps.o pre_stage2_exec-stage2.o +pre_stage2_exec-smp-imps.o pre_stage2_exec-stage2.o \ +pre_stage2_exec-md5.o pre_stage2_exec_OBJECTS = $(am_pre_stage2_exec_OBJECTS) @NETBOOT_SUPPORT_TRUE@pre_stage2_exec_DEPENDENCIES = \ @NETBOOT_SUPPORT_TRUE@../netboot/libdrivers.a @@ -351,9 +353,9 @@ $(DEPDIR)/diskless_exec-fsys_ext2fs.Po \ $(DEPDIR)/diskless_exec-fsys_fat.Po $(DEPDIR)/diskless_exec-fsys_ffs.Po \ $(DEPDIR)/diskless_exec-fsys_minix.Po \ $(DEPDIR)/diskless_exec-fsys_reiserfs.Po \ -$(DEPDIR)/diskless_exec-gunzip.Po $(DEPDIR)/diskless_exec-serial.Po \ -$(DEPDIR)/diskless_exec-smp-imps.Po $(DEPDIR)/diskless_exec-stage2.Po \ -$(DEPDIR)/e2fs_stage1_5_exec-asm.Po \ +$(DEPDIR)/diskless_exec-gunzip.Po $(DEPDIR)/diskless_exec-md5.Po \ +$(DEPDIR)/diskless_exec-serial.Po $(DEPDIR)/diskless_exec-smp-imps.Po \ +$(DEPDIR)/diskless_exec-stage2.Po $(DEPDIR)/e2fs_stage1_5_exec-asm.Po \ $(DEPDIR)/e2fs_stage1_5_exec-bios.Po \ $(DEPDIR)/e2fs_stage1_5_exec-char_io.Po \ $(DEPDIR)/e2fs_stage1_5_exec-common.Po \ @@ -380,8 +382,8 @@ $(DEPDIR)/libgrub_a-cmdline.Po $(DEPDIR)/libgrub_a-common.Po \ $(DEPDIR)/libgrub_a-disk_io.Po $(DEPDIR)/libgrub_a-fsys_ext2fs.Po \ $(DEPDIR)/libgrub_a-fsys_fat.Po $(DEPDIR)/libgrub_a-fsys_ffs.Po \ $(DEPDIR)/libgrub_a-fsys_minix.Po $(DEPDIR)/libgrub_a-fsys_reiserfs.Po \ -$(DEPDIR)/libgrub_a-gunzip.Po $(DEPDIR)/libgrub_a-stage2.Po \ -$(DEPDIR)/minix_stage1_5_exec-asm.Po \ +$(DEPDIR)/libgrub_a-gunzip.Po $(DEPDIR)/libgrub_a-md5.Po \ +$(DEPDIR)/libgrub_a-stage2.Po $(DEPDIR)/minix_stage1_5_exec-asm.Po \ $(DEPDIR)/minix_stage1_5_exec-bios.Po \ $(DEPDIR)/minix_stage1_5_exec-char_io.Po \ $(DEPDIR)/minix_stage1_5_exec-common.Po \ @@ -401,7 +403,8 @@ $(DEPDIR)/pre_stage2_exec-fsys_fat.Po \ $(DEPDIR)/pre_stage2_exec-fsys_ffs.Po \ $(DEPDIR)/pre_stage2_exec-fsys_minix.Po \ $(DEPDIR)/pre_stage2_exec-fsys_reiserfs.Po \ -$(DEPDIR)/pre_stage2_exec-gunzip.Po $(DEPDIR)/pre_stage2_exec-serial.Po \ +$(DEPDIR)/pre_stage2_exec-gunzip.Po $(DEPDIR)/pre_stage2_exec-md5.Po \ +$(DEPDIR)/pre_stage2_exec-serial.Po \ $(DEPDIR)/pre_stage2_exec-smp-imps.Po \ $(DEPDIR)/pre_stage2_exec-stage2.Po \ $(DEPDIR)/pxeloader_exec-pxeloader.Po \ @@ -464,6 +467,7 @@ libgrub_a-fsys_fat.o: fsys_fat.c libgrub_a-fsys_minix.o: fsys_minix.c libgrub_a-fsys_reiserfs.o: fsys_reiserfs.c libgrub_a-stage2.o: stage2.c +libgrub_a-md5.o: md5.c libgrub.a: $(libgrub_a_OBJECTS) $(libgrub_a_DEPENDENCIES) -rm -f libgrub.a @@ -496,6 +500,7 @@ diskless_exec-fsys_reiserfs.o: fsys_reiserfs.c diskless_exec-serial.o: serial.c diskless_exec-smp-imps.o: smp-imps.c diskless_exec-stage2.o: stage2.c +diskless_exec-md5.o: md5.c diskless.exec: $(diskless_exec_OBJECTS) $(diskless_exec_DEPENDENCIES) @rm -f diskless.exec @@ -580,6 +585,7 @@ pre_stage2_exec-fsys_reiserfs.o: fsys_reiserfs.c pre_stage2_exec-serial.o: serial.c pre_stage2_exec-smp-imps.o: smp-imps.c pre_stage2_exec-stage2.o: stage2.c +pre_stage2_exec-md5.o: md5.c pre_stage2.exec: $(pre_stage2_exec_OBJECTS) $(pre_stage2_exec_DEPENDENCIES) @rm -f pre_stage2.exec @@ -678,6 +684,7 @@ maintainer-clean-tags: @AMDEP@include $(DEPDIR)/diskless_exec-fsys_minix.Po @AMDEP@include $(DEPDIR)/diskless_exec-fsys_reiserfs.Po @AMDEP@include $(DEPDIR)/diskless_exec-gunzip.Po +@AMDEP@include $(DEPDIR)/diskless_exec-md5.Po @AMDEP@include $(DEPDIR)/diskless_exec-serial.Po @AMDEP@include $(DEPDIR)/diskless_exec-smp-imps.Po @AMDEP@include $(DEPDIR)/diskless_exec-stage2.Po @@ -717,6 +724,7 @@ maintainer-clean-tags: @AMDEP@include $(DEPDIR)/libgrub_a-fsys_minix.Po @AMDEP@include $(DEPDIR)/libgrub_a-fsys_reiserfs.Po @AMDEP@include $(DEPDIR)/libgrub_a-gunzip.Po +@AMDEP@include $(DEPDIR)/libgrub_a-md5.Po @AMDEP@include $(DEPDIR)/libgrub_a-stage2.Po @AMDEP@include $(DEPDIR)/minix_stage1_5_exec-asm.Po @AMDEP@include $(DEPDIR)/minix_stage1_5_exec-bios.Po @@ -741,6 +749,7 @@ maintainer-clean-tags: @AMDEP@include $(DEPDIR)/pre_stage2_exec-fsys_minix.Po @AMDEP@include $(DEPDIR)/pre_stage2_exec-fsys_reiserfs.Po @AMDEP@include $(DEPDIR)/pre_stage2_exec-gunzip.Po +@AMDEP@include $(DEPDIR)/pre_stage2_exec-md5.Po @AMDEP@include $(DEPDIR)/pre_stage2_exec-serial.Po @AMDEP@include $(DEPDIR)/pre_stage2_exec-smp-imps.Po @AMDEP@include $(DEPDIR)/pre_stage2_exec-stage2.Po @@ -879,6 +888,14 @@ libgrub_a-stage2.o: stage2.c @AMDEP@CCDEPMODE = @CCDEPMODE@ +libgrub_a-md5.o: md5.c +@AMDEP@ source='md5.c' object='libgrub_a-md5.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP@ depfile='$(DEPDIR)/libgrub_a-md5.Po' tmpdepfile='$(DEPDIR)/libgrub_a-md5.TPo' @AMDEPBACKSLASH@ +@AMDEP@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgrub_a_CFLAGS) $(CFLAGS) -c -o libgrub_a-md5.o `test -f md5.c || echo '$(srcdir)/'`md5.c + +@AMDEP@CCDEPMODE = @CCDEPMODE@ + diskless_exec-bios.o: bios.c @AMDEP@ source='bios.c' object='diskless_exec-bios.o' libtool=no @AMDEPBACKSLASH@ @AMDEP@ depfile='$(DEPDIR)/diskless_exec-bios.Po' tmpdepfile='$(DEPDIR)/diskless_exec-bios.TPo' @AMDEPBACKSLASH@ @@ -1007,6 +1024,14 @@ diskless_exec-stage2.o: stage2.c @AMDEP@CCDEPMODE = @CCDEPMODE@ +diskless_exec-md5.o: md5.c +@AMDEP@ source='md5.c' object='diskless_exec-md5.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP@ depfile='$(DEPDIR)/diskless_exec-md5.Po' tmpdepfile='$(DEPDIR)/diskless_exec-md5.TPo' @AMDEPBACKSLASH@ +@AMDEP@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(diskless_exec_CFLAGS) $(CFLAGS) -c -o diskless_exec-md5.o `test -f md5.c || echo '$(srcdir)/'`md5.c + +@AMDEP@CCDEPMODE = @CCDEPMODE@ + e2fs_stage1_5_exec-common.o: common.c @AMDEP@ source='common.c' object='e2fs_stage1_5_exec-common.o' libtool=no @AMDEPBACKSLASH@ @AMDEP@ depfile='$(DEPDIR)/e2fs_stage1_5_exec-common.Po' tmpdepfile='$(DEPDIR)/e2fs_stage1_5_exec-common.TPo' @AMDEPBACKSLASH@ @@ -1327,6 +1352,14 @@ pre_stage2_exec-stage2.o: stage2.c @AMDEP@CCDEPMODE = @CCDEPMODE@ +pre_stage2_exec-md5.o: md5.c +@AMDEP@ source='md5.c' object='pre_stage2_exec-md5.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP@ depfile='$(DEPDIR)/pre_stage2_exec-md5.Po' tmpdepfile='$(DEPDIR)/pre_stage2_exec-md5.TPo' @AMDEPBACKSLASH@ +@AMDEP@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-md5.o `test -f md5.c || echo '$(srcdir)/'`md5.c + +@AMDEP@CCDEPMODE = @CCDEPMODE@ + reiserfs_stage1_5_exec-common.o: common.c @AMDEP@ source='common.c' object='reiserfs_stage1_5_exec-common.o' libtool=no @AMDEPBACKSLASH@ @AMDEP@ depfile='$(DEPDIR)/reiserfs_stage1_5_exec-common.Po' tmpdepfile='$(DEPDIR)/reiserfs_stage1_5_exec-common.TPo' @AMDEPBACKSLASH@ diff --git a/stage2/builtins.c b/stage2/builtins.c index f4eede19d..a2fb187be 100644 --- a/stage2/builtins.c +++ b/stage2/builtins.c @@ -43,6 +43,10 @@ # include #endif /* ! GRUB_UTIL */ +#ifdef USE_MD5_PASSWORDS +# include +#endif + /* Terminal types. */ int terminal = TERMINAL_CONSOLE; /* The type of kernel loaded. */ @@ -62,6 +66,8 @@ int current_entryno; static char *mb_cmdline; /* The password. */ char *password; +/* The password type. */ +password_t password_type; /* The flag for indicating that the user is authoritative. */ int auth = 0; /* Color settings. */ @@ -96,6 +102,26 @@ init_config (void) grub_timeout = -1; } +/* Check a password for correctness. Returns 0 if password was + correct, and a value != 0 for error, similarly to strcmp. */ +int +check_password (char *entered, char* expected, password_t type) +{ + switch (type) + { + case PASSWORD_PLAIN: + return strcmp (entered, expected); + +#ifdef USE_MD5_PASSWORDS + case PASSWORD_MD5: + return check_md5_password (entered, expected); +#endif + default: + /* unsupported password type: be secure */ + return 1; + } +} + /* Print which sector is read when loading a file. */ static void disk_read_print_func (int sector, int offset, int length) @@ -2588,19 +2614,55 @@ static struct builtin builtin_parttype = static int password_func (char *arg, int flags) { - int len = grub_strlen (arg); + int len; + password_t type = PASSWORD_PLAIN; - /* PASSWORD NUL NUL ... */ - if (len + 2 > PASSWORD_BUFLEN) +#ifdef USE_MD5_PASSWORDS + if (grub_memcmp (arg, "--md5", 5) == 0) { - errnum = ERR_WONT_FIT; - return 1; + type = PASSWORD_MD5; + arg = skip_to (0, arg); + } +#endif + if (grub_memcmp (arg, "--", 2) == 0) + { + type = PASSWORD_UNSUPPORTED; + arg = skip_to (0, arg); } - /* Copy the password and clear the rest of the buffer. */ - password = (char *) PASSWORD_BUF; - grub_memmove (password, arg, len); - grub_memset (password + len, 0, PASSWORD_BUFLEN - len); + if ((flags & (BUILTIN_CMDLINE | BUILTIN_SCRIPT)) != 0) + { + /* Do password check! */ + char entered[32]; + + /* Wipe out any previously entered password */ + entered[0] = 0; + get_cmdline ("Password: ", entered, 31, '*', 0); + + nul_terminate (arg); + if (check_password (entered, arg, type) != 0) + { + errnum = ERR_PRIVILEGED; + return 1; + } + } + else + { + len = grub_strlen (arg); + + /* PASSWORD NUL NUL ... */ + if (len + 2 > PASSWORD_BUFLEN) + { + errnum = ERR_WONT_FIT; + return 1; + } + + /* Copy the password and clear the rest of the buffer. */ + password = (char *) PASSWORD_BUF; + grub_memmove (password, arg, len); + grub_memset (password + len, 0, PASSWORD_BUFLEN - len); + password_type = type; + } return 0; } @@ -2608,15 +2670,17 @@ static struct builtin builtin_password = { "password", password_func, - BUILTIN_MENU, -#if 0 - "password PASSWD [FILE]", - "Disable all interactive editing control (menu entry editor and" + BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HIDDEN, + "password [--md5] PASSWD [FILE]", + "If used in the first section of a menu file, disable all" + " interactive editing control (menu entry editor and" " command line). If the password PASSWD is entered, it loads the" " FILE as a new config file and restarts the GRUB Stage 2. If you" " omit the argument FILE, then GRUB just unlocks privileged" - " instructions." -#endif + " instructions. You can also use it in the script section, in" + " which case it will ask for the password, before continueing." + " The option --md5 tells GRUB that PASSWD is encrypted with" + " md5crypt." }; @@ -2624,6 +2688,8 @@ static struct builtin builtin_password = static int pause_func (char *arg, int flags) { + printf("%s\n", arg); + /* If ESC is returned, then abort this entry. */ if (ASCII_CHAR (getkey ()) == 27) return 1; @@ -2635,7 +2701,7 @@ static struct builtin builtin_pause = { "pause", pause_func, - BUILTIN_CMDLINE, + BUILTIN_CMDLINE | BUILTIN_HIDDEN, "pause [MESSAGE ...]", "Print MESSAGE, then wait until a key is pressed." }; diff --git a/stage2/cmdline.c b/stage2/cmdline.c index a6368a4c1..7d7a35dc6 100644 --- a/stage2/cmdline.c +++ b/stage2/cmdline.c @@ -202,8 +202,6 @@ run_script (char *script, char *heap) ; grub_memmove (heap, old_entry, (int) cur_entry - (int) old_entry); - grub_printf ("%s\n", old_entry); - if (! *heap) { /* If there is no more command in SCRIPT... */ @@ -219,7 +217,13 @@ run_script (char *script, char *heap) /* Find a builtin. */ builtin = find_command (heap); if (! builtin) - continue; + { + grub_printf ("%s\n", old_entry); + continue; + } + + if (! (builtin->flags & BUILTIN_HIDDEN)) + grub_printf ("%s\n", old_entry); /* If BUILTIN cannot be run in the command-line, skip it. */ if (! (builtin->flags & BUILTIN_CMDLINE)) diff --git a/stage2/md5.c b/stage2/md5.c new file mode 100644 index 000000000..2d290b421 --- /dev/null +++ b/stage2/md5.c @@ -0,0 +1,327 @@ +/* md5.c - an implementation of the MD5 algorithm and MD5 crypt */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000 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. + */ + +/* See RFC 1321 for a description of the MD5 algorithm. + */ + +#include +#ifndef TEST +#include +#endif + +#ifdef TEST +#include +#define USE_MD5_PASSWORDS +#define USE_MD5 +#endif + +#ifdef USE_MD5_PASSWORDS +#define USE_MD5 +#endif + +#ifdef USE_MD5 + +#define cpu_to_le32(x) (x) +#define le32_to_cpu(x) cpu_to_le32(x) +typedef unsigned int UINT4; + +/* 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 UINT4 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 UINT4 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 UINT4 state[4]; +static unsigned int length; +static unsigned char buffer[64]; + +static void md5_transform (const unsigned char block[64]) +{ + int i, j; + UINT4 a,b,c,d,tmp; + const UINT4 *x = (UINT4*) 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) + le32_to_cpu(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) + le32_to_cpu(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) + le32_to_cpu(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) + le32_to_cpu(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; +} + +void md5_init() { + memcpy ((char *)state, (char *)initstate, sizeof (initstate)); + length = 0; +} + +void md5_update(const char *input, int inputlen) { + int buflen = length & 63; + length += inputlen; + if (buflen + inputlen < 64) + { + memcpy(buffer + buflen, input, inputlen); + buflen += inputlen; + return; + } + + memcpy(buffer + buflen, input, 64 - buflen); + md5_transform (buffer); + input += 64 - buflen; + inputlen -= 64 - buflen; + while (inputlen >= 64) + { + md5_transform (input); + input += 64; + inputlen -= 64; + } + memcpy(buffer, input, inputlen); + buflen = inputlen; +} + +unsigned char* md5_final() +{ + int i, buflen = length & 63; + + buffer[buflen++] = 0x80; + memset (buffer+buflen, 0, 64 - buflen); + if (buflen > 56) + { + md5_transform (buffer); + memset (buffer, 0, 64); + buflen = 0; + } + + *(UINT4 *) (buffer + 56) = cpu_to_le32(8*length); + *(UINT4 *) (buffer + 60) = 0; + md5_transform (buffer); + + for (i=0; i < 4; i++) + state[i] = cpu_to_le32 (state[i]); + return (unsigned char*) state; +} + +#ifdef USE_MD5_PASSWORDS +/* Check a password for correctness. Returns 0 if password was + correct, and a value != 0 for error, similarly to strcmp. */ +int check_md5_password (const char* key, const char* crypted) { + int keylen = strlen(key); + char *salt = crypted + 3; /* skip $1$ header */ + char *p; + int saltlen = strstr(salt, "$") - salt; + int i,n; + unsigned char alt_result[16]; + unsigned char *digest; + + md5_init(); + md5_update(key, keylen); + md5_update(salt, saltlen); + md5_update(key, keylen); + digest = md5_final(); + memcpy(alt_result, digest, 16); + + 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(alt_result, 16); + md5_update(alt_result, i); + + for (i = keylen; i > 0; i >>= 1) + md5_update(key + ((i & 1) ? keylen : 0), 1); + digest = md5_final(); + + for (i = 0; i < 1000; i++) + { + memcpy(alt_result, digest, 16); + + memcpy ((char *)state, (char *)initstate, sizeof (initstate)); + length = 0; + if ((i & 1) != 0) + md5_update(key, keylen); + else + md5_update(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(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 (*p++ != b64t[w & 0x3f]) + return 1; + w >>= 6; + } + } + { + unsigned int w = digest[11]; + for (n = 2; n-- > 0;) + { + if (*p++ != b64t[w & 0x3f]) + return 1; + w >>= 6; + } + } + return *p; +} +#endif + +#ifdef TEST +static char* md5 (const char* input) +{ + memcpy ((char *)state, (char *)initstate, sizeof (initstate)); + length = 0; + md5_update(input, strlen (input)); + return md5_final(); +} + +static void test (char *buffer, char *expected) +{ + char result[16 * 3 +1]; + unsigned char* digest = md5 (buffer); + int i; + + for (i=0; i < 16; i++) + sprintf (result+2*i, "%02x", digest[i]); + + if (strcmp (result, expected)) + printf ("MD5(%s) failed: %s\n", buffer, result); + else + printf ("MD5(%s) OK\n", buffer); +} + +int main () +{ + test ("", "d41d8cd98f00b204e9800998ecf8427e"); + test ("a", "0cc175b9c0f1b6a831c399e269772661"); + test ("abc", "900150983cd24fb0d6963f7d28e17f72"); + test ("message digest", "f96b697d7cb7938d525a2f31aaf161d0"); + test ("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b"); + test ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "d174ab98d277d9f5a5611c2c9f419d9f"); + test ("12345678901234567890123456789012345678901234567890123456789012345678901234567890", + "57edf4a22be3c955ac49da2e2107b67a"); + test ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz3456", + "6831fa90115bb9a54fbcd4f9fee0b5c4"); + test ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz345", + "bc40505cc94a43b7ff3e2ac027325233"); + test ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz34567", + "fa94b73a6f072a0239b52acacfbcf9fa"); + test ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz345678901234", + "bd201eae17f29568927414fa326f1267"); + test ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz34567890123", + "80063db1e6b70a2e91eac903f0e46b85"); + + if (check_md5_password("Hello world!", + "$1$saltstri$YMyguxXMBpd2TEZ.vS/3q1")) + printf("Password differs\n"); + else + printf("Password OK\n"); + return 0; +} +#endif + +#endif diff --git a/stage2/md5.h b/stage2/md5.h new file mode 100644 index 000000000..2b7579050 --- /dev/null +++ b/stage2/md5.h @@ -0,0 +1,34 @@ +/* md5.h - an implementation of the MD5 algorithm and MD5 crypt */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000 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. + */ + +/* Initialize the buffers to compute a new md5 checksum. This will + destroy any previously calculated md5 sum. */ +extern void md5_init(void); + +/* Digestify the given input. This may be called multiple times. */ +extern void md5_update(const char *input, int inputlen); + +/* Calculate the 16 byte md5 check sum. The result will be valid until + the next md5_init(). */ +extern unsigned char* md5_final(void); + +/* Check a md5 password for validity. Returns 0 if password was + correct, and a value != 0 for error, similarly to strcmp. */ +extern int check_md5_password (const char* key, const char* crypted); diff --git a/stage2/shared.h b/stage2/shared.h index dcc16c11c..8e39fb27f 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -501,7 +501,18 @@ extern void assign_device_name (int drive, const char *device); extern int fallback_entry; extern int default_entry; extern int current_entryno; + +/* The constants for password types. */ +typedef enum +{ + PASSWORD_PLAIN, + PASSWORD_MD5, + PASSWORD_UNSUPPORTED +} +password_t; + extern char *password; +extern password_t password_type; extern int auth; extern char commands[]; #endif @@ -718,6 +729,7 @@ void stop_floppy (void); #define BUILTIN_MENU 0x2 /* Run in the menu. */ #define BUILTIN_TITLE 0x4 /* Only for the command title. */ #define BUILTIN_SCRIPT 0x8 /* Run in the script. */ +#define BUILTIN_HIDDEN 0x10 /* Don't print command on booting. */ /* The table for a builtin. */ struct builtin @@ -892,6 +904,8 @@ kernel_t load_image (char *kernel, char *arg, kernel_t suggested_type, int load_module (char *module, char *arg); int load_initrd (char *initrd); + +int check_password(char *entered, char* expected, password_t type); #endif void init_bios_info (void); diff --git a/stage2/stage2.c b/stage2/stage2.c index c6bbf5a12..1f7ffc243 100644 --- a/stage2/stage2.c +++ b/stage2/stage2.c @@ -318,7 +318,7 @@ restart: grub_memset (entered, 0, sizeof (entered)); get_cmdline ("Password: ", entered, 31, '*', 0); } - while (grub_strcmp (password, entered) != 0); + while (check_password (entered, password, password_type) != 0); } enter_cmdline (heap, 1); @@ -558,7 +558,7 @@ restart: /* Make sure that PASSWORD is NUL-terminated. */ *pptr++ = 0; - if (! strcmp (password, entered)) + if (! check_password (entered, password, password_type)) { char *new_file = config_file; while (isspace (*pptr))