Просмотр исходного кода

Improved authentication handling in CLI

alex.kopachov 3 лет назад
Родитель
Сommit
a8f2ca0af1

+ 3 - 19
services/cli/cli.c

@@ -25,25 +25,9 @@ static void totp_cli_print_help() {
     totp_cli_command_timezone_print_help();
 }
 
-static void totp_cli_print_unauthenticated() {
-    printf("Pleases enter PIN on your flipper device\r\n");
-}
-
 static void totp_cli_handler(Cli* cli, FuriString* args, void* context) {
     PluginState* plugin_state = (PluginState* )context;
 
-    if (plugin_state->current_scene == TotpSceneAuthentication) {
-        totp_cli_print_unauthenticated();
-        
-        while (plugin_state->current_scene == TotpSceneAuthentication && !cli_cmd_interrupt_received(cli)) {
-            furi_delay_tick(0);
-        }
-
-        if (plugin_state->current_scene == TotpSceneAuthentication) {
-            return;
-        }
-    }
-
     FuriString* cmd = furi_string_alloc();
 
     args_read_string_and_trim(args, cmd);
@@ -51,13 +35,13 @@ static void totp_cli_handler(Cli* cli, FuriString* args, void* context) {
     if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_HELP) == 0 || furi_string_empty(cmd)) {
         totp_cli_print_help();
     } else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_ADD) == 0) {
-        totp_cli_command_add_handle(plugin_state, args);
+        totp_cli_command_add_handle(plugin_state, args, cli);
     } else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_LIST) == 0) {
-        totp_cli_command_list_handle(plugin_state);
+        totp_cli_command_list_handle(plugin_state, cli);
     } else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_DELETE) == 0) {
         totp_cli_command_delete_handle(plugin_state, args, cli);
     } else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_TIMEZONE) == 0) {
-        totp_cli_command_timezone_handle(plugin_state, args);
+        totp_cli_command_timezone_handle(plugin_state, args, cli);
     } else {
         totp_cli_print_unknown_command(cmd);
     }

+ 19 - 0
services/cli/cli_common_helpers.c

@@ -3,4 +3,23 @@
 
 void totp_cli_print_invalid_arguments() {
     printf("Invalid command arguments. use \"help\" command to get list of available commands");
+}
+
+bool totp_cli_ensure_authenticated(PluginState* plugin_state, Cli* cli) {
+    if (plugin_state->current_scene == TotpSceneAuthentication) {
+        TOTP_CLI_PRINTF("Pleases enter PIN on your flipper device\r\n");
+        
+        while (plugin_state->current_scene == TotpSceneAuthentication && !cli_cmd_interrupt_received(cli)) {
+            furi_delay_tick(0);
+        }
+
+        TOTP_CLI_PRINTF("\033[A\33[2K\r");
+        fflush(stdout);
+
+        if (plugin_state->current_scene == TotpSceneAuthentication) {
+            return false;
+        }
+    }
+
+    return true;
 }

+ 5 - 1
services/cli/cli_common_helpers.h

@@ -1,5 +1,8 @@
 #pragma once
 
+#include <cli/cli.h>
+#include "../../types/plugin_state.h"
+
 #define TOTP_CLI_ARG(arg) "<" arg ">"
 #define TOTP_CLI_OPTIONAL_PARAM(param) "[" param "]"
 #define TOTP_CLI_OPTIONAL_PARAM_MARK "[OPTIONAL]"
@@ -10,4 +13,5 @@
     printf(format, ##__VA_ARGS__); \
     _Pragma(STRINGIFY(GCC diagnostic pop));
 
-void totp_cli_print_invalid_arguments();
+void totp_cli_print_invalid_arguments();
+bool totp_cli_ensure_authenticated(PluginState* plugin_state, Cli* cli);

+ 65 - 23
services/cli/commands/add/add.c

@@ -8,11 +8,11 @@
 #include "../../../../scenes/scene_director.h"
 
 #define TOTP_CLI_COMMAND_ADD_ARG_NAME "NAME"
-#define TOTP_CLI_COMMAND_ADD_ARG_SECRET "SECRET"
 #define TOTP_CLI_COMMAND_ADD_ARG_ALGO "ALGO"
 #define TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX "-a"
 #define TOTP_CLI_COMMAND_ADD_ARG_DIGITS "DIGITS"
 #define TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX "-d"
+#define TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX "-u"
 
 static bool token_info_set_digits_from_str(TokenInfo* token_info, FuriString* str) {
     switch(furi_string_get_char(str, 0)) {
@@ -47,14 +47,14 @@ static bool token_info_set_algo_from_str(TokenInfo* token_info, FuriString* str)
 }
 
 void totp_cli_command_add_print_help() {
-    TOTP_CLI_PRINTF("\t" TOTP_CLI_COMMAND_ADD " " TOTP_CLI_ARG(TOTP_CLI_COMMAND_ADD_ARG_NAME) " " TOTP_CLI_ARG(TOTP_CLI_COMMAND_ADD_ARG_SECRET) " " TOTP_CLI_OPTIONAL_PARAM(TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX " " TOTP_CLI_ARG(TOTP_CLI_COMMAND_ADD_ARG_ALGO)) " " TOTP_CLI_OPTIONAL_PARAM(TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX " " TOTP_CLI_ARG(TOTP_CLI_COMMAND_ADD_ARG_DIGITS)) " - add new token\r\n");
+    TOTP_CLI_PRINTF("\t" TOTP_CLI_COMMAND_ADD " " TOTP_CLI_ARG(TOTP_CLI_COMMAND_ADD_ARG_NAME) " " TOTP_CLI_OPTIONAL_PARAM(TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX " " TOTP_CLI_ARG(TOTP_CLI_COMMAND_ADD_ARG_ALGO)) " " TOTP_CLI_OPTIONAL_PARAM(TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX " " TOTP_CLI_ARG(TOTP_CLI_COMMAND_ADD_ARG_DIGITS)) " " TOTP_CLI_OPTIONAL_PARAM(TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX) " - add new token\r\n");
     TOTP_CLI_PRINTF("\t\t" TOTP_CLI_ARG(TOTP_CLI_COMMAND_ADD_ARG_NAME) "   - token name\r\n");
-    TOTP_CLI_PRINTF("\t\t" TOTP_CLI_ARG(TOTP_CLI_COMMAND_ADD_ARG_SECRET) " - Base32 token secret\r\n");
     TOTP_CLI_PRINTF("\t\t" TOTP_CLI_ARG(TOTP_CLI_COMMAND_ADD_ARG_ALGO) "   - " TOTP_CLI_OPTIONAL_PARAM_MARK " token hashing algorithm, could be one of: sha1, sha256, sha512; default: sha1\r\n");
-    TOTP_CLI_PRINTF("\t\t" TOTP_CLI_ARG(TOTP_CLI_COMMAND_ADD_ARG_DIGITS) " - " TOTP_CLI_OPTIONAL_PARAM_MARK " number of digits to generate, one of: 6, 8; default: 6\r\n\r\n");
+    TOTP_CLI_PRINTF("\t\t" TOTP_CLI_ARG(TOTP_CLI_COMMAND_ADD_ARG_DIGITS) " - " TOTP_CLI_OPTIONAL_PARAM_MARK " number of digits to generate, one of: 6, 8; default: 6\r\n");
+    TOTP_CLI_PRINTF("\t\t" TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX "       - " TOTP_CLI_OPTIONAL_PARAM_MARK " to show console user input as-is without masking; default: show masked\r\n\r\n");
 }
 
-void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args) {
+void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
     FuriString* temp_str = furi_string_alloc();
     const char* temp_cstr;
 
@@ -72,23 +72,8 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args) {
     token_info->name = malloc(strlen(temp_cstr) + 1);
     strcpy(token_info->name, temp_cstr);
 
-    // Reading token secret
-    if (!args_read_probably_quoted_string_and_trim(args, temp_str)) {
-        totp_cli_print_invalid_arguments();
-        furi_string_free(temp_str);
-        token_info_free(token_info);
-        return;
-    }
-
-    temp_cstr = furi_string_get_cstr(temp_str);
-    if (!token_info_set_secret(token_info, temp_cstr, strlen(temp_cstr), plugin_state->iv)) {
-        TOTP_CLI_PRINTF("Token secret seems to be invalid and can not be parsed\r\n");
-        furi_string_free(temp_str);
-        token_info_free(token_info);
-        return;
-    }
-
     // Read optional arguments
+    bool mask_user_input = true;
     while (args_read_string_and_trim(args, temp_str)) {
         bool parsed = false;
         if (furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX) == 0) {
@@ -107,7 +92,11 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args) {
             } else {
                 parsed = true;
             }
+        } else if (furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX) == 0) {
+            mask_user_input = false;
+            parsed = true;
         }
+
         if (!parsed) {
             totp_cli_print_invalid_arguments();
             furi_string_free(temp_str);
@@ -116,6 +105,61 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args) {
         }
     }
 
+    // Reading token secret
+    furi_string_reset(temp_str);
+    TOTP_CLI_PRINTF("Enter token secret and confirm with [ENTER]:\r\n");
+
+    uint8_t c;
+    while(cli_read(cli, &c, 1) == 1) {
+        if (c == CliSymbolAsciiEsc) {
+            uint8_t c2;
+            cli_read_timeout(cli, &c2, 1, 0);
+            cli_read_timeout(cli, &c2, 1, 0);
+        } else if(c == CliSymbolAsciiETX) {
+            TOTP_CLI_PRINTF("Cancelled by user");
+            furi_string_free(temp_str);
+            token_info_free(token_info);
+            return;
+        } else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
+            if (mask_user_input) {
+                putc('*', stdout);
+            } else {
+                putc(c, stdout);
+            }
+            fflush(stdout);
+            furi_string_push_back(temp_str, c);
+        } else if (c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) {
+            size_t temp_str_size = furi_string_size(temp_str);
+            if (temp_str_size > 0) {
+                TOTP_CLI_PRINTF("\b \b");
+                fflush(stdout);
+                furi_string_left(temp_str, temp_str_size - 1);
+            }
+        }
+        else if(c == CliSymbolAsciiCR) {
+            cli_nl();
+            break;
+        }
+    }
+
+    temp_cstr = furi_string_get_cstr(temp_str);
+
+    if (!totp_cli_ensure_authenticated(plugin_state, cli)) {
+        furi_string_free(temp_str);
+        token_info_free(token_info);
+        return;
+    }
+
+    if (!token_info_set_secret(token_info, temp_cstr, strlen(temp_cstr), plugin_state->iv)) {
+        TOTP_CLI_PRINTF("Token secret seems to be invalid and can not be parsed\r\n");
+        furi_string_free(temp_str);
+        token_info_free(token_info);
+        return;
+    }
+
+    furi_string_reset(temp_str);
+    furi_string_free(temp_str);
+
     bool load_generate_token_scene = false;
     if (plugin_state->current_scene == TotpSceneGenerateToken) {
         totp_scene_director_activate_scene(plugin_state, TotpSceneNone, NULL);
@@ -134,7 +178,5 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args) {
         totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
     }
 
-    furi_string_free(temp_str);
-
     TOTP_CLI_PRINTF("Token \"%s\" has been successfully added\r\n", token_info->name);
 }

+ 1 - 1
services/cli/commands/add/add.h

@@ -5,5 +5,5 @@
 
 #define TOTP_CLI_COMMAND_ADD "add"
 
-void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args);
+void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cli* cli);
 void totp_cli_command_add_print_help();

+ 14 - 2
services/cli/commands/delete/delete.c

@@ -14,7 +14,7 @@
 void totp_cli_command_delete_print_help() {
     TOTP_CLI_PRINTF("\t" TOTP_CLI_COMMAND_DELETE " " TOTP_CLI_ARG(TOTP_CLI_COMMAND_DELETE_ARG_INDEX) " " TOTP_CLI_OPTIONAL_PARAM(TOTP_CLI_COMMAND_DELETE_ARG_FORCE_SUFFIX) " - delete token\r\n");
     TOTP_CLI_PRINTF("\t\t" TOTP_CLI_ARG(TOTP_CLI_COMMAND_DELETE_ARG_INDEX) " - token index in the list\r\n");
-    TOTP_CLI_PRINTF("\t\t" TOTP_CLI_COMMAND_DELETE_ARG_FORCE_SUFFIX " - " TOTP_CLI_OPTIONAL_PARAM_MARK " force command to do not ask user for interactive confirmation\r\n\r\n");
+    TOTP_CLI_PRINTF("\t\t" TOTP_CLI_COMMAND_DELETE_ARG_FORCE_SUFFIX "      - " TOTP_CLI_OPTIONAL_PARAM_MARK " force command to do not ask user for interactive confirmation\r\n\r\n");
 }
 
 void totp_cli_command_delete_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
@@ -38,6 +38,10 @@ void totp_cli_command_delete_handle(PluginState* plugin_state, FuriString* args,
     }
     furi_string_free(temp_str);
 
+    if (!totp_cli_ensure_authenticated(plugin_state, cli)) {
+        return;
+    }
+
     ListNode* list_node = list_element_at(plugin_state->tokens_list, token_number - 1);
 
     TokenInfo* token_info = list_node->data;
@@ -51,12 +55,20 @@ void totp_cli_command_delete_handle(PluginState* plugin_state, FuriString* args,
         char user_pick;
         do {
             user_pick = tolower(cli_getc(cli));
-        } while (user_pick != 'y' && user_pick != 'n' && user_pick != CliSymbolAsciiCR);
+        } while (user_pick != 'y' && 
+            user_pick != 'n' && 
+            user_pick != CliSymbolAsciiCR && 
+            user_pick != CliSymbolAsciiETX && 
+            user_pick != CliSymbolAsciiEsc);
 
         confirmed = user_pick == 'y' || user_pick == CliSymbolAsciiCR;
     }
 
     if (confirmed) {
+        if (!totp_cli_ensure_authenticated(plugin_state, cli)) {
+            return;
+        }
+
         bool activate_generate_token_scene = false;
         if (plugin_state->current_scene != TotpSceneAuthentication) {
             totp_scene_director_activate_scene(plugin_state, TotpSceneNone, NULL);

+ 5 - 2
services/cli/commands/list/list.c

@@ -1,5 +1,4 @@
 #include "list.h"
-#include <cli/cli.h>
 #include <stdlib.h>
 #include "../../../list/list.h"
 #include "../../../../types/token_info.h"
@@ -34,7 +33,11 @@ void totp_cli_command_list_print_help() {
     TOTP_CLI_PRINTF("\t" TOTP_CLI_COMMAND_LIST " - list all tokens\r\n\r\n");
 }
 
-void totp_cli_command_list_handle(PluginState* plugin_state) {
+void totp_cli_command_list_handle(PluginState* plugin_state, Cli* cli) {
+    if (!totp_cli_ensure_authenticated(plugin_state, cli)) {
+        return;
+    }
+
     if (plugin_state->tokens_list == NULL) {
         TOTP_CLI_PRINTF("There are no tokens");
         return;

+ 2 - 1
services/cli/commands/list/list.h

@@ -1,8 +1,9 @@
 #pragma once
 
+#include <cli/cli.h>
 #include "../../../../types/plugin_state.h"
 
 #define TOTP_CLI_COMMAND_LIST "list"
 
-void totp_cli_command_list_handle(PluginState* plugin_state);
+void totp_cli_command_list_handle(PluginState* plugin_state, Cli* cli);
 void totp_cli_command_list_print_help();

+ 5 - 1
services/cli/commands/timezone/timezone.c

@@ -11,7 +11,11 @@ void totp_cli_command_timezone_print_help() {
     TOTP_CLI_PRINTF("\t\t" TOTP_CLI_ARG(TOTP_CLI_COMMAND_TIMEZONE_ARG_TIMEZONE) " - " TOTP_CLI_OPTIONAL_PARAM_MARK " timezone offset in hours to be set, if not provided then current timezone offset will be printed\r\n\r\n");
 }
 
-void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args) {
+void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
+    if (!totp_cli_ensure_authenticated(plugin_state, cli)) {
+        return;
+    }
+
     FuriString* temp_str = furi_string_alloc();
     if (args_read_string_and_trim(args, temp_str)) {
         float tz = strtof(furi_string_get_cstr(temp_str), NULL);

+ 1 - 1
services/cli/commands/timezone/timezone.h

@@ -5,5 +5,5 @@
 
 #define TOTP_CLI_COMMAND_TIMEZONE "timezone"
 
-void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args);
+void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args, Cli* cli);
 void totp_cli_command_timezone_print_help();