Skip to content

Commit

Permalink
Improved authentication handling in CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
akopachov committed Oct 25, 2022
1 parent 4c5533f commit a8f2ca0
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 51 deletions.
22 changes: 3 additions & 19 deletions services/cli/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,39 +25,23 @@ 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);

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);
}
Expand Down
19 changes: 19 additions & 0 deletions services/cli/cli_common_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
6 changes: 5 additions & 1 deletion services/cli/cli_common_helpers.h
Original file line number Diff line number Diff line change
@@ -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]"
Expand All @@ -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);
88 changes: 65 additions & 23 deletions services/cli/commands/add/add.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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;

Expand All @@ -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) {
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
}
2 changes: 1 addition & 1 deletion services/cli/commands/add/add.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
16 changes: 14 additions & 2 deletions services/cli/commands/delete/delete.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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;
Expand All @@ -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);
Expand Down
7 changes: 5 additions & 2 deletions services/cli/commands/list/list.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "list.h"
#include <cli/cli.h>
#include <stdlib.h>
#include "../../../list/list.h"
#include "../../../../types/token_info.h"
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion services/cli/commands/list/list.h
Original file line number Diff line number Diff line change
@@ -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();
6 changes: 5 additions & 1 deletion services/cli/commands/timezone/timezone.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion services/cli/commands/timezone/timezone.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();

0 comments on commit a8f2ca0

Please sign in to comment.