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 }