| /* |
| * GRUB -- GRand Unified Bootloader |
| * Copyright (C) 2000, 2001, 2010 Free Software Foundation, Inc. |
| * |
| * GRUB is free software: you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation, either version 3 of the License, or |
| * (at your option) any later version. |
| * |
| * GRUB is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with GRUB. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #include <grub/types.h> |
| #include <grub/misc.h> |
| #include <grub/command.h> |
| #include <grub/mm.h> |
| #include <grub/err.h> |
| #include <grub/dl.h> |
| #include <grub/file.h> |
| #include <grub/normal.h> |
| #include <grub/script_sh.h> |
| #include <grub/i18n.h> |
| #include <grub/term.h> |
| #include <grub/legacy_parse.h> |
| #include <grub/crypto.h> |
| #include <grub/auth.h> |
| #include <grub/disk.h> |
| #include <grub/partition.h> |
| |
| GRUB_MOD_LICENSE ("GPLv3+"); |
| |
| /* Helper for legacy_file. */ |
| static grub_err_t |
| legacy_file_getline (char **line, int cont __attribute__ ((unused)), |
| void *data __attribute__ ((unused))) |
| { |
| *line = 0; |
| return GRUB_ERR_NONE; |
| } |
| |
| static grub_err_t |
| legacy_file (const char *filename) |
| { |
| grub_file_t file; |
| char *entryname = NULL, *entrysrc = NULL; |
| grub_menu_t menu; |
| char *suffix = grub_strdup (""); |
| |
| if (!suffix) |
| return grub_errno; |
| |
| file = grub_file_open (filename, GRUB_FILE_TYPE_CONFIG); |
| if (! file) |
| { |
| grub_free (suffix); |
| return grub_errno; |
| } |
| |
| menu = grub_env_get_menu (); |
| if (! menu) |
| { |
| menu = grub_zalloc (sizeof (*menu)); |
| if (! menu) |
| { |
| grub_free (suffix); |
| return grub_errno; |
| } |
| |
| grub_env_set_menu (menu); |
| } |
| |
| while (1) |
| { |
| char *buf = grub_file_getline (file); |
| char *parsed = NULL; |
| |
| if (!buf && grub_errno) |
| { |
| grub_file_close (file); |
| grub_free (suffix); |
| return grub_errno; |
| } |
| |
| if (!buf) |
| break; |
| |
| { |
| char *oldname = NULL; |
| char *newsuffix; |
| char *ptr; |
| |
| for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); |
| |
| oldname = entryname; |
| parsed = grub_legacy_parse (ptr, &entryname, &newsuffix); |
| grub_free (buf); |
| buf = NULL; |
| if (newsuffix) |
| { |
| char *t; |
| |
| t = suffix; |
| suffix = grub_realloc (suffix, grub_strlen (suffix) |
| + grub_strlen (newsuffix) + 1); |
| if (!suffix) |
| { |
| grub_free (t); |
| grub_free (entrysrc); |
| grub_free (parsed); |
| grub_free (newsuffix); |
| grub_free (suffix); |
| return grub_errno; |
| } |
| grub_memcpy (suffix + grub_strlen (suffix), newsuffix, |
| grub_strlen (newsuffix) + 1); |
| grub_free (newsuffix); |
| newsuffix = NULL; |
| } |
| if (oldname != entryname && oldname) |
| { |
| const char **args = grub_malloc (sizeof (args[0])); |
| if (!args) |
| { |
| grub_file_close (file); |
| return grub_errno; |
| } |
| args[0] = oldname; |
| grub_normal_add_menu_entry (1, args, NULL, NULL, "legacy", |
| NULL, NULL, |
| entrysrc, 0); |
| grub_free (args); |
| entrysrc[0] = 0; |
| grub_free (oldname); |
| } |
| } |
| |
| if (parsed && !entryname) |
| { |
| grub_normal_parse_line (parsed, legacy_file_getline, NULL); |
| grub_print_error (); |
| grub_free (parsed); |
| parsed = NULL; |
| } |
| else if (parsed) |
| { |
| if (!entrysrc) |
| entrysrc = parsed; |
| else |
| { |
| char *t; |
| |
| t = entrysrc; |
| entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc) |
| + grub_strlen (parsed) + 1); |
| if (!entrysrc) |
| { |
| grub_free (t); |
| grub_free (parsed); |
| grub_free (suffix); |
| return grub_errno; |
| } |
| grub_memcpy (entrysrc + grub_strlen (entrysrc), parsed, |
| grub_strlen (parsed) + 1); |
| grub_free (parsed); |
| parsed = NULL; |
| } |
| } |
| } |
| grub_file_close (file); |
| |
| if (entryname) |
| { |
| const char **args = grub_malloc (sizeof (args[0])); |
| if (!args) |
| { |
| grub_file_close (file); |
| grub_free (suffix); |
| grub_free (entrysrc); |
| return grub_errno; |
| } |
| args[0] = entryname; |
| grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, |
| NULL, NULL, entrysrc, 0); |
| grub_free (args); |
| } |
| |
| grub_normal_parse_line (suffix, legacy_file_getline, NULL); |
| grub_print_error (); |
| grub_free (suffix); |
| grub_free (entrysrc); |
| |
| return GRUB_ERR_NONE; |
| } |
| |
| static grub_err_t |
| grub_cmd_legacy_source (struct grub_command *cmd, |
| int argc, char **args) |
| { |
| int new_env, extractor; |
| grub_err_t ret; |
| |
| if (argc != 1) |
| return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); |
| |
| extractor = (cmd->name[0] == 'e'); |
| new_env = (cmd->name[extractor ? (sizeof ("extract_legacy_entries_") - 1) |
| : (sizeof ("legacy_") - 1)] == 'c'); |
| |
| if (new_env) |
| grub_cls (); |
| |
| if (new_env && !extractor) |
| grub_env_context_open (); |
| if (extractor) |
| grub_env_extractor_open (!new_env); |
| |
| ret = legacy_file (args[0]); |
| |
| if (new_env) |
| { |
| grub_menu_t menu; |
| menu = grub_env_get_menu (); |
| if (menu && menu->size) |
| grub_show_menu (menu, 1, 0); |
| if (!extractor) |
| grub_env_context_close (); |
| } |
| if (extractor) |
| grub_env_extractor_close (!new_env); |
| |
| return ret; |
| } |
| |
| static enum |
| { |
| GUESS_IT, LINUX, MULTIBOOT, KFREEBSD, KNETBSD, KOPENBSD |
| } kernel_type; |
| |
| static grub_err_t |
| grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), |
| int argc, char **args) |
| { |
| int i; |
| #ifdef TODO |
| int no_mem_option = 0; |
| #endif |
| struct grub_command *cmd; |
| char **cutargs; |
| int cutargc; |
| grub_err_t err = GRUB_ERR_NONE; |
| |
| for (i = 0; i < 2; i++) |
| { |
| /* FIXME: really support this. */ |
| if (argc >= 1 && grub_strcmp (args[0], "--no-mem-option") == 0) |
| { |
| #ifdef TODO |
| no_mem_option = 1; |
| #endif |
| argc--; |
| args++; |
| continue; |
| } |
| |
| /* linux16 handles both zImages and bzImages. */ |
| if (argc >= 1 && (grub_strcmp (args[0], "--type=linux") == 0 |
| || grub_strcmp (args[0], "--type=biglinux") == 0)) |
| { |
| kernel_type = LINUX; |
| argc--; |
| args++; |
| continue; |
| } |
| |
| if (argc >= 1 && grub_strcmp (args[0], "--type=multiboot") == 0) |
| { |
| kernel_type = MULTIBOOT; |
| argc--; |
| args++; |
| continue; |
| } |
| |
| if (argc >= 1 && grub_strcmp (args[0], "--type=freebsd") == 0) |
| { |
| kernel_type = KFREEBSD; |
| argc--; |
| args++; |
| continue; |
| } |
| |
| if (argc >= 1 && grub_strcmp (args[0], "--type=openbsd") == 0) |
| { |
| kernel_type = KOPENBSD; |
| argc--; |
| args++; |
| continue; |
| } |
| |
| if (argc >= 1 && grub_strcmp (args[0], "--type=netbsd") == 0) |
| { |
| kernel_type = KNETBSD; |
| argc--; |
| args++; |
| continue; |
| } |
| } |
| |
| if (argc < 2) |
| return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); |
| |
| cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1)); |
| if (!cutargs) |
| return grub_errno; |
| cutargc = argc - 1; |
| grub_memcpy (cutargs + 1, args + 2, sizeof (cutargs[0]) * (argc - 2)); |
| cutargs[0] = args[0]; |
| |
| do |
| { |
| /* First try Linux. */ |
| if (kernel_type == GUESS_IT || kernel_type == LINUX) |
| { |
| #ifdef GRUB_MACHINE_PCBIOS |
| cmd = grub_command_find ("linux16"); |
| #else |
| cmd = grub_command_find ("linux"); |
| #endif |
| if (cmd) |
| { |
| if (!(cmd->func) (cmd, cutargc, cutargs)) |
| { |
| kernel_type = LINUX; |
| goto out; |
| } |
| } |
| grub_errno = GRUB_ERR_NONE; |
| } |
| |
| /* Then multiboot. */ |
| if (kernel_type == GUESS_IT || kernel_type == MULTIBOOT) |
| { |
| cmd = grub_command_find ("multiboot"); |
| if (cmd) |
| { |
| if (!(cmd->func) (cmd, argc, args)) |
| { |
| kernel_type = MULTIBOOT; |
| goto out; |
| } |
| } |
| grub_errno = GRUB_ERR_NONE; |
| } |
| |
| { |
| int bsd_device = -1; |
| int bsd_slice = -1; |
| int bsd_part = -1; |
| { |
| grub_device_t dev; |
| const char *hdbiasstr; |
| int hdbias = 0; |
| hdbiasstr = grub_env_get ("legacy_hdbias"); |
| if (hdbiasstr) |
| { |
| hdbias = grub_strtoul (hdbiasstr, 0, 0); |
| grub_errno = GRUB_ERR_NONE; |
| } |
| dev = grub_device_open (0); |
| if (dev && dev->disk |
| && dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID |
| && dev->disk->id >= 0x80 && dev->disk->id <= 0x90) |
| { |
| struct grub_partition *part = dev->disk->partition; |
| bsd_device = dev->disk->id - 0x80 - hdbias; |
| if (part && (grub_strcmp (part->partmap->name, "netbsd") == 0 |
| || grub_strcmp (part->partmap->name, "openbsd") == 0 |
| || grub_strcmp (part->partmap->name, "bsd") == 0)) |
| { |
| bsd_part = part->number; |
| part = part->parent; |
| } |
| if (part && grub_strcmp (part->partmap->name, "msdos") == 0) |
| bsd_slice = part->number; |
| } |
| if (dev) |
| grub_device_close (dev); |
| } |
| |
| /* k*BSD didn't really work well with grub-legacy. */ |
| if (kernel_type == GUESS_IT || kernel_type == KFREEBSD) |
| { |
| char buf[sizeof("adXXXXXXXXXXXXsXXXXXXXXXXXXYYY")]; |
| if (bsd_device != -1) |
| { |
| if (bsd_slice != -1 && bsd_part != -1) |
| grub_snprintf(buf, sizeof(buf), "ad%ds%d%c", bsd_device, |
| bsd_slice, 'a' + bsd_part); |
| else if (bsd_slice != -1) |
| grub_snprintf(buf, sizeof(buf), "ad%ds%d", bsd_device, |
| bsd_slice); |
| else |
| grub_snprintf(buf, sizeof(buf), "ad%d", bsd_device); |
| grub_env_set ("kFreeBSD.vfs.root.mountfrom", buf); |
| } |
| else |
| grub_env_unset ("kFreeBSD.vfs.root.mountfrom"); |
| cmd = grub_command_find ("kfreebsd"); |
| if (cmd) |
| { |
| if (!(cmd->func) (cmd, cutargc, cutargs)) |
| { |
| kernel_type = KFREEBSD; |
| goto out; |
| } |
| } |
| grub_errno = GRUB_ERR_NONE; |
| } |
| { |
| char **bsdargs; |
| int bsdargc; |
| char bsddevname[sizeof ("wdXXXXXXXXXXXXY")]; |
| int found = 0; |
| |
| if (bsd_device == -1) |
| { |
| bsdargs = cutargs; |
| bsdargc = cutargc; |
| } |
| else |
| { |
| char rbuf[3] = "-r"; |
| bsdargc = cutargc + 2; |
| bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc); |
| if (!bsdargs) |
| { |
| err = grub_errno; |
| goto out; |
| } |
| grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0])); |
| bsdargs[argc] = rbuf; |
| bsdargs[argc + 1] = bsddevname; |
| grub_snprintf (bsddevname, sizeof (bsddevname), |
| "wd%d%c", bsd_device, |
| bsd_part != -1 ? bsd_part + 'a' : 'c'); |
| } |
| if (kernel_type == GUESS_IT || kernel_type == KNETBSD) |
| { |
| cmd = grub_command_find ("knetbsd"); |
| if (cmd) |
| { |
| if (!(cmd->func) (cmd, bsdargc, bsdargs)) |
| { |
| kernel_type = KNETBSD; |
| found = 1; |
| goto free_bsdargs; |
| } |
| } |
| grub_errno = GRUB_ERR_NONE; |
| } |
| if (kernel_type == GUESS_IT || kernel_type == KOPENBSD) |
| { |
| cmd = grub_command_find ("kopenbsd"); |
| if (cmd) |
| { |
| if (!(cmd->func) (cmd, bsdargc, bsdargs)) |
| { |
| kernel_type = KOPENBSD; |
| found = 1; |
| goto free_bsdargs; |
| } |
| } |
| grub_errno = GRUB_ERR_NONE; |
| } |
| |
| free_bsdargs: |
| if (bsdargs != cutargs) |
| grub_free (bsdargs); |
| if (found) |
| goto out; |
| } |
| } |
| } |
| while (0); |
| |
| err = grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s", |
| args[0]); |
| out: |
| grub_free (cutargs); |
| return err; |
| } |
| |
| static grub_err_t |
| grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)), |
| int argc, char **args) |
| { |
| struct grub_command *cmd; |
| |
| if (kernel_type == LINUX) |
| { |
| #ifdef GRUB_MACHINE_PCBIOS |
| cmd = grub_command_find ("initrd16"); |
| #else |
| cmd = grub_command_find ("initrd"); |
| #endif |
| if (!cmd) |
| return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"), |
| #ifdef GRUB_MACHINE_PCBIOS |
| "initrd16" |
| #else |
| "initrd" |
| #endif |
| ); |
| |
| return cmd->func (cmd, argc ? 1 : 0, args); |
| } |
| if (kernel_type == MULTIBOOT) |
| { |
| cmd = grub_command_find ("module"); |
| if (!cmd) |
| return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"), |
| "module"); |
| |
| return cmd->func (cmd, argc, args); |
| } |
| |
| return grub_error (GRUB_ERR_BAD_ARGUMENT, |
| N_("you need to load the kernel first")); |
| } |
| |
| static grub_err_t |
| grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused)), |
| int argc, char **args) |
| { |
| struct grub_command *cmd; |
| |
| if (kernel_type == LINUX) |
| { |
| cmd = grub_command_find ("initrd16"); |
| if (!cmd) |
| return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"), |
| "initrd16"); |
| |
| return cmd->func (cmd, argc, args); |
| } |
| if (kernel_type == MULTIBOOT) |
| { |
| char **newargs; |
| grub_err_t err; |
| char nounzipbuf[10] = "--nounzip"; |
| |
| cmd = grub_command_find ("module"); |
| if (!cmd) |
| return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"), |
| "module"); |
| |
| newargs = grub_malloc ((argc + 1) * sizeof (newargs[0])); |
| if (!newargs) |
| return grub_errno; |
| grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0])); |
| newargs[0] = nounzipbuf; |
| |
| err = cmd->func (cmd, argc + 1, newargs); |
| grub_free (newargs); |
| return err; |
| } |
| |
| return grub_error (GRUB_ERR_BAD_ARGUMENT, |
| N_("you need to load the kernel first")); |
| } |
| |
| static grub_err_t |
| check_password_deny (const char *user __attribute__ ((unused)), |
| const char *entered __attribute__ ((unused)), |
| void *password __attribute__ ((unused))) |
| { |
| return GRUB_ACCESS_DENIED; |
| } |
| |
| #define MD5_HASHLEN 16 |
| |
| struct legacy_md5_password |
| { |
| grub_uint8_t *salt; |
| int saltlen; |
| grub_uint8_t hash[MD5_HASHLEN]; |
| }; |
| |
| static int |
| check_password_md5_real (const char *entered, |
| struct legacy_md5_password *pw) |
| { |
| grub_size_t enteredlen = grub_strlen (entered); |
| unsigned char alt_result[MD5_HASHLEN]; |
| unsigned char *digest; |
| grub_uint8_t *ctx; |
| grub_size_t i; |
| int ret; |
| |
| ctx = grub_zalloc (GRUB_MD_MD5->contextsize); |
| if (!ctx) |
| return 0; |
| |
| GRUB_MD_MD5->init (ctx); |
| GRUB_MD_MD5->write (ctx, entered, enteredlen); |
| GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3); |
| GRUB_MD_MD5->write (ctx, entered, enteredlen); |
| digest = GRUB_MD_MD5->read (ctx); |
| GRUB_MD_MD5->final (ctx); |
| grub_memcpy (alt_result, digest, MD5_HASHLEN); |
| |
| GRUB_MD_MD5->init (ctx); |
| GRUB_MD_MD5->write (ctx, entered, enteredlen); |
| GRUB_MD_MD5->write (ctx, pw->salt, pw->saltlen); /* include the $1$ header */ |
| for (i = enteredlen; i > 16; i -= 16) |
| GRUB_MD_MD5->write (ctx, alt_result, 16); |
| GRUB_MD_MD5->write (ctx, alt_result, i); |
| |
| for (i = enteredlen; i > 0; i >>= 1) |
| GRUB_MD_MD5->write (ctx, entered + ((i & 1) ? enteredlen : 0), 1); |
| digest = GRUB_MD_MD5->read (ctx); |
| GRUB_MD_MD5->final (ctx); |
| |
| for (i = 0; i < 1000; i++) |
| { |
| grub_memcpy (alt_result, digest, 16); |
| |
| GRUB_MD_MD5->init (ctx); |
| if ((i & 1) != 0) |
| GRUB_MD_MD5->write (ctx, entered, enteredlen); |
| else |
| GRUB_MD_MD5->write (ctx, alt_result, 16); |
| |
| if (i % 3 != 0) |
| GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3); |
| |
| if (i % 7 != 0) |
| GRUB_MD_MD5->write (ctx, entered, enteredlen); |
| |
| if ((i & 1) != 0) |
| GRUB_MD_MD5->write (ctx, alt_result, 16); |
| else |
| GRUB_MD_MD5->write (ctx, entered, enteredlen); |
| digest = GRUB_MD_MD5->read (ctx); |
| GRUB_MD_MD5->final (ctx); |
| } |
| |
| ret = (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0); |
| grub_free (ctx); |
| return ret; |
| } |
| |
| static grub_err_t |
| check_password_md5 (const char *user, |
| const char *entered, |
| void *password) |
| { |
| if (!check_password_md5_real (entered, password)) |
| return GRUB_ACCESS_DENIED; |
| |
| grub_auth_authenticate (user); |
| |
| return GRUB_ERR_NONE; |
| } |
| |
| static inline int |
| ib64t (char c) |
| { |
| if (c == '.') |
| return 0; |
| if (c == '/') |
| return 1; |
| if (c >= '0' && c <= '9') |
| return c - '0' + 2; |
| if (c >= 'A' && c <= 'Z') |
| return c - 'A' + 12; |
| if (c >= 'a' && c <= 'z') |
| return c - 'a' + 38; |
| return -1; |
| } |
| |
| static struct legacy_md5_password * |
| parse_legacy_md5 (int argc, char **args) |
| { |
| const char *salt, *saltend; |
| struct legacy_md5_password *pw = NULL; |
| int i; |
| const char *p; |
| |
| if (grub_memcmp (args[0], "--md5", sizeof ("--md5")) != 0) |
| goto fail; |
| if (argc == 1) |
| goto fail; |
| if (grub_strlen(args[1]) <= 3) |
| goto fail; |
| salt = args[1]; |
| saltend = grub_strchr (salt + 3, '$'); |
| if (!saltend) |
| goto fail; |
| pw = grub_malloc (sizeof (*pw)); |
| if (!pw) |
| goto fail; |
| |
| p = saltend + 1; |
| for (i = 0; i < 5; i++) |
| { |
| int n; |
| grub_uint32_t w = 0; |
| |
| for (n = 0; n < 4; n++) |
| { |
| int ww = ib64t(*p++); |
| if (ww == -1) |
| goto fail; |
| w |= ww << (n * 6); |
| } |
| pw->hash[i == 4 ? 5 : 12+i] = w & 0xff; |
| pw->hash[6+i] = (w >> 8) & 0xff; |
| pw->hash[i] = (w >> 16) & 0xff; |
| } |
| { |
| int n; |
| grub_uint32_t w = 0; |
| for (n = 0; n < 2; n++) |
| { |
| int ww = ib64t(*p++); |
| if (ww == -1) |
| goto fail; |
| w |= ww << (6 * n); |
| } |
| if (w >= 0x100) |
| goto fail; |
| pw->hash[11] = w; |
| } |
| |
| pw->saltlen = saltend - salt; |
| pw->salt = (grub_uint8_t *) grub_strndup (salt, pw->saltlen); |
| if (!pw->salt) |
| goto fail; |
| |
| return pw; |
| |
| fail: |
| grub_free (pw); |
| return NULL; |
| } |
| |
| static grub_err_t |
| grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)), |
| int argc, char **args) |
| { |
| struct legacy_md5_password *pw = NULL; |
| |
| if (argc == 0) |
| return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); |
| if (args[0][0] != '-' || args[0][1] != '-') |
| return grub_normal_set_password ("legacy", args[0]); |
| |
| pw = parse_legacy_md5 (argc, args); |
| |
| if (pw) |
| return grub_auth_register_authentication ("legacy", check_password_md5, pw); |
| else |
| /* This is to imitate minor difference between grub-legacy in GRUB2. |
| If 2 password commands are executed in a row and second one fails |
| on GRUB2 the password of first one is used, whereas in grub-legacy |
| authenthication is denied. In case of no password command was executed |
| early both versions deny any access. */ |
| return grub_auth_register_authentication ("legacy", check_password_deny, |
| NULL); |
| } |
| |
| int |
| grub_legacy_check_md5_password (int argc, char **args, |
| char *entered) |
| { |
| struct legacy_md5_password *pw = NULL; |
| int ret; |
| |
| if (args[0][0] != '-' || args[0][1] != '-') |
| { |
| char correct[GRUB_AUTH_MAX_PASSLEN]; |
| |
| grub_memset (correct, 0, sizeof (correct)); |
| grub_strncpy (correct, args[0], sizeof (correct)); |
| |
| return grub_crypto_memcmp (entered, correct, GRUB_AUTH_MAX_PASSLEN) == 0; |
| } |
| |
| pw = parse_legacy_md5 (argc, args); |
| |
| if (!pw) |
| return 0; |
| |
| ret = check_password_md5_real (entered, pw); |
| grub_free (pw); |
| return ret; |
| } |
| |
| static grub_err_t |
| grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unused)), |
| int argc, char **args) |
| { |
| char entered[GRUB_AUTH_MAX_PASSLEN]; |
| |
| if (argc == 0) |
| return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); |
| grub_puts_ (N_("Enter password: ")); |
| if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) |
| return GRUB_ACCESS_DENIED; |
| |
| if (!grub_legacy_check_md5_password (argc, args, |
| entered)) |
| return GRUB_ACCESS_DENIED; |
| |
| return GRUB_ERR_NONE; |
| } |
| |
| static grub_command_t cmd_source, cmd_configfile; |
| static grub_command_t cmd_source_extract, cmd_configfile_extract; |
| static grub_command_t cmd_kernel, cmd_initrd, cmd_initrdnounzip; |
| static grub_command_t cmd_password, cmd_check_password; |
| |
| GRUB_MOD_INIT(legacycfg) |
| { |
| cmd_source |
| = grub_register_command ("legacy_source", |
| grub_cmd_legacy_source, |
| N_("FILE"), |
| /* TRANSLATORS: "legacy config" means |
| "config as used by grub-legacy". */ |
| N_("Parse legacy config in same context")); |
| cmd_configfile |
| = grub_register_command ("legacy_configfile", |
| grub_cmd_legacy_source, |
| N_("FILE"), |
| N_("Parse legacy config in new context")); |
| cmd_source_extract |
| = grub_register_command ("extract_legacy_entries_source", |
| grub_cmd_legacy_source, |
| N_("FILE"), |
| N_("Parse legacy config in same context taking only menu entries")); |
| cmd_configfile_extract |
| = grub_register_command ("extract_legacy_entries_configfile", |
| grub_cmd_legacy_source, |
| N_("FILE"), |
| N_("Parse legacy config in new context taking only menu entries")); |
| |
| cmd_kernel = grub_register_command ("legacy_kernel", |
| grub_cmd_legacy_kernel, |
| N_("[--no-mem-option] [--type=TYPE] FILE [ARG ...]"), |
| N_("Simulate grub-legacy `kernel' command")); |
| |
| cmd_initrd = grub_register_command ("legacy_initrd", |
| grub_cmd_legacy_initrd, |
| N_("FILE [ARG ...]"), |
| N_("Simulate grub-legacy `initrd' command")); |
| cmd_initrdnounzip = grub_register_command ("legacy_initrd_nounzip", |
| grub_cmd_legacy_initrdnounzip, |
| N_("FILE [ARG ...]"), |
| N_("Simulate grub-legacy `modulenounzip' command")); |
| |
| cmd_password = grub_register_command ("legacy_password", |
| grub_cmd_legacy_password, |
| N_("[--md5] PASSWD [FILE]"), |
| N_("Simulate grub-legacy `password' command")); |
| |
| cmd_check_password = grub_register_command ("legacy_check_password", |
| grub_cmd_legacy_check_password, |
| N_("[--md5] PASSWD [FILE]"), |
| N_("Simulate grub-legacy `password' command in menu entry mode")); |
| |
| } |
| |
| GRUB_MOD_FINI(legacycfg) |
| { |
| grub_unregister_command (cmd_source); |
| grub_unregister_command (cmd_configfile); |
| grub_unregister_command (cmd_source_extract); |
| grub_unregister_command (cmd_configfile_extract); |
| |
| grub_unregister_command (cmd_kernel); |
| grub_unregister_command (cmd_initrd); |
| grub_unregister_command (cmd_initrdnounzip); |
| |
| grub_unregister_command (cmd_password); |
| grub_unregister_command (cmd_check_password); |
| } |