testing_api_cmd_truth_challenge.c (9735B)
1 /* 2 This file is part of Anastasis 3 Copyright (C) 2020, 2022 Anastasis SARL 4 5 Anastasis 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 Anastasis 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 Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file testing/testing_api_cmd_truth_challenge.c 18 * @brief Testing of Implementation of the /truth GET 19 * @author Christian Grothoff 20 * @author Dennis Neufeld 21 * @author Dominik Meister 22 */ 23 24 #include "platform.h" 25 struct TruthChallengeState; 26 #define ANASTASIS_TRUTH_CHALLENGE_RESULT_CLOSURE struct TruthChallengeState 27 #include "anastasis_testing_lib.h" 28 #include <taler/taler_util.h> 29 #include <taler/taler_testing_lib.h> 30 #include <taler/taler_merchant_service.h> 31 32 33 /** 34 * State for a "keyshare lookup" CMD. 35 */ 36 struct TruthChallengeState 37 { 38 /** 39 * The interpreter state. 40 */ 41 struct TALER_TESTING_Interpreter *is; 42 43 /** 44 * URL of the anastasis backend. 45 */ 46 const char *anastasis_url; 47 48 /** 49 * Expected HTTP status code. 50 */ 51 unsigned int expected_http_status; 52 53 /** 54 * The /truth GET operation handle. 55 */ 56 struct ANASTASIS_TruthChallengeOperation *tco; 57 58 /** 59 * Reference to upload command we expect to lookup. 60 */ 61 const char *upload_reference; 62 63 /** 64 * Reference to upload command we expect to lookup. 65 */ 66 const char *payment_reference; 67 68 /** 69 * Payment secret requested by the service, if any. 70 */ 71 struct ANASTASIS_PaymentSecretP payment_secret_response; 72 73 /** 74 * Taler-URI with payment request, if any. 75 */ 76 char *pay_uri; 77 78 /** 79 * Order ID for payment request, if any. 80 */ 81 char *order_id; 82 83 /** 84 * "code" returned by service, if any. 85 */ 86 char *code; 87 88 /** 89 * "instructions" for how to solve the challenge as returned by service, if any. 90 */ 91 char *instructions; 92 93 }; 94 95 96 static void 97 truth_challenge_cb (struct TruthChallengeState *ksls, 98 const struct ANASTASIS_TruthChallengeDetails *tcd) 99 { 100 ksls->tco = NULL; 101 if (tcd->http_status != ksls->expected_http_status) 102 { 103 TALER_TESTING_unexpected_status (ksls->is, 104 tcd->http_status, 105 ksls->expected_http_status); 106 return; 107 } 108 switch (tcd->http_status) 109 { 110 case MHD_HTTP_OK: 111 switch (tcd->details.success.cs) 112 { 113 case ANASTASIS_CS_FILE_WRITTEN: 114 { 115 FILE *file; 116 char code[22]; 117 118 file = fopen (tcd->details.success.details.challenge_filename, 119 "r"); 120 if (NULL == file) 121 { 122 GNUNET_log_strerror_file ( 123 GNUNET_ERROR_TYPE_ERROR, 124 "open", 125 tcd->details.success.details.challenge_filename); 126 TALER_TESTING_interpreter_fail (ksls->is); 127 return; 128 } 129 /* fscanf returns EOF (-1), not 0, on an empty/short file; checking 130 `0 ==` misses that and would use the uninitialized `code` buffer. */ 131 if (1 != fscanf (file, 132 "%21s", 133 code)) 134 { 135 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, 136 "fscanf", 137 tcd->details.success.details. 138 challenge_filename); 139 GNUNET_break (0 == fclose (file)); 140 TALER_TESTING_interpreter_fail (ksls->is); 141 return; 142 } 143 GNUNET_break (0 == fclose (file)); 144 ksls->code = GNUNET_strdup (code); 145 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 146 "Read code `%s'\n", 147 code); 148 } 149 break; 150 case ANASTASIS_CS_TAN_SENT: 151 ksls->instructions = GNUNET_strdup ( 152 tcd->details.success.details.tan_address_hint); 153 break; 154 case ANASTASIS_CS_TAN_ALREADY_SENT: 155 break; 156 case ANASTASIS_CS_WIRE_FUNDS: 157 /* FIXME: not implemented */ 158 GNUNET_break (0); 159 return; 160 } 161 break; 162 case MHD_HTTP_PAYMENT_REQUIRED: 163 ksls->pay_uri = GNUNET_strdup ( 164 tcd->details.payment_required.payment_request); 165 ksls->payment_secret_response = tcd->details.payment_required.ps; 166 { 167 struct TALER_MERCHANT_PayUriData pd; 168 169 if (GNUNET_OK != 170 TALER_MERCHANT_parse_pay_uri (ksls->pay_uri, 171 &pd)) 172 { 173 GNUNET_break (0); 174 TALER_TESTING_interpreter_fail (ksls->is); 175 return; 176 } 177 ksls->order_id = GNUNET_strdup (pd.order_id); 178 TALER_MERCHANT_parse_pay_uri_free (&pd); 179 } 180 181 break; 182 default: 183 break; 184 } 185 TALER_TESTING_interpreter_next (ksls->is); 186 } 187 188 189 static void 190 truth_challenge_run (void *cls, 191 const struct TALER_TESTING_Command *cmd, 192 struct TALER_TESTING_Interpreter *is) 193 { 194 struct TruthChallengeState *ksls = cls; 195 const struct ANASTASIS_CRYPTO_TruthKeyP *truth_key; 196 const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid; 197 const struct ANASTASIS_PaymentSecretP *payment_secret; 198 199 ksls->is = is; 200 if (NULL == ksls->upload_reference) 201 { 202 GNUNET_break (0); 203 TALER_TESTING_interpreter_fail (ksls->is); 204 return; 205 } 206 { 207 const struct TALER_TESTING_Command *upload_cmd; 208 209 upload_cmd = TALER_TESTING_interpreter_lookup_command ( 210 is, 211 ksls->upload_reference); 212 if (NULL == upload_cmd) 213 { 214 GNUNET_break (0); 215 TALER_TESTING_interpreter_fail (ksls->is); 216 return; 217 } 218 if (GNUNET_OK != 219 ANASTASIS_TESTING_get_trait_truth_uuid (upload_cmd, 220 &truth_uuid)) 221 { 222 GNUNET_break (0); 223 TALER_TESTING_interpreter_fail (ksls->is); 224 return; 225 } 226 if (NULL == truth_uuid) 227 { 228 GNUNET_break (0); 229 TALER_TESTING_interpreter_fail (ksls->is); 230 return; 231 } 232 if (GNUNET_OK != 233 ANASTASIS_TESTING_get_trait_truth_key (upload_cmd, 234 &truth_key)) 235 { 236 GNUNET_break (0); 237 TALER_TESTING_interpreter_fail (ksls->is); 238 return; 239 } 240 if (NULL == truth_key) 241 { 242 GNUNET_break (0); 243 TALER_TESTING_interpreter_fail (ksls->is); 244 return; 245 } 246 } 247 248 if (NULL != ksls->payment_reference) 249 { 250 const struct TALER_TESTING_Command *payment_cmd; 251 252 payment_cmd = TALER_TESTING_interpreter_lookup_command ( 253 is, 254 ksls->payment_reference); 255 if (GNUNET_OK != 256 ANASTASIS_TESTING_get_trait_payment_secret (payment_cmd, 257 &payment_secret)) 258 { 259 GNUNET_break (0); 260 TALER_TESTING_interpreter_fail (ksls->is); 261 return; 262 } 263 } 264 else 265 { 266 payment_secret = NULL; 267 } 268 269 ksls->tco = ANASTASIS_truth_challenge ( 270 TALER_TESTING_interpreter_get_context (is), 271 ksls->anastasis_url, 272 truth_uuid, 273 truth_key, 274 payment_secret, 275 &truth_challenge_cb, 276 ksls); 277 if (NULL == ksls->tco) 278 { 279 GNUNET_break (0); 280 TALER_TESTING_interpreter_fail (ksls->is); 281 return; 282 } 283 } 284 285 286 static void 287 truth_challenge_cleanup (void *cls, 288 const struct TALER_TESTING_Command *cmd) 289 { 290 struct TruthChallengeState *ksls = cls; 291 292 if (NULL != ksls->tco) 293 { 294 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 295 "Command '%s' did not complete (keyshare lookup)\n", 296 cmd->label); 297 ANASTASIS_truth_challenge_cancel (ksls->tco); 298 ksls->tco = NULL; 299 } 300 GNUNET_free (ksls->pay_uri); 301 GNUNET_free (ksls->order_id); 302 GNUNET_free (ksls->code); 303 GNUNET_free (ksls->instructions); 304 GNUNET_free (ksls); 305 } 306 307 308 /** 309 * Offer internal data to other commands. 310 * 311 * @param cls closure 312 * @param[out] ret result (could be anything) 313 * @param[out] trait name of the trait 314 * @param index index number of the object to extract. 315 * @return #GNUNET_OK on success 316 */ 317 static enum GNUNET_GenericReturnValue 318 truth_challenge_traits (void *cls, 319 const void **ret, 320 const char *trait, 321 unsigned int index) 322 { 323 struct TruthChallengeState *ksls = cls; 324 struct TALER_TESTING_Trait traits[] = { 325 ANASTASIS_TESTING_make_trait_payment_secret ( 326 &ksls->payment_secret_response), 327 TALER_TESTING_make_trait_taler_uri (ksls->pay_uri), 328 TALER_TESTING_make_trait_order_id (ksls->order_id), 329 ANASTASIS_TESTING_make_trait_code (ksls->code), 330 TALER_TESTING_trait_end () 331 }; 332 333 return TALER_TESTING_get_trait (traits, 334 ret, 335 trait, 336 index); 337 } 338 339 340 struct TALER_TESTING_Command 341 ANASTASIS_TESTING_cmd_truth_challenge ( 342 const char *label, 343 const char *anastasis_url, 344 const char *payment_ref, 345 const char *upload_ref, 346 unsigned int http_status) 347 { 348 struct TruthChallengeState *ksls; 349 350 GNUNET_assert (NULL != upload_ref); 351 ksls = GNUNET_new (struct TruthChallengeState); 352 ksls->expected_http_status = http_status; 353 ksls->anastasis_url = anastasis_url; 354 ksls->upload_reference = upload_ref; 355 ksls->payment_reference = payment_ref; 356 { 357 struct TALER_TESTING_Command cmd = { 358 .cls = ksls, 359 .label = label, 360 .run = &truth_challenge_run, 361 .cleanup = &truth_challenge_cleanup, 362 .traits = &truth_challenge_traits 363 }; 364 365 return cmd; 366 } 367 } 368 369 370 /* end of testing_api_cmd_truth_challenge.c */