anastasis

Credential backup and recovery protocol and service
Log | Files | Refs | Submodules | README | LICENSE

test_anastasis_db.c (12802B)


      1 /*
      2   This file is part of Anastasis
      3   Copyright (C) 2020, 2021 Anastasis SARL
      4 
      5   Anastasis is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Affero 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 Affero General Public License for more details.
     12 
     13   You should have received a copy of the GNU Affero General Public License along with
     14   Anastasis; see the file COPYING.GPL.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file anastasis/test_anastasis_db.c
     18  * @brief testcase for anastasis postgres db plugin
     19  * @author Marcello Stanisci
     20  * @author Christian Grothoff
     21  */
     22 #include "platform.h"
     23 #include "anastasis_database_lib.h"
     24 #include "anastasis_util_lib.h"
     25 #include <gnunet/gnunet_signatures.h>
     26 
     27 
     28 #define FAILIF(cond)                            \
     29         do {                                          \
     30           if (! (cond)) { break;}                       \
     31           GNUNET_break (0);                           \
     32           goto drop;                                     \
     33         } while (0)
     34 
     35 #define RND_BLK(ptr)                                                    \
     36         GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (* \
     37                                                                              ptr))
     38 
     39 /**
     40  * Global return value for the test.  Initially -1, set to 0 upon
     41  * completion.   Other values indicate some kind of error.
     42  */
     43 static int result;
     44 
     45 /**
     46  * Handle to the plugin we are testing.
     47  */
     48 static struct ANASTASIS_DatabasePlugin *plugin;
     49 
     50 
     51 /**
     52  * Main function that will be run by the scheduler.
     53  *
     54  * @param cls closure with config
     55  */
     56 static void
     57 run (void *cls)
     58 {
     59   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
     60   struct TALER_Amount amount;
     61   struct ANASTASIS_PaymentSecretP paymentSecretP;
     62   struct ANASTASIS_CRYPTO_AccountPublicKeyP accountPubP;
     63   struct ANASTASIS_AccountSignatureP accountSig;
     64   struct ANASTASIS_AccountSignatureP res_account_sig;
     65   struct GNUNET_HashCode recoveryDataHash;
     66   struct GNUNET_HashCode res_recovery_data_hash;
     67   struct GNUNET_HashCode r;
     68   struct GNUNET_TIME_Relative rel_time;
     69   struct ANASTASIS_CRYPTO_TruthUUIDP truth_uuid;
     70   struct ANASTASIS_CRYPTO_EncryptedKeyShareP key_share;
     71   unsigned int post_counter;
     72   const char *mime_type;
     73   const char *method;
     74   uint32_t docVersion;
     75   uint32_t res_version;
     76   size_t recoverydatasize;
     77   void *res_recovery_data = NULL;
     78   struct ANASTASIS_CRYPTO_EncryptedKeyShareP res_key_share;
     79   bool paid;
     80   bool valid_counter;
     81   uint32_t recversion = 1;
     82   unsigned char aes_gcm_tag[16];
     83   const char *recovery_data = "RECOVERY_DATA";
     84   uint64_t challenge_code = 1234;
     85   struct GNUNET_HashCode c_hash;
     86   struct ANASTASIS_UploadSignaturePS usp = {
     87     .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST),
     88     .purpose.size = htonl (sizeof (usp))
     89   };
     90 
     91   if (NULL == (plugin = ANASTASIS_DB_plugin_load (cfg,
     92                                                   true)))
     93   {
     94     result = 77;
     95     return;
     96   }
     97   (void) plugin->drop_tables (plugin->cls);
     98   if (GNUNET_OK !=
     99       plugin->create_tables (plugin->cls))
    100   {
    101     result = 77;
    102     return;
    103   }
    104   if (GNUNET_OK !=
    105       plugin->connect (plugin->cls))
    106   {
    107     result = 77;
    108     return;
    109   }
    110 
    111   GNUNET_CRYPTO_hash (recovery_data,
    112                       strlen (recovery_data),
    113                       &recoveryDataHash);
    114   RND_BLK (&paymentSecretP);
    115   RND_BLK (&aes_gcm_tag);
    116   post_counter = 2;
    117   mime_type = "Picture";
    118   method = "Method";
    119   TALER_string_to_amount ("EUR:30",&amount);
    120 
    121   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
    122                               &truth_uuid,
    123                               sizeof (truth_uuid));
    124   rel_time = GNUNET_TIME_UNIT_MONTHS;
    125 
    126   GNUNET_assert (GNUNET_OK ==
    127                  TALER_string_to_amount ("EUR:1",
    128                                          &amount));
    129 
    130   memset (&key_share, 1, sizeof (key_share));
    131   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    132           plugin->store_truth (plugin->cls,
    133                                &truth_uuid,
    134                                &key_share,
    135                                mime_type,
    136                                "encrypted_truth",
    137                                strlen ("encrypted_truth"),
    138                                method,
    139                                rel_time));
    140 
    141   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    142           plugin->check_payment_identifier (plugin->cls,
    143                                             &paymentSecretP,
    144                                             &paid,
    145                                             &valid_counter));
    146 
    147   memset (&accountPubP, 2, sizeof (accountPubP));
    148   memset (&accountSig, 3, sizeof (accountSig));
    149   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    150           plugin->record_recdoc_payment (plugin->cls,
    151                                          &accountPubP,
    152                                          post_counter,
    153                                          &paymentSecretP,
    154                                          &amount));
    155   {
    156     struct GNUNET_TIME_Timestamp res_time;
    157 
    158     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    159             plugin->increment_lifetime (plugin->cls,
    160                                         &accountPubP,
    161                                         &paymentSecretP,
    162                                         rel_time,
    163                                         &res_time));
    164   }
    165   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    166           plugin->check_payment_identifier (plugin->cls,
    167                                             &paymentSecretP,
    168                                             &paid,
    169                                             &valid_counter));
    170   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    171           plugin->check_challenge_payment (plugin->cls,
    172                                            &paymentSecretP,
    173                                            &truth_uuid,
    174                                            &paid));
    175   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    176           plugin->record_challenge_payment (plugin->cls,
    177                                             &truth_uuid,
    178                                             &paymentSecretP,
    179                                             &amount));
    180   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    181           plugin->update_challenge_payment (plugin->cls,
    182                                             &truth_uuid,
    183                                             &paymentSecretP));
    184   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    185           plugin->check_challenge_payment (plugin->cls,
    186                                            &paymentSecretP,
    187                                            &truth_uuid,
    188                                            &paid));
    189   FAILIF (! paid);
    190   FAILIF (ANASTASIS_DB_STORE_STATUS_SUCCESS !=
    191           plugin->store_recovery_document (plugin->cls,
    192                                            &accountPubP,
    193                                            &accountSig,
    194                                            &recoveryDataHash,
    195                                            recovery_data,
    196                                            strlen (recovery_data),
    197                                            "meta-data",
    198                                            strlen ("meta-data"),
    199                                            &paymentSecretP,
    200                                            &docVersion));
    201   {
    202     uint32_t vrs;
    203     struct GNUNET_TIME_Timestamp exp;
    204 
    205     FAILIF (ANASTASIS_DB_ACCOUNT_STATUS_VALID_HASH_RETURNED !=
    206             plugin->lookup_account (plugin->cls,
    207                                     &accountPubP,
    208                                     &exp,
    209                                     &r,
    210                                     &vrs));
    211   }
    212   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    213           plugin->get_key_share (plugin->cls,
    214                                  &truth_uuid,
    215                                  &res_key_share));
    216   FAILIF (0 !=
    217           GNUNET_memcmp (&res_key_share,
    218                          &key_share));
    219 
    220   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    221           plugin->get_recovery_document (plugin->cls,
    222                                          &accountPubP,
    223                                          recversion,
    224                                          &res_account_sig,
    225                                          &res_recovery_data_hash,
    226                                          &recoverydatasize,
    227                                          &res_recovery_data));
    228   FAILIF (0 != memcmp (res_recovery_data,
    229                        recovery_data,
    230                        strlen (recovery_data)));
    231   GNUNET_free (res_recovery_data);
    232 
    233   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    234           plugin->get_latest_recovery_document (plugin->cls,
    235                                                 &accountPubP,
    236                                                 &res_account_sig,
    237                                                 &res_recovery_data_hash,
    238                                                 &recoverydatasize,
    239                                                 &res_recovery_data,
    240                                                 &res_version));
    241   FAILIF (0 != memcmp (res_recovery_data,
    242                        recovery_data,
    243                        strlen (recovery_data)));
    244   GNUNET_free (res_recovery_data);
    245 
    246   {
    247     struct GNUNET_TIME_Timestamp rt;
    248 
    249     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    250             plugin->create_challenge_code (plugin->cls,
    251                                            &truth_uuid,
    252                                            GNUNET_TIME_UNIT_HOURS,
    253                                            GNUNET_TIME_UNIT_DAYS,
    254                                            3, /* retry counter */
    255                                            &rt,
    256                                            &challenge_code));
    257     FAILIF (! GNUNET_TIME_absolute_is_zero (rt.abs_time));
    258   }
    259   {
    260     struct GNUNET_TIME_Timestamp rt;
    261     uint64_t c2;
    262 
    263     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    264             plugin->create_challenge_code (plugin->cls,
    265                                            &truth_uuid,
    266                                            GNUNET_TIME_UNIT_HOURS,
    267                                            GNUNET_TIME_UNIT_DAYS,
    268                                            3, /* retry counter */
    269                                            &rt,
    270                                            &c2));
    271     FAILIF (c2 != challenge_code);
    272   }
    273   ANASTASIS_hash_answer (123,
    274                          &c_hash);
    275   {
    276     bool sat;
    277     uint64_t r_code;
    278 
    279     FAILIF (ANASTASIS_DB_CODE_STATUS_CHALLENGE_CODE_MISMATCH !=
    280             plugin->verify_challenge_code (plugin->cls,
    281                                            &truth_uuid,
    282                                            &c_hash,
    283                                            &r_code,
    284                                            &sat));
    285 
    286     ANASTASIS_hash_answer (challenge_code,
    287                            &c_hash);
    288     FAILIF (ANASTASIS_DB_CODE_STATUS_VALID_CODE_STORED !=
    289             plugin->verify_challenge_code (plugin->cls,
    290                                            &truth_uuid,
    291                                            &c_hash,
    292                                            &r_code,
    293                                            &sat));
    294   }
    295   if (-1 == result)
    296     result = 0;
    297 
    298 drop:
    299   GNUNET_break (GNUNET_OK ==
    300                 plugin->drop_tables (plugin->cls));
    301   ANASTASIS_DB_plugin_unload (plugin);
    302   if (NULL != plugin)
    303   {
    304     plugin = NULL;
    305   }
    306 }
    307 
    308 
    309 int
    310 main (int argc,
    311       char *const argv[])
    312 {
    313   const char *plugin_name;
    314   char *config_filename;
    315   char *testname;
    316   struct GNUNET_CONFIGURATION_Handle *cfg;
    317 
    318   result = -1;
    319   if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
    320   {
    321     GNUNET_break (0);
    322     return -1;
    323   }
    324   GNUNET_log_setup (argv[0], "DEBUG", NULL);
    325   plugin_name++;
    326   GNUNET_asprintf (&testname,
    327                    "%s",
    328                    plugin_name);
    329   GNUNET_asprintf (&config_filename,
    330                    "test_anastasis_db_%s.conf",
    331                    testname);
    332   cfg = GNUNET_CONFIGURATION_create (ANASTASIS_project_data ());
    333   if (GNUNET_OK !=
    334       GNUNET_CONFIGURATION_load (cfg,
    335                                  config_filename))
    336   {
    337     GNUNET_break (0);
    338     GNUNET_free (config_filename);
    339     GNUNET_free (testname);
    340     return 2;
    341   }
    342   GNUNET_SCHEDULER_run (&run,
    343                         cfg);
    344   GNUNET_CONFIGURATION_destroy (cfg);
    345   GNUNET_free (config_filename);
    346   GNUNET_free (testname);
    347   return result;
    348 }
    349 
    350 
    351 /* end of test_anastasis_db.c */