Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
c82615d
initial todos for client TOTP implementation
ricoandreaslepp Apr 16, 2025
2a43ba9
initial todos for server TOTP implementation
ricoandreaslepp Apr 16, 2025
9938840
additional client TODOs
ricoandreaslepp Apr 16, 2025
b91508c
todo for client TOTP input
ricoandreaslepp Apr 16, 2025
8853228
client-side and library additions
ricoandreaslepp Apr 19, 2025
0ce3058
add totp code, header and export from the libfko
ricoandreaslepp Apr 19, 2025
1761257
client TOTP todos for cmdline parsing
ricoandreaslepp Apr 20, 2025
e129eca
totp function refactoring and using time test vector
ricoandreaslepp Apr 20, 2025
48d04cf
pass secret by reference, basic temporary key-derivation, debug logging
ricoandreaslepp Apr 21, 2025
f850d26
function signatures to export out of libfko
ricoandreaslepp Apr 22, 2025
81d2267
bump TOTP to 6 digits
ricoandreaslepp Apr 22, 2025
5174631
TOTP base32 & secret generation TODOs
ricoandreaslepp Apr 22, 2025
b767c84
implement fko_totp_key_derivation, leverage time-step window in fko_t…
ricoandreaslepp Apr 22, 2025
162d7bc
user input, int to char buf, key derivation, some debug logging to be…
ricoandreaslepp Apr 22, 2025
ecb0729
read TOTP secrets from file and populate in memory, TODO for freeing …
ricoandreaslepp Apr 22, 2025
f482968
struct variables from TOTP access file
ricoandreaslepp Apr 22, 2025
08b5e8c
TOTP decryption branch and function, TOTP window from RFC6238, refact…
ricoandreaslepp Apr 22, 2025
459e189
remove openssl import, add totp.h to source files
ricoandreaslepp Apr 25, 2025
d5bd97e
refactor use_totp, fixed cmd_exec_success, fixed TOTP decryption proc…
ricoandreaslepp Apr 25, 2025
2ceda35
client cmdline options + key_gen base32
ricoandreaslepp May 11, 2025
b10132e
cli options struct TOTP additions
ricoandreaslepp May 11, 2025
c24d907
refactored TOTP prompt into get_totp()
ricoandreaslepp May 11, 2025
e158651
refactor client TOTP flow
ricoandreaslepp May 11, 2025
c256c43
insert TOTP into debug buf printing
ricoandreaslepp May 11, 2025
d679711
compile base32 files
ricoandreaslepp May 11, 2025
ac0ac92
export base32 functions and get/set totp from libfko
ricoandreaslepp May 11, 2025
50027b8
add totp field to ctx struct
ricoandreaslepp May 11, 2025
5babc93
add totp encoding on the client, and decoding + parsing on the sever
ricoandreaslepp May 11, 2025
269a09b
totp secret key generation
ricoandreaslepp May 11, 2025
a80f569
totp fko ctx functions
ricoandreaslepp May 11, 2025
ad602b6
totp key base32 key gen, and printing
ricoandreaslepp May 11, 2025
f787686
add TOTP fields to acc_stanza struct
ricoandreaslepp May 11, 2025
a648b62
verify client-supplied TOTP from obtained SPA data
ricoandreaslepp May 11, 2025
f3c920c
base32 decoding utilities for the initial secret
ricoandreaslepp May 12, 2025
5c64845
offset by 1 was overwriting previous buffer in memory + zero out buffer
ricoandreaslepp May 13, 2025
2a63f2b
GPL license, doxygen comments, base32 utests
ricoandreaslepp May 14, 2025
57cbd26
remove old todos, fix printing tiny mistakes
ricoandreaslepp May 14, 2025
0a4bfde
resolve const variable todo
ricoandreaslepp May 14, 2025
0c5749f
remove resolved todo
ricoandreaslepp May 14, 2025
2dd144b
fixed error message string
ricoandreaslepp May 15, 2025
dea8ada
use FKO_SUCCESS variable
ricoandreaslepp Jun 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions client/cmd_opts.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ enum {
FD_SET_STDIN,
FD_SET_ALT,
FAULT_INJECTION_TAG,
USE_TOTP,

/* Put GPG-related items below the following line */
GPG_ENCRYPTION = 0x200,
Expand Down Expand Up @@ -158,6 +159,7 @@ static struct option cmd_opts[] =
{"verbose", 0, NULL, 'v'},
{"version", 0, NULL, 'V'},
{"wget-cmd", 1, NULL, 'w'},
{"totp", 0, NULL, USE_TOTP},
{0, 0, 0, 0}
};

Expand Down
18 changes: 16 additions & 2 deletions client/config_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ enum
FWKNOP_CLI_ARG_RESOLVE_IP_HTTPS,
FWKNOP_CLI_ARG_RESOLVE_HTTP_ONLY,
FWKNOP_CLI_ARG_WGET_CMD,
FWKNOP_CLI_ARG_USE_TOTP,
FWKNOP_CLI_ARG_NO_SAVE_ARGS,
FWKNOP_CLI_LAST_ARG
} fwknop_cli_arg_t;
Expand Down Expand Up @@ -181,7 +182,8 @@ static fko_var_t fko_var_array[FWKNOP_CLI_LAST_ARG] =
{ "RESOLVE_IP_HTTPS", FWKNOP_CLI_ARG_RESOLVE_IP_HTTPS },
{ "RESOLVE_HTTP_ONLY", FWKNOP_CLI_ARG_RESOLVE_HTTP_ONLY },
{ "WGET_CMD", FWKNOP_CLI_ARG_WGET_CMD },
{ "NO_SAVE_ARGS", FWKNOP_CLI_ARG_NO_SAVE_ARGS }
{ "NO_SAVE_ARGS", FWKNOP_CLI_ARG_NO_SAVE_ARGS },
{ "USE_TOTP", FWKNOP_CLI_ARG_USE_TOTP }
};

/* Array to define which conf. variables are critical and should not be
Expand Down Expand Up @@ -219,7 +221,7 @@ generate_keys(fko_cli_options_t *options)
/* Generate the key through libfko */
res = fko_key_gen(options->key_base64, options->key_len,
options->hmac_key_base64, options->hmac_key_len,
options->hmac_type);
options->hmac_type, options->totp_key_base32, options->totp_key_len);

/* Exit upon key generation failure*/
if(res != FKO_SUCCESS)
Expand Down Expand Up @@ -1294,6 +1296,12 @@ parse_rc_param(fko_cli_options_t *options, const char *var_name, char * val)
options->resolve_http_only = 1;
else;
}
else if (var->pos == FWKNOP_CLI_ARG_USE_TOTP)
{
if (is_yes_str(val))
options->use_totp = 1;
else;
}
/* avoid saving .fwknop.run by default */
else if (var->pos == FWKNOP_CLI_ARG_NO_SAVE_ARGS)
{
Expand Down Expand Up @@ -1418,6 +1426,7 @@ add_single_var_to_rc(FILE* fhandle, short var_pos, fko_cli_options_t *options)
case FWKNOP_CLI_ARG_KEY_HMAC:
strlcpy(val, options->hmac_key, sizeof(val));
break;
/* TODO: does TOTP need FWKNOP_CLI_ARG_TOTP stuff as well? */
case FWKNOP_CLI_ARG_HMAC_DIGEST_TYPE :
hmac_digest_inttostr(options->hmac_type, val, sizeof(val));
break;
Expand Down Expand Up @@ -2470,6 +2479,9 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
options->input_fd = strtol_wrapper(optarg, 0,
-1, EXIT_UPON_ERR, &is_err);
break;
case USE_TOTP:
options->use_totp = 1;
break;
default:
usage();
exit(EXIT_FAILURE);
Expand All @@ -2493,6 +2505,7 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
{
add_var_to_bitmask(FWKNOP_CLI_ARG_KEY_RIJNDAEL_BASE64, &var_bitmask);
add_var_to_bitmask(FWKNOP_CLI_ARG_KEY_HMAC_BASE64, &var_bitmask);
/* TODO: TOTP?*/
}
else;

Expand Down Expand Up @@ -2657,6 +2670,7 @@ usage(void)
" --time-offset-plus Add time to outgoing SPA packet timestamp.\n"
" --time-offset-minus Subtract time from outgoing SPA packet\n"
" timestamp.\n"
" --totp Use TOTP.\n"
);

return;
Expand Down
39 changes: 39 additions & 0 deletions client/fwknop.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
*/
static int get_keys(fko_ctx_t ctx, fko_cli_options_t *options,
char *key, int *key_len, char *hmac_key, int *hmac_key_len);
static int get_totp(fko_ctx_t ctx, fko_cli_options_t *options,
char *totp);
static void errmsg(const char *msg, const int err);
static int prev_exec(fko_cli_options_t *options, int argc, char **argv);
static int get_save_file(char *args_save_file);
Expand Down Expand Up @@ -390,6 +392,19 @@ main(int argc, char **argv)
key_len = 16;
}

if(options.use_totp)
{
char *temp = malloc(6);
get_totp(ctx, &options, temp);
fko_set_totp(ctx, temp);
temp = NULL;
free(temp);
}
else
{
log_msg(LOG_VERBOSITY_NORMAL, "Not using TOTP");
}

/* Finalize the context data (encrypt and encode the SPA data)
*/
res = fko_spa_data_final(ctx, key, key_len, hmac_key, hmac_key_len);
Expand Down Expand Up @@ -1239,6 +1254,30 @@ get_keys(fko_ctx_t ctx, fko_cli_options_t *options,
return 1;
}

/* Prompt for and receive a TOTP
*/
static int
get_totp(fko_ctx_t ctx, fko_cli_options_t *options,
char *totp)
{
char *key_tmp = NULL;
if (options->use_totp)
{
key_tmp = getpasswd("Enter TOTP: ", options->input_fd);
if(key_tmp == NULL)
{
log_msg(LOG_VERBOSITY_ERROR, "[*] get_totp() error.");
return 0;
}
/* TODO: ensure the length of the input */
memcpy(totp, key_tmp, 6);
}
else
{
log_msg(LOG_VERBOSITY_ERROR, "[-] Could not read TOTP from user.");
}
}

/* Display an FKO error message.
*/
void
Expand Down
8 changes: 8 additions & 0 deletions client/fwknop_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ typedef struct fko_cli_options
char args_save_file[MAX_PATH_LEN];
int no_save_args;
int use_hmac;
int use_totp;
char spa_server_str[MAX_SERVER_STR_LEN]; /* may be a hostname */
char allow_ip_str[MAX_IPV4_STR_LEN];
char spoof_ip_src_str[MAX_IPV4_STR_LEN];
Expand All @@ -112,6 +113,13 @@ typedef struct fko_cli_options
int have_hmac_key;
int have_hmac_base64_key;
int hmac_type;
/* TOTP key is never read from the .fwknoprc file, but this is needed for key generation
*/
char totp_key[MAX_KEY_LEN+1];
char totp_key_base32[MAX_KEY_LEN+1];
int totp_key_len;
int have_totp_key;
int have_base64_totp_key;

/* NAT access
*/
Expand Down
25 changes: 25 additions & 0 deletions common/fko_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,28 @@ append_msg_to_buf(char *buf, size_t buf_size, const char* msg, ...)
return bytes_written;
}

/* Determine if a buffer contains only characters from the base32
* encoding set
*/
int
is_base32(const unsigned char * const buf, const unsigned short int len)
{
unsigned short int i;
int rv = 1;

for(i=0; i<len; i++)
{
/* the last check is a modified version of isdigit() in range 2-7*/
if(!(isupper(buf[i]) || buf[i] == '=' || (buf[i] >= 50 && buf[i] <= 55)))
{
rv = 0;
break;
}
}

return rv;
}

/* Determine if a buffer contains only characters from the base64
* encoding set
*/
Expand Down Expand Up @@ -912,6 +934,7 @@ dump_ctx_to_buffer(fko_ctx_t ctx, char *dump_buf, size_t dump_buf_len)
char *enc_data = NULL;
char *hmac_data = NULL;
char *spa_digest = NULL;
char *totp = NULL;
#if HAVE_LIBGPGME
char *gpg_signer = NULL;
char *gpg_recip = NULL;
Expand Down Expand Up @@ -955,6 +978,7 @@ dump_ctx_to_buffer(fko_ctx_t ctx, char *dump_buf, size_t dump_buf_len)
RETURN_ON_FKO_ERROR(err, fko_get_spa_message(ctx, &spa_message));
RETURN_ON_FKO_ERROR(err, fko_get_spa_nat_access(ctx, &nat_access));
RETURN_ON_FKO_ERROR(err, fko_get_spa_server_auth(ctx, &server_auth));
RETURN_ON_FKO_ERROR(err, fko_get_totp(ctx, &totp));
RETURN_ON_FKO_ERROR(err, fko_get_spa_client_timeout(ctx, &client_timeout));
RETURN_ON_FKO_ERROR(err, fko_get_spa_digest_type(ctx, &digest_type));
RETURN_ON_FKO_ERROR(err, fko_get_spa_hmac_type(ctx, &hmac_type));
Expand Down Expand Up @@ -1012,6 +1036,7 @@ dump_ctx_to_buffer(fko_ctx_t ctx, char *dump_buf, size_t dump_buf_len)
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " Message String: %s\n", spa_message == NULL ? NULL_STRING : spa_message);
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " Nat Access: %s\n", nat_access == NULL ? NULL_STRING : nat_access);
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " Server Auth: %s\n", server_auth == NULL ? NULL_STRING : server_auth);
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " TOTP: %s\n", totp == NULL ? NULL_STRING : totp);
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " Client Timeout: %u\n", client_timeout);
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " Digest Type: %u (%s)\n", digest_type, digest_str);
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " HMAC Type: %u (%s)\n", hmac_type, hmac_type == 0 ? "None" : hmac_str);
Expand Down
1 change: 1 addition & 0 deletions common/fko_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ int is_valid_encoded_msg_len(const int len);
int is_valid_pt_msg_len(const int len);
int is_valid_ipv4_addr(const char * const ip_str, const int len);
int is_valid_hostname(const char * const hostname_str, const int len);
int is_base32(const unsigned char * const buf, const unsigned short int len);
int is_base64(const unsigned char * const buf, const unsigned short int len);
void hex_dump(const unsigned char *data, const int size);
int enc_mode_strtoint(const char *enc_mode_str);
Expand Down
5 changes: 3 additions & 2 deletions lib/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
lib_LTLIBRARIES = libfko.la

libfko_source_files = \
base64.c base64.h cipher_funcs.c cipher_funcs.h digest.c digest.h \
base32.c base32.h base64.c base64.h cipher_funcs.c cipher_funcs.h digest.c digest.h \
fko_client_timeout.c fko_common.h fko_digest.c fko_encode.c \
fko_decode.c fko_encryption.c fko_error.c fko_funcs.c fko_message.c \
fko_message.h fko_nat_access.c fko_rand_value.c fko_server_auth.c \
fko.h fko_limits.h fko_timestamp.c fko_hmac.c hmac.c hmac.h \
fko_user.c fko_user.h md5.c md5.h rijndael.c rijndael.h sha1.c \
sha1.h sha2.c sha2.h sha3.c sha3.h fko_context.h fko_state.h \
gpgme_funcs.c gpgme_funcs.h
gpgme_funcs.c gpgme_funcs.h \
totp.c totp.h

if WANT_C_UNIT_TESTS
noinst_PROGRAMS = fko_utests
Expand Down
Loading