summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2021-03-01 23:25:21 +0100
committerFlorian Dold <florian@dold.me>2021-03-01 23:25:21 +0100
commite29a6603fd830338742d295b426728cfd7c9c4af (patch)
treeca60f138b4a7a9e2765571c197b165ce41e0e009 /src/backend
parentc18d676333c148a3c9fb5eea75089c1cff599c21 (diff)
downloadmerchant-e29a6603fd830338742d295b426728cfd7c9c4af.tar.gz
merchant-e29a6603fd830338742d295b426728cfd7c9c4af.tar.bz2
merchant-e29a6603fd830338742d295b426728cfd7c9c4af.zip
towards updated auth API (tests still missing)
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/Makefile.am2
-rw-r--r--src/backend/taler-merchant-httpd.c23
-rw-r--r--src/backend/taler-merchant-httpd.h5
-rw-r--r--src/backend/taler-merchant-httpd_private-patch-instances-ID.c27
-rw-r--r--src/backend/taler-merchant-httpd_private-post-instances-ID-auth.c162
-rw-r--r--src/backend/taler-merchant-httpd_private-post-instances-ID-auth.h44
-rw-r--r--src/backend/taler-merchant-httpd_private-post-instances.c69
7 files changed, 286 insertions, 46 deletions
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index 4c05db42..3dd126a6 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -66,6 +66,8 @@ taler_merchant_httpd_SOURCES = \
taler-merchant-httpd_private-patch-products-ID.h \
taler-merchant-httpd_private-post-instances.c \
taler-merchant-httpd_private-post-instances.h \
+ taler-merchant-httpd_private-post-instances-ID-auth.c \
+ taler-merchant-httpd_private-post-instances-ID-auth.h \
taler-merchant-httpd_private-post-products.c \
taler-merchant-httpd_private-post-products.h \
taler-merchant-httpd_private-post-products-ID-lock.c \
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
index 7f9f8e3b..0690e621 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -49,6 +49,7 @@
#include "taler-merchant-httpd_private-patch-orders-ID-forget.h"
#include "taler-merchant-httpd_private-patch-products-ID.h"
#include "taler-merchant-httpd_private-post-instances.h"
+#include "taler-merchant-httpd_private-post-instances-ID-auth.h"
#include "taler-merchant-httpd_private-post-orders.h"
#include "taler-merchant-httpd_private-post-orders-ID-refund.h"
#include "taler-merchant-httpd_private-post-products.h"
@@ -1053,6 +1054,14 @@ url_handler (void *cls,
in the code... */
.max_upload = 1024 * 1024 * 8
},
+ /* POST /auth: */
+ {
+ .url_prefix = "/auth",
+ .method = MHD_HTTP_METHOD_POST,
+ .handler = &TMH_private_post_instances_ID_auth,
+ /* Body should be pretty small. */
+ .max_upload = 1024 * 1024,
+ },
/* GET /products: */
{
.url_prefix = "/products",
@@ -1494,8 +1503,8 @@ url_handler (void *cls,
{
/* Override default instance access control */
TMH_compute_auth (default_auth,
- &hc->instance->settings.auth_salt,
- &hc->instance->settings.auth_hash);
+ &hc->instance->auth.auth_salt,
+ &hc->instance->auth.auth_hash);
GNUNET_free (default_auth);
}
}
@@ -1677,8 +1686,8 @@ url_handler (void *cls,
(NULL == default_auth) )
auth_ok = (GNUNET_OK ==
TMH_check_auth (auth,
- &def_instance->settings.auth_salt,
- &def_instance->settings.auth_hash));
+ &def_instance->auth.auth_salt,
+ &def_instance->auth.auth_hash));
/* Only permit 'default' auth if we are either working with
the default instance OR patching/deleting an instance OR have no instance */
if ( (hc->rh->handler != &TMH_private_patch_instances_ID) &&
@@ -1691,8 +1700,8 @@ url_handler (void *cls,
if (NULL != hc->instance)
auth_ok |= (GNUNET_OK ==
TMH_check_auth (auth,
- &hc->instance->settings.auth_salt,
- &hc->instance->settings.auth_hash));
+ &hc->instance->auth.auth_salt,
+ &hc->instance->auth.auth_hash));
if (! auth_ok)
{
if (auth_malformed)
@@ -1777,6 +1786,7 @@ add_instance_cb (void *cls,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const struct TALER_MerchantPrivateKeyP *merchant_priv,
const struct TALER_MERCHANTDB_InstanceSettings *is,
+ const struct TALER_MERCHANTDB_InstanceAuthSettings *ias,
unsigned int accounts_length,
const struct TALER_MERCHANTDB_AccountDetails accounts[])
{
@@ -1786,6 +1796,7 @@ add_instance_cb (void *cls,
GNUNET_assert (NULL != merchant_priv);
mi = GNUNET_new (struct TMH_MerchantInstance);
mi->settings = *is;
+ mi->auth = *ias;
mi->settings.id = GNUNET_strdup (mi->settings.id);
mi->settings.name = GNUNET_strdup (mi->settings.name);
mi->settings.address = json_incref (mi->settings.address);
diff --git a/src/backend/taler-merchant-httpd.h b/src/backend/taler-merchant-httpd.h
index 50badbb1..7cb3c836 100644
--- a/src/backend/taler-merchant-httpd.h
+++ b/src/backend/taler-merchant-httpd.h
@@ -133,6 +133,11 @@ struct TMH_MerchantInstance
struct TALER_MERCHANTDB_InstanceSettings settings;
/**
+ * General settings for an instance.
+ */
+ struct TALER_MERCHANTDB_InstanceAuthSettings auth;
+
+ /**
* Reference counter on this structure. Only destroyed if the
* counter hits zero.
*/
diff --git a/src/backend/taler-merchant-httpd_private-patch-instances-ID.c b/src/backend/taler-merchant-httpd_private-patch-instances-ID.c
index 637ded04..edda6228 100644
--- a/src/backend/taler-merchant-httpd_private-patch-instances-ID.c
+++ b/src/backend/taler-merchant-httpd_private-patch-instances-ID.c
@@ -63,14 +63,10 @@ TMH_private_patch_instances_ID (const struct TMH_RequestHandler *rh,
struct TMH_MerchantInstance *mi = hc->instance;
struct TALER_MERCHANTDB_InstanceSettings is;
json_t *payto_uris;
- const char *auth_token = NULL;
const char *name;
struct TMH_WireMethod *wm_head = NULL;
struct TMH_WireMethod *wm_tail = NULL;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_string ("auth_token",
- &auth_token)),
GNUNET_JSON_spec_json ("payto_uris",
&payto_uris),
GNUNET_JSON_spec_string ("name",
@@ -149,14 +145,6 @@ TMH_private_patch_instances_ID (const struct TMH_RequestHandler *rh,
/* Check for equality of settings */
if (! ( (0 == strcmp (mi->settings.name,
name)) &&
- ( ( (NULL != auth_token) &&
- (GNUNET_OK ==
- TMH_check_auth (auth_token,
- &mi->settings.auth_salt,
- &mi->settings.auth_hash)) ) ||
- ( (NULL == auth_token) &&
- (GNUNET_YES ==
- GNUNET_is_zero (&mi->settings.auth_hash))) ) &&
(1 == json_equal (mi->settings.address,
is.address)) &&
(1 == json_equal (mi->settings.jurisdiction,
@@ -404,21 +392,6 @@ giveup:
json_decref (mi->settings.address);
json_decref (mi->settings.jurisdiction);
is.id = mi->settings.id;
- if (NULL == auth_token)
- {
- memset (&is.auth_salt,
- 0,
- sizeof (is.auth_salt));
- memset (&is.auth_hash,
- 0,
- sizeof (is.auth_hash));
- }
- else
- {
- TMH_compute_auth (auth_token,
- &is.auth_salt,
- &is.auth_hash);
- }
mi->settings = is;
mi->settings.address = json_incref (mi->settings.address);
mi->settings.jurisdiction = json_incref (mi->settings.jurisdiction);
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
new file mode 100644
index 00000000..8d8df93f
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-post-instances-ID-auth.c
@@ -0,0 +1,162 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems SA
+
+ GNU Taler is free software; you can redistribute it and/or modify
+ it under the 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.
+
+ GNU Taler is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with TALER; see the file COPYING. If not,
+ see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file taler-merchant-httpd_private-post-instances-ID-auth.c
+ * @brief implementing POST /instances/$ID/auth request handling
+ * @author Christian Grothoff
+ * @author Florian Dold
+ */
+#include "platform.h"
+#include "taler-merchant-httpd_private-post-instances-ID-auth.h"
+#include <taler/taler_json_lib.h>
+
+
+/**
+ * How often do we retry the simple INSERT database transaction?
+ */
+#define MAX_RETRIES 3
+
+
+/**
+ * Change the authentication settings of an instance.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] hc context with further information about the request
+ * @return MHD result code
+ */
+MHD_RESULT
+TMH_private_post_instances_ID_auth (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc)
+{
+ struct TALER_MERCHANTDB_InstanceAuthSettings ias;
+ const char *auth_token = NULL;
+ struct TMH_MerchantInstance *mi = hc->instance;
+ json_t *jauth = hc->request_body;
+
+ {
+ bool auth_ok = false;
+ const char *auth_method = json_string_value (json_object_get (jauth,
+ "method"));
+
+ 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)))
+ GNUNET_break_op (0);
+ else
+ 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");
+ }
+ }
+
+ if (NULL == auth_token)
+ {
+ memset (&ias.auth_salt,
+ 0,
+ sizeof (ias.auth_salt));
+ memset (&ias.auth_hash,
+ 0,
+ sizeof (ias.auth_hash));
+ }
+ else
+ {
+ TMH_compute_auth (auth_token,
+ &ias.auth_salt,
+ &ias.auth_hash);
+ }
+
+ {
+ enum GNUNET_DB_QueryStatus qs;
+
+ for (unsigned int i = 0; i<MAX_RETRIES; i++)
+ {
+ if (GNUNET_OK !=
+ TMH_db->start (TMH_db->cls,
+ "post /instances/$ID/auth"))
+ {
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_START_FAILED,
+ NULL);
+ }
+ qs = TMH_db->update_instance_auth (TMH_db->cls,
+ mi->settings.id,
+ &ias);
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+ {
+ 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);
+ goto retry;
+ }
+ qs = TMH_db->commit (TMH_db->cls);
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+retry:
+ if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+ break; /* success! -- or hard failure */
+ } /* for .. MAX_RETRIES */
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+ {
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_COMMIT_FAILED,
+ NULL);
+ }
+ /* Finally, also update our running process */
+ mi->auth = ias;
+ }
+ return TALER_MHD_reply_static (connection,
+ MHD_HTTP_NO_CONTENT,
+ NULL,
+ NULL,
+ 0);
+}
+
+/* end of taler-merchant-httpd_private-post-instances-ID-auth.c */
diff --git a/src/backend/taler-merchant-httpd_private-post-instances-ID-auth.h b/src/backend/taler-merchant-httpd_private-post-instances-ID-auth.h
new file mode 100644
index 00000000..3a47c42c
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-post-instances-ID-auth.h
@@ -0,0 +1,44 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems SA
+
+ GNU Taler is free software; you can redistribute it and/or modify
+ it under the 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.
+
+ GNU Taler is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with TALER; see the file COPYING. If not,
+ see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file taler-merchant-httpd_private-post-instances-ID-auth.h
+ * @brief implements POST /instances/$ID/auth request handling
+ * @author Christian Grothoff
+ * @author Florian Dold
+ */
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_POST_INSTANCES_ID_AUTH_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_POST_INSTANCES_ID_AUTH_H
+#include "taler-merchant-httpd.h"
+
+
+/**
+ * Change the instance's auth settings.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] hc context with further information about the request
+ * @return MHD result code
+ */
+MHD_RESULT
+TMH_private_post_instances_ID_auth (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc);
+
+#endif
diff --git a/src/backend/taler-merchant-httpd_private-post-instances.c b/src/backend/taler-merchant-httpd_private-post-instances.c
index c4d1d617..88a51a26 100644
--- a/src/backend/taler-merchant-httpd_private-post-instances.c
+++ b/src/backend/taler-merchant-httpd_private-post-instances.c
@@ -141,14 +141,15 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
struct TMH_HandlerContext *hc)
{
struct TALER_MERCHANTDB_InstanceSettings is;
+ struct TALER_MERCHANTDB_InstanceAuthSettings ias;
json_t *payto_uris;
const char *auth_token = NULL;
struct TMH_WireMethod *wm_head = NULL;
struct TMH_WireMethod *wm_tail = NULL;
+ json_t *jauth;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_string ("auth_token",
- &auth_token)),
+ GNUNET_JSON_spec_json ("auth",
+ &jauth),
GNUNET_JSON_spec_json ("payto_uris",
&payto_uris),
GNUNET_JSON_spec_string ("id",
@@ -184,6 +185,47 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
: MHD_NO;
}
+
+ {
+ bool auth_ok = false;
+ const char *auth_method = json_string_value (json_object_get (jauth,
+ "method"));
+
+ 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)))
+ GNUNET_break_op (0);
+ else
+ auth_ok = true;
+ }
+ else
+ GNUNET_break_op (0);
+ }
+
+ if (! auth_ok)
+ {
+ 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");
+ }
+ }
+
+
if ((0 != strcasecmp (is.default_max_deposit_fee.currency,
TMH_currency)) ||
(0 != strcasecmp (is.default_max_wire_fee.currency,
@@ -212,11 +254,11 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
( ( (NULL != auth_token) &&
(GNUNET_OK ==
TMH_check_auth (auth_token,
- &mi->settings.auth_salt,
- &mi->settings.auth_hash)) ) ||
+ &mi->auth.auth_salt,
+ &mi->auth.auth_hash)) ) ||
( (NULL == auth_token) &&
(GNUNET_YES ==
- GNUNET_is_zero (&mi->settings.auth_hash))) ) &&
+ GNUNET_is_zero (&mi->auth.auth_hash))) ) &&
(1 == json_equal (mi->settings.address,
is.address)) &&
(1 == json_equal (mi->settings.jurisdiction,
@@ -357,18 +399,18 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
if (NULL == auth_token)
{
- memset (&is.auth_salt,
+ memset (&ias.auth_salt,
0,
- sizeof (is.auth_salt));
- memset (&is.auth_hash,
+ sizeof (ias.auth_salt));
+ memset (&ias.auth_hash,
0,
- sizeof (is.auth_hash));
+ sizeof (ias.auth_hash));
}
else
{
TMH_compute_auth (auth_token,
- &is.auth_salt,
- &is.auth_hash);
+ &ias.auth_salt,
+ &ias.auth_hash);
}
{
struct TMH_MerchantInstance *mi;
@@ -402,7 +444,8 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
qs = TMH_db->insert_instance (TMH_db->cls,
&mi->merchant_pub,
&mi->merchant_priv,
- &mi->settings);
+ &mi->settings,
+ &mi->auth);
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);