From 8ff75290391c02e92a9b3510b72c1495da25cd13 Mon Sep 17 00:00:00 2001 From: armink Date: Sat, 26 Nov 2016 15:23:12 +0800 Subject: [PATCH] [finsh] Add password authentication. Increased input security. --- components/finsh/shell.c | 96 +++++++++++++++++++++++++++++++++++++++- components/finsh/shell.h | 21 +++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/components/finsh/shell.c b/components/finsh/shell.c index ae0934f5d..83709560b 100644 --- a/components/finsh/shell.c +++ b/components/finsh/shell.c @@ -174,6 +174,91 @@ rt_uint32_t finsh_get_echo() return shell->echo_mode; } +#ifdef FINSH_USING_AUTH +/** + * set a new password for finsh + * + * @param password new password + * + * @return result, RT_EOK on OK, -RT_ERROR on the new password length is less than FINSH_PASSWORD_MIN + */ +rt_err_t finsh_set_password(const char *password) { + rt_ubase_t level; + + if (rt_strlen(password) < FINSH_PASSWORD_MIN) + return -RT_ERROR; + + level = rt_hw_interrupt_disable(); + rt_strncpy(shell->password, password, FINSH_PASSWORD_MAX); + rt_hw_interrupt_enable(level); + + return RT_EOK; +} + +/** + * get the finsh password + * + * @return password + */ +const char *finsh_get_password(void) +{ + return shell->password; +} + +static void finsh_wait_auth(void) +{ + char ch; + rt_bool_t input_finish = RT_FALSE; + char password[FINSH_PASSWORD_MAX] = { 0 }; + rt_size_t cur_pos = 0; + while (1) + { + rt_kprintf("Password for finsh: "); + while (!input_finish) + { + /* wait receive */ + if (rt_sem_take(&shell->rx_sem, RT_WAITING_FOREVER) != RT_EOK) continue; + + /* read one character from device */ + while (rt_device_read(shell->device, 0, &ch, 1) == 1) + { + if (ch >= ' ' && ch <= '~' && cur_pos < FINSH_PASSWORD_MAX) + { + /* change the printable characters to '*' */ + rt_kprintf("*"); + password[cur_pos++] = ch; + } + else if (ch == '\b' && cur_pos > 0) + { + /* backspace */ + password[cur_pos] = '\0'; + cur_pos--; + rt_kprintf("\b \b"); + } + else if (ch == '\r' || ch == '\n') + { + rt_kprintf("\n"); + input_finish = RT_TRUE; + break; + } + } + } + if (!rt_strncmp(shell->password, password, FINSH_PASSWORD_MAX)) return; + else + { + /* authentication failed, delay 2S for retry */ + rt_thread_delay(2 * RT_TICK_PER_SECOND); + rt_kprintf("Sorry, try again.\n"); + cur_pos = 0; + input_finish = RT_FALSE; + rt_memset(password, '\0', FINSH_PASSWORD_MAX); + /* read all last dirty data */ + while (rt_device_read(shell->device, 0, &ch, 1) == 1); + } + } +} +#endif /* FINSH_USING_AUTH */ + static void shell_auto_complete(char *prefix) { @@ -305,7 +390,6 @@ void finsh_thread_entry(void *parameter) #ifndef FINSH_USING_MSH_ONLY finsh_init(&shell->parser); #endif - rt_kprintf(FINSH_PROMPT); /* set console device as shell device */ if (shell->device == RT_NULL) @@ -320,6 +404,16 @@ void finsh_thread_entry(void *parameter) #endif } +#ifdef FINSH_USING_AUTH + /* set the default password when the password isn't setting */ + if (rt_strlen(finsh_get_password()) == 0) + finsh_set_password(FINSH_DEFAULT_PASSWORD); + /* waiting authenticate success */ + finsh_wait_auth(); +#endif + + rt_kprintf(FINSH_PROMPT); + while (1) { /* wait receive */ diff --git a/components/finsh/shell.h b/components/finsh/shell.h index 751590366..a4c96b9a2 100644 --- a/components/finsh/shell.h +++ b/components/finsh/shell.h @@ -68,6 +68,18 @@ const char* finsh_get_prompt(void); #endif #endif +#ifdef FINSH_USING_AUTH + #ifndef FINSH_PASSWORD_MAX + #define FINSH_PASSWORD_MAX RT_NAME_MAX + #endif + #ifndef FINSH_PASSWORD_MIN + #define FINSH_PASSWORD_MIN 6 + #endif + #ifndef FINSH_DEFAULT_PASSWORD + #define FINSH_DEFAULT_PASSWORD "rtthread" + #endif +#endif /* FINSH_USING_AUTH */ + enum input_stat { WAIT_NORMAL, @@ -98,6 +110,10 @@ struct finsh_shell rt_uint8_t line_curpos; rt_device_t device; + +#ifdef FINSH_USING_AUTH + char password[FINSH_PASSWORD_MAX]; +#endif }; void finsh_set_echo(rt_uint32_t echo); @@ -107,4 +123,9 @@ int finsh_system_init(void); void finsh_set_device(const char* device_name); const char* finsh_get_device(void); +#ifdef FINSH_USING_AUTH +rt_err_t finsh_set_password(const char *password); +const char *finsh_get_password(void); +#endif + #endif