diff options
-rw-r--r-- | src/exchange/taler-exchange-httpd.c | 316 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd.h | 6 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_auditors.c | 4 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_auditors.h | 2 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_management.h | 11 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_management_auditors.c | 1 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_management_auditors_AP_disable.c | 10 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_management_post_keys.c | 1 |
8 files changed, 316 insertions, 35 deletions
diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index 6dc689848..4896c8d46 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -28,20 +28,22 @@ #include <pthread.h> #include <sys/resource.h> #include "taler_mhd_lib.h" -#include "taler-exchange-httpd_mhd.h" +#include "taler-exchange-httpd_auditors.h" #include "taler-exchange-httpd_deposit.h" -#include "taler-exchange-httpd_refund.h" -#include "taler-exchange-httpd_reserves_get.h" -#include "taler-exchange-httpd_withdraw.h" -#include "taler-exchange-httpd_recoup.h" +#include "taler-exchange-httpd_deposits_get.h" +#include "taler-exchange-httpd_keystate.h" #include "taler-exchange-httpd_link.h" +#include "taler-exchange-httpd_management.h" #include "taler-exchange-httpd_melt.h" +#include "taler-exchange-httpd_mhd.h" +#include "taler-exchange-httpd_recoup.h" #include "taler-exchange-httpd_refreshes_reveal.h" +#include "taler-exchange-httpd_refund.h" +#include "taler-exchange-httpd_reserves_get.h" #include "taler-exchange-httpd_terms.h" #include "taler-exchange-httpd_transfers_get.h" -#include "taler-exchange-httpd_deposits_get.h" -#include "taler-exchange-httpd_keystate.h" #include "taler-exchange-httpd_wire.h" +#include "taler-exchange-httpd_withdraw.h" #include "taler_exchangedb_plugin.h" #include <gnunet/gnunet_mhd_compat.h> @@ -178,6 +180,24 @@ typedef MHD_RESULT /** + * 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); +} + + +/** * Handle a "/coins/$COIN_PUB/$OP" POST request. Parses the "coin_pub" * EdDSA key of the coin and demultiplexes based on $OP. * @@ -249,10 +269,7 @@ handle_post_coins (const struct TEH_RequestHandler *rh, return h[i].handler (connection, &coin_pub, root); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN, - args[1]); + return r404 (connection, args[1]); } @@ -367,6 +384,7 @@ proceed_with_handler (const struct TEH_RequestHandler *rh, char d[ulen]; /* Parse command-line arguments, if applicable */ + args[0] = NULL; if (rh->nargs > 0) { unsigned int i; @@ -384,9 +402,10 @@ proceed_with_handler (const struct TEH_RequestHandler *rh, args[i++] = strtok_r (NULL, "/", &sp); /* make sure above loop ran nicely until completion, and also that there is no excess data in 'd' afterwards */ - if ( (i != rh->nargs) || - (NULL == args[i - 1]) || - (NULL != (fin = strtok_r (NULL, "/", &sp))) ) + if ( (! rh->nargs_is_upper_bound) && + ( (i != rh->nargs) || + (NULL == args[i - 1]) || + (NULL != (fin = strtok_r (NULL, "/", &sp))) ) ) { char emsg[128 + 512]; @@ -407,12 +426,12 @@ proceed_with_handler (const struct TEH_RequestHandler *rh, TALER_EC_EXCHANGE_GENERIC_WRONG_NUMBER_OF_SEGMENTS, emsg); } + + /* just to be safe(r), we always terminate the array with a NULL + (even if handlers requested precise number of arguments) */ + args[i] = NULL; } - /* just to be safe(r), we always terminate the array with a NULL - (which handlers should not read, but at least if they do, they'll - crash pretty reliably...) */ - args[rh->nargs] = NULL; /* Above logic ensures that 'root' is exactly non-NULL for POST operations, so we test for 'root' to decide which handler to invoke. */ @@ -473,6 +492,244 @@ handler_seed (const struct TEH_RequestHandler *rh, /** + * Handle POST "/management/..." requests. + * + * @param rh context of the handler + * @param connection the MHD connection to handle + * @param root uploaded JSON data + * @param args array of additional options + * @return MHD result code + */ +static MHD_RESULT +handle_post_management (const struct TEH_RequestHandler *rh, + struct MHD_Connection *connection, + const json_t *root, + const char *const args[]) +{ + if (NULL == args[0]) + { + GNUNET_break_op (0); + return r404 (connection, "/management"); + } + if (0 == strcmp (args[0], + "auditors")) + { + struct TALER_AuditorPublicKeyP auditor_pub; + + if (NULL == args[1]) + return TEH_handler_management_auditors (connection, + root); + if ( (NULL == args[1]) || + (NULL == args[2]) || + (0 != strcmp (args[2], + "disable")) || + (NULL != args[3]) ) + return r404 (connection, + "/management/auditors/$AUDITOR_PUB/disable"); + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[1], + strlen (args[1]), + &auditor_pub, + sizeof (auditor_pub))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + args[1]); + } + return TEH_handler_management_auditors_AP_disable (connection, + &auditor_pub, + root); + } + if (0 == strcmp (args[0], + "denominations")) + { + struct GNUNET_HashCode h_denom_pub; + + if ( (NULL == args[0]) || + (NULL == args[1]) || + (NULL == args[2]) || + (0 != strcmp (args[2], + "revoke")) || + (NULL != args[3]) ) + return r404 (connection, + "/management/denominations/$HDP/revoke"); + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[2], + strlen (args[2]), + &h_denom_pub, + sizeof (h_denom_pub))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + args[2]); + } + return TEH_handler_management_denominations_HDP_revoke (connection, + &h_denom_pub, + root); + } + if (0 == strcmp (args[0], + "signkeys")) + { + struct TALER_ExchangePublicKeyP exchange_pub; + + if ( (NULL == args[0]) || + (NULL == args[1]) || + (NULL == args[2]) || + (0 != strcmp (args[2], + "revoke")) || + (NULL != args[3]) ) + return r404 (connection, + "/management/signkeys/$HDP/revoke"); + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[2], + strlen (args[2]), + &exchange_pub, + sizeof (exchange_pub))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + args[2]); + } + return TEH_handler_management_signkeys_EP_revoke (connection, + &exchange_pub, + root); + } +#if FIXME + /* not yet implemented! */ + if (0 == strcmp (args[0], + "keys")) + { + if (NULL != args[1]) + { + GNUNET_break_op (0); + return r404 (connection, "/management/keys/*"); + } + return TEH_handler_management_post_keys (connection, + root); + } +#endif + if (0 == strcmp (args[0], + "wire")) + { + if (NULL == args[1]) + return TEH_handler_management_denominations_wire (connection, + root); + if ( (0 != strcmp (args[1], + "disable")) || + (NULL != args[2]) ) + { + GNUNET_break_op (0); + return r404 (connection, "/management/wire/disable"); + } + return TEH_handler_management_denominations_wire_disable (connection, + root); + } + if (0 == strcmp (args[0], + "wire-fees")) + { + if (NULL != args[1]) + { + GNUNET_break_op (0); + return r404 (connection, "/management/wire-fees/*"); + } + return TEH_handler_management_post_wire_fees (connection, + root); + } + GNUNET_break_op (0); + return r404 (connection, "/management/*"); +} + + +/** + * Handle a get "/management" request. + * + * @param rh context of the handler + * @param connection the MHD connection to handle + * @param args array of additional options (must be empty for this function) + * @return MHD result code + */ +static MHD_RESULT +handle_get_management (const struct TEH_RequestHandler *rh, + struct MHD_Connection *connection, + const char *const args[1]) +{ + if ( (NULL == args[0]) || + (0 != strcmp (args[0], + "keys")) || + (NULL != args[1]) ) + { + GNUNET_break_op (0); + return r404 (connection, "/management/*"); + } + GNUNET_break (0); // not implemented + return MHD_NO; +} + + +/** + * Handle POST "/auditors/..." requests. + * + * @param rh context of the handler + * @param connection the MHD connection to handle + * @param root uploaded JSON data + * @param args array of additional options + * @return MHD result code + */ +static MHD_RESULT +handle_post_auditors (const struct TEH_RequestHandler *rh, + struct MHD_Connection *connection, + const json_t *root, + const char *const args[]) +{ + struct TALER_AuditorPublicKeyP auditor_pub; + struct GNUNET_HashCode h_denom_pub; + + if ( (NULL == args[0]) || + (NULL == args[1]) || + (NULL != args[0]) ) + { + GNUNET_break_op (0); + return r404 (connection, "/auditors/$AUDITOR_PUB/$H_DENOM_PUB"); + } + + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[0], + strlen (args[0]), + &auditor_pub, + sizeof (auditor_pub))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + args[0]); + } + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[1], + strlen (args[1]), + &h_denom_pub, + sizeof (h_denom_pub))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + args[1]); + } + return TEH_handler_auditors (connection, + &auditor_pub, + &h_denom_pub, + root); +} + + +/** * Handle incoming HTTP request. * * @param cls closure for MHD daemon (unused) @@ -600,6 +857,29 @@ handle_mhd_request (void *cls, .handler.get = &TEH_handler_deposits_get, .nargs = 4 }, + /* POST management endpoints */ + { + .url = "management", + .method = MHD_HTTP_METHOD_POST, + .handler.post = &handle_post_management, + .nargs = 4, + .nargs_is_upper_bound = true + }, + /* GET management endpoints (we only really have "/management/keys") */ + { + .url = "management", + .method = MHD_HTTP_METHOD_GET, + .handler.get = &handle_get_management, + .nargs = 1 + }, + /* auditor endpoints */ + { + .url = "auditors", + .method = MHD_HTTP_METHOD_POST, + .handler.post = &handle_post_auditors, + .nargs = 4, + .nargs_is_upper_bound = true + }, /* mark end of list */ { .url = NULL diff --git a/src/exchange/taler-exchange-httpd.h b/src/exchange/taler-exchange-httpd.h index ad46788c4..5e7738163 100644 --- a/src/exchange/taler-exchange-httpd.h +++ b/src/exchange/taler-exchange-httpd.h @@ -134,6 +134,12 @@ struct TEH_RequestHandler unsigned int nargs; /** + * Is the number of arguments given in @e nargs only an upper bound, + * and calling with fewer arguments could be OK? + */ + bool nargs_is_upper_bound; + + /** * Mime type to use in reply (hint, can be NULL). */ const char *mime_type; diff --git a/src/exchange/taler-exchange-httpd_auditors.c b/src/exchange/taler-exchange-httpd_auditors.c index 60c633cf5..f0fbb7ebe 100644 --- a/src/exchange/taler-exchange-httpd_auditors.c +++ b/src/exchange/taler-exchange-httpd_auditors.c @@ -209,7 +209,7 @@ add_auditor_denom_sig (void *cls, MHD_RESULT -TEH_handler_management_denominations_auditors ( +TEH_handler_auditors ( struct MHD_Connection *connection, const struct TALER_AuditorPublicKeyP *auditor_pub, const struct GNUNET_HashCode *h_denom_pub, @@ -255,4 +255,4 @@ TEH_handler_management_denominations_auditors ( } -/* end of taler-exchange-httpd_management_auditors.c */ +/* end of taler-exchange-httpd_auditors.c */ diff --git a/src/exchange/taler-exchange-httpd_auditors.h b/src/exchange/taler-exchange-httpd_auditors.h index de180587d..f8191f8a2 100644 --- a/src/exchange/taler-exchange-httpd_auditors.h +++ b/src/exchange/taler-exchange-httpd_auditors.h @@ -36,7 +36,7 @@ * @return MHD result code */ MHD_RESULT -TEH_handler_management_denominations_auditors ( +TEH_handler_auditors ( struct MHD_Connection *connection, const struct TALER_AuditorPublicKeyP *auditor_pub, const struct GNUNET_HashCode *h_denom_pub, diff --git a/src/exchange/taler-exchange-httpd_management.h b/src/exchange/taler-exchange-httpd_management.h index cd5c5d8af..b5ab8478e 100644 --- a/src/exchange/taler-exchange-httpd_management.h +++ b/src/exchange/taler-exchange-httpd_management.h @@ -29,14 +29,12 @@ * Handle a "/management/auditors" request. * * @param connection the MHD connection to handle - * @param h_denom_pub hash of the public key of the denomination to revoke * @param root uploaded JSON data * @return MHD result code */ MHD_RESULT TEH_handler_management_auditors ( struct MHD_Connection *connection, - const struct GNUNET_HashCode *h_denom_pub, const json_t *root); @@ -44,14 +42,14 @@ TEH_handler_management_auditors ( * Handle a "/management/auditors/$AUDITOR_PUB/disable" request. * * @param connection the MHD connection to handle - * @param h_denom_pub hash of the public key of the denomination to revoke + * @param auditor_pub public key of the auditor to disable * @param root uploaded JSON data * @return MHD result code */ MHD_RESULT TEH_handler_management_auditors_AP_disable ( struct MHD_Connection *connection, - const struct GNUNET_HashCode *h_denom_pub, + const struct TALER_AuditorPublicKeyP *auditor_pub, const json_t *root); @@ -89,16 +87,15 @@ TEH_handler_management_signkeys_EP_revoke ( * Handle a POST "/management/keys" request. * * @param connection the MHD connection to handle - * @param h_denom_pub hash of the public key of the denomination to revoke * @param root uploaded JSON data * @return MHD result code */ MHD_RESULT TEH_handler_management_post_keys ( struct MHD_Connection *connection, - const struct GNUNET_HashCode *h_denom_pub, const json_t *root); + /** * Handle a "/management/wire" request. * @@ -113,7 +110,7 @@ TEH_handler_management_denominations_wire ( /** - * Handle a "/management/wire" request. + * Handle a "/management/wire/disable" request. * * @param connection the MHD connection to handle * @param root uploaded JSON data diff --git a/src/exchange/taler-exchange-httpd_management_auditors.c b/src/exchange/taler-exchange-httpd_management_auditors.c index 02e4d4fa2..33f1c6df3 100644 --- a/src/exchange/taler-exchange-httpd_management_auditors.c +++ b/src/exchange/taler-exchange-httpd_management_auditors.c @@ -145,7 +145,6 @@ add_auditor (void *cls, MHD_RESULT TEH_handler_management_auditors ( struct MHD_Connection *connection, - const struct GNUNET_HashCode *h_denom_pub, const json_t *root) { struct AddAuditorContext aac; diff --git a/src/exchange/taler-exchange-httpd_management_auditors_AP_disable.c b/src/exchange/taler-exchange-httpd_management_auditors_AP_disable.c index 8904b444d..e360c1a52 100644 --- a/src/exchange/taler-exchange-httpd_management_auditors_AP_disable.c +++ b/src/exchange/taler-exchange-httpd_management_auditors_AP_disable.c @@ -137,16 +137,16 @@ del_auditor (void *cls, MHD_RESULT TEH_handler_management_auditors_AP_disable ( struct MHD_Connection *connection, - const struct GNUNET_HashCode *h_denom_pub, + const struct TALER_AuditorPublicKeyP *auditor_pub, const json_t *root) { struct TALER_MasterSignatureP master_sig; - struct DelAuditorContext dac; + struct DelAuditorContext dac = { + .auditor_pub = *auditor_pub + }; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("master_sig", &master_sig), - GNUNET_JSON_spec_fixed_auto ("auditor_pub", - &dac.auditor_pub), TALER_JSON_spec_absolute_time ("validity_end", &dac.validity_end), GNUNET_JSON_spec_end () @@ -171,7 +171,7 @@ TEH_handler_management_auditors_AP_disable ( TALER_SIGNATURE_MASTER_DEL_AUDITOR), .purpose.size = htonl (sizeof (da)), .end_date = GNUNET_TIME_absolute_hton (dac.validity_end), - .auditor_pub = dac.auditor_pub + .auditor_pub = *auditor_pub }; if (GNUNET_OK != diff --git a/src/exchange/taler-exchange-httpd_management_post_keys.c b/src/exchange/taler-exchange-httpd_management_post_keys.c index ab4399bd8..2ac69a1db 100644 --- a/src/exchange/taler-exchange-httpd_management_post_keys.c +++ b/src/exchange/taler-exchange-httpd_management_post_keys.c @@ -323,7 +323,6 @@ add_keys (void *cls, MHD_RESULT TEH_handler_management_post_keys ( struct MHD_Connection *connection, - const struct GNUNET_HashCode *h_denom_pub, const json_t *root) { struct AddKeysContext akc; |