diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index 6f021d726..288b4578d 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015, 2016, 2019 Taler Systems SA + Copyright (C) 2014-2020 Taler Systems SA 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 @@ -147,6 +147,92 @@ static unsigned long long req_count; static unsigned long long req_max; +/** + * Handle a "/coins/$COIN_PUB/$OP" POST request. Parses the "coin_pub" + * EdDSA key of the coin and demultiplexes based on $OP. + * + * @param rh context of the handler + * @param connection the MHD connection to handle + * @param root uploaded JSON data + * @param args array of additional options (first must be the + * reserve public key, the second one should be "withdraw") + * @return MHD result code + */ +static int +handle_post_coins (const struct TEH_RequestHandler *rh, + struct MHD_Connection *connection, + const json_t *root, + const char *const args[2]) +{ + struct TALER_CoinSpendPublicKeyP coin_pub; + static const struct + { + /** + * Name of the operation (args[1]) + */ + const char *op; + + /** + * Function to call to perform the operation. + * + * @param connection the MHD connection to handle + * @param coin_pub the public key of the coin + * @param root uploaded JSON data + * @return MHD result code + */// + int + (*handler)(struct MHD_Connection *connection, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const json_t *root); + } h[] = { + { + .op = "deposit", + .handler = &TEH_DEPOSIT_handler_deposit + }, + { + .op = "melt", + .handler = &TEH_REFRESH_handler_melt + }, + { + .op = "recoup", + .handler = &TEH_RECOUP_handler_recoup + }, + { + .op = "refund", + .handler = &TEH_REFUND_handler_refund + }, + { + .op = NULL, + .handler = NULL + }, + }; + + (void) rh; + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[0], + strlen (args[0]), + &coin_pub, + sizeof (coin_pub))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_COINS_INVALID_COIN_PUB, + "coin public key malformed"); + } + for (unsigned int i = 0; NULL != h[i].op; i++) + if (0 == strcmp (h[i].op, + args[1])) + return h[i].handler (connection, + &coin_pub, + root); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_OPERATION_INVALID, + "requested operation on coin unknown"); +} + + /** * Function called whenever MHD is done with a request. If the * request was a POST, we may have stored a `struct Buffer *` in the @@ -205,6 +291,120 @@ is_valid_correlation_id (const char *correlation_id) } +/** + * We found @a rh responsible for handling a request. Parse the + * @a upload_data (if applicable) and the @a url and call the + * handler. + * + * @param rh request handler to call + * @param connection connection being handled + * @param url rest of the URL to parse + * @param inner_cls closure for the handler, if needed + * @param upload_data upload data to parse (if available) + * @param upload_data_size[in,out] number of bytes in @a upload_data + * @return MHD result code + */ +static int +proceed_with_handler (const struct TEH_RequestHandler *rh, + struct MHD_Connection *connection, + const char *url, + void **inner_cls, + const char *upload_data, + size_t *upload_data_size) +{ + const char *args[rh->nargs + 1]; + size_t ulen = strlen (url) + 1; + json_t *root; + int ret; + + /* We do check for "ulen" here, because we'll later stack-allocate a buffer + of that size and don't want to enable malicious clients to cause us + huge stack allocations. */ + if (ulen > 512) + { + /* 512 is simply "big enough", as it is bigger than "6 * 54", + which is the longest URL format we ever get (for + /deposits/). The value should be adjusted if we ever define protocol + endpoints with plausibly longer inputs. */ + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_URI_TOO_LONG, + TALER_EC_URI_TOO_LONG, + "The URI given is too long"); + } + + /* All POST endpoints come with a body in JSON format. So we parse + the JSON here. */ + if (0 == strcasecmp (rh->method, + MHD_HTTP_METHOD_POST)) + { + int res; + + res = TALER_MHD_parse_post_json (connection, + inner_cls, + upload_data, + upload_data_size, + &root); + if (GNUNET_SYSERR == res) + return MHD_NO; + if ( (GNUNET_NO == res) || (NULL == root) ) + return MHD_YES; + } + + { + char d[ulen]; + + /* Parse command-line arguments, if applicable */ + if (rh->nargs > 0) + { + unsigned int i; + + /* make a copy of 'url' because 'strtok()' will modify */ + memcpy (d, + url, + ulen); + i = 0; + args[i++] = strtok (d, "/"); + while ( (NULL != args[i - 1]) && + (i < rh->nargs) ) + args[i++] = strtok (NULL, "/"); + /* make sure above loop ran nicely until completion, and also + that there is no excess data in 'd' afterwards */ + if ( (i != rh->nargs) || + (NULL == args[i - 1]) || + (NULL != strtok (NULL, "/")) ) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_WRONG_NUMBER_OF_SEGMENTS, + "Number of segments does not match"); + } + } + + /* just to be safe(r), we always terminate the array with a NULL + (which handlers should not read, but at least if they do, they'll + crash pretty reliably... */ + args[rh->nargs] = NULL; + + /* Above logic ensures that 'root' is exactly non-NULL for POST operations */ + if (NULL != root) + ret = rh->handler.post (rh, + connection, + root, + args); + else /* and we only have "POST" or "GET" in the API for at this point + (OPTIONS/HEAD are taken care of earlier) */ + ret = rh->handler.get (rh, + connection, + args); + } + if (NULL != root) + json_decref (root); + return ret; +} + + /** * Handle incoming HTTP request. * @@ -229,134 +429,111 @@ handle_mhd_request (void *cls, void **con_cls) { static struct TEH_RequestHandler handlers[] = { - /* Landing page, tell humans to go away. */ - { "/", MHD_HTTP_METHOD_GET, "text/plain", - "Hello, I'm the Taler exchange. This HTTP server is not for humans.\n", 0, - &TEH_MHD_handler_static_response, MHD_HTTP_OK }, /* /robots.txt: disallow everything */ - { "/robots.txt", MHD_HTTP_METHOD_GET, "text/plain", - "User-agent: *\nDisallow: /\n", 0, - &TEH_MHD_handler_static_response, MHD_HTTP_OK }, + { + .url = "robots.txt", + .method = MHD_HTTP_METHOD_GET, + .handler.get = &TEH_MHD_handler_static_response, + .mime_type = "text/plain", + .data = "User-agent: *\nDisallow: /\n", + .response_code = MHD_HTTP_OK + }, + /* Landing page, tell humans to go away. */ + { + .url = "", + .method = MHD_HTTP_METHOD_GET, + .handler.get = TEH_MHD_handler_static_response, + .mime_type = "text/plain", + .data = + "Hello, I'm the Taler exchange. This HTTP server is not for humans.\n", + .response_code = MHD_HTTP_OK + }, /* AGPL licensing page, redirect to source. As per the AGPL-license, every deployment is required to offer the user a download of the source. We make this easy by including a redirect to the source here. */ - { "/agpl", MHD_HTTP_METHOD_GET, "text/plain", - NULL, 0, - &TEH_MHD_handler_agpl_redirect, MHD_HTTP_FOUND }, + { + .url = "agpl", + .method = MHD_HTTP_METHOD_GET, + .handler.get = &TEH_MHD_handler_agpl_redirect + }, /* Terms of service */ - { "/terms", MHD_HTTP_METHOD_GET, NULL, - NULL, 0, - &TEH_handler_terms, MHD_HTTP_OK }, + { + .url = "terms", + .method = MHD_HTTP_METHOD_GET, + .handler.get = &TEH_handler_terms + }, /* Privacy policy */ - { "/privacy", MHD_HTTP_METHOD_GET, NULL, - NULL, 0, - &TEH_handler_privacy, MHD_HTTP_OK }, + { + .url = "privacy", + .method = MHD_HTTP_METHOD_GET, + .handler.get = &TEH_handler_privacy + }, /* Return key material and fundamental properties for this exchange */ - { "/keys", MHD_HTTP_METHOD_GET, "application/json", - NULL, 0, - &TEH_KS_handler_keys, MHD_HTTP_OK }, - { "/keys", NULL, "text/plain", - "Only GET is allowed", 0, - &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - + { + .url = "/keys", + .method = MHD_HTTP_METHOD_GET, + .handler.get = &TEH_KS_handler_keys, + }, /* Requests for wiring information */ - { "/wire", MHD_HTTP_METHOD_GET, "application/json", - NULL, 0, - &TEH_WIRE_handler_wire, MHD_HTTP_OK }, - { "/wire", NULL, "text/plain", - "Only GET is allowed", 0, - &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - + { + .url = "wire", + .method = MHD_HTTP_METHOD_GET, + .handler.get = &TEH_WIRE_handler_wire + }, /* Withdrawing coins / interaction with reserves */ - { "/reserve/status", MHD_HTTP_METHOD_GET, "application/json", - NULL, 0, - &TEH_RESERVE_handler_reserve_status, MHD_HTTP_OK }, - { "/reserve/status", NULL, "text/plain", - "Only GET is allowed", 0, - &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - - { "/reserve/withdraw", MHD_HTTP_METHOD_POST, "application/json", - NULL, 0, - &TEH_RESERVE_handler_reserve_withdraw, MHD_HTTP_OK }, - { "/reserve/withdraw", NULL, "text/plain", - "Only POST is allowed", 0, - &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - - /* Depositing coins */ - { "/deposit", MHD_HTTP_METHOD_POST, "application/json", - NULL, 0, - &TEH_DEPOSIT_handler_deposit, MHD_HTTP_OK }, - { "/deposit", NULL, "text/plain", - "Only POST is allowed", 0, - &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - - /* Refunding coins */ - { "/refund", MHD_HTTP_METHOD_POST, "application/json", - NULL, 0, - &TEH_REFUND_handler_refund, MHD_HTTP_OK }, - { "/refund", NULL, "text/plain", - "Only POST is allowed", 0, - &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - - /* Dealing with change */ - { "/refresh/melt", MHD_HTTP_METHOD_POST, "application/json", - NULL, 0, - &TEH_REFRESH_handler_refresh_melt, MHD_HTTP_OK }, - { "/refresh/melt", NULL, "text/plain", - "Only POST is allowed", 0, - &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - - { "/refresh/reveal", MHD_HTTP_METHOD_POST, "application/json", - NULL, 0, - &TEH_REFRESH_handler_refresh_reveal, MHD_HTTP_OK }, - { "/refresh/reveal", NULL, "text/plain", - "Only POST is allowed", 0, - &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - - { "/refresh/reveal", MHD_HTTP_METHOD_POST, "application/json", - NULL, 0, - &TEH_REFRESH_handler_refresh_reveal, MHD_HTTP_OK }, - { "/refresh/reveal", NULL, "text/plain", - "Only POST is allowed", 0, - &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - - { "/refresh/link", MHD_HTTP_METHOD_GET, "application/json", - NULL, 0, - &TEH_REFRESH_handler_refresh_link, MHD_HTTP_OK }, - { "/refresh/link", NULL, "text/plain", - "Only GET is allowed", 0, - &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - - { "/track/transfer", MHD_HTTP_METHOD_GET, "application/json", - NULL, 0, - &TEH_TRACKING_handler_track_transfer, MHD_HTTP_OK }, - { "/track/transfer", NULL, "text/plain", - "Only GET is allowed", 0, - &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - { "/track/transaction", MHD_HTTP_METHOD_POST, "application/json", - NULL, 0, - &TEH_TRACKING_handler_track_transaction, MHD_HTTP_OK }, - { "/track/transaction", NULL, "text/plain", - "Only POST is allowed", 0, - &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - - { "/recoup", MHD_HTTP_METHOD_POST, "application/json", - NULL, 0, - &TEH_RECOUP_handler_recoup, MHD_HTTP_OK }, - { "/refresh/link", NULL, "text/plain", - "Only GET is allowed", 0, - &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - - { NULL, NULL, NULL, NULL, 0, NULL, 0 } - }; - static struct TEH_RequestHandler h404 = { - "", NULL, "text/html", - "404: not found", 0, - &TEH_MHD_handler_static_response, MHD_HTTP_NOT_FOUND + { + .url = "reserves", + .method = MHD_HTTP_METHOD_GET, + .handler.get = &TEH_RESERVE_handler_reserve_status, + .nargs = 1 + }, + { + .url = "reserves", + .method = MHD_HTTP_METHOD_POST, + .handler.post = &TEH_RESERVE_handler_reserve_withdraw, + .nargs = 2 + }, + /* coins */ + { + .url = "coins", + .method = MHD_HTTP_METHOD_POST, + .handler.post = &handle_post_coins, + .nargs = 2 + }, + { + .url = "coins", + .method = MHD_HTTP_METHOD_GET, + .handler.get = TEH_REFRESH_handler_link, + .nargs = 2, + }, + /* refreshing */ + { + .url = "refreshes", + .method = MHD_HTTP_METHOD_POST, + .handler.post = &TEH_REFRESH_handler_reveal, + .nargs = 2 + }, + /* tracking transfers */ + { + .url = "transfers", + .method = MHD_HTTP_METHOD_GET, + .handler.get = &TEH_TRACKING_handler_track_transfer, + .nargs = 1 + }, + /* tracking deposits */ + { + .url = "deposits", + .method = MHD_HTTP_METHOD_GET, + .handler.get = &TEH_TRACKING_handler_track_transaction, + .nargs = 4 + }, + /* mark end of list */ + { + .url = NULL + } }; struct ExchangeHttpRequestClosure *ecls = *con_cls; - int ret; void **inner_cls; struct GNUNET_AsyncScopeSave old_scope; const char *correlation_id = NULL; @@ -367,7 +544,8 @@ handle_mhd_request (void *cls, { unsigned long long cnt; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Handling new request\n"); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Handling new request\n"); cnt = __sync_add_and_fetch (&req_count, 1LLU); if (req_max == cnt) { @@ -395,7 +573,8 @@ handle_mhd_request (void *cls, } inner_cls = &ecls->opaque_post_parsing_context; - GNUNET_async_scope_enter (&ecls->async_scope_id, &old_scope); + GNUNET_async_scope_enter (&ecls->async_scope_id, + &old_scope); if (NULL != correlation_id) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Handling request (%s) for URL '%s', correlation_id=%s\n", @@ -410,55 +589,100 @@ handle_mhd_request (void *cls, /* on repeated requests, check our cache first */ if (NULL != ecls->rh) { - ret = ecls->rh->handler (ecls->rh, - connection, - inner_cls, - upload_data, - upload_data_size); + int ret; + + ret = proceed_with_handler (ecls->rh, + connection, + url, + inner_cls, + upload_data, + upload_data_size); GNUNET_async_scope_restore (&old_scope); return ret; } + if (0 == strcasecmp (method, MHD_HTTP_METHOD_HEAD)) - method = MHD_HTTP_METHOD_GET; /* treat HEAD as GET here, MHD will do the rest */ - for (unsigned int i = 0; NULL != handlers[i].url; i++) + method = MHD_HTTP_METHOD_GET; /* treat HEAD as GET here, MHD will do the rest */ + + /* parse first part of URL */ { - struct TEH_RequestHandler *rh = &handlers[i]; + int found = GNUNET_NO; + size_t tok_size; + const char *tok; + const char *rest; - if (0 != strcmp (url, rh->url)) - continue; - - /* The URL is a match! What we now do depends on the method. */ - if (0 == strcasecmp (method, MHD_HTTP_METHOD_OPTIONS)) + if ('\0' == url[0]) + /* strange, should start with '/', treat as just "/" */ + url = "/"; + tok = url + 1; + rest = strchr (tok, '/'); + if (NULL == rest) { - GNUNET_async_scope_restore (&old_scope); - return TALER_MHD_reply_cors_preflight (connection); + tok_size = 0; + } + else + { + tok_size = rest - tok; + rest++; /* skip over '/' */ + } + for (unsigned int i = 0; NULL != handlers[i].url; i++) + { + struct TEH_RequestHandler *rh = &handlers[i]; + + if (0 != strncmp (tok, + rh->url, + tok_size)) + continue; + found = GNUNET_YES; + /* The URL is a match! What we now do depends on the method. */ + if (0 == strcasecmp (method, MHD_HTTP_METHOD_OPTIONS)) + { + GNUNET_async_scope_restore (&old_scope); + return TALER_MHD_reply_cors_preflight (connection); + } + GNUNET_assert (NULL != rh->method); + if (0 == strcasecmp (method, + rh->method)) + { + int ret; + + /* cache to avoid the loop next time */ + ecls->rh = rh; + /* run handler */ + ret = proceed_with_handler (rh, + connection, + url, + inner_cls, + upload_data, + upload_data_size); + GNUNET_async_scope_restore (&old_scope); + return ret; + } } - if ( (NULL == rh->method) || - (0 == strcasecmp (method, - rh->method)) ) + if (GNUNET_YES == found) { - /* cache to avoid the loop next time */ - ecls->rh = rh; - /* run handler */ - ret = rh->handler (rh, - connection, - inner_cls, - upload_data, - upload_data_size); - GNUNET_async_scope_restore (&old_scope); - return ret; + /* we found a matching address, but the method is wrong */ + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_METHOD_NOT_ALLOWED, + TALER_EC_METHOD_INVALID, + "The HTTP method used is invalid for this URL"); } } + /* No handler matches, generate not found */ - ret = TEH_MHD_handler_static_response (&h404, - connection, - inner_cls, - upload_data, - upload_data_size); - GNUNET_async_scope_restore (&old_scope); - return ret; + { + int ret; + + ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_ENDPOINT_UNKNOWN, + "No handler found for the given URL"); + GNUNET_async_scope_restore (&old_scope); + return ret; + } } diff --git a/src/exchange/taler-exchange-httpd.h b/src/exchange/taler-exchange-httpd.h index 38c611c66..8489d1790 100644 --- a/src/exchange/taler-exchange-httpd.h +++ b/src/exchange/taler-exchange-httpd.h @@ -24,6 +24,8 @@ #define TALER_EXCHANGE_HTTPD_H #include +#include "taler_json_lib.h" +#include "taler_crypto_lib.h" /** @@ -65,51 +67,77 @@ struct TEH_RequestHandler { /** - * URL the handler is for. + * URL the handler is for (first part only). */ const char *url; /** - * Method the handler is for, NULL for "all". + * Method the handler is for. */ const char *method; + /** + * Callbacks for handling of the request. Which one is used + * depends on @e method. + */ + union + { + /** + * Function to call to handle a GET requests (and those + * with @e method NULL). + * + * @param rh this struct + * @param mime_type the @e mime_type for the reply (hint, can be NULL) + * @param connection the MHD connection to handle + * @param args array of arguments, needs to be of length @e args_expected + * @return MHD result code + */ + int (*get)(const struct TEH_RequestHandler *rh, + struct MHD_Connection *connection, + const char *const args[]); + + + /** + * Function to call to handle a POST request. + * + * @param rh this struct + * @param mime_type the @e mime_type for the reply (hint, can be NULL) + * @param connection the MHD connection to handle + * @param json uploaded JSON data + * @param args array of arguments, needs to be of length @e args_expected + * @return MHD result code + */ + int (*post)(const struct TEH_RequestHandler *rh, + struct MHD_Connection *connection, + const json_t *root, + const char *const args[]); + + } handler; + + /** + * Number of arguments this handler expects in the @a args array. + */ + unsigned int nargs; + /** * Mime type to use in reply (hint, can be NULL). */ const char *mime_type; /** - * Raw data for the @e handler + * Raw data for the @e handler, can be NULL for none provided. */ const void *data; /** - * Number of bytes in @e data, 0 for 0-terminated. + * Number of bytes in @e data, 0 for data is 0-terminated (!). */ size_t data_size; /** - * Function to call to handle the request. - * - * @param rh this struct - * @param mime_type the @e mime_type for the reply (hint, can be NULL) - * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data - * @return MHD result code + * Default response code. 0 for none provided. */ - int (*handler)(struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); - - /** - * Default response code. - */ - int response_code; + unsigned int response_code; }; diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c index 49b9cc2fc..da89ff47e 100644 --- a/src/exchange/taler-exchange-httpd_deposit.c +++ b/src/exchange/taler-exchange-httpd_deposit.c @@ -381,27 +381,22 @@ check_timestamp_current (struct GNUNET_TIME_Absolute ts) /** - * Handle a "/deposit" request. Parses the JSON, and, if successful, - * passes the JSON data to #verify_and_execute_deposit() to further - * check the details of the operation specified. If everything checks + * Handle a "/coins/$COIN_PUB/deposit" request. Parses the JSON, and, if + * successful, passes the JSON data to #verify_and_execute_deposit() to + * further check the details of the operation specified. If everything checks * out, this will ultimately lead to the "/deposit" being executed, or * rejected. * - * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param coin_pub public key of the coin + * @param root uploaded JSON data * @return MHD result code */ int -TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) +TEH_DEPOSIT_handler_deposit (struct MHD_Connection *connection, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const json_t *root) { - json_t *json; int res; json_t *wire; enum TALER_ErrorCode ec; @@ -415,7 +410,6 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, GNUNET_JSON_spec_fixed_auto ("denom_pub_hash", &deposit.coin.denom_pub_hash), TALER_JSON_spec_denomination_signature ("ub_sig", &deposit.coin.denom_sig), - GNUNET_JSON_spec_fixed_auto ("coin_pub", &deposit.coin.coin_pub), GNUNET_JSON_spec_fixed_auto ("merchant_pub", &deposit.merchant_pub), GNUNET_JSON_spec_fixed_auto ("h_contract_terms", &deposit.h_contract_terms), GNUNET_JSON_spec_fixed_auto ("h_wire", &deposit.h_wire), @@ -428,27 +422,13 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, GNUNET_JSON_spec_end () }; - (void) rh; - res = TALER_MHD_parse_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &json); - if (GNUNET_SYSERR == res) - { - GNUNET_break (0); - return MHD_NO; - } - if ( (GNUNET_NO == res) || - (NULL == json) ) - return MHD_YES; memset (&deposit, 0, sizeof (deposit)); + deposit.coin.coin_pub = *coin_pub; res = TALER_MHD_parse_json_data (connection, - json, + root, spec); - json_decref (json); if (GNUNET_SYSERR == res) { GNUNET_break (0); diff --git a/src/exchange/taler-exchange-httpd_deposit.h b/src/exchange/taler-exchange-httpd_deposit.h index ed1f87d50..23c46c283 100644 --- a/src/exchange/taler-exchange-httpd_deposit.h +++ b/src/exchange/taler-exchange-httpd_deposit.h @@ -29,22 +29,21 @@ /** - * Handle a "/deposit" request. Parses the JSON, and, if successful, - * checks the signatures. If everything checks out, this will - * ultimately lead to the "/deposit" being executed, or rejected. + * Handle a "/coins/$COIN_PUB/deposit" request. Parses the JSON, and, if + * successful, passes the JSON data to #verify_and_execute_deposit() to + * further check the details of the operation specified. If everything checks + * out, this will ultimately lead to the "/deposit" being executed, or + * rejected. * - * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param coin_pub public key of the coin + * @param root uploaded JSON data * @return MHD result code */ int -TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); +TEH_DEPOSIT_handler_deposit (struct MHD_Connection *connection, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const json_t *root); + #endif diff --git a/src/exchange/taler-exchange-httpd_keystate.c b/src/exchange/taler-exchange-httpd_keystate.c index 27f22925d..f0ab2a0d7 100644 --- a/src/exchange/taler-exchange-httpd_keystate.c +++ b/src/exchange/taler-exchange-httpd_keystate.c @@ -2381,17 +2381,13 @@ krd_search_comparator (const void *key, * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (must be empty for this function) * @return MHD result code */ int -TEH_KS_handler_keys (struct TEH_RequestHandler *rh, +TEH_KS_handler_keys (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) + const char *const args[]) { int ret; const char *have_cherrypick; @@ -2400,9 +2396,8 @@ TEH_KS_handler_keys (struct TEH_RequestHandler *rh, struct GNUNET_TIME_Absolute now; const struct KeysResponseData *krd; - (void) connection_cls; - (void) upload_data; - (void) upload_data_size; + (void) rh; + (void) args; have_cherrypick = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "last_issue_date"); @@ -2493,7 +2488,7 @@ TEH_KS_handler_keys (struct TEH_RequestHandler *rh, "no key response found"); } ret = MHD_queue_response (connection, - rh->response_code, + MHD_HTTP_OK, (MHD_YES == TALER_MHD_can_compress (connection)) ? krd->response_compressed : krd->response_uncompressed); diff --git a/src/exchange/taler-exchange-httpd_keystate.h b/src/exchange/taler-exchange-httpd_keystate.h index ebcefa08a..a69060964 100644 --- a/src/exchange/taler-exchange-httpd_keystate.h +++ b/src/exchange/taler-exchange-httpd_keystate.h @@ -188,17 +188,13 @@ TEH_KS_sign (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (must be empty for this function) * @return MHD result code - */ + */ int -TEH_KS_handler_keys (struct TEH_RequestHandler *rh, +TEH_KS_handler_keys (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); + const char *const args[]); #endif diff --git a/src/exchange/taler-exchange-httpd_mhd.c b/src/exchange/taler-exchange-httpd_mhd.c index 0f2ce033a..0d59fad1b 100644 --- a/src/exchange/taler-exchange-httpd_mhd.c +++ b/src/exchange/taler-exchange-httpd_mhd.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014 Taler Systems SA + Copyright (C) 2014-2020 Taler Systems SA 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 @@ -39,27 +39,23 @@ * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (must be empty for this function) * @return MHD result code */ int -TEH_MHD_handler_static_response (struct TEH_RequestHandler *rh, +TEH_MHD_handler_static_response (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) + const char *const args[]) { struct MHD_Response *response; int ret; + size_t dlen; - (void) connection_cls; - (void) upload_data; - (void) upload_data_size; - if (0 == rh->data_size) - rh->data_size = strlen ((const char *) rh->data); - response = MHD_create_response_from_buffer (rh->data_size, + (void) args; + dlen = (0 == rh->data_size) + ? strlen ((const char *) rh->data) + : rh->data_size; + response = MHD_create_response_from_buffer (dlen, (void *) rh->data, MHD_RESPMEM_PERSISTENT); if (NULL == response) @@ -86,22 +82,16 @@ TEH_MHD_handler_static_response (struct TEH_RequestHandler *rh, * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (must be empty for this function) * @return MHD result code */ int -TEH_MHD_handler_agpl_redirect (struct TEH_RequestHandler *rh, +TEH_MHD_handler_agpl_redirect (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) + const char *const args[]) { (void) rh; - (void) connection_cls; - (void) upload_data; - (void) upload_data_size; + (void) args; return TALER_MHD_reply_agpl (connection, "http://www.git.taler.net/?p=exchange.git"); } @@ -113,21 +103,15 @@ TEH_MHD_handler_agpl_redirect (struct TEH_RequestHandler *rh, * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (must be empty for this function) * @return MHD result code */ int -TEH_MHD_handler_send_json_pack_error (struct TEH_RequestHandler *rh, +TEH_MHD_handler_send_json_pack_error (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) + const char *const args[]) { - (void) connection_cls; - (void) upload_data; - (void) upload_data_size; + (void) args; return TALER_MHD_reply_with_error (connection, rh->response_code, TALER_EC_METHOD_INVALID, diff --git a/src/exchange/taler-exchange-httpd_mhd.h b/src/exchange/taler-exchange-httpd_mhd.h index 16fc5a014..0364f0463 100644 --- a/src/exchange/taler-exchange-httpd_mhd.h +++ b/src/exchange/taler-exchange-httpd_mhd.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014 Taler Systems SA + Copyright (C) 2014-2020 Taler Systems SA 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 @@ -34,17 +34,13 @@ * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (must be empty for this function) * @return MHD result code */ int -TEH_MHD_handler_static_response (struct TEH_RequestHandler *rh, +TEH_MHD_handler_static_response (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); + const char *const args[]); /** @@ -53,40 +49,13 @@ TEH_MHD_handler_static_response (struct TEH_RequestHandler *rh, * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (must be empty for this function) * @return MHD result code */ int -TEH_MHD_handler_agpl_redirect (struct TEH_RequestHandler *rh, +TEH_MHD_handler_agpl_redirect (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); - - -/** - * Function to call to handle the request by building a JSON - * reply from varargs. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param response_code HTTP response code to use - * @param do_cache can the response be cached? (0: no, 1: yes) - * @param fmt format string for pack - * @param ... varargs - * @return MHD result code - */ -int -TEH_MHD_helper_send_json_pack (struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void *connection_cls, - int response_code, - int do_cache, - const char *fmt, - ...); + const char *const args[]); /** @@ -95,17 +64,13 @@ TEH_MHD_helper_send_json_pack (struct TEH_RequestHandler *rh, * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (must be empty for this function) * @return MHD result code */ int -TEH_MHD_handler_send_json_pack_error (struct TEH_RequestHandler *rh, +TEH_MHD_handler_send_json_pack_error (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); + const char *const args[]); #endif diff --git a/src/exchange/taler-exchange-httpd_recoup.c b/src/exchange/taler-exchange-httpd_recoup.c index 26bd65b46..f4cd99155 100644 --- a/src/exchange/taler-exchange-httpd_recoup.c +++ b/src/exchange/taler-exchange-httpd_recoup.c @@ -562,27 +562,21 @@ verify_and_execute_recoup (struct MHD_Connection *connection, /** - * Handle a "/recoup" request. Parses the JSON, and, if successful, - * passes the JSON data to #verify_and_execute_recoup() to - * further check the details of the operation specified. If - * everything checks out, this will ultimately lead to the "/refund" - * being executed, or rejected. + * Handle a "/coins/$COIN_PUB/recoup" request. Parses the JSON, and, if + * successful, passes the JSON data to #verify_and_execute_recoup() to further + * check the details of the operation specified. If everything checks out, + * this will ultimately lead to the refund being executed, or rejected. * - * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param coin_pub public key of the coin + * @param root uploaded JSON data * @return MHD result code */ int -TEH_RECOUP_handler_recoup (struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) +TEH_RECOUP_handler_recoup (struct MHD_Connection *connection, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const json_t *root) { - json_t *json; int res; struct TALER_CoinPublicInfo coin; struct TALER_DenominationBlindingKeyP coin_bks; @@ -593,8 +587,6 @@ TEH_RECOUP_handler_recoup (struct TEH_RequestHandler *rh, &coin.denom_pub_hash), TALER_JSON_spec_denomination_signature ("denom_sig", &coin.denom_sig), - GNUNET_JSON_spec_fixed_auto ("coin_pub", - &coin.coin_pub), GNUNET_JSON_spec_fixed_auto ("coin_blind_key_secret", &coin_bks), GNUNET_JSON_spec_fixed_auto ("coin_sig", @@ -605,20 +597,10 @@ TEH_RECOUP_handler_recoup (struct TEH_RequestHandler *rh, GNUNET_JSON_spec_end () }; - (void) rh; - res = TALER_MHD_parse_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &json); - if (GNUNET_SYSERR == res) - return MHD_NO; - if ( (GNUNET_NO == res) || (NULL == json) ) - return MHD_YES; + coin.coin_pub = *coin_pub; res = TALER_MHD_parse_json_data (connection, - json, + root, spec); - json_decref (json); if (GNUNET_SYSERR == res) return MHD_NO; /* hard failure */ if (GNUNET_NO == res) diff --git a/src/exchange/taler-exchange-httpd_recoup.h b/src/exchange/taler-exchange-httpd_recoup.h index 1baefc8ec..f86bf60e7 100644 --- a/src/exchange/taler-exchange-httpd_recoup.h +++ b/src/exchange/taler-exchange-httpd_recoup.h @@ -27,25 +27,20 @@ /** - * Handle a "/recoup" request. Parses the JSON, and, if successful, - * passes the JSON data to #verify_and_execute_recoup() to - * further check the details of the operation specified. If - * everything checks out, this will ultimately lead to the "/refund" - * being executed, or rejected. + * Handle a "/coins/$COIN_PUB/recoup" request. Parses the JSON, and, if + * successful, passes the JSON data to #verify_and_execute_recoup() to further + * check the details of the operation specified. If everything checks out, + * this will ultimately lead to the refund being executed, or rejected. * - * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param coin_pub public key of the coin + * @param root uploaded JSON data * @return MHD result code */ int -TEH_RECOUP_handler_recoup (struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); +TEH_RECOUP_handler_recoup (struct MHD_Connection *connection, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const json_t *root); #endif diff --git a/src/exchange/taler-exchange-httpd_refresh_link.c b/src/exchange/taler-exchange-httpd_refresh_link.c index 5e4360912..6dbaed497 100644 --- a/src/exchange/taler-exchange-httpd_refresh_link.c +++ b/src/exchange/taler-exchange-httpd_refresh_link.c @@ -172,43 +172,37 @@ refresh_link_transaction (void *cls, /** - * Handle a "/refresh/link" request. Note that for "/refresh/link" - * we do use a simple HTTP GET, and a HTTP POST! + * Handle a "/coins/$COIN_PUB/link" request. * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (length: 2, first is the coin_pub, second must be "link") * @return MHD result code */ int -TEH_REFRESH_handler_refresh_link (struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) +TEH_REFRESH_handler_link (const struct TEH_RequestHandler *rh, + struct MHD_Connection *connection, + const char *const args[2]) { - int mhd_ret; - int res; struct HTD_Context ctx; + int mhd_ret; (void) rh; - (void) connection_cls; - (void) upload_data; - (void) upload_data_size; memset (&ctx, 0, sizeof (ctx)); - res = TALER_MHD_parse_request_arg_data (connection, - "coin_pub", - &ctx.coin_pub, - sizeof (struct - TALER_CoinSpendPublicKeyP)); - if (GNUNET_SYSERR == res) - return MHD_NO; - if (GNUNET_OK != res) - return MHD_YES; + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[0], + strlen (args[0]), + &ctx.coin_pub, + sizeof (ctx.coin_pub))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_COINS_INVALID_COIN_PUB, + "coin public key malformed"); + } ctx.mlist = json_array (); if (GNUNET_OK != TEH_DB_run_transaction (connection, diff --git a/src/exchange/taler-exchange-httpd_refresh_link.h b/src/exchange/taler-exchange-httpd_refresh_link.h index d0fcff338..9469c4713 100644 --- a/src/exchange/taler-exchange-httpd_refresh_link.h +++ b/src/exchange/taler-exchange-httpd_refresh_link.h @@ -29,21 +29,17 @@ /** - * Handle a "/refresh/link" request + * Handle a "/coins/$COIN_PUB/link" request. * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (length: 2, first is the coin_pub, second must be "link") * @return MHD result code */ int -TEH_REFRESH_handler_refresh_link (struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); +TEH_REFRESH_handler_link (const struct TEH_RequestHandler *rh, + struct MHD_Connection *connection, + const char *const args[2]); #endif diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c b/src/exchange/taler-exchange-httpd_refresh_melt.c index c7dc700f7..9d92a4cee 100644 --- a/src/exchange/taler-exchange-httpd_refresh_melt.c +++ b/src/exchange/taler-exchange-httpd_refresh_melt.c @@ -577,31 +577,24 @@ check_for_denomination_key (struct MHD_Connection *connection, /** - * Handle a "/refresh/melt" request. Parses the request into the JSON - * components and then hands things of to #check_for_denomination_key() - * to validate the melted coins, the signature and execute the melt - * using handle_refresh_melt(). - * - * @param rh context of the handler + * Handle a "/coins/$COIN_PUB/melt" request. Parses the request into the JSON + * components and then hands things of to #check_for_denomination_key() to + * validate the melted coins, the signature and execute the melt using + * handle_refresh_melt(). + * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param coin_pub public key of the coin + * @param root uploaded JSON data * @return MHD result code */ int -TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) +TEH_REFRESH_handler_melt (struct MHD_Connection *connection, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const json_t *root) { - json_t *root; struct RefreshMeltContext rmc; int res; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("coin_pub", - &rmc.refresh_session.coin.coin_pub), TALER_JSON_spec_denomination_signature ("denom_sig", &rmc.refresh_session.coin.denom_sig), GNUNET_JSON_spec_fixed_auto ("denom_pub_hash", @@ -615,25 +608,13 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, GNUNET_JSON_spec_end () }; - (void) rh; - res = TALER_MHD_parse_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &root); - if (GNUNET_SYSERR == res) - return MHD_NO; - if ( (GNUNET_NO == res) || - (NULL == root) ) - return MHD_YES; - memset (&rmc, 0, sizeof (rmc)); + rmc.refresh_session.coin.coin_pub = *coin_pub; res = TALER_MHD_parse_json_data (connection, root, spec); - json_decref (root); if (GNUNET_OK != res) return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.h b/src/exchange/taler-exchange-httpd_refresh_melt.h index c50fdcb4c..41488c818 100644 --- a/src/exchange/taler-exchange-httpd_refresh_melt.h +++ b/src/exchange/taler-exchange-httpd_refresh_melt.h @@ -29,25 +29,20 @@ /** - * Handle a "/refresh/melt" request after the first parsing has - * happened. We now need to validate the coins being melted and the - * session signature and then hand things of to execute the melt - * operation. This function parses the JSON arrays and then passes - * processing on to #refresh_melt_transaction(). - * - * @param rh context of the handler + * Handle a "/coins/$COIN_PUB/melt" request. Parses the request into the JSON + * components and then hands things of to #check_for_denomination_key() to + * validate the melted coins, the signature and execute the melt using + * handle_refresh_melt(). + * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param coin_pub public key of the coin + * @param root uploaded JSON data * @return MHD result code */ int -TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); +TEH_REFRESH_handler_melt (struct MHD_Connection *connection, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const json_t *root); #endif diff --git a/src/exchange/taler-exchange-httpd_refresh_reveal.c b/src/exchange/taler-exchange-httpd_refresh_reveal.c index 1e03c8e7d..b7d7fb1c7 100644 --- a/src/exchange/taler-exchange-httpd_refresh_reveal.c +++ b/src/exchange/taler-exchange-httpd_refresh_reveal.c @@ -884,30 +884,27 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, /** - * Handle a "/refresh/reveal" request. This time, the client reveals the + * Handle a "/refreshes/$RCH/reveal" request. This time, the client reveals the * private transfer keys except for the cut-and-choose value returned from - * "/refresh/melt". This function parses the revealed keys and secrets and + * "/coins/$COIN_PUB/melt". This function parses the revealed keys and secrets and * ultimately passes everything to #resolve_refresh_reveal_denominations() * which will verify that the revealed information is valid then runs the * transaction in #refresh_reveal_transaction() and finally returns the signed * refreshed coins. * * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param coin_pub public key of the coin + * @param root uploaded JSON data + * @param args array of additional options (length: 2, session hash and the string "reveal") * @return MHD result code - */ + */ int -TEH_REFRESH_handler_refresh_reveal (struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) +TEH_REFRESH_handler_reveal (const struct TEH_RequestHandler *rh, + struct MHD_Connection *connection, + const json_t *root, + const char *const args[2]) { int res; - json_t *root; json_t *coin_evs; json_t *transfer_privs; json_t *link_sigs; @@ -924,24 +921,34 @@ TEH_REFRESH_handler_refresh_reveal (struct TEH_RequestHandler *rh, }; (void) rh; - res = TALER_MHD_parse_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &root); - if (GNUNET_SYSERR == res) - return MHD_NO; - if ( (GNUNET_NO == res) || - (NULL == root) ) - return MHD_YES; - memset (&rctx, 0, sizeof (rctx)); + + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[0], + strlen (args[0]), + &rctx.rc, + sizeof (rctx.rc))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_REFRESHES_INVALID_RCH, + "refresh commitment hash malformed"); + } + if (0 != strcmp (args[1], + "reveal")) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_OPERATION_INVALID, + "expected 'reveal' operation"); + } res = TALER_MHD_parse_json_data (connection, root, spec); - json_decref (root); if (GNUNET_OK != res) { GNUNET_break_op (0); diff --git a/src/exchange/taler-exchange-httpd_refresh_reveal.h b/src/exchange/taler-exchange-httpd_refresh_reveal.h index 0b0c29b76..afc9adce5 100644 --- a/src/exchange/taler-exchange-httpd_refresh_reveal.h +++ b/src/exchange/taler-exchange-httpd_refresh_reveal.h @@ -29,26 +29,25 @@ /** - * Handle a "/refresh/reveal" request. This time, the client reveals the + * Handle a "/refreshes/$RCH/reveal" request. This time, the client reveals the * private transfer keys except for the cut-and-choose value returned from - * "/refresh/melt". This function parses the revealed keys and secrets and + * "/coins/$COIN_PUB/melt". This function parses the revealed keys and secrets and * ultimately passes everything to #resolve_refresh_reveal_denominations() * which will verify that the revealed information is valid then runs the * transaction in #refresh_reveal_transaction() and finally returns the signed * refreshed coins. * * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param coin_pub public key of the coin + * @param root uploaded JSON data + * @param args array of additional options (length: 2, session hash and the string "reveal") * @return MHD result code - */ + */ int -TEH_REFRESH_handler_refresh_reveal (struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); +TEH_REFRESH_handler_reveal (const struct TEH_RequestHandler *rh, + struct MHD_Connection *connection, + const json_t *root, + const char *const args[2]); + #endif diff --git a/src/exchange/taler-exchange-httpd_refund.c b/src/exchange/taler-exchange-httpd_refund.c index 8e24b9b47..e7e34e0ba 100644 --- a/src/exchange/taler-exchange-httpd_refund.c +++ b/src/exchange/taler-exchange-httpd_refund.c @@ -532,27 +532,21 @@ verify_and_execute_refund (struct MHD_Connection *connection, /** - * Handle a "/refund" request. Parses the JSON, and, if successful, - * passes the JSON data to #verify_and_execute_refund() to - * further check the details of the operation specified. If - * everything checks out, this will ultimately lead to the "/refund" - * being executed, or rejected. + * Handle a "/coins/$COIN_PUB/refund" request. Parses the JSON, and, if + * successful, passes the JSON data to #verify_and_execute_refund() to further + * check the details of the operation specified. If everything checks out, + * this will ultimately lead to the refund being executed, or rejected. * - * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param coin_pub public key of the coin + * @param root uploaded JSON data * @return MHD result code */ int -TEH_REFUND_handler_refund (struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) +TEH_REFUND_handler_refund (struct MHD_Connection *connection, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const json_t *root) { - json_t *json; int res; struct TALER_EXCHANGEDB_Refund refund; struct GNUNET_JSON_Specification spec[] = { @@ -560,7 +554,6 @@ TEH_REFUND_handler_refund (struct TEH_RequestHandler *rh, TALER_JSON_spec_amount ("refund_fee", &refund.details.refund_fee), GNUNET_JSON_spec_fixed_auto ("h_contract_terms", &refund.details.h_contract_terms), - GNUNET_JSON_spec_fixed_auto ("coin_pub", &refund.coin.coin_pub), GNUNET_JSON_spec_fixed_auto ("merchant_pub", &refund.details.merchant_pub), GNUNET_JSON_spec_uint64 ("rtransaction_id", &refund.details.rtransaction_id), @@ -568,20 +561,10 @@ TEH_REFUND_handler_refund (struct TEH_RequestHandler *rh, GNUNET_JSON_spec_end () }; - (void) rh; - res = TALER_MHD_parse_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &json); - if (GNUNET_SYSERR == res) - return MHD_NO; - if ( (GNUNET_NO == res) || (NULL == json) ) - return MHD_YES; + refund.coin.coin_pub = *coin_pub; res = TALER_MHD_parse_json_data (connection, - json, + root, spec); - json_decref (json); if (GNUNET_SYSERR == res) return MHD_NO; /* hard failure */ if (GNUNET_NO == res) diff --git a/src/exchange/taler-exchange-httpd_refund.h b/src/exchange/taler-exchange-httpd_refund.h index 4f2b868e8..b79419f16 100644 --- a/src/exchange/taler-exchange-httpd_refund.h +++ b/src/exchange/taler-exchange-httpd_refund.h @@ -29,24 +29,19 @@ /** - * Handle a "/refund" request. Parses the JSON, and, if successful, - * passes the JSON data to #verify_and_execute_refund() to - * further check the details of the operation specified. If - * everything checks out, this will ultimately lead to the "/refund" - * being executed, or rejected. + * Handle a "/coins/$COIN_PUB/refund" request. Parses the JSON, and, if + * successful, passes the JSON data to #verify_and_execute_refund() to further + * check the details of the operation specified. If everything checks out, + * this will ultimately lead to the refund being executed, or rejected. * - * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param coin_pub public key of the coin + * @param root uploaded JSON data * @return MHD result code */ int -TEH_REFUND_handler_refund (struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); +TEH_REFUND_handler_refund (struct MHD_Connection *connection, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const json_t *root); #endif diff --git a/src/exchange/taler-exchange-httpd_reserve_status.c b/src/exchange/taler-exchange-httpd_reserve_status.c index e2d35aaec..251271254 100644 --- a/src/exchange/taler-exchange-httpd_reserve_status.c +++ b/src/exchange/taler-exchange-httpd_reserve_status.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2017 Taler Systems SA + Copyright (C) 2014-2020 Taler Systems SA 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 @@ -15,7 +15,7 @@ */ /** * @file taler-exchange-httpd_reserve_status.c - * @brief Handle /reserve/status requests + * @brief Handle /reserves/$RESERVE_PUB GET requests * @author Florian Dold * @author Benedikt Mueller * @author Christian Grothoff @@ -114,42 +114,37 @@ reserve_status_transaction (void *cls, /** - * Handle a "/reserve/status" request. Parses the - * given "reserve_pub" argument (which should contain the + * Handle a GET "/reserves/" request. Parses the + * given "reserve_pub" in @a args (which should contain the * EdDSA public key of a reserve) and then respond with the * status of the reserve. * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (length: 1, just the reserve_pub) * @return MHD result code */ int -TEH_RESERVE_handler_reserve_status (struct TEH_RequestHandler *rh, +TEH_RESERVE_handler_reserve_status (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) + const char *const args[1]) { struct ReserveStatusContext rsc; - int res; int mhd_ret; (void) rh; - (void) connection_cls; - (void) upload_data; - (void) upload_data_size; - res = TALER_MHD_parse_request_arg_data (connection, - "reserve_pub", - &rsc.reserve_pub, - sizeof (struct - TALER_ReservePublicKeyP)); - if (GNUNET_SYSERR == res) - return MHD_NO; /* internal error */ - if (GNUNET_NO == res) - return MHD_YES; /* parse error */ + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[0], + strlen (args[0]), + &rsc.reserve_pub, + sizeof (rsc.reserve_pub))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_RESERVES_INVALID_RESERVE_PUB, + "reserve public key malformed"); + } rsc.rh = NULL; if (GNUNET_OK != TEH_DB_run_transaction (connection, diff --git a/src/exchange/taler-exchange-httpd_reserve_status.h b/src/exchange/taler-exchange-httpd_reserve_status.h index 67eba2309..584bd3dcb 100644 --- a/src/exchange/taler-exchange-httpd_reserve_status.h +++ b/src/exchange/taler-exchange-httpd_reserve_status.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2017 Taler Systems SA + Copyright (C) 2014-2020 Taler Systems SA 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 @@ -15,7 +15,7 @@ */ /** * @file taler-exchange-httpd_reserve_status.h - * @brief Handle /reserve/status requests + * @brief Handle /reserves/$RESERVE_PUB GET requests * @author Florian Dold * @author Benedikt Mueller * @author Christian Grothoff @@ -26,24 +26,21 @@ #include #include "taler-exchange-httpd.h" + /** - * Handle a "/reserve/status" request. Parses the - * given "reserve_pub" argument (which should contain the + * Handle a GET "/reserves/" request. Parses the + * given "reserve_pub" in @a args (which should contain the * EdDSA public key of a reserve) and then respond with the * status of the reserve. * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (length: 1, just the reserve_pub) * @return MHD result code - */ + */ int -TEH_RESERVE_handler_reserve_status (struct TEH_RequestHandler *rh, +TEH_RESERVE_handler_reserve_status (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); + const char *const args[1]); #endif diff --git a/src/exchange/taler-exchange-httpd_reserve_withdraw.c b/src/exchange/taler-exchange-httpd_reserve_withdraw.c index 9daad0a02..25747eff0 100644 --- a/src/exchange/taler-exchange-httpd_reserve_withdraw.c +++ b/src/exchange/taler-exchange-httpd_reserve_withdraw.c @@ -335,30 +335,27 @@ withdraw_transaction (void *cls, /** - * Handle a "/reserve/withdraw" request. Parses the "reserve_pub" - * EdDSA key of the reserve and the requested "denom_pub" which - * specifies the key/value of the coin to be withdrawn, and checks - * that the signature "reserve_sig" makes this a valid withdrawal - * request from the specified reserve. If so, the envelope - * with the blinded coin "coin_ev" is passed down to execute the - * withdrawl operation. + * Handle a "/reserves/$RESERVE_PUB/withdraw" request. Parses the + * "reserve_pub" EdDSA key of the reserve and the requested "denom_pub" which + * specifies the key/value of the coin to be withdrawn, and checks that the + * signature "reserve_sig" makes this a valid withdrawal request from the + * specified reserve. If so, the envelope with the blinded coin "coin_ev" is + * passed down to execute the withdrawl operation. * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param root uploaded JSON data + * @param args array of additional options (first must be the + * reserve public key, the second one should be "withdraw") * @return MHD result code */ int -TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh, +TEH_RESERVE_handler_reserve_withdraw (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) + const json_t *root, + const char *const args[2]) { struct WithdrawContext wc; - json_t *root; int res; int mhd_ret; unsigned int hc; @@ -369,8 +366,6 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh, GNUNET_JSON_spec_varsize ("coin_ev", (void **) &wc.blinded_msg, &wc.blinded_msg_len), - GNUNET_JSON_spec_fixed_auto ("reserve_pub", - &wc.wsrd.reserve_pub), GNUNET_JSON_spec_fixed_auto ("reserve_sig", &wc.signature), GNUNET_JSON_spec_fixed_auto ("denom_pub_hash", @@ -379,19 +374,22 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh, }; (void) rh; - res = TALER_MHD_parse_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &root); - if (GNUNET_SYSERR == res) - return MHD_NO; - if ( (GNUNET_NO == res) || (NULL == root) ) - return MHD_YES; + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[0], + strlen (args[0]), + &wc.wsrd.reserve_pub, + sizeof (wc.wsrd.reserve_pub))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_RESERVES_INVALID_RESERVE_PUB, + "reserve public key malformed"); + } + res = TALER_MHD_parse_json_data (connection, root, spec); - json_decref (root); if (GNUNET_OK != res) return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; wc.key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ()); diff --git a/src/exchange/taler-exchange-httpd_reserve_withdraw.h b/src/exchange/taler-exchange-httpd_reserve_withdraw.h index 67b4cad0a..c3e56eaaf 100644 --- a/src/exchange/taler-exchange-httpd_reserve_withdraw.h +++ b/src/exchange/taler-exchange-httpd_reserve_withdraw.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2017 Taler Systems SA + Copyright (C) 2014-2020 Taler Systems SA 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 @@ -28,26 +28,24 @@ /** - * Handle a "/reserve/withdraw" request. Parses the "reserve_pub" - * EdDSA key of the reserve and the requested "denom_pub" which - * specifies the key/value of the coin to be withdrawn, and checks - * that the signature "reserve_sig" makes this a valid withdrawl - * request from the specified reserve. If so, the envelope - * with the blinded coin "coin_ev" is passed down to execute the - * withdrawl operation. + * Handle a "/reserves/$RESERVE_PUB/withdraw" request. Parses the + * "reserve_pub" EdDSA key of the reserve and the requested "denom_pub" which + * specifies the key/value of the coin to be withdrawn, and checks that the + * signature "reserve_sig" makes this a valid withdrawl request from the + * specified reserve. If so, the envelope with the blinded coin "coin_ev" is + * passed down to execute the withdrawl operation. * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param root uploaded JSON data + * @param args array of additional options (first must be the + * reserve public key, the second one should be "withdraw") * @return MHD result code */ int -TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh, +TEH_RESERVE_handler_reserve_withdraw (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); + const json_t *root, + const char *const args[2]); #endif diff --git a/src/exchange/taler-exchange-httpd_terms.c b/src/exchange/taler-exchange-httpd_terms.c index 47905f601..121e1c780 100644 --- a/src/exchange/taler-exchange-httpd_terms.c +++ b/src/exchange/taler-exchange-httpd_terms.c @@ -43,22 +43,16 @@ static struct TALER_MHD_Legal *pp; * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (must be empty for this function) * @return MHD result code */ int -TEH_handler_terms (struct TEH_RequestHandler *rh, +TEH_handler_terms (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) + const char *const args[]) { (void) rh; - (void) upload_data; - (void) upload_data_size; - (void) connection_cls; + (void) args; return TALER_MHD_reply_legal (connection, tos); } @@ -69,22 +63,16 @@ TEH_handler_terms (struct TEH_RequestHandler *rh, * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (must be empty for this function) * @return MHD result code */ int -TEH_handler_privacy (struct TEH_RequestHandler *rh, +TEH_handler_privacy (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) + const char *const args[]) { (void) rh; - (void) upload_data; - (void) upload_data_size; - (void) connection_cls; + (void) args; return TALER_MHD_reply_legal (connection, pp); } diff --git a/src/exchange/taler-exchange-httpd_terms.h b/src/exchange/taler-exchange-httpd_terms.h index 75909df9a..7fe7774ad 100644 --- a/src/exchange/taler-exchange-httpd_terms.h +++ b/src/exchange/taler-exchange-httpd_terms.h @@ -34,34 +34,27 @@ * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (must be empty for this function) * @return MHD result code */ int -TEH_handler_terms (struct TEH_RequestHandler *rh, +TEH_handler_terms (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); + const char *const args[]); + /** * Handle a "/privacy" request. * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (must be empty for this function) * @return MHD result code */ int -TEH_handler_privacy (struct TEH_RequestHandler *rh, +TEH_handler_privacy (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); + const char *const args[]); /** diff --git a/src/exchange/taler-exchange-httpd_track_transaction.c b/src/exchange/taler-exchange-httpd_track_transaction.c index e8143213a..d0f1d0aa3 100644 --- a/src/exchange/taler-exchange-httpd_track_transaction.c +++ b/src/exchange/taler-exchange-httpd_track_transaction.c @@ -336,62 +336,86 @@ check_and_handle_track_transaction_request (struct MHD_Connection *connection, /** - * Handle a "/track/transaction" request. + * Handle a "/deposits/$H_WIRE/$MERCHANT_PUB/$H_CONTRACT_TERMS/$COIN_PUB" + * request. * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (length: 4, contains: + * h_wire, merchant_pub, h_contract_terms and coin_pub) * @return MHD result code - */ + */ int -TEH_TRACKING_handler_track_transaction (struct TEH_RequestHandler *rh, +TEH_TRACKING_handler_track_transaction (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) + const char *const args[4]) { int res; - json_t *json; struct TALER_DepositTrackPS tps; struct TALER_MerchantSignatureP merchant_sig; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("h_wire", &tps.h_wire), - GNUNET_JSON_spec_fixed_auto ("h_contract_terms", &tps.h_contract_terms), - GNUNET_JSON_spec_fixed_auto ("coin_pub", &tps.coin_pub), - GNUNET_JSON_spec_fixed_auto ("merchant_pub", &tps.merchant), - GNUNET_JSON_spec_fixed_auto ("merchant_sig", &merchant_sig), - GNUNET_JSON_spec_end () - }; - (void) rh; - res = TALER_MHD_parse_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &json); - if (GNUNET_SYSERR == res) - return MHD_NO; - if ( (GNUNET_NO == res) || (NULL == json) ) - return MHD_YES; - res = TALER_MHD_parse_json_data (connection, - json, - spec); - if (GNUNET_OK != res) + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[0], + strlen (args[0]), + &tps.h_wire, + sizeof (tps.h_wire))) { - json_decref (json); - return (GNUNET_NO == res) ? MHD_YES : MHD_NO; + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_DEPOSITS_INVALID_H_WIRE, + "wire hash malformed"); } + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[1], + strlen (args[1]), + &tps.merchant, + sizeof (tps.merchant))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_DEPOSITS_INVALID_MERCHANT_PUB, + "merchant public key malformed"); + } + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[2], + strlen (args[2]), + &tps.h_contract_terms, + sizeof (tps.h_contract_terms))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_DEPOSITS_INVALID_H_CONTRACT_TERMS, + "contract terms hash malformed"); + } + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[3], + strlen (args[3]), + &tps.coin_pub, + sizeof (tps.coin_pub))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_DEPOSITS_INVALID_COIN_PUB, + "coin public key malformed"); + } + res = TALER_MHD_parse_request_arg_data (connection, + "merchant_sig", + &merchant_sig, + sizeof (merchant_sig)); + if (GNUNET_SYSERR == res) + return MHD_NO; /* internal error */ + if (GNUNET_NO == res) + return MHD_YES; /* parse error */ tps.purpose.size = htonl (sizeof (struct TALER_DepositTrackPS)); tps.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION); - res = check_and_handle_track_transaction_request (connection, - &tps, - &tps.merchant, - &merchant_sig); - GNUNET_JSON_parse_free (spec); - json_decref (json); - return res; + return check_and_handle_track_transaction_request (connection, + &tps, + &tps.merchant, + &merchant_sig); } diff --git a/src/exchange/taler-exchange-httpd_track_transaction.h b/src/exchange/taler-exchange-httpd_track_transaction.h index 929ee638e..5f54754f3 100644 --- a/src/exchange/taler-exchange-httpd_track_transaction.h +++ b/src/exchange/taler-exchange-httpd_track_transaction.h @@ -27,21 +27,19 @@ /** - * Handle a "/track/transaction" request. + * Handle a "/deposits/$H_WIRE/$MERCHANT_PUB/$H_CONTRACT_TERMS/$COIN_PUB" + * request. * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (length: 4, contains: + * h_wire, merchant_pub, h_contract_terms and coin_pub) * @return MHD result code */ int -TEH_TRACKING_handler_track_transaction (struct TEH_RequestHandler *rh, +TEH_TRACKING_handler_track_transaction (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); + const char *const args[4]); #endif diff --git a/src/exchange/taler-exchange-httpd_track_transfer.c b/src/exchange/taler-exchange-httpd_track_transfer.c index 1a780c063..cff6045ef 100644 --- a/src/exchange/taler-exchange-httpd_track_transfer.c +++ b/src/exchange/taler-exchange-httpd_track_transfer.c @@ -482,40 +482,37 @@ free_ctx (struct WtidTransactionContext *ctx) /** - * Handle a "/track/transfer" request. + * Handle a GET "/transfers/$WTID" request. * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (length: 1, just the wtid) * @return MHD result code */ int -TEH_TRACKING_handler_track_transfer (struct TEH_RequestHandler *rh, +TEH_TRACKING_handler_track_transfer (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) + const char *const args[1]) { struct WtidTransactionContext ctx; - int res; int mhd_ret; (void) rh; - (void) connection_cls; - (void) upload_data; - (void) upload_data_size; - memset (&ctx, 0, sizeof (ctx)); - res = TALER_MHD_parse_request_arg_data (connection, - "wtid", - &ctx.wtid, - sizeof (struct - TALER_WireTransferIdentifierRawP)); - if (GNUNET_SYSERR == res) - return MHD_NO; /* internal error */ - if (GNUNET_NO == res) - return MHD_YES; /* parse error */ + memset (&ctx, + 0, + sizeof (ctx)); + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[0], + strlen (args[0]), + &ctx.wtid, + sizeof (ctx.wtid))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_TRANSFERS_INVALID_WTID, + "wire transfer identifier malformed"); + } if (GNUNET_OK != TEH_DB_run_transaction (connection, "run track transfer", diff --git a/src/exchange/taler-exchange-httpd_track_transfer.h b/src/exchange/taler-exchange-httpd_track_transfer.h index c68cb288a..c6bd7c5d2 100644 --- a/src/exchange/taler-exchange-httpd_track_transfer.h +++ b/src/exchange/taler-exchange-httpd_track_transfer.h @@ -27,20 +27,17 @@ /** - * Handle a "/track/transfer" request. + * Handle a GET "/transfers/$WTID" request. * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (length: 1, just the wtid) * @return MHD result code */ int -TEH_TRACKING_handler_track_transfer (struct TEH_RequestHandler *rh, +TEH_TRACKING_handler_track_transfer (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); + const char *const args[1]); + #endif diff --git a/src/exchange/taler-exchange-httpd_validation.c b/src/exchange/taler-exchange-httpd_validation.c index e3dd8e86e..e55100e14 100644 --- a/src/exchange/taler-exchange-httpd_validation.c +++ b/src/exchange/taler-exchange-httpd_validation.c @@ -25,7 +25,6 @@ #include "taler-exchange-httpd_validation.h" #include "taler-exchange-httpd_wire.h" #include "taler_exchangedb_lib.h" -#include "taler_json_lib.h" /** diff --git a/src/exchange/taler-exchange-httpd_wire.c b/src/exchange/taler-exchange-httpd_wire.c index e4bcbec5a..de4e2db4d 100644 --- a/src/exchange/taler-exchange-httpd_wire.c +++ b/src/exchange/taler-exchange-httpd_wire.c @@ -124,22 +124,16 @@ TEH_WIRE_get_fees (const char *method) * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (must be empty for this function) * @return MHD result code */ int -TEH_WIRE_handler_wire (struct TEH_RequestHandler *rh, +TEH_WIRE_handler_wire (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) + const char *const args[]) { (void) rh; - (void) connection_cls; - (void) upload_data; - (void) upload_data_size; + (void) args; GNUNET_assert (NULL != wire_methods); return TALER_MHD_reply_json (connection, wire_methods, diff --git a/src/exchange/taler-exchange-httpd_wire.h b/src/exchange/taler-exchange-httpd_wire.h index 75c60353f..ac4ea39cc 100644 --- a/src/exchange/taler-exchange-httpd_wire.h +++ b/src/exchange/taler-exchange-httpd_wire.h @@ -51,17 +51,13 @@ TEH_WIRE_get_fees (const char *method); * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param args array of additional options (must be empty for this function) * @return MHD result code - */ + */ int -TEH_WIRE_handler_wire (struct TEH_RequestHandler *rh, +TEH_WIRE_handler_wire (const struct TEH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); + const char *const args[]); #endif diff --git a/src/include/taler_error_codes.h b/src/include/taler_error_codes.h index 917ac36db..1c48fe333 100644 --- a/src/include/taler_error_codes.h +++ b/src/include/taler_error_codes.h @@ -85,6 +85,32 @@ enum TALER_ErrorCode */ TALER_EC_METHOD_INVALID = 8, + /** + * Operation specified invalid for this URL (resulting in a "NOT + * FOUND" for the overall response). + */ + TALER_EC_OPERATION_INVALID = 9, + + /** + * There is no endpoint defined for the URL provided by the client + * (returned together with a MHD_HTTP_NOT FOUND status code). + */ + TALER_EC_ENDPOINT_UNKNOWN = 10, + + /** + * The URI is longer than the longest URI the HTTP server is willing + * to parse. Returned together with an HTTP status code of + * MHD_HTTP_URI_TOO_LONG. + */ + TALER_EC_URI_TOO_LONG = 11, + + /** + * The number of segments included in the URI does not match the + * number of segments expected by the endpoint. (returned together + * with a MHD_HTTP_NOT FOUND status code). + */ + TALER_EC_WRONG_NUMBER_OF_SEGMENTS = 12, + /** * The exchange failed to even just initialize its connection to the * database. This response is provided with HTTP status code @@ -181,6 +207,50 @@ enum TALER_ErrorCode */ TALER_EC_DB_COIN_HISTORY_STORE_ERROR = 1014, + /** + * The public key of given to a /coins/ handler was malformed. + */ + TALER_EC_COINS_INVALID_COIN_PUB = 1050, + + /** + * The public key of given to a /reserves/ handler was malformed. + */ + TALER_EC_RESERVES_INVALID_RESERVE_PUB = 1051, + + /** + * The public key of given to a /transfers/ handler was malformed. + */ + TALER_EC_TRANSFERS_INVALID_WTID = 1052, + + /** + * The hash of the wire details of given to a /deposits/ handler was + * malformed. + */ + TALER_EC_DEPOSITS_INVALID_H_WIRE = 1053, + + /** + * The merchant public key given to a /deposits/ handler was + * malformed. + */ + TALER_EC_DEPOSITS_INVALID_MERCHANT_PUB = 1054, + + /** + * The hash of the contract given to a /deposits/ handler was + * malformed. + */ + TALER_EC_DEPOSITS_INVALID_H_CONTRACT_TERMS = 1055, + + /** + * The coin public key given to a /deposits/ handler was malformed. + */ + TALER_EC_DEPOSITS_INVALID_COIN_PUB = 1056, + + /** + * The hash of the refresh commitment given to a /refreshes/ handler + * was malformed. + */ + TALER_EC_REFRESHES_INVALID_RCH = 1057, + /** * The given reserve does not have sufficient funds to admit the * requested withdraw operation at this time. The response includes