/* * VasEBoot -- GRand Unified Bootloader * Copyright (C) 2000, 2001, 2010 Free Software Foundation, Inc. * * VasEBoot 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. * * VasEBoot 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 VasEBoot. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include VasEBoot_MOD_LICENSE ("GPLv3+"); /* Helper for legacy_file. */ static VasEBoot_err_t legacy_file_getline (char **line, int cont __attribute__ ((unused)), void *data __attribute__ ((unused))) { *line = 0; return VasEBoot_ERR_NONE; } static VasEBoot_err_t legacy_file (const char *filename) { VasEBoot_file_t file; char *entryname = NULL, *entrysrc = NULL; VasEBoot_menu_t menu; char *suffix = VasEBoot_strdup (""); if (!suffix) return VasEBoot_errno; file = VasEBoot_file_open (filename); if (! file) { VasEBoot_free (suffix); return VasEBoot_errno; } menu = VasEBoot_env_get_menu (); if (! menu) { menu = VasEBoot_zalloc (sizeof (*menu)); if (! menu) { VasEBoot_free (suffix); return VasEBoot_errno; } VasEBoot_env_set_menu (menu); } while (1) { char *buf = VasEBoot_file_getline (file); char *parsed = NULL; if (!buf && VasEBoot_errno) { VasEBoot_file_close (file); VasEBoot_free (suffix); return VasEBoot_errno; } if (!buf) break; { char *oldname = NULL; char *newsuffix; char *ptr; for (ptr = buf; *ptr && VasEBoot_isspace (*ptr); ptr++); oldname = entryname; parsed = VasEBoot_legacy_parse (ptr, &entryname, &newsuffix); VasEBoot_free (buf); buf = NULL; if (newsuffix) { char *t; t = suffix; suffix = VasEBoot_realloc (suffix, VasEBoot_strlen (suffix) + VasEBoot_strlen (newsuffix) + 1); if (!suffix) { VasEBoot_free (t); VasEBoot_free (entrysrc); VasEBoot_free (parsed); VasEBoot_free (newsuffix); VasEBoot_free (suffix); return VasEBoot_errno; } VasEBoot_memcpy (suffix + VasEBoot_strlen (suffix), newsuffix, VasEBoot_strlen (newsuffix) + 1); VasEBoot_free (newsuffix); newsuffix = NULL; } if (oldname != entryname && oldname) { const char **args = VasEBoot_malloc (sizeof (args[0])); if (!args) { VasEBoot_file_close (file); return VasEBoot_errno; } args[0] = oldname; VasEBoot_normal_add_menu_entry (1, args, NULL, NULL, "legacy", NULL, NULL, entrysrc, 0); VasEBoot_free (args); entrysrc[0] = 0; VasEBoot_free (oldname); } } if (parsed && !entryname) { VasEBoot_normal_parse_line (parsed, legacy_file_getline, NULL); VasEBoot_print_error (); VasEBoot_free (parsed); parsed = NULL; } else if (parsed) { if (!entrysrc) entrysrc = parsed; else { char *t; t = entrysrc; entrysrc = VasEBoot_realloc (entrysrc, VasEBoot_strlen (entrysrc) + VasEBoot_strlen (parsed) + 1); if (!entrysrc) { VasEBoot_free (t); VasEBoot_free (parsed); VasEBoot_free (suffix); return VasEBoot_errno; } VasEBoot_memcpy (entrysrc + VasEBoot_strlen (entrysrc), parsed, VasEBoot_strlen (parsed) + 1); VasEBoot_free (parsed); parsed = NULL; } } } VasEBoot_file_close (file); if (entryname) { const char **args = VasEBoot_malloc (sizeof (args[0])); if (!args) { VasEBoot_file_close (file); VasEBoot_free (suffix); VasEBoot_free (entrysrc); return VasEBoot_errno; } args[0] = entryname; VasEBoot_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL, NULL, entrysrc, 0); VasEBoot_free (args); } VasEBoot_normal_parse_line (suffix, legacy_file_getline, NULL); VasEBoot_print_error (); VasEBoot_free (suffix); VasEBoot_free (entrysrc); return VasEBoot_ERR_NONE; } static VasEBoot_err_t VasEBoot_cmd_legacy_source (struct VasEBoot_command *cmd, int argc, char **args) { int new_env, extractor; VasEBoot_err_t ret; if (argc != 1) return VasEBoot_error (VasEBoot_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) VasEBoot_cls (); if (new_env && !extractor) VasEBoot_env_context_open (); if (extractor) VasEBoot_env_extractor_open (!new_env); ret = legacy_file (args[0]); if (new_env) { VasEBoot_menu_t menu; menu = VasEBoot_env_get_menu (); if (menu && menu->size) VasEBoot_show_menu (menu, 1, 0); if (!extractor) VasEBoot_env_context_close (); } if (extractor) VasEBoot_env_extractor_close (!new_env); return ret; } static enum { GUESS_IT, LINUX, MULTIBOOT, KFREEBSD, KNETBSD, KOPENBSD } kernel_type; static VasEBoot_err_t VasEBoot_cmd_legacy_kernel (struct VasEBoot_command *mycmd __attribute__ ((unused)), int argc, char **args) { int i; #ifdef TODO int no_mem_option = 0; #endif struct VasEBoot_command *cmd; char **cutargs; int cutargc; VasEBoot_err_t err = VasEBoot_ERR_NONE; for (i = 0; i < 2; i++) { /* FIXME: really support this. */ if (argc >= 1 && VasEBoot_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 && (VasEBoot_strcmp (args[0], "--type=linux") == 0 || VasEBoot_strcmp (args[0], "--type=biglinux") == 0)) { kernel_type = LINUX; argc--; args++; continue; } if (argc >= 1 && VasEBoot_strcmp (args[0], "--type=multiboot") == 0) { kernel_type = MULTIBOOT; argc--; args++; continue; } if (argc >= 1 && VasEBoot_strcmp (args[0], "--type=freebsd") == 0) { kernel_type = KFREEBSD; argc--; args++; continue; } if (argc >= 1 && VasEBoot_strcmp (args[0], "--type=openbsd") == 0) { kernel_type = KOPENBSD; argc--; args++; continue; } if (argc >= 1 && VasEBoot_strcmp (args[0], "--type=netbsd") == 0) { kernel_type = KNETBSD; argc--; args++; continue; } } if (argc < 2) return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT, N_("filename expected")); cutargs = VasEBoot_malloc (sizeof (cutargs[0]) * (argc - 1)); if (!cutargs) return VasEBoot_errno; cutargc = argc - 1; VasEBoot_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 VasEBoot_MACHINE_PCBIOS cmd = VasEBoot_command_find ("linux16"); #else cmd = VasEBoot_command_find ("linux"); #endif if (cmd) { if (!(cmd->func) (cmd, cutargc, cutargs)) { kernel_type = LINUX; goto out; } } VasEBoot_errno = VasEBoot_ERR_NONE; } /* Then multiboot. */ if (kernel_type == GUESS_IT || kernel_type == MULTIBOOT) { cmd = VasEBoot_command_find ("multiboot"); if (cmd) { if (!(cmd->func) (cmd, argc, args)) { kernel_type = MULTIBOOT; goto out; } } VasEBoot_errno = VasEBoot_ERR_NONE; } { int bsd_device = -1; int bsd_slice = -1; int bsd_part = -1; { VasEBoot_device_t dev; const char *hdbiasstr; int hdbias = 0; hdbiasstr = VasEBoot_env_get ("legacy_hdbias"); if (hdbiasstr) { hdbias = VasEBoot_strtoul (hdbiasstr, 0, 0); VasEBoot_errno = VasEBoot_ERR_NONE; } dev = VasEBoot_device_open (0); if (dev && dev->disk && dev->disk->dev->id == VasEBoot_DISK_DEVICE_BIOSDISK_ID && dev->disk->id >= 0x80 && dev->disk->id <= 0x90) { struct VasEBoot_partition *part = dev->disk->partition; bsd_device = dev->disk->id - 0x80 - hdbias; if (part && (VasEBoot_strcmp (part->partmap->name, "netbsd") == 0 || VasEBoot_strcmp (part->partmap->name, "openbsd") == 0 || VasEBoot_strcmp (part->partmap->name, "bsd") == 0)) { bsd_part = part->number; part = part->parent; } if (part && VasEBoot_strcmp (part->partmap->name, "msdos") == 0) bsd_slice = part->number; } if (dev) VasEBoot_device_close (dev); } /* k*BSD didn't really work well with VasEBoot-legacy. */ if (kernel_type == GUESS_IT || kernel_type == KFREEBSD) { char buf[sizeof("adXXXXXXXXXXXXsXXXXXXXXXXXXYYY")]; if (bsd_device != -1) { if (bsd_slice != -1 && bsd_part != -1) VasEBoot_snprintf(buf, sizeof(buf), "ad%ds%d%c", bsd_device, bsd_slice, 'a' + bsd_part); else if (bsd_slice != -1) VasEBoot_snprintf(buf, sizeof(buf), "ad%ds%d", bsd_device, bsd_slice); else VasEBoot_snprintf(buf, sizeof(buf), "ad%d", bsd_device); VasEBoot_env_set ("kFreeBSD.vfs.root.mountfrom", buf); } else VasEBoot_env_unset ("kFreeBSD.vfs.root.mountfrom"); cmd = VasEBoot_command_find ("kfreebsd"); if (cmd) { if (!(cmd->func) (cmd, cutargc, cutargs)) { kernel_type = KFREEBSD; goto out; } } VasEBoot_errno = VasEBoot_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 = VasEBoot_malloc (sizeof (bsdargs[0]) * bsdargc); if (!bsdargs) { err = VasEBoot_errno; goto out; } VasEBoot_memcpy (bsdargs, args, argc * sizeof (bsdargs[0])); bsdargs[argc] = rbuf; bsdargs[argc + 1] = bsddevname; VasEBoot_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 = VasEBoot_command_find ("knetbsd"); if (cmd) { if (!(cmd->func) (cmd, bsdargc, bsdargs)) { kernel_type = KNETBSD; found = 1; goto free_bsdargs; } } VasEBoot_errno = VasEBoot_ERR_NONE; } if (kernel_type == GUESS_IT || kernel_type == KOPENBSD) { cmd = VasEBoot_command_find ("kopenbsd"); if (cmd) { if (!(cmd->func) (cmd, bsdargc, bsdargs)) { kernel_type = KOPENBSD; found = 1; goto free_bsdargs; } } VasEBoot_errno = VasEBoot_ERR_NONE; } free_bsdargs: if (bsdargs != cutargs) VasEBoot_free (bsdargs); if (found) goto out; } } } while (0); err = VasEBoot_error (VasEBoot_ERR_BAD_OS, "couldn't load file %s", args[0]); out: VasEBoot_free (cutargs); return err; } static VasEBoot_err_t VasEBoot_cmd_legacy_initrd (struct VasEBoot_command *mycmd __attribute__ ((unused)), int argc, char **args) { struct VasEBoot_command *cmd; if (kernel_type == LINUX) { #ifdef VasEBoot_MACHINE_PCBIOS cmd = VasEBoot_command_find ("initrd16"); #else cmd = VasEBoot_command_find ("initrd"); #endif if (!cmd) return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT, N_("can't find command `%s'"), #ifdef VasEBoot_MACHINE_PCBIOS "initrd16" #else "initrd" #endif ); return cmd->func (cmd, argc ? 1 : 0, args); } if (kernel_type == MULTIBOOT) { cmd = VasEBoot_command_find ("module"); if (!cmd) return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT, N_("can't find command `%s'"), "module"); return cmd->func (cmd, argc, args); } return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); } static VasEBoot_err_t VasEBoot_cmd_legacy_initrdnounzip (struct VasEBoot_command *mycmd __attribute__ ((unused)), int argc, char **args) { struct VasEBoot_command *cmd; if (kernel_type == LINUX) { cmd = VasEBoot_command_find ("initrd16"); if (!cmd) return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT, N_("can't find command `%s'"), "initrd16"); return cmd->func (cmd, argc, args); } if (kernel_type == MULTIBOOT) { char **newargs; VasEBoot_err_t err; char nounzipbuf[10] = "--nounzip"; cmd = VasEBoot_command_find ("module"); if (!cmd) return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT, N_("can't find command `%s'"), "module"); newargs = VasEBoot_malloc ((argc + 1) * sizeof (newargs[0])); if (!newargs) return VasEBoot_errno; VasEBoot_memcpy (newargs + 1, args, argc * sizeof (newargs[0])); newargs[0] = nounzipbuf; err = cmd->func (cmd, argc + 1, newargs); VasEBoot_free (newargs); return err; } return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); } static VasEBoot_err_t check_password_deny (const char *user __attribute__ ((unused)), const char *entered __attribute__ ((unused)), void *password __attribute__ ((unused))) { return VasEBoot_ACCESS_DENIED; } #define MD5_HASHLEN 16 struct legacy_md5_password { VasEBoot_uint8_t *salt; int saltlen; VasEBoot_uint8_t hash[MD5_HASHLEN]; }; static int check_password_md5_real (const char *entered, struct legacy_md5_password *pw) { VasEBoot_size_t enteredlen = VasEBoot_strlen (entered); unsigned char alt_result[MD5_HASHLEN]; unsigned char *digest; VasEBoot_uint8_t *ctx; VasEBoot_size_t i; int ret; ctx = VasEBoot_zalloc (VasEBoot_MD_MD5->contextsize); if (!ctx) return 0; VasEBoot_MD_MD5->init (ctx); VasEBoot_MD_MD5->write (ctx, entered, enteredlen); VasEBoot_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3); VasEBoot_MD_MD5->write (ctx, entered, enteredlen); digest = VasEBoot_MD_MD5->read (ctx); VasEBoot_MD_MD5->final (ctx); VasEBoot_memcpy (alt_result, digest, MD5_HASHLEN); VasEBoot_MD_MD5->init (ctx); VasEBoot_MD_MD5->write (ctx, entered, enteredlen); VasEBoot_MD_MD5->write (ctx, pw->salt, pw->saltlen); /* include the $1$ header */ for (i = enteredlen; i > 16; i -= 16) VasEBoot_MD_MD5->write (ctx, alt_result, 16); VasEBoot_MD_MD5->write (ctx, alt_result, i); for (i = enteredlen; i > 0; i >>= 1) VasEBoot_MD_MD5->write (ctx, entered + ((i & 1) ? enteredlen : 0), 1); digest = VasEBoot_MD_MD5->read (ctx); VasEBoot_MD_MD5->final (ctx); for (i = 0; i < 1000; i++) { VasEBoot_memcpy (alt_result, digest, 16); VasEBoot_MD_MD5->init (ctx); if ((i & 1) != 0) VasEBoot_MD_MD5->write (ctx, entered, enteredlen); else VasEBoot_MD_MD5->write (ctx, alt_result, 16); if (i % 3 != 0) VasEBoot_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3); if (i % 7 != 0) VasEBoot_MD_MD5->write (ctx, entered, enteredlen); if ((i & 1) != 0) VasEBoot_MD_MD5->write (ctx, alt_result, 16); else VasEBoot_MD_MD5->write (ctx, entered, enteredlen); digest = VasEBoot_MD_MD5->read (ctx); VasEBoot_MD_MD5->final (ctx); } ret = (VasEBoot_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0); VasEBoot_free (ctx); return ret; } static VasEBoot_err_t check_password_md5 (const char *user, const char *entered, void *password) { if (!check_password_md5_real (entered, password)) return VasEBoot_ACCESS_DENIED; VasEBoot_auth_authenticate (user); return VasEBoot_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 (VasEBoot_memcmp (args[0], "--md5", sizeof ("--md5")) != 0) goto fail; if (argc == 1) goto fail; if (VasEBoot_strlen(args[1]) <= 3) goto fail; salt = args[1]; saltend = VasEBoot_strchr (salt + 3, '$'); if (!saltend) goto fail; pw = VasEBoot_malloc (sizeof (*pw)); if (!pw) goto fail; p = saltend + 1; for (i = 0; i < 5; i++) { int n; VasEBoot_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; VasEBoot_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 = (VasEBoot_uint8_t *) VasEBoot_strndup (salt, pw->saltlen); if (!pw->salt) goto fail; return pw; fail: VasEBoot_free (pw); return NULL; } static VasEBoot_err_t VasEBoot_cmd_legacy_password (struct VasEBoot_command *mycmd __attribute__ ((unused)), int argc, char **args) { struct legacy_md5_password *pw = NULL; if (argc == 0) return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT, N_("one argument expected")); if (args[0][0] != '-' || args[0][1] != '-') return VasEBoot_normal_set_password ("legacy", args[0]); pw = parse_legacy_md5 (argc, args); if (pw) return VasEBoot_auth_register_authentication ("legacy", check_password_md5, pw); else /* This is to imitate minor difference between VasEBoot-legacy in VasEBoot2. If 2 password commands are executed in a row and second one fails on VasEBoot2 the password of first one is used, whereas in VasEBoot-legacy authenthication is denied. In case of no password command was executed early both versions deny any access. */ return VasEBoot_auth_register_authentication ("legacy", check_password_deny, NULL); } int VasEBoot_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[VasEBoot_AUTH_MAX_PASSLEN]; VasEBoot_memset (correct, 0, sizeof (correct)); VasEBoot_strncpy (correct, args[0], sizeof (correct)); return VasEBoot_crypto_memcmp (entered, correct, VasEBoot_AUTH_MAX_PASSLEN) == 0; } pw = parse_legacy_md5 (argc, args); if (!pw) return 0; ret = check_password_md5_real (entered, pw); VasEBoot_free (pw); return ret; } static VasEBoot_err_t VasEBoot_cmd_legacy_check_password (struct VasEBoot_command *mycmd __attribute__ ((unused)), int argc, char **args) { char entered[VasEBoot_AUTH_MAX_PASSLEN]; if (argc == 0) return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT, N_("one argument expected")); VasEBoot_puts_ (N_("Enter password: ")); if (!VasEBoot_password_get (entered, VasEBoot_AUTH_MAX_PASSLEN)) return VasEBoot_ACCESS_DENIED; if (!VasEBoot_legacy_check_md5_password (argc, args, entered)) return VasEBoot_ACCESS_DENIED; return VasEBoot_ERR_NONE; } static VasEBoot_command_t cmd_source, cmd_configfile; static VasEBoot_command_t cmd_source_extract, cmd_configfile_extract; static VasEBoot_command_t cmd_kernel, cmd_initrd, cmd_initrdnounzip; static VasEBoot_command_t cmd_password, cmd_check_password; VasEBoot_MOD_INIT(legacycfg) { cmd_source = VasEBoot_register_command ("legacy_source", VasEBoot_cmd_legacy_source, N_("FILE"), /* TRANSLATORS: "legacy config" means "config as used by VasEBoot-legacy". */ N_("Parse legacy config in same context")); cmd_configfile = VasEBoot_register_command ("legacy_configfile", VasEBoot_cmd_legacy_source, N_("FILE"), N_("Parse legacy config in new context")); cmd_source_extract = VasEBoot_register_command ("extract_legacy_entries_source", VasEBoot_cmd_legacy_source, N_("FILE"), N_("Parse legacy config in same context taking only menu entries")); cmd_configfile_extract = VasEBoot_register_command ("extract_legacy_entries_configfile", VasEBoot_cmd_legacy_source, N_("FILE"), N_("Parse legacy config in new context taking only menu entries")); cmd_kernel = VasEBoot_register_command ("legacy_kernel", VasEBoot_cmd_legacy_kernel, N_("[--no-mem-option] [--type=TYPE] FILE [ARG ...]"), N_("Simulate VasEBoot-legacy `kernel' command")); cmd_initrd = VasEBoot_register_command ("legacy_initrd", VasEBoot_cmd_legacy_initrd, N_("FILE [ARG ...]"), N_("Simulate VasEBoot-legacy `initrd' command")); cmd_initrdnounzip = VasEBoot_register_command ("legacy_initrd_nounzip", VasEBoot_cmd_legacy_initrdnounzip, N_("FILE [ARG ...]"), N_("Simulate VasEBoot-legacy `modulenounzip' command")); cmd_password = VasEBoot_register_command ("legacy_password", VasEBoot_cmd_legacy_password, N_("[--md5] PASSWD [FILE]"), N_("Simulate VasEBoot-legacy `password' command")); cmd_check_password = VasEBoot_register_command ("legacy_check_password", VasEBoot_cmd_legacy_check_password, N_("[--md5] PASSWD [FILE]"), N_("Simulate VasEBoot-legacy `password' command in menu entry mode")); } VasEBoot_MOD_FINI(legacycfg) { VasEBoot_unregister_command (cmd_source); VasEBoot_unregister_command (cmd_configfile); VasEBoot_unregister_command (cmd_source_extract); VasEBoot_unregister_command (cmd_configfile_extract); VasEBoot_unregister_command (cmd_kernel); VasEBoot_unregister_command (cmd_initrd); VasEBoot_unregister_command (cmd_initrdnounzip); VasEBoot_unregister_command (cmd_password); VasEBoot_unregister_command (cmd_check_password); }