Line data Source code
1 : /* Copyright (c) 2013-2021, The Tor Project, Inc. */
2 : /* See LICENSE for licensing information */
3 :
4 : #define CONNECTION_PRIVATE
5 : #define EXT_ORPORT_PRIVATE
6 : #define MAINLOOP_PRIVATE
7 : #include "core/or/or.h"
8 : #include "lib/buf/buffers.h"
9 : #include "core/mainloop/connection.h"
10 : #include "core/or/connection_or.h"
11 : #include "app/config/config.h"
12 : #include "feature/control/control_events.h"
13 : #include "lib/crypt_ops/crypto_rand.h"
14 : #include "feature/relay/ext_orport.h"
15 : #include "core/mainloop/mainloop.h"
16 :
17 : #include "core/or/or_connection_st.h"
18 :
19 : #include "test/test.h"
20 : #include "test/test_helpers.h"
21 : #include "test/rng_test_helpers.h"
22 :
23 : #ifdef HAVE_SYS_STAT_H
24 : #include <sys/stat.h>
25 : #endif
26 :
27 : /* Simple connection_write_to_buf_impl_ replacement that unconditionally
28 : * writes to outbuf. */
29 : static void
30 22 : connection_write_to_buf_impl_replacement(const char *string, size_t len,
31 : connection_t *conn, int compressed)
32 : {
33 22 : (void) compressed;
34 :
35 22 : tor_assert(string);
36 22 : tor_assert(conn);
37 22 : buf_add(conn->outbuf, string, len);
38 22 : }
39 :
40 : static void
41 1 : test_ext_or_write_command(void *arg)
42 : {
43 1 : or_connection_t *c1;
44 1 : char *cp = NULL;
45 1 : char *buf = NULL;
46 1 : size_t sz;
47 :
48 1 : (void) arg;
49 1 : MOCK(connection_write_to_buf_impl_,
50 : connection_write_to_buf_impl_replacement);
51 :
52 1 : c1 = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
53 1 : tt_assert(c1);
54 :
55 : /* Length too long */
56 1 : tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 100, "X", 100000),
57 : OP_LT, 0);
58 :
59 : /* Empty command */
60 1 : tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0x99, NULL, 0),
61 : OP_EQ, 0);
62 1 : cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
63 1 : tt_int_op(sz, OP_EQ, 4);
64 1 : tt_mem_op(cp, OP_EQ, "\x00\x99\x00\x00", 4);
65 1 : tor_free(cp);
66 :
67 : /* Medium command. */
68 1 : tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0x99,
69 : "Wai\0Hello", 9), OP_EQ, 0);
70 1 : cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
71 1 : tt_int_op(sz, OP_EQ, 13);
72 1 : tt_mem_op(cp, OP_EQ, "\x00\x99\x00\x09Wai\x00Hello", 13);
73 1 : tor_free(cp);
74 :
75 : /* Long command */
76 1 : buf = tor_malloc(65535);
77 1 : memset(buf, 'x', 65535);
78 1 : tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0xf00d,
79 : buf, 65535), OP_EQ, 0);
80 1 : cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
81 1 : tt_int_op(sz, OP_EQ, 65539);
82 1 : tt_mem_op(cp, OP_EQ, "\xf0\x0d\xff\xff", 4);
83 1 : tt_mem_op(cp+4, OP_EQ, buf, 65535);
84 1 : tor_free(cp);
85 :
86 1 : done:
87 1 : if (c1)
88 1 : connection_free_minimal(TO_CONN(c1));
89 1 : tor_free(cp);
90 1 : tor_free(buf);
91 1 : UNMOCK(connection_write_to_buf_impl_);
92 1 : }
93 :
94 : static int
95 1 : write_bytes_to_file_fail(const char *fname, const char *str, size_t len,
96 : int bin)
97 : {
98 1 : (void) fname;
99 1 : (void) str;
100 1 : (void) len;
101 1 : (void) bin;
102 :
103 1 : return -1;
104 : }
105 :
106 : static void
107 1 : test_ext_or_init_auth(void *arg)
108 : {
109 1 : or_options_t *options = get_options_mutable();
110 1 : const char *fn;
111 1 : char *cp = NULL;
112 1 : struct stat st;
113 1 : char cookie0[32];
114 1 : (void)arg;
115 :
116 : /* Check default filename location */
117 1 : tor_free(options->DataDirectory);
118 1 : options->DataDirectory = tor_strdup("foo");
119 1 : cp = get_ext_or_auth_cookie_file_name();
120 1 : tt_str_op(cp, OP_EQ, "foo"PATH_SEPARATOR"extended_orport_auth_cookie");
121 1 : tor_free(cp);
122 :
123 : /* Shouldn't be initialized already, or our tests will be a bit
124 : * meaningless */
125 1 : ext_or_auth_cookie = tor_malloc_zero(32);
126 1 : tt_assert(fast_mem_is_zero((char*)ext_or_auth_cookie, 32));
127 :
128 : /* Now make sure we use a temporary file */
129 1 : fn = get_fname("ext_cookie_file");
130 1 : options->ExtORPortCookieAuthFile = tor_strdup(fn);
131 1 : cp = get_ext_or_auth_cookie_file_name();
132 1 : tt_str_op(cp, OP_EQ, fn);
133 1 : tor_free(cp);
134 :
135 : /* Test the initialization function with a broken
136 : write_bytes_to_file(). See if the problem is handled properly. */
137 1 : MOCK(write_bytes_to_file, write_bytes_to_file_fail);
138 1 : tt_int_op(-1, OP_EQ, init_ext_or_cookie_authentication(1));
139 1 : tt_int_op(ext_or_auth_cookie_is_set, OP_EQ, 0);
140 1 : UNMOCK(write_bytes_to_file);
141 :
142 : /* Now do the actual initialization. */
143 1 : tt_int_op(0, OP_EQ, init_ext_or_cookie_authentication(1));
144 1 : tt_int_op(ext_or_auth_cookie_is_set, OP_EQ, 1);
145 1 : cp = read_file_to_str(fn, RFTS_BIN, &st);
146 1 : tt_ptr_op(cp, OP_NE, NULL);
147 1 : tt_u64_op((uint64_t)st.st_size, OP_EQ, 64);
148 1 : tt_mem_op(cp,OP_EQ, "! Extended ORPort Auth Cookie !\x0a", 32);
149 1 : tt_mem_op(cp+32,OP_EQ, ext_or_auth_cookie, 32);
150 1 : memcpy(cookie0, ext_or_auth_cookie, 32);
151 1 : tt_assert(!fast_mem_is_zero((char*)ext_or_auth_cookie, 32));
152 :
153 : /* Operation should be idempotent. */
154 1 : tt_int_op(0, OP_EQ, init_ext_or_cookie_authentication(1));
155 1 : tt_mem_op(cookie0,OP_EQ, ext_or_auth_cookie, 32);
156 :
157 1 : done:
158 1 : tor_free(cp);
159 1 : ext_orport_free_all();
160 1 : }
161 :
162 : static void
163 1 : test_ext_or_cookie_auth(void *arg)
164 : {
165 1 : char *reply=NULL, *reply2=NULL, *client_hash=NULL, *client_hash2=NULL;
166 1 : size_t reply_len=0;
167 1 : char hmac1[32], hmac2[32];
168 :
169 1 : const char client_nonce[32] =
170 : "Who is the third who walks alway";
171 1 : char server_hash_input[] =
172 : "ExtORPort authentication server-to-client hash"
173 : "Who is the third who walks alway"
174 : "................................";
175 1 : char client_hash_input[] =
176 : "ExtORPort authentication client-to-server hash"
177 : "Who is the third who walks alway"
178 : "................................";
179 :
180 1 : (void)arg;
181 :
182 1 : tt_int_op(strlen(client_hash_input), OP_EQ, 46+32+32);
183 1 : tt_int_op(strlen(server_hash_input), OP_EQ, 46+32+32);
184 :
185 1 : ext_or_auth_cookie = tor_malloc_zero(32);
186 1 : memcpy(ext_or_auth_cookie, "s beside you? When I count, ther", 32);
187 1 : ext_or_auth_cookie_is_set = 1;
188 :
189 : /* For this authentication, the client sends 32 random bytes (ClientNonce)
190 : * The server replies with 32 byte ServerHash and 32 byte ServerNonce,
191 : * where ServerHash is:
192 : * HMAC-SHA256(CookieString,
193 : * "ExtORPort authentication server-to-client hash" | ClientNonce |
194 : * ServerNonce)"
195 : * The client must reply with 32-byte ClientHash, which we compute as:
196 : * ClientHash is computed as:
197 : * HMAC-SHA256(CookieString,
198 : * "ExtORPort authentication client-to-server hash" | ClientNonce |
199 : * ServerNonce)
200 : */
201 :
202 : /* Wrong length */
203 1 : tt_int_op(-1, OP_EQ,
204 : handle_client_auth_nonce(client_nonce, 33, &client_hash, &reply,
205 : &reply_len));
206 1 : tt_int_op(-1, OP_EQ,
207 : handle_client_auth_nonce(client_nonce, 31, &client_hash, &reply,
208 : &reply_len));
209 :
210 : /* Now let's try this for real! */
211 1 : tt_int_op(0, OP_EQ,
212 : handle_client_auth_nonce(client_nonce, 32, &client_hash, &reply,
213 : &reply_len));
214 1 : tt_int_op(reply_len, OP_EQ, 64);
215 1 : tt_ptr_op(reply, OP_NE, NULL);
216 1 : tt_ptr_op(client_hash, OP_NE, NULL);
217 : /* Fill in the server nonce into the hash inputs... */
218 1 : memcpy(server_hash_input+46+32, reply+32, 32);
219 1 : memcpy(client_hash_input+46+32, reply+32, 32);
220 : /* Check the HMACs are correct... */
221 1 : crypto_hmac_sha256(hmac1, (char*)ext_or_auth_cookie, 32, server_hash_input,
222 : 46+32+32);
223 1 : crypto_hmac_sha256(hmac2, (char*)ext_or_auth_cookie, 32, client_hash_input,
224 : 46+32+32);
225 1 : tt_mem_op(hmac1,OP_EQ, reply, 32);
226 1 : tt_mem_op(hmac2,OP_EQ, client_hash, 32);
227 :
228 : /* Now do it again and make sure that the results are *different* */
229 1 : tt_int_op(0, OP_EQ,
230 : handle_client_auth_nonce(client_nonce, 32, &client_hash2, &reply2,
231 : &reply_len));
232 1 : tt_mem_op(reply2,OP_NE, reply, reply_len);
233 1 : tt_mem_op(client_hash2,OP_NE, client_hash, 32);
234 : /* But that this one checks out too. */
235 1 : memcpy(server_hash_input+46+32, reply2+32, 32);
236 1 : memcpy(client_hash_input+46+32, reply2+32, 32);
237 : /* Check the HMACs are correct... */
238 1 : crypto_hmac_sha256(hmac1, (char*)ext_or_auth_cookie, 32, server_hash_input,
239 : 46+32+32);
240 1 : crypto_hmac_sha256(hmac2, (char*)ext_or_auth_cookie, 32, client_hash_input,
241 : 46+32+32);
242 1 : tt_mem_op(hmac1,OP_EQ, reply2, 32);
243 1 : tt_mem_op(hmac2,OP_EQ, client_hash2, 32);
244 :
245 1 : done:
246 1 : tor_free(reply);
247 1 : tor_free(client_hash);
248 1 : tor_free(reply2);
249 1 : tor_free(client_hash2);
250 1 : }
251 :
252 : static void
253 1 : test_ext_or_cookie_auth_testvec(void *arg)
254 : {
255 1 : char *reply=NULL, *client_hash=NULL;
256 1 : size_t reply_len;
257 1 : char *mem_op_hex_tmp=NULL;
258 :
259 1 : const char client_nonce[] = "But when I look ahead up the whi";
260 1 : (void)arg;
261 :
262 1 : ext_or_auth_cookie = tor_malloc_zero(32);
263 1 : memcpy(ext_or_auth_cookie, "Gliding wrapt in a brown mantle," , 32);
264 1 : ext_or_auth_cookie_is_set = 1;
265 :
266 1 : testing_enable_prefilled_rng("te road There is always another ", 32);
267 :
268 1 : tt_int_op(0, OP_EQ,
269 : handle_client_auth_nonce(client_nonce, 32, &client_hash, &reply,
270 : &reply_len));
271 1 : tt_ptr_op(reply, OP_NE, NULL );
272 1 : tt_uint_op(reply_len, OP_EQ, 64);
273 1 : tt_mem_op(reply+32,OP_EQ, "te road There is always another ", 32);
274 : /* HMACSHA256("Gliding wrapt in a brown mantle,"
275 : * "ExtORPort authentication server-to-client hash"
276 : * "But when I look ahead up the write road There is always another ");
277 : */
278 1 : test_memeq_hex(reply,
279 : "ec80ed6e546d3b36fdfc22fe1315416b"
280 : "029f1ade7610d910878b62eeb7403821");
281 : /* HMACSHA256("Gliding wrapt in a brown mantle,"
282 : * "ExtORPort authentication client-to-server hash"
283 : * "But when I look ahead up the write road There is always another ");
284 : * (Both values computed using Python CLI.)
285 : */
286 1 : test_memeq_hex(client_hash,
287 : "ab391732dd2ed968cd40c087d1b1f25b"
288 : "33b3cd77ff79bd80c2074bbf438119a2");
289 :
290 1 : done:
291 1 : testing_disable_prefilled_rng();
292 1 : tor_free(reply);
293 1 : tor_free(client_hash);
294 1 : tor_free(mem_op_hex_tmp);
295 1 : }
296 :
297 : static void
298 4 : ignore_bootstrap_problem(const char *warn, int reason,
299 : or_connection_t *conn)
300 : {
301 4 : (void)warn;
302 4 : (void)reason;
303 4 : (void)conn;
304 4 : }
305 :
306 : static int is_reading = 1;
307 : static int handshake_start_called = 0;
308 :
309 : static void
310 1 : note_read_stopped(connection_t *conn)
311 : {
312 1 : (void)conn;
313 1 : is_reading=0;
314 1 : }
315 : static void
316 1 : note_read_started(connection_t *conn)
317 : {
318 1 : (void)conn;
319 1 : is_reading=1;
320 1 : }
321 : static int
322 1 : handshake_start(or_connection_t *conn, int receiving)
323 : {
324 1 : if (!conn || !receiving)
325 0 : TT_FAIL(("Bad arguments to handshake_start"));
326 1 : handshake_start_called = 1;
327 1 : return 0;
328 : }
329 :
330 : #define WRITE(s,n) \
331 : do { \
332 : buf_add(TO_CONN(conn)->inbuf, (s), (n)); \
333 : } while (0)
334 : #define CONTAINS(s,n) \
335 : do { \
336 : tt_int_op((n), OP_LE, sizeof(b)); \
337 : tt_int_op(buf_datalen(TO_CONN(conn)->outbuf), OP_EQ, (n)); \
338 : if ((n)) { \
339 : buf_get_bytes(TO_CONN(conn)->outbuf, b, (n)); \
340 : tt_mem_op(b, OP_EQ, (s), (n)); \
341 : } \
342 : } while (0)
343 :
344 : /* Helper: Do a successful Extended ORPort authentication handshake. */
345 : static void
346 4 : do_ext_or_handshake(or_connection_t *conn)
347 : {
348 4 : char b[256];
349 :
350 4 : tt_int_op(0, OP_EQ, connection_ext_or_start_auth(conn));
351 4 : CONTAINS("\x01\x00", 2);
352 4 : WRITE("\x01", 1);
353 4 : WRITE("But when I look ahead up the whi", 32);
354 4 : testing_enable_prefilled_rng("te road There is always another ", 32);
355 4 : tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
356 4 : testing_disable_prefilled_rng();
357 4 : tt_int_op(TO_CONN(conn)->state, OP_EQ,
358 : EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_HASH);
359 4 : CONTAINS("\xec\x80\xed\x6e\x54\x6d\x3b\x36\xfd\xfc\x22\xfe\x13\x15\x41\x6b"
360 : "\x02\x9f\x1a\xde\x76\x10\xd9\x10\x87\x8b\x62\xee\xb7\x40\x38\x21"
361 : "te road There is always another ", 64);
362 : /* Send the right response this time. */
363 4 : WRITE("\xab\x39\x17\x32\xdd\x2e\xd9\x68\xcd\x40\xc0\x87\xd1\xb1\xf2\x5b"
364 : "\x33\xb3\xcd\x77\xff\x79\xbd\x80\xc2\x07\x4b\xbf\x43\x81\x19\xa2",
365 : 32);
366 4 : tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
367 4 : CONTAINS("\x01", 1);
368 4 : tt_assert(! TO_CONN(conn)->marked_for_close);
369 4 : tt_int_op(TO_CONN(conn)->state, OP_EQ, EXT_OR_CONN_STATE_OPEN);
370 :
371 4 : done: ;
372 4 : }
373 :
374 : static void
375 1 : test_ext_or_handshake(void *arg)
376 : {
377 1 : or_connection_t *conn=NULL;
378 1 : char b[256];
379 :
380 1 : (void) arg;
381 1 : MOCK(connection_write_to_buf_impl_,
382 : connection_write_to_buf_impl_replacement);
383 : /* Use same authenticators as for test_ext_or_cookie_auth_testvec */
384 1 : ext_or_auth_cookie = tor_malloc_zero(32);
385 1 : memcpy(ext_or_auth_cookie, "Gliding wrapt in a brown mantle," , 32);
386 1 : ext_or_auth_cookie_is_set = 1;
387 :
388 1 : tor_init_connection_lists();
389 :
390 1 : conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
391 1 : tt_int_op(0, OP_EQ, connection_ext_or_start_auth(conn));
392 : /* The server starts by telling us about the one supported authtype. */
393 1 : CONTAINS("\x01\x00", 2);
394 : /* Say the client hasn't responded yet. */
395 1 : tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
396 : /* Let's say the client replies badly. */
397 1 : WRITE("\x99", 1);
398 1 : tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
399 1 : CONTAINS("", 0);
400 1 : tt_assert(TO_CONN(conn)->marked_for_close);
401 1 : close_closeable_connections();
402 1 : conn = NULL;
403 :
404 : /* Okay, try again. */
405 1 : conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
406 1 : tt_int_op(0, OP_EQ, connection_ext_or_start_auth(conn));
407 1 : CONTAINS("\x01\x00", 2);
408 : /* Let's say the client replies sensibly this time. "Yes, AUTHTYPE_COOKIE
409 : * sounds delicious. Let's have some of that!" */
410 1 : WRITE("\x01", 1);
411 : /* Let's say that the client also sends part of a nonce. */
412 1 : WRITE("But when I look ", 16);
413 1 : tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
414 1 : CONTAINS("", 0);
415 1 : tt_int_op(TO_CONN(conn)->state, OP_EQ,
416 : EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE);
417 : /* Pump it again. Nothing should happen. */
418 1 : tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
419 : /* send the rest of the nonce. */
420 1 : WRITE("ahead up the whi", 16);
421 1 : testing_enable_prefilled_rng("te road There is always another ", 32);
422 1 : tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
423 1 : testing_disable_prefilled_rng();
424 : /* We should get the right reply from the server. */
425 1 : CONTAINS("\xec\x80\xed\x6e\x54\x6d\x3b\x36\xfd\xfc\x22\xfe\x13\x15\x41\x6b"
426 : "\x02\x9f\x1a\xde\x76\x10\xd9\x10\x87\x8b\x62\xee\xb7\x40\x38\x21"
427 : "te road There is always another ", 64);
428 : /* Send the wrong response. */
429 1 : WRITE("not with a bang but a whimper...", 32);
430 1 : MOCK(control_event_bootstrap_prob_or, ignore_bootstrap_problem);
431 1 : tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
432 1 : CONTAINS("\x00", 1);
433 1 : tt_assert(TO_CONN(conn)->marked_for_close);
434 : /* XXXX Hold-open-until-flushed. */
435 1 : close_closeable_connections();
436 1 : conn = NULL;
437 1 : UNMOCK(control_event_bootstrap_prob_or);
438 :
439 1 : MOCK(connection_start_reading, note_read_started);
440 1 : MOCK(connection_stop_reading, note_read_stopped);
441 1 : MOCK(connection_tls_start_handshake, handshake_start);
442 :
443 : /* Okay, this time let's succeed. */
444 1 : conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
445 1 : do_ext_or_handshake(conn);
446 :
447 : /* Now let's run through some messages. */
448 : /* First let's send some junk and make sure it's ignored. */
449 1 : WRITE("\xff\xf0\x00\x03""ABC", 7);
450 1 : tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
451 1 : CONTAINS("", 0);
452 : /* Now let's send a USERADDR command. */
453 1 : WRITE("\x00\x01\x00\x0c""1.2.3.4:5678", 16);
454 1 : tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
455 1 : tt_int_op(TO_CONN(conn)->port, OP_EQ, 5678);
456 1 : tt_int_op(tor_addr_to_ipv4h(&TO_CONN(conn)->addr), OP_EQ, 0x01020304);
457 : /* Now let's send a TRANSPORT command. */
458 1 : WRITE("\x00\x02\x00\x07""rfc1149", 11);
459 1 : tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
460 1 : tt_ptr_op(NULL, OP_NE, conn->ext_or_transport);
461 1 : tt_str_op("rfc1149", OP_EQ, conn->ext_or_transport);
462 1 : tt_int_op(is_reading,OP_EQ,1);
463 1 : tt_int_op(TO_CONN(conn)->state, OP_EQ, EXT_OR_CONN_STATE_OPEN);
464 : /* DONE */
465 1 : WRITE("\x00\x00\x00\x00", 4);
466 1 : tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
467 1 : tt_int_op(TO_CONN(conn)->state, OP_EQ, EXT_OR_CONN_STATE_FLUSHING);
468 1 : tt_int_op(is_reading,OP_EQ,0);
469 1 : CONTAINS("\x10\x00\x00\x00", 4);
470 1 : tt_int_op(handshake_start_called,OP_EQ,0);
471 1 : tt_int_op(0, OP_EQ, connection_ext_or_finished_flushing(conn));
472 1 : tt_int_op(is_reading,OP_EQ,1);
473 1 : tt_int_op(handshake_start_called,OP_EQ,1);
474 1 : tt_int_op(TO_CONN(conn)->type, OP_EQ, CONN_TYPE_OR);
475 1 : tt_int_op(TO_CONN(conn)->state, OP_EQ, 0);
476 1 : connection_free_(TO_CONN(conn));
477 1 : conn = NULL;
478 :
479 : /* Okay, this time let's succeed the handshake but fail the USERADDR
480 : command. */
481 1 : conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
482 1 : do_ext_or_handshake(conn);
483 : /* USERADDR command with an extra NUL byte */
484 1 : WRITE("\x00\x01\x00\x0d""1.2.3.4:5678\x00", 17);
485 1 : MOCK(control_event_bootstrap_prob_or, ignore_bootstrap_problem);
486 1 : tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
487 1 : CONTAINS("", 0);
488 1 : tt_assert(TO_CONN(conn)->marked_for_close);
489 1 : close_closeable_connections();
490 1 : conn = NULL;
491 1 : UNMOCK(control_event_bootstrap_prob_or);
492 :
493 : /* Now fail the TRANSPORT command. */
494 1 : conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
495 1 : do_ext_or_handshake(conn);
496 : /* TRANSPORT command with an extra NUL byte */
497 1 : WRITE("\x00\x02\x00\x08""rfc1149\x00", 12);
498 1 : MOCK(control_event_bootstrap_prob_or, ignore_bootstrap_problem);
499 1 : tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
500 1 : CONTAINS("", 0);
501 1 : tt_assert(TO_CONN(conn)->marked_for_close);
502 1 : close_closeable_connections();
503 1 : conn = NULL;
504 1 : UNMOCK(control_event_bootstrap_prob_or);
505 :
506 : /* Now fail the TRANSPORT command. */
507 1 : conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
508 1 : do_ext_or_handshake(conn);
509 : /* TRANSPORT command with transport name with symbols (not a
510 : C-identifier) */
511 1 : WRITE("\x00\x02\x00\x07""rf*1149", 11);
512 1 : MOCK(control_event_bootstrap_prob_or, ignore_bootstrap_problem);
513 1 : tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
514 1 : CONTAINS("", 0);
515 1 : tt_assert(TO_CONN(conn)->marked_for_close);
516 1 : close_closeable_connections();
517 1 : conn = NULL;
518 1 : UNMOCK(control_event_bootstrap_prob_or);
519 :
520 1 : done:
521 1 : UNMOCK(connection_write_to_buf_impl_);
522 1 : testing_disable_prefilled_rng();
523 1 : if (conn)
524 0 : connection_free_minimal(TO_CONN(conn));
525 : #undef CONTAINS
526 : #undef WRITE
527 1 : }
528 :
529 : struct testcase_t extorport_tests[] = {
530 : { "write_command", test_ext_or_write_command, TT_FORK, NULL, NULL },
531 : { "init_auth", test_ext_or_init_auth, TT_FORK, NULL, NULL },
532 : { "cookie_auth", test_ext_or_cookie_auth, TT_FORK, NULL, NULL },
533 : { "cookie_auth_testvec", test_ext_or_cookie_auth_testvec, TT_FORK,
534 : NULL, NULL },
535 : { "handshake", test_ext_or_handshake, TT_FORK, &helper_pubsub_setup, NULL },
536 : END_OF_TESTCASES
537 : };
|