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