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 }