frosix_api_request-challenge.c (9171B)
1 /* 2 This file is part of Frosix 3 Copyright (C) 2020, 2021 Anastasis SARL 4 5 Frosix is free software; you can redistribute it and/or modify it under the 6 terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 Frosix is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 Frosix; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file reducer/frosix_api_authenticate.c 18 * @brief frosix reducer sign api 19 * @author Christian Grothoff 20 * @author Dominik Meister 21 * @author Dennis Neufeld 22 * @author Joel Urech 23 */ 24 25 #include "platform.h" 26 #include "frost_verify.h" 27 #include "frosix.h" 28 #include "frosix_api.h" 29 #include <taler/taler_merchant_service.h> 30 31 32 /** 33 * FIXME 34 */ 35 struct FROSIX_Provider 36 { 37 /** 38 * URL of the provider. 39 */ 40 char *backend_url; 41 42 /** 43 * Index of the provider 44 */ 45 uint8_t provider_index; 46 47 /** 48 * Authentication method. 49 */ 50 char *auth_method; 51 52 /** 53 * Authentication data. 54 */ 55 char *auth_data; 56 57 /** 58 * Salt for the hash of the authentication data 59 */ 60 struct GNUNET_HashCode auth_nonce; 61 62 /** 63 * Encryption key 64 */ 65 struct FROSIX_EncryptionKey enc_key; 66 }; 67 68 /** 69 * Struct to store all parsed data from the cli and /config and /seed 70 */ 71 struct FROSIX_ChallengeRequestData 72 { 73 /** 74 * Our hashed message. 75 */ 76 struct FROST_MessageHash message_hash; 77 78 /** 79 * Our provider 80 */ 81 struct FROSIX_Provider provider; 82 }; 83 84 /** 85 * State of a challenge request procedure 86 */ 87 struct FROSIX_ChallengeRequestState 88 { 89 /** 90 * State we are updating. 91 */ 92 struct FROSIX_ChallengeRequestData *challenge_data; 93 94 /** 95 * Function to call when we are done. 96 */ 97 FROSIX_ActionCallback cb; 98 99 /** 100 * Closure for @e cb. 101 */ 102 void *cb_cls; 103 104 /** 105 * Redux action we returned to our controller. 106 */ 107 struct FROSIX_ReduxAction ra; 108 109 /** 110 * Last error code 111 */ 112 enum TALER_ErrorCode error_code; 113 114 /** 115 * Response as JSON 116 */ 117 json_t *response; 118 119 /** 120 * Pointer to our AuthChallengeRequestOperation 121 */ 122 struct FROSIX_ChallengeRequestOperation *ao; 123 }; 124 125 126 /** 127 * Function to free all initialized memory of a provider from a 128 * `struct FROSIX_Provider` 129 * 130 * @param fp the struct to clean up 131 */ 132 static void 133 free_provider_struct (struct FROSIX_Provider *fp) 134 { 135 if (NULL != fp->backend_url) 136 GNUNET_free (fp->backend_url); 137 138 if (NULL != fp->auth_method) 139 GNUNET_free (fp->auth_method); 140 141 if (NULL != fp->auth_data) 142 GNUNET_free (fp->auth_data); 143 } 144 145 146 /** 147 * Function called when challenge-request process is being aborted. 148 * Frees all initialized memory! 149 * 150 * @param cls a `struct FROSIX_ChallengeRequestState` 151 */ 152 static void 153 challenge_request_cancel_cb (void *cls) 154 { 155 struct FROSIX_ChallengeRequestState *cs = cls; 156 157 if (NULL != cs->challenge_data) 158 { 159 free_provider_struct (&cs->challenge_data->provider); 160 GNUNET_free (cs->challenge_data); 161 } 162 163 GNUNET_free (cs); 164 } 165 166 167 /** 168 * FIXME 169 */ 170 static void 171 return_feedback (struct FROSIX_ChallengeRequestState *cs) 172 { 173 /* return empty */ 174 cs->cb (cs->cb_cls, 175 cs->error_code, 176 cs->response); 177 } 178 179 180 /** 181 * Callback to process a POST /auth-challenge request 182 * 183 * @param cls closure 184 * @param scd the decoded response body 185 */ 186 static void 187 challenge_request_cb (void *cls, 188 const struct FROSIX_ChallengeRequestDetails *crd) 189 { 190 GNUNET_assert (NULL != cls); 191 struct FROSIX_ChallengeRequestState *cs = cls; 192 193 /* set error code */ 194 cs->error_code = crd->ec; 195 cs->response = json_deep_copy (crd->response); 196 197 /* call callback and give a return message to the user */ 198 return_feedback (cs); 199 } 200 201 202 /** 203 * FIXME 204 */ 205 static void 206 start_challenge_request (struct FROSIX_ChallengeRequestState *cs) 207 { 208 /* calculate request id*/ 209 struct FROSIX_ChallengeRequestIdP request_id; 210 FROSIX_compute_challenge_request_id ( 211 &request_id, 212 &cs->challenge_data->provider.enc_key, 213 &cs->challenge_data->message_hash); 214 215 cs->ao = FROSIX_auth_challenge_post ( 216 FROSIX_REDUX_ctx_, 217 cs->challenge_data->provider.backend_url, 218 &request_id, 219 &cs->challenge_data->provider.enc_key, 220 cs->challenge_data->provider.auth_method, 221 cs->challenge_data->provider.auth_data, 222 &cs->challenge_data->provider.auth_nonce, 223 &cs->challenge_data->message_hash, 224 &challenge_request_cb, 225 cs); 226 } 227 228 229 /** 230 * Helper function to parse a keygen input 231 * 232 * @param[in,out] dkg_data A initialized struct 233 * @param[in] arguments Input from the cli 234 */ 235 enum GNUNET_GenericReturnValue 236 parse_challenge_request_arguments ( 237 struct FROSIX_ChallengeRequestData *challenge_data, 238 const json_t *arguments, 239 const json_t *input) 240 { 241 json_t *providers = NULL; 242 243 struct GNUNET_JSON_Specification spec[] = { 244 GNUNET_JSON_spec_json ("providers", 245 &providers), 246 GNUNET_JSON_spec_end () 247 }; 248 249 if (GNUNET_OK != GNUNET_JSON_parse (arguments, 250 spec, 251 NULL, 252 NULL)) 253 { 254 GNUNET_break (0); 255 GNUNET_JSON_parse_free (spec); 256 return GNUNET_NO; 257 } 258 259 /* check number of parsed providers */ 260 size_t max_num = json_array_size (providers); 261 262 /* enforce that only one provider is selected */ 263 GNUNET_assert (1 == json_object_size (input)); 264 265 struct GNUNET_JSON_Specification selection_spec[] = { 266 GNUNET_JSON_spec_uint8 ("provider_index", 267 &challenge_data->provider.provider_index), 268 GNUNET_JSON_spec_end () 269 }; 270 271 if (GNUNET_OK != GNUNET_JSON_parse (input, 272 selection_spec, 273 NULL, 274 NULL)) 275 { 276 GNUNET_break (0); 277 GNUNET_JSON_parse_free (selection_spec); 278 GNUNET_JSON_parse_free (spec); 279 return GNUNET_NO; 280 } 281 282 GNUNET_JSON_parse_free (selection_spec); 283 284 /* check if our selected provider is in the keyfile */ 285 GNUNET_assert (max_num > challenge_data->provider.provider_index); 286 GNUNET_assert (0 < challenge_data->provider.provider_index); 287 uint8_t parsed_provider_index; 288 289 /* parse provider data */ 290 struct GNUNET_JSON_Specification prov_spec[] = { 291 GNUNET_JSON_spec_uint8 ("provider_index", 292 &parsed_provider_index), 293 GNUNET_JSON_spec_string ( 294 "backend_url", 295 (const char**) &challenge_data->provider.backend_url), 296 GNUNET_JSON_spec_fixed_auto ("encryption_key", 297 &challenge_data->provider.enc_key), 298 GNUNET_JSON_spec_string ( 299 "auth_method", 300 (const char**) &challenge_data->provider.auth_method), 301 GNUNET_JSON_spec_string ( 302 "auth_data", 303 (const char**) &challenge_data->provider.auth_data), 304 GNUNET_JSON_spec_fixed_auto ("auth_nonce", 305 &challenge_data->provider.auth_nonce), 306 GNUNET_JSON_spec_end () 307 }; 308 309 if (GNUNET_OK != GNUNET_JSON_parse ( 310 json_array_get ( 311 providers, 312 challenge_data->provider.provider_index - 1), 313 prov_spec, 314 NULL, 315 NULL)) 316 { 317 GNUNET_break (0); 318 GNUNET_JSON_parse_free (prov_spec); 319 GNUNET_JSON_parse_free (spec); 320 return GNUNET_NO; 321 } 322 323 GNUNET_JSON_parse_free (prov_spec); 324 GNUNET_JSON_parse_free (spec); 325 326 /* check if parsed provider has correct index */ 327 GNUNET_assert (parsed_provider_index == 328 challenge_data->provider.provider_index); 329 330 return GNUNET_OK; 331 } 332 333 334 /** 335 * 336 */ 337 struct FROSIX_ReduxAction * 338 FROSIX_redux_challenge_request_start (const json_t *arguments, 339 const json_t *input, 340 const char *message, 341 FROSIX_ActionCallback cb, 342 void *cb_cls) 343 { 344 /* initialize signature data struct */ 345 struct FROSIX_ChallengeRequestData *challenge_data = 346 GNUNET_new (struct FROSIX_ChallengeRequestData); 347 348 /* parse arguments from cli */ 349 if (GNUNET_OK != parse_challenge_request_arguments (challenge_data, 350 arguments, 351 input)) 352 { 353 // free_challenge_request_data_struct (challenge_data); 354 355 // FIXME: Return some useful error message 356 return NULL; 357 } 358 359 /* hash message */ 360 FROST_message_to_hash (&challenge_data->message_hash, 361 message, 362 strlen (message)); 363 364 /* lets create a state */ 365 struct FROSIX_ChallengeRequestState *cs = GNUNET_new (struct 366 FROSIX_ChallengeRequestState); 367 cs->cb = cb; 368 cs->cb_cls = cb_cls; 369 cs->challenge_data = challenge_data; 370 cs->ra.cleanup = &challenge_request_cancel_cb; 371 cs->ra.cleanup_cls = cs; 372 373 /* get commitments from all parsed providers */ 374 start_challenge_request (cs); 375 376 return &cs->ra; 377 }