200 lines
4.2 KiB
C
200 lines
4.2 KiB
C
/*
|
|
* (C) Copyright 2000
|
|
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
/* #define DEBUG */
|
|
|
|
#include <common.h>
|
|
#include <autoboot.h>
|
|
#include <cli.h>
|
|
#include <console.h>
|
|
#include <version.h>
|
|
|
|
#ifdef CONFIG_NM_LOGIN
|
|
#include <fs.h>
|
|
#include <u-boot/md5.h>
|
|
#include <malloc.h>
|
|
#include <crypt.h>
|
|
|
|
/* Set defaults for passwd file location */
|
|
#ifndef CONFIG_NM_LOGIN_PART
|
|
#define CONFIG_NM_LOGIN_PART "1:3"
|
|
#endif
|
|
#ifndef CONFIG_NM_LOGIN_PASSWD
|
|
#define CONFIG_NM_LOGIN_PASSWD "/root/boot/bootpass"
|
|
#endif
|
|
|
|
#endif
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
/*
|
|
* Board-specific Platform code can reimplement show_boot_progress () if needed
|
|
*/
|
|
__weak void show_boot_progress(int val) {}
|
|
|
|
|
|
#ifdef CONFIG_NM_LOGIN
|
|
/****************************************************************************
|
|
* check if ubootpwd exists in data partition and perform a login,
|
|
* otherwise continue booting
|
|
*/
|
|
int login (void)
|
|
{
|
|
#define MAX_TRIES_ENTER 4096
|
|
#define PASSWORD_LEN 256
|
|
|
|
char stored_pw_hash[PASSWORD_LEN];
|
|
char password[PASSWORD_LEN];
|
|
int res, i, tries;
|
|
int legacy_md5 = 0;
|
|
loff_t actread;
|
|
char c;
|
|
|
|
puts("\nautoboot has been stopped, press 'e' to enter: ");
|
|
|
|
for (i=0; i<=MAX_TRIES_ENTER; i++) {
|
|
c = getc();
|
|
if (c == 'e' || c == '\n') {
|
|
puts("e");
|
|
break;
|
|
}
|
|
|
|
/* Enter condition not given -> restart */
|
|
if (i == MAX_TRIES_ENTER)
|
|
return 0;
|
|
}
|
|
puts("\n");
|
|
|
|
/* Try to get password hash file */
|
|
memset(stored_pw_hash, 0x0, sizeof(stored_pw_hash));
|
|
if (fs_set_blk_dev("mmc", CONFIG_NM_LOGIN_PART, FS_TYPE_EXT) != 0) {
|
|
puts("Error, can not set blk device\n");
|
|
return 1;
|
|
}
|
|
|
|
res = fs_read(CONFIG_NM_LOGIN_PASSWD, (ulong)stored_pw_hash, 0, sizeof(stored_pw_hash), &actread);
|
|
if ((res != 0) || (actread <= 0)) {
|
|
/* no file or hash found -> allow login w/o password */
|
|
puts("Login succeeded\n\n");
|
|
return 1;
|
|
} else if (actread == 16) {
|
|
legacy_md5 = 1;
|
|
}
|
|
|
|
for (tries = 1; ; tries++) {
|
|
puts("\nEnter password: ");
|
|
|
|
/* TODO: no backspace ? */
|
|
/* TODO: rename buf to something more useful */
|
|
/* TODO: print a dot or blind? */
|
|
password[0] = 0;
|
|
for (i=0; i<PASSWORD_LEN; i++) {
|
|
password[i] = getc();
|
|
if (password[i] == '\r' || password[i] == '\n') {
|
|
password[i] = 0;
|
|
break;
|
|
}
|
|
}
|
|
password[PASSWORD_LEN-1] = 0;
|
|
|
|
if (strlen(password) > 0) {
|
|
puts("\n");
|
|
if (legacy_md5) {
|
|
/* MD5 - legacy */
|
|
char entered[32]; /* TODO: Why 32, MD5 algo uses only 16 bytes */
|
|
|
|
md5((unsigned char *)password, strlen(password), (unsigned char *)entered);
|
|
if (memcmp(stored_pw_hash, entered, 16) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
/* SHA256 */
|
|
char *cp = sha_crypt(password, stored_pw_hash); /* TODO: Salt = PW? */
|
|
res = memcmp(cp, stored_pw_hash, actread);
|
|
free(cp);
|
|
if (res == 0)
|
|
break;
|
|
}
|
|
|
|
/* TODO: exponentional delay */
|
|
puts("Login incorrect\n");
|
|
if (tries == 3) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* TODO: remove password from memory !!!!! */
|
|
memset(password, 0, sizeof(password));
|
|
}
|
|
|
|
/* succeeded */
|
|
puts("Login succeeded\n\n");
|
|
|
|
return 1;
|
|
}
|
|
|
|
#endif /* CONIFG_NM_LOGIN */
|
|
|
|
/****************************************************************************/
|
|
|
|
static void run_preboot_environment_command(void)
|
|
{
|
|
#ifdef CONFIG_PREBOOT
|
|
char *p;
|
|
|
|
p = getenv("preboot");
|
|
if (p != NULL) {
|
|
# ifdef CONFIG_AUTOBOOT_KEYED
|
|
int prev = disable_ctrlc(1); /* disable Control C checking */
|
|
# endif
|
|
|
|
run_command_list(p, -1, 0);
|
|
|
|
# ifdef CONFIG_AUTOBOOT_KEYED
|
|
disable_ctrlc(prev); /* restore Control C checking */
|
|
# endif
|
|
}
|
|
#endif /* CONFIG_PREBOOT */
|
|
}
|
|
|
|
/* We come here after U-Boot is initialised and ready to process commands */
|
|
void main_loop(void)
|
|
{
|
|
const char *s;
|
|
|
|
bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");
|
|
|
|
#ifdef CONFIG_VERSION_VARIABLE
|
|
setenv("ver", version_string); /* set version variable */
|
|
#endif /* CONFIG_VERSION_VARIABLE */
|
|
|
|
cli_init();
|
|
|
|
run_preboot_environment_command();
|
|
|
|
#if defined(CONFIG_UPDATE_TFTP)
|
|
update_tftp(0UL, NULL, NULL);
|
|
#endif /* CONFIG_UPDATE_TFTP */
|
|
|
|
s = bootdelay_process();
|
|
if (cli_process_fdt(&s))
|
|
cli_secure_boot_cmd(s);
|
|
|
|
autoboot_command(s);
|
|
|
|
#ifdef CONFIG_NM_LOGIN
|
|
if (!login()) {
|
|
puts ("Login failed, resetting...\n");
|
|
do_reset (NULL, 0, 0, NULL);
|
|
}
|
|
#endif
|
|
|
|
cli_loop();
|
|
panic("No CLI available");
|
|
}
|