Skip to content

Commit a8f2ca0

Browse files
committed
Improved authentication handling in CLI
1 parent 4c5533f commit a8f2ca0

File tree

10 files changed

+120
-51
lines changed

10 files changed

+120
-51
lines changed

services/cli/cli.c

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,39 +25,23 @@ static void totp_cli_print_help() {
2525
totp_cli_command_timezone_print_help();
2626
}
2727

28-
static void totp_cli_print_unauthenticated() {
29-
printf("Pleases enter PIN on your flipper device\r\n");
30-
}
31-
3228
static void totp_cli_handler(Cli* cli, FuriString* args, void* context) {
3329
PluginState* plugin_state = (PluginState* )context;
3430

35-
if (plugin_state->current_scene == TotpSceneAuthentication) {
36-
totp_cli_print_unauthenticated();
37-
38-
while (plugin_state->current_scene == TotpSceneAuthentication && !cli_cmd_interrupt_received(cli)) {
39-
furi_delay_tick(0);
40-
}
41-
42-
if (plugin_state->current_scene == TotpSceneAuthentication) {
43-
return;
44-
}
45-
}
46-
4731
FuriString* cmd = furi_string_alloc();
4832

4933
args_read_string_and_trim(args, cmd);
5034

5135
if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_HELP) == 0 || furi_string_empty(cmd)) {
5236
totp_cli_print_help();
5337
} else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_ADD) == 0) {
54-
totp_cli_command_add_handle(plugin_state, args);
38+
totp_cli_command_add_handle(plugin_state, args, cli);
5539
} else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_LIST) == 0) {
56-
totp_cli_command_list_handle(plugin_state);
40+
totp_cli_command_list_handle(plugin_state, cli);
5741
} else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_DELETE) == 0) {
5842
totp_cli_command_delete_handle(plugin_state, args, cli);
5943
} else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_TIMEZONE) == 0) {
60-
totp_cli_command_timezone_handle(plugin_state, args);
44+
totp_cli_command_timezone_handle(plugin_state, args, cli);
6145
} else {
6246
totp_cli_print_unknown_command(cmd);
6347
}

services/cli/cli_common_helpers.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,23 @@
33

44
void totp_cli_print_invalid_arguments() {
55
printf("Invalid command arguments. use \"help\" command to get list of available commands");
6+
}
7+
8+
bool totp_cli_ensure_authenticated(PluginState* plugin_state, Cli* cli) {
9+
if (plugin_state->current_scene == TotpSceneAuthentication) {
10+
TOTP_CLI_PRINTF("Pleases enter PIN on your flipper device\r\n");
11+
12+
while (plugin_state->current_scene == TotpSceneAuthentication && !cli_cmd_interrupt_received(cli)) {
13+
furi_delay_tick(0);
14+
}
15+
16+
TOTP_CLI_PRINTF("\033[A\33[2K\r");
17+
fflush(stdout);
18+
19+
if (plugin_state->current_scene == TotpSceneAuthentication) {
20+
return false;
21+
}
22+
}
23+
24+
return true;
625
}

services/cli/cli_common_helpers.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#pragma once
22

3+
#include <cli/cli.h>
4+
#include "../../types/plugin_state.h"
5+
36
#define TOTP_CLI_ARG(arg) "<" arg ">"
47
#define TOTP_CLI_OPTIONAL_PARAM(param) "[" param "]"
58
#define TOTP_CLI_OPTIONAL_PARAM_MARK "[OPTIONAL]"
@@ -10,4 +13,5 @@
1013
printf(format, ##__VA_ARGS__); \
1114
_Pragma(STRINGIFY(GCC diagnostic pop));
1215

13-
void totp_cli_print_invalid_arguments();
16+
void totp_cli_print_invalid_arguments();
17+
bool totp_cli_ensure_authenticated(PluginState* plugin_state, Cli* cli);

services/cli/commands/add/add.c

Lines changed: 65 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
#include "../../../../scenes/scene_director.h"
99

1010
#define TOTP_CLI_COMMAND_ADD_ARG_NAME "NAME"
11-
#define TOTP_CLI_COMMAND_ADD_ARG_SECRET "SECRET"
1211
#define TOTP_CLI_COMMAND_ADD_ARG_ALGO "ALGO"
1312
#define TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX "-a"
1413
#define TOTP_CLI_COMMAND_ADD_ARG_DIGITS "DIGITS"
1514
#define TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX "-d"
15+
#define TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX "-u"
1616

1717
static bool token_info_set_digits_from_str(TokenInfo* token_info, FuriString* str) {
1818
switch(furi_string_get_char(str, 0)) {
@@ -47,14 +47,14 @@ static bool token_info_set_algo_from_str(TokenInfo* token_info, FuriString* str)
4747
}
4848

4949
void totp_cli_command_add_print_help() {
50-
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");
50+
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");
5151
TOTP_CLI_PRINTF("\t\t" TOTP_CLI_ARG(TOTP_CLI_COMMAND_ADD_ARG_NAME) " - token name\r\n");
52-
TOTP_CLI_PRINTF("\t\t" TOTP_CLI_ARG(TOTP_CLI_COMMAND_ADD_ARG_SECRET) " - Base32 token secret\r\n");
5352
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");
54-
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");
53+
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");
54+
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");
5555
}
5656

57-
void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args) {
57+
void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
5858
FuriString* temp_str = furi_string_alloc();
5959
const char* temp_cstr;
6060

@@ -72,23 +72,8 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args) {
7272
token_info->name = malloc(strlen(temp_cstr) + 1);
7373
strcpy(token_info->name, temp_cstr);
7474

75-
// Reading token secret
76-
if (!args_read_probably_quoted_string_and_trim(args, temp_str)) {
77-
totp_cli_print_invalid_arguments();
78-
furi_string_free(temp_str);
79-
token_info_free(token_info);
80-
return;
81-
}
82-
83-
temp_cstr = furi_string_get_cstr(temp_str);
84-
if (!token_info_set_secret(token_info, temp_cstr, strlen(temp_cstr), plugin_state->iv)) {
85-
TOTP_CLI_PRINTF("Token secret seems to be invalid and can not be parsed\r\n");
86-
furi_string_free(temp_str);
87-
token_info_free(token_info);
88-
return;
89-
}
90-
9175
// Read optional arguments
76+
bool mask_user_input = true;
9277
while (args_read_string_and_trim(args, temp_str)) {
9378
bool parsed = false;
9479
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) {
10792
} else {
10893
parsed = true;
10994
}
95+
} else if (furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX) == 0) {
96+
mask_user_input = false;
97+
parsed = true;
11098
}
99+
111100
if (!parsed) {
112101
totp_cli_print_invalid_arguments();
113102
furi_string_free(temp_str);
@@ -116,6 +105,61 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args) {
116105
}
117106
}
118107

108+
// Reading token secret
109+
furi_string_reset(temp_str);
110+
TOTP_CLI_PRINTF("Enter token secret and confirm with [ENTER]:\r\n");
111+
112+
uint8_t c;
113+
while(cli_read(cli, &c, 1) == 1) {
114+
if (c == CliSymbolAsciiEsc) {
115+
uint8_t c2;
116+
cli_read_timeout(cli, &c2, 1, 0);
117+
cli_read_timeout(cli, &c2, 1, 0);
118+
} else if(c == CliSymbolAsciiETX) {
119+
TOTP_CLI_PRINTF("Cancelled by user");
120+
furi_string_free(temp_str);
121+
token_info_free(token_info);
122+
return;
123+
} else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
124+
if (mask_user_input) {
125+
putc('*', stdout);
126+
} else {
127+
putc(c, stdout);
128+
}
129+
fflush(stdout);
130+
furi_string_push_back(temp_str, c);
131+
} else if (c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) {
132+
size_t temp_str_size = furi_string_size(temp_str);
133+
if (temp_str_size > 0) {
134+
TOTP_CLI_PRINTF("\b \b");
135+
fflush(stdout);
136+
furi_string_left(temp_str, temp_str_size - 1);
137+
}
138+
}
139+
else if(c == CliSymbolAsciiCR) {
140+
cli_nl();
141+
break;
142+
}
143+
}
144+
145+
temp_cstr = furi_string_get_cstr(temp_str);
146+
147+
if (!totp_cli_ensure_authenticated(plugin_state, cli)) {
148+
furi_string_free(temp_str);
149+
token_info_free(token_info);
150+
return;
151+
}
152+
153+
if (!token_info_set_secret(token_info, temp_cstr, strlen(temp_cstr), plugin_state->iv)) {
154+
TOTP_CLI_PRINTF("Token secret seems to be invalid and can not be parsed\r\n");
155+
furi_string_free(temp_str);
156+
token_info_free(token_info);
157+
return;
158+
}
159+
160+
furi_string_reset(temp_str);
161+
furi_string_free(temp_str);
162+
119163
bool load_generate_token_scene = false;
120164
if (plugin_state->current_scene == TotpSceneGenerateToken) {
121165
totp_scene_director_activate_scene(plugin_state, TotpSceneNone, NULL);
@@ -134,7 +178,5 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args) {
134178
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
135179
}
136180

137-
furi_string_free(temp_str);
138-
139181
TOTP_CLI_PRINTF("Token \"%s\" has been successfully added\r\n", token_info->name);
140182
}

services/cli/commands/add/add.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55

66
#define TOTP_CLI_COMMAND_ADD "add"
77

8-
void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args);
8+
void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cli* cli);
99
void totp_cli_command_add_print_help();

services/cli/commands/delete/delete.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
void totp_cli_command_delete_print_help() {
1515
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");
1616
TOTP_CLI_PRINTF("\t\t" TOTP_CLI_ARG(TOTP_CLI_COMMAND_DELETE_ARG_INDEX) " - token index in the list\r\n");
17-
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");
17+
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");
1818
}
1919

2020
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,
3838
}
3939
furi_string_free(temp_str);
4040

41+
if (!totp_cli_ensure_authenticated(plugin_state, cli)) {
42+
return;
43+
}
44+
4145
ListNode* list_node = list_element_at(plugin_state->tokens_list, token_number - 1);
4246

4347
TokenInfo* token_info = list_node->data;
@@ -51,12 +55,20 @@ void totp_cli_command_delete_handle(PluginState* plugin_state, FuriString* args,
5155
char user_pick;
5256
do {
5357
user_pick = tolower(cli_getc(cli));
54-
} while (user_pick != 'y' && user_pick != 'n' && user_pick != CliSymbolAsciiCR);
58+
} while (user_pick != 'y' &&
59+
user_pick != 'n' &&
60+
user_pick != CliSymbolAsciiCR &&
61+
user_pick != CliSymbolAsciiETX &&
62+
user_pick != CliSymbolAsciiEsc);
5563

5664
confirmed = user_pick == 'y' || user_pick == CliSymbolAsciiCR;
5765
}
5866

5967
if (confirmed) {
68+
if (!totp_cli_ensure_authenticated(plugin_state, cli)) {
69+
return;
70+
}
71+
6072
bool activate_generate_token_scene = false;
6173
if (plugin_state->current_scene != TotpSceneAuthentication) {
6274
totp_scene_director_activate_scene(plugin_state, TotpSceneNone, NULL);

services/cli/commands/list/list.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#include "list.h"
2-
#include <cli/cli.h>
32
#include <stdlib.h>
43
#include "../../../list/list.h"
54
#include "../../../../types/token_info.h"
@@ -34,7 +33,11 @@ void totp_cli_command_list_print_help() {
3433
TOTP_CLI_PRINTF("\t" TOTP_CLI_COMMAND_LIST " - list all tokens\r\n\r\n");
3534
}
3635

37-
void totp_cli_command_list_handle(PluginState* plugin_state) {
36+
void totp_cli_command_list_handle(PluginState* plugin_state, Cli* cli) {
37+
if (!totp_cli_ensure_authenticated(plugin_state, cli)) {
38+
return;
39+
}
40+
3841
if (plugin_state->tokens_list == NULL) {
3942
TOTP_CLI_PRINTF("There are no tokens");
4043
return;

services/cli/commands/list/list.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
#pragma once
22

3+
#include <cli/cli.h>
34
#include "../../../../types/plugin_state.h"
45

56
#define TOTP_CLI_COMMAND_LIST "list"
67

7-
void totp_cli_command_list_handle(PluginState* plugin_state);
8+
void totp_cli_command_list_handle(PluginState* plugin_state, Cli* cli);
89
void totp_cli_command_list_print_help();

services/cli/commands/timezone/timezone.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ void totp_cli_command_timezone_print_help() {
1111
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");
1212
}
1313

14-
void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args) {
14+
void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
15+
if (!totp_cli_ensure_authenticated(plugin_state, cli)) {
16+
return;
17+
}
18+
1519
FuriString* temp_str = furi_string_alloc();
1620
if (args_read_string_and_trim(args, temp_str)) {
1721
float tz = strtof(furi_string_get_cstr(temp_str), NULL);

services/cli/commands/timezone/timezone.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55

66
#define TOTP_CLI_COMMAND_TIMEZONE "timezone"
77

8-
void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args);
8+
void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args, Cli* cli);
99
void totp_cli_command_timezone_print_help();

0 commit comments

Comments
 (0)