diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/mint-lib/mint_api_admin.c | 112 | ||||
| -rw-r--r-- | src/mint-lib/mint_api_context.c | 133 | ||||
| -rw-r--r-- | src/mint-lib/mint_api_context.h | 82 | ||||
| -rw-r--r-- | src/mint-lib/mint_api_deposit.c | 115 | ||||
| -rw-r--r-- | src/mint-lib/mint_api_handle.c | 160 | ||||
| -rw-r--r-- | src/mint-lib/mint_api_withdraw.c | 208 | ||||
| -rw-r--r-- | src/mint/taler-mint-httpd_admin.c | 1 | ||||
| -rw-r--r-- | src/mint/taler-mint-httpd_parsing.c | 31 | 
8 files changed, 303 insertions, 539 deletions
| diff --git a/src/mint-lib/mint_api_admin.c b/src/mint-lib/mint_api_admin.c index 47158665..472b02e7 100644 --- a/src/mint-lib/mint_api_admin.c +++ b/src/mint-lib/mint_api_admin.c @@ -32,15 +32,6 @@  /** - * Print JSON parsing related error information - */ -#define JSON_WARN(error)                                                \ -    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,                              \ -                "JSON parsing failed at %s:%u: %s (%s)",                \ -                __FILE__, __LINE__, error.text, error.source) - - -/**   * @brief An admin/add/incoming Handle   */  struct TALER_MINT_AdminAddIncomingHandle @@ -84,18 +75,7 @@ struct TALER_MINT_AdminAddIncomingHandle    /**     * Download buffer     */ -  void *buf; - -  /** -   * The size of the download buffer -   */ -  size_t buf_size; - -  /** -   * Error code (based on libc errno) if we failed to download -   * (i.e. response too large). -   */ -  int eno; +  struct MAC_DownloadBuffer db;  }; @@ -113,35 +93,12 @@ handle_admin_add_incoming_finished (void *cls,  {    struct TALER_MINT_AdminAddIncomingHandle *aai = cls;    long response_code; -  json_error_t error;    json_t *json;    aai->job = NULL; -  json = NULL; -  if (0 == aai->eno) -  { -    json = json_loadb (aai->buf, -                       aai->buf_size, -                       JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK, -                       &error); -    if (NULL == json) -    { -      JSON_WARN (error); -      response_code = 0; -    } -  } -  if (NULL != json) -  { -    if (CURLE_OK != -        curl_easy_getinfo (eh, -                           CURLINFO_RESPONSE_CODE, -                           &response_code)) -    { -      /* unexpected error... */ -      GNUNET_break (0); -      response_code = 0; -    } -  } +  json = MAC_download_get_result (&aai->db, +                                  eh, +                                  &response_code);    switch (response_code)    {    case 0: @@ -170,6 +127,9 @@ handle_admin_add_incoming_finished (void *cls,      break;    default:      /* unexpected response code */ +    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                "Unexpected response code %u\n", +                response_code);      GNUNET_break (0);      response_code = 0;      break; @@ -183,49 +143,6 @@ handle_admin_add_incoming_finished (void *cls,  /** - * Callback used when downloading the reply to a /admin/add/incoming - * request.  Just appends all of the data to the `buf` in the `struct - * TALER_MINT_AdminAddIncomingHandle` for further processing. The size - * of the download is limited to #GNUNET_MAX_MALLOC_CHECKED, if the - * download exceeds this size, we abort with an error. - * - * @param bufptr data downloaded via HTTP - * @param size size of an item in @a bufptr - * @param nitems number of items in @a bufptr - * @param cls the `struct TALER_MINT_DepositHandle` - * @return number of bytes processed from @a bufptr - */ -static int -admin_add_incoming_download_cb (char *bufptr, -                                size_t size, -                                size_t nitems, -                                void *cls) -{ -  struct TALER_MINT_AdminAddIncomingHandle *aai = cls; -  size_t msize; -  void *buf; - -  if (0 == size * nitems) -  { -    /* Nothing (left) to do */ -    return 0; -  } -  msize = size * nitems; -  if ( (msize + aai->buf_size) >= GNUNET_MAX_MALLOC_CHECKED) -  { -    aai->eno = ENOMEM; -    return 0; /* signals an error to curl */ -  } -  aai->buf = GNUNET_realloc (aai->buf, -                             aai->buf_size + msize); -  buf = aai->buf + aai->buf_size; -  memcpy (buf, bufptr, msize); -  aai->buf_size += msize; -  return msize; -} - - -/**   * Notify the mint that we have received an incoming transaction   * which fills a reserve.  Note that this API is an administrative   * API and thus not accessible to typical mint clients, but only @@ -265,7 +182,7 @@ TALER_MINT_admin_add_incoming (struct TALER_MINT_Handle *mint,      return NULL;    }    admin_obj = json_pack ("{s:o, s:o," /* reserve_pub/amount */ -                         " s:o, s:o}", /* execution_Date/wire */ +                         " s:o, s:O}", /* execution_Date/wire */                           "reserve_pub", TALER_json_from_data (reserve_pub,                                                                 sizeof (*reserve_pub)),                           "amount", TALER_json_from_amount (amount), @@ -297,21 +214,15 @@ TALER_MINT_admin_add_incoming (struct TALER_MINT_Handle *mint,    GNUNET_assert (CURLE_OK ==                   curl_easy_setopt (eh,                                     CURLOPT_WRITEFUNCTION, -                                   &admin_add_incoming_download_cb)); +                                   &MAC_download_cb));    GNUNET_assert (CURLE_OK ==                   curl_easy_setopt (eh,                                     CURLOPT_WRITEDATA, -                                   aai)); -  GNUNET_assert (NULL != (aai->headers = -                          curl_slist_append (aai->headers, -                                             "Content-Type: application/json"))); -  GNUNET_assert (CURLE_OK == -                 curl_easy_setopt (eh, -                                   CURLOPT_HTTPHEADER, -                                   aai->headers)); +                                   &aai->db));    ctx = MAH_handle_to_context (mint);    aai->job = MAC_job_add (ctx,                            eh, +                          GNUNET_YES,                            &handle_admin_add_incoming_finished,                            aai);    return aai; @@ -333,6 +244,7 @@ TALER_MINT_admin_add_incoming_cancel (struct TALER_MINT_AdminAddIncomingHandle *      aai->job = NULL;    }    curl_slist_free_all (aai->headers); +  GNUNET_free_non_null (aai->db.buf);    GNUNET_free (aai->url);    GNUNET_free (aai->json_enc);    GNUNET_free (aai); diff --git a/src/mint-lib/mint_api_context.c b/src/mint-lib/mint_api_context.c index 2daba89e..9beeef14 100644 --- a/src/mint-lib/mint_api_context.c +++ b/src/mint-lib/mint_api_context.c @@ -34,9 +34,18 @@   * @param code what was the curl error code   */  #define CURL_STRERROR(type, function, code)      \ - GNUNET_log (type, "Curl function `%s' has failed at `%s:%d' with error: %s", \ + GNUNET_log (type,                               \ +             "Curl function `%s' has failed at `%s:%d' with error: %s\n", \               function, __FILE__, __LINE__, curl_easy_strerror (code)); +/** + * Print JSON parsing related error information + */ +#define JSON_WARN(error)                                                \ +    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,                              \ +                "JSON parsing failed at %s:%u: %s (%s)\n",              \ +                __FILE__, __LINE__, error.text, error.source) +  /**   * Failsafe flag. Raised if our constructor fails to initialize @@ -109,6 +118,12 @@ struct TALER_MINT_Context     */    struct MAC_Job *jobs_tail; +  /** +   * HTTP header "application/json", created once and used +   * for all requests that need it. +   */ +  struct curl_slist *json_header; +  }; @@ -146,6 +161,9 @@ TALER_MINT_init ()    ctx = GNUNET_new (struct TALER_MINT_Context);    ctx->multi = multi;    ctx->share = share; +  GNUNET_assert (NULL != (ctx->json_header = +                          curl_slist_append (NULL, +                                             "Content-Type: application/json")));    return ctx;  } @@ -157,20 +175,31 @@ TALER_MINT_init ()   * instead use #MAC_easy_to_closure to extract the @a jcc_cls argument   * from a valid @a eh afterwards.   * + * This function modifies the CURL handle to add the + * "Content-Type: application/json" header if @a add_json is set. + *   * @param ctx context to execute the job in   * @param eh curl easy handle for the request, will   *           be executed AND cleaned up + * @param add_json add "application/json" content type header   * @param jcc callback to invoke upon completion   * @param jcc_cls closure for @a jcc   */  struct MAC_Job *  MAC_job_add (struct TALER_MINT_Context *ctx,               CURL *eh, +             int add_json,               MAC_JobCompletionCallback jcc,               void *jcc_cls)  {    struct MAC_Job *job; +  if (GNUNET_YES == add_json) +    GNUNET_assert (CURLE_OK == +                   curl_easy_setopt (eh, +                                     CURLOPT_HTTPHEADER, +                                     ctx->json_header)); +    job = GNUNET_new (struct MAC_Job);    job->easy_handle = eh;    job->ctx = ctx; @@ -333,11 +362,113 @@ TALER_MINT_fini (struct TALER_MINT_Context *ctx)    GNUNET_assert (NULL == ctx->jobs_head);    curl_share_cleanup (ctx->share);    curl_multi_cleanup (ctx->multi); +  curl_slist_free_all (ctx->json_header);    GNUNET_free (ctx);  }  /** + * Callback used when downloading the reply to an HTTP request. + * Just appends all of the data to the `buf` in the + * `struct MAC_DownloadBuffer` for further processing. The size of + * the download is limited to #GNUNET_MAX_MALLOC_CHECKED, if + * the download exceeds this size, we abort with an error. + * + * @param bufptr data downloaded via HTTP + * @param size size of an item in @a bufptr + * @param nitems number of items in @a bufptr + * @param cls the `struct KeysRequest` + * @return number of bytes processed from @a bufptr + */ +size_t +MAC_download_cb (char *bufptr, +                 size_t size, +                 size_t nitems, +                 void *cls) +{ +  struct MAC_DownloadBuffer *db = cls; +  size_t msize; +  void *buf; + +  if (0 == size * nitems) +  { +    /* Nothing (left) to do */ +    return 0; +  } +  msize = size * nitems; +  if ( (msize + db->buf_size) >= GNUNET_MAX_MALLOC_CHECKED) +  { +    db->eno = ENOMEM; +    return 0; /* signals an error to curl */ +  } +  db->buf = GNUNET_realloc (db->buf, +                            db->buf_size + msize); +  buf = db->buf + db->buf_size; +  memcpy (buf, bufptr, msize); +  db->buf_size += msize; +  return msize; +} + + +/** + * Obtain information about the final result about the + * HTTP download. If the download was successful, parses + * the JSON in the @a db and returns it. Also returns + * the HTTP @a response_code.  If the download failed, + * the return value is NULL.  The response code is set + * in any case, on download errors to zero. + * + * Calling this function also cleans up @a db. + * + * @param db download buffer + * @param eh CURL handle (to get the response code) + * @param[out] response_code set to the HTTP response code + *             (or zero if we aborted the download, i.e. + *              because the response was too big, or if + *              the JSON we received was malformed). + * @return NULL if downloading a JSON reply failed + */ +json_t * +MAC_download_get_result (struct MAC_DownloadBuffer *db, +                         CURL *eh, +                         long *response_code) +{ +  json_t *json; +  json_error_t error; + +  json = NULL; +  if (0 == db->eno) +  { +    json = json_loadb (db->buf, +                       db->buf_size, +                       JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK, +                       &error); +    if (NULL == json) +    { +      JSON_WARN (error); +      *response_code = 0; +    } +  } +  GNUNET_free_non_null (db->buf); +  db->buf = NULL; +  db->buf_size = 0; +  if (NULL != json) +  { +    if (CURLE_OK != +        curl_easy_getinfo (eh, +                           CURLINFO_RESPONSE_CODE, +                           response_code)) +    { +      /* unexpected error... */ +      GNUNET_break (0); +      *response_code = 0; +    } +  } +  return json; +} + + +/**   * Initial global setup logic, specifically runs the Curl setup.   */  __attribute__ ((constructor)) diff --git a/src/mint-lib/mint_api_context.h b/src/mint-lib/mint_api_context.h index 235c32bd..c545a3fe 100644 --- a/src/mint-lib/mint_api_context.h +++ b/src/mint-lib/mint_api_context.h @@ -50,15 +50,20 @@ typedef void   * instead use #MAC_easy_to_closure to extract the @a jcc_cls argument   * from a valid @a eh afterwards.   * + * This function modifies the CURL handle to add the + * "Content-Type: application/json" header if @a add_json is set. + *   * @param ctx context to execute the job in   * @param eh curl easy handle for the request, will   *           be executed AND cleaned up + * @param add_json add "application/json" content type header   * @param jcc callback to invoke upon completion   * @param jcc_cls closure for @a jcc   */  struct MAC_Job *  MAC_job_add (struct TALER_MINT_Context *ctx,               CURL *eh, +             int add_json,               MAC_JobCompletionCallback jcc,               void *jcc_cls); @@ -84,4 +89,81 @@ void  MAC_job_cancel (struct MAC_Job *job); +/** + * Buffer data structure we use to buffer the HTTP download + * before giving it to the JSON parser. + */ +struct MAC_DownloadBuffer +{ + +  /** +   * Download buffer +   */ +  void *buf; + +  /** +   * The size of the download buffer +   */ +  size_t buf_size; + +  /** +   * Error code (based on libc errno) if we failed to download +   * (i.e. response too large). +   */ +  int eno; + +}; + + +/** + * Callback used when downloading the reply to an HTTP request. + * Just appends all of the data to the `buf` in the + * `struct MAC_DownloadBuffer` for further processing. The size of + * the download is limited to #GNUNET_MAX_MALLOC_CHECKED, if + * the download exceeds this size, we abort with an error. + * + * Should be used by the various routines as the + * CURLOPT_WRITEFUNCTION.  A `struct MAC_DownloadBuffer` needs to be + * passed to the CURLOPT_WRITEDATA. + * + * Afterwards, `eno` needs to be checked to ensure that the download + * completed correctly. + * + * @param bufptr data downloaded via HTTP + * @param size size of an item in @a bufptr + * @param nitems number of items in @a bufptr + * @param cls the `struct KeysRequest` + * @return number of bytes processed from @a bufptr + */ +size_t +MAC_download_cb (char *bufptr, +                 size_t size, +                 size_t nitems, +                 void *cls); + + +/** + * Obtain information about the final result about the + * HTTP download. If the download was successful, parses + * the JSON in the @a db and returns it. Also returns + * the HTTP @a response_code.  If the download failed, + * the return value is NULL.  The response code is set + * in any case, on download errors to zero. + * + * Calling this function also cleans up @a db. + * + * @param db download buffer + * @param eh CURL handle (to get the response code) + * @param[out] response_code set to the HTTP response code + *             (or zero if we aborted the download, i.e. + *              because the response was too big, or if + *              the JSON we received was malformed). + * @return NULL if downloading a JSON reply failed + */ +json_t * +MAC_download_get_result (struct MAC_DownloadBuffer *db, +                         CURL *eh, +                         long *response_code); + +  /* end of mint_api_context.h */ diff --git a/src/mint-lib/mint_api_deposit.c b/src/mint-lib/mint_api_deposit.c index 34915eaf..7be88a88 100644 --- a/src/mint-lib/mint_api_deposit.c +++ b/src/mint-lib/mint_api_deposit.c @@ -33,15 +33,6 @@  /** - * Print JSON parsing related error information - */ -#define JSON_WARN(error)                                                \ -    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,                              \ -                "JSON parsing failed at %s:%u: %s (%s)\n",              \ -                __FILE__, __LINE__, error.text, error.source) - - -/**   * @brief A Deposit Handle   */  struct TALER_MINT_DepositHandle @@ -68,11 +59,6 @@ struct TALER_MINT_DepositHandle    struct MAC_Job *job;    /** -   * HTTP headers for the request. -   */ -  struct curl_slist *headers; - -  /**     * Function to call with the result.     */    TALER_MINT_DepositResultCallback cb; @@ -85,7 +71,7 @@ struct TALER_MINT_DepositHandle    /**     * Download buffer     */ -  void *buf; +  struct MAC_DownloadBuffer db;    /**     * Information the mint should sign in response. @@ -102,17 +88,6 @@ struct TALER_MINT_DepositHandle     */    struct TALER_Amount coin_value; -  /** -   * The size of the download buffer -   */ -  size_t buf_size; - -  /** -   * Error code (based on libc errno) if we failed to download -   * (i.e. response too large). -   */ -  int eno; -  }; @@ -321,35 +296,12 @@ handle_deposit_finished (void *cls,  {    struct TALER_MINT_DepositHandle *dh = cls;    long response_code; -  json_error_t error;    json_t *json;    dh->job = NULL; -  json = NULL; -  if (0 == dh->eno) -  { -    json = json_loadb (dh->buf, -                       dh->buf_size, -                       JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK, -                       &error); -    if (NULL == json) -    { -      JSON_WARN (error); -      response_code = 0; -    } -  } -  if (NULL != json) -  { -    if (CURLE_OK != -        curl_easy_getinfo (eh, -                           CURLINFO_RESPONSE_CODE, -                           &response_code)) -    { -      /* unexpected error... */ -      GNUNET_break (0); -      response_code = 0; -    } -  } +  json = MAC_download_get_result (&dh->db, +                                  eh, +                                  &response_code);    switch (response_code)    {    case 0: @@ -485,49 +437,6 @@ verify_signatures (const struct TALER_MINT_DenomPublicKey *dki,  /** - * Callback used when downloading the reply to a /deposit request. - * Just appends all of the data to the `buf` in the - * `struct TALER_MINT_DepositHandle` for further processing. The size of - * the download is limited to #GNUNET_MAX_MALLOC_CHECKED, if - * the download exceeds this size, we abort with an error. - * - * @param bufptr data downloaded via HTTP - * @param size size of an item in @a bufptr - * @param nitems number of items in @a bufptr - * @param cls the `struct TALER_MINT_DepositHandle` - * @return number of bytes processed from @a bufptr - */ -static int -deposit_download_cb (char *bufptr, -                     size_t size, -                     size_t nitems, -                     void *cls) -{ -  struct TALER_MINT_DepositHandle *dh = cls; -  size_t msize; -  void *buf; - -  if (0 == size * nitems) -  { -    /* Nothing (left) to do */ -    return 0; -  } -  msize = size * nitems; -  if ( (msize + dh->buf_size) >= GNUNET_MAX_MALLOC_CHECKED) -  { -    dh->eno = ENOMEM; -    return 0; /* signals an error to curl */ -  } -  dh->buf = GNUNET_realloc (dh->buf, -                            dh->buf_size + msize); -  buf = dh->buf + dh->buf_size; -  memcpy (buf, bufptr, msize); -  dh->buf_size += msize; -  return msize; -} - - -/**   * Submit a deposit permission to the mint and get the mint's response.   * Note that while we return the response verbatim to the caller for   * further processing, we do already verify that the response is @@ -624,7 +533,7 @@ TALER_MINT_deposit (struct TALER_MINT_Handle *mint,      return NULL;    } -  deposit_obj = json_pack ("{s:o, s:o," /* f/wire */ +  deposit_obj = json_pack ("{s:o, s:O," /* f/wire */                             " s:o, s:o," /* H_wire, H_contract */                             " s:o, s:o," /* coin_pub, denom_pub */                             " s:o, s:o," /* ub_sig, timestamp */ @@ -691,21 +600,15 @@ TALER_MINT_deposit (struct TALER_MINT_Handle *mint,    GNUNET_assert (CURLE_OK ==                   curl_easy_setopt (eh,                                     CURLOPT_WRITEFUNCTION, -                                   &deposit_download_cb)); +                                   &MAC_download_cb));    GNUNET_assert (CURLE_OK ==                   curl_easy_setopt (eh,                                     CURLOPT_WRITEDATA, -                                   dh)); -  GNUNET_assert (NULL != (dh->headers = -                          curl_slist_append (dh->headers, -                                             "Content-Type: application/json"))); -  GNUNET_assert (CURLE_OK == -                 curl_easy_setopt (eh, -                                   CURLOPT_HTTPHEADER, -                                   dh->headers)); +                                   &dh->db));    ctx = MAH_handle_to_context (mint);    dh->job = MAC_job_add (ctx,                           eh, +                         GNUNET_YES,                           &handle_deposit_finished,                           dh);    return dh; @@ -726,7 +629,7 @@ TALER_MINT_deposit_cancel (struct TALER_MINT_DepositHandle *deposit)      MAC_job_cancel (deposit->job);      deposit->job = NULL;    } -  curl_slist_free_all (deposit->headers); +  GNUNET_free_non_null (deposit->db.buf);    GNUNET_free (deposit->url);    GNUNET_free (deposit->json_enc);    GNUNET_free (deposit); diff --git a/src/mint-lib/mint_api_handle.c b/src/mint-lib/mint_api_handle.c index 88a4f933..f5e26ff1 100644 --- a/src/mint-lib/mint_api_handle.c +++ b/src/mint-lib/mint_api_handle.c @@ -45,14 +45,6 @@  /** - * Print JSON parsing related error information - */ -#define JSON_WARN(error)                                                \ -    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,                              \ -                "JSON parsing failed at %s:%u: %s (%s)",                \ -                __FILE__, __LINE__, error.text, error.source) - -/**   * Stages of initialization for the `struct TALER_MINT_Handle`   */  enum MintHandleState @@ -149,73 +141,14 @@ struct KeysRequest    struct MAC_Job *job;    /** -   * Error buffer for Curl. Do we need this? -   */ -  char emsg[CURL_ERROR_SIZE]; - -  /** -   * Download buffer -   */ -  void *buf; - -  /** -   * The size of the download buffer -   */ -  size_t buf_size; - -  /** -   * Error code (based on libc errno) if we failed to download -   * (i.e. response too large). +   * Data structure for the download.     */ -  int eno; +  struct MAC_DownloadBuffer db;  };  /** - * Callback used when downloading the reply to a /keys request. - * Just appends all of the data to the `buf` in the - * `struct KeysRequest` for further processing. The size of - * the download is limited to #GNUNET_MAX_MALLOC_CHECKED, if - * the download exceeds this size, we abort with an error. - * - * @param bufptr data downloaded via HTTP - * @param size size of an item in @a bufptr - * @param nitems number of items in @a bufptr - * @param cls the `struct KeysRequest` - * @return number of bytes processed from @a bufptr - */ -static size_t -keys_download_cb (char *bufptr, -                  size_t size, -                  size_t nitems, -                  void *cls) -{ -  struct KeysRequest *kr = cls; -  size_t msize; -  void *buf; - -  if (0 == size * nitems) -  { -    /* Nothing (left) to do */ -    return 0; -  } -  msize = size * nitems; -  if ( (msize + kr->buf_size) >= GNUNET_MAX_MALLOC_CHECKED) -  { -    kr->eno = ENOMEM; -    return 0; /* signals an error to curl */ -  } -  kr->buf = GNUNET_realloc (kr->buf, -                            kr->buf_size + msize); -  buf = kr->buf + kr->buf_size; -  memcpy (buf, bufptr, msize); -  kr->buf_size += msize; -  return msize; -} - - -/**   * Release memory occupied by a keys request.   * Note that this does not cancel the request   * itself. @@ -225,7 +158,7 @@ keys_download_cb (char *bufptr,  static void  free_keys_request (struct KeysRequest *kr)  { -  GNUNET_free_non_null (kr->buf); +  GNUNET_free_non_null (kr->db.buf);    GNUNET_free (kr->url);    GNUNET_free (kr);  } @@ -493,7 +426,6 @@ decode_keys_json (json_t *resp_obj,                                     hash_context));      }    } -  return GNUNET_OK;    /* FIXME: parse the auditor keys (#3847) */ @@ -522,48 +454,6 @@ decode_keys_json (json_t *resp_obj,  /** - * We have successfully received the reply to the /keys - * request from the mint. We now need to parse the reply - * and, if successful, store the resulting information - * in the `key_data` structure. - * - * @param kr key request with all of the data to parse - *        and references to the `struct TALER_MINT_Handle` - *        where we need to store the result - * @return #GNUNET_OK on success, - *         #GNUNET_SYSERR on failure - */ -static int -parse_response_keys_get (struct KeysRequest *kr) -{ -  json_t *resp_obj; -  json_error_t error; -  int ret; - -  resp_obj = json_loadb (kr->buf, -                         kr->buf_size, -                         JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK, -                         &error); -  if (NULL == resp_obj) -  { -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "Unable to parse received /keys data as JSON object\n"); -    GNUNET_free_non_null (kr->buf); -    kr->buf = NULL; -    kr->buf_size = 0; -    return GNUNET_SYSERR; -  } -  GNUNET_free_non_null (kr->buf); -  kr->buf = NULL; -  kr->buf_size = 0; -  ret = decode_keys_json (resp_obj, -                          &kr->mint->key_data); -  json_decref (resp_obj); -  return ret; -} - - -/**   * Callback used when downloading the reply to a /keys request   * is complete.   * @@ -576,35 +466,32 @@ keys_completed_cb (void *cls,  {    struct KeysRequest *kr = cls;    struct TALER_MINT_Handle *mint = kr->mint; +  json_t *resp_obj;    long response_code; -  /* FIXME: might want to check response code? */ -  if (CURLE_OK != -      curl_easy_getinfo (eh, -                         CURLINFO_RESPONSE_CODE, -                         &response_code)) -  { -    /* unexpected error... */ -    GNUNET_break (0); -    response_code = 0; -  } +  resp_obj = MAC_download_get_result (&kr->db, +                                      eh, +                                      &response_code);    switch (response_code) {    case 0: -    kr->eno = 1;      break;    case MHD_HTTP_OK: +    if ( (NULL == resp_obj) || +         (GNUNET_OK != +          decode_keys_json (resp_obj, +                            &kr->mint->key_data)) ) +      response_code = 0;      break;    default: -    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, -                "Mint returned status code %u for /keys\n", +    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                "Unexpected response code %u\n",                  response_code); -    kr->eno = 1;      break;    } +  if (NULL != resp_obj) +    json_decref (resp_obj); -  if ( (0 != kr->eno) || -       (GNUNET_OK != -        parse_response_keys_get (kr)) ) +  if (MHD_HTTP_OK != response_code)    {      mint->kr = NULL;      free_keys_request (kr); @@ -724,18 +611,15 @@ TALER_MINT_connect (struct TALER_MINT_Context *ctx,                                     kr->url));    GNUNET_assert (CURLE_OK ==                   curl_easy_setopt (c, -                                   CURLOPT_ERRORBUFFER, -                                   kr->emsg)); -  GNUNET_assert (CURLE_OK == -                 curl_easy_setopt (c,                                     CURLOPT_WRITEFUNCTION, -                                   &keys_download_cb)); +                                   &MAC_download_cb));    GNUNET_assert (CURLE_OK ==                   curl_easy_setopt (c,                                     CURLOPT_WRITEDATA, -                                   kr)); +                                   &kr->db));    kr->job = MAC_job_add (mint->ctx,                           c, +                         GNUNET_NO,                           &keys_completed_cb,                           kr);    mint->kr = kr; @@ -751,6 +635,8 @@ TALER_MINT_connect (struct TALER_MINT_Context *ctx,  void  TALER_MINT_disconnect (struct TALER_MINT_Handle *mint)  { +  unsigned int i; +    if (NULL != mint->kr)    {      MAC_job_cancel (mint->kr->job); @@ -760,6 +646,8 @@ TALER_MINT_disconnect (struct TALER_MINT_Handle *mint)    GNUNET_array_grow (mint->key_data.sign_keys,                       mint->key_data.num_sign_keys,                       0); +  for (i=0;i<mint->key_data.num_denom_keys;i++) +    GNUNET_CRYPTO_rsa_public_key_free (mint->key_data.denom_keys[i].key.rsa_public_key);    GNUNET_array_grow (mint->key_data.denom_keys,                       mint->key_data.num_denom_keys,                       0); diff --git a/src/mint-lib/mint_api_withdraw.c b/src/mint-lib/mint_api_withdraw.c index 157d2db7..e7a1a61d 100644 --- a/src/mint-lib/mint_api_withdraw.c +++ b/src/mint-lib/mint_api_withdraw.c @@ -31,15 +31,6 @@  #include "taler_signatures.h" -/** - * Print JSON parsing related error information - */ -#define JSON_WARN(error)                                                \ -    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,                              \ -                "JSON parsing failed at %s:%u: %s (%s)\n",              \ -                __FILE__, __LINE__, error.text, error.source) - -  /* ********************** /withdraw/status ********************** */  /** @@ -81,18 +72,7 @@ struct TALER_MINT_WithdrawStatusHandle    /**     * Download buffer     */ -  void *buf; - -  /** -   * The size of the download buffer -   */ -  size_t buf_size; - -  /** -   * Error code (based on libc errno) if we failed to download -   * (i.e. response too large). -   */ -  int eno; +  struct MAC_DownloadBuffer db;  }; @@ -295,35 +275,12 @@ handle_withdraw_status_finished (void *cls,  {    struct TALER_MINT_WithdrawStatusHandle *wsh = cls;    long response_code; -  json_error_t error;    json_t *json;    wsh->job = NULL; -  json = NULL; -  if (0 == wsh->eno) -  { -    json = json_loadb (wsh->buf, -                       wsh->buf_size, -                       JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK, -                       &error); -    if (NULL == json) -    { -      JSON_WARN (error); -      response_code = 0; -    } -  } -  if (NULL != json) -  { -    if (CURLE_OK != -        curl_easy_getinfo (eh, -                           CURLINFO_RESPONSE_CODE, -                           &response_code)) -    { -      /* unexpected error... */ -      GNUNET_break (0); -      response_code = 0; -    } -  } +  json = MAC_download_get_result (&wsh->db, +                                  eh, +                                  &response_code);    switch (response_code)    {    case 0: @@ -404,6 +361,9 @@ handle_withdraw_status_finished (void *cls,      break;    default:      /* unexpected response code */ +    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                "Unexpected response code %u\n", +                response_code);      GNUNET_break (0);      response_code = 0;      break; @@ -420,49 +380,6 @@ handle_withdraw_status_finished (void *cls,  /** - * Callback used when downloading the reply to a /withdraw/status request. - * Just appends all of the data to the `buf` in the - * `struct TALER_MINT_WithdrawStatusHandle` for further processing. The size of - * the download is limited to #GNUNET_MAX_MALLOC_CHECKED, if - * the download exceeds this size, we abort with an error. - * - * @param bufptr data downloaded via HTTP - * @param size size of an item in @a bufptr - * @param nitems number of items in @a bufptr - * @param cls the `struct TALER_MINT_DepositHandle` - * @return number of bytes processed from @a bufptr - */ -static int -withdraw_status_download_cb (char *bufptr, -                             size_t size, -                             size_t nitems, -                             void *cls) -{ -  struct TALER_MINT_WithdrawStatusHandle *wsh = cls; -  size_t msize; -  void *buf; - -  if (0 == size * nitems) -  { -    /* Nothing (left) to do */ -    return 0; -  } -  msize = size * nitems; -  if ( (msize + wsh->buf_size) >= GNUNET_MAX_MALLOC_CHECKED) -  { -    wsh->eno = ENOMEM; -    return 0; /* signals an error to curl */ -  } -  wsh->buf = GNUNET_realloc (wsh->buf, -                            wsh->buf_size + msize); -  buf = wsh->buf + wsh->buf_size; -  memcpy (buf, bufptr, msize); -  wsh->buf_size += msize; -  return msize; -} - - -/**   * Submit a request to obtain the transaction history of a reserve   * from the mint.  Note that while we return the full response to the   * caller for further processing, we do already verify that the @@ -519,14 +436,15 @@ TALER_MINT_withdraw_status (struct TALER_MINT_Handle *mint,    GNUNET_assert (CURLE_OK ==                   curl_easy_setopt (eh,                                     CURLOPT_WRITEFUNCTION, -                                   &withdraw_status_download_cb)); +                                   &MAC_download_cb));    GNUNET_assert (CURLE_OK ==                   curl_easy_setopt (eh,                                     CURLOPT_WRITEDATA, -                                   wsh)); +                                   &wsh->db));    ctx = MAH_handle_to_context (mint);    wsh->job = MAC_job_add (ctx,                            eh, +                          GNUNET_NO,                            &handle_withdraw_status_finished,                            wsh);    return wsh; @@ -547,6 +465,7 @@ TALER_MINT_withdraw_status_cancel (struct TALER_MINT_WithdrawStatusHandle *wsh)      MAC_job_cancel (wsh->job);      wsh->job = NULL;    } +  GNUNET_free_non_null (wsh->db.buf);    GNUNET_free (wsh->url);    GNUNET_free (wsh);  } @@ -581,11 +500,6 @@ struct TALER_MINT_WithdrawSignHandle    struct MAC_Job *job;    /** -   * HTTP headers for the request. -   */ -  struct curl_slist *headers; - -  /**     * Function to call with the result.     */    TALER_MINT_WithdrawSignResultCallback cb; @@ -608,7 +522,7 @@ struct TALER_MINT_WithdrawSignHandle    /**     * Download buffer     */ -  void *buf; +  struct MAC_DownloadBuffer db;    /**     * Hash of the public key of the coin we are signing. @@ -620,17 +534,6 @@ struct TALER_MINT_WithdrawSignHandle     */    struct TALER_ReservePublicKeyP reserve_pub; -  /** -   * The size of the download buffer -   */ -  size_t buf_size; - -  /** -   * Error code (based on libc errno) if we failed to download -   * (i.e. response too large). -   */ -  int eno; -  }; @@ -797,33 +700,12 @@ handle_withdraw_sign_finished (void *cls,  {    struct TALER_MINT_WithdrawSignHandle *wsh = cls;    long response_code; -  json_error_t error;    json_t *json;    wsh->job = NULL; -  json = NULL; -  if (CURLE_OK != -      curl_easy_getinfo (eh, -                         CURLINFO_RESPONSE_CODE, -                         &response_code)) -  { -    /* unexpected error... */ -    GNUNET_break (0); -    response_code = 0; -  } -  if ( (0 == wsh->eno) && -       (0 != response_code) ) -  { -    json = json_loadb (wsh->buf, -                       wsh->buf_size, -                       JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK, -                       &error); -    if (NULL == json) -    { -      JSON_WARN (error); -      response_code = 0; -    } -  } +  json = MAC_download_get_result (&wsh->db, +                                  eh, +                                  &response_code);    switch (response_code)    {    case 0: @@ -870,6 +752,9 @@ handle_withdraw_sign_finished (void *cls,      break;    default:      /* unexpected response code */ +    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                "Unexpected response code %u\n", +                response_code);      GNUNET_break (0);      response_code = 0;      break; @@ -885,49 +770,6 @@ handle_withdraw_sign_finished (void *cls,  /** - * Callback used when downloading the reply to a /withdraw/sign request. - * Just appends all of the data to the `buf` in the - * `struct TALER_MINT_WithdrawSignHandle` for further processing. The size of - * the download is limited to #GNUNET_MAX_MALLOC_CHECKED, if - * the download exceeds this size, we abort with an error. - * - * @param bufptr data downloaded via HTTP - * @param size size of an item in @a bufptr - * @param nitems number of items in @a bufptr - * @param cls the `struct TALER_MINT_DepositHandle` - * @return number of bytes processed from @a bufptr - */ -static int -withdraw_sign_download_cb (char *bufptr, -                           size_t size, -                           size_t nitems, -                           void *cls) -{ -  struct TALER_MINT_WithdrawSignHandle *wsh = cls; -  size_t msize; -  void *buf; - -  if (0 == size * nitems) -  { -    /* Nothing (left) to do */ -    return 0; -  } -  msize = size * nitems; -  if ( (msize + wsh->buf_size) >= GNUNET_MAX_MALLOC_CHECKED) -  { -    wsh->eno = ENOMEM; -    return 0; /* signals an error to curl */ -  } -  wsh->buf = GNUNET_realloc (wsh->buf, -                             wsh->buf_size + msize); -  buf = wsh->buf + wsh->buf_size; -  memcpy (buf, bufptr, msize); -  wsh->buf_size += msize; -  return msize; -} - - -/**   * Withdraw a coin from the mint using a /withdraw/sign request.  Note   * that to ensure that no money is lost in case of hardware failures,   * the caller must have committed (most of) the arguments to disk @@ -1045,21 +887,15 @@ TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,    GNUNET_assert (CURLE_OK ==                   curl_easy_setopt (eh,                                     CURLOPT_WRITEFUNCTION, -                                   &withdraw_sign_download_cb)); +                                   &MAC_download_cb));    GNUNET_assert (CURLE_OK ==                   curl_easy_setopt (eh,                                     CURLOPT_WRITEDATA, -                                   wsh)); -  GNUNET_assert (NULL != (wsh->headers = -                          curl_slist_append (wsh->headers, -                                             "Content-Type: application/json"))); -  GNUNET_assert (CURLE_OK == -                 curl_easy_setopt (eh, -                                   CURLOPT_HTTPHEADER, -                                   wsh->headers)); +                                   &wsh->db));    ctx = MAH_handle_to_context (mint);    wsh->job = MAC_job_add (ctx,                            eh, +                          GNUNET_YES,                            &handle_withdraw_sign_finished,                            wsh);    return wsh; @@ -1080,7 +916,7 @@ TALER_MINT_withdraw_sign_cancel (struct TALER_MINT_WithdrawSignHandle *sign)      MAC_job_cancel (sign->job);      sign->job = NULL;    } -  curl_slist_free_all (sign->headers); +  GNUNET_free_non_null (sign->db.buf);    GNUNET_free (sign->url);    GNUNET_free (sign->json_enc);    GNUNET_free (sign); diff --git a/src/mint/taler-mint-httpd_admin.c b/src/mint/taler-mint-httpd_admin.c index c757fd18..5fdfa58e 100644 --- a/src/mint/taler-mint-httpd_admin.c +++ b/src/mint/taler-mint-httpd_admin.c @@ -146,6 +146,7 @@ TMH_ADMIN_handler_admin_add_incoming (struct TMH_RequestHandler *rh,  				      wire))    {      TMH_PARSE_release_data (spec); +    json_decref (root);      return TMH_RESPONSE_reply_arg_unknown (connection,                                             "wire");    } diff --git a/src/mint/taler-mint-httpd_parsing.c b/src/mint/taler-mint-httpd_parsing.c index 8d7903eb..78380f86 100644 --- a/src/mint/taler-mint-httpd_parsing.c +++ b/src/mint/taler-mint-httpd_parsing.c @@ -152,7 +152,6 @@ release_data (struct TMH_PARSE_FieldSpecification *spec,                unsigned int spec_len)  {    unsigned int i; -  void *ptr;    for (i=0; i < spec_len; i++)    { @@ -175,11 +174,15 @@ release_data (struct TMH_PARSE_FieldSpecification *spec,        }        break;      case TMH_PARSE_JNC_RET_TYPED_JSON: -      ptr = *(void **) spec[i].destination; -      if (NULL != ptr)        { -        json_decref (ptr); -        *(void**) spec[i].destination = NULL; +        json_t *json; + +        json = *(json_t **) spec[i].destination; +        if (NULL != json) +        { +          json_decref (json); +          *(json_t**) spec[i].destination = NULL; +        }        }        break;      case TMH_PARSE_JNC_RET_RSA_PUBLIC_KEY: @@ -606,7 +609,9 @@ TMH_PARSE_navigate_json (struct MHD_Connection *connection,          int typ = va_arg (argp, int);          const json_t **r_json = va_arg (argp, const json_t **); -        if ( (-1 != typ) && (json_typeof (root) != typ)) +        if ( (NULL == root) || +             ( (-1 != typ) && +               (json_typeof (root) != typ)) )          {            *r_json = NULL;            ret = (MHD_YES == @@ -899,7 +904,7 @@ TMH_PARSE_json_data (struct MHD_Connection *connection,                                       spec[i].field_name,                                       TMH_PARSE_JNC_RET_TYPED_JSON,                                       spec[i].type, -                                     &spec[i].destination); +                                     spec[i].destination);        break;      case TMH_PARSE_JNC_RET_RSA_PUBLIC_KEY:        ret = TMH_PARSE_navigate_json (connection, @@ -994,7 +999,7 @@ TMH_PARSE_member_uint64 (const char *field,   * Generate line in parser specification for JSON object value.   *   * @param field name of the field - * @param jsonp address of pointer to JSON to initialize + * @param[out] jsonp address of pointer to JSON to initialize   * @return corresponding field spec   */  struct TMH_PARSE_FieldSpecification @@ -1002,7 +1007,8 @@ TMH_PARSE_member_object (const char *field,                           json_t **jsonp)  {    struct TMH_PARSE_FieldSpecification ret = -    { field, (void **) jsonp, 0, NULL, TMH_PARSE_JNC_RET_TYPED_JSON, JSON_OBJECT }; +    { field, jsonp, 0, NULL, TMH_PARSE_JNC_RET_TYPED_JSON, JSON_OBJECT }; +  *jsonp = NULL;    return ret;  } @@ -1011,7 +1017,7 @@ TMH_PARSE_member_object (const char *field,   * Generate line in parser specification for JSON array value.   *   * @param field name of the field - * @param jsonp address of JSON pointer to initialize + * @param[out] jsonp address of JSON pointer to initialize   * @return corresponding field spec   */  struct TMH_PARSE_FieldSpecification @@ -1020,6 +1026,7 @@ TMH_PARSE_member_array (const char *field,  {    struct TMH_PARSE_FieldSpecification ret =      { field, jsonp, 0, NULL, TMH_PARSE_JNC_RET_TYPED_JSON, JSON_ARRAY }; +  *jsonp = NULL;    return ret;  } @@ -1053,6 +1060,7 @@ TMH_PARSE_member_denomination_public_key (const char *field,  {    struct TMH_PARSE_FieldSpecification ret =      { field, pk, 0, NULL, TMH_PARSE_JNC_RET_RSA_PUBLIC_KEY, 0 }; +  pk->rsa_public_key = NULL;    return ret;  } @@ -1070,6 +1078,7 @@ TMH_PARSE_member_denomination_signature (const char *field,  {    struct TMH_PARSE_FieldSpecification ret =      { field, sig, 0, NULL, TMH_PARSE_JNC_RET_RSA_SIGNATURE, 0 }; +  sig->rsa_signature = NULL;    return ret;  } @@ -1087,6 +1096,7 @@ TMH_PARSE_member_amount (const char *field,  {    struct TMH_PARSE_FieldSpecification ret =      { field, amount, sizeof(struct TALER_Amount), NULL, TMH_PARSE_JNC_RET_AMOUNT, 0 }; +  memset (amount, 0, sizeof (struct TALER_Amount));    return ret;  } @@ -1106,6 +1116,7 @@ TMH_PARSE_member_variable (const char *field,  {    struct TMH_PARSE_FieldSpecification ret =      { field, ptr, 0, ptr_size, TMH_PARSE_JNC_RET_DATA_VAR, 0 }; +  *ptr = NULL;    return ret;  } | 
