summaryrefslogtreecommitdiff
path: root/src/authorization/anastasis_authorization_plugin_totp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/authorization/anastasis_authorization_plugin_totp.c')
-rw-r--r--src/authorization/anastasis_authorization_plugin_totp.c87
1 files changed, 46 insertions, 41 deletions
diff --git a/src/authorization/anastasis_authorization_plugin_totp.c b/src/authorization/anastasis_authorization_plugin_totp.c
index 6fcdd39..c127e38 100644
--- a/src/authorization/anastasis_authorization_plugin_totp.c
+++ b/src/authorization/anastasis_authorization_plugin_totp.c
@@ -3,7 +3,7 @@
Copyright (C) 2021 Anastasis SARL
Anastasis is free software; you can redistribute it and/or modify it under the
- terms of the GNU Lesser General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -59,14 +59,14 @@ struct ANASTASIS_AUTHORIZATION_State
struct ANASTASIS_CRYPTO_TruthUUIDP truth_uuid;
/**
- * Our context.
+ * Was the challenge satisfied?
*/
- const struct ANASTASIS_AuthorizationContext *ac;
+ struct GNUNET_HashCode valid_replies[TIME_INTERVAL_RANGE * 2 + 1];
/**
- * Was the challenge satisfied?
+ * Our context.
*/
- bool ok;
+ const struct ANASTASIS_AuthorizationContext *ac;
};
@@ -103,7 +103,7 @@ totp_validate (void *cls,
GNUNET_break_op (0);
if (MHD_NO ==
TALER_MHD_reply_with_error (connection,
- MHD_HTTP_EXPECTATION_FAILED,
+ MHD_HTTP_CONFLICT,
TALER_EC_ANASTASIS_TOTP_KEY_MISSING,
NULL))
return GNUNET_SYSERR;
@@ -114,7 +114,7 @@ totp_validate (void *cls,
GNUNET_break_op (0);
if (MHD_NO ==
TALER_MHD_reply_with_error (connection,
- MHD_HTTP_EXPECTATION_FAILED,
+ MHD_HTTP_CONFLICT,
TALER_EC_ANASTASIS_TOTP_KEY_INVALID,
NULL))
return GNUNET_SYSERR;
@@ -141,7 +141,7 @@ compute_totp (int time_off,
struct GNUNET_TIME_Absolute now;
time_t t;
uint64_t ctr;
- uint8_t hmac[16]; /* SHA1: 16 bytes */
+ uint8_t hmac[20]; /* SHA1: 20 bytes */
now = GNUNET_TIME_absolute_get ();
while (time_off < 0)
@@ -184,21 +184,14 @@ compute_totp (int time_off,
{
uint32_t code = 0;
+ int offset;
+ offset = hmac[sizeof (hmac) - 1] & 0x0f;
for (int count = 0; count < 4; count++)
- code += hmac[(hmac[sizeof (hmac) - 1] & 0x0f) + 3 - count] << 8 * count;
+ code |= ((uint32_t) hmac[offset + 3 - count]) << (8 * count);
code &= 0x7fffffff;
-
-#if VAR_DIGITS
- if (digits == 6)
- code = code % 1000000;
- else if (digits == 7)
- code = code % 10000000;
- else if (digits == 8)
- code = code % 100000000;
-#else
- code = code % 1000000;
-#endif
+ /* always use 8 digits (maximum) */
+ code = code % 100000000;
return code;
}
}
@@ -212,9 +205,9 @@ compute_totp (int time_off,
* @param trigger_cls closure for @a trigger
* @param truth_uuid Identifier of the challenge, to be (if possible) included in the
* interaction with the user
- * @param code set to secret code that the user provided to satisfy the challenge in
- * the main anastasis protocol
- * @param data input to validate (i.e. the shared secret)
+ * @param code always 0 (direct validation, backend does
+ * not generate a code in this mode)
+ * @param data truth for input to validate (i.e. the shared secret)
* @param data_length number of bytes in @a data
* @return state to track progress on the authorization operation, NULL on failure
*/
@@ -230,43 +223,50 @@ totp_start (void *cls,
const struct ANASTASIS_AuthorizationContext *ac = cls;
struct ANASTASIS_AUTHORIZATION_State *as;
uint64_t want;
+ unsigned int off = 0;
+ GNUNET_assert (0 == code);
as = GNUNET_new (struct ANASTASIS_AUTHORIZATION_State);
as->ac = ac;
as->truth_uuid = *truth_uuid;
for (int i = -TIME_INTERVAL_RANGE;
- i < TIME_INTERVAL_RANGE;
+ i <= TIME_INTERVAL_RANGE;
i++)
{
want = compute_totp (i,
data,
data_length);
- if (code == want)
- as->ok = true;
+ ANASTASIS_hash_answer (want,
+ &as->valid_replies[off++]);
}
return as;
}
/**
- * Begin issuing authentication challenge to user based on @a data.
+ * Check authentication response from the user.
*
* @param as authorization state
* @param timeout how long do we have to produce a reply
+ * @param challenge_response hash of the response
* @param connection HTTP client request (for queuing response, such as redirection to video portal)
* @return state of the request
*/
-static enum ANASTASIS_AUTHORIZATION_Result
-totp_process (struct ANASTASIS_AUTHORIZATION_State *as,
- struct GNUNET_TIME_Absolute timeout,
- struct MHD_Connection *connection)
+static enum ANASTASIS_AUTHORIZATION_SolveResult
+totp_solve (struct ANASTASIS_AUTHORIZATION_State *as,
+ struct GNUNET_TIME_Absolute timeout,
+ const struct GNUNET_HashCode *challenge_response,
+ struct MHD_Connection *connection)
{
MHD_RESULT mres;
const char *mime;
const char *lang;
- if (as->ok)
- return ANASTASIS_AUTHORIZATION_RES_FINISHED;
+ for (unsigned int i = 0; i<=TIME_INTERVAL_RANGE * 2; i++)
+ if (0 ==
+ GNUNET_memcmp (challenge_response,
+ &as->valid_replies[i]))
+ return ANASTASIS_AUTHORIZATION_SRES_FINISHED;
mime = MHD_lookup_connection_value (connection,
MHD_HEADER_KIND,
MHD_HTTP_HEADER_ACCEPT);
@@ -281,15 +281,20 @@ totp_process (struct ANASTASIS_AUTHORIZATION_State *as,
/* Build HTTP response */
{
struct MHD_Response *resp;
- struct GNUNET_TIME_Absolute now;
+ struct GNUNET_TIME_Timestamp now;
- now = GNUNET_TIME_absolute_get ();
+ now = GNUNET_TIME_timestamp_get ();
if (TALER_MHD_xmime_matches (mime,
"application/json"))
{
resp = TALER_MHD_MAKE_JSON_PACK (
- GNUNET_JSON_pack_time_abs ("server_time",
- now));
+ GNUNET_JSON_pack_uint64 ("code",
+ TALER_EC_ANASTASIS_TRUTH_CHALLENGE_FAILED),
+ GNUNET_JSON_pack_string ("hint",
+ TALER_ErrorCode_get_hint (
+ TALER_EC_ANASTASIS_TRUTH_CHALLENGE_FAILED)),
+ GNUNET_JSON_pack_timestamp ("server_time",
+ now));
}
else
{
@@ -300,7 +305,7 @@ totp_process (struct ANASTASIS_AUTHORIZATION_State *as,
response_size
= GNUNET_asprintf (&response,
"Server time: %s",
- GNUNET_STRINGS_absolute_time_to_string (now));
+ GNUNET_TIME_timestamp2s (now));
resp = MHD_create_response_from_buffer (response_size,
response,
MHD_RESPMEM_MUST_COPY);
@@ -316,8 +321,8 @@ totp_process (struct ANASTASIS_AUTHORIZATION_State *as,
MHD_destroy_response (resp);
}
if (MHD_YES != mres)
- return ANASTASIS_AUTHORIZATION_RES_SUCCESS_REPLY_FAILED;
- return ANASTASIS_AUTHORIZATION_RES_SUCCESS;
+ return ANASTASIS_AUTHORIZATION_SRES_FAILED_REPLY_FAILED;
+ return ANASTASIS_AUTHORIZATION_SRES_FAILED;
}
@@ -354,7 +359,7 @@ libanastasis_plugin_authorization_totp_init (void *cls)
plugin->code_retransmission_frequency = plugin->code_validity_period;
plugin->validate = &totp_validate;
plugin->start = &totp_start;
- plugin->process = &totp_process;
+ plugin->solve = &totp_solve;
plugin->cleanup = &totp_cleanup;
return plugin;
}