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 : };
|