frosix

Multiparty signature service (experimental)
Log | Files | Refs | README | LICENSE

frosix_api_sig-commitment_request.c (10061B)


      1 /*
      2   This file is part of ANASTASIS
      3   Copyright (C) 2014-2019 Anastasis SARL
      4 
      5   ANASTASIS is free software; you can redistribute it and/or modify
      6   it under the terms of the GNU General Public License as
      7   published by the Free Software Foundation; either version 2.1,
      8   or (at your option) any later version.
      9 
     10   ANASTASIS 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 ANASTASIS; see the file COPYING.LGPL.  If not,
     17   see <http://www.gnu.org/licenses/>
     18 */
     19 
     20 /**
     21  * @file restclient/frosix_api_sig-commitment_request.c
     22  * @brief Implementation of the /sig-commitment POST
     23  * @author Christian Grothoff
     24  * @author Dennis Neufeld
     25  * @author Dominik Meister
     26  * @author Joel Urech
     27  */
     28 #include "platform.h"
     29 #include <curl/curl.h>
     30 #include <microhttpd.h> /* just for HTTP status codes */
     31 #include "frosix_service.h"
     32 #include "frost_high.h"
     33 #include "frosix_api_curl_defaults.h"
     34 #include <gnunet/gnunet_json_lib.h>
     35 #include <taler/taler_json_lib.h>
     36 
     37 
     38 /**
     39  * @brief A Contract Operation Handle
     40  */
     41 struct FROSIX_SigCommitmentRequestOperation
     42 {
     43   /**
     44    * The url for this request, including parameters.
     45    */
     46   char *url;
     47 
     48   /**
     49    * Index of the provider.
     50   */
     51   uint8_t provider_index;
     52 
     53   /**
     54    * Index in the provider array.
     55   */
     56   uint8_t array_index;
     57 
     58   /**
     59    * Handle for the request.
     60    */
     61   struct GNUNET_CURL_Job *job;
     62 
     63   /**
     64    * The CURL context to connect to the backend
     65   */
     66   struct GNUNET_CURL_Context *ctx;
     67 
     68   /**
     69    * Function to call with the result.
     70    */
     71   FROSIX_SigCommitmentRequestCallback cb;
     72 
     73   /**
     74    * Closure for @a cb.
     75    */
     76   void *cb_cls;
     77 };
     78 
     79 
     80 void
     81 FROSIX_sig_commitment_request_cancel (
     82   struct FROSIX_SigCommitmentRequestOperation *sco)
     83 {
     84   if (NULL != sco->job)
     85   {
     86     GNUNET_CURL_job_cancel (sco->job);
     87     sco->job = NULL;
     88   }
     89   GNUNET_free (sco->url);
     90   GNUNET_free (sco);
     91 }
     92 
     93 
     94 /**
     95  * Callback to process POST /sig-commitment response
     96  *
     97  * @param cls the `struct FROSIX_SigCommitmentRequestOperation`
     98  * @param response_code HTTP response code, 0 on error
     99  * @param data response body
    100  * @param data_size number of byte in @a data
    101 */
    102 static void
    103 handle_sig_commitment_request_finished (void *cls,
    104                                         long response_code,
    105                                         const void *response)
    106 {
    107   struct FROSIX_SigCommitmentRequestOperation *sco = cls;
    108   struct FROSIX_SigCommitmentRequestDetails scd;
    109   const json_t *json_response = response;
    110 
    111   sco->job = NULL;
    112   scd.http_status = response_code;
    113   scd.ec = TALER_EC_NONE;
    114   scd.array_index = sco->array_index;
    115   scd.sig_commitment.identifier = sco->provider_index;
    116 
    117   switch (response_code)
    118   {
    119   case 0:
    120     /* Hard error */
    121     GNUNET_break (0);
    122     scd.scs = FROSIX_SCS_HTTP_ERROR;
    123     scd.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
    124     break;
    125   case MHD_HTTP_CREATED:
    126   case MHD_HTTP_OK:
    127     {
    128       scd.scs = FROSIX_SCS_SUCCESS;
    129 
    130       /* We got a result, lets parse it */
    131       struct GNUNET_JSON_Specification spec[] = {
    132         GNUNET_JSON_spec_fixed_auto ("hiding_commitment",
    133                                      &scd.sig_commitment.hiding_commitment),
    134         GNUNET_JSON_spec_fixed_auto ("binding_commitment",
    135                                      &scd.sig_commitment.binding_commitment),
    136         GNUNET_JSON_spec_end ()
    137       };
    138 
    139       if (GNUNET_OK !=
    140           GNUNET_JSON_parse (json_response,
    141                              spec,
    142                              NULL,
    143                              NULL))
    144       {
    145         /* Parsing failed! */
    146         GNUNET_break_op (0);
    147         scd.http_status = 0;
    148         GNUNET_JSON_parse_free (spec);
    149         break;
    150       }
    151 
    152       GNUNET_JSON_parse_free (spec);
    153       break;
    154     }
    155   case MHD_HTTP_BAD_REQUEST:
    156     /* We have a conflict with the API */
    157     scd.http_status = 0;
    158     GNUNET_break (0);
    159     scd.scs = FROSIX_SCS_CLIENT_ERROR;
    160     scd.ec = TALER_JSON_get_error_code2 (json_response,
    161                                          json_object_size (json_response));
    162     break;
    163   case MHD_HTTP_INTERNAL_SERVER_ERROR:
    164     /* The provider has a problem! */
    165     scd.http_status = 0;
    166     GNUNET_break (0);
    167     scd.scs = FROSIX_SCS_SERVER_ERROR;
    168     scd.ec = TALER_JSON_get_error_code2 (json_response,
    169                                          json_object_size (json_response));
    170     break;
    171   default:
    172     /* Unexpected response code */
    173     scd.http_status = 0;
    174     GNUNET_break (0);
    175     scd.ec = TALER_JSON_get_error_code2 (json_response,
    176                                          json_object_size (json_response));
    177     break;
    178   }
    179 
    180   /* return to callback function with the data from the response */
    181   sco->cb (sco->cb_cls,
    182            &scd);
    183   sco->cb = NULL;
    184 
    185   FROSIX_sig_commitment_request_cancel (sco);
    186   return;
    187 }
    188 
    189 /**
    190  * Handle HTTP header received by curl.
    191  *
    192  * @param buffer one line of HTTP header data
    193  * @param size size of an item
    194  * @param userdata our `struct FROSIX_DkgCommitmentRequestOperation`
    195  * @return `size * nitems`
    196 */
    197 static size_t
    198 handle_header (char *buffer,
    199                size_t size,
    200                size_t nitems,
    201                void *userdata)
    202 {
    203   // struct FROSIX_DkgCommitmentRequestOperation *dco = userdata;
    204   size_t total = size * nitems;
    205   return total;
    206 
    207   /*char *ndup;
    208   const char *hdr_type;
    209   char *hdr_val;
    210   char *sp;
    211 
    212   ndup = GNUNET_strndup (buffer,
    213                          total);
    214 
    215   hdr_type = strtok_r (ndup,
    216                        ":",
    217                        &sp);
    218   if (NULL == hdr_type)
    219   {
    220     GNUNET_free (ndup);
    221     return total;
    222   }
    223   hdr_val = strtok_r (NULL,
    224                       "\n\r",
    225                       &sp);
    226   if (NULL == hdr_val)
    227   {
    228     GNUNET_free (ndup);
    229     return total;
    230   }
    231   if (' ' == *hdr_val)
    232     hdr_val++;
    233 
    234   return total;*/
    235 }
    236 
    237 
    238 struct FROSIX_SigCommitmentRequestOperation *
    239 FROSIX_sig_commitment_request (
    240   struct GNUNET_CURL_Context *ctx,
    241   const char *backend_url,
    242   const struct FROSIX_SigRequestIdP *uuid,
    243   uint8_t provider_index,
    244   uint8_t array_index,
    245   const struct FROST_HashCode *encryption_key_hash,
    246   const struct GNUNET_HashCode *auth_data,
    247   const struct GNUNET_CRYPTO_Edx25519PublicKey *auth_pub,
    248   const struct GNUNET_CRYPTO_Edx25519Signature *auth_sig,
    249   const char *auth_method,
    250   const struct FROST_MessageHash *message_hash,
    251   FROSIX_SigCommitmentRequestCallback cb,
    252   void *cb_cls)
    253 {
    254   struct FROSIX_SigCommitmentRequestOperation *sco;
    255   CURL *eh;
    256   char *json_str;
    257 
    258   /* check if we got a callback function, abort if not */
    259   GNUNET_assert (NULL != cb);
    260 
    261   sco = GNUNET_new (struct FROSIX_SigCommitmentRequestOperation);
    262   sco->array_index = array_index;
    263   sco->provider_index = provider_index;
    264 
    265   {
    266     /* prepare URL */
    267     char *uuid_str;
    268     char *path;
    269 
    270     uuid_str = GNUNET_STRINGS_data_to_string_alloc (uuid,
    271                                                     sizeof (*uuid));
    272 
    273     GNUNET_asprintf (&path,
    274                      "sig-commitment/%s",
    275                      uuid_str);
    276 
    277     sco->url = TALER_url_join (backend_url,
    278                                path,
    279                                NULL);
    280 
    281     GNUNET_free (path);
    282     GNUNET_free (uuid_str);
    283   }
    284 
    285   if (0 == strcmp (auth_method,
    286                    "question"))
    287   {
    288     /* pack the json object for the request body */
    289     json_t *sig_commitment_data;
    290     sig_commitment_data = GNUNET_JSON_PACK (
    291       GNUNET_JSON_pack_data_auto ("encryption_key_hash",
    292                                   encryption_key_hash),
    293       GNUNET_JSON_pack_string ("auth_method",
    294                                auth_method),
    295       GNUNET_JSON_pack_data_auto ("auth_pub",
    296                                   auth_pub),
    297       GNUNET_JSON_pack_data_auto ("auth_sig",
    298                                   auth_sig),
    299       GNUNET_JSON_pack_data_auto ("message_hash",
    300                                   message_hash));
    301 
    302     json_str = json_dumps (sig_commitment_data,
    303                            JSON_COMPACT);
    304 
    305     /* check if we have a json object, abort if it was not successful */
    306     GNUNET_assert (NULL != json_str);
    307 
    308     json_decref (sig_commitment_data);
    309   }
    310   else
    311   {
    312     /* pack the json object for the request body */
    313     json_t *sig_commitment_data;
    314     sig_commitment_data = GNUNET_JSON_PACK (
    315       GNUNET_JSON_pack_data_auto ("encryption_key_hash",
    316                                   encryption_key_hash),
    317       GNUNET_JSON_pack_string ("auth_method",
    318                                auth_method),
    319       GNUNET_JSON_pack_data_auto ("auth_data",
    320                                   auth_data),
    321       GNUNET_JSON_pack_data_auto ("message_hash",
    322                                   message_hash));
    323 
    324     json_str = json_dumps (sig_commitment_data,
    325                            JSON_COMPACT);
    326 
    327     /* check if we have a json object, abort if it was not successful */
    328     GNUNET_assert (NULL != json_str);
    329 
    330     json_decref (sig_commitment_data);
    331   }
    332 
    333   /* prepare curl options and fire the request */
    334   sco->ctx = ctx;
    335   sco->cb = cb;
    336   sco->cb_cls = cb_cls;
    337 
    338   eh = FROSIX_curl_easy_get_ (sco->url);
    339 
    340   GNUNET_assert (CURLE_OK ==
    341                  curl_easy_setopt (eh,
    342                                    CURLOPT_POSTFIELDS,
    343                                    json_str));
    344   GNUNET_assert (CURLE_OK ==
    345                  curl_easy_setopt (eh,
    346                                    CURLOPT_POSTFIELDSIZE,
    347                                    strlen (json_str)));
    348   GNUNET_assert (CURLE_OK ==
    349                  curl_easy_setopt (eh,
    350                                    CURLOPT_HEADERFUNCTION,
    351                                    &handle_header));
    352   GNUNET_assert (CURLE_OK ==
    353                  curl_easy_setopt (eh,
    354                                    CURLOPT_HEADERDATA,
    355                                    sco));
    356 
    357   sco->job = GNUNET_CURL_job_add (ctx,
    358                                   eh,
    359                                   &handle_sig_commitment_request_finished,
    360                                   sco);
    361 
    362   return sco;
    363 }