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

          Line data    Source code
       1             : /* Copyright (c) 2018-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : #define DOS_PRIVATE
       5             : #define CHANNEL_OBJECT_PRIVATE
       6             : #define CIRCUITLIST_PRIVATE
       7             : 
       8             : #include "core/or/or.h"
       9             : #include "core/or/dos.h"
      10             : #include "core/or/circuitlist.h"
      11             : #include "lib/crypt_ops/crypto_rand.h"
      12             : #include "feature/stats/geoip_stats.h"
      13             : #include "core/or/channel.h"
      14             : #include "feature/nodelist/microdesc.h"
      15             : #include "feature/nodelist/networkstatus.h"
      16             : #include "feature/nodelist/nodelist.h"
      17             : #include "feature/nodelist/routerlist.h"
      18             : 
      19             : #include "feature/nodelist/networkstatus_st.h"
      20             : #include "core/or/or_connection_st.h"
      21             : #include "feature/nodelist/routerstatus_st.h"
      22             : 
      23             : #include "test/test.h"
      24             : #include "test/log_test_helpers.h"
      25             : 
      26             : static networkstatus_t *dummy_ns = NULL;
      27             : static networkstatus_t *
      28          12 : mock_networkstatus_get_latest_consensus(void)
      29             : {
      30          12 :   return dummy_ns;
      31             : }
      32             : 
      33             : static networkstatus_t *
      34           1 : mock_networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f)
      35             : {
      36           1 :   tor_assert(f == FLAV_MICRODESC);
      37           1 :   return dummy_ns;
      38             : }
      39             : 
      40             : /* Number of address a single node_t can have. Default to the production
      41             :  * value. This is to control the size of the bloom filter. */
      42             : static int addr_per_node = 2;
      43             : static int
      44           2 : mock_get_estimated_address_per_node(void)
      45             : {
      46           2 :   return addr_per_node;
      47             : }
      48             : 
      49             : static unsigned int
      50           9 : mock_enable_dos_protection(const networkstatus_t *ns)
      51             : {
      52           9 :   (void) ns;
      53           9 :   return 1;
      54             : }
      55             : 
      56             : /** Test that the connection tracker of the DoS subsystem will block clients
      57             :  *  who try to establish too many connections */
      58             : static void
      59           1 : test_dos_conn_creation(void *arg)
      60             : {
      61           1 :   (void) arg;
      62             : 
      63           1 :   MOCK(get_param_cc_enabled, mock_enable_dos_protection);
      64           1 :   MOCK(get_param_conn_enabled, mock_enable_dos_protection);
      65             : 
      66             :   /* Initialize test data */
      67           1 :   or_connection_t or_conn;
      68           1 :   time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
      69           1 :   tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&TO_CONN(&or_conn)->addr,
      70             :                                           "18.0.0.1"));
      71           1 :   tor_addr_t *addr = &TO_CONN(&or_conn)->addr;
      72             : 
      73             :   /* Get DoS subsystem limits */
      74           1 :   dos_init();
      75           1 :   uint32_t max_concurrent_conns = get_param_conn_max_concurrent_count(NULL);
      76             : 
      77             :   /* Introduce new client */
      78           1 :   geoip_note_client_seen(GEOIP_CLIENT_CONNECT, addr, NULL, now);
      79             :   { /* Register many conns from this client but not enough to get it blocked */
      80           1 :     unsigned int i;
      81         102 :     for (i = 0; i < max_concurrent_conns; i++) {
      82             :       /* Don't trigger the connect() rate limitation so advance the clock 1
      83             :        * second for each connection. */
      84         100 :       update_approx_time(++now);
      85         100 :       dos_new_client_conn(&or_conn, NULL);
      86             :     }
      87             :   }
      88             : 
      89             :   /* Check that new conns are still permitted */
      90           1 :   tt_int_op(DOS_CONN_DEFENSE_NONE, OP_EQ,
      91             :             dos_conn_addr_get_defense_type(addr));
      92             : 
      93             :   /* Register another conn and check that new conns are not allowed anymore */
      94           1 :   dos_new_client_conn(&or_conn, NULL);
      95           1 :   tt_int_op(DOS_CONN_DEFENSE_CLOSE, OP_EQ,
      96             :             dos_conn_addr_get_defense_type(addr));
      97             : 
      98             :   /* Close a client conn and see that a new conn will be permitted again */
      99           1 :   dos_close_client_conn(&or_conn);
     100           1 :   tt_int_op(DOS_CONN_DEFENSE_NONE, OP_EQ,
     101             :             dos_conn_addr_get_defense_type(addr));
     102             : 
     103             :   /* Register another conn and see that defense measures get reactivated */
     104           1 :   dos_new_client_conn(&or_conn, NULL);
     105           1 :   tt_int_op(DOS_CONN_DEFENSE_CLOSE, OP_EQ,
     106             :             dos_conn_addr_get_defense_type(addr));
     107             : 
     108           1 :  done:
     109           1 :   dos_free_all();
     110           1 : }
     111             : 
     112             : /** Helper mock: Place a fake IP addr for this channel in <b>addr_out</b> */
     113             : static int
     114         821 : mock_channel_get_addr_if_possible(const channel_t *chan, tor_addr_t *addr_out)
     115             : {
     116         821 :   (void)chan;
     117         821 :   tt_int_op(AF_INET,OP_EQ, tor_addr_parse(addr_out, "18.0.0.1"));
     118             :   return 1;
     119             : 
     120           0 :  done:
     121           0 :   return 0;
     122             : }
     123             : 
     124             : /** Test that the circuit tracker of the DoS subsystem will block clients who
     125             :  *  try to establish too many circuits. */
     126             : static void
     127           1 : test_dos_circuit_creation(void *arg)
     128             : {
     129           1 :   (void) arg;
     130           1 :   unsigned int i;
     131             : 
     132           1 :   MOCK(get_param_cc_enabled, mock_enable_dos_protection);
     133           1 :   MOCK(get_param_conn_enabled, mock_enable_dos_protection);
     134           1 :   MOCK(channel_get_addr_if_possible,
     135             :        mock_channel_get_addr_if_possible);
     136             : 
     137             :   /* Initialize channels/conns/circs that will be used */
     138           1 :   channel_t *chan = tor_malloc_zero(sizeof(channel_t));
     139           1 :   channel_init(chan);
     140           1 :   chan->is_client = 1;
     141             : 
     142             :   /* Initialize test data */
     143           1 :   or_connection_t or_conn;
     144           1 :   time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
     145           1 :   tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&TO_CONN(&or_conn)->addr,
     146             :                                           "18.0.0.1"));
     147           1 :   tor_addr_t *addr = &TO_CONN(&or_conn)->addr;
     148             : 
     149             :   /* Get DoS subsystem limits */
     150           1 :   dos_init();
     151           1 :   uint32_t max_circuit_count = get_param_cc_circuit_burst(NULL);
     152           1 :   uint32_t min_conc_conns_for_cc =
     153           1 :     get_param_cc_min_concurrent_connection(NULL);
     154             : 
     155             :   /* Introduce new client and establish enough connections to activate the
     156             :    * circuit counting subsystem */
     157           1 :   geoip_note_client_seen(GEOIP_CLIENT_CONNECT, addr, NULL, now);
     158           5 :   for (i = 0; i < min_conc_conns_for_cc ; i++) {
     159           3 :     dos_new_client_conn(&or_conn, NULL);
     160             :   }
     161             : 
     162             :   /* Register new circuits for this client and conn, but not enough to get
     163             :    * detected as dos */
     164          90 :   for (i=0; i < max_circuit_count-1; i++) {
     165          89 :     dos_cc_new_create_cell(chan);
     166             :   }
     167             :   /* see that we didn't get detected for dosing */
     168           1 :   tt_int_op(DOS_CC_DEFENSE_NONE, OP_EQ, dos_cc_get_defense_type(chan));
     169             : 
     170             :   /* Register another CREATE cell that will push us over the limit. Check that
     171             :    * the cell gets refused. */
     172           1 :   dos_cc_new_create_cell(chan);
     173           1 :   tt_int_op(DOS_CC_DEFENSE_REFUSE_CELL, OP_EQ, dos_cc_get_defense_type(chan));
     174             : 
     175             :   /* TODO: Wait a few seconds before sending the cell, and check that the
     176             :      buckets got refilled properly. */
     177             :   /* TODO: Actually send a Tor cell (instead of calling the DoS function) and
     178             :    * check that it will get refused */
     179             : 
     180           1 :  done:
     181           1 :   tor_free(chan);
     182           1 :   dos_free_all();
     183           1 : }
     184             : 
     185             : /** Test that the DoS subsystem properly refills the circuit token buckets. */
     186             : static void
     187           1 : test_dos_bucket_refill(void *arg)
     188             : {
     189           1 :   (void) arg;
     190           1 :   int i;
     191             :   /* For this test, this variable is set to the current circ count of the token
     192             :    * bucket. */
     193           1 :   uint32_t current_circ_count;
     194             : 
     195           1 :   MOCK(get_param_cc_enabled, mock_enable_dos_protection);
     196           1 :   MOCK(get_param_conn_enabled, mock_enable_dos_protection);
     197           1 :   MOCK(channel_get_addr_if_possible,
     198             :        mock_channel_get_addr_if_possible);
     199             : 
     200           1 :   time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
     201           1 :   update_approx_time(now);
     202             : 
     203             :   /* Initialize channels/conns/circs that will be used */
     204           1 :   channel_t *chan = tor_malloc_zero(sizeof(channel_t));
     205           1 :   channel_init(chan);
     206           1 :   chan->is_client = 1;
     207           1 :   or_connection_t or_conn;
     208           1 :   tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&TO_CONN(&or_conn)->addr,
     209             :                                           "18.0.0.1"));
     210           1 :   tor_addr_t *addr = &TO_CONN(&or_conn)->addr;
     211             : 
     212             :   /* Initialize DoS subsystem and get relevant limits */
     213           1 :   dos_init();
     214           1 :   uint32_t max_circuit_count = get_param_cc_circuit_burst(NULL);
     215           1 :   uint64_t circ_rate = get_circuit_rate_per_second();
     216             :   /* Check that the circuit rate is a positive number and smaller than the max
     217             :    * circuit count */
     218           1 :   tt_u64_op(circ_rate, OP_GT, 1);
     219           1 :   tt_u64_op(circ_rate, OP_LT, max_circuit_count);
     220             : 
     221             :   /* Register this client */
     222           1 :   geoip_note_client_seen(GEOIP_CLIENT_CONNECT, addr, NULL, now);
     223           1 :   dos_new_client_conn(&or_conn, NULL);
     224             : 
     225             :   /* Fetch this client from the geoip cache and get its DoS structs */
     226           1 :   clientmap_entry_t *entry = geoip_lookup_client(addr, NULL,
     227             :                                                  GEOIP_CLIENT_CONNECT);
     228           1 :   tt_assert(entry);
     229           1 :   dos_client_stats_t* dos_stats = &entry->dos_stats;
     230             :   /* Check that the circuit bucket is still uninitialized */
     231           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, 0);
     232             : 
     233             :   /* Send a create cell: then check that the circ token bucket got initialized
     234             :    * and one circ was subtracted. */
     235           1 :   dos_cc_new_create_cell(chan);
     236           1 :   current_circ_count = max_circuit_count - 1;
     237           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     238             : 
     239             :   /* Now send 29 more CREATEs and ensure that the bucket is missing 30
     240             :    * tokens */
     241          30 :   for (i=0; i < 29; i++) {
     242          29 :    dos_cc_new_create_cell(chan);
     243          29 :    current_circ_count--;
     244             :   }
     245           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     246             : 
     247             :   /* OK! Progress time forward one sec, refill the bucket and check that the
     248             :    * refill happened correctly. */
     249           1 :   now += 1;
     250           1 :   update_approx_time(now);
     251           1 :   cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
     252             :   /* check refill */
     253           1 :   current_circ_count += circ_rate;
     254           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     255             : 
     256             :   /* Now send as many CREATE cells as needed to deplete our token bucket
     257             :    * completely */
     258          64 :   for (; current_circ_count != 0; current_circ_count--) {
     259          63 :    dos_cc_new_create_cell(chan);
     260             :   }
     261           1 :   tt_uint_op(current_circ_count, OP_EQ, 0);
     262           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     263             : 
     264             :   /* Now progress time a week forward, and check that the token bucket does not
     265             :    * have more than max_circs allowance, even tho we let it simmer for so
     266             :    * long. */
     267           1 :   now += 604800; /* a week */
     268           1 :   update_approx_time(now);
     269           1 :   cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
     270           1 :   current_circ_count += max_circuit_count;
     271           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     272             : 
     273             :   /* Now send as many CREATE cells as needed to deplete our token bucket
     274             :    * completely */
     275          91 :   for (; current_circ_count != 0; current_circ_count--) {
     276          90 :     dos_cc_new_create_cell(chan);
     277             :   }
     278           1 :   tt_uint_op(current_circ_count, OP_EQ, 0);
     279           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     280             : 
     281             :   /* Now use a very large time, and check that the token bucket does not have
     282             :    * more than max_circs allowance, even tho we let it simmer for so long. */
     283           1 :   now = INT32_MAX; /* 2038? */
     284           1 :   update_approx_time(now);
     285           1 :   cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
     286           1 :   current_circ_count += max_circuit_count;
     287           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     288             : 
     289             :   /* Now send as many CREATE cells as needed to deplete our token bucket
     290             :    * completely */
     291          91 :   for (; current_circ_count != 0; current_circ_count--) {
     292          90 :     dos_cc_new_create_cell(chan);
     293             :   }
     294           1 :   tt_uint_op(current_circ_count, OP_EQ, 0);
     295           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     296             : 
     297             :   /* Now use a very small time, and check that the token bucket has exactly
     298             :    * the max_circs allowance, because backward clock jumps are rare. */
     299           1 :   now = INT32_MIN; /* 19?? */
     300           1 :   update_approx_time(now);
     301           1 :   cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
     302           1 :   current_circ_count += max_circuit_count;
     303           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     304             : 
     305             :   /* Now send as many CREATE cells as needed to deplete our token bucket
     306             :    * completely */
     307          91 :   for (; current_circ_count != 0; current_circ_count--) {
     308          90 :     dos_cc_new_create_cell(chan);
     309             :   }
     310           1 :   tt_uint_op(current_circ_count, OP_EQ, 0);
     311           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     312             : 
     313             :   /* Progress time forward one sec again, refill the bucket and check that the
     314             :    * refill happened correctly. */
     315           1 :   now += 1;
     316           1 :   update_approx_time(now);
     317           1 :   cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
     318             :   /* check refill */
     319           1 :   current_circ_count += circ_rate;
     320           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     321             : 
     322             :   /* Now send as many CREATE cells as needed to deplete our token bucket
     323             :    * completely */
     324           4 :   for (; current_circ_count != 0; current_circ_count--) {
     325           3 :     dos_cc_new_create_cell(chan);
     326             :   }
     327           1 :   tt_uint_op(current_circ_count, OP_EQ, 0);
     328           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     329             : 
     330             :   /* Now use a very large time (again), and check that the token bucket does
     331             :    * not have more than max_circs allowance, even tho we let it simmer for so
     332             :    * long. */
     333           1 :   now = INT32_MAX; /* 2038? */
     334           1 :   update_approx_time(now);
     335           1 :   cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
     336           1 :   current_circ_count += max_circuit_count;
     337           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     338             : 
     339             :   /* Now send as many CREATE cells as needed to deplete our token bucket
     340             :    * completely */
     341          91 :   for (; current_circ_count != 0; current_circ_count--) {
     342          90 :     dos_cc_new_create_cell(chan);
     343             :   }
     344           1 :   tt_uint_op(current_circ_count, OP_EQ, 0);
     345           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     346             : 
     347             :   /* This code resets the time to zero with 32-bit time_t, which triggers the
     348             :    * code that initialises the bucket. */
     349             : #if SIZEOF_TIME_T == 8
     350             :   /* Now use a very very small time, and check that the token bucket has
     351             :    * exactly the max_circs allowance, because backward clock jumps are rare.
     352             :    */
     353           1 :   now = (time_t)INT64_MIN; /* ???? */
     354           1 :   update_approx_time(now);
     355           1 :   cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
     356           1 :   current_circ_count += max_circuit_count;
     357           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     358             : 
     359             :   /* Now send as many CREATE cells as needed to deplete our token bucket
     360             :    * completely */
     361          91 :   for (; current_circ_count != 0; current_circ_count--) {
     362          90 :     dos_cc_new_create_cell(chan);
     363             :   }
     364           1 :   tt_uint_op(current_circ_count, OP_EQ, 0);
     365           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     366             : 
     367             :   /* Progress time forward one sec again, refill the bucket and check that the
     368             :    * refill happened correctly. */
     369           1 :   now += 1;
     370           1 :   update_approx_time(now);
     371           1 :   cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
     372             :   /* check refill */
     373           1 :   current_circ_count += circ_rate;
     374           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     375             : 
     376             :   /* Now send as many CREATE cells as needed to deplete our token bucket
     377             :    * completely */
     378           4 :   for (; current_circ_count != 0; current_circ_count--) {
     379           3 :     dos_cc_new_create_cell(chan);
     380             :   }
     381           1 :   tt_uint_op(current_circ_count, OP_EQ, 0);
     382           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     383             : 
     384             :   /* Now use a very very small time, and check that the token bucket has
     385             :    * exactly the max_circs allowance, because backward clock jumps are rare.
     386             :    */
     387           1 :   now = (time_t)INT64_MIN; /* ???? */
     388           1 :   update_approx_time(now);
     389           1 :   cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
     390           1 :   current_circ_count += max_circuit_count;
     391           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     392             : 
     393             :   /* Now send as many CREATE cells as needed to deplete our token bucket
     394             :    * completely */
     395          91 :   for (; current_circ_count != 0; current_circ_count--) {
     396          90 :     dos_cc_new_create_cell(chan);
     397             :   }
     398           1 :   tt_uint_op(current_circ_count, OP_EQ, 0);
     399           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     400             : 
     401             :   /* Now use a very very large time, and check that the token bucket does not
     402             :    * have more than max_circs allowance, even tho we let it simmer for so
     403             :    * long. */
     404           1 :   now = (time_t)INT64_MAX; /* ???? */
     405           1 :   update_approx_time(now);
     406           1 :   cc_stats_refill_bucket(&dos_stats->cc_stats, addr);
     407           1 :   current_circ_count += max_circuit_count;
     408           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     409             : 
     410             :   /* Now send as many CREATE cells as needed to deplete our token bucket
     411             :    * completely */
     412          91 :   for (; current_circ_count != 0; current_circ_count--) {
     413          90 :     dos_cc_new_create_cell(chan);
     414             :   }
     415           1 :   tt_uint_op(current_circ_count, OP_EQ, 0);
     416           1 :   tt_uint_op(dos_stats->cc_stats.circuit_bucket, OP_EQ, current_circ_count);
     417             : #endif /* SIZEOF_TIME_T == 8 */
     418             : 
     419           1 :  done:
     420           1 :   tor_free(chan);
     421           1 :   dos_free_all();
     422           1 : }
     423             : 
     424             : /* Test if we avoid counting a known relay. */
     425             : static void
     426           1 : test_known_relay(void *arg)
     427             : {
     428           1 :   clientmap_entry_t *entry = NULL;
     429           1 :   routerstatus_t *rs = NULL; microdesc_t *md = NULL; routerinfo_t *ri = NULL;
     430             : 
     431           1 :   (void) arg;
     432             : 
     433           1 :   MOCK(networkstatus_get_latest_consensus,
     434             :        mock_networkstatus_get_latest_consensus);
     435           1 :   MOCK(networkstatus_get_latest_consensus_by_flavor,
     436             :        mock_networkstatus_get_latest_consensus_by_flavor);
     437           1 :   MOCK(get_estimated_address_per_node,
     438             :        mock_get_estimated_address_per_node);
     439           1 :   MOCK(get_param_cc_enabled, mock_enable_dos_protection);
     440             : 
     441           1 :   dos_init();
     442             : 
     443           1 :   dummy_ns = tor_malloc_zero(sizeof(*dummy_ns));
     444           1 :   dummy_ns->flavor = FLAV_MICRODESC;
     445           1 :   dummy_ns->routerstatus_list = smartlist_new();
     446             : 
     447             :   /* Setup an OR conn so we can pass it to the DoS subsystem. */
     448           1 :   or_connection_t or_conn;
     449           1 :   tor_addr_parse(&TO_CONN(&or_conn)->addr, "42.42.42.42");
     450             : 
     451           1 :   rs = tor_malloc_zero(sizeof(*rs));
     452           1 :   tor_addr_copy(&rs->ipv4_addr, &TO_CONN(&or_conn)->addr);
     453           1 :   crypto_rand(rs->identity_digest, sizeof(rs->identity_digest));
     454           1 :   smartlist_add(dummy_ns->routerstatus_list, rs);
     455             : 
     456             :   /* This will make the nodelist bloom filter very large
     457             :    * (the_nodelist->node_addrs) so we will fail the contain test rarely. */
     458           1 :   addr_per_node = 1024;
     459           1 :   nodelist_set_consensus(dummy_ns);
     460             : 
     461             :   /* We have now a node in our list so we'll make sure we don't count it as a
     462             :    * client connection. */
     463           1 :   geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &TO_CONN(&or_conn)->addr,
     464             :                          NULL, 0);
     465             :   /* Suppose we have 5 connections in rapid succession, the counter should
     466             :    * always be 0 because we should ignore this. */
     467           1 :   dos_new_client_conn(&or_conn, NULL);
     468           1 :   dos_new_client_conn(&or_conn, NULL);
     469           1 :   dos_new_client_conn(&or_conn, NULL);
     470           1 :   dos_new_client_conn(&or_conn, NULL);
     471           1 :   dos_new_client_conn(&or_conn, NULL);
     472           1 :   entry = geoip_lookup_client(&TO_CONN(&or_conn)->addr, NULL,
     473             :                               GEOIP_CLIENT_CONNECT);
     474           1 :   tt_assert(entry);
     475             :   /* We should have a count of 0. */
     476           1 :   tt_uint_op(entry->dos_stats.conn_stats.concurrent_count, OP_EQ, 0);
     477             : 
     478             :   /* To make sure that his is working properly, make a unknown client
     479             :    * connection and see if we do get it. */
     480           1 :   tor_addr_parse(&TO_CONN(&or_conn)->addr, "42.42.42.43");
     481           1 :   geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &TO_CONN(&or_conn)->addr,
     482             :                          NULL, 0);
     483           1 :   dos_new_client_conn(&or_conn, NULL);
     484           1 :   dos_new_client_conn(&or_conn, NULL);
     485           1 :   entry = geoip_lookup_client(&TO_CONN(&or_conn)->addr, NULL,
     486             :                               GEOIP_CLIENT_CONNECT);
     487           1 :   tt_assert(entry);
     488             :   /* We should have a count of 2. */
     489           1 :   tt_uint_op(entry->dos_stats.conn_stats.concurrent_count, OP_EQ, 2);
     490             : 
     491           1 :  done:
     492           1 :   routerstatus_free(rs); routerinfo_free(ri); microdesc_free(md);
     493           1 :   smartlist_clear(dummy_ns->routerstatus_list);
     494           1 :   networkstatus_vote_free(dummy_ns);
     495           1 :   dos_free_all();
     496           1 :   UNMOCK(networkstatus_get_latest_consensus);
     497           1 :   UNMOCK(networkstatus_get_latest_consensus_by_flavor);
     498           1 :   UNMOCK(get_estimated_address_per_node);
     499           1 :   UNMOCK(get_param_cc_enabled);
     500           1 : }
     501             : 
     502             : /** Test that the connection tracker of the DoS subsystem will block clients
     503             :  *  who try to establish too many connections */
     504             : static void
     505           1 : test_dos_conn_rate(void *arg)
     506             : {
     507           1 :   (void) arg;
     508             : 
     509           1 :   MOCK(get_param_cc_enabled, mock_enable_dos_protection);
     510           1 :   MOCK(get_param_conn_enabled, mock_enable_dos_protection);
     511             : 
     512             :   /* Initialize test data */
     513           1 :   or_connection_t or_conn;
     514           1 :   time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
     515           1 :   tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&TO_CONN(&or_conn)->addr,
     516             :                                           "18.0.0.1"));
     517           1 :   tor_addr_t *addr = &TO_CONN(&or_conn)->addr;
     518           1 :   update_approx_time(now);
     519             : 
     520             :   /* Get DoS subsystem limits */
     521           1 :   dos_init();
     522           1 :   uint32_t burst_conn = get_param_conn_connect_burst(NULL);
     523             : 
     524             :   /* Introduce new client */
     525           1 :   geoip_note_client_seen(GEOIP_CLIENT_CONNECT, addr, NULL, now);
     526             :   { /* Register many conns from this client but not enough to get it blocked */
     527           1 :     unsigned int i;
     528          41 :     for (i = 0; i < burst_conn - 1; i++) {
     529          39 :       dos_new_client_conn(&or_conn, NULL);
     530             :     }
     531             :   }
     532             : 
     533             :   /* Check that new conns are still permitted */
     534           1 :   tt_int_op(DOS_CONN_DEFENSE_NONE, OP_EQ,
     535             :             dos_conn_addr_get_defense_type(addr));
     536             : 
     537             :   /* Register another conn and check that new conns are not allowed anymore.
     538             :    * We should have reached our burst. */
     539           1 :   dos_new_client_conn(&or_conn, NULL);
     540           1 :   tt_int_op(DOS_CONN_DEFENSE_CLOSE, OP_EQ,
     541             :             dos_conn_addr_get_defense_type(addr));
     542             : 
     543             :   /* Advance the time 12 hours. It should still be blocked. */
     544           1 :   update_approx_time(now + (12 * 60 * 60));
     545           1 :   tt_int_op(DOS_CONN_DEFENSE_CLOSE, OP_EQ,
     546             :             dos_conn_addr_get_defense_type(addr));
     547             : 
     548             :   /* Advance the time 24 hours plus 13 hours. It should be unblocked.
     549             :    * Remember, we had a random value between 24 hours and rand(24/2) thus
     550             :    * adding 13 hours is safe. */
     551           1 :   update_approx_time(now + (37 * 60 * 60));
     552           1 :   tt_int_op(DOS_CONN_DEFENSE_NONE, OP_EQ,
     553             :             dos_conn_addr_get_defense_type(addr));
     554             : 
     555           1 :  done:
     556           1 :   dos_free_all();
     557           1 : }
     558             : 
     559             : struct testcase_t dos_tests[] = {
     560             :   { "conn_creation", test_dos_conn_creation, TT_FORK, NULL, NULL },
     561             :   { "circuit_creation", test_dos_circuit_creation, TT_FORK, NULL, NULL },
     562             :   { "bucket_refill", test_dos_bucket_refill, TT_FORK, NULL, NULL },
     563             :   { "known_relay" , test_known_relay, TT_FORK,
     564             :     NULL, NULL },
     565             :   { "conn_rate", test_dos_conn_rate, TT_FORK, NULL, NULL },
     566             :   END_OF_TESTCASES
     567             : };

Generated by: LCOV version 1.14