From a2a5f429159a5be2a453dcc7dacf30e7c0f9e963 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 10:48:05 +0100 Subject: start with libtalermhd --- src/Makefile.am | 2 +- src/exchange-tools/taler-exchange-keyup.c | 2 +- src/exchange/taler-exchange-aggregator.c | 4 +- src/exchange/taler-exchange-httpd_refresh_reveal.c | 6 +- src/exchange/taler-exchange-wirewatch.c | 4 +- src/include/Makefile.am | 1 + src/include/gauger.h | 2 +- src/include/taler_mhd_lib.h | 156 ++++++++++ src/lib/exchange_api_handle.c | 2 +- src/mhd/Makefile.am | 24 ++ src/mhd/mhd_responses.c | 319 +++++++++++++++++++++ 11 files changed, 511 insertions(+), 11 deletions(-) create mode 100644 src/include/taler_mhd_lib.h create mode 100644 src/mhd/Makefile.am create mode 100644 src/mhd/mhd_responses.c (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 38bf715fe..761b9c335 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,7 +22,7 @@ pkgcfg_DATA = \ EXTRA_DIST = \ taler.conf -SUBDIRS = include util wire json curl $(PQ_DIR) $(BANK_LIB) wire-plugins exchangedb exchange exchange-tools auditordb auditor +SUBDIRS = include util wire json curl $(PQ_DIR) mhd $(BANK_LIB) wire-plugins exchangedb exchange exchange-tools auditordb auditor if HAVE_LIBCURL SUBDIRS += lib benchmark else diff --git a/src/exchange-tools/taler-exchange-keyup.c b/src/exchange-tools/taler-exchange-keyup.c index d974ec46a..e6e3db0d1 100644 --- a/src/exchange-tools/taler-exchange-keyup.c +++ b/src/exchange-tools/taler-exchange-keyup.c @@ -765,7 +765,7 @@ create_denomkey_issue (const struct CoinTypeParams *params, GNUNET_assert (NULL != dki->denom_priv.rsa_private_key); dki->denom_pub.rsa_public_key = GNUNET_CRYPTO_rsa_private_key_get_public ( - dki->denom_priv.rsa_private_key); + dki->denom_priv.rsa_private_key); GNUNET_CRYPTO_rsa_public_key_hash (dki->denom_pub.rsa_public_key, &dki->issue.properties.denom_hash); dki->issue.properties.master = master_public_key; diff --git a/src/exchange/taler-exchange-aggregator.c b/src/exchange/taler-exchange-aggregator.c index 95f56d0df..98de86da0 100644 --- a/src/exchange/taler-exchange-aggregator.c +++ b/src/exchange/taler-exchange-aggregator.c @@ -1960,10 +1960,10 @@ main (int argc, options, &run, NULL)) { - GNUNET_free ((void*) argv); + GNUNET_free ((void *) argv); return 1; } - GNUNET_free ((void*) argv); + GNUNET_free ((void *) argv); return global_ret; } diff --git a/src/exchange/taler-exchange-httpd_refresh_reveal.c b/src/exchange/taler-exchange-httpd_refresh_reveal.c index be5228dd9..fbfe432de 100644 --- a/src/exchange/taler-exchange-httpd_refresh_reveal.c +++ b/src/exchange/taler-exchange-httpd_refresh_reveal.c @@ -751,9 +751,9 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, { rctx->ev_sigs[i].rsa_signature = GNUNET_CRYPTO_rsa_sign_blinded ( - rctx->dkis[i]->denom_priv.rsa_private_key, - rctx->rcds[i].coin_ev, - rctx->rcds[i].coin_ev_size); + rctx->dkis[i]->denom_priv.rsa_private_key, + rctx->rcds[i].coin_ev, + rctx->rcds[i].coin_ev_size); if (NULL == rctx->ev_sigs[i].rsa_signature) { GNUNET_break (0); diff --git a/src/exchange/taler-exchange-wirewatch.c b/src/exchange/taler-exchange-wirewatch.c index 3699c9d3b..21f62cd82 100644 --- a/src/exchange/taler-exchange-wirewatch.c +++ b/src/exchange/taler-exchange-wirewatch.c @@ -733,10 +733,10 @@ main (int argc, options, &run, NULL)) { - GNUNET_free ((void*) argv); + GNUNET_free ((void *) argv); return 1; } - GNUNET_free ((void*) argv); + GNUNET_free ((void *) argv); return global_ret; } diff --git a/src/include/Makefile.am b/src/include/Makefile.am index 1e624caa4..645bdc9f9 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -27,6 +27,7 @@ talerinclude_HEADERS = \ taler_json_lib.h \ taler_testing_lib.h \ taler_util.h \ + taler_mhd_lib.h \ taler_pq_lib.h \ taler_signatures.h \ taler_wire_lib.h \ diff --git a/src/include/gauger.h b/src/include/gauger.h index 7d66051b7..36dc055bb 100644 --- a/src/include/gauger.h +++ b/src/include/gauger.h @@ -35,7 +35,7 @@ __gauger_v[7] = "-c"; \ __gauger_v[8] = (char *) category; \ __gauger_v[9] = (char *) NULL; \ - execvp ("gauger", (char*const*) __gauger_v); \ + execvp ("gauger", (char *const *) __gauger_v); \ perror ("gauger"); \ _exit (1); \ }else{ \ diff --git a/src/include/taler_mhd_lib.h b/src/include/taler_mhd_lib.h new file mode 100644 index 000000000..553960909 --- /dev/null +++ b/src/include/taler_mhd_lib.h @@ -0,0 +1,156 @@ +/* + This file is part of TALER + Copyright (C) 2014 GNUnet e.V. + + 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. + + 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, see +*/ + +/** + * @file taler_mhd_lib.h + * @brief API for generating MHD replies + * @author Florian Dold + * @author Benedikt Mueller + * @author Christian Grothoff + */ +#ifndef TALER_MHD_LIB_H +#define TALER_MHD_LIB_H +#include +#include +#include +#include "taler_error_codes.h" + +/** + * Global options for response generation. + */ +enum TALER_MHD_GlobalOptions +{ + + /** + * Use defaults. + */ + TALER_MHD_GO_NONE = 0, + + /** + * Add "Connection: Close" header. + */ + TALER_MHD_GO_FORCE_CONNECTION_CLOSE = 1, + + /** + * Disable use of compression, even if the client + * supports it. + */ + TALER_MHD_GO_DISABLE_COMPRESSION = 2 + +}; + + +/** + * Set global options for response generation + * within libtalermhd. + * + * @param go global options to use + */ +void +TALER_MHD_setup (enum TALER_MHD_GlobalOptions go); + + +/** + * Add headers we want to return in every response. + * Useful for testing, like if we want to always close + * connections. + * + * @param response response to modify + */ +void +TALER_MHD_add_global_headers (struct MHD_Response *response); + + +/** + * Try to compress a response body. Updates @a buf and @a buf_size. + * + * @param[in,out] buf pointer to body to compress + * @param[in,out] buf_size pointer to initial size of @a buf + * @return #MHD_YES if @a buf was compressed + */ +int +TALER_MHD_body_compress (void **buf, + size_t *buf_size); + + +/** + * Is HTTP body deflate compression supported by the client? + * + * @param connection connection to check + * @return #MHD_YES if 'deflate' compression is allowed + */ +int +TALER_MHD_can_compress (struct MHD_Connection *connection); + + +/** + * Send JSON object as response. + * + * @param connection the MHD connection + * @param json the json object + * @param response_code the http response code + * @return MHD result code + */ +int +TALER_MHD_reply_json (struct MHD_Connection *connection, + const json_t *json, + unsigned int response_code); + + +/** + * Function to call to handle the request by building a JSON + * reply from a format string and varargs. + * + * @param connection the MHD connection to handle + * @param response_code HTTP response code to use + * @param fmt format string for pack + * @param ... varargs + * @return MHD result code + */ +int +TALER_MHD_reply_json_pack (struct MHD_Connection *connection, + unsigned int response_code, + const char *fmt, + ...); + + +/** + * Send a response indicating an error. + * + * @param connection the MHD connection to use + * @param ec error code uniquely identifying the error + * @param http_status HTTP status code to use + * @param hint human readable hint about the error + * @return a MHD result code + */ +int +TALER_MHD_reply_with_error (struct MHD_Connection *connection, + unsigned int http_status, + enum TALER_ErrorCode ec, + const char *hint); + + +/** + * Send a response indicating that the request was too big. + * + * @param connection the MHD connection to use + * @return a MHD result code + */ +int +TALER_MHD_reply_request_too_large (struct MHD_Connection *connection); + + +#endif diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c index efac70777..04de37677 100644 --- a/src/lib/exchange_api_handle.c +++ b/src/lib/exchange_api_handle.c @@ -1262,7 +1262,7 @@ keys_completed_cb (void *cls, for (unsigned int i = 0; i +*/ +/** + * @file mhd_responses.c + * @brief API for generating HTTP replies + * @author Florian Dold + * @author Benedikt Mueller + * @author Christian Grothoff + */ +#include "platform.h" +#include +#include "taler_util.h" +#include "taler_mhd_lib.h" + + +/** + * Enable checking signatures before we hand them out + * (even though we should have checked them before). + * So technically these checks are redundant, but good + * during testing. + */ +#define SANITY_CHECKS_ON 1 + + +/** + * Global options for response generation. + */ +static enum TALER_MHD_GlobalOptions TM_go; + + +/** + * Set global options for response generation + * within libtalermhd. + * + * @param go global options to use + */ +void +TALER_MHD_setup (enum TALER_MHD_GlobalOptions go) +{ + TM_go = go; +} + + +/** + * Add headers we want to return in every response. + * Useful for testing, like if we want to always close + * connections. + * + * @param response response to modify + */ +void +TALER_MHD_add_global_headers (struct MHD_Response *response) +{ + if (0 != (TM_go & TALER_MHD_GO_FORCE_CONNECTION_CLOSE)) + GNUNET_break (MHD_YES == + MHD_add_response_header (response, + MHD_HTTP_HEADER_CONNECTION, + "close")); +} + + +/** + * Is HTTP body deflate compression supported by the client? + * + * @param connection connection to check + * @return #MHD_YES if 'deflate' compression is allowed + * + * Note that right now we're ignoring q-values, which is technically + * not correct, and also do not support "*" anywhere but in a line by + * itself. This should eventually be fixed, see also + * https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html + */ +int +TALER_MHD_can_compress (struct MHD_Connection *connection) +{ + const char *ae; + const char *de; + + if (0 != (TM_go & TALER_MHD_GO_DISABLE_COMPRESSION)) + return MHD_NO; + ae = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_ACCEPT_ENCODING); + if (NULL == ae) + return MHD_NO; + if (0 == strcmp (ae, + "*")) + return MHD_YES; + de = strstr (ae, + "deflate"); + if (NULL == de) + return MHD_NO; + if ( ( (de == ae) || + (de[-1] == ',') || + (de[-1] == ' ') ) && + ( (de[strlen ("deflate")] == '\0') || + (de[strlen ("deflate")] == ',') || + (de[strlen ("deflate")] == ';') ) ) + return MHD_YES; + return MHD_NO; +} + + +/** + * Try to compress a response body. Updates @a buf and @a buf_size. + * + * @param[in,out] buf pointer to body to compress + * @param[in,out] buf_size pointer to initial size of @a buf + * @return #MHD_YES if @a buf was compressed + */ +int +TALER_MHD_body_compress (void **buf, + size_t *buf_size) +{ + Bytef *cbuf; + uLongf cbuf_size; + int ret; + + cbuf_size = compressBound (*buf_size); + cbuf = malloc (cbuf_size); + if (NULL == cbuf) + return MHD_NO; + ret = compress (cbuf, + &cbuf_size, + (const Bytef *) *buf, + *buf_size); + if ( (Z_OK != ret) || + (cbuf_size >= *buf_size) ) + { + /* compression failed */ + free (cbuf); + return MHD_NO; + } + free (*buf); + *buf = (void *) cbuf; + *buf_size = (size_t) cbuf_size; + return MHD_YES; +} + + +/** + * Send JSON object as response. + * + * @param connection the MHD connection + * @param json the json object + * @param response_code the http response code + * @return MHD result code + */ +int +TALER_MHD_reply_json (struct MHD_Connection *connection, + const json_t *json, + unsigned int response_code) +{ + struct MHD_Response *resp; + void *json_str; + size_t json_len; + int ret; + int comp; + + json_str = json_dumps (json, + JSON_INDENT (2)); + if (NULL == json_str) + { + /** + * This log helps to figure out which + * function called this one and assert-failed. + */ + TALER_LOG_ERROR ("Aborting json-packing for HTTP code: %u\n", + response_code); + + GNUNET_assert (0); + return MHD_NO; + } + json_len = strlen (json_str); + /* try to compress the body */ + comp = MHD_NO; + if (MHD_YES == + TALER_MHD_can_compress (connection)) + comp = TALER_MHD_body_compress (&json_str, + &json_len); + resp = MHD_create_response_from_buffer (json_len, + json_str, + MHD_RESPMEM_MUST_FREE); + if (NULL == resp) + { + free (json_str); + GNUNET_break (0); + return MHD_NO; + } + TALER_MHD_add_global_headers (resp); + GNUNET_break (MHD_YES == + MHD_add_response_header (resp, + MHD_HTTP_HEADER_CONTENT_TYPE, + "application/json")); + if (MHD_YES == comp) + { + /* Need to indicate to client that body is compressed */ + if (MHD_NO == + MHD_add_response_header (resp, + MHD_HTTP_HEADER_CONTENT_ENCODING, + "deflate")) + { + GNUNET_break (0); + MHD_destroy_response (resp); + return MHD_NO; + } + } + ret = MHD_queue_response (connection, + response_code, + resp); + MHD_destroy_response (resp); + return ret; +} + + +/** + * Function to call to handle the request by building a JSON + * reply from a format string and varargs. + * + * @param connection the MHD connection to handle + * @param response_code HTTP response code to use + * @param fmt format string for pack + * @param ... varargs + * @return MHD result code + */ +int +TALER_MHD_reply_json_pack (struct MHD_Connection *connection, + unsigned int response_code, + const char *fmt, + ...) +{ + json_t *json; + va_list argp; + int ret; + json_error_t jerror; + + va_start (argp, fmt); + json = json_vpack_ex (&jerror, 0, fmt, argp); + va_end (argp); + if (NULL == json) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to pack JSON with format `%s': %s\n", + fmt, + jerror.text); + GNUNET_break (0); + return MHD_NO; + } + ret = TALER_MHD_reply_json (connection, + json, + response_code); + json_decref (json); + return ret; +} + + +/** + * Send a response indicating an error. + * + * @param connection the MHD connection to use + * @param ec error code uniquely identifying the error + * @param http_status HTTP status code to use + * @param hint human readable hint about the error + * @return a MHD result code + */ +int +TALER_MHD_reply_with_error (struct MHD_Connection *connection, + unsigned int http_status, + enum TALER_ErrorCode ec, + const char *hint) +{ + return TALER_MHD_reply_json_pack (connection, + http_status, + "{s:I, s:s}", + "code", (json_int_t) ec, + "hint", hint); +} + + +/** + * Send a response indicating that the request was too big. + * + * @param connection the MHD connection to use + * @return a MHD result code + */ +int +TALER_MHD_reply_request_too_large (struct MHD_Connection *connection) +{ + struct MHD_Response *resp; + int ret; + + resp = MHD_create_response_from_buffer (0, + NULL, + MHD_RESPMEM_PERSISTENT); + if (NULL == resp) + return MHD_NO; + TALER_MHD_add_global_headers (resp); + ret = MHD_queue_response (connection, + MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, + resp); + MHD_destroy_response (resp); + return ret; +} + + +/* end of mhd_responses.c */ -- cgit v1.2.3 From fef8a57fae513259fd0b08e430b04d3b59d20210 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 11:02:34 +0100 Subject: add parsing API to new libtalermhd --- src/include/taler_mhd_lib.h | 108 ++++++++++++++++ src/mhd/Makefile.am | 3 +- src/mhd/mhd_parsing.c | 294 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 404 insertions(+), 1 deletion(-) create mode 100644 src/mhd/mhd_parsing.c (limited to 'src') diff --git a/src/include/taler_mhd_lib.h b/src/include/taler_mhd_lib.h index 553960909..d126d0aee 100644 --- a/src/include/taler_mhd_lib.h +++ b/src/include/taler_mhd_lib.h @@ -24,6 +24,7 @@ #ifndef TALER_MHD_LIB_H #define TALER_MHD_LIB_H #include +#include #include #include #include "taler_error_codes.h" @@ -153,4 +154,111 @@ int TALER_MHD_reply_request_too_large (struct MHD_Connection *connection); +/** + * Process a POST request containing a JSON object. This + * function realizes an MHD POST processor that will + * (incrementally) process JSON data uploaded to the HTTP + * server. It will store the required state in the + * "connection_cls", which must be cleaned up using + * #TALER_MHD_post_cleanup_callback(). + * + * @param connection the MHD connection + * @param con_cls the closure (points to a `struct Buffer *`) + * @param upload_data the POST data + * @param upload_data_size number of bytes in @a upload_data + * @param json the JSON object for a completed request + * @return + * #GNUNET_YES if json object was parsed or at least + * may be parsed in the future (call again); + * `*json` will be NULL if we need to be called again, + * and non-NULL if we are done. + * #GNUNET_NO is request incomplete or invalid + * (error message was generated) + * #GNUNET_SYSERR on internal error + * (we could not even queue an error message, + * close HTTP session with MHD_NO) + */ +int +TALER_MHD_parse_post_json (struct MHD_Connection *connection, + void **con_cls, + const char *upload_data, + size_t *upload_data_size, + json_t **json); + + +/** + * Function called whenever we are done with a request + * to clean up our state. + * + * @param con_cls value as it was left by + * #TALER_MHD_post_json(), to be cleaned up + */ +void +TALER_MHD_parse_post_cleanup_callback (void *con_cls); + + +/** + * Parse JSON object into components based on the given field + * specification. + * + * @param connection the connection to send an error response to + * @param root the JSON node to start the navigation at. + * @param spec field specification for the parser + * @return + * #GNUNET_YES if navigation was successful (caller is responsible + * for freeing allocated variable-size data using + * GNUNET_JSON_parse_free() when done) + * #GNUNET_NO if json is malformed, error response was generated + * #GNUNET_SYSERR on internal error + */ +int +TALER_MHD_parse_json_data (struct MHD_Connection *connection, + const json_t *root, + struct GNUNET_JSON_Specification *spec); + + +/** + * Parse JSON array into components based on the given field + * specification. Generates error response on parse errors. + * + * @param connection the connection to send an error response to + * @param root the JSON node to start the navigation at. + * @param[in,out] spec field specification for the parser + * @param ... -1-terminated list of array offsets of type 'int' + * @return + * #GNUNET_YES if navigation was successful (caller is responsible + * for freeing allocated variable-size data using + * GNUNET_JSON_parse_free() when done) + * #GNUNET_NO if json is malformed, error response was generated + * #GNUNET_SYSERR on internal error + */ +int +TALER_MHD_parse_json_array (struct MHD_Connection *connection, + const json_t *root, + struct GNUNET_JSON_Specification *spec, + ...); + + +/** + * Extraxt fixed-size base32crockford encoded data from request. + * + * Queues an error response to the connection if the parameter is missing or + * invalid. + * + * @param connection the MHD connection + * @param param_name the name of the parameter with the key + * @param[out] out_data pointer to store the result + * @param out_size expected size of @a out_data + * @return + * #GNUNET_YES if the the argument is present + * #GNUNET_NO if the argument is absent or malformed + * #GNUNET_SYSERR on internal error (error response could not be sent) + */ +int +TALER_MHD_parse_request_arg_data (struct MHD_Connection *connection, + const char *param_name, + void *out_data, + size_t out_size); + + #endif diff --git a/src/mhd/Makefile.am b/src/mhd/Makefile.am index 2c6d464f1..ed0c88417 100644 --- a/src/mhd/Makefile.am +++ b/src/mhd/Makefile.am @@ -10,7 +10,8 @@ lib_LTLIBRARIES = \ libtalermhd.la libtalermhd_la_SOURCES = \ - mhd_responses.c + mhd_parsing.c \ + mhd_responses.c libtalermhd_la_LDFLAGS = \ -version-info 0:0:0 \ -export-dynamic -no-undefined diff --git a/src/mhd/mhd_parsing.c b/src/mhd/mhd_parsing.c new file mode 100644 index 000000000..0b070ffe5 --- /dev/null +++ b/src/mhd/mhd_parsing.c @@ -0,0 +1,294 @@ +/* + This file is part of TALER + Copyright (C) 2014--2019 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 + Foundation; either version 3, or (at your option) any later version. + + 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, see +*/ +/** + * @file mhd_parsing.c + * @brief functions to parse incoming requests (MHD arguments and JSON snippets) + * @author Florian Dold + * @author Benedikt Mueller + * @author Christian Grothoff + */ +#include "platform.h" +#include +#include +#include "taler_json_lib.h" +#include "taler_mhd_lib.h" + + +/** + * Maximum POST request size. + */ +#define REQUEST_BUFFER_MAX (1024 * 1024) + + +/** + * Process a POST request containing a JSON object. This function + * realizes an MHD POST processor that will (incrementally) process + * JSON data uploaded to the HTTP server. It will store the required + * state in the @a con_cls, which must be cleaned up using + * #TALER_MHD_post_cleanup_callback(). + * + * @param connection the MHD connection + * @param con_cls the closure (points to a `struct Buffer *`) + * @param upload_data the POST data + * @param upload_data_size number of bytes in @a upload_data + * @param json the JSON object for a completed request + * @return + * #GNUNET_YES if json object was parsed or at least + * may be parsed in the future (call again); + * `*json` will be NULL if we need to be called again, + * and non-NULL if we are done. + * #GNUNET_NO is request incomplete or invalid + * (error message was generated) + * #GNUNET_SYSERR on internal error + * (we could not even queue an error message, + * close HTTP session with MHD_NO) + */ +int +TALER_MHD_parse_post_json (struct MHD_Connection *connection, + void **con_cls, + const char *upload_data, + size_t *upload_data_size, + json_t **json) +{ + enum GNUNET_JSON_PostResult pr; + + pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX, + connection, + con_cls, + upload_data, + upload_data_size, + json); + switch (pr) + { + case GNUNET_JSON_PR_OUT_OF_MEMORY: + return (MHD_NO == + TALER_MHD_reply_with_error + (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_PARSER_OUT_OF_MEMORY, + "out of memory")) ? GNUNET_SYSERR : GNUNET_NO; + + case GNUNET_JSON_PR_CONTINUE: + return GNUNET_YES; + case GNUNET_JSON_PR_REQUEST_TOO_LARGE: + return (MHD_NO == + TALER_MHD_reply_request_too_large + (connection)) ? GNUNET_SYSERR : GNUNET_NO; + case GNUNET_JSON_PR_JSON_INVALID: + return (MHD_YES == + TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_JSON_INVALID, + "invalid JSON uploaded")) + ? GNUNET_NO : GNUNET_SYSERR; + case GNUNET_JSON_PR_SUCCESS: + GNUNET_break (NULL != *json); + return GNUNET_YES; + } + /* this should never happen */ + GNUNET_break (0); + return GNUNET_SYSERR; +} + + +/** + * Function called whenever we are done with a request + * to clean up our state. + * + * @param con_cls value as it was left by + * #TALER_MHD_post_json(), to be cleaned up + */ +void +TALER_MHD_parse_post_cleanup_callback (void *con_cls) +{ + // FIXME: this should probably NOT be done with a 'void *' like this! + GNUNET_JSON_post_parser_cleanup (con_cls); +} + + +/** + * Extract base32crockford encoded data from request. + * + * Queues an error response to the connection if the parameter is + * missing or invalid. + * + * @param connection the MHD connection + * @param param_name the name of the parameter with the key + * @param[out] out_data pointer to store the result + * @param out_size expected size of data + * @return + * #GNUNET_YES if the the argument is present + * #GNUNET_NO if the argument is absent or malformed + * #GNUNET_SYSERR on internal error (error response could not be sent) + */ +int +TALER_MHD_parse_request_arg_data (struct MHD_Connection *connection, + const char *param_name, + void *out_data, + size_t out_size) +{ + const char *str; + + str = MHD_lookup_connection_value (connection, + MHD_GET_ARGUMENT_KIND, + param_name); + if (NULL == str) + { + return (MHD_NO == + TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_PARAMETER_MISSING, + param_name)) + ? GNUNET_SYSERR : GNUNET_NO; + } + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (str, + strlen (str), + out_data, + out_size)) + return (MHD_NO == + TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_PARAMETER_MALFORMED, + param_name)) + ? GNUNET_SYSERR : GNUNET_NO; + return GNUNET_OK; +} + + +/** + * Parse JSON object into components based on the given field + * specification. Generates error response on parse errors. + * + * @param connection the connection to send an error response to + * @param root the JSON node to start the navigation at. + * @param[in,out] spec field specification for the parser + * @return + * #GNUNET_YES if navigation was successful (caller is responsible + * for freeing allocated variable-size data using + * GNUNET_JSON_parse_free() when done) + * #GNUNET_NO if json is malformed, error response was generated + * #GNUNET_SYSERR on internal error + */ +int +TALER_MHD_parse_json_data (struct MHD_Connection *connection, + const json_t *root, + struct GNUNET_JSON_Specification *spec) +{ + int ret; + const char *error_json_name; + unsigned int error_line; + + ret = GNUNET_JSON_parse (root, + spec, + &error_json_name, + &error_line); + if (GNUNET_SYSERR == ret) + { + if (NULL == error_json_name) + error_json_name = ""; + ret = (MHD_YES == + TALER_MHD_reply_json_pack (connection, + MHD_HTTP_BAD_REQUEST, + "{s:s, s:I, s:s, s:I}", + "hint", "JSON parse error", + "code", + (json_int_t) + TALER_EC_JSON_INVALID_WITH_DETAILS, + "field", error_json_name, + "line", (json_int_t) error_line)) + ? GNUNET_NO : GNUNET_SYSERR; + return ret; + } + return GNUNET_YES; +} + + +/** + * Parse JSON array into components based on the given field + * specification. Generates error response on parse errors. + * + * @param connection the connection to send an error response to + * @param root the JSON node to start the navigation at. + * @param[in,out] spec field specification for the parser + * @param ... -1-terminated list of array offsets of type 'int' + * @return + * #GNUNET_YES if navigation was successful (caller is responsible + * for freeing allocated variable-size data using + * GNUNET_JSON_parse_free() when done) + * #GNUNET_NO if json is malformed, error response was generated + * #GNUNET_SYSERR on internal error + */ +int +TALER_MHD_parse_json_array (struct MHD_Connection *connection, + const json_t *root, + struct GNUNET_JSON_Specification *spec, + ...) +{ + int ret; + const char *error_json_name; + unsigned int error_line; + va_list ap; + json_int_t dim; + + va_start (ap, spec); + dim = 0; + while ( (-1 != (ret = va_arg (ap, int))) && + (NULL != root) ) + { + dim++; + root = json_array_get (root, ret); + } + va_end (ap); + if (NULL == root) + { + ret = (MHD_YES == + TALER_MHD_reply_json_pack (connection, + MHD_HTTP_BAD_REQUEST, + "{s:s, s:I, s:I}", + "hint", "expected array", + "code", + (json_int_t) + TALER_EC_JSON_INVALID_WITH_DETAILS, + "dimension", dim)) + ? GNUNET_NO : GNUNET_SYSERR; + return ret; + } + ret = GNUNET_JSON_parse (root, + spec, + &error_json_name, + &error_line); + if (GNUNET_SYSERR == ret) + { + if (NULL == error_json_name) + error_json_name = ""; + ret = (MHD_YES == + TALER_MHD_reply_json_pack (connection, + MHD_HTTP_BAD_REQUEST, + "{s:s, s:I, s:I}", + "hint", error_json_name, + "code", + (json_int_t) + TALER_EC_JSON_INVALID_WITH_DETAILS, + "line", (json_int_t) error_line)) + ? GNUNET_NO : GNUNET_SYSERR; + return ret; + } + return GNUNET_YES; +} + + +/* end of mhd_parsing.c */ -- cgit v1.2.3 From 0c85d195f8c0fe8363ae234fe962636fca8a77ea Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 11:48:35 +0100 Subject: add common setup logic to libtalermhd --- src/include/taler_mhd_lib.h | 79 +++++++++++- src/mhd/Makefile.am | 1 + src/mhd/mhd_config.c | 287 ++++++++++++++++++++++++++++++++++++++++++++ src/mhd/mhd_responses.c | 91 ++++++++++++++ 4 files changed, 457 insertions(+), 1 deletion(-) create mode 100644 src/mhd/mhd_config.c (limited to 'src') diff --git a/src/include/taler_mhd_lib.h b/src/include/taler_mhd_lib.h index d126d0aee..979f83854 100644 --- a/src/include/taler_mhd_lib.h +++ b/src/include/taler_mhd_lib.h @@ -13,7 +13,6 @@ You should have received a copy of the GNU Affero General Public License along with TALER; see the file COPYING. If not, see */ - /** * @file taler_mhd_lib.h * @brief API for generating MHD replies @@ -154,6 +153,39 @@ int TALER_MHD_reply_request_too_large (struct MHD_Connection *connection); +/** + * Function to call to handle the request by sending + * back a redirect to the AGPL source code. + * + * @param connection the MHD connection to handle + * @param url where to redirect for the sources + * @return MHD result code + */ +int +TALER_MHD_reply_agpl (struct MHD_Connection *connection, + const char *url); + + +/** + * Function to call to handle the request by sending + * back static data. + * + * @param rh context of the handler + * @param connection the MHD connection to handle + * @param http_status status code to return + * @param mime_type content-type to use + * @param body response payload + * @param body_size number of bytes in @a body + * @return MHD result code + */ +int +TALER_MHD_reply_static (struct MHD_Connection *connection, + unsigned int http_status, + const char *mime_type, + const char *body, + size_t *body_size); + + /** * Process a POST request containing a JSON object. This * function realizes an MHD POST processor that will @@ -261,4 +293,49 @@ TALER_MHD_parse_request_arg_data (struct MHD_Connection *connection, size_t out_size); +/** + * Parse the configuration to determine on which port + * or UNIX domain path we should run an HTTP service. + * + * @param cfg configuration to parse + * @param section section of the configuration to parse (usually "exchange") + * @param[out] rport set to the port number, or 0 for none + * @param[out] unix_path set to the UNIX path, or NULL for none + * @param[out] unix_mode set to the mode to be used for @a unix_path + * @return #GNUNET_OK on success + */ +int +TALER_MHD_parse_config (const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section, + uint16_t *rport, + char **unix_path, + mode_t *unix_mode); + + +/** + * Function called for logging by MHD. + * + * @param cls closure, NULL + * @param fm format string (`printf()`-style) + * @param ap arguments to @a fm + */ +void +TALER_MHD_handle_logs (void *cls, + const char *fm, + va_list ap); + + +/** + * Open UNIX domain socket for listining at @a unix_path with + * permissions @a unix_mode. + * + * @param unix_path where to listen + * @param unix_mode access permissions to set + * @return -1 on error, otherwise the listen socket + */ +int +TALER_MHD_open_unix_path (const char *unix_path, + mode_t unix_mode); + + #endif diff --git a/src/mhd/Makefile.am b/src/mhd/Makefile.am index ed0c88417..cc4c70735 100644 --- a/src/mhd/Makefile.am +++ b/src/mhd/Makefile.am @@ -10,6 +10,7 @@ lib_LTLIBRARIES = \ libtalermhd.la libtalermhd_la_SOURCES = \ + mhd_config.c \ mhd_parsing.c \ mhd_responses.c libtalermhd_la_LDFLAGS = \ diff --git a/src/mhd/mhd_config.c b/src/mhd/mhd_config.c new file mode 100644 index 000000000..afaceae40 --- /dev/null +++ b/src/mhd/mhd_config.c @@ -0,0 +1,287 @@ +/* + This file is part of TALER + Copyright (C) 2014--2019 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 + Foundation; either version 3, or (at your option) any later version. + + 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, see +*/ +/** + * @file mhd_config.c + * @brief functions to configure and setup MHD + * @author Florian Dold + * @author Benedikt Mueller + * @author Christian Grothoff + */ +#include "platform.h" +#include +#include "taler_mhd_lib.h" + + +/** + * Backlog for listen operation on UNIX domain sockets. + */ +#define UNIX_BACKLOG 500 + + +/** + * Parse the configuration to determine on which port + * or UNIX domain path we should run an HTTP service. + * + * @param cfg configuration to parse + * @param section section of the configuration to parse (usually "exchange") + * @param[out] rport set to the port number, or 0 for none + * @param[out] unix_path set to the UNIX path, or NULL for none + * @param[out] unix_mode set to the mode to be used for @a unix_path + * @return #GNUNET_OK on success + */ +int +TALER_MHD_parse_config (const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section, + uint16_t *rport, + char **unix_path, + mode_t *unix_mode) +{ + const char *choices[] = {"tcp", "unix"}; + const char *serve_type; + unsigned long long port; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_choice (cfg, + section, + "serve", + choices, + &serve_type)) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + "serve", + "serve type required"); + return GNUNET_SYSERR; + } + + if (0 == strcasecmp (serve_type, "tcp")) + { + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (cfg, + section, + "port", + &port)) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + "port", + "port number required"); + return GNUNET_SYSERR; + } + + if ( (0 == port) || + (port > UINT16_MAX) ) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + "port", + "value not in [1,65535]"); + return GNUNET_SYSERR; + } + *rport = (uint16_t) port; + *unix_path = NULL; + return GNUNET_OK; + } + if (0 == strcmp (serve_type, "unix")) + { + struct sockaddr_un s_un; + char *modestring; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_filename (cfg, + section, + "unixpath", + unix_path)) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + "unixpath", + "unixpath required"); + return GNUNET_SYSERR; + } + if (strlen (*unix_path) >= sizeof (s_un.sun_path)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "unixpath `%s' is too long\n", + *unix_path); + return GNUNET_SYSERR; + } + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + section, + "UNIXPATH_MODE", + &modestring)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + section, + "UNIXPATH_MODE"); + return GNUNET_SYSERR; + } + errno = 0; + *unix_mode = (mode_t) strtoul (modestring, NULL, 8); + if (0 != errno) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + "UNIXPATH_MODE", + "must be octal number"); + GNUNET_free (modestring); + return GNUNET_SYSERR; + } + GNUNET_free (modestring); + return GNUNET_OK; + } + /* not reached */ + GNUNET_assert (0); + return GNUNET_SYSERR; +} + + +/** + * Function called for logging by MHD. + * + * @param cls closure, NULL + * @param fm format string (`printf()`-style) + * @param ap arguments to @a fm + */ +void +TALER_MHD_handle_logs (void *cls, + const char *fm, + va_list ap) +{ + static int cache; + char buf[2048]; + + (void) cls; + if (-1 == cache) + return; + if (0 == cache) + { + if (0 == + GNUNET_get_log_call_status (GNUNET_ERROR_TYPE_INFO, + "libmicrohttpd", + __FILE__, + __FUNCTION__, + __LINE__)) + { + cache = -1; + return; + } + } + cache = 1; + vsnprintf (buf, + sizeof (buf), + fm, + ap); + GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_INFO, + "libmicrohttpd", + "%s", + buf); +} + + +/** + * Open UNIX domain socket for listining at @a unix_path with + * permissions @a unix_mode. + * + * @param unix_path where to listen + * @param unix_mode access permissions to set + * @return -1 on error, otherwise the listen socket + */ +int +TALER_MHD_open_unix_path (const char *unix_path, + mode_t unix_mode) +{ + struct GNUNET_NETWORK_Handle *nh; + struct sockaddr_un *un; + int fd; + + if (sizeof (un->sun_path) <= strlen (unix_path)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "unixpath `%s' is too long\n", + unix_path); + return -1; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Creating listen socket '%s' with mode %o\n", + unix_path, + unix_mode); + + if (GNUNET_OK != + GNUNET_DISK_directory_create_for_file (unix_path)) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "mkdir", + unix_path); + } + + un = GNUNET_new (struct sockaddr_un); + un->sun_family = AF_UNIX; + strncpy (un->sun_path, + unix_path, + sizeof (un->sun_path) - 1); + GNUNET_NETWORK_unix_precheck (un); + + if (NULL == (nh = GNUNET_NETWORK_socket_create (AF_UNIX, + SOCK_STREAM, + 0))) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "socket"); + GNUNET_free (un); + return -1; + } + if (GNUNET_OK != + GNUNET_NETWORK_socket_bind (nh, + (void *) un, + sizeof (struct sockaddr_un))) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "bind", + unix_path); + GNUNET_free (un); + GNUNET_NETWORK_socket_close (nh); + return -1; + } + GNUNET_free (un); + if (GNUNET_OK != + GNUNET_NETWORK_socket_listen (nh, + UNIX_BACKLOG)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "listen"); + GNUNET_NETWORK_socket_close (nh); + return -1; + } + + if (0 != chmod (unix_path, + unix_mode)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "chmod"); + GNUNET_NETWORK_socket_close (nh); + return -1; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "set socket '%s' to mode %o\n", + unix_path, + unix_mode); + fd = GNUNET_NETWORK_get_fd (nh); + GNUNET_NETWORK_socket_free_memory_only_ (nh); + return fd; +} diff --git a/src/mhd/mhd_responses.c b/src/mhd/mhd_responses.c index 24d55bfac..223381f3d 100644 --- a/src/mhd/mhd_responses.c +++ b/src/mhd/mhd_responses.c @@ -316,4 +316,95 @@ TALER_MHD_reply_request_too_large (struct MHD_Connection *connection) } +/** + * Function to call to handle the request by sending + * back a redirect to the AGPL source code. + * + * @param connection the MHD connection to handle + * @param url where to redirect for the sources + * @return MHD result code + */ +int +TALER_MHD_reply_agpl (struct MHD_Connection *connection, + const char *url) +{ + const char *agpl = + "This server is licensed under the Affero GPL. You will now be redirected to the source code."; + struct MHD_Response *response; + int ret; + + response = MHD_create_response_from_buffer (strlen (agpl), + (void *) agpl, + MHD_RESPMEM_PERSISTENT); + if (NULL == response) + { + GNUNET_break (0); + return MHD_NO; + } + TALER_MHD_add_global_headers (response); + GNUNET_break (MHD_YES == + MHD_add_response_header (response, + MHD_HTTP_HEADER_CONTENT_TYPE, + "text/plain")); + if (MHD_NO == + MHD_add_response_header (response, + MHD_HTTP_HEADER_LOCATION, + url)) + { + GNUNET_break (0); + MHD_destroy_response (response); + return MHD_NO; + } + ret = MHD_queue_response (connection, + MHD_HTTP_FOUND, + response); + MHD_destroy_response (response); + return ret; +} + + +/** + * Function to call to handle the request by sending + * back static data. + * + * @param rh context of the handler + * @param connection the MHD connection to handle + * @param http_status status code to return + * @param mime_type content-type to use + * @param body response payload + * @param body_size number of bytes in @a body + * @return MHD result code + */ +int +TALER_MHD_reply_static (struct MHD_Connection *connection, + unsigned int http_status, + const char *mime_type, + const char *body, + size_t *body_size) +{ + struct MHD_Response *response; + int ret; + + response = MHD_create_response_from_buffer (body_size, + (void *) body, + MHD_RESPMEM_PERSISTENT); + if (NULL == response) + { + GNUNET_break (0); + return MHD_NO; + } + TEH_RESPONSE_add_global_headers (response); + if (NULL != mime_type) + GNUNET_break (MHD_YES == + MHD_add_response_header (response, + MHD_HTTP_HEADER_CONTENT_TYPE, + mime_type)); + ret = MHD_queue_response (connection, + http_status, + response); + MHD_destroy_response (response); + return ret; +} + + /* end of mhd_responses.c */ -- cgit v1.2.3 From c693ec4a3ea797618bee867244f8affe034028b9 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 17:48:45 +0100 Subject: fix warnings --- src/include/taler_mhd_lib.h | 2 +- src/mhd/mhd_responses.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/include/taler_mhd_lib.h b/src/include/taler_mhd_lib.h index 979f83854..17783f1c4 100644 --- a/src/include/taler_mhd_lib.h +++ b/src/include/taler_mhd_lib.h @@ -183,7 +183,7 @@ TALER_MHD_reply_static (struct MHD_Connection *connection, unsigned int http_status, const char *mime_type, const char *body, - size_t *body_size); + size_t body_size); /** diff --git a/src/mhd/mhd_responses.c b/src/mhd/mhd_responses.c index 223381f3d..e1609d996 100644 --- a/src/mhd/mhd_responses.c +++ b/src/mhd/mhd_responses.c @@ -380,7 +380,7 @@ TALER_MHD_reply_static (struct MHD_Connection *connection, unsigned int http_status, const char *mime_type, const char *body, - size_t *body_size) + size_t body_size) { struct MHD_Response *response; int ret; @@ -393,7 +393,7 @@ TALER_MHD_reply_static (struct MHD_Connection *connection, GNUNET_break (0); return MHD_NO; } - TEH_RESPONSE_add_global_headers (response); + TALER_MHD_add_global_headers (response); if (NULL != mime_type) GNUNET_break (MHD_YES == MHD_add_response_header (response, -- cgit v1.2.3 From 062bbbb2d713223a7b18bc19bd048c0f40e3cbb3 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 17:53:42 +0100 Subject: first uses of libtalermhd --- src/exchange/Makefile.am | 1 + src/exchange/taler-exchange-httpd.c | 273 ++---------------------------------- 2 files changed, 16 insertions(+), 258 deletions(-) (limited to 'src') diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am index b5419a7a6..899e98d2e 100644 --- a/src/exchange/Makefile.am +++ b/src/exchange/Makefile.am @@ -63,6 +63,7 @@ taler_exchange_httpd_SOURCES = \ taler_exchange_httpd_LDADD = \ $(LIBGCRYPT_LIBS) \ $(top_builddir)/src/wire/libtalerwire.la \ + $(top_builddir)/src/mhd/libtalermhd.la \ $(top_builddir)/src/json/libtalerjson.la \ $(top_builddir)/src/exchangedb/libtalerexchangedb.la \ $(top_builddir)/src/util/libtalerutil.la \ diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index af38a605a..07378120e 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -27,6 +27,7 @@ #include #include #include +#include "taler_mhd_lib.h" #include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_mhd.h" #include "taler-exchange-httpd_deposit.h" @@ -486,122 +487,6 @@ handle_mhd_request (void *cls, } -/** - * Parse the configuration to determine on which port - * or UNIX domain path we should run an HTTP service. - * - * @param section section of the configuration to parse (usually "exchange") - * @param[out] rport set to the port number, or 0 for none - * @param[out] unix_path set to the UNIX path, or NULL for none - * @param[out] unix_mode set to the mode to be used for @a unix_path - * @return #GNUNET_OK on success - */ -static int -parse_port_config (const char *section, - uint16_t *rport, - char **unix_path, - mode_t *unix_mode) -{ - const char *choices[] = {"tcp", "unix"}; - const char *serve_type; - unsigned long long port; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_choice (cfg, - section, - "serve", - choices, - &serve_type)) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - section, - "serve", - "serve type required"); - return GNUNET_SYSERR; - } - - if (0 == strcasecmp (serve_type, "tcp")) - { - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, - section, - "port", - &port)) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - section, - "port", - "port number required"); - return GNUNET_SYSERR; - } - - if ( (0 == port) || - (port > UINT16_MAX) ) - { - fprintf (stderr, - "Invalid configuration (value out of range): %llu is not a valid port\n", - port); - return GNUNET_SYSERR; - } - *rport = (uint16_t) port; - *unix_path = NULL; - return GNUNET_OK; - } - if (0 == strcmp (serve_type, "unix")) - { - struct sockaddr_un s_un; - char *modestring; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (cfg, - section, - "unixpath", - unix_path)) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - section, - "unixpath", - "unixpath required"); - return GNUNET_SYSERR; - } - if (strlen (*unix_path) >= sizeof (s_un.sun_path)) - { - fprintf (stderr, - "Invalid configuration: unix path too long\n"); - return GNUNET_SYSERR; - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - section, - "UNIXPATH_MODE", - &modestring)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - section, - "UNIXPATH_MODE"); - return GNUNET_SYSERR; - } - errno = 0; - *unix_mode = (mode_t) strtoul (modestring, NULL, 8); - if (0 != errno) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - section, - "UNIXPATH_MODE", - "must be octal number"); - GNUNET_free (modestring); - return GNUNET_SYSERR; - } - GNUNET_free (modestring); - return GNUNET_OK; - } - /* not reached */ - GNUNET_assert (0); - return GNUNET_SYSERR; -} - - /** * Load configuration parameters for the exchange * server into the corresponding global variables. @@ -717,10 +602,11 @@ exchange_serve_process_config () } if (GNUNET_OK != - parse_port_config ("exchange", - &serve_port, - &serve_unixpath, - &unixpath_mode)) + TALER_MHD_parse_config (cfg, + "exchange", + &serve_port, + &serve_unixpath, + &unixpath_mode)) { TEH_VALIDATION_done (); return GNUNET_SYSERR; @@ -843,141 +729,6 @@ connection_done (void *cls, /* end of HAVE_DEVELOPER */ #endif -/** - * Function called for logging by MHD. - * - * @param cls closure, NULL - * @param fm format string (`printf()`-style) - * @param ap arguments to @a fm - */ -static void -handle_mhd_logs (void *cls, - const char *fm, - va_list ap) -{ - static int cache; - char buf[2048]; - - (void) cls; - if (-1 == cache) - return; - if (0 == cache) - { - if (0 == - GNUNET_get_log_call_status (GNUNET_ERROR_TYPE_INFO, - "libmicrohttpd", - __FILE__, - __FUNCTION__, - __LINE__)) - { - cache = -1; - return; - } - } - cache = 1; - vsnprintf (buf, - sizeof (buf), - fm, - ap); - GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_INFO, - "libmicrohttpd", - "%s", - buf); -} - - -/** - * Open UNIX domain socket for listining at @a unix_path with - * permissions @a unix_mode. - * - * @param unix_path where to listen - * @param unix_mode access permissions to set - * @return -1 on error, otherwise the listen socket - */ -static int -open_unix_path (const char *unix_path, - mode_t unix_mode) -{ - struct GNUNET_NETWORK_Handle *nh; - struct sockaddr_un *un; - int fd; - - if (sizeof (un->sun_path) <= strlen (unix_path)) - { - fprintf (stderr, - "unixpath `%s' too long\n", - unix_path); - return -1; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Creating listen socket '%s' with mode %o\n", - unix_path, - unix_mode); - - if (GNUNET_OK != - GNUNET_DISK_directory_create_for_file (unix_path)) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "mkdir", - unix_path); - } - - un = GNUNET_new (struct sockaddr_un); - un->sun_family = AF_UNIX; - strncpy (un->sun_path, - unix_path, - sizeof (un->sun_path) - 1); - GNUNET_NETWORK_unix_precheck (un); - - if (NULL == (nh = GNUNET_NETWORK_socket_create (AF_UNIX, - SOCK_STREAM, - 0))) - { - fprintf (stderr, - "create failed for AF_UNIX\n"); - GNUNET_free (un); - return -1; - } - if (GNUNET_OK != - GNUNET_NETWORK_socket_bind (nh, - (void *) un, - sizeof (struct sockaddr_un))) - { - fprintf (stderr, - "bind failed for AF_UNIX\n"); - GNUNET_free (un); - GNUNET_NETWORK_socket_close (nh); - return -1; - } - GNUNET_free (un); - if (GNUNET_OK != - GNUNET_NETWORK_socket_listen (nh, - UNIX_BACKLOG)) - { - fprintf (stderr, - "listen failed for AF_UNIX\n"); - GNUNET_NETWORK_socket_close (nh); - return -1; - } - - if (0 != chmod (unix_path, - unix_mode)) - { - fprintf (stderr, - "chmod failed: %s\n", - strerror (errno)); - GNUNET_NETWORK_socket_close (nh); - return -1; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "set socket '%s' to mode %o\n", - unix_path, - unix_mode); - fd = GNUNET_NETWORK_get_fd (nh); - GNUNET_NETWORK_socket_free_memory_only_ (nh); - return fd; -} - /** * Called when the main thread exits, writes out performance @@ -1074,12 +825,17 @@ main (int argc, const char *listen_pid; const char *listen_fds; int fh = -1; + enum TALER_MHD_GlobalOptions go; if (0 >= GNUNET_GETOPT_run ("taler-exchange-httpd", options, argc, argv)) return 1; + go = TALER_MHD_GO_NONE; + if (TEH_exchange_connection_close) + go |= TALER_MHD_GO_FORCE_CONNECTION_CLOSE; + TALER_MHD_setup (go); GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("taler-exchange-httpd", (NULL == loglev) ? "INFO" : loglev, @@ -1138,8 +894,8 @@ main (int argc, if ( (-1 == fh) && (NULL != serve_unixpath) ) { - fh = open_unix_path (serve_unixpath, - unixpath_mode); + fh = TALER_MHD_open_unix_path (serve_unixpath, + unixpath_mode); if (-1 == fh) return 1; } @@ -1155,7 +911,8 @@ main (int argc, MHD_OPTION_THREAD_POOL_SIZE, (unsigned int) 32, MHD_OPTION_LISTEN_BACKLOG_SIZE, (unsigned int) 1024, MHD_OPTION_LISTEN_SOCKET, fh, - MHD_OPTION_EXTERNAL_LOGGER, &handle_mhd_logs, NULL, + MHD_OPTION_EXTERNAL_LOGGER, &TALER_MHD_handle_logs, + NULL, MHD_OPTION_NOTIFY_COMPLETED, &handle_mhd_completion_callback, NULL, MHD_OPTION_CONNECTION_TIMEOUT, connection_timeout, -- cgit v1.2.3 From 8bca461ea9f604e4bce279255663f207f0d104ac Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 17:55:47 +0100 Subject: first uses of libtalermhd --- src/auditor/Makefile.am | 1 + src/auditor/taler-auditor-httpd.c | 268 ++------------------------------------ 2 files changed, 11 insertions(+), 258 deletions(-) (limited to 'src') diff --git a/src/auditor/Makefile.am b/src/auditor/Makefile.am index e3600e20f..c04fb167e 100644 --- a/src/auditor/Makefile.am +++ b/src/auditor/Makefile.am @@ -23,6 +23,7 @@ taler_auditor_dbinit_SOURCES = \ taler-auditor-dbinit.c taler_auditor_dbinit_LDADD = \ $(LIBGCRYPT_LIBS) \ + $(top_builddir)/src/mhd/libtalermhd.la \ $(top_builddir)/src/util/libtalerutil.la \ $(top_builddir)/src/pq/libtalerpq.la \ $(top_builddir)/src/auditordb/libtalerauditordb.la \ diff --git a/src/auditor/taler-auditor-httpd.c b/src/auditor/taler-auditor-httpd.c index e37b4a0e8..f0e735c01 100644 --- a/src/auditor/taler-auditor-httpd.c +++ b/src/auditor/taler-auditor-httpd.c @@ -27,6 +27,7 @@ #include #include #include +#include "taler_mhd_lib.h" #include "taler_auditordb_lib.h" #include "taler-auditor-httpd_deposit-confirmation.h" #include "taler-auditor-httpd_exchanges.h" @@ -427,122 +428,6 @@ handle_mhd_request (void *cls, } -/** - * Parse the configuration to determine on which port - * or UNIX domain path we should run an HTTP service. - * - * @param section section of the configuration to parse ("auditor" or "auditor-admin") - * @param[out] rport set to the port number, or 0 for none - * @param[out] unix_path set to the UNIX path, or NULL for none - * @param[out] unix_mode set to the mode to be used for @a unix_path - * @return #GNUNET_OK on success - */ -static int -parse_port_config (const char *section, - uint16_t *rport, - char **unix_path, - mode_t *unix_mode) -{ - const char *choices[] = {"tcp", "unix"}; - const char *serve_type; - unsigned long long port; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_choice (cfg, - section, - "serve", - choices, - &serve_type)) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - section, - "serve", - "serve type required"); - return GNUNET_SYSERR; - } - - if (0 == strcmp (serve_type, "tcp")) - { - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, - section, - "port", - &port)) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - section, - "port", - "port number required"); - return GNUNET_SYSERR; - } - - if ( (0 == port) || - (port > UINT16_MAX) ) - { - fprintf (stderr, - "Invalid configuration (value out of range): %llu is not a valid port\n", - port); - return GNUNET_SYSERR; - } - *rport = (uint16_t) port; - *unix_path = NULL; - return GNUNET_OK; - } - if (0 == strcmp (serve_type, "unix")) - { - struct sockaddr_un s_un; - char *modestring; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (cfg, - section, - "unixpath", - unix_path)) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - section, - "unixpath", - "unixpath required"); - return GNUNET_SYSERR; - } - if (strlen (*unix_path) >= sizeof (s_un.sun_path)) - { - fprintf (stderr, - "Invalid configuration: unix path too long\n"); - return GNUNET_SYSERR; - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - section, - "UNIXPATH_MODE", - &modestring)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - section, - "UNIXPATH_MODE"); - return GNUNET_SYSERR; - } - errno = 0; - *unix_mode = (mode_t) strtoul (modestring, NULL, 8); - if (0 != errno) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - section, - "UNIXPATH_MODE", - "must be octal number"); - GNUNET_free (modestring); - return GNUNET_SYSERR; - } - GNUNET_free (modestring); - return GNUNET_OK; - } - /* not reached */ - GNUNET_assert (0); - return GNUNET_SYSERR; -} - - /** * Load configuration parameters for the auditor * server into the corresponding global variables. @@ -562,10 +447,11 @@ auditor_serve_process_config () return GNUNET_SYSERR; } if (GNUNET_OK != - parse_port_config ("auditor", - &serve_port, - &serve_unixpath, - &unixpath_mode)) + TALER_MHD_parse_config (cfg, + "auditor", + &serve_port, + &serve_unixpath, + &unixpath_mode)) { return GNUNET_SYSERR; } @@ -640,141 +526,6 @@ auditor_serve_process_config () } -/** - * Function called for logging by MHD. - * - * @param cls closure, NULL - * @param fm format string (`printf()`-style) - * @param ap arguments to @a fm - */ -static void -handle_mhd_logs (void *cls, - const char *fm, - va_list ap) -{ - static int cache; - char buf[2048]; - - if (-1 == cache) - return; - if (0 == cache) - { - if (0 == - GNUNET_get_log_call_status (GNUNET_ERROR_TYPE_INFO, - "auditor-httpd", - __FILE__, - __FUNCTION__, - __LINE__)) - { - cache = -1; - return; - } - } - cache = 1; - vsnprintf (buf, - sizeof (buf), - fm, - ap); - GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_INFO, - "auditor-httpd", - "%s", - buf); -} - - -/** - * Open UNIX domain socket for listining at @a unix_path with - * permissions @a unix_mode. - * - * @param unix_path where to listen - * @param unix_mode access permissions to set - * @return -1 on error, otherwise the listen socket - */ -static int -open_unix_path (const char *unix_path, - mode_t unix_mode) -{ - struct GNUNET_NETWORK_Handle *nh; - struct sockaddr_un *un; - int fd; - - if (sizeof (un->sun_path) <= strlen (unix_path)) - { - fprintf (stderr, - "unixpath `%s' too long\n", - unix_path); - return -1; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Creating listen socket '%s' with mode %o\n", - unix_path, - unix_mode); - - if (GNUNET_OK != - GNUNET_DISK_directory_create_for_file (unix_path)) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "mkdir", - unix_path); - } - - un = GNUNET_new (struct sockaddr_un); - un->sun_family = AF_UNIX; - strncpy (un->sun_path, - unix_path, - sizeof (un->sun_path) - 1); - GNUNET_NETWORK_unix_precheck (un); - - if (NULL == (nh = GNUNET_NETWORK_socket_create (AF_UNIX, - SOCK_STREAM, - 0))) - { - fprintf (stderr, - "create failed for AF_UNIX\n"); - GNUNET_free (un); - return -1; - } - if (GNUNET_OK != - GNUNET_NETWORK_socket_bind (nh, - (void *) un, - sizeof (struct sockaddr_un))) - { - fprintf (stderr, - "bind failed for AF_UNIX\n"); - GNUNET_free (un); - GNUNET_NETWORK_socket_close (nh); - return -1; - } - GNUNET_free (un); - if (GNUNET_OK != - GNUNET_NETWORK_socket_listen (nh, - UNIX_BACKLOG)) - { - fprintf (stderr, - "listen failed for AF_UNIX\n"); - GNUNET_NETWORK_socket_close (nh); - return -1; - } - - if (0 != chmod (unix_path, - unix_mode)) - { - fprintf (stderr, - "chmod failed: %s\n", - strerror (errno)); - GNUNET_NETWORK_socket_close (nh); - return -1; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "set socket '%s' to mode %o\n", - unix_path, - unix_mode); - fd = GNUNET_NETWORK_get_fd (nh); - GNUNET_NETWORK_socket_free_memory_only_ (nh); - return fd; -} - - /** * The main function of the taler-auditor-httpd server ("the auditor"). * @@ -877,8 +628,8 @@ main (int argc, if ( (-1 == fh) && (NULL != serve_unixpath) ) { - fh = open_unix_path (serve_unixpath, - unixpath_mode); + fh = TALER_MHD_open_unix_path (serve_unixpath, + unixpath_mode); if (-1 == fh) return 1; } @@ -894,7 +645,8 @@ main (int argc, MHD_OPTION_THREAD_POOL_SIZE, (unsigned int) 32, MHD_OPTION_LISTEN_BACKLOG_SIZE, (unsigned int) 1024, MHD_OPTION_LISTEN_SOCKET, fh, - MHD_OPTION_EXTERNAL_LOGGER, &handle_mhd_logs, NULL, + MHD_OPTION_EXTERNAL_LOGGER, &TALER_MHD_handle_logs, + NULL, MHD_OPTION_NOTIFY_COMPLETED, &handle_mhd_completion_callback, NULL, MHD_OPTION_CONNECTION_TIMEOUT, connection_timeout, -- cgit v1.2.3 From e8a88392da98c3325ba39b20901a5c220158d1f5 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 18:47:07 +0100 Subject: more refactoring towards using libtalermhd --- src/auditor/Makefile.am | 2 +- src/auditor/taler-auditor-httpd.c | 19 +- src/auditor/taler-auditor-httpd_mhd.c | 40 +--- src/auditor/taler-auditor-httpd_responses.c | 3 +- src/exchange/taler-exchange-httpd.c | 1 - src/exchange/taler-exchange-httpd_deposit.c | 109 +++++----- src/exchange/taler-exchange-httpd_keystate.c | 24 ++- src/exchange/taler-exchange-httpd_mhd.c | 36 +--- src/exchange/taler-exchange-httpd_payback.c | 97 +++++---- src/exchange/taler-exchange-httpd_refresh_link.c | 21 +- src/exchange/taler-exchange-httpd_refresh_melt.c | 136 ++++++------ src/exchange/taler-exchange-httpd_refresh_reveal.c | 138 +++++++------ src/exchange/taler-exchange-httpd_responses.c | 20 +- src/exchange/taler-exchange-httpd_responses.h | 227 +-------------------- 14 files changed, 331 insertions(+), 542 deletions(-) (limited to 'src') diff --git a/src/auditor/Makefile.am b/src/auditor/Makefile.am index c04fb167e..6d0c81582 100644 --- a/src/auditor/Makefile.am +++ b/src/auditor/Makefile.am @@ -23,7 +23,6 @@ taler_auditor_dbinit_SOURCES = \ taler-auditor-dbinit.c taler_auditor_dbinit_LDADD = \ $(LIBGCRYPT_LIBS) \ - $(top_builddir)/src/mhd/libtalermhd.la \ $(top_builddir)/src/util/libtalerutil.la \ $(top_builddir)/src/pq/libtalerpq.la \ $(top_builddir)/src/auditordb/libtalerauditordb.la \ @@ -58,6 +57,7 @@ taler_auditor_httpd_SOURCES = \ taler-auditor-httpd_responses.c taler-auditor-httpd_responses.h taler_auditor_httpd_LDADD = \ $(LIBGCRYPT_LIBS) \ + $(top_builddir)/src/mhd/libtalermhd.la \ $(top_builddir)/src/util/libtalerutil.la \ $(top_builddir)/src/json/libtalerjson.la \ $(top_builddir)/src/wire/libtalerwire.la \ diff --git a/src/auditor/taler-auditor-httpd.c b/src/auditor/taler-auditor-httpd.c index f0e735c01..fa4f572ec 100644 --- a/src/auditor/taler-auditor-httpd.c +++ b/src/auditor/taler-auditor-httpd.c @@ -385,7 +385,7 @@ handle_mhd_request (void *cls, &TAH_MHD_handler_static_response, 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 + source. We make this easy by including a redirect t the source here. */ { "/agpl", MHD_HTTP_METHOD_GET, "text/plain", NULL, 0, @@ -393,11 +393,6 @@ handle_mhd_request (void *cls, { NULL, NULL, NULL, NULL, 0, 0 } }; - static struct TAH_RequestHandler h404 = { - "", NULL, "text/html", - "404: not found", 0, - &TAH_MHD_handler_static_response, MHD_HTTP_NOT_FOUND - }; struct TAH_RequestHandler *rh; GNUNET_log (GNUNET_ERROR_TYPE_INFO, @@ -420,11 +415,13 @@ handle_mhd_request (void *cls, upload_data, upload_data_size); } - return TAH_MHD_handler_static_response (&h404, - connection, - con_cls, - upload_data, - upload_data_size); +#define NOT_FOUND "404: not found" + return TALER_MHD_reply_static (connection, + MHD_HTTP_NOT_FOUND, + "text/html", + NOT_FOUND, + strlen (NOT_FOUND)); +#undef NOT_FOUND } diff --git a/src/auditor/taler-auditor-httpd_mhd.c b/src/auditor/taler-auditor-httpd_mhd.c index 5f13691f5..6613ddb0d 100644 --- a/src/auditor/taler-auditor-httpd_mhd.c +++ b/src/auditor/taler-auditor-httpd_mhd.c @@ -28,6 +28,8 @@ #include #include #include +#include "taler_mhd_lib.h" +#include "taler-auditor-httpd_responses.h" #include "taler-auditor-httpd_responses.h" #include "taler-auditor-httpd.h" #include "taler-auditor-httpd_mhd.h" @@ -94,38 +96,12 @@ TAH_MHD_handler_agpl_redirect (struct TAH_RequestHandler *rh, const char *upload_data, size_t *upload_data_size) { - const char *agpl = - "This server is licensed under the Affero GPL. You will now be redirected to the source code."; - struct MHD_Response *response; - int ret; - - response = MHD_create_response_from_buffer (strlen (agpl), - (void *) agpl, - MHD_RESPMEM_PERSISTENT); - if (NULL == response) - { - GNUNET_break (0); - return MHD_NO; - } - TAH_RESPONSE_add_global_headers (response); - if (NULL != rh->mime_type) - (void) MHD_add_response_header (response, - MHD_HTTP_HEADER_CONTENT_TYPE, - rh->mime_type); - if (MHD_NO == - MHD_add_response_header (response, - MHD_HTTP_HEADER_LOCATION, - "http://www.git.taler.net/?p=auditor.git")) - { - GNUNET_break (0); - MHD_destroy_response (response); - return MHD_NO; - } - ret = MHD_queue_response (connection, - rh->response_code, - response); - MHD_destroy_response (response); - return ret; + (void) rh; + (void) connection_cls; + (void) upload_data; + (void) upload_data_size; + return TALER_MHD_reply_agpl (connection, + "http://www.git.taler.net/?p=exchange.git"); } diff --git a/src/auditor/taler-auditor-httpd_responses.c b/src/auditor/taler-auditor-httpd_responses.c index 4c7b429e3..2f78fb0f5 100644 --- a/src/auditor/taler-auditor-httpd_responses.c +++ b/src/auditor/taler-auditor-httpd_responses.c @@ -14,7 +14,7 @@ TALER; see the file COPYING. If not, see */ /** - * @file taler-exchange-httpd_responses.c + * @file taler-auditor-httpd_responses.c * @brief API for generating genric replies of the exchange; these * functions are called TAH_RESPONSE_reply_ and they generate * and queue MHD response objects for a given connection. @@ -24,6 +24,7 @@ */ #include "platform.h" #include +#include "taler_mhd_lib.h" #include "taler-auditor-httpd_responses.h" #include "taler_util.h" #include "taler_json_lib.h" diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index 07378120e..b3f73de60 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -737,7 +737,6 @@ connection_done (void *cls, static void write_stats () { - struct GNUNET_DISK_FileHandle *fh; pid_t pid = getpid (); char *benchmark_dir; diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c index fd36bb4a0..7e71dcaa6 100644 --- a/src/exchange/taler-exchange-httpd_deposit.c +++ b/src/exchange/taler-exchange-httpd_deposit.c @@ -29,6 +29,7 @@ #include #include #include "taler_json_lib.h" +#include "taler_mhd_lib.h" #include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_deposit.h" #include "taler-exchange-httpd_responses.h" @@ -83,17 +84,17 @@ reply_deposit_success (struct MHD_Connection *connection, &pub, &sig)) { - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_EXCHANGE_BAD_CONFIGURATION, - "no keys"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_EXCHANGE_BAD_CONFIGURATION, + "no keys"); } - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:s, s:o, s:o}", - "status", "DEPOSIT_OK", - "sig", GNUNET_JSON_from_data_auto (&sig), - "pub", GNUNET_JSON_from_data_auto ( - &pub)); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:s, s:o, s:o}", + "status", "DEPOSIT_OK", + "sig", GNUNET_JSON_from_data_auto (&sig), + "pub", GNUNET_JSON_from_data_auto (&pub)); } @@ -149,8 +150,10 @@ deposit_transaction (void *cls, { if (GNUNET_DB_STATUS_HARD_ERROR == qs) { - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_DEPOSIT_HISTORY_DB_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_DEPOSIT_HISTORY_DB_ERROR, + "Could not check for existing identical deposit"); return GNUNET_DB_STATUS_HARD_ERROR; } return qs; @@ -197,8 +200,10 @@ deposit_transaction (void *cls, { TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, tl); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_DEPOSIT_HISTORY_DB_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_DEPOSIT_HISTORY_DB_ERROR, + "could not access coin history"); return GNUNET_DB_STATUS_HARD_ERROR; } /* Check that cost of all transactions is smaller than @@ -223,8 +228,10 @@ deposit_transaction (void *cls, if (GNUNET_DB_STATUS_HARD_ERROR == qs) { TALER_LOG_WARNING ("Failed to store /deposit information in database\n"); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_DEPOSIT_STORE_DB_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_DEPOSIT_STORE_DB_ERROR, + "Could not persist /deposit data"); } return qs; } @@ -273,9 +280,10 @@ verify_and_execute_deposit (struct MHD_Connection *connection, &deposit->coin.coin_pub.eddsa_pub)) { TALER_LOG_WARNING ("Invalid signature on /deposit request\n"); - return TEH_RESPONSE_reply_signature_invalid (connection, - TALER_EC_DEPOSIT_COIN_SIGNATURE_INVALID, - "coin_sig"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_UNAUTHORIZED, + TALER_EC_DEPOSIT_COIN_SIGNATURE_INVALID, + "coin_sig"); } /* check denomination */ @@ -295,9 +303,10 @@ verify_and_execute_deposit (struct MHD_Connection *connection, if (NULL == dki) { TEH_KS_release (mks); - return TEH_RESPONSE_reply_with_error (connection, - ec, - hc); + return TALER_MHD_reply_with_error (connection, + ec, + hc, + "Could not find denomination key used in deposit"); } TALER_amount_ntoh (&dc.value, &dki->issue.properties.value); @@ -445,9 +454,10 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, { GNUNET_break_op (0); GNUNET_JSON_parse_free (spec); - return TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE, - "refund_deadline"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE, + "refund_deadline"); } if (TALER_EC_NONE != @@ -466,9 +476,10 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, { GNUNET_break_op (0); GNUNET_JSON_parse_free (spec); - return TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_DEPOSIT_INVALID_TIMESTAMP, - "timestamp"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_DEPOSIT_INVALID_TIMESTAMP, + "timestamp"); } if (GNUNET_OK != TALER_JSON_merchant_wire_signature_hash (wire, @@ -477,18 +488,20 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, TALER_LOG_WARNING ( "Failed to parse JSON wire format specification for /deposit request\n"); GNUNET_JSON_parse_free (spec); - return TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_JSON, - "wire"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_JSON, + "wire"); } if (0 != GNUNET_memcmp (&deposit.h_wire, &my_h_wire)) { /* Client hashed contract differently than we did, reject */ GNUNET_JSON_parse_free (spec); - return TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_CONTRACT_HASH_CONFLICT, - "H_wire"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_CONTRACT_HASH_CONFLICT, + "H_wire"); } /* check denomination exists and is valid */ @@ -497,9 +510,10 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, { TALER_LOG_ERROR ("Lacking keys to operate\n"); GNUNET_JSON_parse_free (spec); - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_EXCHANGE_BAD_CONFIGURATION, - "no keys"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_EXCHANGE_BAD_CONFIGURATION, + "no keys"); } dki = TEH_KS_denomination_key_lookup_by_hash (key_state, &deposit.coin.denom_pub_hash, @@ -511,9 +525,10 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, TEH_KS_release (key_state); TALER_LOG_WARNING ("Unknown denomination key in /deposit request\n"); GNUNET_JSON_parse_free (spec); - return TEH_RESPONSE_reply_with_error (connection, - ec, - hc); + return TALER_MHD_reply_with_error (connection, + ec, + hc, + "Could not find denomination key used in deposit"); } TALER_amount_ntoh (&deposit.deposit_fee, &dki->issue.properties.fee_deposit); @@ -525,9 +540,10 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, TALER_LOG_WARNING ("Invalid coin passed for /deposit\n"); TEH_KS_release (key_state); GNUNET_JSON_parse_free (spec); - return TEH_RESPONSE_reply_signature_invalid (connection, - TALER_EC_DEPOSIT_DENOMINATION_SIGNATURE_INVALID, - "ub_sig"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_UNAUTHORIZED, + TALER_EC_DEPOSIT_DENOMINATION_SIGNATURE_INVALID, + "ub_sig"); } TALER_amount_ntoh (&deposit.deposit_fee, &dki->issue.properties.fee_deposit); @@ -538,9 +554,10 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, { GNUNET_break_op (0); GNUNET_JSON_parse_free (spec); - return TEH_RESPONSE_reply_external_error (connection, - TALER_EC_DEPOSIT_NEGATIVE_VALUE_AFTER_FEE, - "deposited amount smaller than depositing fee"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_DEPOSIT_NEGATIVE_VALUE_AFTER_FEE, + "deposited amount smaller than depositing fee"); } /* make sure coin is 'known' in database */ diff --git a/src/exchange/taler-exchange-httpd_keystate.c b/src/exchange/taler-exchange-httpd_keystate.c index bde5c7d7e..7297a741b 100644 --- a/src/exchange/taler-exchange-httpd_keystate.c +++ b/src/exchange/taler-exchange-httpd_keystate.c @@ -23,6 +23,7 @@ #include "platform.h" #include #include "taler_json_lib.h" +#include "taler_mhd_lib.h" #include "taler-exchange-httpd_keystate.h" #include "taler-exchange-httpd_responses.h" #include "taler_exchangedb_plugin.h" @@ -2378,9 +2379,10 @@ TEH_KS_handler_keys (struct TEH_RequestHandler *rh, &cherrypickn)) { GNUNET_break_op (0); - return TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_KEYS_HAVE_NOT_NUMERIC, - "last_issue_date"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_KEYS_HAVE_NOT_NUMERIC, + "last_issue_date"); } last_issue_date.abs_value_us = (uint64_t) cherrypickn * 1000000LLU; } @@ -2402,9 +2404,10 @@ TEH_KS_handler_keys (struct TEH_RequestHandler *rh, &fakenown)) { GNUNET_break_op (0); - return TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_KEYS_HAVE_NOT_NUMERIC, - "now"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_KEYS_HAVE_NOT_NUMERIC, + "now"); } now.abs_value_us = (uint64_t) fakenown * 1000000LLU; } @@ -2413,9 +2416,10 @@ TEH_KS_handler_keys (struct TEH_RequestHandler *rh, if (NULL == key_state) { TALER_LOG_ERROR ("Lacking keys to operate\n"); - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_EXCHANGE_BAD_CONFIGURATION, - "no keys"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_EXCHANGE_BAD_CONFIGURATION, + "no keys"); } krd = bsearch (&last_issue_date, key_state->krd_array, @@ -2444,7 +2448,7 @@ TEH_KS_handler_keys (struct TEH_RequestHandler *rh, } ret = MHD_queue_response (connection, rh->response_code, - (MHD_YES == TEH_RESPONSE_can_compress (connection)) + (MHD_YES == TALER_MHD_can_compress (connection)) ? krd->response_compressed : krd->response_uncompressed); TEH_KS_release (key_state); diff --git a/src/exchange/taler-exchange-httpd_mhd.c b/src/exchange/taler-exchange-httpd_mhd.c index 95e51c8ed..36d10bae3 100644 --- a/src/exchange/taler-exchange-httpd_mhd.c +++ b/src/exchange/taler-exchange-httpd_mhd.c @@ -28,6 +28,7 @@ #include #include #include +#include "taler_mhd_lib.h" #include "taler-exchange-httpd_responses.h" #include "taler-exchange-httpd.h" #include "taler-exchange-httpd_mhd.h" @@ -97,41 +98,12 @@ TEH_MHD_handler_agpl_redirect (struct TEH_RequestHandler *rh, const char *upload_data, size_t *upload_data_size) { - const char *agpl = - "This server is licensed under the Affero GPL. You will now be redirected to the source code."; - struct MHD_Response *response; - int ret; - + (void) rh; (void) connection_cls; (void) upload_data; (void) upload_data_size; - response = MHD_create_response_from_buffer (strlen (agpl), - (void *) agpl, - MHD_RESPMEM_PERSISTENT); - if (NULL == response) - { - GNUNET_break (0); - return MHD_NO; - } - TEH_RESPONSE_add_global_headers (response); - if (NULL != rh->mime_type) - (void) MHD_add_response_header (response, - MHD_HTTP_HEADER_CONTENT_TYPE, - rh->mime_type); - if (MHD_NO == - MHD_add_response_header (response, - MHD_HTTP_HEADER_LOCATION, - "http://www.git.taler.net/?p=exchange.git")) - { - GNUNET_break (0); - MHD_destroy_response (response); - return MHD_NO; - } - ret = MHD_queue_response (connection, - rh->response_code, - response); - MHD_destroy_response (response); - return ret; + return TALER_MHD_reply_agpl (connection, + "http://www.git.taler.net/?p=exchange.git"); } diff --git a/src/exchange/taler-exchange-httpd_payback.c b/src/exchange/taler-exchange-httpd_payback.c index 05a2355a3..b8adc950d 100644 --- a/src/exchange/taler-exchange-httpd_payback.c +++ b/src/exchange/taler-exchange-httpd_payback.c @@ -34,26 +34,6 @@ #include "taler-exchange-httpd_validation.h" -/** - * A wallet asked for /payback, but we do not know anything about the - * original withdraw operation specified. Generates a 404 reply. - * - * @param connection connection to the client - * @param ec Taler error code - * @return MHD result code - */ -static int -reply_payback_unknown (struct MHD_Connection *connection, - enum TALER_ErrorCode ec) -{ - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_NOT_FOUND, - "{s:s, s:I}", - "error", "blinded coin unknown", - "code", (json_int_t) ec); -} - - /** * A wallet asked for /payback, return the successful response. * @@ -268,8 +248,10 @@ payback_transaction (void *cls, if (GNUNET_DB_STATUS_HARD_ERROR == qs) { GNUNET_break (0); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_PAYBACK_DB_FETCH_FAILED); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_PAYBACK_DB_FETCH_FAILED, + "failed to fetch old coin of blind coin"); } return qs; } @@ -285,8 +267,10 @@ payback_transaction (void *cls, if (GNUNET_DB_STATUS_HARD_ERROR == qs) { GNUNET_break (0); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_PAYBACK_DB_FETCH_FAILED); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_PAYBACK_DB_FETCH_FAILED, + "failed to fetch reserve of blinded coin"); } return qs; } @@ -296,8 +280,10 @@ payback_transaction (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Payback requested for unknown envelope %s\n", GNUNET_h2s (&pc->h_blind)); - *mhd_ret = reply_payback_unknown (connection, - TALER_EC_PAYBACK_WITHDRAW_NOT_FOUND); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_PAYBACK_WITHDRAW_NOT_FOUND, + "blind coin unknown"); return GNUNET_DB_STATUS_HARD_ERROR; } @@ -312,8 +298,10 @@ payback_transaction (void *cls, if (GNUNET_DB_STATUS_HARD_ERROR == qs) { GNUNET_break (0); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_PAYBACK_DB_FETCH_FAILED); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_PAYBACK_DB_FETCH_FAILED, + "failed to fetch old coin transaction history"); } return qs; } @@ -329,8 +317,10 @@ payback_transaction (void *cls, GNUNET_break (0); TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, tl); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_PAYBACK_HISTORY_DB_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_PAYBACK_HISTORY_DB_ERROR, + "failed to calculate old coin transaction history"); return GNUNET_DB_STATUS_HARD_ERROR; } if (GNUNET_SYSERR == @@ -341,8 +331,10 @@ payback_transaction (void *cls, GNUNET_break (0); TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, tl); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_PAYBACK_COIN_BALANCE_NEGATIVE); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_PAYBACK_COIN_BALANCE_NEGATIVE, + "calculated negative old coin balance"); return GNUNET_DB_STATUS_HARD_ERROR; } if ( (0 == pc->amount.fraction) && @@ -391,8 +383,10 @@ payback_transaction (void *cls, if (GNUNET_DB_STATUS_HARD_ERROR == qs) { TALER_LOG_WARNING ("Failed to store /payback information in database\n"); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_PAYBACK_DB_PUT_FAILED); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_PAYBACK_DB_PUT_FAILED, + "failed to persist payback data"); } return qs; } @@ -437,9 +431,10 @@ verify_and_execute_payback (struct MHD_Connection *connection, if (NULL == key_state) { TALER_LOG_ERROR ("Lacking keys to operate\n"); - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_EXCHANGE_BAD_CONFIGURATION, - "no keys"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_EXCHANGE_BAD_CONFIGURATION, + "no keys"); } dki = TEH_KS_denomination_key_lookup_by_hash (key_state, &coin->denom_pub_hash, @@ -451,9 +446,10 @@ verify_and_execute_payback (struct MHD_Connection *connection, TEH_KS_release (key_state); TALER_LOG_WARNING ( "Denomination key in /payback request not in payback mode\n"); - return TEH_RESPONSE_reply_with_error (connection, - ec, - hc); + return TALER_MHD_reply_with_error (connection, + ec, + hc, + "denomination not allowing payback"); } TALER_amount_ntoh (&pc.value, &dki->issue.properties.value); @@ -465,9 +461,10 @@ verify_and_execute_payback (struct MHD_Connection *connection, { TALER_LOG_WARNING ("Invalid coin passed for /payback\n"); TEH_KS_release (key_state); - return TEH_RESPONSE_reply_signature_invalid (connection, - TALER_EC_PAYBACK_DENOMINATION_SIGNATURE_INVALID, - "denom_sig"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_PAYBACK_DENOMINATION_SIGNATURE_INVALID, + "denom_sig"); } /* check payback request signature */ @@ -485,9 +482,10 @@ verify_and_execute_payback (struct MHD_Connection *connection, { TALER_LOG_WARNING ("Invalid signature on /payback request\n"); TEH_KS_release (key_state); - return TEH_RESPONSE_reply_signature_invalid (connection, - TALER_EC_PAYBACK_SIGNATURE_INVALID, - "coin_sig"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_PAYBACK_SIGNATURE_INVALID, + "coin_sig"); } GNUNET_CRYPTO_hash (&coin->coin_pub.eddsa_pub, @@ -503,9 +501,10 @@ verify_and_execute_payback (struct MHD_Connection *connection, GNUNET_break (0); TEH_KS_release (key_state); - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_PAYBACK_BLINDING_FAILED, - "coin_bks"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_PAYBACK_BLINDING_FAILED, + "coin_bks"); } TEH_KS_release (key_state); GNUNET_CRYPTO_hash (coin_ev, diff --git a/src/exchange/taler-exchange-httpd_refresh_link.c b/src/exchange/taler-exchange-httpd_refresh_link.c index c51887a95..10aed2df8 100644 --- a/src/exchange/taler-exchange-httpd_refresh_link.c +++ b/src/exchange/taler-exchange-httpd_refresh_link.c @@ -24,6 +24,7 @@ #include #include #include +#include "taler_mhd_lib.h" #include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_mhd.h" #include "taler-exchange-httpd_refresh_link.h" @@ -156,16 +157,18 @@ refresh_link_transaction (void *cls, ctx); if (NULL == ctx->mlist) { - *mhd_ret = TEH_RESPONSE_reply_internal_error (connection, - ctx->ec, - "coin_pub"); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + ctx->ec, + "coin_pub"); return GNUNET_DB_STATUS_HARD_ERROR; } if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) { - *mhd_ret = TEH_RESPONSE_reply_arg_unknown (connection, - TALER_EC_REFRESH_LINK_COIN_UNKNOWN, - "coin_pub"); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_REFRESH_LINK_COIN_UNKNOWN, + "coin_pub"); return GNUNET_DB_STATUS_HARD_ERROR; } return qs; @@ -222,9 +225,9 @@ TEH_REFRESH_handler_refresh_link (struct TEH_RequestHandler *rh, json_decref (ctx.mlist); return mhd_ret; } - mhd_ret = TEH_RESPONSE_reply_json (connection, - ctx.mlist, - MHD_HTTP_OK); + mhd_ret = TALER_MHD_reply_json (connection, + ctx.mlist, + MHD_HTTP_OK); json_decref (ctx.mlist); return mhd_ret; } diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c b/src/exchange/taler-exchange-httpd_refresh_melt.c index a00fda14f..2de5027f1 100644 --- a/src/exchange/taler-exchange-httpd_refresh_melt.c +++ b/src/exchange/taler-exchange-httpd_refresh_melt.c @@ -24,6 +24,7 @@ #include #include #include +#include "taler_mhd_lib.h" #include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_mhd.h" #include "taler-exchange-httpd_refresh_melt.h" @@ -60,26 +61,28 @@ reply_refresh_melt_insufficient_funds (struct MHD_Connection *connection, history = TEH_RESPONSE_compile_transaction_history (tl); if (NULL == history) - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_MELT_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS); - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_FORBIDDEN, - "{s:s, s:I, s:o, s:o, s:o, s:o, s:o}", - "error", - "insufficient funds", - "code", - (json_int_t) - TALER_EC_REFRESH_MELT_INSUFFICIENT_FUNDS, - "coin_pub", - GNUNET_JSON_from_data_auto (coin_pub), - "original_value", - TALER_JSON_from_amount (&coin_value), - "residual_value", - TALER_JSON_from_amount (residual), - "requested_value", - TALER_JSON_from_amount (requested), - "history", - history); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFRESH_MELT_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS, + "Failed to compile transaction history"); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_FORBIDDEN, + "{s:s, s:I, s:o, s:o, s:o, s:o, s:o}", + "error", + "insufficient funds", + "code", + (json_int_t) + TALER_EC_REFRESH_MELT_INSUFFICIENT_FUNDS, + "coin_pub", + GNUNET_JSON_from_data_auto (coin_pub), + "original_value", + TALER_JSON_from_amount (&coin_value), + "residual_value", + TALER_JSON_from_amount (residual), + "requested_value", + TALER_JSON_from_amount (requested), + "history", + history); } @@ -110,19 +113,20 @@ reply_refresh_melt_success (struct MHD_Connection *connection, &pub, &sig)) { - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_EXCHANGE_BAD_CONFIGURATION, - "no keys"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_EXCHANGE_BAD_CONFIGURATION, + "no keys"); } sig_json = GNUNET_JSON_from_data_auto (&sig); GNUNET_assert (NULL != sig_json); - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:i, s:o, s:o}", - "noreveal_index", (int) noreveal_index, - "exchange_sig", sig_json, - "exchange_pub", - GNUNET_JSON_from_data_auto (&pub)); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:i, s:o, s:o}", + "noreveal_index", (int) noreveal_index, + "exchange_sig", sig_json, + "exchange_pub", + GNUNET_JSON_from_data_auto (&pub)); } @@ -189,8 +193,10 @@ refresh_check_melt (struct MHD_Connection *connection, if (0 > qs) { if (GNUNET_DB_STATUS_HARD_ERROR == qs) - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_MELT_DB_FETCH_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFRESH_MELT_DB_FETCH_ERROR, + "failed to fetch old coin history"); return qs; } if (rmc->zombie_required) @@ -211,9 +217,10 @@ refresh_check_melt (struct MHD_Connection *connection, GNUNET_break (0); TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, tl); - *mhd_ret = TEH_RESPONSE_reply_external_error (connection, - TALER_EC_REFRESH_MELT_COIN_EXPIRED_NO_ZOMBIE, - "denomination expired"); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_REFRESH_MELT_COIN_EXPIRED_NO_ZOMBIE, + "denomination expired"); return GNUNET_DB_STATUS_HARD_ERROR; } } @@ -225,8 +232,10 @@ refresh_check_melt (struct MHD_Connection *connection, GNUNET_break (0); TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, tl); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_MELT_COIN_HISTORY_COMPUTATION_FAILED); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFRESH_MELT_COIN_HISTORY_COMPUTATION_FAILED, + "failed to compute coin transaction history"); return GNUNET_DB_STATUS_HARD_ERROR; } @@ -310,8 +319,10 @@ refresh_melt_transaction (void *cls, if (0 > qs) { if (GNUNET_DB_STATUS_HARD_ERROR == qs) - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_MELT_DB_FETCH_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFRESH_MELT_DB_FETCH_ERROR, + "failed to fetch melt index"); return qs; } @@ -335,8 +346,10 @@ refresh_melt_transaction (void *cls, { if (GNUNET_DB_STATUS_SOFT_ERROR != qs) { - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_MELT_DB_STORE_SESSION_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFRESH_MELT_DB_STORE_SESSION_ERROR, + "failed to persist melt data"); return GNUNET_DB_STATUS_HARD_ERROR; } return qs; @@ -370,9 +383,10 @@ handle_refresh_melt (struct MHD_Connection *connection, &rmc->refresh_session.amount_with_fee) > 0) { GNUNET_break_op (0); - return TEH_RESPONSE_reply_external_error (connection, - TALER_EC_REFRESH_MELT_FEES_EXCEED_CONTRIBUTION, - "melt amount smaller than melting fee"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_REFRESH_MELT_FEES_EXCEED_CONTRIBUTION, + "melt amount smaller than melting fee"); } } @@ -398,9 +412,10 @@ handle_refresh_melt (struct MHD_Connection *connection, eddsa_pub)) { GNUNET_break_op (0); - return TEH_RESPONSE_reply_signature_invalid (connection, - TALER_EC_REFRESH_MELT_COIN_SIGNATURE_INVALID, - "confirm_sig"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_REFRESH_MELT_COIN_SIGNATURE_INVALID, + "confirm_sig"); } } @@ -492,9 +507,10 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, if (NULL == key_state) { TALER_LOG_ERROR ("Lacking keys to operate\n"); - res = TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_EXCHANGE_BAD_CONFIGURATION, - "no keys"); + res = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_EXCHANGE_BAD_CONFIGURATION, + "no keys"); goto cleanup; } @@ -530,8 +546,10 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, if (0 > qs) { GNUNET_break (0); - res = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_MELT_DB_FETCH_ERROR); + res = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFRESH_MELT_DB_FETCH_ERROR, + "failed to find information about old coin"); goto cleanup; } if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) @@ -566,9 +584,10 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, if (NULL == rmc.dki) { TALER_LOG_WARNING ("Unknown denomination key in /refresh/melt request\n"); - res = TEH_RESPONSE_reply_with_error (connection, - ec, - hc); + res = TALER_MHD_reply_with_error (connection, + ec, + hc, + "unknown denomination"); goto cleanup; } @@ -579,9 +598,10 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, GNUNET_break_op (0); GNUNET_JSON_parse_free (spec); TEH_KS_release (key_state); - return TEH_RESPONSE_reply_signature_invalid (connection, - TALER_EC_REFRESH_MELT_DENOMINATION_SIGNATURE_INVALID, - "denom_sig"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_REFRESH_MELT_DENOMINATION_SIGNATURE_INVALID, + "denom_sig"); } /* run actual logic, now that the request was parsed */ diff --git a/src/exchange/taler-exchange-httpd_refresh_reveal.c b/src/exchange/taler-exchange-httpd_refresh_reveal.c index fbfe432de..a1200f39e 100644 --- a/src/exchange/taler-exchange-httpd_refresh_reveal.c +++ b/src/exchange/taler-exchange-httpd_refresh_reveal.c @@ -24,6 +24,7 @@ #include #include #include +#include "taler_mhd_lib.h" #include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_mhd.h" #include "taler-exchange-httpd_refresh_reveal.h" @@ -84,9 +85,9 @@ reply_refresh_reveal_success (struct MHD_Connection *connection, json_object_set_new (root, "ev_sigs", list); - ret = TEH_RESPONSE_reply_json (connection, - root, - MHD_HTTP_OK); + ret = TALER_MHD_reply_json (connection, + root, + MHD_HTTP_OK); json_decref (root); } return ret; @@ -105,15 +106,15 @@ static int reply_refresh_reveal_missmatch (struct MHD_Connection *connection, const struct TALER_RefreshCommitmentP *rc) { - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_CONFLICT, - "{s:s, s:I, s:o}", - "error", "commitment violation", - "code", - (json_int_t) - TALER_EC_REFRESH_REVEAL_COMMITMENT_VIOLATION, - "rc_expected", - GNUNET_JSON_from_data_auto (rc)); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_CONFLICT, + "{s:s, s:I, s:o}", + "error", "commitment violation", + "code", + (json_int_t) + TALER_EC_REFRESH_REVEAL_COMMITMENT_VIOLATION, + "rc_expected", + GNUNET_JSON_from_data_auto (rc)); } @@ -258,8 +259,10 @@ refresh_reveal_preflight (void *cls, return qs; case GNUNET_DB_STATUS_HARD_ERROR: GNUNET_break (qs); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_REVEAL_DB_FETCH_REVEAL_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFRESH_REVEAL_DB_FETCH_REVEAL_ERROR, + "failed to fetch reveal data"); rctx->preflight_ok = GNUNET_SYSERR; return GNUNET_DB_STATUS_HARD_ERROR; case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: @@ -308,9 +311,10 @@ refresh_reveal_transaction (void *cls, &refresh_melt); if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) { - *mhd_ret = TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_REFRESH_REVEAL_SESSION_UNKNOWN, - "rc"); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_REFRESH_REVEAL_SESSION_UNKNOWN, + "rc"); return GNUNET_DB_STATUS_HARD_ERROR; } if (GNUNET_DB_STATUS_SOFT_ERROR == qs) @@ -319,8 +323,10 @@ refresh_reveal_transaction (void *cls, (refresh_melt.session.noreveal_index >= TALER_CNC_KAPPA) ) { GNUNET_break (0); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_REVEAL_DB_FETCH_SESSION_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFRESH_REVEAL_DB_FETCH_SESSION_ERROR, + "failed to fetch valid challenge from database"); return GNUNET_DB_STATUS_HARD_ERROR; } @@ -437,9 +443,10 @@ refresh_reveal_transaction (void *cls, &total)) ) { GNUNET_break_op (0); - *mhd_ret = TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_REFRESH_REVEAL_COST_CALCULATION_OVERFLOW, - "failed to add up refresh costs"); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFRESH_REVEAL_COST_CALCULATION_OVERFLOW, + "failed to add up refresh costs"); return GNUNET_DB_STATUS_HARD_ERROR; } } @@ -447,9 +454,10 @@ refresh_reveal_transaction (void *cls, &refresh_melt.session.amount_with_fee)) { GNUNET_break_op (0); - *mhd_ret = TEH_RESPONSE_reply_external_error (connection, - TALER_EC_REFRESH_REVEAL_AMOUNT_INSUFFICIENT, - "melted coin value is insufficient to cover cost of operation"); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFRESH_REVEAL_AMOUNT_INSUFFICIENT, + "melted coin value is insufficient to cover cost of operation"); return GNUNET_DB_STATUS_HARD_ERROR; } } @@ -501,8 +509,10 @@ refresh_reveal_persist (void *cls, } if (GNUNET_DB_STATUS_HARD_ERROR == qs) { - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_REVEAL_DB_COMMIT_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFRESH_REVEAL_DB_COMMIT_ERROR, + "failed to persist reveal data"); } return qs; } @@ -542,26 +552,29 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, (0 == num_fresh_coins) ) { GNUNET_break_op (0); - return TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_REFRESH_REVEAL_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE, - "new_denoms_h"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_REFRESH_REVEAL_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE, + "new_denoms_h"); } if (json_array_size (new_denoms_h_json) != json_array_size (coin_evs)) { GNUNET_break_op (0); - return TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_REFRESH_REVEAL_NEW_DENOMS_ARRAY_SIZE_MISSMATCH, - "new_denoms/coin_evs"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_REFRESH_REVEAL_NEW_DENOMS_ARRAY_SIZE_MISSMATCH, + "new_denoms/coin_evs"); } if (json_array_size (new_denoms_h_json) != json_array_size (link_sigs_json)) { GNUNET_break_op (0); - return TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_REFRESH_REVEAL_NEW_DENOMS_ARRAY_SIZE_MISSMATCH, - "new_denoms/link_sigs"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_REFRESH_REVEAL_NEW_DENOMS_ARRAY_SIZE_MISSMATCH, + "new_denoms/link_sigs"); } /* Parse transfer private keys array */ @@ -597,9 +610,10 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, { TALER_LOG_ERROR ("Lacking keys to operate\n"); /* FIXME: use correct EC code! */ - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_REFRESH_REVEAL_SIGNING_ERROR, - "exchange lacks keys"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFRESH_REVEAL_SIGNING_ERROR, + "exchange lacks keys"); } /* Parse denomination key hashes */ @@ -631,9 +645,10 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, if (NULL == dkis[i]) { TEH_KS_release (key_state); - return TEH_RESPONSE_reply_with_error (connection, - ec, - hc); + return TALER_MHD_reply_with_error (connection, + ec, + hc, + "failed to find denomination key"); } GNUNET_assert (NULL != dkis[i]->denom_priv.rsa_private_key); } @@ -677,19 +692,24 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, switch (qs) { case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - res = TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_REFRESH_REVEAL_SESSION_UNKNOWN, - "rc"); + res = TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_REFRESH_REVEAL_SESSION_UNKNOWN, + "rc"); break; case GNUNET_DB_STATUS_HARD_ERROR: - res = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_REVEAL_DB_FETCH_SESSION_ERROR); + res = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFRESH_REVEAL_DB_FETCH_SESSION_ERROR, + "failed to fetch session data"); break; case GNUNET_DB_STATUS_SOFT_ERROR: default: GNUNET_break (0); /* should be impossible */ - res = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_INTERNAL_INVARIANT_FAILURE); + res = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_INTERNAL_INVARIANT_FAILURE, + "assertion failed"); break; } goto cleanup; @@ -731,9 +751,10 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, eddsa_pub)) { GNUNET_break_op (0); - res = TEH_RESPONSE_reply_signature_invalid (connection, - TALER_EC_REFRESH_REVEAL_LINK_SIGNATURE_INVALID, - "link_sig"); + res = TALER_MHD_reply_with_error (connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_REFRESH_REVEAL_LINK_SIGNATURE_INVALID, + "link_sig"); goto cleanup; } } @@ -757,8 +778,10 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, if (NULL == rctx->ev_sigs[i].rsa_signature) { GNUNET_break (0); - res = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_REVEAL_SIGNING_ERROR); + res = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFRESH_REVEAL_SIGNING_ERROR, + "internal signing error"); goto cleanup; } } @@ -909,9 +932,10 @@ TEH_REFRESH_handler_refresh_reveal (struct TEH_RequestHandler *rh, { GNUNET_JSON_parse_free (spec); GNUNET_break_op (0); - return TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_REFRESH_REVEAL_CNC_TRANSFER_ARRAY_SIZE_INVALID, - "transfer_privs"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_REFRESH_REVEAL_CNC_TRANSFER_ARRAY_SIZE_INVALID, + "transfer_privs"); } res = handle_refresh_reveal_json (connection, &rctx, diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c index 048a8bef0..f051cd2e5 100644 --- a/src/exchange/taler-exchange-httpd_responses.c +++ b/src/exchange/taler-exchange-httpd_responses.c @@ -27,6 +27,7 @@ #include "taler-exchange-httpd_responses.h" #include "taler_util.h" #include "taler_json_lib.h" +#include "taler_mhd_lib.h" #include "taler-exchange-httpd_keystate.h" /** @@ -874,15 +875,16 @@ TEH_RESPONSE_reply_coin_insufficient_funds (struct MHD_Connection *connection, history = TEH_RESPONSE_compile_transaction_history (tl); if (NULL == history) - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_COIN_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS, - "failed to convert transaction history to JSON"); - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_FORBIDDEN, - "{s:s, s:I, s:o}", - "error", "insufficient funds", - "code", (json_int_t) ec, - "history", history); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_COIN_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS, + "failed to convert transaction history to JSON"); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_FORBIDDEN, + "{s:s, s:I, s:o}", + "error", "insufficient funds", + "code", (json_int_t) ec, + "history", history); } diff --git a/src/exchange/taler-exchange-httpd_responses.h b/src/exchange/taler-exchange-httpd_responses.h index 9b6a78859..ec0515829 100644 --- a/src/exchange/taler-exchange-httpd_responses.h +++ b/src/exchange/taler-exchange-httpd_responses.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014 GNUnet e.V. + Copyright (C) 2014-2019 GNUnet e.V. 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 @@ -13,7 +13,6 @@ You should have received a copy of the GNU Affero General Public License along with TALER; see the file COPYING. If not, see */ - /** * @file taler-exchange-httpd_responses.h * @brief API for generating generic replies of the exchange; these @@ -34,216 +33,6 @@ #include "taler-exchange-httpd_db.h" -/** - * Add headers we want to return in every response. - * Useful for testing, like if we want to always close - * connections. - * - * @param response response to modify - */ -void -TEH_RESPONSE_add_global_headers (struct MHD_Response *response); - - -/** - * Try to compress a response body. Updates @a buf and @a buf_size. - * - * @param[in,out] buf pointer to body to compress - * @param[in,out] buf_size pointer to initial size of @a buf - * @return #MHD_YES if @a buf was compressed - */ -int -TEH_RESPONSE_body_compress (void **buf, - size_t *buf_size); - - -/** - * Is HTTP body deflate compression supported by the client? - * - * @param connection connection to check - * @return #MHD_YES if 'deflate' compression is allowed - */ -int -TEH_RESPONSE_can_compress (struct MHD_Connection *connection); - - -/** - * Send JSON object as response. - * - * @param connection the MHD connection - * @param json the json object - * @param response_code the http response code - * @return MHD result code - */ -int -TEH_RESPONSE_reply_json (struct MHD_Connection *connection, - const json_t *json, - unsigned int response_code); - - -/** - * Function to call to handle the request by building a JSON - * reply from a format string and varargs. - * - * @param connection the MHD connection to handle - * @param response_code HTTP response code to use - * @param fmt format string for pack - * @param ... varargs - * @return MHD result code - */ -int -TEH_RESPONSE_reply_json_pack (struct MHD_Connection *connection, - unsigned int response_code, - const char *fmt, - ...); - - -/** - * Send a response indicating an invalid signature. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param param_name the parameter that is invalid - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_signature_invalid (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *param_name); - - -/** - * Send a response indicating an invalid argument. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param param_name the parameter that is invalid - * @return MHD result code - */ -int -TEH_RESPONSE_reply_arg_invalid (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *param_name); - - -/** - * Send a response indicating an argument refering to a - * resource unknown to the exchange (i.e. unknown reserve or - * denomination key). - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param param_name the parameter that is invalid - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_arg_unknown (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *param_name); - - -/** - * Send a response indicating a missing argument. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param param_name the parameter that is missing - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_arg_missing (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *param_name); - - -/** - * Send a response indicating an internal error. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param hint hint about the internal error's nature - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_internal_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *hint); - - -/** - * Send a response indicating an error. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param http_status HTTP status code to use - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_with_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - unsigned int http_status); - - -/** - * Send a response indicating an external error. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param hint hint about the error's nature - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_external_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *hint); - - -/** - * Send a response indicating an error committing a - * transaction (concurrent interference). - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_commit_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec); - - -/** - * Send a response indicating a failure to talk to the Exchange's - * database. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_internal_db_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec); - - -/** - * Send a response indicating that the request was too big. - * - * @param connection the MHD connection to use - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_request_too_large (struct MHD_Connection *connection); - - -/** - * Send a response indicating that the JSON was malformed. - * - * @param connection the MHD connection to use - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_invalid_json (struct MHD_Connection *connectionx); - - /** * Compile the history of a reserve into a JSON object * and calculate the total balance. @@ -276,20 +65,6 @@ TEH_RESPONSE_reply_coin_insufficient_funds (struct MHD_Connection *connection, TALER_EXCHANGEDB_TransactionList *tl); -/** - * A merchant asked for details about a deposit, but - * we do not know anything about the deposit. Generate the - * 404 reply. - * - * @param connection connection to the client - * @param ec Taler error code - * @return MHD result code - */ -int -TEH_RESPONSE_reply_transaction_unknown (struct MHD_Connection *connection, - enum TALER_ErrorCode ec); - - /** * Compile the transaction history of a coin into a JSON object. * -- cgit v1.2.3 From 7c11a822ba9ebce8a0dfe04510945ad36c0a0c71 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 19:29:50 +0100 Subject: more libtalermhd refactoring --- src/exchange/taler-exchange-httpd_payback.c | 69 ++++++------- src/exchange/taler-exchange-httpd_refund.c | 110 ++++++++++++--------- src/exchange/taler-exchange-httpd_reserve_status.c | 34 ++++--- .../taler-exchange-httpd_reserve_withdraw.c | 110 ++++++++++++--------- 4 files changed, 178 insertions(+), 145 deletions(-) (limited to 'src') diff --git a/src/exchange/taler-exchange-httpd_payback.c b/src/exchange/taler-exchange-httpd_payback.c index b8adc950d..e8a179f1b 100644 --- a/src/exchange/taler-exchange-httpd_payback.c +++ b/src/exchange/taler-exchange-httpd_payback.c @@ -27,6 +27,7 @@ #include #include #include "taler_json_lib.h" +#include "taler_mhd_lib.h" #include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_payback.h" #include "taler-exchange-httpd_responses.h" @@ -68,24 +69,25 @@ reply_payback_refresh_success (struct MHD_Connection *connection, &pub, &sig)) { - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_EXCHANGE_BAD_CONFIGURATION, - "no keys"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_EXCHANGE_BAD_CONFIGURATION, + "no keys"); } - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o, s:o, s:o, s:o, s:o}", - "old_coin_pub", - GNUNET_JSON_from_data_auto ( - old_coin_pub), - "timestamp", GNUNET_JSON_from_time_abs ( - timestamp), - "amount", TALER_JSON_from_amount ( - amount), - "exchange_sig", - GNUNET_JSON_from_data_auto (&sig), - "exchange_pub", - GNUNET_JSON_from_data_auto (&pub)); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o, s:o, s:o, s:o, s:o}", + "old_coin_pub", + GNUNET_JSON_from_data_auto ( + old_coin_pub), + "timestamp", GNUNET_JSON_from_time_abs ( + timestamp), + "amount", TALER_JSON_from_amount ( + amount), + "exchange_sig", + GNUNET_JSON_from_data_auto (&sig), + "exchange_pub", + GNUNET_JSON_from_data_auto (&pub)); } @@ -122,23 +124,24 @@ reply_payback_success (struct MHD_Connection *connection, &pub, &sig)) { - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_EXCHANGE_BAD_CONFIGURATION, - "no keys"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_EXCHANGE_BAD_CONFIGURATION, + "no keys"); } - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o, s:o, s:o, s:o, s:o}", - "reserve_pub", - GNUNET_JSON_from_data_auto (reserve_pub), - "timestamp", GNUNET_JSON_from_time_abs ( - timestamp), - "amount", TALER_JSON_from_amount ( - amount), - "exchange_sig", - GNUNET_JSON_from_data_auto (&sig), - "exchange_pub", - GNUNET_JSON_from_data_auto (&pub)); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o, s:o, s:o, s:o, s:o}", + "reserve_pub", + GNUNET_JSON_from_data_auto (reserve_pub), + "timestamp", GNUNET_JSON_from_time_abs ( + timestamp), + "amount", TALER_JSON_from_amount ( + amount), + "exchange_sig", + GNUNET_JSON_from_data_auto (&sig), + "exchange_pub", + GNUNET_JSON_from_data_auto (&pub)); } diff --git a/src/exchange/taler-exchange-httpd_refund.c b/src/exchange/taler-exchange-httpd_refund.c index 48532a2ce..adc712c11 100644 --- a/src/exchange/taler-exchange-httpd_refund.c +++ b/src/exchange/taler-exchange-httpd_refund.c @@ -29,6 +29,7 @@ #include #include #include "taler_json_lib.h" +#include "taler_mhd_lib.h" #include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_refund.h" #include "taler-exchange-httpd_responses.h" @@ -66,17 +67,17 @@ reply_refund_success (struct MHD_Connection *connection, &pub, &sig)) { - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_EXCHANGE_BAD_CONFIGURATION, - "no keys"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_EXCHANGE_BAD_CONFIGURATION, + "no keys"); } - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:s, s:o, s:o}", - "status", "REFUND_OK", - "sig", GNUNET_JSON_from_data_auto (&sig), - "pub", GNUNET_JSON_from_data_auto ( - &pub)); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:s, s:o, s:o}", + "status", "REFUND_OK", + "sig", GNUNET_JSON_from_data_auto (&sig), + "pub", GNUNET_JSON_from_data_auto (&pub)); } @@ -94,11 +95,11 @@ reply_refund_failure (struct MHD_Connection *connection, unsigned int response_code, enum TALER_ErrorCode ec) { - return TEH_RESPONSE_reply_json_pack (connection, - response_code, - "{s:s, s:I}", - "status", "refund failure", - "code", (json_int_t) ec); + return TALER_MHD_reply_json_pack (connection, + response_code, + "{s:s, s:I}", + "hint", "refund failure", + "code", (json_int_t) ec); } @@ -114,15 +115,15 @@ static int reply_refund_conflict (struct MHD_Connection *connection, const struct TALER_EXCHANGEDB_TransactionList *tl) { - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_CONFLICT, - "{s:s, s:I, s:o}", - "status", "conflicting refund", - "code", - (json_int_t) TALER_EC_REFUND_CONFLICT, - "history", - TEH_RESPONSE_compile_transaction_history ( - tl)); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_CONFLICT, + "{s:s, s:I, s:o}", + "hint", "conflicting refund", + "code", + (json_int_t) TALER_EC_REFUND_CONFLICT, + "history", + TEH_RESPONSE_compile_transaction_history ( + tl)); } @@ -259,8 +260,10 @@ refund_transaction (void *cls, TALER_LOG_WARNING ("Deposit to /refund was not found\n"); TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, tl); - *mhd_ret = TEH_RESPONSE_reply_transaction_unknown (connection, - TALER_EC_REFUND_DEPOSIT_NOT_FOUND); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_REFUND_DEPOSIT_NOT_FOUND, + "deposit unknown"); return GNUNET_DB_STATUS_HARD_ERROR; } /* handle if conflicting refund found */ @@ -309,9 +312,10 @@ refund_transaction (void *cls, GNUNET_break (0); TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, tl); - *mhd_ret = TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_REFUND_DB_INCONSISTENT, - "database inconsistent"); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFUND_DB_INCONSISTENT, + "database inconsistent"); return qs; } if (GNUNET_DB_STATUS_SOFT_ERROR == qs) @@ -349,9 +353,10 @@ refund_transaction (void *cls, TALER_LOG_ERROR ("Lacking keys to operate\n"); TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, tl); - *mhd_ret = TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_EXCHANGE_BAD_CONFIGURATION, - "no keys"); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_EXCHANGE_BAD_CONFIGURATION, + "no keys"); return GNUNET_DB_STATUS_HARD_ERROR; } dki = TEH_KS_denomination_key_lookup_by_hash (mks, @@ -367,9 +372,10 @@ refund_transaction (void *cls, TEH_KS_release (mks); TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, tl); - *mhd_ret = TEH_RESPONSE_reply_with_error (connection, - ec, - hc); + *mhd_ret = TALER_MHD_reply_with_error (connection, + ec, + hc, + "denomination not found, but coin known"); return GNUNET_DB_STATUS_HARD_ERROR; } TALER_amount_ntoh (&expect_fee, @@ -382,9 +388,10 @@ refund_transaction (void *cls, { TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, tl); - *mhd_ret = TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_REFUND_FEE_TOO_LOW, - "refund_fee"); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_REFUND_FEE_TOO_LOW, + "refund_fee"); return GNUNET_DB_STATUS_HARD_ERROR; } if (1 == fee_cmp) @@ -402,8 +409,10 @@ refund_transaction (void *cls, if (GNUNET_DB_STATUS_HARD_ERROR == qs) { TALER_LOG_WARNING ("Failed to store /refund information in database\n"); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFUND_STORE_DB_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFUND_STORE_DB_ERROR, + "could not persist store information"); return qs; } /* Success or soft failure */ @@ -443,17 +452,19 @@ verify_and_execute_refund (struct MHD_Connection *connection, &refund->refund_fee) ) { GNUNET_break_op (0); - return TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_REFUND_FEE_CURRENCY_MISSMATCH, - "refund_fee"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_REFUND_FEE_CURRENCY_MISSMATCH, + "refund_fee"); } if (-1 == TALER_amount_cmp (&refund->refund_amount, &refund->refund_fee) ) { GNUNET_break_op (0); - return TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_REFUND_FEE_ABOVE_AMOUNT, - "refund_amount"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_REFUND_FEE_ABOVE_AMOUNT, + "refund_amount"); } if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND, @@ -462,9 +473,10 @@ verify_and_execute_refund (struct MHD_Connection *connection, &refund->merchant_pub.eddsa_pub)) { TALER_LOG_WARNING ("Invalid signature on /refund request\n"); - return TEH_RESPONSE_reply_signature_invalid (connection, - TALER_EC_REFUND_MERCHANT_SIGNATURE_INVALID, - "merchant_sig"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_REFUND_MERCHANT_SIGNATURE_INVALID, + "merchant_sig"); } if (GNUNET_OK != TEH_DB_run_transaction (connection, diff --git a/src/exchange/taler-exchange-httpd_reserve_status.c b/src/exchange/taler-exchange-httpd_reserve_status.c index 4f9761485..0e46c0b24 100644 --- a/src/exchange/taler-exchange-httpd_reserve_status.c +++ b/src/exchange/taler-exchange-httpd_reserve_status.c @@ -23,6 +23,7 @@ #include "platform.h" #include #include +#include "taler_mhd_lib.h" #include "taler-exchange-httpd_reserve_status.h" #include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_responses.h" @@ -47,15 +48,16 @@ reply_reserve_status_success (struct MHD_Connection *connection, json_history = TEH_RESPONSE_compile_reserve_history (rh, &balance); if (NULL == json_history) - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_RESERVE_STATUS_DB_ERROR, - "balance calculation failure"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_RESERVE_STATUS_DB_ERROR, + "balance calculation failure"); json_balance = TALER_JSON_from_amount (&balance); - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o, s:o}", - "balance", json_balance, - "history", json_history); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o, s:o}", + "balance", json_balance, + "history", json_history); } @@ -155,14 +157,14 @@ TEH_RESERVE_handler_reserve_status (struct TEH_RequestHandler *rh, /* generate proper response */ if (NULL == rsc.rh) - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_NOT_FOUND, - "{s:s, s:s, s:I}", - "error", "Reserve not found", - "parameter", "withdraw_pub", - "code", - (json_int_t) - TALER_EC_RESERVE_STATUS_UNKNOWN); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_NOT_FOUND, + "{s:s, s:s, s:I}", + "error", "Reserve not found", + "parameter", "withdraw_pub", + "code", + (json_int_t) + TALER_EC_RESERVE_STATUS_UNKNOWN); mhd_ret = reply_reserve_status_success (connection, rsc.rh); TEH_plugin->free_reserve_history (TEH_plugin->cls, diff --git a/src/exchange/taler-exchange-httpd_reserve_withdraw.c b/src/exchange/taler-exchange-httpd_reserve_withdraw.c index 578aace31..229da564a 100644 --- a/src/exchange/taler-exchange-httpd_reserve_withdraw.c +++ b/src/exchange/taler-exchange-httpd_reserve_withdraw.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2017 GNUnet e.V. + Copyright (C) 2014-2019 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 @@ -16,7 +16,6 @@ Public License along with TALER; see the file COPYING. If not, see */ - /** * @file taler-exchange-httpd_reserve_withdraw.c * @brief Handle /reserve/withdraw requests @@ -27,6 +26,7 @@ #include "platform.h" #include #include +#include "taler_mhd_lib.h" #include "taler-exchange-httpd_reserve_withdraw.h" #include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_responses.h" @@ -65,20 +65,21 @@ reply_reserve_withdraw_insufficient_funds (struct MHD_Connection *connection, /* Address the case where the ptr is not null, but * it fails "internally" to dump as string (= corrupted). */ || (0 == json_dumpb (json_history, NULL, 0, 0))) - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_WITHDRAW_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS, - "balance calculation failure"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_WITHDRAW_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS, + "balance calculation failure"); json_balance = TALER_JSON_from_amount (&balance); - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_FORBIDDEN, - "{s:s, s:I, s:o, s:o}", - "error", "Insufficient funds", - "code", - (json_int_t) - TALER_EC_WITHDRAW_INSUFFICIENT_FUNDS, - "balance", json_balance, - "history", json_history); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_FORBIDDEN, + "{s:s, s:I, s:o, s:o}", + "error", "Insufficient funds", + "code", + (json_int_t) + TALER_EC_WITHDRAW_INSUFFICIENT_FUNDS, + "balance", json_balance, + "history", json_history); } @@ -98,10 +99,10 @@ reply_reserve_withdraw_success (struct MHD_Connection *connection, json_t *sig_json; sig_json = GNUNET_JSON_from_rsa_signature (collectable->sig.rsa_signature); - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o}", - "ev_sig", sig_json); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o}", + "ev_sig", sig_json); } @@ -209,8 +210,10 @@ withdraw_transaction (void *cls, { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); if (GNUNET_DB_STATUS_HARD_ERROR == qs) - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_WITHDRAW_DB_FETCH_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_WITHDRAW_DB_FETCH_ERROR, + "failed to fetch withdraw data"); wc->collectable.sig = denom_sig; return qs; } @@ -252,15 +255,18 @@ withdraw_transaction (void *cls, if (0 > qs) { if (GNUNET_DB_STATUS_HARD_ERROR == qs) - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_WITHDRAW_DB_FETCH_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_WITHDRAW_DB_FETCH_ERROR, + "failed to fetch reserve data"); return qs; } if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) { - *mhd_ret = TEH_RESPONSE_reply_arg_unknown (connection, - TALER_EC_WITHDRAW_RESERVE_UNKNOWN, - "reserve_pub"); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_WITHDRAW_RESERVE_UNKNOWN, + "reserve_pub"); return GNUNET_DB_STATUS_HARD_ERROR; } if (0 < TALER_amount_cmp (&wc->amount_required, @@ -286,8 +292,10 @@ withdraw_transaction (void *cls, if (NULL == rh) { if (GNUNET_DB_STATUS_HARD_ERROR == qs) - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_WITHDRAW_DB_FETCH_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_WITHDRAW_DB_FETCH_ERROR, + "failed to fetch reserve history"); return GNUNET_DB_STATUS_HARD_ERROR; } *mhd_ret = reply_reserve_withdraw_insufficient_funds (connection, @@ -308,9 +316,10 @@ withdraw_transaction (void *cls, if (NULL == wc->collectable.sig.rsa_signature) { GNUNET_break (0); - *mhd_ret = TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_WITHDRAW_SIGNATURE_FAILED, - "Internal error"); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_WITHDRAW_SIGNATURE_FAILED, + "Failed to create signature"); return GNUNET_DB_STATUS_HARD_ERROR; } } @@ -330,8 +339,10 @@ withdraw_transaction (void *cls, { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); if (GNUNET_DB_STATUS_HARD_ERROR == qs) - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_WITHDRAW_DB_STORE_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_WITHDRAW_DB_STORE_ERROR, + "failed to persist withdraw data"); return qs; } return qs; @@ -403,9 +414,10 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh, { TALER_LOG_ERROR ("Lacking keys to operate\n"); GNUNET_JSON_parse_free (spec); - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_EXCHANGE_BAD_CONFIGURATION, - "no keys"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_EXCHANGE_BAD_CONFIGURATION, + "no keys"); } wc.dki = TEH_KS_denomination_key_lookup_by_hash (wc.key_state, &wc.denom_pub_hash, @@ -416,9 +428,10 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh, { GNUNET_JSON_parse_free (spec); TEH_KS_release (wc.key_state); - return TEH_RESPONSE_reply_with_error (connection, - ec, - hc); + return TALER_MHD_reply_with_error (connection, + ec, + hc, + "could not find denomination key"); } GNUNET_assert (NULL != wc.dki->denom_priv.rsa_private_key); TALER_amount_ntoh (&amount, @@ -432,9 +445,10 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh, { GNUNET_JSON_parse_free (spec); TEH_KS_release (wc.key_state); - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_WITHDRAW_AMOUNT_FEE_OVERFLOW, - "amount overflow for value plus withdraw fee"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_WITHDRAW_AMOUNT_FEE_OVERFLOW, + "amount overflow for value plus withdraw fee"); } TALER_amount_hton (&wc.wsrd.amount_with_fee, &wc.amount_required); @@ -460,9 +474,10 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh, "Client supplied invalid signature for /reserve/withdraw request\n"); GNUNET_JSON_parse_free (spec); TEH_KS_release (wc.key_state); - return TEH_RESPONSE_reply_signature_invalid (connection, - TALER_EC_WITHDRAW_RESERVE_SIGNATURE_INVALID, - "reserve_sig"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_WITHDRAW_RESERVE_SIGNATURE_INVALID, + "reserve_sig"); } #if OPTIMISTIC_SIGN @@ -476,9 +491,10 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh, GNUNET_break (0); GNUNET_JSON_parse_free (spec); TEH_KS_release (wc.key_state); - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_WITHDRAW_SIGNATURE_FAILED, - "Internal error"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_WITHDRAW_SIGNATURE_FAILED, + "Failed to sign"); } #endif -- cgit v1.2.3 From cf6ba0c77196b77f5c54f0533ac1be3d1d5ee6d6 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 21:03:05 +0100 Subject: more refactoring for libtalermhd --- src/exchange/taler-exchange-httpd_deposit.c | 14 ++- src/exchange/taler-exchange-httpd_keystate.h | 1 + src/exchange/taler-exchange-httpd_mhd.c | 12 +- src/exchange/taler-exchange-httpd_test.c | 134 +++++++++++---------- .../taler-exchange-httpd_track_transaction.c | 73 ++++++----- src/exchange/taler-exchange-httpd_track_transfer.c | 75 +++++++----- src/exchange/taler-exchange-httpd_wire.c | 7 +- 7 files changed, 174 insertions(+), 142 deletions(-) (limited to 'src') diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c index 7e71dcaa6..1db8d7621 100644 --- a/src/exchange/taler-exchange-httpd_deposit.c +++ b/src/exchange/taler-exchange-httpd_deposit.c @@ -291,9 +291,10 @@ verify_and_execute_deposit (struct MHD_Connection *connection, if (NULL == mks) { TALER_LOG_ERROR ("Lacking keys to operate\n"); - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_EXCHANGE_BAD_CONFIGURATION, - "no keys"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_EXCHANGE_BAD_CONFIGURATION, + "no keys"); } dki = TEH_KS_denomination_key_lookup_by_hash (mks, &deposit->coin.denom_pub_hash, @@ -465,9 +466,10 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, &emsg))) { GNUNET_JSON_parse_free (spec); - res = TEH_RESPONSE_reply_external_error (connection, - ec, - emsg); + res = TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + ec, + emsg); GNUNET_free (emsg); return res; } diff --git a/src/exchange/taler-exchange-httpd_keystate.h b/src/exchange/taler-exchange-httpd_keystate.h index 708b043b5..5d92af2b2 100644 --- a/src/exchange/taler-exchange-httpd_keystate.h +++ b/src/exchange/taler-exchange-httpd_keystate.h @@ -26,6 +26,7 @@ #include #include #include "taler-exchange-httpd.h" +#include "taler_error_codes.h" #include "taler_exchangedb_lib.h" diff --git a/src/exchange/taler-exchange-httpd_mhd.c b/src/exchange/taler-exchange-httpd_mhd.c index 36d10bae3..825a1b310 100644 --- a/src/exchange/taler-exchange-httpd_mhd.c +++ b/src/exchange/taler-exchange-httpd_mhd.c @@ -67,7 +67,7 @@ TEH_MHD_handler_static_response (struct TEH_RequestHandler *rh, GNUNET_break (0); return MHD_NO; } - TEH_RESPONSE_add_global_headers (response); + TALER_MHD_add_global_headers (response); if (NULL != rh->mime_type) (void) MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, @@ -128,11 +128,11 @@ TEH_MHD_handler_send_json_pack_error (struct TEH_RequestHandler *rh, (void) connection_cls; (void) upload_data; (void) upload_data_size; - return TEH_RESPONSE_reply_json_pack (connection, - rh->response_code, - "{s:s}", - "error", - rh->data); + return TALER_MHD_reply_json_pack (connection, + rh->response_code, + "{s:s}", + "error", + rh->data); } diff --git a/src/exchange/taler-exchange-httpd_test.c b/src/exchange/taler-exchange-httpd_test.c index 0a64f267f..4d0e7d691 100644 --- a/src/exchange/taler-exchange-httpd_test.c +++ b/src/exchange/taler-exchange-httpd_test.c @@ -24,6 +24,7 @@ #include #include #include +#include "taler_mhd_lib.h" #include "taler_signatures.h" #include "taler-exchange-httpd_test.h" #include "taler-exchange-httpd_parsing.h" @@ -88,11 +89,11 @@ TEH_TEST_handler_test_base32 (struct TEH_RequestHandler *rh, &hc); GNUNET_JSON_parse_free (spec); json_decref (json); - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o}", - "output", - GNUNET_JSON_from_data_auto (&hc)); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o}", + "output", + GNUNET_JSON_from_data_auto (&hc)); } @@ -172,11 +173,11 @@ TEH_TEST_handler_test_encrypt (struct TEH_RequestHandler *rh, in_ptr_size); GNUNET_free (out); GNUNET_JSON_parse_free (spec); - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o}", - "output", - json); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o}", + "output", + json); } @@ -237,11 +238,11 @@ TEH_TEST_handler_test_hkdf (struct TEH_RequestHandler *rh, NULL, 0)); GNUNET_JSON_parse_free (spec); json = GNUNET_JSON_from_data_auto (&hc); - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o}", - "output", - json); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o}", + "output", + json); } @@ -298,16 +299,17 @@ TEH_TEST_handler_test_ecdhe (struct TEH_RequestHandler *rh, &hc)) { GNUNET_JSON_parse_free (spec); - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_TEST_ECDH_ERROR, - "Failed to perform ECDH"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_TEST_ECDH_ERROR, + "Failed to perform ECDH"); } GNUNET_JSON_parse_free (spec); - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o}", - "ecdh_hash", - GNUNET_JSON_from_data_auto (&hc)); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o}", + "ecdh_hash", + GNUNET_JSON_from_data_auto (&hc)); } @@ -369,9 +371,10 @@ TEH_TEST_handler_test_eddsa (struct TEH_RequestHandler *rh, &pub)) { GNUNET_JSON_parse_free (spec); - return TEH_RESPONSE_reply_signature_invalid (connection, - TALER_EC_TEST_EDDSA_INVALID, - "eddsa_sig"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_TEST_EDDSA_INVALID, + "eddsa_sig"); } GNUNET_JSON_parse_free (spec); pk = GNUNET_CRYPTO_eddsa_key_create (); @@ -382,20 +385,21 @@ TEH_TEST_handler_test_eddsa (struct TEH_RequestHandler *rh, &sig)) { GNUNET_free (pk); - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_TEST_EDDSA_ERROR, - "Failed to EdDSA-sign"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_TEST_EDDSA_ERROR, + "Failed to EdDSA-sign"); } GNUNET_CRYPTO_eddsa_key_get_public (pk, &pub); GNUNET_free (pk); - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o, s:o}", - "eddsa_pub", - GNUNET_JSON_from_data_auto (&pub), - "eddsa_sig", - GNUNET_JSON_from_data_auto (&sig)); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o, s:o}", + "eddsa_pub", + GNUNET_JSON_from_data_auto (&pub), + "eddsa_sig", + GNUNET_JSON_from_data_auto (&sig)); } @@ -425,23 +429,25 @@ TEH_TEST_handler_test_rsa_get (struct TEH_RequestHandler *rh, if (NULL == rsa_pk) { GNUNET_break (0); - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_TEST_RSA_GEN_ERROR, - "Failed to create RSA key"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_TEST_RSA_GEN_ERROR, + "Failed to create RSA key"); } pub = GNUNET_CRYPTO_rsa_private_key_get_public (rsa_pk); if (NULL == pub) { GNUNET_break (0); - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_TEST_RSA_PUB_ERROR, - "Failed to get public RSA key"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_TEST_RSA_PUB_ERROR, + "Failed to get public RSA key"); } - res = TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o}", - "rsa_pub", - GNUNET_JSON_from_rsa_public_key (pub)); + res = TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o}", + "rsa_pub", + GNUNET_JSON_from_rsa_public_key (pub)); GNUNET_CRYPTO_rsa_public_key_free (pub); return res; } @@ -497,9 +503,10 @@ TEH_TEST_handler_test_rsa_sign (struct TEH_RequestHandler *rh, { GNUNET_break (0); GNUNET_JSON_parse_free (spec); - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_TEST_RSA_GEN_ERROR, - "Failed to create RSA key"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_TEST_RSA_GEN_ERROR, + "Failed to create RSA key"); } sig = GNUNET_CRYPTO_rsa_sign_blinded (rsa_pk, in_ptr, @@ -508,16 +515,17 @@ TEH_TEST_handler_test_rsa_sign (struct TEH_RequestHandler *rh, { GNUNET_break (0); GNUNET_JSON_parse_free (spec); - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_TEST_RSA_SIGN_ERROR, - "Failed to RSA-sign"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_TEST_RSA_SIGN_ERROR, + "Failed to RSA-sign"); } GNUNET_JSON_parse_free (spec); - res = TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o}", - "rsa_blind_sig", - GNUNET_JSON_from_rsa_signature (sig)); + res = TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o}", + "rsa_blind_sig", + GNUNET_JSON_from_rsa_signature (sig)); GNUNET_CRYPTO_rsa_signature_free (sig); return res; } @@ -573,11 +581,11 @@ TEH_TEST_handler_test_transfer (struct TEH_RequestHandler *rh, TALER_link_reveal_transfer_secret (&trans_priv, &coin_pub, &secret); - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o}", - "secret", - GNUNET_JSON_from_data_auto (&secret)); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o}", + "secret", + GNUNET_JSON_from_data_auto (&secret)); } diff --git a/src/exchange/taler-exchange-httpd_track_transaction.c b/src/exchange/taler-exchange-httpd_track_transaction.c index 3b8d14a01..5a057d665 100644 --- a/src/exchange/taler-exchange-httpd_track_transaction.c +++ b/src/exchange/taler-exchange-httpd_track_transaction.c @@ -23,6 +23,7 @@ #include #include #include +#include "taler_mhd_lib.h" #include "taler_signatures.h" #include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_keystate.h" @@ -42,12 +43,12 @@ static int reply_transfer_pending (struct MHD_Connection *connection, struct GNUNET_TIME_Absolute planned_exec_time) { - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_ACCEPTED, - "{s:o}", - "execution_time", - GNUNET_JSON_from_time_abs ( - planned_exec_time)); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_ACCEPTED, + "{s:o}", + "execution_time", + GNUNET_JSON_from_time_abs ( + planned_exec_time)); } @@ -92,24 +93,25 @@ reply_track_transaction (struct MHD_Connection *connection, &pub, &sig)) { - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_EXCHANGE_BAD_CONFIGURATION, - "no keys"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_EXCHANGE_BAD_CONFIGURATION, + "no keys"); } - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o, s:o, s:o, s:o, s:o}", - "wtid", GNUNET_JSON_from_data_auto ( - wtid), - "execution_time", - GNUNET_JSON_from_time_abs (exec_time), - "coin_contribution", - TALER_JSON_from_amount ( - coin_contribution), - "exchange_sig", - GNUNET_JSON_from_data_auto (&sig), - "exchange_pub", - GNUNET_JSON_from_data_auto (&pub)); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o, s:o, s:o, s:o, s:o}", + "wtid", GNUNET_JSON_from_data_auto ( + wtid), + "execution_time", + GNUNET_JSON_from_time_abs (exec_time), + "coin_contribution", + TALER_JSON_from_amount ( + coin_contribution), + "exchange_sig", + GNUNET_JSON_from_data_auto (&sig), + "exchange_pub", + GNUNET_JSON_from_data_auto (&pub)); } @@ -249,15 +251,19 @@ track_transaction_transaction (void *cls, if (GNUNET_DB_STATUS_HARD_ERROR == qs) { GNUNET_break (0); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_TRACK_TRANSACTION_DB_FETCH_FAILED); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_TRACK_TRANSACTION_DB_FETCH_FAILED, + "failed to fetch transaction data"); } return qs; } if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) { - *mhd_ret = TEH_RESPONSE_reply_transaction_unknown (connection, - TALER_EC_TRACK_TRANSACTION_NOT_FOUND); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_TRACK_TRANSACTION_NOT_FOUND, + "transaction unknown"); return GNUNET_DB_STATUS_HARD_ERROR; } return qs; @@ -295,9 +301,10 @@ check_and_handle_track_transaction_request (struct MHD_Connection *connection, &merchant_pub->eddsa_pub)) { GNUNET_break_op (0); - return TEH_RESPONSE_reply_signature_invalid (connection, - TALER_EC_TRACK_TRANSACTION_MERCHANT_SIGNATURE_INVALID, - "merchant_sig"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_TRACK_TRANSACTION_MERCHANT_SIGNATURE_INVALID, + "merchant_sig"); } ctx.pending = GNUNET_NO; ctx.tps = tps; @@ -314,8 +321,10 @@ check_and_handle_track_transaction_request (struct MHD_Connection *connection, return reply_transfer_pending (connection, ctx.execution_time); if (GNUNET_SYSERR == ctx.pending) - return TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_TRACK_TRANSACTION_DB_FEE_INCONSISTENT); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_TRACK_TRANSACTION_DB_FEE_INCONSISTENT, + "fees are inconsistent"); return reply_track_transaction (connection, &tps->h_contract_terms, &tps->h_wire, diff --git a/src/exchange/taler-exchange-httpd_track_transfer.c b/src/exchange/taler-exchange-httpd_track_transfer.c index cacbfaa85..83521f736 100644 --- a/src/exchange/taler-exchange-httpd_track_transfer.c +++ b/src/exchange/taler-exchange-httpd_track_transfer.c @@ -28,6 +28,7 @@ #include "taler-exchange-httpd_keystate.h" #include "taler-exchange-httpd_track_transfer.h" #include "taler-exchange-httpd_responses.h" +#include "taler_mhd_lib.h" #include "taler_wire_lib.h" @@ -148,29 +149,30 @@ reply_track_transfer_details (struct MHD_Connection *connection, &sig)) { json_decref (deposits); - return TEH_RESPONSE_reply_internal_error (connection, - TALER_EC_EXCHANGE_BAD_CONFIGURATION, - "no keys"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_EXCHANGE_BAD_CONFIGURATION, + "no keys"); } - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}", - "total", TALER_JSON_from_amount (total), - "wire_fee", TALER_JSON_from_amount ( - wire_fee), - "merchant_pub", - GNUNET_JSON_from_data_auto ( - merchant_pub), - "H_wire", GNUNET_JSON_from_data_auto ( - h_wire), - "execution_time", - GNUNET_JSON_from_time_abs (exec_time), - "deposits", deposits, - "exchange_sig", - GNUNET_JSON_from_data_auto (&sig), - "exchange_pub", - GNUNET_JSON_from_data_auto (&pub)); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}", + "total", TALER_JSON_from_amount (total), + "wire_fee", TALER_JSON_from_amount ( + wire_fee), + "merchant_pub", + GNUNET_JSON_from_data_auto ( + merchant_pub), + "H_wire", GNUNET_JSON_from_data_auto ( + h_wire), + "execution_time", + GNUNET_JSON_from_time_abs (exec_time), + "deposits", deposits, + "exchange_sig", + GNUNET_JSON_from_data_auto (&sig), + "exchange_pub", + GNUNET_JSON_from_data_auto (&pub)); } @@ -396,23 +398,28 @@ track_transfer_transaction (void *cls, if (GNUNET_DB_STATUS_HARD_ERROR == qs) { GNUNET_break (0); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_TRACK_TRANSFER_DB_FETCH_FAILED); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_TRACK_TRANSFER_DB_FETCH_FAILED, + "failed to fetch transaction data"); } return qs; } if (GNUNET_SYSERR == ctx->is_valid) { GNUNET_break (0); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_TRACK_TRANSFER_DB_INCONSISTENT); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_TRACK_TRANSFER_DB_INCONSISTENT, + "exchange database internally inconsistent"); return GNUNET_DB_STATUS_HARD_ERROR; } if (GNUNET_NO == ctx->is_valid) { - *mhd_ret = TEH_RESPONSE_reply_arg_unknown (connection, - TALER_EC_TRACK_TRANSFER_WTID_NOT_FOUND, - "wtid"); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_TRACK_TRANSFER_WTID_NOT_FOUND, + "wtid"); return GNUNET_DB_STATUS_HARD_ERROR; } qs = TEH_plugin->get_wire_fee (TEH_plugin->cls, @@ -430,8 +437,10 @@ track_transfer_transaction (void *cls, (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS) ) { GNUNET_break (0); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_TRACK_TRANSFER_WIRE_FEE_NOT_FOUND); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_TRACK_TRANSFER_WIRE_FEE_NOT_FOUND, + "did not find wire fee"); } return qs; } @@ -441,8 +450,10 @@ track_transfer_transaction (void *cls, &ctx->wire_fee)) { GNUNET_break (0); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_TRACK_TRANSFER_WIRE_FEE_INCONSISTENT); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_TRACK_TRANSFER_WIRE_FEE_INCONSISTENT, + "could not subtract wire fee"); return GNUNET_DB_STATUS_HARD_ERROR; } return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; diff --git a/src/exchange/taler-exchange-httpd_wire.c b/src/exchange/taler-exchange-httpd_wire.c index 91c928f94..4e4c34db5 100644 --- a/src/exchange/taler-exchange-httpd_wire.c +++ b/src/exchange/taler-exchange-httpd_wire.c @@ -25,6 +25,7 @@ #include "taler-exchange-httpd_validation.h" #include "taler-exchange-httpd_wire.h" #include "taler_json_lib.h" +#include "taler_mhd_lib.h" #include /** @@ -140,9 +141,9 @@ TEH_WIRE_handler_wire (struct TEH_RequestHandler *rh, (void) upload_data; (void) upload_data_size; GNUNET_assert (NULL != wire_methods); - return TEH_RESPONSE_reply_json (connection, - wire_methods, - MHD_HTTP_OK); + return TALER_MHD_reply_json (connection, + wire_methods, + MHD_HTTP_OK); } -- cgit v1.2.3 From 8f006e779e12fed604182faa096ebe6b5726d04d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 21:06:25 +0100 Subject: more refactoring for libtalermhd --- src/exchange/taler-exchange-httpd_db.c | 31 +++++++++++++++++++--------- src/exchange/taler-exchange-httpd_keystate.c | 6 +++--- 2 files changed, 24 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/exchange/taler-exchange-httpd_db.c b/src/exchange/taler-exchange-httpd_db.c index 37bd23792..19781f97f 100644 --- a/src/exchange/taler-exchange-httpd_db.c +++ b/src/exchange/taler-exchange-httpd_db.c @@ -23,6 +23,7 @@ #include #include #include "taler_json_lib.h" +#include "taler_mhd_lib.h" #include "taler-exchange-httpd_responses.h" #include "taler-exchange-httpd_keystate.h" @@ -62,8 +63,10 @@ TEH_DB_know_coin_transaction (void *cls, if (GNUNET_DB_STATUS_HARD_ERROR == qs) { *mhd_ret - = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_DB_COIN_HISTORY_STORE_ERROR); + = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_DB_COIN_HISTORY_STORE_ERROR, + "could not persist coin data"); return GNUNET_DB_STATUS_HARD_ERROR; } return qs; @@ -99,8 +102,10 @@ TEH_DB_run_transaction (struct MHD_Connection *connection, { GNUNET_break (0); if (NULL != mhd_ret) - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_DB_SETUP_FAILED); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_DB_SETUP_FAILED, + "could not establish database session"); return GNUNET_SYSERR; } TEH_plugin->preflight (TEH_plugin->cls, @@ -117,8 +122,10 @@ TEH_DB_run_transaction (struct MHD_Connection *connection, { GNUNET_break (0); if (NULL != mhd_ret) - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_DB_START_FAILED); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_DB_START_FAILED, + "could not begin transaction"); return GNUNET_SYSERR; } qs = cb (cb_cls, @@ -136,8 +143,10 @@ TEH_DB_run_transaction (struct MHD_Connection *connection, if (GNUNET_DB_STATUS_HARD_ERROR == qs) { if (NULL != mhd_ret) - *mhd_ret = TEH_RESPONSE_reply_commit_error (connection, - TALER_EC_DB_COMMIT_FAILED_HARD); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_DB_COMMIT_FAILED_HARD, + "could not commit database transaction"); return GNUNET_SYSERR; } /* make sure callback did not violate invariants! */ @@ -150,8 +159,10 @@ TEH_DB_run_transaction (struct MHD_Connection *connection, name, MAX_TRANSACTION_COMMIT_RETRIES); if (NULL != mhd_ret) - *mhd_ret = TEH_RESPONSE_reply_commit_error (connection, - TALER_EC_DB_COMMIT_FAILED_ON_RETRY); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_DB_COMMIT_FAILED_ON_RETRY, + "repatedly failed to serialize database transaction"); return GNUNET_SYSERR; } diff --git a/src/exchange/taler-exchange-httpd_keystate.c b/src/exchange/taler-exchange-httpd_keystate.c index 7297a741b..cf5cbe9a0 100644 --- a/src/exchange/taler-exchange-httpd_keystate.c +++ b/src/exchange/taler-exchange-httpd_keystate.c @@ -1243,7 +1243,7 @@ setup_general_response_headers (const struct TEH_KS_StateHandle *key_state, { char dat[128]; - TEH_RESPONSE_add_global_headers (response); + TALER_MHD_add_global_headers (response); GNUNET_break (MHD_YES == MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, @@ -1546,8 +1546,8 @@ build_keys_response (const struct ResponseFactoryContext *rfc, } /* Also compute compressed version of /keys response */ - comp = TEH_RESPONSE_body_compress (&keys_jsonz, - &keys_jsonz_size); + comp = TALER_MHD_body_compress (&keys_jsonz, + &keys_jsonz_size); krd->response_compressed = MHD_create_response_from_buffer (keys_jsonz_size, keys_jsonz, -- cgit v1.2.3 From c22efccce8ce864ff8fd84fa968f5c0d44c36d3d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 21:12:27 +0100 Subject: migrate parsing logic to libtalermhd --- src/exchange/Makefile.am | 1 - src/exchange/taler-exchange-httpd.c | 3 +- src/exchange/taler-exchange-httpd_deposit.c | 17 +- src/exchange/taler-exchange-httpd_parsing.c | 286 --------------------- src/exchange/taler-exchange-httpd_parsing.h | 139 ---------- src/exchange/taler-exchange-httpd_payback.c | 17 +- src/exchange/taler-exchange-httpd_refresh_link.c | 11 +- src/exchange/taler-exchange-httpd_refresh_melt.c | 18 +- src/exchange/taler-exchange-httpd_refresh_reveal.c | 57 ++-- src/exchange/taler-exchange-httpd_refund.c | 17 +- src/exchange/taler-exchange-httpd_reserve_status.c | 12 +- .../taler-exchange-httpd_reserve_withdraw.c | 18 +- src/exchange/taler-exchange-httpd_test.c | 123 +++++---- .../taler-exchange-httpd_track_transaction.c | 18 +- src/exchange/taler-exchange-httpd_track_transfer.c | 12 +- 15 files changed, 158 insertions(+), 591 deletions(-) delete mode 100644 src/exchange/taler-exchange-httpd_parsing.c delete mode 100644 src/exchange/taler-exchange-httpd_parsing.h (limited to 'src') diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am index 899e98d2e..8e1621821 100644 --- a/src/exchange/Makefile.am +++ b/src/exchange/Makefile.am @@ -47,7 +47,6 @@ taler_exchange_httpd_SOURCES = \ taler-exchange-httpd_deposit.c taler-exchange-httpd_deposit.h \ taler-exchange-httpd_keystate.c taler-exchange-httpd_keystate.h \ taler-exchange-httpd_mhd.c taler-exchange-httpd_mhd.h \ - taler-exchange-httpd_parsing.c taler-exchange-httpd_parsing.h \ taler-exchange-httpd_payback.c taler-exchange-httpd_payback.h \ taler-exchange-httpd_refresh_link.c taler-exchange-httpd_refresh_link.h \ taler-exchange-httpd_refresh_melt.c taler-exchange-httpd_refresh_melt.h \ diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index b3f73de60..30efb8bc2 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -28,7 +28,6 @@ #include #include #include "taler_mhd_lib.h" -#include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_mhd.h" #include "taler-exchange-httpd_deposit.h" #include "taler-exchange-httpd_refund.h" @@ -175,7 +174,7 @@ handle_mhd_completion_callback (void *cls, "Request completed\n"); if (NULL == ecls) return; - TEH_PARSE_post_cleanup_callback (ecls->opaque_post_parsing_context); + TALER_MHD_parse_post_cleanup_callback (ecls->opaque_post_parsing_context); GNUNET_free (ecls); *con_cls = NULL; /* check that we didn't leave any transactions hanging */ diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c index 1db8d7621..28116e28b 100644 --- a/src/exchange/taler-exchange-httpd_deposit.c +++ b/src/exchange/taler-exchange-httpd_deposit.c @@ -30,7 +30,6 @@ #include #include "taler_json_lib.h" #include "taler_mhd_lib.h" -#include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_deposit.h" #include "taler-exchange-httpd_responses.h" #include "taler-exchange-httpd_keystate.h" @@ -428,11 +427,11 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, }; (void) rh; - res = TEH_PARSE_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &json); + 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) || @@ -441,9 +440,9 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, memset (&deposit, 0, sizeof (deposit)); - res = TEH_PARSE_json_data (connection, - json, - spec); + res = TALER_MHD_parse_json_data (connection, + json, + spec); json_decref (json); if (GNUNET_SYSERR == res) return MHD_NO; /* hard failure */ diff --git a/src/exchange/taler-exchange-httpd_parsing.c b/src/exchange/taler-exchange-httpd_parsing.c deleted file mode 100644 index fb8932b9a..000000000 --- a/src/exchange/taler-exchange-httpd_parsing.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014, 2015, 2016 GNUnet e.V. - - 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. - - 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, see -*/ - -/** - * @file taler-exchange-httpd_parsing.c - * @brief functions to parse incoming requests (MHD arguments and JSON snippets) - * @author Florian Dold - * @author Benedikt Mueller - * @author Christian Grothoff - */ - -#include "platform.h" -#include -#include -#include "taler_json_lib.h" -#include "taler-exchange-httpd_parsing.h" -#include "taler-exchange-httpd_responses.h" - - -/** - * Maximum POST request size. - */ -#define REQUEST_BUFFER_MAX (1024 * 1024) - - -/** - * Process a POST request containing a JSON object. This function - * realizes an MHD POST processor that will (incrementally) process - * JSON data uploaded to the HTTP server. It will store the required - * state in the @a con_cls, which must be cleaned up using - * #TEH_PARSE_post_cleanup_callback(). - * - * @param connection the MHD connection - * @param con_cls the closure (points to a `struct Buffer *`) - * @param upload_data the POST data - * @param upload_data_size number of bytes in @a upload_data - * @param json the JSON object for a completed request - * @return - * #GNUNET_YES if json object was parsed or at least - * may be parsed in the future (call again); - * `*json` will be NULL if we need to be called again, - * and non-NULL if we are done. - * #GNUNET_NO is request incomplete or invalid - * (error message was generated) - * #GNUNET_SYSERR on internal error - * (we could not even queue an error message, - * close HTTP session with MHD_NO) - */ -int -TEH_PARSE_post_json (struct MHD_Connection *connection, - void **con_cls, - const char *upload_data, - size_t *upload_data_size, - json_t **json) -{ - enum GNUNET_JSON_PostResult pr; - - pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX, - connection, - con_cls, - upload_data, - upload_data_size, - json); - switch (pr) - { - - case GNUNET_JSON_PR_OUT_OF_MEMORY: - return (MHD_NO == TEH_RESPONSE_reply_internal_error - (connection, - TALER_EC_PARSER_OUT_OF_MEMORY, - "out of memory")) ? GNUNET_SYSERR : GNUNET_NO; - - case GNUNET_JSON_PR_CONTINUE: - return GNUNET_YES; - - case GNUNET_JSON_PR_REQUEST_TOO_LARGE: - return (MHD_NO == TEH_RESPONSE_reply_request_too_large - (connection)) ? GNUNET_SYSERR : GNUNET_NO; - - case GNUNET_JSON_PR_JSON_INVALID: - return (MHD_YES == - TEH_RESPONSE_reply_invalid_json (connection)) - ? GNUNET_NO : GNUNET_SYSERR; - case GNUNET_JSON_PR_SUCCESS: - GNUNET_break (NULL != *json); - return GNUNET_YES; - } - /* this should never happen */ - GNUNET_break (0); - return GNUNET_SYSERR; -} - - -/** - * Function called whenever we are done with a request - * to clean up our state. - * - * @param con_cls value as it was left by - * #TEH_PARSE_post_json(), to be cleaned up - */ -void -TEH_PARSE_post_cleanup_callback (void *con_cls) -{ - GNUNET_JSON_post_parser_cleanup (con_cls); -} - - -/** - * Extract base32crockford encoded data from request. - * - * Queues an error response to the connection if the parameter is - * missing or invalid. - * - * @param connection the MHD connection - * @param param_name the name of the parameter with the key - * @param[out] out_data pointer to store the result - * @param out_size expected size of data - * @return - * #GNUNET_YES if the the argument is present - * #GNUNET_NO if the argument is absent or malformed - * #GNUNET_SYSERR on internal error (error response could not be sent) - */ -int -TEH_PARSE_mhd_request_arg_data (struct MHD_Connection *connection, - const char *param_name, - void *out_data, - size_t out_size) -{ - const char *str; - - str = MHD_lookup_connection_value (connection, - MHD_GET_ARGUMENT_KIND, - param_name); - if (NULL == str) - { - return (MHD_NO == - TEH_RESPONSE_reply_arg_missing (connection, - TALER_EC_PARAMETER_MISSING, - param_name)) - ? GNUNET_SYSERR : GNUNET_NO; - } - if (GNUNET_OK != - GNUNET_STRINGS_string_to_data (str, - strlen (str), - out_data, - out_size)) - return (MHD_NO == - TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_PARAMETER_MALFORMED, - param_name)) - ? GNUNET_SYSERR : GNUNET_NO; - return GNUNET_OK; -} - - -/** - * Parse JSON object into components based on the given field - * specification. Generates error response on parse errors. - * - * @param connection the connection to send an error response to - * @param root the JSON node to start the navigation at. - * @param[in,out] spec field specification for the parser - * @return - * #GNUNET_YES if navigation was successful (caller is responsible - * for freeing allocated variable-size data using - * GNUNET_JSON_parse_free() when done) - * #GNUNET_NO if json is malformed, error response was generated - * #GNUNET_SYSERR on internal error - */ -int -TEH_PARSE_json_data (struct MHD_Connection *connection, - const json_t *root, - struct GNUNET_JSON_Specification *spec) -{ - int ret; - const char *error_json_name; - unsigned int error_line; - - ret = GNUNET_JSON_parse (root, - spec, - &error_json_name, - &error_line); - if (GNUNET_SYSERR == ret) - { - if (NULL == error_json_name) - error_json_name = ""; - ret = (MHD_YES == - TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:I, s:s, s:I}", - "error", "parse error", - "code", - (json_int_t) - TALER_EC_JSON_INVALID_WITH_DETAILS, - "field", error_json_name, - "line", (json_int_t) error_line)) - ? GNUNET_NO : GNUNET_SYSERR; - return ret; - } - return GNUNET_YES; -} - - -/** - * Parse JSON array into components based on the given field - * specification. Generates error response on parse errors. - * - * @param connection the connection to send an error response to - * @param root the JSON node to start the navigation at. - * @param[in,out] spec field specification for the parser - * @param ... -1-terminated list of array offsets of type 'int' - * @return - * #GNUNET_YES if navigation was successful (caller is responsible - * for freeing allocated variable-size data using - * GNUNET_JSON_parse_free() when done) - * #GNUNET_NO if json is malformed, error response was generated - * #GNUNET_SYSERR on internal error - */ -int -TEH_PARSE_json_array (struct MHD_Connection *connection, - const json_t *root, - struct GNUNET_JSON_Specification *spec, - ...) -{ - int ret; - const char *error_json_name; - unsigned int error_line; - va_list ap; - json_int_t dim; - - va_start (ap, spec); - dim = 0; - while ( (-1 != (ret = va_arg (ap, int))) && - (NULL != root) ) - { - dim++; - root = json_array_get (root, ret); - } - va_end (ap); - if (NULL == root) - { - ret = (MHD_YES == - TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:I}", - "error", "parse error", - "dimension", dim)) - ? GNUNET_NO : GNUNET_SYSERR; - return ret; - } - ret = GNUNET_JSON_parse (root, - spec, - &error_json_name, - &error_line); - if (GNUNET_SYSERR == ret) - { - if (NULL == error_json_name) - error_json_name = ""; - ret = (MHD_YES == - TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:s, s:I}", - "error", "parse error", - "field", error_json_name, - "line", (json_int_t) error_line)) - ? GNUNET_NO : GNUNET_SYSERR; - return ret; - } - return GNUNET_YES; -} - - -/* end of taler-exchange-httpd_parsing.c */ diff --git a/src/exchange/taler-exchange-httpd_parsing.h b/src/exchange/taler-exchange-httpd_parsing.h deleted file mode 100644 index 9c5381756..000000000 --- a/src/exchange/taler-exchange-httpd_parsing.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014, 2015, 2016 GNUnet e.V. - - 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. - - 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, see -*/ -/** - * @file taler-exchange-httpd_parsing.h - * @brief functions to parse incoming requests - * @author Florian Dold - * @author Benedikt Mueller - * @author Christian Grothoff - */ -#ifndef TALER_EXCHANGE_HTTPD_PARSING_H -#define TALER_EXCHANGE_HTTPD_PARSING_H - -#include -#include -#include "taler_util.h" -#include "taler_json_lib.h" - - -/** - * Process a POST request containing a JSON object. This - * function realizes an MHD POST processor that will - * (incrementally) process JSON data uploaded to the HTTP - * server. It will store the required state in the - * "connection_cls", which must be cleaned up using - * #TEH_PARSE_post_cleanup_callback(). - * - * @param connection the MHD connection - * @param con_cls the closure (points to a `struct Buffer *`) - * @param upload_data the POST data - * @param upload_data_size number of bytes in @a upload_data - * @param json the JSON object for a completed request - * @return - * #GNUNET_YES if json object was parsed or at least - * may be parsed in the future (call again); - * `*json` will be NULL if we need to be called again, - * and non-NULL if we are done. - * #GNUNET_NO is request incomplete or invalid - * (error message was generated) - * #GNUNET_SYSERR on internal error - * (we could not even queue an error message, - * close HTTP session with MHD_NO) - */ -int -TEH_PARSE_post_json (struct MHD_Connection *connection, - void **con_cls, - const char *upload_data, - size_t *upload_data_size, - json_t **json); - - -/** - * Function called whenever we are done with a request - * to clean up our state. - * - * @param con_cls value as it was left by - * #TEH_PARSE_post_json(), to be cleaned up - */ -void -TEH_PARSE_post_cleanup_callback (void *con_cls); - - -/** - * Parse JSON object into components based on the given field - * specification. - * - * @param connection the connection to send an error response to - * @param root the JSON node to start the navigation at. - * @param spec field specification for the parser - * @return - * #GNUNET_YES if navigation was successful (caller is responsible - * for freeing allocated variable-size data using - * GNUNET_JSON_parse_free() when done) - * #GNUNET_NO if json is malformed, error response was generated - * #GNUNET_SYSERR on internal error - */ -int -TEH_PARSE_json_data (struct MHD_Connection *connection, - const json_t *root, - struct GNUNET_JSON_Specification *spec); - - -/** - * Parse JSON array into components based on the given field - * specification. Generates error response on parse errors. - * - * @param connection the connection to send an error response to - * @param root the JSON node to start the navigation at. - * @param[in,out] spec field specification for the parser - * @param ... -1-terminated list of array offsets of type 'int' - * @return - * #GNUNET_YES if navigation was successful (caller is responsible - * for freeing allocated variable-size data using - * GNUNET_JSON_parse_free() when done) - * #GNUNET_NO if json is malformed, error response was generated - * #GNUNET_SYSERR on internal error - */ -int -TEH_PARSE_json_array (struct MHD_Connection *connection, - const json_t *root, - struct GNUNET_JSON_Specification *spec, - ...); - - -/** - * Extraxt fixed-size base32crockford encoded data from request. - * - * Queues an error response to the connection if the parameter is missing or - * invalid. - * - * @param connection the MHD connection - * @param param_name the name of the parameter with the key - * @param[out] out_data pointer to store the result - * @param out_size expected size of @a out_data - * @return - * #GNUNET_YES if the the argument is present - * #GNUNET_NO if the argument is absent or malformed - * #GNUNET_SYSERR on internal error (error response could not be sent) - */ -int -TEH_PARSE_mhd_request_arg_data (struct MHD_Connection *connection, - const char *param_name, - void *out_data, - size_t out_size); - - -#endif /* TALER_EXCHANGE_HTTPD_PARSING_H */ diff --git a/src/exchange/taler-exchange-httpd_payback.c b/src/exchange/taler-exchange-httpd_payback.c index e8a179f1b..f5f315bed 100644 --- a/src/exchange/taler-exchange-httpd_payback.c +++ b/src/exchange/taler-exchange-httpd_payback.c @@ -28,7 +28,6 @@ #include #include "taler_json_lib.h" #include "taler_mhd_lib.h" -#include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_payback.h" #include "taler-exchange-httpd_responses.h" #include "taler-exchange-httpd_keystate.h" @@ -605,18 +604,18 @@ TEH_PAYBACK_handler_payback (struct TEH_RequestHandler *rh, }; (void) rh; - res = TEH_PARSE_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &json); + 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 = TEH_PARSE_json_data (connection, - json, - spec); + res = TALER_MHD_parse_json_data (connection, + json, + spec); json_decref (json); if (GNUNET_SYSERR == res) return MHD_NO; /* hard failure */ diff --git a/src/exchange/taler-exchange-httpd_refresh_link.c b/src/exchange/taler-exchange-httpd_refresh_link.c index 10aed2df8..c3d36e29b 100644 --- a/src/exchange/taler-exchange-httpd_refresh_link.c +++ b/src/exchange/taler-exchange-httpd_refresh_link.c @@ -25,7 +25,6 @@ #include #include #include "taler_mhd_lib.h" -#include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_mhd.h" #include "taler-exchange-httpd_refresh_link.h" #include "taler-exchange-httpd_responses.h" @@ -204,11 +203,11 @@ TEH_REFRESH_handler_refresh_link (struct TEH_RequestHandler *rh, memset (&ctx, 0, sizeof (ctx)); - res = TEH_PARSE_mhd_request_arg_data (connection, - "coin_pub", - &ctx.coin_pub, - sizeof (struct - TALER_CoinSpendPublicKeyP)); + 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) diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c b/src/exchange/taler-exchange-httpd_refresh_melt.c index 2de5027f1..20e788452 100644 --- a/src/exchange/taler-exchange-httpd_refresh_melt.c +++ b/src/exchange/taler-exchange-httpd_refresh_melt.c @@ -24,8 +24,8 @@ #include #include #include +#include "taler_json_lib.h" #include "taler_mhd_lib.h" -#include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_mhd.h" #include "taler-exchange-httpd_refresh_melt.h" #include "taler-exchange-httpd_responses.h" @@ -482,11 +482,11 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, }; (void) rh; - res = TEH_PARSE_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &root); + 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) || @@ -496,9 +496,9 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, memset (&rmc, 0, sizeof (rmc)); - res = TEH_PARSE_json_data (connection, - root, - spec); + 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_reveal.c b/src/exchange/taler-exchange-httpd_refresh_reveal.c index a1200f39e..5276a105a 100644 --- a/src/exchange/taler-exchange-httpd_refresh_reveal.c +++ b/src/exchange/taler-exchange-httpd_refresh_reveal.c @@ -25,7 +25,6 @@ #include #include #include "taler_mhd_lib.h" -#include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_mhd.h" #include "taler-exchange-httpd_refresh_reveal.h" #include "taler-exchange-httpd_responses.h" @@ -586,11 +585,11 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, }; int res; - res = TEH_PARSE_json_array (connection, - tp_json, - trans_spec, - i, - -1); + res = TALER_MHD_parse_json_array (connection, + tp_json, + trans_spec, + i, + -1); if (GNUNET_OK != res) return (GNUNET_NO == res) ? MHD_YES : MHD_NO; } @@ -627,11 +626,11 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, unsigned int hc; enum TALER_ErrorCode ec; - res = TEH_PARSE_json_array (connection, - new_denoms_h_json, - spec, - i, - -1); + res = TALER_MHD_parse_json_array (connection, + new_denoms_h_json, + spec, + i, + -1); if (GNUNET_OK != res) { TEH_KS_release (key_state); @@ -664,11 +663,11 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, GNUNET_JSON_spec_end () }; - res = TEH_PARSE_json_array (connection, - coin_evs, - spec, - i, - -1); + res = TALER_MHD_parse_json_array (connection, + coin_evs, + spec, + i, + -1); if (GNUNET_OK != res) { for (unsigned int j = 0; j #include "taler_json_lib.h" #include "taler_mhd_lib.h" -#include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_refund.h" #include "taler-exchange-httpd_responses.h" #include "taler-exchange-httpd_keystate.h" @@ -526,18 +525,18 @@ TEH_REFUND_handler_refund (struct TEH_RequestHandler *rh, }; (void) rh; - res = TEH_PARSE_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &json); + 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 = TEH_PARSE_json_data (connection, - json, - spec); + res = TALER_MHD_parse_json_data (connection, + json, + spec); json_decref (json); if (GNUNET_SYSERR == res) return MHD_NO; /* hard failure */ diff --git a/src/exchange/taler-exchange-httpd_reserve_status.c b/src/exchange/taler-exchange-httpd_reserve_status.c index 0e46c0b24..60cdd4f5a 100644 --- a/src/exchange/taler-exchange-httpd_reserve_status.c +++ b/src/exchange/taler-exchange-httpd_reserve_status.c @@ -24,8 +24,8 @@ #include #include #include "taler_mhd_lib.h" +#include "taler_json_lib.h" #include "taler-exchange-httpd_reserve_status.h" -#include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_responses.h" #include "taler-exchange-httpd_keystate.h" @@ -137,11 +137,11 @@ TEH_RESERVE_handler_reserve_status (struct TEH_RequestHandler *rh, int res; int mhd_ret; - res = TEH_PARSE_mhd_request_arg_data (connection, - "reserve_pub", - &rsc.reserve_pub, - sizeof (struct - TALER_ReservePublicKeyP)); + 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) diff --git a/src/exchange/taler-exchange-httpd_reserve_withdraw.c b/src/exchange/taler-exchange-httpd_reserve_withdraw.c index 229da564a..120a1e86a 100644 --- a/src/exchange/taler-exchange-httpd_reserve_withdraw.c +++ b/src/exchange/taler-exchange-httpd_reserve_withdraw.c @@ -26,9 +26,9 @@ #include "platform.h" #include #include +#include "taler_json_lib.h" #include "taler_mhd_lib.h" #include "taler-exchange-httpd_reserve_withdraw.h" -#include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_responses.h" #include "taler-exchange-httpd_keystate.h" @@ -394,18 +394,18 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh, }; (void) rh; - res = TEH_PARSE_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &root); + 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; - res = TEH_PARSE_json_data (connection, - root, - spec); + 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_test.c b/src/exchange/taler-exchange-httpd_test.c index 4d0e7d691..4b3c50b2c 100644 --- a/src/exchange/taler-exchange-httpd_test.c +++ b/src/exchange/taler-exchange-httpd_test.c @@ -27,7 +27,6 @@ #include "taler_mhd_lib.h" #include "taler_signatures.h" #include "taler-exchange-httpd_test.h" -#include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_responses.h" @@ -70,18 +69,18 @@ TEH_TEST_handler_test_base32 (struct TEH_RequestHandler *rh, }; (void) rh; - res = TEH_PARSE_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &json); + 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 = TEH_PARSE_json_data (connection, - json, - spec); + res = TALER_MHD_parse_json_data (connection, + json, + spec); if (GNUNET_YES != res) return (GNUNET_NO == res) ? MHD_YES : MHD_NO; GNUNET_CRYPTO_hash (in_ptr, @@ -135,18 +134,18 @@ TEH_TEST_handler_test_encrypt (struct TEH_RequestHandler *rh, }; char *out; - res = TEH_PARSE_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &json); + 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 = TEH_PARSE_json_data (connection, - json, - spec); + res = TALER_MHD_parse_json_data (connection, + json, + spec); json_decref (json); if (GNUNET_YES != res) return (GNUNET_NO == res) ? MHD_YES : MHD_NO; @@ -215,18 +214,18 @@ TEH_TEST_handler_test_hkdf (struct TEH_RequestHandler *rh, GNUNET_JSON_spec_end () }; - res = TEH_PARSE_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &json); + 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 = TEH_PARSE_json_data (connection, - json, - spec); + res = TALER_MHD_parse_json_data (connection, + json, + spec); json_decref (json); if (GNUNET_YES != res) return (GNUNET_NO == res) ? MHD_YES : MHD_NO; @@ -278,18 +277,18 @@ TEH_TEST_handler_test_ecdhe (struct TEH_RequestHandler *rh, GNUNET_JSON_spec_end () }; - res = TEH_PARSE_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &json); + 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 = TEH_PARSE_json_data (connection, - json, - spec); + res = TALER_MHD_parse_json_data (connection, + json, + spec); json_decref (json); if (GNUNET_YES != res) return (GNUNET_NO == res) ? MHD_YES : MHD_NO; @@ -347,18 +346,18 @@ TEH_TEST_handler_test_eddsa (struct TEH_RequestHandler *rh, }; struct GNUNET_CRYPTO_EddsaPrivateKey *pk; - res = TEH_PARSE_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &json); + 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 = TEH_PARSE_json_data (connection, - json, - spec); + res = TALER_MHD_parse_json_data (connection, + json, + spec); json_decref (json); if (GNUNET_YES != res) return (GNUNET_NO == res) ? MHD_YES : MHD_NO; @@ -482,18 +481,18 @@ TEH_TEST_handler_test_rsa_sign (struct TEH_RequestHandler *rh, GNUNET_JSON_spec_end () }; - res = TEH_PARSE_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &json); + 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 = TEH_PARSE_json_data (connection, - json, - spec); + res = TALER_MHD_parse_json_data (connection, + json, + spec); json_decref (json); if (GNUNET_YES != res) return (GNUNET_NO == res) ? MHD_YES : MHD_NO; @@ -563,18 +562,18 @@ TEH_TEST_handler_test_transfer (struct TEH_RequestHandler *rh, }; struct TALER_TransferSecretP secret; - res = TEH_PARSE_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &json); + 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 = TEH_PARSE_json_data (connection, - json, - spec); + res = TALER_MHD_parse_json_data (connection, + json, + spec); json_decref (json); if (GNUNET_YES != res) return (GNUNET_NO == res) ? MHD_YES : MHD_NO; @@ -609,11 +608,11 @@ TEH_TEST_handler_test (struct TEH_RequestHandler *rh, json_t *json; int res; - res = TEH_PARSE_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &json); + 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) ) diff --git a/src/exchange/taler-exchange-httpd_track_transaction.c b/src/exchange/taler-exchange-httpd_track_transaction.c index 5a057d665..757f28bad 100644 --- a/src/exchange/taler-exchange-httpd_track_transaction.c +++ b/src/exchange/taler-exchange-httpd_track_transaction.c @@ -23,9 +23,9 @@ #include #include #include +#include "taler_json_lib.h" #include "taler_mhd_lib.h" #include "taler_signatures.h" -#include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_keystate.h" #include "taler-exchange-httpd_track_transaction.h" #include "taler-exchange-httpd_responses.h" @@ -366,18 +366,18 @@ TEH_TRACKING_handler_track_transaction (struct TEH_RequestHandler *rh, }; (void) rh; - res = TEH_PARSE_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &json); + 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 = TEH_PARSE_json_data (connection, - json, - spec); + res = TALER_MHD_parse_json_data (connection, + json, + spec); if (GNUNET_OK != res) { json_decref (json); diff --git a/src/exchange/taler-exchange-httpd_track_transfer.c b/src/exchange/taler-exchange-httpd_track_transfer.c index 83521f736..f40d7c819 100644 --- a/src/exchange/taler-exchange-httpd_track_transfer.c +++ b/src/exchange/taler-exchange-httpd_track_transfer.c @@ -24,10 +24,10 @@ #include #include #include "taler_signatures.h" -#include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_keystate.h" #include "taler-exchange-httpd_track_transfer.h" #include "taler-exchange-httpd_responses.h" +#include "taler_json_lib.h" #include "taler_mhd_lib.h" #include "taler_wire_lib.h" @@ -503,11 +503,11 @@ TEH_TRACKING_handler_track_transfer (struct TEH_RequestHandler *rh, int mhd_ret; memset (&ctx, 0, sizeof (ctx)); - res = TEH_PARSE_mhd_request_arg_data (connection, - "wtid", - &ctx.wtid, - sizeof (struct - TALER_WireTransferIdentifierRawP)); + 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) -- cgit v1.2.3 From 4c42e7924e8705ab94c6dd2eab3ec8742fa9acc5 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 21:38:09 +0100 Subject: fix --- src/exchange/taler-exchange-httpd_deposit.c | 4 ++-- src/exchange/taler-exchange-httpd_payback.c | 2 +- src/exchange/taler-exchange-httpd_refresh_melt.c | 2 +- src/exchange/taler-exchange-httpd_refresh_reveal.c | 2 +- src/exchange/taler-exchange-httpd_refund.c | 2 +- src/exchange/taler-exchange-httpd_reserve_withdraw.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c index 28116e28b..23a97fb1b 100644 --- a/src/exchange/taler-exchange-httpd_deposit.c +++ b/src/exchange/taler-exchange-httpd_deposit.c @@ -304,8 +304,8 @@ verify_and_execute_deposit (struct MHD_Connection *connection, { TEH_KS_release (mks); return TALER_MHD_reply_with_error (connection, - ec, hc, + ec, "Could not find denomination key used in deposit"); } TALER_amount_ntoh (&dc.value, @@ -527,8 +527,8 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, TALER_LOG_WARNING ("Unknown denomination key in /deposit request\n"); GNUNET_JSON_parse_free (spec); return TALER_MHD_reply_with_error (connection, - ec, hc, + ec, "Could not find denomination key used in deposit"); } TALER_amount_ntoh (&deposit.deposit_fee, diff --git a/src/exchange/taler-exchange-httpd_payback.c b/src/exchange/taler-exchange-httpd_payback.c index f5f315bed..b7fe593d9 100644 --- a/src/exchange/taler-exchange-httpd_payback.c +++ b/src/exchange/taler-exchange-httpd_payback.c @@ -449,8 +449,8 @@ verify_and_execute_payback (struct MHD_Connection *connection, TALER_LOG_WARNING ( "Denomination key in /payback request not in payback mode\n"); return TALER_MHD_reply_with_error (connection, - ec, hc, + ec, "denomination not allowing payback"); } TALER_amount_ntoh (&pc.value, diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c b/src/exchange/taler-exchange-httpd_refresh_melt.c index 20e788452..71f1a6142 100644 --- a/src/exchange/taler-exchange-httpd_refresh_melt.c +++ b/src/exchange/taler-exchange-httpd_refresh_melt.c @@ -585,8 +585,8 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, { TALER_LOG_WARNING ("Unknown denomination key in /refresh/melt request\n"); res = TALER_MHD_reply_with_error (connection, - ec, hc, + ec, "unknown denomination"); goto cleanup; } diff --git a/src/exchange/taler-exchange-httpd_refresh_reveal.c b/src/exchange/taler-exchange-httpd_refresh_reveal.c index 5276a105a..97e687ea9 100644 --- a/src/exchange/taler-exchange-httpd_refresh_reveal.c +++ b/src/exchange/taler-exchange-httpd_refresh_reveal.c @@ -645,8 +645,8 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, { TEH_KS_release (key_state); return TALER_MHD_reply_with_error (connection, - ec, hc, + ec, "failed to find denomination key"); } GNUNET_assert (NULL != dkis[i]->denom_priv.rsa_private_key); diff --git a/src/exchange/taler-exchange-httpd_refund.c b/src/exchange/taler-exchange-httpd_refund.c index 5b0d4ca58..6a96ff982 100644 --- a/src/exchange/taler-exchange-httpd_refund.c +++ b/src/exchange/taler-exchange-httpd_refund.c @@ -372,8 +372,8 @@ refund_transaction (void *cls, TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, tl); *mhd_ret = TALER_MHD_reply_with_error (connection, - ec, hc, + ec, "denomination not found, but coin known"); return GNUNET_DB_STATUS_HARD_ERROR; } diff --git a/src/exchange/taler-exchange-httpd_reserve_withdraw.c b/src/exchange/taler-exchange-httpd_reserve_withdraw.c index 120a1e86a..2b4d2b93d 100644 --- a/src/exchange/taler-exchange-httpd_reserve_withdraw.c +++ b/src/exchange/taler-exchange-httpd_reserve_withdraw.c @@ -429,8 +429,8 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh, GNUNET_JSON_parse_free (spec); TEH_KS_release (wc.key_state); return TALER_MHD_reply_with_error (connection, - ec, hc, + ec, "could not find denomination key"); } GNUNET_assert (NULL != wc.dki->denom_priv.rsa_private_key); -- cgit v1.2.3 From bd8bae913ce0fbd316bd8f0608799d3547f4cba6 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 21:46:41 +0100 Subject: define TINY_AMOUNT --- src/lib/test_auditor_api.conf | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/lib/test_auditor_api.conf b/src/lib/test_auditor_api.conf index e01cbfcbd..3a12b3c5e 100644 --- a/src/lib/test_auditor_api.conf +++ b/src/lib/test_auditor_api.conf @@ -15,6 +15,8 @@ BASE_URL = "http://localhost:8083/" # HTTP port the auditor listens to PORT = 8083 +TINY_AMOUNT = EUR:0.01 + [exchange] # how long is one signkey valid? -- cgit v1.2.3 From 51e54bbaa18397f599e5078153671c98c719c695 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 21:53:14 +0100 Subject: use FORBIDDEN, never UNAUTHORIZED --- src/include/taler_error_codes.h | 4 ++-- src/lib/test_exchange_api_twisted.c | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/include/taler_error_codes.h b/src/include/taler_error_codes.h index 28ee64fed..a2a9bcc46 100644 --- a/src/include/taler_error_codes.h +++ b/src/include/taler_error_codes.h @@ -929,7 +929,7 @@ enum TALER_ErrorCode /** * The given coin signature is invalid for the request. * This response is provided with an - * HTTP status code of MHD_HTTP_UNAUTHORIZED. + * HTTP status code of MHD_HTTP_FORBIDDEN. */ TALER_EC_PAYBACK_SIGNATURE_INVALID = 1851, @@ -1905,7 +1905,7 @@ enum TALER_ErrorCode * The signature provided in the "Sync-Signature" header * does not match the account, old or new Etags. * This response is provided with HTTP status code - * MHD_HTTP_UNAUTHORIZED. + * MHD_HTTP_FORBIDDEN. */ TALER_EC_SYNC_INVALID_SIGNATURE = 6007, diff --git a/src/lib/test_exchange_api_twisted.c b/src/lib/test_exchange_api_twisted.c index 739669b97..968b7e626 100644 --- a/src/lib/test_exchange_api_twisted.c +++ b/src/lib/test_exchange_api_twisted.c @@ -16,9 +16,8 @@ License along with TALER; see the file COPYING. If not, see */ - /** - * @file exchange/test_exchange_api_twister.c + * @file exchange/test_exchange_api_twisted.c * @brief testcase to test exchange's HTTP API interface * @author Marcello Stanisci * @author Sree Harsha Totakura @@ -262,7 +261,7 @@ run (void *cls, TALER_TESTING_cmd_refund ("refund-bad-sig", - MHD_HTTP_UNAUTHORIZED, + MHD_HTTP_FORBIDDEN, "EUR:5", "EUR:0.01", "deposit-refund-1"), -- cgit v1.2.3 From 7aae6c90452c1e9bcae78a5e948f381c1165010a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 22:21:47 +0100 Subject: use CONFLICT for double spending to distinguish properly from FORBIDDEN for bad signatures --- src/auditor/Makefile.am | 4 +- src/auditor/taler-auditor-httpd.c | 8 +- .../taler-auditor-httpd_deposit-confirmation.c | 52 ++- src/auditor/taler-auditor-httpd_exchanges.c | 18 +- src/auditor/taler-auditor-httpd_parsing.c | 284 ------------ src/auditor/taler-auditor-httpd_parsing.h | 139 ------ src/auditor/taler-auditor-httpd_responses.c | 481 --------------------- src/auditor/taler-auditor-httpd_responses.h | 245 ----------- src/exchange/taler-exchange-httpd_refresh_melt.c | 2 +- .../taler-exchange-httpd_reserve_withdraw.c | 2 +- src/exchange/taler-exchange-httpd_responses.c | 2 +- src/include/taler_error_codes.h | 6 +- src/lib/auditor_api_deposit_confirmation.c | 2 +- src/lib/exchange_api_deposit.c | 4 +- src/lib/exchange_api_payback.c | 4 +- src/lib/exchange_api_refresh.c | 16 +- src/lib/exchange_api_refund.c | 2 +- src/lib/exchange_api_reserve.c | 6 +- src/lib/exchange_api_track_transaction.c | 2 +- src/lib/exchange_api_track_transfer.c | 2 +- 20 files changed, 71 insertions(+), 1210 deletions(-) delete mode 100644 src/auditor/taler-auditor-httpd_parsing.c delete mode 100644 src/auditor/taler-auditor-httpd_parsing.h delete mode 100644 src/auditor/taler-auditor-httpd_responses.c delete mode 100644 src/auditor/taler-auditor-httpd_responses.h (limited to 'src') diff --git a/src/auditor/Makefile.am b/src/auditor/Makefile.am index 6d0c81582..a1bb4d247 100644 --- a/src/auditor/Makefile.am +++ b/src/auditor/Makefile.am @@ -52,9 +52,7 @@ taler_auditor_httpd_SOURCES = \ taler-auditor-httpd_db.c taler-auditor-httpd_db.h \ taler-auditor-httpd_deposit-confirmation.c taler-auditor-httpd_deposit-confirmation.h \ taler-auditor-httpd_exchanges.c taler-auditor-httpd_exchanges.h \ - taler-auditor-httpd_mhd.c taler-auditor-httpd_mhd.h \ - taler-auditor-httpd_parsing.c taler-auditor-httpd_parsing.h \ - taler-auditor-httpd_responses.c taler-auditor-httpd_responses.h + taler-auditor-httpd_mhd.c taler-auditor-httpd_mhd.h taler_auditor_httpd_LDADD = \ $(LIBGCRYPT_LIBS) \ $(top_builddir)/src/mhd/libtalermhd.la \ diff --git a/src/auditor/taler-auditor-httpd.c b/src/auditor/taler-auditor-httpd.c index fa4f572ec..bf1e7ac71 100644 --- a/src/auditor/taler-auditor-httpd.c +++ b/src/auditor/taler-auditor-httpd.c @@ -31,7 +31,6 @@ #include "taler_auditordb_lib.h" #include "taler-auditor-httpd_deposit-confirmation.h" #include "taler-auditor-httpd_exchanges.h" -#include "taler-auditor-httpd_parsing.h" #include "taler-auditor-httpd_responses.h" #include "taler-auditor-httpd_mhd.h" #include "taler-auditor-httpd.h" @@ -292,7 +291,7 @@ handle_mhd_completion_callback (void *cls, { if (NULL == *con_cls) return; - TAH_PARSE_post_cleanup_callback (*con_cls); + TALER_MHD_parse_post_cleanup_callback (*con_cls); *con_cls = NULL; } @@ -559,12 +558,17 @@ main (int argc, const char *listen_pid; const char *listen_fds; int fh = -1; + enum TALER_MHD_GlobalOptions go; if (0 >= GNUNET_GETOPT_run ("taler-auditor-httpd", options, argc, argv)) return 1; + go = TALER_MHD_GO_NONE; + if (TAH_auditor_connection_close) + go |= TALER_MHD_GO_FORCE_CONNECTION_CLOSE; + TALER_MHD_setup (go); GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("taler-auditor-httpd", (NULL == loglev) ? "INFO" : loglev, diff --git a/src/auditor/taler-auditor-httpd_deposit-confirmation.c b/src/auditor/taler-auditor-httpd_deposit-confirmation.c index 2b73a910a..23ea14a9f 100644 --- a/src/auditor/taler-auditor-httpd_deposit-confirmation.c +++ b/src/auditor/taler-auditor-httpd_deposit-confirmation.c @@ -27,10 +27,10 @@ #include #include #include "taler_json_lib.h" +#include "taler_mhd_lib.h" #include "taler-auditor-httpd.h" #include "taler-auditor-httpd_db.h" #include "taler-auditor-httpd_deposit-confirmation.h" -#include "taler-auditor-httpd_parsing.h" #include "taler-auditor-httpd_responses.h" @@ -43,10 +43,10 @@ static int reply_deposit_confirmation_success (struct MHD_Connection *connection) { - return TAH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:s}", - "status", "DEPOSIT_CONFIRMATION_OK"); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:s}", + "status", "DEPOSIT_CONFIRMATION_OK"); } @@ -74,8 +74,10 @@ store_exchange_signing_key_transaction (void *cls, if (GNUNET_DB_STATUS_HARD_ERROR == qs) { TALER_LOG_WARNING ("Failed to store exchange signing key in database\n"); - *mhd_ret = TAH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_AUDITOR_EXCHANGE_STORE_DB_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_AUDITOR_EXCHANGE_STORE_DB_ERROR, + "failed to persist exchange signing key"); } return qs; } @@ -111,8 +113,10 @@ deposit_confirmation_transaction (void *cls, { TALER_LOG_WARNING ( "Failed to store /deposit-confirmation information in database\n"); - *mhd_ret = TAH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_DEPOSIT_CONFIRMATION_STORE_DB_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_DEPOSIT_CONFIRMATION_STORE_DB_ERROR, + "failed to persist deposit-confirmation data"); } return qs; } @@ -155,9 +159,10 @@ verify_and_execute_deposit_confirmation (struct MHD_Connection *connection, &es->master_public_key.eddsa_pub)) { TALER_LOG_WARNING ("Invalid signature on exchange signing key\n"); - return TAH_RESPONSE_reply_signature_invalid (connection, - TALER_EC_DEPOSIT_CONFIRMATION_SIGNATURE_INVALID, - "master_sig"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_DEPOSIT_CONFIRMATION_SIGNATURE_INVALID, + "master_sig"); } /* execute transaction */ @@ -187,9 +192,10 @@ verify_and_execute_deposit_confirmation (struct MHD_Connection *connection, &dc->exchange_pub.eddsa_pub)) { TALER_LOG_WARNING ("Invalid signature on /deposit-confirmation request\n"); - return TAH_RESPONSE_reply_signature_invalid (connection, - TALER_EC_DEPOSIT_CONFIRMATION_SIGNATURE_INVALID, - "exchange_sig"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_DEPOSIT_CONFIRMATION_SIGNATURE_INVALID, + "exchange_sig"); } /* execute transaction */ @@ -248,19 +254,19 @@ TAH_DEPOSIT_CONFIRMATION_handler (struct TAH_RequestHandler *rh, GNUNET_JSON_spec_end () }; - res = TAH_PARSE_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &json); + 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 = TAH_PARSE_json_data (connection, - json, - spec); + res = TALER_MHD_parse_json_data (connection, + json, + spec); json_decref (json); es.exchange_pub = dc.exchange_pub; /* used twice! */ dc.master_public_key = es.master_public_key; diff --git a/src/auditor/taler-auditor-httpd_exchanges.c b/src/auditor/taler-auditor-httpd_exchanges.c index 881c45a23..27b339636 100644 --- a/src/auditor/taler-auditor-httpd_exchanges.c +++ b/src/auditor/taler-auditor-httpd_exchanges.c @@ -25,10 +25,10 @@ #include #include #include "taler_json_lib.h" +#include "taler_mhd_lib.h" #include "taler-auditor-httpd.h" #include "taler-auditor-httpd_db.h" #include "taler-auditor-httpd_exchanges.h" -#include "taler-auditor-httpd_parsing.h" #include "taler-auditor-httpd_responses.h" @@ -43,10 +43,10 @@ static int reply_exchanges_success (struct MHD_Connection *connection, json_t *ja) { - return TAH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o}", - "exchanges", ja); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o}", + "exchanges", ja); } @@ -108,8 +108,10 @@ list_exchanges (void *cls, if (GNUNET_DB_STATUS_HARD_ERROR == qs) { TALER_LOG_WARNING ("Failed to handle /exchanges in database\n"); - *mhd_ret = TAH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_LIST_EXCHANGES_DB_ERROR); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_LIST_EXCHANGES_DB_ERROR, + "Could not fetch exchange list from database"); } return qs; } @@ -148,4 +150,4 @@ TAH_EXCHANGES_handler (struct TAH_RequestHandler *rh, } -/* end of taler-auditor-httpd_deposit-confirmation.c */ +/* end of taler-auditor-httpd_exchanges.c */ diff --git a/src/auditor/taler-auditor-httpd_parsing.c b/src/auditor/taler-auditor-httpd_parsing.c deleted file mode 100644 index fb707c88f..000000000 --- a/src/auditor/taler-auditor-httpd_parsing.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014, 2015, 2016 GNUnet e.V. - - 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. - - 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, see -*/ - -/** - * @file taler-auditor-httpd_parsing.c - * @brief functions to parse incoming requests (MHD arguments and JSON snippets) - * @author Florian Dold - * @author Benedikt Mueller - * @author Christian Grothoff - */ - -#include "platform.h" -#include -#include -#include "taler_json_lib.h" -#include "taler-auditor-httpd_parsing.h" -#include "taler-auditor-httpd_responses.h" - - -/** - * Maximum POST request size. - */ -#define REQUEST_BUFFER_MAX (1024 * 1024) - - -/** - * Process a POST request containing a JSON object. This function - * realizes an MHD POST processor that will (incrementally) process - * JSON data uploaded to the HTTP server. It will store the required - * state in the @a con_cls, which must be cleaned up using - * #TAH_PARSE_post_cleanup_callback(). - * - * @param connection the MHD connection - * @param con_cls the closure (points to a `struct Buffer *`) - * @param upload_data the POST data - * @param upload_data_size number of bytes in @a upload_data - * @param json the JSON object for a completed request - * @return - * #GNUNET_YES if json object was parsed or at least - * may be parsed in the future (call again); - * `*json` will be NULL if we need to be called again, - * and non-NULL if we are done. - * #GNUNET_NO is request incomplete or invalid - * (error message was generated) - * #GNUNET_SYSERR on internal error - * (we could not even queue an error message, - * close HTTP session with MHD_NO) - */ -int -TAH_PARSE_post_json (struct MHD_Connection *connection, - void **con_cls, - const char *upload_data, - size_t *upload_data_size, - json_t **json) -{ - enum GNUNET_JSON_PostResult pr; - - pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX, - connection, - con_cls, - upload_data, - upload_data_size, - json); - switch (pr) - { - case GNUNET_JSON_PR_OUT_OF_MEMORY: - return (MHD_NO == - TAH_RESPONSE_reply_internal_error (connection, - TALER_EC_PARSER_OUT_OF_MEMORY, - "out of memory")) - ? GNUNET_SYSERR : GNUNET_NO; - case GNUNET_JSON_PR_CONTINUE: - return GNUNET_YES; - case GNUNET_JSON_PR_REQUEST_TOO_LARGE: - return (MHD_NO == - TAH_RESPONSE_reply_request_too_large (connection)) - ? GNUNET_SYSERR : GNUNET_NO; - case GNUNET_JSON_PR_JSON_INVALID: - return (MHD_YES == - TAH_RESPONSE_reply_invalid_json (connection)) - ? GNUNET_NO : GNUNET_SYSERR; - case GNUNET_JSON_PR_SUCCESS: - GNUNET_break (NULL != *json); - return GNUNET_YES; - } - /* this should never happen */ - GNUNET_break (0); - return GNUNET_SYSERR; -} - - -/** - * Function called whenever we are done with a request - * to clean up our state. - * - * @param con_cls value as it was left by - * #TAH_PARSE_post_json(), to be cleaned up - */ -void -TAH_PARSE_post_cleanup_callback (void *con_cls) -{ - GNUNET_JSON_post_parser_cleanup (con_cls); -} - - -/** - * Extract base32crockford encoded data from request. - * - * Queues an error response to the connection if the parameter is - * missing or invalid. - * - * @param connection the MHD connection - * @param param_name the name of the parameter with the key - * @param[out] out_data pointer to store the result - * @param out_size expected size of data - * @return - * #GNUNET_YES if the the argument is present - * #GNUNET_NO if the argument is absent or malformed - * #GNUNET_SYSERR on internal error (error response could not be sent) - */ -int -TAH_PARSE_mhd_request_arg_data (struct MHD_Connection *connection, - const char *param_name, - void *out_data, - size_t out_size) -{ - const char *str; - - str = MHD_lookup_connection_value (connection, - MHD_GET_ARGUMENT_KIND, - param_name); - if (NULL == str) - { - return (MHD_NO == - TAH_RESPONSE_reply_arg_missing (connection, - TALER_EC_PARAMETER_MISSING, - param_name)) - ? GNUNET_SYSERR : GNUNET_NO; - } - if (GNUNET_OK != - GNUNET_STRINGS_string_to_data (str, - strlen (str), - out_data, - out_size)) - return (MHD_NO == - TAH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_PARAMETER_MALFORMED, - param_name)) - ? GNUNET_SYSERR : GNUNET_NO; - return GNUNET_OK; -} - - -/** - * Parse JSON object into components based on the given field - * specification. Generates error response on parse errors. - * - * @param connection the connection to send an error response to - * @param root the JSON node to start the navigation at. - * @param[in,out] spec field specification for the parser - * @return - * #GNUNET_YES if navigation was successful (caller is responsible - * for freeing allocated variable-size data using - * GNUNET_JSON_parse_free() when done) - * #GNUNET_NO if json is malformed, error response was generated - * #GNUNET_SYSERR on internal error - */ -int -TAH_PARSE_json_data (struct MHD_Connection *connection, - const json_t *root, - struct GNUNET_JSON_Specification *spec) -{ - int ret; - const char *error_json_name; - unsigned int error_line; - - ret = GNUNET_JSON_parse (root, - spec, - &error_json_name, - &error_line); - if (GNUNET_SYSERR == ret) - { - if (NULL == error_json_name) - error_json_name = ""; - ret = (MHD_YES == - TAH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:I, s:s, s:I}", - "error", "parse error", - "code", - (json_int_t) - TALER_EC_JSON_INVALID_WITH_DETAILS, - "field", error_json_name, - "line", (json_int_t) error_line)) - ? GNUNET_NO : GNUNET_SYSERR; - return ret; - } - return GNUNET_YES; -} - - -/** - * Parse JSON array into components based on the given field - * specification. Generates error response on parse errors. - * - * @param connection the connection to send an error response to - * @param root the JSON node to start the navigation at. - * @param[in,out] spec field specification for the parser - * @param ... -1-terminated list of array offsets of type 'int' - * @return - * #GNUNET_YES if navigation was successful (caller is responsible - * for freeing allocated variable-size data using - * GNUNET_JSON_parse_free() when done) - * #GNUNET_NO if json is malformed, error response was generated - * #GNUNET_SYSERR on internal error - */ -int -TAH_PARSE_json_array (struct MHD_Connection *connection, - const json_t *root, - struct GNUNET_JSON_Specification *spec, - ...) -{ - int ret; - const char *error_json_name; - unsigned int error_line; - va_list ap; - json_int_t dim; - - va_start (ap, spec); - dim = 0; - while ( (-1 != (ret = va_arg (ap, int))) && - (NULL != root) ) - { - dim++; - root = json_array_get (root, ret); - } - va_end (ap); - if (NULL == root) - { - ret = (MHD_YES == - TAH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:I}", - "error", "parse error", - "dimension", dim)) - ? GNUNET_NO : GNUNET_SYSERR; - return ret; - } - ret = GNUNET_JSON_parse (root, - spec, - &error_json_name, - &error_line); - if (GNUNET_SYSERR == ret) - { - if (NULL == error_json_name) - error_json_name = ""; - ret = (MHD_YES == - TAH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:s, s:I}", - "error", "parse error", - "field", error_json_name, - "line", (json_int_t) error_line)) - ? GNUNET_NO : GNUNET_SYSERR; - return ret; - } - return GNUNET_YES; -} - - -/* end of taler-auditor-httpd_parsing.c */ diff --git a/src/auditor/taler-auditor-httpd_parsing.h b/src/auditor/taler-auditor-httpd_parsing.h deleted file mode 100644 index 7df76ef54..000000000 --- a/src/auditor/taler-auditor-httpd_parsing.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014, 2015, 2016 GNUnet e.V. - - 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. - - 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, see -*/ -/** - * @file taler-auditor-httpd_parsing.h - * @brief functions to parse incoming requests - * @author Florian Dold - * @author Benedikt Mueller - * @author Christian Grothoff - */ -#ifndef TALER_AUDITOR_HTTPD_PARSING_H -#define TALER_AUDITOR_HTTPD_PARSING_H - -#include -#include -#include "taler_util.h" -#include "taler_json_lib.h" - - -/** - * Process a POST request containing a JSON object. This - * function realizes an MHD POST processor that will - * (incrementally) process JSON data uploaded to the HTTP - * server. It will store the required state in the - * "connection_cls", which must be cleaned up using - * #TAH_PARSE_post_cleanup_callback(). - * - * @param connection the MHD connection - * @param con_cls the closure (points to a `struct Buffer *`) - * @param upload_data the POST data - * @param upload_data_size number of bytes in @a upload_data - * @param json the JSON object for a completed request - * @return - * #GNUNET_YES if json object was parsed or at least - * may be parsed in the future (call again); - * `*json` will be NULL if we need to be called again, - * and non-NULL if we are done. - * #GNUNET_NO is request incomplete or invalid - * (error message was generated) - * #GNUNET_SYSERR on internal error - * (we could not even queue an error message, - * close HTTP session with MHD_NO) - */ -int -TAH_PARSE_post_json (struct MHD_Connection *connection, - void **con_cls, - const char *upload_data, - size_t *upload_data_size, - json_t **json); - - -/** - * Function called whenever we are done with a request - * to clean up our state. - * - * @param con_cls value as it was left by - * #TAH_PARSE_post_json(), to be cleaned up - */ -void -TAH_PARSE_post_cleanup_callback (void *con_cls); - - -/** - * Parse JSON object into components based on the given field - * specification. - * - * @param connection the connection to send an error response to - * @param root the JSON node to start the navigation at. - * @param spec field specification for the parser - * @return - * #GNUNET_YES if navigation was successful (caller is responsible - * for freeing allocated variable-size data using - * GNUNET_JSON_parse_free() when done) - * #GNUNET_NO if json is malformed, error response was generated - * #GNUNET_SYSERR on internal error - */ -int -TAH_PARSE_json_data (struct MHD_Connection *connection, - const json_t *root, - struct GNUNET_JSON_Specification *spec); - - -/** - * Parse JSON array into components based on the given field - * specification. Generates error response on parse errors. - * - * @param connection the connection to send an error response to - * @param root the JSON node to start the navigation at. - * @param[in,out] spec field specification for the parser - * @param ... -1-terminated list of array offsets of type 'int' - * @return - * #GNUNET_YES if navigation was successful (caller is responsible - * for freeing allocated variable-size data using - * GNUNET_JSON_parse_free() when done) - * #GNUNET_NO if json is malformed, error response was generated - * #GNUNET_SYSERR on internal error - */ -int -TAH_PARSE_json_array (struct MHD_Connection *connection, - const json_t *root, - struct GNUNET_JSON_Specification *spec, - ...); - - -/** - * Extraxt fixed-size base32crockford encoded data from request. - * - * Queues an error response to the connection if the parameter is missing or - * invalid. - * - * @param connection the MHD connection - * @param param_name the name of the parameter with the key - * @param[out] out_data pointer to store the result - * @param out_size expected size of @a out_data - * @return - * #GNUNET_YES if the the argument is present - * #GNUNET_NO if the argument is absent or malformed - * #GNUNET_SYSERR on internal error (error response could not be sent) - */ -int -TAH_PARSE_mhd_request_arg_data (struct MHD_Connection *connection, - const char *param_name, - void *out_data, - size_t out_size); - - -#endif /* TALER_AUDITOR_HTTPD_PARSING_H */ diff --git a/src/auditor/taler-auditor-httpd_responses.c b/src/auditor/taler-auditor-httpd_responses.c deleted file mode 100644 index 2f78fb0f5..000000000 --- a/src/auditor/taler-auditor-httpd_responses.c +++ /dev/null @@ -1,481 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2017 Inria & GNUnet e.V. - - 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. - - 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, see -*/ -/** - * @file taler-auditor-httpd_responses.c - * @brief API for generating genric replies of the exchange; these - * functions are called TAH_RESPONSE_reply_ and they generate - * and queue MHD response objects for a given connection. - * @author Florian Dold - * @author Benedikt Mueller - * @author Christian Grothoff - */ -#include "platform.h" -#include -#include "taler_mhd_lib.h" -#include "taler-auditor-httpd_responses.h" -#include "taler_util.h" -#include "taler_json_lib.h" - - -/** - * Add headers we want to return in every response. - * Useful for testing, like if we want to always close - * connections. - * - * @param response response to modify - */ -void -TAH_RESPONSE_add_global_headers (struct MHD_Response *response) -{ - if (TAH_auditor_connection_close) - GNUNET_break (MHD_YES == - MHD_add_response_header (response, - MHD_HTTP_HEADER_CONNECTION, - "close")); -} - - -/** - * Is HTTP body deflate compression supported by the client? - * - * @param connection connection to check - * @return #MHD_YES if 'deflate' compression is allowed - * - * Note that right now we're ignoring q-values, which is technically - * not correct, and also do not support "*" anywhere but in a line by - * itself. This should eventually be fixed, see also - * https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html - */ -int -TAH_RESPONSE_can_compress (struct MHD_Connection *connection) -{ - const char *ae; - const char *de; - - ae = MHD_lookup_connection_value (connection, - MHD_HEADER_KIND, - MHD_HTTP_HEADER_ACCEPT_ENCODING); - if (NULL == ae) - return MHD_NO; - if (0 == strcmp (ae, - "*")) - return MHD_YES; - de = strstr (ae, - "deflate"); - if (NULL == de) - return MHD_NO; - if ( ( (de == ae) || - (de[-1] == ',') || - (de[-1] == ' ') ) && - ( (de[strlen ("deflate")] == '\0') || - (de[strlen ("deflate")] == ',') || - (de[strlen ("deflate")] == ';') ) ) - return MHD_YES; - return MHD_NO; -} - - -/** - * Try to compress a response body. Updates @a buf and @a buf_size. - * - * @param[in,out] buf pointer to body to compress - * @param[in,out] buf_size pointer to initial size of @a buf - * @return #MHD_YES if @a buf was compressed - */ -int -TAH_RESPONSE_body_compress (void **buf, - size_t *buf_size) -{ - Bytef *cbuf; - uLongf cbuf_size; - int ret; - - cbuf_size = compressBound (*buf_size); - cbuf = malloc (cbuf_size); - if (NULL == cbuf) - return MHD_NO; - ret = compress (cbuf, - &cbuf_size, - (const Bytef *) *buf, - *buf_size); - if ( (Z_OK != ret) || - (cbuf_size >= *buf_size) ) - { - /* compression failed */ - free (cbuf); - return MHD_NO; - } - free (*buf); - *buf = (void *) cbuf; - *buf_size = (size_t) cbuf_size; - return MHD_YES; -} - - -/** - * Send JSON object as response. - * - * @param connection the MHD connection - * @param json the json object - * @param response_code the http response code - * @return MHD result code - */ -int -TAH_RESPONSE_reply_json (struct MHD_Connection *connection, - const json_t *json, - unsigned int response_code) -{ - struct MHD_Response *resp; - void *json_str; - size_t json_len; - int ret; - int comp; - - json_str = json_dumps (json, - JSON_INDENT (2)); - if (NULL == json_str) - { - /** - * This log helps to figure out which - * function called this one and assert-failed. - */ - TALER_LOG_ERROR ("Aborting json-packing for HTTP code: %u\n", - response_code); - - GNUNET_assert (0); - return MHD_NO; - } - json_len = strlen (json_str); - /* try to compress the body */ - comp = MHD_NO; - if (MHD_YES == - TAH_RESPONSE_can_compress (connection)) - comp = TAH_RESPONSE_body_compress (&json_str, - &json_len); - resp = MHD_create_response_from_buffer (json_len, - json_str, - MHD_RESPMEM_MUST_FREE); - if (NULL == resp) - { - free (json_str); - GNUNET_break (0); - return MHD_NO; - } - TAH_RESPONSE_add_global_headers (resp); - (void) MHD_add_response_header (resp, - MHD_HTTP_HEADER_CONTENT_TYPE, - "application/json"); - if (MHD_YES == comp) - { - /* Need to indicate to client that body is compressed */ - if (MHD_NO == - MHD_add_response_header (resp, - MHD_HTTP_HEADER_CONTENT_ENCODING, - "deflate")) - { - GNUNET_break (0); - MHD_destroy_response (resp); - return MHD_NO; - } - } - ret = MHD_queue_response (connection, - response_code, - resp); - MHD_destroy_response (resp); - return ret; -} - - -/** - * Function to call to handle the request by building a JSON - * reply from a format string and varargs. - * - * @param connection the MHD connection to handle - * @param response_code HTTP response code to use - * @param fmt format string for pack - * @param ... varargs - * @return MHD result code - */ -int -TAH_RESPONSE_reply_json_pack (struct MHD_Connection *connection, - unsigned int response_code, - const char *fmt, - ...) -{ - json_t *json; - va_list argp; - int ret; - json_error_t jerror; - - va_start (argp, fmt); - json = json_vpack_ex (&jerror, 0, fmt, argp); - va_end (argp); - if (NULL == json) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to pack JSON with format `%s': %s\n", - fmt, - jerror.text); - GNUNET_break (0); - return MHD_NO; - } - ret = TAH_RESPONSE_reply_json (connection, - json, - response_code); - json_decref (json); - return ret; -} - - -/** - * Send a response indicating an invalid argument. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param param_name the parameter that is invalid - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_arg_invalid (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *param_name) -{ - return TAH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:I, s:s}", - "error", "invalid parameter", - "code", (json_int_t) ec, - "parameter", param_name); -} - - -/** - * Send a response indicating an argument refering to a - * resource unknown to the auditor (i.e. unknown reserve or - * denomination key). - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param param_name the parameter that is invalid - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_arg_unknown (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *param_name) -{ - return TAH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_NOT_FOUND, - "{s:s, s:I, s:s}", - "error", "unknown entity referenced", - "code", (json_int_t) ec, - "parameter", param_name); -} - - -/** - * Send a response indicating an invalid signature. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param param_name the parameter that is invalid - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_signature_invalid (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *param_name) -{ - return TAH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_UNAUTHORIZED, - "{s:s, s:I, s:s}", - "error", "invalid signature", - "code", (json_int_t) ec, - "parameter", param_name); -} - - -/** - * Send a response indicating a missing argument. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param param_name the parameter that is missing - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_arg_missing (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *param_name) -{ - return TAH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:I, s:s}", - "error", "missing parameter", - "code", (json_int_t) ec, - "parameter", param_name); -} - - -/** - * Send a response indicating permission denied. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param hint hint about why access was denied - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_permission_denied (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *hint) -{ - return TAH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_FORBIDDEN, - "{s:s, s:I, s:s}", - "error", "permission denied", - "code", (json_int_t) ec, - "hint", hint); -} - - -/** - * Send a response indicating an internal error. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param hint hint about the internal error's nature - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_internal_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *hint) -{ - return TAH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - "{s:s, s:I, s:s}", - "error", "internal error", - "code", (json_int_t) ec, - "hint", hint); -} - - -/** - * Send a response indicating an external error. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param hint hint about the error's nature - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_external_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *hint) -{ - return TAH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:I, s:s}", - "error", "client error", - "code", (json_int_t) ec, - "hint", hint); -} - - -/** - * Send a response indicating an error committing a - * transaction (concurrent interference). - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_commit_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec) -{ - return TAH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - "{s:s, s:I}", - "error", "commit failure", - "code", (json_int_t) ec); -} - - -/** - * Send a response indicating a failure to talk to the Auditor's - * database. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_internal_db_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec) -{ - return TAH_RESPONSE_reply_internal_error (connection, - ec, - "Failure in database interaction"); -} - - -/** - * Send a response indicating that the request was too big. - * - * @param connection the MHD connection to use - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_request_too_large (struct MHD_Connection *connection) -{ - struct MHD_Response *resp; - int ret; - - resp = MHD_create_response_from_buffer (0, - NULL, - MHD_RESPMEM_PERSISTENT); - if (NULL == resp) - return MHD_NO; - TAH_RESPONSE_add_global_headers (resp); - ret = MHD_queue_response (connection, - MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, - resp); - MHD_destroy_response (resp); - return ret; -} - - -/** - * Send a response indicating that the JSON was malformed. - * - * @param connection the MHD connection to use - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_invalid_json (struct MHD_Connection *connection) -{ - return TAH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:I}", - "error", "invalid json", - "code", - (json_int_t) TALER_EC_JSON_INVALID); -} - - -/* end of taler-auditor-httpd_responses.c */ diff --git a/src/auditor/taler-auditor-httpd_responses.h b/src/auditor/taler-auditor-httpd_responses.h deleted file mode 100644 index 1cb5faa82..000000000 --- a/src/auditor/taler-auditor-httpd_responses.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014 GNUnet e.V. - - 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. - - 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, see -*/ - -/** - * @file taler-auditor-httpd_responses.h - * @brief API for generating generic replies of the auditor; these - * functions are called TAH_RESPONSE_reply_ and they generate - * and queue MHD response objects for a given connection. - * @author Florian Dold - * @author Benedikt Mueller - * @author Christian Grothoff - */ -#ifndef TALER_AUDITOR_HTTPD_RESPONSES_H -#define TALER_AUDITOR_HTTPD_RESPONSES_H -#include -#include -#include -#include -#include "taler_error_codes.h" -#include "taler-auditor-httpd.h" - - -/** - * Add headers we want to return in every response. - * Useful for testing, like if we want to always close - * connections. - * - * @param response response to modify - */ -void -TAH_RESPONSE_add_global_headers (struct MHD_Response *response); - - -/** - * Try to compress a response body. Updates @a buf and @a buf_size. - * - * @param[in,out] buf pointer to body to compress - * @param[in,out] buf_size pointer to initial size of @a buf - * @return #MHD_YES if @a buf was compressed - */ -int -TAH_RESPONSE_body_compress (void **buf, - size_t *buf_size); - - -/** - * Is HTTP body deflate compression supported by the client? - * - * @param connection connection to check - * @return #MHD_YES if 'deflate' compression is allowed - */ -int -TAH_RESPONSE_can_compress (struct MHD_Connection *connection); - - -/** - * Send JSON object as response. - * - * @param connection the MHD connection - * @param json the json object - * @param response_code the http response code - * @return MHD result code - */ -int -TAH_RESPONSE_reply_json (struct MHD_Connection *connection, - const json_t *json, - unsigned int response_code); - - -/** - * Function to call to handle the request by building a JSON - * reply from a format string and varargs. - * - * @param connection the MHD connection to handle - * @param response_code HTTP response code to use - * @param fmt format string for pack - * @param ... varargs - * @return MHD result code - */ -int -TAH_RESPONSE_reply_json_pack (struct MHD_Connection *connection, - unsigned int response_code, - const char *fmt, - ...); - - -/** - * Send a response indicating an invalid signature. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param param_name the parameter that is invalid - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_signature_invalid (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *param_name); - - -/** - * Send a response indicating an invalid argument. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param param_name the parameter that is invalid - * @return MHD result code - */ -int -TAH_RESPONSE_reply_arg_invalid (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *param_name); - - -/** - * Send a response indicating an argument refering to a - * resource unknown to the auditor (i.e. unknown reserve or - * denomination key). - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param param_name the parameter that is invalid - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_arg_unknown (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *param_name); - - -/** - * Send a response indicating a missing argument. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param param_name the parameter that is missing - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_arg_missing (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *param_name); - - -/** - * Send a response indicating permission denied. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param hint hint about why access was denied - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_permission_denied (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *hint); - - -/** - * Send a response indicating an internal error. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param hint hint about the internal error's nature - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_internal_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *hint); - - -/** - * Send a response indicating an external error. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param hint hint about the error's nature - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_external_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *hint); - - -/** - * Send a response indicating an error committing a - * transaction (concurrent interference). - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_commit_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec); - -/** - * Send a response indicating a failure to talk to the Auditor's - * database. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_internal_db_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec); - - -/** - * Send a response indicating that the request was too big. - * - * @param connection the MHD connection to use - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_request_too_large (struct MHD_Connection *connection); - - -/** - * Send a response indicating that the JSON was malformed. - * - * @param connection the MHD connection to use - * @return a MHD result code - */ -int -TAH_RESPONSE_reply_invalid_json (struct MHD_Connection *connectionx); - - -#endif diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c b/src/exchange/taler-exchange-httpd_refresh_melt.c index 71f1a6142..8fbb58513 100644 --- a/src/exchange/taler-exchange-httpd_refresh_melt.c +++ b/src/exchange/taler-exchange-httpd_refresh_melt.c @@ -66,7 +66,7 @@ reply_refresh_melt_insufficient_funds (struct MHD_Connection *connection, TALER_EC_REFRESH_MELT_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS, "Failed to compile transaction history"); return TALER_MHD_reply_json_pack (connection, - MHD_HTTP_FORBIDDEN, + MHD_HTTP_CONFLICT, "{s:s, s:I, s:o, s:o, s:o, s:o, s:o}", "error", "insufficient funds", diff --git a/src/exchange/taler-exchange-httpd_reserve_withdraw.c b/src/exchange/taler-exchange-httpd_reserve_withdraw.c index 2b4d2b93d..8b59817a7 100644 --- a/src/exchange/taler-exchange-httpd_reserve_withdraw.c +++ b/src/exchange/taler-exchange-httpd_reserve_withdraw.c @@ -72,7 +72,7 @@ reply_reserve_withdraw_insufficient_funds (struct MHD_Connection *connection, json_balance = TALER_JSON_from_amount (&balance); return TALER_MHD_reply_json_pack (connection, - MHD_HTTP_FORBIDDEN, + MHD_HTTP_CONFLICT, "{s:s, s:I, s:o, s:o}", "error", "Insufficient funds", "code", diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c index f051cd2e5..97b1e8f1e 100644 --- a/src/exchange/taler-exchange-httpd_responses.c +++ b/src/exchange/taler-exchange-httpd_responses.c @@ -880,7 +880,7 @@ TEH_RESPONSE_reply_coin_insufficient_funds (struct MHD_Connection *connection, TALER_EC_COIN_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS, "failed to convert transaction history to JSON"); return TALER_MHD_reply_json_pack (connection, - MHD_HTTP_FORBIDDEN, + MHD_HTTP_CONFLICT, "{s:s, s:I, s:o}", "error", "insufficient funds", "code", (json_int_t) ec, diff --git a/src/include/taler_error_codes.h b/src/include/taler_error_codes.h index a2a9bcc46..871ec2bfe 100644 --- a/src/include/taler_error_codes.h +++ b/src/include/taler_error_codes.h @@ -188,7 +188,7 @@ enum TALER_ErrorCode * requested withdraw operation at this time. The response includes * the current "balance" of the reserve as well as the transaction * "history" that lead to this balance. This response is provided - * with HTTP status code MHD_HTTP_FORBIDDEN. + * with HTTP status code MHD_HTTP_CONFLICT. */ TALER_EC_WITHDRAW_INSUFFICIENT_FUNDS = 1100, @@ -340,7 +340,7 @@ enum TALER_ErrorCode * for the /deposit operation (i.e. due to double spending). * The "history" in the respose provides the transaction history * of the coin proving this fact. This response is provided - * with HTTP status code MHD_HTTP_FORBIDDEN. + * with HTTP status code MHD_HTTP_CONFLICT. */ TALER_EC_DEPOSIT_INSUFFICIENT_FUNDS = 1200, @@ -496,7 +496,7 @@ enum TALER_ErrorCode * for the /refresh/melt operation. The "history" in this * response provdes the "residual_value" of the coin, which may * be less than its "original_value". This response is provided - * with HTTP status code MHD_HTTP_FORBIDDEN. + * with HTTP status code MHD_HTTP_CONFLICT. */ TALER_EC_REFRESH_MELT_INSUFFICIENT_FUNDS = 1300, diff --git a/src/lib/auditor_api_deposit_confirmation.c b/src/lib/auditor_api_deposit_confirmation.c index f221b7fd7..73173cc31 100644 --- a/src/lib/auditor_api_deposit_confirmation.c +++ b/src/lib/auditor_api_deposit_confirmation.c @@ -99,7 +99,7 @@ handle_deposit_confirmation_finished (void *cls, /* This should never happen, either us or the auditor is buggy (or API version conflict); just pass JSON reply to the application */ break; - case MHD_HTTP_UNAUTHORIZED: + case MHD_HTTP_FORBIDDEN: /* Nothing really to verify, auditor says one of the signatures is invalid; as we checked them, this should never happen, we should pass the JSON reply to the application */ diff --git a/src/lib/exchange_api_deposit.c b/src/lib/exchange_api_deposit.c index 48f9a06bb..30bb6c976 100644 --- a/src/lib/exchange_api_deposit.c +++ b/src/lib/exchange_api_deposit.c @@ -325,7 +325,7 @@ handle_deposit_finished (void *cls, /* This should never happen, either us or the exchange is buggy (or API version conflict); just pass JSON reply to the application */ break; - case MHD_HTTP_FORBIDDEN: + case MHD_HTTP_CONFLICT: /* Double spending; check signatures on transaction history */ if (GNUNET_OK != verify_deposit_signature_forbidden (dh, @@ -335,7 +335,7 @@ handle_deposit_finished (void *cls, response_code = 0; } break; - case MHD_HTTP_UNAUTHORIZED: + case MHD_HTTP_FORBIDDEN: /* Nothing really to verify, exchange says one of the signatures is invalid; as we checked them, this should never happen, we should pass the JSON reply to the application */ diff --git a/src/lib/exchange_api_payback.c b/src/lib/exchange_api_payback.c index 912548cfe..f9df27e7a 100644 --- a/src/lib/exchange_api_payback.c +++ b/src/lib/exchange_api_payback.c @@ -226,7 +226,7 @@ handle_payback_finished (void *cls, /* This should never happen, either us or the exchange is buggy (or API version conflict); just pass JSON reply to the application */ break; - case MHD_HTTP_FORBIDDEN: + case MHD_HTTP_CONFLICT: { /* Insufficient funds, proof attached */ json_t *history; @@ -256,7 +256,7 @@ handle_payback_finished (void *cls, TALER_EXCHANGE_payback_cancel (ph); return; } - case MHD_HTTP_UNAUTHORIZED: + case MHD_HTTP_FORBIDDEN: /* Nothing really to verify, exchange says one of the signatures is invalid; as we checked them, this should never happen, we should pass the JSON reply to the application */ diff --git a/src/lib/exchange_api_refresh.c b/src/lib/exchange_api_refresh.c index db3692bcd..a75baec86 100644 --- a/src/lib/exchange_api_refresh.c +++ b/src/lib/exchange_api_refresh.c @@ -939,7 +939,7 @@ verify_refresh_melt_signature_ok (struct TALER_EXCHANGE_RefreshMeltHandle *rmh, /** - * Verify that the signatures on the "403 FORBIDDEN" response from the + * Verify that the signatures on the "409 CONFLICT" response from the * exchange demonstrating customer double-spending are valid. * * @param rmh melt handle @@ -947,9 +947,9 @@ verify_refresh_melt_signature_ok (struct TALER_EXCHANGE_RefreshMeltHandle *rmh, * @return #GNUNET_OK if the signature(s) is valid, #GNUNET_SYSERR if not */ static int -verify_refresh_melt_signature_forbidden (struct - TALER_EXCHANGE_RefreshMeltHandle *rmh, - const json_t *json) +verify_refresh_melt_signature_conflict (struct + TALER_EXCHANGE_RefreshMeltHandle *rmh, + const json_t *json) { json_t *history; struct TALER_Amount original_value; @@ -1083,17 +1083,17 @@ handle_refresh_melt_finished (void *cls, /* This should never happen, either us or the exchange is buggy (or API version conflict); just pass JSON reply to the application */ break; - case MHD_HTTP_FORBIDDEN: + case MHD_HTTP_CONFLICT: /* Double spending; check signatures on transaction history */ if (GNUNET_OK != - verify_refresh_melt_signature_forbidden (rmh, - j)) + verify_refresh_melt_signature_conflict (rmh, + j)) { GNUNET_break_op (0); response_code = 0; } break; - case MHD_HTTP_UNAUTHORIZED: + case MHD_HTTP_FORBIDDEN: /* Nothing really to verify, exchange says one of the signatures is invalid; assuming we checked them, this should never happen, we should pass the JSON reply to the application */ diff --git a/src/lib/exchange_api_refund.c b/src/lib/exchange_api_refund.c index e8ae6b74a..b8c422e88 100644 --- a/src/lib/exchange_api_refund.c +++ b/src/lib/exchange_api_refund.c @@ -169,7 +169,7 @@ handle_refund_finished (void *cls, /* This should never happen, either us or the exchange is buggy (or API version conflict); just pass JSON reply to the application */ break; - case MHD_HTTP_UNAUTHORIZED: + case MHD_HTTP_FORBIDDEN: /* Nothing really to verify, exchange says one of the signatures is invalid; as we checked them, this should never happen, we should pass the JSON reply to the application */ diff --git a/src/lib/exchange_api_reserve.c b/src/lib/exchange_api_reserve.c index a57d4e9dc..2c62cac20 100644 --- a/src/lib/exchange_api_reserve.c +++ b/src/lib/exchange_api_reserve.c @@ -797,7 +797,7 @@ reserve_withdraw_ok (struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh, /** - * We got a 403 FORBIDDEN response for the /reserve/withdraw operation. + * We got a 409 CONFLICT response for the /reserve/withdraw operation. * Check the signatures on the withdraw transactions in the provided * history and that the balances add up. We don't do anything directly * with the information, as the JSON will be returned to the application. @@ -941,7 +941,7 @@ handle_reserve_withdraw_finished (void *cls, /* This should never happen, either us or the exchange is buggy (or API version conflict); just pass JSON reply to the application */ break; - case MHD_HTTP_FORBIDDEN: + case MHD_HTTP_CONFLICT: /* The exchange says that the reserve has insufficient funds; check the signatures in the history... */ if (GNUNET_OK != @@ -952,7 +952,7 @@ handle_reserve_withdraw_finished (void *cls, response_code = 0; } break; - case MHD_HTTP_UNAUTHORIZED: + case MHD_HTTP_FORBIDDEN: GNUNET_break (0); /* Nothing really to verify, exchange says one of the signatures is invalid; as we checked them, this should never happen, we diff --git a/src/lib/exchange_api_track_transaction.c b/src/lib/exchange_api_track_transaction.c index 29b85facf..de3f98b65 100644 --- a/src/lib/exchange_api_track_transaction.c +++ b/src/lib/exchange_api_track_transaction.c @@ -217,7 +217,7 @@ handle_deposit_wtid_finished (void *cls, /* This should never happen, either us or the exchange is buggy (or API version conflict); just pass JSON reply to the application */ break; - case MHD_HTTP_UNAUTHORIZED: + case MHD_HTTP_FORBIDDEN: /* Nothing really to verify, exchange says one of the signatures is invalid; as we checked them, this should never happen, we should pass the JSON reply to the application */ diff --git a/src/lib/exchange_api_track_transfer.c b/src/lib/exchange_api_track_transfer.c index 419998a2c..2c90bf199 100644 --- a/src/lib/exchange_api_track_transfer.c +++ b/src/lib/exchange_api_track_transfer.c @@ -279,7 +279,7 @@ handle_track_transfer_finished (void *cls, /* This should never happen, either us or the exchange is buggy (or API version conflict); just pass JSON reply to the application */ break; - case MHD_HTTP_UNAUTHORIZED: + case MHD_HTTP_FORBIDDEN: /* Nothing really to verify, exchange says one of the signatures is invalid; as we checked them, this should never happen, we should pass the JSON reply to the application */ -- cgit v1.2.3 From 7510b6310b59967a21e3683a13b8232179f7b26a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 22:26:11 +0100 Subject: more libtalermhd migration --- src/auditor/taler-auditor-httpd.c | 7 +++--- src/auditor/taler-auditor-httpd_db.c | 27 ++++++++++++++-------- .../taler-auditor-httpd_deposit-confirmation.c | 1 - src/auditor/taler-auditor-httpd_exchanges.c | 1 - src/auditor/taler-auditor-httpd_mhd.c | 14 +++++------ 5 files changed, 27 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/auditor/taler-auditor-httpd.c b/src/auditor/taler-auditor-httpd.c index bf1e7ac71..55a343776 100644 --- a/src/auditor/taler-auditor-httpd.c +++ b/src/auditor/taler-auditor-httpd.c @@ -31,7 +31,6 @@ #include "taler_auditordb_lib.h" #include "taler-auditor-httpd_deposit-confirmation.h" #include "taler-auditor-httpd_exchanges.h" -#include "taler-auditor-httpd_responses.h" #include "taler-auditor-httpd_mhd.h" #include "taler-auditor-httpd.h" @@ -332,9 +331,9 @@ handle_version (struct TAH_RequestHandler *rh, GNUNET_break (0); return MHD_NO; } - return TAH_RESPONSE_reply_json (connection, - ver, - MHD_HTTP_OK); + return TALER_MHD_reply_json (connection, + ver, + MHD_HTTP_OK); } diff --git a/src/auditor/taler-auditor-httpd_db.c b/src/auditor/taler-auditor-httpd_db.c index e0ab8f2e1..3433e9a9f 100644 --- a/src/auditor/taler-auditor-httpd_db.c +++ b/src/auditor/taler-auditor-httpd_db.c @@ -23,8 +23,9 @@ #include #include #include "taler_json_lib.h" +#include "taler_mhd_lib.h" #include "taler-auditor-httpd_db.h" -#include "taler-auditor-httpd_responses.h" +#include "taler-auditor-httpd.h" /** @@ -63,8 +64,10 @@ TAH_DB_run_transaction (struct MHD_Connection *connection, { GNUNET_break (0); if (NULL != mhd_ret) - *mhd_ret = TAH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_DB_SETUP_FAILED); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_DB_SETUP_FAILED, + "failed to establish session with database"); return GNUNET_SYSERR; } // TAH_plugin->preflight (TAH_plugin->cls, session); // FIXME: needed? @@ -79,8 +82,10 @@ TAH_DB_run_transaction (struct MHD_Connection *connection, { GNUNET_break (0); if (NULL != mhd_ret) - *mhd_ret = TAH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_DB_START_FAILED); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_DB_START_FAILED, + "failed to begin transaction"); return GNUNET_SYSERR; } qs = cb (cb_cls, @@ -98,8 +103,10 @@ TAH_DB_run_transaction (struct MHD_Connection *connection, if (GNUNET_DB_STATUS_HARD_ERROR == qs) { if (NULL != mhd_ret) - *mhd_ret = TAH_RESPONSE_reply_commit_error (connection, - TALER_EC_DB_COMMIT_FAILED_HARD); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_DB_COMMIT_FAILED_HARD, + "failed to commit transaction"); return GNUNET_SYSERR; } /* make sure callback did not violate invariants! */ @@ -112,8 +119,10 @@ TAH_DB_run_transaction (struct MHD_Connection *connection, name, MAX_TRANSACTION_COMMIT_RETRIES); if (NULL != mhd_ret) - *mhd_ret = TAH_RESPONSE_reply_commit_error (connection, - TALER_EC_DB_COMMIT_FAILED_ON_RETRY); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_DB_COMMIT_FAILED_ON_RETRY, + "transaction repeatedly failed to serialize"); return GNUNET_SYSERR; } diff --git a/src/auditor/taler-auditor-httpd_deposit-confirmation.c b/src/auditor/taler-auditor-httpd_deposit-confirmation.c index 23ea14a9f..0a121fdae 100644 --- a/src/auditor/taler-auditor-httpd_deposit-confirmation.c +++ b/src/auditor/taler-auditor-httpd_deposit-confirmation.c @@ -31,7 +31,6 @@ #include "taler-auditor-httpd.h" #include "taler-auditor-httpd_db.h" #include "taler-auditor-httpd_deposit-confirmation.h" -#include "taler-auditor-httpd_responses.h" /** diff --git a/src/auditor/taler-auditor-httpd_exchanges.c b/src/auditor/taler-auditor-httpd_exchanges.c index 27b339636..3c6bfe68f 100644 --- a/src/auditor/taler-auditor-httpd_exchanges.c +++ b/src/auditor/taler-auditor-httpd_exchanges.c @@ -29,7 +29,6 @@ #include "taler-auditor-httpd.h" #include "taler-auditor-httpd_db.h" #include "taler-auditor-httpd_exchanges.h" -#include "taler-auditor-httpd_responses.h" /** diff --git a/src/auditor/taler-auditor-httpd_mhd.c b/src/auditor/taler-auditor-httpd_mhd.c index 6613ddb0d..ca87b8dac 100644 --- a/src/auditor/taler-auditor-httpd_mhd.c +++ b/src/auditor/taler-auditor-httpd_mhd.c @@ -29,8 +29,6 @@ #include #include #include "taler_mhd_lib.h" -#include "taler-auditor-httpd_responses.h" -#include "taler-auditor-httpd_responses.h" #include "taler-auditor-httpd.h" #include "taler-auditor-httpd_mhd.h" @@ -65,7 +63,7 @@ TAH_MHD_handler_static_response (struct TAH_RequestHandler *rh, GNUNET_break (0); return MHD_NO; } - TAH_RESPONSE_add_global_headers (response); + TALER_MHD_add_global_headers (response); if (NULL != rh->mime_type) (void) MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, @@ -123,11 +121,11 @@ TAH_MHD_handler_send_json_pack_error (struct TAH_RequestHandler *rh, const char *upload_data, size_t *upload_data_size) { - return TAH_RESPONSE_reply_json_pack (connection, - rh->response_code, - "{s:s}", - "error", - rh->data); + return TALER_MHD_reply_json_pack (connection, + rh->response_code, + "{s:s}", + "error", + rh->data); } -- cgit v1.2.3 From 633ae7edd1a80f1abb2fdc751d487cbed2fd6a29 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 22:27:27 +0100 Subject: cleanup --- src/auditor/taler-auditor-httpd_mhd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/auditor/taler-auditor-httpd_mhd.c b/src/auditor/taler-auditor-httpd_mhd.c index ca87b8dac..01927469e 100644 --- a/src/auditor/taler-auditor-httpd_mhd.c +++ b/src/auditor/taler-auditor-httpd_mhd.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014 GNUnet e.V. + Copyright (C) 2014-2019 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 @@ -53,6 +53,9 @@ TAH_MHD_handler_static_response (struct TAH_RequestHandler *rh, struct MHD_Response *response; int ret; + (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, -- cgit v1.2.3 From 0ea09d3d6e0f6b11de0c95bea885db0eecdef1f4 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 22:30:32 +0100 Subject: fix test expectations --- src/lib/test_exchange_api.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/lib/test_exchange_api.c b/src/lib/test_exchange_api.c index 23a52be1f..4e8eb7e09 100644 --- a/src/lib/test_exchange_api.c +++ b/src/lib/test_exchange_api.c @@ -228,7 +228,7 @@ run (void *cls, TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-2", "create-reserve-1", "EUR:5", - MHD_HTTP_FORBIDDEN), + MHD_HTTP_CONFLICT), /** * Try to double spend using different wire details. @@ -238,7 +238,7 @@ run (void *cls, TALER_TESTING_make_wire_details (43, fakebank_url), "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", - GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_FORBIDDEN), + GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_CONFLICT), /** * Try to double spend using a different transaction id. @@ -253,7 +253,7 @@ run (void *cls, TALER_TESTING_make_wire_details (43, fakebank_url), "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", - GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_FORBIDDEN), + GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_CONFLICT), /** * Try to double spend with different proposal. @@ -263,7 +263,7 @@ run (void *cls, TALER_TESTING_make_wire_details (43, fakebank_url), "{\"items\":[{\"name\":\"ice cream\",\"value\":2}]}", - GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_FORBIDDEN), + GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_CONFLICT), TALER_TESTING_cmd_end () }; @@ -364,7 +364,7 @@ run (void *cls, TALER_TESTING_cmd_refresh_melt ("refresh-melt-failing", "refresh-withdraw-coin-1", - MHD_HTTP_FORBIDDEN, + MHD_HTTP_CONFLICT, NULL), /* FIXME: also test with coin that was already melted @@ -708,7 +708,7 @@ run (void *cls, ("payback-withdraw-coin-2-over", "payback-create-reserve-1", "EUR:10", - MHD_HTTP_FORBIDDEN), + MHD_HTTP_CONFLICT), TALER_TESTING_cmd_status ("payback-reserve-status-2", "payback-create-reserve-1", @@ -740,7 +740,7 @@ run (void *cls, ("expired-withdraw", "short-lived-reserve", "EUR:1", - MHD_HTTP_FORBIDDEN), + MHD_HTTP_CONFLICT), TALER_TESTING_cmd_check_bank_transfer ("check_bank_short-lived_transfer", @@ -798,7 +798,7 @@ run (void *cls, "EUR:0.5", NULL), - TALER_TESTING_cmd_payback ("payback-2b", MHD_HTTP_FORBIDDEN, + TALER_TESTING_cmd_payback ("payback-2b", MHD_HTTP_CONFLICT, "payback-withdraw-coin-2a", "EUR:0.5", NULL), -- cgit v1.2.3 From f5a783c1698bbbd46e4744de5cfd95e655aa329b Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 22:39:13 +0100 Subject: profit --- src/exchange/taler-exchange-httpd_responses.c | 468 -------------------------- 1 file changed, 468 deletions(-) (limited to 'src') diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c index 97b1e8f1e..4ef0f2d15 100644 --- a/src/exchange/taler-exchange-httpd_responses.c +++ b/src/exchange/taler-exchange-httpd_responses.c @@ -39,453 +39,6 @@ #define SANITY_CHECKS_ON 1 -/** - * Add headers we want to return in every response. - * Useful for testing, like if we want to always close - * connections. - * - * @param response response to modify - */ -void -TEH_RESPONSE_add_global_headers (struct MHD_Response *response) -{ - if (TEH_exchange_connection_close) - GNUNET_break (MHD_YES == - MHD_add_response_header (response, - MHD_HTTP_HEADER_CONNECTION, - "close")); -} - - -/** - * Is HTTP body deflate compression supported by the client? - * - * @param connection connection to check - * @return #MHD_YES if 'deflate' compression is allowed - * - * Note that right now we're ignoring q-values, which is technically - * not correct, and also do not support "*" anywhere but in a line by - * itself. This should eventually be fixed, see also - * https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html - */ -int -TEH_RESPONSE_can_compress (struct MHD_Connection *connection) -{ - const char *ae; - const char *de; - - ae = MHD_lookup_connection_value (connection, - MHD_HEADER_KIND, - MHD_HTTP_HEADER_ACCEPT_ENCODING); - if (NULL == ae) - return MHD_NO; - if (0 == strcmp (ae, - "*")) - return MHD_YES; - de = strstr (ae, - "deflate"); - if (NULL == de) - return MHD_NO; - if ( ( (de == ae) || - (de[-1] == ',') || - (de[-1] == ' ') ) && - ( (de[strlen ("deflate")] == '\0') || - (de[strlen ("deflate")] == ',') || - (de[strlen ("deflate")] == ';') ) ) - return MHD_YES; - return MHD_NO; -} - - -/** - * Try to compress a response body. Updates @a buf and @a buf_size. - * - * @param[in,out] buf pointer to body to compress - * @param[in,out] buf_size pointer to initial size of @a buf - * @return #MHD_YES if @a buf was compressed - */ -int -TEH_RESPONSE_body_compress (void **buf, - size_t *buf_size) -{ - Bytef *cbuf; - uLongf cbuf_size; - int ret; - - cbuf_size = compressBound (*buf_size); - cbuf = malloc (cbuf_size); - if (NULL == cbuf) - return MHD_NO; - ret = compress (cbuf, - &cbuf_size, - (const Bytef *) *buf, - *buf_size); - if ( (Z_OK != ret) || - (cbuf_size >= *buf_size) ) - { - /* compression failed */ - free (cbuf); - return MHD_NO; - } - free (*buf); - *buf = (void *) cbuf; - *buf_size = (size_t) cbuf_size; - return MHD_YES; -} - - -/** - * Send JSON object as response. - * - * @param connection the MHD connection - * @param json the json object - * @param response_code the http response code - * @return MHD result code - */ -int -TEH_RESPONSE_reply_json (struct MHD_Connection *connection, - const json_t *json, - unsigned int response_code) -{ - struct MHD_Response *resp; - void *json_str; - size_t json_len; - int ret; - int comp; - - json_str = json_dumps (json, - JSON_INDENT (2)); - if (NULL == json_str) - { - /** - * This log helps to figure out which - * function called this one and assert-failed. - */ - TALER_LOG_ERROR ("Aborting json-packing for HTTP code: %u\n", - response_code); - - GNUNET_assert (0); - return MHD_NO; - } - json_len = strlen (json_str); - /* try to compress the body */ - comp = MHD_NO; - if (MHD_YES == - TEH_RESPONSE_can_compress (connection)) - comp = TEH_RESPONSE_body_compress (&json_str, - &json_len); - resp = MHD_create_response_from_buffer (json_len, - json_str, - MHD_RESPMEM_MUST_FREE); - if (NULL == resp) - { - free (json_str); - GNUNET_break (0); - return MHD_NO; - } - TEH_RESPONSE_add_global_headers (resp); - GNUNET_break (MHD_YES == - MHD_add_response_header (resp, - MHD_HTTP_HEADER_CONTENT_TYPE, - "application/json")); - if (MHD_YES == comp) - { - /* Need to indicate to client that body is compressed */ - if (MHD_NO == - MHD_add_response_header (resp, - MHD_HTTP_HEADER_CONTENT_ENCODING, - "deflate")) - { - GNUNET_break (0); - MHD_destroy_response (resp); - return MHD_NO; - } - } - ret = MHD_queue_response (connection, - response_code, - resp); - MHD_destroy_response (resp); - return ret; -} - - -/** - * Function to call to handle the request by building a JSON - * reply from a format string and varargs. - * - * @param connection the MHD connection to handle - * @param response_code HTTP response code to use - * @param fmt format string for pack - * @param ... varargs - * @return MHD result code - */ -int -TEH_RESPONSE_reply_json_pack (struct MHD_Connection *connection, - unsigned int response_code, - const char *fmt, - ...) -{ - json_t *json; - va_list argp; - int ret; - json_error_t jerror; - - va_start (argp, fmt); - json = json_vpack_ex (&jerror, 0, fmt, argp); - va_end (argp); - if (NULL == json) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to pack JSON with format `%s': %s\n", - fmt, - jerror.text); - GNUNET_break (0); - return MHD_NO; - } - ret = TEH_RESPONSE_reply_json (connection, - json, - response_code); - json_decref (json); - return ret; -} - - -/** - * Send a response indicating an invalid argument. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param param_name the parameter that is invalid - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_arg_invalid (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *param_name) -{ - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:I, s:s}", - "error", "invalid parameter", - "code", (json_int_t) ec, - "parameter", param_name); -} - - -/** - * Send a response indicating an argument refering to a - * resource unknown to the exchange (i.e. unknown reserve or - * denomination key). - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param param_name the parameter that is invalid - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_arg_unknown (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *param_name) -{ - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_NOT_FOUND, - "{s:s, s:I, s:s}", - "error", "unknown entity referenced", - "code", (json_int_t) ec, - "parameter", param_name); -} - - -/** - * Send a response indicating an invalid signature. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param param_name the parameter that is invalid - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_signature_invalid (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *param_name) -{ - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_UNAUTHORIZED, - "{s:s, s:I, s:s}", - "error", "invalid signature", - "code", (json_int_t) ec, - "parameter", param_name); -} - - -/** - * Send a response indicating a missing argument. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param param_name the parameter that is missing - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_arg_missing (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *param_name) -{ - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:I, s:s}", - "error", "missing parameter", - "code", (json_int_t) ec, - "parameter", param_name); -} - - -/** - * Send a response indicating an internal error. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param hint hint about the internal error's nature - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_internal_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *hint) -{ - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - "{s:s, s:I, s:s}", - "error", "internal error", - "code", (json_int_t) ec, - "hint", hint); -} - - -/** - * Send a response indicating an error. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param http_status HTTP status code to use - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_with_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - unsigned int http_status) -{ - return TEH_RESPONSE_reply_json_pack (connection, - http_status, - "{s:I}", - "code", (json_int_t) ec); -} - - -/** - * Send a response indicating an external error. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @param hint hint about the error's nature - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_external_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const char *hint) -{ - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:I, s:s}", - "error", "client error", - "code", (json_int_t) ec, - "hint", hint); -} - - -/** - * Send a response indicating an error committing a - * transaction (concurrent interference). - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_commit_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec) -{ - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - "{s:s, s:I}", - "error", "commit failure", - "code", (json_int_t) ec); -} - - -/** - * Send a response indicating a failure to talk to the Exchange's - * database. - * - * @param connection the MHD connection to use - * @param ec error code uniquely identifying the error - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_internal_db_error (struct MHD_Connection *connection, - enum TALER_ErrorCode ec) -{ - return TEH_RESPONSE_reply_internal_error (connection, - ec, - "Failure in database interaction"); -} - - -/** - * Send a response indicating that the request was too big. - * - * @param connection the MHD connection to use - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_request_too_large (struct MHD_Connection *connection) -{ - struct MHD_Response *resp; - int ret; - - resp = MHD_create_response_from_buffer (0, - NULL, - MHD_RESPMEM_PERSISTENT); - if (NULL == resp) - return MHD_NO; - TEH_RESPONSE_add_global_headers (resp); - ret = MHD_queue_response (connection, - MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, - resp); - MHD_destroy_response (resp); - return ret; -} - - -/** - * Send a response indicating that the JSON was malformed. - * - * @param connection the MHD connection to use - * @return a MHD result code - */ -int -TEH_RESPONSE_reply_invalid_json (struct MHD_Connection *connection) -{ - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s, s:I}", - "error", "invalid json", - "code", - (json_int_t) TALER_EC_JSON_INVALID); -} - - /** * Compile the transaction history of a coin into a JSON object. * @@ -1172,25 +725,4 @@ TEH_RESPONSE_compile_reserve_history (const struct } -/** - * A merchant asked for details about a deposit, but - * we do not know anything about the deposit. Generate the - * 404 reply. - * - * @param connection connection to the client - * @param ec Taler error code - * @return MHD result code - */ -int -TEH_RESPONSE_reply_transaction_unknown (struct MHD_Connection *connection, - enum TALER_ErrorCode ec) -{ - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_NOT_FOUND, - "{s:s, s:I}", - "error", "Deposit unknown", - "code", (json_int_t) ec); -} - - /* end of taler-exchange-httpd_responses.c */ -- cgit v1.2.3 From 481223e2eb9d1311b245fc35ad487cffbbb4de8f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 23 Nov 2019 22:41:03 +0100 Subject: fix expectation --- src/lib/test_exchange_api_twisted.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lib/test_exchange_api_twisted.c b/src/lib/test_exchange_api_twisted.c index 968b7e626..f648b871d 100644 --- a/src/lib/test_exchange_api_twisted.c +++ b/src/lib/test_exchange_api_twisted.c @@ -284,7 +284,7 @@ run (void *cls, "\"value\":\"EUR:5\"}]}", GNUNET_TIME_UNIT_MINUTES, "EUR:5", - MHD_HTTP_FORBIDDEN), + MHD_HTTP_CONFLICT), TALER_TESTING_cmd_refund ("refund-deposit-not-found", @@ -349,7 +349,7 @@ main (int argc, /* These environment variables get in the way... */ unsetenv ("XDG_DATA_HOME"); unsetenv ("XDG_CONFIG_HOME"); - GNUNET_log_setup ("test-exchange-api-new-twisted", + GNUNET_log_setup ("test-exchange-api-twisted", "DEBUG", NULL); if (NULL == (fakebank_url = TALER_TESTING_prepare_fakebank -- cgit v1.2.3 From 287a8dec9b3d6d2ee77a55fec4afff45f2cb826d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 24 Nov 2019 17:15:01 +0100 Subject: add another convenience function to libtalermhd --- src/include/taler_error_codes.h | 1 + src/include/taler_mhd_lib.h | 52 +++++++++++++++++++ src/mhd/mhd_config.c | 109 ++++++++++++++++++++++++++++++++++++++++ src/mhd/mhd_responses.c | 91 +++++++++++++++++++++++++++++++++ 4 files changed, 253 insertions(+) (limited to 'src') diff --git a/src/include/taler_error_codes.h b/src/include/taler_error_codes.h index 871ec2bfe..55cdbacbd 100644 --- a/src/include/taler_error_codes.h +++ b/src/include/taler_error_codes.h @@ -1442,6 +1442,7 @@ enum TALER_ErrorCode * The amount to be refunded is inconsistent: either is lower than * the previous amount being awarded, or it is too big to be paid back. * In this second case, the fault stays on the business dept. side. + * Returned with an HTTP status of #MHD_HTTP_CONFLICT. */ TALER_EC_REFUND_INCONSISTENT_AMOUNT = 2602, diff --git a/src/include/taler_mhd_lib.h b/src/include/taler_mhd_lib.h index 17783f1c4..cdbc8d290 100644 --- a/src/include/taler_mhd_lib.h +++ b/src/include/taler_mhd_lib.h @@ -143,6 +143,40 @@ TALER_MHD_reply_with_error (struct MHD_Connection *connection, const char *hint); +/** + * Make JSON response object. + * + * @param json the json object + * @return MHD response object + */ +struct MHD_Response * +TALER_MHD_make_json (const json_t *json); + + +/** + * Make JSON response object. + * + * @param fmt format string for pack + * @param ... varargs + * @return MHD response object + */ +struct MHD_Response * +TALER_MHD_make_json_pack (const char *fmt, + ...); + + +/** + * Create a response indicating an internal error. + * + * @param ec error code to return + * @param hint hint about the internal error's nature + * @return a MHD response object + */ +struct MHD_Response * +TALER_MHD_make_error (enum TALER_ErrorCode ec, + const char *hint); + + /** * Send a response indicating that the request was too big. * @@ -338,4 +372,22 @@ TALER_MHD_open_unix_path (const char *unix_path, mode_t unix_mode); +/** + * Bind a listen socket to the UNIX domain path + * or the TCP port and IP address as specified + * in @a cfg in section @a section. IF only a + * port was specified, set @a port and return -1. + * Otherwise, return the bound file descriptor. + * + * @param cfg configuration to parse + * @param section configuration section to use + * @param port[out] port to set, if TCP without BINDTO + * @return -1 and a port of zero on error, otherwise + * either -1 and a port, or a bound stream socket + */ +int +TALER_MHD_bind (const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section, + uint16_t *port); + #endif diff --git a/src/mhd/mhd_config.c b/src/mhd/mhd_config.c index afaceae40..d4b0e9795 100644 --- a/src/mhd/mhd_config.c +++ b/src/mhd/mhd_config.c @@ -285,3 +285,112 @@ TALER_MHD_open_unix_path (const char *unix_path, GNUNET_NETWORK_socket_free_memory_only_ (nh); return fd; } + + +/** + * Bind a listen socket to the UNIX domain path + * or the TCP port and IP address as specified + * in @a cfg in section @a section. IF only a + * port was specified, set @a port and return -1. + * Otherwise, return the bound file descriptor. + * + * @param cfg configuration to parse + * @param section configuration section to use + * @param port[out] port to set, if TCP without BINDTO + * @return -1 and a port of zero on error, otherwise + * either -1 and a port, or a bound stream socket + */ +int +TALER_MHD_bind (const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section, + uint16_t *port) +{ + char *bind_to; + char *serve_unixpath; + mode_t unixpath_mode; + int fh; + char port_str[6]; + struct addrinfo hints; + struct addrinfo *res; + int ec; + struct GNUNET_NETWORK_Handle *nh; + + *port = 0; + if (GNUNET_OK != + TALER_MHD_parse_config (cfg, + section, + port, + &serve_unixpath, + &unixpath_mode)) + return -1; + if (NULL != serve_unixpath) + return TALER_MHD_open_unix_path (serve_unixpath, + unixpath_mode); + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + section, + "BIND_TO", + &bind_to)) + return -1; /* only set port */ + /* let's have fun binding... */ + GNUNET_snprintf (port_str, + sizeof (port_str), + "%u", + (unsigned int) *port); + *port = 0; /* do NOT return port in case of errors */ + memset (&hints, 0, sizeof (hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_flags = AI_PASSIVE +#ifdef AI_IDN + | AI_IDN +#endif + ; + if (0 != + (ec = getaddrinfo (bind_to, + port_str, + &hints, + &res))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to resolve BIND_TO address `%s': %s\n", + bind_to, gai_strerror (ec)); + GNUNET_free (bind_to); + return -1; + } + GNUNET_free (bind_to); + + if (NULL == (nh = GNUNET_NETWORK_socket_create (res->ai_family, + res->ai_socktype, + res->ai_protocol))) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "socket"); + freeaddrinfo (res); + return -1; + } + if (GNUNET_OK != + GNUNET_NETWORK_socket_bind (nh, + res->ai_addr, + res->ai_addrlen)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "bind"); + freeaddrinfo (res); + return -1; + } + freeaddrinfo (res); + if (GNUNET_OK != + GNUNET_NETWORK_socket_listen (nh, + UNIX_BACKLOG)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "listen"); + GNUNET_SCHEDULER_shutdown (); + return -1; + } + fh = GNUNET_NETWORK_get_fd (nh); + GNUNET_NETWORK_socket_free_memory_only_ (nh); + return fh; +} diff --git a/src/mhd/mhd_responses.c b/src/mhd/mhd_responses.c index e1609d996..3642e7d54 100644 --- a/src/mhd/mhd_responses.c +++ b/src/mhd/mhd_responses.c @@ -151,6 +151,43 @@ TALER_MHD_body_compress (void **buf, } +/** + * Make JSON response object. + * + * @param json the json object + * @return MHD response object + */ +struct MHD_Response * +TALER_MHD_make_json (const json_t *json) +{ + struct MHD_Response *resp; + char *json_str; + + json_str = json_dumps (json, + JSON_INDENT (2)); + if (NULL == json_str) + { + GNUNET_break (0); + return NULL; + } + resp = MHD_create_response_from_buffer (strlen (json_str), + json_str, + MHD_RESPMEM_MUST_FREE); + if (NULL == resp) + { + free (json_str); + GNUNET_break (0); + return NULL; + } + TALER_MHD_add_global_headers (resp); + GNUNET_break (MHD_YES == + MHD_add_response_header (resp, + MHD_HTTP_HEADER_CONTENT_TYPE, + "application/json")); + return resp; +} + + /** * Send JSON object as response. * @@ -267,6 +304,60 @@ TALER_MHD_reply_json_pack (struct MHD_Connection *connection, } +/** + * Make JSON response object. + * + * @param fmt format string for pack + * @param ... varargs + * @return MHD response object + */ +struct MHD_Response * +TALER_MHD_make_json_pack (const char *fmt, + ...) +{ + json_t *json; + va_list argp; + struct MHD_Response *ret; + json_error_t jerror; + + va_start (argp, fmt); + json = json_vpack_ex (&jerror, + 0, + fmt, + argp); + va_end (argp); + if (NULL == json) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to pack JSON with format `%s': %s\n", + fmt, + jerror.text); + GNUNET_break (0); + return MHD_NO; + } + ret = TALER_MHD_make_json (json); + json_decref (json); + return ret; +} + + +/** + * Create a response indicating an internal error. + * + * @param ec error code to return + * @param hint hint about the internal error's nature + * @return a MHD response object + */ +struct MHD_Response * +TALER_MHD_make_error (enum TALER_ErrorCode ec, + const char *hint) +{ + return TALER_MHD_make_json_pack ("{s:I, s:s}", + "code", (json_int_t) ec, + "hint", hint); +} + + /** * Send a response indicating an error. * -- cgit v1.2.3 From b7a5af7fd4ea302df013ad492d8a420efca5864c Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 24 Nov 2019 17:20:13 +0100 Subject: another sync code --- src/include/taler_error_codes.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/include/taler_error_codes.h b/src/include/taler_error_codes.h index 55cdbacbd..05bd9ce91 100644 --- a/src/include/taler_error_codes.h +++ b/src/include/taler_error_codes.h @@ -1852,7 +1852,7 @@ enum TALER_ErrorCode /** * The sync service failed to access its database. * This response is provided with HTTP status code - * MHD_HTTP_INTERNAL_ERROR. + * MHD_HTTP_INTERNAL_SERVER_ERROR. */ TALER_EC_SYNC_DB_FETCH_ERROR = 6000, @@ -1967,17 +1967,23 @@ enum TALER_ErrorCode /** * Sync could not store order data in its own database. * This response is provided with HTTP status code - * MHD_HTTP_INTERNAL_ERROR. + * MHD_HTTP_INTERNAL_SERVER_ERROR. */ TALER_EC_SYNC_PAYMENT_CREATE_DB_ERROR = 6015, /** * Sync could not store payment confirmation in its own database. * This response is provided with HTTP status code - * MHD_HTTP_INTERNAL_ERROR. + * MHD_HTTP_INTERNAL_SERVER_ERROR. */ TALER_EC_SYNC_PAYMENT_CONFIRM_DB_ERROR = 6016, + /** + * Sync could check for payment confirmation in its own database. + * This response is provided with HTTP status code + * MHD_HTTP_INTERNAL_SERVER_ERROR. + */ + TALER_EC_SYNC_PAYMENT_CHECK_ORDER_DB_ERROR = 6017, /** * End of error code range. -- cgit v1.2.3 From 70a210ac4db07a28867e23db13c68aecc117810a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 25 Nov 2019 01:42:55 +0100 Subject: add another helper --- src/include/taler_json_lib.h | 13 +++++++++++++ src/json/json.c | 29 +++++++++++++++++++++++++++++ src/lib/exchange_api_curl_defaults.c | 1 - 3 files changed, 42 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h index 382bb19ee..6adb76b24 100644 --- a/src/include/taler_json_lib.h +++ b/src/include/taler_json_lib.h @@ -126,6 +126,19 @@ enum TALER_ErrorCode TALER_JSON_get_error_code (const json_t *json); +/** + * Extract the Taler error code from the given @a data object, which is expected to be in JSON. + * Note that #TALER_EC_INVALID is returned if no "code" is present or if @a data is not in JSON. + * + * @param data response to extract the error code from + * @param data_size number of bytes in @a data + * @return the "code" value from @a json + */ +enum TALER_ErrorCode +TALER_JSON_get_error_code2 (const void *data, + size_t data_size); + + /* **************** /wire account offline signing **************** */ /** diff --git a/src/json/json.c b/src/json/json.c index 90fe3dd4f..8d4089795 100644 --- a/src/json/json.c +++ b/src/json/json.c @@ -80,4 +80,33 @@ TALER_JSON_get_error_code (const json_t *json) } +/** + * Extract the Taler error code from the given @a data object, which is expected to be in JSON. + * Note that #TALER_EC_INVALID is returned if no "code" is present or if @a data is not in JSON. + * + * @param data response to extract the error code from + * @param data_size number of bytes in @a data + * @return the "code" value from @a json + */ +enum TALER_ErrorCode +TALER_JSON_get_error_code2 (const void *data, + size_t data_size) +{ + json_t *json; + enum TALER_ErrorCode ec; + json_error_t err; + + json = json_loads (data, + data_size, + &err); + if (NULL == json) + return TALER_EC_INVALID; + ec = TALER_JSON_get_error_code (json); + json_decref (json); + if (ec == TALER_EC_NONE) + return TALER_EC_INVALID; + return ec; +} + + /* End of json/json.c */ diff --git a/src/lib/exchange_api_curl_defaults.c b/src/lib/exchange_api_curl_defaults.c index 36d1edf7b..7b642bc89 100644 --- a/src/lib/exchange_api_curl_defaults.c +++ b/src/lib/exchange_api_curl_defaults.c @@ -35,7 +35,6 @@ TEL_curl_easy_get (const char *url) CURL *eh; eh = curl_easy_init (); - GNUNET_assert (CURLE_OK == curl_easy_setopt (eh, CURLOPT_URL, -- cgit v1.2.3 From d3f78be9fc7a85a4bb18712d0c2e39a2e9445b63 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 25 Nov 2019 13:36:30 +0100 Subject: exchange-tools: add test vector generation tool --- .gitignore | 1 + src/exchange-tools/Makefile.am | 8 + src/exchange-tools/taler-exchange-tvg.c | 254 ++++++++++++++++++++++++++++++++ 3 files changed, 263 insertions(+) create mode 100644 src/exchange-tools/taler-exchange-tvg.c (limited to 'src') diff --git a/.gitignore b/.gitignore index 5bb943a9d..5bb95cb46 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,7 @@ src/exchange/test_taler_exchange_httpd_home/.local/share/taler/exchange/live-key src/exchange/test_taler_exchange_httpd_home/.local/share/taler/exchange/wirefees/ src/exchange-tools/taler-auditor-sign src/exchange-tools/taler-exchange-dbinit +src/exchange-tools/taler-exchange-tvg src/exchange-tools/taler-exchange-keycheck src/exchange-tools/taler-exchange-keyup src/exchange-tools/taler-exchange-wire diff --git a/src/exchange-tools/Makefile.am b/src/exchange-tools/Makefile.am index 409c6bfdd..64b4cee87 100644 --- a/src/exchange-tools/Makefile.am +++ b/src/exchange-tools/Makefile.am @@ -16,6 +16,7 @@ bin_PROGRAMS = \ taler-exchange-keycheck \ taler-exchange-wire \ taler-exchange-dbinit \ + taler-exchange-tvg \ taler-wire taler_wire_SOURCES = \ @@ -59,6 +60,13 @@ taler_exchange_keycheck_LDADD = \ -lgnunetutil $(XLIB) taler_exchange_keycheck_LDFLAGS = $(POSTGRESQL_LDFLAGS) +taler_exchange_tvg_SOURCES = \ + taler-exchange-tvg.c +taler_exchange_tvg_LDADD = \ + $(LIBGCRYPT_LIBS) \ + $(top_builddir)/src/util/libtalerutil.la \ + -lgnunetutil $(XLIB) + taler_exchange_dbinit_SOURCES = \ taler-exchange-dbinit.c taler_exchange_dbinit_LDADD = \ diff --git a/src/exchange-tools/taler-exchange-tvg.c b/src/exchange-tools/taler-exchange-tvg.c new file mode 100644 index 000000000..7fc06b0c2 --- /dev/null +++ b/src/exchange-tools/taler-exchange-tvg.c @@ -0,0 +1,254 @@ +/* + This file is part of TALER + Copyright (C) 2019 GNUnet e.V. + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + 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 exchange-tools/taler-exchange-tvg.c + * @brief Generate test vectors for cryptographic operations. + * @author Florian Dold + */ +#include "platform.h" +#include "taler_util.h" +#include "taler_signatures.h" +#include + + +/** + * Print data base32-crockford with a preceding label. + * + * @param label label to print + * @param data data to print + * @param size size of data + */ +static void +display_data (char *label, void *data, size_t size) +{ + char *enc = GNUNET_STRINGS_data_to_string_alloc (data, size); + printf ("%s %s\n", label, enc); + GNUNET_free (enc); +} + + +/** + * Main function that will be run. + * + * @param cls closure + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param cfg configuration + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + { + struct GNUNET_HashCode hc; + char *str = "Hello, GNU Taler"; + + GNUNET_CRYPTO_hash (str, strlen (str), &hc); + + printf ("hash code:\n"); + display_data (" input", str, strlen (str)); + display_data (" output", &hc, sizeof (struct GNUNET_HashCode)); + } + { + struct GNUNET_CRYPTO_EcdhePrivateKey *priv1; + struct GNUNET_CRYPTO_EcdhePublicKey pub1; + struct GNUNET_CRYPTO_EcdhePrivateKey *priv2; + struct GNUNET_HashCode skm; + priv1 = GNUNET_CRYPTO_ecdhe_key_create (); + priv2 = GNUNET_CRYPTO_ecdhe_key_create (); + GNUNET_CRYPTO_ecdhe_key_get_public (priv1, &pub1); + GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecc_ecdh (priv2, &pub1, &skm)); + + printf ("ecdhe key:\n"); + display_data (" priv1", priv1, sizeof (struct + GNUNET_CRYPTO_EcdhePrivateKey)); + display_data (" pub1", &pub1, sizeof (struct + GNUNET_CRYPTO_EcdhePublicKey)); + display_data (" priv2", &priv2, sizeof (struct + GNUNET_CRYPTO_EcdhePublicKey)); + display_data (" skm", &skm, sizeof (struct GNUNET_HashCode)); + GNUNET_free (priv1); + GNUNET_free (priv2); + } + + { + struct GNUNET_CRYPTO_EddsaPrivateKey *priv; + struct GNUNET_CRYPTO_EddsaPublicKey pub; + priv = GNUNET_CRYPTO_eddsa_key_create (); + GNUNET_CRYPTO_eddsa_key_get_public (priv, &pub); + + printf ("eddsa key:\n"); + display_data (" priv", priv, sizeof (struct + GNUNET_CRYPTO_EddsaPrivateKey)); + display_data (" pub", &pub, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); + GNUNET_free (priv); + } + { + struct GNUNET_CRYPTO_EddsaPrivateKey *priv; + struct GNUNET_CRYPTO_EddsaPublicKey pub; + struct GNUNET_CRYPTO_EddsaSignature sig; + struct TALER_ProposalDataPS data = { 0 }; + priv = GNUNET_CRYPTO_eddsa_key_create (); + GNUNET_CRYPTO_eddsa_key_get_public (priv, &pub); + data.purpose.size = htonl (sizeof (struct TALER_ProposalDataPS)); + GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (priv, &data.purpose, + &sig)); + + printf ("eddsa sig:\n"); + display_data (" priv", priv, sizeof (struct + GNUNET_CRYPTO_EddsaPrivateKey)); + display_data (" pub", &pub, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); + display_data (" data", &data, sizeof (struct TALER_ProposalDataPS)); + display_data (" sig", &sig, sizeof (struct GNUNET_CRYPTO_EddsaSignature)); + GNUNET_free (priv); + } + + { + size_t out_len = 64; + char out[out_len]; + char *ikm = "I'm the secret input key material"; + char *salt = "I'm very salty"; + char *ctx = "I'm a context chunk, also known as 'info' in the RFC"; + + GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_kdf (&out, + out_len, + salt, + strlen (salt), + ikm, + strlen (ikm), + ctx, + strlen (ctx), + NULL)); + + printf ("kdf:\n"); + display_data (" salt", salt, strlen (salt)); + display_data (" ikm", ikm, strlen (ikm)); + display_data (" ctx", ctx, strlen (ctx)); + display_data (" out", out, out_len); + } + { + struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ecdhe; + struct GNUNET_CRYPTO_EcdhePublicKey pub_ecdhe; + struct GNUNET_CRYPTO_EddsaPrivateKey *priv_eddsa; + struct GNUNET_CRYPTO_EddsaPublicKey pub_eddsa; + struct GNUNET_HashCode key_material; + priv_ecdhe = GNUNET_CRYPTO_ecdhe_key_create (); + GNUNET_CRYPTO_ecdhe_key_get_public (priv_ecdhe, &pub_ecdhe); + priv_eddsa = GNUNET_CRYPTO_eddsa_key_create (); + GNUNET_CRYPTO_eddsa_key_get_public (priv_eddsa, &pub_eddsa); + GNUNET_CRYPTO_ecdh_eddsa (priv_ecdhe, &pub_eddsa, &key_material); + + printf ("eddsa_ecdh:\n"); + display_data (" priv_ecdhe", priv_ecdhe, sizeof (struct + GNUNET_CRYPTO_EcdhePrivateKey)); + display_data (" pub_ecdhe", &pub_ecdhe, sizeof (struct + GNUNET_CRYPTO_EcdhePublicKey)); + display_data (" priv_ecdhe", priv_ecdhe, sizeof (struct + GNUNET_CRYPTO_EddsaPrivateKey)); + display_data (" pub_ecdhe", &pub_ecdhe, sizeof (struct + GNUNET_CRYPTO_EcdhePublicKey)); + display_data (" key_material", &key_material, sizeof (struct + GNUNET_HashCode)); + } + + { + struct GNUNET_CRYPTO_RsaPrivateKey *skey; + struct GNUNET_CRYPTO_RsaPublicKey *pkey; + struct GNUNET_HashCode message_hash; + struct GNUNET_CRYPTO_RsaBlindingKeySecret bks; + struct GNUNET_CRYPTO_RsaSignature *blinded_sig; + struct GNUNET_CRYPTO_RsaSignature *sig; + char *blinded_data; + size_t blinded_len; + char *public_enc_data; + size_t public_enc_len; + char *blinded_sig_enc_data; + size_t blinded_sig_enc_length; + char *sig_enc_data; + size_t sig_enc_length; + skey = GNUNET_CRYPTO_rsa_private_key_create (2048); + pkey = GNUNET_CRYPTO_rsa_private_key_get_public (skey); + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, &message_hash, + sizeof (struct GNUNET_HashCode)); + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, &bks, sizeof (struct + GNUNET_CRYPTO_RsaBlindingKeySecret)); + GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_rsa_blind (&message_hash, &bks, + pkey, &blinded_data, + &blinded_len)); + blinded_sig = GNUNET_CRYPTO_rsa_sign_blinded (skey, blinded_data, + blinded_len); + sig = GNUNET_CRYPTO_rsa_unblind (blinded_sig, &bks, pkey); + GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_rsa_verify (&message_hash, sig, + pkey)); + public_enc_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, + &public_enc_data); + blinded_sig_enc_length = GNUNET_CRYPTO_rsa_signature_encode (blinded_sig, + & + blinded_sig_enc_data); + sig_enc_length = GNUNET_CRYPTO_rsa_signature_encode (sig, &sig_enc_data); + printf ("blind signing:\n"); + display_data (" message_hash", &message_hash, sizeof (struct + GNUNET_HashCode)); + display_data (" rsa_public_key", public_enc_data, public_enc_len); + display_data (" blinding_key_secret", &bks, sizeof (struct + GNUNET_CRYPTO_RsaBlindingKeySecret)); + display_data (" blinded_message", blinded_data, blinded_len); + display_data (" blinded_sig", blinded_sig_enc_data, + blinded_sig_enc_length); + display_data (" sig", sig_enc_data, sig_enc_length); + GNUNET_CRYPTO_rsa_private_key_free (skey); + GNUNET_CRYPTO_rsa_public_key_free (pkey); + GNUNET_CRYPTO_rsa_signature_free (sig); + GNUNET_CRYPTO_rsa_signature_free (blinded_sig); + } +} + + +/** + * The main function of the test vector generation tool. + * + * @param argc number of arguments from the command line + * @param argv command line arguments + * @return 0 ok, 1 on error + */ +int +main (int argc, + char *const *argv) +{ + const struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + /* force linker to link against libtalerutil; if we do + not do this, the linker may "optimize" libtalerutil + away and skip #TALER_OS_init(), which we do need */ + (void) TALER_project_data_default (); + GNUNET_assert (GNUNET_OK == + GNUNET_log_setup ("taler-exchange-dbinit", + "INFO", + NULL)); + if (GNUNET_OK != + GNUNET_PROGRAM_run (argc, argv, + "taler-exchange-tvg", + "Generate test vectors", + options, + &run, NULL)) + return 1; + return 0; +} -- cgit v1.2.3 From 3de10da7574e04a5375534583464adda0fc33e2b Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 25 Nov 2019 13:50:04 +0100 Subject: taler-exchange-tvg: fix copy-paste error --- src/exchange-tools/taler-exchange-tvg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/exchange-tools/taler-exchange-tvg.c b/src/exchange-tools/taler-exchange-tvg.c index 7fc06b0c2..366ef7cb2 100644 --- a/src/exchange-tools/taler-exchange-tvg.c +++ b/src/exchange-tools/taler-exchange-tvg.c @@ -80,8 +80,8 @@ run (void *cls, GNUNET_CRYPTO_EcdhePrivateKey)); display_data (" pub1", &pub1, sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)); - display_data (" priv2", &priv2, sizeof (struct - GNUNET_CRYPTO_EcdhePublicKey)); + display_data (" priv2", priv2, sizeof (struct + GNUNET_CRYPTO_EcdhePrivateKey)); display_data (" skm", &skm, sizeof (struct GNUNET_HashCode)); GNUNET_free (priv1); GNUNET_free (priv2); -- cgit v1.2.3 From 499cff87bf62863860264e95fc8482d5767a1418 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 28 Nov 2019 00:24:05 +0100 Subject: remove patch_private_key, as it doesn't make any sense In particular, we were patching the EdDSA private keys, which are *hashed* before doing the curve multiplication. Thus clearing the bits *before* the hashing doesn't make any sense at all. These bits are cleared anyway when deriving the public key. --- src/util/crypto.c | 28 ---------------------------- 1 file changed, 28 deletions(-) (limited to 'src') diff --git a/src/util/crypto.c b/src/util/crypto.c index 077f049eb..cf351d3f2 100644 --- a/src/util/crypto.c +++ b/src/util/crypto.c @@ -190,32 +190,6 @@ TALER_link_recover_transfer_secret (const struct } -/** - * Set the bits in the private EdDSA key so that they match - * the specification. - * - * @param[in,out] pk private key to patch - */ -static void -patch_private_key (struct GNUNET_CRYPTO_EddsaPrivateKey *pk) -{ - uint8_t *p = (uint8_t *) pk; - - /* Taken from like 170-172 of libgcrypt/cipher/ecc.c - * We note that libgcrypt stores the private key in the reverse order - * from many Ed25519 implementatons. */ - p[0] &= 0x7f; /* Clear bit 255. */ - p[0] |= 0x40; /* Set bit 254. */ - p[31] &= 0xf8; /* Clear bits 2..0 so that d mod 8 == 0 */ - - /* FIXME: Run GNUNET_CRYPTO_ecdhe_key_create several times and inspect - * the output to verify that the same bits are set and cleared. - * Is it worth also adding a test case that runs gcry_pk_testkey on - * this key after first parsing it into libgcrypt's s-expression mess - * ala decode_private_eddsa_key from gnunet/src/util/crypto_ecc.c? - * It'd run check_secret_key but not test_keys from libgcrypt/cipher/ecc.c */} - - /** * Setup information for a fresh coin. * @@ -240,7 +214,6 @@ TALER_planchet_setup_refresh (const struct TALER_TransferSecretP *secret_seed, "taler-coin-derivation", strlen ("taler-coin-derivation"), NULL, 0)); - patch_private_key (&ps->coin_priv.eddsa_priv); } @@ -255,7 +228,6 @@ TALER_planchet_setup_random (struct TALER_PlanchetSecretsP *ps) GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, ps, sizeof (*ps)); - patch_private_key (&ps->coin_priv.eddsa_priv); } -- cgit v1.2.3 From 785f5fb7dd5f8e4aa0258e3e72f519c77942cb7d Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 28 Nov 2019 00:26:32 +0100 Subject: more test vectors --- src/exchange-tools/taler-exchange-tvg.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/exchange-tools/taler-exchange-tvg.c b/src/exchange-tools/taler-exchange-tvg.c index 366ef7cb2..55e658fc4 100644 --- a/src/exchange-tools/taler-exchange-tvg.c +++ b/src/exchange-tools/taler-exchange-tvg.c @@ -109,6 +109,10 @@ run (void *cls, data.purpose.size = htonl (sizeof (struct TALER_ProposalDataPS)); GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (priv, &data.purpose, &sig)); + GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_verify (0, + &data.purpose, + &sig, + &pub)); printf ("eddsa sig:\n"); display_data (" priv", priv, sizeof (struct @@ -140,6 +144,7 @@ run (void *cls, display_data (" salt", salt, strlen (salt)); display_data (" ikm", ikm, strlen (ikm)); display_data (" ctx", ctx, strlen (ctx)); + printf (" out_len %u\n", (unsigned int) out_len); display_data (" out", out, out_len); } { @@ -159,10 +164,10 @@ run (void *cls, GNUNET_CRYPTO_EcdhePrivateKey)); display_data (" pub_ecdhe", &pub_ecdhe, sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)); - display_data (" priv_ecdhe", priv_ecdhe, sizeof (struct + display_data (" priv_eddsa", priv_eddsa, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)); - display_data (" pub_ecdhe", &pub_ecdhe, sizeof (struct - GNUNET_CRYPTO_EcdhePublicKey)); + display_data (" pub_eddsa", &pub_eddsa, sizeof (struct + GNUNET_CRYPTO_EddsaPublicKey)); display_data (" key_material", &key_material, sizeof (struct GNUNET_HashCode)); } -- cgit v1.2.3