Procházet zdrojové kódy

[finsh] Add password authentication. Increased input security.

armink před 8 roky
rodič
revize
8ff7529039
2 změnil soubory, kde provedl 116 přidání a 1 odebrání
  1. 95 1
      components/finsh/shell.c
  2. 21 0
      components/finsh/shell.h

+ 95 - 1
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 */

+ 21 - 0
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