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");
 | |
| }
 |