[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-anastasis] branch master updated: fix #6532
From: |
gnunet |
Subject: |
[taler-anastasis] branch master updated: fix #6532 |
Date: |
Sun, 14 Feb 2021 23:53:51 +0100 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository anastasis.
The following commit(s) were added to refs/heads/master by this push:
new 5c251da fix #6532
5c251da is described below
commit 5c251da3b088c75d3ff16192bb9d24175a94798e
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sun Feb 14 23:53:49 2021 +0100
fix #6532
---
contrib/gana | 2 +-
src/authorization/Makefile.am | 21 +-
.../anastasis_authorization_plugin_email.c | 375 +++++++++++++++++----
.../anastasis_authorization_plugin_sms.c | 15 +-
src/include/anastasis_redux.h | 8 +-
5 files changed, 331 insertions(+), 90 deletions(-)
diff --git a/contrib/gana b/contrib/gana
index 95a0e41..30748ad 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit 95a0e418f0b6801e09f2251a4e777ed8906e0f56
+Subproject commit 30748ada3fa0b5d5281dca87b117e774db62a431
diff --git a/src/authorization/Makefile.am b/src/authorization/Makefile.am
index 719258c..b1af53d 100644
--- a/src/authorization/Makefile.am
+++ b/src/authorization/Makefile.am
@@ -21,6 +21,7 @@ libanastasisauthorization_la_LDFLAGS = \
-lgnunetutil
plugin_LTLIBRARIES = \
+ libanastasis_plugin_authorization_email.la \
libanastasis_plugin_authorization_file.la \
libanastasis_plugin_authorization_sms.la
libanastasis_plugin_authorization_file_la_SOURCES = \
@@ -34,16 +35,16 @@ libanastasis_plugin_authorization_file_la_LDFLAGS = \
-lgnunetutil \
$(XLIB)
-#libanastasis_plugin_authorization_email_la_SOURCES = \
-# anastasis_authorization_plugin_email.c
-#libanastasis_plugin_authorization_email_la_LIBADD = \
-# $(LTLIBINTL)
-#libanastasis_plugin_authorization_email_la_LDFLAGS = \
-# $(ANASTASIS_PLUGIN_LDFLAGS) \
-# -ljansson \
-# -ltalerutil \
-# -lgnunetutil \
-# $(XLIB)
+libanastasis_plugin_authorization_email_la_SOURCES = \
+ anastasis_authorization_plugin_email.c
+libanastasis_plugin_authorization_email_la_LIBADD = \
+ $(LTLIBINTL)
+libanastasis_plugin_authorization_email_la_LDFLAGS = \
+ $(ANASTASIS_PLUGIN_LDFLAGS) \
+ -ljansson \
+ -ltalerutil \
+ -lgnunetutil \
+ $(XLIB)
libanastasis_plugin_authorization_sms_la_SOURCES = \
anastasis_authorization_plugin_sms.c
diff --git a/src/authorization/anastasis_authorization_plugin_email.c
b/src/authorization/anastasis_authorization_plugin_email.c
index 574fd7f..0f50557 100644
--- a/src/authorization/anastasis_authorization_plugin_email.c
+++ b/src/authorization/anastasis_authorization_plugin_email.c
@@ -19,13 +19,32 @@
* @author Dominik Meister
*/
#include "platform.h"
-#include "anastasis-httpd.h"
#include "anastasis_authorization_plugin.h"
#include <taler/taler_mhd_lib.h>
#include <regex.h>
#include "anastasis_util_lib.h"
+/**
+ * Saves the State of a authorization plugin.
+ */
+struct Email_Context
+{
+
+ /**
+ * Command which is executed to run the plugin (some bash script or a
+ * command line argument)
+ */
+ char *auth_command;
+
+ /**
+ * Regex for email address validation.
+ */
+ regex_t regex;
+
+};
+
+
/**
* Saves the state of a authorization process
*/
@@ -34,27 +53,69 @@ struct ANASTASIS_AUTHORIZATION_State
/**
* Public key of the challenge which is authorised
*/
- const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_public_key;
+ struct ANASTASIS_CRYPTO_TruthUUIDP truth_uuid;
/**
- * Code which is sent to the user (here saved into a file)
+ * Code which is sent to the user.
*/
uint64_t code;
+ /**
+ * Our plugin context.
+ */
+ struct Email_Context *ctx;
+
+ /**
+ * Function to call when we made progress.
+ */
+ GNUNET_SCHEDULER_TaskCallback trigger;
+
+ /**
+ * Closure for @e trigger.
+ */
+ void *trigger_cls;
+
/**
* holds the truth information
*/
char *email;
/**
- * closure
+ * Handle to the helper process.
*/
- void *cls;
+ struct GNUNET_OS_Process *child;
/**
- * Command which is executed to run the email authentication
+ * Handle to wait for @e child
*/
- char *auth_command;
+ struct ANASTASIS_ChildWaitHandle *cwh;
+
+ /**
+ * Our client connection, set if suspended.
+ */
+ struct MHD_Connection *connection;
+
+ /**
+ * Message to send.
+ */
+ char *msg;
+
+ /**
+ * Offset of transmission in msg.
+ */
+ size_t msg_off;
+
+ /**
+ * Exit code from helper.
+ */
+ long unsigned int exit_code;
+
+ /**
+ * How did the helper die?
+ */
+ enum GNUNET_OS_ProcessStatusType pst;
+
+
};
@@ -82,37 +143,28 @@ email_validate (void *cls,
const char *data,
size_t data_length)
{
- regex_t regex;
+ struct Email_Context *ctx = cls;
int regex_result;
- /*FIXME very basic check */
- const char *regexp = "[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}";
- char *email = GNUNET_STRINGS_data_to_string_alloc (data,
- data_length);
-
- regex_result = regcomp (®ex,
- regexp,
- REG_EXTENDED);
- if (0 < regex_result)
- {
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to compile regular expression.");
- regfree (®ex);
- return GNUNET_NO;
- }
+ char *phone_number;
- regex_result = regexec (®ex,
- email,
+ phone_number = GNUNET_strndup (data,
+ data_length);
+ regex_result = regexec (&ctx->regex,
+ phone_number,
0,
NULL,
0);
+ GNUNET_free (phone_number);
if (0 != regex_result)
{
- regfree (®ex);
+ if (MHD_NO ==
+ TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_EXPECTATION_FAILED,
+ TALER_EC_ANASTASIS_EMAIL_INVALID,
+ NULL))
+ return GNUNET_SYSERR;
return GNUNET_NO;
}
- regfree (®ex);
- GNUNET_free (email);
return GNUNET_OK;
}
@@ -122,7 +174,9 @@ email_validate (void *cls,
* I.e. start to send SMS or e-mail or launch video identification.
*
* @param cls closure
- * @param truth_public_key Identifier of the challenge, to be (if possible)
included in the
+ * @param trigger function to call when we made progress
+ * @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 secret code that the user has to provide back to satisfy the
challenge in
* the main anastasis protocol
@@ -131,25 +185,51 @@ email_validate (void *cls,
*/
static struct ANASTASIS_AUTHORIZATION_State *
email_start (void *cls,
- const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_public_key,
+ GNUNET_SCHEDULER_TaskCallback trigger,
+ void *trigger_cls,
+ const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid,
uint64_t code,
- char *auth_command,
const void *data,
size_t data_length)
{
+ struct Email_Context *ctx = cls;
struct ANASTASIS_AUTHORIZATION_State *as;
as = GNUNET_new (struct ANASTASIS_AUTHORIZATION_State);
- as->cls = cls;
- as->truth_public_key = truth_public_key;
+ as->trigger = trigger;
+ as->trigger_cls = trigger_cls;
+ as->ctx = ctx;
+ as->truth_uuid = *truth_uuid;
as->code = code;
- as->auth_command = auth_command;
- as->email = GNUNET_STRINGS_data_to_string_alloc (data,
- data_length);
+ as->email = GNUNET_strndup (data,
+ data_length);
return as;
}
+/**
+ * Function called when our Email helper has terminated.
+ *
+ * @param cls our `struct ANASTASIS_AUHTORIZATION_State`
+ * @param type type of the process
+ * @param exit_code status code of the process
+ */
+static void
+email_done_cb (void *cls,
+ enum GNUNET_OS_ProcessStatusType type,
+ long unsigned int exit_code)
+{
+ struct ANASTASIS_AUTHORIZATION_State *as = cls;
+
+ as->child = NULL;
+ as->cwh = NULL;
+ as->pst = type;
+ as->exit_code = exit_code;
+ MHD_resume_connection (as->connection);
+ as->trigger (as->trigger_cls);
+}
+
+
/**
* Begin issuing authentication challenge to user based on @a data.
* I.e. start to send SMS or e-mail or launch video identification.
@@ -163,44 +243,154 @@ email_process (struct ANASTASIS_AUTHORIZATION_State *as,
struct MHD_Connection *connection)
{
MHD_RESULT mres;
- struct MHD_Response *resp;
- char *subject = "Anastasis E-Mail Authentication Service";
- int p[2];
- /*FIXME ERROR HANDLING*/
- int ret = pipe (p);
-
- pid_t pid = fork ();
- switch (pid)
+
+ if (NULL == as->msg)
{
- case -1:
- close (p[0]);
- close (p[1]);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Error while trying to send email");
- resp = TALER_MHD_make_error (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
- "Failed to fork process");
- mres = MHD_queue_response (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- resp);
- MHD_destroy_response (resp);
+ /* First time, start child process and feed pipe */
+ struct GNUNET_DISK_PipeHandle *p;
+ struct GNUNET_DISK_FileHandle *pipe_stdin;
+
+ p = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
+ if (NULL == p)
+ {
+ mres = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+
TALER_EC_ANASTASIS_EMAIL_HELPER_EXEC_FAILED,
+ "pipe");
+ if (MHD_YES != mres)
+ return ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED;
+ return ANASTASIS_AUTHORIZATION_RES_FAILED;
+ }
+ as->child = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ERR,
+ p,
+ NULL,
+ NULL,
+ as->ctx->auth_command,
+ as->ctx->auth_command,
+ as->email,
+ NULL);
+ if (NULL == as->child)
+ {
+ GNUNET_DISK_pipe_close (p);
+ mres = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+
TALER_EC_ANASTASIS_EMAIL_HELPER_EXEC_FAILED,
+ "exec");
+ if (MHD_YES != mres)
+ return ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED;
+ return ANASTASIS_AUTHORIZATION_RES_FAILED;
+ }
+ pipe_stdin = GNUNET_DISK_pipe_detach_end (p,
+ GNUNET_DISK_PIPE_END_WRITE);
+ GNUNET_assert (NULL != pipe_stdin);
+ GNUNET_DISK_pipe_close (p);
+ {
+ char *tpk;
+
+ tpk = GNUNET_STRINGS_data_to_string_alloc (
+ &as->truth_uuid,
+ sizeof (as->truth_uuid));
+ GNUNET_asprintf (&as->msg,
+ "Subject: Anastasis recovery code: #%llu\n\nThis is for
challenge %s.\n",
+ (unsigned long long) as->code,
+ tpk);
+ GNUNET_free (tpk);
+ }
+
+ {
+ const char *off = as->msg;
+ size_t left = strlen (off);
+
+ while (0 != left)
+ {
+ ssize_t ret;
+
+ if (0 == left)
+ break;
+ ret = GNUNET_DISK_file_write (pipe_stdin,
+ off,
+ left);
+ if (ret <= 0)
+ {
+ mres = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+
TALER_EC_ANASTASIS_EMAIL_HELPER_EXEC_FAILED,
+ "write");
+ if (MHD_YES != mres)
+ return ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED;
+ return ANASTASIS_AUTHORIZATION_RES_FAILED;
+ }
+ as->msg_off += ret;
+ off += ret;
+ left -= ret;
+ }
+ GNUNET_DISK_file_close (pipe_stdin);
+ }
+ as->cwh = ANASTASIS_wait_child (as->child,
+ &email_done_cb,
+ as);
+ as->connection = connection;
+ MHD_suspend_connection (connection);
+ return ANASTASIS_AUTHORIZATION_RES_SUSPENDED;
+ }
+ if (NULL != as->cwh)
+ {
+ /* Spurious call, why are we here? */
+ GNUNET_break (0);
+ MHD_suspend_connection (connection);
+ return ANASTASIS_AUTHORIZATION_RES_SUSPENDED;
+ }
+ if ( (GNUNET_OS_PROCESS_EXITED != as->pst) ||
+ (0 != as->exit_code) )
+ {
+ char es[32];
+
+ GNUNET_snprintf (es,
+ sizeof (es),
+ "%u/%d",
+ (unsigned int) as->exit_code,
+ as->pst);
+ mres = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+
TALER_EC_ANASTASIS_EMAIL_HELPER_COMMAND_FAILED,
+ es);
if (MHD_YES != mres)
return ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED;
return ANASTASIS_AUTHORIZATION_RES_FAILED;
- case 0:
- dup2 (p[0],0);
- close (p[1]);
- execlp (as->auth_command, subject, as->email, NULL);
- close (p[0]);
- char buff[21];
- sprintf (buff, "%lu", as->code);
- ret = write (p[1], buff, strlen (buff));
- close (p[1]);
-
- break;
- default:
- /*FIXME */
- break;
}
+
+ /* Build HTTP response */
+ {
+ struct MHD_Response *resp;
+ size_t reply_len;
+ char *reply;
+ const char *at;
+ size_t len;
+
+ /* FIXME: i18n based on language preferences of the client */
+ /* FIXME: Reply in JSON if requested by client */
+ at = strchr (as->email, '@');
+ if (NULL == at)
+ len = 0;
+ else
+ len = at - as->email;
+ reply_len = GNUNET_asprintf (&reply,
+ "Recovery TAN send to email %.*s@DOMAIN",
+ (unsigned int) len,
+ as->email);
+ resp = MHD_create_response_from_buffer (reply_len,
+ reply,
+ MHD_RESPMEM_MUST_COPY);
+ GNUNET_free (reply);
+ TALER_MHD_add_global_headers (resp);
+ mres = MHD_queue_response (connection,
+ MHD_HTTP_FORBIDDEN,
+ resp);
+ MHD_destroy_response (resp);
+ }
+
+ if (MHD_YES != mres)
+ return ANASTASIS_AUTHORIZATION_RES_SUCCESS_REPLY_FAILED;
return ANASTASIS_AUTHORIZATION_RES_SUCCESS;
}
@@ -213,6 +403,20 @@ email_process (struct ANASTASIS_AUTHORIZATION_State *as,
static void
email_cleanup (struct ANASTASIS_AUTHORIZATION_State *as)
{
+ if (NULL != as->cwh)
+ {
+ ANASTASIS_wait_child_cancel (as->cwh);
+ as->cwh = NULL;
+ }
+ if (NULL != as->child)
+ {
+ (void) GNUNET_OS_process_kill (as->child,
+ SIGKILL);
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_OS_process_wait (as->child));
+ as->child = NULL;
+ }
+ GNUNET_free (as->msg);
GNUNET_free (as->email);
GNUNET_free (as);
}
@@ -229,7 +433,29 @@ libanastasis_plugin_authorization_email_init (void *cls)
{
struct ANASTASIS_AuthorizationPlugin *plugin;
struct GNUNET_CONFIGURATION_Handle *cfg = cls;
+ struct Email_Context *ctx;
+
+ ctx = GNUNET_new (struct Email_Context);
+ {
+ int regex_result;
+ const char *regexp = "[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}";
+
+ regex_result = regcomp (&ctx->regex,
+ regexp,
+ REG_EXTENDED);
+ if (0 < regex_result)
+ {
+ GNUNET_break (0);
+ GNUNET_free (ctx);
+ return NULL;
+ }
+ }
+
plugin = GNUNET_new (struct ANASTASIS_AuthorizationPlugin);
+ plugin->code_validity_period = GNUNET_TIME_UNIT_DAYS;
+ plugin->code_rotation_period = GNUNET_TIME_UNIT_HOURS;
+ plugin->code_retransmission_frequency = GNUNET_TIME_UNIT_MINUTES;
+ plugin->cls = ctx;
plugin->validate = &email_validate;
plugin->start = &email_start;
plugin->process = &email_process;
@@ -239,11 +465,13 @@ libanastasis_plugin_authorization_email_init (void *cls)
GNUNET_CONFIGURATION_get_value_string (cfg,
"authorization-email",
"COMMAND",
- &plugin->auth_command))
+ &ctx->auth_command))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"authorization-email",
"COMMAND");
+ regfree (&ctx->regex);
+ GNUNET_free (ctx);
GNUNET_free (plugin);
return NULL;
}
@@ -261,6 +489,11 @@ void *
libanastasis_plugin_authorization_email_done (void *cls)
{
struct ANASTASIS_AuthorizationPlugin *plugin = cls;
+ struct Email_Context *ctx = plugin->cls;
+
+ GNUNET_free (ctx->auth_command);
+ regfree (&ctx->regex);
+ GNUNET_free (ctx);
GNUNET_free (plugin);
return NULL;
}
diff --git a/src/authorization/anastasis_authorization_plugin_sms.c
b/src/authorization/anastasis_authorization_plugin_sms.c
index a2075fd..0dbdf89 100644
--- a/src/authorization/anastasis_authorization_plugin_sms.c
+++ b/src/authorization/anastasis_authorization_plugin_sms.c
@@ -26,7 +26,7 @@
/**
- * Saves the State of a authorization process
+ * Saves the State of a authorization plugin.
*/
struct SMS_Context
{
@@ -53,7 +53,7 @@ struct ANASTASIS_AUTHORIZATION_State
/**
* Public key of the challenge which is authorised
*/
- struct ANASTASIS_CRYPTO_TruthUUIDP truth_public_key;
+ struct ANASTASIS_CRYPTO_TruthUUIDP truth_uuid;
/**
* Code which is sent to the user (here sent via SMS)
@@ -175,7 +175,7 @@ sms_validate (void *cls,
* @param cls closure with a `struct SMS_Context`
* @param trigger function to call when we made progress
* @param trigger_cls closure for @a trigger
- * @param truth_public_key Identifier of the challenge, to be (if possible)
included in the
+ * @param truth_uuid Identifier of the challenge, to be (if possible) included
in the
* interaction with the user
* @param code secret code that the user has to provide back to satisfy the
challenge in
* the main anastasis protocol
@@ -186,7 +186,7 @@ static struct ANASTASIS_AUTHORIZATION_State *
sms_start (void *cls,
GNUNET_SCHEDULER_TaskCallback trigger,
void *trigger_cls,
- const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_public_key,
+ const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid,
uint64_t code,
const void *data,
size_t data_length)
@@ -198,7 +198,7 @@ sms_start (void *cls,
as->trigger = trigger;
as->trigger_cls = trigger_cls;
as->ctx = ctx;
- as->truth_public_key = *truth_public_key;
+ as->truth_uuid = *truth_uuid;
as->code = code;
as->phone_number = GNUNET_strndup (data,
data_length);
@@ -287,8 +287,8 @@ sms_process (struct ANASTASIS_AUTHORIZATION_State *as,
char *tpk;
tpk = GNUNET_STRINGS_data_to_string_alloc (
- &as->truth_public_key,
- sizeof (as->truth_public_key));
+ &as->truth_uuid,
+ sizeof (as->truth_uuid));
GNUNET_asprintf (&as->msg,
"#%llu\nAnastasis\n%s",
(unsigned long long) as->code,
@@ -467,6 +467,7 @@ libanastasis_plugin_authorization_sms_init (void *cls)
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"authorization-sms",
"SMSAUTH_COMMAND");
+ regfree (&ctx->regex);
GNUNET_free (ctx);
GNUNET_free (plugin);
return NULL;
diff --git a/src/include/anastasis_redux.h b/src/include/anastasis_redux.h
index c43cb84..c8241da 100644
--- a/src/include/anastasis_redux.h
+++ b/src/include/anastasis_redux.h
@@ -118,6 +118,7 @@ ANASTASIS_generic_state_to_string (enum
ANASTASIS_GenericState gs);
enum ANASTASIS_BackupState
ANASTASIS_backup_state_from_string (const char *state_string);
+
/**
* Returns the string value of a state.
*
@@ -137,6 +138,7 @@ ANASTASIS_backup_state_to_string (enum
ANASTASIS_BackupState bs);
enum ANASTASIS_RecoveryState
ANASTASIS_recovery_state_from_string (const char *state_string);
+
/**
* Returns the string value of a state.
*
@@ -181,7 +183,6 @@ ANASTASIS_recovery_start (const struct
GNUNET_CONFIGURATION_Handle *cfg);
* @param cls closure
* @param error error code, #TALER_EC_NONE if @a new_bs is the new successful
state
* @param new_state the new state of the operation (client should
json_incref() to keep an alias)
- * @param error error code
*/
typedef void
(*ANASTASIS_ActionCallback)(
@@ -196,6 +197,11 @@ typedef void
struct ANASTASIS_ReduxAction;
+/**
+ * Cancel ongoing redux action.
+ *
+ * @param ra action to cancel
+ */
void
ANASTASIS_redux_action_cancel (struct ANASTASIS_ReduxAction *ra);
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-anastasis] branch master updated: fix #6532,
gnunet <=