donau

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

donau_api_csr_post.c (6515B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2024 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it
      6   under the terms of the GNU General Public License as published
      7   by the Free Software Foundation; either version 3, or (at your
      8   option) any later version.
      9 
     10   TALER is distributed in the hope that it will be useful, but
     11   WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13   GNU General Public License for more details.
     14 
     15   You should have received a copy of the GNU General Public
     16   License along with TALER; see the file COPYING.  If not, see
     17   <http://www.gnu.org/licenses/>
     18 */
     19 
     20 /**
     21  * @file lib/donau_api_csr_post.c
     22  * @brief Implementation of the "handle" component of the donau's HTTP API
     23  * @author Lukas Matyja
     24  */
     25 #include <gnunet/gnunet_curl_lib.h>
     26 #include <taler/taler_json_lib.h>
     27 #include <taler/taler_curl_lib.h>
     28 #include "donau_service.h"
     29 #include "donau_api_curl_defaults.h"
     30 #include "donau_json_lib.h"
     31 
     32 
     33 /**
     34  * Handle for a POST /csr-issue request.
     35  */
     36 struct DONAU_CsRBatchIssueHandle
     37 {
     38   /**
     39    * The url for the /csr-issue request.
     40    */
     41   char *url;
     42 
     43   /**
     44    * Minor context that holds body and headers.
     45    */
     46   struct TALER_CURL_PostContext post_ctx;
     47 
     48   /**
     49    * Entry for this request with the `struct GNUNET_CURL_Context`.
     50    */
     51   struct GNUNET_CURL_Job *job;
     52 
     53   /**
     54    * Function to call with the result.
     55    */
     56   DONAU_CsRBatchIssueCallback cb;
     57 
     58   /**
     59    * Closure to pass to @e cb.
     60    */
     61   void *cb_cls;
     62 
     63   /**
     64    * Reference to the execution context.
     65    */
     66   struct GNUNET_CURL_Context *ctx;
     67 
     68 };
     69 
     70 /**
     71  * Function called when we're done processing the
     72  * HTTP POST /csr-issue request.
     73  *
     74  * @param cls the `struct KeysRequest`
     75  * @param response_code HTTP response code, 0 on error
     76  * @param resp_obj parsed JSON result, NULL on error
     77  */
     78 static void
     79 handle_csr_issue_post_finished (void *cls,
     80                                 long response_code,
     81                                 const void *resp_obj)
     82 {
     83   struct DONAU_CsRBatchIssueHandle *csrh = cls;
     84   const json_t *j = resp_obj;
     85 
     86   struct DONAU_CsRBatchIssueResponse csrresp = {
     87     .hr.reply = j,
     88     .hr.http_status = (unsigned int) response_code
     89   };
     90 
     91   csrh->job = NULL;
     92   switch (response_code)
     93   {
     94   case MHD_HTTP_CREATED:
     95     {
     96       struct GNUNET_JSON_Specification spec[] = {
     97         TALER_JSON_spec_exchange_blinding_values (
     98           "r_pubs",
     99           (struct TALER_ExchangeBlindingValues *) &csrresp.details.ok.alg_values
    100           ),
    101         GNUNET_JSON_spec_end ()
    102       };
    103 
    104       if (GNUNET_OK !=
    105           GNUNET_JSON_parse (j,
    106                              spec,
    107                              NULL,
    108                              NULL))
    109       {
    110         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    111                     "Could not parse response from csr POST\n");
    112         GNUNET_break_op (0);
    113         csrresp.hr.http_status = 0;
    114         csrresp.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
    115       }
    116       csrh->cb (csrh->cb_cls,
    117                 &csrresp);
    118       csrh->cb = NULL;
    119       GNUNET_JSON_parse_free (spec);
    120       break;
    121     }
    122   // Donation unit was revoked.
    123   case MHD_HTTP_GONE:
    124     csrresp.hr.ec = TALER_JSON_get_error_code (j);
    125     csrresp.hr.hint = TALER_JSON_get_error_hint (j);
    126     break;
    127   // Donation unit or endpoint not found.
    128   case MHD_HTTP_NOT_FOUND:
    129     csrresp.hr.ec = TALER_JSON_get_error_code (j);
    130     csrresp.hr.hint = TALER_JSON_get_error_hint (j);
    131     break;
    132   case MHD_HTTP_BAD_REQUEST:
    133     csrresp.hr.ec = TALER_JSON_get_error_code (j);
    134     csrresp.hr.hint = TALER_JSON_get_error_hint (j);
    135     break;
    136   default:
    137     /* unexpected response code */
    138     GNUNET_break_op (0);
    139     csrresp.hr.ec = TALER_JSON_get_error_code (j);
    140     csrresp.hr.hint = TALER_JSON_get_error_hint (j);
    141     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    142                 "Unexpected response code %u/%d for POST %s\n",
    143                 (unsigned int) response_code,
    144                 (int) csrresp.hr.ec,
    145                 csrh->url);
    146     break;
    147   }
    148   if (NULL != csrh->cb)
    149   {
    150     csrh->cb (csrh->cb_cls,
    151               &csrresp);
    152     csrh->cb = NULL;
    153   }
    154   DONAU_csr_cancel (csrh);
    155 }
    156 
    157 
    158 struct DONAU_CsRBatchIssueHandle *
    159 DONAU_csr_issue (
    160   struct GNUNET_CURL_Context *ctx,
    161   const char *url,
    162   const struct DONAU_DonationUnitPublicKey *pk,
    163   const struct GNUNET_CRYPTO_CsSessionNonce *nonce,
    164   DONAU_CsRBatchIssueCallback cb,
    165   void *cb_cls)
    166 {
    167   struct DONAU_CsRBatchIssueHandle *csrh;
    168   CURL *eh;
    169   json_t *body;
    170 
    171   struct DONAU_DonationUnitHashP h_donation_unit_pub;
    172   DONAU_donation_unit_pub_hash (pk,
    173                                 &h_donation_unit_pub);
    174 
    175   TALER_LOG_DEBUG ("Connecting to the donau (%s)\n",
    176                    url);
    177   csrh = GNUNET_new (struct DONAU_CsRBatchIssueHandle);
    178   csrh->cb = cb;
    179   csrh->cb_cls = cb_cls;
    180   csrh->ctx = ctx;
    181   csrh->url = TALER_url_join (url,
    182                               "csr-issue",
    183                               NULL);
    184   if (NULL == csrh->url)
    185   {
    186     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    187                 "Could not construct requested URL.\n");
    188     GNUNET_free (csrh);
    189     return NULL;
    190   }
    191   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    192               "Request CS R with URL `%s'.\n",
    193               csrh->url);
    194   body = GNUNET_JSON_PACK (
    195     GNUNET_JSON_pack_data_varsize ("nonce",
    196                                    nonce,
    197                                    sizeof(*nonce)),
    198     GNUNET_JSON_pack_data_varsize ("du_pub_hash",
    199                                    &h_donation_unit_pub,
    200                                    sizeof(h_donation_unit_pub)));
    201   eh = DONAU_curl_easy_get_ (csrh->url);
    202   if ( (NULL == eh) ||
    203        (GNUNET_OK !=
    204         TALER_curl_easy_post (&csrh->post_ctx,
    205                               eh,
    206                               body)) )
    207   {
    208     GNUNET_break (0);
    209     if (NULL != eh)
    210       curl_easy_cleanup (eh);
    211     json_decref (body);
    212     GNUNET_free (csrh->url);
    213     GNUNET_free (csrh);
    214     return NULL;
    215   }
    216   json_decref (body);
    217   csrh->job = GNUNET_CURL_job_add2 (ctx,
    218                                     eh,
    219                                     csrh->post_ctx.headers,
    220                                     &handle_csr_issue_post_finished,
    221                                     csrh);
    222   return csrh;
    223 }
    224 
    225 
    226 void
    227 DONAU_csr_cancel (
    228   struct DONAU_CsRBatchIssueHandle *csrh)
    229 {
    230   if (NULL != csrh->job)
    231   {
    232     GNUNET_CURL_job_cancel (csrh->job);
    233     csrh->job = NULL;
    234   }
    235   TALER_curl_easy_post_finished (&csrh->post_ctx);
    236   GNUNET_free (csrh->url);
    237   GNUNET_free (csrh);
    238 }