From 8ff75290391c02e92a9b3510b72c1495da25cd13 Mon Sep 17 00:00:00 2001 From: armink Date: Sat, 26 Nov 2016 15:23:12 +0800 Subject: [PATCH 1/2] [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 ae0934f5d1..83709560b1 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 751590366a..a4c96b9a26 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 From 72e4efb46ee6a395f27ff54a64d3daaf24d85187 Mon Sep 17 00:00:00 2001 From: armink Date: Sat, 26 Nov 2016 16:45:54 +0800 Subject: [PATCH 2/2] [finsh]Improve the set password. --- components/finsh/shell.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/components/finsh/shell.c b/components/finsh/shell.c index 83709560b1..7e8a84ab27 100644 --- a/components/finsh/shell.c +++ b/components/finsh/shell.c @@ -33,6 +33,7 @@ * 2010-04-01 Bernard add prompt output when start and remove the empty history * 2011-02-23 Bernard fix variable section end issue of finsh shell * initialization when use GNU GCC compiler. + * 2016-11-26 armink add password authentication */ #include @@ -180,12 +181,14 @@ rt_uint32_t finsh_get_echo() * * @param password new password * - * @return result, RT_EOK on OK, -RT_ERROR on the new password length is less than FINSH_PASSWORD_MIN + * @return result, RT_EOK on OK, -RT_ERROR on the new password length is less than + * FINSH_PASSWORD_MIN or greater than FINSH_PASSWORD_MAX */ rt_err_t finsh_set_password(const char *password) { rt_ubase_t level; + rt_size_t pw_len = rt_strlen(password); - if (rt_strlen(password) < FINSH_PASSWORD_MIN) + if (pw_len < FINSH_PASSWORD_MIN || pw_len > FINSH_PASSWORD_MAX) return -RT_ERROR; level = rt_hw_interrupt_disable(); @@ -407,7 +410,7 @@ void finsh_thread_entry(void *parameter) #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); + RT_ASSERT(finsh_set_password(FINSH_DEFAULT_PASSWORD) == RT_EOK); /* waiting authenticate success */ finsh_wait_auth(); #endif