From 1e257c787a4344f242fd941dbfcdb957c7be4ba0 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 20 Jul 2021 20:52:58 +0200 Subject: instance auth: refactor, make it serializable --- ...merchant-httpd_private-post-instances-ID-auth.c | 114 +++++++++++++-------- 1 file changed, 70 insertions(+), 44 deletions(-) (limited to 'src/backend/taler-merchant-httpd_private-post-instances-ID-auth.c') 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 @@ -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, -- cgit v1.2.3