donau

Donation authority for GNU Taler (experimental)
Log | Files | Refs | Submodules | README | LICENSE

commit 6ee38f352c6ceea910f7314c74eeb451f2a1c9cd
parent d1c6347de77387344197e9dced739f4609972d18
Author: Pius Loosli <loosp2@bfh.ch>
Date:   Wed, 29 Nov 2023 14:21:59 +0100

[build] comment out code in httpd-* files

Diffstat:
Msrc/donau/donau-httpd.c | 2364+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/donau/donau-httpd_keys.h | 638++++++++++++++++++++-----------------------------------------------------------
Msrc/donau/donau-httpd_responses.c | 1684+++++++++++++++++++++++++------------------------------------------------------
Msrc/donau/donau-httpd_terms.c | 70+++++++++++++++++++++++++++++++++++-----------------------------------
4 files changed, 1897 insertions(+), 2859 deletions(-)

diff --git a/src/donau/donau-httpd.c b/src/donau/donau-httpd.c @@ -35,126 +35,126 @@ #include "taler/taler_extensions.h" #include <gnunet/gnunet_mhd_compat.h> -/** - * Backlog for listen operation on unix domain sockets. - */ -#define UNIX_BACKLOG 50 +// /** +// * Backlog for listen operation on unix domain sockets. +// */ +// #define UNIX_BACKLOG 50 -/** - * How often will we try to connect to the database before giving up? - */ -#define MAX_DB_RETRIES 5 +// /** +// * How often will we try to connect to the database before giving up? +// */ +// #define MAX_DB_RETRIES 5 -/** - * Above what request latency do we start to log? - */ -#define WARN_LATENCY GNUNET_TIME_relative_multiply ( \ - GNUNET_TIME_UNIT_MILLISECONDS, 500) +// /** +// * Above what request latency do we start to log? +// */ +// #define WARN_LATENCY GNUNET_TIME_relative_multiply ( \ +// GNUNET_TIME_UNIT_MILLISECONDS, 500) -/** - * Are clients allowed to request /keys for times other than the - * current time? Allowing this could be abused in a DoS-attack - * as building new /keys responses is expensive. Should only be - * enabled for testcases, development and test systems. - */ -int TEH_allow_keys_timetravel; +// /** +// * Are clients allowed to request /keys for times other than the +// * current time? Allowing this could be abused in a DoS-attack +// * as building new /keys responses is expensive. Should only be +// * enabled for testcases, development and test systems. +// */ +// int TEH_allow_keys_timetravel; /** * Should we allow two HTTPDs to bind to the same port? */ static int allow_address_reuse; -/** - * The donau's configuration (global) - */ -const struct GNUNET_CONFIGURATION_Handle *TEH_cfg; +// /** +// * The donau's configuration (global) +// */ +// const struct GNUNET_CONFIGURATION_Handle *TEH_cfg; -/** - * Configuration of age restriction - * - * Set after loading the library, enabled in database event handler. - */ -bool TEH_age_restriction_enabled = false; -struct TALER_AgeRestrictionConfig TEH_age_restriction_config = {0}; +// /** +// * Configuration of age restriction +// * +// * Set after loading the library, enabled in database event handler. +// */ +// bool TEH_age_restriction_enabled = false; +// struct TALER_AgeRestrictionConfig TEH_age_restriction_config = {0}; -/** - * Handle to the HTTP server. - */ -static struct MHD_Daemon *mhd; +// /** +// * Handle to the HTTP server. +// */ +// static struct MHD_Daemon *mhd; -/** - * How long is caching /keys allowed at most? (global) - */ -struct GNUNET_TIME_Relative TEH_max_keys_caching; +// /** +// * How long is caching /keys allowed at most? (global) +// */ +// struct GNUNET_TIME_Relative TEH_max_keys_caching; -/** - * How long is the delay before we close reserves? - */ -struct GNUNET_TIME_Relative TEH_reserve_closing_delay; +// /** +// * How long is the delay before we close reserves? +// */ +// struct GNUNET_TIME_Relative TEH_reserve_closing_delay; -/** - * Master public key (according to the - * configuration in the donau directory). (global) - */ -struct TALER_MasterPublicKeyP TEH_master_public_key; +// /** +// * Master public key (according to the +// * configuration in the donau directory). (global) +// */ +// struct TALER_MasterPublicKeyP TEH_master_public_key; -/** - * Key used to encrypt KYC attribute data in our database. - */ -struct TALER_AttributeEncryptionKeyP TEH_attribute_key; +// /** +// * Key used to encrypt KYC attribute data in our database. +// */ +// struct TALER_AttributeEncryptionKeyP TEH_attribute_key; -/** - * Our DB plugin. (global) - */ -struct DONAUDB_Plugin *TEH_plugin; +// /** +// * Our DB plugin. (global) +// */ +// struct DONAUDB_Plugin *TEH_plugin; -/** - * Absolute STEFAN parameter. - */ -struct TALER_Amount TEH_stefan_abs; +// /** +// * Absolute STEFAN parameter. +// */ +// struct TALER_Amount TEH_stefan_abs; -/** - * Logarithmic STEFAN parameter. - */ -struct TALER_Amount TEH_stefan_log; +// /** +// * Logarithmic STEFAN parameter. +// */ +// struct TALER_Amount TEH_stefan_log; -/** - * Linear STEFAN parameter. - */ -struct TALER_Amount TEH_stefan_lin; +// /** +// * Linear STEFAN parameter. +// */ +// struct TALER_Amount TEH_stefan_lin; -/** - * Default number of fractional digits to render - * amounts with. - */ -unsigned int TEH_currency_fraction_digits; +// /** +// * Default number of fractional digits to render +// * amounts with. +// */ +// unsigned int TEH_currency_fraction_digits; -/** - * Our currency. - */ -char *TEH_currency; +// /** +// * Our currency. +// */ +// char *TEH_currency; -/** - * Name of the KYC-AML-trigger evaluation binary. - */ -char *TEH_kyc_aml_trigger; +// /** +// * Name of the KYC-AML-trigger evaluation binary. +// */ +// char *TEH_kyc_aml_trigger; -/** - * Option set to #GNUNET_YES if rewards are enabled. - */ -int TEH_enable_rewards; +// /** +// * Option set to #GNUNET_YES if rewards are enabled. +// */ +// int TEH_enable_rewards; -/** - * What is the largest amount we allow a peer to - * merge into a reserve before always triggering - * an AML check? - */ -struct TALER_Amount TEH_aml_threshold; +// /** +// * What is the largest amount we allow a peer to +// * merge into a reserve before always triggering +// * an AML check? +// */ +// struct TALER_Amount TEH_aml_threshold; -/** - * Our base URL. - */ -char *TEH_base_url; +// /** +// * Our base URL. +// */ +// char *TEH_base_url; /** * Default timeout in seconds for HTTP requests. @@ -166,171 +166,171 @@ static unsigned int connection_timeout = 30; */ static int connection_close; -/** - * -I command-line flag given? - */ -int TEH_check_invariants_flag; +// /** +// * -I command-line flag given? +// */ +// int TEH_check_invariants_flag; -/** - * True if we should commit suicide once all active - * connections are finished. - */ -bool TEH_suicide; +// /** +// * True if we should commit suicide once all active +// * connections are finished. +// */ +// bool TEH_suicide; -/** - * Signature of the configuration of all enabled extensions, - * signed by the donau's offline master key with purpose - * TALER_SIGNATURE_MASTER_EXTENSION. - */ -struct TALER_MasterSignatureP TEH_extensions_sig; -bool TEH_extensions_signed = false; +// /** +// * Signature of the configuration of all enabled extensions, +// * signed by the donau's offline master key with purpose +// * TALER_SIGNATURE_MASTER_EXTENSION. +// */ +// struct TALER_MasterSignatureP TEH_extensions_sig; +// bool TEH_extensions_signed = false; -/** - * Value to return from main() - */ -static int global_ret; +// /** +// * Value to return from main() +// */ +// static int global_ret; -/** - * Port to run the daemon on. - */ -static uint16_t serve_port; +// /** +// * Port to run the daemon on. +// */ +// static uint16_t serve_port; -/** - * Counter for the number of requests this HTTP has processed so far. - */ -static unsigned long long req_count; +// /** +// * Counter for the number of requests this HTTP has processed so far. +// */ +// static unsigned long long req_count; -/** - * Counter for the number of open connections. - */ -static unsigned long long active_connections; +// /** +// * Counter for the number of open connections. +// */ +// static unsigned long long active_connections; -/** - * Limit for the number of requests this HTTP may process before restarting. - * (This was added as one way of dealing with unavoidable memory fragmentation - * happening slowly over time.) - */ -static unsigned long long req_max; +// /** +// * Limit for the number of requests this HTTP may process before restarting. +// * (This was added as one way of dealing with unavoidable memory fragmentation +// * happening slowly over time.) +// */ +// static unsigned long long req_max; -/** - * Context for all CURL operations (useful to the event loop) - */ -struct GNUNET_CURL_Context *TEH_curl_ctx; +// /** +// * Context for all CURL operations (useful to the event loop) +// */ +// struct GNUNET_CURL_Context *TEH_curl_ctx; -/** - * Context for integrating #TEH_curl_ctx with the - * GNUnet event loop. - */ -static struct GNUNET_CURL_RescheduleContext *donau_curl_rc; +// /** +// * Context for integrating #TEH_curl_ctx with the +// * GNUnet event loop. +// */ +// static struct GNUNET_CURL_RescheduleContext *donau_curl_rc; -/** - * Signature of functions that handle operations on coins. - * - * @param connection the MHD connection to handle - * @param coin_pub the public key of the coin - * @param root uploaded JSON data - * @return MHD result code - */ -typedef MHD_RESULT -(*CoinOpHandler)(struct MHD_Connection *connection, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const json_t *root); +// /** +// * Signature of functions that handle operations on coins. +// * +// * @param connection the MHD connection to handle +// * @param coin_pub the public key of the coin +// * @param root uploaded JSON data +// * @return MHD result code +// */ +// typedef MHD_RESULT +// (*CoinOpHandler)(struct MHD_Connection *connection, +// const struct TALER_CoinSpendPublicKeyP *coin_pub, +// const json_t *root); -/** - * Generate a 404 "not found" reply on @a connection with - * the hint @a details. - * - * @param connection where to send the reply on - * @param details details for the error message, can be NULL - */ -static MHD_RESULT -r404 (struct MHD_Connection *connection, - const char *details) -{ - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN, - details); -} +// /** +// * Generate a 404 "not found" reply on @a connection with +// * the hint @a details. +// * +// * @param connection where to send the reply on +// * @param details details for the error message, can be NULL +// */ +// static MHD_RESULT +// r404 (struct MHD_Connection *connection, +// const char *details) +// { +// return TALER_MHD_reply_with_error (connection, +// MHD_HTTP_NOT_FOUND, +// TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN, +// details); +// } -/** - * Function called whenever MHD is done with a request. If the - * request was a POST, we may have stored a `struct Buffer *` in the - * @a con_cls that might still need to be cleaned up. Call the - * respective function to free the memory. - * - * @param cls client-defined closure - * @param connection connection handle - * @param con_cls value as set by the last call to - * the #MHD_AccessHandlerCallback - * @param toe reason for request termination - * @see #MHD_OPTION_NOTIFY_COMPLETED - * @ingroup request - */ -static void -handle_mhd_completion_callback (void *cls, - struct MHD_Connection *connection, - void **con_cls, - enum MHD_RequestTerminationCode toe) -{ - struct TEH_RequestContext *rc = *con_cls; - struct GNUNET_AsyncScopeSave old_scope; - - (void) cls; - if (NULL == rc) - return; - GNUNET_async_scope_enter (&rc->async_scope_id, - &old_scope); - check_suicide (); - TEH_check_invariants (); - if (NULL != rc->rh_cleaner) - rc->rh_cleaner (rc); - TEH_check_invariants (); - { -#if MHD_VERSION >= 0x00097304 - const union MHD_ConnectionInfo *ci; - unsigned int http_status = 0; - - ci = MHD_get_connection_info (connection, - MHD_CONNECTION_INFO_HTTP_STATUS); - if (NULL != ci) - http_status = ci->http_status; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Request for `%s' completed with HTTP status %u (%d)\n", - rc->url, - http_status, - toe); -#else - (void) connection; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Request for `%s' completed (%d)\n", - rc->url, - toe); -#endif - } - - TALER_MHD_parse_post_cleanup_callback (rc->opaque_post_parsing_context); - /* Sanity-check that we didn't leave any transactions hanging */ - // GNUNET_break (GNUNET_OK == - // TEH_plugin->preflight (TEH_plugin->cls)); - { - struct GNUNET_TIME_Relative latency; - - latency = GNUNET_TIME_absolute_get_duration (rc->start_time); - if (latency.rel_value_us > - WARN_LATENCY.rel_value_us) - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Request for `%s' took %s\n", - rc->url, - GNUNET_STRINGS_relative_time_to_string (latency, - GNUNET_YES)); - } - GNUNET_free (rc); - *con_cls = NULL; - GNUNET_async_scope_restore (&old_scope); -} +// /** +// * Function called whenever MHD is done with a request. If the +// * request was a POST, we may have stored a `struct Buffer *` in the +// * @a con_cls that might still need to be cleaned up. Call the +// * respective function to free the memory. +// * +// * @param cls client-defined closure +// * @param connection connection handle +// * @param con_cls value as set by the last call to +// * the #MHD_AccessHandlerCallback +// * @param toe reason for request termination +// * @see #MHD_OPTION_NOTIFY_COMPLETED +// * @ingroup request +// */ +// static void +// handle_mhd_completion_callback (void *cls, +// struct MHD_Connection *connection, +// void **con_cls, +// enum MHD_RequestTerminationCode toe) +// { +// struct TEH_RequestContext *rc = *con_cls; +// struct GNUNET_AsyncScopeSave old_scope; + +// (void) cls; +// if (NULL == rc) +// return; +// GNUNET_async_scope_enter (&rc->async_scope_id, +// &old_scope); +// check_suicide (); +// TEH_check_invariants (); +// if (NULL != rc->rh_cleaner) +// rc->rh_cleaner (rc); +// TEH_check_invariants (); +// { +// #if MHD_VERSION >= 0x00097304 +// const union MHD_ConnectionInfo *ci; +// unsigned int http_status = 0; + +// ci = MHD_get_connection_info (connection, +// MHD_CONNECTION_INFO_HTTP_STATUS); +// if (NULL != ci) +// http_status = ci->http_status; +// GNUNET_log (GNUNET_ERROR_TYPE_INFO, +// "Request for `%s' completed with HTTP status %u (%d)\n", +// rc->url, +// http_status, +// toe); +// #else +// (void) connection; +// GNUNET_log (GNUNET_ERROR_TYPE_INFO, +// "Request for `%s' completed (%d)\n", +// rc->url, +// toe); +// #endif +// } + +// TALER_MHD_parse_post_cleanup_callback (rc->opaque_post_parsing_context); +// /* Sanity-check that we didn't leave any transactions hanging */ +// // GNUNET_break (GNUNET_OK == +// // TEH_plugin->preflight (TEH_plugin->cls)); +// { +// struct GNUNET_TIME_Relative latency; + +// latency = GNUNET_TIME_absolute_get_duration (rc->start_time); +// if (latency.rel_value_us > +// WARN_LATENCY.rel_value_us) +// GNUNET_log (GNUNET_ERROR_TYPE_INFO, +// "Request for `%s' took %s\n", +// rc->url, +// GNUNET_STRINGS_relative_time_to_string (latency, +// GNUNET_YES)); +// } +// GNUNET_free (rc); +// *con_cls = NULL; +// GNUNET_async_scope_restore (&old_scope); +// } // /** @@ -494,614 +494,614 @@ handle_mhd_completion_callback (void *cls, // } -/** - * Handle incoming HTTP request. - * - * @param cls closure for MHD daemon (unused) - * @param connection the connection - * @param url the requested url - * @param method the method (POST, GET, ...) - * @param version HTTP version (ignored) - * @param upload_data request data - * @param upload_data_size size of @a upload_data in bytes - * @param con_cls closure for request (a `struct TEH_RequestContext *`) - * @return MHD result code - */ -static MHD_RESULT -handle_mhd_request (void *cls, - struct MHD_Connection *connection, - const char *url, - const char *method, - const char *version, - const char *upload_data, - size_t *upload_data_size, - void **con_cls) -{ - static struct TEH_RequestHandler handlers[] = { - /* /robots.txt: disallow everything */ - // { - // .url = "robots.txt", - // .method = MHD_HTTP_METHOD_GET, - // .handler.get = &TEH_handler_static_response, - // .mime_type = "text/plain", - // .data = "User-agent: *\nDisallow: /\n", - // .response_code = MHD_HTTP_OK - // }, - /* Landing page, tell humans to go away. */ - // { - // .url = "", - // .method = MHD_HTTP_METHOD_GET, - // .handler.get = TEH_handler_static_response, - // .mime_type = "text/plain", - // .data = - // "Hello, I'm the Taler donau. This HTTP server is not for humans.\n", - // .response_code = MHD_HTTP_OK - // }, - /* AGPL licensing page, redirect to source. As per the AGPL-license, every +// /** +// * Handle incoming HTTP request. +// * +// * @param cls closure for MHD daemon (unused) +// * @param connection the connection +// * @param url the requested url +// * @param method the method (POST, GET, ...) +// * @param version HTTP version (ignored) +// * @param upload_data request data +// * @param upload_data_size size of @a upload_data in bytes +// * @param con_cls closure for request (a `struct TEH_RequestContext *`) +// * @return MHD result code +// */ +// static MHD_RESULT +// handle_mhd_request (void *cls, +// struct MHD_Connection *connection, +// const char *url, +// const char *method, +// const char *version, +// const char *upload_data, +// size_t *upload_data_size, +// void **con_cls) +// { +// static struct TEH_RequestHandler handlers[] = { +/* /robots.txt: disallow everything */ +// { +// .url = "robots.txt", +// .method = MHD_HTTP_METHOD_GET, +// .handler.get = &TEH_handler_static_response, +// .mime_type = "text/plain", +// .data = "User-agent: *\nDisallow: /\n", +// .response_code = MHD_HTTP_OK +// }, +/* Landing page, tell humans to go away. */ +// { +// .url = "", +// .method = MHD_HTTP_METHOD_GET, +// .handler.get = TEH_handler_static_response, +// .mime_type = "text/plain", +// .data = +// "Hello, I'm the Taler donau. This HTTP server is not for humans.\n", +// .response_code = MHD_HTTP_OK +// }, +/* AGPL licensing page, redirect to source. As per the AGPL-license, every deployment is required to offer the user a download of the source of the actual deployment. We make this easy by including a redirect to the source here. */ - // { - // .url = "agpl", - // .method = MHD_HTTP_METHOD_GET, - // .handler.get = &TEH_handler_agpl_redirect - // }, - // { - // .url = "seed", - // .method = MHD_HTTP_METHOD_GET, - // .handler.get = &handler_seed - // }, - /* Configuration */ - // { - // .url = "config", - // .method = MHD_HTTP_METHOD_GET, - // .handler.get = &TEH_handler_config - // }, - /* Performance metrics */ - // { - // .url = "metrics", - // .method = MHD_HTTP_METHOD_GET, - // .handler.get = &TEH_handler_metrics - // }, - /* Terms of service */ - // { - // .url = "terms", - // .method = MHD_HTTP_METHOD_GET, - // .handler.get = &TEH_handler_terms - // }, - /* Privacy policy */ - // { - // .url = "privacy", - // .method = MHD_HTTP_METHOD_GET, - // .handler.get = &TEH_handler_privacy - // }, - /* Return key material and fundamental properties for this donau */ - // { - // .url = "keys", - // .method = MHD_HTTP_METHOD_GET, - // .handler.get = &TEH_keys_get_handler, - // }, - /* request R, used in clause schnorr withdraw and refresh */ - // { - // .url = "csr-melt", - // .method = MHD_HTTP_METHOD_POST, - // .handler.post = &TEH_handler_csr_melt, - // .nargs = 0 - // }, - - - /* mark end of list */ - { - .url = NULL - } - }; - struct TEH_RequestContext *rc = *con_cls; - struct GNUNET_AsyncScopeSave old_scope; - const char *correlation_id = NULL; - - (void) cls; - (void) version; - if (NULL == rc) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Handling new request\n"); - - /* We're in a new async scope! */ - rc = *con_cls = GNUNET_new (struct TEH_RequestContext); - rc->start_time = GNUNET_TIME_absolute_get (); - GNUNET_async_scope_fresh (&rc->async_scope_id); - TEH_check_invariants (); - rc->url = url; - rc->connection = connection; - /* We only read the correlation ID on the first callback for every client */ - correlation_id = MHD_lookup_connection_value (connection, - MHD_HEADER_KIND, - "Taler-Correlation-Id"); - if ( (NULL != correlation_id) && - (GNUNET_YES != - GNUNET_CURL_is_valid_scope_id (correlation_id)) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "illegal incoming correlation ID\n"); - correlation_id = NULL; - } - - /* Check if upload is in bounds */ - if (0 == strcasecmp (method, - MHD_HTTP_METHOD_POST)) - { - TALER_MHD_check_content_length (connection, - TALER_MHD_REQUEST_BUFFER_MAX); - } - } - - GNUNET_async_scope_enter (&rc->async_scope_id, - &old_scope); - TEH_check_invariants (); - if (NULL != correlation_id) - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Handling request (%s) for URL '%s', correlation_id=%s\n", - method, - url, - correlation_id); - else - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Handling request (%s) for URL '%s'\n", - method, - url); - /* on repeated requests, check our cache first */ - if (NULL != rc->rh) - { - MHD_RESULT ret; - const char *start; - - if ('\0' == url[0]) - /* strange, should start with '/', treat as just "/" */ - url = "/"; - start = strchr (url + 1, '/'); - if (NULL == start) - start = ""; - ret = proceed_with_handler (rc, - start, - upload_data, - upload_data_size); - GNUNET_async_scope_restore (&old_scope); - return ret; - } - - if ( (0 == strcasecmp (method, - MHD_HTTP_METHOD_OPTIONS)) && - (0 == strcmp ("*", - url)) ) - return TALER_MHD_reply_cors_preflight (connection); - - if (0 == strcasecmp (method, - MHD_HTTP_METHOD_HEAD)) - method = MHD_HTTP_METHOD_GET; /* treat HEAD as GET here, MHD will do the rest */ - - /* parse first part of URL */ - { - bool found = false; - size_t tok_size; - const char *tok; - const char *rest; - - if ('\0' == url[0]) - /* strange, should start with '/', treat as just "/" */ - url = "/"; - tok = url + 1; - rest = strchr (tok, '/'); - if (NULL == rest) - { - tok_size = strlen (tok); - } - else - { - tok_size = rest - tok; - rest++; /* skip over '/' */ - } - for (unsigned int i = 0; NULL != handlers[i].url; i++) - { - struct TEH_RequestHandler *rh = &handlers[i]; - - if ( (0 != strncmp (tok, - rh->url, - tok_size)) || - (tok_size != strlen (rh->url) ) ) - continue; - found = true; - /* The URL is a match! What we now do depends on the method. */ - if (0 == strcasecmp (method, - MHD_HTTP_METHOD_OPTIONS)) - { - GNUNET_async_scope_restore (&old_scope); - return TALER_MHD_reply_cors_preflight (connection); - } - GNUNET_assert (NULL != rh->method); - if (0 == strcasecmp (method, - rh->method)) - { - MHD_RESULT ret; - - /* cache to avoid the loop next time */ - rc->rh = rh; - /* run handler */ - ret = proceed_with_handler (rc, - url + tok_size + 1, - upload_data, - upload_data_size); - GNUNET_async_scope_restore (&old_scope); - return ret; - } - } - - if (found) - { - /* we found a matching address, but the method is wrong */ - struct MHD_Response *reply; - MHD_RESULT ret; - char *allowed = NULL; - - GNUNET_break_op (0); - for (unsigned int i = 0; NULL != handlers[i].url; i++) - { - struct TEH_RequestHandler *rh = &handlers[i]; - - if ( (0 != strncmp (tok, - rh->url, - tok_size)) || - (tok_size != strlen (rh->url) ) ) - continue; - if (NULL == allowed) - { - allowed = GNUNET_strdup (rh->method); - } - else - { - char *tmp; - - GNUNET_asprintf (&tmp, - "%s, %s", - allowed, - rh->method); - GNUNET_free (allowed); - allowed = tmp; - } - if (0 == strcasecmp (rh->method, - MHD_HTTP_METHOD_GET)) - { - char *tmp; - - GNUNET_asprintf (&tmp, - "%s, %s", - allowed, - MHD_HTTP_METHOD_HEAD); - GNUNET_free (allowed); - allowed = tmp; - } - } - reply = TALER_MHD_make_error (TALER_EC_GENERIC_METHOD_INVALID, - method); - GNUNET_break (MHD_YES == - MHD_add_response_header (reply, - MHD_HTTP_HEADER_ALLOW, - allowed)); - GNUNET_free (allowed); - ret = MHD_queue_response (connection, - MHD_HTTP_METHOD_NOT_ALLOWED, - reply); - MHD_destroy_response (reply); - return ret; - } - } - - /* No handler matches, generate not found */ - { - MHD_RESULT ret; - - ret = TALER_MHD_reply_with_error (connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_GENERIC_ENDPOINT_UNKNOWN, - url); - GNUNET_async_scope_restore (&old_scope); - return ret; - } -} +// { +// .url = "agpl", +// .method = MHD_HTTP_METHOD_GET, +// .handler.get = &TEH_handler_agpl_redirect +// }, +// { +// .url = "seed", +// .method = MHD_HTTP_METHOD_GET, +// .handler.get = &handler_seed +// }, +/* Configuration */ +// { +// .url = "config", +// .method = MHD_HTTP_METHOD_GET, +// .handler.get = &TEH_handler_config +// }, +/* Performance metrics */ +// { +// .url = "metrics", +// .method = MHD_HTTP_METHOD_GET, +// .handler.get = &TEH_handler_metrics +// }, +/* Terms of service */ +// { +// .url = "terms", +// .method = MHD_HTTP_METHOD_GET, +// .handler.get = &TEH_handler_terms +// }, +/* Privacy policy */ +// { +// .url = "privacy", +// .method = MHD_HTTP_METHOD_GET, +// .handler.get = &TEH_handler_privacy +// }, +/* Return key material and fundamental properties for this donau */ +// { +// .url = "keys", +// .method = MHD_HTTP_METHOD_GET, +// .handler.get = &TEH_keys_get_handler, +// }, +/* request R, used in clause schnorr withdraw and refresh */ +// { +// .url = "csr-melt", +// .method = MHD_HTTP_METHOD_POST, +// .handler.post = &TEH_handler_csr_melt, +// .nargs = 0 +// }, -/** - * Load configuration parameters for the donau - * server into the corresponding global variables. - * - * @return #GNUNET_OK on success - */ -static enum GNUNET_GenericReturnValue -donau_serve_process_config (void) -{ - if (GNUNET_OK != - TALER_KYCLOGIC_kyc_init (TEH_cfg)) - { - return GNUNET_SYSERR; - } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (TEH_cfg, - "donau", - "MAX_REQUESTS", - &req_max)) - { - req_max = ULLONG_MAX; - } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (TEH_cfg, - "donaudb", - "IDLE_RESERVE_EXPIRATION_TIME", - &TEH_reserve_closing_delay)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "donaudb", - "IDLE_RESERVE_EXPIRATION_TIME"); - /* use default */ - TEH_reserve_closing_delay - = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_WEEKS, - 4); - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (TEH_cfg, - "donau", - "MAX_KEYS_CACHING", - &TEH_max_keys_caching)) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - "donau", - "MAX_KEYS_CACHING", - "valid relative time expected"); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (TEH_cfg, - "donau", - "KYC_AML_TRIGGER", - &TEH_kyc_aml_trigger)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "donau", - "KYC_AML_TRIGGER"); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_config_get_currency (TEH_cfg, - &TEH_currency)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "taler", - "CURRENCY"); - return GNUNET_SYSERR; - } - { - unsigned long long cfd; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (TEH_cfg, - "donau", - "CURRENCY_FRACTION_DIGITS", - &cfd)) - cfd = 0; - if (cfd > 8) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - "taler", - "CURRENCY_FRACTION_DIGITS", - "Value must be below 8"); - return GNUNET_SYSERR; - } - TEH_currency_fraction_digits = (unsigned int) cfd; - } - if (GNUNET_OK != - TALER_config_get_amount (TEH_cfg, - "donau", - "AML_THRESHOLD", - &TEH_aml_threshold)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Need amount in section `donau' under `AML_THRESHOLD'\n"); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_config_get_amount (TEH_cfg, - "donau", - "STEFAN_ABS", - &TEH_stefan_abs)) - { - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (TEH_currency, - &TEH_stefan_abs)); - } - if (GNUNET_OK != - TALER_config_get_amount (TEH_cfg, - "donau", - "STEFAN_LOG", - &TEH_stefan_log)) - { - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (TEH_currency, - &TEH_stefan_log)); - } - if (GNUNET_OK != - TALER_config_get_amount (TEH_cfg, - "donau", - "STEFAN_LIN", - &TEH_stefan_lin)) - { - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (TEH_currency, - &TEH_stefan_lin)); - } - - if (0 != strcmp (TEH_currency, - TEH_aml_threshold.currency)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Amount in section `donau' under `AML_THRESHOLD' uses the wrong currency!\n"); - return GNUNET_SYSERR; - } - TEH_enable_rewards - = GNUNET_CONFIGURATION_get_value_yesno ( - TEH_cfg, - "donau", - "ENABLE_REWARDS"); - if (GNUNET_SYSERR == TEH_enable_rewards) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Need YES or NO in section `donau' under `ENABLE_REWARDS'\n"); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (TEH_cfg, - "donau", - "BASE_URL", - &TEH_base_url)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "donau", - "BASE_URL"); - return GNUNET_SYSERR; - } - if (! TALER_url_valid_charset (TEH_base_url)) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - "donau", - "BASE_URL", - "invalid URL"); - return GNUNET_SYSERR; - } - - { - char *master_public_key_str; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (TEH_cfg, - "donau", - "MASTER_PUBLIC_KEY", - &master_public_key_str)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "donau", - "MASTER_PUBLIC_KEY"); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_public_key_from_string (master_public_key_str, - strlen ( - master_public_key_str), - &TEH_master_public_key. - eddsa_pub)) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - "donau", - "MASTER_PUBLIC_KEY", - "invalid base32 encoding for a master public key"); - GNUNET_free (master_public_key_str); - return GNUNET_SYSERR; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Launching donau with public key `%s'...\n", - master_public_key_str); - GNUNET_free (master_public_key_str); - } - - { - char *attr_enc_key_str; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (TEH_cfg, - "donau", - "ATTRIBUTE_ENCRYPTION_KEY", - &attr_enc_key_str)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "donau", - "ATTRIBUTE_ENCRYPTION_KEY"); - return GNUNET_SYSERR; - } - GNUNET_CRYPTO_hash (attr_enc_key_str, - strlen (attr_enc_key_str), - &TEH_attribute_key.hash); - GNUNET_free (attr_enc_key_str); - } - - for (unsigned int i = 0; i<MAX_DB_RETRIES; i++) - { - TEH_plugin = DONAUDB_plugin_load (TEH_cfg); - if (NULL != TEH_plugin) - break; - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to connect to DB, will try again %u times\n", - MAX_DB_RETRIES - i); - sleep (1); - } - if (NULL == TEH_plugin) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to initialize DB subsystem. Giving up.\n"); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} +// /* mark end of list */ +// { +// .url = NULL +// } +// }; +// struct TEH_RequestContext *rc = *con_cls; +// struct GNUNET_AsyncScopeSave old_scope; +// const char *correlation_id = NULL; + +// (void) cls; +// (void) version; +// if (NULL == rc) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_INFO, +// "Handling new request\n"); + +// /* We're in a new async scope! */ +// rc = *con_cls = GNUNET_new (struct TEH_RequestContext); +// rc->start_time = GNUNET_TIME_absolute_get (); +// GNUNET_async_scope_fresh (&rc->async_scope_id); +// TEH_check_invariants (); +// rc->url = url; +// rc->connection = connection; +// /* We only read the correlation ID on the first callback for every client */ +// correlation_id = MHD_lookup_connection_value (connection, +// MHD_HEADER_KIND, +// "Taler-Correlation-Id"); +// if ( (NULL != correlation_id) && +// (GNUNET_YES != +// GNUNET_CURL_is_valid_scope_id (correlation_id)) ) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_WARNING, +// "illegal incoming correlation ID\n"); +// correlation_id = NULL; +// } + +// /* Check if upload is in bounds */ +// if (0 == strcasecmp (method, +// MHD_HTTP_METHOD_POST)) +// { +// TALER_MHD_check_content_length (connection, +// TALER_MHD_REQUEST_BUFFER_MAX); +// } +// } +// GNUNET_async_scope_enter (&rc->async_scope_id, +// &old_scope); +// TEH_check_invariants (); +// if (NULL != correlation_id) +// GNUNET_log (GNUNET_ERROR_TYPE_INFO, +// "Handling request (%s) for URL '%s', correlation_id=%s\n", +// method, +// url, +// correlation_id); +// else +// GNUNET_log (GNUNET_ERROR_TYPE_INFO, +// "Handling request (%s) for URL '%s'\n", +// method, +// url); +// /* on repeated requests, check our cache first */ +// if (NULL != rc->rh) +// { +// MHD_RESULT ret; +// const char *start; + +// if ('\0' == url[0]) +// /* strange, should start with '/', treat as just "/" */ +// url = "/"; +// start = strchr (url + 1, '/'); +// if (NULL == start) +// start = ""; +// ret = proceed_with_handler (rc, +// start, +// upload_data, +// upload_data_size); +// GNUNET_async_scope_restore (&old_scope); +// return ret; +// } -/** - * Called when the main thread exits, writes out performance - * stats if requested. - */ -static void -write_stats (void) -{ - struct GNUNET_DISK_FileHandle *fh; - pid_t pid = getpid (); - char *benchmark_dir; - char *s; - struct rusage usage; - - benchmark_dir = getenv ("GNUNET_BENCHMARK_DIR"); - if (NULL == benchmark_dir) - return; - GNUNET_asprintf (&s, - "%s/taler-donau-%llu.txt", - benchmark_dir, - (unsigned long long) pid); - fh = GNUNET_DISK_file_open (s, - (GNUNET_DISK_OPEN_WRITE - | GNUNET_DISK_OPEN_TRUNCATE - | GNUNET_DISK_OPEN_CREATE), - (GNUNET_DISK_PERM_USER_READ - | GNUNET_DISK_PERM_USER_WRITE)); - GNUNET_free (s); - if (NULL == fh) - return; /* permission denied? */ - - /* Collect stats, summed up for all threads */ - GNUNET_assert (0 == - getrusage (RUSAGE_SELF, - &usage)); - GNUNET_asprintf (&s, - "time_donau sys %llu user %llu\n", - (unsigned long long) (usage.ru_stime.tv_sec * 1000 * 1000 - + usage.ru_stime.tv_usec), - (unsigned long long) (usage.ru_utime.tv_sec * 1000 * 1000 - + usage.ru_utime.tv_usec)); - GNUNET_assert (GNUNET_SYSERR != - GNUNET_DISK_file_write_blocking (fh, - s, - strlen (s))); - GNUNET_free (s); - GNUNET_assert (GNUNET_OK == - GNUNET_DISK_file_close (fh)); -} +// if ( (0 == strcasecmp (method, +// MHD_HTTP_METHOD_OPTIONS)) && +// (0 == strcmp ("*", +// url)) ) +// return TALER_MHD_reply_cors_preflight (connection); +// if (0 == strcasecmp (method, +// MHD_HTTP_METHOD_HEAD)) +// method = MHD_HTTP_METHOD_GET; /* treat HEAD as GET here, MHD will do the rest */ -/* Developer logic for supporting the `-f' option. */ -#if HAVE_DEVELOPER +// /* parse first part of URL */ +// { +// bool found = false; +// size_t tok_size; +// const char *tok; +// const char *rest; + +// if ('\0' == url[0]) +// /* strange, should start with '/', treat as just "/" */ +// url = "/"; +// tok = url + 1; +// rest = strchr (tok, '/'); +// if (NULL == rest) +// { +// tok_size = strlen (tok); +// } +// else +// { +// tok_size = rest - tok; +// rest++; /* skip over '/' */ +// } +// for (unsigned int i = 0; NULL != handlers[i].url; i++) +// { +// struct TEH_RequestHandler *rh = &handlers[i]; + +// if ( (0 != strncmp (tok, +// rh->url, +// tok_size)) || +// (tok_size != strlen (rh->url) ) ) +// continue; +// found = true; +// /* The URL is a match! What we now do depends on the method. */ +// if (0 == strcasecmp (method, +// MHD_HTTP_METHOD_OPTIONS)) +// { +// GNUNET_async_scope_restore (&old_scope); +// return TALER_MHD_reply_cors_preflight (connection); +// } +// GNUNET_assert (NULL != rh->method); +// if (0 == strcasecmp (method, +// rh->method)) +// { +// MHD_RESULT ret; + +// /* cache to avoid the loop next time */ +// rc->rh = rh; +// /* run handler */ +// ret = proceed_with_handler (rc, +// url + tok_size + 1, +// upload_data, +// upload_data_size); +// GNUNET_async_scope_restore (&old_scope); +// return ret; +// } +// } + +// if (found) +// { +// /* we found a matching address, but the method is wrong */ +// struct MHD_Response *reply; +// MHD_RESULT ret; +// char *allowed = NULL; + +// GNUNET_break_op (0); +// for (unsigned int i = 0; NULL != handlers[i].url; i++) +// { +// struct TEH_RequestHandler *rh = &handlers[i]; + +// if ( (0 != strncmp (tok, +// rh->url, +// tok_size)) || +// (tok_size != strlen (rh->url) ) ) +// continue; +// if (NULL == allowed) +// { +// allowed = GNUNET_strdup (rh->method); +// } +// else +// { +// char *tmp; + +// GNUNET_asprintf (&tmp, +// "%s, %s", +// allowed, +// rh->method); +// GNUNET_free (allowed); +// allowed = tmp; +// } +// if (0 == strcasecmp (rh->method, +// MHD_HTTP_METHOD_GET)) +// { +// char *tmp; + +// GNUNET_asprintf (&tmp, +// "%s, %s", +// allowed, +// MHD_HTTP_METHOD_HEAD); +// GNUNET_free (allowed); +// allowed = tmp; +// } +// } +// reply = TALER_MHD_make_error (TALER_EC_GENERIC_METHOD_INVALID, +// method); +// GNUNET_break (MHD_YES == +// MHD_add_response_header (reply, +// MHD_HTTP_HEADER_ALLOW, +// allowed)); +// GNUNET_free (allowed); +// ret = MHD_queue_response (connection, +// MHD_HTTP_METHOD_NOT_ALLOWED, +// reply); +// MHD_destroy_response (reply); +// return ret; +// } +// } + +// /* No handler matches, generate not found */ +// { +// MHD_RESULT ret; + +// ret = TALER_MHD_reply_with_error (connection, +// MHD_HTTP_NOT_FOUND, +// TALER_EC_GENERIC_ENDPOINT_UNKNOWN, +// url); +// GNUNET_async_scope_restore (&old_scope); +// return ret; +// } +// } + + +// /** +// * Load configuration parameters for the donau +// * server into the corresponding global variables. +// * +// * @return #GNUNET_OK on success +// */ +// static enum GNUNET_GenericReturnValue +// donau_serve_process_config (void) +// { +// if (GNUNET_OK != +// TALER_KYCLOGIC_kyc_init (TEH_cfg)) +// { +// return GNUNET_SYSERR; +// } +// if (GNUNET_OK != +// GNUNET_CONFIGURATION_get_value_number (TEH_cfg, +// "donau", +// "MAX_REQUESTS", +// &req_max)) +// { +// req_max = ULLONG_MAX; +// } +// if (GNUNET_OK != +// GNUNET_CONFIGURATION_get_value_time (TEH_cfg, +// "donaudb", +// "IDLE_RESERVE_EXPIRATION_TIME", +// &TEH_reserve_closing_delay)) +// { +// GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, +// "donaudb", +// "IDLE_RESERVE_EXPIRATION_TIME"); +// /* use default */ +// TEH_reserve_closing_delay +// = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_WEEKS, +// 4); +// } + +// if (GNUNET_OK != +// GNUNET_CONFIGURATION_get_value_time (TEH_cfg, +// "donau", +// "MAX_KEYS_CACHING", +// &TEH_max_keys_caching)) +// { +// GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, +// "donau", +// "MAX_KEYS_CACHING", +// "valid relative time expected"); +// return GNUNET_SYSERR; +// } +// if (GNUNET_OK != +// GNUNET_CONFIGURATION_get_value_string (TEH_cfg, +// "donau", +// "KYC_AML_TRIGGER", +// &TEH_kyc_aml_trigger)) +// { +// GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, +// "donau", +// "KYC_AML_TRIGGER"); +// return GNUNET_SYSERR; +// } +// if (GNUNET_OK != +// TALER_config_get_currency (TEH_cfg, +// &TEH_currency)) +// { +// GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, +// "taler", +// "CURRENCY"); +// return GNUNET_SYSERR; +// } +// { +// unsigned long long cfd; + +// if (GNUNET_OK != +// GNUNET_CONFIGURATION_get_value_number (TEH_cfg, +// "donau", +// "CURRENCY_FRACTION_DIGITS", +// &cfd)) +// cfd = 0; +// if (cfd > 8) +// { +// GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, +// "taler", +// "CURRENCY_FRACTION_DIGITS", +// "Value must be below 8"); +// return GNUNET_SYSERR; +// } +// TEH_currency_fraction_digits = (unsigned int) cfd; +// } +// if (GNUNET_OK != +// TALER_config_get_amount (TEH_cfg, +// "donau", +// "AML_THRESHOLD", +// &TEH_aml_threshold)) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Need amount in section `donau' under `AML_THRESHOLD'\n"); +// return GNUNET_SYSERR; +// } +// if (GNUNET_OK != +// TALER_config_get_amount (TEH_cfg, +// "donau", +// "STEFAN_ABS", +// &TEH_stefan_abs)) +// { +// GNUNET_assert (GNUNET_OK == +// TALER_amount_set_zero (TEH_currency, +// &TEH_stefan_abs)); +// } +// if (GNUNET_OK != +// TALER_config_get_amount (TEH_cfg, +// "donau", +// "STEFAN_LOG", +// &TEH_stefan_log)) +// { +// GNUNET_assert (GNUNET_OK == +// TALER_amount_set_zero (TEH_currency, +// &TEH_stefan_log)); +// } +// if (GNUNET_OK != +// TALER_config_get_amount (TEH_cfg, +// "donau", +// "STEFAN_LIN", +// &TEH_stefan_lin)) +// { +// GNUNET_assert (GNUNET_OK == +// TALER_amount_set_zero (TEH_currency, +// &TEH_stefan_lin)); +// } + +// if (0 != strcmp (TEH_currency, +// TEH_aml_threshold.currency)) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Amount in section `donau' under `AML_THRESHOLD' uses the wrong currency!\n"); +// return GNUNET_SYSERR; +// } +// TEH_enable_rewards +// = GNUNET_CONFIGURATION_get_value_yesno ( +// TEH_cfg, +// "donau", +// "ENABLE_REWARDS"); +// if (GNUNET_SYSERR == TEH_enable_rewards) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Need YES or NO in section `donau' under `ENABLE_REWARDS'\n"); +// return GNUNET_SYSERR; +// } +// if (GNUNET_OK != +// GNUNET_CONFIGURATION_get_value_string (TEH_cfg, +// "donau", +// "BASE_URL", +// &TEH_base_url)) +// { +// GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, +// "donau", +// "BASE_URL"); +// return GNUNET_SYSERR; +// } +// if (! TALER_url_valid_charset (TEH_base_url)) +// { +// GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, +// "donau", +// "BASE_URL", +// "invalid URL"); +// return GNUNET_SYSERR; +// } + +// { +// char *master_public_key_str; + +// if (GNUNET_OK != +// GNUNET_CONFIGURATION_get_value_string (TEH_cfg, +// "donau", +// "MASTER_PUBLIC_KEY", +// &master_public_key_str)) +// { +// GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, +// "donau", +// "MASTER_PUBLIC_KEY"); +// return GNUNET_SYSERR; +// } +// if (GNUNET_OK != +// GNUNET_CRYPTO_eddsa_public_key_from_string (master_public_key_str, +// strlen ( +// master_public_key_str), +// &TEH_master_public_key. +// eddsa_pub)) +// { +// GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, +// "donau", +// "MASTER_PUBLIC_KEY", +// "invalid base32 encoding for a master public key"); +// GNUNET_free (master_public_key_str); +// return GNUNET_SYSERR; +// } +// GNUNET_log (GNUNET_ERROR_TYPE_INFO, +// "Launching donau with public key `%s'...\n", +// master_public_key_str); +// GNUNET_free (master_public_key_str); +// } + +// { +// char *attr_enc_key_str; + +// if (GNUNET_OK != +// GNUNET_CONFIGURATION_get_value_string (TEH_cfg, +// "donau", +// "ATTRIBUTE_ENCRYPTION_KEY", +// &attr_enc_key_str)) +// { +// GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, +// "donau", +// "ATTRIBUTE_ENCRYPTION_KEY"); +// return GNUNET_SYSERR; +// } +// GNUNET_CRYPTO_hash (attr_enc_key_str, +// strlen (attr_enc_key_str), +// &TEH_attribute_key.hash); +// GNUNET_free (attr_enc_key_str); +// } + +// for (unsigned int i = 0; i<MAX_DB_RETRIES; i++) +// { +// TEH_plugin = DONAUDB_plugin_load (TEH_cfg); +// if (NULL != TEH_plugin) +// break; +// GNUNET_log (GNUNET_ERROR_TYPE_WARNING, +// "Failed to connect to DB, will try again %u times\n", +// MAX_DB_RETRIES - i); +// sleep (1); +// } +// if (NULL == TEH_plugin) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Failed to initialize DB subsystem. Giving up.\n"); +// return GNUNET_SYSERR; +// } +// return GNUNET_OK; +// } + + +// /** +// * Called when the main thread exits, writes out performance +// * stats if requested. +// */ +// static void +// write_stats (void) +// { +// struct GNUNET_DISK_FileHandle *fh; +// pid_t pid = getpid (); +// char *benchmark_dir; +// char *s; +// struct rusage usage; + +// benchmark_dir = getenv ("GNUNET_BENCHMARK_DIR"); +// if (NULL == benchmark_dir) +// return; +// GNUNET_asprintf (&s, +// "%s/taler-donau-%llu.txt", +// benchmark_dir, +// (unsigned long long) pid); +// fh = GNUNET_DISK_file_open (s, +// (GNUNET_DISK_OPEN_WRITE +// | GNUNET_DISK_OPEN_TRUNCATE +// | GNUNET_DISK_OPEN_CREATE), +// (GNUNET_DISK_PERM_USER_READ +// | GNUNET_DISK_PERM_USER_WRITE)); +// GNUNET_free (s); +// if (NULL == fh) +// return; /* permission denied? */ + +// /* Collect stats, summed up for all threads */ +// GNUNET_assert (0 == +// getrusage (RUSAGE_SELF, +// &usage)); +// GNUNET_asprintf (&s, +// "time_donau sys %llu user %llu\n", +// (unsigned long long) (usage.ru_stime.tv_sec * 1000 * 1000 +// + usage.ru_stime.tv_usec), +// (unsigned long long) (usage.ru_utime.tv_sec * 1000 * 1000 +// + usage.ru_utime.tv_usec)); +// GNUNET_assert (GNUNET_SYSERR != +// GNUNET_DISK_file_write_blocking (fh, +// s, +// strlen (s))); +// GNUNET_free (s); +// GNUNET_assert (GNUNET_OK == +// GNUNET_DISK_file_close (fh)); +// } + + +// /* Developer logic for supporting the `-f' option. */ +// #if HAVE_DEVELOPER /** * Option `-f' (specifies an input file to give to the HTTP server). @@ -1109,341 +1109,341 @@ write_stats (void) static char *input_filename; -/** - * Run 'nc' or 'ncat' as a fake HTTP client using #input_filename - * as the input for the request. If launching the client worked, - * run the #TEH_KS_loop() event loop as usual. - * - * @return child pid - */ -static pid_t -run_fake_client (void) -{ - pid_t cld; - char ports[6]; - int fd; - - if (0 == strcmp (input_filename, - "-")) - fd = STDIN_FILENO; - else - fd = open (input_filename, - O_RDONLY); - if (-1 == fd) - { - fprintf (stderr, - "Failed to open `%s': %s\n", - input_filename, - strerror (errno)); - return -1; - } - /* Fake HTTP client request with #input_filename as input. - We do this using the nc tool. */ - GNUNET_snprintf (ports, - sizeof (ports), - "%u", - serve_port); - if (0 == (cld = fork ())) - { - GNUNET_break (0 == close (0)); - GNUNET_break (0 == dup2 (fd, 0)); - GNUNET_break (0 == close (fd)); - if ( (0 != execlp ("nc", - "nc", - "localhost", - ports, - "-w", "30", - NULL)) && - (0 != execlp ("ncat", - "ncat", - "localhost", - ports, - "-i", "30", - NULL)) ) - { - fprintf (stderr, - "Failed to run both `nc' and `ncat': %s\n", - strerror (errno)); - } - _exit (1); - } - /* parent process */ - if (0 != strcmp (input_filename, - "-")) - GNUNET_break (0 == close (fd)); - return cld; -} +// /** +// * Run 'nc' or 'ncat' as a fake HTTP client using #input_filename +// * as the input for the request. If launching the client worked, +// * run the #TEH_KS_loop() event loop as usual. +// * +// * @return child pid +// */ +// static pid_t +// run_fake_client (void) +// { +// pid_t cld; +// char ports[6]; +// int fd; + +// if (0 == strcmp (input_filename, +// "-")) +// fd = STDIN_FILENO; +// else +// fd = open (input_filename, +// O_RDONLY); +// if (-1 == fd) +// { +// fprintf (stderr, +// "Failed to open `%s': %s\n", +// input_filename, +// strerror (errno)); +// return -1; +// } +// /* Fake HTTP client request with #input_filename as input. +// We do this using the nc tool. */ +// GNUNET_snprintf (ports, +// sizeof (ports), +// "%u", +// serve_port); +// if (0 == (cld = fork ())) +// { +// GNUNET_break (0 == close (0)); +// GNUNET_break (0 == dup2 (fd, 0)); +// GNUNET_break (0 == close (fd)); +// if ( (0 != execlp ("nc", +// "nc", +// "localhost", +// ports, +// "-w", "30", +// NULL)) && +// (0 != execlp ("ncat", +// "ncat", +// "localhost", +// ports, +// "-i", "30", +// NULL)) ) +// { +// fprintf (stderr, +// "Failed to run both `nc' and `ncat': %s\n", +// strerror (errno)); +// } +// _exit (1); +// } +// /* parent process */ +// if (0 != strcmp (input_filename, +// "-")) +// GNUNET_break (0 == close (fd)); +// return cld; +// } -/** - * Run the donau to serve a single request only, without threads. - * - * @return #GNUNET_OK on success - */ -static void -run_single_request (void) -{ - pid_t xfork; - - xfork = fork (); - if (-1 == xfork) - { - global_ret = EXIT_FAILURE; - GNUNET_SCHEDULER_shutdown (); - return; - } - if (0 == xfork) - { - pid_t cld; - - cld = run_fake_client (); - if (-1 == cld) - _exit (EXIT_FAILURE); - _exit (EXIT_SUCCESS); - } - - { - int status; - - if (xfork != waitpid (xfork, - &status, - 0)) - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Waiting for `nc' child failed: %s\n", - strerror (errno)); - } -} +// /** +// * Run the donau to serve a single request only, without threads. +// * +// * @return #GNUNET_OK on success +// */ +// static void +// run_single_request (void) +// { +// pid_t xfork; +// xfork = fork (); +// if (-1 == xfork) +// { +// global_ret = EXIT_FAILURE; +// GNUNET_SCHEDULER_shutdown (); +// return; +// } +// if (0 == xfork) +// { +// pid_t cld; -/* end of HAVE_DEVELOPER */ -#endif +// cld = run_fake_client (); +// if (-1 == cld) +// _exit (EXIT_FAILURE); +// _exit (EXIT_SUCCESS); +// } +// { +// int status; + +// if (xfork != waitpid (xfork, +// &status, +// 0)) +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Waiting for `nc' child failed: %s\n", +// strerror (errno)); +// } +// } -/** - * Signature of the callback used by MHD to notify the application - * about completed connections. If we are running in test-mode with - * an input_filename, this function is used to terminate the HTTPD - * after the first request has been processed. - * - * @param cls client-defined closure, NULL - * @param connection connection handle (ignored) - * @param socket_context socket-specific pointer (ignored) - * @param toe reason for connection notification - */ -static void -connection_done (void *cls, - struct MHD_Connection *connection, - void **socket_context, - enum MHD_ConnectionNotificationCode toe) -{ - (void) cls; - (void) connection; - (void) socket_context; - - switch (toe) - { - case MHD_CONNECTION_NOTIFY_STARTED: - active_connections++; - break; - case MHD_CONNECTION_NOTIFY_CLOSED: - active_connections--; - if (TEH_suicide && - (0 == active_connections) ) - GNUNET_SCHEDULER_shutdown (); - break; - } -#if HAVE_DEVELOPER - /* We only act if the connection is closed. */ - if (MHD_CONNECTION_NOTIFY_CLOSED != toe) - return; - if (NULL != input_filename) - GNUNET_SCHEDULER_shutdown (); -#endif -} +// /* end of HAVE_DEVELOPER */ +// #endif -/** - * Function run on shutdown. - * - * @param cls NULL - */ -static void -do_shutdown (void *cls) -{ - struct MHD_Daemon *mhd; - (void) cls; - - mhd = TALER_MHD_daemon_stop (); - TEH_resume_keys_requests (true); - TEH_deposits_get_cleanup (); - TEH_reserves_get_cleanup (); - TEH_purses_get_cleanup (); - TEH_kyc_check_cleanup (); - TEH_kyc_proof_cleanup (); - TALER_KYCLOGIC_kyc_done (); - if (NULL != mhd) - { - MHD_stop_daemon (mhd); - mhd = NULL; - } - TEH_wire_done (); - TEH_extensions_done (); - TEH_keys_finished (); - if (NULL != TEH_plugin) - { - DONAUDB_plugin_unload (TEH_plugin); - TEH_plugin = NULL; - } - if (NULL != TEH_curl_ctx) - { - GNUNET_CURL_fini (TEH_curl_ctx); - TEH_curl_ctx = NULL; - } - if (NULL != donau_curl_rc) - { - GNUNET_CURL_gnunet_rc_destroy (donau_curl_rc); - donau_curl_rc = NULL; - } - TALER_TEMPLATING_done (); -} +// /** +// * Signature of the callback used by MHD to notify the application +// * about completed connections. If we are running in test-mode with +// * an input_filename, this function is used to terminate the HTTPD +// * after the first request has been processed. +// * +// * @param cls client-defined closure, NULL +// * @param connection connection handle (ignored) +// * @param socket_context socket-specific pointer (ignored) +// * @param toe reason for connection notification +// */ +// static void +// connection_done (void *cls, +// struct MHD_Connection *connection, +// void **socket_context, +// enum MHD_ConnectionNotificationCode toe) +// { +// (void) cls; +// (void) connection; +// (void) socket_context; -/** - * Main function that will be run by the scheduler. - * - * @param cls closure - * @param args remaining command-line arguments - * @param cfgfile name of the configuration file used (for saving, can be - * NULL!) - * @param config configuration - */ -static void -run (void *cls, - char *const *args, - const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) -{ - enum TALER_MHD_GlobalOptions go; - int fh; - - (void) cls; - (void) args; - (void ) cfgfile; - go = TALER_MHD_GO_NONE; - if (connection_close) - go |= TALER_MHD_GO_FORCE_CONNECTION_CLOSE; - TALER_MHD_setup (go); - TEH_cfg = config; - - if (GNUNET_OK != - donau_serve_process_config ()) - { - global_ret = EXIT_NOTCONFIGURED; - GNUNET_SCHEDULER_shutdown (); - return; - } - if (GNUNET_OK != - TALER_TEMPLATING_init ("donau")) - { - global_ret = EXIT_FAILURE; - GNUNET_SCHEDULER_shutdown (); - return; - } - // if (GNUNET_SYSERR == - // TEH_plugin->preflight (TEH_plugin->cls)) - // { - // global_ret = EXIT_FAILURE; - // GNUNET_SCHEDULER_shutdown (); - // return; - // } - if (GNUNET_OK != - TEH_extensions_init ()) - { - global_ret = EXIT_FAILURE; - GNUNET_SCHEDULER_shutdown (); - return; - } - if (GNUNET_OK != - TEH_keys_init ()) - { - global_ret = EXIT_FAILURE; - GNUNET_SCHEDULER_shutdown (); - return; - } - if (GNUNET_OK != - TEH_wire_init ()) - { - global_ret = EXIT_FAILURE; - GNUNET_SCHEDULER_shutdown (); - return; - } - - TEH_load_terms (TEH_cfg); - TEH_curl_ctx - = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, - &donau_curl_rc); - if (NULL == TEH_curl_ctx) - { - GNUNET_break (0); - global_ret = EXIT_FAILURE; - GNUNET_SCHEDULER_shutdown (); - return; - } - donau_curl_rc = GNUNET_CURL_gnunet_rc_create (TEH_curl_ctx); - GNUNET_SCHEDULER_add_shutdown (&do_shutdown, - NULL); - fh = TALER_MHD_bind (TEH_cfg, - "donau", - &serve_port); - if ( (0 == serve_port) && - (-1 == fh) ) - { - GNUNET_SCHEDULER_shutdown (); - return; - } - mhd = MHD_start_daemon (MHD_USE_SUSPEND_RESUME - | MHD_USE_PIPE_FOR_SHUTDOWN - | MHD_USE_DEBUG | MHD_USE_DUAL_STACK - | MHD_USE_TCP_FASTOPEN, - (-1 == fh) ? serve_port : 0, - NULL, NULL, - &handle_mhd_request, NULL, - MHD_OPTION_LISTEN_BACKLOG_SIZE, - (unsigned int) 1024, - MHD_OPTION_LISTEN_SOCKET, - fh, - MHD_OPTION_EXTERNAL_LOGGER, - &TALER_MHD_handle_logs, - NULL, - MHD_OPTION_NOTIFY_COMPLETED, - &handle_mhd_completion_callback, - NULL, - MHD_OPTION_NOTIFY_CONNECTION, - &connection_done, - NULL, - MHD_OPTION_CONNECTION_TIMEOUT, - connection_timeout, - (0 == allow_address_reuse) - ? MHD_OPTION_END - : MHD_OPTION_LISTENING_ADDRESS_REUSE, - (unsigned int) allow_address_reuse, - MHD_OPTION_END); - if (NULL == mhd) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to launch HTTP service. Is the port in use?\n"); - GNUNET_SCHEDULER_shutdown (); - return; - } - global_ret = EXIT_SUCCESS; - TALER_MHD_daemon_start (mhd); - atexit (&write_stats); +// switch (toe) +// { +// case MHD_CONNECTION_NOTIFY_STARTED: +// active_connections++; +// break; +// case MHD_CONNECTION_NOTIFY_CLOSED: +// active_connections--; +// if (TEH_suicide && +// (0 == active_connections) ) +// GNUNET_SCHEDULER_shutdown (); +// break; +// } +// #if HAVE_DEVELOPER +// /* We only act if the connection is closed. */ +// if (MHD_CONNECTION_NOTIFY_CLOSED != toe) +// return; +// if (NULL != input_filename) +// GNUNET_SCHEDULER_shutdown (); +// #endif +// } -#if HAVE_DEVELOPER - if (NULL != input_filename) - run_single_request (); -#endif -} + +// /** +// * Function run on shutdown. +// * +// * @param cls NULL +// */ +// static void +// do_shutdown (void *cls) +// { +// struct MHD_Daemon *mhd; +// (void) cls; + +// mhd = TALER_MHD_daemon_stop (); +// TEH_resume_keys_requests (true); +// TEH_deposits_get_cleanup (); +// TEH_reserves_get_cleanup (); +// TEH_purses_get_cleanup (); +// TEH_kyc_check_cleanup (); +// TEH_kyc_proof_cleanup (); +// TALER_KYCLOGIC_kyc_done (); +// if (NULL != mhd) +// { +// MHD_stop_daemon (mhd); +// mhd = NULL; +// } +// TEH_wire_done (); +// TEH_extensions_done (); +// TEH_keys_finished (); +// if (NULL != TEH_plugin) +// { +// DONAUDB_plugin_unload (TEH_plugin); +// TEH_plugin = NULL; +// } +// if (NULL != TEH_curl_ctx) +// { +// GNUNET_CURL_fini (TEH_curl_ctx); +// TEH_curl_ctx = NULL; +// } +// if (NULL != donau_curl_rc) +// { +// GNUNET_CURL_gnunet_rc_destroy (donau_curl_rc); +// donau_curl_rc = NULL; +// } +// TALER_TEMPLATING_done (); +// } + + +// /** +// * Main function that will be run by the scheduler. +// * +// * @param cls closure +// * @param args remaining command-line arguments +// * @param cfgfile name of the configuration file used (for saving, can be +// * NULL!) +// * @param config configuration +// */ +// static void +// run (void *cls, +// char *const *args, +// const char *cfgfile, +// const struct GNUNET_CONFIGURATION_Handle *config) +// { +// enum TALER_MHD_GlobalOptions go; +// int fh; + +// (void) cls; +// (void) args; +// (void ) cfgfile; +// go = TALER_MHD_GO_NONE; +// if (connection_close) +// go |= TALER_MHD_GO_FORCE_CONNECTION_CLOSE; +// TALER_MHD_setup (go); +// TEH_cfg = config; + +// if (GNUNET_OK != +// donau_serve_process_config ()) +// { +// global_ret = EXIT_NOTCONFIGURED; +// GNUNET_SCHEDULER_shutdown (); +// return; +// } +// if (GNUNET_OK != +// TALER_TEMPLATING_init ("donau")) +// { +// global_ret = EXIT_FAILURE; +// GNUNET_SCHEDULER_shutdown (); +// return; +// } +// // if (GNUNET_SYSERR == +// // TEH_plugin->preflight (TEH_plugin->cls)) +// // { +// // global_ret = EXIT_FAILURE; +// // GNUNET_SCHEDULER_shutdown (); +// // return; +// // } +// if (GNUNET_OK != +// TEH_extensions_init ()) +// { +// global_ret = EXIT_FAILURE; +// GNUNET_SCHEDULER_shutdown (); +// return; +// } +// if (GNUNET_OK != +// TEH_keys_init ()) +// { +// global_ret = EXIT_FAILURE; +// GNUNET_SCHEDULER_shutdown (); +// return; +// } +// if (GNUNET_OK != +// TEH_wire_init ()) +// { +// global_ret = EXIT_FAILURE; +// GNUNET_SCHEDULER_shutdown (); +// return; +// } + +// TEH_load_terms (TEH_cfg); +// TEH_curl_ctx +// = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, +// &donau_curl_rc); +// if (NULL == TEH_curl_ctx) +// { +// GNUNET_break (0); +// global_ret = EXIT_FAILURE; +// GNUNET_SCHEDULER_shutdown (); +// return; +// } +// donau_curl_rc = GNUNET_CURL_gnunet_rc_create (TEH_curl_ctx); +// GNUNET_SCHEDULER_add_shutdown (&do_shutdown, +// NULL); +// fh = TALER_MHD_bind (TEH_cfg, +// "donau", +// &serve_port); +// if ( (0 == serve_port) && +// (-1 == fh) ) +// { +// GNUNET_SCHEDULER_shutdown (); +// return; +// } +// mhd = MHD_start_daemon (MHD_USE_SUSPEND_RESUME +// | MHD_USE_PIPE_FOR_SHUTDOWN +// | MHD_USE_DEBUG | MHD_USE_DUAL_STACK +// | MHD_USE_TCP_FASTOPEN, +// (-1 == fh) ? serve_port : 0, +// NULL, NULL, +// &handle_mhd_request, NULL, +// MHD_OPTION_LISTEN_BACKLOG_SIZE, +// (unsigned int) 1024, +// MHD_OPTION_LISTEN_SOCKET, +// fh, +// MHD_OPTION_EXTERNAL_LOGGER, +// &TALER_MHD_handle_logs, +// NULL, +// MHD_OPTION_NOTIFY_COMPLETED, +// &handle_mhd_completion_callback, +// NULL, +// MHD_OPTION_NOTIFY_CONNECTION, +// &connection_done, +// NULL, +// MHD_OPTION_CONNECTION_TIMEOUT, +// connection_timeout, +// (0 == allow_address_reuse) +// ? MHD_OPTION_END +// : MHD_OPTION_LISTENING_ADDRESS_REUSE, +// (unsigned int) allow_address_reuse, +// MHD_OPTION_END); +// if (NULL == mhd) +// { +// GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +// "Failed to launch HTTP service. Is the port in use?\n"); +// GNUNET_SCHEDULER_shutdown (); +// return; +// } +// global_ret = EXIT_SUCCESS; +// TALER_MHD_daemon_start (mhd); +// atexit (&write_stats); + +// #if HAVE_DEVELOPER +// if (NULL != input_filename) +// run_single_request (); +// #endif +// } /** @@ -1458,18 +1458,10 @@ main (int argc, char *const *argv) { const struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_option_flag ('a', - "allow-timetravel", - "allow clients to request /keys for arbitrary timestamps (for testing and development only)", - &TEH_allow_keys_timetravel), GNUNET_GETOPT_option_flag ('C', "connection-close", "force HTTP connections to be closed after each request", &connection_close), - GNUNET_GETOPT_option_flag ('I', - "check-invariants", - "enable expensive invariant checks", - &TEH_check_invariants_flag), GNUNET_GETOPT_option_flag ('r', "allow-reuse-address", "allow multiple HTTPDs to listen to the same port", @@ -1494,18 +1486,19 @@ main (int argc, }; enum GNUNET_GenericReturnValue ret; - TALER_OS_init (); - ret = GNUNET_PROGRAM_run (argc, argv, - "taler-donau-httpd", - "Taler donau HTTP service", - options, - &run, NULL); + // TALER_OS_init (); + // ret = GNUNET_PROGRAM_run (argc, argv, + // "taler-donau-httpd", + // "Taler donau HTTP service", + // options, + // &run, NULL); if (GNUNET_SYSERR == ret) return EXIT_INVALIDARGUMENT; if (GNUNET_NO == ret) return EXIT_SUCCESS; - return global_ret; + // return global_ret; + return -1; } -/* end of taler-donau-httpd.c */ +/* end of taler-donau-httpd.c */ +\ No newline at end of file diff --git a/src/donau/donau-httpd_keys.h b/src/donau/donau-httpd_keys.h @@ -21,7 +21,7 @@ #include "taler/platform.h" #include "taler/taler_json_lib.h" #include "taler/taler_mhd_lib.h" -#include "taler-donau-httpd_responses.h" +#include "donau-httpd_responses.h" #ifndef DONAU_HTTPD_KEYS_H @@ -33,427 +33,161 @@ struct TEH_AuditorSignature; -/** - * @brief All information about a denomination key (which is used to - * sign coins into existence). - */ -struct TEH_DenominationKey -{ - - /** - * Decoded denomination public key (the hash of it is in - * @e issue, but we sometimes need the full public key as well). - */ - struct TALER_DenominationPublicKey denom_pub; - - /** - * Hash code of the denomination public key. - */ - struct TALER_DenominationHashP h_denom_pub; - - /** - * Meta data about the type of the denomination, such as fees and validity - * periods. - */ - struct DONAUDB_DenominationKeyMetaData meta; - - /** - * The long-term offline master key's signature for this denomination. - * Signs over @e h_denom_pub and @e meta. - */ - struct TALER_MasterSignatureP master_sig; - - /** - * We store the auditor signatures for this denomination in a DLL. - */ - struct TEH_AuditorSignature *as_head; - - /** - * We store the auditor signatures for this denomination in a DLL. - */ - struct TEH_AuditorSignature *as_tail; - - /** - * Set to 'true' if this denomination has been revoked and recoup is - * thus supported right now. - */ - bool recoup_possible; - -}; - - -/** - * Set of global fees (and options) for a time range. - */ -struct TEH_GlobalFee -{ - /** - * Kept in a DLL. - */ - struct TEH_GlobalFee *next; - - /** - * Kept in a DLL. - */ - struct TEH_GlobalFee *prev; - - /** - * Beginning of the validity period (inclusive). - */ - struct GNUNET_TIME_Timestamp start_date; - - /** - * End of the validity period (exclusive). - */ - struct GNUNET_TIME_Timestamp end_date; - - /** - * How long do unmerged purses stay around at most? - */ - struct GNUNET_TIME_Relative purse_timeout; - - /** - * What is the longest history we return? - */ - struct GNUNET_TIME_Relative history_expiration; - - /** - * Signature affirming these details. - */ - struct TALER_MasterSignatureP master_sig; - - /** - * Fee structure for operations that do not depend - * on a denomination or wire method. - */ - struct TALER_GlobalFeeSet fees; - - /** - * Number of free purses per account. - */ - uint32_t purse_account_limit; -}; - - -/** - * Snapshot of the (coin and signing) keys (including private keys) of - * the donau. There can be multiple instances of this struct, as it is - * reference counted and only destroyed once the last user is done - * with it. The current instance is acquired using - * #TEH_KS_acquire(). Using this function increases the - * reference count. The contents of this structure (except for the - * reference counter) should be considered READ-ONLY until it is - * ultimately destroyed (as there can be many concurrent users). - */ -struct TEH_KeyStateHandle; - - -/** - * Run internal invariant checks. For debugging. - */ -void -TEH_check_invariants (void); - -/** - * Clean up wire subsystem. - */ -void -TEH_wire_done (void); - - -/** - * Look up wire fee structure by @a ts. - * - * @param ts timestamp to lookup wire fees at - * @param method wire method to lookup fees for - * @return the wire fee details, or - * NULL if none are configured for @a ts and @a method - */ -const struct TALER_WireFeeSet * -TEH_wire_fees_by_time ( - struct GNUNET_TIME_Timestamp ts, - const char *method); - - -/** - * Initialize wire subsystem. - * - * @return #GNUNET_OK on success - */ -enum GNUNET_GenericReturnValue -TEH_wire_init (void); - - -/** - * Something changed in the database. Rebuild the wire replies. This function - * should be called if the donau learns about a new signature from our - * master key. - * - * (We do not do so immediately, but merely signal to all threads that they - * need to rebuild their wire state upon the next call to - * #TEH_keys_get_state()). - */ -void -TEH_wire_update_state (void); - - -/** - * Return the current key state for this thread. Possibly re-builds the key - * state if we have reason to believe that something changed. - * - * The result is ONLY valid until the next call to - * #TEH_keys_denomination_by_hash() or #TEH_keys_get_state() - * or #TEH_keys_donau_sign(). - * - * @return NULL on error - */ -struct TEH_KeyStateHandle * -TEH_keys_get_state (void); - -/** - * Obtain the key state if we should NOT run finish_keys_response() because we - * only need the state for the /management/keys API - */ -struct TEH_KeyStateHandle * -TEH_keys_get_state_for_management_only (void); - -/** - * Something changed in the database. Rebuild all key states. This function - * should be called if the donau learns about a new signature from an - * auditor or our master key. - * - * (We do not do so immediately, but merely signal to all threads that they - * need to rebuild their key state upon the next call to - * #TEH_keys_get_state()). - */ -void -TEH_keys_update_states (void); - - -/** - * Look up global fee structure by @a ts. - * - * @param ksh key state state to look in - * @param ts timestamp to lookup global fees at - * @return the global fee details, or - * NULL if none are configured for @a ts - */ -const struct TEH_GlobalFee * -TEH_keys_global_fee_by_time ( - struct TEH_KeyStateHandle *ksh, - struct GNUNET_TIME_Timestamp ts); - - -/** - * Look up the issue for a denom public key. Note that the result - * must only be used in this thread and only until another key or - * key state is resolved. - * - * @param h_denom_pub hash of denomination public key - * @param[in,out] conn used to return status message if NULL is returned - * @param[out] mret set to the MHD status if NULL is returned - * @return the denomination key issue, - * or NULL if @a h_denom_pub could not be found - */ -struct TEH_DenominationKey * -TEH_keys_denomination_by_hash ( - const struct TALER_DenominationHashP *h_denom_pub, - struct MHD_Connection *conn, - MHD_RESULT *mret); - - -/** - * Look up the issue for a denom public key using a given @a ksh. This allows - * requesting multiple denominations with the same @a ksh which thus will - * remain valid until the next call to #TEH_keys_denomination_by_hash() or - * #TEH_keys_get_state() or #TEH_keys_donau_sign(). - * - * @param ksh key state state to look in - * @param h_denom_pub hash of denomination public key - * @param[in,out] conn connection used to return status message if NULL is returned - * @param[out] mret set to the MHD status if NULL is returned - * @return the denomination key issue, - * or NULL if @a h_denom_pub could not be found - */ -struct TEH_DenominationKey * -TEH_keys_denomination_by_hash_from_state ( - const struct TEH_KeyStateHandle *ksh, - const struct TALER_DenominationHashP *h_denom_pub, - struct MHD_Connection *conn, - MHD_RESULT *mret); - -/** - * Information needed to create a blind signature. - */ -struct TEH_CoinSignData -{ - /** - * Hash of key to sign with. - */ - const struct TALER_DenominationHashP *h_denom_pub; - - /** - * Blinded planchet to sign over. - */ - const struct TALER_BlindedPlanchet *bp; -}; - - -/** - * Request to sign @a csd for melting. - * - * @param csd identifies data to blindly sign and key to sign with - * @param for_melt true if this is for a melt operation - * @param[out] bs set to the blind signature on success - * @return #TALER_EC_NONE on success - */ -enum TALER_ErrorCode -TEH_keys_denomination_sign ( - const struct TEH_CoinSignData *csd, - bool for_melt, - struct TALER_BlindedDenominationSignature *bs); - - -/** - * Request to sign @a csds for melting. - * - * @param csds array with data to blindly sign (and keys to sign with) - * @param csds_length length of @a csds array - * @param for_melt true if this is for a melt operation - * @param[out] bss array set to the blind signature on success; must be of length @a csds_length - * @return #TALER_EC_NONE on success - */ -enum TALER_ErrorCode -TEH_keys_denomination_batch_sign ( - const struct TEH_CoinSignData *csds, - unsigned int csds_length, - bool for_melt, - struct TALER_BlindedDenominationSignature *bss); - - -/** - * Information needed to derive the CS r_pub. - */ -struct TEH_CsDeriveData -{ - /** - * Hash of key to sign with. - */ - const struct TALER_DenominationHashP *h_denom_pub; - - /** - * Nonce to use. - */ - const struct TALER_CsNonce *nonce; -}; - - -/** - * Request to derive CS @a r_pub using the denomination and nonce from @a cdd. - * - * @param cdd data to compute @a r_pub from - * @param for_melt true if this is for a melt operation - * @param[out] r_pub where to write the result - * @return #TALER_EC_NONE on success - */ -enum TALER_ErrorCode -TEH_keys_denomination_cs_r_pub ( - const struct TEH_CsDeriveData *cdd, - bool for_melt, - struct TALER_DenominationCSPublicRPairP *r_pub); - - -/** - * Request to derive a bunch of CS @a r_pubs using the - * denominations and nonces from @a cdds. - * - * @param cdds array to compute @a r_pubs from - * @param cdds_length length of the @a cdds array - * @param for_melt true if this is for a melt operation - * @param[out] r_pubs array where to write the result; must be of length @a cdds_length - * @return #TALER_EC_NONE on success - */ -enum TALER_ErrorCode -TEH_keys_denomination_cs_batch_r_pub ( - const struct TEH_CsDeriveData *cdds, - unsigned int cdds_length, - bool for_melt, - struct TALER_DenominationCSPublicRPairP *r_pubs); - - -/** - * Revoke the public key associated with @a h_denom_pub. - * This function should be called AFTER the database was - * updated, as it also triggers #TEH_keys_update_states(). - * - * Note that the actual revocation happens asynchronously and - * may thus fail silently. To verify that the revocation succeeded, - * clients must watch for the associated change to the key state. - * - * @param h_denom_pub hash of the public key to revoke - */ -void -TEH_keys_denomination_revoke ( - const struct TALER_DenominationHashP *h_denom_pub); - - -/** - * Fully clean up keys subsystem. - */ -void -TEH_keys_finished (void); - - -/** - * Resumse all suspended /keys requests, we may now have key material - * (or are shutting down). - * - * @param do_shutdown are we shutting down? - */ -void -TEH_resume_keys_requests (bool do_shutdown); - - -/** - * Sign the message in @a purpose with the donau's signing key. - * - * The @a purpose data is the beginning of the data of which the signature is - * to be created. The `size` field in @a purpose must correctly indicate the - * number of bytes of the data structure, including its header. Use - * #TEH_keys_donau_sign() instead of calling this function directly! - * - * @param purpose the message to sign - * @param[out] pub set to the current public signing key of the donau - * @param[out] sig signature over purpose using current signing key - * @return #TALER_EC_NONE on success - */ -enum TALER_ErrorCode -TEH_keys_donau_sign_ ( - const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, - struct DONAU_DonauPublicKeyP *pub, - struct TALER_DonauSignatureP *sig); - - -/** - * Sign the message in @a purpose with the donau's signing key. - * - * The @a purpose data is the beginning of the data of which the signature is - * to be created. The `size` field in @a purpose must correctly indicate the - * number of bytes of the data structure, including its header. Use - * #TEH_keys_donau_sign() instead of calling this function directly! - * - * @param cls key state state to look in - * @param purpose the message to sign - * @param[out] pub set to the current public signing key of the donau - * @param[out] sig signature over purpose using current signing key - * @return #TALER_EC_NONE on success - */ -enum TALER_ErrorCode -TEH_keys_donau_sign2_ ( - void *cls, - const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, - struct DONAU_DonauPublicKeyP *pub, - struct TALER_DonauSignatureP *sig); +// /** +// * @brief All information about a denomination key (which is used to +// * sign coins into existence). +// */ +// struct TEH_DenominationKey +// { + +// /** +// * Decoded denomination public key (the hash of it is in +// * @e issue, but we sometimes need the full public key as well). +// */ +// struct TALER_DenominationPublicKey denom_pub; + +// /** +// * Hash code of the denomination public key. +// */ +// struct TALER_DenominationHashP h_denom_pub; + +// /** +// * Meta data about the type of the denomination, such as fees and validity +// * periods. +// */ +// struct DONAUDB_DenominationKeyMetaData meta; + +// /** +// * The long-term offline master key's signature for this denomination. +// * Signs over @e h_denom_pub and @e meta. +// */ +// struct TALER_MasterSignatureP master_sig; + +// /** +// * We store the auditor signatures for this denomination in a DLL. +// */ +// struct TEH_AuditorSignature *as_head; + +// /** +// * We store the auditor signatures for this denomination in a DLL. +// */ +// struct TEH_AuditorSignature *as_tail; + +// /** +// * Set to 'true' if this denomination has been revoked and recoup is +// * thus supported right now. +// */ +// bool recoup_possible; + +// }; + + +/** +// * Information needed to create a blind signature. +// */ +// struct TEH_CoinSignData +// { +// /** +// * Hash of key to sign with. +// */ +// const struct TALER_DenominationHashP *h_denom_pub; + +// /** +// * Blinded planchet to sign over. +// */ +// const struct TALER_BlindedPlanchet *bp; +// }; + + +// /** +// * Information needed to derive the CS r_pub. +// */ +// struct TEH_CsDeriveData +// { +// /** +// * Hash of key to sign with. +// */ +// const struct TALER_DenominationHashP *h_denom_pub; + +// /** +// * Nonce to use. +// */ +// const struct TALER_CsNonce *nonce; +// }; + + +// /** +// * Request to derive CS @a r_pub using the denomination and nonce from @a cdd. +// * +// * @param cdd data to compute @a r_pub from +// * @param for_melt true if this is for a melt operation +// * @param[out] r_pub where to write the result +// * @return #TALER_EC_NONE on success +// */ +// enum TALER_ErrorCode +// TEH_keys_denomination_cs_r_pub ( +// const struct TEH_CsDeriveData *cdd, +// bool for_melt, +// struct TALER_DenominationCSPublicRPairP *r_pub); + + +// /** +// * Request to derive a bunch of CS @a r_pubs using the +// * denominations and nonces from @a cdds. +// * +// * @param cdds array to compute @a r_pubs from +// * @param cdds_length length of the @a cdds array +// * @param for_melt true if this is for a melt operation +// * @param[out] r_pubs array where to write the result; must be of length @a cdds_length +// * @return #TALER_EC_NONE on success +// */ +// enum TALER_ErrorCode +// TEH_keys_denomination_cs_batch_r_pub ( +// const struct TEH_CsDeriveData *cdds, +// unsigned int cdds_length, +// bool for_melt, +// struct TALER_DenominationCSPublicRPairP *r_pubs); + +/** +// * Sign the message in @a purpose with the donau's signing key. +// * +// * The @a purpose data is the beginning of the data of which the signature is +// * to be created. The `size` field in @a purpose must correctly indicate the +// * number of bytes of the data structure, including its header. Use +// * #TEH_keys_donau_sign() instead of calling this function directly! +// * +// * @param purpose the message to sign +// * @param[out] pub set to the current public signing key of the donau +// * @param[out] sig signature over purpose using current signing key +// * @return #TALER_EC_NONE on success +// */ +// enum TALER_ErrorCode +// TEH_keys_donau_sign_ ( +// const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, +// struct DONAU_DonauPublicKeyP *pub, +// struct TALER_DonauSignatureP *sig); + + +// /** +// * Sign the message in @a purpose with the donau's signing key. +// * +// * The @a purpose data is the beginning of the data of which the signature is +// * to be created. The `size` field in @a purpose must correctly indicate the +// * number of bytes of the data structure, including its header. Use +// * #TEH_keys_donau_sign() instead of calling this function directly! +// * +// * @param cls key state state to look in +// * @param purpose the message to sign +// * @param[out] pub set to the current public signing key of the donau +// * @param[out] sig signature over purpose using current signing key +// * @return #TALER_EC_NONE on success +// */ +// enum TALER_ErrorCode +// TEH_keys_donau_sign2_ ( +// void *cls, +// const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, +// struct DONAU_DonauPublicKeyP *pub, +// struct TALER_DonauSignatureP *sig); /** @@ -518,21 +252,6 @@ TEH_keys_donau_sign2_ ( /** - * Revoke the given donau's signing key. - * This function should be called AFTER the database was - * updated, as it also triggers #TEH_keys_update_states(). - * - * Note that the actual revocation happens asynchronously and - * may thus fail silently. To verify that the revocation succeeded, - * clients must watch for the associated change to the key state. - * - * @param donau_pub key to revoke - */ -void -TEH_keys_donau_revoke (const struct DONAU_DonauPublicKeyP *donau_pub); - - -/** * Function to call to handle requests to "/keys" by sending * back our current key material. * @@ -546,51 +265,6 @@ TEH_keys_get_handler (struct TEH_RequestContext *rc, /** - * Function to call to handle requests to "/management/keys" by sending - * back our future key material. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @return MHD result code - */ -MHD_RESULT -TEH_keys_management_get_keys_handler (const struct TEH_RequestHandler *rh, - struct MHD_Connection *connection); - - -/** - * Load fees and expiration times (!) for the denomination type configured for - * the denomination matching @a h_denom_pub. - * - * @param ksh key state to load fees from - * @param h_denom_pub hash of the denomination public key - * to use to derive the section name of the configuration to use - * @param[out] denom_pub set to the denomination public key (to be freed by caller!) - * @param[out] meta denomination type data to complete - * @return #GNUNET_OK on success, - * #GNUNET_NO if @a h_denom_pub is not known - * #GNUNET_SYSERR on hard errors - */ -enum GNUNET_GenericReturnValue -TEH_keys_load_fees (struct TEH_KeyStateHandle *ksh, - const struct TALER_DenominationHashP *h_denom_pub, - struct TALER_DenominationPublicKey *denom_pub, - struct DONAUDB_DenominationKeyMetaData *meta); - - -/** - * Load expiration times for the given onling signing key. - * - * @param donau_pub the online signing key - * @param[out] meta set to meta data about the key - * @return #GNUNET_OK on success - */ -enum GNUNET_GenericReturnValue -TEH_keys_get_timing (const struct DONAU_DonauPublicKeyP *donau_pub, - struct DONAUDB_SignkeyMetaData *meta); - - -/** * Initialize keys subsystem. * * @return #GNUNET_OK on success diff --git a/src/donau/donau-httpd_responses.c b/src/donau/donau-httpd_responses.c @@ -25,1166 +25,536 @@ #include "taler/platform.h" #include <microhttpd.h> #include <zlib.h> -#include "taler-donau-httpd_responses.h" +#include "donau-httpd_responses.h" #include "taler_util.h" #include "taler/taler_json_lib.h" #include "taler/taler_mhd_lib.h" -#include "taler-donau-httpd_keys.h" - - -/** - * Compile the transaction history of a coin into a JSON object. - * - * @param coin_pub public key of the coin - * @param tl transaction history to JSON-ify - * @return json representation of the @a rh, NULL on error - */ -json_t * -TEH_RESPONSE_compile_transaction_history ( - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct DONAUDB_TransactionList *tl) -{ - json_t *history; - - history = json_array (); - if (NULL == history) - { - GNUNET_break (0); /* out of memory!? */ - return NULL; - } - for (const struct DONAUDB_TransactionList *pos = tl; - NULL != pos; - pos = pos->next) - { - switch (pos->type) - { - case DONAUDB_TT_DEPOSIT: - { - const struct DONAUDB_DepositListEntry *deposit = - pos->details.deposit; - struct TALER_CharityWireHashP h_wire; - - TALER_charity_wire_signature_hash (deposit->receiver_wire_account, - &deposit->wire_salt, - &h_wire); -#if ENABLE_SANITY_CHECKS - /* internal sanity check before we hand out a bogus sig... */ - TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++; - if (GNUNET_OK != - TALER_wallet_deposit_verify ( - &deposit->amount_with_fee, - &deposit->deposit_fee, - &h_wire, - &deposit->h_contract_terms, - deposit->no_wallet_data_hash - ? NULL - : &deposit->wallet_data_hash, - deposit->no_age_commitment - ? NULL - : &deposit->h_age_commitment, - &deposit->h_policy, - &deposit->h_denom_pub, - deposit->timestamp, - &deposit->charity_pub, - deposit->refund_deadline, - coin_pub, - &deposit->csig)) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } -#endif - if (0 != - json_array_append_new ( - history, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "DEPOSIT"), - TALER_JSON_pack_amount ("amount", - &deposit->amount_with_fee), - TALER_JSON_pack_amount ("deposit_fee", - &deposit->deposit_fee), - GNUNET_JSON_pack_timestamp ("timestamp", - deposit->timestamp), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_timestamp ("refund_deadline", - deposit->refund_deadline)), - GNUNET_JSON_pack_data_auto ("charity_pub", - &deposit->charity_pub), - GNUNET_JSON_pack_data_auto ("h_contract_terms", - &deposit->h_contract_terms), - GNUNET_JSON_pack_data_auto ("h_wire", - &h_wire), - GNUNET_JSON_pack_allow_null ( - deposit->no_age_commitment ? - GNUNET_JSON_pack_string ( - "h_age_commitment", NULL) : - GNUNET_JSON_pack_data_auto ("h_age_commitment", - &deposit->h_age_commitment)), - GNUNET_JSON_pack_data_auto ("coin_sig", - &deposit->csig)))) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } - break; - } - case DONAUDB_TT_MELT: - { - const struct DONAUDB_MeltListEntry *melt = - pos->details.melt; - const struct TALER_AgeCommitmentHash *phac = NULL; - -#if ENABLE_SANITY_CHECKS - TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++; - if (GNUNET_OK != - TALER_wallet_melt_verify ( - &melt->amount_with_fee, - &melt->melt_fee, - &melt->rc, - &melt->h_denom_pub, - &melt->h_age_commitment, - coin_pub, - &melt->coin_sig)) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } -#endif - - /* Age restriction is optional. We communicate a NULL value to - * JSON_PACK below */ - if (! melt->no_age_commitment) - phac = &melt->h_age_commitment; - - if (0 != - json_array_append_new ( - history, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "MELT"), - TALER_JSON_pack_amount ("amount", - &melt->amount_with_fee), - TALER_JSON_pack_amount ("melt_fee", - &melt->melt_fee), - GNUNET_JSON_pack_data_auto ("rc", - &melt->rc), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_data_auto ("h_age_commitment", - phac)), - GNUNET_JSON_pack_data_auto ("coin_sig", - &melt->coin_sig)))) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } - } - break; - case DONAUDB_TT_REFUND: - { - const struct DONAUDB_RefundListEntry *refund = - pos->details.refund; - struct TALER_Amount value; - -#if ENABLE_SANITY_CHECKS - TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++; - if (GNUNET_OK != - TALER_charity_refund_verify ( - coin_pub, - &refund->h_contract_terms, - refund->rtransaction_id, - &refund->refund_amount, - &refund->charity_pub, - &refund->charity_sig)) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } -#endif - if (0 > - TALER_amount_subtract (&value, - &refund->refund_amount, - &refund->refund_fee)) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } - if (0 != - json_array_append_new ( - history, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "REFUND"), - TALER_JSON_pack_amount ("amount", - &value), - TALER_JSON_pack_amount ("refund_fee", - &refund->refund_fee), - GNUNET_JSON_pack_data_auto ("h_contract_terms", - &refund->h_contract_terms), - GNUNET_JSON_pack_data_auto ("charity_pub", - &refund->charity_pub), - GNUNET_JSON_pack_uint64 ("rtransaction_id", - refund->rtransaction_id), - GNUNET_JSON_pack_data_auto ("charity_sig", - &refund->charity_sig)))) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } - } - break; - case DONAUDB_TT_OLD_COIN_RECOUP: - { - struct DONAUDB_RecoupRefreshListEntry *pr = - pos->details.old_coin_recoup; - struct DONAU_DonauPublicKeyP epub; - struct TALER_DonauSignatureP esig; - - if (TALER_EC_NONE != - TALER_donau_online_confirm_recoup_refresh_sign ( - &TEH_keys_donau_sign_, - pr->timestamp, - &pr->value, - &pr->coin.coin_pub, - &pr->old_coin_pub, - &epub, - &esig)) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } - /* NOTE: we could also provide coin_pub's coin_sig, denomination key hash and - the denomination key's RSA signature over coin_pub, but as the - wallet should really already have this information (and cannot - check or do anything with it anyway if it doesn't), it seems - strictly unnecessary. */ - if (0 != - json_array_append_new ( - history, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "OLD-COIN-RECOUP"), - TALER_JSON_pack_amount ("amount", - &pr->value), - GNUNET_JSON_pack_data_auto ("donau_sig", - &esig), - GNUNET_JSON_pack_data_auto ("donau_pub", - &epub), - GNUNET_JSON_pack_data_auto ("coin_pub", - &pr->coin.coin_pub), - GNUNET_JSON_pack_timestamp ("timestamp", - pr->timestamp)))) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } - break; - } - case DONAUDB_TT_RECOUP: - { - const struct DONAUDB_RecoupListEntry *recoup = - pos->details.recoup; - struct DONAU_DonauPublicKeyP epub; - struct TALER_DonauSignatureP esig; - - if (TALER_EC_NONE != - TALER_donau_online_confirm_recoup_sign ( - &TEH_keys_donau_sign_, - recoup->timestamp, - &recoup->value, - coin_pub, - &recoup->reserve_pub, - &epub, - &esig)) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } - if (0 != - json_array_append_new ( - history, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "RECOUP"), - TALER_JSON_pack_amount ("amount", - &recoup->value), - GNUNET_JSON_pack_data_auto ("donau_sig", - &esig), - GNUNET_JSON_pack_data_auto ("donau_pub", - &epub), - GNUNET_JSON_pack_data_auto ("reserve_pub", - &recoup->reserve_pub), - GNUNET_JSON_pack_data_auto ("coin_sig", - &recoup->coin_sig), - GNUNET_JSON_pack_data_auto ("coin_blind", - &recoup->coin_blind), - GNUNET_JSON_pack_data_auto ("reserve_pub", - &recoup->reserve_pub), - GNUNET_JSON_pack_timestamp ("timestamp", - recoup->timestamp)))) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } - } - break; - case DONAUDB_TT_RECOUP_REFRESH: - { - struct DONAUDB_RecoupRefreshListEntry *pr = - pos->details.recoup_refresh; - struct DONAU_DonauPublicKeyP epub; - struct TALER_DonauSignatureP esig; - - if (TALER_EC_NONE != - TALER_donau_online_confirm_recoup_refresh_sign ( - &TEH_keys_donau_sign_, - pr->timestamp, - &pr->value, - coin_pub, - &pr->old_coin_pub, - &epub, - &esig)) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } - /* NOTE: we could also provide coin_pub's coin_sig, denomination key - hash and the denomination key's RSA signature over coin_pub, but as - the wallet should really already have this information (and cannot - check or do anything with it anyway if it doesn't), it seems - strictly unnecessary. */ - if (0 != - json_array_append_new ( - history, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "RECOUP-REFRESH"), - TALER_JSON_pack_amount ("amount", - &pr->value), - GNUNET_JSON_pack_data_auto ("donau_sig", - &esig), - GNUNET_JSON_pack_data_auto ("donau_pub", - &epub), - GNUNET_JSON_pack_data_auto ("old_coin_pub", - &pr->old_coin_pub), - GNUNET_JSON_pack_data_auto ("coin_sig", - &pr->coin_sig), - GNUNET_JSON_pack_data_auto ("coin_blind", - &pr->coin_blind), - GNUNET_JSON_pack_timestamp ("timestamp", - pr->timestamp)))) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } - break; - } - - case DONAUDB_TT_PURSE_DEPOSIT: - { - struct DONAUDB_PurseDepositListEntry *pd - = pos->details.purse_deposit; - const struct TALER_AgeCommitmentHash *phac = NULL; - - if (! pd->no_age_commitment) - phac = &pd->h_age_commitment; - - if (0 != - json_array_append_new ( - history, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "PURSE-DEPOSIT"), - TALER_JSON_pack_amount ("amount", - &pd->amount), - GNUNET_JSON_pack_string ("donau_base_url", - NULL == pd->donau_base_url - ? TEH_base_url - : pd->donau_base_url), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_data_auto ("h_age_commitment", - phac)), - GNUNET_JSON_pack_data_auto ("purse_pub", - &pd->purse_pub), - GNUNET_JSON_pack_bool ("refunded", - pd->refunded), - GNUNET_JSON_pack_data_auto ("coin_sig", - &pd->coin_sig)))) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } - break; - } - - case DONAUDB_TT_PURSE_REFUND: - { - const struct DONAUDB_PurseRefundListEntry *prefund = - pos->details.purse_refund; - struct TALER_Amount value; - enum TALER_ErrorCode ec; - struct DONAU_DonauPublicKeyP epub; - struct TALER_DonauSignatureP esig; - - if (0 > - TALER_amount_subtract (&value, - &prefund->refund_amount, - &prefund->refund_fee)) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } - ec = TALER_donau_online_purse_refund_sign ( - &TEH_keys_donau_sign_, - &value, - &prefund->refund_fee, - coin_pub, - &prefund->purse_pub, - &epub, - &esig); - if (TALER_EC_NONE != ec) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } - if (0 != - json_array_append_new ( - history, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "PURSE-REFUND"), - TALER_JSON_pack_amount ("amount", - &value), - TALER_JSON_pack_amount ("refund_fee", - &prefund->refund_fee), - GNUNET_JSON_pack_data_auto ("donau_sig", - &esig), - GNUNET_JSON_pack_data_auto ("donau_pub", - &epub), - GNUNET_JSON_pack_data_auto ("purse_pub", - &prefund->purse_pub)))) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } - } - break; - - case DONAUDB_TT_RESERVE_OPEN: - { - struct DONAUDB_ReserveOpenListEntry *role - = pos->details.reserve_open; - - if (0 != - json_array_append_new ( - history, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "RESERVE-OPEN-DEPOSIT"), - TALER_JSON_pack_amount ("coin_contribution", - &role->coin_contribution), - GNUNET_JSON_pack_data_auto ("reserve_sig", - &role->reserve_sig), - GNUNET_JSON_pack_data_auto ("coin_sig", - &role->coin_sig)))) - { - GNUNET_break (0); - json_decref (history); - return NULL; - } - break; - } - } - } - return history; -} - - -MHD_RESULT -TEH_RESPONSE_reply_unknown_denom_pub_hash ( - struct MHD_Connection *connection, - const struct TALER_DenominationHashP *dph) -{ - struct DONAU_DonauPublicKeyP epub; - struct TALER_DonauSignatureP esig; - struct GNUNET_TIME_Timestamp now; - enum TALER_ErrorCode ec; - - now = GNUNET_TIME_timestamp_get (); - ec = TALER_donau_online_denomination_unknown_sign ( - &TEH_keys_donau_sign_, - now, - dph, - &epub, - &esig); - if (TALER_EC_NONE != ec) - { - GNUNET_break (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - ec, - NULL); - } - return TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_NOT_FOUND, - TALER_JSON_pack_ec (TALER_EC_DONAU_GENERIC_DENOMINATION_KEY_UNKNOWN), - GNUNET_JSON_pack_timestamp ("timestamp", - now), - GNUNET_JSON_pack_data_auto ("donau_pub", - &epub), - GNUNET_JSON_pack_data_auto ("donau_sig", - &esig), - GNUNET_JSON_pack_data_auto ("h_denom_pub", - dph)); -} - - -MHD_RESULT -TEH_RESPONSE_reply_expired_denom_pub_hash ( - struct MHD_Connection *connection, - const struct TALER_DenominationHashP *dph, - enum TALER_ErrorCode ec, - const char *oper) -{ - struct DONAU_DonauPublicKeyP epub; - struct TALER_DonauSignatureP esig; - enum TALER_ErrorCode ecr; - struct GNUNET_TIME_Timestamp now - = GNUNET_TIME_timestamp_get (); - - ecr = TALER_donau_online_denomination_expired_sign ( - &TEH_keys_donau_sign_, - now, - dph, - oper, - &epub, - &esig); - if (TALER_EC_NONE != ecr) - { - GNUNET_break (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - ec, - NULL); - } - return TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_GONE, - TALER_JSON_pack_ec (ec), - GNUNET_JSON_pack_string ("oper", - oper), - GNUNET_JSON_pack_timestamp ("timestamp", - now), - GNUNET_JSON_pack_data_auto ("donau_pub", - &epub), - GNUNET_JSON_pack_data_auto ("donau_sig", - &esig), - GNUNET_JSON_pack_data_auto ("h_denom_pub", - dph)); -} - - -MHD_RESULT -TEH_RESPONSE_reply_invalid_denom_cipher_for_operation ( - struct MHD_Connection *connection, - const struct TALER_DenominationHashP *dph) -{ - struct DONAU_DonauPublicKeyP epub; - struct TALER_DonauSignatureP esig; - struct GNUNET_TIME_Timestamp now; - enum TALER_ErrorCode ec; - - now = GNUNET_TIME_timestamp_get (); - ec = TALER_donau_online_denomination_unknown_sign ( - &TEH_keys_donau_sign_, - now, - dph, - &epub, - &esig); - if (TALER_EC_NONE != ec) - { - GNUNET_break (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - ec, - NULL); - } - return TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_NOT_FOUND, - TALER_JSON_pack_ec ( - TALER_EC_DONAU_GENERIC_INVALID_DENOMINATION_CIPHER_FOR_OPERATION), - GNUNET_JSON_pack_timestamp ("timestamp", - now), - GNUNET_JSON_pack_data_auto ("donau_pub", - &epub), - GNUNET_JSON_pack_data_auto ("donau_sig", - &esig), - GNUNET_JSON_pack_data_auto ("h_denom_pub", - dph)); -} - - -MHD_RESULT -TEH_RESPONSE_reply_coin_insufficient_funds ( - struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const struct TALER_DenominationHashP *h_denom_pub, - const struct TALER_CoinSpendPublicKeyP *coin_pub) -{ - struct DONAUDB_TransactionList *tl; - enum GNUNET_DB_QueryStatus qs; - json_t *history; - - TEH_plugin->rollback (TEH_plugin->cls); - if (GNUNET_OK != - TEH_plugin->start_read_only (TEH_plugin->cls, - "get_coin_transactions")) - { - return TALER_MHD_reply_with_error ( - connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_START_FAILED, - NULL); - } - qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls, - coin_pub, - &tl); - TEH_plugin->rollback (TEH_plugin->cls); - if (0 > qs) - { - return TALER_MHD_reply_with_error ( - connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_FETCH_FAILED, - NULL); - } - - history = TEH_RESPONSE_compile_transaction_history (coin_pub, - tl); - TEH_plugin->free_coin_transaction_list (TEH_plugin->cls, - tl); - if (NULL == history) - { - GNUNET_break (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_JSON_ALLOCATION_FAILURE, - "Failed to generated proof of insufficient funds"); - } - return TALER_MHD_REPLY_JSON_PACK ( - connection, - TALER_ErrorCode_get_http_status_safe (ec), - TALER_JSON_pack_ec (ec), - GNUNET_JSON_pack_data_auto ("coin_pub", - coin_pub), - GNUNET_JSON_pack_data_auto ("h_denom_pub", - h_denom_pub), - GNUNET_JSON_pack_array_steal ("history", - history)); -} - - -json_t * -TEH_RESPONSE_compile_reserve_history ( - const struct DONAUDB_ReserveHistory *rh) -{ - json_t *json_history; - - json_history = json_array (); - GNUNET_assert (NULL != json_history); - for (const struct DONAUDB_ReserveHistory *pos = rh; - NULL != pos; - pos = pos->next) - { - switch (pos->type) - { - case DONAUDB_RO_BANK_TO_DONAU: - { - const struct DONAUDB_BankTransfer *bank = - pos->details.bank; - - if (0 != - json_array_append_new ( - json_history, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "CREDIT"), - GNUNET_JSON_pack_timestamp ("timestamp", - bank->execution_date), - GNUNET_JSON_pack_string ("sender_account_url", - bank->sender_account_details), - GNUNET_JSON_pack_uint64 ("wire_reference", - bank->wire_reference), - TALER_JSON_pack_amount ("amount", - &bank->amount)))) - { - GNUNET_break (0); - json_decref (json_history); - return NULL; - } - break; - } - case DONAUDB_RO_WITHDRAW_COIN: - { - const struct DONAUDB_CollectableBlindcoin *withdraw - = pos->details.withdraw; - - if (0 != - json_array_append_new ( - json_history, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "WITHDRAW"), - GNUNET_JSON_pack_data_auto ("reserve_sig", - &withdraw->reserve_sig), - GNUNET_JSON_pack_data_auto ("h_coin_envelope", - &withdraw->h_coin_envelope), - GNUNET_JSON_pack_data_auto ("h_denom_pub", - &withdraw->denom_pub_hash), - TALER_JSON_pack_amount ("withdraw_fee", - &withdraw->withdraw_fee), - TALER_JSON_pack_amount ("amount", - &withdraw->amount_with_fee)))) - { - GNUNET_break (0); - json_decref (json_history); - return NULL; - } - } - break; - case DONAUDB_RO_RECOUP_COIN: - { - const struct DONAUDB_Recoup *recoup - = pos->details.recoup; - struct DONAU_DonauPublicKeyP pub; - struct TALER_DonauSignatureP sig; - - if (TALER_EC_NONE != - TALER_donau_online_confirm_recoup_sign ( - &TEH_keys_donau_sign_, - recoup->timestamp, - &recoup->value, - &recoup->coin.coin_pub, - &recoup->reserve_pub, - &pub, - &sig)) - { - GNUNET_break (0); - json_decref (json_history); - return NULL; - } - - if (0 != - json_array_append_new ( - json_history, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "RECOUP"), - GNUNET_JSON_pack_data_auto ("donau_pub", - &pub), - GNUNET_JSON_pack_data_auto ("donau_sig", - &sig), - GNUNET_JSON_pack_timestamp ("timestamp", - recoup->timestamp), - TALER_JSON_pack_amount ("amount", - &recoup->value), - GNUNET_JSON_pack_data_auto ("coin_pub", - &recoup->coin.coin_pub)))) - { - GNUNET_break (0); - json_decref (json_history); - return NULL; - } - } - break; - case DONAUDB_RO_DONAU_TO_BANK: - { - const struct DONAUDB_ClosingTransfer *closing = - pos->details.closing; - struct DONAU_DonauPublicKeyP pub; - struct TALER_DonauSignatureP sig; - - if (TALER_EC_NONE != - TALER_donau_online_reserve_closed_sign ( - &TEH_keys_donau_sign_, - closing->execution_date, - &closing->amount, - &closing->closing_fee, - closing->receiver_account_details, - &closing->wtid, - &pos->details.closing->reserve_pub, - &pub, - &sig)) - { - GNUNET_break (0); - json_decref (json_history); - return NULL; - } - if (0 != - json_array_append_new ( - json_history, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "CLOSING"), - GNUNET_JSON_pack_string ("receiver_account_details", - closing->receiver_account_details), - GNUNET_JSON_pack_data_auto ("wtid", - &closing->wtid), - GNUNET_JSON_pack_data_auto ("donau_pub", - &pub), - GNUNET_JSON_pack_data_auto ("donau_sig", - &sig), - GNUNET_JSON_pack_timestamp ("timestamp", - closing->execution_date), - TALER_JSON_pack_amount ("amount", - &closing->amount), - TALER_JSON_pack_amount ("closing_fee", - &closing->closing_fee)))) - { - GNUNET_break (0); - json_decref (json_history); - return NULL; - } - } - break; - case DONAUDB_RO_PURSE_MERGE: - { - const struct DONAUDB_PurseMerge *merge = - pos->details.merge; - - if (0 != - json_array_append_new ( - json_history, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "MERGE"), - GNUNET_JSON_pack_data_auto ("h_contract_terms", - &merge->h_contract_terms), - GNUNET_JSON_pack_data_auto ("merge_pub", - &merge->merge_pub), - GNUNET_JSON_pack_uint64 ("min_age", - merge->min_age), - GNUNET_JSON_pack_uint64 ("flags", - merge->flags), - GNUNET_JSON_pack_data_auto ("purse_pub", - &merge->purse_pub), - GNUNET_JSON_pack_data_auto ("reserve_sig", - &merge->reserve_sig), - GNUNET_JSON_pack_timestamp ("merge_timestamp", - merge->merge_timestamp), - GNUNET_JSON_pack_timestamp ("purse_expiration", - merge->purse_expiration), - TALER_JSON_pack_amount ("purse_fee", - &merge->purse_fee), - TALER_JSON_pack_amount ("amount", - &merge->amount_with_fee), - GNUNET_JSON_pack_bool ("merged", - merge->merged)))) - { - GNUNET_break (0); - json_decref (json_history); - return NULL; - } - } - break; - case DONAUDB_RO_HISTORY_REQUEST: - { - const struct DONAUDB_HistoryRequest *history = - pos->details.history; - - if (0 != - json_array_append_new ( - json_history, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "HISTORY"), - GNUNET_JSON_pack_data_auto ("reserve_sig", - &history->reserve_sig), - GNUNET_JSON_pack_timestamp ("request_timestamp", - history->request_timestamp), - TALER_JSON_pack_amount ("amount", - &history->history_fee)))) - { - GNUNET_break (0); - json_decref (json_history); - return NULL; - } - } - break; - - case DONAUDB_RO_OPEN_REQUEST: - { - const struct DONAUDB_OpenRequest *orq = - pos->details.open_request; - - if (0 != - json_array_append_new ( - json_history, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "OPEN"), - GNUNET_JSON_pack_uint64 ("requested_min_purses", - orq->purse_limit), - GNUNET_JSON_pack_data_auto ("reserve_sig", - &orq->reserve_sig), - GNUNET_JSON_pack_timestamp ("request_timestamp", - orq->request_timestamp), - GNUNET_JSON_pack_timestamp ("requested_expiration", - orq->reserve_expiration), - TALER_JSON_pack_amount ("open_fee", - &orq->open_fee)))) - { - GNUNET_break (0); - json_decref (json_history); - return NULL; - } - } - break; - - case DONAUDB_RO_CLOSE_REQUEST: - { - const struct DONAUDB_CloseRequest *crq = - pos->details.close_request; - - if (0 != - json_array_append_new ( - json_history, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "CLOSE"), - GNUNET_JSON_pack_data_auto ("reserve_sig", - &crq->reserve_sig), - GNUNET_is_zero (&crq->target_account_h_payto) - ? GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_string ("h_payto", - NULL)) - : GNUNET_JSON_pack_data_auto ("h_payto", - &crq->target_account_h_payto), - GNUNET_JSON_pack_timestamp ("request_timestamp", - crq->request_timestamp)))) - { - GNUNET_break (0); - json_decref (json_history); - return NULL; - } - } - break; - } - } - - return json_history; -} - - -/** - * Send reserve history information to client with the - * message that we have insufficient funds for the - * requested withdraw operation. - * - * @param connection connection to the client - * @param ec error code to return - * @param ebalance expected balance based on our database - * @param withdraw_amount amount that the client requested to withdraw - * @param rh reserve history to return - * @return MHD result code - */ -static MHD_RESULT -reply_reserve_insufficient_funds ( - struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const struct TALER_Amount *ebalance, - const struct TALER_Amount *withdraw_amount, - const struct DONAUDB_ReserveHistory *rh) -{ - json_t *json_history; - - json_history = TEH_RESPONSE_compile_reserve_history (rh); - if (NULL == json_history) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to compile reserve history\n"); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_DONAU_RESERVE_HISTORY_ERROR_INSUFFICIENT_FUNDS, - NULL); - } - return TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_CONFLICT, - TALER_JSON_pack_ec (ec), - TALER_JSON_pack_amount ("balance", - ebalance), - TALER_JSON_pack_amount ("requested_amount", - withdraw_amount), - GNUNET_JSON_pack_array_steal ("history", - json_history)); -} - - -MHD_RESULT -TEH_RESPONSE_reply_reserve_insufficient_balance ( - struct MHD_Connection *connection, - enum TALER_ErrorCode ec, - const struct TALER_Amount *balance_required, - const struct TALER_ReservePublicKeyP *reserve_pub) -{ - struct DONAUDB_ReserveHistory *rh = NULL; - struct TALER_Amount balance; - enum GNUNET_DB_QueryStatus qs; - MHD_RESULT mhd_ret; - - if (GNUNET_OK != - TEH_plugin->start_read_only (TEH_plugin->cls, - "get_reserve_history on insufficient balance")) - { - GNUNET_break (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_START_FAILED, - NULL); - } - /* The reserve does not have the required amount (actual - * amount + withdraw fee) */ - qs = TEH_plugin->get_reserve_history (TEH_plugin->cls, - reserve_pub, - &balance, - &rh); - TEH_plugin->rollback (TEH_plugin->cls); - if ( (qs < 0) || - (NULL == rh) ) - { - GNUNET_break (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_FETCH_FAILED, - "reserve history"); - } - mhd_ret = reply_reserve_insufficient_funds ( - connection, - ec, - &balance, - balance_required, - rh); - TEH_plugin->free_reserve_history (TEH_plugin->cls, - rh); - return mhd_ret; -} - - -MHD_RESULT -TEH_RESPONSE_reply_reserve_age_restriction_required ( - struct MHD_Connection *connection, - uint16_t maximum_allowed_age) -{ - return TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_CONFLICT, - TALER_JSON_pack_ec (TALER_EC_DONAU_RESERVES_AGE_RESTRICTION_REQUIRED), - GNUNET_JSON_pack_uint64 ("maximum_allowed_age", - maximum_allowed_age)); -} - - -MHD_RESULT -TEH_RESPONSE_reply_purse_created ( - struct MHD_Connection *connection, - struct GNUNET_TIME_Timestamp donau_timestamp, - const struct TALER_Amount *purse_balance, - const struct TEH_PurseDetails *pd) -{ - struct DONAU_DonauPublicKeyP pub; - struct TALER_DonauSignatureP sig; - enum TALER_ErrorCode ec; - - if (TALER_EC_NONE != - (ec = TALER_donau_online_purse_created_sign ( - &TEH_keys_donau_sign_, - donau_timestamp, - pd->purse_expiration, - &pd->target_amount, - purse_balance, - &pd->purse_pub, - &pd->h_contract_terms, - &pub, - &sig))) - { - GNUNET_break (0); - return TALER_MHD_reply_with_ec (connection, - ec, - NULL); - } - return TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_OK, - TALER_JSON_pack_amount ("total_deposited", - purse_balance), - GNUNET_JSON_pack_timestamp ("donau_timestamp", - donau_timestamp), - GNUNET_JSON_pack_data_auto ("donau_sig", - &sig), - GNUNET_JSON_pack_data_auto ("donau_pub", - &pub)); -} - - -MHD_RESULT -TEH_RESPONSE_reply_kyc_required (struct MHD_Connection *connection, - const struct TALER_PaytoHashP *h_payto, - const struct DONAUDB_KycStatus *kyc) -{ - return TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS, - TALER_JSON_pack_ec (TALER_EC_DONAU_GENERIC_KYC_REQUIRED), - GNUNET_JSON_pack_data_auto ("h_payto", - h_payto), - GNUNET_JSON_pack_uint64 ("requirement_row", - kyc->requirement_row)); -} - - -MHD_RESULT -TEH_RESPONSE_reply_aml_blocked (struct MHD_Connection *connection, - enum TALER_AmlDecisionState status) -{ - enum TALER_ErrorCode ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; - - switch (status) - { - case TALER_AML_NORMAL: - GNUNET_break (0); - return MHD_NO; - case TALER_AML_PENDING: - ec = TALER_EC_DONAU_GENERIC_AML_PENDING; - break; - case TALER_AML_FROZEN: - ec = TALER_EC_DONAU_GENERIC_AML_FROZEN; - break; - } - return TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS, - TALER_JSON_pack_ec (ec)); -} +#include "donau-httpd_keys.h" + + +// /** +// * Compile the transaction history of a coin into a JSON object. +// * +// * @param coin_pub public key of the coin +// * @param tl transaction history to JSON-ify +// * @return json representation of the @a rh, NULL on error +// */ +// json_t * +// TEH_RESPONSE_compile_transaction_history ( +// const struct TALER_CoinSpendPublicKeyP *coin_pub, +// const struct DONAUDB_TransactionList *tl) +// { +// json_t *history; + +// history = json_array (); +// if (NULL == history) +// { +// GNUNET_break (0); /* out of memory!? */ +// return NULL; +// } +// for (const struct DONAUDB_TransactionList *pos = tl; +// NULL != pos; +// pos = pos->next) +// { +// switch (pos->type) +// { +// case DONAUDB_TT_DEPOSIT: +// { +// const struct DONAUDB_DepositListEntry *deposit = +// pos->details.deposit; +// struct TALER_CharityWireHashP h_wire; + +// TALER_charity_wire_signature_hash (deposit->receiver_wire_account, +// &deposit->wire_salt, +// &h_wire); +// #if ENABLE_SANITY_CHECKS +// /* internal sanity check before we hand out a bogus sig... */ +// TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++; +// if (GNUNET_OK != +// TALER_wallet_deposit_verify ( +// &deposit->amount_with_fee, +// &deposit->deposit_fee, +// &h_wire, +// &deposit->h_contract_terms, +// deposit->no_wallet_data_hash +// ? NULL +// : &deposit->wallet_data_hash, +// deposit->no_age_commitment +// ? NULL +// : &deposit->h_age_commitment, +// &deposit->h_policy, +// &deposit->h_denom_pub, +// deposit->timestamp, +// &deposit->charity_pub, +// deposit->refund_deadline, +// coin_pub, +// &deposit->csig)) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// #endif +// if (0 != +// json_array_append_new ( +// history, +// GNUNET_JSON_PACK ( +// GNUNET_JSON_pack_string ("type", +// "DEPOSIT"), +// TALER_JSON_pack_amount ("amount", +// &deposit->amount_with_fee), +// TALER_JSON_pack_amount ("deposit_fee", +// &deposit->deposit_fee), +// GNUNET_JSON_pack_timestamp ("timestamp", +// deposit->timestamp), +// GNUNET_JSON_pack_allow_null ( +// GNUNET_JSON_pack_timestamp ("refund_deadline", +// deposit->refund_deadline)), +// GNUNET_JSON_pack_data_auto ("charity_pub", +// &deposit->charity_pub), +// GNUNET_JSON_pack_data_auto ("h_contract_terms", +// &deposit->h_contract_terms), +// GNUNET_JSON_pack_data_auto ("h_wire", +// &h_wire), +// GNUNET_JSON_pack_allow_null ( +// deposit->no_age_commitment ? +// GNUNET_JSON_pack_string ( +// "h_age_commitment", NULL) : +// GNUNET_JSON_pack_data_auto ("h_age_commitment", +// &deposit->h_age_commitment)), +// GNUNET_JSON_pack_data_auto ("coin_sig", +// &deposit->csig)))) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// break; +// } +// case DONAUDB_TT_MELT: +// { +// const struct DONAUDB_MeltListEntry *melt = +// pos->details.melt; +// const struct TALER_AgeCommitmentHash *phac = NULL; + +// #if ENABLE_SANITY_CHECKS +// TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++; +// if (GNUNET_OK != +// TALER_wallet_melt_verify ( +// &melt->amount_with_fee, +// &melt->melt_fee, +// &melt->rc, +// &melt->h_denom_pub, +// &melt->h_age_commitment, +// coin_pub, +// &melt->coin_sig)) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// #endif + +// /* Age restriction is optional. We communicate a NULL value to +// * JSON_PACK below */ +// if (! melt->no_age_commitment) +// phac = &melt->h_age_commitment; + +// if (0 != +// json_array_append_new ( +// history, +// GNUNET_JSON_PACK ( +// GNUNET_JSON_pack_string ("type", +// "MELT"), +// TALER_JSON_pack_amount ("amount", +// &melt->amount_with_fee), +// TALER_JSON_pack_amount ("melt_fee", +// &melt->melt_fee), +// GNUNET_JSON_pack_data_auto ("rc", +// &melt->rc), +// GNUNET_JSON_pack_allow_null ( +// GNUNET_JSON_pack_data_auto ("h_age_commitment", +// phac)), +// GNUNET_JSON_pack_data_auto ("coin_sig", +// &melt->coin_sig)))) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// } +// break; +// case DONAUDB_TT_REFUND: +// { +// const struct DONAUDB_RefundListEntry *refund = +// pos->details.refund; +// struct TALER_Amount value; + +// #if ENABLE_SANITY_CHECKS +// TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++; +// if (GNUNET_OK != +// TALER_charity_refund_verify ( +// coin_pub, +// &refund->h_contract_terms, +// refund->rtransaction_id, +// &refund->refund_amount, +// &refund->charity_pub, +// &refund->charity_sig)) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// #endif +// if (0 > +// TALER_amount_subtract (&value, +// &refund->refund_amount, +// &refund->refund_fee)) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// if (0 != +// json_array_append_new ( +// history, +// GNUNET_JSON_PACK ( +// GNUNET_JSON_pack_string ("type", +// "REFUND"), +// TALER_JSON_pack_amount ("amount", +// &value), +// TALER_JSON_pack_amount ("refund_fee", +// &refund->refund_fee), +// GNUNET_JSON_pack_data_auto ("h_contract_terms", +// &refund->h_contract_terms), +// GNUNET_JSON_pack_data_auto ("charity_pub", +// &refund->charity_pub), +// GNUNET_JSON_pack_uint64 ("rtransaction_id", +// refund->rtransaction_id), +// GNUNET_JSON_pack_data_auto ("charity_sig", +// &refund->charity_sig)))) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// } +// break; +// case DONAUDB_TT_OLD_COIN_RECOUP: +// { +// struct DONAUDB_RecoupRefreshListEntry *pr = +// pos->details.old_coin_recoup; +// struct DONAU_DonauPublicKeyP epub; +// struct TALER_DonauSignatureP esig; + +// if (TALER_EC_NONE != +// TALER_donau_online_confirm_recoup_refresh_sign ( +// &TEH_keys_donau_sign_, +// pr->timestamp, +// &pr->value, +// &pr->coin.coin_pub, +// &pr->old_coin_pub, +// &epub, +// &esig)) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// /* NOTE: we could also provide coin_pub's coin_sig, denomination key hash and +// the denomination key's RSA signature over coin_pub, but as the +// wallet should really already have this information (and cannot +// check or do anything with it anyway if it doesn't), it seems +// strictly unnecessary. */ +// if (0 != +// json_array_append_new ( +// history, +// GNUNET_JSON_PACK ( +// GNUNET_JSON_pack_string ("type", +// "OLD-COIN-RECOUP"), +// TALER_JSON_pack_amount ("amount", +// &pr->value), +// GNUNET_JSON_pack_data_auto ("donau_sig", +// &esig), +// GNUNET_JSON_pack_data_auto ("donau_pub", +// &epub), +// GNUNET_JSON_pack_data_auto ("coin_pub", +// &pr->coin.coin_pub), +// GNUNET_JSON_pack_timestamp ("timestamp", +// pr->timestamp)))) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// break; +// } +// case DONAUDB_TT_RECOUP: +// { +// const struct DONAUDB_RecoupListEntry *recoup = +// pos->details.recoup; +// struct DONAU_DonauPublicKeyP epub; +// struct TALER_DonauSignatureP esig; + +// if (TALER_EC_NONE != +// TALER_donau_online_confirm_recoup_sign ( +// &TEH_keys_donau_sign_, +// recoup->timestamp, +// &recoup->value, +// coin_pub, +// &recoup->reserve_pub, +// &epub, +// &esig)) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// if (0 != +// json_array_append_new ( +// history, +// GNUNET_JSON_PACK ( +// GNUNET_JSON_pack_string ("type", +// "RECOUP"), +// TALER_JSON_pack_amount ("amount", +// &recoup->value), +// GNUNET_JSON_pack_data_auto ("donau_sig", +// &esig), +// GNUNET_JSON_pack_data_auto ("donau_pub", +// &epub), +// GNUNET_JSON_pack_data_auto ("reserve_pub", +// &recoup->reserve_pub), +// GNUNET_JSON_pack_data_auto ("coin_sig", +// &recoup->coin_sig), +// GNUNET_JSON_pack_data_auto ("coin_blind", +// &recoup->coin_blind), +// GNUNET_JSON_pack_data_auto ("reserve_pub", +// &recoup->reserve_pub), +// GNUNET_JSON_pack_timestamp ("timestamp", +// recoup->timestamp)))) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// } +// break; +// case DONAUDB_TT_RECOUP_REFRESH: +// { +// struct DONAUDB_RecoupRefreshListEntry *pr = +// pos->details.recoup_refresh; +// struct DONAU_DonauPublicKeyP epub; +// struct TALER_DonauSignatureP esig; + +// if (TALER_EC_NONE != +// TALER_donau_online_confirm_recoup_refresh_sign ( +// &TEH_keys_donau_sign_, +// pr->timestamp, +// &pr->value, +// coin_pub, +// &pr->old_coin_pub, +// &epub, +// &esig)) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// /* NOTE: we could also provide coin_pub's coin_sig, denomination key +// hash and the denomination key's RSA signature over coin_pub, but as +// the wallet should really already have this information (and cannot +// check or do anything with it anyway if it doesn't), it seems +// strictly unnecessary. */ +// if (0 != +// json_array_append_new ( +// history, +// GNUNET_JSON_PACK ( +// GNUNET_JSON_pack_string ("type", +// "RECOUP-REFRESH"), +// TALER_JSON_pack_amount ("amount", +// &pr->value), +// GNUNET_JSON_pack_data_auto ("donau_sig", +// &esig), +// GNUNET_JSON_pack_data_auto ("donau_pub", +// &epub), +// GNUNET_JSON_pack_data_auto ("old_coin_pub", +// &pr->old_coin_pub), +// GNUNET_JSON_pack_data_auto ("coin_sig", +// &pr->coin_sig), +// GNUNET_JSON_pack_data_auto ("coin_blind", +// &pr->coin_blind), +// GNUNET_JSON_pack_timestamp ("timestamp", +// pr->timestamp)))) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// break; +// } + +// case DONAUDB_TT_PURSE_DEPOSIT: +// { +// struct DONAUDB_PurseDepositListEntry *pd +// = pos->details.purse_deposit; +// const struct TALER_AgeCommitmentHash *phac = NULL; + +// if (! pd->no_age_commitment) +// phac = &pd->h_age_commitment; + +// if (0 != +// json_array_append_new ( +// history, +// GNUNET_JSON_PACK ( +// GNUNET_JSON_pack_string ("type", +// "PURSE-DEPOSIT"), +// TALER_JSON_pack_amount ("amount", +// &pd->amount), +// GNUNET_JSON_pack_string ("donau_base_url", +// NULL == pd->donau_base_url +// ? TEH_base_url +// : pd->donau_base_url), +// GNUNET_JSON_pack_allow_null ( +// GNUNET_JSON_pack_data_auto ("h_age_commitment", +// phac)), +// GNUNET_JSON_pack_data_auto ("purse_pub", +// &pd->purse_pub), +// GNUNET_JSON_pack_bool ("refunded", +// pd->refunded), +// GNUNET_JSON_pack_data_auto ("coin_sig", +// &pd->coin_sig)))) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// break; +// } + +// case DONAUDB_TT_PURSE_REFUND: +// { +// const struct DONAUDB_PurseRefundListEntry *prefund = +// pos->details.purse_refund; +// struct TALER_Amount value; +// enum TALER_ErrorCode ec; +// struct DONAU_DonauPublicKeyP epub; +// struct TALER_DonauSignatureP esig; + +// if (0 > +// TALER_amount_subtract (&value, +// &prefund->refund_amount, +// &prefund->refund_fee)) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// ec = TALER_donau_online_purse_refund_sign ( +// &TEH_keys_donau_sign_, +// &value, +// &prefund->refund_fee, +// coin_pub, +// &prefund->purse_pub, +// &epub, +// &esig); +// if (TALER_EC_NONE != ec) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// if (0 != +// json_array_append_new ( +// history, +// GNUNET_JSON_PACK ( +// GNUNET_JSON_pack_string ("type", +// "PURSE-REFUND"), +// TALER_JSON_pack_amount ("amount", +// &value), +// TALER_JSON_pack_amount ("refund_fee", +// &prefund->refund_fee), +// GNUNET_JSON_pack_data_auto ("donau_sig", +// &esig), +// GNUNET_JSON_pack_data_auto ("donau_pub", +// &epub), +// GNUNET_JSON_pack_data_auto ("purse_pub", +// &prefund->purse_pub)))) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// } +// break; + +// case DONAUDB_TT_RESERVE_OPEN: +// { +// struct DONAUDB_ReserveOpenListEntry *role +// = pos->details.reserve_open; + +// if (0 != +// json_array_append_new ( +// history, +// GNUNET_JSON_PACK ( +// GNUNET_JSON_pack_string ("type", +// "RESERVE-OPEN-DEPOSIT"), +// TALER_JSON_pack_amount ("coin_contribution", +// &role->coin_contribution), +// GNUNET_JSON_pack_data_auto ("reserve_sig", +// &role->reserve_sig), +// GNUNET_JSON_pack_data_auto ("coin_sig", +// &role->coin_sig)))) +// { +// GNUNET_break (0); +// json_decref (history); +// return NULL; +// } +// break; +// } +// } +// } +// return history; +// } + + +// MHD_RESULT +// TEH_RESPONSE_reply_unknown_denom_pub_hash ( +// struct MHD_Connection *connection, +// const struct TALER_DenominationHashP *dph) +// { +// struct DONAU_DonauPublicKeyP epub; +// struct TALER_DonauSignatureP esig; +// struct GNUNET_TIME_Timestamp now; +// enum TALER_ErrorCode ec; + +// now = GNUNET_TIME_timestamp_get (); +// ec = TALER_donau_online_denomination_unknown_sign ( +// &TEH_keys_donau_sign_, +// now, +// dph, +// &epub, +// &esig); +// if (TALER_EC_NONE != ec) +// { +// GNUNET_break (0); +// return TALER_MHD_reply_with_error (connection, +// MHD_HTTP_INTERNAL_SERVER_ERROR, +// ec, +// NULL); +// } +// return TALER_MHD_REPLY_JSON_PACK ( +// connection, +// MHD_HTTP_NOT_FOUND, +// TALER_JSON_pack_ec (TALER_EC_DONAU_GENERIC_DENOMINATION_KEY_UNKNOWN), +// GNUNET_JSON_pack_timestamp ("timestamp", +// now), +// GNUNET_JSON_pack_data_auto ("donau_pub", +// &epub), +// GNUNET_JSON_pack_data_auto ("donau_sig", +// &esig), +// GNUNET_JSON_pack_data_auto ("h_denom_pub", +// dph)); +// } /* end of taler-donau-httpd_responses.c */ diff --git a/src/donau/donau-httpd_terms.c b/src/donau/donau-httpd_terms.c @@ -24,7 +24,7 @@ #include <jansson.h> #include <microhttpd.h> #include "taler/taler_mhd_lib.h" -#include "taler-donau-httpd_responses.h" +#include "donau-httpd_responses.h" /** * Our terms of service. @@ -38,44 +38,44 @@ static struct TALER_MHD_Legal *tos; static struct TALER_MHD_Legal *pp; -MHD_RESULT -TEH_handler_terms (struct TEH_RequestContext *rc, - const char *const args[]) -{ - (void) args; - return TALER_MHD_reply_legal (rc->connection, - tos); -} +// MHD_RESULT +// TEH_handler_terms (struct TEH_RequestContext *rc, +// const char *const args[]) +// { +// (void) args; +// return TALER_MHD_reply_legal (rc->connection, +// tos); +// } -MHD_RESULT -TEH_handler_privacy (struct TEH_RequestContext *rc, - const char *const args[]) -{ - (void) args; - return TALER_MHD_reply_legal (rc->connection, - pp); -} +// MHD_RESULT +// TEH_handler_privacy (struct TEH_RequestContext *rc, +// const char *const args[]) +// { +// (void) args; +// return TALER_MHD_reply_legal (rc->connection, +// pp); +// } -void -TEH_load_terms (const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - tos = TALER_MHD_legal_load (cfg, - "donau", - "TERMS_DIR", - "TERMS_ETAG"); - if (NULL == tos) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Terms of service not configured\n"); - pp = TALER_MHD_legal_load (cfg, - "donau", - "PRIVACY_DIR", - "PRIVACY_ETAG"); - if (NULL == pp) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Privacy policy not configured\n"); -} +// void +// TEH_load_terms (const struct GNUNET_CONFIGURATION_Handle *cfg) +// { +// tos = TALER_MHD_legal_load (cfg, +// "donau", +// "TERMS_DIR", +// "TERMS_ETAG"); +// if (NULL == tos) +// GNUNET_log (GNUNET_ERROR_TYPE_WARNING, +// "Terms of service not configured\n"); +// pp = TALER_MHD_legal_load (cfg, +// "donau", +// "PRIVACY_DIR", +// "PRIVACY_ETAG"); +// if (NULL == pp) +// GNUNET_log (GNUNET_ERROR_TYPE_WARNING, +// "Privacy policy not configured\n"); +// } /* end of taler-donau-httpd_terms.c */