From e29a6603fd830338742d295b426728cfd7c9c4af Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 1 Mar 2021 23:25:21 +0100 Subject: towards updated auth API (tests still missing) --- src/backend/Makefile.am | 2 + src/backend/taler-merchant-httpd.c | 23 ++- src/backend/taler-merchant-httpd.h | 5 + ...ler-merchant-httpd_private-patch-instances-ID.c | 27 ---- ...merchant-httpd_private-post-instances-ID-auth.c | 162 +++++++++++++++++++++ ...merchant-httpd_private-post-instances-ID-auth.h | 44 ++++++ .../taler-merchant-httpd_private-post-instances.c | 69 +++++++-- src/backenddb/plugin_merchantdb_postgres.c | 64 ++++++-- src/backenddb/test_merchantdb.c | 6 +- src/include/taler_merchantdb_plugin.h | 45 ++++-- src/lib/merchant_api_post_instances.c | 27 +++- src/testing/test_merchant_api.c | 5 +- 12 files changed, 402 insertions(+), 77 deletions(-) create mode 100644 src/backend/taler-merchant-httpd_private-post-instances-ID-auth.c create mode 100644 src/backend/taler-merchant-httpd_private-post-instances-ID-auth.h (limited to 'src') 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 @@ -132,6 +132,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 +*/ + +/** + * @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 + + +/** + * 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; istart (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 +*/ + +/** + * @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); diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c index 616172f1..a1b659db 100644 --- a/src/backenddb/plugin_merchantdb_postgres.c +++ b/src/backenddb/plugin_merchantdb_postgres.c @@ -342,6 +342,11 @@ struct LookupInstancesContext */ struct TALER_MERCHANTDB_InstanceSettings is; + /** + * Instance authentication settings, valid only during find_instances_cb(). + */ + struct TALER_MERCHANTDB_InstanceAuthSettings ias; + /** * Instance serial number, valid only during find_instances_cb(). */ @@ -407,6 +412,7 @@ call_with_accounts (struct LookupInstancesContext *lic, &lic->merchant_pub, (0 == qs) ? NULL : &merchant_priv, &lic->is, + &lic->ias, num_accounts, accounts); } @@ -493,11 +499,11 @@ lookup_instances_cb (void *cls, &lic->merchant_pub), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("auth_hash", - &lic->is.auth_hash), + &lic->ias.auth_hash), &no_auth), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("auth_salt", - &lic->is.auth_salt), + &lic->ias.auth_salt), &no_salt), GNUNET_PQ_result_spec_string ("merchant_id", &lic->is.id), @@ -524,12 +530,12 @@ lookup_instances_cb (void *cls, GNUNET_PQ_query_param_end }; - memset (&lic->is.auth_salt, + memset (&lic->ias.auth_salt, 0, - sizeof (lic->is.auth_salt)); - memset (&lic->is.auth_hash, + sizeof (lic->ias.auth_salt)); + memset (&lic->ias.auth_hash, 0, - sizeof (lic->is.auth_hash)); + sizeof (lic->ias.auth_hash)); if (GNUNET_OK != GNUNET_PQ_extract_result (result, rs, @@ -610,13 +616,14 @@ static enum GNUNET_DB_QueryStatus postgres_insert_instance (void *cls, const struct TALER_MerchantPublicKeyP *merchant_pub, const struct TALER_MerchantPrivateKeyP *merchant_priv, - const struct TALER_MERCHANTDB_InstanceSettings *is) + const struct TALER_MERCHANTDB_InstanceSettings *is, + const struct TALER_MERCHANTDB_InstanceAuthSettings *ias) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_auto_from_type (&is->auth_hash), - GNUNET_PQ_query_param_auto_from_type (&is->auth_salt), + GNUNET_PQ_query_param_auto_from_type (&ias->auth_hash), + GNUNET_PQ_query_param_auto_from_type (&ias->auth_salt), GNUNET_PQ_query_param_string (is->id), GNUNET_PQ_query_param_string (is->name), TALER_PQ_query_param_json (is->address), @@ -753,6 +760,31 @@ postgres_update_instance (void *cls, GNUNET_PQ_query_param_relative_time ( &is->default_wire_transfer_delay), GNUNET_PQ_query_param_relative_time (&is->default_pay_delay), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "update_instance", + params); +} + +/** + * Update information about an instance's authentication settings + * into our database. + * + * @param cls closure + * @param ias details about the instance + * @return database result code + */ +static enum GNUNET_DB_QueryStatus +postgres_update_instance_auth (void *cls, + const char *merchant_id, + const struct TALER_MERCHANTDB_InstanceAuthSettings *is) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (merchant_id), GNUNET_PQ_query_param_auto_from_type (&is->auth_hash), GNUNET_PQ_query_param_auto_from_type (&is->auth_salt), GNUNET_PQ_query_param_end @@ -760,7 +792,7 @@ postgres_update_instance (void *cls, check_connection (pg); return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "update_instance", + "update_instance_auth", params); } @@ -6149,10 +6181,15 @@ postgres_connect (void *cls) ",default_wire_fee_amortization=$9" ",default_wire_transfer_delay=$10" ",default_pay_delay=$11" - ",auth_hash=$12" - ",auth_salt=$13" " WHERE merchant_id = $1", - 13), + 11), + /* for postgres_update_instance_auth() */ + GNUNET_PQ_make_prepare ("update_instance_auth", + "UPDATE merchant_instances SET" + " auth_hash=$2" + ",auth_salt=$3" + " WHERE merchant_id = $1", + 3), /* for postgres_inactivate_account() */ GNUNET_PQ_make_prepare ("inactivate_account", "UPDATE merchant_accounts SET" @@ -8487,6 +8524,7 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) plugin->delete_instance_private_key = &postgres_delete_instance_private_key; plugin->purge_instance = &postgres_purge_instance; plugin->update_instance = &postgres_update_instance; + plugin->update_instance_auth = &postgres_update_instance_auth; plugin->activate_account = &postgres_activate_account; plugin->inactivate_account = &postgres_inactivate_account; plugin->lookup_products = &postgres_lookup_products; diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c index 9be7933d..be07c3cf 100644 --- a/src/backenddb/test_merchantdb.c +++ b/src/backenddb/test_merchantdb.c @@ -266,6 +266,7 @@ check_accounts_equal (const struct TALER_MERCHANTDB_AccountDetails *a, * @param merchant_pub public key of the instance * @param merchant_priv private key of the instance, NULL if not available * @param is general instance settings + * @param ias instance authentication settings * @param accounts_length length of the @a accounts array * @param accounts list of accounts of the merchant */ @@ -274,6 +275,7 @@ lookup_instances_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[]) { @@ -324,11 +326,13 @@ static int test_insert_instance (const struct InstanceData *instance, enum GNUNET_DB_QueryStatus expected_result) { + struct TALER_MERCHANTDB_InstanceAuthSettings ias = { 0 }; TEST_COND_RET_ON_FAIL (expected_result == plugin->insert_instance (plugin->cls, &instance->merchant_pub, &instance->merchant_priv, - &instance->instance), + &instance->instance, + &ias), "Insert instance failed\n"); return 0; } diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h index 963f9234..6f94e514 100644 --- a/src/include/taler_merchantdb_plugin.h +++ b/src/include/taler_merchantdb_plugin.h @@ -60,6 +60,22 @@ struct TALER_MERCHANTDB_AccountDetails }; +/** + * Authentication settings for an instance. + */ +struct TALER_MERCHANTDB_InstanceAuthSettings +{ + /** + * Hash used for authentication. All zero if authentication is off. + */ + struct GNUNET_HashCode auth_hash; + + /** + * Salt used to hash the "Authentication" header, the result must then + * match the @e auth_hash. + */ + struct GNUNET_ShortHashCode auth_salt; +}; /** * General settings for an instance. @@ -118,17 +134,6 @@ struct TALER_MERCHANTDB_InstanceSettings */ struct GNUNET_TIME_Relative default_pay_delay; - /** - * Hash used for authentication. All zero if authentication is off. - */ - struct GNUNET_HashCode auth_hash; - - /** - * Salt used to hash the "Authentication" header, the result must then - * match the @e auth_hash. - */ - struct GNUNET_ShortHashCode auth_salt; - }; @@ -148,6 +153,7 @@ typedef void 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[]); @@ -784,7 +790,8 @@ struct TALER_MERCHANTDB_Plugin (*insert_instance)(void *cls, const struct TALER_MerchantPublicKeyP *merchant_pub, const struct TALER_MerchantPrivateKeyP *merchant_priv, - const struct TALER_MERCHANTDB_InstanceSettings *is); + const struct TALER_MERCHANTDB_InstanceSettings *is, + const struct TALER_MERCHANTDB_InstanceAuthSettings *ias); /** * Insert information about an instance's account into our database. @@ -835,6 +842,20 @@ struct TALER_MERCHANTDB_Plugin (*update_instance)(void *cls, const struct TALER_MERCHANTDB_InstanceSettings *is); + /** + * Update information about an instance's authentication settings + * into our database. + * + * @param cls closure + * @param merchant_id merchant backend instance ID + * @param ias instance auth settings + * @return database result code + */ + enum GNUNET_DB_QueryStatus + (*update_instance_auth)(void *cls, + const char *merchant_id, + const struct TALER_MERCHANTDB_InstanceAuthSettings *ias); + /** * Set an instance's account in our database to "inactive". * diff --git a/src/lib/merchant_api_post_instances.c b/src/lib/merchant_api_post_instances.c index a6452045..8aede243 100644 --- a/src/lib/merchant_api_post_instances.c +++ b/src/lib/merchant_api_post_instances.c @@ -178,6 +178,7 @@ TALER_MERCHANT_instances_post ( struct TALER_MERCHANT_InstancesPostHandle *iph; json_t *jpayto_uris; json_t *req_obj; + json_t *auth_obj; if (NULL != auth_token) { @@ -190,11 +191,27 @@ TALER_MERCHANT_instances_post ( RFC_8959_PREFIX); return NULL; } - auth_token += strlen (RFC_8959_PREFIX); + auth_obj = json_pack ("{s:s, s:s}", + "method", + "token", + "token", + auth_token); + } + else + { + auth_obj = json_pack ("{s:s}", + "method", + "external"); + } + if (NULL == auth_obj) + { + GNUNET_break (0); + return NULL; } jpayto_uris = json_array (); if (NULL == jpayto_uris) { + json_decref (auth_obj); GNUNET_break (0); return NULL; } @@ -205,13 +222,14 @@ TALER_MERCHANT_instances_post ( json_string (payto_uris[i]))) { GNUNET_break (0); + json_decref (auth_obj); json_decref (jpayto_uris); return NULL; } } req_obj = json_pack ("{s:o, s:s, s:s, s:O, s:O" ",s:o, s:I: s:o, s:o, s:o" - ",s:s?}", + ",s:o}", "payto_uris", jpayto_uris, "id", @@ -233,10 +251,11 @@ TALER_MERCHANT_instances_post ( GNUNET_JSON_from_time_rel (default_wire_transfer_delay), "default_pay_delay", GNUNET_JSON_from_time_rel (default_pay_delay), - "auth_token", - auth_token); + "auth", + auth_obj); if (NULL == req_obj) { + json_decref (auth_obj); GNUNET_break (0); return NULL; } diff --git a/src/testing/test_merchant_api.c b/src/testing/test_merchant_api.c index ea1e1258..93b6194f 100644 --- a/src/testing/test_merchant_api.c +++ b/src/testing/test_merchant_api.c @@ -1262,7 +1262,10 @@ run (void *cls, "EUR:0.2", GNUNET_TIME_UNIT_MINUTES, GNUNET_TIME_UNIT_MINUTES, - RFC_8959_PREFIX "EXAMPLE", + // FIXME: change this back once + // we have a update auth test CMD + //RFC_8959_PREFIX "EXAMPLE", + NULL, MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_patch_instance ("instance-patch-ACL", merchant_url, -- cgit v1.2.3