frosix

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

frosix_api_auth-challenge_request.c (7626B)


      1 /*
      2   This file is part of Frosix
      3   Copyright (C) 2014-2019 Anastasis SARL
      4 
      5   Frosix 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   Frosix 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 Frosix; see the file COPYING.LGPL.  If not,
     17   see <http://www.gnu.org/licenses/>
     18 */
     19 
     20 /**
     21  * @file restclient/frosix_api_auth-challenge_request.c
     22  * @brief Implementation of the /auth-challenge 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 "frosix_api_curl_defaults.h"
     33 #include <taler/taler_json_lib.h>
     34 
     35 /**
     36  * @brief A Contract Operation Handle
     37  */
     38 struct FROSIX_ChallengeRequestOperation
     39 {
     40   /**
     41    * The url for this request, including parameters.
     42    */
     43   char *url;
     44 
     45   /**
     46    * Handle for the request.
     47    */
     48   struct GNUNET_CURL_Job *job;
     49 
     50   /**
     51    * The CURL context to connect to the backend
     52   */
     53   struct GNUNET_CURL_Context *ctx;
     54 
     55   /**
     56    * Function to call with the result.
     57    */
     58   FROSIX_ChallengeRequestCallback cb;
     59 
     60   /**
     61    * Closure for @a cb.
     62    */
     63   void *cb_cls;
     64 };
     65 
     66 
     67 void
     68 FROSIX_auth_challenge_post_cancel (struct FROSIX_ChallengeRequestOperation *aco)
     69 {
     70   if (NULL != aco->job)
     71   {
     72     GNUNET_CURL_job_cancel (aco->job);
     73     aco->job = NULL;
     74   }
     75   GNUNET_free (aco->url);
     76   GNUNET_free (aco);
     77 }
     78 
     79 
     80 /**
     81  * Process POST /auth-challenge response
     82  */
     83 static void
     84 handle_auth_challenge_post_finished (void *cls,
     85                                      long response_code,
     86                                      const void *response)
     87 {
     88   struct FROSIX_ChallengeRequestOperation *aco = cls;
     89   struct FROSIX_ChallengeRequestDetails acd;
     90   const json_t *json_response = response;
     91 
     92   aco->job = NULL;
     93   acd.http_status = response_code;
     94   acd.ec = TALER_EC_NONE;
     95 
     96   switch (response_code)
     97   {
     98   case 0:
     99     /* Hard error */
    100     GNUNET_break (0);
    101     acd.crs = FROSIX_CRS_HTTP_ERROR;
    102     acd.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
    103     break;
    104   case MHD_HTTP_CREATED:
    105   case MHD_HTTP_OK:
    106     {
    107       acd.crs = FROSIX_CRS_SUCCESS;
    108       acd.response = json_deep_copy (json_response);
    109       break;
    110     }
    111   case MHD_HTTP_BAD_REQUEST:
    112     /* We have a conflict with the API */
    113     GNUNET_break (0);
    114     acd.crs = FROSIX_CRS_CLIENT_ERROR;
    115     acd.ec = TALER_JSON_get_error_code2 (json_response,
    116                                          json_object_size (json_response));
    117     break;
    118   case MHD_HTTP_INTERNAL_SERVER_ERROR:
    119     /* The provider has a problem! */
    120     GNUNET_break (0);
    121     acd.crs = FROSIX_CRS_SERVER_ERROR;
    122     acd.ec = TALER_JSON_get_error_code2 (json_response,
    123                                          json_object_size (json_response));
    124     break;
    125   default:
    126     /* Unexpected response code */
    127     GNUNET_break (0);
    128     acd.ec = TALER_JSON_get_error_code2 (json_response,
    129                                          json_object_size (json_response));
    130     break;
    131   }
    132 
    133   /* return to callback function with the data from the response */
    134   aco->cb (aco->cb_cls,
    135            &acd);
    136   aco->cb = NULL;
    137 
    138   FROSIX_auth_challenge_post_cancel (aco);
    139   return;
    140 }
    141 
    142 
    143 /**
    144  * Handle HTTP header received by curl.
    145  *
    146  * @param buffer one line of HTTP header data
    147  * @param size size of an item
    148  * @param userdata our `struct FROSIX_SigCommitmentRequestOperation`
    149  * @return `size * nitems`
    150 */
    151 static size_t
    152 handle_header (char *buffer,
    153                size_t size,
    154                size_t nitems,
    155                void *userdata)
    156 {
    157   // struct FROSIX_SigCommitmentRequestOperation *sco = userdata;
    158   size_t total = size * nitems;
    159   char *ndup;
    160   const char *hdr_type;
    161   char *hdr_val;
    162   char *sp;
    163 
    164   ndup = GNUNET_strndup (buffer,
    165                          total);
    166 
    167   hdr_type = strtok_r (ndup,
    168                        ":",
    169                        &sp);
    170   if (NULL == hdr_type)
    171   {
    172     GNUNET_free (ndup);
    173     return total;
    174   }
    175   hdr_val = strtok_r (NULL,
    176                       "\n\r",
    177                       &sp);
    178   if (NULL == hdr_val)
    179   {
    180     GNUNET_free (ndup);
    181     return total;
    182   }
    183   if (' ' == *hdr_val)
    184     hdr_val++;
    185   /* ... FIXME */
    186   return total;
    187 }
    188 
    189 
    190 struct FROSIX_ChallengeRequestOperation *
    191 FROSIX_auth_challenge_post (
    192   struct GNUNET_CURL_Context *ctx,
    193   const char *backend_url,
    194   const struct FROSIX_ChallengeRequestIdP *uuid,
    195   const struct FROSIX_EncryptionKey *encryption_key,
    196   const char *auth_method,
    197   const char *auth_data,
    198   const struct GNUNET_HashCode *auth_nonce,
    199   const struct FROST_MessageHash *message_hash,
    200   FROSIX_ChallengeRequestCallback cb,
    201   void *cb_cls)
    202 {
    203   struct FROSIX_ChallengeRequestOperation *aco;
    204   CURL *eh;
    205   char *json_str;
    206 
    207   /* check if we got a callback function, abort if not */
    208   GNUNET_assert (NULL != cb);
    209 
    210   aco = GNUNET_new (struct FROSIX_ChallengeRequestOperation);
    211 
    212   {
    213     /* prepare URL */
    214     char *uuid_str;
    215     char *path;
    216 
    217     uuid_str = GNUNET_STRINGS_data_to_string_alloc (uuid,
    218                                                     sizeof (*uuid));
    219 
    220     GNUNET_asprintf (&path,
    221                      "auth-challenge/%s",
    222                      uuid_str);
    223 
    224     aco->url = TALER_url_join (backend_url,
    225                                path,
    226                                NULL);
    227 
    228     GNUNET_free (path);
    229     GNUNET_free (uuid_str);
    230   }
    231 
    232   {
    233     /* pack the json object for the request body */
    234     json_t *auth_challenge_data;
    235     auth_challenge_data = GNUNET_JSON_PACK (
    236       GNUNET_JSON_pack_data_auto ("encryption_key",
    237                                   encryption_key),
    238       GNUNET_JSON_pack_string ("auth_method",
    239                                auth_method),
    240       GNUNET_JSON_pack_string ("auth_data",
    241                                auth_data),
    242       GNUNET_JSON_pack_data_auto ("auth_nonce",
    243                                   auth_nonce),
    244       GNUNET_JSON_pack_data_auto ("message_hash",
    245                                   message_hash));
    246 
    247     json_str = json_dumps (auth_challenge_data,
    248                            JSON_COMPACT);
    249 
    250     /* check if we have a json object, abort if it was not successful */
    251     GNUNET_assert (NULL != json_str);
    252 
    253     json_decref (auth_challenge_data);
    254   }
    255 
    256   /* prepare curl options and fire the request */
    257   aco->ctx = ctx;
    258   aco->cb = cb;
    259   aco->cb_cls = cb_cls;
    260 
    261   eh = FROSIX_curl_easy_get_ (aco->url);
    262 
    263   GNUNET_assert (CURLE_OK ==
    264                  curl_easy_setopt (eh,
    265                                    CURLOPT_POSTFIELDS,
    266                                    json_str));
    267   GNUNET_assert (CURLE_OK ==
    268                  curl_easy_setopt (eh,
    269                                    CURLOPT_POSTFIELDSIZE,
    270                                    strlen (json_str)));
    271   GNUNET_assert (CURLE_OK ==
    272                  curl_easy_setopt (eh,
    273                                    CURLOPT_HEADERFUNCTION,
    274                                    &handle_header));
    275   GNUNET_assert (CURLE_OK ==
    276                  curl_easy_setopt (eh,
    277                                    CURLOPT_HEADERDATA,
    278                                    aco));
    279 
    280   aco->job = GNUNET_CURL_job_add (ctx,
    281                                   eh,
    282                                   &handle_auth_challenge_post_finished,
    283                                   aco);
    284 
    285   return aco;
    286 }