LCOV - code coverage report
Current view: top level - test - test_dir_handle_get.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 1579 1582 99.8 %
Date: 2021-11-24 03:28:48 Functions: 68 69 98.6 %

          Line data    Source code
       1             : /* Copyright (c) 2001-2004, Roger Dingledine.
       2             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       3             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       4             : /* See LICENSE for licensing information */
       5             : 
       6             : #define RENDCOMMON_PRIVATE
       7             : #define GEOIP_PRIVATE
       8             : #define CONNECTION_PRIVATE
       9             : #define CONFIG_PRIVATE
      10             : #define RENDCACHE_PRIVATE
      11             : #define DIRCACHE_PRIVATE
      12             : 
      13             : #include "core/or/or.h"
      14             : #include "app/config/config.h"
      15             : #include "core/mainloop/connection.h"
      16             : #include "feature/dircache/consdiffmgr.h"
      17             : #include "feature/dircommon/directory.h"
      18             : #include "feature/dircache/dircache.h"
      19             : #include "test/test.h"
      20             : #include "lib/compress/compress.h"
      21             : #include "feature/relay/relay_config.h"
      22             : #include "feature/relay/router.h"
      23             : #include "feature/nodelist/authcert.h"
      24             : #include "feature/nodelist/dirlist.h"
      25             : #include "feature/nodelist/routerlist.h"
      26             : #include "feature/nodelist/microdesc.h"
      27             : #include "test/test_helpers.h"
      28             : #include "feature/nodelist/nodelist.h"
      29             : #include "feature/client/entrynodes.h"
      30             : #include "feature/dirparse/authcert_parse.h"
      31             : #include "feature/dirparse/sigcommon.h"
      32             : #include "feature/nodelist/networkstatus.h"
      33             : #include "core/proto/proto_http.h"
      34             : #include "lib/geoip/geoip.h"
      35             : #include "feature/stats/geoip_stats.h"
      36             : #include "feature/dircache/dirserv.h"
      37             : #include "feature/dirauth/dirvote.h"
      38             : #include "test/log_test_helpers.h"
      39             : #include "feature/dirauth/voting_schedule.h"
      40             : 
      41             : #include "feature/dircommon/dir_connection_st.h"
      42             : #include "feature/dirclient/dir_server_st.h"
      43             : #include "feature/nodelist/networkstatus_st.h"
      44             : #include "feature/nodelist/routerinfo_st.h"
      45             : #include "feature/nodelist/routerlist_st.h"
      46             : 
      47             : #ifdef _WIN32
      48             : /* For mkdir() */
      49             : #include <direct.h>
      50             : #else
      51             : #include <dirent.h>
      52             : #endif /* defined(_WIN32) */
      53             : 
      54             : #ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
      55             : DISABLE_GCC_WARNING("-Woverlength-strings")
      56             : /* We allow huge string constants in the unit tests, but not in the code
      57             :  * at large. */
      58             : #endif
      59             : #include "vote_descriptors.inc"
      60             : #ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
      61             : ENABLE_GCC_WARNING("-Woverlength-strings")
      62             : #endif
      63             : 
      64             : #define NOT_FOUND "HTTP/1.0 404 Not found\r\n\r\n"
      65             : #define BAD_REQUEST "HTTP/1.0 400 Bad request\r\n\r\n"
      66             : #define SERVER_BUSY "HTTP/1.0 503 Directory busy, try again later\r\n\r\n"
      67             : #define TOO_OLD "HTTP/1.0 404 Consensus is too old\r\n\r\n"
      68             : #define NOT_ENOUGH_CONSENSUS_SIGNATURES "HTTP/1.0 404 " \
      69             :   "Consensus not signed by sufficient number of requested authorities\r\n\r\n"
      70             : 
      71             : #define consdiffmgr_add_consensus consdiffmgr_add_consensus_nulterm
      72             : 
      73             : static int
      74          55 : mock_ignore_signature_token(const char *digest,
      75             :                             ssize_t digest_len,
      76             :                             struct directory_token_t *tok,
      77             :                             crypto_pk_t *pkey,
      78             :                             int flags,
      79             :                             const char *doctype)
      80             : {
      81          55 :   (void)digest;
      82          55 :   (void)digest_len;
      83          55 :   (void)tok;
      84          55 :   (void)pkey;
      85          55 :   (void)flags;
      86          55 :   (void)doctype;
      87          55 :   return 0;
      88             : }
      89             : 
      90             : static dir_connection_t *
      91          56 : new_dir_conn(void)
      92             : {
      93          56 :   dir_connection_t *conn = dir_connection_new(AF_INET);
      94          56 :   tor_addr_from_ipv4h(&conn->base_.addr, 0x7f000001);
      95          56 :   TO_CONN(conn)->address = tor_strdup("127.0.0.1");
      96          56 :   return conn;
      97             : }
      98             : 
      99             : static void
     100           1 : test_dir_handle_get_bad_request(void *data)
     101             : {
     102           1 :   dir_connection_t *conn = NULL;
     103           1 :   char *header = NULL;
     104           1 :   (void) data;
     105             : 
     106           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     107             : 
     108           1 :   conn = new_dir_conn();
     109           1 :   tt_int_op(directory_handle_command_get(conn, "", NULL, 0), OP_EQ, 0);
     110             : 
     111           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     112             :                       NULL, NULL, 1, 0);
     113             : 
     114           1 :   tt_str_op(header, OP_EQ, BAD_REQUEST);
     115             : 
     116           1 :   done:
     117           1 :     UNMOCK(connection_write_to_buf_impl_);
     118           1 :     connection_free_minimal(TO_CONN(conn));
     119           1 :     tor_free(header);
     120           1 : }
     121             : 
     122             : static void
     123           1 : test_dir_handle_get_v1_command_not_found(void *data)
     124             : {
     125           1 :   dir_connection_t *conn = NULL;
     126           1 :   char *header = NULL;
     127           1 :   (void) data;
     128             : 
     129           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     130             : 
     131           1 :   conn = new_dir_conn();
     132             : 
     133             :   // no frontpage configured
     134           1 :   tt_ptr_op(relay_get_dirportfrontpage(), OP_EQ, NULL);
     135             : 
     136             :   /* V1 path */
     137           1 :   tt_int_op(directory_handle_command_get(conn, GET("/tor/"), NULL, 0),
     138             :             OP_EQ, 0);
     139             : 
     140           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     141             :                       NULL, NULL, 1, 0);
     142             : 
     143           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
     144             : 
     145           1 :   done:
     146           1 :     UNMOCK(connection_write_to_buf_impl_);
     147           1 :     connection_free_minimal(TO_CONN(conn));
     148           1 :     tor_free(header);
     149           1 : }
     150             : 
     151             : static const char*
     152           2 : mock_get_dirportfrontpage(void)
     153             : {
     154           2 :   return "HELLO FROM FRONTPAGE";
     155             : }
     156             : 
     157             : static void
     158           1 : test_dir_handle_get_v1_command(void *data)
     159             : {
     160           1 :   dir_connection_t *conn = NULL;
     161           1 :   char *header = NULL;
     162           1 :   char *body = NULL;
     163           1 :   size_t body_used = 0, body_len = 0;
     164           1 :   const char *exp_body = NULL;
     165           1 :   (void) data;
     166             : 
     167           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     168           1 :   MOCK(relay_get_dirportfrontpage, mock_get_dirportfrontpage);
     169             : 
     170           1 :   exp_body = relay_get_dirportfrontpage();
     171           1 :   body_len = strlen(exp_body);
     172             : 
     173           1 :   conn = new_dir_conn();
     174           1 :   tt_int_op(directory_handle_command_get(conn, GET("/tor/"), NULL, 0),
     175             :             OP_EQ, 0);
     176             : 
     177           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     178             :                       &body, &body_used, body_len+1, 0);
     179             : 
     180           1 :   tt_assert(header);
     181           1 :   tt_assert(body);
     182             : 
     183           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
     184           1 :   tt_assert(strstr(header, "Content-Type: text/html\r\n"));
     185           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
     186           1 :   tt_assert(strstr(header, "Content-Length: 20\r\n"));
     187             : 
     188           1 :   tt_int_op(body_used, OP_EQ, strlen(body));
     189           1 :   tt_str_op(body, OP_EQ, exp_body);
     190             : 
     191           1 :   done:
     192           1 :     UNMOCK(connection_write_to_buf_impl_);
     193           1 :     UNMOCK(relay_get_dirportfrontpage);
     194           1 :     connection_free_minimal(TO_CONN(conn));
     195           1 :     tor_free(header);
     196           1 :     tor_free(body);
     197           1 : }
     198             : 
     199             : static void
     200           1 : test_dir_handle_get_not_found(void *data)
     201             : {
     202           1 :   dir_connection_t *conn = NULL;
     203           1 :   char *header = NULL;
     204           1 :   (void) data;
     205             : 
     206           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     207             : 
     208           1 :   conn = new_dir_conn();
     209             : 
     210             :   /* Unrecognized path */
     211           1 :   tt_int_op(directory_handle_command_get(conn, GET("/anything"), NULL, 0),
     212             :             OP_EQ, 0);
     213           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     214             :                       NULL, NULL, 1, 0);
     215             : 
     216           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
     217             : 
     218           1 :   done:
     219           1 :     UNMOCK(connection_write_to_buf_impl_);
     220           1 :     connection_free_minimal(TO_CONN(conn));
     221           1 :     tor_free(header);
     222           1 : }
     223             : 
     224             : static void
     225           1 : test_dir_handle_get_robots_txt(void *data)
     226             : {
     227           1 :   dir_connection_t *conn = NULL;
     228           1 :   char *header = NULL;
     229           1 :   char *body = NULL;
     230           1 :   size_t body_used = 0;
     231           1 :   (void) data;
     232             : 
     233           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     234             : 
     235           1 :   conn = new_dir_conn();
     236             : 
     237           1 :   tt_int_op(directory_handle_command_get(conn, GET("/tor/robots.txt"),
     238             :                                          NULL, 0), OP_EQ, 0);
     239           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     240             :                       &body, &body_used, 29, 0);
     241             : 
     242           1 :   tt_assert(header);
     243           1 :   tt_assert(body);
     244             : 
     245           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
     246           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
     247           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
     248           1 :   tt_assert(strstr(header, "Content-Length: 28\r\n"));
     249             : 
     250           1 :   tt_int_op(body_used, OP_EQ, strlen(body));
     251           1 :   tt_str_op(body, OP_EQ, "User-agent: *\r\nDisallow: /\r\n");
     252             : 
     253           1 :   done:
     254           1 :     UNMOCK(connection_write_to_buf_impl_);
     255           1 :     connection_free_minimal(TO_CONN(conn));
     256           1 :     tor_free(header);
     257           1 :     tor_free(body);
     258           1 : }
     259             : 
     260             : static const routerinfo_t * dhg_tests_router_get_my_routerinfo(void);
     261             : ATTR_UNUSED static int dhg_tests_router_get_my_routerinfo_called = 0;
     262             : 
     263             : static routerinfo_t *mock_routerinfo;
     264             : 
     265             : static const routerinfo_t *
     266          12 : dhg_tests_router_get_my_routerinfo(void)
     267             : {
     268          12 :   if (!mock_routerinfo) {
     269           2 :     mock_routerinfo = tor_malloc_zero(sizeof(routerinfo_t));
     270             :   }
     271             : 
     272          12 :   return mock_routerinfo;
     273             : }
     274             : 
     275             : #define MICRODESC_GET(digest) GET("/tor/micro/d/" digest)
     276             : static void
     277           1 : test_dir_handle_get_micro_d_not_found(void *data)
     278             : {
     279           1 :   dir_connection_t *conn = NULL;
     280           1 :   char *header = NULL;
     281           1 :   (void) data;
     282             : 
     283           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     284             : 
     285             :   #define B64_256_1 "8/Pz8/u7vz8/Pz+7vz8/Pz+7u/Pz8/P7u/Pz8/P7u78"
     286             :   #define B64_256_2 "zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMw"
     287           1 :   conn = new_dir_conn();
     288             : 
     289           1 :   const char *req = MICRODESC_GET(B64_256_1 "-" B64_256_2);
     290           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
     291             : 
     292           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     293             :                       NULL, NULL, 1, 0);
     294             : 
     295           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
     296             : 
     297           1 :   done:
     298           1 :     UNMOCK(connection_write_to_buf_impl_);
     299             : 
     300           1 :     connection_free_minimal(TO_CONN(conn));
     301           1 :     tor_free(header);
     302           1 : }
     303             : 
     304             : static or_options_t *mock_options = NULL;
     305             : static void
     306          22 : init_mock_options(void)
     307             : {
     308          22 :   mock_options = options_new();
     309          22 :   mock_options->TestingTorNetwork = 1;
     310          22 :   mock_options->DataDirectory = tor_strdup(get_fname_rnd("datadir_tmp"));
     311          22 :   mock_options->CacheDirectory = tor_strdup(mock_options->DataDirectory);
     312          22 :   check_private_dir(mock_options->DataDirectory, CPD_CREATE, NULL);
     313          22 : }
     314             : 
     315             : static const or_options_t *
     316          56 : mock_get_options(void)
     317             : {
     318          56 :   tor_assert(mock_options);
     319          56 :   return mock_options;
     320             : }
     321             : 
     322             : static const char microdesc[] =
     323             :   "onion-key\n"
     324             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     325             :   "MIGJAoGBAMjlHH/daN43cSVRaHBwgUfnszzAhg98EvivJ9Qxfv51mvQUxPjQ07es\n"
     326             :   "gV/3n8fyh3Kqr/ehi9jxkdgSRfSnmF7giaHL1SLZ29kA7KtST+pBvmTpDtHa3ykX\n"
     327             :   "Xorc7hJvIyTZoc1HU+5XSynj3gsBE5IGK1ZRzrNS688LnuZMVp1tAgMBAAE=\n"
     328             :   "-----END RSA PUBLIC KEY-----\n"
     329             :   "ntor-onion-key QlrOXAa8j3LD31LESsPm/lIKFBwevk2oXdqJcd9SEUc=\n";
     330             : 
     331             : static void
     332           1 : test_dir_handle_get_micro_d(void *data)
     333             : {
     334           1 :   dir_connection_t *conn = NULL;
     335           1 :   microdesc_cache_t *mc = NULL ;
     336           1 :   smartlist_t *list = NULL;
     337           1 :   char digest[DIGEST256_LEN];
     338           1 :   char digest_base64[128];
     339           1 :   char path[80];
     340           1 :   char *header = NULL;
     341           1 :   char *body = NULL;
     342           1 :   size_t body_used = 0;
     343           1 :   (void) data;
     344             : 
     345           1 :   MOCK(get_options, mock_get_options);
     346           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     347             : 
     348             :   /* SETUP */
     349           1 :   init_mock_options();
     350             : 
     351             :   /* Add microdesc to cache */
     352           1 :   crypto_digest256(digest, microdesc, strlen(microdesc), DIGEST_SHA256);
     353           1 :   base64_encode_nopad(digest_base64, sizeof(digest_base64),
     354             :                       (uint8_t *) digest, DIGEST256_LEN);
     355             : 
     356           1 :   mc = get_microdesc_cache();
     357           1 :   list = microdescs_add_to_cache(mc, microdesc, NULL, SAVED_NOWHERE, 0,
     358             :                                   time(NULL), NULL);
     359           1 :   tt_int_op(1, OP_EQ, smartlist_len(list));
     360             : 
     361             :   /* Make the request */
     362           1 :   conn = new_dir_conn();
     363             : 
     364           1 :   tor_snprintf(path, sizeof(path), MICRODESC_GET("%s"), digest_base64);
     365           1 :   tt_int_op(directory_handle_command_get(conn, path, NULL, 0), OP_EQ, 0);
     366             : 
     367           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     368             :                       &body, &body_used, strlen(microdesc)+1, 0);
     369             : 
     370           1 :   tt_assert(header);
     371           1 :   tt_assert(body);
     372             : 
     373           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
     374           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
     375           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
     376             : 
     377           1 :   tt_int_op(body_used, OP_EQ, strlen(body));
     378           1 :   tt_str_op(body, OP_EQ, microdesc);
     379             : 
     380           1 :   done:
     381           1 :     UNMOCK(get_options);
     382           1 :     UNMOCK(connection_write_to_buf_impl_);
     383             : 
     384           1 :     or_options_free(mock_options); mock_options = NULL;
     385           1 :     connection_free_minimal(TO_CONN(conn));
     386           1 :     tor_free(header);
     387           1 :     tor_free(body);
     388           1 :     smartlist_free(list);
     389           1 :     microdesc_free_all();
     390           1 : }
     391             : 
     392             : static void
     393           1 : test_dir_handle_get_micro_d_server_busy(void *data)
     394             : {
     395           1 :   dir_connection_t *conn = NULL;
     396           1 :   microdesc_cache_t *mc = NULL ;
     397           1 :   smartlist_t *list = NULL;
     398           1 :   char digest[DIGEST256_LEN];
     399           1 :   char digest_base64[128];
     400           1 :   char path[80];
     401           1 :   char *header = NULL;
     402           1 :   (void) data;
     403             : 
     404           1 :   MOCK(get_options, mock_get_options);
     405           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     406             : 
     407             :   /* SETUP */
     408           1 :   init_mock_options();
     409             : 
     410             :   /* Add microdesc to cache */
     411           1 :   crypto_digest256(digest, microdesc, strlen(microdesc), DIGEST_SHA256);
     412           1 :   base64_encode_nopad(digest_base64, sizeof(digest_base64),
     413             :                       (uint8_t *) digest, DIGEST256_LEN);
     414             : 
     415           1 :   mc = get_microdesc_cache();
     416           1 :   list = microdescs_add_to_cache(mc, microdesc, NULL, SAVED_NOWHERE, 0,
     417             :                                   time(NULL), NULL);
     418           1 :   tt_int_op(1, OP_EQ, smartlist_len(list));
     419             : 
     420             :   //Make it busy
     421           1 :   mock_options->CountPrivateBandwidth = 1;
     422             : 
     423             :   /* Make the request */
     424           1 :   conn = new_dir_conn();
     425             : 
     426           1 :   tor_snprintf(path, sizeof(path), MICRODESC_GET("%s"), digest_base64);
     427           1 :   tt_int_op(directory_handle_command_get(conn, path, NULL, 0), OP_EQ, 0);
     428             : 
     429           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     430             :                       NULL, NULL, 1, 0);
     431             : 
     432           1 :   tt_str_op(SERVER_BUSY, OP_EQ, header);
     433             : 
     434           1 :   done:
     435           1 :     UNMOCK(get_options);
     436           1 :     UNMOCK(connection_write_to_buf_impl_);
     437             : 
     438           1 :     or_options_free(mock_options); mock_options = NULL;
     439           1 :     connection_free_minimal(TO_CONN(conn));
     440           1 :     tor_free(header);
     441           1 :     smartlist_free(list);
     442           1 :     microdesc_free_all();
     443           1 : }
     444             : 
     445             : #define BRIDGES_PATH "/tor/networkstatus-bridges"
     446             : static void
     447           1 : test_dir_handle_get_networkstatus_bridges_not_found_without_auth(void *data)
     448             : {
     449           1 :   dir_connection_t *conn = NULL;
     450           1 :   char *header = NULL;
     451           1 :   (void) data;
     452             : 
     453           1 :   MOCK(get_options, mock_get_options);
     454           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     455             : 
     456             :   /* SETUP */
     457           1 :   init_mock_options();
     458           1 :   mock_options->BridgeAuthoritativeDir = 1;
     459           1 :   mock_options->BridgePassword_AuthDigest_ = tor_strdup("digest");
     460             : 
     461           1 :   conn = new_dir_conn();
     462           1 :   TO_CONN(conn)->linked = 1;
     463             : 
     464           1 :   const char *req = GET(BRIDGES_PATH);
     465           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
     466             : 
     467           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     468             :                       NULL, NULL, 1, 0);
     469             : 
     470           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
     471             : 
     472           1 :   done:
     473           1 :     UNMOCK(get_options);
     474           1 :     UNMOCK(connection_write_to_buf_impl_);
     475           1 :     or_options_free(mock_options); mock_options = NULL;
     476           1 :     connection_free_minimal(TO_CONN(conn));
     477           1 :     tor_free(header);
     478           1 : }
     479             : 
     480             : static void
     481           1 : test_dir_handle_get_networkstatus_bridges(void *data)
     482             : {
     483           1 :   dir_connection_t *conn = NULL;
     484           1 :   char *header = NULL;
     485           1 :   (void) data;
     486             : 
     487           1 :   MOCK(get_options, mock_get_options);
     488           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     489             : 
     490             :   /* SETUP */
     491           1 :   init_mock_options();
     492           1 :   mock_options->BridgeAuthoritativeDir = 1;
     493           1 :   mock_options->BridgePassword_AuthDigest_ = tor_malloc(DIGEST256_LEN);
     494           1 :   crypto_digest256(mock_options->BridgePassword_AuthDigest_,
     495             :                      "abcdefghijklm12345", 18, DIGEST_SHA256);
     496             : 
     497           1 :   conn = new_dir_conn();
     498           1 :   TO_CONN(conn)->linked = 1;
     499             : 
     500           1 :   const char *req = "GET " BRIDGES_PATH " HTTP/1.0\r\n"
     501             :                     "Authorization: Basic abcdefghijklm12345\r\n\r\n";
     502           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
     503             : 
     504           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     505             :                       NULL, NULL, 1, 0);
     506             : 
     507           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
     508           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
     509           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
     510           1 :   tt_assert(strstr(header, "Content-Length: 0\r\n"));
     511             : 
     512           1 :   done:
     513           1 :     UNMOCK(get_options);
     514           1 :     UNMOCK(connection_write_to_buf_impl_);
     515           1 :     or_options_free(mock_options); mock_options = NULL;
     516           1 :     connection_free_minimal(TO_CONN(conn));
     517           1 :     tor_free(header);
     518           1 : }
     519             : 
     520             : static void
     521           1 : test_dir_handle_get_networkstatus_bridges_not_found_wrong_auth(void *data)
     522             : {
     523           1 :   dir_connection_t *conn = NULL;
     524           1 :   char *header = NULL;
     525           1 :   (void) data;
     526             : 
     527           1 :   MOCK(get_options, mock_get_options);
     528           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     529             : 
     530             :   /* SETUP */
     531           1 :   init_mock_options();
     532           1 :   mock_options->BridgeAuthoritativeDir = 1;
     533           1 :   mock_options->BridgePassword_AuthDigest_ = tor_malloc(DIGEST256_LEN);
     534           1 :   crypto_digest256(mock_options->BridgePassword_AuthDigest_,
     535             :                      "abcdefghijklm12345", 18, DIGEST_SHA256);
     536             : 
     537           1 :   conn = new_dir_conn();
     538           1 :   TO_CONN(conn)->linked = 1;
     539             : 
     540           1 :   const char *req = "GET " BRIDGES_PATH " HTTP/1.0\r\n"
     541             :                            "Authorization: Basic NOTSAMEDIGEST\r\n\r\n";
     542           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
     543             : 
     544           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     545             :                       NULL, NULL, 1, 0);
     546             : 
     547           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
     548             : 
     549           1 :   done:
     550           1 :     UNMOCK(get_options);
     551           1 :     UNMOCK(connection_write_to_buf_impl_);
     552           1 :     or_options_free(mock_options); mock_options = NULL;
     553           1 :     connection_free_minimal(TO_CONN(conn));
     554           1 :     tor_free(header);
     555           1 : }
     556             : 
     557             : #define SERVER_DESC_GET(id) GET("/tor/server/" id)
     558             : static void
     559           1 : test_dir_handle_get_server_descriptors_not_found(void* data)
     560             : {
     561           1 :   dir_connection_t *conn = NULL;
     562           1 :   char *header = NULL;
     563           1 :   (void) data;
     564             : 
     565           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     566             : 
     567           1 :   conn = new_dir_conn();
     568             : 
     569           1 :   const char *req = SERVER_DESC_GET("invalid");
     570           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
     571             : 
     572           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     573             :                       NULL, NULL, 1, 0);
     574             : 
     575           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
     576           1 :   tt_ptr_op(conn->spool, OP_EQ, NULL);
     577             : 
     578           1 :   done:
     579           1 :     UNMOCK(connection_write_to_buf_impl_);
     580           1 :     or_options_free(mock_options); mock_options = NULL;
     581           1 :     connection_free_minimal(TO_CONN(conn));
     582           1 :     tor_free(header);
     583           1 : }
     584             : 
     585             : static void
     586           1 : test_dir_handle_get_server_descriptors_all(void* data)
     587             : {
     588           1 :   dir_connection_t *conn = NULL;
     589           1 :   char *header = NULL;
     590           1 :   char *body = NULL;
     591           1 :   size_t body_used = 0;
     592           1 :   (void) data;
     593             : 
     594             :   /* Setup fake routerlist. */
     595           1 :   helper_setup_fake_routerlist();
     596             : 
     597             :   //TODO: change to router_get_my_extrainfo when testing "extra" path
     598           1 :   MOCK(router_get_my_routerinfo,
     599             :        dhg_tests_router_get_my_routerinfo);
     600           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     601             : 
     602             :   // We are one of the routers
     603           1 :   routerlist_t *our_routerlist = router_get_routerlist();
     604           1 :   tt_int_op(smartlist_len(our_routerlist->routers), OP_GE, 1);
     605           1 :   mock_routerinfo = smartlist_get(our_routerlist->routers, 0);
     606           1 :   set_server_identity_key(mock_routerinfo->identity_pkey);
     607           1 :   mock_routerinfo->cache_info.published_on = time(NULL);
     608             : 
     609             :   /* Treat "all" requests as if they were unencrypted */
     610           1 :   mock_routerinfo->cache_info.send_unencrypted = 1;
     611             : 
     612           1 :   conn = new_dir_conn();
     613             : 
     614           1 :   const char *req = SERVER_DESC_GET("all");
     615           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
     616             : 
     617             :   //TODO: Is this a BUG?
     618             :   //It requires strlen(signed_descriptor_len)+1 as body_len but returns a body
     619             :   //which is smaller than that by annotation_len bytes
     620           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     621             :                       &body, &body_used,
     622             :                       1024*1024, 0);
     623             : 
     624           1 :   tt_assert(header);
     625           1 :   tt_assert(body);
     626             : 
     627           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
     628           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
     629           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
     630             : 
     631             :   //TODO: Is this a BUG?
     632             :   //This is what should be expected: tt_int_op(body_used, OP_EQ, strlen(body));
     633           1 :   tt_int_op(body_used, OP_EQ,
     634             :             mock_routerinfo->cache_info.signed_descriptor_len);
     635             : 
     636           1 :   tt_str_op(body, OP_EQ, mock_routerinfo->cache_info.signed_descriptor_body +
     637             :                          mock_routerinfo->cache_info.annotations_len);
     638           1 :   tt_ptr_op(conn->spool, OP_EQ, NULL);
     639             : 
     640           1 :   done:
     641           1 :     UNMOCK(router_get_my_routerinfo);
     642           1 :     UNMOCK(connection_write_to_buf_impl_);
     643           1 :     connection_free_minimal(TO_CONN(conn));
     644           1 :     tor_free(header);
     645           1 :     tor_free(body);
     646             : 
     647           1 :     routerlist_free_all();
     648           1 :     nodelist_free_all();
     649           1 :     entry_guards_free_all();
     650           1 : }
     651             : 
     652             : static char
     653             : TEST_DESCRIPTOR[] =
     654             : "@uploaded-at 2014-06-08 19:20:11\n"
     655             : "@source \"127.0.0.1\"\n"
     656             : "router test000a 127.0.0.1 5000 0 7000\n"
     657             : "platform Tor 0.2.5.3-alpha-dev on Linux\n"
     658             : "protocols Link 1 2 Circuit 1\n"
     659             : "published 2014-06-08 19:20:11\n"
     660             : "fingerprint C7E7 CCB8 179F 8CC3 7F5C 8A04 2B3A 180B 934B 14BA\n"
     661             : "uptime 0\n"
     662             : "bandwidth 1073741824 1073741824 0\n"
     663             : "extra-info-digest 67A152A4C7686FB07664F872620635F194D76D95\n"
     664             : "caches-extra-info\n"
     665             : "onion-key\n"
     666             : "-----BEGIN RSA PUBLIC KEY-----\n"
     667             : "MIGJAoGBAOuBUIEBARMkkka/TGyaQNgUEDLP0KG7sy6KNQTNOlZHUresPr/vlVjo\n"
     668             : "HPpLMfu9M2z18c51YX/muWwY9x4MyQooD56wI4+AqXQcJRwQfQlPn3Ay82uZViA9\n"
     669             : "DpBajRieLlKKkl145KjArpD7F5BVsqccvjErgFYXvhhjSrx7BVLnAgMBAAE=\n"
     670             : "-----END RSA PUBLIC KEY-----\n"
     671             : "signing-key\n"
     672             : "-----BEGIN RSA PUBLIC KEY-----\n"
     673             : "MIGJAoGBAN6NLnSxWQnFXxqZi5D3b0BMgV6y9NJLGjYQVP+eWtPZWgqyv4zeYsqv\n"
     674             : "O9y6c5lvxyUxmNHfoAbe/s8f2Vf3/YaC17asAVSln4ktrr3e9iY74a9RMWHv1Gzk\n"
     675             : "3042nMcqj3PEhRN0PoLkcOZNjjmNbaqki6qy9bWWZDNTdo+uI44dAgMBAAE=\n"
     676             : "-----END RSA PUBLIC KEY-----\n"
     677             : "hidden-service-dir\n"
     678             : "contact auth0@test.test\n"
     679             : "ntor-onion-key pK4bs08ERYN591jj7ca17Rn9Q02TIEfhnjR6hSq+fhU=\n"
     680             : "reject *:*\n"
     681             : "router-signature\n"
     682             : "-----BEGIN SIGNATURE-----\n"
     683             : "rx88DuM3Y7tODlHNDDEVzKpwh3csaG1or+T4l2Xs1oq3iHHyPEtB6QTLYrC60trG\n"
     684             : "aAPsj3DEowGfjga1b248g2dtic8Ab+0exfjMm1RHXfDam5TXXZU3A0wMyoHjqHuf\n"
     685             : "eChGPgFNUvEc+5YtD27qEDcUjcinYztTs7/dzxBT4PE=\n"
     686             : "-----END SIGNATURE-----\n";
     687             : 
     688             : static void
     689           1 : test_dir_handle_get_server_descriptors_authority(void* data)
     690             : {
     691           1 :   dir_connection_t *conn = NULL;
     692           1 :   char *header = NULL;
     693           1 :   char *body = NULL;
     694           1 :   size_t body_used = 0;
     695           1 :   crypto_pk_t *identity_pkey = pk_generate(0);
     696           1 :   (void) data;
     697             : 
     698           1 :   MOCK(router_get_my_routerinfo,
     699             :        dhg_tests_router_get_my_routerinfo);
     700           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     701             : 
     702             :   /* init mock */
     703           1 :   router_get_my_routerinfo();
     704           1 :   crypto_pk_get_digest(identity_pkey,
     705           1 :                        mock_routerinfo->cache_info.identity_digest);
     706             : 
     707             :   // the digest is mine (the channel is unnecrypted, so we must allow sending)
     708           1 :   set_server_identity_key(identity_pkey);
     709           1 :   mock_routerinfo->cache_info.send_unencrypted = 1;
     710             : 
     711             :   /* Setup descriptor */
     712           1 :   long annotation_len = strstr(TEST_DESCRIPTOR, "router ") - TEST_DESCRIPTOR;
     713           2 :   mock_routerinfo->cache_info.signed_descriptor_body =
     714           1 :     tor_strdup(TEST_DESCRIPTOR);
     715           1 :   mock_routerinfo->cache_info.signed_descriptor_len =
     716           1 :     strlen(TEST_DESCRIPTOR) - annotation_len;
     717           1 :   mock_routerinfo->cache_info.annotations_len = annotation_len;
     718           1 :   mock_routerinfo->cache_info.published_on = time(NULL);
     719             : 
     720           1 :   conn = new_dir_conn();
     721             : 
     722           1 :   const char *req = SERVER_DESC_GET("authority");
     723           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
     724             : 
     725             :   //TODO: Is this a BUG?
     726             :   //It requires strlen(TEST_DESCRIPTOR)+1 as body_len but returns a body which
     727             :   //is smaller than that by annotation_len bytes
     728           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     729           1 :                       &body, &body_used, strlen(TEST_DESCRIPTOR)+1, 0);
     730             : 
     731           1 :   tt_assert(header);
     732           1 :   tt_assert(body);
     733             : 
     734           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
     735           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
     736           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
     737             : 
     738           1 :   tt_int_op(body_used, OP_EQ, strlen(body));
     739             : 
     740           1 :   tt_str_op(body, OP_EQ, TEST_DESCRIPTOR + annotation_len);
     741           1 :   tt_ptr_op(conn->spool, OP_EQ, NULL);
     742             : 
     743           1 :   done:
     744           1 :     UNMOCK(router_get_my_routerinfo);
     745           1 :     UNMOCK(connection_write_to_buf_impl_);
     746           1 :     tor_free(mock_routerinfo->cache_info.signed_descriptor_body);
     747           1 :     tor_free(mock_routerinfo);
     748           1 :     connection_free_minimal(TO_CONN(conn));
     749           1 :     tor_free(header);
     750           1 :     tor_free(body);
     751           1 :     crypto_pk_free(identity_pkey);
     752           1 : }
     753             : 
     754             : static void
     755           1 : test_dir_handle_get_server_descriptors_fp(void* data)
     756             : {
     757           1 :   dir_connection_t *conn = NULL;
     758           1 :   char *header = NULL;
     759           1 :   char *body = NULL;
     760           1 :   size_t body_used = 0;
     761           1 :   crypto_pk_t *identity_pkey = pk_generate(0);
     762           1 :   (void) data;
     763             : 
     764           1 :   MOCK(router_get_my_routerinfo,
     765             :        dhg_tests_router_get_my_routerinfo);
     766           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     767             : 
     768             :   /* init mock */
     769           1 :   router_get_my_routerinfo();
     770           1 :   crypto_pk_get_digest(identity_pkey,
     771           1 :                        mock_routerinfo->cache_info.identity_digest);
     772             : 
     773             :   // the digest is mine (the channel is unnecrypted, so we must allow sending)
     774           1 :   set_server_identity_key(identity_pkey);
     775           1 :   mock_routerinfo->cache_info.send_unencrypted = 1;
     776             : 
     777             :   /* Setup descriptor */
     778           1 :   long annotation_len = strstr(TEST_DESCRIPTOR, "router ") - TEST_DESCRIPTOR;
     779           2 :   mock_routerinfo->cache_info.signed_descriptor_body =
     780           1 :     tor_strdup(TEST_DESCRIPTOR);
     781           1 :   mock_routerinfo->cache_info.signed_descriptor_len =
     782           1 :     strlen(TEST_DESCRIPTOR) - annotation_len;
     783           1 :   mock_routerinfo->cache_info.annotations_len = annotation_len;
     784           1 :   mock_routerinfo->cache_info.published_on = time(NULL);
     785             : 
     786           1 :   conn = new_dir_conn();
     787             : 
     788             :   #define HEX1 "Fe0daff89127389bc67558691231234551193EEE"
     789             :   #define HEX2 "Deadbeef99999991111119999911111111f00ba4"
     790           1 :   const char *hex_digest = hex_str(mock_routerinfo->cache_info.identity_digest,
     791             :                                    DIGEST_LEN);
     792             : 
     793           1 :   char req[155];
     794           1 :   tor_snprintf(req, sizeof(req), SERVER_DESC_GET("fp/%s+" HEX1 "+" HEX2),
     795             :                hex_digest);
     796           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
     797             : 
     798             :   //TODO: Is this a BUG?
     799             :   //It requires strlen(TEST_DESCRIPTOR)+1 as body_len but returns a body which
     800             :   //is smaller than that by annotation_len bytes
     801           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     802           1 :                       &body, &body_used, strlen(TEST_DESCRIPTOR)+1, 0);
     803             : 
     804           1 :   tt_assert(header);
     805           1 :   tt_assert(body);
     806             : 
     807           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
     808           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
     809           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
     810             : 
     811           1 :   tt_int_op(body_used, OP_EQ, strlen(body));
     812             : 
     813           1 :   tt_str_op(body, OP_EQ, TEST_DESCRIPTOR + annotation_len);
     814           1 :   tt_ptr_op(conn->spool, OP_EQ, NULL);
     815             : 
     816           1 :   done:
     817           1 :     UNMOCK(router_get_my_routerinfo);
     818           1 :     UNMOCK(connection_write_to_buf_impl_);
     819           1 :     tor_free(mock_routerinfo->cache_info.signed_descriptor_body);
     820           1 :     tor_free(mock_routerinfo);
     821           1 :     connection_free_minimal(TO_CONN(conn));
     822           1 :     tor_free(header);
     823           1 :     tor_free(body);
     824           1 :     crypto_pk_free(identity_pkey);
     825           1 : }
     826             : 
     827             : #define HEX1 "Fe0daff89127389bc67558691231234551193EEE"
     828             : #define HEX2 "Deadbeef99999991111119999911111111f00ba4"
     829             : 
     830             : static void
     831           1 : test_dir_handle_get_server_descriptors_d(void* data)
     832             : {
     833           1 :   dir_connection_t *conn = NULL;
     834           1 :   char *header = NULL;
     835           1 :   char *body = NULL;
     836           1 :   size_t body_used = 0;
     837           1 :   crypto_pk_t *identity_pkey = pk_generate(0);
     838           1 :   (void) data;
     839             : 
     840             :   /* Setup fake routerlist. */
     841           1 :   helper_setup_fake_routerlist();
     842             : 
     843           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     844             : 
     845             :   /* Get one router's signed_descriptor_digest */
     846           1 :   routerlist_t *our_routerlist = router_get_routerlist();
     847           1 :   tt_int_op(smartlist_len(our_routerlist->routers), OP_GE, 1);
     848           1 :   routerinfo_t *router = smartlist_get(our_routerlist->routers, 0);
     849           1 :   const char *hex_digest = hex_str(router->cache_info.signed_descriptor_digest,
     850             :                                    DIGEST_LEN);
     851             : 
     852           1 :   conn = new_dir_conn();
     853             : 
     854           1 :   char req_header[155]; /* XXX Why 155? What kind of number is that?? */
     855           1 :   tor_snprintf(req_header, sizeof(req_header),
     856             :                SERVER_DESC_GET("d/%s+" HEX1 "+" HEX2), hex_digest);
     857           1 :   tt_int_op(directory_handle_command_get(conn, req_header, NULL, 0), OP_EQ, 0);
     858             : 
     859             :   //TODO: Is this a BUG?
     860             :   //It requires strlen(signed_descriptor_len)+1 as body_len but returns a body
     861             :   //which is smaller than that by annotation_len bytes
     862           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     863             :                       &body, &body_used,
     864           1 :                       router->cache_info.signed_descriptor_len+1, 0);
     865             : 
     866           1 :   tt_assert(header);
     867           1 :   tt_assert(body);
     868             : 
     869           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
     870           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
     871           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
     872             : 
     873             :   //TODO: Is this a BUG?
     874             :   //This is what should be expected:
     875             :   //tt_int_op(body_used, OP_EQ, strlen(body));
     876           1 :   tt_int_op(body_used, OP_EQ, router->cache_info.signed_descriptor_len);
     877             : 
     878           1 :   tt_str_op(body, OP_EQ, router->cache_info.signed_descriptor_body +
     879             :                          router->cache_info.annotations_len);
     880           1 :   tt_ptr_op(conn->spool, OP_EQ, NULL);
     881             : 
     882           1 :   done:
     883           1 :     UNMOCK(connection_write_to_buf_impl_);
     884           1 :     tor_free(mock_routerinfo);
     885           1 :     connection_free_minimal(TO_CONN(conn));
     886           1 :     tor_free(header);
     887           1 :     tor_free(body);
     888           1 :     crypto_pk_free(identity_pkey);
     889             : 
     890           1 :     routerlist_free_all();
     891           1 :     nodelist_free_all();
     892           1 :     entry_guards_free_all();
     893           1 : }
     894             : 
     895             : static void
     896           1 : test_dir_handle_get_server_descriptors_busy(void* data)
     897             : {
     898           1 :   dir_connection_t *conn = NULL;
     899           1 :   char *header = NULL;
     900           1 :   crypto_pk_t *identity_pkey = pk_generate(0);
     901           1 :   (void) data;
     902             : 
     903             :   /* Setup fake routerlist. */
     904           1 :   helper_setup_fake_routerlist();
     905             : 
     906           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     907             : 
     908             :   //Make it busy
     909           1 :   MOCK(get_options, mock_get_options);
     910           1 :   init_mock_options();
     911           1 :   mock_options->CountPrivateBandwidth = 1;
     912             : 
     913             :   /* Get one router's signed_descriptor_digest */
     914           1 :   routerlist_t *our_routerlist = router_get_routerlist();
     915           1 :   tt_int_op(smartlist_len(our_routerlist->routers), OP_GE, 1);
     916           1 :   routerinfo_t *router = smartlist_get(our_routerlist->routers, 0);
     917           1 :   const char *hex_digest = hex_str(router->cache_info.signed_descriptor_digest,
     918             :                                    DIGEST_LEN);
     919             : 
     920           1 :   conn = new_dir_conn();
     921             : 
     922             :   #define HEX1 "Fe0daff89127389bc67558691231234551193EEE"
     923             :   #define HEX2 "Deadbeef99999991111119999911111111f00ba4"
     924           1 :   char req_header[155]; /* XXX 155? Why 155? */
     925           1 :   tor_snprintf(req_header, sizeof(req_header),
     926             :                SERVER_DESC_GET("d/%s+" HEX1 "+" HEX2), hex_digest);
     927           1 :   tt_int_op(directory_handle_command_get(conn, req_header, NULL, 0), OP_EQ, 0);
     928             : 
     929           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     930             :                       NULL, NULL, 1, 0);
     931             : 
     932           1 :   tt_assert(header);
     933           1 :   tt_str_op(SERVER_BUSY, OP_EQ, header);
     934             : 
     935           1 :   tt_ptr_op(conn->spool, OP_EQ, NULL);
     936             : 
     937           1 :   done:
     938           1 :     UNMOCK(get_options);
     939           1 :     UNMOCK(connection_write_to_buf_impl_);
     940           1 :     tor_free(mock_routerinfo);
     941           1 :     connection_free_minimal(TO_CONN(conn));
     942           1 :     tor_free(header);
     943           1 :     crypto_pk_free(identity_pkey);
     944             : 
     945           1 :     routerlist_free_all();
     946           1 :     nodelist_free_all();
     947           1 :     entry_guards_free_all();
     948           1 : }
     949             : 
     950             : static void
     951           1 : test_dir_handle_get_server_keys_bad_req(void* data)
     952             : {
     953           1 :   dir_connection_t *conn = NULL;
     954           1 :   char *header = NULL;
     955           1 :   (void) data;
     956             : 
     957           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     958             : 
     959           1 :   conn = new_dir_conn();
     960             : 
     961           1 :   const char *req = GET("/tor/keys/");
     962           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
     963             : 
     964           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     965             :                       NULL, NULL, 1, 0);
     966             : 
     967           1 :   tt_assert(header);
     968           1 :   tt_str_op(BAD_REQUEST, OP_EQ, header);
     969             : 
     970           1 :   done:
     971           1 :     UNMOCK(connection_write_to_buf_impl_);
     972           1 :     connection_free_minimal(TO_CONN(conn));
     973           1 :     tor_free(header);
     974           1 : }
     975             : 
     976             : static void
     977           1 : test_dir_handle_get_server_keys_all_not_found(void* data)
     978             : {
     979           1 :   dir_connection_t *conn = NULL;
     980           1 :   char *header = NULL;
     981           1 :   (void) data;
     982             : 
     983           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
     984             : 
     985           1 :   conn = new_dir_conn();
     986             : 
     987           1 :   const char *req = GET("/tor/keys/all");
     988           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
     989             : 
     990           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
     991             :                       NULL, NULL, 1, 0);
     992             : 
     993           1 :   tt_assert(header);
     994           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
     995             : 
     996           1 :   done:
     997           1 :     UNMOCK(connection_write_to_buf_impl_);
     998           1 :     connection_free_minimal(TO_CONN(conn));
     999           1 :     tor_free(header);
    1000           1 : }
    1001             : 
    1002             : #define TEST_CERTIFICATE AUTHORITY_CERT_3
    1003             : #define TEST_SIGNING_KEY AUTHORITY_SIGNKEY_A_DIGEST
    1004             : 
    1005             : static const char TEST_CERT_IDENT_KEY[] =
    1006             :   "D867ACF56A9D229B35C25F0090BC9867E906BE69";
    1007             : 
    1008             : static void
    1009           1 : test_dir_handle_get_server_keys_all(void* data)
    1010             : {
    1011           1 :   dir_connection_t *conn = NULL;
    1012           1 :   char *header = NULL;
    1013           1 :   char *body = NULL;
    1014           1 :   size_t body_used = 0;
    1015           1 :   const char digest[DIGEST_LEN] = "";
    1016             : 
    1017           1 :   dir_server_t *ds = NULL;
    1018           1 :   (void) data;
    1019             : 
    1020           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1021             : 
    1022           1 :   clear_dir_servers();
    1023           1 :   routerlist_free_all();
    1024             : 
    1025             :   /* create a trusted ds */
    1026           1 :   ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
    1027             :                               NULL, V3_DIRINFO, 1.0);
    1028           1 :   tt_assert(ds);
    1029           1 :   dir_server_add(ds);
    1030             : 
    1031             :   /* ds v3_identity_digest is the certificate's identity_key */
    1032           1 :   base16_decode(ds->v3_identity_digest, DIGEST_LEN,
    1033             :                 TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
    1034           1 :   tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
    1035             :     TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
    1036             : 
    1037           1 :   conn = new_dir_conn();
    1038             : 
    1039           1 :   const char *req = GET("/tor/keys/all");
    1040           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
    1041             : 
    1042           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    1043           1 :                       &body, &body_used, strlen(TEST_CERTIFICATE)+1, 0);
    1044             : 
    1045           1 :   tt_assert(header);
    1046           1 :   tt_assert(body);
    1047             : 
    1048           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
    1049           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
    1050           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
    1051           1 :   tt_assert(strstr(header, "Content-Length: 1883\r\n"));
    1052             : 
    1053           1 :   tt_str_op(TEST_CERTIFICATE, OP_EQ, body);
    1054             : 
    1055           1 :   done:
    1056           1 :     UNMOCK(connection_write_to_buf_impl_);
    1057           1 :     connection_free_minimal(TO_CONN(conn));
    1058           1 :     tor_free(header);
    1059           1 :     tor_free(body);
    1060             : 
    1061           1 :     clear_dir_servers();
    1062           1 :     routerlist_free_all();
    1063           1 : }
    1064             : 
    1065             : static void
    1066           1 : test_dir_handle_get_server_keys_authority_not_found(void* data)
    1067             : {
    1068           1 :   dir_connection_t *conn = NULL;
    1069           1 :   char *header = NULL;
    1070           1 :   (void) data;
    1071             : 
    1072           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1073             : 
    1074           1 :   conn = new_dir_conn();
    1075             : 
    1076           1 :   const char *req = GET("/tor/keys/authority");
    1077           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
    1078             : 
    1079           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    1080             :                       NULL, NULL, 1, 0);
    1081             : 
    1082           1 :   tt_assert(header);
    1083           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
    1084             : 
    1085           1 :   done:
    1086           1 :     UNMOCK(connection_write_to_buf_impl_);
    1087           1 :     connection_free_minimal(TO_CONN(conn));
    1088           1 :     tor_free(header);
    1089           1 : }
    1090             : 
    1091             : static authority_cert_t * mock_cert = NULL;
    1092             : 
    1093             : static authority_cert_t *
    1094           8 : get_my_v3_authority_cert_m(void)
    1095             : {
    1096           8 :   tor_assert(mock_cert);
    1097           8 :   return mock_cert;
    1098             : }
    1099             : 
    1100             : static void
    1101           1 : test_dir_handle_get_server_keys_authority(void* data)
    1102             : {
    1103           1 :   dir_connection_t *conn = NULL;
    1104           1 :   char *header = NULL;
    1105           1 :   char *body = NULL;
    1106           1 :   size_t body_used = 0;
    1107           1 :   (void) data;
    1108             : 
    1109           1 :   mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE,
    1110             :                                                strlen(TEST_CERTIFICATE),
    1111             :                                                NULL);
    1112             : 
    1113           1 :   MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
    1114           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1115             : 
    1116           1 :   conn = new_dir_conn();
    1117             : 
    1118           1 :   const char *req = GET("/tor/keys/authority");
    1119           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
    1120             : 
    1121           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    1122           1 :                       &body, &body_used, strlen(TEST_CERTIFICATE)+1, 0);
    1123             : 
    1124           1 :   tt_assert(header);
    1125           1 :   tt_assert(body);
    1126             : 
    1127           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
    1128           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
    1129           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
    1130           1 :   tt_assert(strstr(header, "Content-Length: 1883\r\n"));
    1131             : 
    1132           1 :   tt_str_op(TEST_CERTIFICATE, OP_EQ, body);
    1133             : 
    1134           1 :   done:
    1135           1 :     UNMOCK(get_my_v3_authority_cert);
    1136           1 :     UNMOCK(connection_write_to_buf_impl_);
    1137           1 :     connection_free_minimal(TO_CONN(conn));
    1138           1 :     tor_free(header);
    1139           1 :     tor_free(body);
    1140           1 :     authority_cert_free(mock_cert); mock_cert = NULL;
    1141           1 : }
    1142             : 
    1143             : static void
    1144           1 : test_dir_handle_get_server_keys_fp_not_found(void* data)
    1145             : {
    1146           1 :   dir_connection_t *conn = NULL;
    1147           1 :   char *header = NULL;
    1148           1 :   (void) data;
    1149             : 
    1150           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1151             : 
    1152           1 :   conn = new_dir_conn();
    1153             : 
    1154           1 :   const char *req = GET("/tor/keys/fp/somehex");
    1155           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
    1156             : 
    1157           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    1158             :                       NULL, NULL, 1, 0);
    1159             : 
    1160           1 :   tt_assert(header);
    1161           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
    1162             : 
    1163           1 :   done:
    1164           1 :     UNMOCK(connection_write_to_buf_impl_);
    1165           1 :     connection_free_minimal(TO_CONN(conn));
    1166           1 :     tor_free(header);
    1167           1 : }
    1168             : 
    1169             : static void
    1170           1 : test_dir_handle_get_server_keys_fp(void* data)
    1171             : {
    1172           1 :   dir_connection_t *conn = NULL;
    1173           1 :   char *header = NULL;
    1174           1 :   char *body = NULL;
    1175           1 :   size_t body_used = 0;
    1176           1 :   dir_server_t *ds = NULL;
    1177           1 :   const char digest[DIGEST_LEN] = "";
    1178           1 :   (void) data;
    1179             : 
    1180           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1181             : 
    1182           1 :   clear_dir_servers();
    1183           1 :   routerlist_free_all();
    1184             : 
    1185             :   /* create a trusted ds */
    1186           1 :   ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
    1187             :                               NULL, V3_DIRINFO, 1.0);
    1188           1 :   tt_assert(ds);
    1189           1 :   dir_server_add(ds);
    1190             : 
    1191             :   /* ds v3_identity_digest is the certificate's identity_key */
    1192           1 :   base16_decode(ds->v3_identity_digest, DIGEST_LEN,
    1193             :                 TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
    1194             : 
    1195           1 :   tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
    1196             :     TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
    1197             : 
    1198           1 :   conn = new_dir_conn();
    1199           1 :   char req[71];
    1200           1 :   tor_snprintf(req, sizeof(req),
    1201             :                      GET("/tor/keys/fp/%s"), TEST_CERT_IDENT_KEY);
    1202           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
    1203             : 
    1204           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    1205           1 :                       &body, &body_used, strlen(TEST_CERTIFICATE)+1, 0);
    1206             : 
    1207           1 :   tt_assert(header);
    1208           1 :   tt_assert(body);
    1209             : 
    1210           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
    1211           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
    1212           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
    1213           1 :   tt_assert(strstr(header, "Content-Length: 1883\r\n"));
    1214             : 
    1215           1 :   tt_str_op(TEST_CERTIFICATE, OP_EQ, body);
    1216             : 
    1217           1 :   done:
    1218           1 :     UNMOCK(connection_write_to_buf_impl_);
    1219           1 :     connection_free_minimal(TO_CONN(conn));
    1220           1 :     tor_free(header);
    1221           1 :     tor_free(body);
    1222           1 :     clear_dir_servers();
    1223           1 :     routerlist_free_all();
    1224           1 : }
    1225             : 
    1226             : static void
    1227           1 : test_dir_handle_get_server_keys_sk_not_found(void* data)
    1228             : {
    1229           1 :   dir_connection_t *conn = NULL;
    1230           1 :   char *header = NULL;
    1231           1 :   (void) data;
    1232             : 
    1233           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1234             : 
    1235           1 :   conn = new_dir_conn();
    1236             : 
    1237           1 :   const char *req = GET("/tor/keys/sk/somehex");
    1238           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
    1239             : 
    1240           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    1241             :                       NULL, NULL, 1, 0);
    1242             : 
    1243           1 :   tt_assert(header);
    1244           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
    1245             : 
    1246           1 :   done:
    1247           1 :     UNMOCK(connection_write_to_buf_impl_);
    1248           1 :     connection_free_minimal(TO_CONN(conn));
    1249           1 :     tor_free(header);
    1250           1 : }
    1251             : 
    1252             : static void
    1253           1 : test_dir_handle_get_server_keys_sk(void* data)
    1254             : {
    1255           1 :   dir_connection_t *conn = NULL;
    1256           1 :   char *header = NULL;
    1257           1 :   char *body = NULL;
    1258           1 :   size_t body_used = 0;
    1259           1 :   (void) data;
    1260             : 
    1261           1 :   mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE,
    1262             :                                                strlen(TEST_CERTIFICATE),
    1263             :                                                NULL);
    1264           1 :   MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
    1265           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1266             : 
    1267           1 :   clear_dir_servers();
    1268           1 :   routerlist_free_all();
    1269             : 
    1270           1 :   tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
    1271             :     TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
    1272             : 
    1273           1 :   conn = new_dir_conn();
    1274           1 :   char req[71];
    1275           1 :   tor_snprintf(req, sizeof(req),
    1276             :                GET("/tor/keys/sk/%s"), TEST_SIGNING_KEY);
    1277           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
    1278             : 
    1279           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    1280           1 :                       &body, &body_used, strlen(TEST_CERTIFICATE)+1, 0);
    1281             : 
    1282           1 :   tt_assert(header);
    1283           1 :   tt_assert(body);
    1284             : 
    1285           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
    1286           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
    1287           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
    1288           1 :   tt_assert(strstr(header, "Content-Length: 1883\r\n"));
    1289             : 
    1290           1 :   tt_str_op(TEST_CERTIFICATE, OP_EQ, body);
    1291             : 
    1292           1 :   done:
    1293           1 :     UNMOCK(get_my_v3_authority_cert);
    1294           1 :     UNMOCK(connection_write_to_buf_impl_);
    1295           1 :     connection_free_minimal(TO_CONN(conn));
    1296           1 :     authority_cert_free(mock_cert); mock_cert = NULL;
    1297           1 :     tor_free(header);
    1298           1 :     tor_free(body);
    1299           1 : }
    1300             : 
    1301             : static void
    1302           1 : test_dir_handle_get_server_keys_fpsk_not_found(void* data)
    1303             : {
    1304           1 :   dir_connection_t *conn = NULL;
    1305           1 :   char *header = NULL;
    1306           1 :   (void) data;
    1307             : 
    1308           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1309             : 
    1310           1 :   conn = new_dir_conn();
    1311             : 
    1312           1 :   const char *req = GET("/tor/keys/fp-sk/somehex");
    1313           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
    1314             : 
    1315           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    1316             :                       NULL, NULL, 1, 0);
    1317             : 
    1318           1 :   tt_assert(header);
    1319           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
    1320             : 
    1321           1 :   done:
    1322           1 :     UNMOCK(connection_write_to_buf_impl_);
    1323           1 :     connection_free_minimal(TO_CONN(conn));
    1324           1 :     tor_free(header);
    1325           1 : }
    1326             : 
    1327             : static void
    1328           1 : test_dir_handle_get_server_keys_fpsk(void* data)
    1329             : {
    1330           1 :   dir_connection_t *conn = NULL;
    1331           1 :   char *header = NULL;
    1332           1 :   char *body = NULL;
    1333           1 :   size_t body_used = 0;
    1334           1 :   dir_server_t *ds = NULL;
    1335           1 :   const char digest[DIGEST_LEN] = "";
    1336           1 :   (void) data;
    1337             : 
    1338           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1339             : 
    1340           1 :   clear_dir_servers();
    1341           1 :   routerlist_free_all();
    1342             : 
    1343             :   /* create a trusted ds */
    1344           1 :   ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
    1345             :                               NULL, V3_DIRINFO, 1.0);
    1346           1 :   tt_assert(ds);
    1347             : 
    1348             :   /* ds v3_identity_digest is the certificate's identity_key */
    1349           1 :   base16_decode(ds->v3_identity_digest, DIGEST_LEN,
    1350             :                 TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
    1351           1 :   dir_server_add(ds);
    1352             : 
    1353           1 :   tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
    1354             :     TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
    1355             : 
    1356           1 :   conn = new_dir_conn();
    1357             : 
    1358           1 :   char req[115];
    1359           1 :   tor_snprintf(req, sizeof(req),
    1360             :                GET("/tor/keys/fp-sk/%s-%s"),
    1361             :                TEST_CERT_IDENT_KEY, TEST_SIGNING_KEY);
    1362             : 
    1363           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
    1364             : 
    1365           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    1366           1 :                       &body, &body_used, strlen(TEST_CERTIFICATE)+1, 0);
    1367             : 
    1368           1 :   tt_assert(header);
    1369           1 :   tt_assert(body);
    1370             : 
    1371           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
    1372           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
    1373           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
    1374           1 :   tt_assert(strstr(header, "Content-Length: 1883\r\n"));
    1375             : 
    1376           1 :   tt_str_op(TEST_CERTIFICATE, OP_EQ, body);
    1377             : 
    1378           1 :   done:
    1379           1 :     UNMOCK(connection_write_to_buf_impl_);
    1380           1 :     connection_free_minimal(TO_CONN(conn));
    1381           1 :     tor_free(header);
    1382           1 :     tor_free(body);
    1383             : 
    1384           1 :     clear_dir_servers();
    1385           1 :     routerlist_free_all();
    1386           1 : }
    1387             : 
    1388             : static void
    1389           1 : test_dir_handle_get_server_keys_busy(void* data)
    1390             : {
    1391           1 :   dir_connection_t *conn = NULL;
    1392           1 :   char *header = NULL;
    1393           1 :   dir_server_t *ds = NULL;
    1394           1 :   const char digest[DIGEST_LEN] = "";
    1395           1 :   (void) data;
    1396             : 
    1397           1 :   clear_dir_servers();
    1398           1 :   routerlist_free_all();
    1399             : 
    1400             :   /* create a trusted ds */
    1401           1 :   ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
    1402             :                               NULL, V3_DIRINFO, 1.0);
    1403           1 :   tt_assert(ds);
    1404             : 
    1405             :   /* ds v3_identity_digest is the certificate's identity_key */
    1406           1 :   base16_decode(ds->v3_identity_digest, DIGEST_LEN,
    1407             :                 TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
    1408           1 :   dir_server_add(ds);
    1409             : 
    1410           1 :   tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
    1411             :     TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
    1412             : 
    1413           1 :   MOCK(get_options, mock_get_options);
    1414           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1415             : 
    1416             :   /* setup busy server */
    1417           1 :   init_mock_options();
    1418           1 :   mock_options->CountPrivateBandwidth = 1;
    1419             : 
    1420           1 :   conn = new_dir_conn();
    1421           1 :   char req[71];
    1422           1 :   tor_snprintf(req, sizeof(req), GET("/tor/keys/fp/%s"), TEST_CERT_IDENT_KEY);
    1423           1 :   tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
    1424             : 
    1425           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    1426             :                       NULL, NULL, 1, 0);
    1427             : 
    1428           1 :   tt_assert(header);
    1429           1 :   tt_str_op(SERVER_BUSY, OP_EQ, header);
    1430             : 
    1431           1 :   done:
    1432           1 :     UNMOCK(get_options);
    1433           1 :     UNMOCK(connection_write_to_buf_impl_);
    1434           1 :     connection_free_minimal(TO_CONN(conn));
    1435           1 :     tor_free(header);
    1436           1 :     or_options_free(mock_options); mock_options = NULL;
    1437             : 
    1438           1 :     clear_dir_servers();
    1439           1 :     routerlist_free_all();
    1440           1 : }
    1441             : 
    1442             : static networkstatus_t *mock_ns_val = NULL;
    1443             : static networkstatus_t *
    1444           0 : mock_ns_get_by_flavor(consensus_flavor_t f)
    1445             : {
    1446           0 :   (void)f;
    1447           0 :   return mock_ns_val;
    1448             : }
    1449             : 
    1450             : static void
    1451           1 : test_dir_handle_get_status_vote_current_consensus_ns_not_enough_sigs(void* d)
    1452             : {
    1453           1 :   dir_connection_t *conn = NULL;
    1454           1 :   char *header = NULL;
    1455           1 :   char *stats = NULL;
    1456           1 :   (void) d;
    1457             : 
    1458             :   /* init mock */
    1459           1 :   mock_ns_val = tor_malloc_zero(sizeof(networkstatus_t));
    1460           1 :   mock_ns_val->flavor = FLAV_NS;
    1461           1 :   mock_ns_val->type = NS_TYPE_CONSENSUS;
    1462           1 :   mock_ns_val->voters = smartlist_new();
    1463           1 :   mock_ns_val->valid_after = time(NULL) - 1800;
    1464           1 :   mock_ns_val->valid_until = time(NULL) - 60;
    1465             : 
    1466             :   #define NETWORK_STATUS "some network status string"
    1467           1 :   consdiffmgr_add_consensus(NETWORK_STATUS, mock_ns_val);
    1468             : 
    1469             :   /* init mock */
    1470           1 :   init_mock_options();
    1471             : 
    1472           1 :   MOCK(get_options, mock_get_options);
    1473           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1474           1 :   MOCK(networkstatus_get_latest_consensus_by_flavor, mock_ns_get_by_flavor);
    1475             : 
    1476             :   /* start gathering stats */
    1477           1 :   mock_options->DirReqStatistics = 1;
    1478           1 :   geoip_dirreq_stats_init(time(NULL));
    1479             : 
    1480           1 :   conn = new_dir_conn();
    1481             : 
    1482           1 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    1483             :     GET("/tor/status-vote/current/consensus-ns/" HEX1 "+" HEX2), NULL, 0));
    1484             : 
    1485           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    1486             :                       NULL, NULL, 1, 0);
    1487             : 
    1488           1 :   tt_assert(header);
    1489           1 :   tt_str_op(NOT_ENOUGH_CONSENSUS_SIGNATURES, OP_EQ, header);
    1490             : 
    1491           1 :   stats = geoip_format_dirreq_stats(time(NULL));
    1492           1 :   tt_assert(stats);
    1493           1 :   tt_assert(strstr(stats, "not-enough-sigs=8"));
    1494             : 
    1495           1 :   done:
    1496           1 :     UNMOCK(networkstatus_get_latest_consensus_by_flavor);
    1497           1 :     UNMOCK(connection_write_to_buf_impl_);
    1498           1 :     UNMOCK(get_options);
    1499             : 
    1500           1 :     connection_free_minimal(TO_CONN(conn));
    1501           1 :     tor_free(header);
    1502           1 :     tor_free(stats);
    1503           1 :     smartlist_free(mock_ns_val->voters);
    1504           1 :     tor_free(mock_ns_val);
    1505           1 :     or_options_free(mock_options); mock_options = NULL;
    1506           1 : }
    1507             : 
    1508             : static void
    1509           1 : test_dir_handle_get_status_vote_current_consensus_ns_not_found(void* data)
    1510             : {
    1511           1 :   dir_connection_t *conn = NULL;
    1512           1 :   char *header = NULL;
    1513           1 :   char *stats = NULL;
    1514           1 :   (void) data;
    1515             : 
    1516           1 :   init_mock_options();
    1517             : 
    1518           1 :   MOCK(get_options, mock_get_options);
    1519           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1520             : 
    1521             :   /* start gathering stats */
    1522           1 :   mock_options->DirReqStatistics = 1;
    1523           1 :   geoip_dirreq_stats_init(time(NULL));
    1524             : 
    1525           1 :   conn = new_dir_conn();
    1526           1 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    1527             :     GET("/tor/status-vote/current/consensus-ns"), NULL, 0));
    1528             : 
    1529           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    1530             :                       NULL, NULL, 1, 0);
    1531           1 :   tt_assert(header);
    1532           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
    1533             : 
    1534           1 :   stats = geoip_format_dirreq_stats(time(NULL));
    1535           1 :   tt_assert(stats);
    1536           1 :   tt_assert(strstr(stats, "not-found=8"));
    1537             : 
    1538           1 :   done:
    1539           1 :     UNMOCK(connection_write_to_buf_impl_);
    1540           1 :     UNMOCK(get_options);
    1541           1 :     connection_free_minimal(TO_CONN(conn));
    1542           1 :     tor_free(header);
    1543           1 :     tor_free(stats);
    1544           1 :     or_options_free(mock_options); mock_options = NULL;
    1545           1 : }
    1546             : 
    1547             : static void
    1548           1 : test_dir_handle_get_status_vote_current_consensus_too_old(void *data)
    1549             : {
    1550           1 :   dir_connection_t *conn = NULL;
    1551           1 :   char *header = NULL;
    1552           1 :   (void)data;
    1553             : 
    1554           1 :   mock_ns_val = tor_malloc_zero(sizeof(networkstatus_t));
    1555           1 :   mock_ns_val->type = NS_TYPE_CONSENSUS;
    1556           1 :   mock_ns_val->flavor = FLAV_MICRODESC;
    1557           1 :   mock_ns_val->valid_after = time(NULL) - (24 * 60 * 60 + 1800);
    1558           1 :   mock_ns_val->fresh_until = time(NULL) - (24 * 60 * 60 + 900);
    1559           1 :   mock_ns_val->valid_until = time(NULL) - (24 * 60 * 60 + 20);
    1560             : 
    1561             :   #define NETWORK_STATUS "some network status string"
    1562           1 :   consdiffmgr_add_consensus(NETWORK_STATUS, mock_ns_val);
    1563             : 
    1564           1 :   init_mock_options();
    1565             : 
    1566           1 :   MOCK(get_options, mock_get_options);
    1567           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1568           1 :   MOCK(networkstatus_get_latest_consensus_by_flavor, mock_ns_get_by_flavor);
    1569             : 
    1570           1 :   conn = new_dir_conn();
    1571             : 
    1572           1 :   setup_capture_of_logs(LOG_WARN);
    1573             : 
    1574           1 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    1575             :     GET("/tor/status-vote/current/consensus-microdesc"), NULL, 0));
    1576             : 
    1577           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    1578             :                       NULL, NULL, 1, 0);
    1579           1 :   tt_assert(header);
    1580           1 :   tt_str_op(TOO_OLD, OP_EQ, header);
    1581             : 
    1582           1 :   expect_log_msg_containing("too old");
    1583             : 
    1584           1 :   tor_free(header);
    1585           1 :   teardown_capture_of_logs();
    1586           1 :   tor_free(mock_ns_val);
    1587             : 
    1588           1 :   mock_ns_val = tor_malloc_zero(sizeof(networkstatus_t));
    1589           1 :   mock_ns_val->type = NS_TYPE_CONSENSUS;
    1590           1 :   mock_ns_val->flavor = FLAV_NS;
    1591           1 :   mock_ns_val->valid_after = time(NULL) - (24 * 60 * 60 + 1800);
    1592           1 :   mock_ns_val->fresh_until = time(NULL) - (24 * 60 * 60 + 900);
    1593           1 :   mock_ns_val->valid_until = time(NULL) - (24 * 60 * 60 + 20);
    1594             : 
    1595             :   #define NETWORK_STATUS "some network status string"
    1596           1 :   consdiffmgr_add_consensus(NETWORK_STATUS, mock_ns_val);
    1597             : 
    1598           1 :   setup_capture_of_logs(LOG_WARN);
    1599             : 
    1600           1 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    1601             :     GET("/tor/status-vote/current/consensus"), NULL, 0));
    1602             : 
    1603           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    1604             :                       NULL, NULL, 1, 0);
    1605           1 :   tt_assert(header);
    1606           1 :   tt_str_op(TOO_OLD, OP_EQ, header);
    1607             : 
    1608           1 :   expect_no_log_entry();
    1609             : 
    1610           1 :   done:
    1611           1 :     teardown_capture_of_logs();
    1612           1 :     UNMOCK(networkstatus_get_latest_consensus_by_flavor);
    1613           1 :     UNMOCK(connection_write_to_buf_impl_);
    1614           1 :     UNMOCK(get_options);
    1615           1 :     connection_free_minimal(TO_CONN(conn));
    1616           1 :     tor_free(header);
    1617           1 :     tor_free(mock_ns_val);
    1618           1 :     or_options_free(mock_options); mock_options = NULL;
    1619           1 : }
    1620             : 
    1621             : static int dhg_tests_geoip_get_country_by_addr(const tor_addr_t *addr);
    1622             : ATTR_UNUSED static int dhg_tests_geoip_get_country_by_addr_called = 0;
    1623             : 
    1624             : int
    1625           2 : dhg_tests_geoip_get_country_by_addr(const tor_addr_t *addr)
    1626             : {
    1627           2 :   (void)addr;
    1628           2 :   dhg_tests_geoip_get_country_by_addr_called++;
    1629           2 :   return 1;
    1630             : }
    1631             : 
    1632             : static void
    1633           2 : status_vote_current_consensus_ns_test(char **header, char **body,
    1634             :                                       size_t *body_len)
    1635             : {
    1636           2 :   dir_connection_t *conn = NULL;
    1637             : 
    1638             :   #define NETWORK_STATUS "some network status string"
    1639             : #if 0
    1640             :   common_digests_t digests;
    1641             :   uint8_t sha3[DIGEST256_LEN];
    1642             :   memset(&digests, 0x60, sizeof(digests));
    1643             :   memset(sha3, 0x06, sizeof(sha3));
    1644             :   dirserv_set_cached_consensus_networkstatus(NETWORK_STATUS, "ns", &digests,
    1645             :                                              sha3,
    1646             :                                              time(NULL));
    1647             : #endif /* 0 */
    1648           2 :   networkstatus_t *ns = tor_malloc_zero(sizeof(networkstatus_t));
    1649           2 :   ns->type = NS_TYPE_CONSENSUS;
    1650           2 :   ns->flavor = FLAV_NS;
    1651           2 :   ns->valid_after = time(NULL) - 1800;
    1652           2 :   ns->fresh_until = time(NULL) - 900;
    1653           2 :   ns->valid_until = time(NULL) - 60;
    1654           2 :   consdiffmgr_add_consensus(NETWORK_STATUS, ns);
    1655           2 :   networkstatus_vote_free(ns);
    1656             : 
    1657           2 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1658             : 
    1659           2 :   tt_assert(mock_options);
    1660           2 :   mock_options->DirReqStatistics = 1;
    1661           2 :   geoip_dirreq_stats_init(time(NULL));
    1662             : 
    1663             :   /* init geoip database */
    1664           2 :   geoip_parse_entry("10,50,AB", AF_INET);
    1665           2 :   tt_str_op("ab", OP_EQ, geoip_get_country_name(1));
    1666             : 
    1667           2 :   conn = new_dir_conn();
    1668             : 
    1669           2 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    1670             :     GET("/tor/status-vote/current/consensus-ns"), NULL, 0));
    1671             : 
    1672           2 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, header, MAX_HEADERS_SIZE,
    1673             :                       body, body_len, strlen(NETWORK_STATUS)+7, 0);
    1674             : 
    1675           2 :   done:
    1676           2 :     UNMOCK(connection_write_to_buf_impl_);
    1677           2 :     connection_free_minimal(TO_CONN(conn));
    1678           2 : }
    1679             : 
    1680             : static void
    1681           1 : test_dir_handle_get_status_vote_current_consensus_ns(void* data)
    1682             : {
    1683           1 :   char *header = NULL;
    1684           1 :   char *body = NULL, *comp_body = NULL;
    1685           1 :   size_t body_used = 0, comp_body_used = 0;
    1686           1 :   char *stats = NULL, *hist = NULL;
    1687           1 :   (void) data;
    1688             : 
    1689           1 :   dirserv_free_all();
    1690           1 :   clear_geoip_db();
    1691             : 
    1692           1 :   MOCK(geoip_get_country_by_addr,
    1693             :        dhg_tests_geoip_get_country_by_addr);
    1694           1 :   MOCK(get_options, mock_get_options);
    1695             : 
    1696           1 :   init_mock_options();
    1697             : 
    1698           1 :   status_vote_current_consensus_ns_test(&header, &comp_body, &comp_body_used);
    1699           1 :   tt_assert(header);
    1700             : 
    1701           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
    1702           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
    1703           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
    1704           1 :   tt_assert(strstr(header, "Pragma: no-cache\r\n"));
    1705             : 
    1706           1 :   compress_method_t compression = detect_compression_method(comp_body,
    1707             :                                                             comp_body_used);
    1708           1 :   tt_int_op(ZLIB_METHOD, OP_EQ, compression);
    1709             : 
    1710           1 :   tor_uncompress(&body, &body_used, comp_body, comp_body_used,
    1711             :                  compression, 0, LOG_PROTOCOL_WARN);
    1712             : 
    1713           1 :   tt_str_op(NETWORK_STATUS, OP_EQ, body);
    1714           1 :   tt_int_op(strlen(NETWORK_STATUS), OP_EQ, body_used);
    1715             : 
    1716           1 :   stats = geoip_format_dirreq_stats(time(NULL));
    1717           1 :   tt_assert(stats);
    1718             : 
    1719           1 :   tt_assert(strstr(stats, "ok=8"));
    1720           1 :   tt_assert(strstr(stats, "dirreq-v3-ips ab=8"));
    1721           1 :   tt_assert(strstr(stats, "dirreq-v3-reqs ab=8"));
    1722           1 :   tt_assert(strstr(stats, "dirreq-v3-direct-dl"
    1723             :                           " complete=0,timeout=0,running=4"));
    1724             : 
    1725           1 :   hist = geoip_get_request_history();
    1726           1 :   tt_assert(hist);
    1727           1 :   tt_str_op("ab=8", OP_EQ, hist);
    1728             : 
    1729           1 :   done:
    1730           1 :     UNMOCK(geoip_get_country_by_addr);
    1731           1 :     UNMOCK(get_options);
    1732           1 :     tor_free(header);
    1733           1 :     tor_free(comp_body);
    1734           1 :     tor_free(body);
    1735           1 :     tor_free(stats);
    1736           1 :     tor_free(hist);
    1737           1 :     or_options_free(mock_options); mock_options = NULL;
    1738             : 
    1739           1 :     dirserv_free_all();
    1740           1 :     clear_geoip_db();
    1741           1 : }
    1742             : 
    1743             : static void
    1744           1 : test_dir_handle_get_status_vote_current_consensus_ns_busy(void* data)
    1745             : {
    1746           1 :   char *header = NULL;
    1747           1 :   char *body = NULL;
    1748           1 :   size_t body_used = 0;
    1749           1 :   char *stats = NULL;
    1750           1 :   (void) data;
    1751             : 
    1752           1 :   dirserv_free_all();
    1753           1 :   clear_geoip_db();
    1754             : 
    1755           1 :   MOCK(get_options, mock_get_options);
    1756             : 
    1757             :   // Make it busy
    1758           1 :   init_mock_options();
    1759           1 :   mock_options->CountPrivateBandwidth = 1;
    1760             : 
    1761           1 :   status_vote_current_consensus_ns_test(&header, &body, &body_used);
    1762           1 :   tt_assert(header);
    1763             : 
    1764           1 :   tt_str_op(SERVER_BUSY, OP_EQ, header);
    1765             : 
    1766           1 :   stats = geoip_format_dirreq_stats(time(NULL));
    1767           1 :   tt_assert(stats);
    1768           1 :   tt_assert(strstr(stats, "busy=8"));
    1769             : 
    1770           1 :   done:
    1771           1 :     UNMOCK(get_options);
    1772           1 :     tor_free(header);
    1773           1 :     tor_free(body);
    1774           1 :     or_options_free(mock_options); mock_options = NULL;
    1775             : 
    1776           1 :     tor_free(stats);
    1777           1 :     dirserv_free_all();
    1778           1 :     clear_geoip_db();
    1779           1 : }
    1780             : 
    1781             : static void
    1782           1 : test_dir_handle_get_status_vote_current_not_found(void* data)
    1783             : {
    1784           1 :   dir_connection_t *conn = NULL;
    1785           1 :   char *header = NULL;
    1786           1 :   (void) data;
    1787             : 
    1788           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1789             : 
    1790           1 :   conn = new_dir_conn();
    1791           1 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    1792             :     GET("/tor/status-vote/current/" HEX1), NULL, 0));
    1793             : 
    1794           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    1795             :                       NULL, NULL, 1, 0);
    1796           1 :   tt_assert(header);
    1797           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
    1798             : 
    1799           1 :   done:
    1800           1 :     UNMOCK(connection_write_to_buf_impl_);
    1801           1 :     connection_free_minimal(TO_CONN(conn));
    1802           1 :     tor_free(header);
    1803           1 : }
    1804             : 
    1805             : /* What vote do we ask for, to get the vote in vote_descriptors.inc ? */
    1806             : #define VOTE_DIGEST "78400095d8e834d87135cfc46235c909f0e99911"
    1807             : 
    1808             : static void
    1809           2 : status_vote_current_d_test(char **header, char **body, size_t *body_l)
    1810             : {
    1811           2 :   dir_connection_t *conn = NULL;
    1812             : 
    1813           2 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1814             : 
    1815           2 :   conn = new_dir_conn();
    1816           2 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    1817             :     GET("/tor/status-vote/current/d/" VOTE_DIGEST), NULL, 0));
    1818             : 
    1819           2 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, header, MAX_HEADERS_SIZE,
    1820           2 :                       body, body_l, strlen(VOTE_BODY_V3)+1, 0);
    1821           2 :   tt_assert(header);
    1822             : 
    1823           2 :   done:
    1824           2 :     UNMOCK(connection_write_to_buf_impl_);
    1825           2 :     connection_free_minimal(TO_CONN(conn));
    1826           2 : }
    1827             : 
    1828             : static void
    1829           2 : status_vote_next_d_test(char **header, char **body, size_t *body_l)
    1830             : {
    1831           2 :   dir_connection_t *conn = NULL;
    1832             : 
    1833           2 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1834             : 
    1835           2 :   conn = new_dir_conn();
    1836           2 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    1837             :     GET("/tor/status-vote/next/d/" VOTE_DIGEST), NULL, 0));
    1838             : 
    1839           2 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, header, MAX_HEADERS_SIZE,
    1840           2 :                       body, body_l, strlen(VOTE_BODY_V3)+1, 0);
    1841           2 :   tt_assert(header);
    1842             : 
    1843           2 :   done:
    1844           2 :     UNMOCK(connection_write_to_buf_impl_);
    1845           2 :     connection_free_minimal(TO_CONN(conn));
    1846           2 : }
    1847             : 
    1848             : static void
    1849           1 : test_dir_handle_get_status_vote_current_d_not_found(void* data)
    1850             : {
    1851           1 :   char *header = NULL;
    1852           1 :   (void) data;
    1853             : 
    1854           1 :   status_vote_current_d_test(&header, NULL, NULL);
    1855             : 
    1856           1 :   tt_assert(header);
    1857           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
    1858             : 
    1859           1 :   done:
    1860           1 :     tor_free(header);
    1861           1 : }
    1862             : 
    1863             : static void
    1864           1 : test_dir_handle_get_status_vote_next_d_not_found(void* data)
    1865             : {
    1866           1 :   char *header = NULL;
    1867           1 :   (void) data;
    1868             : 
    1869           1 :   status_vote_next_d_test(&header, NULL, NULL);
    1870             : 
    1871           1 :   tt_assert(header);
    1872           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
    1873             : 
    1874           1 :   done:
    1875           1 :     UNMOCK(connection_write_to_buf_impl_);
    1876           1 :     tor_free(header);
    1877           1 : }
    1878             : 
    1879             : static void
    1880           1 : test_dir_handle_get_status_vote_d(void* data)
    1881             : {
    1882           1 :   char *header = NULL, *body = NULL;
    1883           1 :   size_t body_used = 0;
    1884           1 :   dir_server_t *ds = NULL;
    1885           1 :   const char digest[DIGEST_LEN] = "";
    1886           1 :   (void) data;
    1887             : 
    1888           1 :   MOCK(check_signature_token, mock_ignore_signature_token);
    1889           1 :   clear_dir_servers();
    1890           1 :   dirvote_free_all();
    1891             : 
    1892             :   /* create a trusted ds */
    1893           1 :   ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
    1894             :                               NULL, V3_DIRINFO, 1.0);
    1895           1 :   tt_assert(ds);
    1896           1 :   dir_server_add(ds);
    1897             : 
    1898             :   /* ds v3_identity_digest is the certificate's identity_key */
    1899           1 :   base16_decode(ds->v3_identity_digest, DIGEST_LEN,
    1900             :                 TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
    1901             : 
    1902           1 :   init_mock_options();
    1903           1 :   mock_options->AuthoritativeDir = 1;
    1904           1 :   mock_options->V3AuthoritativeDir = 1;
    1905           1 :   mock_options->TestingV3AuthVotingStartOffset = 0;
    1906           1 :   mock_options->TestingV3AuthInitialVotingInterval = 1;
    1907           1 :   mock_options->TestingV3AuthInitialVoteDelay = 1;
    1908           1 :   mock_options->TestingV3AuthInitialDistDelay = 1;
    1909             : 
    1910           1 :   time_t now = 1441223455 -1;
    1911           1 :   dirauth_sched_recalculate_timing(mock_options, now);
    1912             : 
    1913           1 :   const char *msg_out = NULL;
    1914           1 :   int status_out = 0;
    1915           1 :   struct pending_vote_t *pv = dirvote_add_vote(VOTE_BODY_V3, 0, "foo",
    1916             :                                                &msg_out, &status_out);
    1917           1 :   tt_assert(pv);
    1918             : 
    1919           1 :   status_vote_current_d_test(&header, &body, &body_used);
    1920             : 
    1921           1 :   tt_assert(header);
    1922           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
    1923           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
    1924           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
    1925           1 :   tt_assert(strstr(header, "Content-Length: 4403\r\n"));
    1926             : 
    1927           1 :   tt_str_op(VOTE_BODY_V3, OP_EQ, body);
    1928             : 
    1929           1 :   tor_free(header);
    1930           1 :   tor_free(body);
    1931             : 
    1932           1 :   status_vote_next_d_test(&header, &body, &body_used);
    1933             : 
    1934           1 :   tt_assert(header);
    1935           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
    1936           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
    1937           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
    1938           1 :   tt_assert(strstr(header, "Content-Length: 4403\r\n"));
    1939             : 
    1940           1 :   tt_str_op(VOTE_BODY_V3, OP_EQ, body);
    1941             : 
    1942           1 :   done:
    1943           1 :     UNMOCK(check_signature_token);
    1944           1 :     tor_free(header);
    1945           1 :     tor_free(body);
    1946           1 :     or_options_free(mock_options); mock_options = NULL;
    1947             : 
    1948           1 :     clear_dir_servers();
    1949           1 :     dirvote_free_all();
    1950           1 :     routerlist_free_all();
    1951           1 : }
    1952             : 
    1953             : static void
    1954           1 : test_dir_handle_get_status_vote_next_not_found(void* data)
    1955             : {
    1956           1 :   dir_connection_t *conn = NULL;
    1957           1 :   char *header = NULL;
    1958           1 :   (void) data;
    1959             : 
    1960           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1961             : 
    1962           1 :   conn = new_dir_conn();
    1963           1 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    1964             :     GET("/tor/status-vote/next/" HEX1), NULL, 0));
    1965             : 
    1966           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    1967             :                       NULL, NULL, 1, 0);
    1968           1 :   tt_assert(header);
    1969           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
    1970             : 
    1971           1 :   done:
    1972           1 :     UNMOCK(connection_write_to_buf_impl_);
    1973           1 :     connection_free_minimal(TO_CONN(conn));
    1974           1 :     tor_free(header);
    1975           1 : }
    1976             : 
    1977             : static void
    1978           3 : status_vote_next_consensus_test(char **header, char **body, size_t *body_used)
    1979             : {
    1980           3 :   dir_connection_t *conn = NULL;
    1981             : 
    1982           3 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    1983             : 
    1984           3 :   conn = new_dir_conn();
    1985           3 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    1986             :     GET("/tor/status-vote/next/consensus"), NULL, 0));
    1987             : 
    1988           3 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, header, MAX_HEADERS_SIZE,
    1989             :                       body, body_used, 18, 0);
    1990           3 :   done:
    1991           3 :     UNMOCK(connection_write_to_buf_impl_);
    1992           3 :     connection_free_minimal(TO_CONN(conn));
    1993           3 : }
    1994             : 
    1995             : static void
    1996           1 : test_dir_handle_get_status_vote_next_consensus_not_found(void* data)
    1997             : {
    1998           1 :   char *header = NULL, *body = NULL;
    1999           1 :   size_t body_used;
    2000           1 :   (void) data;
    2001             : 
    2002           1 :   status_vote_next_consensus_test(&header, &body, &body_used);
    2003             : 
    2004           1 :   tt_assert(header);
    2005           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
    2006             : 
    2007           1 :   done:
    2008           1 :     tor_free(header);
    2009           1 :     tor_free(body);
    2010           1 : }
    2011             : 
    2012             : static void
    2013           1 : test_dir_handle_get_status_vote_current_authority_not_found(void* data)
    2014             : {
    2015           1 :   dir_connection_t *conn = NULL;
    2016           1 :   char *header = NULL;
    2017           1 :   (void) data;
    2018             : 
    2019           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    2020           1 :   MOCK(check_signature_token, mock_ignore_signature_token);
    2021             : 
    2022           1 :   conn = new_dir_conn();
    2023           1 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    2024             :     GET("/tor/status-vote/current/authority"), NULL, 0));
    2025             : 
    2026           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    2027             :                       NULL, NULL, 1, 0);
    2028           1 :   tt_assert(header);
    2029           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
    2030             : 
    2031           1 :   done:
    2032           1 :     UNMOCK(check_signature_token);
    2033           1 :     UNMOCK(connection_write_to_buf_impl_);
    2034           1 :     connection_free_minimal(TO_CONN(conn));
    2035           1 :     tor_free(header);
    2036           1 : }
    2037             : 
    2038             : static void
    2039           1 : test_dir_handle_get_status_vote_next_authority_not_found(void* data)
    2040             : {
    2041           1 :   dir_connection_t *conn = NULL;
    2042           1 :   char *header = NULL;
    2043           1 :   (void) data;
    2044             : 
    2045           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    2046           1 :   MOCK(check_signature_token, mock_ignore_signature_token);
    2047             : 
    2048           1 :   conn = new_dir_conn();
    2049           1 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    2050             :     GET("/tor/status-vote/next/authority"), NULL, 0));
    2051             : 
    2052           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    2053             :                       NULL, NULL, 1, 0);
    2054           1 :   tt_assert(header);
    2055           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
    2056             : 
    2057           1 :   done:
    2058           1 :     UNMOCK(check_signature_token);
    2059           1 :     UNMOCK(connection_write_to_buf_impl_);
    2060           1 :     connection_free_minimal(TO_CONN(conn));
    2061           1 :     tor_free(header);
    2062           1 : }
    2063             : 
    2064             : static void
    2065           1 : test_dir_handle_get_status_vote_next_bandwidth_not_found(void* data)
    2066             : {
    2067           1 :   dir_connection_t *conn = NULL;
    2068           1 :   char *header = NULL;
    2069           1 :   (void) data;
    2070             : 
    2071           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    2072           1 :   MOCK(check_signature_token, mock_ignore_signature_token);
    2073           1 :   conn = new_dir_conn();
    2074             : 
    2075           1 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    2076             :     GET("/tor/status-vote/next/bandwdith"), NULL, 0));
    2077             : 
    2078           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    2079             :                       NULL, NULL, 1, 0);
    2080           1 :   tt_assert(header);
    2081           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
    2082             : 
    2083           1 :   done:
    2084           1 :     UNMOCK(check_signature_token);
    2085           1 :     UNMOCK(connection_write_to_buf_impl_);
    2086           1 :     connection_free_minimal(TO_CONN(conn));
    2087           1 :     tor_free(header);
    2088           1 : }
    2089             : 
    2090             : static const char* dhg_tests_dirvote_get_pending_consensus(
    2091             :                                            consensus_flavor_t flav);
    2092             : 
    2093             : const char*
    2094           2 : dhg_tests_dirvote_get_pending_consensus(consensus_flavor_t flav)
    2095             : {
    2096           2 :   (void)flav;
    2097           2 :   return "pending consensus";
    2098             : }
    2099             : 
    2100             : static void
    2101           1 : test_dir_handle_get_status_vote_next_consensus(void* data)
    2102             : {
    2103           1 :   char *header = NULL, *body = NULL;
    2104           1 :   size_t body_used = 0;
    2105           1 :   (void) data;
    2106             : 
    2107           1 :   MOCK(dirvote_get_pending_consensus,
    2108             :        dhg_tests_dirvote_get_pending_consensus);
    2109             : 
    2110           1 :   status_vote_next_consensus_test(&header, &body, &body_used);
    2111           1 :   tt_assert(header);
    2112             : 
    2113           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
    2114           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
    2115           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
    2116           1 :   tt_assert(strstr(header, "Content-Length: 17\r\n"));
    2117             : 
    2118           1 :   tt_str_op("pending consensus", OP_EQ, body);
    2119             : 
    2120           1 :   done:
    2121           1 :     UNMOCK(dirvote_get_pending_consensus);
    2122           1 :     tor_free(header);
    2123           1 :     tor_free(body);
    2124           1 : }
    2125             : 
    2126             : static void
    2127           1 : test_dir_handle_get_status_vote_next_consensus_busy(void* data)
    2128             : {
    2129           1 :   char *header = NULL, *body = NULL;
    2130           1 :   size_t body_used = 0;
    2131           1 :   (void) data;
    2132             : 
    2133           1 :   MOCK(get_options, mock_get_options);
    2134           1 :   MOCK(dirvote_get_pending_consensus,
    2135             :        dhg_tests_dirvote_get_pending_consensus);
    2136             : 
    2137             :   //Make it busy
    2138           1 :   init_mock_options();
    2139           1 :   mock_options->CountPrivateBandwidth = 1;
    2140             : 
    2141           1 :   status_vote_next_consensus_test(&header, &body, &body_used);
    2142             : 
    2143           1 :   tt_assert(header);
    2144           1 :   tt_str_op(SERVER_BUSY, OP_EQ, header);
    2145             : 
    2146           1 :   done:
    2147           1 :     UNMOCK(dirvote_get_pending_consensus);
    2148           1 :     UNMOCK(get_options);
    2149           1 :     tor_free(header);
    2150           1 :     tor_free(body);
    2151           1 :     or_options_free(mock_options); mock_options = NULL;
    2152           1 : }
    2153             : 
    2154             : static void
    2155           3 : status_vote_next_consensus_signatures_test(char **header, char **body,
    2156             :                                            size_t *body_used)
    2157             : {
    2158           3 :   dir_connection_t *conn = NULL;
    2159             : 
    2160           3 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    2161             : 
    2162           3 :   conn = new_dir_conn();
    2163           3 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    2164             :     GET("/tor/status-vote/next/consensus-signatures"), NULL, 0));
    2165             : 
    2166           3 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, header, MAX_HEADERS_SIZE,
    2167             :                       body, body_used, 22, 0);
    2168             : 
    2169           3 :   done:
    2170           3 :     connection_free_minimal(TO_CONN(conn));
    2171           3 :     UNMOCK(connection_write_to_buf_impl_);
    2172           3 : }
    2173             : 
    2174             : static void
    2175           1 : test_dir_handle_get_status_vote_next_consensus_signatures_not_found(void* data)
    2176             : {
    2177           1 :   char *header = NULL, *body = NULL;
    2178           1 :   size_t body_used;
    2179           1 :   (void) data;
    2180             : 
    2181           1 :   status_vote_next_consensus_signatures_test(&header, &body, &body_used);
    2182             : 
    2183           1 :   tt_assert(header);
    2184           1 :   tt_str_op(NOT_FOUND, OP_EQ, header);
    2185             : 
    2186           1 :   done:
    2187           1 :     tor_free(header);
    2188           1 :     tor_free(body);
    2189           1 : }
    2190             : 
    2191             : static const char* dhg_tests_dirvote_get_pending_detached_signatures(void);
    2192             : 
    2193             : const char*
    2194           2 : dhg_tests_dirvote_get_pending_detached_signatures(void)
    2195             : {
    2196           2 :   return "pending detached sigs";
    2197             : }
    2198             : 
    2199             : static void
    2200           1 : test_dir_handle_get_status_vote_next_consensus_signatures(void* data)
    2201             : {
    2202           1 :   char *header = NULL, *body = NULL;
    2203           1 :   size_t body_used = 0;
    2204           1 :   (void) data;
    2205             : 
    2206           1 :   MOCK(dirvote_get_pending_detached_signatures,
    2207             :        dhg_tests_dirvote_get_pending_detached_signatures);
    2208             : 
    2209           1 :   status_vote_next_consensus_signatures_test(&header, &body, &body_used);
    2210           1 :   tt_assert(header);
    2211             : 
    2212           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
    2213           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
    2214           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
    2215           1 :   tt_assert(strstr(header, "Content-Length: 21\r\n"));
    2216             : 
    2217           1 :   tt_str_op("pending detached sigs", OP_EQ, body);
    2218             : 
    2219           1 :   done:
    2220           1 :     UNMOCK(dirvote_get_pending_detached_signatures);
    2221           1 :     tor_free(header);
    2222           1 :     tor_free(body);
    2223           1 : }
    2224             : 
    2225             : static void
    2226           1 : test_dir_handle_get_status_vote_next_consensus_signatures_busy(void* data)
    2227             : {
    2228           1 :   char *header = NULL, *body = NULL;
    2229           1 :   size_t body_used;
    2230           1 :   (void) data;
    2231             : 
    2232           1 :   MOCK(dirvote_get_pending_detached_signatures,
    2233             :        dhg_tests_dirvote_get_pending_detached_signatures);
    2234           1 :   MOCK(get_options, mock_get_options);
    2235             : 
    2236             :   //Make it busy
    2237           1 :   init_mock_options();
    2238           1 :   mock_options->CountPrivateBandwidth = 1;
    2239             : 
    2240           1 :   status_vote_next_consensus_signatures_test(&header, &body, &body_used);
    2241             : 
    2242           1 :   tt_assert(header);
    2243           1 :   tt_str_op(SERVER_BUSY, OP_EQ, header);
    2244             : 
    2245           1 :   done:
    2246           1 :     UNMOCK(get_options);
    2247           1 :     UNMOCK(dirvote_get_pending_detached_signatures);
    2248           1 :     tor_free(header);
    2249           1 :     tor_free(body);
    2250           1 :     or_options_free(mock_options); mock_options = NULL;
    2251           1 : }
    2252             : 
    2253             : static void
    2254           1 : test_dir_handle_get_status_vote_next_authority(void* data)
    2255             : {
    2256           1 :   dir_connection_t *conn = NULL;
    2257           1 :   char *header = NULL, *body = NULL;
    2258           1 :   const char *msg_out = NULL;
    2259           1 :   int status_out = 0;
    2260           1 :   size_t body_used = 0;
    2261           1 :   dir_server_t *ds = NULL;
    2262           1 :   const char digest[DIGEST_LEN] = "";
    2263           1 :   (void) data;
    2264             : 
    2265           1 :   MOCK(check_signature_token, mock_ignore_signature_token);
    2266           1 :   clear_dir_servers();
    2267           1 :   routerlist_free_all();
    2268           1 :   dirvote_free_all();
    2269             : 
    2270           1 :   mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE,
    2271             :                                                strlen(TEST_CERTIFICATE),
    2272             :                                                NULL);
    2273             : 
    2274             :   /* create a trusted ds */
    2275           1 :   ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
    2276             :                               NULL, V3_DIRINFO, 1.0);
    2277           1 :   tt_assert(ds);
    2278           1 :   dir_server_add(ds);
    2279             : 
    2280             :   /* ds v3_identity_digest is the certificate's identity_key */
    2281           1 :   base16_decode(ds->v3_identity_digest, DIGEST_LEN,
    2282             :                 TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
    2283           1 :   tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
    2284             :     TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
    2285             : 
    2286           1 :   init_mock_options();
    2287           1 :   mock_options->AuthoritativeDir = 1;
    2288           1 :   mock_options->V3AuthoritativeDir = 1;
    2289           1 :   mock_options->TestingV3AuthVotingStartOffset = 0;
    2290           1 :   mock_options->TestingV3AuthInitialVotingInterval = 1;
    2291           1 :   mock_options->TestingV3AuthInitialVoteDelay = 1;
    2292           1 :   mock_options->TestingV3AuthInitialDistDelay = 1;
    2293             : 
    2294           1 :   time_t now = 1441223455 -1;
    2295           1 :   dirauth_sched_recalculate_timing(mock_options, now);
    2296             : 
    2297           1 :   struct pending_vote_t *vote = dirvote_add_vote(VOTE_BODY_V3, 0, "foo",
    2298             :                                                  &msg_out, &status_out);
    2299           1 :   tt_assert(vote);
    2300             : 
    2301           1 :   MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
    2302           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    2303             : 
    2304           1 :   conn = new_dir_conn();
    2305           1 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    2306             :     GET("/tor/status-vote/next/authority"), NULL, 0));
    2307             : 
    2308           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    2309           1 :                       &body, &body_used, strlen(VOTE_BODY_V3)+1, 0);
    2310             : 
    2311           1 :   tt_assert(header);
    2312           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
    2313           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
    2314           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
    2315           1 :   tt_assert(strstr(header, "Content-Length: 4403\r\n"));
    2316             : 
    2317           1 :   tt_str_op(VOTE_BODY_V3, OP_EQ, body);
    2318             : 
    2319           1 :   done:
    2320           1 :     UNMOCK(check_signature_token);
    2321           1 :     UNMOCK(connection_write_to_buf_impl_);
    2322           1 :     UNMOCK(get_my_v3_authority_cert);
    2323           1 :     connection_free_minimal(TO_CONN(conn));
    2324           1 :     tor_free(header);
    2325           1 :     tor_free(body);
    2326           1 :     authority_cert_free(mock_cert); mock_cert = NULL;
    2327           1 :     or_options_free(mock_options); mock_options = NULL;
    2328             : 
    2329           1 :     clear_dir_servers();
    2330           1 :     routerlist_free_all();
    2331           1 :     dirvote_free_all();
    2332           1 : }
    2333             : 
    2334             : static void
    2335           1 : test_dir_handle_get_status_vote_next_bandwidth(void* data)
    2336             : {
    2337           1 :   dir_connection_t *conn = NULL;
    2338           1 :   char *header = NULL, *body = NULL;
    2339           1 :   size_t body_used = 0;
    2340           1 :   (void) data;
    2341             : 
    2342           1 :   const char *content =
    2343             :     "1541171221\n"
    2344             :     "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A27F80 "
    2345             :     "master_key_ed25519=YaqV4vbvPYKucElk297eVdNArDz9HtIwUoIeo0+cVIpQ "
    2346             :     "bw=760 nick=Test time=2018-05-08T16:13:26\n";
    2347             : 
    2348           1 :   init_mock_options();
    2349           1 :   MOCK(get_options, mock_get_options);
    2350           1 :   mock_options->V3BandwidthsFile = tor_strdup(
    2351             :     get_fname_rnd("V3BandwidthsFile")
    2352             :   );
    2353             : 
    2354           1 :   write_str_to_file(mock_options->V3BandwidthsFile, content, 0);
    2355             : 
    2356           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    2357             : 
    2358           1 :   conn = new_dir_conn();
    2359           1 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    2360             :     GET("/tor/status-vote/next/bandwidth"), NULL, 0));
    2361             : 
    2362           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    2363             :                       &body, &body_used, strlen(content)+1, 0);
    2364             : 
    2365           1 :   tt_assert(header);
    2366           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
    2367           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
    2368           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
    2369           1 :   tt_assert(strstr(header, "Content-Length: 167\r\n"));
    2370             : 
    2371             :   /* Check cache lifetime */
    2372           1 :   char expbuf[RFC1123_TIME_LEN+1];
    2373           1 :   time_t now = approx_time();
    2374             :   /* BANDWIDTH_CACHE_LIFETIME is defined in dircache.c. */
    2375           1 :   format_rfc1123_time(expbuf, (time_t)(now + 30*60));
    2376           1 :   char *expires = NULL;
    2377             :   /* Change to 'Cache-control: max-age=%d' if using http/1.1. */
    2378           1 :   tor_asprintf(&expires, "Expires: %s\r\n", expbuf);
    2379           1 :   tt_assert(strstr(header, expires));
    2380             : 
    2381           1 :   tt_int_op(body_used, OP_EQ, strlen(body));
    2382           1 :   tt_str_op(content, OP_EQ, body);
    2383             : 
    2384           1 :   tor_free(header);
    2385           1 :   tor_free(body);
    2386             : 
    2387             :   /* Request the file using compression, the result should be the same. */
    2388           1 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    2389             :     GET("/tor/status-vote/next/bandwidth.z"), NULL, 0));
    2390             : 
    2391           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    2392             :                       &body, &body_used, strlen(content)+1, 0);
    2393             : 
    2394           1 :   tt_assert(header);
    2395           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
    2396           1 :   tt_assert(strstr(header, "Content-Encoding: deflate\r\n"));
    2397             : 
    2398             :   /* Since using connection_write_to_buf_mock instead of mocking
    2399             :    * connection_buf_add_compress, the content is not actually compressed.
    2400             :    * If it would, the size and content would be different than the original.
    2401             :   */
    2402             : 
    2403           1 :  done:
    2404           1 :   UNMOCK(get_options);
    2405           1 :   UNMOCK(connection_write_to_buf_impl_);
    2406           1 :   connection_free_minimal(TO_CONN(conn));
    2407           1 :   tor_free(header);
    2408           1 :   tor_free(body);
    2409           1 :   tor_free(expires);
    2410           1 :   or_options_free(mock_options);
    2411           1 : }
    2412             : 
    2413             : static void
    2414           1 : test_dir_handle_get_status_vote_current_authority(void* data)
    2415             : {
    2416           1 :   dir_connection_t *conn = NULL;
    2417           1 :   char *header = NULL, *body = NULL;
    2418           1 :   const char *msg_out = NULL;
    2419           1 :   int status_out = 0;
    2420           1 :   size_t body_used = 0;
    2421           1 :   const char digest[DIGEST_LEN] = "";
    2422             : 
    2423           1 :   dir_server_t *ds = NULL;
    2424           1 :   (void) data;
    2425             : 
    2426           1 :   MOCK(check_signature_token, mock_ignore_signature_token);
    2427           1 :   clear_dir_servers();
    2428           1 :   routerlist_free_all();
    2429           1 :   dirvote_free_all();
    2430             : 
    2431           1 :   mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE,
    2432             :                                                strlen(TEST_CERTIFICATE),
    2433             :                                                NULL);
    2434             : 
    2435             :   /* create a trusted ds */
    2436           1 :   ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
    2437             :                               NULL, V3_DIRINFO, 1.0);
    2438           1 :   tt_assert(ds);
    2439           1 :   dir_server_add(ds);
    2440             : 
    2441             :   /* ds v3_identity_digest is the certificate's identity_key */
    2442           1 :   base16_decode(ds->v3_identity_digest, DIGEST_LEN,
    2443             :                 TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
    2444             : 
    2445           1 :   tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
    2446             :     TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
    2447             : 
    2448           1 :   init_mock_options();
    2449           1 :   mock_options->AuthoritativeDir = 1;
    2450           1 :   mock_options->V3AuthoritativeDir = 1;
    2451           1 :   mock_options->TestingV3AuthVotingStartOffset = 0;
    2452           1 :   mock_options->TestingV3AuthInitialVotingInterval = 1;
    2453           1 :   mock_options->TestingV3AuthInitialVoteDelay = 1;
    2454           1 :   mock_options->TestingV3AuthInitialDistDelay = 1;
    2455             : 
    2456           1 :   time_t now = 1441223455;
    2457           1 :   dirauth_sched_recalculate_timing(mock_options, now-1);
    2458             : 
    2459           1 :   struct pending_vote_t *vote = dirvote_add_vote(VOTE_BODY_V3, 0, "foo",
    2460             :                                                  &msg_out, &status_out);
    2461           1 :   tt_assert(vote);
    2462             : 
    2463             :   // move the pending vote to previous vote
    2464           1 :   dirvote_act(mock_options, now+1);
    2465             : 
    2466           1 :   MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
    2467           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    2468             : 
    2469           1 :   conn = new_dir_conn();
    2470           1 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    2471             :     GET("/tor/status-vote/current/authority"), NULL, 0));
    2472             : 
    2473           1 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    2474           1 :                       &body, &body_used, strlen(VOTE_BODY_V3)+1, 0);
    2475             : 
    2476           1 :   tt_assert(header);
    2477           1 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
    2478           1 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
    2479           1 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
    2480           1 :   tt_assert(strstr(header, "Content-Length: 4403\r\n"));
    2481             : 
    2482           1 :   tt_str_op(VOTE_BODY_V3, OP_EQ, body);
    2483             : 
    2484           1 :   done:
    2485           1 :     UNMOCK(check_signature_token);
    2486           1 :     UNMOCK(connection_write_to_buf_impl_);
    2487           1 :     UNMOCK(get_my_v3_authority_cert);
    2488           1 :     connection_free_minimal(TO_CONN(conn));
    2489           1 :     tor_free(header);
    2490           1 :     tor_free(body);
    2491           1 :     authority_cert_free(mock_cert); mock_cert = NULL;
    2492           1 :     or_options_free(mock_options); mock_options = NULL;
    2493             : 
    2494           1 :     clear_dir_servers();
    2495           1 :     routerlist_free_all();
    2496           1 :     dirvote_free_all();
    2497           1 : }
    2498             : 
    2499             : /* Test that a late vote is rejected, but an on-time vote is accepted. */
    2500             : static void
    2501           4 : test_dir_handle_get_status_vote_too_late(void* data)
    2502             : {
    2503           4 :   dir_connection_t *conn = NULL;
    2504           4 :   char *header = NULL, *body = NULL;
    2505           4 :   const char *msg_out = NULL;
    2506           4 :   int status_out = 0;
    2507           4 :   size_t body_used = 0;
    2508           4 :   const char digest[DIGEST_LEN] = "";
    2509             : 
    2510           4 :   dir_server_t *ds = NULL;
    2511           4 :   const char* mode = (const char *)data;
    2512             : 
    2513           4 :   MOCK(check_signature_token, mock_ignore_signature_token);
    2514           4 :   clear_dir_servers();
    2515           4 :   routerlist_free_all();
    2516           4 :   dirvote_free_all();
    2517             : 
    2518           4 :   mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE,
    2519             :                                                strlen(TEST_CERTIFICATE),
    2520             :                                                NULL);
    2521             : 
    2522             :   /* create a trusted ds */
    2523           4 :   ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
    2524             :                               NULL, V3_DIRINFO, 1.0);
    2525           4 :   tt_assert(ds);
    2526           4 :   dir_server_add(ds);
    2527             : 
    2528             :   /* ds v3_identity_digest is the certificate's identity_key */
    2529           4 :   base16_decode(ds->v3_identity_digest, DIGEST_LEN,
    2530             :                 TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
    2531             : 
    2532           4 :   tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
    2533             :     TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
    2534             : 
    2535           4 :   init_mock_options();
    2536           4 :   mock_options->AuthoritativeDir = 1;
    2537           4 :   mock_options->V3AuthoritativeDir = 1;
    2538             : 
    2539           4 :   int base_delay = 0;
    2540           4 :   int vote_interval = 0;
    2541           4 :   int start_offset = 0;
    2542             : 
    2543           4 :   tt_assert(mode);
    2544             :   /* Set the required timings, see below for details */
    2545           4 :   if (strcmp(mode, "min") == 0) {
    2546             :     /* The minimum valid test network timing */
    2547             :     base_delay = 2;
    2548             :     vote_interval = 10;
    2549             :     start_offset = vote_interval - 5;
    2550           3 :   } else if (strcmp(mode, "chutney") == 0) {
    2551             :     /* The test network timing used by chutney */
    2552             :     base_delay = 4;
    2553             :     vote_interval = 20;
    2554             :     start_offset = vote_interval - 5;
    2555           2 :   } else if (strcmp(mode, "half-public") == 0) {
    2556             :     /* The short consensus failure timing used in the public network */
    2557             :     base_delay = 5*60;
    2558             :     vote_interval = 30*60;
    2559             :     start_offset = vote_interval - 9*60 - 5;
    2560           1 :   } else if (strcmp(mode, "public") == 0) {
    2561             :     /* The standard timing used in the public network */
    2562           1 :     base_delay = 5*60;
    2563           1 :     vote_interval = 60*60;
    2564           1 :     start_offset = vote_interval - 9*60 - 5;
    2565             :   }
    2566             : 
    2567           4 :   tt_assert(base_delay > 0);
    2568           4 :   tt_assert(vote_interval > 0);
    2569           4 :   tt_assert(start_offset > 0);
    2570             : 
    2571             :   /* Skew the time to fit the fixed time in the vote */
    2572           4 :   mock_options->TestingV3AuthVotingStartOffset = start_offset;
    2573             :   /* Calculate the rest of the timings */
    2574           4 :   mock_options->TestingV3AuthInitialVotingInterval = vote_interval;
    2575           4 :   mock_options->TestingV3AuthInitialVoteDelay = base_delay;
    2576           4 :   mock_options->TestingV3AuthInitialDistDelay = base_delay;
    2577             : 
    2578           4 :   time_t now = 1441223455;
    2579           4 :   dirauth_sched_recalculate_timing(mock_options, now-1);
    2580           4 :   const time_t voting_starts = voting_schedule.voting_starts;
    2581           4 :   const time_t fetch_missing = voting_schedule.fetch_missing_votes;
    2582             : 
    2583           4 :   struct pending_vote_t *vote = NULL;
    2584             : 
    2585             :   /* Next voting interval */
    2586           4 :   vote = dirvote_add_vote(VOTE_BODY_V3,
    2587             :                           fetch_missing + vote_interval, "foo",
    2588             :                           &msg_out, &status_out);
    2589           4 :   tt_assert(!vote);
    2590           4 :   tt_int_op(status_out, OP_EQ, 400);
    2591           4 :   tt_str_op(msg_out, OP_EQ,
    2592             :             "Posted vote received too late, would be dangerous to count it");
    2593             : 
    2594             :   /* Just after fetch missing */
    2595           4 :   vote = dirvote_add_vote(VOTE_BODY_V3,
    2596             :                           fetch_missing + 1, "foo",
    2597             :                           &msg_out, &status_out);
    2598           4 :   tt_assert(!vote);
    2599           4 :   tt_int_op(status_out, OP_EQ, 400);
    2600           4 :   tt_str_op(msg_out, OP_EQ,
    2601             :             "Posted vote received too late, would be dangerous to count it");
    2602             : 
    2603             :   /* On fetch missing */
    2604           4 :   vote = dirvote_add_vote(VOTE_BODY_V3,
    2605             :                           fetch_missing, "foo",
    2606             :                           &msg_out, &status_out);
    2607           4 :   tt_assert(vote);
    2608             : 
    2609             :   /* Move the pending vote to previous vote */
    2610           4 :   dirvote_act(mock_options, now+1);
    2611             :   /* And reset the timing */
    2612           4 :   dirauth_sched_recalculate_timing(mock_options, now-1);
    2613             : 
    2614             :   /* Between voting starts and fetch missing */
    2615           4 :   vote = dirvote_add_vote(VOTE_BODY_V3,
    2616             :                           voting_starts + 1, "foo",
    2617             :                           &msg_out, &status_out);
    2618           4 :   tt_assert(vote);
    2619             : 
    2620             :   /* Move the pending vote to previous vote */
    2621           4 :   dirvote_act(mock_options, now+1);
    2622             :   /* And reset the timing */
    2623           4 :   dirauth_sched_recalculate_timing(mock_options, now-1);
    2624             : 
    2625             :   /* On voting starts */
    2626           4 :   vote = dirvote_add_vote(VOTE_BODY_V3,
    2627             :                           voting_starts, "foo",
    2628             :                           &msg_out, &status_out);
    2629           4 :   tt_assert(vote);
    2630             : 
    2631             :   /* Move the pending vote to previous vote */
    2632           4 :   dirvote_act(mock_options, now+1);
    2633             :   /* And reset the timing */
    2634           4 :   dirauth_sched_recalculate_timing(mock_options, now-1);
    2635             : 
    2636             :   /* Just before voting starts */
    2637           4 :   vote = dirvote_add_vote(VOTE_BODY_V3,
    2638             :                           voting_starts - 1, "foo",
    2639             :                           &msg_out, &status_out);
    2640           4 :   tt_assert(vote);
    2641             : 
    2642             :   /* Move the pending vote to previous vote */
    2643           4 :   dirvote_act(mock_options, now+1);
    2644             : 
    2645           4 :   MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
    2646           4 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    2647             : 
    2648           4 :   conn = new_dir_conn();
    2649           4 :   tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
    2650             :     GET("/tor/status-vote/current/authority"), NULL, 0));
    2651             : 
    2652           4 :   fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
    2653           4 :                       &body, &body_used, strlen(VOTE_BODY_V3)+1, 0);
    2654             : 
    2655           4 :   tt_assert(header);
    2656           4 :   tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
    2657           4 :   tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
    2658           4 :   tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
    2659           4 :   tt_assert(strstr(header, "Content-Length: 4403\r\n"));
    2660             : 
    2661           4 :   tt_str_op(VOTE_BODY_V3, OP_EQ, body);
    2662             : 
    2663           4 :   done:
    2664           4 :     UNMOCK(check_signature_token);
    2665           4 :     UNMOCK(connection_write_to_buf_impl_);
    2666           4 :     UNMOCK(get_my_v3_authority_cert);
    2667           4 :     connection_free_minimal(TO_CONN(conn));
    2668           4 :     tor_free(header);
    2669           4 :     tor_free(body);
    2670           4 :     authority_cert_free(mock_cert); mock_cert = NULL;
    2671           4 :     or_options_free(mock_options); mock_options = NULL;
    2672             : 
    2673           4 :     clear_dir_servers();
    2674           4 :     routerlist_free_all();
    2675           4 :     dirvote_free_all();
    2676           4 : }
    2677             : 
    2678             : static void
    2679           1 : test_dir_handle_get_parse_accept_encoding(void *arg)
    2680             : {
    2681           1 :   (void)arg;
    2682           1 :   const unsigned B_NONE = 1u << NO_METHOD;
    2683           1 :   const unsigned B_ZLIB = 1u << ZLIB_METHOD;
    2684           1 :   const unsigned B_GZIP = 1u << GZIP_METHOD;
    2685           1 :   const unsigned B_LZMA = 1u << LZMA_METHOD;
    2686           1 :   const unsigned B_ZSTD = 1u << ZSTD_METHOD;
    2687             : 
    2688           1 :   unsigned encodings;
    2689             : 
    2690           1 :   encodings = parse_accept_encoding_header("");
    2691           1 :   tt_uint_op(B_NONE, OP_EQ, encodings);
    2692             : 
    2693           1 :   encodings = parse_accept_encoding_header("  ");
    2694           1 :   tt_uint_op(B_NONE, OP_EQ, encodings);
    2695             : 
    2696           1 :   encodings = parse_accept_encoding_header("dewey, cheatham, and howe ");
    2697           1 :   tt_uint_op(B_NONE, OP_EQ, encodings);
    2698             : 
    2699           1 :   encodings = parse_accept_encoding_header("dewey, cheatham, and gzip");
    2700           1 :   tt_uint_op(B_NONE, OP_EQ, encodings);
    2701             : 
    2702           1 :   encodings = parse_accept_encoding_header("dewey, cheatham, and, gzip");
    2703           1 :   tt_uint_op(B_NONE|B_GZIP, OP_EQ, encodings);
    2704             : 
    2705           1 :   encodings = parse_accept_encoding_header(" gzip");
    2706           1 :   tt_uint_op(B_NONE|B_GZIP, OP_EQ, encodings);
    2707             : 
    2708           1 :   encodings = parse_accept_encoding_header("gzip");
    2709           1 :   tt_uint_op(B_NONE|B_GZIP, OP_EQ, encodings);
    2710             : 
    2711           1 :   encodings = parse_accept_encoding_header("x-zstd, deflate, x-tor-lzma");
    2712           1 :   tt_uint_op(B_NONE|B_ZLIB|B_ZSTD|B_LZMA, OP_EQ, encodings);
    2713             : 
    2714           1 :   encodings = parse_accept_encoding_header(
    2715             :                                         "x-zstd, deflate, x-tor-lzma, gzip");
    2716           1 :   tt_uint_op(B_NONE|B_ZLIB|B_ZSTD|B_LZMA|B_GZIP, OP_EQ, encodings);
    2717             : 
    2718           1 :   encodings = parse_accept_encoding_header("x-zstd,deflate,x-tor-lzma,gzip");
    2719           1 :   tt_uint_op(B_NONE|B_ZLIB|B_ZSTD|B_LZMA|B_GZIP, OP_EQ, encodings);
    2720             : 
    2721           1 :  done:
    2722           1 :   ;
    2723           1 : }
    2724             : 
    2725             : #define DIR_HANDLE_CMD(name,flags) \
    2726             :   { #name, test_dir_handle_get_##name, (flags), NULL, NULL }
    2727             : 
    2728             : #ifdef COCCI
    2729             : /* Coccinelle doesn't like the stringification in this macro */
    2730             : #define DIR_HANDLE_CMD_ARG(name,flags,arg) \
    2731             :   DIR_HANDLE_CMD(name,flags)
    2732             : #else
    2733             : #define DIR_HANDLE_CMD_ARG(name,flags,arg) \
    2734             :   { #name "/" arg, test_dir_handle_get_##name, (flags), \
    2735             :     &passthrough_setup, (void *)(arg) }
    2736             : #endif /* defined(COCCI) */
    2737             : 
    2738             : struct testcase_t dir_handle_get_tests[] = {
    2739             :   DIR_HANDLE_CMD(not_found, 0),
    2740             :   DIR_HANDLE_CMD(bad_request, 0),
    2741             :   DIR_HANDLE_CMD(v1_command_not_found, 0),
    2742             :   DIR_HANDLE_CMD(v1_command, 0),
    2743             :   DIR_HANDLE_CMD(robots_txt, 0),
    2744             :   DIR_HANDLE_CMD(micro_d_not_found, 0),
    2745             :   DIR_HANDLE_CMD(micro_d_server_busy, 0),
    2746             :   DIR_HANDLE_CMD(micro_d, 0),
    2747             :   DIR_HANDLE_CMD(networkstatus_bridges_not_found_without_auth, 0),
    2748             :   DIR_HANDLE_CMD(networkstatus_bridges_not_found_wrong_auth, 0),
    2749             :   DIR_HANDLE_CMD(networkstatus_bridges, 0),
    2750             :   DIR_HANDLE_CMD(server_descriptors_not_found, 0),
    2751             :   DIR_HANDLE_CMD(server_descriptors_busy, TT_FORK),
    2752             :   DIR_HANDLE_CMD(server_descriptors_all, TT_FORK),
    2753             :   DIR_HANDLE_CMD(server_descriptors_authority, TT_FORK),
    2754             :   DIR_HANDLE_CMD(server_descriptors_fp, TT_FORK),
    2755             :   DIR_HANDLE_CMD(server_descriptors_d, TT_FORK),
    2756             :   DIR_HANDLE_CMD(server_keys_bad_req, 0),
    2757             :   DIR_HANDLE_CMD(server_keys_busy, 0),
    2758             :   DIR_HANDLE_CMD(server_keys_all_not_found, 0),
    2759             :   DIR_HANDLE_CMD(server_keys_all, 0),
    2760             :   DIR_HANDLE_CMD(server_keys_authority_not_found, 0),
    2761             :   DIR_HANDLE_CMD(server_keys_authority, 0),
    2762             :   DIR_HANDLE_CMD(server_keys_fp_not_found, 0),
    2763             :   DIR_HANDLE_CMD(server_keys_fp, 0),
    2764             :   DIR_HANDLE_CMD(server_keys_sk_not_found, 0),
    2765             :   DIR_HANDLE_CMD(server_keys_sk, 0),
    2766             :   DIR_HANDLE_CMD(server_keys_fpsk_not_found, 0),
    2767             :   DIR_HANDLE_CMD(server_keys_fpsk, 0),
    2768             :   DIR_HANDLE_CMD(status_vote_current_not_found, 0),
    2769             :   DIR_HANDLE_CMD(status_vote_next_not_found, 0),
    2770             :   DIR_HANDLE_CMD(status_vote_current_authority_not_found, 0),
    2771             :   DIR_HANDLE_CMD(status_vote_current_authority, 0),
    2772             :   DIR_HANDLE_CMD_ARG(status_vote_too_late, 0, "min"),
    2773             :   DIR_HANDLE_CMD_ARG(status_vote_too_late, 0, "chutney"),
    2774             :   DIR_HANDLE_CMD_ARG(status_vote_too_late, 0, "half-public"),
    2775             :   DIR_HANDLE_CMD_ARG(status_vote_too_late, 0, "public"),
    2776             :   DIR_HANDLE_CMD(status_vote_next_authority_not_found, 0),
    2777             :   DIR_HANDLE_CMD(status_vote_next_authority, 0),
    2778             :   DIR_HANDLE_CMD(status_vote_next_bandwidth_not_found, 0),
    2779             :   DIR_HANDLE_CMD(status_vote_next_bandwidth, 0),
    2780             :   DIR_HANDLE_CMD(status_vote_current_consensus_ns_not_enough_sigs, TT_FORK),
    2781             :   DIR_HANDLE_CMD(status_vote_current_consensus_ns_not_found, TT_FORK),
    2782             :   DIR_HANDLE_CMD(status_vote_current_consensus_too_old, TT_FORK),
    2783             :   DIR_HANDLE_CMD(status_vote_current_consensus_ns_busy, TT_FORK),
    2784             :   DIR_HANDLE_CMD(status_vote_current_consensus_ns, TT_FORK),
    2785             :   DIR_HANDLE_CMD(status_vote_current_d_not_found, 0),
    2786             :   DIR_HANDLE_CMD(status_vote_next_d_not_found, 0),
    2787             :   DIR_HANDLE_CMD(status_vote_d, 0),
    2788             :   DIR_HANDLE_CMD(status_vote_next_consensus_not_found, 0),
    2789             :   DIR_HANDLE_CMD(status_vote_next_consensus_busy, 0),
    2790             :   DIR_HANDLE_CMD(status_vote_next_consensus, 0),
    2791             :   DIR_HANDLE_CMD(status_vote_next_consensus_signatures_not_found, 0),
    2792             :   DIR_HANDLE_CMD(status_vote_next_consensus_signatures_busy, 0),
    2793             :   DIR_HANDLE_CMD(status_vote_next_consensus_signatures, 0),
    2794             :   DIR_HANDLE_CMD(parse_accept_encoding, 0),
    2795             :   END_OF_TESTCASES
    2796             : };

Generated by: LCOV version 1.14