diff --git a/doc/taler-exchange.texi b/doc/taler-exchange.texi index 558a57eff..e354b58c1 100644 --- a/doc/taler-exchange.texi +++ b/doc/taler-exchange.texi @@ -400,13 +400,10 @@ gap. See keys-duration. @section Serving -The exchange can serve HTTP over both TCP and UNIX domain socket. It -needs this configuration @emph{twice}, because it opens one connection -for ordinary REST calls, and one for "/admin" and "/test" REST calls, -because the operator may want to restrict the access to "/admin". +The exchange can serve HTTP over both TCP and UNIX domain socket. -The following values are to be configured under the section -@cite{[exchange]} and @cite{[exchange-admin]}: +The following values are to be configured in the section +@cite{[exchange]}: @itemize @@ -425,13 +422,9 @@ The following values are to be configured under the section @item @cite{unixpath_mode}: number giving the mode with the access -permissiON MASK for the @cite{unixpath} (i.e. 660 = rw-rw----). +permission MASK for the @cite{unixpath} (i.e. 660 = rw-rw----). @end itemize -The exchange can be started with the @cite{-D} option to disable the administrative -functions entirely. It is recommended that the administrative API is only -accessible via a properly protected UNIX domain socket. - @node Currency @section Currency @@ -673,7 +666,7 @@ get signed by every auditor he wishes (or is forced to) work with. In a normal scenario, an auditor must have some way of receiving the blob to sign (Website, manual delivery, ..). Nonetheless, the exchange admin can fake -an auditor signature - for testing purposes - by running the following command +an auditor signature --- for testing purposes --- by running the following command @example taler-auditor-sign -m EXCHANGE_MASTER_PUB -r BLOB -u AUDITOR_URI -o OUTPUT_FILE diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am index 9ff98d12b..b5419a7a6 100644 --- a/src/exchange/Makefile.am +++ b/src/exchange/Makefile.am @@ -43,7 +43,6 @@ taler_exchange_wirewatch_LDADD = \ taler_exchange_httpd_SOURCES = \ taler-exchange-httpd.c taler-exchange-httpd.h \ - taler-exchange-httpd_admin.c taler-exchange-httpd_admin.h \ taler-exchange-httpd_db.c taler-exchange-httpd_db.h \ taler-exchange-httpd_deposit.c taler-exchange-httpd_deposit.h \ taler-exchange-httpd_keystate.c taler-exchange-httpd_keystate.h \ diff --git a/src/exchange/exchange.conf b/src/exchange/exchange.conf index 4c10b31aa..39c496ec5 100644 --- a/src/exchange/exchange.conf +++ b/src/exchange/exchange.conf @@ -36,18 +36,3 @@ PORT = 8081 # Required for wire transfers as we need to include it in the wire # transfers to enable tracking. BASE_URL = http://localhost:8081/ - - -[exchange-admin] -# Network configuration for the /admin HTTP server - -# serve via tcp socket (on PORT) -SERVE = tcp - -# Unix domain socket to listen on, -# only effective with "SERVE = unix" -UNIXPATH = ${TALER_RUNTIME_DIR}/exchange-admin.http -UNIXPATH_MODE = 660 - -# HTTP port the exchange listens to -PORT = 18080 diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index 42fe16b22..f45b5470d 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -28,7 +28,6 @@ #include #include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_mhd.h" -#include "taler-exchange-httpd_admin.h" #include "taler-exchange-httpd_deposit.h" #include "taler-exchange-httpd_refund.h" #include "taler-exchange-httpd_reserve_status.h" @@ -95,16 +94,6 @@ static unsigned int connection_timeout = 30; */ static struct MHD_Daemon *mhd; -/** - * The HTTP Daemon for /admin-requests. - */ -static struct MHD_Daemon *mhd_admin; - -/** - * Do not offer /admin API. - */ -static int no_admin; - /** * Initialize the database by creating tables and indices. */ @@ -115,33 +104,17 @@ static int init_db; */ static uint16_t serve_port; -/** - * Port to run the admin daemon on. - */ -static uint16_t serve_admin_port; - /** * Path for the unix domain-socket * to run the daemon on. */ static char *serve_unixpath; -/** - * Path for the unix domain-socket - * to run the admin daemon on. - */ -static char *serve_admin_unixpath; - /** * File mode for unix-domain socket. */ static mode_t unixpath_mode; -/** - * File mode for unix-domain socket. - */ -static mode_t unixpath_admin_mode; - /** * Function called whenever MHD is done with a request. If the @@ -307,76 +280,6 @@ handle_mhd_request (void *cls, "Only GET is allowed", 0, &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - { NULL, NULL, NULL, NULL, 0, 0 } - }; - static struct TEH_RequestHandler h404 = - { - "", NULL, "text/html", - "404: not found", 0, - &TEH_MHD_handler_static_response, MHD_HTTP_NOT_FOUND - }; - struct TEH_RequestHandler *rh; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Handling request for URL '%s'\n", - url); - if (0 == strcasecmp (method, - MHD_HTTP_METHOD_HEAD)) - method = MHD_HTTP_METHOD_GET; /* treat HEAD as GET here, MHD will do the rest */ - for (unsigned int i=0;NULL != handlers[i].url;i++) - { - rh = &handlers[i]; - if ( (0 == strcasecmp (url, - rh->url)) && - ( (NULL == rh->method) || - (0 == strcasecmp (method, - rh->method)) ) ) - return rh->handler (rh, - connection, - con_cls, - upload_data, - upload_data_size); - } - return TEH_MHD_handler_static_response (&h404, - connection, - con_cls, - upload_data, - upload_data_size); -} - - -/** - * Handle incoming administrative 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 Buffer *`) - * @return MHD result code - */ -static int -handle_mhd_admin_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[] = - { - { "/admin/add/incoming", MHD_HTTP_METHOD_POST, "application/json", - NULL, 0, - &TEH_ADMIN_handler_admin_add_incoming, MHD_HTTP_OK }, - { "/admin/add/incoming", NULL, "text/plain", - "Only POST is allowed", 0, - &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - #if HAVE_DEVELOPER /* Client crypto-interoperability test functions */ { "/test", MHD_HTTP_METHOD_POST, "application/json", @@ -452,12 +355,14 @@ handle_mhd_admin_request (void *cls, &TEH_MHD_handler_static_response, MHD_HTTP_NOT_FOUND }; struct TEH_RequestHandler *rh; - unsigned int i; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Handling request for URL '%s'\n", url); - for (i=0;NULL != handlers[i].url;i++) + if (0 == strcasecmp (method, + MHD_HTTP_METHOD_HEAD)) + method = MHD_HTTP_METHOD_GET; /* treat HEAD as GET here, MHD will do the rest */ + for (unsigned int i=0;NULL != handlers[i].url;i++) { rh = &handlers[i]; if ( (0 == strcasecmp (url, @@ -691,15 +596,6 @@ exchange_serve_process_config () TEH_VALIDATION_done (); return GNUNET_SYSERR; } - if (GNUNET_OK != - parse_port_config ("exchange-admin", - &serve_admin_port, - &serve_admin_unixpath, - &unixpath_admin_mode)) - { - TEH_VALIDATION_done (); - return GNUNET_SYSERR; - } return GNUNET_OK; } @@ -948,23 +844,19 @@ main (int argc, char *logfile = NULL; const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_option_flag ('C', - "connection-close", - "force HTTP connections to be closed after each request", - &TEH_exchange_connection_close), + "connection-close", + "force HTTP connections to be closed after each request", + &TEH_exchange_connection_close), GNUNET_GETOPT_option_cfgfile (&cfgfile), - GNUNET_GETOPT_option_flag ('D', - "disable-admin", - "do not run the /admin-HTTP server", - &no_admin), GNUNET_GETOPT_option_flag ('i', - "init-db", - "create database tables and indicies if necessary", - &init_db), + "init-db", + "create database tables and indicies if necessary", + &init_db), GNUNET_GETOPT_option_uint ('t', - "timeout", - "SECONDS", - "after how long do connections timeout by default (in seconds)", - &connection_timeout), + "timeout", + "SECONDS", + "after how long do connections timeout by default (in seconds)", + &connection_timeout), #if HAVE_DEVELOPER GNUNET_GETOPT_option_filename ('f', "file-input", @@ -982,7 +874,6 @@ main (int argc, const char *listen_pid; const char *listen_fds; int fh = -1; - int fh_admin = -1; if (0 >= GNUNET_GETOPT_run ("taler-exchange-httpd", @@ -1018,12 +909,9 @@ main (int argc, (getpid() == strtol (listen_pid, NULL, 10)) && - ( (1 == strtoul (listen_fds, - NULL, - 10)) || - (2 == strtoul (listen_fds, - NULL, - 10)) ) ) + (1 == strtoul (listen_fds, + NULL, + 10)) ) { int flags; @@ -1044,29 +932,6 @@ main (int argc, flags)) ) GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fcntl"); - - if (2 == strtoul (listen_fds, - NULL, - 10)) - { - fh_admin = 4; - flags = fcntl (fh_admin, - F_GETFD); - if ( (-1 == flags) && - (EBADF == errno) ) - { - fprintf (stderr, - "Bad listen socket passed, ignored\n"); - fh_admin = -1; - } - flags |= FD_CLOEXEC; - if ( (-1 != fh_admin) && - (0 != fcntl (fh_admin, - F_SETFD, - flags)) ) - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, - "fcntl"); - } } /* consider unix path */ @@ -1078,19 +943,6 @@ main (int argc, if (-1 == fh) return 1; } - if ( (-1 == fh_admin) && - (0 == no_admin) && - (NULL != serve_admin_unixpath) ) - { - fh_admin = open_unix_path (serve_admin_unixpath, - unixpath_admin_mode); - if (-1 == fh_admin) - { - if (-1 != fh) - GNUNET_break (0 == close (fh)); - return 1; - } - } mhd = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_PIPE_FOR_SHUTDOWN | MHD_USE_DEBUG | MHD_USE_DUAL_STACK, @@ -1112,30 +964,6 @@ main (int argc, return 1; } - if (0 == no_admin) - { - mhd_admin - = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_PIPE_FOR_SHUTDOWN | MHD_USE_DEBUG, - (-1 == fh) ? serve_admin_port : 0, - NULL, NULL, - &handle_mhd_admin_request, NULL, - MHD_OPTION_LISTEN_SOCKET, fh_admin, - MHD_OPTION_EXTERNAL_LOGGER, &handle_mhd_logs, NULL, - MHD_OPTION_NOTIFY_COMPLETED, &handle_mhd_completion_callback, NULL, - MHD_OPTION_CONNECTION_TIMEOUT, connection_timeout, -#if HAVE_DEVELOPER - MHD_OPTION_NOTIFY_CONNECTION, &connection_done, NULL, -#endif - MHD_OPTION_END); - if (NULL == mhd_admin) - { - fprintf (stderr, - "Failed to start administrative HTTP server.\n"); - MHD_stop_daemon (mhd); - return 1; - } - } - #if HAVE_DEVELOPER if (NULL != input_filename) { @@ -1157,23 +985,14 @@ main (int argc, case GNUNET_OK: case GNUNET_SYSERR: MHD_stop_daemon (mhd); - if (NULL != mhd_admin) - MHD_stop_daemon (mhd_admin); break; case GNUNET_NO: { MHD_socket sock = MHD_quiesce_daemon (mhd); - MHD_socket admin_sock; - int admin_sock_opened = GNUNET_NO; pid_t chld; int flags; /* Set flags to make 'sock' inherited by child */ - if (NULL != mhd_admin) - { - admin_sock = MHD_quiesce_daemon (mhd_admin); - admin_sock_opened = GNUNET_YES; - } flags = fcntl (sock, F_GETFD); GNUNET_assert (-1 != flags); flags &= ~FD_CLOEXEC; @@ -1197,20 +1016,13 @@ main (int argc, "dup2"); _exit (1); } - if ( (GNUNET_YES == admin_sock_opened) && - (4 != dup2 (admin_sock, 4)) ) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, - "dup2"); - _exit (1); - } /* Tell the child that it is the desired recipient for FD #3 */ GNUNET_snprintf (pids, sizeof (pids), "%u", getpid ()); setenv ("LISTEN_PID", pids, 1); - setenv ("LISTEN_FDS", (NULL != mhd_admin) ? "2" : "1", 1); + setenv ("LISTEN_FDS", "1", 1); /* Finally, exec the (presumably) more recent exchange binary */ execvp ("taler-exchange-httpd", argv); @@ -1222,25 +1034,16 @@ main (int argc, before exiting; as the listen socket is no longer used, close it here */ GNUNET_break (0 == close (sock)); - if (GNUNET_YES == admin_sock_opened) - GNUNET_break (0 == close (admin_sock)); - while ( (0 != MHD_get_daemon_info (mhd, - MHD_DAEMON_INFO_CURRENT_CONNECTIONS)->num_connections) || - ( (NULL != mhd_admin) && - (0 != MHD_get_daemon_info (mhd_admin, - MHD_DAEMON_INFO_CURRENT_CONNECTIONS)->num_connections) ) ) + while (0 != MHD_get_daemon_info (mhd, + MHD_DAEMON_INFO_CURRENT_CONNECTIONS)->num_connections) sleep (1); /* Now we're really done, practice clean shutdown */ MHD_stop_daemon (mhd); - if (NULL != mhd_admin) - MHD_stop_daemon (mhd_admin); } break; default: GNUNET_break (0); MHD_stop_daemon (mhd); - if (NULL != mhd_admin) - MHD_stop_daemon (mhd_admin); break; } TALER_EXCHANGEDB_plugin_unload (TEH_plugin); diff --git a/src/exchange/taler-exchange-httpd_admin.c b/src/exchange/taler-exchange-httpd_admin.c deleted file mode 100644 index f65b9c38a..000000000 --- a/src/exchange/taler-exchange-httpd_admin.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014, 2015 GNUnet e.V. - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, see -*/ -/** - * @file taler-exchange-httpd_admin.c - * @brief Handle /admin/ requests - * @author Christian Grothoff - */ -#include "platform.h" -#include -#include -#include "taler-exchange-httpd_admin.h" -#include "taler-exchange-httpd_parsing.h" -#include "taler-exchange-httpd_responses.h" -#include "taler-exchange-httpd_validation.h" - - -/** - * Closure for #admin_add_incoming_transaction() - */ -struct AddIncomingContext -{ - /** - * public key of the reserve - */ - struct TALER_ReservePublicKeyP reserve_pub; - - /** - * amount to add to the reserve - */ - struct TALER_Amount amount; - - /** - * When did we receive the wire transfer - */ - struct GNUNET_TIME_Absolute execution_time; - - /** - * which account send the funds - */ - json_t *sender_account_details; - - /** - * Information that uniquely identifies the transfer - */ - json_t *transfer_details; - - /** - * Set to the transaction status. - */ - enum GNUNET_DB_QueryStatus qs; -}; - - -/** - * Add an incoming transaction to the database. Checks if the - * transaction is fresh (not a duplicate) and if so adds it to the - * database. - * - * If it returns a non-error code, the transaction logic MUST - * NOT queue a MHD response. IF it returns an hard error, the - * transaction logic MUST queue a MHD response and set @a mhd_ret. IF - * it returns the soft error code, the function MAY be called again to - * retry and MUST not queue a MHD response. - * - * @param cls closure with the `struct AddIncomingContext *` - * @param connection MHD request which triggered the transaction - * @param session database session to use - * @param[out] mhd_ret set to MHD response status for @a connection, - * if transaction failed (!) - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -admin_add_incoming_transaction (void *cls, - struct MHD_Connection *connection, - struct TALER_EXCHANGEDB_Session *session, - int *mhd_ret) -{ - struct AddIncomingContext *aic = cls; - void *json_str; - - json_str = json_dumps (aic->transfer_details, - JSON_INDENT(2)); - if (NULL == json_str) - { - GNUNET_break (0); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_PARSER_OUT_OF_MEMORY); - return GNUNET_DB_STATUS_HARD_ERROR; - } - aic->qs = TEH_plugin->reserves_in_insert (TEH_plugin->cls, - session, - &aic->reserve_pub, - &aic->amount, - aic->execution_time, - aic->sender_account_details, - json_str, - strlen (json_str)); - free (json_str); - - if (GNUNET_DB_STATUS_HARD_ERROR == aic->qs) - { - GNUNET_break (0); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_ADMIN_ADD_INCOMING_DB_STORE); - return GNUNET_DB_STATUS_HARD_ERROR; - } - return aic->qs; -} - - -/** - * Handle a "/admin/add/incoming" request. Parses the - * given "reserve_pub", "amount", "transaction" and "h_wire" - * details and adds the respective transaction to the database. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data - * @return MHD result code - */ -int -TEH_ADMIN_handler_admin_add_incoming (struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) -{ - struct AddIncomingContext aic; - enum TALER_ErrorCode ec; - char *emsg; - json_t *root; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("reserve_pub", &aic.reserve_pub), - TALER_JSON_spec_amount ("amount", &aic.amount), - GNUNET_JSON_spec_absolute_time ("execution_date", &aic.execution_time), - GNUNET_JSON_spec_json ("sender_account_details", &aic.sender_account_details), - GNUNET_JSON_spec_json ("transfer_details", &aic.transfer_details), - GNUNET_JSON_spec_end () - }; - int res; - int mhd_ret; - - res = TEH_PARSE_post_json (connection, - connection_cls, - upload_data, - upload_data_size, - &root); - if (GNUNET_SYSERR == res) - return MHD_NO; - if ( (GNUNET_NO == res) || - (NULL == root) ) - return MHD_YES; - res = TEH_PARSE_json_data (connection, - root, - spec); - json_decref (root); - if (GNUNET_OK != res) - { - GNUNET_break_op (0); - json_decref (root); - return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; - } - if (TALER_EC_NONE != - (ec = TEH_json_validate_wireformat (aic.sender_account_details, - GNUNET_NO, - &emsg))) - { - GNUNET_JSON_parse_free (spec); - mhd_ret = TEH_RESPONSE_reply_external_error (connection, - ec, - emsg); - GNUNET_free (emsg); - return mhd_ret; - } - if (0 != strcasecmp (aic.amount.currency, - TEH_exchange_currency_string)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Exchange uses currency `%s', but /admin/add/incoming tried to use currency `%s'\n", - TEH_exchange_currency_string, - aic.amount.currency); - GNUNET_JSON_parse_free (spec); - return TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_ADMIN_ADD_INCOMING_CURRENCY_UNSUPPORTED, - "amount:currency"); - } - res = TEH_DB_run_transaction (connection, - &mhd_ret, - &admin_add_incoming_transaction, - &aic); - GNUNET_JSON_parse_free (spec); - if (GNUNET_OK != res) - return mhd_ret; - return TEH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:s}", - "status", - (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == aic.qs) - ? "NEW" - : "DUP"); -} - -/* end of taler-exchange-httpd_admin.c */ diff --git a/src/exchange/taler-exchange-httpd_admin.h b/src/exchange/taler-exchange-httpd_admin.h deleted file mode 100644 index 8ed1e3d54..000000000 --- a/src/exchange/taler-exchange-httpd_admin.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014 GNUnet e.V. - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, see -*/ -/** - * @file taler-exchange-httpd_admin.h - * @brief Handle /admin/ requests - * @author Christian Grothoff - */ -#ifndef TALER_EXCHANGE_HTTPD_ADMIN_H -#define TALER_EXCHANGE_HTTPD_ADMIN_H - -#include -#include "taler-exchange-httpd.h" - -/** - * Handle a "/admin/add/incoming" request. Parses the - * given "reserve_pub", "amount", "transaction" and "h_wire" - * details and adds the respective transaction to the database. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data - * @return MHD result code - */ -int -TEH_ADMIN_handler_admin_add_incoming (struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); - -#endif