From 90e766a78fe8ebf8acdc19713e9194266c78c093 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 27 Aug 2015 15:29:58 +0200 Subject: login: rework login mechanism We used to have the login functionality in the /env/bin/init script. This is hard to review and it's too easy to break the login functionality with changes to this script. Move the places to ask for a password to C code where we have only a few places where we have to ask for a password. Mainly these are run_shell() and the menutree command. This patch introduces a login() function which will only return if the correct password has been entered. Following calls will return immediately without asking for a password again. Signed-off-by: Sascha Hauer --- common/console.c | 6 ---- common/console_common.c | 27 ------------------ common/console_simple.c | 6 ---- common/hush.c | 3 ++ common/parser.c | 3 ++ common/password.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++-- common/startup.c | 7 ++--- 7 files changed, 81 insertions(+), 46 deletions(-) (limited to 'common') diff --git a/common/console.c b/common/console.c index bf64c08b7c..84d4ea714d 100644 --- a/common/console.c +++ b/common/console.c @@ -344,9 +344,6 @@ int getc(void) unsigned char ch; uint64_t start; - if (unlikely(!console_is_input_allow())) - return -EPERM; - /* * For 100us we read the characters from the serial driver * into a kfifo. This helps us not to lose characters @@ -381,9 +378,6 @@ EXPORT_SYMBOL(fgetc); int tstc(void) { - if (unlikely(!console_is_input_allow())) - return 0; - return kfifo_len(console_input_fifo) || tstc_raw(); } EXPORT_SYMBOL(tstc); diff --git a/common/console_common.c b/common/console_common.c index 2c82c6fd46..fcf89e8568 100644 --- a/common/console_common.c +++ b/common/console_common.c @@ -33,33 +33,6 @@ #ifndef CONFIG_CONSOLE_NONE -static int console_input_allow; - -static int console_global_init(void) -{ - if (IS_ENABLED(CONFIG_CMD_LOGIN) && is_passwd_enable()) - console_input_allow = 0; - else - console_input_allow = 1; - - globalvar_add_simple_bool("console.input_allow", &console_input_allow); - - return 0; -} -late_initcall(console_global_init); - -BAREBOX_MAGICVAR_NAMED(global_console_input_allow, global.console.input_allow, "console input allowed"); - -bool console_is_input_allow(void) -{ - return console_input_allow; -} - -void console_allow_input(bool val) -{ - console_input_allow = val; -} - int barebox_loglevel = CONFIG_DEFAULT_LOGLEVEL; LIST_HEAD(barebox_logbuf); diff --git a/common/console_simple.c b/common/console_simple.c index 6cb72bb46a..69e76593ad 100644 --- a/common/console_simple.c +++ b/common/console_simple.c @@ -41,9 +41,6 @@ EXPORT_SYMBOL(console_putc); int tstc(void) { - if (unlikely(!console_is_input_allow())) - return 0; - if (!console) return 0; @@ -53,9 +50,6 @@ EXPORT_SYMBOL(tstc); int getc(void) { - if (unlikely(!console_is_input_allow())) - return -EPERM; - if (!console) return -EINVAL; return console->getc(console); diff --git a/common/hush.c b/common/hush.c index ffd251339e..abe87137b5 100644 --- a/common/hush.c +++ b/common/hush.c @@ -116,6 +116,7 @@ #include #include #include +#include #include #include #include @@ -1914,6 +1915,8 @@ int run_shell(void) struct p_context ctx; int exit = 0; + login(); + do { setup_file_in_str(&input); rcode = parse_stream_outer(&ctx, &input, FLAG_PARSE_SEMICOLON); diff --git a/common/parser.c b/common/parser.c index 207599f429..ed414d04ea 100644 --- a/common/parser.c +++ b/common/parser.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -266,6 +267,8 @@ int run_shell(void) int len; int rc = 1; + login(); + for (;;) { len = readline (CONFIG_PROMPT, console_buffer, CONFIG_CBSIZE); diff --git a/common/password.c b/common/password.c index c8454228d0..6532143e4f 100644 --- a/common/password.c +++ b/common/password.c @@ -24,8 +24,11 @@ #include #include #include +#include #include +#include #include +#include #include #include @@ -73,7 +76,7 @@ int password(unsigned char *passwd, size_t length, int flags, int timeout) case CTL_CH('c'): passwd[0] = '\0'; puts("\r\n"); - return 0; + return -EINTR; case CTL_CH('h'): case BB_KEY_DEL7: case BB_KEY_DEL: @@ -104,7 +107,7 @@ int password(unsigned char *passwd, size_t length, int flags, int timeout) } } while (!is_timeout(start, timeout * SECOND) || timeout == 0); - return -1; + return -ETIMEDOUT; } EXPORT_SYMBOL(password); @@ -374,6 +377,8 @@ int set_env_passwd(unsigned char* passwd, size_t length) hash_len = PBKDF2_LENGTH; } else { d = digest_alloc(PASSWD_SUM); + if (!d) + return -EINVAL; hash_len = digest_length(d); } @@ -406,3 +411,69 @@ err: return ret; } EXPORT_SYMBOL(set_env_passwd); + +#define PASSWD_MAX_LENGTH (128 + 1) + +#if defined(CONFIG_PASSWD_MODE_STAR) +#define LOGIN_MODE STAR +#elif defined(CONFIG_PASSWD_MODE_CLEAR) +#define LOGIN_MODE CLEAR +#else +#define LOGIN_MODE HIDE +#endif + +static int logged_in; +static int login_timeout; +static char *login_fail_command; + +/** + * login() - Prompt for password + * + * This function only returns when the correct password has been entered or + * no password is necessary because either no password is configured or the + * correct password has been entered in a previous call to this function. + */ +void login(void) +{ + unsigned char passwd[PASSWD_MAX_LENGTH]; + int ret; + + if (!is_passwd_enable()) + return; + + if (logged_in) + return; + + while (1) { + printf("Password: "); + + ret = password(passwd, PASSWD_MAX_LENGTH, LOGIN_MODE, login_timeout); + if (ret < 0) + run_command(login_fail_command); + + if (ret < 0) + continue; + + if (check_passwd(passwd, ret) != 1) + continue; + + logged_in = 1; + return; + } +} + +static int login_global_init(void) +{ + login_fail_command = xstrdup("boot"); + + globalvar_add_simple_int("login.timeout", &login_timeout, "%d"); + globalvar_add_simple_string("login.fail_command", &login_fail_command); + + return 0; +} +late_initcall(login_global_init); + +BAREBOX_MAGICVAR_NAMED(global_login_fail_command, global.login.fail_command, + "command to run when password entry failed"); +BAREBOX_MAGICVAR_NAMED(global_login_timeout, global.login.timeout, + "timeout to type the password"); diff --git a/common/startup.c b/common/startup.c index 802b90e0e8..4a303b297a 100644 --- a/common/startup.c +++ b/common/startup.c @@ -108,13 +108,10 @@ void __noreturn start_barebox(void) if (IS_ENABLED(CONFIG_COMMAND_SUPPORT)) { pr_info("running /env/bin/init...\n"); - if (!stat("/env/bin/init", &s)) { + if (!stat("/env/bin/init", &s)) run_command("source /env/bin/init"); - } else { + else pr_err("/env/bin/init not found\n"); - if (IS_ENABLED(CONFIG_CMD_LOGIN)) - while(run_command("login -t 0")); - } } if (!barebox_main) { -- cgit v1.2.3