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

          Line data    Source code
       1             : /* Copyright (c) 2010-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : #include "orconfig.h"
       5             : #include "core/or/or.h"
       6             : 
       7             : #define DIRVOTE_PRIVATE
       8             : #include "app/config/config.h"
       9             : #include "feature/dirauth/dirvote.h"
      10             : #include "feature/dirparse/microdesc_parse.h"
      11             : #include "feature/dirparse/routerparse.h"
      12             : #include "feature/nodelist/microdesc.h"
      13             : #include "feature/nodelist/networkstatus.h"
      14             : #include "feature/nodelist/nodefamily.h"
      15             : #include "feature/nodelist/routerlist.h"
      16             : #include "feature/nodelist/torcert.h"
      17             : 
      18             : #include "feature/nodelist/microdesc_st.h"
      19             : #include "feature/nodelist/networkstatus_st.h"
      20             : #include "feature/nodelist/routerinfo_st.h"
      21             : #include "feature/nodelist/routerstatus_st.h"
      22             : 
      23             : #include "test/test.h"
      24             : #include "test/log_test_helpers.h"
      25             : 
      26             : #ifdef HAVE_SYS_STAT_H
      27             : #include <sys/stat.h>
      28             : #endif
      29             : 
      30             : #ifdef _WIN32
      31             : /* For mkdir() */
      32             : #include <direct.h>
      33             : #else
      34             : #include <dirent.h>
      35             : #endif /* defined(_WIN32) */
      36             : 
      37             : static const char test_md1[] =
      38             :   "onion-key\n"
      39             :   "-----BEGIN RSA PUBLIC KEY-----\n"
      40             :   "MIGJAoGBAMjlHH/daN43cSVRaHBwgUfnszzAhg98EvivJ9Qxfv51mvQUxPjQ07es\n"
      41             :   "gV/3n8fyh3Kqr/ehi9jxkdgSRfSnmF7giaHL1SLZ29kA7KtST+pBvmTpDtHa3ykX\n"
      42             :   "Xorc7hJvIyTZoc1HU+5XSynj3gsBE5IGK1ZRzrNS688LnuZMVp1tAgMBAAE=\n"
      43             :   "-----END RSA PUBLIC KEY-----\n"
      44             :   "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n";
      45             : 
      46             : static const char test_md2[] =
      47             :   "onion-key\n"
      48             :   "-----BEGIN RSA PUBLIC KEY-----\n"
      49             :   "MIGJAoGBAMIixIowh2DyPmDNMDwBX2DHcYcqdcH1zdIQJZkyV6c6rQHnvbcaDoSg\n"
      50             :   "jgFSLJKpnGmh71FVRqep+yVB0zI1JY43kuEnXry2HbZCD9UDo3d3n7t015X5S7ON\n"
      51             :   "bSSYtQGPwOr6Epf96IF6DoQxy4iDnPUAlejuhAG51s1y6/rZQ3zxAgMBAAE=\n"
      52             :   "-----END RSA PUBLIC KEY-----\n"
      53             :   "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n";
      54             : 
      55             : static const char test_md3[] =
      56             :   "@last-listed 2009-06-22\n"
      57             :   "onion-key\n"
      58             :   "-----BEGIN RSA PUBLIC KEY-----\n"
      59             :   "MIGJAoGBAMH3340d4ENNGrqx7UxT+lB7x6DNUKOdPEOn4teceE11xlMyZ9TPv41c\n"
      60             :   "qj2fRZzfxlc88G/tmiaHshmdtEpklZ740OFqaaJVj4LjPMKFNE+J7Xc1142BE9Ci\n"
      61             :   "KgsbjGYe2RY261aADRWLetJ8T9QDMm+JngL4288hc8pq1uB/3TAbAgMBAAE=\n"
      62             :   "-----END RSA PUBLIC KEY-----\n"
      63             :   "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n"
      64             :   "p accept 1-700,800-1000\n"
      65             :   "family nodeX nodeY nodeZ\n";
      66             : 
      67             : static void
      68           1 : test_md_cache(void *data)
      69             : {
      70           1 :   or_options_t *options = NULL;
      71           1 :   microdesc_cache_t *mc = NULL ;
      72           1 :   smartlist_t *added = NULL, *wanted = NULL;
      73           1 :   microdesc_t *md1, *md2, *md3;
      74           1 :   char d1[DIGEST256_LEN], d2[DIGEST256_LEN], d3[DIGEST256_LEN];
      75           1 :   const char *test_md3_noannotation = strchr(test_md3, '\n')+1;
      76           1 :   time_t time1, time2, time3;
      77           1 :   char *fn = NULL, *s = NULL;
      78           1 :   char *encoded_family = NULL;
      79           1 :   (void)data;
      80             : 
      81           1 :   options = get_options_mutable();
      82           1 :   tt_assert(options);
      83             : 
      84           1 :   time1 = time(NULL);
      85           1 :   time2 = time(NULL) - 2*24*60*60;
      86           1 :   time3 = time(NULL) - 15*24*60*60;
      87             : 
      88             :   /* Possibly, turn this into a test setup/cleanup pair */
      89           1 :   tor_free(options->CacheDirectory);
      90           1 :   options->CacheDirectory = tor_strdup(get_fname("md_datadir_test"));
      91             : #ifdef _WIN32
      92             :   tt_int_op(0, OP_EQ, mkdir(options->CacheDirectory));
      93             : #else
      94           1 :   tt_int_op(0, OP_EQ, mkdir(options->CacheDirectory, 0700));
      95             : #endif
      96             : 
      97           1 :   tt_assert(!strcmpstart(test_md3_noannotation, "onion-key"));
      98             : 
      99           1 :   crypto_digest256(d1, test_md1, strlen(test_md1), DIGEST_SHA256);
     100           1 :   crypto_digest256(d2, test_md2, strlen(test_md1), DIGEST_SHA256);
     101           1 :   crypto_digest256(d3, test_md3_noannotation, strlen(test_md3_noannotation),
     102             :                    DIGEST_SHA256);
     103             : 
     104           1 :   mc = get_microdesc_cache();
     105             : 
     106           1 :   added = microdescs_add_to_cache(mc, test_md1, NULL, SAVED_NOWHERE, 0,
     107             :                                   time1, NULL);
     108           1 :   tt_int_op(1, OP_EQ, smartlist_len(added));
     109           1 :   md1 = smartlist_get(added, 0);
     110           1 :   smartlist_free(added);
     111           1 :   added = NULL;
     112             : 
     113           1 :   wanted = smartlist_new();
     114           1 :   added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0,
     115             :                                   time2, wanted);
     116             :   /* Should fail, since we didn't list test_md2's digest in wanted */
     117           1 :   tt_int_op(0, OP_EQ, smartlist_len(added));
     118           1 :   smartlist_free(added);
     119           1 :   added = NULL;
     120             : 
     121           1 :   smartlist_add(wanted, tor_memdup(d2, DIGEST256_LEN));
     122           1 :   smartlist_add(wanted, tor_memdup(d3, DIGEST256_LEN));
     123           1 :   added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0,
     124             :                                   time2, wanted);
     125             :   /* Now it can work. md2 should have been added */
     126           1 :   tt_int_op(1, OP_EQ, smartlist_len(added));
     127           1 :   md2 = smartlist_get(added, 0);
     128             :   /* And it should have gotten removed from 'wanted' */
     129           1 :   tt_int_op(smartlist_len(wanted), OP_EQ, 1);
     130           1 :   tt_mem_op(smartlist_get(wanted, 0), OP_EQ, d3, DIGEST256_LEN);
     131           1 :   smartlist_free(added);
     132           1 :   added = NULL;
     133             : 
     134           1 :   added = microdescs_add_to_cache(mc, test_md3, NULL,
     135             :                                   SAVED_NOWHERE, 0, -1, NULL);
     136             :   /* Must fail, since SAVED_NOWHERE precludes annotations */
     137           1 :   tt_int_op(0, OP_EQ, smartlist_len(added));
     138           1 :   smartlist_free(added);
     139           1 :   added = NULL;
     140             : 
     141           1 :   added = microdescs_add_to_cache(mc, test_md3_noannotation, NULL,
     142             :                                   SAVED_NOWHERE, 0, time3, NULL);
     143             :   /* Now it can work */
     144           1 :   tt_int_op(1, OP_EQ, smartlist_len(added));
     145           1 :   md3 = smartlist_get(added, 0);
     146           1 :   smartlist_free(added);
     147           1 :   added = NULL;
     148             : 
     149             :   /* Okay.  We added 1...3.  Let's poke them to see how they look, and make
     150             :    * sure they're really in the journal. */
     151           1 :   tt_ptr_op(md1, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d1));
     152           1 :   tt_ptr_op(md2, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d2));
     153           1 :   tt_ptr_op(md3, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d3));
     154             : 
     155           1 :   tt_int_op(md1->last_listed, OP_EQ, time1);
     156           1 :   tt_int_op(md2->last_listed, OP_EQ, time2);
     157           1 :   tt_int_op(md3->last_listed, OP_EQ, time3);
     158             : 
     159           1 :   tt_int_op(md1->saved_location, OP_EQ, SAVED_IN_JOURNAL);
     160           1 :   tt_int_op(md2->saved_location, OP_EQ, SAVED_IN_JOURNAL);
     161           1 :   tt_int_op(md3->saved_location, OP_EQ, SAVED_IN_JOURNAL);
     162             : 
     163           1 :   tt_int_op(md1->bodylen, OP_EQ, strlen(test_md1));
     164           1 :   tt_int_op(md2->bodylen, OP_EQ, strlen(test_md2));
     165           1 :   tt_int_op(md3->bodylen, OP_EQ, strlen(test_md3_noannotation));
     166           1 :   tt_mem_op(md1->body, OP_EQ, test_md1, strlen(test_md1));
     167           1 :   tt_mem_op(md2->body, OP_EQ, test_md2, strlen(test_md2));
     168           1 :   tt_mem_op(md3->body, OP_EQ, test_md3_noannotation,
     169           1 :               strlen(test_md3_noannotation));
     170             : 
     171           1 :   tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs.new",
     172             :                options->CacheDirectory);
     173           1 :   s = read_file_to_str(fn, RFTS_BIN, NULL);
     174           1 :   tt_assert(s);
     175           1 :   tt_mem_op(md1->body, OP_EQ, s + md1->off, md1->bodylen);
     176           1 :   tt_mem_op(md2->body, OP_EQ, s + md2->off, md2->bodylen);
     177           1 :   tt_mem_op(md3->body, OP_EQ, s + md3->off, md3->bodylen);
     178             : 
     179           1 :   tt_ptr_op(md1->family, OP_EQ, NULL);
     180           1 :   tt_ptr_op(md3->family, OP_NE, NULL);
     181             : 
     182           1 :   encoded_family = nodefamily_format(md3->family);
     183           1 :   tt_str_op(encoded_family, OP_EQ, "nodex nodey nodez");
     184             : 
     185             :   /* Now rebuild the cache! */
     186           1 :   tt_int_op(microdesc_cache_rebuild(mc, 1), OP_EQ, 0);
     187             : 
     188           1 :   tt_int_op(md1->saved_location, OP_EQ, SAVED_IN_CACHE);
     189           1 :   tt_int_op(md2->saved_location, OP_EQ, SAVED_IN_CACHE);
     190           1 :   tt_int_op(md3->saved_location, OP_EQ, SAVED_IN_CACHE);
     191             : 
     192             :   /* The journal should be empty now */
     193           1 :   tor_free(s);
     194           1 :   s = read_file_to_str(fn, RFTS_BIN, NULL);
     195           1 :   tt_str_op(s, OP_EQ, "");
     196           1 :   tor_free(s);
     197           1 :   tor_free(fn);
     198             : 
     199             :   /* read the cache. */
     200           1 :   tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs",
     201             :                options->CacheDirectory);
     202           1 :   s = read_file_to_str(fn, RFTS_BIN, NULL);
     203           1 :   tt_mem_op(md1->body, OP_EQ, s + md1->off, strlen(test_md1));
     204           1 :   tt_mem_op(md2->body, OP_EQ, s + md2->off, strlen(test_md2));
     205           1 :   tt_mem_op(md3->body, OP_EQ, s + md3->off, strlen(test_md3_noannotation));
     206             : 
     207             :   /* Okay, now we are going to forget about the cache entirely, and reload it
     208             :    * from the disk. */
     209           1 :   microdesc_free_all();
     210           1 :   mc = get_microdesc_cache();
     211           1 :   md1 = microdesc_cache_lookup_by_digest256(mc, d1);
     212           1 :   md2 = microdesc_cache_lookup_by_digest256(mc, d2);
     213           1 :   md3 = microdesc_cache_lookup_by_digest256(mc, d3);
     214           1 :   tt_assert(md1);
     215           1 :   tt_assert(md2);
     216           1 :   tt_assert(md3);
     217           1 :   tt_mem_op(md1->body, OP_EQ, s + md1->off, strlen(test_md1));
     218           1 :   tt_mem_op(md2->body, OP_EQ, s + md2->off, strlen(test_md2));
     219           1 :   tt_mem_op(md3->body, OP_EQ, s + md3->off, strlen(test_md3_noannotation));
     220             : 
     221           1 :   tt_int_op(md1->last_listed, OP_EQ, time1);
     222           1 :   tt_int_op(md2->last_listed, OP_EQ, time2);
     223           1 :   tt_int_op(md3->last_listed, OP_EQ, time3);
     224             : 
     225             :   /* Okay, now we are going to clear out everything older than a week old.
     226             :    * In practice, that means md3 */
     227           1 :   microdesc_cache_clean(mc, time(NULL)-7*24*60*60, 1/*force*/);
     228           1 :   tt_ptr_op(md1, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d1));
     229           1 :   tt_ptr_op(md2, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d2));
     230           1 :   tt_ptr_op(NULL, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d3));
     231           1 :   md3 = NULL; /* it's history now! */
     232             : 
     233             :   /* rebuild again, make sure it stays gone. */
     234           1 :   tt_int_op(microdesc_cache_rebuild(mc, 1), OP_EQ, 0);
     235           1 :   tt_ptr_op(md1, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d1));
     236           1 :   tt_ptr_op(md2, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d2));
     237           1 :   tt_ptr_op(NULL, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d3));
     238             : 
     239             :   /* Re-add md3, and make sure we can rebuild the cache. */
     240           1 :   added = microdescs_add_to_cache(mc, test_md3_noannotation, NULL,
     241             :                                   SAVED_NOWHERE, 0, time3, NULL);
     242           1 :   tt_int_op(1, OP_EQ, smartlist_len(added));
     243           1 :   md3 = smartlist_get(added, 0);
     244           1 :   smartlist_free(added);
     245           1 :   added = NULL;
     246           1 :   tt_int_op(md1->saved_location, OP_EQ, SAVED_IN_CACHE);
     247           1 :   tt_int_op(md2->saved_location, OP_EQ, SAVED_IN_CACHE);
     248           1 :   tt_int_op(md3->saved_location, OP_EQ, SAVED_IN_JOURNAL);
     249             : 
     250           1 :   tt_int_op(microdesc_cache_rebuild(mc, 1), OP_EQ, 0);
     251           1 :   tt_int_op(md3->saved_location, OP_EQ, SAVED_IN_CACHE);
     252             : 
     253           1 :  done:
     254           1 :   if (options)
     255           1 :     tor_free(options->CacheDirectory);
     256           1 :   microdesc_free_all();
     257             : 
     258           1 :   smartlist_free(added);
     259           1 :   if (wanted)
     260           2 :     SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
     261           1 :   smartlist_free(wanted);
     262           1 :   tor_free(s);
     263           1 :   tor_free(fn);
     264           1 :   tor_free(encoded_family);
     265           1 : }
     266             : 
     267             : static const char truncated_md[] =
     268             :   "@last-listed 2013-08-08 19:02:59\n"
     269             :   "onion-key\n"
     270             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     271             :   "MIGJAoGBAM91vLFNaM+gGhnRIdz2Cm/Kl7Xz0cOobIdVzhS3cKUJfk867hCuTipS\n"
     272             :   "NveLBzNopvgXKruAAzEj3cACxk6Q8lv5UWOGCD1UolkgsWSE62RBjap44g+oc9J1\n"
     273             :   "RI9968xOTZw0VaBQg9giEILNXl0djoikQ+5tQRUvLDDa67gpa5Q1AgMBAAE=\n"
     274             :   "-----END RSA PUBLIC KEY-----\n"
     275             :   "family @\n";
     276             : 
     277             : static void
     278           1 : test_md_cache_broken(void *data)
     279             : {
     280           1 :   or_options_t *options;
     281           1 :   char *fn=NULL;
     282           1 :   microdesc_cache_t *mc = NULL;
     283             : 
     284           1 :   (void)data;
     285             : 
     286           1 :   options = get_options_mutable();
     287           1 :   tt_assert(options);
     288           1 :   tor_free(options->CacheDirectory);
     289           1 :   options->CacheDirectory = tor_strdup(get_fname("md_datadir_test2"));
     290             : 
     291             : #ifdef _WIN32
     292             :   tt_int_op(0, OP_EQ, mkdir(options->CacheDirectory));
     293             : #else
     294           1 :   tt_int_op(0, OP_EQ, mkdir(options->CacheDirectory, 0700));
     295             : #endif
     296             : 
     297           1 :   tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs",
     298             :                options->CacheDirectory);
     299             : 
     300           1 :   write_str_to_file(fn, truncated_md, 1);
     301             : 
     302           1 :   mc = get_microdesc_cache();
     303           1 :   tt_assert(mc);
     304             : 
     305           1 :  done:
     306           1 :   if (options)
     307           1 :     tor_free(options->CacheDirectory);
     308           1 :   tor_free(fn);
     309           1 :   microdesc_free_all();
     310           1 : }
     311             : 
     312             : /* Generated by chutney. */
     313             : static const char test_ri[] =
     314             :   "router test005r 127.0.0.1 5005 0 7005\n"
     315             :   "identity-ed25519\n"
     316             :   "-----BEGIN ED25519 CERT-----\n"
     317             :   "AQQABs1eAfTuBhu6ypB5/9avDiY3qBzulkCvfYqbFN/ABk/o4xFcAQAgBAAnmWRG\n"
     318             :   "rIvqpb4Kk3cThEiWAll4uDCO2Y46uNm9WG7AtPt4LG+XfktG3GAxv6aVQimwlyHc\n"
     319             :   "1x2Lfm9KG3mWWj+hxnum4Z7873OE0B9l2Hg0YQZCW/PuHSWN0rspTvY5SgA=\n"
     320             :   "-----END ED25519 CERT-----\n"
     321             :   "master-key-ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n"
     322             :   "or-address [::]:5005\n"
     323             :   "platform Tor 0.4.5.0-alpha-dev on Linux\n"
     324             :   "proto Cons=1-2 Desc=1-2 DirCache=1-2 FlowCtrl=1 HSDir=1-2 HSIntro=3-5 "
     325             :       "HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Padding=2 Relay=1-3\n"
     326             :   "published 2020-10-13 13:27:34\n"
     327             :   "fingerprint D219 590A C951 3BCD EBBA 9AB7 2100 7A4C C01B BAE3\n"
     328             :   "uptime 324451\n"
     329             :   "bandwidth 1073741824 1073741824 637796\n"
     330             :   "extra-info-digest 78E6D382BC826B95B4111554EEE7D541A32AAAA3 "
     331             :        "c61Onjpq+1S0TrdvoaOvGAxew6yfO+uHNhipbemQmgA\n"
     332             :   "onion-key\n"
     333             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     334             :   "MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n"
     335             :   "83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n"
     336             :   "nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n"
     337             :   "-----END RSA PUBLIC KEY-----\n"
     338             :   "signing-key\n"
     339             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     340             :   "MIGJAoGBANBzejGAwyPTPq2Gm03wpg3qICo0uDQau8opude2mW3eyxAqOqHzC8De\n"
     341             :   "gRgbmn040vqe9gwvH4iaHpVeTxyDwQefbfULdq6bETmX3aSUj6LKBCqqcyuOJFQu\n"
     342             :   "7M2QfNSfHtldUABpIaqFvEA3AV8qjOoUtauoFNJKMy7Wj2//S70VAgMBAAE=\n"
     343             :   "-----END RSA PUBLIC KEY-----\n"
     344             :   "onion-key-crosscert\n"
     345             :   "-----BEGIN CROSSCERT-----\n"
     346             :   "pD3Nkkunt8zP6PO6H3uHT0t7xnorC7cY/KfF75mFB+90pHCD9f0Xdu3Pjrur/q23\n"
     347             :   "PIKV3hdtdsODoJuoh8LPGNAjS5rO6HMCtHNDNunNOs69bvfaO0jThnurXmOpY0sW\n"
     348             :   "eRfBeYN2KNgrN0B1eDejfPSr03dkFY48yoUDROv9EJQ=\n"
     349             :   "-----END CROSSCERT-----\n"
     350             :   "ntor-onion-key-crosscert 0\n"
     351             :   "-----BEGIN ED25519 CERT-----\n"
     352             :   "AQoABs2OASeZZEasi+qlvgqTdxOESJYCWXi4MI7Zjjq42b1YbsC0AKc5y5qYUYvw\n"
     353             :   "VATtWkV9DVIZbZSb9mQP5pmNaqmX+DbmINCYt8j7l+U7g3ftUyh0Wlrgevx0pFUI\n"
     354             :   "RcIU0HKHZQA=\n"
     355             :   "-----END ED25519 CERT-----\n"
     356             :   "hidden-service-dir\n"
     357             :   "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA\n"
     358             :   "accept *:*\n"
     359             :   "tunnelled-dir-server\n"
     360             :   "router-sig-ed25519 Xm56dYbo/hCHWyzcdUPmfTeZ4qly2TYf1/2Q1lXKQDMJyBti"
     361             :       "8ZE8R2TTYsYimr+UtAapbzBItccZLze505nhBw\n"
     362             :   "router-signature\n"
     363             :   "-----BEGIN SIGNATURE-----\n"
     364             :   "bbeN0lq6nCfJQXGcKa1M9TQ6b2upig7clrlVXuzKeR0JhGwnDCXUAFxDtrw3vkVo\n"
     365             :   "ExBXXvJeBPyustFOQkdiAEWHHSW5CwEgeVCBYZeEnaiySIgDVKuu+9B53ezFdC0Y\n"
     366             :   "iFJkKxxDx7ksxX0zdl7aPT4ORFEuRhCYS6el7YJmoyg=\n"
     367             :   "-----END SIGNATURE-----\n";
     368             : 
     369             : static const char test_md2_25[] =
     370             :   "onion-key\n"
     371             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     372             :   "MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n"
     373             :   "83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n"
     374             :   "nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n"
     375             :   "-----END RSA PUBLIC KEY-----\n"
     376             :   "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA=\n"
     377             :   "p accept 1-65535\n"
     378             :   "id ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n";
     379             : 
     380             : static const char test_md2_withfamily_28[] =
     381             :   "onion-key\n"
     382             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     383             :   "MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n"
     384             :   "83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n"
     385             :   "nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n"
     386             :   "-----END RSA PUBLIC KEY-----\n"
     387             :   "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA=\n"
     388             :   "family OtherNode !Strange\n"
     389             :   "p accept 1-65535\n"
     390             :   "id ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n";
     391             : 
     392             : static const char test_md2_withfamily_29[] =
     393             :   "onion-key\n"
     394             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     395             :   "MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n"
     396             :   "83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n"
     397             :   "nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n"
     398             :   "-----END RSA PUBLIC KEY-----\n"
     399             :   "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA=\n"
     400             :   "family !Strange $D219590AC9513BCDEBBA9AB721007A4CC01BBAE3 othernode\n"
     401             :   "p accept 1-65535\n"
     402             :   "id ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n";
     403             : 
     404             : static void
     405           1 : test_md_generate(void *arg)
     406             : {
     407           1 :   routerinfo_t *ri;
     408           1 :   microdesc_t *md = NULL;
     409           1 :   (void)arg;
     410             : 
     411           1 :   ri = router_parse_entry_from_string(test_ri, NULL, 0, 0, NULL, NULL);
     412           1 :   tt_assert(ri);
     413             : 
     414           1 :   md = dirvote_create_microdescriptor(ri, 25);
     415           1 :   tt_str_op(md->body, OP_EQ, test_md2_25);
     416           1 :   tt_assert(ed25519_pubkey_eq(md->ed25519_identity_pkey,
     417             :                               &ri->cache_info.signing_key_cert->signing_key));
     418             : 
     419             :   // Try family encoding.
     420           1 :   microdesc_free(md);
     421           1 :   ri->declared_family = smartlist_new();
     422           1 :   smartlist_add_strdup(ri->declared_family, "OtherNode !Strange");
     423           1 :   md = dirvote_create_microdescriptor(ri, 28);
     424           1 :   tt_str_op(md->body, OP_EQ, test_md2_withfamily_28);
     425             : 
     426           1 :   microdesc_free(md);
     427           1 :   md = dirvote_create_microdescriptor(ri, 29);
     428           1 :   tt_str_op(md->body, OP_EQ, test_md2_withfamily_29);
     429             : 
     430           1 :  done:
     431           1 :   microdesc_free(md);
     432           1 :   routerinfo_free(ri);
     433           1 : }
     434             : 
     435             : #ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
     436             : DISABLE_GCC_WARNING("-Woverlength-strings")
     437             : /* We allow huge string constants in the unit tests, but not in the code
     438             :  * at large. */
     439             : #endif
     440             : /* Taken at random from my ~/.tor/cached-microdescs file and then
     441             :  * hand-munged */
     442             : static const char MD_PARSE_TEST_DATA[] =
     443             :   /* Good 0 */
     444             :   "onion-key\n"
     445             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     446             :   "MIGJAoGBANsKd1GRfOuSR1MkcwKqs6SVy4Gi/JXplt/bHDkIGm6Q96TeJ5uyVgUL\n"
     447             :   "DBr/ij6+JqgVFeriuiMzHKREytzjdaTuKsKBFFpLwb+Ppcjr5nMIH/AR6/aHO8hW\n"
     448             :   "T3B9lx5T6Kl7CqZ4yqXxYRHzn50EPTIZuz0y9se4J4gi9mLmL+pHAgMBAAE=\n"
     449             :   "-----END RSA PUBLIC KEY-----\n"
     450             :   "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n"
     451             :   "p accept 20-23,43,53,79-81,88,110,143,194,220,443,464,531,543-544\n"
     452             :   "id rsa1024 GEo59/iR1GWSIWZDzXTd5QxtqnU\n"
     453             :   /* Bad 0: I've messed with the onion-key in the second one. */
     454             :   "onion-key\n"
     455             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     456             :   "MIGJAoGBAMr4o/pflVwscx11vC1AKEADlKEqnhpvCIjAEzNEenMhvGQHRlA0EXLC\n"
     457             :   "7G7O5bhnCwEHqK8Pvg8cuX/fD8v08TF1EVPhwPa0UI6ab8KnPP2F!!!!!!b92DG7EQIk3q\n"
     458             :   "d68Uxp7E9/t3v1WWZjzDqvEe0par6ul+DKW6HMlTGebFo5Q4e8R1AgMBAAE=\n"
     459             :   "-----END RSA PUBLIC KEY-----\n"
     460             :   "ntor-onion-key 761Dmm27via7lXygNHM3l+oJLrYU2Nye0Uz4pkpipyY=\n"
     461             :   "p accept 53\n"
     462             :   "id rsa1024 3Y4fwXhtgkdGDZ5ef5mtb6TJRQQ\n"
     463             :   /* Good 1 */
     464             :   "onion-key\n"
     465             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     466             :   "MIGJAoGBANsMSjVi3EX8ZHfm/dvPF6KdVR66k1tVul7Jp+dDbDajBYNhgKRzVCxy\n"
     467             :   "Yac1CBuQjOqK89tKap9PQBnhF087eDrfaZDqYTLwB2W2sBJncVej15WEPXPRBifo\n"
     468             :   "iFZ8337kgczkaY+IOfSuhtbOUyDOoDpRJheIKBNq0ZiTqtLbbadVAgMBAAE=\n"
     469             :   "-----END RSA PUBLIC KEY-----\n"
     470             :   "ntor-onion-key ncfiHJjSgdDEW/gc6q6/7idac7j+x7ejQrRm6i75pGA=\n"
     471             :   "p accept 443,6660-6669,6697,7000-7001\n"
     472             :   "id rsa1024 XXuLzw3mfBELEq3veXoNhdehwD4\n"
     473             :   /* Good 2 */
     474             :   "onion-key\n"
     475             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     476             :   "MIGJAoGBANQfBlrHrh9F/CAOytrNFgi0ikWMW/HZxuoszF9X+AQ+MudR8bcxxOGl\n"
     477             :   "1RFwb74s8E3uuzrCkNFvSw9Ar1L02F2DOX0gLsxEGuYC4Ave9NUteGqSqDyEJQUJ\n"
     478             :   "KlfxCPn2qC9nvNT7wR/Dg2WRvAEKnJmkpb57N3+WSAOPLjKOFEz3AgMBAAE=\n"
     479             :   "-----END RSA PUBLIC KEY-----\n"
     480             :   "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n"
     481             :   "id rsa1024 6y60AEI9a1PUUlRPO0YQT9WzrjI\n"
     482             :   /* Bad 1: Here I've messed with the ntor key */
     483             :   "onion-key\n"
     484             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     485             :   "MIGJAoGBAPjy2HacU3jDNO5nTOFGSwNa0qKCNn4yhtrDVcAJ5alIQeBWZZGJLZ0q\n"
     486             :   "Cqylw1vYqxu8E09g+QXXFbAgBv1U9TICaATxrIJhIJzc8TJPhqJemp1kq0DvHLDx\n"
     487             :   "mxwlkNnCD/P5NS+JYB3EjOlU9EnSKUWNU61+Co344m2JqhEau40vAgMBAAE=\n"
     488             :   "-----END RSA PUBLIC KEY-----\n"
     489             :   "ntor-onion-key 4i2Fp9JHTUr1uQs0pxD5j5spl4/RG56S2P0gQxU=\n"
     490             :   "id rsa1024 nMRmNEGysA0NmlALVaUmI7D5jLU\n"
     491             :   /* Good 3: I've added a weird token in this one. This shouldn't prevent
     492             :    * it parsing */
     493             :   "onion-key\n"
     494             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     495             :   "MIGJAoGBAKmosxudyNA/yJNz3S890VqV/ebylzoD11Sc0b/d5tyNNaNZjcYy5vRD\n"
     496             :   "kwyxFRMbP2TLZQ1zRfNwY7IDnYjU2SbW0pxuM6M8WRtsmx/YOE3kHMVAFJNrTUqU\n"
     497             :   "6D1zB3IiRDS5q5+NoRxwqo+hYUck60O3WTwEoqb+l3lvXeu7z9rFAgMBAAE=\n"
     498             :   "-----END RSA PUBLIC KEY-----\n"
     499             :   "flux-capacitor 1.21 GW\n"
     500             :   "ntor-onion-key MWBoEkl+RlBiGX44XKIvTSqbznTNZStOmUYtcYRQQyY=\n"
     501             :   "id rsa1024 R+A5O9qRvRac4FT3C4L2QnFyxsc\n"
     502             :   /* Good 4: Here I've made the 'id rsa' token odd.  It should still parse
     503             :    * just fine. */
     504             :   "onion-key\n"
     505             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     506             :   "MIGJAoGBAOh+WMkdNe/Pkjb8UjQyfLOlFgpuVFrxAIGnJsmWWx0yBE97DQxGyh2n\n"
     507             :   "h8G5OJZHRarJQyCIf7vpZQAi0oP0OkGGaCaDQsM+D8TnqhnU++RWGnMqY/cXxPrL\n"
     508             :   "MEq+n6aGiLmzkO7ah8yorZpoREk4GqLUIN89/tHHGOhJL3c4CPGjAgMBAAE=\n"
     509             :   "-----END RSA PUBLIC KEY-----\n"
     510             :   "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n"
     511             :   "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"
     512             :   "id rsa1234 jlqAKFD2E7uMKv+8TmKSeo7NBho\n"
     513             :   /* Good 5: Extra id type. */
     514             :   "onion-key\n"
     515             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     516             :   "MIGJAoGBAMdgPPc5uaw4y/q+SUTN/I8Y+Gvdx9kKgWV4dmDGJ0mxsVZmo1v6+v3F\n"
     517             :   "12M2f9m99G3WB8F8now29C+9XyEv8MBHj1lHRdUFHSQes3YTFvDNlgj+FjLqO5TJ\n"
     518             :   "adOOmfu4DCUUtUEDyQKbNVL4EkMTXY73omTVsjcH3xxFjTx5wixhAgMBAAE=\n"
     519             :   "-----END RSA PUBLIC KEY-----\n"
     520             :   "ntor-onion-key AAVnWZcnDbxasdZwKqb4fL6O9sZV+XsRNHTpNd1YMz8=\n"
     521             :   "id rsa1024 72EfBL11QuwX2vU8y+p9ExGfGEg\n"
     522             :   "id expolding hedgehog 0+A5O9qRvRac4FT3C4L2QnFyxsc\n"
     523             :   /* Good 6: I've given this a bogus policy. It should parse. */
     524             :   "onion-key\n"
     525             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     526             :   "MIGJAoGBALNuufwhPMF8BooxYMNvhYJMPqUB8hQDt8wGmPKphJcD1sVD1i4gAZM2\n"
     527             :   "HIo+zUBlljDrRWL5NzVzd1yxUJAiQxvXS5dRRFY3B70M7wTVpXw53xe0/BM5t1AX\n"
     528             :   "n0MFk7Jl6XIKMlzRalZvmMvE/odtyWXkP4Nd1MyZ1QcIwrQ2iwyrAgMBAAE=\n"
     529             :   "-----END RSA PUBLIC KEY-----\n"
     530             :   "p condone 1-10\n"
     531             :   "ntor-onion-key 2/nMJ+L4dd/2GpMyTYjz3zC59MvQy4MIzJZhdzKHekg=\n"
     532             :   "id rsa1024 FHyh10glEMA6MCmBb5R9Y+X/MhQ\n"
     533             :   /* Good 7: I've given this one another sort of odd policy. Should parse. */
     534             :   "onion-key\n"
     535             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     536             :   "MIGJAoGBAKcd3FmQ8iAADghyvX8eca0ePqtJ2w1IDdUdTlf5Y/8+OMdp//sD01yC\n"
     537             :   "YmiX45LK5ge1O3AzcakYCO6fb3pyIqvXdvm24OjyYZELQ40cmKSLjdhcSf4Fr/N9\n"
     538             :   "uR/CkknR9cEePu1wZ5WBIGmGdXI6s7t3LB+e7XFyBYAx6wMGlnX7AgMBAAE=\n"
     539             :   "-----END RSA PUBLIC KEY-----\n"
     540             :   "p accept frogs-mice\n"
     541             :   "ntor-onion-key AMxvhaQ1Qg7jBJFoyHuPRgETvLbFmJ194hExV24FuAI=\n"
     542             :   "family $D8CFEA0D996F5D1473D2063C041B7910DB23981E\n"
     543             :   "id rsa1024 d0VVZC/cHh1P3y4MMbfKlQHFycc\n"
     544             :   /* Good 8: This one has the ntor-onion-key without terminating =. That's
     545             :    * allowed. */
     546             :   "onion-key\n"
     547             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     548             :   "MIGJAoGBAL438YfjrJE2SPqkkXeQwICygu8KNO54Juj6sjqk5hgsiazIWMOBgbaX\n"
     549             :   "LIRqPNGaiSq01xSqwjwCBCfwZYT/nSdDBqj1h9aoR8rnjxZjyQ+m3rWpdDqeCDMx\n"
     550             :   "I3NgZ5w4bNX4poRb42lrV6NmQiFdjzpqszVbv5Lpn2CSKu32CwKVAgMBAAE=\n"
     551             :   "-----END RSA PUBLIC KEY-----\n"
     552             :   "ntor-onion-key UKL6Dnj2KwYsFlkCvOkXVatxvOPB4MaxqwPQQgZMTwI\n"
     553             :   "id rsa1024 FPIXc6k++JnKCtSKWUxaR6oXEKs\n"
     554             :   /* Good 9: Another totally normal one.*/
     555             :   "onion-key\n"
     556             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     557             :   "MIGJAoGBANNGIKRd8PFNXkJ2JPV1ohDMFNbJwKbwybeieaQFjtU9KWedHCbr+QD4\n"
     558             :   "B6zNY5ysguNjHNnlq2f6D09+uhnfDBON8tAz0mPQH/6JqnOXm+EiUn+8bN0E8Nke\n"
     559             :   "/i3GEgDeaxJJMNQcpsJvmmSmKFOlYy9Fy7ejAjTGqtAnqOte7BnTAgMBAAE=\n"
     560             :   "-----END RSA PUBLIC KEY-----\n"
     561             :   "ntor-onion-key gUsq3e5iYgsQQvyxINtLzBpHxmIt5rtuFlEbKfI4gFk=\n"
     562             :   "id rsa1024 jv+LdatDzsMfEW6pLBeL/5uzwCc\n"
     563             :   /* Bad 2: RSA key has bad exponent of 3. */
     564             :   "onion-key\n"
     565             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     566             :   "MIGHAoGBAMMTWtvPxYnUNJ5Y7B+XENcpxzPoGstrdiUszCBS+/42xvluLJ+JDSdR\n"
     567             :   "qJaMD6ax8vKAeLS5C6O17MNdG2VldlPRbtgl41MXsOoUqEJ+nY9e3WG9Snjp47xC\n"
     568             :   "zmWIfeduXSavIsb3a43/MLIz/9qO0TkgAAiuQr79JlwKhLdzCqTLAgED\n"
     569             :   "-----END RSA PUBLIC KEY-----\n"
     570             :   "ntor-onion-key NkRB4wTUFogiVp5jYmjGORe2ffb/y5Kk8Itw8jdzMjA=\n"
     571             :   "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"
     572             :   "id rsa1024 fKvYjP7TAjCC1FzYee5bYAwYkoDg\n"
     573             :   /* Bad 3: Bogus annotation */
     574             :   "@last-listed with strange aeons\n"
     575             :   "onion-key\n"
     576             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     577             :   "MIGJAoGBALcRBFNCZtpd2TFJysU77/fJMFzKisRQEBOtDGtTZ2Bg4aEGosssa0Id\n"
     578             :   "YtUagRLYle08QVGvGB+EHBI5qf6Ah2yPH7k5QiN2a3Sq+nyh85dXKPazBGBBbM+C\n"
     579             :   "DOfDauV02CAnADNMLJEf1voY3oBVvYyIsmHxn5i1R19ZYIiR8NX5AgMBAAE=\n"
     580             :   "-----END RSA PUBLIC KEY-----\n"
     581             :   "ntor-onion-key m4xcFXMWMjCvZDXq8FT3XmS0EHYseGOeu+fV+6FYDlk=\n"
     582             :   "p accept 20-23,43,53,79-81,88,110,143,194,220,389,443,464,531,543-544\n"
     583             :   "id rsa1024 SSbfNE9vmaiwRKH+eqNAkiKQhds\n"
     584             :   /* Good 10: Normal, with added ipv6 address and added other address */
     585             :   "onion-key\n"
     586             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     587             :   "MIGJAoGBAM7uUtq5F6h63QNYIvC+4NcWaD0DjtnrOORZMkdpJhinXUOwce3cD5Dj\n"
     588             :   "sgdN1wJpWpTQMXJ2DssfSgmOVXETP7qJuZyRprxalQhaEATMDNJA/66Ml1jSO9mZ\n"
     589             :   "+8Xb7m/4q778lNtkSbsvMaYD2Dq6k2QQ3kMhr9z8oUtX0XA23+pfAgMBAAE=\n"
     590             :   "-----END RSA PUBLIC KEY-----\n"
     591             :   "a [::1:2:3:4]:9090\n"
     592             :   "a 18.0.0.1:9999\n"
     593             :   "ntor-onion-key k2yFqTU2vzMCQDEiE/j9UcEHxKrXMLpB3IL0or09sik=\n"
     594             :   "id rsa1024 2A8wYpHxnkKJ92orocvIQBzeHlE\n"
     595             :   "p6 allow 80\n"
     596             :   /* Good 11: Normal, non-exit relay with ipv6 address */
     597             :   "onion-key\n"
     598             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     599             :   "MIGJAoGBAM7uUtq5F6h63QNYIvC+4NcWaD0DjtnrOORZMkdpJhinXUOwce3cD5Dj\n"
     600             :   "sgdN1wJpWpTQMXJ2DssfSgmOVXETP7qJuZyRprxalQhaEATMDNJA/66Ml1jSO9mZ\n"
     601             :   "+8Xb7m/4q778lNtkSbsvMaYD2Dq6k2QQ3kMhr9z8oUtX0XA23+pfAgMBAAE=\n"
     602             :   "-----END RSA PUBLIC KEY-----\n"
     603             :   "a [::1:2:3:4]:9090\n"
     604             :   "a 18.0.0.1:9999\n"
     605             :   "ntor-onion-key k2yFqTU2vzMCQDEiE/j9UcEHxKrXMLpB3IL0or09sik=\n"
     606             :   "id rsa1024 2A8wYpHxnkKJ92orocvIQBzeHlE\n"
     607             :   /* Good 12: Normal, exit relay with ipv6 address */
     608             :   "onion-key\n"
     609             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     610             :   "MIGJAoGBAM7uUtq5F6h63QNYIvC+4NcWaD0DjtnrOORZMkdpJhinXUOwce3cD5Dj\n"
     611             :   "sgdN1wJpWpTQMXJ2DssfSgmOVXETP7qJuZyRprxalQhaEATMDNJA/66Ml1jSO9mZ\n"
     612             :   "+8Xb7m/4q778lNtkSbsvMaYD2Dq6k2QQ3kMhr9z8oUtX0XA23+pfAgMBAAE=\n"
     613             :   "-----END RSA PUBLIC KEY-----\n"
     614             :   "a [::1:2:3:4]:9090\n"
     615             :   "a 18.0.0.1:9999\n"
     616             :   "ntor-onion-key k2yFqTU2vzMCQDEiE/j9UcEHxKrXMLpB3IL0or09sik=\n"
     617             :   "p accept 20-23,43,53,79-81,88,110,143,194,220,389,443,464,531,543-544\n"
     618             :   "id rsa1024 2A8wYpHxnkKJ92orocvIQBzeHlE\n"
     619             :   /* Good 13: Normal, exit relay with only ipv6 exit policy */
     620             :   "onion-key\n"
     621             :   "-----BEGIN RSA PUBLIC KEY-----\n"
     622             :   "MIGJAoGBAM7uUtq5F6h63QNYIvC+4NcWaD0DjtnrOORZMkdpJhinXUOwce3cD5Dj\n"
     623             :   "sgdN1wJpWpTQMXJ2DssfSgmOVXETP7qJuZyRprxalQhaEATMDNJA/66Ml1jSO9mZ\n"
     624             :   "+8Xb7m/4q778lNtkSbsvMaYD2Dq6k2QQ3kMhr9z8oUtX0XA23+pfAgMBAAE=\n"
     625             :   "-----END RSA PUBLIC KEY-----\n"
     626             :   "a [::1:2:3:4]:9090\n"
     627             :   "a 18.0.0.1:9999\n"
     628             :   "ntor-onion-key k2yFqTU2vzMCQDEiE/j9UcEHxKrXMLpB3IL0or09sik=\n"
     629             :   "p6 accept 20-23,43,53,79-81,88,110,143,194,220,389,443,464,531,543-544\n"
     630             :   "id rsa1024 2A8wYpHxnkKJ92orocvIQBzeHlE\n"
     631             :   ;
     632             : #ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
     633             : ENABLE_GCC_WARNING("-Woverlength-strings")
     634             : #endif
     635             : 
     636             : /** More tests for parsing different kinds of microdescriptors, and getting
     637             :  * invalid digests trackd from them. */
     638             : static void
     639           1 : test_md_parse(void *arg)
     640             : {
     641           1 :   (void) arg;
     642           1 :   char *mem_op_hex_tmp = NULL;
     643           1 :   smartlist_t *invalid = smartlist_new();
     644             : 
     645           1 :   smartlist_t *mds = microdescs_parse_from_string(MD_PARSE_TEST_DATA,
     646             :                                                   NULL, 1, SAVED_NOWHERE,
     647             :                                                   invalid);
     648           1 :   tt_int_op(smartlist_len(mds), OP_EQ, 14);
     649           1 :   tt_int_op(smartlist_len(invalid), OP_EQ, 4);
     650             : 
     651           1 :   test_memeq_hex(smartlist_get(invalid,0),
     652             :                  "5d76bf1c6614e885614a1e0ad074e1ab"
     653             :                  "4ea14655ebeefb1736a71b5ed8a15a51");
     654           1 :   test_memeq_hex(smartlist_get(invalid,1),
     655             :                  "2fde0ee3343669c2444cd9d53cbd39c6"
     656             :                  "a7d1fc0513513e840ca7f6e68864b36c");
     657           1 :   test_memeq_hex(smartlist_get(invalid,2),
     658             :                  "20d1576c5ab11bbcff0dedb1db4a3cfc"
     659             :                  "c8bc8dd839d8cbfef92d00a1a7d7b294");
     660           1 :   test_memeq_hex(smartlist_get(invalid,3),
     661             :                  "074770f394c73dbde7b44412e9692add"
     662             :                  "691a478d4727f9804b77646c95420a96");
     663             : 
     664             :   /* Spot-check the valid ones. */
     665           1 :   const microdesc_t *md = smartlist_get(mds, 5);
     666           1 :   test_memeq_hex(md->digest,
     667             :                  "54bb6d733ddeb375d2456c79ae103961"
     668             :                  "da0cae29620375ac4cf13d54da4d92b3");
     669           1 :   tt_int_op(md->last_listed, OP_EQ, 0);
     670           1 :   tt_int_op(md->saved_location, OP_EQ, SAVED_NOWHERE);
     671           1 :   tt_int_op(md->no_save, OP_EQ, 0);
     672           1 :   tt_uint_op(md->held_in_map, OP_EQ, 0);
     673           1 :   tt_uint_op(md->held_by_nodes, OP_EQ, 0);
     674           1 :   tt_assert(md->onion_curve25519_pkey);
     675             : 
     676           1 :   md = smartlist_get(mds, 6);
     677           1 :   test_memeq_hex(md->digest,
     678             :                  "53f740bd222ab37f19f604b1d3759aa6"
     679             :                  "5eff1fbce9ac254bd0fa50d4af9b1bae");
     680           1 :   tt_assert(! md->exit_policy);
     681             : 
     682           1 :   md = smartlist_get(mds, 8);
     683           1 :   test_memeq_hex(md->digest,
     684             :                  "a0a155562d8093d8fd0feb7b93b7226e"
     685             :                  "17f056c2142aab7a4ea8c5867a0376d5");
     686           1 :   tt_assert(md->onion_curve25519_pkey);
     687             : 
     688           1 :   md = smartlist_get(mds, 10);
     689           1 :   test_memeq_hex(md->digest,
     690             :                  "409ebd87d23925a2732bd467a92813c9"
     691             :                  "21ca378fcb9ca193d354c51550b6d5e9");
     692           1 :   tt_assert(tor_addr_family(&md->ipv6_addr) == AF_INET6);
     693           1 :   tt_int_op(md->ipv6_orport, OP_EQ, 9090);
     694             : 
     695           1 :   md = smartlist_get(mds, 11);
     696           1 :   tt_assert(tor_addr_family(&md->ipv6_addr) == AF_INET6);
     697           1 :   tt_int_op(md->ipv6_orport, OP_EQ, 9090);
     698           1 :   tt_int_op(md->policy_is_reject_star, OP_EQ, 1);
     699             : 
     700           1 :   md = smartlist_get(mds, 12);
     701           1 :   tt_assert(tor_addr_family(&md->ipv6_addr) == AF_INET6);
     702           1 :   tt_int_op(md->ipv6_orport, OP_EQ, 9090);
     703           1 :   tt_int_op(md->policy_is_reject_star, OP_EQ, 0);
     704             : 
     705           1 :   md = smartlist_get(mds, 13);
     706           1 :   tt_assert(tor_addr_family(&md->ipv6_addr) == AF_INET6);
     707           1 :   tt_int_op(md->ipv6_orport, OP_EQ, 9090);
     708           1 :   tt_int_op(md->policy_is_reject_star, OP_EQ, 0);
     709             : 
     710           1 :  done:
     711          15 :   SMARTLIST_FOREACH(mds, microdesc_t *, mdsc, microdesc_free(mdsc));
     712           1 :   smartlist_free(mds);
     713           5 :   SMARTLIST_FOREACH(invalid, char *, cp, tor_free(cp));
     714           1 :   smartlist_free(invalid);
     715           1 :   tor_free(mem_op_hex_tmp);
     716           1 : }
     717             : 
     718             : static void
     719           1 : test_md_parse_id_ed25519(void *arg)
     720             : {
     721           1 :   (void)arg;
     722             : 
     723             :   /* A correct MD with an ed25519 ID ... and an unspecified ID type,
     724             :    * which is permitted. */
     725           1 :   const char GOOD_MD[] =
     726             :     "onion-key\n"
     727             :     "-----BEGIN RSA PUBLIC KEY-----\n"
     728             :     "MIGJAoGBAM7uUtq5F6h63QNYIvC+4NcWaD0DjtnrOORZMkdpJhinXUOwce3cD5Dj\n"
     729             :     "sgdN1wJpWpTQMXJ2DssfSgmOVXETP7qJuZyRprxalQhaEATMDNJA/66Ml1jSO9mZ\n"
     730             :     "+8Xb7m/4q778lNtkSbsvMaYD2Dq6k2QQ3kMhr9z8oUtX0XA23+pfAgMBAAE=\n"
     731             :     "-----END RSA PUBLIC KEY-----\n"
     732             :     "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n"
     733             :     "id ed25519 VGhpcyBpc24ndCBhY3R1YWxseSBhIHB1YmxpYyBrZXk\n"
     734             :     "id wumpus dodecahedron\n";
     735             : 
     736           1 :   smartlist_t *mds = NULL;
     737           1 :   const microdesc_t *md;
     738             : 
     739           1 :   mds = microdescs_parse_from_string(GOOD_MD,
     740             :                                      NULL, 1, SAVED_NOWHERE, NULL);
     741           1 :   tt_assert(mds);
     742           1 :   tt_int_op(smartlist_len(mds), OP_EQ, 1);
     743           1 :   md = smartlist_get(mds, 0);
     744           1 :   tt_mem_op(md->ed25519_identity_pkey, OP_EQ,
     745           1 :             "This isn't actually a public key", ED25519_PUBKEY_LEN);
     746           2 :   SMARTLIST_FOREACH(mds, microdesc_t *, m, microdesc_free(m));
     747           1 :   smartlist_free(mds);
     748             : 
     749             :   /* As above, but ed25519 ID key appears twice. */
     750           1 :   const char DUPLICATE_KEY[] =
     751             :     "onion-key\n"
     752             :     "-----BEGIN RSA PUBLIC KEY-----\n"
     753             :     "MIGJAoGBAM7uUtq5F6h63QNYIvC+4NcWaD0DjtnrOORZMkdpJhinXUOwce3cD5Dj\n"
     754             :     "sgdN1wJpWpTQMXJ2DssfSgmOVXETP7qJuZyRprxalQhaEATMDNJA/66Ml1jSO9mZ\n"
     755             :     "+8Xb7m/4q778lNtkSbsvMaYD2Dq6k2QQ3kMhr9z8oUtX0XA23+pfAgMBAAE=\n"
     756             :     "-----END RSA PUBLIC KEY-----\n"
     757             :     "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs\n"
     758             :     "id ed25519 VGhpcyBpc24ndCBhY3R1YWxseSBhIHB1YmxpYyBrZXk\n"
     759             :     "id ed25519 VGhpcyBpc24ndCBhY3R1YWxseSBhIHB1YmxpYyBrZXk\n";
     760             : 
     761           1 :   setup_capture_of_logs(LOG_WARN);
     762           1 :   mds = microdescs_parse_from_string(DUPLICATE_KEY,
     763             :                                      NULL, 1, SAVED_NOWHERE, NULL);
     764           1 :   tt_assert(mds);
     765           1 :   tt_int_op(smartlist_len(mds), OP_EQ, 0); // no entries.
     766           1 :   expect_single_log_msg_containing("Extra ed25519 key");
     767           1 :   mock_clean_saved_logs();
     768           1 :   smartlist_free(mds);
     769             : 
     770             :   /* As above, but ed25519 ID key is invalid. */
     771           1 :   const char BOGUS_KEY[] =
     772             :     "onion-key\n"
     773             :     "-----BEGIN RSA PUBLIC KEY-----\n"
     774             :     "MIGJAoGBAM7uUtq5F6h63QNYIvC+4NcWaD0DjtnrOORZMkdpJhinXUOwce3cD5Dj\n"
     775             :     "sgdN1wJpWpTQMXJ2DssfSgmOVXETP7qJuZyRprxalQhaEATMDNJA/66Ml1jSO9mZ\n"
     776             :     "+8Xb7m/4q778lNtkSbsvMaYD2Dq6k2QQ3kMhr9z8oUtX0XA23+pfAgMBAAE=\n"
     777             :     "-----END RSA PUBLIC KEY-----\n"
     778             :     "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs\n"
     779             :     "id ed25519 VGhpcyBpc24ndCBhY3R1YWxseSBhIHB1YmxpYyZZZZZZZZZZZ\n";
     780             : 
     781           1 :   mds = microdescs_parse_from_string(BOGUS_KEY,
     782             :                                      NULL, 1, SAVED_NOWHERE, NULL);
     783           1 :   tt_assert(mds);
     784           1 :   tt_int_op(smartlist_len(mds), OP_EQ, 0); // no entries.
     785           1 :   expect_single_log_msg_containing("Bogus ed25519 key");
     786             : 
     787           1 :  done:
     788           1 :   if (mds) {
     789           1 :     SMARTLIST_FOREACH(mds, microdesc_t *, m, microdesc_free(m));
     790           1 :     smartlist_free(mds);
     791             :   }
     792           1 :   teardown_capture_of_logs();
     793           1 : }
     794             : 
     795             : static int mock_rgsbd_called = 0;
     796             : static routerstatus_t *mock_rgsbd_val_a = NULL;
     797             : static routerstatus_t *mock_rgsbd_val_b = NULL;
     798             : static routerstatus_t *
     799           2 : mock_router_get_status_by_digest(networkstatus_t *c, const char *d)
     800             : {
     801           2 :   (void) c;
     802           2 :   ++mock_rgsbd_called;
     803             : 
     804           2 :   if (fast_memeq(d, "\x5d\x76", 2)) {
     805           1 :     memcpy(mock_rgsbd_val_a->descriptor_digest, d, 32);
     806           1 :     return mock_rgsbd_val_a;
     807           1 :   } else if (fast_memeq(d, "\x20\xd1", 2)) {
     808           1 :     memcpy(mock_rgsbd_val_b->descriptor_digest, d, 32);
     809           1 :     return mock_rgsbd_val_b;
     810             :   } else {
     811             :     return NULL;
     812             :   }
     813             : }
     814             : 
     815             : static networkstatus_t *mock_ns_val = NULL;
     816             : static networkstatus_t *
     817           2 : mock_ns_get_by_flavor(consensus_flavor_t f)
     818             : {
     819           2 :   (void)f;
     820           2 :   return mock_ns_val;
     821             : }
     822             : 
     823             : static void
     824           1 : test_md_reject_cache(void *arg)
     825             : {
     826           1 :   (void) arg;
     827           1 :   microdesc_cache_t *mc = NULL ;
     828           1 :   smartlist_t *added = NULL, *wanted = smartlist_new();
     829           1 :   or_options_t *options = get_options_mutable();
     830           1 :   char buf[DIGEST256_LEN];
     831             : 
     832           1 :   tor_free(options->CacheDirectory);
     833           1 :   options->CacheDirectory = tor_strdup(get_fname("md_datadir_test_rej"));
     834           1 :   mock_rgsbd_val_a = tor_malloc_zero(sizeof(routerstatus_t));
     835           1 :   mock_rgsbd_val_b = tor_malloc_zero(sizeof(routerstatus_t));
     836           1 :   mock_ns_val = tor_malloc_zero(sizeof(networkstatus_t));
     837             : 
     838           1 :   mock_ns_val->valid_after = time(NULL) - 86400;
     839           1 :   mock_ns_val->valid_until = time(NULL) + 86400;
     840           1 :   mock_ns_val->flavor = FLAV_MICRODESC;
     841             : 
     842             : #ifdef _WIN32
     843             :   tt_int_op(0, OP_EQ, mkdir(options->CacheDirectory));
     844             : #else
     845           1 :   tt_int_op(0, OP_EQ, mkdir(options->CacheDirectory, 0700));
     846             : #endif
     847             : 
     848           1 :   MOCK(router_get_mutable_consensus_status_by_descriptor_digest,
     849             :        mock_router_get_status_by_digest);
     850           1 :   MOCK(networkstatus_get_latest_consensus_by_flavor, mock_ns_get_by_flavor);
     851             : 
     852           1 :   mc = get_microdesc_cache();
     853             : #define ADD(hex)                                                        \
     854             :   do {                                                                  \
     855             :     tt_int_op(sizeof(buf),OP_EQ,base16_decode(buf,sizeof(buf),          \
     856             :                 hex,strlen(hex)));\
     857             :     smartlist_add(wanted, tor_memdup(buf, DIGEST256_LEN));              \
     858             :   } while (0)
     859             : 
     860             :   /* invalid,0 */
     861           1 :   ADD("5d76bf1c6614e885614a1e0ad074e1ab4ea14655ebeefb1736a71b5ed8a15a51");
     862             :   /* invalid,2 */
     863           1 :   ADD("20d1576c5ab11bbcff0dedb1db4a3cfcc8bc8dd839d8cbfef92d00a1a7d7b294");
     864             :   /* valid, 6 */
     865           1 :   ADD("53f740bd222ab37f19f604b1d3759aa65eff1fbce9ac254bd0fa50d4af9b1bae");
     866             :   /* valid, 8 */
     867           1 :   ADD("a0a155562d8093d8fd0feb7b93b7226e17f056c2142aab7a4ea8c5867a0376d5");
     868             : 
     869           1 :   added = microdescs_add_to_cache(mc, MD_PARSE_TEST_DATA, NULL,
     870             :                                   SAVED_NOWHERE, 0, time(NULL), wanted);
     871             : 
     872           1 :   tt_int_op(smartlist_len(added), OP_EQ, 2);
     873           1 :   tt_int_op(mock_rgsbd_called, OP_EQ, 2);
     874           1 :   tt_int_op(mock_rgsbd_val_a->dl_status.n_download_failures, OP_EQ, 255);
     875           1 :   tt_int_op(mock_rgsbd_val_b->dl_status.n_download_failures, OP_EQ, 255);
     876             : 
     877           1 :  done:
     878           1 :   UNMOCK(networkstatus_get_latest_consensus_by_flavor);
     879           1 :   UNMOCK(router_get_mutable_consensus_status_by_descriptor_digest);
     880           1 :   tor_free(options->CacheDirectory);
     881           1 :   microdesc_free_all();
     882           1 :   smartlist_free(added);
     883           1 :   SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
     884           1 :   smartlist_free(wanted);
     885           1 :   tor_free(mock_rgsbd_val_a);
     886           1 :   tor_free(mock_rgsbd_val_b);
     887           1 :   tor_free(mock_ns_val);
     888           1 : }
     889             : 
     890             : static void
     891           1 : test_md_corrupt_desc(void *arg)
     892             : {
     893           1 :   char *cp = NULL;
     894           1 :   smartlist_t *sl = NULL;
     895           1 :   (void) arg;
     896             : 
     897           1 :   sl = microdescs_add_to_cache(get_microdesc_cache(),
     898             :                                "@last-listed 2015-06-22 10:00:00\n"
     899             :                                "onion-k\n",
     900             :                                NULL, SAVED_IN_JOURNAL, 0, time(NULL), NULL);
     901           1 :   tt_int_op(smartlist_len(sl), OP_EQ, 0);
     902           1 :   smartlist_free(sl);
     903             : 
     904           1 :   sl = microdescs_add_to_cache(get_microdesc_cache(),
     905             :                                "@last-listed 2015-06-22 10:00:00\n"
     906             :                                "wiggly\n",
     907             :                                NULL, SAVED_IN_JOURNAL, 0, time(NULL), NULL);
     908           1 :   tt_int_op(smartlist_len(sl), OP_EQ, 0);
     909           1 :   smartlist_free(sl);
     910             : 
     911           1 :   tor_asprintf(&cp, "%s\n%s", test_md1, "@foobar\nonion-wobble\n");
     912             : 
     913           2 :   sl = microdescs_add_to_cache(get_microdesc_cache(),
     914           1 :                                cp, cp+strlen(cp),
     915             :                                SAVED_IN_JOURNAL, 0, time(NULL), NULL);
     916           1 :   tt_int_op(smartlist_len(sl), OP_EQ, 0);
     917             : 
     918           1 :  done:
     919           1 :   tor_free(cp);
     920           1 :   smartlist_free(sl);
     921           1 : }
     922             : 
     923             : struct testcase_t microdesc_tests[] = {
     924             :   { "cache", test_md_cache, TT_FORK, NULL, NULL },
     925             :   { "broken_cache", test_md_cache_broken, TT_FORK, NULL, NULL },
     926             :   { "generate", test_md_generate, 0, NULL, NULL },
     927             :   { "parse", test_md_parse, 0, NULL, NULL },
     928             :   { "parse_id_ed25519", test_md_parse_id_ed25519, 0, NULL, NULL },
     929             :   { "reject_cache", test_md_reject_cache, TT_FORK, NULL, NULL },
     930             :   { "corrupt_desc", test_md_corrupt_desc, TT_FORK, NULL, NULL },
     931             :   END_OF_TESTCASES
     932             : };

Generated by: LCOV version 1.14