[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-merchant] branch master updated: instance auth: refactor, make it
From: |
gnunet |
Subject: |
[taler-merchant] branch master updated: instance auth: refactor, make it serializable |
Date: |
Tue, 20 Jul 2021 20:53:04 +0200 |
This is an automated email from the git hooks/post-receive script.
dold pushed a commit to branch master
in repository merchant.
The following commit(s) were added to refs/heads/master by this push:
new 1e257c78 instance auth: refactor, make it serializable
1e257c78 is described below
commit 1e257c787a4344f242fd941dbfcdb957c7be4ba0
Author: Florian Dold <florian@dold.me>
AuthorDate: Tue Jul 20 20:52:58 2021 +0200
instance auth: refactor, make it serializable
---
contrib/merchant-backoffice | 2 +-
src/backend/taler-merchant-httpd.c | 1 +
src/backend/taler-merchant-httpd.h | 9 ++
src/backend/taler-merchant-httpd_helper.c | 50 +++++++++
src/backend/taler-merchant-httpd_helper.h | 8 ++
...merchant-httpd_private-post-instances-ID-auth.c | 114 +++++++++++++--------
.../taler-merchant-httpd_private-post-instances.c | 48 ++-------
src/backenddb/plugin_merchantdb_postgres.c | 3 +
8 files changed, 148 insertions(+), 87 deletions(-)
diff --git a/contrib/merchant-backoffice b/contrib/merchant-backoffice
index 1732185a..4320467d 160000
--- a/contrib/merchant-backoffice
+++ b/contrib/merchant-backoffice
@@ -1 +1 @@
-Subproject commit 1732185ac1d1dcc783b8f2489f2ce333b5254d92
+Subproject commit 4320467db1392e5f48a4acd079f7e2a253cf9984
diff --git a/src/backend/taler-merchant-httpd.c
b/src/backend/taler-merchant-httpd.c
index 861b5f47..58f82f35 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -1916,6 +1916,7 @@ url_handler (void *cls,
extract_token (&auth);
if (NULL == auth)
auth_malformed = true;
+ hc->auth_token = auth;
}
/* If we have zero configured instances (not even ones that have been
diff --git a/src/backend/taler-merchant-httpd.h
b/src/backend/taler-merchant-httpd.h
index 29a67acc..03e62d2c 100644
--- a/src/backend/taler-merchant-httpd.h
+++ b/src/backend/taler-merchant-httpd.h
@@ -322,6 +322,15 @@ struct TMH_HandlerContext
*/
const char *url;
+ /**
+ * Client-provided authentication token for this
+ * request, can be NULL.
+ *
+ * Used to check for concurrent, conflicting updates of
+ * the authentication information in the database.
+ */
+ const char *auth_token;
+
/**
* Infix part of @a url.
*/
diff --git a/src/backend/taler-merchant-httpd_helper.c
b/src/backend/taler-merchant-httpd_helper.c
index 30ff4a90..fb0cf318 100644
--- a/src/backend/taler-merchant-httpd_helper.c
+++ b/src/backend/taler-merchant-httpd_helper.c
@@ -104,3 +104,53 @@ TMH_setup_wire_account (const char *payto_uri)
wm->active = true;
return wm;
}
+
+enum GNUNET_GenericReturnValue
+TMH_check_auth_config (struct MHD_Connection *connection,
+ const json_t *jauth,
+ const char **auth_token)
+{
+ bool auth_wellformed = false;
+ const char *auth_method = json_string_value (json_object_get (jauth,
+ "method"));
+ *auth_token = NULL;
+ if (NULL == auth_method)
+ {
+ GNUNET_break_op (0);
+ }
+ else if (0 == strcmp (auth_method,
+ "external"))
+ {
+ auth_wellformed = true;
+ }
+ else if (0 == strcmp (auth_method,
+ "token"))
+ {
+ *auth_token = json_string_value (json_object_get (jauth,
+ "token"));
+ if (NULL == *auth_token)
+ {
+ GNUNET_break_op (0);
+ }
+ else
+ {
+ if (0 != strncasecmp (RFC_8959_PREFIX,
+ *auth_token,
+ strlen (RFC_8959_PREFIX)))
+ GNUNET_break_op (0);
+ else
+ auth_wellformed = true;
+ }
+ }
+
+ if (! auth_wellformed)
+ {
+ GNUNET_break_op (0);
+ return (MHD_YES ==
+ TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+
TALER_EC_MERCHANT_PRIVATE_POST_INSTANCES_BAD_AUTH,
+ "bad authentication config")) ?
GNUNET_NO : GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
diff --git a/src/backend/taler-merchant-httpd_helper.h
b/src/backend/taler-merchant-httpd_helper.h
index 5f478c18..d15ef2e0 100644
--- a/src/backend/taler-merchant-httpd_helper.h
+++ b/src/backend/taler-merchant-httpd_helper.h
@@ -46,5 +46,13 @@ TMH_payto_uri_array_valid (const json_t *payto_uris);
struct TMH_WireMethod *
TMH_setup_wire_account (const char *payto_uri);
+/**
+ * FIXME: document
+ */
+enum GNUNET_GenericReturnValue
+TMH_check_auth_config (struct MHD_Connection *connection,
+ const json_t *jauth,
+ const char **auth_token);
+
#endif
diff --git a/src/backend/taler-merchant-httpd_private-post-instances-ID-auth.c
b/src/backend/taler-merchant-httpd_private-post-instances-ID-auth.c
index 93b0f784..17316348 100644
--- a/src/backend/taler-merchant-httpd_private-post-instances-ID-auth.c
+++ b/src/backend/taler-merchant-httpd_private-post-instances-ID-auth.c
@@ -25,6 +25,7 @@
*/
#include "platform.h"
#include "taler-merchant-httpd_private-post-instances-ID-auth.h"
+#include "taler-merchant-httpd_helper.h"
#include <taler/taler_json_lib.h>
@@ -52,44 +53,13 @@ post_instances_ID_auth (struct TMH_MerchantInstance *mi,
json_t *jauth = hc->request_body;
{
- bool auth_ok = false;
- const char *auth_method = json_string_value (json_object_get (jauth,
- "method"));
+ enum GNUNET_GenericReturnValue ret;
- if (NULL == auth_method)
- {
- GNUNET_break_op (0);
- }
- else if (0 == strcmp (auth_method,
- "external"))
- {
- auth_token = NULL;
- auth_ok = true;
- }
- else if (0 == strcmp (auth_method,
- "token"))
- {
- auth_token = json_string_value (json_object_get (jauth,
- "token"));
- if (NULL != auth_token)
- {
- if (0 == strncasecmp (RFC_8959_PREFIX,
- auth_token,
- strlen (RFC_8959_PREFIX)))
- auth_ok = true;
- }
- else
- GNUNET_break_op (0);
- }
-
- if (! auth_ok)
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
-
TALER_EC_MERCHANT_PRIVATE_POST_INSTANCE_AUTH_BAD_AUTH,
- "bad authentication config");
- }
+ ret = TMH_check_auth_config (connection,
+ jauth,
+ &auth_token);
+ if (GNUNET_OK != ret)
+ return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
}
if (NULL == auth_token)
@@ -108,6 +78,7 @@ post_instances_ID_auth (struct TMH_MerchantInstance *mi,
&ias.auth_hash);
}
+ /* Store the new auth information in the database */
{
enum GNUNET_DB_QueryStatus qs;
@@ -122,6 +93,55 @@ post_instances_ID_auth (struct TMH_MerchantInstance *mi,
TALER_EC_GENERIC_DB_START_FAILED,
NULL);
}
+
+ /* Make the authentication update a serializable operation.
+ We first check that the authentication information
+ that the caller's request authenticated with
+ is still up to date.
+ Otherwise, we've detected a conflicting update
+ to the authentication. */
+ {
+ struct TALER_MERCHANTDB_InstanceAuthSettings db_ias;
+ qs = TMH_db->lookup_instance_auth (TMH_db->cls,
+ mi->settings.id,
+ &db_ias);
+
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ /* Instance got purged. */
+ TMH_db->rollback (TMH_db->cls);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_UNAUTHORIZED,
+
TALER_EC_GENERIC_DB_COMMIT_FAILED,
+ NULL);
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ TMH_db->rollback (TMH_db->cls);
+ goto retry;
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ TMH_db->rollback (TMH_db->cls);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ NULL);
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ /* Success! */
+ break;
+ }
+
+ if (GNUNET_OK !=
+ TMH_check_auth (hc->auth_token,
+ &db_ias.auth_salt,
+ &db_ias.auth_hash))
+ {
+ TMH_db->rollback (TMH_db->cls);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_UNAUTHORIZED,
+
TALER_EC_MERCHANT_GENERIC_UNAUTHORIZED,
+ NULL);
+ }
+ }
+
qs = TMH_db->update_instance_auth (TMH_db->cls,
mi->settings.id,
&ias);
@@ -129,12 +149,13 @@ post_instances_ID_auth (struct TMH_MerchantInstance *mi,
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
TMH_db->rollback (TMH_db->cls);
- goto retry;
- }
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- TMH_db->rollback (TMH_db->cls);
+ if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+ {
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ NULL);
+ }
goto retry;
}
qs = TMH_db->commit (TMH_db->cls);
@@ -156,7 +177,12 @@ retry:
}
if (0 == strcmp (mi->settings.id,
"default"))
- GNUNET_free (TMH_default_auth); /* clear after it was manually set */
+ {
+ /* The default auth string should've been
+ cleared with the first request
+ for the default instance. */
+ GNUNET_assert (NULL == TMH_default_auth);
+ }
return TALER_MHD_reply_static (connection,
MHD_HTTP_NO_CONTENT,
NULL,
diff --git a/src/backend/taler-merchant-httpd_private-post-instances.c
b/src/backend/taler-merchant-httpd_private-post-instances.c
index 71739c3d..4c5919e9 100644
--- a/src/backend/taler-merchant-httpd_private-post-instances.c
+++ b/src/backend/taler-merchant-httpd_private-post-instances.c
@@ -189,49 +189,13 @@ TMH_private_post_instances (const struct
TMH_RequestHandler *rh,
}
{
- bool auth_wellformed = false;
- const char *auth_method = json_string_value (json_object_get (jauth,
- "method"));
+ enum GNUNET_GenericReturnValue ret;
- if (NULL == auth_method)
- {
- GNUNET_break_op (0);
- }
- else if (0 == strcmp (auth_method,
- "external"))
- {
- auth_token = NULL;
- auth_wellformed = true;
- }
- else if (0 == strcmp (auth_method,
- "token"))
- {
- auth_token = json_string_value (json_object_get (jauth,
- "token"));
- if (NULL == auth_token)
- {
- GNUNET_break_op (0);
- }
- else
- {
- if (0 != strncasecmp (RFC_8959_PREFIX,
- auth_token,
- strlen (RFC_8959_PREFIX)))
- GNUNET_break_op (0);
- else
- auth_wellformed = true;
- }
- }
-
- if (! auth_wellformed)
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
-
TALER_EC_MERCHANT_PRIVATE_POST_INSTANCES_BAD_AUTH,
- "bad authentication config");
- }
+ ret = TMH_check_auth_config (connection,
+ jauth,
+ &auth_token);
+ if (GNUNET_OK != ret)
+ return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
}
/* check payto_uris for well-formedness */
diff --git a/src/backenddb/plugin_merchantdb_postgres.c
b/src/backenddb/plugin_merchantdb_postgres.c
index 2327b16c..86e30d0b 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -3640,6 +3640,7 @@ RETRY:
params);
if (0 > qs)
{
+ /* FIXME: distinguish hard error */
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
postgres_rollback (pg);
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
@@ -3681,6 +3682,7 @@ RETRY:
params);
if (0 > qs)
{
+ /* FIXME: distinguish hard error */
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
postgres_rollback (pg);
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
@@ -3710,6 +3712,7 @@ RETRY:
params);
if (0 > qs)
{
+ /* FIXME: distinguish hard error */
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
postgres_rollback (pg);
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-merchant] branch master updated: instance auth: refactor, make it serializable,
gnunet <=