LCOV - code coverage report
Current view: top level - test - test_hs_cache.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 360 360 100.0 %
Date: 2021-11-24 03:28:48 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /* Copyright (c) 2016-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : /**
       5             :  * \file test_hs_cache.c
       6             :  * \brief Test hidden service caches.
       7             :  */
       8             : 
       9             : #define CONNECTION_PRIVATE
      10             : #define DIRCACHE_PRIVATE
      11             : #define DIRCLIENT_PRIVATE
      12             : #define HS_CACHE_PRIVATE
      13             : #define CHANNEL_OBJECT_PRIVATE
      14             : 
      15             : #include "trunnel/ed25519_cert.h"
      16             : #include "feature/hs/hs_cache.h"
      17             : #include "feature/dircache/dircache.h"
      18             : #include "feature/dirclient/dirclient.h"
      19             : #include "feature/nodelist/networkstatus.h"
      20             : #include "core/mainloop/connection.h"
      21             : #include "core/proto/proto_http.h"
      22             : #include "core/or/circuitlist.h"
      23             : #include "core/or/channel.h"
      24             : #include "lib/crypt_ops/crypto_format.h"
      25             : #include "lib/crypt_ops/crypto_rand.h"
      26             : 
      27             : #include "core/or/edge_connection_st.h"
      28             : #include "core/or/or_circuit_st.h"
      29             : #include "core/or/or_connection_st.h"
      30             : #include "feature/dircommon/dir_connection_st.h"
      31             : #include "feature/nodelist/networkstatus_st.h"
      32             : 
      33             : #include "test/hs_test_helpers.h"
      34             : #include "test/test_helpers.h"
      35             : #include "test/test.h"
      36             : 
      37             : /* Static variable used to encoded the HSDir query. */
      38             : static char query_b64[256];
      39             : 
      40             : /* Build an HSDir query using a ed25519 public key. */
      41             : static const char *
      42           9 : helper_get_hsdir_query(const hs_descriptor_t *desc)
      43             : {
      44           9 :   ed25519_public_to_base64(query_b64, &desc->plaintext_data.blinded_pubkey);
      45           9 :   return query_b64;
      46             : }
      47             : 
      48             : static void
      49           5 : init_test(void)
      50             : {
      51             :   /* Always needed. Initialize the subsystem. */
      52           5 :   hs_cache_init();
      53           5 : }
      54             : 
      55             : static void
      56           1 : test_directory(void *arg)
      57             : {
      58           1 :   int ret;
      59           1 :   size_t oom_size;
      60           1 :   char *desc1_str = NULL;
      61           1 :   const char *desc_out;
      62           1 :   ed25519_keypair_t signing_kp1;
      63           1 :   hs_descriptor_t *desc1 = NULL;
      64             : 
      65           1 :   (void) arg;
      66             : 
      67           1 :   init_test();
      68             :   /* Generate a valid descriptor with normal values. */
      69           1 :   ret = ed25519_keypair_generate(&signing_kp1, 0);
      70           1 :   tt_int_op(ret, OP_EQ, 0);
      71           1 :   desc1 = hs_helper_build_hs_desc_with_ip(&signing_kp1);
      72           1 :   tt_assert(desc1);
      73           1 :   ret = hs_desc_encode_descriptor(desc1, &signing_kp1, NULL, &desc1_str);
      74           1 :   tt_int_op(ret, OP_EQ, 0);
      75             : 
      76             :   /* Very first basic test, should be able to be stored, survive a
      77             :    * clean, found with a lookup and then cleaned by our OOM. */
      78             :   {
      79           1 :     ret = hs_cache_store_as_dir(desc1_str);
      80           1 :     tt_int_op(ret, OP_EQ, 0);
      81             :     /* Re-add, it should fail since we already have it. */
      82           1 :     ret = hs_cache_store_as_dir(desc1_str);
      83           1 :     tt_int_op(ret, OP_EQ, -1);
      84             :     /* Try to clean now which should be fine, there is at worst few seconds
      85             :      * between the store and this call. */
      86           1 :     hs_cache_clean_as_dir(time(NULL));
      87             :     /* We should find it in our cache. */
      88           1 :     ret = hs_cache_lookup_as_dir(3, helper_get_hsdir_query(desc1), &desc_out);
      89           1 :     tt_int_op(ret, OP_EQ, 1);
      90           1 :     tt_str_op(desc_out, OP_EQ, desc1_str);
      91             :     /* Tell our OOM to run and to at least remove a byte which will result in
      92             :      * removing the descriptor from our cache. */
      93           1 :     oom_size = hs_cache_handle_oom(time(NULL), 1);
      94           1 :     tt_int_op(oom_size, OP_GE, 1);
      95           1 :     ret = hs_cache_lookup_as_dir(3, helper_get_hsdir_query(desc1), NULL);
      96           1 :     tt_int_op(ret, OP_EQ, 0);
      97             :   }
      98             : 
      99             :   /* Store two descriptors and remove the expiring one only. */
     100             :   {
     101           1 :     ed25519_keypair_t signing_kp_zero;
     102           1 :     ret = ed25519_keypair_generate(&signing_kp_zero, 0);
     103           1 :     tt_int_op(ret, OP_EQ, 0);
     104           1 :     hs_descriptor_t *desc_zero_lifetime;
     105           1 :     desc_zero_lifetime = hs_helper_build_hs_desc_with_ip(&signing_kp_zero);
     106           1 :     tt_assert(desc_zero_lifetime);
     107           1 :     desc_zero_lifetime->plaintext_data.revision_counter = 1;
     108           1 :     desc_zero_lifetime->plaintext_data.lifetime_sec = 0;
     109           1 :     char *desc_zero_lifetime_str;
     110           1 :     ret = hs_desc_encode_descriptor(desc_zero_lifetime, &signing_kp_zero,
     111             :                                     NULL, &desc_zero_lifetime_str);
     112           1 :     tt_int_op(ret, OP_EQ, 0);
     113             : 
     114           1 :     ret = hs_cache_store_as_dir(desc1_str);
     115           1 :     tt_int_op(ret, OP_EQ, 0);
     116           1 :     ret = hs_cache_store_as_dir(desc_zero_lifetime_str);
     117           1 :     tt_int_op(ret, OP_EQ, 0);
     118             :     /* This one should clear out our zero lifetime desc. */
     119           1 :     hs_cache_clean_as_dir(time(NULL));
     120             :     /* We should find desc1 in our cache. */
     121           1 :     ret = hs_cache_lookup_as_dir(3, helper_get_hsdir_query(desc1), &desc_out);
     122           1 :     tt_int_op(ret, OP_EQ, 1);
     123           1 :     tt_str_op(desc_out, OP_EQ, desc1_str);
     124             :     /* We should NOT find our zero lifetime desc in our cache. */
     125           1 :     ret = hs_cache_lookup_as_dir(3,
     126             :                                  helper_get_hsdir_query(desc_zero_lifetime),
     127             :                                  NULL);
     128           1 :     tt_int_op(ret, OP_EQ, 0);
     129             :     /* Cleanup our entire cache. */
     130           1 :     oom_size = hs_cache_handle_oom(time(NULL), 1);
     131           1 :     tt_int_op(oom_size, OP_GE, 1);
     132           1 :     hs_descriptor_free(desc_zero_lifetime);
     133           1 :     tor_free(desc_zero_lifetime_str);
     134             :   }
     135             : 
     136             :   /* Throw junk at it. */
     137             :   {
     138           1 :     ret = hs_cache_store_as_dir("blah");
     139           1 :     tt_int_op(ret, OP_EQ, -1);
     140             :     /* Poor attempt at tricking the decoding. */
     141           1 :     ret = hs_cache_store_as_dir("hs-descriptor 3\nJUNK");
     142           1 :     tt_int_op(ret, OP_EQ, -1);
     143             :     /* Undecodable base64 query. */
     144           1 :     ret = hs_cache_lookup_as_dir(3, "blah", NULL);
     145           1 :     tt_int_op(ret, OP_EQ, -1);
     146             :     /* Decodable base64 query but wrong ed25519 size. */
     147           1 :     ret = hs_cache_lookup_as_dir(3, "dW5pY29ybg==", NULL);
     148           1 :     tt_int_op(ret, OP_EQ, -1);
     149             :   }
     150             : 
     151             :   /* Test descriptor replacement with revision counter. */
     152             :   {
     153           1 :     char *new_desc_str;
     154             : 
     155             :     /* Add a descriptor. */
     156           1 :     ret = hs_cache_store_as_dir(desc1_str);
     157           1 :     tt_int_op(ret, OP_EQ, 0);
     158           1 :     ret = hs_cache_lookup_as_dir(3, helper_get_hsdir_query(desc1), &desc_out);
     159           1 :     tt_int_op(ret, OP_EQ, 1);
     160             :     /* Bump revision counter. */
     161           1 :     desc1->plaintext_data.revision_counter++;
     162           1 :     ret = hs_desc_encode_descriptor(desc1, &signing_kp1, NULL, &new_desc_str);
     163           1 :     tt_int_op(ret, OP_EQ, 0);
     164           1 :     ret = hs_cache_store_as_dir(new_desc_str);
     165           1 :     tt_int_op(ret, OP_EQ, 0);
     166             :     /* Look it up, it should have been replaced. */
     167           1 :     ret = hs_cache_lookup_as_dir(3, helper_get_hsdir_query(desc1), &desc_out);
     168           1 :     tt_int_op(ret, OP_EQ, 1);
     169           1 :     tt_str_op(desc_out, OP_EQ, new_desc_str);
     170           1 :     tor_free(new_desc_str);
     171             :   }
     172             : 
     173           1 :  done:
     174           1 :   hs_descriptor_free(desc1);
     175           1 :   tor_free(desc1_str);
     176           1 : }
     177             : 
     178             : static void
     179           1 : test_clean_as_dir(void *arg)
     180             : {
     181           1 :   size_t ret;
     182           1 :   char *desc1_str = NULL;
     183           1 :   time_t now = time(NULL);
     184           1 :   hs_descriptor_t *desc1 = NULL;
     185           1 :   ed25519_keypair_t signing_kp1;
     186             : 
     187           1 :   (void) arg;
     188             : 
     189           1 :   init_test();
     190             : 
     191             :   /* Generate a valid descriptor with values. */
     192           1 :   ret = ed25519_keypair_generate(&signing_kp1, 0);
     193           1 :   tt_int_op(ret, OP_EQ, 0);
     194           1 :   desc1 = hs_helper_build_hs_desc_with_ip(&signing_kp1);
     195           1 :   tt_assert(desc1);
     196           1 :   ret = hs_desc_encode_descriptor(desc1, &signing_kp1, NULL, &desc1_str);
     197           1 :   tt_int_op(ret, OP_EQ, 0);
     198           1 :   ret = hs_cache_store_as_dir(desc1_str);
     199           1 :   tt_int_op(ret, OP_EQ, 0);
     200             : 
     201             :   /* With the lifetime being 3 hours, a cleanup shouldn't remove it. */
     202           1 :   ret = cache_clean_v3_as_dir(now, 0);
     203           1 :   tt_int_op(ret, OP_EQ, 0);
     204             :   /* Should be present after clean up. */
     205           1 :   ret = hs_cache_lookup_as_dir(3, helper_get_hsdir_query(desc1), NULL);
     206           1 :   tt_int_op(ret, OP_EQ, 1);
     207             :   /* Set a cutoff 100 seconds in the past. It should not remove the entry
     208             :    * since the entry is still recent enough. */
     209           1 :   ret = cache_clean_v3_as_dir(now, now - 100);
     210           1 :   tt_int_op(ret, OP_EQ, 0);
     211             :   /* Should be present after clean up. */
     212           1 :   ret = hs_cache_lookup_as_dir(3, helper_get_hsdir_query(desc1), NULL);
     213           1 :   tt_int_op(ret, OP_EQ, 1);
     214             :   /* Set a cutoff of 100 seconds in the future. It should remove the entry
     215             :    * that we've just added since it's not too old for the cutoff. */
     216           1 :   ret = cache_clean_v3_as_dir(now, now + 100);
     217           1 :   tt_int_op(ret, OP_GT, 0);
     218             :   /* Shouldn't be present after clean up. */
     219           1 :   ret = hs_cache_lookup_as_dir(3, helper_get_hsdir_query(desc1), NULL);
     220           1 :   tt_int_op(ret, OP_EQ, 0);
     221             : 
     222           1 :  done:
     223           1 :   hs_descriptor_free(desc1);
     224           1 :   tor_free(desc1_str);
     225           1 : }
     226             : 
     227             : /* Test helper: Fetch an HS descriptor from an HSDir (for the hidden service
     228             :    with <b>blinded_key</b>. Return the received descriptor string. */
     229             : static char *
     230           5 : helper_fetch_desc_from_hsdir(const ed25519_public_key_t *blinded_key)
     231             : {
     232           5 :   int retval;
     233             : 
     234           5 :   char *received_desc = NULL;
     235           5 :   char *hsdir_query_str = NULL;
     236             : 
     237             :   /* The dir conn we are going to simulate */
     238           5 :   dir_connection_t *conn = NULL;
     239           5 :   edge_connection_t *edge_conn = NULL;
     240           5 :   or_circuit_t *or_circ = NULL;
     241             : 
     242             :   /* First extract the blinded public key that we are going to use in our
     243             :      query, and then build the actual query string. */
     244             :   {
     245           5 :     char hsdir_cache_key[ED25519_BASE64_LEN+1];
     246             : 
     247           5 :     ed25519_public_to_base64(hsdir_cache_key, blinded_key);
     248           5 :     tor_asprintf(&hsdir_query_str, GET("/tor/hs/3/%s"), hsdir_cache_key);
     249             :   }
     250             : 
     251             :   /* Simulate an HTTP GET request to the HSDir */
     252           5 :   conn = dir_connection_new(AF_INET);
     253           5 :   tt_assert(conn);
     254           5 :   TO_CONN(conn)->linked = 1; /* Signal that it is encrypted. */
     255           5 :   tor_addr_from_ipv4h(&conn->base_.addr, 0x7f000001);
     256             : 
     257             :   /* Pretend this conn is anonymous. */
     258           5 :   edge_conn = edge_connection_new(CONN_TYPE_EXIT, AF_INET);
     259           5 :   TO_CONN(conn)->linked_conn = TO_CONN(edge_conn);
     260           5 :   or_circ = or_circuit_new(0, NULL);
     261           5 :   or_circ->p_chan = tor_malloc_zero(sizeof(channel_t));
     262           5 :   edge_conn->on_circuit = TO_CIRCUIT(or_circ);
     263             : 
     264           5 :   retval = directory_handle_command_get(conn, hsdir_query_str,
     265             :                                         NULL, 0);
     266           5 :   tt_int_op(retval, OP_EQ, 0);
     267             : 
     268             :   /* Read the descriptor that the HSDir just served us */
     269             :   {
     270           5 :     char *headers = NULL;
     271           5 :     size_t body_used = 0;
     272             : 
     273           5 :     fetch_from_buf_http(TO_CONN(conn)->outbuf, &headers, MAX_HEADERS_SIZE,
     274             :                         &received_desc, &body_used, HS_DESC_MAX_LEN, 0);
     275           5 :     tor_free(headers);
     276             :   }
     277             : 
     278           5 :  done:
     279           5 :   tor_free(hsdir_query_str);
     280           5 :   if (conn) {
     281           5 :     tor_free(or_circ->p_chan);
     282           5 :     connection_free_minimal(TO_CONN(conn)->linked_conn);
     283           5 :     connection_free_minimal(TO_CONN(conn));
     284             :   }
     285             : 
     286           5 :   return received_desc;
     287             : }
     288             : 
     289             : /* Publish a descriptor to the HSDir, then fetch it. Check that the received
     290             :    descriptor matches the published one. */
     291             : static void
     292           1 : test_upload_and_download_hs_desc(void *arg)
     293             : {
     294           1 :   int retval;
     295           1 :   hs_descriptor_t *published_desc = NULL;
     296             : 
     297           1 :   char *published_desc_str = NULL;
     298           1 :   char *received_desc_str = NULL;
     299             : 
     300           1 :   (void) arg;
     301             : 
     302             :   /* Initialize HSDir cache subsystem */
     303           1 :   init_test();
     304             : 
     305             :   /* Test a descriptor not found in the directory cache. */
     306             :   {
     307           1 :     ed25519_public_key_t blinded_key;
     308           1 :     memset(&blinded_key.pubkey, 'A', sizeof(blinded_key.pubkey));
     309           1 :     received_desc_str = helper_fetch_desc_from_hsdir(&blinded_key);
     310           1 :     tt_int_op(strlen(received_desc_str), OP_EQ, 0);
     311           1 :     tor_free(received_desc_str);
     312             :   }
     313             : 
     314             :   /* Generate a valid descriptor with normal values. */
     315             :   {
     316           1 :     ed25519_keypair_t signing_kp;
     317           1 :     retval = ed25519_keypair_generate(&signing_kp, 0);
     318           1 :     tt_int_op(retval, OP_EQ, 0);
     319           1 :     published_desc = hs_helper_build_hs_desc_with_ip(&signing_kp);
     320           1 :     tt_assert(published_desc);
     321           1 :     retval = hs_desc_encode_descriptor(published_desc, &signing_kp,
     322             :                                        NULL, &published_desc_str);
     323           1 :     tt_int_op(retval, OP_EQ, 0);
     324             :   }
     325             : 
     326             :   /* Publish descriptor to the HSDir */
     327             :   {
     328           1 :     retval = handle_post_hs_descriptor("/tor/hs/3/publish",published_desc_str);
     329           1 :     tt_int_op(retval, OP_EQ, 200);
     330             :   }
     331             : 
     332             :   /* Simulate a fetch of the previously published descriptor */
     333             :   {
     334           1 :     const ed25519_public_key_t *blinded_key;
     335           1 :     blinded_key = &published_desc->plaintext_data.blinded_pubkey;
     336           1 :     received_desc_str = helper_fetch_desc_from_hsdir(blinded_key);
     337             :   }
     338             : 
     339             :   /* Verify we received the exact same descriptor we published earlier */
     340           1 :   tt_str_op(received_desc_str, OP_EQ, published_desc_str);
     341           1 :   tor_free(received_desc_str);
     342             : 
     343             :   /* With a valid descriptor in the directory cache, try again an invalid. */
     344             :   {
     345           1 :     ed25519_public_key_t blinded_key;
     346           1 :     memset(&blinded_key.pubkey, 'A', sizeof(blinded_key.pubkey));
     347           1 :     received_desc_str = helper_fetch_desc_from_hsdir(&blinded_key);
     348           1 :     tt_int_op(strlen(received_desc_str), OP_EQ, 0);
     349             :   }
     350             : 
     351           1 :  done:
     352           1 :   tor_free(received_desc_str);
     353           1 :   tor_free(published_desc_str);
     354           1 :   hs_descriptor_free(published_desc);
     355           1 : }
     356             : 
     357             : /* Test that HSDirs reject outdated descriptors based on their revision
     358             :  * counter. Also test that HSDirs correctly replace old descriptors with newer
     359             :  * descriptors. */
     360             : static void
     361           1 : test_hsdir_revision_counter_check(void *arg)
     362             : {
     363           1 :   int retval;
     364             : 
     365           1 :   ed25519_keypair_t signing_kp;
     366             : 
     367           1 :   hs_descriptor_t *published_desc = NULL;
     368           1 :   char *published_desc_str = NULL;
     369             : 
     370           1 :   hs_subcredential_t subcredential;
     371           1 :   char *received_desc_str = NULL;
     372           1 :   hs_descriptor_t *received_desc = NULL;
     373             : 
     374           1 :   (void) arg;
     375             : 
     376             :   /* Initialize HSDir cache subsystem */
     377           1 :   init_test();
     378             : 
     379             :   /* Generate a valid descriptor with normal values. */
     380             :   {
     381           1 :     retval = ed25519_keypair_generate(&signing_kp, 0);
     382           1 :     tt_int_op(retval, OP_EQ, 0);
     383           1 :     published_desc = hs_helper_build_hs_desc_with_ip(&signing_kp);
     384           1 :     tt_assert(published_desc);
     385           1 :     retval = hs_desc_encode_descriptor(published_desc, &signing_kp,
     386             :                                        NULL, &published_desc_str);
     387           1 :     tt_int_op(retval, OP_EQ, 0);
     388             :   }
     389             : 
     390             :   /* Publish descriptor to the HSDir */
     391             :   {
     392           1 :     retval = handle_post_hs_descriptor("/tor/hs/3/publish",published_desc_str);
     393           1 :     tt_int_op(retval, OP_EQ, 200);
     394             :   }
     395             : 
     396             :   /* Try publishing again with the same revision counter: Should fail. */
     397             :   {
     398           1 :     retval = handle_post_hs_descriptor("/tor/hs/3/publish",published_desc_str);
     399           1 :     tt_int_op(retval, OP_EQ, 400);
     400             :   }
     401             : 
     402             :   /* Fetch the published descriptor and validate the revision counter. */
     403             :   {
     404           1 :     const ed25519_public_key_t *blinded_key;
     405             : 
     406           1 :     blinded_key = &published_desc->plaintext_data.blinded_pubkey;
     407           1 :     hs_get_subcredential(&signing_kp.pubkey, blinded_key, &subcredential);
     408           1 :     received_desc_str = helper_fetch_desc_from_hsdir(blinded_key);
     409             : 
     410           1 :     retval = hs_desc_decode_descriptor(received_desc_str,
     411             :                                        &subcredential, NULL, &received_desc);
     412           1 :     tt_int_op(retval, OP_EQ, HS_DESC_DECODE_OK);
     413           1 :     tt_assert(received_desc);
     414             : 
     415             :     /* Check that the revision counter is correct */
     416           1 :     tt_u64_op(received_desc->plaintext_data.revision_counter, OP_EQ, 42);
     417             : 
     418           1 :     hs_descriptor_free(received_desc);
     419           1 :     received_desc = NULL;
     420           1 :     tor_free(received_desc_str);
     421             :   }
     422             : 
     423             :   /* Increment the revision counter and try again. Should work. */
     424             :   {
     425           1 :     published_desc->plaintext_data.revision_counter = 1313;
     426           1 :     tor_free(published_desc_str);
     427           1 :     retval = hs_desc_encode_descriptor(published_desc, &signing_kp,
     428             :                                        NULL, &published_desc_str);
     429           1 :     tt_int_op(retval, OP_EQ, 0);
     430             : 
     431           1 :     retval = handle_post_hs_descriptor("/tor/hs/3/publish",published_desc_str);
     432           1 :     tt_int_op(retval, OP_EQ, 200);
     433             :   }
     434             : 
     435             :   /* Again, fetch the published descriptor and perform the revision counter
     436             :      validation. The revision counter must have changed. */
     437             :   {
     438           1 :     const ed25519_public_key_t *blinded_key;
     439             : 
     440           1 :     blinded_key = &published_desc->plaintext_data.blinded_pubkey;
     441           1 :     received_desc_str = helper_fetch_desc_from_hsdir(blinded_key);
     442             : 
     443           1 :     retval = hs_desc_decode_descriptor(received_desc_str,
     444             :                                        &subcredential, NULL, &received_desc);
     445           1 :     tt_int_op(retval, OP_EQ, HS_DESC_DECODE_OK);
     446           1 :     tt_assert(received_desc);
     447             : 
     448             :     /* Check that the revision counter is the latest */
     449           1 :     tt_u64_op(received_desc->plaintext_data.revision_counter, OP_EQ, 1313);
     450             :   }
     451             : 
     452           1 :  done:
     453           1 :   hs_descriptor_free(published_desc);
     454           1 :   hs_descriptor_free(received_desc);
     455           1 :   tor_free(received_desc_str);
     456           1 :   tor_free(published_desc_str);
     457           1 : }
     458             : 
     459             : static networkstatus_t mock_ns;
     460             : 
     461             : static networkstatus_t *
     462          33 : mock_networkstatus_get_reasonably_live_consensus(time_t now, int flavor)
     463             : {
     464          33 :   (void) now;
     465          33 :   (void) flavor;
     466          33 :   return &mock_ns;
     467             : }
     468             : 
     469             : /** Test that we can store HS descriptors in the client HS cache. */
     470             : static void
     471           1 : test_client_cache(void *arg)
     472             : {
     473           1 :   int retval;
     474           1 :   ed25519_keypair_t signing_kp;
     475           1 :   hs_descriptor_t *published_desc = NULL;
     476           1 :   char *published_desc_str = NULL;
     477           1 :   hs_subcredential_t wanted_subcredential;
     478           1 :   response_handler_args_t *args = NULL;
     479           1 :   dir_connection_t *conn = NULL;
     480             : 
     481           1 :   (void) arg;
     482             : 
     483             :   /* Initialize HSDir cache subsystem */
     484           1 :   init_test();
     485             : 
     486           1 :   MOCK(networkstatus_get_reasonably_live_consensus,
     487             :        mock_networkstatus_get_reasonably_live_consensus);
     488             : 
     489             :   /* Set consensus time */
     490           1 :   parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
     491             :                            &mock_ns.valid_after);
     492           1 :   parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
     493             :                            &mock_ns.fresh_until);
     494           1 :   parse_rfc1123_time("Sat, 26 Oct 1985 16:00:00 UTC",
     495             :                            &mock_ns.valid_until);
     496             : 
     497             :   /* Generate a valid descriptor with normal values. */
     498             :   {
     499           1 :     retval = ed25519_keypair_generate(&signing_kp, 0);
     500           1 :     tt_int_op(retval, OP_EQ, 0);
     501           1 :     published_desc = hs_helper_build_hs_desc_with_ip(&signing_kp);
     502           1 :     tt_assert(published_desc);
     503           1 :     retval = hs_desc_encode_descriptor(published_desc, &signing_kp,
     504             :                                        NULL, &published_desc_str);
     505           1 :     tt_int_op(retval, OP_EQ, 0);
     506           1 :     memcpy(&wanted_subcredential, &published_desc->subcredential,
     507             :            sizeof(hs_subcredential_t));
     508           1 :     tt_assert(!fast_mem_is_zero((char*)wanted_subcredential.subcred,
     509             :                                 DIGEST256_LEN));
     510             :   }
     511             : 
     512             :   /* Test handle_response_fetch_hsdesc_v3() */
     513             :   {
     514           1 :     args = tor_malloc_zero(sizeof(response_handler_args_t));
     515           1 :     args->status_code = 200;
     516           1 :     args->reason = NULL;
     517           1 :     args->body = published_desc_str;
     518           1 :     args->body_len = strlen(published_desc_str);
     519             : 
     520           1 :     conn = tor_malloc_zero(sizeof(dir_connection_t));
     521           1 :     conn->hs_ident = tor_malloc_zero(sizeof(hs_ident_dir_conn_t));
     522           1 :     ed25519_pubkey_copy(&conn->hs_ident->identity_pk, &signing_kp.pubkey);
     523             :   }
     524             : 
     525             :   /* store the descriptor! */
     526           1 :   retval = handle_response_fetch_hsdesc_v3(conn, args);
     527           1 :   tt_int_op(retval, == , 0);
     528             : 
     529             :   /* Progress time a bit and attempt to clean cache: our desc should not be
     530             :    * cleaned since we still in the same TP. */
     531             :   {
     532           1 :     parse_rfc1123_time("Sat, 27 Oct 1985 02:00:00 UTC",
     533             :                        &mock_ns.valid_after);
     534           1 :     parse_rfc1123_time("Sat, 27 Oct 1985 03:00:00 UTC",
     535             :                        &mock_ns.fresh_until);
     536           1 :     parse_rfc1123_time("Sat, 27 Oct 1985 05:00:00 UTC",
     537             :                        &mock_ns.valid_until);
     538             : 
     539             :     /* fetch the descriptor and make sure it's there */
     540           1 :     const hs_descriptor_t *cached_desc = NULL;
     541           1 :     cached_desc = hs_cache_lookup_as_client(&signing_kp.pubkey);
     542           1 :     tt_assert(cached_desc);
     543           1 :     tt_mem_op(cached_desc->subcredential.subcred,
     544             :               OP_EQ, wanted_subcredential.subcred,
     545           1 :               SUBCRED_LEN);
     546             :   }
     547             : 
     548             :   /* Progress time to next TP and check that desc was cleaned */
     549             :   {
     550           1 :     parse_rfc1123_time("Sat, 27 Oct 1985 12:00:00 UTC",
     551             :                        &mock_ns.valid_after);
     552           1 :     parse_rfc1123_time("Sat, 27 Oct 1985 13:00:00 UTC",
     553             :                        &mock_ns.fresh_until);
     554           1 :     parse_rfc1123_time("Sat, 27 Oct 1985 15:00:00 UTC",
     555             :                        &mock_ns.valid_until);
     556             : 
     557           1 :     const hs_descriptor_t *cached_desc = NULL;
     558           1 :     cached_desc = hs_cache_lookup_as_client(&signing_kp.pubkey);
     559           1 :     tt_assert(!cached_desc);
     560             :   }
     561             : 
     562           1 :  done:
     563           1 :   tor_free(args);
     564           1 :   hs_descriptor_free(published_desc);
     565           1 :   tor_free(published_desc_str);
     566           1 :   if (conn) {
     567           1 :     tor_free(conn->hs_ident);
     568           1 :     tor_free(conn);
     569             :   }
     570           1 : }
     571             : 
     572             : /** Test that we can store HS descriptors in the client HS cache. */
     573             : static void
     574           1 : test_client_cache_decrypt(void *arg)
     575             : {
     576           1 :   int ret;
     577           1 :   char *desc_encoded = NULL;
     578           1 :   uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN];
     579           1 :   curve25519_keypair_t client_kp;
     580           1 :   ed25519_keypair_t service_kp;
     581           1 :   hs_descriptor_t *desc = NULL;
     582           1 :   const hs_descriptor_t *search_desc;
     583           1 :   const char *search_desc_encoded;
     584             : 
     585           1 :   (void) arg;
     586             : 
     587             :   /* Initialize HSDir cache subsystem */
     588           1 :   hs_init();
     589             : 
     590           1 :   MOCK(networkstatus_get_reasonably_live_consensus,
     591             :        mock_networkstatus_get_reasonably_live_consensus);
     592             : 
     593             :   /* Set consensus time */
     594           1 :   parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
     595             :                      &mock_ns.valid_after);
     596           1 :   parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
     597             :                      &mock_ns.fresh_until);
     598           1 :   parse_rfc1123_time("Sat, 26 Oct 1985 16:00:00 UTC",
     599             :                      &mock_ns.valid_until);
     600             : 
     601             :   /* Generate a valid descriptor with normal values. */
     602             :   {
     603           1 :     ret = ed25519_keypair_generate(&service_kp, 0);
     604           1 :     tt_int_op(ret, OP_EQ, 0);
     605           1 :     ret = curve25519_keypair_generate(&client_kp, 0);
     606           1 :     tt_int_op(ret, OP_EQ, 0);
     607           1 :     crypto_rand((char *) descriptor_cookie, sizeof(descriptor_cookie));
     608             : 
     609           1 :     desc = hs_helper_build_hs_desc_with_client_auth(descriptor_cookie,
     610             :                                                     &client_kp.pubkey,
     611             :                                                     &service_kp);
     612           1 :     tt_assert(desc);
     613           1 :     ret = hs_desc_encode_descriptor(desc, &service_kp, descriptor_cookie,
     614             :                                     &desc_encoded);
     615           1 :     tt_int_op(ret, OP_EQ, 0);
     616             :   }
     617             : 
     618             :   /* Put it in the cache. Should not be decrypted since the client
     619             :    * authorization creds were not added to the global map. */
     620           1 :   ret = hs_cache_store_as_client(desc_encoded, &service_kp.pubkey);
     621           1 :   tt_int_op(ret, OP_EQ, HS_DESC_DECODE_NEED_CLIENT_AUTH);
     622             : 
     623             :   /* We should not be able to decrypt anything. */
     624           1 :   ret = hs_cache_client_new_auth_parse(&service_kp.pubkey);
     625           1 :   tt_int_op(ret, OP_EQ, false);
     626             : 
     627             :   /* Add client auth to global map. */
     628           1 :   hs_helper_add_client_auth(&service_kp.pubkey, &client_kp.seckey);
     629             : 
     630             :   /* We should not be able to decrypt anything. */
     631           1 :   ret = hs_cache_client_new_auth_parse(&service_kp.pubkey);
     632           1 :   tt_int_op(ret, OP_EQ, true);
     633             : 
     634             :   /* Lookup the cache to make sure it is usable and there. */
     635           1 :   search_desc = hs_cache_lookup_as_client(&service_kp.pubkey);
     636           1 :   tt_assert(search_desc);
     637           1 :   search_desc_encoded = hs_cache_lookup_encoded_as_client(&service_kp.pubkey);
     638           1 :   tt_mem_op(search_desc_encoded, OP_EQ, desc_encoded, strlen(desc_encoded));
     639             : 
     640           1 :  done:
     641           1 :   hs_descriptor_free(desc);
     642           1 :   tor_free(desc_encoded);
     643             : 
     644           1 :   hs_free_all();
     645             : 
     646           1 :   UNMOCK(networkstatus_get_reasonably_live_consensus);
     647           1 : }
     648             : 
     649             : static void
     650           1 : test_client_cache_remove(void *arg)
     651             : {
     652           1 :   int ret;
     653           1 :   ed25519_keypair_t service_kp;
     654           1 :   hs_descriptor_t *desc1 = NULL;
     655             : 
     656           1 :   (void) arg;
     657             : 
     658           1 :   hs_init();
     659             : 
     660           1 :   MOCK(networkstatus_get_reasonably_live_consensus,
     661             :        mock_networkstatus_get_reasonably_live_consensus);
     662             : 
     663             :   /* Set consensus time. Lookup will not return the entry if it has expired
     664             :    * and it is checked against the consensus valid_after time. */
     665           1 :   parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
     666             :                      &mock_ns.valid_after);
     667           1 :   parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
     668             :                      &mock_ns.fresh_until);
     669           1 :   parse_rfc1123_time("Sat, 26 Oct 1985 16:00:00 UTC",
     670             :                      &mock_ns.valid_until);
     671             : 
     672             :   /* Generate service keypair */
     673           1 :   tt_int_op(0, OP_EQ, ed25519_keypair_generate(&service_kp, 0));
     674             : 
     675             :   /* Build a descriptor and cache it. */
     676             :   {
     677           1 :     char *encoded;
     678           1 :     desc1 = hs_helper_build_hs_desc_with_ip(&service_kp);
     679           1 :     tt_assert(desc1);
     680           1 :     ret = hs_desc_encode_descriptor(desc1, &service_kp, NULL, &encoded);
     681           1 :     tt_int_op(ret, OP_EQ, 0);
     682           1 :     tt_assert(encoded);
     683             : 
     684             :     /* Store it */
     685           1 :     ret = hs_cache_store_as_client(encoded, &service_kp.pubkey);
     686           1 :     tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
     687           1 :     tor_free(encoded);
     688           1 :     tt_assert(hs_cache_lookup_as_client(&service_kp.pubkey));
     689             :   }
     690             : 
     691             :   /* Remove the cached entry. */
     692           1 :   hs_cache_remove_as_client(&service_kp.pubkey);
     693           1 :   tt_assert(!hs_cache_lookup_as_client(&service_kp.pubkey));
     694             : 
     695           1 :  done:
     696           1 :   hs_descriptor_free(desc1);
     697           1 :   hs_free_all();
     698             : 
     699           1 :   UNMOCK(networkstatus_get_reasonably_live_consensus);
     700           1 : }
     701             : 
     702             : struct testcase_t hs_cache[] = {
     703             :   /* Encoding tests. */
     704             :   { "directory", test_directory, TT_FORK,
     705             :     NULL, NULL },
     706             :   { "clean_as_dir", test_clean_as_dir, TT_FORK,
     707             :     NULL, NULL },
     708             :   { "hsdir_revision_counter_check", test_hsdir_revision_counter_check, TT_FORK,
     709             :     NULL, NULL },
     710             :   { "upload_and_download_hs_desc", test_upload_and_download_hs_desc, TT_FORK,
     711             :     NULL, NULL },
     712             :   { "client_cache", test_client_cache, TT_FORK,
     713             :     NULL, NULL },
     714             :   { "client_cache_decrypt", test_client_cache_decrypt, TT_FORK,
     715             :     NULL, NULL },
     716             :   { "client_cache_remove", test_client_cache_remove, TT_FORK,
     717             :     NULL, NULL },
     718             : 
     719             :   END_OF_TESTCASES
     720             : };

Generated by: LCOV version 1.14