Edit changelog a little for clarity and conciseness
[tor.git] / src / test / test_extorport.c
blob1f92780177f8c7dc05206fcd000d548a7b8430d6
1 /* Copyright (c) 2013-2016, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 #define CONNECTION_PRIVATE
5 #define EXT_ORPORT_PRIVATE
6 #define MAIN_PRIVATE
7 #include "or.h"
8 #include "buffers.h"
9 #include "connection.h"
10 #include "connection_or.h"
11 #include "config.h"
12 #include "control.h"
13 #include "ext_orport.h"
14 #include "main.h"
15 #include "test.h"
17 /* Test connection_or_remove_from_ext_or_id_map and
18 * connection_or_set_ext_or_identifier */
19 static void
20 test_ext_or_id_map(void *arg)
22 or_connection_t *c1 = NULL, *c2 = NULL, *c3 = NULL;
23 char *idp = NULL, *idp2 = NULL;
24 (void)arg;
26 /* pre-initialization */
27 tt_ptr_op(NULL, OP_EQ,
28 connection_or_get_by_ext_or_id("xxxxxxxxxxxxxxxxxxxx"));
30 c1 = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
31 c2 = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
32 c3 = or_connection_new(CONN_TYPE_OR, AF_INET);
34 tt_ptr_op(c1->ext_or_conn_id, OP_NE, NULL);
35 tt_ptr_op(c2->ext_or_conn_id, OP_NE, NULL);
36 tt_ptr_op(c3->ext_or_conn_id, OP_EQ, NULL);
38 tt_ptr_op(c1, OP_EQ, connection_or_get_by_ext_or_id(c1->ext_or_conn_id));
39 tt_ptr_op(c2, OP_EQ, connection_or_get_by_ext_or_id(c2->ext_or_conn_id));
40 tt_ptr_op(NULL, OP_EQ,
41 connection_or_get_by_ext_or_id("xxxxxxxxxxxxxxxxxxxx"));
43 idp = tor_memdup(c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
45 /* Give c2 a new ID. */
46 connection_or_set_ext_or_identifier(c2);
47 tt_mem_op(idp, OP_NE, c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
48 idp2 = tor_memdup(c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
49 tt_assert(!tor_digest_is_zero(idp2));
51 tt_ptr_op(NULL, OP_EQ, connection_or_get_by_ext_or_id(idp));
52 tt_ptr_op(c2, OP_EQ, connection_or_get_by_ext_or_id(idp2));
54 /* Now remove it. */
55 connection_or_remove_from_ext_or_id_map(c2);
56 tt_ptr_op(NULL, OP_EQ, connection_or_get_by_ext_or_id(idp));
57 tt_ptr_op(NULL, OP_EQ, connection_or_get_by_ext_or_id(idp2));
59 done:
60 if (c1)
61 connection_free_(TO_CONN(c1));
62 if (c2)
63 connection_free_(TO_CONN(c2));
64 if (c3)
65 connection_free_(TO_CONN(c3));
66 tor_free(idp);
67 tor_free(idp2);
68 connection_or_clear_ext_or_id_map();
71 /* Simple connection_write_to_buf_impl_ replacement that unconditionally
72 * writes to outbuf. */
73 static void
74 connection_write_to_buf_impl_replacement(const char *string, size_t len,
75 connection_t *conn, int zlib)
77 (void) zlib;
79 tor_assert(string);
80 tor_assert(conn);
81 write_to_buf(string, len, conn->outbuf);
84 static char *
85 buf_get_contents(buf_t *buf, size_t *sz_out)
87 char *out;
88 *sz_out = buf_datalen(buf);
89 if (*sz_out >= ULONG_MAX)
90 return NULL; /* C'mon, really? */
91 out = tor_malloc(*sz_out + 1);
92 if (fetch_from_buf(out, (unsigned long)*sz_out, buf) != 0) {
93 tor_free(out);
94 return NULL;
96 out[*sz_out] = '\0'; /* Hopefully gratuitous. */
97 return out;
100 static void
101 test_ext_or_write_command(void *arg)
103 or_connection_t *c1;
104 char *cp = NULL;
105 char *buf = NULL;
106 size_t sz;
108 (void) arg;
109 MOCK(connection_write_to_buf_impl_,
110 connection_write_to_buf_impl_replacement);
112 c1 = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
113 tt_assert(c1);
115 /* Length too long */
116 tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 100, "X", 100000),
117 OP_LT, 0);
119 /* Empty command */
120 tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0x99, NULL, 0),
121 OP_EQ, 0);
122 cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
123 tt_int_op(sz, OP_EQ, 4);
124 tt_mem_op(cp, OP_EQ, "\x00\x99\x00\x00", 4);
125 tor_free(cp);
127 /* Medium command. */
128 tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0x99,
129 "Wai\0Hello", 9), OP_EQ, 0);
130 cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
131 tt_int_op(sz, OP_EQ, 13);
132 tt_mem_op(cp, OP_EQ, "\x00\x99\x00\x09Wai\x00Hello", 13);
133 tor_free(cp);
135 /* Long command */
136 buf = tor_malloc(65535);
137 memset(buf, 'x', 65535);
138 tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0xf00d,
139 buf, 65535), OP_EQ, 0);
140 cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
141 tt_int_op(sz, OP_EQ, 65539);
142 tt_mem_op(cp, OP_EQ, "\xf0\x0d\xff\xff", 4);
143 tt_mem_op(cp+4, OP_EQ, buf, 65535);
144 tor_free(cp);
146 done:
147 if (c1)
148 connection_free_(TO_CONN(c1));
149 tor_free(cp);
150 tor_free(buf);
151 UNMOCK(connection_write_to_buf_impl_);
154 static int
155 write_bytes_to_file_fail(const char *fname, const char *str, size_t len,
156 int bin)
158 (void) fname;
159 (void) str;
160 (void) len;
161 (void) bin;
163 return -1;
166 static void
167 test_ext_or_init_auth(void *arg)
169 or_options_t *options = get_options_mutable();
170 const char *fn;
171 char *cp = NULL;
172 struct stat st;
173 char cookie0[32];
174 (void)arg;
176 /* Check default filename location */
177 tor_free(options->DataDirectory);
178 options->DataDirectory = tor_strdup("foo");
179 cp = get_ext_or_auth_cookie_file_name();
180 tt_str_op(cp, OP_EQ, "foo"PATH_SEPARATOR"extended_orport_auth_cookie");
181 tor_free(cp);
183 /* Shouldn't be initialized already, or our tests will be a bit
184 * meaningless */
185 ext_or_auth_cookie = tor_malloc_zero(32);
186 tt_assert(tor_mem_is_zero((char*)ext_or_auth_cookie, 32));
188 /* Now make sure we use a temporary file */
189 fn = get_fname("ext_cookie_file");
190 options->ExtORPortCookieAuthFile = tor_strdup(fn);
191 cp = get_ext_or_auth_cookie_file_name();
192 tt_str_op(cp, OP_EQ, fn);
193 tor_free(cp);
195 /* Test the initialization function with a broken
196 write_bytes_to_file(). See if the problem is handled properly. */
197 MOCK(write_bytes_to_file, write_bytes_to_file_fail);
198 tt_int_op(-1, OP_EQ, init_ext_or_cookie_authentication(1));
199 tt_int_op(ext_or_auth_cookie_is_set, OP_EQ, 0);
200 UNMOCK(write_bytes_to_file);
202 /* Now do the actual initialization. */
203 tt_int_op(0, OP_EQ, init_ext_or_cookie_authentication(1));
204 tt_int_op(ext_or_auth_cookie_is_set, OP_EQ, 1);
205 cp = read_file_to_str(fn, RFTS_BIN, &st);
206 tt_ptr_op(cp, OP_NE, NULL);
207 tt_u64_op((uint64_t)st.st_size, OP_EQ, 64);
208 tt_mem_op(cp,OP_EQ, "! Extended ORPort Auth Cookie !\x0a", 32);
209 tt_mem_op(cp+32,OP_EQ, ext_or_auth_cookie, 32);
210 memcpy(cookie0, ext_or_auth_cookie, 32);
211 tt_assert(!tor_mem_is_zero((char*)ext_or_auth_cookie, 32));
213 /* Operation should be idempotent. */
214 tt_int_op(0, OP_EQ, init_ext_or_cookie_authentication(1));
215 tt_mem_op(cookie0,OP_EQ, ext_or_auth_cookie, 32);
217 done:
218 tor_free(cp);
219 ext_orport_free_all();
222 static void
223 test_ext_or_cookie_auth(void *arg)
225 char *reply=NULL, *reply2=NULL, *client_hash=NULL, *client_hash2=NULL;
226 size_t reply_len=0;
227 char hmac1[32], hmac2[32];
229 const char client_nonce[32] =
230 "Who is the third who walks alway";
231 char server_hash_input[] =
232 "ExtORPort authentication server-to-client hash"
233 "Who is the third who walks alway"
234 "................................";
235 char client_hash_input[] =
236 "ExtORPort authentication client-to-server hash"
237 "Who is the third who walks alway"
238 "................................";
240 (void)arg;
242 tt_int_op(strlen(client_hash_input), OP_EQ, 46+32+32);
243 tt_int_op(strlen(server_hash_input), OP_EQ, 46+32+32);
245 ext_or_auth_cookie = tor_malloc_zero(32);
246 memcpy(ext_or_auth_cookie, "s beside you? When I count, ther", 32);
247 ext_or_auth_cookie_is_set = 1;
249 /* For this authentication, the client sends 32 random bytes (ClientNonce)
250 * The server replies with 32 byte ServerHash and 32 byte ServerNonce,
251 * where ServerHash is:
252 * HMAC-SHA256(CookieString,
253 * "ExtORPort authentication server-to-client hash" | ClientNonce |
254 * ServerNonce)"
255 * The client must reply with 32-byte ClientHash, which we compute as:
256 * ClientHash is computed as:
257 * HMAC-SHA256(CookieString,
258 * "ExtORPort authentication client-to-server hash" | ClientNonce |
259 * ServerNonce)
262 /* Wrong length */
263 tt_int_op(-1, OP_EQ,
264 handle_client_auth_nonce(client_nonce, 33, &client_hash, &reply,
265 &reply_len));
266 tt_int_op(-1, OP_EQ,
267 handle_client_auth_nonce(client_nonce, 31, &client_hash, &reply,
268 &reply_len));
270 /* Now let's try this for real! */
271 tt_int_op(0, OP_EQ,
272 handle_client_auth_nonce(client_nonce, 32, &client_hash, &reply,
273 &reply_len));
274 tt_int_op(reply_len, OP_EQ, 64);
275 tt_ptr_op(reply, OP_NE, NULL);
276 tt_ptr_op(client_hash, OP_NE, NULL);
277 /* Fill in the server nonce into the hash inputs... */
278 memcpy(server_hash_input+46+32, reply+32, 32);
279 memcpy(client_hash_input+46+32, reply+32, 32);
280 /* Check the HMACs are correct... */
281 crypto_hmac_sha256(hmac1, (char*)ext_or_auth_cookie, 32, server_hash_input,
282 46+32+32);
283 crypto_hmac_sha256(hmac2, (char*)ext_or_auth_cookie, 32, client_hash_input,
284 46+32+32);
285 tt_mem_op(hmac1,OP_EQ, reply, 32);
286 tt_mem_op(hmac2,OP_EQ, client_hash, 32);
288 /* Now do it again and make sure that the results are *different* */
289 tt_int_op(0, OP_EQ,
290 handle_client_auth_nonce(client_nonce, 32, &client_hash2, &reply2,
291 &reply_len));
292 tt_mem_op(reply2,OP_NE, reply, reply_len);
293 tt_mem_op(client_hash2,OP_NE, client_hash, 32);
294 /* But that this one checks out too. */
295 memcpy(server_hash_input+46+32, reply2+32, 32);
296 memcpy(client_hash_input+46+32, reply2+32, 32);
297 /* Check the HMACs are correct... */
298 crypto_hmac_sha256(hmac1, (char*)ext_or_auth_cookie, 32, server_hash_input,
299 46+32+32);
300 crypto_hmac_sha256(hmac2, (char*)ext_or_auth_cookie, 32, client_hash_input,
301 46+32+32);
302 tt_mem_op(hmac1,OP_EQ, reply2, 32);
303 tt_mem_op(hmac2,OP_EQ, client_hash2, 32);
305 done:
306 tor_free(reply);
307 tor_free(client_hash);
308 tor_free(reply2);
309 tor_free(client_hash2);
312 static void
313 crypto_rand_return_tse_str(char *to, size_t n)
315 if (n != 32) {
316 TT_FAIL(("Asked for %d bytes, not 32", (int)n));
317 return;
319 memcpy(to, "te road There is always another ", 32);
322 static void
323 test_ext_or_cookie_auth_testvec(void *arg)
325 char *reply=NULL, *client_hash=NULL;
326 size_t reply_len;
327 char *mem_op_hex_tmp=NULL;
329 const char client_nonce[] = "But when I look ahead up the whi";
330 (void)arg;
332 ext_or_auth_cookie = tor_malloc_zero(32);
333 memcpy(ext_or_auth_cookie, "Gliding wrapt in a brown mantle," , 32);
334 ext_or_auth_cookie_is_set = 1;
336 MOCK(crypto_rand, crypto_rand_return_tse_str);
338 tt_int_op(0, OP_EQ,
339 handle_client_auth_nonce(client_nonce, 32, &client_hash, &reply,
340 &reply_len));
341 tt_ptr_op(reply, OP_NE, NULL );
342 tt_uint_op(reply_len, OP_EQ, 64);
343 tt_mem_op(reply+32,OP_EQ, "te road There is always another ", 32);
344 /* HMACSHA256("Gliding wrapt in a brown mantle,"
345 * "ExtORPort authentication server-to-client hash"
346 * "But when I look ahead up the write road There is always another ");
348 test_memeq_hex(reply,
349 "ec80ed6e546d3b36fdfc22fe1315416b"
350 "029f1ade7610d910878b62eeb7403821");
351 /* HMACSHA256("Gliding wrapt in a brown mantle,"
352 * "ExtORPort authentication client-to-server hash"
353 * "But when I look ahead up the write road There is always another ");
354 * (Both values computed using Python CLI.)
356 test_memeq_hex(client_hash,
357 "ab391732dd2ed968cd40c087d1b1f25b"
358 "33b3cd77ff79bd80c2074bbf438119a2");
360 done:
361 UNMOCK(crypto_rand);
362 tor_free(reply);
363 tor_free(client_hash);
364 tor_free(mem_op_hex_tmp);
367 static void
368 ignore_bootstrap_problem(const char *warn, int reason,
369 or_connection_t *conn)
371 (void)warn;
372 (void)reason;
373 (void)conn;
376 static int is_reading = 1;
377 static int handshake_start_called = 0;
379 static void
380 note_read_stopped(connection_t *conn)
382 (void)conn;
383 is_reading=0;
385 static void
386 note_read_started(connection_t *conn)
388 (void)conn;
389 is_reading=1;
391 static int
392 handshake_start(or_connection_t *conn, int receiving)
394 if (!conn || !receiving)
395 TT_FAIL(("Bad arguments to handshake_start"));
396 handshake_start_called = 1;
397 return 0;
400 #define WRITE(s,n) \
401 do { \
402 write_to_buf((s), (n), TO_CONN(conn)->inbuf); \
403 } while (0)
404 #define CONTAINS(s,n) \
405 do { \
406 tt_int_op((n), OP_LE, sizeof(b)); \
407 tt_int_op(buf_datalen(TO_CONN(conn)->outbuf), OP_EQ, (n)); \
408 if ((n)) { \
409 fetch_from_buf(b, (n), TO_CONN(conn)->outbuf); \
410 tt_mem_op(b, OP_EQ, (s), (n)); \
412 } while (0)
414 /* Helper: Do a successful Extended ORPort authentication handshake. */
415 static void
416 do_ext_or_handshake(or_connection_t *conn)
418 char b[256];
420 tt_int_op(0, OP_EQ, connection_ext_or_start_auth(conn));
421 CONTAINS("\x01\x00", 2);
422 WRITE("\x01", 1);
423 WRITE("But when I look ahead up the whi", 32);
424 MOCK(crypto_rand, crypto_rand_return_tse_str);
425 tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
426 UNMOCK(crypto_rand);
427 tt_int_op(TO_CONN(conn)->state, OP_EQ,
428 EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_HASH);
429 CONTAINS("\xec\x80\xed\x6e\x54\x6d\x3b\x36\xfd\xfc\x22\xfe\x13\x15\x41\x6b"
430 "\x02\x9f\x1a\xde\x76\x10\xd9\x10\x87\x8b\x62\xee\xb7\x40\x38\x21"
431 "te road There is always another ", 64);
432 /* Send the right response this time. */
433 WRITE("\xab\x39\x17\x32\xdd\x2e\xd9\x68\xcd\x40\xc0\x87\xd1\xb1\xf2\x5b"
434 "\x33\xb3\xcd\x77\xff\x79\xbd\x80\xc2\x07\x4b\xbf\x43\x81\x19\xa2",
435 32);
436 tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
437 CONTAINS("\x01", 1);
438 tt_assert(! TO_CONN(conn)->marked_for_close);
439 tt_int_op(TO_CONN(conn)->state, OP_EQ, EXT_OR_CONN_STATE_OPEN);
441 done: ;
444 static void
445 test_ext_or_handshake(void *arg)
447 or_connection_t *conn=NULL;
448 char b[256];
450 (void) arg;
451 MOCK(connection_write_to_buf_impl_,
452 connection_write_to_buf_impl_replacement);
453 /* Use same authenticators as for test_ext_or_cookie_auth_testvec */
454 ext_or_auth_cookie = tor_malloc_zero(32);
455 memcpy(ext_or_auth_cookie, "Gliding wrapt in a brown mantle," , 32);
456 ext_or_auth_cookie_is_set = 1;
458 init_connection_lists();
460 conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
461 tt_int_op(0, OP_EQ, connection_ext_or_start_auth(conn));
462 /* The server starts by telling us about the one supported authtype. */
463 CONTAINS("\x01\x00", 2);
464 /* Say the client hasn't responded yet. */
465 tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
466 /* Let's say the client replies badly. */
467 WRITE("\x99", 1);
468 tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
469 CONTAINS("", 0);
470 tt_assert(TO_CONN(conn)->marked_for_close);
471 close_closeable_connections();
472 conn = NULL;
474 /* Okay, try again. */
475 conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
476 tt_int_op(0, OP_EQ, connection_ext_or_start_auth(conn));
477 CONTAINS("\x01\x00", 2);
478 /* Let's say the client replies sensibly this time. "Yes, AUTHTYPE_COOKIE
479 * sounds delicious. Let's have some of that!" */
480 WRITE("\x01", 1);
481 /* Let's say that the client also sends part of a nonce. */
482 WRITE("But when I look ", 16);
483 tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
484 CONTAINS("", 0);
485 tt_int_op(TO_CONN(conn)->state, OP_EQ,
486 EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE);
487 /* Pump it again. Nothing should happen. */
488 tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
489 /* send the rest of the nonce. */
490 WRITE("ahead up the whi", 16);
491 MOCK(crypto_rand, crypto_rand_return_tse_str);
492 tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
493 UNMOCK(crypto_rand);
494 /* We should get the right reply from the server. */
495 CONTAINS("\xec\x80\xed\x6e\x54\x6d\x3b\x36\xfd\xfc\x22\xfe\x13\x15\x41\x6b"
496 "\x02\x9f\x1a\xde\x76\x10\xd9\x10\x87\x8b\x62\xee\xb7\x40\x38\x21"
497 "te road There is always another ", 64);
498 /* Send the wrong response. */
499 WRITE("not with a bang but a whimper...", 32);
500 MOCK(control_event_bootstrap_problem, ignore_bootstrap_problem);
501 tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
502 CONTAINS("\x00", 1);
503 tt_assert(TO_CONN(conn)->marked_for_close);
504 /* XXXX Hold-open-until-flushed. */
505 close_closeable_connections();
506 conn = NULL;
507 UNMOCK(control_event_bootstrap_problem);
509 MOCK(connection_start_reading, note_read_started);
510 MOCK(connection_stop_reading, note_read_stopped);
511 MOCK(connection_tls_start_handshake, handshake_start);
513 /* Okay, this time let's succeed. */
514 conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
515 do_ext_or_handshake(conn);
517 /* Now let's run through some messages. */
518 /* First let's send some junk and make sure it's ignored. */
519 WRITE("\xff\xf0\x00\x03""ABC", 7);
520 tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
521 CONTAINS("", 0);
522 /* Now let's send a USERADDR command. */
523 WRITE("\x00\x01\x00\x0c""1.2.3.4:5678", 16);
524 tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
525 tt_int_op(TO_CONN(conn)->port, OP_EQ, 5678);
526 tt_int_op(tor_addr_to_ipv4h(&TO_CONN(conn)->addr), OP_EQ, 0x01020304);
527 /* Now let's send a TRANSPORT command. */
528 WRITE("\x00\x02\x00\x07""rfc1149", 11);
529 tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
530 tt_ptr_op(NULL, OP_NE, conn->ext_or_transport);
531 tt_str_op("rfc1149", OP_EQ, conn->ext_or_transport);
532 tt_int_op(is_reading,OP_EQ,1);
533 tt_int_op(TO_CONN(conn)->state, OP_EQ, EXT_OR_CONN_STATE_OPEN);
534 /* DONE */
535 WRITE("\x00\x00\x00\x00", 4);
536 tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
537 tt_int_op(TO_CONN(conn)->state, OP_EQ, EXT_OR_CONN_STATE_FLUSHING);
538 tt_int_op(is_reading,OP_EQ,0);
539 CONTAINS("\x10\x00\x00\x00", 4);
540 tt_int_op(handshake_start_called,OP_EQ,0);
541 tt_int_op(0, OP_EQ, connection_ext_or_finished_flushing(conn));
542 tt_int_op(is_reading,OP_EQ,1);
543 tt_int_op(handshake_start_called,OP_EQ,1);
544 tt_int_op(TO_CONN(conn)->type, OP_EQ, CONN_TYPE_OR);
545 tt_int_op(TO_CONN(conn)->state, OP_EQ, 0);
546 close_closeable_connections();
547 conn = NULL;
549 /* Okay, this time let's succeed the handshake but fail the USERADDR
550 command. */
551 conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
552 do_ext_or_handshake(conn);
553 /* USERADDR command with an extra NUL byte */
554 WRITE("\x00\x01\x00\x0d""1.2.3.4:5678\x00", 17);
555 MOCK(control_event_bootstrap_problem, ignore_bootstrap_problem);
556 tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
557 CONTAINS("", 0);
558 tt_assert(TO_CONN(conn)->marked_for_close);
559 close_closeable_connections();
560 conn = NULL;
561 UNMOCK(control_event_bootstrap_problem);
563 /* Now fail the TRANSPORT command. */
564 conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
565 do_ext_or_handshake(conn);
566 /* TRANSPORT command with an extra NUL byte */
567 WRITE("\x00\x02\x00\x08""rfc1149\x00", 12);
568 MOCK(control_event_bootstrap_problem, ignore_bootstrap_problem);
569 tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
570 CONTAINS("", 0);
571 tt_assert(TO_CONN(conn)->marked_for_close);
572 close_closeable_connections();
573 conn = NULL;
574 UNMOCK(control_event_bootstrap_problem);
576 /* Now fail the TRANSPORT command. */
577 conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
578 do_ext_or_handshake(conn);
579 /* TRANSPORT command with transport name with symbols (not a
580 C-identifier) */
581 WRITE("\x00\x02\x00\x07""rf*1149", 11);
582 MOCK(control_event_bootstrap_problem, ignore_bootstrap_problem);
583 tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
584 CONTAINS("", 0);
585 tt_assert(TO_CONN(conn)->marked_for_close);
586 close_closeable_connections();
587 conn = NULL;
588 UNMOCK(control_event_bootstrap_problem);
590 done:
591 UNMOCK(connection_write_to_buf_impl_);
592 UNMOCK(crypto_rand);
593 if (conn)
594 connection_free_(TO_CONN(conn));
595 #undef CONTAINS
596 #undef WRITE
599 struct testcase_t extorport_tests[] = {
600 { "id_map", test_ext_or_id_map, TT_FORK, NULL, NULL },
601 { "write_command", test_ext_or_write_command, TT_FORK, NULL, NULL },
602 { "init_auth", test_ext_or_init_auth, TT_FORK, NULL, NULL },
603 { "cookie_auth", test_ext_or_cookie_auth, TT_FORK, NULL, NULL },
604 { "cookie_auth_testvec", test_ext_or_cookie_auth_testvec, TT_FORK,
605 NULL, NULL },
606 { "handshake", test_ext_or_handshake, TT_FORK, NULL, NULL },
607 END_OF_TESTCASES