aboutsummaryrefslogtreecommitdiff
path: root/src/testing/testing_cmd_challenge_answer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing/testing_cmd_challenge_answer.c')
-rw-r--r--src/testing/testing_cmd_challenge_answer.c584
1 files changed, 584 insertions, 0 deletions
diff --git a/src/testing/testing_cmd_challenge_answer.c b/src/testing/testing_cmd_challenge_answer.c
new file mode 100644
index 0000000..b243d61
--- /dev/null
+++ b/src/testing/testing_cmd_challenge_answer.c
@@ -0,0 +1,584 @@
1/*
2 This file is part of Anastasis
3 Copyright (C) 2020 Taler Systems SA
4
5 Anastasis is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Lesser 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 lib/testing_cmd_challenge_answer.c
18 * @brief command to execute the anastasis recovery service
19 * @author Christian Grothoff
20 * @author Dennis Neufeld
21 * @author Dominik Meister
22 */
23
24#include "platform.h"
25#include "anastasis_testing_lib.h"
26#include <taler/taler_util.h>
27#include <taler/taler_testing_lib.h>
28#include <taler/taler_merchant_service.h>
29
30
31/**
32 * State for a "challenge answer" CMD.
33 */
34struct ChallengeState
35{
36 /**
37 * The interpreter state.
38 */
39 struct TALER_TESTING_Interpreter *is;
40
41 /**
42 * Reference to the challenge we are solving
43 */
44 struct ANASTASIS_Challenge *c;
45
46 /**
47 * Answer to the challenge we are solving
48 */
49 const char *answer;
50
51 /**
52 * Reference to the recovery process
53 */
54 const char *challenge_ref;
55
56 /**
57 * Reference to the payment
58 */
59 const char *payment_ref;
60
61 /**
62 * "taler://pay/" URL we got back, if any. Otherwise NULL.
63 */
64 char *payment_uri;
65
66 /**
67 * Order ID extracted from @e payment_uri, or NULL.
68 */
69 char *order_id;
70
71 /**
72 * Payment order ID we are to provide in the request.
73 */
74 struct ANASTASIS_PaymentSecretP payment_order_req;
75
76 /**
77 * Expected status code.
78 */
79 enum ANASTASIS_ChallengeStatus expected_cs;
80
81 /**
82 * Index of the challenge we are solving
83 */
84 unsigned int challenge_index;
85
86 /**
87 * 0 for no plugin needed 1 for plugin needed to authenticate
88 */
89 unsigned int mode;
90
91 /**
92 * code we read in the file generated by the plugin
93 */
94 char code[22];
95
96};
97
98
99static void
100challenge_answer_cb (void *af_cls,
101 const struct ANASTASIS_ChallengeStartResponse *csr)
102{
103 struct ChallengeState *cs = af_cls;
104
105 cs->c = NULL;
106 if (csr->cs != cs->expected_cs)
107 {
108 GNUNET_break (0);
109 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
110 "Expected status %u, got %u\n",
111 cs->expected_cs,
112 csr->cs);
113 TALER_TESTING_interpreter_fail (cs->is);
114 return;
115 }
116 switch (csr->cs)
117 {
118 case ANASTASIS_CHALLENGE_STATUS_SOLVED:
119 break;
120 case ANASTASIS_CHALLENGE_STATUS_INSTRUCTIONS:
121 {
122 FILE *file;
123 char *fn;
124
125 if (0 == strcasecmp (csr->details.open_challenge.content_type,
126 "application/json"))
127 {
128 const char *filename;
129 json_t *in;
130
131 in = json_loadb (csr->details.open_challenge.body,
132 csr->details.open_challenge.body_size,
133 JSON_REJECT_DUPLICATES,
134 NULL);
135 if (NULL == in)
136 {
137 GNUNET_break (0);
138 TALER_TESTING_interpreter_fail (cs->is);
139 return;
140 }
141 filename = json_string_value (json_object_get (in,
142 "filename"));
143 if (NULL == filename)
144 {
145 GNUNET_break (0);
146 json_decref (in);
147 TALER_TESTING_interpreter_fail (cs->is);
148 return;
149 }
150 fn = GNUNET_strdup (filename);
151 json_decref (in);
152 }
153 else
154 {
155 fn = GNUNET_strndup (csr->details.open_challenge.body,
156 csr->details.open_challenge.body_size);
157 }
158 file = fopen (fn,
159 "r");
160 if (NULL == file)
161 {
162 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
163 "open",
164 fn);
165 GNUNET_free (fn);
166 TALER_TESTING_interpreter_fail (cs->is);
167 return;
168 }
169 if (0 == fscanf (file,
170 "%21s",
171 cs->code))
172 {
173 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
174 "fscanf",
175 fn);
176 TALER_TESTING_interpreter_fail (cs->is);
177 fclose (file);
178 GNUNET_free (fn);
179 return;
180 }
181 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
182 "Read challenge answer `%s' from file `%s'\n",
183 cs->code,
184 fn);
185 TALER_TESTING_interpreter_next (cs->is);
186 GNUNET_break (0 == fclose (file));
187 GNUNET_free (fn);
188 return;
189 }
190 case ANASTASIS_CHALLENGE_STATUS_PAYMENT_REQUIRED:
191 if (0 != strncmp (csr->details.payment_required.taler_pay_uri,
192 "taler+http://pay/",
193 strlen ("taler+http://pay/")))
194 {
195 GNUNET_break (0);
196 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
197 "Invalid payment URI `%s'\n",
198 csr->details.payment_required.taler_pay_uri);
199 TALER_TESTING_interpreter_fail (cs->is);
200 return;
201 }
202 cs->payment_uri = GNUNET_strdup (
203 csr->details.payment_required.taler_pay_uri);
204 {
205 struct TALER_MERCHANT_PayUriData pud;
206
207 if (GNUNET_OK !=
208 TALER_MERCHANT_parse_pay_uri (cs->payment_uri,
209 &pud))
210 {
211 GNUNET_break (0);
212 TALER_TESTING_interpreter_fail (cs->is);
213 return;
214 }
215 cs->order_id = GNUNET_strdup (pud.order_id);
216 if (GNUNET_OK !=
217 GNUNET_STRINGS_string_to_data (cs->order_id,
218 strlen (cs->order_id),
219 &cs->payment_order_req,
220 sizeof (cs->payment_order_req)))
221 {
222 GNUNET_break (0);
223 TALER_TESTING_interpreter_fail (cs->is);
224 return;
225 }
226 TALER_MERCHANT_parse_pay_uri_free (&pud);
227 }
228 TALER_TESTING_interpreter_next (cs->is);
229 return;
230 case ANASTASIS_CHALLENGE_STATUS_TRUTH_UNKNOWN:
231 break;
232 case ANASTASIS_CHALLENGE_STATUS_REDIRECT_FOR_AUTHENTICATION:
233 break;
234 case ANASTASIS_CHALLENGE_STATUS_SERVER_FAILURE:
235 GNUNET_break (0);
236 TALER_TESTING_interpreter_fail (cs->is);
237 return;
238 case ANASTASIS_CHALLENGE_STATUS_RATE_LIMIT_EXCEEDED:
239 break;
240 }
241 TALER_TESTING_interpreter_next (cs->is);
242}
243
244
245/**
246 * Run a "recover secret" CMD.
247 *
248 * @param cls closure.
249 * @param cmd command currently being run.
250 * @param is interpreter state.
251 */
252static void
253challenge_answer_run (void *cls,
254 const struct TALER_TESTING_Command *cmd,
255 struct TALER_TESTING_Interpreter *is)
256{
257 struct ChallengeState *cs = cls;
258 const struct ANASTASIS_Challenge *c;
259 const struct ANASTASIS_PaymentSecretP *ps;
260
261 cs->is = is;
262 if (NULL != cs->challenge_ref)
263 {
264 const struct TALER_TESTING_Command *ref;
265
266 ref = TALER_TESTING_interpreter_lookup_command (
267 is,
268 cs->challenge_ref);
269 if (NULL == ref)
270 {
271 GNUNET_break (0);
272 TALER_TESTING_interpreter_fail (cs->is);
273 return;
274 }
275 if (GNUNET_OK !=
276 ANASTASIS_TESTING_get_trait_challenge (ref,
277 cs->challenge_index,
278 &c))
279 {
280 GNUNET_break (0);
281 TALER_TESTING_interpreter_fail (cs->is);
282 return;
283 }
284 }
285
286 if (NULL != cs->payment_ref)
287 {
288 const struct TALER_TESTING_Command *ref;
289
290 ref = TALER_TESTING_interpreter_lookup_command (is,
291 cs->payment_ref);
292 if (NULL == ref)
293 {
294 GNUNET_break (0);
295 TALER_TESTING_interpreter_fail (cs->is);
296 return;
297 }
298 if (GNUNET_OK !=
299 ANASTASIS_TESTING_get_trait_payment_secret (ref,
300 0,
301 &ps))
302 {
303 GNUNET_break (0);
304 TALER_TESTING_interpreter_fail (cs->is);
305 return;
306 }
307 }
308 else
309 {
310 ps = NULL;
311 }
312
313 cs->c = (struct ANASTASIS_Challenge *) c;
314
315 if (1 == cs->mode)
316 {
317 const struct TALER_TESTING_Command *ref;
318 const char *answer;
319 unsigned long long code;
320 char dummy;
321
322 ref = TALER_TESTING_interpreter_lookup_command (is,
323 cs->answer);
324 if (NULL == ref)
325 {
326 GNUNET_break (0);
327 TALER_TESTING_interpreter_fail (cs->is);
328 return;
329 }
330 if (GNUNET_OK !=
331 ANASTASIS_TESTING_get_trait_code (ref,
332 0,
333 &answer))
334 {
335 GNUNET_break (0);
336 TALER_TESTING_interpreter_fail (cs->is);
337 return;
338 }
339 if (1 !=
340 sscanf (answer,
341 "%llu%c",
342 &code,
343 &dummy))
344 {
345 GNUNET_break (0);
346 TALER_TESTING_interpreter_fail (cs->is);
347 return;
348 }
349 if (GNUNET_OK !=
350 ANASTASIS_challenge_answer2 (cs->c,
351 ps,
352 GNUNET_TIME_UNIT_ZERO,
353 code,
354 &challenge_answer_cb,
355 cs))
356 {
357 GNUNET_break (0);
358 cs->c = NULL;
359 TALER_TESTING_interpreter_fail (cs->is);
360 return;
361 }
362
363 }
364 else
365 {
366 if (GNUNET_OK !=
367 ANASTASIS_challenge_answer (cs->c,
368 ps,
369 GNUNET_TIME_UNIT_ZERO,
370 cs->answer,
371 &challenge_answer_cb,
372 cs))
373 {
374 GNUNET_break (0);
375 cs->c = NULL;
376 TALER_TESTING_interpreter_fail (cs->is);
377 return;
378 }
379 }
380}
381
382
383/**
384 * Run a "recover secret" CMD.
385 *
386 * @param cls closure.
387 * @param cmd command currently being run.
388 * @param is interpreter state.
389 */
390static void
391challenge_start_run (void *cls,
392 const struct TALER_TESTING_Command *cmd,
393 struct TALER_TESTING_Interpreter *is)
394{
395 struct ChallengeState *cs = cls;
396 const struct ANASTASIS_Challenge *c;
397 const struct TALER_TESTING_Command *ref;
398 const struct ANASTASIS_PaymentSecretP *ps;
399
400 cs->is = is;
401 ref = TALER_TESTING_interpreter_lookup_command (
402 is,
403 cs->challenge_ref);
404 if (NULL == ref)
405 {
406 GNUNET_break (0);
407 TALER_TESTING_interpreter_fail (cs->is);
408 return;
409 }
410 if (GNUNET_OK !=
411 ANASTASIS_TESTING_get_trait_challenge (ref,
412 cs->challenge_index,
413 &c))
414 {
415 GNUNET_break (0);
416 TALER_TESTING_interpreter_fail (cs->is);
417 return;
418 }
419 if (NULL != cs->payment_ref)
420 {
421 const struct TALER_TESTING_Command *ref;
422
423 ref = TALER_TESTING_interpreter_lookup_command (is,
424 cs->payment_ref);
425 if (NULL == ref)
426 {
427 GNUNET_break (0);
428 TALER_TESTING_interpreter_fail (cs->is);
429 return;
430 }
431 if (GNUNET_OK !=
432 ANASTASIS_TESTING_get_trait_payment_secret (ref,
433 0,
434 &ps))
435 {
436 GNUNET_break (0);
437 TALER_TESTING_interpreter_fail (cs->is);
438 return;
439 }
440 }
441 else
442 {
443 ps = NULL;
444 }
445 if (GNUNET_OK !=
446 ANASTASIS_challenge_start ((struct ANASTASIS_Challenge *) c,
447 ps,
448 GNUNET_TIME_UNIT_ZERO,
449 NULL,
450 &challenge_answer_cb,
451 cs))
452 {
453 GNUNET_break (0);
454 TALER_TESTING_interpreter_fail (cs->is);
455 return;
456 }
457}
458
459
460/**
461 * Free the state of a "recover secret" CMD, and possibly
462 * cancel it if it did not complete.
463 *
464 * @param cls closure.
465 * @param cmd command being freed.
466 */
467static void
468challenge_cleanup (void *cls,
469 const struct TALER_TESTING_Command *cmd)
470{
471 struct ChallengeState *cs = cls;
472
473 if (NULL != cs->c)
474 {
475 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
476 "Command '%s' did not complete (challenge answer)\n",
477 cmd->label);
478 ANASTASIS_challenge_abort (cs->c);
479 cs->c = NULL;
480 }
481 GNUNET_free (cs->payment_uri);
482 GNUNET_free (cs->order_id);
483 GNUNET_free (cs);
484}
485
486
487/**
488 * Offer internal data to other commands.
489 *
490 * @param cls closure
491 * @param ret[out] result (could be anything)
492 * @param trait name of the trait
493 * @param index index number of the object to extract.
494 * @return #GNUNET_OK on success
495 */
496static int
497challenge_create_traits (void *cls,
498 const void **ret,
499 const char *trait,
500 unsigned int index)
501{
502 struct ChallengeState *cs = cls;
503 struct TALER_TESTING_Trait traits[] = {
504 ANASTASIS_TESTING_make_trait_code (0,
505 cs->code),
506 ANASTASIS_TESTING_make_trait_payment_secret (0,
507 &cs->payment_order_req),
508 TALER_TESTING_make_trait_url (TALER_TESTING_UT_TALER_URL,
509 cs->payment_uri),
510 TALER_TESTING_make_trait_order_id (0,
511 cs->order_id),
512 TALER_TESTING_trait_end ()
513 };
514
515 return TALER_TESTING_get_trait (traits,
516 ret,
517 trait,
518 index);
519}
520
521
522struct TALER_TESTING_Command
523ANASTASIS_TESTING_cmd_challenge_start (
524 const char *label,
525 const char *payment_ref,
526 const char *challenge_ref,
527 unsigned int challenge_index,
528 enum ANASTASIS_ChallengeStatus expected_cs)
529{
530 struct ChallengeState *cs;
531
532 cs = GNUNET_new (struct ChallengeState);
533 cs->expected_cs = expected_cs;
534 cs->challenge_ref = challenge_ref;
535 cs->payment_ref = payment_ref;
536 cs->challenge_index = challenge_index;
537 {
538 struct TALER_TESTING_Command cmd = {
539 .cls = cs,
540 .label = label,
541 .run = &challenge_start_run,
542 .cleanup = &challenge_cleanup,
543 .traits = &challenge_create_traits
544 };
545
546 return cmd;
547 }
548}
549
550
551struct TALER_TESTING_Command
552ANASTASIS_TESTING_cmd_challenge_answer (
553 const char *label,
554 const char *payment_ref,
555 const char *challenge_ref,
556 unsigned int challenge_index,
557 const char *answer,
558 unsigned int mode,
559 enum ANASTASIS_ChallengeStatus expected_cs)
560{
561 struct ChallengeState *cs;
562
563 cs = GNUNET_new (struct ChallengeState);
564 cs->expected_cs = expected_cs;
565 cs->challenge_ref = challenge_ref;
566 cs->payment_ref = payment_ref;
567 cs->answer = answer;
568 cs->challenge_index = challenge_index;
569 cs->mode = mode;
570 {
571 struct TALER_TESTING_Command cmd = {
572 .cls = cs,
573 .label = label,
574 .run = &challenge_answer_run,
575 .cleanup = &challenge_cleanup,
576 .traits = &challenge_create_traits
577 };
578
579 return cmd;
580 }
581}
582
583
584/* end of testing_cmd_challenge_answer.c */