123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- /* Copyright (c) 2013, The Tor Project, Inc. */
- /* See LICENSE for licensing information */
- #define CONNECTION_PRIVATE
- #define EXT_ORPORT_PRIVATE
- #include "or.h"
- #include "buffers.h"
- #include "connection.h"
- #include "ext_orport.h"
- #include "test.h"
- /* Test connection_or_remove_from_ext_or_id_map and
- * connection_or_set_ext_or_identifier */
- static void
- test_ext_or_id_map(void *arg)
- {
- or_connection_t *c1 = NULL, *c2 = NULL, *c3 = NULL;
- char *idp = NULL, *idp2 = NULL;
- (void)arg;
- /* pre-initialization */
- tt_ptr_op(NULL, ==, connection_or_get_by_ext_or_id("xxxxxxxxxxxxxxxxxxxx"));
- c1 = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
- c2 = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
- c3 = or_connection_new(CONN_TYPE_OR, AF_INET);
- tt_ptr_op(c1->ext_or_conn_id, !=, NULL);
- tt_ptr_op(c2->ext_or_conn_id, !=, NULL);
- tt_ptr_op(c3->ext_or_conn_id, ==, NULL);
- tt_ptr_op(c1, ==, connection_or_get_by_ext_or_id(c1->ext_or_conn_id));
- tt_ptr_op(c2, ==, connection_or_get_by_ext_or_id(c2->ext_or_conn_id));
- tt_ptr_op(NULL, ==, connection_or_get_by_ext_or_id("xxxxxxxxxxxxxxxxxxxx"));
- idp = tor_memdup(c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
- /* Give c2 a new ID. */
- connection_or_set_ext_or_identifier(c2);
- test_mem_op(idp, !=, c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
- idp2 = tor_memdup(c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
- tt_assert(!tor_digest_is_zero(idp2));
- tt_ptr_op(NULL, ==, connection_or_get_by_ext_or_id(idp));
- tt_ptr_op(c2, ==, connection_or_get_by_ext_or_id(idp2));
- /* Now remove it. */
- connection_or_remove_from_ext_or_id_map(c2);
- tt_ptr_op(NULL, ==, connection_or_get_by_ext_or_id(idp));
- tt_ptr_op(NULL, ==, connection_or_get_by_ext_or_id(idp2));
- done:
- if (c1)
- connection_free_(TO_CONN(c1));
- if (c2)
- connection_free_(TO_CONN(c2));
- if (c3)
- connection_free_(TO_CONN(c3));
- tor_free(idp);
- tor_free(idp2);
- connection_or_clear_ext_or_id_map();
- }
- /* Simple connection_write_to_buf_impl_ replacement that unconditionally
- * writes to outbuf. */
- static void
- connection_write_to_buf_impl_replacement(const char *string, size_t len,
- connection_t *conn, int zlib)
- {
- (void) zlib;
- tor_assert(string);
- tor_assert(conn);
- write_to_buf(string, len, conn->outbuf);
- }
- static char *
- buf_get_contents(buf_t *buf, size_t *sz_out)
- {
- char *out;
- *sz_out = buf_datalen(buf);
- if (*sz_out >= ULONG_MAX)
- return NULL; /* C'mon, really? */
- out = tor_malloc(*sz_out + 1);
- if (fetch_from_buf(out, (unsigned long)*sz_out, buf) != 0) {
- tor_free(out);
- return NULL;
- }
- out[*sz_out] = '\0'; /* Hopefully gratuitous. */
- return out;
- }
- static void
- test_ext_or_write_command(void *arg)
- {
- or_connection_t *c1;
- char *cp = NULL;
- char *buf = NULL;
- size_t sz;
- (void) arg;
- MOCK(connection_write_to_buf_impl_,
- connection_write_to_buf_impl_replacement);
- c1 = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
- tt_assert(c1);
- /* Length too long */
- tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 100, "X", 100000),
- <, 0);
- /* Empty command */
- tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0x99, NULL, 0),
- ==, 0);
- cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
- tt_int_op(sz, ==, 4);
- test_mem_op(cp, ==, "\x00\x99\x00\x00", 4);
- tor_free(cp);
- /* Medium command. */
- tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0x99,
- "Wai\0Hello", 9), ==, 0);
- cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
- tt_int_op(sz, ==, 13);
- test_mem_op(cp, ==, "\x00\x99\x00\x09Wai\x00Hello", 13);
- tor_free(cp);
- /* Long command */
- buf = tor_malloc(65535);
- memset(buf, 'x', 65535);
- tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0xf00d,
- buf, 65535), ==, 0);
- cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
- tt_int_op(sz, ==, 65539);
- test_mem_op(cp, ==, "\xf0\x0d\xff\xff", 4);
- test_mem_op(cp+4, ==, buf, 65535);
- tor_free(cp);
- done:
- if (c1)
- connection_free_(TO_CONN(c1));
- tor_free(cp);
- tor_free(buf);
- UNMOCK(connection_write_to_buf_impl_);
- }
- static void
- test_ext_or_cookie_auth(void *arg)
- {
- char *reply=NULL, *reply2=NULL, *client_hash=NULL, *client_hash2=NULL;
- size_t reply_len=0;
- char hmac1[32], hmac2[32];
- const char client_nonce[32] =
- "Who is the third who walks alway";
- char server_hash_input[] =
- "ExtORPort authentication server-to-client hash"
- "Who is the third who walks alway"
- "................................";
- char client_hash_input[] =
- "ExtORPort authentication client-to-server hash"
- "Who is the third who walks alway"
- "................................";
- (void)arg;
- tt_int_op(strlen(client_hash_input), ==, 46+32+32);
- tt_int_op(strlen(server_hash_input), ==, 46+32+32);
- memcpy(ext_or_auth_cookie, "s beside you? When I count, ther", 32);
- ext_or_auth_cookie_is_set = 1;
- /* For this authentication, the client sends 32 random bytes (ClientNonce)
- * The server replies with 32 byte ServerHash and 32 byte ServerNonce,
- * where ServerHash is:
- * HMAC-SHA256(CookieString,
- * "ExtORPort authentication server-to-client hash" | ClientNonce |
- * ServerNonce)"
- * The client must reply with 32-byte ClientHash, which we compute as:
- * ClientHash is computed as:
- * HMAC-SHA256(CookieString,
- * "ExtORPort authentication client-to-server hash" | ClientNonce |
- * ServerNonce)
- */
- /* Wrong length */
- tt_int_op(-1, ==,
- handle_client_auth_nonce(client_nonce, 33, &client_hash, &reply,
- &reply_len));
- tt_int_op(-1, ==,
- handle_client_auth_nonce(client_nonce, 31, &client_hash, &reply,
- &reply_len));
- /* Now let's try this for real! */
- tt_int_op(0, ==,
- handle_client_auth_nonce(client_nonce, 32, &client_hash, &reply,
- &reply_len));
- tt_int_op(reply_len, ==, 64);
- tt_ptr_op(reply, !=, NULL);
- tt_ptr_op(client_hash, !=, NULL);
- /* Fill in the server nonce into the hash inputs... */
- memcpy(server_hash_input+46+32, reply+32, 32);
- memcpy(client_hash_input+46+32, reply+32, 32);
- /* Check the HMACs are correct... */
- crypto_hmac_sha256(hmac1, ext_or_auth_cookie, 32, server_hash_input,
- 46+32+32);
- crypto_hmac_sha256(hmac2, ext_or_auth_cookie, 32, client_hash_input,
- 46+32+32);
- test_memeq(hmac1, reply, 32);
- test_memeq(hmac2, client_hash, 32);
- /* Now do it again and make sure that the results are *different* */
- tt_int_op(0, ==,
- handle_client_auth_nonce(client_nonce, 32, &client_hash2, &reply2,
- &reply_len));
- test_memneq(reply2, reply, reply_len);
- test_memneq(client_hash2, client_hash, 32);
- /* But that this one checks out too. */
- memcpy(server_hash_input+46+32, reply2+32, 32);
- memcpy(client_hash_input+46+32, reply2+32, 32);
- /* Check the HMACs are correct... */
- crypto_hmac_sha256(hmac1, ext_or_auth_cookie, 32, server_hash_input,
- 46+32+32);
- crypto_hmac_sha256(hmac2, ext_or_auth_cookie, 32, client_hash_input,
- 46+32+32);
- test_memeq(hmac1, reply2, 32);
- test_memeq(hmac2, client_hash2, 32);
- done:
- tor_free(reply);
- tor_free(client_hash);
- tor_free(reply2);
- tor_free(client_hash2);
- }
- static int
- crypto_rand_return_tse_str(char *to, size_t n)
- {
- if (n != 32) {
- TT_FAIL(("Asked for %d bytes, not 32", (int)n));
- return -1;
- }
- memcpy(to, "te road There is always another ", 32);
- return 0;
- }
- static void
- test_ext_or_cookie_auth_testvec(void *arg)
- {
- char *reply=NULL, *client_hash=NULL;
- size_t reply_len;
- char *mem_op_hex_tmp=NULL;
- const char client_nonce[] = "But when I look ahead up the whi";
- (void)arg;
- memcpy(ext_or_auth_cookie, "Gliding wrapt in a brown mantle," , 32);
- ext_or_auth_cookie_is_set = 1;
- MOCK(crypto_rand, crypto_rand_return_tse_str);
- tt_int_op(0, ==,
- handle_client_auth_nonce(client_nonce, 32, &client_hash, &reply,
- &reply_len));
- tt_ptr_op(reply, !=, NULL );
- tt_ptr_op(reply_len, ==, 64);
- test_memeq(reply+32, "te road There is always another ", 32);
- /* HMACSHA256("Gliding wrapt in a brown mantle,"
- * "ExtORPort authentication server-to-client hash"
- * "But when I look ahead up the write road There is always another ");
- */
- test_memeq_hex(reply,
- "ec80ed6e546d3b36fdfc22fe1315416b"
- "029f1ade7610d910878b62eeb7403821");
- /* HMACSHA256("Gliding wrapt in a brown mantle,"
- * "ExtORPort authentication client-to-server hash"
- * "But when I look ahead up the write road There is always another ");
- * (Both values computed using Python CLI.)
- */
- test_memeq_hex(client_hash,
- "ab391732dd2ed968cd40c087d1b1f25b"
- "33b3cd77ff79bd80c2074bbf438119a2");
- done:
- UNMOCK(crypto_rand);
- tor_free(reply);
- tor_free(client_hash);
- tor_free(mem_op_hex_tmp);
- }
- struct testcase_t extorport_tests[] = {
- { "id_map", test_ext_or_id_map, TT_FORK, NULL, NULL },
- { "write_command", test_ext_or_write_command, TT_FORK, NULL, NULL },
- { "cookie_auth", test_ext_or_cookie_auth, TT_FORK, NULL, NULL },
- { "cookie_auth_testvec", test_ext_or_cookie_auth_testvec, TT_FORK,
- NULL, NULL },
- END_OF_TESTCASES
- };
|