Skip to content

Commit 4374e30

Browse files
authored
Initial changes on #58 (#59)
1 parent 4a84686 commit 4374e30

File tree

13 files changed

+166
-55
lines changed

13 files changed

+166
-55
lines changed

FAQ.md

+11-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ When Flipper Authenticator is running `totp` CLI is available for you to list, a
3434

3535
**YES!**
3636

37-
Just pick the token you would like to auto-type then hold "arrow down" button for 1-2sec. and Flipper Authenticator will type it instead of you 😀
37+
Just pick the token you would like to auto-type then hold <span title="Arrow Down">▼</span> button for 1-2sec. and let Flipper Authenticator type it instead of you 😀
3838

3939
## How to change\recover PIN?
4040

@@ -49,6 +49,15 @@ To do that you may use following CLI commands:
4949

5050
All token secrets are stored in encrypted form and are tied to an original Flipper device and PIN. Given that, there is no sense to try to backup `/ext/apps/Misc/totp.conf` file as it will not help you in situation when you loose your Flipper device. Instead use your favorite password manager to store plain token secrets and\or any other information which will help you recover your accounts.
5151

52+
## How to reset application?
53+
54+
There are two options to reset Flipper Authenticator to its default:
55+
56+
1. Delete `/ext/authenticator/totp.conf` file
57+
2. Use `totp reset` CLI command
58+
59+
**Regardless of which option you use, please pay attention to the fact that <ins>you will loose everything you configured and added to Flipper Authenticator application, including token secrets.</ins>**
60+
5261
## Flipper Authenticator generates invalid codes, why so?
5362

5463
There are multiple reasons why Flipper Authenticator generates invalid codes:
@@ -67,4 +76,4 @@ Sometimes it is possible that you just made a mistake while typing or copying to
6776

6877
### Token hashing algorithm is not correct
6978

70-
In majority of situation using default hashing algorithm `SHA1` should work just fine. But for some rare providers it might be necessary to use `SHA256` or `SHA512` as a hashinig alogorithm.
79+
In majority of situations using default hashing algorithm `SHA1` should work just fine. But for some rare providers it might be necessary to use `SHA256` or `SHA512` as a hashinig alogorithm.

totp/cli/cli.c

+15-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "commands/move/move.h"
1212
#include "commands/pin/pin.h"
1313
#include "commands/notification/notification.h"
14+
#include "commands/reset/reset.h"
1415

1516
static void totp_cli_print_unknown_command(const FuriString* unknown_command) {
1617
TOTP_CLI_PRINTF(
@@ -20,7 +21,8 @@ static void totp_cli_print_unknown_command(const FuriString* unknown_command) {
2021
}
2122

2223
static void totp_cli_handler(Cli* cli, FuriString* args, void* context) {
23-
PluginState* plugin_state = (PluginState*)context;
24+
TotpCliContext* cli_context = context;
25+
PluginState* plugin_state = cli_context->plugin_state;
2426

2527
FuriString* cmd = furi_string_alloc();
2628

@@ -55,22 +57,31 @@ static void totp_cli_handler(Cli* cli, FuriString* args, void* context) {
5557
totp_cli_command_pin_handle(plugin_state, args, cli);
5658
} else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_NOTIFICATION) == 0) {
5759
totp_cli_command_notification_handle(plugin_state, args, cli);
60+
} else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_RESET) == 0) {
61+
totp_cli_command_reset_handle(cli, cli_context->event_queue);
5862
} else {
5963
totp_cli_print_unknown_command(cmd);
6064
}
6165

6266
furi_string_free(cmd);
6367
}
6468

65-
void totp_cli_register_command_handler(PluginState* plugin_state) {
69+
TotpCliContext*
70+
totp_cli_register_command_handler(PluginState* plugin_state, FuriMessageQueue* event_queue) {
6671
Cli* cli = furi_record_open(RECORD_CLI);
72+
TotpCliContext* context = malloc(sizeof(TotpCliContext));
73+
furi_check(context != NULL);
74+
context->plugin_state = plugin_state;
75+
context->event_queue = event_queue;
6776
cli_add_command(
68-
cli, TOTP_CLI_COMMAND_NAME, CliCommandFlagParallelSafe, totp_cli_handler, plugin_state);
77+
cli, TOTP_CLI_COMMAND_NAME, CliCommandFlagParallelSafe, totp_cli_handler, context);
6978
furi_record_close(RECORD_CLI);
79+
return context;
7080
}
7181

72-
void totp_cli_unregister_command_handler() {
82+
void totp_cli_unregister_command_handler(TotpCliContext* context) {
7383
Cli* cli = furi_record_open(RECORD_CLI);
7484
cli_delete_command(cli, TOTP_CLI_COMMAND_NAME);
7585
furi_record_close(RECORD_CLI);
86+
free(context);
7687
}

totp/cli/cli.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,11 @@
33
#include <cli/cli.h>
44
#include "../types/plugin_state.h"
55

6-
void totp_cli_register_command_handler(PluginState* plugin_state);
7-
void totp_cli_unregister_command_handler();
6+
typedef struct {
7+
PluginState* plugin_state;
8+
FuriMessageQueue* event_queue;
9+
} TotpCliContext;
10+
11+
TotpCliContext*
12+
totp_cli_register_command_handler(PluginState* plugin_state, FuriMessageQueue* event_queue);
13+
void totp_cli_unregister_command_handler(TotpCliContext* context);

totp/cli/cli_helpers.c

+41
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "cli_helpers.h"
22
#include <cli/cli.h>
3+
#include "../types/plugin_event.h"
34

45
bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli) {
56
if(plugin_state->current_scene == TotpSceneAuthentication) {
@@ -17,5 +18,45 @@ bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli) {
1718
}
1819
}
1920

21+
return true;
22+
}
23+
24+
void totp_cli_force_close_app(FuriMessageQueue* event_queue) {
25+
PluginEvent event = {.type = EventForceCloseApp};
26+
furi_message_queue_put(event_queue, &event, FuriWaitForever);
27+
}
28+
29+
bool totp_cli_read_line(Cli* cli, FuriString* out_str, bool mask_user_input) {
30+
uint8_t c;
31+
while(cli_read(cli, &c, 1) == 1) {
32+
if(c == CliSymbolAsciiEsc) {
33+
// Some keys generating escape-sequences
34+
// We need to ignore them as we care about alpha-numerics only
35+
uint8_t c2;
36+
cli_read_timeout(cli, &c2, 1, 0);
37+
cli_read_timeout(cli, &c2, 1, 0);
38+
} else if(c == CliSymbolAsciiETX) {
39+
cli_nl();
40+
return false;
41+
} else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
42+
if(mask_user_input) {
43+
putc('*', stdout);
44+
} else {
45+
putc(c, stdout);
46+
}
47+
fflush(stdout);
48+
furi_string_push_back(out_str, c);
49+
} else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) {
50+
size_t out_str_size = furi_string_size(out_str);
51+
if(out_str_size > 0) {
52+
TOTP_CLI_DELETE_LAST_CHAR();
53+
furi_string_left(out_str, out_str_size - 1);
54+
}
55+
} else if(c == CliSymbolAsciiCR) {
56+
cli_nl();
57+
break;
58+
}
59+
}
60+
2061
return true;
2162
}

totp/cli/cli_helpers.h

+16-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,22 @@
4545
* @brief Checks whether user is authenticated and entered correct PIN.
4646
* If user is not authenticated it prompts user to enter correct PIN to authenticate.
4747
* @param plugin_state application state
48-
* @param cli reference to the firmware CLI subsystem
48+
* @param cli pointer to the firmware CLI subsystem
4949
* @return \c true if user is already authenticated or successfully authenticated; \c false otherwise
5050
*/
5151
bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli);
52+
53+
/**
54+
* @brief Forces application to be instantly closed
55+
* @param event_queue main app queue
56+
*/
57+
void totp_cli_force_close_app(FuriMessageQueue* event_queue);
58+
59+
/**
60+
* @brief Reads line of characters from console
61+
* @param cli pointer to the firmware CLI subsystem
62+
* @param out_str pointer to an output string to put read line to
63+
* @param mask_user_input whether to mask input characters in console or not
64+
* @return \c true if line successfully read and confirmed; \c false otherwise
65+
*/
66+
bool totp_cli_read_line(Cli* cli, FuriString* out_str, bool mask_user_input);

totp/cli/commands/add/add.c

+5-38
Original file line numberDiff line numberDiff line change
@@ -76,43 +76,6 @@ static void furi_string_secure_free(FuriString* str) {
7676
furi_string_free(str);
7777
}
7878

79-
static bool totp_cli_read_secret(Cli* cli, FuriString* out_str, bool mask_user_input) {
80-
uint8_t c;
81-
while(cli_read(cli, &c, 1) == 1) {
82-
if(c == CliSymbolAsciiEsc) {
83-
// Some keys generating escape-sequences
84-
// We need to ignore them as we care about alpha-numerics only
85-
uint8_t c2;
86-
cli_read_timeout(cli, &c2, 1, 0);
87-
cli_read_timeout(cli, &c2, 1, 0);
88-
} else if(c == CliSymbolAsciiETX) {
89-
TOTP_CLI_DELETE_CURRENT_LINE();
90-
TOTP_CLI_PRINTF("Cancelled by user\r\n");
91-
return false;
92-
} else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
93-
if(mask_user_input) {
94-
putc('*', stdout);
95-
} else {
96-
putc(c, stdout);
97-
}
98-
fflush(stdout);
99-
furi_string_push_back(out_str, c);
100-
} else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) {
101-
size_t out_str_size = furi_string_size(out_str);
102-
if(out_str_size > 0) {
103-
TOTP_CLI_DELETE_LAST_CHAR();
104-
furi_string_left(out_str, out_str_size - 1);
105-
}
106-
} else if(c == CliSymbolAsciiCR) {
107-
cli_nl();
108-
break;
109-
}
110-
}
111-
112-
TOTP_CLI_DELETE_LAST_LINE();
113-
return true;
114-
}
115-
11679
void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
11780
FuriString* temp_str = furi_string_alloc();
11881
TokenInfo* token_info = token_info_alloc();
@@ -178,13 +141,17 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl
178141
// Reading token secret
179142
furi_string_reset(temp_str);
180143
TOTP_CLI_PRINTF("Enter token secret and confirm with [ENTER]\r\n");
181-
if(!totp_cli_read_secret(cli, temp_str, mask_user_input) ||
144+
if(!totp_cli_read_line(cli, temp_str, mask_user_input) ||
182145
!totp_cli_ensure_authenticated(plugin_state, cli)) {
146+
TOTP_CLI_DELETE_LAST_LINE();
147+
TOTP_CLI_PRINTF("Cancelled by user\r\n");
183148
furi_string_secure_free(temp_str);
184149
token_info_free(token_info);
185150
return;
186151
}
187152

153+
TOTP_CLI_DELETE_LAST_LINE();
154+
188155
if(!token_info_set_secret(
189156
token_info,
190157
furi_string_get_cstr(temp_str),

totp/cli/commands/help/help.c

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "../move/move.h"
88
#include "../pin/pin.h"
99
#include "../notification/notification.h"
10+
#include "../reset/reset.h"
1011

1112
void totp_cli_command_help_docopt_commands() {
1213
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_HELP ", " TOTP_CLI_COMMAND_HELP_ALT
@@ -29,6 +30,7 @@ void totp_cli_command_help_handle() {
2930
totp_cli_command_move_docopt_usage();
3031
totp_cli_command_pin_docopt_usage();
3132
totp_cli_command_notification_docopt_usage();
33+
totp_cli_command_reset_docopt_usage();
3234
cli_nl();
3335
TOTP_CLI_PRINTF("Commands:\r\n");
3436
totp_cli_command_help_docopt_commands();
@@ -39,6 +41,7 @@ void totp_cli_command_help_handle() {
3941
totp_cli_command_move_docopt_commands();
4042
totp_cli_command_pin_docopt_commands();
4143
totp_cli_command_notification_docopt_commands();
44+
totp_cli_command_reset_docopt_commands();
4245
cli_nl();
4346
TOTP_CLI_PRINTF("Arguments:\r\n");
4447
totp_cli_command_add_docopt_arguments();

totp/cli/commands/reset/reset.c

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include "reset.h"
2+
3+
#include <stdlib.h>
4+
#include <furi/furi.h>
5+
#include "../../cli_helpers.h"
6+
#include "../../../services/config/config.h"
7+
8+
#define TOTP_CLI_RESET_CONFIRMATION_KEYWORD "YES"
9+
10+
void totp_cli_command_reset_docopt_commands() {
11+
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_RESET
12+
" Reset application to default settings\r\n");
13+
}
14+
15+
void totp_cli_command_reset_docopt_usage() {
16+
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_NAME " " TOTP_CLI_COMMAND_RESET "\r\n");
17+
}
18+
19+
void totp_cli_command_reset_handle(Cli* cli, FuriMessageQueue* event_queue) {
20+
TOTP_CLI_PRINTF(
21+
"As a result of reset all the settings and tokens will be permanently lost.\r\n");
22+
TOTP_CLI_PRINTF("Do you really want to reset application?\r\n");
23+
TOTP_CLI_PRINTF("Type \"" TOTP_CLI_RESET_CONFIRMATION_KEYWORD
24+
"\" and hit <ENTER> to confirm:\r\n");
25+
FuriString* temp_str = furi_string_alloc();
26+
bool is_confirmed = totp_cli_read_line(cli, temp_str, false) &&
27+
furi_string_cmpi_str(temp_str, TOTP_CLI_RESET_CONFIRMATION_KEYWORD) == 0;
28+
furi_string_free(temp_str);
29+
if(is_confirmed) {
30+
totp_config_file_reset();
31+
TOTP_CLI_PRINTF("Application has been successfully reset to default.\r\n");
32+
TOTP_CLI_PRINTF("Now application will be closed to apply all the changes.\r\n");
33+
totp_cli_force_close_app(event_queue);
34+
} else {
35+
TOTP_CLI_PRINTF("Action was not confirmed by user\r\n");
36+
}
37+
}

totp/cli/commands/reset/reset.h

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#pragma once
2+
3+
#include <cli/cli.h>
4+
#include "../../../types/plugin_state.h"
5+
6+
#define TOTP_CLI_COMMAND_RESET "reset"
7+
8+
void totp_cli_command_reset_handle(Cli* cli, FuriMessageQueue* event_queue);
9+
void totp_cli_command_reset_docopt_commands();
10+
void totp_cli_command_reset_docopt_usage();

totp/services/config/config.c

+6
Original file line numberDiff line numberDiff line change
@@ -730,4 +730,10 @@ TotpConfigFileUpdateResult
730730

731731
totp_close_storage();
732732
return update_result;
733+
}
734+
735+
void totp_config_file_reset() {
736+
Storage* storage = totp_open_storage();
737+
storage_simply_remove(storage, CONFIG_FILE_PATH);
738+
totp_close_storage();
733739
}

totp/services/config/config.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,9 @@ TotpConfigFileUpdateResult totp_config_file_update_user_settings(const PluginSta
116116
* @return Config file update result
117117
*/
118118
TotpConfigFileUpdateResult
119-
totp_config_file_update_crypto_signatures(const PluginState* plugin_state);
119+
totp_config_file_update_crypto_signatures(const PluginState* plugin_state);
120+
121+
/**
122+
* @brief Reset all the settings to default
123+
*/
124+
void totp_config_file_reset();

totp/totp_app.c

+7-3
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ int32_t totp_app() {
143143
return 255;
144144
}
145145

146-
totp_cli_register_command_handler(plugin_state);
146+
TotpCliContext* cli_context = totp_cli_register_command_handler(plugin_state, event_queue);
147147
totp_scene_director_init_scenes(plugin_state);
148148
if(!totp_activate_initial_scene(plugin_state)) {
149149
FURI_LOG_E(LOGGING_TAG, "An error ocurred during activating initial scene\r\n");
@@ -172,7 +172,11 @@ int32_t totp_app() {
172172
last_user_interaction_time = furi_get_tick();
173173
}
174174

175-
processing = totp_scene_director_handle_event(&event, plugin_state_m);
175+
if(event.type == EventForceCloseApp) {
176+
processing = false;
177+
} else {
178+
processing = totp_scene_director_handle_event(&event, plugin_state_m);
179+
}
176180
} else if(
177181
plugin_state_m->pin_set && plugin_state_m->current_scene != TotpSceneAuthentication &&
178182
furi_get_tick() - last_user_interaction_time > IDLE_TIMEOUT) {
@@ -183,7 +187,7 @@ int32_t totp_app() {
183187
release_mutex(&state_mutex, plugin_state_m);
184188
}
185189

186-
totp_cli_unregister_command_handler();
190+
totp_cli_unregister_command_handler(cli_context);
187191
totp_scene_director_deactivate_active_scene(plugin_state);
188192
totp_scene_director_dispose(plugin_state);
189193

totp/types/event_type.h

+1-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,4 @@
33

44
typedef uint8_t EventType;
55

6-
enum EventTypes {
7-
EventTypeTick,
8-
EventTypeKey,
9-
};
6+
enum EventTypes { EventTypeTick, EventTypeKey, EventForceCloseApp };

0 commit comments

Comments
 (0)