Skip to content

Commit

Permalink
Implementation of #65 (#66)
Browse files Browse the repository at this point in the history
* Initial implementation of #65
  • Loading branch information
akopachov committed Jan 18, 2023
1 parent cd7c9c7 commit 41c23ba
Show file tree
Hide file tree
Showing 11 changed files with 234 additions and 35 deletions.
48 changes: 39 additions & 9 deletions cli/commands/add/add.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#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"
#define TOTP_CLI_COMMAND_ADD_ARG_DURATION "duration"
#define TOTP_CLI_COMMAND_ADD_ARG_DURATION_PREFIX "-l"

static bool token_info_set_algo_from_str(TokenInfo* token_info, const FuriString* str) {
if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME) == 0) {
Expand All @@ -34,6 +36,16 @@ static bool token_info_set_algo_from_str(TokenInfo* token_info, const FuriString
return false;
}

static bool args_read_uint8_and_trim(FuriString* args, uint8_t* value) {
int int_value;
if (!args_read_int_and_trim(args, &int_value) || int_value < 0 || int_value > UINT8_MAX) {
return false;
}

*value = (uint8_t)int_value;
return true;
}

void totp_cli_command_add_docopt_commands() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_ADD ", " TOTP_CLI_COMMAND_ADD_ALT
", " TOTP_CLI_COMMAND_ADD_ALT2 " Add new token\r\n");
Expand All @@ -42,11 +54,11 @@ void totp_cli_command_add_docopt_commands() {
void totp_cli_command_add_docopt_usage() {
TOTP_CLI_PRINTF(
" " TOTP_CLI_COMMAND_NAME
" " DOCOPT_REQUIRED(TOTP_CLI_COMMAND_ADD " | " TOTP_CLI_COMMAND_ADD_ALT " | " TOTP_CLI_COMMAND_ADD_ALT2) " " DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ADD_ARG_NAME) " " DOCOPT_OPTIONAL(
" " DOCOPT_REQUIRED(TOTP_CLI_COMMAND_ADD " | " TOTP_CLI_COMMAND_ADD_ALT " | " TOTP_CLI_COMMAND_ADD_ALT2) " " DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ADD_ARG_NAME) " " DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ADD_ARG_ALGO))) " " DOCOPT_OPTIONAL(
DOCOPT_OPTION(
TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX,
TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX,
DOCOPT_ARGUMENT(
TOTP_CLI_COMMAND_ADD_ARG_ALGO))) " " DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ADD_ARG_DIGITS))) " " DOCOPT_OPTIONAL(DOCOPT_SWITCH(TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX)) "\r\n");
TOTP_CLI_COMMAND_ADD_ARG_DIGITS))) " " DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ADD_ARG_DURATION_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ADD_ARG_DURATION))) " " DOCOPT_OPTIONAL(DOCOPT_SWITCH(TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX)) "\r\n");
}

void totp_cli_command_add_docopt_arguments() {
Expand All @@ -64,6 +76,10 @@ void totp_cli_command_add_docopt_options() {
TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX,
DOCOPT_ARGUMENT(
TOTP_CLI_COMMAND_ADD_ARG_DIGITS)) " Number of digits to generate, one of: 6, 8 " DOCOPT_DEFAULT("6") "\r\n");
TOTP_CLI_PRINTF(" " DOCOPT_OPTION(
TOTP_CLI_COMMAND_ADD_ARG_DURATION_PREFIX,
DOCOPT_ARGUMENT(
TOTP_CLI_COMMAND_ADD_ARG_DURATION)) " Token lifetime duration in seconds, between: 15 and 255 " DOCOPT_DEFAULT("30") "\r\n");
TOTP_CLI_PRINTF(" " DOCOPT_SWITCH(
TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX) " Show console user input as-is without masking\r\n");
}
Expand Down Expand Up @@ -110,16 +126,30 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl
parsed = true;
}
} else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX) == 0) {
if(!args_read_string_and_trim(args, temp_str)) {
uint8_t digit_value;
if(!args_read_uint8_and_trim(args, &digit_value)) {
TOTP_CLI_PRINTF(
"Missed value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX
"Missed or incorrect value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX
"\"\r\n");
} else if(!token_info_set_digits_from_int(
token_info, CONVERT_CHAR_TO_DIGIT(furi_string_get_char(temp_str, 0)))) {
} else if(!token_info_set_digits_from_int(token_info, digit_value)) {
TOTP_CLI_PRINTF(
"\"%s\" is incorrect value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX
"\"%" PRIu8 "\" is incorrect value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX
"\"\r\n",
furi_string_get_cstr(temp_str));
digit_value);
} else {
parsed = true;
}
} else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_ADD_ARG_DURATION_PREFIX) == 0) {
uint8_t duration_value;
if(!args_read_uint8_and_trim(args, &duration_value)) {
TOTP_CLI_PRINTF(
"Missed or incorrect value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_DURATION_PREFIX
"\"\r\n");
} else if(!token_info_set_duration_from_int(token_info, duration_value)) {
TOTP_CLI_PRINTF(
"\"%" PRIu8 "\" is incorrect value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_DURATION_PREFIX
"\"\r\n",
duration_value);
} else {
parsed = true;
}
Expand Down
14 changes: 8 additions & 6 deletions cli/commands/list/list.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,21 @@ void totp_cli_command_list_handle(PluginState* plugin_state, Cli* cli) {
return;
}

TOTP_CLI_PRINTF("+-----+-----------------------------+--------+--------+\r\n");
TOTP_CLI_PRINTF("| %-*s | %-*s | %-*s | %-s |\r\n", 3, "#", 27, "Name", 6, "Algo", "Digits");
TOTP_CLI_PRINTF("+-----+-----------------------------+--------+--------+\r\n");
TOTP_CLI_PRINTF("+-----+---------------------------+--------+----+-----+\r\n");
TOTP_CLI_PRINTF(
"| %-*s | %-*s | %-*s | %-s | %-s |\r\n", 3, "#", 25, "Name", 6, "Algo", "Ln", "Dur");
TOTP_CLI_PRINTF("+-----+---------------------------+--------+----+-----+\r\n");
uint16_t index = 1;
TOTP_LIST_FOREACH(plugin_state->tokens_list, node, {
TokenInfo* token_info = (TokenInfo*)node->data;
TOTP_CLI_PRINTF(
"| %-3" PRIu16 " | %-27.27s | %-6s | %-6" PRIu8 " |\r\n",
"| %-3" PRIu16 " | %-25.25s | %-6s | %-2" PRIu8 " | %-3" PRIu8 " |\r\n",
index,
token_info->name,
get_algo_as_cstr(token_info->algo),
token_info->digits);
token_info->digits,
token_info->duration);
index++;
});
TOTP_CLI_PRINTF("+-----+-----------------------------+--------+--------+\r\n");
TOTP_CLI_PRINTF("+-----+---------------------------+--------+----+-----+\r\n");
}
33 changes: 33 additions & 0 deletions services/config/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "../../types/common.h"
#include "../../types/token_info.h"
#include "migrations/config_migration_v1_to_v2.h"
#include "migrations/config_migration_v2_to_v3.h"

#define CONFIG_FILE_DIRECTORY_PATH EXT_PATH("authenticator")
#define CONFIG_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf"
Expand Down Expand Up @@ -173,6 +174,13 @@ static TotpConfigFileOpenResult totp_open_config_file(Storage* storage, FlipperF
flipper_format_write_comment(fff_data_file, temp_str);
flipper_format_write_comment_cstr(fff_data_file, " ");

flipper_format_write_comment_cstr(
fff_data_file,
"# Token lifetime duration in seconds. Should be between 15 and 255. Majority websites requires 30, however some rare websites may require custom lifetime. If you are not sure which one to use - use 30");
furi_string_printf(temp_str, "%s: 30", TOTP_CONFIG_KEY_TOKEN_DURATION);
flipper_format_write_comment(fff_data_file, temp_str);
flipper_format_write_comment_cstr(fff_data_file, " ");

flipper_format_write_comment_cstr(fff_data_file, "=== TOKEN SAMPLE END ===");
flipper_format_write_comment_cstr(fff_data_file, " ");

Expand Down Expand Up @@ -232,6 +240,12 @@ TotpConfigFileUpdateResult
break;
}

tmp_uint32 = token_info->duration;
if(!flipper_format_write_uint32(file, TOTP_CONFIG_KEY_TOKEN_DURATION, &tmp_uint32, 1)) {
update_result = TotpConfigFileUpdateError;
break;
}

update_result = TotpConfigFileUpdateSuccess;
} while(false);

Expand Down Expand Up @@ -483,6 +497,7 @@ TotpConfigFileOpenResult totp_config_file_load_base(PluginState* const plugin_st
if(file_version == 1) {
if(totp_config_migrate_v1_to_v2(fff_data_file, fff_backup_data_file)) {
FURI_LOG_I(LOGGING_TAG, "Applied migration from v1 to v2");
file_version = 2;
} else {
FURI_LOG_W(
LOGGING_TAG, "An error occurred during migration from v1 to v2");
Expand All @@ -491,6 +506,18 @@ TotpConfigFileOpenResult totp_config_file_load_base(PluginState* const plugin_st
}
}

if(file_version == 2) {
if(totp_config_migrate_v2_to_v3(fff_data_file, fff_backup_data_file)) {
FURI_LOG_I(LOGGING_TAG, "Applied migration from v2 to v3");
file_version = 3;
} else {
FURI_LOG_W(
LOGGING_TAG, "An error occurred during migration from v2 to v3");
result = TotpConfigFileOpenError;
break;
}
}

flipper_format_file_close(fff_backup_data_file);
flipper_format_free(fff_backup_data_file);
flipper_format_rewind(fff_data_file);
Expand Down Expand Up @@ -669,6 +696,12 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state)
tokenInfo->digits = TOTP_6_DIGITS;
}

if(!flipper_format_read_uint32(
fff_data_file, TOTP_CONFIG_KEY_TOKEN_DURATION, &temp_data32, 1) ||
!token_info_set_duration_from_int(tokenInfo, temp_data32)) {
tokenInfo->duration = TOTP_TOKEN_DURATION_DEFAULT;
}

FURI_LOG_D(LOGGING_TAG, "Found token \"%s\"", tokenInfo->name);

TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, tokenInfo, furi_check);
Expand Down
3 changes: 2 additions & 1 deletion services/config/constants.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#pragma once

#define CONFIG_FILE_HEADER "Flipper TOTP plugin config file"
#define CONFIG_FILE_ACTUAL_VERSION 2
#define CONFIG_FILE_ACTUAL_VERSION 3

#define TOTP_CONFIG_KEY_TIMEZONE "Timezone"
#define TOTP_CONFIG_KEY_TOKEN_NAME "TokenName"
#define TOTP_CONFIG_KEY_TOKEN_SECRET "TokenSecret"
#define TOTP_CONFIG_KEY_TOKEN_ALGO "TokenAlgo"
#define TOTP_CONFIG_KEY_TOKEN_DIGITS "TokenDigits"
#define TOTP_CONFIG_KEY_TOKEN_DURATION "TokenDuration"
#define TOTP_CONFIG_KEY_CRYPTO_VERIFY "Crypto"
#define TOTP_CONFIG_KEY_BASE_IV "BaseIV"
#define TOTP_CONFIG_KEY_PINSET "PinIsSet"
Expand Down
3 changes: 2 additions & 1 deletion services/config/migrations/config_migration_v1_to_v2.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "config_migration_v1_to_v2.h"
#include <flipper_format/flipper_format.h>
#include "../constants.h"
#include "../../../types/token_info.h"

#define NEW_VERSION 2

Expand Down Expand Up @@ -36,7 +37,7 @@ bool totp_config_migrate_v1_to_v2(

flipper_format_write_string_cstr(
fff_data_file, TOTP_CONFIG_KEY_TOKEN_ALGO, TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME);
uint32_t default_digits = 6;
const uint32_t default_digits = TOTP_6_DIGITS;
flipper_format_write_uint32(
fff_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &default_digits, 1);
}
Expand Down
70 changes: 70 additions & 0 deletions services/config/migrations/config_migration_v2_to_v3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include "config_migration_v2_to_v3.h"
#include <flipper_format/flipper_format.h>
#include "../constants.h"
#include "../../../types/token_info.h"

#define NEW_VERSION 3

bool totp_config_migrate_v2_to_v3(
FlipperFormat* fff_data_file,
FlipperFormat* fff_backup_data_file) {
flipper_format_write_header_cstr(fff_data_file, CONFIG_FILE_HEADER, NEW_VERSION);

FuriString* temp_str = furi_string_alloc();

if(flipper_format_read_string(fff_backup_data_file, TOTP_CONFIG_KEY_BASE_IV, temp_str)) {
flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_BASE_IV, temp_str);
}

flipper_format_rewind(fff_backup_data_file);

if(flipper_format_read_string(fff_backup_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, temp_str)) {
flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, temp_str);
}

flipper_format_rewind(fff_backup_data_file);

if(flipper_format_read_string(fff_backup_data_file, TOTP_CONFIG_KEY_TIMEZONE, temp_str)) {
flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, temp_str);
}

flipper_format_rewind(fff_backup_data_file);

if(flipper_format_read_string(fff_backup_data_file, TOTP_CONFIG_KEY_PINSET, temp_str)) {
flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_PINSET, temp_str);
}

flipper_format_rewind(fff_backup_data_file);

if(flipper_format_read_string(
fff_backup_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, temp_str)) {
flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, temp_str);
}

flipper_format_rewind(fff_backup_data_file);

while(true) {
if(!flipper_format_read_string(
fff_backup_data_file, TOTP_CONFIG_KEY_TOKEN_NAME, temp_str)) {
break;
}

flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_NAME, temp_str);

flipper_format_read_string(fff_backup_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, temp_str);
flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, temp_str);

flipper_format_read_string(fff_backup_data_file, TOTP_CONFIG_KEY_TOKEN_ALGO, temp_str);
flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_ALGO, temp_str);

flipper_format_read_string(fff_backup_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, temp_str);
flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, temp_str);

const uint32_t default_duration = TOTP_TOKEN_DURATION_DEFAULT;
flipper_format_write_uint32(
fff_data_file, TOTP_CONFIG_KEY_TOKEN_DURATION, &default_duration, 1);
}

furi_string_free(temp_str);
return true;
}
7 changes: 7 additions & 0 deletions services/config/migrations/config_migration_v2_to_v3.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once

#include <flipper_format/flipper_format.h>

bool totp_config_migrate_v2_to_v3(
FlipperFormat* fff_data_file,
FlipperFormat* fff_backup_data_file);
9 changes: 9 additions & 0 deletions types/token_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,12 @@ bool token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits) {

return false;
}

bool token_info_set_duration_from_int(TokenInfo* token_info, uint8_t duration) {
if(duration >= 15) {
token_info->duration = duration;
return true;
}

return false;
}
17 changes: 16 additions & 1 deletion types/token_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <inttypes.h>

#define TOTP_TOKEN_DURATION_DEFAULT 30

typedef uint8_t TokenHashAlgo;
typedef uint8_t TokenDigitsCount;

Expand Down Expand Up @@ -70,6 +72,11 @@ typedef struct {
* @brief Desired TOTP token length
*/
TokenDigitsCount digits;

/**
* @brief Desired TOTP token duration in seconds
*/
uint8_t duration;
} TokenInfo;

/**
Expand Down Expand Up @@ -102,6 +109,14 @@ bool token_info_set_secret(
* @brief Sets token digits count from \c uint8_t value
* @param token_info instance whichs token digits count length should be updated
* @param digits desired token digits count length
* @return \c true if token digits count length has been updated; \c false p
* @return \c true if token digits count length has been updated; \c false otherwise
*/
bool token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits);

/**
* @brief Sets token duration from \c uint8_t value
* @param token_info instance whichs token digits count length should be updated
* @param duration desired token duration in seconds
* @return \c true if token duration has been updated; \c false otherwise
*/
bool token_info_set_duration_from_int(TokenInfo* token_info, uint8_t duration);
Loading

0 comments on commit 41c23ba

Please sign in to comment.