LCOV - code coverage report
Current view: top level - testing - testing_cmd_challenge_answer.c (source / functions) Hit Total Coverage
Test: GNU Taler anastasis coverage report Lines: 116 204 56.9 %
Date: 2021-06-16 06:33:01 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             :  */
      34             : struct 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             : 
      99             : static void
     100           4 : challenge_answer_cb (void *af_cls,
     101             :                      const struct ANASTASIS_ChallengeStartResponse *csr)
     102             : {
     103           4 :   struct ChallengeState *cs = af_cls;
     104             : 
     105           4 :   cs->c = NULL;
     106           4 :   if (csr->cs != cs->expected_cs)
     107             :   {
     108           0 :     GNUNET_break (0);
     109           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     110             :                 "Expected status %u, got %u\n",
     111             :                 cs->expected_cs,
     112             :                 csr->cs);
     113           0 :     TALER_TESTING_interpreter_fail (cs->is);
     114           0 :     return;
     115             :   }
     116           4 :   switch (csr->cs)
     117             :   {
     118           2 :   case ANASTASIS_CHALLENGE_STATUS_SOLVED:
     119           2 :     break;
     120           1 :   case ANASTASIS_CHALLENGE_STATUS_INSTRUCTIONS:
     121             :     {
     122             :       FILE *file;
     123             :       char *fn;
     124             : 
     125           1 :       if (0 == strcasecmp (csr->details.open_challenge.content_type,
     126             :                            "application/json"))
     127             :       {
     128             :         const char *filename;
     129             :         json_t *in;
     130             : 
     131           1 :         in = json_loadb (csr->details.open_challenge.body,
     132             :                          csr->details.open_challenge.body_size,
     133             :                          JSON_REJECT_DUPLICATES,
     134             :                          NULL);
     135           1 :         if (NULL == in)
     136             :         {
     137           0 :           GNUNET_break (0);
     138           0 :           TALER_TESTING_interpreter_fail (cs->is);
     139           0 :           return;
     140             :         }
     141           1 :         filename = json_string_value (json_object_get (in,
     142             :                                                        "filename"));
     143           1 :         if (NULL == filename)
     144             :         {
     145           0 :           GNUNET_break (0);
     146           0 :           json_decref (in);
     147           0 :           TALER_TESTING_interpreter_fail (cs->is);
     148           0 :           return;
     149             :         }
     150           1 :         fn = GNUNET_strdup (filename);
     151           1 :         json_decref (in);
     152             :       }
     153             :       else
     154             :       {
     155           0 :         fn = GNUNET_strndup (csr->details.open_challenge.body,
     156             :                              csr->details.open_challenge.body_size);
     157             :       }
     158           1 :       file = fopen (fn,
     159             :                     "r");
     160           1 :       if (NULL == file)
     161             :       {
     162           0 :         GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
     163             :                                   "open",
     164             :                                   fn);
     165           0 :         GNUNET_free (fn);
     166           0 :         TALER_TESTING_interpreter_fail (cs->is);
     167           0 :         return;
     168             :       }
     169           1 :       if (0 == fscanf (file,
     170             :                        "%21s",
     171           1 :                        cs->code))
     172             :       {
     173           0 :         GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
     174             :                                   "fscanf",
     175             :                                   fn);
     176           0 :         TALER_TESTING_interpreter_fail (cs->is);
     177           0 :         fclose (file);
     178           0 :         GNUNET_free (fn);
     179           0 :         return;
     180             :       }
     181           1 :       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     182             :                   "Read challenge answer `%s' from file `%s'\n",
     183             :                   cs->code,
     184             :                   fn);
     185           1 :       TALER_TESTING_interpreter_next (cs->is);
     186           1 :       GNUNET_break (0 == fclose (file));
     187           1 :       GNUNET_free (fn);
     188           1 :       return;
     189             :     }
     190           1 :   case ANASTASIS_CHALLENGE_STATUS_PAYMENT_REQUIRED:
     191           1 :     if (0 != strncmp (csr->details.payment_required.taler_pay_uri,
     192             :                       "taler+http://pay/",
     193             :                       strlen ("taler+http://pay/")))
     194             :     {
     195           0 :       GNUNET_break (0);
     196           0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     197             :                   "Invalid payment URI `%s'\n",
     198             :                   csr->details.payment_required.taler_pay_uri);
     199           0 :       TALER_TESTING_interpreter_fail (cs->is);
     200           0 :       return;
     201             :     }
     202           1 :     cs->payment_uri = GNUNET_strdup (
     203             :       csr->details.payment_required.taler_pay_uri);
     204             :     {
     205             :       struct TALER_MERCHANT_PayUriData pud;
     206             : 
     207           1 :       if (GNUNET_OK !=
     208           1 :           TALER_MERCHANT_parse_pay_uri (cs->payment_uri,
     209             :                                         &pud))
     210             :       {
     211           0 :         GNUNET_break (0);
     212           0 :         TALER_TESTING_interpreter_fail (cs->is);
     213           0 :         return;
     214             :       }
     215           1 :       cs->order_id = GNUNET_strdup (pud.order_id);
     216           1 :       if (GNUNET_OK !=
     217           1 :           GNUNET_STRINGS_string_to_data (cs->order_id,
     218           1 :                                          strlen (cs->order_id),
     219           1 :                                          &cs->payment_order_req,
     220             :                                          sizeof (cs->payment_order_req)))
     221             :       {
     222           0 :         GNUNET_break (0);
     223           0 :         TALER_TESTING_interpreter_fail (cs->is);
     224           0 :         return;
     225             :       }
     226           1 :       TALER_MERCHANT_parse_pay_uri_free (&pud);
     227             :     }
     228           1 :     TALER_TESTING_interpreter_next (cs->is);
     229           1 :     return;
     230           0 :   case ANASTASIS_CHALLENGE_STATUS_TRUTH_UNKNOWN:
     231           0 :     break;
     232           0 :   case ANASTASIS_CHALLENGE_STATUS_REDIRECT_FOR_AUTHENTICATION:
     233           0 :     break;
     234           0 :   case ANASTASIS_CHALLENGE_STATUS_SERVER_FAILURE:
     235           0 :     GNUNET_break (0);
     236           0 :     TALER_TESTING_interpreter_fail (cs->is);
     237           0 :     return;
     238           0 :   case ANASTASIS_CHALLENGE_STATUS_RATE_LIMIT_EXCEEDED:
     239           0 :     break;
     240             :   }
     241           2 :   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             :  */
     252             : static void
     253           2 : challenge_answer_run (void *cls,
     254             :                       const struct TALER_TESTING_Command *cmd,
     255             :                       struct TALER_TESTING_Interpreter *is)
     256             : {
     257           2 :   struct ChallengeState *cs = cls;
     258             :   const struct ANASTASIS_Challenge *c;
     259             :   const struct ANASTASIS_PaymentSecretP *ps;
     260             : 
     261           2 :   cs->is = is;
     262           2 :   if (NULL != cs->challenge_ref)
     263             :   {
     264             :     const struct TALER_TESTING_Command *ref;
     265             : 
     266           2 :     ref = TALER_TESTING_interpreter_lookup_command (
     267             :       is,
     268             :       cs->challenge_ref);
     269           2 :     if (NULL == ref)
     270             :     {
     271           0 :       GNUNET_break (0);
     272           0 :       TALER_TESTING_interpreter_fail (cs->is);
     273           0 :       return;
     274             :     }
     275           2 :     if (GNUNET_OK !=
     276           2 :         ANASTASIS_TESTING_get_trait_challenge (ref,
     277             :                                                cs->challenge_index,
     278             :                                                &c))
     279             :     {
     280           0 :       GNUNET_break (0);
     281           0 :       TALER_TESTING_interpreter_fail (cs->is);
     282           0 :       return;
     283             :     }
     284             :   }
     285             : 
     286           2 :   if (NULL != cs->payment_ref)
     287             :   {
     288             :     const struct TALER_TESTING_Command *ref;
     289             : 
     290           1 :     ref = TALER_TESTING_interpreter_lookup_command (is,
     291             :                                                     cs->payment_ref);
     292           1 :     if (NULL == ref)
     293             :     {
     294           0 :       GNUNET_break (0);
     295           0 :       TALER_TESTING_interpreter_fail (cs->is);
     296           0 :       return;
     297             :     }
     298           1 :     if (GNUNET_OK !=
     299           1 :         ANASTASIS_TESTING_get_trait_payment_secret (ref,
     300             :                                                     0,
     301             :                                                     &ps))
     302             :     {
     303           0 :       GNUNET_break (0);
     304           0 :       TALER_TESTING_interpreter_fail (cs->is);
     305           0 :       return;
     306             :     }
     307             :   }
     308             :   else
     309             :   {
     310           1 :     ps = NULL;
     311             :   }
     312             : 
     313           2 :   cs->c = (struct ANASTASIS_Challenge *) c;
     314             : 
     315           2 :   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           1 :     ref = TALER_TESTING_interpreter_lookup_command (is,
     323             :                                                     cs->answer);
     324           1 :     if (NULL == ref)
     325             :     {
     326           0 :       GNUNET_break (0);
     327           0 :       TALER_TESTING_interpreter_fail (cs->is);
     328           0 :       return;
     329             :     }
     330           1 :     if (GNUNET_OK !=
     331           1 :         ANASTASIS_TESTING_get_trait_code (ref,
     332             :                                           0,
     333             :                                           &answer))
     334             :     {
     335           0 :       GNUNET_break (0);
     336           0 :       TALER_TESTING_interpreter_fail (cs->is);
     337           0 :       return;
     338             :     }
     339           1 :     if (1 !=
     340           1 :         sscanf (answer,
     341             :                 "%llu%c",
     342             :                 &code,
     343             :                 &dummy))
     344             :     {
     345           0 :       GNUNET_break (0);
     346           0 :       TALER_TESTING_interpreter_fail (cs->is);
     347           0 :       return;
     348             :     }
     349           1 :     if (GNUNET_OK !=
     350           1 :         ANASTASIS_challenge_answer2 (cs->c,
     351             :                                      ps,
     352             :                                      GNUNET_TIME_UNIT_ZERO,
     353             :                                      code,
     354             :                                      &challenge_answer_cb,
     355             :                                      cs))
     356             :     {
     357           0 :       GNUNET_break (0);
     358           0 :       cs->c = NULL;
     359           0 :       TALER_TESTING_interpreter_fail (cs->is);
     360           0 :       return;
     361             :     }
     362             : 
     363             :   }
     364             :   else
     365             :   {
     366           1 :     if (GNUNET_OK !=
     367           1 :         ANASTASIS_challenge_answer (cs->c,
     368             :                                     ps,
     369             :                                     GNUNET_TIME_UNIT_ZERO,
     370             :                                     cs->answer,
     371             :                                     &challenge_answer_cb,
     372             :                                     cs))
     373             :     {
     374           0 :       GNUNET_break (0);
     375           0 :       cs->c = NULL;
     376           0 :       TALER_TESTING_interpreter_fail (cs->is);
     377           0 :       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             :  */
     390             : static void
     391           2 : challenge_start_run (void *cls,
     392             :                      const struct TALER_TESTING_Command *cmd,
     393             :                      struct TALER_TESTING_Interpreter *is)
     394             : {
     395           2 :   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           2 :   cs->is = is;
     401           2 :   ref = TALER_TESTING_interpreter_lookup_command (
     402             :     is,
     403             :     cs->challenge_ref);
     404           2 :   if (NULL == ref)
     405             :   {
     406           0 :     GNUNET_break (0);
     407           0 :     TALER_TESTING_interpreter_fail (cs->is);
     408           0 :     return;
     409             :   }
     410           2 :   if (GNUNET_OK !=
     411           2 :       ANASTASIS_TESTING_get_trait_challenge (ref,
     412             :                                              cs->challenge_index,
     413             :                                              &c))
     414             :   {
     415           0 :     GNUNET_break (0);
     416           0 :     TALER_TESTING_interpreter_fail (cs->is);
     417           0 :     return;
     418             :   }
     419           2 :   if (NULL != cs->payment_ref)
     420             :   {
     421             :     const struct TALER_TESTING_Command *ref;
     422             : 
     423           1 :     ref = TALER_TESTING_interpreter_lookup_command (is,
     424             :                                                     cs->payment_ref);
     425           1 :     if (NULL == ref)
     426             :     {
     427           0 :       GNUNET_break (0);
     428           0 :       TALER_TESTING_interpreter_fail (cs->is);
     429           0 :       return;
     430             :     }
     431           1 :     if (GNUNET_OK !=
     432           1 :         ANASTASIS_TESTING_get_trait_payment_secret (ref,
     433             :                                                     0,
     434             :                                                     &ps))
     435             :     {
     436           0 :       GNUNET_break (0);
     437           0 :       TALER_TESTING_interpreter_fail (cs->is);
     438           0 :       return;
     439             :     }
     440             :   }
     441             :   else
     442             :   {
     443           1 :     ps = NULL;
     444             :   }
     445           2 :   if (GNUNET_OK !=
     446           2 :       ANASTASIS_challenge_start ((struct ANASTASIS_Challenge *) c,
     447             :                                  ps,
     448             :                                  GNUNET_TIME_UNIT_ZERO,
     449             :                                  NULL,
     450             :                                  &challenge_answer_cb,
     451             :                                  cs))
     452             :   {
     453           0 :     GNUNET_break (0);
     454           0 :     TALER_TESTING_interpreter_fail (cs->is);
     455           0 :     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             :  */
     467             : static void
     468           4 : challenge_cleanup (void *cls,
     469             :                    const struct TALER_TESTING_Command *cmd)
     470             : {
     471           4 :   struct ChallengeState *cs = cls;
     472             : 
     473           4 :   if (NULL != cs->c)
     474             :   {
     475           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     476             :                 "Command '%s' did not complete (challenge answer)\n",
     477             :                 cmd->label);
     478           0 :     ANASTASIS_challenge_abort (cs->c);
     479           0 :     cs->c = NULL;
     480             :   }
     481           4 :   GNUNET_free (cs->payment_uri);
     482           4 :   GNUNET_free (cs->order_id);
     483           4 :   GNUNET_free (cs);
     484           4 : }
     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             :  */
     496             : static int
     497           6 : challenge_create_traits (void *cls,
     498             :                          const void **ret,
     499             :                          const char *trait,
     500             :                          unsigned int index)
     501             : {
     502           6 :   struct ChallengeState *cs = cls;
     503             :   struct TALER_TESTING_Trait traits[] = {
     504           6 :     ANASTASIS_TESTING_make_trait_code (0,
     505           6 :                                        cs->code),
     506           6 :     ANASTASIS_TESTING_make_trait_payment_secret (0,
     507           6 :                                                  &cs->payment_order_req),
     508           6 :     TALER_TESTING_make_trait_url (TALER_TESTING_UT_TALER_URL,
     509           6 :                                   cs->payment_uri),
     510           6 :     TALER_TESTING_make_trait_order_id (0,
     511           6 :                                        cs->order_id),
     512           6 :     TALER_TESTING_trait_end ()
     513             :   };
     514             : 
     515           6 :   return TALER_TESTING_get_trait (traits,
     516             :                                   ret,
     517             :                                   trait,
     518             :                                   index);
     519             : }
     520             : 
     521             : 
     522             : struct TALER_TESTING_Command
     523           2 : ANASTASIS_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           2 :   cs = GNUNET_new (struct ChallengeState);
     533           2 :   cs->expected_cs = expected_cs;
     534           2 :   cs->challenge_ref = challenge_ref;
     535           2 :   cs->payment_ref = payment_ref;
     536           2 :   cs->challenge_index = challenge_index;
     537             :   {
     538           2 :     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           2 :     return cmd;
     547             :   }
     548             : }
     549             : 
     550             : 
     551             : struct TALER_TESTING_Command
     552           2 : ANASTASIS_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           2 :   cs = GNUNET_new (struct ChallengeState);
     564           2 :   cs->expected_cs = expected_cs;
     565           2 :   cs->challenge_ref = challenge_ref;
     566           2 :   cs->payment_ref = payment_ref;
     567           2 :   cs->answer = answer;
     568           2 :   cs->challenge_index = challenge_index;
     569           2 :   cs->mode = mode;
     570             :   {
     571           2 :     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           2 :     return cmd;
     580             :   }
     581             : }
     582             : 
     583             : 
     584             : /* end of testing_cmd_challenge_answer.c */

Generated by: LCOV version 1.14