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

          Line data    Source code
       1             : /* Copyright (c) 2017-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : /**
       5             :  * \file test_hs_cell.c
       6             :  * \brief Test hidden service cell functionality.
       7             :  */
       8             : 
       9             : #define CIRCUITLIST_PRIVATE
      10             : #define NETWORKSTATUS_PRIVATE
      11             : #define HS_DOS_PRIVATE
      12             : #define HS_INTROPOINT_PRIVATE
      13             : 
      14             : #include "test/test.h"
      15             : #include "test/test_helpers.h"
      16             : #include "test/log_test_helpers.h"
      17             : 
      18             : #include "app/config/config.h"
      19             : 
      20             : #include "core/or/circuitlist.h"
      21             : #include "core/or/circuituse.h"
      22             : #include "core/or/or_circuit_st.h"
      23             : 
      24             : #include "feature/hs/hs_dos.h"
      25             : #include "feature/hs/hs_intropoint.h"
      26             : #include "feature/nodelist/networkstatus.h"
      27             : 
      28             : static void
      29           1 : setup_mock_consensus(void)
      30             : {
      31           1 :   current_ns_consensus = tor_malloc_zero(sizeof(networkstatus_t));
      32           1 :   current_ns_consensus->net_params = smartlist_new();
      33           1 :   smartlist_add(current_ns_consensus->net_params,
      34             :                 (void *) "HiddenServiceEnableIntroDoSDefense=1");
      35           1 :   hs_dos_consensus_has_changed(current_ns_consensus);
      36           1 : }
      37             : 
      38             : static void
      39           1 : free_mock_consensus(void)
      40             : {
      41           1 :   smartlist_free(current_ns_consensus->net_params);
      42           1 :   tor_free(current_ns_consensus);
      43           1 : }
      44             : 
      45             : static void
      46           1 : test_can_send_intro2(void *arg)
      47             : {
      48           1 :   uint32_t now = (uint32_t) approx_time();
      49           1 :   or_circuit_t *or_circ = NULL;
      50             : 
      51           1 :   (void) arg;
      52             : 
      53           1 :   hs_init();
      54           1 :   hs_dos_init();
      55             : 
      56           1 :   get_options_mutable()->ORPort_set = 1;
      57           1 :   setup_mock_consensus();
      58             : 
      59           1 :   or_circ =  or_circuit_new(1, NULL);
      60             : 
      61             :   /* Make that circuit a service intro point. */
      62           1 :   circuit_change_purpose(TO_CIRCUIT(or_circ), CIRCUIT_PURPOSE_INTRO_POINT);
      63           1 :   hs_dos_setup_default_intro2_defenses(or_circ);
      64           1 :   or_circ->introduce2_dos_defense_enabled = 1;
      65             : 
      66             :   /* Brand new circuit, we should be able to send INTRODUCE2 cells. */
      67           1 :   tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ));
      68             : 
      69             :   /* Simulate that 10 cells have arrived in 1 second. There should be no
      70             :    * refill since the bucket is already at maximum on the first cell. */
      71           1 :   update_approx_time(++now);
      72          11 :   for (int i = 0; i < 10; i++) {
      73          10 :     tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ));
      74             :   }
      75           1 :   tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ,
      76             :              get_intro2_burst_consensus_param(NULL) - 10);
      77             : 
      78             :   /* Fully refill the bucket minus 1 cell. */
      79           1 :   update_approx_time(++now);
      80           1 :   tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ));
      81           1 :   tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ,
      82             :              get_intro2_burst_consensus_param(NULL) - 1);
      83             : 
      84             :   /* Receive an INTRODUCE2 at each second. We should have the bucket full
      85             :    * since at every second it gets refilled. */
      86          11 :   for (int i = 0; i < 10; i++) {
      87          10 :     update_approx_time(++now);
      88          10 :     tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ));
      89             :   }
      90             :   /* Last check if we can send the cell decrements the bucket so minus 1. */
      91           1 :   tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ,
      92             :              get_intro2_burst_consensus_param(NULL) - 1);
      93             : 
      94             :   /* Manually reset bucket for next test. */
      95           1 :   token_bucket_ctr_reset(&or_circ->introduce2_bucket, now);
      96           1 :   tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ,
      97             :              get_intro2_burst_consensus_param(NULL));
      98             : 
      99             :   /* Do a full burst in the current second which should empty the bucket and
     100             :    * we shouldn't be allowed to send one more cell after that. We go minus 1
     101             :    * cell else the very last check if we can send the INTRO2 cell returns
     102             :    * false because the bucket goes down to 0. */
     103         200 :   for (uint32_t i = 0; i < get_intro2_burst_consensus_param(NULL) - 1; i++) {
     104         199 :     tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ));
     105             :   }
     106           1 :   tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, 1);
     107             :   /* Get the last remaining cell, we shouldn't be allowed to send it. */
     108           1 :   tt_int_op(false, OP_EQ, hs_dos_can_send_intro2(or_circ));
     109           1 :   tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, 0);
     110             : 
     111             :   /* Make sure the next 100 cells aren't allowed and bucket stays at 0. */
     112         101 :   for (int i = 0; i < 100; i++) {
     113         100 :     tt_int_op(false, OP_EQ, hs_dos_can_send_intro2(or_circ));
     114         100 :     tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, 0);
     115             :   }
     116             : 
     117             :   /* One second has passed, we should have the rate minus 1 cell added. */
     118           1 :   update_approx_time(++now);
     119           1 :   tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ));
     120           1 :   tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ,
     121             :              get_intro2_rate_consensus_param(NULL) - 1);
     122             : 
     123           1 :  done:
     124           1 :   circuit_free_(TO_CIRCUIT(or_circ));
     125             : 
     126           1 :   hs_free_all();
     127           1 :   free_mock_consensus();
     128           1 : }
     129             : 
     130             : static void
     131           1 : test_validate_dos_extension_params(void *arg)
     132             : {
     133           1 :   bool ret;
     134             : 
     135           1 :   (void) arg;
     136             : 
     137             :   /* Validate the default values. */
     138           1 :   ret = cell_dos_extension_parameters_are_valid(
     139           1 :                                       get_intro2_rate_consensus_param(NULL),
     140           1 :                                       get_intro2_burst_consensus_param(NULL));
     141           1 :   tt_assert(ret);
     142             : 
     143             :   /* Valid custom rate/burst. */
     144           1 :   ret = cell_dos_extension_parameters_are_valid(17, 42);
     145           1 :   tt_assert(ret);
     146           1 :   ret = cell_dos_extension_parameters_are_valid(INT32_MAX, INT32_MAX);
     147           1 :   tt_assert(ret);
     148             : 
     149             :   /* Invalid rate. */
     150           1 :   ret = cell_dos_extension_parameters_are_valid(UINT64_MAX, 42);
     151           1 :   tt_assert(!ret);
     152             : 
     153             :   /* Invalid burst. */
     154           1 :   ret = cell_dos_extension_parameters_are_valid(42, UINT64_MAX);
     155           1 :   tt_assert(!ret);
     156             : 
     157             :   /* Value of 0 is valid (but should disable defenses) */
     158           1 :   ret = cell_dos_extension_parameters_are_valid(0, 0);
     159           1 :   tt_assert(ret);
     160             : 
     161             :   /* Can't have burst smaller than rate. */
     162           1 :   ret = cell_dos_extension_parameters_are_valid(42, 40);
     163           1 :   tt_assert(!ret);
     164             : 
     165           1 :  done:
     166           1 :   return;
     167             : }
     168             : 
     169             : struct testcase_t hs_dos_tests[] = {
     170             :   { "can_send_intro2", test_can_send_intro2, TT_FORK,
     171             :     NULL, NULL },
     172             :   { "validate_dos_extension_params", test_validate_dos_extension_params,
     173             :     TT_FORK, NULL, NULL },
     174             : 
     175             :   END_OF_TESTCASES
     176             : };

Generated by: LCOV version 1.14