diff options
Diffstat (limited to 'src/test')
152 files changed, 12048 insertions, 5477 deletions
diff --git a/src/test/bench.c b/src/test/bench.c index 92d7a244f7..959d4374b1 100644 --- a/src/test/bench.c +++ b/src/test/bench.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -10,20 +10,33 @@ #include "orconfig.h" -#include "or.h" -#include "onion_tap.h" -#include "relay.h" +#include "core/or/or.h" +#include "core/crypto/onion_tap.h" +#include "core/crypto/relay_crypto.h" + +#ifdef ENABLE_OPENSSL #include <openssl/opensslv.h> #include <openssl/evp.h> #include <openssl/ec.h> #include <openssl/ecdh.h> #include <openssl/obj_mac.h> +#endif + +#include "core/or/circuitlist.h" +#include "app/config/config.h" +#include "lib/crypt_ops/crypto_curve25519.h" +#include "lib/crypt_ops/crypto_dh.h" +#include "core/crypto/onion_ntor.h" +#include "lib/crypt_ops/crypto_ed25519.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "feature/dircommon/consdiff.h" +#include "lib/compress/compress.h" + +#include "core/or/cell_st.h" +#include "core/or/or_circuit_st.h" -#include "config.h" -#include "crypto_curve25519.h" -#include "onion_ntor.h" -#include "crypto_ed25519.h" -#include "consdiff.h" +#include "lib/crypt_ops/digestset.h" +#include "lib/crypt_ops/crypto_init.h" #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) static uint64_t nanostart; @@ -370,7 +383,7 @@ bench_dmap(void) crypto_rand(d, 20); smartlist_add(sl2, tor_memdup(d, 20)); } - printf("nbits=%d\n", ds->mask+1); + //printf("nbits=%d\n", ds->mask+1); reset_perftime(); @@ -398,18 +411,20 @@ bench_dmap(void) NANOCOUNT(pt3, pt4, iters*elts)); for (i = 0; i < iters; ++i) { - SMARTLIST_FOREACH(sl, const char *, cp, n += digestset_contains(ds, cp)); - SMARTLIST_FOREACH(sl2, const char *, cp, n += digestset_contains(ds, cp)); + SMARTLIST_FOREACH(sl, const char *, cp, + n += digestset_probably_contains(ds, cp)); + SMARTLIST_FOREACH(sl2, const char *, cp, + n += digestset_probably_contains(ds, cp)); } end = perftime(); - printf("digestset_contains: %.2f ns per element.\n", + printf("digestset_probably_contains: %.2f ns per element.\n", NANOCOUNT(pt4, end, iters*elts*2)); /* We need to use this, or else the whole loop gets optimized out. */ printf("Hits == %d\n", n); for (i = 0; i < fpostests; ++i) { crypto_rand(d, 20); - if (digestset_contains(ds, d)) ++fp; + if (digestset_probably_contains(ds, d)) ++fp; } printf("False positive rate on digestset: %.2f%%\n", (fp/(double)fpostests)*100); @@ -458,18 +473,19 @@ bench_digest(void) for (int i = 0; lens[i] > 0; ++i) { reset_perftime(); start = perftime(); + int failures = 0; for (int j = 0; j < N; ++j) { switch (alg) { case DIGEST_SHA1: - crypto_digest(out, buf, lens[i]); + failures += crypto_digest(out, buf, lens[i]) < 0; break; case DIGEST_SHA256: case DIGEST_SHA3_256: - crypto_digest256(out, buf, lens[i], alg); + failures += crypto_digest256(out, buf, lens[i], alg) < 0; break; case DIGEST_SHA512: case DIGEST_SHA3_512: - crypto_digest512(out, buf, lens[i], alg); + failures += crypto_digest512(out, buf, lens[i], alg) < 0; break; default: tor_assert(0); @@ -479,6 +495,8 @@ bench_digest(void) printf("%s(%d): %.2f ns per call\n", crypto_digest_algorithm_get_name(alg), lens[i], NANOCOUNT(start,end,N)); + if (failures) + printf("ERROR: crypto_digest failed %d times.\n", failures); } } } @@ -505,10 +523,10 @@ bench_cell_ops(void) char key1[CIPHER_KEY_LEN], key2[CIPHER_KEY_LEN]; crypto_rand(key1, sizeof(key1)); crypto_rand(key2, sizeof(key2)); - or_circ->p_crypto = crypto_cipher_new(key1); - or_circ->n_crypto = crypto_cipher_new(key2); - or_circ->p_digest = crypto_digest_new(); - or_circ->n_digest = crypto_digest_new(); + or_circ->crypto.f_crypto = crypto_cipher_new(key1); + or_circ->crypto.b_crypto = crypto_cipher_new(key2); + or_circ->crypto.f_digest = crypto_digest_new(); + or_circ->crypto.b_digest = crypto_digest_new(); reset_perftime(); @@ -518,7 +536,8 @@ bench_cell_ops(void) for (i = 0; i < iters; ++i) { char recognized = 0; crypt_path_t *layer_hint = NULL; - relay_crypt(TO_CIRCUIT(or_circ), cell, d, &layer_hint, &recognized); + relay_decrypt_cell(TO_CIRCUIT(or_circ), cell, d, + &layer_hint, &recognized); } end = perftime(); printf("%sbound cells: %.2f ns per cell. (%.2f ns per byte of payload)\n", @@ -527,10 +546,7 @@ bench_cell_ops(void) NANOCOUNT(start,end,iters*CELL_PAYLOAD_SIZE)); } - crypto_digest_free(or_circ->p_digest); - crypto_digest_free(or_circ->n_digest); - crypto_cipher_free(or_circ->p_crypto); - crypto_cipher_free(or_circ->n_crypto); + relay_crypto_clear(&or_circ->crypto); tor_free(or_circ); tor_free(cell); } @@ -545,8 +561,8 @@ bench_dh(void) reset_perftime(); start = perftime(); for (i = 0; i < iters; ++i) { - char dh_pubkey_a[DH_BYTES], dh_pubkey_b[DH_BYTES]; - char secret_a[DH_BYTES], secret_b[DH_BYTES]; + char dh_pubkey_a[DH1024_KEY_LEN], dh_pubkey_b[DH1024_KEY_LEN]; + char secret_a[DH1024_KEY_LEN], secret_b[DH1024_KEY_LEN]; ssize_t slen_a, slen_b; crypto_dh_t *dh_a = crypto_dh_new(DH_TYPE_TLS); crypto_dh_t *dh_b = crypto_dh_new(DH_TYPE_TLS); @@ -570,6 +586,7 @@ bench_dh(void) " %f millisec each.\n", NANOCOUNT(start, end, iters)/1e6); } +#ifdef ENABLE_OPENSSL static void bench_ecdh_impl(int nid, const char *name) { @@ -580,7 +597,7 @@ bench_ecdh_impl(int nid, const char *name) reset_perftime(); start = perftime(); for (i = 0; i < iters; ++i) { - char secret_a[DH_BYTES], secret_b[DH_BYTES]; + char secret_a[DH1024_KEY_LEN], secret_b[DH1024_KEY_LEN]; ssize_t slen_a, slen_b; EC_KEY *dh_a = EC_KEY_new_by_curve_name(nid); EC_KEY *dh_b = EC_KEY_new_by_curve_name(nid); @@ -591,10 +608,10 @@ bench_ecdh_impl(int nid, const char *name) EC_KEY_generate_key(dh_a); EC_KEY_generate_key(dh_b); - slen_a = ECDH_compute_key(secret_a, DH_BYTES, + slen_a = ECDH_compute_key(secret_a, DH1024_KEY_LEN, EC_KEY_get0_public_key(dh_b), dh_a, NULL); - slen_b = ECDH_compute_key(secret_b, DH_BYTES, + slen_b = ECDH_compute_key(secret_b, DH1024_KEY_LEN, EC_KEY_get0_public_key(dh_a), dh_b, NULL); @@ -619,6 +636,7 @@ bench_ecdh_p224(void) { bench_ecdh_impl(NID_secp224r1, "P-224"); } +#endif typedef void (*bench_fn)(void); @@ -642,8 +660,11 @@ static struct benchmark_t benchmarks[] = { ENT(cell_aes), ENT(cell_ops), ENT(dh), + +#ifdef ENABLE_OPENSSL ENT(ecdh_p256), ENT(ecdh_p224), +#endif {NULL,NULL,0} }; @@ -671,9 +692,9 @@ main(int argc, const char **argv) tor_threads_init(); tor_compress_init(); + init_logging(1); if (argc == 4 && !strcmp(argv[1], "diff")) { - init_logging(1); const int N = 200; char *f1 = read_file_to_str(argv[2], RFTS_BIN, NULL); char *f2 = read_file_to_str(argv[3], RFTS_BIN, NULL); @@ -709,13 +730,12 @@ main(int argc, const char **argv) reset_perftime(); - if (crypto_seed_rng() < 0) { + if (crypto_global_init(0, NULL, NULL) < 0) { printf("Couldn't seed RNG; exiting.\n"); return 1; } init_protocol_warning_severity_level(); - crypto_init_siphash_key(); options = options_new(); init_logging(1); options->command = CMD_RUN_UNITTESTS; @@ -739,4 +759,3 @@ main(int argc, const char **argv) return 0; } - diff --git a/src/test/bt_test.py b/src/test/bt_test.py index 4cb3326042..0eeb58c16c 100755 --- a/src/test/bt_test.py +++ b/src/test/bt_test.py @@ -1,4 +1,4 @@ -# Copyright 2013-2017, The Tor Project, Inc +# Copyright 2013-2018, The Tor Project, Inc # See LICENSE for licensing information """ diff --git a/src/test/ed25519_exts_ref.py b/src/test/ed25519_exts_ref.py index f84d3002d3..a9090c9ed2 100644 --- a/src/test/ed25519_exts_ref.py +++ b/src/test/ed25519_exts_ref.py @@ -1,5 +1,5 @@ #!/usr/bin/python -# Copyright 2014-2017, The Tor Project, Inc +# Copyright 2014-2018, The Tor Project, Inc # See LICENSE for licensing information """ diff --git a/src/test/fakechans.h b/src/test/fakechans.h index ab5d8461b6..0770be8e04 100644 --- a/src/test/fakechans.h +++ b/src/test/fakechans.h @@ -1,4 +1,4 @@ - /* Copyright (c) 2014-2017, The Tor Project, Inc. */ + /* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #ifndef TOR_FAKECHANS_H diff --git a/src/test/fuzz/dict/http b/src/test/fuzz/dict/http index 3b0531579d..63627ac380 100644 --- a/src/test/fuzz/dict/http +++ b/src/test/fuzz/dict/http @@ -4,7 +4,7 @@ # # Extracted from directory_handle_command() in the tor source code # -# Copyright (c) 2016-2017, The Tor Project, Inc. +# Copyright (c) 2016-2018, The Tor Project, Inc. # See LICENSE for licensing information # # Usage: diff --git a/src/test/fuzz/fuzz_consensus.c b/src/test/fuzz/fuzz_consensus.c index 6610ade7ad..b56702a650 100644 --- a/src/test/fuzz/fuzz_consensus.c +++ b/src/test/fuzz/fuzz_consensus.c @@ -1,10 +1,14 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define ROUTERPARSE_PRIVATE -#include "or.h" -#include "routerparse.h" -#include "networkstatus.h" -#include "fuzzing.h" +#define SIGCOMMON_PRIVATE +#include "core/or/or.h" +#include "feature/dirparse/ns_parse.h" +#include "feature/dirparse/sigcommon.h" +#include "feature/dirparse/unparseable.h" +#include "feature/nodelist/networkstatus.h" +#include "lib/crypt_ops/crypto_ed25519.h" +#include "feature/nodelist/networkstatus_st.h" +#include "test/fuzz/fuzzing.h" static void mock_dump_desc__nodump(const char *desc, const char *type) @@ -75,4 +79,3 @@ fuzz_main(const uint8_t *data, size_t sz) tor_free(str); return 0; } - diff --git a/src/test/fuzz/fuzz_descriptor.c b/src/test/fuzz/fuzz_descriptor.c index 1a50beae17..3420113717 100644 --- a/src/test/fuzz/fuzz_descriptor.c +++ b/src/test/fuzz/fuzz_descriptor.c @@ -1,11 +1,14 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define ROUTERPARSE_PRIVATE -#include "or.h" -#include "routerparse.h" -#include "routerlist.h" -#include "routerkeys.h" -#include "fuzzing.h" +#define SIGCOMMON_PRIVATE +#include "core/or/or.h" +#include "feature/dirparse/routerparse.h" +#include "feature/dirparse/sigcommon.h" +#include "feature/dirparse/unparseable.h" +#include "feature/nodelist/routerlist.h" +#include "feature/nodelist/torcert.h" +#include "feature/keymgt/loadkey.h" +#include "test/fuzz/fuzzing.h" static int mock_check_tap_onion_key_crosscert__nocheck(const uint8_t *crosscert, @@ -76,4 +79,3 @@ fuzz_main(const uint8_t *data, size_t sz) } return 0; } - diff --git a/src/test/fuzz/fuzz_diff.c b/src/test/fuzz/fuzz_diff.c index 642380b512..1079856fdb 100644 --- a/src/test/fuzz/fuzz_diff.c +++ b/src/test/fuzz/fuzz_diff.c @@ -1,13 +1,13 @@ -/* Copyright (c) 2016, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define CONSDIFF_PRIVATE #include "orconfig.h" -#include "or.h" -#include "consdiff.h" +#include "core/or/or.h" +#include "feature/dircommon/consdiff.h" -#include "fuzzing.h" +#include "test/fuzz/fuzzing.h" static int mock_consensus_compute_digest_(const char *c, consensus_digest_t *d) diff --git a/src/test/fuzz/fuzz_diff_apply.c b/src/test/fuzz/fuzz_diff_apply.c index 8d7bf751bf..165d0e6126 100644 --- a/src/test/fuzz/fuzz_diff_apply.c +++ b/src/test/fuzz/fuzz_diff_apply.c @@ -1,13 +1,13 @@ -/* Copyright (c) 2016, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define CONSDIFF_PRIVATE #include "orconfig.h" -#include "or.h" -#include "consdiff.h" +#include "core/or/or.h" +#include "feature/dircommon/consdiff.h" -#include "fuzzing.h" +#include "test/fuzz/fuzzing.h" static int mock_consensus_compute_digest_(const char *c, consensus_digest_t *d) diff --git a/src/test/fuzz/fuzz_extrainfo.c b/src/test/fuzz/fuzz_extrainfo.c index 2a3de7ecf7..da0fe80838 100644 --- a/src/test/fuzz/fuzz_extrainfo.c +++ b/src/test/fuzz/fuzz_extrainfo.c @@ -1,11 +1,13 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define ROUTERPARSE_PRIVATE -#include "or.h" -#include "routerparse.h" -#include "routerlist.h" -#include "routerkeys.h" -#include "fuzzing.h" +#define SIGCOMMON_PRIVATE +#include "core/or/or.h" +#include "feature/dirparse/routerparse.h" +#include "feature/dirparse/sigcommon.h" +#include "feature/dirparse/unparseable.h" +#include "feature/nodelist/routerlist.h" +#include "feature/relay/routerkeys.h" +#include "test/fuzz/fuzzing.h" static void mock_dump_desc__nodump(const char *desc, const char *type) diff --git a/src/test/fuzz/fuzz_hsdescv2.c b/src/test/fuzz/fuzz_hsdescv2.c index 19db265716..667b58b3aa 100644 --- a/src/test/fuzz/fuzz_hsdescv2.c +++ b/src/test/fuzz/fuzz_hsdescv2.c @@ -1,10 +1,11 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define ROUTERPARSE_PRIVATE -#include "or.h" -#include "routerparse.h" -#include "rendcommon.h" -#include "fuzzing.h" +#include "core/or/or.h" +#include "feature/dirparse/unparseable.h" +#include "feature/rend/rendcommon.h" +#include "feature/rend/rendparse.h" +#include "lib/crypt_ops/crypto_ed25519.h" +#include "test/fuzz/fuzzing.h" static void mock_dump_desc__nodump(const char *desc, const char *type) @@ -49,4 +50,3 @@ fuzz_main(const uint8_t *data, size_t sz) tor_free(str); return 0; } - diff --git a/src/test/fuzz/fuzz_hsdescv3.c b/src/test/fuzz/fuzz_hsdescv3.c index 428774e330..d5ddcc2e27 100644 --- a/src/test/fuzz/fuzz_hsdescv3.c +++ b/src/test/fuzz/fuzz_hsdescv3.c @@ -1,17 +1,15 @@ -/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define ROUTERPARSE_PRIVATE #define HS_DESCRIPTOR_PRIVATE -#include "or.h" -#include "ed25519_cert.h" /* Trunnel interface. */ -#include "crypto_ed25519.h" -#include "hs_descriptor.h" -#include "routerparse.h" -#include "util.h" +#include "core/or/or.h" +#include "trunnel/ed25519_cert.h" /* Trunnel interface. */ +#include "lib/crypt_ops/crypto_ed25519.h" +#include "feature/hs/hs_descriptor.h" +#include "feature/dirparse/unparseable.h" -#include "fuzzing.h" +#include "test/fuzz/fuzzing.h" static void mock_dump_desc__nodump(const char *desc, const char *type) @@ -39,11 +37,13 @@ static size_t mock_decrypt_desc_layer(const hs_descriptor_t *desc, const uint8_t *encrypted_blob, size_t encrypted_blob_size, + const uint8_t *descriptor_cookie, int is_superencrypted_layer, char **decrypted_out) { (void)is_superencrypted_layer; (void)desc; + (void)descriptor_cookie; const size_t overhead = HS_DESC_ENCRYPTED_SALT_LEN + DIGEST256_LEN; if (encrypted_blob_size < overhead) return 0; @@ -85,7 +85,7 @@ fuzz_main(const uint8_t *data, size_t sz) char *fuzzing_data = tor_memdup_nulterm(data, sz); memset(subcredential, 'A', sizeof(subcredential)); - hs_desc_decode_descriptor(fuzzing_data, subcredential, &desc); + hs_desc_decode_descriptor(fuzzing_data, subcredential, NULL, &desc); if (desc) { log_debug(LD_GENERAL, "Decoding okay"); hs_descriptor_free(desc); diff --git a/src/test/fuzz/fuzz_http.c b/src/test/fuzz/fuzz_http.c index 2ffeb60244..06483282bc 100644 --- a/src/test/fuzz/fuzz_http.c +++ b/src/test/fuzz/fuzz_http.c @@ -1,20 +1,22 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" #define BUFFERS_PRIVATE -#define DIRECTORY_PRIVATE +#define DIRCACHE_PRIVATE -#include "or.h" -#include "backtrace.h" -#include "buffers.h" -#include "config.h" -#include "connection.h" -#include "directory.h" -#include "torlog.h" +#include "core/or/or.h" +#include "lib/err/backtrace.h" +#include "lib/container/buffers.h" +#include "app/config/config.h" +#include "core/mainloop/connection.h" +#include "feature/dircache/dircache.h" +#include "lib/log/log.h" -#include "fuzzing.h" +#include "feature/dircommon/dir_connection_st.h" + +#include "test/fuzz/fuzzing.h" static void mock_connection_write_to_buf_impl_(const char *string, size_t len, @@ -130,4 +132,3 @@ fuzz_main(const uint8_t *stdin_buf, size_t data_size) return 0; } - diff --git a/src/test/fuzz/fuzz_http_connect.c b/src/test/fuzz/fuzz_http_connect.c index dc674070b2..ca007a2c7f 100644 --- a/src/test/fuzz/fuzz_http_connect.c +++ b/src/test/fuzz/fuzz_http_connect.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" @@ -6,16 +6,19 @@ #define BUFFERS_PRIVATE #define CONNECTION_EDGE_PRIVATE -#include "or.h" -#include "backtrace.h" -#include "buffers.h" -#include "config.h" -#include "connection.h" -#include "connection_edge.h" -#include "proto_socks.h" -#include "torlog.h" +#include "core/or/or.h" +#include "lib/err/backtrace.h" +#include "lib/container/buffers.h" +#include "app/config/config.h" +#include "core/mainloop/connection.h" +#include "core/or/connection_edge.h" +#include "core/proto/proto_socks.h" +#include "lib/log/log.h" -#include "fuzzing.h" +#include "core/or/entry_connection_st.h" +#include "core/or/socks_request_st.h" + +#include "test/fuzz/fuzzing.h" static void mock_connection_write_to_buf_impl_(const char *string, size_t len, diff --git a/src/test/fuzz/fuzz_iptsv2.c b/src/test/fuzz/fuzz_iptsv2.c index 4abde0c16d..265677eebe 100644 --- a/src/test/fuzz/fuzz_iptsv2.c +++ b/src/test/fuzz/fuzz_iptsv2.c @@ -1,10 +1,15 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define ROUTERPARSE_PRIVATE -#include "or.h" -#include "routerparse.h" -#include "rendcommon.h" -#include "fuzzing.h" + +#include "core/or/or.h" +#include "feature/dirparse/unparseable.h" +#include "feature/rend/rendcommon.h" +#include "feature/rend/rendparse.h" +#include "lib/crypt_ops/crypto_ed25519.h" + +#include "feature/rend/rend_service_descriptor_st.h" + +#include "test/fuzz/fuzzing.h" static void mock_dump_desc__nodump(const char *desc, const char *type) @@ -43,4 +48,3 @@ fuzz_main(const uint8_t *data, size_t sz) rend_service_descriptor_free(desc); return 0; } - diff --git a/src/test/fuzz/fuzz_microdesc.c b/src/test/fuzz/fuzz_microdesc.c index 396115026e..ab54cf2a34 100644 --- a/src/test/fuzz/fuzz_microdesc.c +++ b/src/test/fuzz/fuzz_microdesc.c @@ -1,10 +1,13 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define ROUTERPARSE_PRIVATE -#include "or.h" -#include "routerparse.h" -#include "microdesc.h" -#include "fuzzing.h" + +#include "core/or/or.h" +#include "feature/dirparse/microdesc_parse.h" +#include "feature/dirparse/unparseable.h" +#include "feature/nodelist/microdesc.h" +#include "lib/crypt_ops/crypto_ed25519.h" + +#include "test/fuzz/fuzzing.h" static void mock_dump_desc__nodump(const char *desc, const char *type) @@ -44,4 +47,3 @@ fuzz_main(const uint8_t *data, size_t sz) } return 0; } - diff --git a/src/test/fuzz/fuzz_socks.c b/src/test/fuzz/fuzz_socks.c new file mode 100644 index 0000000000..14c25304b1 --- /dev/null +++ b/src/test/fuzz/fuzz_socks.c @@ -0,0 +1,50 @@ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" + +#define BUFFERS_PRIVATE +#include "core/or/or.h" + +#include "lib/container/buffers.h" +#include "lib/err/backtrace.h" +#include "lib/log/log.h" +#include "core/proto/proto_socks.h" +#include "feature/client/addressmap.h" + +#include "test/fuzz/fuzzing.h" + +int +fuzz_init(void) +{ + addressmap_init(); + return 0; +} + +int +fuzz_cleanup(void) +{ + addressmap_free_all(); + return 0; +} + +int +fuzz_main(const uint8_t *stdin_buf, size_t data_size) +{ + buf_t *buffer = buf_new_with_data((char*)stdin_buf, data_size); + if (!buffer) { + tor_assert(data_size==0); + buffer = buf_new(); + } + + socks_request_t *request = socks_request_new(); + + int r = fetch_from_buf_socks(buffer, request, 0, 0); + log_info(LD_GENERAL, "Socks request status: %d", r); + + /* Reset. */ + buf_free(buffer); + socks_request_free(request); + + return 0; +} diff --git a/src/test/fuzz/fuzz_vrs.c b/src/test/fuzz/fuzz_vrs.c index baf0610a0b..0b869aa5c0 100644 --- a/src/test/fuzz/fuzz_vrs.c +++ b/src/test/fuzz/fuzz_vrs.c @@ -1,13 +1,19 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define ROUTERPARSE_PRIVATE +#define NS_PARSE_PRIVATE #define NETWORKSTATUS_PRIVATE -#include "or.h" -#include "routerparse.h" -#include "memarea.h" -#include "microdesc.h" -#include "networkstatus.h" -#include "fuzzing.h" +#include "core/or/or.h" +#include "feature/dirparse/ns_parse.h" +#include "feature/dirparse/unparseable.h" +#include "lib/memarea/memarea.h" +#include "feature/nodelist/microdesc.h" +#include "feature/nodelist/networkstatus.h" + +#include "feature/nodelist/networkstatus_st.h" +#include "feature/nodelist/vote_routerstatus_st.h" +#include "lib/crypt_ops/crypto_ed25519.h" + +#include "test/fuzz/fuzzing.h" static void mock_dump_desc__nodump(const char *desc, const char *type) @@ -79,4 +85,3 @@ fuzz_main(const uint8_t *data, size_t sz) tor_free(str); return 0; } - diff --git a/src/test/fuzz/fuzzing.h b/src/test/fuzz/fuzzing.h index aecdbb4e52..e90e5d58e0 100644 --- a/src/test/fuzz/fuzzing.h +++ b/src/test/fuzz/fuzzing.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #ifndef FUZZING_H #define FUZZING_H diff --git a/src/test/fuzz/fuzzing_common.c b/src/test/fuzz/fuzzing_common.c index a96552f0fc..1401e4c28d 100644 --- a/src/test/fuzz/fuzzing_common.c +++ b/src/test/fuzz/fuzzing_common.c @@ -1,13 +1,14 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define CRYPTO_ED25519_PRIVATE #include "orconfig.h" -#include "or.h" -#include "backtrace.h" -#include "config.h" -#include "fuzzing.h" -#include "crypto.h" -#include "crypto_ed25519.h" +#include "core/or/or.h" +#include "lib/err/backtrace.h" +#include "app/config/config.h" +#include "test/fuzz/fuzzing.h" +#include "lib/compress/compress.h" +#include "lib/crypt_ops/crypto_ed25519.h" +#include "lib/crypt_ops/crypto_init.h" static or_options_t *mock_options = NULL; static const or_options_t * @@ -95,15 +96,20 @@ global_init(void) { tor_threads_init(); tor_compress_init(); - { - struct sipkey sipkey = { 1337, 7331 }; - siphash_set_global_key(&sipkey); - } /* Initialise logging first */ init_logging(1); configure_backtrace_handler(get_version()); + if (crypto_global_init(0, NULL, NULL) < 0) + abort(); + + { + struct sipkey sipkey = { 1337, 7331 }; + siphash_unset_global_key(); + siphash_set_global_key(&sipkey); + } + /* set up the options. */ mock_options = tor_malloc_zero(sizeof(or_options_t)); MOCK(get_options, mock_get_options); @@ -189,4 +195,3 @@ main(int argc, char **argv) } #endif - diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am index cd16dc05be..27eeced8c5 100644 --- a/src/test/fuzz/include.am +++ b/src/test/fuzz/include.am @@ -5,33 +5,19 @@ FUZZING_CPPFLAGS = \ FUZZING_CFLAGS = \ $(AM_CFLAGS) $(TEST_CFLAGS) FUZZING_LDFLAG = \ - @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@ + @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) @TOR_LDFLAGS_libevent@ FUZZING_LIBS = \ - src/or/libtor-testing.a \ - src/common/libor-crypto-testing.a \ - $(LIBKECCAK_TINY) \ - $(LIBDONNA) \ - src/common/libor-testing.a \ - src/common/libor-ctime-testing.a \ - src/common/libor-event-testing.a \ - src/trunnel/libor-trunnel-testing.a \ + $(TOR_INTERNAL_TESTING_LIBS) \ $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \ - @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \ - @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@ \ + @TOR_LIBEVENT_LIBS@ $(TOR_LIBS_CRYPTLIB) \ + @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@ \ @TOR_SYSTEMD_LIBS@ \ @TOR_LZMA_LIBS@ \ @TOR_ZSTD_LIBS@ oss-fuzz-prereqs: \ - src/or/libtor-testing.a \ - src/common/libor-crypto-testing.a \ - $(LIBKECCAK_TINY) \ - $(LIBDONNA) \ - src/common/libor-testing.a \ - src/common/libor-ctime-testing.a \ - src/common/libor-event-testing.a \ - src/trunnel/libor-trunnel-testing.a + $(TOR_INTERNAL_TESTING_LIBS) noinst_HEADERS += \ src/test/fuzz/fuzzing.h @@ -46,6 +32,7 @@ LIBOSS_FUZZ_CPPFLAGS = $(FUZZING_CPPFLAGS) -DLLVM_FUZZ LIBOSS_FUZZ_CFLAGS = $(FUZZING_CFLAGS) # ===== AFL fuzzers +if UNITTESTS_ENABLED src_test_fuzz_fuzz_consensus_SOURCES = \ src/test/fuzz/fuzzing_common.c \ src/test/fuzz/fuzz_consensus.c @@ -53,7 +40,9 @@ src_test_fuzz_fuzz_consensus_CPPFLAGS = $(FUZZING_CPPFLAGS) src_test_fuzz_fuzz_consensus_CFLAGS = $(FUZZING_CFLAGS) src_test_fuzz_fuzz_consensus_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_consensus_LDADD = $(FUZZING_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_fuzz_descriptor_SOURCES = \ src/test/fuzz/fuzzing_common.c \ src/test/fuzz/fuzz_descriptor.c @@ -61,7 +50,9 @@ src_test_fuzz_fuzz_descriptor_CPPFLAGS = $(FUZZING_CPPFLAGS) src_test_fuzz_fuzz_descriptor_CFLAGS = $(FUZZING_CFLAGS) src_test_fuzz_fuzz_descriptor_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_descriptor_LDADD = $(FUZZING_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_fuzz_diff_SOURCES = \ src/test/fuzz/fuzzing_common.c \ src/test/fuzz/fuzz_diff.c @@ -69,7 +60,9 @@ src_test_fuzz_fuzz_diff_CPPFLAGS = $(FUZZING_CPPFLAGS) src_test_fuzz_fuzz_diff_CFLAGS = $(FUZZING_CFLAGS) src_test_fuzz_fuzz_diff_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_diff_LDADD = $(FUZZING_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_fuzz_diff_apply_SOURCES = \ src/test/fuzz/fuzzing_common.c \ src/test/fuzz/fuzz_diff_apply.c @@ -77,7 +70,9 @@ src_test_fuzz_fuzz_diff_apply_CPPFLAGS = $(FUZZING_CPPFLAGS) src_test_fuzz_fuzz_diff_apply_CFLAGS = $(FUZZING_CFLAGS) src_test_fuzz_fuzz_diff_apply_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_diff_apply_LDADD = $(FUZZING_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_fuzz_extrainfo_SOURCES = \ src/test/fuzz/fuzzing_common.c \ src/test/fuzz/fuzz_extrainfo.c @@ -85,7 +80,9 @@ src_test_fuzz_fuzz_extrainfo_CPPFLAGS = $(FUZZING_CPPFLAGS) src_test_fuzz_fuzz_extrainfo_CFLAGS = $(FUZZING_CFLAGS) src_test_fuzz_fuzz_extrainfo_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_extrainfo_LDADD = $(FUZZING_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_fuzz_hsdescv2_SOURCES = \ src/test/fuzz/fuzzing_common.c \ src/test/fuzz/fuzz_hsdescv2.c @@ -93,7 +90,9 @@ src_test_fuzz_fuzz_hsdescv2_CPPFLAGS = $(FUZZING_CPPFLAGS) src_test_fuzz_fuzz_hsdescv2_CFLAGS = $(FUZZING_CFLAGS) src_test_fuzz_fuzz_hsdescv2_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_hsdescv2_LDADD = $(FUZZING_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_fuzz_hsdescv3_SOURCES = \ src/test/fuzz/fuzzing_common.c \ src/test/fuzz/fuzz_hsdescv3.c @@ -101,7 +100,9 @@ src_test_fuzz_fuzz_hsdescv3_CPPFLAGS = $(FUZZING_CPPFLAGS) src_test_fuzz_fuzz_hsdescv3_CFLAGS = $(FUZZING_CFLAGS) src_test_fuzz_fuzz_hsdescv3_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_hsdescv3_LDADD = $(FUZZING_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_fuzz_http_SOURCES = \ src/test/fuzz/fuzzing_common.c \ src/test/fuzz/fuzz_http.c @@ -109,7 +110,9 @@ src_test_fuzz_fuzz_http_CPPFLAGS = $(FUZZING_CPPFLAGS) src_test_fuzz_fuzz_http_CFLAGS = $(FUZZING_CFLAGS) src_test_fuzz_fuzz_http_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_http_LDADD = $(FUZZING_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_fuzz_http_connect_SOURCES = \ src/test/fuzz/fuzzing_common.c \ src/test/fuzz/fuzz_http_connect.c @@ -117,7 +120,9 @@ src_test_fuzz_fuzz_http_connect_CPPFLAGS = $(FUZZING_CPPFLAGS) src_test_fuzz_fuzz_http_connect_CFLAGS = $(FUZZING_CFLAGS) src_test_fuzz_fuzz_http_connect_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_http_connect_LDADD = $(FUZZING_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_fuzz_iptsv2_SOURCES = \ src/test/fuzz/fuzzing_common.c \ src/test/fuzz/fuzz_iptsv2.c @@ -125,7 +130,9 @@ src_test_fuzz_fuzz_iptsv2_CPPFLAGS = $(FUZZING_CPPFLAGS) src_test_fuzz_fuzz_iptsv2_CFLAGS = $(FUZZING_CFLAGS) src_test_fuzz_fuzz_iptsv2_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_iptsv2_LDADD = $(FUZZING_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_fuzz_microdesc_SOURCES = \ src/test/fuzz/fuzzing_common.c \ src/test/fuzz/fuzz_microdesc.c @@ -133,7 +140,19 @@ src_test_fuzz_fuzz_microdesc_CPPFLAGS = $(FUZZING_CPPFLAGS) src_test_fuzz_fuzz_microdesc_CFLAGS = $(FUZZING_CFLAGS) src_test_fuzz_fuzz_microdesc_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_microdesc_LDADD = $(FUZZING_LIBS) +endif +if UNITTESTS_ENABLED +src_test_fuzz_fuzz_socks_SOURCES = \ + src/test/fuzz/fuzzing_common.c \ + src/test/fuzz/fuzz_socks.c +src_test_fuzz_fuzz_socks_CPPFLAGS = $(FUZZING_CPPFLAGS) +src_test_fuzz_fuzz_socks_CFLAGS = $(FUZZING_CFLAGS) +src_test_fuzz_fuzz_socks_LDFLAGS = $(FUZZING_LDFLAG) +src_test_fuzz_fuzz_socks_LDADD = $(FUZZING_LIBS) +endif + +if UNITTESTS_ENABLED src_test_fuzz_fuzz_vrs_SOURCES = \ src/test/fuzz/fuzzing_common.c \ src/test/fuzz/fuzz_vrs.c @@ -141,7 +160,9 @@ src_test_fuzz_fuzz_vrs_CPPFLAGS = $(FUZZING_CPPFLAGS) src_test_fuzz_fuzz_vrs_CFLAGS = $(FUZZING_CFLAGS) src_test_fuzz_fuzz_vrs_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_vrs_LDADD = $(FUZZING_LIBS) +endif +if UNITTESTS_ENABLED FUZZERS = \ src/test/fuzz/fuzz-consensus \ src/test/fuzz/fuzz-descriptor \ @@ -154,94 +175,129 @@ FUZZERS = \ src/test/fuzz/fuzz-http-connect \ src/test/fuzz/fuzz-iptsv2 \ src/test/fuzz/fuzz-microdesc \ + src/test/fuzz/fuzz-socks \ src/test/fuzz/fuzz-vrs +endif # ===== libfuzzer if LIBFUZZER_ENABLED +if UNITTESTS_ENABLED src_test_fuzz_lf_fuzz_consensus_SOURCES = \ $(src_test_fuzz_fuzz_consensus_SOURCES) src_test_fuzz_lf_fuzz_consensus_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) src_test_fuzz_lf_fuzz_consensus_CFLAGS = $(LIBFUZZER_CFLAGS) src_test_fuzz_lf_fuzz_consensus_LDFLAGS = $(LIBFUZZER_LDFLAG) src_test_fuzz_lf_fuzz_consensus_LDADD = $(LIBFUZZER_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_lf_fuzz_descriptor_SOURCES = \ $(src_test_fuzz_fuzz_descriptor_SOURCES) src_test_fuzz_lf_fuzz_descriptor_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) src_test_fuzz_lf_fuzz_descriptor_CFLAGS = $(LIBFUZZER_CFLAGS) src_test_fuzz_lf_fuzz_descriptor_LDFLAGS = $(LIBFUZZER_LDFLAG) src_test_fuzz_lf_fuzz_descriptor_LDADD = $(LIBFUZZER_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_lf_fuzz_diff_SOURCES = \ $(src_test_fuzz_fuzz_diff_SOURCES) src_test_fuzz_lf_fuzz_diff_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) src_test_fuzz_lf_fuzz_diff_CFLAGS = $(LIBFUZZER_CFLAGS) src_test_fuzz_lf_fuzz_diff_LDFLAGS = $(LIBFUZZER_LDFLAG) src_test_fuzz_lf_fuzz_diff_LDADD = $(LIBFUZZER_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_lf_fuzz_diff_apply_SOURCES = \ $(src_test_fuzz_fuzz_diff_apply_SOURCES) src_test_fuzz_lf_fuzz_diff_apply_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) src_test_fuzz_lf_fuzz_diff_apply_CFLAGS = $(LIBFUZZER_CFLAGS) src_test_fuzz_lf_fuzz_diff_apply_LDFLAGS = $(LIBFUZZER_LDFLAG) src_test_fuzz_lf_fuzz_diff_apply_LDADD = $(LIBFUZZER_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_lf_fuzz_extrainfo_SOURCES = \ $(src_test_fuzz_fuzz_extrainfo_SOURCES) src_test_fuzz_lf_fuzz_extrainfo_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) src_test_fuzz_lf_fuzz_extrainfo_CFLAGS = $(LIBFUZZER_CFLAGS) src_test_fuzz_lf_fuzz_extrainfo_LDFLAGS = $(LIBFUZZER_LDFLAG) src_test_fuzz_lf_fuzz_extrainfo_LDADD = $(LIBFUZZER_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_lf_fuzz_hsdescv2_SOURCES = \ $(src_test_fuzz_fuzz_hsdescv2_SOURCES) src_test_fuzz_lf_fuzz_hsdescv2_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) src_test_fuzz_lf_fuzz_hsdescv2_CFLAGS = $(LIBFUZZER_CFLAGS) src_test_fuzz_lf_fuzz_hsdescv2_LDFLAGS = $(LIBFUZZER_LDFLAG) src_test_fuzz_lf_fuzz_hsdescv2_LDADD = $(LIBFUZZER_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_lf_fuzz_hsdescv3_SOURCES = \ $(src_test_fuzz_fuzz_hsdescv3_SOURCES) src_test_fuzz_lf_fuzz_hsdescv3_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) src_test_fuzz_lf_fuzz_hsdescv3_CFLAGS = $(LIBFUZZER_CFLAGS) src_test_fuzz_lf_fuzz_hsdescv3_LDFLAGS = $(LIBFUZZER_LDFLAG) src_test_fuzz_lf_fuzz_hsdescv3_LDADD = $(LIBFUZZER_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_lf_fuzz_http_SOURCES = \ $(src_test_fuzz_fuzz_http_SOURCES) src_test_fuzz_lf_fuzz_http_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) src_test_fuzz_lf_fuzz_http_CFLAGS = $(LIBFUZZER_CFLAGS) src_test_fuzz_lf_fuzz_http_LDFLAGS = $(LIBFUZZER_LDFLAG) src_test_fuzz_lf_fuzz_http_LDADD = $(LIBFUZZER_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_lf_fuzz_http_connect_SOURCES = \ $(src_test_fuzz_fuzz_http_connect_SOURCES) src_test_fuzz_lf_fuzz_http_connect_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) src_test_fuzz_lf_fuzz_http_connect_CFLAGS = $(LIBFUZZER_CFLAGS) src_test_fuzz_lf_fuzz_http_connect_LDFLAGS = $(LIBFUZZER_LDFLAG) src_test_fuzz_lf_fuzz_http_connect_LDADD = $(LIBFUZZER_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_lf_fuzz_iptsv2_SOURCES = \ $(src_test_fuzz_fuzz_iptsv2_SOURCES) src_test_fuzz_lf_fuzz_iptsv2_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) src_test_fuzz_lf_fuzz_iptsv2_CFLAGS = $(LIBFUZZER_CFLAGS) src_test_fuzz_lf_fuzz_iptsv2_LDFLAGS = $(LIBFUZZER_LDFLAG) src_test_fuzz_lf_fuzz_iptsv2_LDADD = $(LIBFUZZER_LIBS) +endif +if UNITTESTS_ENABLED src_test_fuzz_lf_fuzz_microdesc_SOURCES = \ $(src_test_fuzz_fuzz_microdesc_SOURCES) src_test_fuzz_lf_fuzz_microdesc_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) src_test_fuzz_lf_fuzz_microdesc_CFLAGS = $(LIBFUZZER_CFLAGS) src_test_fuzz_lf_fuzz_microdesc_LDFLAGS = $(LIBFUZZER_LDFLAG) src_test_fuzz_lf_fuzz_microdesc_LDADD = $(LIBFUZZER_LIBS) +endif +if UNITTESTS_ENABLED +src_test_fuzz_lf_fuzz_socks_SOURCES = \ + $(src_test_fuzz_fuzz_socks_SOURCES) +src_test_fuzz_lf_fuzz_socks_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) +src_test_fuzz_lf_fuzz_socks_CFLAGS = $(LIBFUZZER_CFLAGS) +src_test_fuzz_lf_fuzz_socks_LDFLAGS = $(LIBFUZZER_LDFLAG) +src_test_fuzz_lf_fuzz_socks_LDADD = $(LIBFUZZER_LIBS) +endif + +if UNITTESTS_ENABLED src_test_fuzz_lf_fuzz_vrs_SOURCES = \ $(src_test_fuzz_fuzz_vrs_SOURCES) src_test_fuzz_lf_fuzz_vrs_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) src_test_fuzz_lf_fuzz_vrs_CFLAGS = $(LIBFUZZER_CFLAGS) src_test_fuzz_lf_fuzz_vrs_LDFLAGS = $(LIBFUZZER_LDFLAG) src_test_fuzz_lf_fuzz_vrs_LDADD = $(LIBFUZZER_LIBS) +endif LIBFUZZER_FUZZERS = \ src/test/fuzz/lf-fuzz-consensus \ @@ -255,6 +311,7 @@ LIBFUZZER_FUZZERS = \ src/test/fuzz/lf-fuzz-http-connect \ src/test/fuzz/lf-fuzz-iptsv2 \ src/test/fuzz/lf-fuzz-microdesc \ + src/test/fuzz/lf-fuzz-socks \ src/test/fuzz/lf-fuzz-vrs else @@ -264,65 +321,96 @@ endif # ===== oss-fuzz if OSS_FUZZ_ENABLED +if UNITTESTS_ENABLED src_test_fuzz_liboss_fuzz_consensus_a_SOURCES = \ $(src_test_fuzz_fuzz_consensus_SOURCES) src_test_fuzz_liboss_fuzz_consensus_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) src_test_fuzz_liboss_fuzz_consensus_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) +endif +if UNITTESTS_ENABLED src_test_fuzz_liboss_fuzz_descriptor_a_SOURCES = \ $(src_test_fuzz_fuzz_descriptor_SOURCES) src_test_fuzz_liboss_fuzz_descriptor_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) src_test_fuzz_liboss_fuzz_descriptor_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) +endif +if UNITTESTS_ENABLED src_test_fuzz_liboss_fuzz_diff_a_SOURCES = \ $(src_test_fuzz_fuzz_diff_SOURCES) src_test_fuzz_liboss_fuzz_diff_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) src_test_fuzz_liboss_fuzz_diff_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) +endif +if UNITTESTS_ENABLED src_test_fuzz_liboss_fuzz_diff_apply_a_SOURCES = \ $(src_test_fuzz_fuzz_diff_apply_SOURCES) src_test_fuzz_liboss_fuzz_diff_apply_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) src_test_fuzz_liboss_fuzz_diff_apply_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) +endif +if UNITTESTS_ENABLED src_test_fuzz_liboss_fuzz_extrainfo_a_SOURCES = \ $(src_test_fuzz_fuzz_extrainfo_SOURCES) src_test_fuzz_liboss_fuzz_extrainfo_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) src_test_fuzz_liboss_fuzz_extrainfo_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) +endif +if UNITTESTS_ENABLED src_test_fuzz_liboss_fuzz_hsdescv2_a_SOURCES = \ $(src_test_fuzz_fuzz_hsdescv2_SOURCES) src_test_fuzz_liboss_fuzz_hsdescv2_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) src_test_fuzz_liboss_fuzz_hsdescv2_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) +endif +if UNITTESTS_ENABLED src_test_fuzz_liboss_fuzz_hsdescv3_a_SOURCES = \ $(src_test_fuzz_fuzz_hsdescv3_SOURCES) src_test_fuzz_liboss_fuzz_hsdescv3_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) src_test_fuzz_liboss_fuzz_hsdescv3_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) +endif +if UNITTESTS_ENABLED src_test_fuzz_liboss_fuzz_http_a_SOURCES = \ $(src_test_fuzz_fuzz_http_SOURCES) src_test_fuzz_liboss_fuzz_http_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) src_test_fuzz_liboss_fuzz_http_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) +endif +if UNITTESTS_ENABLED src_test_fuzz_liboss_fuzz_http_connect_a_SOURCES = \ $(src_test_fuzz_fuzz_http_connect_SOURCES) src_test_fuzz_liboss_fuzz_http_connect_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) src_test_fuzz_liboss_fuzz_http_connect_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) +endif +if UNITTESTS_ENABLED src_test_fuzz_liboss_fuzz_iptsv2_a_SOURCES = \ $(src_test_fuzz_fuzz_iptsv2_SOURCES) src_test_fuzz_liboss_fuzz_iptsv2_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) src_test_fuzz_liboss_fuzz_iptsv2_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) +endif +if UNITTESTS_ENABLED src_test_fuzz_liboss_fuzz_microdesc_a_SOURCES = \ $(src_test_fuzz_fuzz_microdesc_SOURCES) src_test_fuzz_liboss_fuzz_microdesc_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) src_test_fuzz_liboss_fuzz_microdesc_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) +endif +if UNITTESTS_ENABLED +src_test_fuzz_liboss_fuzz_socks_a_SOURCES = \ + $(src_test_fuzz_fuzz_socks_SOURCES) +src_test_fuzz_liboss_fuzz_socks_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) +src_test_fuzz_liboss_fuzz_socks_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) +endif + +if UNITTESTS_ENABLED src_test_fuzz_liboss_fuzz_vrs_a_SOURCES = \ $(src_test_fuzz_fuzz_vrs_SOURCES) src_test_fuzz_liboss_fuzz_vrs_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) src_test_fuzz_liboss_fuzz_vrs_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) +endif OSS_FUZZ_FUZZERS = \ src/test/fuzz/liboss-fuzz-consensus.a \ @@ -336,6 +424,7 @@ OSS_FUZZ_FUZZERS = \ src/test/fuzz/liboss-fuzz-http-connect.a \ src/test/fuzz/liboss-fuzz-iptsv2.a \ src/test/fuzz/liboss-fuzz-microdesc.a \ + src/test/fuzz/liboss-fuzz-socks.a \ src/test/fuzz/liboss-fuzz-vrs.a else diff --git a/src/test/fuzz_static_testcases.sh b/src/test/fuzz_static_testcases.sh index 3cb45ad5e6..138f85b106 100755 --- a/src/test/fuzz_static_testcases.sh +++ b/src/test/fuzz_static_testcases.sh @@ -1,6 +1,6 @@ #!/bin/sh -# Copyright (c) 2016-2017, The Tor Project, Inc. +# Copyright (c) 2016-2018, The Tor Project, Inc. # See LICENSE for licensing information set -e diff --git a/src/test/hs_ntor_ref.py b/src/test/hs_ntor_ref.py index 542b02d2e0..0c5756ad73 100644 --- a/src/test/hs_ntor_ref.py +++ b/src/test/hs_ntor_ref.py @@ -1,5 +1,5 @@ #!/usr/bin/python -# Copyright 2017, The Tor Project, Inc +# Copyright 2017-2018, The Tor Project, Inc # See LICENSE for licensing information """ diff --git a/src/test/hs_test_helpers.c b/src/test/hs_test_helpers.c index 5c1b9123d8..dcec1b9d48 100644 --- a/src/test/hs_test_helpers.c +++ b/src/test/hs_test_helpers.c @@ -1,13 +1,13 @@ -/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "or.h" -#include "crypto_ed25519.h" -#include "test.h" -#include "torcert.h" +#include "core/or/or.h" +#include "lib/crypt_ops/crypto_ed25519.h" +#include "test/test.h" +#include "feature/nodelist/torcert.h" -#include "hs_common.h" -#include "hs_test_helpers.h" +#include "feature/hs/hs_common.h" +#include "test/hs_test_helpers.h" hs_desc_intro_point_t * hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now, @@ -98,8 +98,11 @@ static hs_descriptor_t * hs_helper_build_hs_desc_impl(unsigned int no_ip, const ed25519_keypair_t *signing_kp) { + int ret; + int i; time_t now = approx_time(); ed25519_keypair_t blinded_kp; + curve25519_keypair_t auth_ephemeral_kp; hs_descriptor_t *descp = NULL, *desc = tor_malloc_zero(sizeof(*desc)); desc->plaintext_data.version = HS_DESC_SUPPORTED_FORMAT_VERSION_MAX; @@ -126,6 +129,20 @@ hs_helper_build_hs_desc_impl(unsigned int no_ip, hs_get_subcredential(&signing_kp->pubkey, &blinded_kp.pubkey, desc->subcredential); + /* Setup superencrypted data section. */ + ret = curve25519_keypair_generate(&auth_ephemeral_kp, 0); + tt_int_op(ret, ==, 0); + memcpy(&desc->superencrypted_data.auth_ephemeral_pubkey, + &auth_ephemeral_kp.pubkey, + sizeof(curve25519_public_key_t)); + + desc->superencrypted_data.clients = smartlist_new(); + for (i = 0; i < HS_DESC_AUTH_CLIENT_MULTIPLE; i++) { + hs_desc_authorized_client_t *desc_client = + hs_desc_build_fake_authorized_client(); + smartlist_add(desc->superencrypted_data.clients, desc_client); + } + /* Setup encrypted data section. */ desc->encrypted_data.create2_ntor = 1; desc->encrypted_data.intro_auth_types = smartlist_new(); @@ -207,6 +224,32 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1, * encrypted blob. As contrast to the decoding process where we populate a * descriptor object. */ + /* Superencrypted data section. */ + tt_mem_op(desc1->superencrypted_data.auth_ephemeral_pubkey.public_key, OP_EQ, + desc2->superencrypted_data.auth_ephemeral_pubkey.public_key, + CURVE25519_PUBKEY_LEN); + + /* Auth clients. */ + { + tt_assert(desc1->superencrypted_data.clients); + tt_assert(desc2->superencrypted_data.clients); + tt_int_op(smartlist_len(desc1->superencrypted_data.clients), ==, + smartlist_len(desc2->superencrypted_data.clients)); + for (int i=0; + i < smartlist_len(desc1->superencrypted_data.clients); + i++) { + hs_desc_authorized_client_t + *client1 = smartlist_get(desc1->superencrypted_data.clients, i), + *client2 = smartlist_get(desc2->superencrypted_data.clients, i); + tt_mem_op(client1->client_id, OP_EQ, client2->client_id, + sizeof(client1->client_id)); + tt_mem_op(client1->iv, OP_EQ, client2->iv, + sizeof(client1->iv)); + tt_mem_op(client1->encrypted_cookie, OP_EQ, client2->encrypted_cookie, + sizeof(client1->encrypted_cookie)); + } + } + /* Encrypted data section. */ tt_uint_op(desc1->encrypted_data.create2_ntor, ==, desc2->encrypted_data.create2_ntor); diff --git a/src/test/hs_test_helpers.h b/src/test/hs_test_helpers.h index b1b0490f05..b7c2714769 100644 --- a/src/test/hs_test_helpers.h +++ b/src/test/hs_test_helpers.h @@ -1,11 +1,11 @@ -/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #ifndef TOR_HS_TEST_HELPERS_H #define TOR_HS_TEST_HELPERS_H -#include "ed25519_cert.h" -#include "hs_descriptor.h" +#include "trunnel/ed25519_cert.h" +#include "feature/hs/hs_descriptor.h" /* Set of functions to help build and test descriptors. */ hs_desc_intro_point_t *hs_helper_build_intro_point( diff --git a/src/test/include.am b/src/test/include.am index 93fc008419..1055cd0a81 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -10,7 +10,10 @@ TESTS_ENVIRONMENT = \ export TESTING_TOR_BINARY="$(TESTING_TOR_BINARY)"; \ export CARGO="$(CARGO)"; \ export EXTRA_CARGO_OPTIONS="$(EXTRA_CARGO_OPTIONS)"; \ - export CARGO_ONLINE="$(CARGO_ONLINE)"; + export CARGO_ONLINE="$(CARGO_ONLINE)"; \ + export CCLD="$(CCLD)"; \ + chmod +x "$(abs_top_builddir)/link_rust.sh"; \ + export RUSTFLAGS="-C linker=$(abs_top_builddir)/link_rust.sh"; TESTSCRIPTS = \ src/test/fuzz_static_testcases.sh \ @@ -30,6 +33,7 @@ endif if USEPYTHON TESTSCRIPTS += src/test/test_ntor.sh src/test/test_hs_ntor.sh src/test/test_bt.sh +TESTSCRIPTS += src/test/test_rebind.sh endif TESTS += src/test/test src/test/test-slow src/test/test-memwipe \ @@ -69,18 +73,19 @@ noinst_PROGRAMS+= \ endif src_test_AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \ - -DLOCALSTATEDIR="\"$(localstatedir)\"" \ - -DBINDIR="\"$(bindir)\"" \ - -I"$(top_srcdir)/src/or" -I"$(top_srcdir)/src/ext" \ - -I"$(top_srcdir)/src/trunnel" \ - -I"$(top_srcdir)/src/ext/trunnel" \ - -DTOR_UNIT_TESTS + -DLOCALSTATEDIR="\"$(localstatedir)\"" \ + -DBINDIR="\"$(bindir)\"" \ + -DTOR_UNIT_TESTS \ + $(AM_CPPFLAGS) # -L flags need to go in LDFLAGS. -l flags need to go in LDADD. # This seems to matter nowhere but on Windows, but I assure you that it # matters a lot there, and is quite hard to debug if you forget to do it. -src_test_test_SOURCES = \ +src_test_test_SOURCES = + +if UNITTESTS_ENABLED +src_test_test_SOURCES += \ src/test/log_test_helpers.c \ src/test/hs_test_helpers.c \ src/test/rend_test_helpers.c \ @@ -89,7 +94,9 @@ src_test_test_SOURCES = \ src/test/test_addr.c \ src/test/test_address.c \ src/test/test_address_set.c \ + src/test/test_bridges.c \ src/test/test_buffers.c \ + src/test/test_bwmgt.c \ src/test/test_cell_formats.c \ src/test/test_cell_queue.c \ src/test/test_channel.c \ @@ -111,7 +118,7 @@ src_test_test_SOURCES = \ src/test/test_controller.c \ src/test/test_controller_events.c \ src/test/test_crypto.c \ - src/test/test_crypto_openssl.c \ + src/test/test_crypto_ope.c \ src/test/test_data.c \ src/test/test_dir.c \ src/test/test_dir_common.c \ @@ -119,6 +126,7 @@ src_test_test_SOURCES = \ src/test/test_dos.c \ src/test/test_entryconn.c \ src/test/test_entrynodes.c \ + src/test/test_geoip.c \ src/test/test_guardfraction.c \ src/test/test_extorport.c \ src/test/test_hs.c \ @@ -137,20 +145,23 @@ src_test_test_SOURCES = \ src/test/test_keypin.c \ src/test/test_link_handshake.c \ src/test/test_logging.c \ + src/test/test_mainloop.c \ src/test/test_microdesc.c \ src/test/test_nodelist.c \ src/test/test_oom.c \ src/test/test_oos.c \ src/test/test_options.c \ + src/test/test_pem.c \ + src/test/test_periodic_event.c \ src/test/test_policy.c \ src/test/test_procmon.c \ src/test/test_proto_http.c \ src/test/test_proto_misc.c \ src/test/test_protover.c \ src/test/test_pt.c \ - src/test/test_pubsub.c \ src/test/test_relay.c \ src/test/test_relaycell.c \ + src/test/test_relaycrypt.c \ src/test/test_rendcache.c \ src/test/test_replay.c \ src/test/test_router.c \ @@ -167,19 +178,34 @@ src_test_test_SOURCES = \ src/test/test_util.c \ src/test/test_util_format.c \ src/test/test_util_process.c \ + src/test/test_voting_schedule.c \ + src/test/test_x509.c \ src/test/test_helpers.c \ src/test/test_dns.c \ src/test/testing_common.c \ src/test/testing_rsakeys.c \ src/ext/tinytest.c -src_test_test_slow_SOURCES = \ +if USE_NSS +# ... +else +src_test_test_SOURCES += \ + src/test/test_crypto_openssl.c \ + src/test/test_tortls_openssl.c +endif + +endif + +src_test_test_slow_SOURCES = +if UNITTESTS_ENABLED +src_test_test_slow_SOURCES += \ src/test/test_slow.c \ src/test/test_crypto_slow.c \ src/test/test_util_slow.c \ src/test/testing_common.c \ src/test/testing_rsakeys.c \ src/ext/tinytest.c +endif src_test_test_memwipe_SOURCES = \ src/test/test-memwipe.c @@ -205,27 +231,19 @@ src_test_test_switch_id_CPPFLAGS= $(src_test_AM_CPPFLAGS) src_test_test_switch_id_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) src_test_test_switch_id_LDFLAGS = @TOR_LDFLAGS_zlib@ src_test_test_switch_id_LDADD = \ - src/common/libor-testing.a \ - src/common/libor-ctime-testing.a \ + $(TOR_UTIL_TESTING_LIBS) \ $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \ - @TOR_LIB_WS32@ @TOR_LIB_USERENV@ \ + @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_USERENV@ \ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ -src_test_test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ - @TOR_LDFLAGS_libevent@ -src_test_test_LDADD = src/or/libtor-testing.a \ - src/common/libor-crypto-testing.a \ - $(LIBKECCAK_TINY) \ - $(LIBDONNA) \ - src/common/libor-testing.a \ - src/common/libor-ctime-testing.a \ - src/common/libor-event-testing.a \ - src/trunnel/libor-trunnel-testing.a \ - src/trace/libor-trace.a \ +src_test_test_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) \ + @TOR_LDFLAGS_libevent@ +src_test_test_LDADD = \ + $(TOR_INTERNAL_TESTING_LIBS) \ $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ - @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ + $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ @CURVE25519_LIBS@ \ @TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ @@ -242,43 +260,35 @@ src_test_test_memwipe_LDADD = $(src_test_test_LDADD) # successfully with the libraries built with them. src_test_test_memwipe_LDFLAGS = $(src_test_test_LDFLAGS) @CFLAGS_BUGTRAP@ -src_test_bench_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ - @TOR_LDFLAGS_libevent@ -src_test_bench_LDADD = src/or/libtor.a src/common/libor.a \ - src/common/libor-ctime.a \ - src/common/libor-crypto.a $(LIBKECCAK_TINY) $(LIBDONNA) \ - src/common/libor-event.a src/trunnel/libor-trunnel.a \ - src/trace/libor-trace.a \ +src_test_bench_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) \ + @TOR_LDFLAGS_libevent@ +src_test_bench_LDADD = \ + $(TOR_INTERNAL_LIBS) \ $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ - @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ + $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ @CURVE25519_LIBS@ \ @TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ -src_test_test_workqueue_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ - @TOR_LDFLAGS_libevent@ -src_test_test_workqueue_LDADD = src/or/libtor-testing.a \ - src/common/libor-testing.a \ - src/common/libor-ctime-testing.a \ - src/common/libor-crypto-testing.a $(LIBKECCAK_TINY) $(LIBDONNA) \ - src/common/libor-event-testing.a \ - src/trace/libor-trace.a \ +src_test_test_workqueue_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) \ + @TOR_LDFLAGS_libevent@ +src_test_test_workqueue_LDADD = \ + $(TOR_INTERNAL_TESTING_LIBS) \ $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ - @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ + $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ @CURVE25519_LIBS@ \ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ src_test_test_timers_CPPFLAGS = $(src_test_test_CPPFLAGS) src_test_test_timers_CFLAGS = $(src_test_test_CFLAGS) src_test_test_timers_LDADD = \ - src/common/libor-testing.a \ - src/common/libor-ctime-testing.a \ - src/common/libor-event-testing.a \ - src/common/libor-crypto-testing.a $(LIBKECCAK_TINY) $(LIBDONNA) \ + src/lib/libtor-evloop-testing.a \ + $(TOR_CRYPTO_TESTING_LIBS) \ + $(TOR_UTIL_TESTING_LIBS) \ $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ - @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ + $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ @CURVE25519_LIBS@ \ @TOR_LZMA_LIBS@ src_test_test_timers_LDFLAGS = $(src_test_test_LDFLAGS) @@ -292,6 +302,7 @@ noinst_HEADERS+= \ src/test/test_helpers.h \ src/test/test_dir_common.h \ src/test/test_connection.h \ + src/test/test_tortls.h \ src/test/test_descriptors.inc \ src/test/example_extrainfo.inc \ src/test/failing_routerdescs.inc \ @@ -303,39 +314,37 @@ noinst_HEADERS+= \ noinst_PROGRAMS+= src/test/test-ntor-cl noinst_PROGRAMS+= src/test/test-hs-ntor-cl src_test_test_ntor_cl_SOURCES = src/test/test_ntor_cl.c -src_test_test_ntor_cl_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ -src_test_test_ntor_cl_LDADD = src/or/libtor.a src/common/libor.a \ - src/common/libor-ctime.a \ - src/common/libor-crypto.a $(LIBKECCAK_TINY) $(LIBDONNA) \ - src/trace/libor-trace.a \ +src_test_test_ntor_cl_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) +src_test_test_ntor_cl_LDADD = \ + $(TOR_INTERNAL_LIBS) \ $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \ - @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ + $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ @CURVE25519_LIBS@ @TOR_LZMA_LIBS@ src_test_test_ntor_cl_AM_CPPFLAGS = \ - -I"$(top_srcdir)/src/or" + $(AM_CPPFLAGS) src_test_test_hs_ntor_cl_SOURCES = src/test/test_hs_ntor_cl.c -src_test_test_hs_ntor_cl_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ -src_test_test_hs_ntor_cl_LDADD = src/or/libtor.a src/common/libor.a \ - src/common/libor-ctime.a \ - src/common/libor-crypto.a $(LIBKECCAK_TINY) $(LIBDONNA) \ +src_test_test_hs_ntor_cl_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) +src_test_test_hs_ntor_cl_LDADD = \ + $(TOR_INTERNAL_LIBS) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \ - @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ + $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ src_test_test_hs_ntor_cl_AM_CPPFLAGS = \ - -I"$(top_srcdir)/src/or" + $(AM_CPPFLAGS) +if UNITTESTS_ENABLED noinst_PROGRAMS += src/test/test-bt-cl src_test_test_bt_cl_SOURCES = src/test/test_bt_cl.c -src_test_test_bt_cl_LDADD = src/common/libor-testing.a \ - src/common/libor-ctime-testing.a \ - src/trace/libor-trace.a \ +src_test_test_bt_cl_LDADD = \ + $(TOR_UTIL_TESTING_LIBS) \ $(rust_ldadd) \ @TOR_LIB_MATH@ \ - @TOR_LIB_WS32@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ + @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ src_test_test_bt_cl_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS) +endif EXTRA_DIST += \ src/test/bt_test.py \ @@ -345,7 +354,10 @@ EXTRA_DIST += \ src/test/hs_indexes.py \ src/test/fuzz_static_testcases.sh \ src/test/slownacl_curve25519.py \ + src/test/test_rebind.sh \ + src/test/test_rebind.py \ src/test/zero_length_keys.sh \ + src/test/rust_supp.txt \ src/test/test_keygen.sh \ src/test/test_key_expiration.sh \ src/test/test_zero_length_keys.sh \ diff --git a/src/test/log_test_helpers.c b/src/test/log_test_helpers.c index d5a39cfeee..2e91b1ecdc 100644 --- a/src/test/log_test_helpers.c +++ b/src/test/log_test_helpers.c @@ -1,8 +1,8 @@ -/* Copyright (c) 2015-2017, The Tor Project, Inc. */ +/* Copyright (c) 2015-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define LOG_PRIVATE -#include "torlog.h" -#include "log_test_helpers.h" +#include "lib/log/log.h" +#include "test/log_test_helpers.h" /** * \file log_test_helpers.c @@ -158,6 +158,26 @@ mock_saved_log_has_message_containing(const char *msg) return 0; } +/** + * Return true iff there is not a message recorded by log capture + * that contains <b>msg</b> as a substring. + */ +int +mock_saved_log_has_message_not_containing(const char *msg) +{ + if (saved_logs) { + SMARTLIST_FOREACH( + saved_logs, mock_saved_log_entry_t *, m, + { + if (msg && m->generated_msg && strstr(m->generated_msg, msg)) + return 0; + } + ); + } + + return 1; +} + /** Return true iff the saved logs have any messages with <b>severity</b> */ int mock_saved_log_has_severity(int severity) diff --git a/src/test/log_test_helpers.h b/src/test/log_test_helpers.h index 70c584eb37..6a774cdfc7 100644 --- a/src/test/log_test_helpers.h +++ b/src/test/log_test_helpers.h @@ -1,7 +1,7 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "or.h" +#include "core/or/or.h" #ifndef TOR_LOG_TEST_HELPERS_H #define TOR_LOG_TEST_HELPERS_H @@ -24,6 +24,7 @@ void teardown_capture_of_logs(void); int mock_saved_log_has_message(const char *msg); int mock_saved_log_has_message_containing(const char *msg); +int mock_saved_log_has_message_not_containing(const char *msg); int mock_saved_log_has_severity(int severity); int mock_saved_log_has_entry(void); int mock_saved_log_n_entries(void); @@ -32,7 +33,7 @@ void mock_dump_saved_logs(void); #define assert_log_predicate(predicate, failure_msg) \ do { \ if (!(predicate)) { \ - tt_fail_msg((failure_msg)); \ + TT_FAIL(failure_msg); \ mock_dump_saved_logs(); \ TT_EXIT_TEST_FUNCTION; \ } \ @@ -40,66 +41,75 @@ void mock_dump_saved_logs(void); #define expect_log_msg(str) \ assert_log_predicate(mock_saved_log_has_message(str), \ - "expected log to contain " # str); + ("expected log to contain \"%s\"", str)); #define expect_log_msg_containing(str) \ assert_log_predicate(mock_saved_log_has_message_containing(str), \ - "expected log to contain " # str); + ("expected log to contain \"%s\"", str)); + +#define expect_log_msg_not_containing(str) \ + assert_log_predicate(mock_saved_log_has_message_not_containing(str), \ + ("expected log to not contain \"%s\"", str)); #define expect_log_msg_containing_either(str1, str2) \ assert_log_predicate(mock_saved_log_has_message_containing(str1) || \ mock_saved_log_has_message_containing(str2), \ - "expected log to contain " # str1 " or " # str2); + ("expected log to contain \"%s\" or \"%s\"", str1, str2)); #define expect_log_msg_containing_either3(str1, str2, str3) \ assert_log_predicate(mock_saved_log_has_message_containing(str1) || \ mock_saved_log_has_message_containing(str2) || \ mock_saved_log_has_message_containing(str3), \ - "expected log to contain " # str1 " or " # str2 \ - " or " # str3); + ("expected log to contain \"%s\" or \"%s\" or \"%s\"", \ + str1, str2, str3)) #define expect_log_msg_containing_either4(str1, str2, str3, str4) \ assert_log_predicate(mock_saved_log_has_message_containing(str1) || \ mock_saved_log_has_message_containing(str2) || \ mock_saved_log_has_message_containing(str3) || \ mock_saved_log_has_message_containing(str4), \ - "expected log to contain " # str1 " or " # str2 \ - " or " # str3 " or " # str4); + ("expected log to contain \"%s\" or \"%s\" or \"%s\" or \"%s\"", \ + str1, str2, str3, str4)) #define expect_single_log_msg(str) \ do { \ \ assert_log_predicate(mock_saved_log_has_message_containing(str) && \ mock_saved_log_n_entries() == 1, \ - "expected log to contain exactly 1 message " # str); \ + ("expected log to contain exactly 1 message \"%s\"", \ + str)); \ } while (0); #define expect_single_log_msg_containing(str) \ do { \ assert_log_predicate(mock_saved_log_has_message_containing(str)&& \ mock_saved_log_n_entries() == 1 , \ - "expected log to contain 1 message, containing " # str); \ + ("expected log to contain 1 message, containing \"%s\"",\ + str)); \ } while (0); #define expect_no_log_msg(str) \ assert_log_predicate(!mock_saved_log_has_message(str), \ - "expected log to not contain " # str); + ("expected log to not contain \"%s\"",str)); + +#define expect_no_log_msg_containing(str) \ + assert_log_predicate(!mock_saved_log_has_message_containing(str), \ + ("expected log to not contain \"%s\"", str)); #define expect_log_severity(severity) \ assert_log_predicate(mock_saved_log_has_severity(severity), \ - "expected log to contain severity " # severity); + ("expected log to contain severity " # severity)); #define expect_no_log_severity(severity) \ assert_log_predicate(!mock_saved_log_has_severity(severity), \ - "expected log to not contain severity " # severity); + ("expected log to not contain severity " # severity)); #define expect_log_entry() \ assert_log_predicate(mock_saved_log_has_entry(), \ - "expected log to contain entries"); + ("expected log to contain entries")); #define expect_no_log_entry() \ assert_log_predicate(!mock_saved_log_has_entry(), \ - "expected log to not contain entries"); + ("expected log to not contain entries")); #endif /* !defined(TOR_LOG_TEST_HELPERS_H) */ - diff --git a/src/test/ntor_ref.py b/src/test/ntor_ref.py index 51f218f512..56e97ece36 100755 --- a/src/test/ntor_ref.py +++ b/src/test/ntor_ref.py @@ -1,5 +1,5 @@ #!/usr/bin/python -# Copyright 2012-2017, The Tor Project, Inc +# Copyright 2012-2018, The Tor Project, Inc # See LICENSE for licensing information """ diff --git a/src/test/ope_ref.py b/src/test/ope_ref.py new file mode 100644 index 0000000000..3677e57a61 --- /dev/null +++ b/src/test/ope_ref.py @@ -0,0 +1,40 @@ +#!/usr/bin/python3 +# Copyright 2018, The Tor Project, Inc. See LICENSE for licensing info. + +# Reference implementation for our rudimentary OPE code, used to +# generate test vectors. See crypto_ope.c for more details. + +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from cryptography.hazmat.primitives.ciphers.algorithms import AES +from cryptography.hazmat.backends import default_backend + +from binascii import a2b_hex + +#randomly generated and values. +KEY = a2b_hex( + "19e05891d55232c08c2cad91d612fdb9cbd6691949a0742434a76c80bc6992fe") +PTS = [ 121132, 82283, 72661, 72941, 123122, 12154, 121574, 11391, 65845, + 86301, 61284, 70505, 30438, 60150, 114800, 109403, 21893, 123569, + 95617, 48561, 53334, 92746, 7110, 9612, 106958, 46889, 87790, 68878, + 47917, 121128, 108602, 28217, 69498, 63870, 57542, 122148, 46254, + 42850, 92661, 57720] + +IV = b'\x00' * 16 + +backend = default_backend() + +def words(): + cipher = Cipher(algorithms.AES(KEY), modes.CTR(IV), backend=backend) + e = cipher.encryptor() + while True: + v = e.update(b'\x00\x00') + yield v[0] + 256 * v[1] + 1 + +def encrypt(n): + return sum(w for w, _ in zip(words(), range(n))) + +def example(n): + return ' {{ {}, UINT64_C({}) }},'.format(n, encrypt(n)) + +for v in PTS: + print(example(v)) diff --git a/src/test/rend_test_helpers.c b/src/test/rend_test_helpers.c index 095bfecf21..85a679a967 100644 --- a/src/test/rend_test_helpers.c +++ b/src/test/rend_test_helpers.c @@ -1,10 +1,15 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "or.h" -#include "test.h" -#include "rendcommon.h" -#include "rend_test_helpers.h" +#include "core/or/or.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "test/test.h" +#include "feature/rend/rendcommon.h" +#include "test/rend_test_helpers.h" + +#include "core/or/extend_info_st.h" +#include "feature/rend/rend_intro_point_st.h" +#include "feature/rend/rend_service_descriptor_st.h" void generate_desc(int time_diff, rend_encoded_v2_service_descriptor_t **desc, diff --git a/src/test/rend_test_helpers.h b/src/test/rend_test_helpers.h index abf4324988..103e143ec6 100644 --- a/src/test/rend_test_helpers.h +++ b/src/test/rend_test_helpers.h @@ -1,7 +1,7 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "or.h" +#include "core/or/or.h" #ifndef TOR_REND_TEST_HELPERS_H #define TOR_REND_TEST_HELPERS_H diff --git a/src/test/rust_supp.txt b/src/test/rust_supp.txt new file mode 100644 index 0000000000..7fa50f3fb1 --- /dev/null +++ b/src/test/rust_supp.txt @@ -0,0 +1 @@ +leak:backtrace_alloc diff --git a/src/test/test-child.c b/src/test/test-child.c index f78a829107..14df1a9b76 100644 --- a/src/test/test-child.c +++ b/src/test/test-child.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2017, The Tor Project, Inc. */ +/* Copyright (c) 2011-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" diff --git a/src/test/test-memwipe.c b/src/test/test-memwipe.c index 89d946d506..c879013ed6 100644 --- a/src/test/test-memwipe.c +++ b/src/test/test-memwipe.c @@ -1,16 +1,17 @@ -/* Copyright (c) 2015-2017, The Tor Project, Inc. */ +/* Copyright (c) 2015-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" +#include "lib/crypt_ops/crypto_util.h" + +#include "lib/intmath/cmp.h" +#include "lib/malloc/malloc.h" + #include <string.h> #include <stdio.h> #include <sys/types.h> #include <stdlib.h> -#include "crypto.h" -#include "compat.h" -#include "util.h" - static unsigned fill_a_buffer_memset(void) __attribute__((noinline)); static unsigned fill_a_buffer_memwipe(void) __attribute__((noinline)); static unsigned fill_a_buffer_nothing(void) __attribute__((noinline)); @@ -215,4 +216,3 @@ main(int argc, char **argv) return 0; } } - diff --git a/src/test/test-network.sh b/src/test/test-network.sh index 6e0f286573..b7a9f1b3c0 100755 --- a/src/test/test-network.sh +++ b/src/test/test-network.sh @@ -52,12 +52,12 @@ done # - if $PWD looks like a tor build directory, set it to $PWD, or # - unset $TOR_DIR, and let chutney fall back to finding tor binaries in $PATH if [ ! -d "$TOR_DIR" ]; then - if [ -d "$BUILDDIR/src/or" -a -d "$BUILDDIR/src/tools" ]; then + if [ -d "$BUILDDIR/src/core/or" -a -d "$BUILDDIR/src/tools" ]; then # Choose the build directory # But only if it looks like one $ECHO "$myname: \$TOR_DIR not set, trying \$BUILDDIR" TOR_DIR="$BUILDDIR" - elif [ -d "$PWD/src/or" -a -d "$PWD/src/tools" ]; then + elif [ -d "$PWD/src/core/or" -a -d "$PWD/src/tools" ]; then # Guess the tor directory is the current directory # But only if it looks like one $ECHO "$myname: \$TOR_DIR not set, trying \$PWD" diff --git a/src/test/test-timers.c b/src/test/test-timers.c index a0b5b535c2..923f51ecce 100644 --- a/src/test/test-timers.c +++ b/src/test/test-timers.c @@ -1,4 +1,4 @@ -/* Copyright 2016-2017, The Tor Project, Inc. */ +/* Copyright 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" @@ -7,13 +7,13 @@ #include <stdio.h> #include <string.h> -#include <event2/event.h> - -#include "compat.h" -#include "compat_libevent.h" -#include "crypto.h" -#include "timers.h" -#include "util.h" +#include "lib/evloop/compat_libevent.h" +#include "lib/evloop/timers.h" +#include "lib/crypt_ops/crypto_init.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "lib/log/util_bug.h" +#include "lib/time/compat_time.h" +#include "lib/wallclock/timeval.h" #define N_TIMERS 1000 #define MAX_DURATION 30 @@ -50,7 +50,7 @@ timer_cb(tor_timer_t *t, void *arg, const monotime_t *now_mono) // printf("%d / %d\n",n_fired, N_TIMERS); if (n_fired == n_active_timers) { - event_base_loopbreak(tor_libevent_get_base()); + tor_libevent_exit_loop_after_callback(tor_libevent_get_base()); } } @@ -63,6 +63,10 @@ main(int argc, char **argv) memset(&cfg, 0, sizeof(cfg)); tor_libevent_initialize(&cfg); timers_initialize(); + init_logging(1); + + if (crypto_global_init(0, NULL, NULL) < 0) + return 1; int i; int ret; @@ -90,7 +94,7 @@ main(int argc, char **argv) --n_active_timers; } - event_base_loop(tor_libevent_get_base(), 0); + tor_libevent_run_event_loop(tor_libevent_get_base(), 0); int64_t total_difference = 0; uint64_t total_square_difference = 0; @@ -107,8 +111,8 @@ main(int argc, char **argv) total_square_difference += diff*diff; } const int64_t mean_diff = total_difference / n_active_timers; - printf("mean difference: "I64_FORMAT" usec\n", - I64_PRINTF_ARG(mean_diff)); + printf("mean difference: %"PRId64" usec\n", + (mean_diff)); const double mean_sq = ((double)total_square_difference)/ n_active_timers; const double sq_mean = mean_diff * mean_diff; @@ -141,4 +145,3 @@ main(int argc, char **argv) timers_shutdown(); return ret; } - diff --git a/src/test/test.c b/src/test/test.c index 2e7d399322..70d91e3967 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,6 +9,9 @@ **/ #include "orconfig.h" +#include "lib/crypt_ops/crypto_dh.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "app/config/or_state_st.h" #include <stdio.h> #ifdef HAVE_FCNTL_H @@ -26,36 +29,41 @@ /* These macros pull in declarations for some functions and structures that * are typically file-private. */ -#define GEOIP_PRIVATE #define ROUTER_PRIVATE #define CIRCUITSTATS_PRIVATE #define CIRCUITLIST_PRIVATE -#define MAIN_PRIVATE +#define MAINLOOP_PRIVATE #define STATEFILE_PRIVATE -#include "or.h" -#include "backtrace.h" -#include "buffers.h" -#include "circuitlist.h" -#include "circuitstats.h" -#include "compress.h" -#include "config.h" -#include "connection_edge.h" -#include "geoip.h" -#include "rendcommon.h" -#include "rendcache.h" -#include "test.h" -#include "main.h" -#include "memarea.h" -#include "onion.h" -#include "onion_ntor.h" -#include "onion_fast.h" -#include "onion_tap.h" -#include "policies.h" -#include "rephist.h" -#include "routerparse.h" -#include "statefile.h" -#include "crypto_curve25519.h" +#include "core/or/or.h" +#include "lib/err/backtrace.h" +#include "lib/container/buffers.h" +#include "core/or/circuitlist.h" +#include "core/or/circuitstats.h" +#include "lib/compress/compress.h" +#include "app/config/config.h" +#include "core/or/connection_edge.h" +#include "feature/rend/rendcommon.h" +#include "feature/rend/rendcache.h" +#include "feature/rend/rendparse.h" +#include "test/test.h" +#include "core/mainloop/mainloop.h" +#include "lib/memarea/memarea.h" +#include "core/or/onion.h" +#include "core/crypto/onion_ntor.h" +#include "core/crypto/onion_fast.h" +#include "core/crypto/onion_tap.h" +#include "core/or/policies.h" +#include "feature/stats/rephist.h" +#include "app/config/statefile.h" +#include "lib/crypt_ops/crypto_curve25519.h" + +#include "core/or/extend_info_st.h" +#include "core/or/or_circuit_st.h" +#include "feature/rend/rend_encoded_v2_service_descriptor_st.h" +#include "feature/rend/rend_intro_point_st.h" +#include "feature/rend/rend_service_descriptor_st.h" +#include "feature/relay/onion_queue.h" /** Run unit tests for the onion handshake code. */ static void @@ -137,7 +145,8 @@ test_bad_onion_handshake(void *arg) memset(junk_buf, 0, sizeof(junk_buf)); crypto_pk_obsolete_public_hybrid_encrypt(pk, junk_buf2, TAP_ONIONSKIN_CHALLENGE_LEN, - junk_buf, DH_KEY_LEN, PK_PKCS1_OAEP_PADDING, 1); + junk_buf, DH1024_KEY_LEN, + PK_PKCS1_OAEP_PADDING, 1); tt_int_op(-1, OP_EQ, onion_skin_TAP_server_handshake(junk_buf2, pk, NULL, s_buf, s_keys, 40)); @@ -345,6 +354,18 @@ test_onion_queues(void *arg) tor_free(onionskin); } +static crypto_cipher_t *crypto_rand_aes_cipher = NULL; + +// Mock replacement for crypto_rand: Generates bytes from a provided AES_CTR +// cipher in <b>crypto_rand_aes_cipher</b>. +static void +crypto_rand_deterministic_aes(char *out, size_t n) +{ + tor_assert(crypto_rand_aes_cipher); + memset(out, 0, n); + crypto_cipher_crypt_inplace(crypto_rand_aes_cipher, out, n); +} + static void test_circuit_timeout(void *arg) { @@ -374,6 +395,11 @@ test_circuit_timeout(void *arg) state = or_state_new(); + // Use a deterministic RNG here, or else we'll get nondeterministic + // coverage in some of the circuitstats functions. + MOCK(crypto_rand, crypto_rand_deterministic_aes); + crypto_rand_aes_cipher = crypto_cipher_new("xyzzyplughplover"); + circuitbuild_running_unit_tests(); #define timeout0 (build_time_t)(30*1000.0) initial.Xm = 3000; @@ -508,6 +534,8 @@ test_circuit_timeout(void *arg) circuit_build_times_free_timeouts(&final); or_state_free(state); teardown_periodic_events(); + UNMOCK(crypto_rand); + crypto_cipher_free(crypto_rand_aes_cipher); } /** Test encoding and parsing of rendezvous service descriptors. */ @@ -623,376 +651,6 @@ test_rend_fns(void *arg) tor_free(intro_points_encrypted); } - /* Record odd numbered fake-IPs using ipv6, even numbered fake-IPs - * using ipv4. Since our fake geoip database is the same between - * ipv4 and ipv6, we should get the same result no matter which - * address family we pick for each IP. */ -#define SET_TEST_ADDRESS(i) do { \ - if ((i) & 1) { \ - SET_TEST_IPV6(i); \ - tor_addr_from_in6(&addr, &in6); \ - } else { \ - tor_addr_from_ipv4h(&addr, (uint32_t) i); \ - } \ - } while (0) - - /* Make sure that country ID actually works. */ -#define SET_TEST_IPV6(i) \ - do { \ - set_uint32(in6.s6_addr + 12, htonl((uint32_t) (i))); \ - } while (0) -#define CHECK_COUNTRY(country, val) do { \ - /* test ipv4 country lookup */ \ - tt_str_op(country, OP_EQ, \ - geoip_get_country_name(geoip_get_country_by_ipv4(val))); \ - /* test ipv6 country lookup */ \ - SET_TEST_IPV6(val); \ - tt_str_op(country, OP_EQ, \ - geoip_get_country_name(geoip_get_country_by_ipv6(&in6))); \ - } while (0) - -/** Run unit tests for GeoIP code. */ -static void -test_geoip(void *arg) -{ - int i, j; - time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */ - char *s = NULL, *v = NULL; - const char *bridge_stats_1 = - "bridge-stats-end 2010-08-12 13:27:30 (86400 s)\n" - "bridge-ips zz=24,xy=8\n" - "bridge-ip-versions v4=16,v6=16\n" - "bridge-ip-transports <OR>=24\n", - *dirreq_stats_1 = - "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" - "dirreq-v3-ips ab=8\n" - "dirreq-v3-reqs ab=8\n" - "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0," - "not-modified=0,busy=0\n" - "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" - "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n", - *dirreq_stats_2 = - "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" - "dirreq-v3-ips \n" - "dirreq-v3-reqs \n" - "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0," - "not-modified=0,busy=0\n" - "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" - "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n", - *dirreq_stats_3 = - "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" - "dirreq-v3-ips \n" - "dirreq-v3-reqs \n" - "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0," - "not-modified=0,busy=0\n" - "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" - "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n", - *dirreq_stats_4 = - "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" - "dirreq-v3-ips \n" - "dirreq-v3-reqs \n" - "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0," - "not-modified=0,busy=0\n" - "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" - "dirreq-v3-tunneled-dl complete=0,timeout=0,running=4\n", - *entry_stats_1 = - "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n" - "entry-ips ab=8\n", - *entry_stats_2 = - "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n" - "entry-ips \n"; - tor_addr_t addr; - struct in6_addr in6; - - /* Populate the DB a bit. Add these in order, since we can't do the final - * 'sort' step. These aren't very good IP addresses, but they're perfectly - * fine uint32_t values. */ - (void)arg; - tt_int_op(0,OP_EQ, geoip_parse_entry("10,50,AB", AF_INET)); - tt_int_op(0,OP_EQ, geoip_parse_entry("52,90,XY", AF_INET)); - tt_int_op(0,OP_EQ, geoip_parse_entry("95,100,AB", AF_INET)); - tt_int_op(0,OP_EQ, geoip_parse_entry("\"105\",\"140\",\"ZZ\"", AF_INET)); - tt_int_op(0,OP_EQ, geoip_parse_entry("\"150\",\"190\",\"XY\"", AF_INET)); - tt_int_op(0,OP_EQ, geoip_parse_entry("\"200\",\"250\",\"AB\"", AF_INET)); - - /* Populate the IPv6 DB equivalently with fake IPs in the same range */ - tt_int_op(0,OP_EQ, geoip_parse_entry("::a,::32,AB", AF_INET6)); - tt_int_op(0,OP_EQ, geoip_parse_entry("::34,::5a,XY", AF_INET6)); - tt_int_op(0,OP_EQ, geoip_parse_entry("::5f,::64,AB", AF_INET6)); - tt_int_op(0,OP_EQ, geoip_parse_entry("::69,::8c,ZZ", AF_INET6)); - tt_int_op(0,OP_EQ, geoip_parse_entry("::96,::be,XY", AF_INET6)); - tt_int_op(0,OP_EQ, geoip_parse_entry("::c8,::fa,AB", AF_INET6)); - - /* We should have 4 countries: ??, ab, xy, zz. */ - tt_int_op(4,OP_EQ, geoip_get_n_countries()); - memset(&in6, 0, sizeof(in6)); - - CHECK_COUNTRY("??", 3); - CHECK_COUNTRY("ab", 32); - CHECK_COUNTRY("??", 5); - CHECK_COUNTRY("??", 51); - CHECK_COUNTRY("xy", 150); - CHECK_COUNTRY("xy", 190); - CHECK_COUNTRY("??", 2000); - - tt_int_op(0,OP_EQ, geoip_get_country_by_ipv4(3)); - SET_TEST_IPV6(3); - tt_int_op(0,OP_EQ, geoip_get_country_by_ipv6(&in6)); - - get_options_mutable()->BridgeRelay = 1; - get_options_mutable()->BridgeRecordUsageByCountry = 1; - /* Put 9 observations in AB... */ - for (i=32; i < 40; ++i) { - SET_TEST_ADDRESS(i); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200); - } - SET_TEST_ADDRESS(225); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200); - /* and 3 observations in XY, several times. */ - for (j=0; j < 10; ++j) - for (i=52; i < 55; ++i) { - SET_TEST_ADDRESS(i); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-3600); - } - /* and 17 observations in ZZ... */ - for (i=110; i < 127; ++i) { - SET_TEST_ADDRESS(i); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now); - } - geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v); - tt_assert(s); - tt_assert(v); - tt_str_op("zz=24,ab=16,xy=8",OP_EQ, s); - tt_str_op("v4=16,v6=16",OP_EQ, v); - tor_free(s); - tor_free(v); - - /* Now clear out all the AB observations. */ - geoip_remove_old_clients(now-6000); - geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v); - tt_assert(s); - tt_assert(v); - tt_str_op("zz=24,xy=8",OP_EQ, s); - tt_str_op("v4=16,v6=16",OP_EQ, v); - tor_free(s); - tor_free(v); - - /* Start testing bridge statistics by making sure that we don't output - * bridge stats without initializing them. */ - s = geoip_format_bridge_stats(now + 86400); - tt_ptr_op(s, OP_EQ, NULL); - - /* Initialize stats and generate the bridge-stats history string out of - * the connecting clients added above. */ - geoip_bridge_stats_init(now); - s = geoip_format_bridge_stats(now + 86400); - tt_assert(s); - tt_str_op(bridge_stats_1,OP_EQ, s); - tor_free(s); - - /* Stop collecting bridge stats and make sure we don't write a history - * string anymore. */ - geoip_bridge_stats_term(); - s = geoip_format_bridge_stats(now + 86400); - tt_ptr_op(s, OP_EQ, NULL); - - /* Stop being a bridge and start being a directory mirror that gathers - * directory request statistics. */ - geoip_bridge_stats_term(); - get_options_mutable()->BridgeRelay = 0; - get_options_mutable()->BridgeRecordUsageByCountry = 0; - get_options_mutable()->DirReqStatistics = 1; - - /* Start testing dirreq statistics by making sure that we don't collect - * dirreq stats without initializing them. */ - SET_TEST_ADDRESS(100); - geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now); - s = geoip_format_dirreq_stats(now + 86400); - tt_ptr_op(s, OP_EQ, NULL); - - /* Initialize stats, note one connecting client, and generate the - * dirreq-stats history string. */ - geoip_dirreq_stats_init(now); - SET_TEST_ADDRESS(100); - geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now); - s = geoip_format_dirreq_stats(now + 86400); - tt_str_op(dirreq_stats_1,OP_EQ, s); - tor_free(s); - - /* Stop collecting stats, add another connecting client, and ensure we - * don't generate a history string. */ - geoip_dirreq_stats_term(); - SET_TEST_ADDRESS(101); - geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now); - s = geoip_format_dirreq_stats(now + 86400); - tt_ptr_op(s, OP_EQ, NULL); - - /* Re-start stats, add a connecting client, reset stats, and make sure - * that we get an all empty history string. */ - geoip_dirreq_stats_init(now); - SET_TEST_ADDRESS(100); - geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now); - geoip_reset_dirreq_stats(now); - s = geoip_format_dirreq_stats(now + 86400); - tt_str_op(dirreq_stats_2,OP_EQ, s); - tor_free(s); - - /* Note a successful network status response and make sure that it - * appears in the history string. */ - geoip_note_ns_response(GEOIP_SUCCESS); - s = geoip_format_dirreq_stats(now + 86400); - tt_str_op(dirreq_stats_3,OP_EQ, s); - tor_free(s); - - /* Start a tunneled directory request. */ - geoip_start_dirreq((uint64_t) 1, 1024, DIRREQ_TUNNELED); - s = geoip_format_dirreq_stats(now + 86400); - tt_str_op(dirreq_stats_4,OP_EQ, s); - tor_free(s); - - /* Stop collecting directory request statistics and start gathering - * entry stats. */ - geoip_dirreq_stats_term(); - get_options_mutable()->DirReqStatistics = 0; - get_options_mutable()->EntryStatistics = 1; - - /* Start testing entry statistics by making sure that we don't collect - * anything without initializing entry stats. */ - SET_TEST_ADDRESS(100); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now); - s = geoip_format_entry_stats(now + 86400); - tt_ptr_op(s, OP_EQ, NULL); - - /* Initialize stats, note one connecting client, and generate the - * entry-stats history string. */ - geoip_entry_stats_init(now); - SET_TEST_ADDRESS(100); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now); - s = geoip_format_entry_stats(now + 86400); - tt_str_op(entry_stats_1,OP_EQ, s); - tor_free(s); - - /* Stop collecting stats, add another connecting client, and ensure we - * don't generate a history string. */ - geoip_entry_stats_term(); - SET_TEST_ADDRESS(101); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now); - s = geoip_format_entry_stats(now + 86400); - tt_ptr_op(s, OP_EQ, NULL); - - /* Re-start stats, add a connecting client, reset stats, and make sure - * that we get an all empty history string. */ - geoip_entry_stats_init(now); - SET_TEST_ADDRESS(100); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now); - geoip_reset_entry_stats(now); - s = geoip_format_entry_stats(now + 86400); - tt_str_op(entry_stats_2,OP_EQ, s); - tor_free(s); - - /* Test the OOM handler. Add a client, run the OOM. */ - geoip_entry_stats_init(now); - SET_TEST_ADDRESS(100); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, - now - (12 * 60 * 60)); - /* We've seen this 12 hours ago. Run the OOM, it should clean the entry - * because it is above the minimum cutoff of 4 hours. */ - size_t bytes_removed = geoip_client_cache_handle_oom(now, 1000); - tt_size_op(bytes_removed, OP_GT, 0); - - /* Do it again but this time with an entry with a lower cutoff. */ - geoip_entry_stats_init(now); - SET_TEST_ADDRESS(100); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, - now - (3 * 60 * 60)); - bytes_removed = geoip_client_cache_handle_oom(now, 1000); - tt_size_op(bytes_removed, OP_EQ, 0); - - /* Stop collecting entry statistics. */ - geoip_entry_stats_term(); - get_options_mutable()->EntryStatistics = 0; - - done: - tor_free(s); - tor_free(v); -} - -static void -test_geoip_with_pt(void *arg) -{ - time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */ - char *s = NULL; - int i; - tor_addr_t addr; - struct in6_addr in6; - - (void)arg; - get_options_mutable()->BridgeRelay = 1; - get_options_mutable()->BridgeRecordUsageByCountry = 1; - - memset(&in6, 0, sizeof(in6)); - - /* No clients seen yet. */ - s = geoip_get_transport_history(); - tor_assert(!s); - - /* 4 connections without a pluggable transport */ - for (i=0; i < 4; ++i) { - SET_TEST_ADDRESS(i); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200); - } - - /* 9 connections with "alpha" */ - for (i=4; i < 13; ++i) { - SET_TEST_ADDRESS(i); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "alpha", now-7200); - } - - /* one connection with "beta" */ - SET_TEST_ADDRESS(13); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "beta", now-7200); - - /* 14 connections with "charlie" */ - for (i=14; i < 28; ++i) { - SET_TEST_ADDRESS(i); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "charlie", now-7200); - } - - /* 131 connections with "ddr" */ - for (i=28; i < 159; ++i) { - SET_TEST_ADDRESS(i); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "ddr", now-7200); - } - - /* 8 connections with "entropy" */ - for (i=159; i < 167; ++i) { - SET_TEST_ADDRESS(i); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "entropy", now-7200); - } - - /* 2 connections from the same IP with two different transports. */ - SET_TEST_ADDRESS(++i); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "fire", now-7200); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "google", now-7200); - - /* Test the transport history string. */ - s = geoip_get_transport_history(); - tor_assert(s); - tt_str_op(s,OP_EQ, "<OR>=8,alpha=16,beta=8,charlie=16,ddr=136," - "entropy=8,fire=8,google=8"); - - /* Stop collecting entry statistics. */ - geoip_entry_stats_term(); - get_options_mutable()->EntryStatistics = 0; - - done: - tor_free(s); -} - -#undef SET_TEST_ADDRESS -#undef SET_TEST_IPV6 -#undef CHECK_COUNTRY - /** Run unit tests for stats code. */ static void test_stats(void *arg) @@ -1166,8 +824,6 @@ static struct testcase_t test_array[] = { { "fast_handshake", test_fast_handshake, 0, NULL, NULL }, FORK(circuit_timeout), FORK(rend_fns), - ENT(geoip), - FORK(geoip_with_pt), FORK(stats), END_OF_TESTCASES @@ -1179,7 +835,9 @@ struct testgroup_t testgroups[] = { { "addr/", addr_tests }, { "address/", address_tests }, { "address_set/", address_set_tests }, + { "bridges/", bridges_tests }, { "buffer/", buffer_tests }, + { "bwmgt/", bwmgt_tests }, { "cellfmt/", cell_format_tests }, { "cellqueue/", cell_queue_tests }, { "channel/", channel_tests }, @@ -1201,15 +859,21 @@ struct testgroup_t testgroups[] = { { "control/", controller_tests }, { "control/event/", controller_event_tests }, { "crypto/", crypto_tests }, + { "crypto/ope/", crypto_ope_tests }, +#ifdef ENABLE_OPENSSL { "crypto/openssl/", crypto_openssl_tests }, +#endif + { "crypto/pem/", pem_tests }, { "dir/", dir_tests }, { "dir_handle_get/", dir_handle_get_tests }, { "dir/md/", microdesc_tests }, + { "dir/voting-schedule/", voting_schedule_tests }, { "dos/", dos_tests }, { "entryconn/", entryconn_tests }, { "entrynodes/", entrynodes_tests }, { "guardfraction/", guardfraction_tests }, { "extorport/", extorport_tests }, + { "geoip/", geoip_tests }, { "legacy_hs/", hs_tests }, { "hs_cache/", hs_cache }, { "hs_cell/", hs_cell_tests }, @@ -1224,10 +888,12 @@ struct testgroup_t testgroups[] = { { "introduce/", introduce_tests }, { "keypin/", keypin_tests }, { "link-handshake/", link_handshake_tests }, + { "mainloop/", mainloop_tests }, { "nodelist/", nodelist_tests }, { "oom/", oom_tests }, { "oos/", oos_tests }, { "options/", options_tests }, + { "periodic-event/" , periodic_event_tests }, { "policy/" , policy_tests }, { "procmon/", procmon_tests }, { "proto/http/", proto_http_tests }, @@ -1236,6 +902,7 @@ struct testgroup_t testgroups[] = { { "pt/", pt_tests }, { "relay/" , relay_tests }, { "relaycell/", relaycell_tests }, + { "relaycrypt/", relaycrypt_tests }, { "rend_cache/", rend_cache_tests }, { "replaycache/", replaycache_tests }, { "router/", router_tests }, @@ -1248,14 +915,16 @@ struct testgroup_t testgroups[] = { { "status/" , status_tests }, { "storagedir/", storagedir_tests }, { "tortls/", tortls_tests }, +#ifndef ENABLE_NSS + { "tortls/openssl/", tortls_openssl_tests }, +#endif + { "tortls/x509/", x509_tests }, { "util/", util_tests }, { "util/format/", util_format_tests }, { "util/logging/", logging_tests }, { "util/process/", util_process_tests }, - { "util/pubsub/", pubsub_tests }, { "util/thread/", thread_tests }, { "util/handle/", handle_tests }, { "dns/", dns_tests }, END_OF_GROUPS }; - diff --git a/src/test/test.h b/src/test/test.h index 26139fc5fe..a46fedf3e0 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2003, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #ifndef TOR_TEST_H @@ -11,7 +11,8 @@ * \brief Macros and functions used by unit tests. */ -#include "compat.h" +#define DEBUG_SMARTLIST 1 + #include "tinytest.h" #define TT_EXIT_TEST_FUNCTION STMT_BEGIN goto done; STMT_END #include "tinytest_macros.h" @@ -49,28 +50,28 @@ tt_double_op((a), OP_LE, (b)); \ STMT_END -#ifdef _MSC_VER -#define U64_PRINTF_TYPE uint64_t -#define I64_PRINTF_TYPE int64_t -#else -#define U64_PRINTF_TYPE unsigned long long -#define I64_PRINTF_TYPE long long -#endif /* defined(_MSC_VER) */ - #define tt_size_op(a,op,b) \ tt_assert_test_fmt_type(a,b,#a" "#op" "#b,size_t,(val1_ op val2_), \ - U64_PRINTF_TYPE, U64_FORMAT, \ - {print_ = (U64_PRINTF_TYPE) value_;}, {}, TT_EXIT_TEST_FUNCTION) + size_t, "%"TOR_PRIuSZ, \ + {print_ = (size_t) value_;}, {}, TT_EXIT_TEST_FUNCTION) #define tt_u64_op(a,op,b) \ tt_assert_test_fmt_type(a,b,#a" "#op" "#b,uint64_t,(val1_ op val2_), \ - U64_PRINTF_TYPE, U64_FORMAT, \ - {print_ = (U64_PRINTF_TYPE) value_;}, {}, TT_EXIT_TEST_FUNCTION) + uint64_t, "%"PRIu64, \ + {print_ = (uint64_t) value_;}, {}, TT_EXIT_TEST_FUNCTION) #define tt_i64_op(a,op,b) \ - tt_assert_test_fmt_type(a,b,#a" "#op" "#b,int64_t,(val1_ op val2_), \ - I64_PRINTF_TYPE, I64_FORMAT, \ - {print_ = (I64_PRINTF_TYPE) value_;}, {}, TT_EXIT_TEST_FUNCTION) + tt_assert_test_fmt_type(a,b,#a" "#op" "#b,int64_t,(val1_ op val2_), \ + int64_t, "%"PRId64, \ + {print_ = (int64_t) value_;}, {}, TT_EXIT_TEST_FUNCTION) + +/** + * Declare that the test is done, even though no tt___op() calls were made. + * + * For use when you only want to test calling something, but not check + * any values/pointers/etc afterwards. + */ +#define tt_finished() TT_EXIT_TEST_FUNCTION const char *get_fname(const char *name); const char *get_fname_rnd(const char *name); @@ -178,6 +179,8 @@ extern struct testcase_t accounting_tests[]; extern struct testcase_t addr_tests[]; extern struct testcase_t address_tests[]; extern struct testcase_t address_set_tests[]; +extern struct testcase_t bridges_tests[]; +extern struct testcase_t bwmgt_tests[]; extern struct testcase_t buffer_tests[]; extern struct testcase_t cell_format_tests[]; extern struct testcase_t cell_queue_tests[]; @@ -200,6 +203,7 @@ extern struct testcase_t container_tests[]; extern struct testcase_t controller_tests[]; extern struct testcase_t controller_event_tests[]; extern struct testcase_t crypto_tests[]; +extern struct testcase_t crypto_ope_tests[]; extern struct testcase_t crypto_openssl_tests[]; extern struct testcase_t dir_tests[]; extern struct testcase_t dir_handle_get_tests[]; @@ -208,6 +212,7 @@ extern struct testcase_t entryconn_tests[]; extern struct testcase_t entrynodes_tests[]; extern struct testcase_t guardfraction_tests[]; extern struct testcase_t extorport_tests[]; +extern struct testcase_t geoip_tests[]; extern struct testcase_t hs_tests[]; extern struct testcase_t hs_cache[]; extern struct testcase_t hs_cell_tests[]; @@ -223,20 +228,23 @@ extern struct testcase_t introduce_tests[]; extern struct testcase_t keypin_tests[]; extern struct testcase_t link_handshake_tests[]; extern struct testcase_t logging_tests[]; +extern struct testcase_t mainloop_tests[]; extern struct testcase_t microdesc_tests[]; extern struct testcase_t nodelist_tests[]; extern struct testcase_t oom_tests[]; extern struct testcase_t oos_tests[]; extern struct testcase_t options_tests[]; +extern struct testcase_t pem_tests[]; +extern struct testcase_t periodic_event_tests[]; extern struct testcase_t policy_tests[]; extern struct testcase_t procmon_tests[]; extern struct testcase_t proto_http_tests[]; extern struct testcase_t proto_misc_tests[]; extern struct testcase_t protover_tests[]; -extern struct testcase_t pubsub_tests[]; extern struct testcase_t pt_tests[]; extern struct testcase_t relay_tests[]; extern struct testcase_t relaycell_tests[]; +extern struct testcase_t relaycrypt_tests[]; extern struct testcase_t rend_cache_tests[]; extern struct testcase_t replaycache_tests[]; extern struct testcase_t router_tests[]; @@ -249,12 +257,15 @@ extern struct testcase_t socks_tests[]; extern struct testcase_t status_tests[]; extern struct testcase_t thread_tests[]; extern struct testcase_t tortls_tests[]; +extern struct testcase_t tortls_openssl_tests[]; extern struct testcase_t util_tests[]; extern struct testcase_t util_format_tests[]; extern struct testcase_t util_process_tests[]; +extern struct testcase_t voting_schedule_tests[]; extern struct testcase_t dns_tests[]; extern struct testcase_t handle_tests[]; extern struct testcase_t sr_tests[]; +extern struct testcase_t x509_tests[]; extern struct testcase_t slow_crypto_tests[]; extern struct testcase_t slow_util_tests[]; @@ -275,4 +286,3 @@ extern const char AUTHORITY_SIGNKEY_C_DIGEST[]; extern const char AUTHORITY_SIGNKEY_C_DIGEST256[]; #endif /* !defined(TOR_TEST_H) */ - diff --git a/src/test/test_accounting.c b/src/test/test_accounting.c index b0d37b2989..7721a9eb99 100644 --- a/src/test/test_accounting.c +++ b/src/test/test_accounting.c @@ -1,13 +1,15 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "or.h" -#include "test.h" +#include "core/or/or.h" +#include "test/test.h" #define HIBERNATE_PRIVATE -#include "hibernate.h" -#include "config.h" +#include "feature/hibernate/hibernate.h" +#include "app/config/config.h" #define STATEFILE_PRIVATE -#include "statefile.h" +#include "app/config/statefile.h" + +#include "app/config/or_state_st.h" #define NS_MODULE accounting @@ -102,4 +104,3 @@ struct testcase_t accounting_tests[] = { { "bwlimits", test_accounting_limits, TT_FORK, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_addr.c b/src/test/test_addr.c index e1a40b7e60..a9004048a5 100644 --- a/src/test/test_addr.c +++ b/src/test/test_addr.c @@ -1,74 +1,25 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define ADDRESSMAP_PRIVATE #include "orconfig.h" -#include "or.h" -#include "test.h" -#include "addressmap.h" +#include "core/or/or.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "test/test.h" +#include "feature/client/addressmap.h" +#include "test/log_test_helpers.h" +#include "lib/net/resolve.h" -/** Mocking replacement: only handles localhost. */ -static int -mock_tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr_out) -{ - if (!strcmp(name, "localhost")) { - if (family == AF_INET || family == AF_UNSPEC) { - tor_addr_from_ipv4h(addr_out, 0x7f000001); - return 0; - } else if (family == AF_INET6) { - char bytes[16] = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1 }; - tor_addr_from_ipv6_bytes(addr_out, bytes); - return 0; - } - } - return -1; -} +#ifdef HAVE_SYS_UN_H +#include <sys/un.h> +#endif static void test_addr_basic(void *arg) { - uint32_t u32; - uint16_t u16; - char *cp; - - /* Test addr_port_lookup */ - (void)arg; - cp = NULL; u32 = 3; u16 = 3; - tt_assert(!addr_port_lookup(LOG_WARN, "1.2.3.4", &cp, &u32, &u16)); - tt_str_op(cp,OP_EQ, "1.2.3.4"); - tt_int_op(u32,OP_EQ, 0x01020304u); - tt_int_op(u16,OP_EQ, 0); - tor_free(cp); - tt_assert(!addr_port_lookup(LOG_WARN, "4.3.2.1:99", &cp, &u32, &u16)); - tt_str_op(cp,OP_EQ, "4.3.2.1"); - tt_int_op(u32,OP_EQ, 0x04030201u); - tt_int_op(u16,OP_EQ, 99); - tor_free(cp); - - MOCK(tor_addr_lookup, mock_tor_addr_lookup); - - tt_assert(!addr_port_lookup(LOG_WARN, "nonexistent.address:4040", - &cp, NULL, &u16)); - tt_str_op(cp,OP_EQ, "nonexistent.address"); - tt_int_op(u16,OP_EQ, 4040); - tor_free(cp); - tt_assert(!addr_port_lookup(LOG_WARN, "localhost:9999", &cp, &u32, &u16)); - tt_str_op(cp,OP_EQ, "localhost"); - tt_int_op(u16,OP_EQ, 9999); - tt_int_op(u32,OP_EQ, 0x7f000001u); - tor_free(cp); - u32 = 3; - tt_assert(!addr_port_lookup(LOG_WARN, "localhost", NULL, &u32, &u16)); - tt_ptr_op(cp,OP_EQ, NULL); - tt_int_op(u32,OP_EQ, 0x7f000001u); - tt_int_op(u16,OP_EQ, 0); - tor_free(cp); - - tt_assert(addr_port_lookup(LOG_WARN, "localhost:3", &cp, &u32, NULL)); - tor_free(cp); + (void) arg; tt_int_op(0,OP_EQ, addr_mask_get_bits(0x0u)); tt_int_op(32,OP_EQ, addr_mask_get_bits(0xFFFFFFFFu)); @@ -96,8 +47,7 @@ test_addr_basic(void *arg) } done: - UNMOCK(tor_addr_lookup); - tor_free(cp); + ; } #define test_op_ip6_(a,op,b,e1,e2) \ @@ -941,6 +891,158 @@ test_virtaddrmap(void *data) ; } +static const char *canned_data = NULL; +static size_t canned_data_len = 0; + +/* Mock replacement for crypto_rand() that returns canned data from + * canned_data above. */ +static void +crypto_canned(char *ptr, size_t n) +{ + if (canned_data_len) { + size_t to_copy = MIN(n, canned_data_len); + memcpy(ptr, canned_data, to_copy); + canned_data += to_copy; + canned_data_len -= to_copy; + n -= to_copy; + ptr += to_copy; + } + if (n) { + crypto_rand_unmocked(ptr, n); + } +} + +static void +test_virtaddrmap_persist(void *data) +{ + (void)data; + const char *a, *b, *c; + tor_addr_t addr; + char *ones = NULL; + + addressmap_init(); + + // Try a hostname. + a = addressmap_register_virtual_address(RESOLVED_TYPE_HOSTNAME, + tor_strdup("foobar.baz")); + tt_assert(a); + tt_assert(!strcmpend(a, ".virtual")); + + // mock crypto_rand to repeat the same result twice; make sure we get + // different outcomes. (Because even though the odds for receiving the + // same 80-bit address twice is only 1/2^40, it could still happen for + // some user -- but running our test through 2^40 iterations isn't + // reasonable.) + canned_data = "1234567890" // the first call returns this. + "1234567890" // the second call returns this. + "abcdefghij"; // the third call returns this. + canned_data_len = 30; + MOCK(crypto_rand, crypto_canned); + + a = addressmap_register_virtual_address(RESOLVED_TYPE_HOSTNAME, + tor_strdup("quuxit.baz")); + b = addressmap_register_virtual_address(RESOLVED_TYPE_HOSTNAME, + tor_strdup("nescio.baz")); + tt_assert(a); + tt_assert(b); + tt_str_op(a, OP_EQ, "gezdgnbvgy3tqojq.virtual"); + tt_str_op(b, OP_EQ, "mfrggzdfmztwq2lk.virtual"); + + // Now try something to get us an ipv4 address + UNMOCK(crypto_rand); + tt_int_op(0,OP_EQ, parse_virtual_addr_network("192.168.0.0/16", + AF_INET, 0, NULL)); + a = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4, + tor_strdup("foobar.baz")); + tt_assert(a); + tt_assert(!strcmpstart(a, "192.168.")); + tor_addr_parse(&addr, a); + tt_int_op(AF_INET, OP_EQ, tor_addr_family(&addr)); + + b = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4, + tor_strdup("quuxit.baz")); + tt_str_op(b, OP_NE, a); + tt_assert(!strcmpstart(b, "192.168.")); + + // Try some canned entropy and verify all the we discard duplicates, + // addresses that end with 0, and addresses that end with 255. + MOCK(crypto_rand, crypto_canned); + canned_data = "\x01\x02\x03\x04" // okay + "\x01\x02\x03\x04" // duplicate + "\x03\x04\x00\x00" // bad ending 1 + "\x05\x05\x00\xff" // bad ending 2 + "\x05\x06\x07\xf0"; // okay + canned_data_len = 20; + a = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4, + tor_strdup("wumble.onion")); + b = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4, + tor_strdup("wumpus.onion")); + tt_str_op(a, OP_EQ, "192.168.3.4"); + tt_str_op(b, OP_EQ, "192.168.7.240"); + + // Now try IPv6! + UNMOCK(crypto_rand); + tt_int_op(0,OP_EQ, parse_virtual_addr_network("1010:F000::/20", + AF_INET6, 0, NULL)); + a = addressmap_register_virtual_address(RESOLVED_TYPE_IPV6, + tor_strdup("foobar.baz")); + tt_assert(a); + tt_assert(!strcmpstart(a, "[1010:f")); + tor_addr_parse(&addr, a); + tt_int_op(AF_INET6, OP_EQ, tor_addr_family(&addr)); + + b = addressmap_register_virtual_address(RESOLVED_TYPE_IPV6, + tor_strdup("quuxit.baz")); + tt_str_op(b, OP_NE, a); + tt_assert(!strcmpstart(b, "[1010:f")); + + // Try IPv6 with canned entropy, to make sure we detect duplicates. + MOCK(crypto_rand, crypto_canned); + canned_data = "acanthopterygian" // okay + "cinematographist" // okay + "acanthopterygian" // duplicate + "acanthopterygian" // duplicate + "acanthopterygian" // duplicate + "cinematographist" // duplicate + "coadministration"; // okay + canned_data_len = 16 * 7; + a = addressmap_register_virtual_address(RESOLVED_TYPE_IPV6, + tor_strdup("wuffle.baz")); + b = addressmap_register_virtual_address(RESOLVED_TYPE_IPV6, + tor_strdup("gribble.baz")); + c = addressmap_register_virtual_address(RESOLVED_TYPE_IPV6, + tor_strdup("surprisingly-legible.baz")); + tt_str_op(a, OP_EQ, "[1010:f16e:7468:6f70:7465:7279:6769:616e]"); + tt_str_op(b, OP_EQ, "[1010:fe65:6d61:746f:6772:6170:6869:7374]"); + tt_str_op(c, OP_EQ, "[1010:f164:6d69:6e69:7374:7261:7469:6f6e]"); + + // Try address exhaustion: make sure we can actually fail if we + // get too many already-existing addresses. + canned_data_len = 128*1024; + canned_data = ones = tor_malloc(canned_data_len); + memset(ones, 1, canned_data_len); + // There is some chance this one will fail if a previous random + // allocation gave out the address already. + a = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4, + tor_strdup("might-work.onion")); + if (a) { + tt_str_op(a, OP_EQ, "192.168.1.1"); + } + setup_capture_of_logs(LOG_WARN); + // This one will definitely fail, since we've set up the RNG to hand + // out "1" forever. + b = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4, + tor_strdup("wont-work.onion")); + tt_assert(b == NULL); + expect_single_log_msg_containing("Ran out of virtual addresses!"); + + done: + UNMOCK(crypto_rand); + tor_free(ones); + addressmap_free_all(); + teardown_capture_of_logs(); +} + static void test_addr_localname(void *arg) { @@ -1095,6 +1197,7 @@ struct testcase_t addr_tests[] = { ADDR_LEGACY(ip6_helpers), ADDR_LEGACY(parse), { "virtaddr", test_virtaddrmap, 0, NULL, NULL }, + { "virtaddr_persist", test_virtaddrmap_persist, TT_FORK, NULL, NULL }, { "localname", test_addr_localname, 0, NULL, NULL }, { "dup_ip", test_addr_dup_ip, 0, NULL, NULL }, { "sockaddr_to_str", test_addr_sockaddr_to_str, 0, NULL, NULL }, @@ -1102,4 +1205,3 @@ struct testcase_t addr_tests[] = { { "make_null", test_addr_make_null, 0, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_address.c b/src/test/test_address.c index 9c88d37a41..e99220f838 100644 --- a/src/test/test_address.c +++ b/src/test/test_address.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define ADDRESS_PRIVATE @@ -23,10 +23,11 @@ #include <net/if.h> #endif /* defined(HAVE_IFCONF_TO_SMARTLIST) */ -#include "or.h" -#include "address.h" -#include "test.h" -#include "log_test_helpers.h" +#include "core/or/or.h" +#include "feature/nodelist/nodelist.h" +#include "lib/net/address.h" +#include "test/test.h" +#include "test/log_test_helpers.h" /** Return 1 iff <b>sockaddr1</b> and <b>sockaddr2</b> represent * the same IP address and port combination. Otherwise, return 0. @@ -1139,6 +1140,36 @@ test_address_tor_addr_eq_ipv4h(void *ignored) tor_free(a); } +static void +test_address_tor_addr_in_same_network_family(void *ignored) +{ + (void)ignored; + tor_addr_t a, b; + + tor_addr_parse(&a, "8.8.8.8"); + tor_addr_parse(&b, "8.8.4.4"); + tt_int_op(addrs_in_same_network_family(&a, &b), OP_EQ, 1); + + tor_addr_parse(&a, "8.8.8.8"); + tor_addr_parse(&b, "1.1.1.1"); + tt_int_op(addrs_in_same_network_family(&a, &b), OP_EQ, 0); + + tor_addr_parse(&a, "8.8.8.8"); + tor_addr_parse(&b, "2001:4860:4860::8844"); + tt_int_op(addrs_in_same_network_family(&a, &b), OP_EQ, 0); + + tor_addr_parse(&a, "2001:4860:4860::8888"); + tor_addr_parse(&b, "2001:4860:4860::8844"); + tt_int_op(addrs_in_same_network_family(&a, &b), OP_EQ, 1); + + tor_addr_parse(&a, "2001:4860:4860::8888"); + tor_addr_parse(&b, "2001:470:20::2"); + tt_int_op(addrs_in_same_network_family(&a, &b), OP_EQ, 0); + + done: + return; +} + #define ADDRESS_TEST(name, flags) \ { #name, test_address_ ## name, flags, NULL, NULL } @@ -1170,6 +1201,7 @@ struct testcase_t address_tests[] = { ADDRESS_TEST(tor_addr_to_ipv4n, 0), ADDRESS_TEST(tor_addr_to_mapped_ipv4h, 0), ADDRESS_TEST(tor_addr_eq_ipv4h, 0), + ADDRESS_TEST(tor_addr_in_same_network_family, 0), END_OF_TESTCASES }; diff --git a/src/test/test_address_set.c b/src/test/test_address_set.c index df022f539a..f231740011 100644 --- a/src/test/test_address_set.c +++ b/src/test/test_address_set.c @@ -1,15 +1,21 @@ -/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "or.h" -#include "address_set.h" -#include "microdesc.h" -#include "networkstatus.h" -#include "nodelist.h" -#include "routerlist.h" -#include "torcert.h" - -#include "test.h" +#include "core/or/or.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "core/or/address_set.h" +#include "feature/nodelist/microdesc.h" +#include "feature/nodelist/networkstatus.h" +#include "feature/nodelist/nodelist.h" +#include "feature/nodelist/routerlist.h" +#include "feature/nodelist/torcert.h" + +#include "feature/nodelist/microdesc_st.h" +#include "feature/nodelist/networkstatus_st.h" +#include "feature/nodelist/routerinfo_st.h" +#include "feature/nodelist/routerstatus_st.h" + +#include "test/test.h" static networkstatus_t *dummy_ns = NULL; static networkstatus_t * diff --git a/src/test/test_bridges.c b/src/test/test_bridges.c new file mode 100644 index 0000000000..1cad5445f4 --- /dev/null +++ b/src/test/test_bridges.c @@ -0,0 +1,704 @@ +/* Copyright (c) 2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file test_bridges.c + * \brief Unittests for code in bridges.c + **/ + +#define TOR_BRIDGES_PRIVATE +#define PT_PRIVATE /* Only needed for the mock_* items below */ + +#include <stdbool.h> + +#include "core/or/or.h" +#include "lib/net/address.h" +#include "feature/client/bridges.h" +#include "app/config/config.h" +#include "feature/client/transports.h" +#include "feature/nodelist/node_st.h" +#include "feature/nodelist/routerinfo_st.h" +#include "feature/nodelist/routerstatus_st.h" +#include "feature/nodelist/microdesc_st.h" + +/* Test suite stuff */ +#include "test/test.h" + +/** + * A mocked transport_t, constructed via mock_transport_get_by_name(). + */ +static transport_t *mock_transport = NULL; + +/** + * Mock transport_get_by_name() to simply return a transport_t for the + * transport name that was input to it. + */ +static transport_t * +mock_transport_get_by_name(const char *name) +{ + tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t)); + uint16_t port = 9999; + int socksv = 9; + char *args = tor_strdup("foo=bar"); + + if (!mock_transport) { + tor_addr_parse(addr, "99.99.99.99"); + mock_transport = transport_new(addr, port, name, socksv, args); + } + + tor_free(addr); + tor_free(args); + + return mock_transport; +} + +#undef PT_PRIVATE /* defined(PT_PRIVATE) */ + +/** + * Test helper: Add a variety of bridges to our global bridgelist. + */ +static void +helper_add_bridges_to_bridgelist(void *arg) +{ + /* Note: the two bridges which do not have specified fingerprints will be + * internally stored as both having the same fingerprint of all-zero bytes. + */ + + (void)arg; + char *bridge0 = tor_strdup("6.6.6.6:6666"); + char *bridge1 = tor_strdup("6.6.6.7:6667 " + "A10C4F666D27364036B562823E5830BC448E046A"); + char *bridge2 = tor_strdup("obfs4 198.245.60.51:443 " + "752CF7825B3B9EA6A98C83AC41F7099D67007EA5 " + "cert=xpmQtKUqQ/6v5X7ijgYE/f03+l2/EuQ1dexjyUhh16wQlu/" + "cpXUGalmhDIlhuiQPNEKmKw iat-mode=0"); + char *bridge3 = tor_strdup("banana 5.5.5.5:5555 " + "9D6AE1BD4FDF39721CE908966E79E16F9BFCCF2F"); + char *bridge4 = tor_strdup("obfs4 1.2.3.4:1234 " + "foo=abcdefghijklmnopqrstuvwxyz"); + char *bridge5 = tor_strdup("apple 4.4.4.4:4444 " + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA " + "foo=abcdefghijklmnopqrstuvwxyz"); + char *bridge6 = tor_strdup("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:6666"); + + mark_bridge_list(); + +#define ADD_BRIDGE(bridge) \ + bridge_line_t *bridge_line_ ##bridge = parse_bridge_line(bridge); \ + if (!bridge_line_ ##bridge) { \ + printf("Unparseable bridge line: '%s'", #bridge); \ + } else { \ + bridge_add_from_config(bridge_line_ ##bridge); \ + } \ + tor_free(bridge); + + ADD_BRIDGE(bridge0); + ADD_BRIDGE(bridge1); + ADD_BRIDGE(bridge2); + ADD_BRIDGE(bridge3); + ADD_BRIDGE(bridge4); + ADD_BRIDGE(bridge5); + ADD_BRIDGE(bridge6); +#undef ADD_BRIDGES + + sweep_bridge_list(); +} + +/** + * Make sure our test helper works too. + */ +static void +test_bridges_helper_func_add_bridges_to_bridgelist(void *arg) +{ + helper_add_bridges_to_bridgelist(arg); + tt_finished(); + + done: + mark_bridge_list(); + sweep_bridge_list(); +} + +/** + * Calling bridge_list_get() should create a new bridgelist if we + * didn't have one before. + */ +static void +test_bridges_bridge_list_get_creates_new_bridgelist(void *arg) +{ + const smartlist_t *bridgelist = bridge_list_get(); + + (void)arg; + + tt_ptr_op(bridgelist, OP_NE, NULL); + + done: + return; +} + +/** + * Calling clear_bridge_list() should remove all bridges from the bridgelist. + */ +static void +test_bridges_clear_bridge_list(void *arg) +{ + const smartlist_t *bridgelist; + const smartlist_t *bridgelist_after; + const bridge_info_t *bridge; + + helper_add_bridges_to_bridgelist(arg); + bridgelist = bridge_list_get(); + tt_ptr_op(bridgelist, OP_NE, NULL); + + bridge = smartlist_get(bridgelist, 0); + tt_ptr_op(bridge, OP_NE, NULL); + + clear_bridge_list(); + bridgelist_after = bridge_list_get(); + tt_ptr_op(bridgelist_after, OP_NE, NULL); + tt_int_op(smartlist_len(bridgelist_after), OP_EQ, 0); + + done: + return; +} + +/** + * Calling bridge_get_addrport() should give me the address and port + * of the bridge. In this case, we sort the smartlist of bridges on + * fingerprints and choose the first one. + */ +static void +test_bridges_bridge_get_addrport(void *arg) +{ + smartlist_t *bridgelist; + const bridge_info_t *bridge; + const tor_addr_port_t *addrport; + + helper_add_bridges_to_bridgelist(arg); + bridgelist = (smartlist_t*)bridge_list_get(); + tt_ptr_op(bridgelist, OP_NE, NULL); + + // This should be the bridge at 6.6.6.6:6666 with fingerprint + // 0000000000000000000000000000000000000000 + bridge = smartlist_get(bridgelist, 0); + tt_ptr_op(bridge, OP_NE, NULL); + + addrport = bridge_get_addr_port(bridge); + tt_int_op(addrport->port, OP_EQ, 6666); + + done: + mark_bridge_list(); + sweep_bridge_list(); +} + +/** + * Calling get_configured_bridge_by_orports_digest() with two + * configured bridge orports and an invalid digest should return the + * bridge of the first addrport in the list. + */ +static void +test_bridges_get_configured_bridge_by_orports_digest(void *arg) +{ + smartlist_t *orports = NULL; + const smartlist_t *bridgelist; + const bridge_info_t *bridge1; + const bridge_info_t *bridge2; + const bridge_info_t *ret; + tor_addr_port_t *addrport1; + tor_addr_port_t *addrport2; + const char *digest; + + helper_add_bridges_to_bridgelist(arg); + bridgelist = bridge_list_get(); + tt_ptr_op(bridgelist, OP_NE, NULL); + + // This should be the bridge at 6.6.6.6:6666 with fingerprint + // 0000000000000000000000000000000000000000 + bridge1 = smartlist_get(bridgelist, 0); + tt_ptr_op(bridge1, OP_NE, NULL); + // This should be the bridge at 6.6.6.7:6667 with fingerprint + // A10C4F666D27364036B562823E5830BC448E046A + bridge2 = smartlist_get(bridgelist, 1); + tt_ptr_op(bridge2, OP_NE, NULL); + + addrport1 = (tor_addr_port_t*)bridge_get_addr_port(bridge1); + tt_int_op(addrport1->port, OP_EQ, 6666); + addrport2 = (tor_addr_port_t*)bridge_get_addr_port(bridge2); + tt_int_op(addrport2->port, OP_EQ, 6667); + + orports = smartlist_new(); + smartlist_add(orports, addrport1); + smartlist_add(orports, addrport2); + + digest = "zzzzzzzzzzzzzzzz"; + + ret = get_configured_bridge_by_orports_digest(digest, orports); + tt_ptr_op(ret, OP_NE, NULL); + + tt_assert(tor_addr_port_eq(addrport1, bridge_get_addr_port(ret))); + + done: + smartlist_free(orports); + + mark_bridge_list(); + sweep_bridge_list(); +} + +/** + * Calling get_configured_bridge_by_addr_port_digest() with a digest that we do + * have and an addr:port pair we don't should return the bridge for that + * digest. + */ +static void +test_bridges_get_configured_bridge_by_addr_port_digest_digest_only(void *arg) +{ + char digest[DIGEST_LEN]; + bridge_info_t *bridge; + const char fingerprint[HEX_DIGEST_LEN] = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t)); + char ret_addr[16]; + uint16_t port = 11111; + int ret; + + helper_add_bridges_to_bridgelist(arg); + + // We don't actually have a bridge with this addr:port pair + base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN); + ret = tor_addr_parse(addr, "111.111.111.111"); + tt_int_op(ret, OP_EQ, 2); // it returns the address family on success + + bridge = get_configured_bridge_by_addr_port_digest(addr, port, digest); + tt_ptr_op(bridge, OP_NE, NULL); + + tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0); + tt_str_op("4.4.4.4", OP_EQ, ret_addr); + + done: + tor_free(addr); + + mark_bridge_list(); + sweep_bridge_list(); +} + +/** + * Calling get_configured_bridge_by_addr_port_digest() with only an + * addr:port (i.e. digest set to NULL) should return the bridge for + * that digest when there is such a bridge. + */ +static void +test_bridges_get_configured_bridge_by_addr_port_digest_address_only(void *arg) +{ + bridge_info_t *bridge; + tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t)); + char ret_addr[16]; + uint16_t port = 6666; + int ret; + + helper_add_bridges_to_bridgelist(arg); + + ret = tor_addr_parse(addr, "6.6.6.6"); + tt_int_op(ret, OP_EQ, 2); // it returns the address family on success + + bridge = get_configured_bridge_by_addr_port_digest(addr, port, NULL); + tt_ptr_op(bridge, OP_NE, NULL); + + tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0); + tt_str_op("6.6.6.6", OP_EQ, ret_addr); + + done: + tor_free(addr); + + mark_bridge_list(); + sweep_bridge_list(); +} + +/** + * Calling get_configured_bridge_by_exact_addr_port_digest() with a digest that + * we do have, and an addr:port pair we don't have, should return NULL. + */ +static void +test_bridges_get_configured_bridge_by_exact_addr_port_digest_donly(void *arg) +{ + char digest[DIGEST_LEN]; + bridge_info_t *bridge; + const char fingerprint[HEX_DIGEST_LEN] = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t)); + uint16_t port = 11111; + int ret; + + helper_add_bridges_to_bridgelist(arg); + + // We don't actually have a bridge with this addr:port pair + base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN); + ret = tor_addr_parse(addr, "111.111.111.111"); + tt_int_op(ret, OP_EQ, 2); // it returns the address family on success + + bridge = get_configured_bridge_by_exact_addr_port_digest(addr, port, digest); + tt_ptr_op(bridge, OP_EQ, NULL); + + done: + tor_free(addr); + + mark_bridge_list(); + sweep_bridge_list(); +} + +/** + * Calling get_configured_bridge_by_exact_addr_port_digest() with a digest that + * we do have, and an addr:port pair we do have, should return the bridge. + */ +static void +test_bridges_get_configured_bridge_by_exact_addr_port_digest_both(void *arg) +{ + char digest[DIGEST_LEN]; + bridge_info_t *bridge; + const char fingerprint[HEX_DIGEST_LEN] = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t)); + uint16_t port = 4444; + char ret_addr[16]; + int ret; + + helper_add_bridges_to_bridgelist(arg); + + base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN); + ret = tor_addr_parse(addr, "4.4.4.4"); + tt_int_op(ret, OP_EQ, 2); // it returns the address family on success + + bridge = get_configured_bridge_by_exact_addr_port_digest(addr, port, digest); + tt_ptr_op(bridge, OP_NE, NULL); + + tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0); + tt_str_op("4.4.4.4", OP_EQ, ret_addr); + + done: + tor_free(addr); + + mark_bridge_list(); + sweep_bridge_list(); +} + +/** + * Calling get_configured_bridge_by_exact_addr_port_digest() with no digest, + * and an addr:port pair we do have, should return the bridge. + */ +static void +test_bridges_get_configured_bridge_by_exact_addr_port_digest_aonly(void *arg) +{ + bridge_info_t *bridge; + tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t)); + uint16_t port = 4444; + char ret_addr[16]; + int ret; + + helper_add_bridges_to_bridgelist(arg); + + ret = tor_addr_parse(addr, "4.4.4.4"); + tt_int_op(ret, OP_EQ, 2); // it returns the address family on success + + bridge = get_configured_bridge_by_exact_addr_port_digest(addr, port, NULL); + tt_ptr_op(bridge, OP_NE, NULL); + + tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0); + tt_str_op("4.4.4.4", OP_EQ, ret_addr); + + done: + tor_free(addr); + + mark_bridge_list(); + sweep_bridge_list(); +} + +/** + * Calling find_bridge_by_digest() when we have a bridge with a known + * identity digest should return the bridge's information. + */ +static void +test_bridges_find_bridge_by_digest_known(void *arg) +{ + char digest1[DIGEST_LEN]; + bridge_info_t *bridge; + const char fingerprint[HEX_DIGEST_LEN] = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + + helper_add_bridges_to_bridgelist(arg); + + base16_decode(digest1, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN); + bridge = find_bridge_by_digest(digest1); + + tt_ptr_op(bridge, OP_NE, NULL); + + /* We have to call bridge_get_rsa_id_digest() here because the bridge_info_t + * struct is opaquely defined in bridges.h. */ + const uint8_t *digest2 = bridge_get_rsa_id_digest(bridge); + + tt_mem_op((char*)digest2, OP_EQ, digest1, DIGEST_LEN); + + done: + mark_bridge_list(); + sweep_bridge_list(); +} + +/** + * Calling find_bridge_by_digest() when we do NOT have a bridge with that + * identity digest should return NULL. + */ +static void +test_bridges_find_bridge_by_digest_unknown(void *arg) +{ + const char *fingerprint = "cccccccccccccccccccccccccccccccccccccccc"; + bridge_info_t *bridge; + + helper_add_bridges_to_bridgelist(arg); + + bridge = find_bridge_by_digest(fingerprint); + + tt_ptr_op(bridge, OP_EQ, NULL); + + done: + mark_bridge_list(); + sweep_bridge_list(); +} + +/** + * Calling bridge_resolve_conflicts() with an identical bridge to one we've + * already configure should mark the pre-configured bridge for removal. + */ +static void +test_bridges_bridge_resolve_conflicts(void *arg) +{ + tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t)); + uint16_t port = 4444; + const char *digest = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + const char *transport = "apple"; + int ret; + + helper_add_bridges_to_bridgelist(arg); + + ret = tor_addr_parse(addr, "4.4.4.4"); + tt_int_op(ret, OP_EQ, 2); // it returns the address family on success + + bridge_resolve_conflicts((const tor_addr_t*)addr, port, digest, transport); + + /* The bridge should now be marked for removal, and removed when we sweep the + * bridge_list */ + sweep_bridge_list(); + ret = addr_is_a_configured_bridge((const tor_addr_t*)addr, port, digest); + tt_int_op(ret, OP_EQ, 0); + + done: + tor_free(addr); + + mark_bridge_list(); + sweep_bridge_list(); +} + +/** + * Calling transport_is_needed() with a transport we do need ("obfs4") and a + * bogus transport that we don't need should return 1 and 0, respectively. + */ +static void +test_bridges_transport_is_needed(void *arg) +{ + int ret; + + helper_add_bridges_to_bridgelist(arg); + + ret = transport_is_needed("obfs4"); + tt_int_op(ret, OP_EQ, 1); + + ret = transport_is_needed("apowefjaoewpaief"); + tt_int_op(ret, OP_EQ, 0); + + done: + mark_bridge_list(); + sweep_bridge_list(); +} + +/** + * Calling get_transport_by_bridge_addrport() with the address and port of a + * configured bridge which uses a pluggable transport when there is no global + * transport_list should return -1 and the transport_t should be NULL. + */ +static void +test_bridges_get_transport_by_bridge_addrport_no_ptlist(void *arg) +{ + transport_t *transport = NULL; + tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t)); + uint16_t port = 1234; + int ret; + + helper_add_bridges_to_bridgelist(arg); + + ret = tor_addr_parse(addr, "1.2.3.4"); + tt_int_op(ret, OP_EQ, 2); // it returns the address family on success? + + /* This will fail because the global transport_list has nothing in it, and so + * transport_get_by_name() has nothing to return, even the the bridge *did* + * say it had an obfs4 transport. + */ + ret = get_transport_by_bridge_addrport((const tor_addr_t*)addr, port, + (const transport_t**)&transport); + tt_int_op(ret, OP_EQ, -1); // returns -1 on failure + tt_ptr_op(transport, OP_EQ, NULL); + + done: + tor_free(addr); + + mark_bridge_list(); + sweep_bridge_list(); +} + +#define PT_PRIVATE + +/** + * Calling get_transport_by_bridge_addrport() with the address and port of a + * configured bridge which uses a pluggable transport should return 0 and set + * appropriate transport_t. + */ +static void +test_bridges_get_transport_by_bridge_addrport(void *arg) +{ + transport_t *transport = NULL; + tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t)); + uint16_t port = 1234; + int ret; + + helper_add_bridges_to_bridgelist(arg); + mark_transport_list(); // Also initialise our transport_list + + ret = tor_addr_parse(addr, "1.2.3.4"); + tt_int_op(ret, OP_EQ, 2); // it returns the address family on success? + + /* After we mock transport_get_by_name() to return a bogus transport_t with + * the name it was asked for, the call should succeed. + */ + MOCK(transport_get_by_name, mock_transport_get_by_name); + ret = get_transport_by_bridge_addrport((const tor_addr_t*)addr, port, + (const transport_t**)&transport); + tt_int_op(ret, OP_EQ, 0); // returns 0 on success + tt_ptr_op(transport, OP_NE, NULL); + tt_str_op(transport->name, OP_EQ, "obfs4"); + + done: + UNMOCK(transport_get_by_name); + + tor_free(addr); + transport_free(transport); + + mark_bridge_list(); + sweep_bridge_list(); +} + +static void +test_bridges_node_is_a_configured_bridge(void *arg) +{ + routerinfo_t ri_ipv4 = { .addr = 0x06060606, .or_port = 6666 }; + routerstatus_t rs_ipv4 = { .addr = 0x06060606, .or_port = 6666 }; + + routerinfo_t ri_ipv6 = { .ipv6_orport = 6666 }; + tor_addr_parse(&(ri_ipv6.ipv6_addr), + "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); + + routerstatus_t rs_ipv6 = { .ipv6_orport = 6666 }; + tor_addr_parse(&(rs_ipv6.ipv6_addr), + "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); + + microdesc_t md_ipv6 = { .ipv6_orport = 6666 }; + tor_addr_parse(&(md_ipv6.ipv6_addr), + "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); + + helper_add_bridges_to_bridgelist(arg); + + node_t node_with_digest; + memset(&node_with_digest, 0, sizeof(node_with_digest)); + + const char fingerprint[HEX_DIGEST_LEN] = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + + const char fingerprint2[HEX_DIGEST_LEN] = + "ffffffffffffffffffffffffffffffffffffffff"; + + base16_decode(node_with_digest.identity, DIGEST_LEN, + fingerprint, HEX_DIGEST_LEN); + + node_t node_ri_ipv4 = { .ri = &ri_ipv4 }; + base16_decode(node_ri_ipv4.identity, DIGEST_LEN, + fingerprint2, HEX_DIGEST_LEN); + tt_assert(node_is_a_configured_bridge(&node_ri_ipv4)); + + /* This will still match bridge0, since bridge0 has no digest set. */ + memset(node_ri_ipv4.identity, 0x3f, DIGEST_LEN); + tt_assert(node_is_a_configured_bridge(&node_ri_ipv4)); + + /* It won't match bridge1, though, since bridge1 has a digest, and this + isn't it! */ + node_ri_ipv4.ri->addr = 0x06060607; + node_ri_ipv4.ri->or_port = 6667; + tt_assert(! node_is_a_configured_bridge(&node_ri_ipv4)); + /* If we set the fingerprint right, though, it will match. */ + base16_decode(node_ri_ipv4.identity, DIGEST_LEN, + "A10C4F666D27364036B562823E5830BC448E046A", HEX_DIGEST_LEN); + tt_assert(node_is_a_configured_bridge(&node_ri_ipv4)); + + node_t node_rs_ipv4 = { .rs = &rs_ipv4 }; + base16_decode(node_rs_ipv4.identity, DIGEST_LEN, + fingerprint2, HEX_DIGEST_LEN); + tt_assert(node_is_a_configured_bridge(&node_rs_ipv4)); + + node_t node_ri_ipv6 = { .ri = &ri_ipv6 }; + base16_decode(node_ri_ipv6.identity, DIGEST_LEN, + fingerprint2, HEX_DIGEST_LEN); + tt_assert(node_is_a_configured_bridge(&node_ri_ipv6)); + + node_t node_rs_ipv6 = { .rs = &rs_ipv6 }; + base16_decode(node_rs_ipv6.identity, DIGEST_LEN, + fingerprint2, HEX_DIGEST_LEN); + tt_assert(node_is_a_configured_bridge(&node_rs_ipv6)); + + node_t node_md_ipv6 = { .md = &md_ipv6 }; + base16_decode(node_md_ipv6.identity, DIGEST_LEN, + fingerprint2, HEX_DIGEST_LEN); + tt_assert(node_is_a_configured_bridge(&node_md_ipv6)); + + mark_bridge_list(); + sweep_bridge_list(); + + tt_assert(!node_is_a_configured_bridge(&node_with_digest)); + tt_assert(!node_is_a_configured_bridge(&node_ri_ipv4)); + tt_assert(!node_is_a_configured_bridge(&node_ri_ipv6)); + tt_assert(!node_is_a_configured_bridge(&node_rs_ipv4)); + tt_assert(!node_is_a_configured_bridge(&node_rs_ipv6)); + tt_assert(!node_is_a_configured_bridge(&node_md_ipv6)); + + done: + mark_bridge_list(); + sweep_bridge_list(); +} + +#undef PT_PRIVATE /* defined(PT_PRIVATE) */ + +#define B_TEST(name, flags) \ + { #name, test_bridges_ ##name, (flags), NULL, NULL } + +struct testcase_t bridges_tests[] = { + B_TEST(helper_func_add_bridges_to_bridgelist, 0), + B_TEST(bridge_list_get_creates_new_bridgelist, 0), + B_TEST(clear_bridge_list, 0), + B_TEST(bridge_get_addrport, 0), + B_TEST(get_configured_bridge_by_orports_digest, 0), + B_TEST(get_configured_bridge_by_addr_port_digest_digest_only, 0), + B_TEST(get_configured_bridge_by_addr_port_digest_address_only, 0), + B_TEST(get_configured_bridge_by_exact_addr_port_digest_donly, 0), + B_TEST(get_configured_bridge_by_exact_addr_port_digest_both, 0), + B_TEST(get_configured_bridge_by_exact_addr_port_digest_aonly, 0), + B_TEST(find_bridge_by_digest_known, 0), + B_TEST(find_bridge_by_digest_unknown, 0), + B_TEST(bridge_resolve_conflicts, 0), + B_TEST(get_transport_by_bridge_addrport_no_ptlist, 0), + B_TEST(get_transport_by_bridge_addrport, 0), + B_TEST(transport_is_needed, 0), + B_TEST(node_is_a_configured_bridge, 0), + END_OF_TESTCASES +}; diff --git a/src/test/test_bt_cl.c b/src/test/test_bt_cl.c index b5c8d7cf9e..89cbca2066 100644 --- a/src/test/test_bt_cl.c +++ b/src/test/test_bt_cl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Tor Project, Inc. */ +/* Copyright (c) 2012-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" @@ -7,10 +7,13 @@ /* To prevent 'assert' from going away. */ #undef TOR_COVERAGE -#include "or.h" -#include "util.h" -#include "backtrace.h" -#include "torlog.h" +#include "core/or/or.h" +#include "lib/err/backtrace.h" +#include "lib/log/log.h" + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif /* -1: no crash. * 0: crash with a segmentation fault. @@ -118,4 +121,3 @@ main(int argc, char **argv) return 0; } - diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c index 057d9fa2dc..477066f699 100644 --- a/src/test/test_buffers.c +++ b/src/test/test_buffers.c @@ -1,16 +1,19 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define BUFFERS_PRIVATE #define PROTO_HTTP_PRIVATE -#include "or.h" -#include "buffers.h" -#include "buffers_tls.h" -#include "proto_http.h" -#include "proto_socks.h" -#include "test.h" +#include "core/or/or.h" +#include "lib/container/buffers.h" +#include "lib/tls/buffers_tls.h" +#include "lib/tls/tortls.h" +#include "lib/compress/compress.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "core/proto/proto_http.h" +#include "core/proto/proto_socks.h" +#include "test/test.h" /** Run unit tests for buffers.c */ static void @@ -818,4 +821,3 @@ struct testcase_t buffer_tests[] = { END_OF_TESTCASES }; - diff --git a/src/test/test_bwmgt.c b/src/test/test_bwmgt.c new file mode 100644 index 0000000000..7a1782c2c9 --- /dev/null +++ b/src/test/test_bwmgt.c @@ -0,0 +1,233 @@ +/* Copyright (c) 2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file test_bwmgt.c + * \brief tests for bandwidth management / token bucket functions + */ + +#define TOKEN_BUCKET_PRIVATE + +#include "core/or/or.h" +#include "test/test.h" + +#include "lib/evloop/token_bucket.h" + +// an imaginary time, in timestamp units. Chosen so it will roll over. +static const uint32_t START_TS = UINT32_MAX-10; +static const int32_t KB = 1024; +static const uint32_t GB = (UINT64_C(1) << 30); + +static void +test_bwmgt_token_buf_init(void *arg) +{ + (void)arg; + token_bucket_rw_t b; + + token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS); + // Burst is correct + tt_uint_op(b.cfg.burst, OP_EQ, 64*KB); + // Rate is correct, within 1 percent. + { + uint32_t ticks_per_sec = + (uint32_t) monotime_msec_to_approx_coarse_stamp_units(1000); + uint32_t rate_per_sec = (b.cfg.rate * ticks_per_sec / TICKS_PER_STEP); + + tt_uint_op(rate_per_sec, OP_GT, 16*KB-160); + tt_uint_op(rate_per_sec, OP_LT, 16*KB+160); + } + // Bucket starts out full: + tt_uint_op(b.last_refilled_at_timestamp, OP_EQ, START_TS); + tt_int_op(b.read_bucket.bucket, OP_EQ, 64*KB); + + done: + ; +} + +static void +test_bwmgt_token_buf_adjust(void *arg) +{ + (void)arg; + token_bucket_rw_t b; + + token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS); + + uint32_t rate_orig = b.cfg.rate; + // Increasing burst + token_bucket_rw_adjust(&b, 16*KB, 128*KB); + tt_uint_op(b.cfg.rate, OP_EQ, rate_orig); + tt_uint_op(b.read_bucket.bucket, OP_EQ, 64*KB); + tt_uint_op(b.cfg.burst, OP_EQ, 128*KB); + + // Decreasing burst but staying above bucket + token_bucket_rw_adjust(&b, 16*KB, 96*KB); + tt_uint_op(b.cfg.rate, OP_EQ, rate_orig); + tt_uint_op(b.read_bucket.bucket, OP_EQ, 64*KB); + tt_uint_op(b.cfg.burst, OP_EQ, 96*KB); + + // Decreasing burst below bucket, + token_bucket_rw_adjust(&b, 16*KB, 48*KB); + tt_uint_op(b.cfg.rate, OP_EQ, rate_orig); + tt_uint_op(b.read_bucket.bucket, OP_EQ, 48*KB); + tt_uint_op(b.cfg.burst, OP_EQ, 48*KB); + + // Changing rate. + token_bucket_rw_adjust(&b, 32*KB, 48*KB); + tt_uint_op(b.cfg.rate, OP_GE, rate_orig*2 - 10); + tt_uint_op(b.cfg.rate, OP_LE, rate_orig*2 + 10); + tt_uint_op(b.read_bucket.bucket, OP_EQ, 48*KB); + tt_uint_op(b.cfg.burst, OP_EQ, 48*KB); + + done: + ; +} + +static void +test_bwmgt_token_buf_dec(void *arg) +{ + (void)arg; + token_bucket_rw_t b; + token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS); + + // full-to-not-full. + tt_int_op(0, OP_EQ, token_bucket_rw_dec_read(&b, KB)); + tt_int_op(b.read_bucket.bucket, OP_EQ, 63*KB); + + // Full to almost-not-full + tt_int_op(0, OP_EQ, token_bucket_rw_dec_read(&b, 63*KB - 1)); + tt_int_op(b.read_bucket.bucket, OP_EQ, 1); + + // almost-not-full to empty. + tt_int_op(1, OP_EQ, token_bucket_rw_dec_read(&b, 1)); + tt_int_op(b.read_bucket.bucket, OP_EQ, 0); + + // reset bucket, try full-to-empty + token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS); + tt_int_op(1, OP_EQ, token_bucket_rw_dec_read(&b, 64*KB)); + tt_int_op(b.read_bucket.bucket, OP_EQ, 0); + + // reset bucket, try underflow. + token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS); + tt_int_op(1, OP_EQ, token_bucket_rw_dec_read(&b, 64*KB + 1)); + tt_int_op(b.read_bucket.bucket, OP_EQ, -1); + + // A second underflow does not make the bucket empty. + tt_int_op(0, OP_EQ, token_bucket_rw_dec_read(&b, 1000)); + tt_int_op(b.read_bucket.bucket, OP_EQ, -1001); + + done: + ; +} + +static void +test_bwmgt_token_buf_refill(void *arg) +{ + (void)arg; + token_bucket_rw_t b; + const uint32_t BW_SEC = + (uint32_t)monotime_msec_to_approx_coarse_stamp_units(1000); + token_bucket_rw_init(&b, 16*KB, 64*KB, START_TS); + + /* Make the buffer much emptier, then let one second elapse. */ + token_bucket_rw_dec_read(&b, 48*KB); + tt_int_op(b.read_bucket.bucket, OP_EQ, 16*KB); + tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + BW_SEC)); + tt_int_op(b.read_bucket.bucket, OP_GT, 32*KB - 300); + tt_int_op(b.read_bucket.bucket, OP_LT, 32*KB + 300); + + /* Another half second. */ + tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + BW_SEC*3/2)); + tt_int_op(b.read_bucket.bucket, OP_GT, 40*KB - 400); + tt_int_op(b.read_bucket.bucket, OP_LT, 40*KB + 400); + tt_uint_op(b.last_refilled_at_timestamp, OP_EQ, START_TS + BW_SEC*3/2); + + /* No time: nothing happens. */ + { + const uint32_t bucket_orig = b.read_bucket.bucket; + tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + BW_SEC*3/2)); + tt_int_op(b.read_bucket.bucket, OP_EQ, bucket_orig); + } + + /* Another 30 seconds: fill the bucket. */ + tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, + START_TS + BW_SEC*3/2 + BW_SEC*30)); + tt_int_op(b.read_bucket.bucket, OP_EQ, b.cfg.burst); + tt_uint_op(b.last_refilled_at_timestamp, OP_EQ, + START_TS + BW_SEC*3/2 + BW_SEC*30); + + /* Another 30 seconds: nothing happens. */ + tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, + START_TS + BW_SEC*3/2 + BW_SEC*60)); + tt_int_op(b.read_bucket.bucket, OP_EQ, b.cfg.burst); + tt_uint_op(b.last_refilled_at_timestamp, OP_EQ, + START_TS + BW_SEC*3/2 + BW_SEC*60); + + /* Empty the bucket, let two seconds pass, and make sure that a refill is + * noticed. */ + tt_int_op(1, OP_EQ, token_bucket_rw_dec_read(&b, b.cfg.burst)); + tt_int_op(0, OP_EQ, b.read_bucket.bucket); + tt_int_op(1, OP_EQ, token_bucket_rw_refill(&b, + START_TS + BW_SEC*3/2 + BW_SEC*61)); + tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, + START_TS + BW_SEC*3/2 + BW_SEC*62)); + tt_int_op(b.read_bucket.bucket, OP_GT, 32*KB-400); + tt_int_op(b.read_bucket.bucket, OP_LT, 32*KB+400); + + /* Underflow the bucket, make sure we detect when it has tokens again. */ + tt_int_op(1, OP_EQ, + token_bucket_rw_dec_read(&b, b.read_bucket.bucket+16*KB)); + tt_int_op(-16*KB, OP_EQ, b.read_bucket.bucket); + // half a second passes... + tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + BW_SEC*64)); + tt_int_op(b.read_bucket.bucket, OP_GT, -8*KB-300); + tt_int_op(b.read_bucket.bucket, OP_LT, -8*KB+300); + // a second passes + tt_int_op(1, OP_EQ, token_bucket_rw_refill(&b, START_TS + BW_SEC*65)); + tt_int_op(b.read_bucket.bucket, OP_GT, 8*KB-400); + tt_int_op(b.read_bucket.bucket, OP_LT, 8*KB+400); + + // We step a second backwards, and nothing happens. + tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, START_TS + BW_SEC*64)); + tt_int_op(b.read_bucket.bucket, OP_GT, 8*KB-400); + tt_int_op(b.read_bucket.bucket, OP_LT, 8*KB+400); + + // A ridiculous amount of time passes. + tt_int_op(0, OP_EQ, token_bucket_rw_refill(&b, INT32_MAX)); + tt_int_op(b.read_bucket.bucket, OP_EQ, b.cfg.burst); + + done: + ; +} + +/* Test some helper functions we use within the token bucket interface. */ +static void +test_bwmgt_token_buf_helpers(void *arg) +{ + uint32_t ret; + + (void) arg; + + /* The returned value will be OS specific but in any case, it should be + * greater than 1 since we are passing 1GB/sec rate. */ + ret = rate_per_sec_to_rate_per_step(1 * GB); + tt_u64_op(ret, OP_GT, 1); + + /* We default to 1 in case rate is 0. */ + ret = rate_per_sec_to_rate_per_step(0); + tt_u64_op(ret, OP_EQ, 1); + + done: + ; +} + +#define BWMGT(name) \ + { #name, test_bwmgt_ ## name , 0, NULL, NULL } + +struct testcase_t bwmgt_tests[] = { + BWMGT(token_buf_init), + BWMGT(token_buf_adjust), + BWMGT(token_buf_dec), + BWMGT(token_buf_refill), + BWMGT(token_buf_helpers), + END_OF_TESTCASES +}; diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c index 88cdef383f..daf0296e2a 100644 --- a/src/test/test_cell_formats.c +++ b/src/test/test_cell_formats.c @@ -1,23 +1,29 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" #define CONNECTION_EDGE_PRIVATE #define RELAY_PRIVATE -#include "or.h" -#include "channel.h" -#include "connection_edge.h" -#include "connection_or.h" -#include "config.h" -#include "onion.h" -#include "onion_tap.h" -#include "onion_fast.h" -#include "onion_ntor.h" -#include "relay.h" -#include "test.h" +#include "core/or/or.h" +#include "core/or/channel.h" +#include "core/or/connection_edge.h" +#include "core/or/connection_or.h" +#include "app/config/config.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "core/or/onion.h" +#include "core/crypto/onion_tap.h" +#include "core/crypto/onion_fast.h" +#include "core/crypto/onion_ntor.h" +#include "core/or/relay.h" + +#include "core/or/cell_st.h" +#include "core/or/cell_queue_st.h" +#include "core/or/var_cell_st.h" + +#include "test/test.h" #include <stdlib.h> #include <string.h> @@ -1296,4 +1302,3 @@ struct testcase_t cell_format_tests[] = { TEST(is_destroy, 0), END_OF_TESTCASES }; - diff --git a/src/test/test_cell_queue.c b/src/test/test_cell_queue.c index df987f82ce..d74bb9c622 100644 --- a/src/test/test_cell_queue.c +++ b/src/test/test_cell_queue.c @@ -1,12 +1,17 @@ -/* Copyright (c) 2013-2017, The Tor Project, Inc. */ +/* Copyright (c) 2013-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define CIRCUITLIST_PRIVATE #define RELAY_PRIVATE -#include "or.h" -#include "circuitlist.h" -#include "relay.h" -#include "test.h" +#include "core/or/or.h" +#include "core/or/circuitlist.h" +#include "core/or/relay.h" +#include "test/test.h" + +#include "core/or/cell_st.h" +#include "core/or/cell_queue_st.h" +#include "core/or/or_circuit_st.h" +#include "core/or/origin_circuit_st.h" static void test_cq_manip(void *arg) diff --git a/src/test/test_channel.c b/src/test/test_channel.c index bdc9d32f78..26af8de917 100644 --- a/src/test/test_channel.c +++ b/src/test/test_channel.c @@ -1,28 +1,35 @@ -/* Copyright (c) 2013-2017, The Tor Project, Inc. */ +/* Copyright (c) 2013-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define TOR_CHANNEL_INTERNAL_ #define CHANNEL_PRIVATE_ -#include "or.h" -#include "channel.h" +#include "core/or/or.h" +#include "core/or/channel.h" /* For channel_note_destroy_not_pending */ #define CIRCUITLIST_PRIVATE -#include "circuitlist.h" -#include "circuitmux.h" -#include "circuitmux_ewma.h" +#include "core/or/circuitlist.h" +#include "core/or/circuitmux.h" +#include "core/or/circuitmux_ewma.h" /* For var_cell_free */ -#include "connection_or.h" +#include "core/or/connection_or.h" +#include "lib/crypt_ops/crypto_rand.h" /* For packed_cell stuff */ #define RELAY_PRIVATE -#include "relay.h" +#include "core/or/relay.h" /* For init/free stuff */ -#include "scheduler.h" -#include "networkstatus.h" +#include "core/or/scheduler.h" +#include "feature/nodelist/networkstatus.h" + +#include "core/or/cell_st.h" +#include "feature/nodelist/networkstatus_st.h" +#include "core/or/origin_circuit_st.h" +#include "feature/nodelist/routerstatus_st.h" +#include "core/or/var_cell_st.h" /* Test suite stuff */ -#include "log_test_helpers.h" -#include "test.h" -#include "fakechans.h" +#include "test/log_test_helpers.h" +#include "test/test.h" +#include "test/fakechans.h" static int test_chan_accept_cells = 0; static int test_chan_fixed_cells_recved = 0; @@ -281,6 +288,7 @@ new_fake_channel(void) chan->state = CHANNEL_STATE_OPEN; chan->cmux = circuitmux_alloc(); + circuitmux_set_policy(chan->cmux, &ewma_policy); return chan; } @@ -543,6 +551,13 @@ test_channel_outbound_cell(void *arg) (void) arg; + /* Set the test time to be mocked, since this test assumes that no + * time will pass, ewma values will not need to be re-scaled, and so on */ + monotime_enable_test_mocking(); + monotime_set_mock_time_nsec(UINT64_C(1000000000) * 12345); + + cmux_ewma_set_options(NULL,NULL); + /* The channel will be freed so we need to hijack this so the scheduler * doesn't get confused. */ MOCK(scheduler_release_channel, scheduler_release_channel_mock); @@ -575,15 +590,13 @@ test_channel_outbound_cell(void *arg) channel_register(chan); tt_int_op(chan->registered, OP_EQ, 1); /* Set EWMA policy so we can pick it when flushing. */ - channel_set_cmux_policy_everywhere(&ewma_policy); + circuitmux_set_policy(chan->cmux, &ewma_policy); tt_ptr_op(circuitmux_get_policy(chan->cmux), OP_EQ, &ewma_policy); /* Register circuit to the channel circid map which will attach the circuit * to the channel's cmux as well. */ circuit_set_n_circid_chan(TO_CIRCUIT(circ), 42, chan); tt_int_op(channel_num_circuits(chan), OP_EQ, 1); - tt_assert(!TO_CIRCUIT(circ)->next_active_on_n_chan); - tt_assert(!TO_CIRCUIT(circ)->prev_active_on_n_chan); /* Test the cmux state. */ tt_ptr_op(TO_CIRCUIT(circ)->n_mux, OP_EQ, chan->cmux); tt_int_op(circuitmux_is_circuit_attached(chan->cmux, TO_CIRCUIT(circ)), @@ -659,6 +672,7 @@ test_channel_outbound_cell(void *arg) tor_free(p_cell); channel_free_all(); UNMOCK(scheduler_release_channel); + monotime_disable_test_mocking(); } /* Test inbound cell. The callstack is: diff --git a/src/test/test_channelpadding.c b/src/test/test_channelpadding.c index 90da2163a6..0fd60d0a92 100644 --- a/src/test/test_channelpadding.c +++ b/src/test/test_channelpadding.c @@ -1,25 +1,32 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define TOR_CHANNEL_INTERNAL_ -#define MAIN_PRIVATE +#define MAINLOOP_PRIVATE #define NETWORKSTATUS_PRIVATE #define TOR_TIMERS_PRIVATE -#include "or.h" -#include "test.h" -#include "testsupport.h" -#include "connection.h" -#include "connection_or.h" -#include "channel.h" -#include "channeltls.h" -#include "channelpadding.h" -#include "compat_libevent.h" -#include "config.h" -#include <event2/event.h> -#include "compat_time.h" -#include "main.h" -#include "networkstatus.h" -#include "log_test_helpers.h" +#include "core/or/or.h" +#include "test/test.h" +#include "lib/testsupport/testsupport.h" +#include "core/mainloop/connection.h" +#include "core/or/connection_or.h" +#include "core/or/channel.h" +#include "core/or/channeltls.h" +#include "core/or/channelpadding.h" +#include "lib/evloop/compat_libevent.h" +#include "app/config/config.h" +#include "lib/time/compat_time.h" +#include "core/mainloop/mainloop.h" +#include "feature/nodelist/networkstatus.h" +#include "test/log_test_helpers.h" +#include "lib/tls/tortls.h" +#include "lib/evloop/timers.h" +#include "lib/container/buffers.h" + +#include "core/or/cell_st.h" +#include "feature/nodelist/networkstatus_st.h" +#include "core/or/or_connection_st.h" +#include "feature/nodelist/routerstatus_st.h" int channelpadding_get_netflow_inactive_timeout_ms(channel_t *chan); int64_t channelpadding_compute_time_until_pad_for_netflow(channel_t *chan); @@ -65,7 +72,7 @@ mock_channel_write_cell_relay2(channel_t *chan, cell_t *cell) (void)chan; tried_to_write_cell++; channel_tls_handle_cell(cell, ((channel_tls_t*)relay1_relay2)->conn); - event_base_loopbreak(tor_libevent_get_base()); + tor_libevent_exit_loop_after_callback(tor_libevent_get_base()); return 0; } @@ -75,7 +82,7 @@ mock_channel_write_cell_relay1(channel_t *chan, cell_t *cell) (void)chan; tried_to_write_cell++; channel_tls_handle_cell(cell, ((channel_tls_t*)relay2_relay1)->conn); - event_base_loopbreak(tor_libevent_get_base()); + tor_libevent_exit_loop_after_callback(tor_libevent_get_base()); return 0; } @@ -85,7 +92,7 @@ mock_channel_write_cell_relay3(channel_t *chan, cell_t *cell) (void)chan; tried_to_write_cell++; channel_tls_handle_cell(cell, ((channel_tls_t*)client_relay3)->conn); - event_base_loopbreak(tor_libevent_get_base()); + tor_libevent_exit_loop_after_callback(tor_libevent_get_base()); return 0; } @@ -95,7 +102,7 @@ mock_channel_write_cell_client(channel_t *chan, cell_t *cell) (void)chan; tried_to_write_cell++; channel_tls_handle_cell(cell, ((channel_tls_t*)relay3_client)->conn); - event_base_loopbreak(tor_libevent_get_base()); + tor_libevent_exit_loop_after_callback(tor_libevent_get_base()); return 0; } @@ -105,7 +112,7 @@ mock_channel_write_cell(channel_t *chan, cell_t *cell) tried_to_write_cell++; channel_tls_handle_cell(cell, ((channel_tls_t*)chan)->conn); if (!dont_stop_libevent) - event_base_loopbreak(tor_libevent_get_base()); + tor_libevent_exit_loop_after_callback(tor_libevent_get_base()); return 0; } @@ -246,7 +253,7 @@ static void dummy_timer_cb(tor_timer_t *t, void *arg, const monotime_t *now_mono) { (void)t; (void)arg; (void)now_mono; - event_base_loopbreak(tor_libevent_get_base()); + tor_libevent_exit_loop_after_callback(tor_libevent_get_base()); return; } @@ -264,7 +271,8 @@ dummy_nop_timer(void) timer_schedule(dummy_timer, &timeout); - event_base_loop(tor_libevent_get_base(), 0); + tor_libevent_run_event_loop(tor_libevent_get_base(), 0); + timer_free(dummy_timer); } @@ -398,81 +406,12 @@ test_channelpadding_killonehop(void *arg) setup_mock_consensus(); setup_mock_network(); - /* Do we disable padding if tor2webmode or rsos are enabled, and - * the consensus says don't pad? */ - - /* Ensure we can kill tor2web and rsos padding if we want. */ - // First, test that padding works if either is enabled - smartlist_clear(current_md_consensus->net_params); - channelpadding_new_consensus_params(current_md_consensus); + /* Do we disable padding if rsos is enabled, and the consensus says don't + * pad? */ monotime_coarse_t now; monotime_coarse_get(&now); - tried_to_write_cell = 0; - get_options_mutable()->Tor2webMode = 1; - monotime_coarse_add_msec(&client_relay3->next_padding_time, &now, 100); - decision = channelpadding_decide_to_pad_channel(client_relay3); - tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED); - tt_assert(client_relay3->pending_padding_callback); - tt_int_op(tried_to_write_cell, OP_EQ, 0); - - decision = channelpadding_decide_to_pad_channel(client_relay3); - tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_ALREADY_SCHEDULED); - - // Wait for the timer - new_time += 101*NSEC_PER_MSEC; - monotime_coarse_set_mock_time_nsec(new_time); - monotime_set_mock_time_nsec(new_time); - monotime_coarse_get(&now); - timers_run_pending(); - tt_int_op(tried_to_write_cell, OP_EQ, 1); - tt_assert(!client_relay3->pending_padding_callback); - - // Then test disabling each via consensus param - smartlist_add(current_md_consensus->net_params, - (void*)"nf_pad_tor2web=0"); - channelpadding_new_consensus_params(current_md_consensus); - - // Before the client tries to pad, the relay will still pad: - tried_to_write_cell = 0; - monotime_coarse_add_msec(&relay3_client->next_padding_time, &now, 100); - get_options_mutable()->ORPort_set = 1; - get_options_mutable()->Tor2webMode = 0; - decision = channelpadding_decide_to_pad_channel(relay3_client); - tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED); - tt_assert(relay3_client->pending_padding_callback); - - // Wait for the timer - new_time += 101*NSEC_PER_MSEC; - monotime_coarse_set_mock_time_nsec(new_time); - monotime_set_mock_time_nsec(new_time); - monotime_coarse_get(&now); - timers_run_pending(); - tt_int_op(tried_to_write_cell, OP_EQ, 1); - tt_assert(!client_relay3->pending_padding_callback); - - // Test client side (it should stop immediately, but send a negotiate) - tried_to_write_cell = 0; - tt_assert(relay3_client->padding_enabled); - tt_assert(client_relay3->padding_enabled); - get_options_mutable()->Tor2webMode = 1; - /* For the relay to receive the negotiate: */ - get_options_mutable()->ORPort_set = 1; - decision = channelpadding_decide_to_pad_channel(client_relay3); - tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD); - tt_int_op(tried_to_write_cell, OP_EQ, 1); - tt_assert(!client_relay3->pending_padding_callback); - tt_assert(!relay3_client->padding_enabled); - - // Test relay side (it should have gotten the negotiation to disable) - get_options_mutable()->ORPort_set = 1; - get_options_mutable()->Tor2webMode = 0; - tt_int_op(channelpadding_decide_to_pad_channel(relay3_client), OP_EQ, - CHANNELPADDING_WONTPAD); - tt_assert(!relay3_client->padding_enabled); - - /* Repeat for SOS */ // First, test that padding works if either is enabled smartlist_clear(current_md_consensus->net_params); channelpadding_new_consensus_params(current_md_consensus); @@ -1163,4 +1102,3 @@ struct testcase_t channelpadding_tests[] = { TEST_CHANNELPADDING(channelpadding_timers, TT_FORK), END_OF_TESTCASES }; - diff --git a/src/test/test_channeltls.c b/src/test/test_channeltls.c index 94f1893cae..787a30a85d 100644 --- a/src/test/test_channeltls.c +++ b/src/test/test_channeltls.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" @@ -6,20 +6,23 @@ #include <math.h> #define TOR_CHANNEL_INTERNAL_ -#include "or.h" -#include "address.h" -#include "buffers.h" -#include "channel.h" -#include "channeltls.h" -#include "connection_or.h" -#include "config.h" +#include "core/or/or.h" +#include "lib/net/address.h" +#include "lib/container/buffers.h" +#include "core/or/channel.h" +#include "core/or/channeltls.h" +#include "core/mainloop/connection.h" +#include "core/or/connection_or.h" +#include "app/config/config.h" /* For init/free stuff */ -#include "scheduler.h" -#include "tortls.h" +#include "core/or/scheduler.h" +#include "lib/tls/tortls.h" + +#include "core/or/or_connection_st.h" /* Test suite stuff */ -#include "test.h" -#include "fakechans.h" +#include "test/test.h" +#include "test/fakechans.h" /* The channeltls unit tests */ static void test_channeltls_create(void *arg); @@ -334,4 +337,3 @@ struct testcase_t channeltls_tests[] = { TT_FORK, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_checkdir.c b/src/test/test_checkdir.c index bf6a8376b3..652e308ed8 100644 --- a/src/test/test_checkdir.c +++ b/src/test/test_checkdir.c @@ -1,8 +1,8 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" -#include "or.h" +#include "core/or/or.h" #ifdef _WIN32 #include <direct.h> @@ -10,9 +10,12 @@ #include <dirent.h> #endif -#include "config.h" -#include "test.h" -#include "util.h" +#include "app/config/config.h" +#include "test/test.h" + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif #ifdef _WIN32 #define mkdir(a,b) mkdir(a) @@ -146,4 +149,3 @@ struct testcase_t checkdir_tests[] = { CHECKDIR(perms, TT_FORK), END_OF_TESTCASES }; - diff --git a/src/test/test_circuitbuild.c b/src/test/test_circuitbuild.c index a5282df69d..02eadecd98 100644 --- a/src/test/test_circuitbuild.c +++ b/src/test/test_circuitbuild.c @@ -1,16 +1,19 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2016, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define CIRCUITBUILD_PRIVATE -#include "or.h" -#include "test.h" -#include "test_helpers.h" -#include "log_test_helpers.h" -#include "config.h" -#include "circuitbuild.h" +#include "core/or/or.h" +#include "test/test.h" +#include "test/test_helpers.h" +#include "test/log_test_helpers.h" +#include "app/config/config.h" +#include "core/or/circuitbuild.h" +#include "core/or/circuitlist.h" + +#include "core/or/extend_info_st.h" /* Dummy nodes smartlist for testing */ static smartlist_t dummy_nodes; @@ -130,4 +133,3 @@ struct testcase_t circuitbuild_tests[] = { { "unhandled_exit", test_new_route_len_unhandled_exit, 0, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_circuitlist.c b/src/test/test_circuitlist.c index d170009a9c..8dd7f5f5a9 100644 --- a/src/test/test_circuitlist.c +++ b/src/test/test_circuitlist.c @@ -1,17 +1,23 @@ -/* Copyright (c) 2013-2017, The Tor Project, Inc. */ +/* Copyright (c) 2013-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define TOR_CHANNEL_INTERNAL_ #define CIRCUITBUILD_PRIVATE #define CIRCUITLIST_PRIVATE #define HS_CIRCUITMAP_PRIVATE -#include "or.h" -#include "channel.h" -#include "circuitbuild.h" -#include "circuitlist.h" -#include "hs_circuitmap.h" -#include "test.h" -#include "log_test_helpers.h" +#include "core/or/or.h" +#include "core/or/channel.h" +#include "core/or/circuitbuild.h" +#include "core/or/circuitlist.h" +#include "core/or/circuitmux_ewma.h" +#include "feature/hs/hs_circuitmap.h" +#include "test/test.h" +#include "test/log_test_helpers.h" + +#include "core/or/or_circuit_st.h" +#include "core/or/origin_circuit_st.h" + +#include "lib/container/bitarray.h" static channel_t * new_fake_channel(void) @@ -466,4 +472,3 @@ struct testcase_t circuitlist_tests[] = { TT_FORK, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_circuitmux.c b/src/test/test_circuitmux.c index 854f725054..1be2ff5281 100644 --- a/src/test/test_circuitmux.c +++ b/src/test/test_circuitmux.c @@ -1,15 +1,21 @@ -/* Copyright (c) 2013-2017, The Tor Project, Inc. */ +/* Copyright (c) 2013-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define TOR_CHANNEL_INTERNAL_ #define CIRCUITMUX_PRIVATE +#define CIRCUITMUX_EWMA_PRIVATE #define RELAY_PRIVATE -#include "or.h" -#include "channel.h" -#include "circuitmux.h" -#include "relay.h" -#include "scheduler.h" -#include "test.h" +#include "core/or/or.h" +#include "core/or/channel.h" +#include "core/or/circuitmux.h" +#include "core/or/circuitmux_ewma.h" +#include "core/or/relay.h" +#include "core/or/scheduler.h" +#include "test/test.h" + +#include "core/or/destroy_cell_queue_st.h" + +#include <math.h> /* XXXX duplicated function from test_circuitlist.c */ static channel_t * @@ -45,6 +51,7 @@ test_cmux_destroy_cell_queue(void *arg) cmux = circuitmux_alloc(); tt_assert(cmux); ch = new_fake_channel(); + circuitmux_set_policy(cmux, &ewma_policy); ch->has_queued_writes = has_queued_writes; ch->wide_circ_ids = 1; @@ -77,8 +84,50 @@ test_cmux_destroy_cell_queue(void *arg) tor_free(dc); } +static void +test_cmux_compute_ticks(void *arg) +{ + const int64_t NS_PER_S = 1000 * 1000 * 1000; + const int64_t START_NS = UINT64_C(1217709000)*NS_PER_S; + int64_t now; + double rem; + unsigned tick; + (void)arg; + circuitmux_ewma_free_all(); + monotime_enable_test_mocking(); + + monotime_coarse_set_mock_time_nsec(START_NS); + cell_ewma_initialize_ticks(); + const unsigned tick_zero = cell_ewma_get_current_tick_and_fraction(&rem); + tt_double_op(rem, OP_GT, -1e-9); + tt_double_op(rem, OP_LT, 1e-9); + + /* 1.5 second later and we should still be in the same tick. */ + now = START_NS + NS_PER_S + NS_PER_S/2; + monotime_coarse_set_mock_time_nsec(now); + tick = cell_ewma_get_current_tick_and_fraction(&rem); + tt_uint_op(tick, OP_EQ, tick_zero); +#ifdef USING_32BIT_MSEC_HACK + const double tolerance = .0005; +#else + const double tolerance = .00000001; +#endif + tt_double_op(fabs(rem - .15), OP_LT, tolerance); + + /* 25 second later and we should be in another tick. */ + now = START_NS + NS_PER_S * 25; + monotime_coarse_set_mock_time_nsec(now); + tick = cell_ewma_get_current_tick_and_fraction(&rem); + tt_uint_op(tick, OP_EQ, tick_zero + 2); + tt_double_op(fabs(rem - .5), OP_LT, tolerance); + + done: + ; +} + struct testcase_t circuitmux_tests[] = { { "destroy_cell_queue", test_cmux_destroy_cell_queue, TT_FORK, NULL, NULL }, + { "compute_ticks", test_cmux_compute_ticks, TT_FORK, NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_circuitstats.c b/src/test/test_circuitstats.c index 8ebef659ca..c3cfad88da 100644 --- a/src/test/test_circuitstats.c +++ b/src/test/test_circuitstats.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define CIRCUITBUILD_PRIVATE @@ -6,16 +6,21 @@ #define CIRCUITLIST_PRIVATE #define CHANNEL_PRIVATE_ -#include "or.h" -#include "test.h" -#include "test_helpers.h" -#include "log_test_helpers.h" -#include "config.h" -#include "circuitlist.h" -#include "circuitbuild.h" -#include "circuitstats.h" -#include "circuituse.h" -#include "channel.h" +#include "core/or/or.h" +#include "test/test.h" +#include "test/test_helpers.h" +#include "test/log_test_helpers.h" +#include "app/config/config.h" +#include "core/or/circuitlist.h" +#include "core/or/circuitbuild.h" +#include "core/or/circuitstats.h" +#include "core/or/circuituse.h" +#include "core/or/channel.h" + +#include "core/or/cpath_build_state_st.h" +#include "core/or/crypt_path_st.h" +#include "core/or/extend_info_st.h" +#include "core/or/origin_circuit_st.h" void test_circuitstats_timeout(void *arg); void test_circuitstats_hoplen(void *arg); diff --git a/src/test/test_circuituse.c b/src/test/test_circuituse.c index df1b43807f..720adeac84 100644 --- a/src/test/test_circuituse.c +++ b/src/test/test_circuituse.c @@ -1,18 +1,21 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define CIRCUITLIST_PRIVATE -#include "or.h" -#include "test.h" -#include "test_helpers.h" -#include "config.h" -#include "circuitlist.h" -#include "circuituse.h" -#include "circuitbuild.h" -#include "nodelist.h" +#include "core/or/or.h" +#include "test/test.h" +#include "test/test_helpers.h" +#include "app/config/config.h" +#include "core/or/circuitlist.h" +#include "core/or/circuituse.h" +#include "core/or/circuitbuild.h" +#include "feature/nodelist/nodelist.h" + +#include "core/or/cpath_build_state_st.h" +#include "core/or/origin_circuit_st.h" static void test_circuit_is_available_for_use_ret_false_when_marked_for_close(void *arg) diff --git a/src/test/test_compat_libevent.c b/src/test/test_compat_libevent.c index 7dd8e65194..3f505d013b 100644 --- a/src/test/test_compat_libevent.c +++ b/src/test/test_compat_libevent.c @@ -1,18 +1,17 @@ -/* Copyright (c) 2010-2017, The Tor Project, Inc. */ +/* Copyright (c) 2010-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define COMPAT_LIBEVENT_PRIVATE #include "orconfig.h" -#include "or.h" +#include "core/or/or.h" -#include "test.h" +#include "test/test.h" -#include "compat_libevent.h" +#include "lib/evloop/compat_libevent.h" #include <event2/event.h> -#include <event2/thread.h> -#include "log_test_helpers.h" +#include "test/log_test_helpers.h" #define NS_MODULE compat_libevent @@ -122,10 +121,70 @@ test_compat_libevent_header_version(void *ignored) (void)0; } +/* Test for postloop events */ + +/* Event callback to increment a counter. */ +static void +increment_int_counter_cb(periodic_timer_t *timer, void *arg) +{ + (void)timer; + int *ctr = arg; + ++*ctr; +} + +static int activated_counter = 0; + +/* Mainloop event callback to activate another mainloop event */ +static void +activate_event_cb(mainloop_event_t *ev, void *arg) +{ + (void)ev; + mainloop_event_t **other_event = arg; + mainloop_event_activate(*other_event); + ++activated_counter; +} + +static void +test_compat_libevent_postloop_events(void *arg) +{ + (void)arg; + mainloop_event_t *a = NULL, *b = NULL; + periodic_timer_t *timed = NULL; + + tor_libevent_postfork(); + + /* If postloop events don't work, then these events will activate one + * another ad infinitum and, and the periodic event will never occur. */ + b = mainloop_event_postloop_new(activate_event_cb, &a); + a = mainloop_event_postloop_new(activate_event_cb, &b); + + int counter = 0; + struct timeval fifty_ms = { 0, 10 * 1000 }; + timed = periodic_timer_new(tor_libevent_get_base(), &fifty_ms, + increment_int_counter_cb, &counter); + + mainloop_event_activate(a); + int r; + do { + r = tor_libevent_run_event_loop(tor_libevent_get_base(), 0); + if (r == -1) + break; + } while (counter < 5); + + tt_int_op(activated_counter, OP_GE, 2); + + done: + mainloop_event_free(a); + mainloop_event_free(b); + periodic_timer_free(timed); +} + struct testcase_t compat_libevent_tests[] = { { "logging_callback", test_compat_libevent_logging_callback, TT_FORK, NULL, NULL }, { "header_version", test_compat_libevent_header_version, 0, NULL, NULL }, + { "postloop_events", test_compat_libevent_postloop_events, + TT_FORK, NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_config.c b/src/test/test_config.c index 2bcc0cad7b..dae4d83766 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" @@ -8,45 +8,59 @@ #define CONFIG_PRIVATE #define PT_PRIVATE #define ROUTERSET_PRIVATE -#include "or.h" -#include "address.h" -#include "addressmap.h" -#include "bridges.h" -#include "circuitmux_ewma.h" -#include "circuitbuild.h" -#include "config.h" -#include "confparse.h" -#include "connection.h" -#include "connection_edge.h" -#include "test.h" -#include "util.h" -#include "address.h" -#include "connection_or.h" -#include "control.h" -#include "cpuworker.h" -#include "dirserv.h" -#include "dirvote.h" -#include "dns.h" -#include "entrynodes.h" -#include "transports.h" -#include "ext_orport.h" -#include "geoip.h" -#include "hibernate.h" -#include "main.h" -#include "networkstatus.h" -#include "nodelist.h" -#include "policies.h" -#include "rendclient.h" -#include "rendservice.h" -#include "router.h" -#include "routerlist.h" -#include "routerset.h" -#include "statefile.h" -#include "test.h" -#include "transports.h" -#include "util.h" - -#include "test_helpers.h" +#include "core/or/or.h" +#include "lib/net/address.h" +#include "lib/net/resolve.h" +#include "feature/client/addressmap.h" +#include "feature/client/bridges.h" +#include "core/or/circuitmux_ewma.h" +#include "core/or/circuitbuild.h" +#include "app/config/config.h" +#include "app/config/confparse.h" +#include "core/mainloop/connection.h" +#include "core/or/connection_edge.h" +#include "test/test.h" +#include "core/or/connection_or.h" +#include "feature/control/control.h" +#include "core/mainloop/cpuworker.h" +#include "feature/dircache/dirserv.h" +#include "feature/dirauth/dirvote.h" +#include "feature/relay/dns.h" +#include "feature/client/entrynodes.h" +#include "feature/client/transports.h" +#include "feature/relay/ext_orport.h" +#include "lib/geoip/geoip.h" +#include "feature/hibernate/hibernate.h" +#include "core/mainloop/mainloop.h" +#include "feature/nodelist/networkstatus.h" +#include "feature/nodelist/nodelist.h" +#include "core/or/policies.h" +#include "feature/rend/rendclient.h" +#include "feature/rend/rendservice.h" +#include "feature/relay/router.h" +#include "feature/relay/routermode.h" +#include "feature/nodelist/dirlist.h" +#include "feature/nodelist/routerlist.h" +#include "feature/nodelist/routerset.h" +#include "app/config/statefile.h" + +#include "test/test_helpers.h" + +#include "feature/dirclient/dir_server_st.h" +#include "core/or/port_cfg_st.h" +#include "feature/nodelist/routerinfo_st.h" + +#include "lib/fs/conffile.h" +#include "lib/meminfo/meminfo.h" +#include "lib/net/gethostname.h" +#include "lib/encoding/confline.h" + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif static void test_config_addressmap(void *arg) @@ -1623,6 +1637,40 @@ test_config_parsing_trusted_dir_server(void *arg) #undef TEST_DIR_AUTH_LINE_END #undef TEST_DIR_AUTH_IPV6_FLAG +#define TEST_DIR_AUTH_LINE_START \ + "foobar orport=12345 " \ + "v3ident=14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4 " +#define TEST_DIR_AUTH_LINE_END_BAD_IP \ + "0.256.3.4:54321 " \ + "FDB2 FBD2 AAA5 25FA 2999 E617 5091 5A32 C777 3B17" +#define TEST_DIR_AUTH_LINE_END_WITH_DNS_ADDR \ + "torproject.org:54321 " \ + "FDB2 FBD2 AAA5 25FA 2999 E617 5091 5A32 C777 3B17" + +static void +test_config_parsing_invalid_dir_address(void *arg) +{ + (void)arg; + int rv; + + rv = parse_dir_authority_line(TEST_DIR_AUTH_LINE_START + TEST_DIR_AUTH_LINE_END_BAD_IP, + V3_DIRINFO, 1); + tt_int_op(rv, OP_EQ, -1); + + rv = parse_dir_authority_line(TEST_DIR_AUTH_LINE_START + TEST_DIR_AUTH_LINE_END_WITH_DNS_ADDR, + V3_DIRINFO, 1); + tt_int_op(rv, OP_EQ, -1); + + done: + return; +} + +#undef TEST_DIR_AUTH_LINE_START +#undef TEST_DIR_AUTH_LINE_END_BAD_IP +#undef TEST_DIR_AUTH_LINE_END_WITH_DNS_ADDR + /* No secrets here: * id is `echo "syn-propanethial-S-oxide" | shasum | cut -d" " -f1` */ @@ -3728,7 +3776,7 @@ static void test_config_default_fallback_dirs(void *arg) { const char *fallback[] = { -#include "../or/fallback_dirs.inc" +#include "app/config/fallback_dirs.inc" NULL }; @@ -4591,6 +4639,20 @@ test_config_parse_port_config__ports__ports_given(void *data) tor_addr_parse(&addr, "127.0.0.46"); tt_assert(tor_addr_eq(&port_cfg->addr, &addr)) + // Test success with a port of auto in mixed case + config_free_lines(config_port_valid); config_port_valid = NULL; + SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); + smartlist_clear(slout); + config_port_valid = mock_config_line("DNSPort", "AuTo"); + ret = parse_port_config(slout, config_port_valid, "DNS", 0, + "127.0.0.46", 0, 0); + tt_int_op(ret, OP_EQ, 0); + tt_int_op(smartlist_len(slout), OP_EQ, 1); + port_cfg = (port_cfg_t *)smartlist_get(slout, 0); + tt_int_op(port_cfg->port, OP_EQ, CFG_AUTO_PORT); + tor_addr_parse(&addr, "127.0.0.46"); + tt_assert(tor_addr_eq(&port_cfg->addr, &addr)) + // Test success with parsing both an address and an auto port config_free_lines(config_port_valid); config_port_valid = NULL; SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); @@ -5620,8 +5682,8 @@ test_config_include_opened_file_list(void *data) static void test_config_compute_max_mem_in_queues(void *data) { -#define GIGABYTE(x) (U64_LITERAL(x) << 30) -#define MEGABYTE(x) (U64_LITERAL(x) << 20) +#define GIGABYTE(x) (UINT64_C(x) << 30) +#define MEGABYTE(x) (UINT64_C(x) << 20) (void)data; MOCK(get_total_system_memory, get_total_system_memory_mock); @@ -5685,6 +5747,72 @@ test_config_compute_max_mem_in_queues(void *data) #undef MEGABYTE } +static void +test_config_extended_fmt(void *arg) +{ + (void)arg; + config_line_t *lines = NULL, *lp; + const char string1[] = + "thing1 is here\n" + "+thing2 is over here\n" + "/thing3\n" + "/thing4 is back here\n"; + + /* Try with the "extended" flag disabled. */ + int r = config_get_lines(string1, &lines, 0); + tt_int_op(r, OP_EQ, 0); + lp = lines; + tt_ptr_op(lp, OP_NE, NULL); + tt_str_op(lp->key, OP_EQ, "thing1"); + tt_str_op(lp->value, OP_EQ, "is here"); + tt_int_op(lp->command, OP_EQ, CONFIG_LINE_NORMAL); + lp = lp->next; + tt_ptr_op(lp, OP_NE, NULL); + tt_str_op(lp->key, OP_EQ, "+thing2"); + tt_str_op(lp->value, OP_EQ, "is over here"); + tt_int_op(lp->command, OP_EQ, CONFIG_LINE_NORMAL); + lp = lp->next; + tt_ptr_op(lp, OP_NE, NULL); + tt_str_op(lp->key, OP_EQ, "/thing3"); + tt_str_op(lp->value, OP_EQ, ""); + tt_int_op(lp->command, OP_EQ, CONFIG_LINE_NORMAL); + lp = lp->next; + tt_ptr_op(lp, OP_NE, NULL); + tt_str_op(lp->key, OP_EQ, "/thing4"); + tt_str_op(lp->value, OP_EQ, "is back here"); + tt_int_op(lp->command, OP_EQ, CONFIG_LINE_NORMAL); + lp = lp->next; + config_free_lines(lines); + + /* Try with the "extended" flag enabled. */ + r = config_get_lines(string1, &lines, 1); + tt_int_op(r, OP_EQ, 0); + lp = lines; + tt_ptr_op(lp, OP_NE, NULL); + tt_str_op(lp->key, OP_EQ, "thing1"); + tt_str_op(lp->value, OP_EQ, "is here"); + tt_int_op(lp->command, OP_EQ, CONFIG_LINE_NORMAL); + lp = lp->next; + tt_ptr_op(lp, OP_NE, NULL); + tt_str_op(lp->key, OP_EQ, "thing2"); + tt_str_op(lp->value, OP_EQ, "is over here"); + tt_int_op(lp->command, OP_EQ, CONFIG_LINE_APPEND); + lp = lp->next; + tt_ptr_op(lp, OP_NE, NULL); + tt_str_op(lp->key, OP_EQ, "thing3"); + tt_str_op(lp->value, OP_EQ, ""); + tt_int_op(lp->command, OP_EQ, CONFIG_LINE_CLEAR); + lp = lp->next; + tt_ptr_op(lp, OP_NE, NULL); + tt_str_op(lp->key, OP_EQ, "thing4"); + tt_str_op(lp->value, OP_EQ, ""); + tt_int_op(lp->command, OP_EQ, CONFIG_LINE_CLEAR); + lp = lp->next; + + done: + config_free_lines(lines); +} + #define CONFIG_TEST(name, flags) \ { #name, test_config_ ## name, flags, NULL, NULL } @@ -5692,6 +5820,7 @@ struct testcase_t config_tests[] = { CONFIG_TEST(adding_trusted_dir_server, TT_FORK), CONFIG_TEST(adding_fallback_dir_server, TT_FORK), CONFIG_TEST(parsing_trusted_dir_server, 0), + CONFIG_TEST(parsing_invalid_dir_address, 0), CONFIG_TEST(parsing_fallback_dir_server, 0), CONFIG_TEST(adding_default_trusted_dir_servers, TT_FORK), CONFIG_TEST(adding_dir_servers, TT_FORK), @@ -5734,6 +5863,6 @@ struct testcase_t config_tests[] = { CONFIG_TEST(check_bridge_distribution_setting_unrecognised, 0), CONFIG_TEST(include_opened_file_list, 0), CONFIG_TEST(compute_max_mem_in_queues, 0), + CONFIG_TEST(extended_fmt, 0), END_OF_TESTCASES }; - diff --git a/src/test/test_connection.c b/src/test/test_connection.c index dc0f6860d9..0013f47fbc 100644 --- a/src/test/test_connection.c +++ b/src/test/test_connection.c @@ -1,27 +1,36 @@ -/* Copyright (c) 2015-2017, The Tor Project, Inc. */ +/* Copyright (c) 2015-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" #define CONNECTION_PRIVATE -#define MAIN_PRIVATE +#define MAINLOOP_PRIVATE #define CONNECTION_OR_PRIVATE -#include "or.h" -#include "test.h" - -#include "connection.h" -#include "hs_common.h" -#include "main.h" -#include "microdesc.h" -#include "nodelist.h" -#include "networkstatus.h" -#include "rendcache.h" -#include "directory.h" -#include "connection_or.h" - -#include "test_connection.h" -#include "test_helpers.h" +#include "core/or/or.h" +#include "test/test.h" + +#include "core/mainloop/connection.h" +#include "core/or/connection_edge.h" +#include "feature/hs/hs_common.h" +#include "core/mainloop/mainloop.h" +#include "feature/nodelist/microdesc.h" +#include "feature/nodelist/nodelist.h" +#include "feature/nodelist/networkstatus.h" +#include "feature/rend/rendcache.h" +#include "feature/dircommon/directory.h" +#include "core/or/connection_or.h" +#include "lib/net/resolve.h" + +#include "test/test_connection.h" +#include "test/test_helpers.h" + +#include "feature/dircommon/dir_connection_st.h" +#include "core/or/entry_connection_st.h" +#include "feature/nodelist/node_st.h" +#include "core/or/or_connection_st.h" +#include "feature/nodelist/routerinfo_st.h" +#include "core/or/socks_request_st.h" static void * test_conn_get_basic_setup(const struct testcase_t *tc); static int test_conn_get_basic_teardown(const struct testcase_t *tc, @@ -891,4 +900,3 @@ struct testcase_t connection_tests[] = { { "failed_orconn_tracker", test_failed_orconn_tracker, TT_FORK, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_connection.h b/src/test/test_connection.h index 392783b53b..27c296504a 100644 --- a/src/test/test_connection.h +++ b/src/test/test_connection.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** Some constants used by test_connection and helpers */ diff --git a/src/test/test_conscache.c b/src/test/test_conscache.c index ffec3149b0..b5cbd72515 100644 --- a/src/test/test_conscache.c +++ b/src/test/test_conscache.c @@ -1,10 +1,11 @@ -/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "or.h" -#include "config.h" -#include "conscache.h" -#include "test.h" +#include "core/or/or.h" +#include "app/config/config.h" +#include "feature/dircache/conscache.h" +#include "lib/encoding/confline.h" +#include "test/test.h" #ifdef HAVE_UTIME_H #include <utime.h> @@ -337,4 +338,3 @@ struct testcase_t conscache_tests[] = { ENT(filter), END_OF_TESTCASES }; - diff --git a/src/test/test_consdiff.c b/src/test/test_consdiff.c index fda3a7f186..b836befd22 100644 --- a/src/test/test_consdiff.c +++ b/src/test/test_consdiff.c @@ -1,15 +1,15 @@ /* Copyright (c) 2014, Daniel Martà - * Copyright (c) 2014, The Tor Project, Inc. */ + * Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define CONSDIFF_PRIVATE -#include "or.h" -#include "test.h" +#include "core/or/or.h" +#include "test/test.h" -#include "consdiff.h" -#include "memarea.h" -#include "log_test_helpers.h" +#include "feature/dircommon/consdiff.h" +#include "lib/memarea/memarea.h" +#include "test/log_test_helpers.h" #define tt_str_eq_line(a,b) \ tt_assert(line_str_eq((b),(a))) diff --git a/src/test/test_consdiffmgr.c b/src/test/test_consdiffmgr.c index a9a4b6a98e..6c451da685 100644 --- a/src/test/test_consdiffmgr.c +++ b/src/test/test_consdiffmgr.c @@ -1,20 +1,25 @@ -/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define CONSDIFFMGR_PRIVATE -#include "or.h" -#include "config.h" -#include "conscache.h" -#include "consdiff.h" -#include "consdiffmgr.h" -#include "cpuworker.h" -#include "networkstatus.h" -#include "routerparse.h" -#include "workqueue.h" +#include "core/or/or.h" +#include "app/config/config.h" +#include "feature/dircache/conscache.h" +#include "feature/dircommon/consdiff.h" +#include "feature/dircache/consdiffmgr.h" +#include "core/mainloop/cpuworker.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "feature/nodelist/networkstatus.h" +#include "feature/dirparse/ns_parse.h" +#include "lib/evloop/workqueue.h" +#include "lib/compress/compress.h" +#include "lib/encoding/confline.h" -#include "test.h" -#include "log_test_helpers.h" +#include "feature/nodelist/networkstatus_st.h" + +#include "test/test.h" +#include "test/log_test_helpers.h" // ============================== Setup/teardown the consdiffmgr // These functions get run before/after each test in this module @@ -893,4 +898,3 @@ struct testcase_t consdiffmgr_tests[] = { END_OF_TESTCASES }; - diff --git a/src/test/test_containers.c b/src/test/test_containers.c index c4dba73750..717eb0892a 100644 --- a/src/test/test_containers.c +++ b/src/test/test_containers.c @@ -1,12 +1,17 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" -#include "or.h" -#include "fp_pair.h" -#include "test.h" +#include "core/or/or.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "feature/dircommon/fp_pair.h" +#include "test/test.h" + +#include "lib/container/bitarray.h" +#include "lib/container/order.h" +#include "lib/crypt_ops/digestset.h" /** Helper: return a tristate based on comparing the strings in *<b>a</b> and * *<b>b</b>. */ @@ -639,18 +644,18 @@ test_container_digestset(void *arg) } set = digestset_new(1000); SMARTLIST_FOREACH(included, const char *, cp, - if (digestset_contains(set, cp)) + if (digestset_probably_contains(set, cp)) ok = 0); tt_assert(ok); SMARTLIST_FOREACH(included, const char *, cp, digestset_add(set, cp)); SMARTLIST_FOREACH(included, const char *, cp, - if (!digestset_contains(set, cp)) + if (!digestset_probably_contains(set, cp)) ok = 0); tt_assert(ok); for (i = 0; i < 1000; ++i) { crypto_rand(d, DIGEST_LEN); - if (digestset_contains(set, d)) + if (digestset_probably_contains(set, d)) ++false_positives; } tt_int_op(50, OP_GT, false_positives); /* Should be far lower. */ @@ -1294,4 +1299,3 @@ struct testcase_t container_tests[] = { CONTAINER(smartlist_strings_eq, 0), END_OF_TESTCASES }; - diff --git a/src/test/test_controller.c b/src/test/test_controller.c index 1c285bb3a2..4f5a9f58d5 100644 --- a/src/test/test_controller.c +++ b/src/test/test_controller.c @@ -1,17 +1,25 @@ -/* Copyright (c) 2015-2017, The Tor Project, Inc. */ +/* Copyright (c) 2015-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define CONTROL_PRIVATE -#include "or.h" -#include "bridges.h" -#include "control.h" -#include "entrynodes.h" -#include "hs_common.h" -#include "networkstatus.h" -#include "rendservice.h" -#include "routerlist.h" -#include "test.h" -#include "test_helpers.h" +#include "core/or/or.h" +#include "lib/crypt_ops/crypto_ed25519.h" +#include "feature/client/bridges.h" +#include "feature/control/control.h" +#include "feature/client/entrynodes.h" +#include "feature/hs/hs_common.h" +#include "feature/nodelist/networkstatus.h" +#include "feature/rend/rendservice.h" +#include "feature/nodelist/authcert.h" +#include "feature/nodelist/nodelist.h" +#include "test/test.h" +#include "test/test_helpers.h" +#include "lib/net/resolve.h" + +#include "feature/control/control_connection_st.h" +#include "feature/dirclient/download_status_st.h" +#include "feature/nodelist/microdesc_st.h" +#include "feature/nodelist/node_st.h" static void test_add_onion_helper_keyarg_v3(void *arg) @@ -153,7 +161,7 @@ test_add_onion_helper_keyarg_v2(void *arg) /* Test loading a RSA1024 key. */ tor_free(err_msg); pk1 = pk_generate(0); - tt_int_op(0, OP_EQ, crypto_pk_base64_encode(pk1, &encoded)); + tt_int_op(0, OP_EQ, crypto_pk_base64_encode_private(pk1, &encoded)); tor_asprintf(&arg_str, "RSA1024:%s", encoded); ret = add_onion_helper_keyarg(arg_str, 0, &key_new_alg, &key_new_blob, &pk, &hs_version, &err_msg); @@ -338,6 +346,13 @@ test_rend_service_parse_port_config(void *arg) "in hidden service port configuration."); tor_free(err_msg); + /* Wrong target address and port separation */ + cfg = rend_service_parse_port_config("80,127.0.0.1 1234", sep, + &err_msg); + tt_ptr_op(cfg, OP_EQ, NULL); + tt_assert(err_msg); + tor_free(err_msg); + done: rend_service_port_config_free(cfg); tor_free(err_msg); @@ -1470,6 +1485,135 @@ test_download_status_bridge(void *arg) return; } +/** Set timeval to a mock date and time. This is necessary + * to make tor_gettimeofday() mockable. */ +static void +mock_tor_gettimeofday(struct timeval *timeval) +{ + timeval->tv_sec = 1523405073; + timeval->tv_usec = 271645; +} + +static void +test_current_time(void *arg) +{ + /* We just need one of these to pass, it doesn't matter what's in it */ + control_connection_t dummy; + /* Get results out */ + char *answer = NULL; + const char *errmsg = NULL; + + (void)arg; + + /* We need these for storing the (mock) time. */ + MOCK(tor_gettimeofday, mock_tor_gettimeofday); + struct timeval now; + tor_gettimeofday(&now); + char timebuf[ISO_TIME_LEN+1]; + + /* Case 1 - local time */ + format_local_iso_time_nospace(timebuf, (time_t)now.tv_sec); + getinfo_helper_current_time(&dummy, + "current-time/local", + &answer, &errmsg); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); + tt_str_op(answer, OP_EQ, timebuf); + tor_free(answer); + errmsg = NULL; + + /* Case 2 - UTC time */ + format_iso_time_nospace(timebuf, (time_t)now.tv_sec); + getinfo_helper_current_time(&dummy, + "current-time/utc", + &answer, &errmsg); + tt_ptr_op(answer, OP_NE, NULL); + tt_ptr_op(errmsg, OP_EQ, NULL); + tt_str_op(answer, OP_EQ, timebuf); + tor_free(answer); + errmsg = NULL; + + done: + UNMOCK(tor_gettimeofday); + tor_free(answer); + + return; +} + +static size_t n_nodelist_get_list = 0; +static smartlist_t *nodes = NULL; + +static smartlist_t * +mock_nodelist_get_list(void) +{ + n_nodelist_get_list++; + tor_assert(nodes); + + return nodes; +} + +static void +test_getinfo_md_all(void *arg) +{ + char *answer = NULL; + const char *errmsg = NULL; + int retval = 0; + + (void)arg; + + node_t *node1 = tor_malloc(sizeof(node_t)); + memset(node1, 0, sizeof(node_t)); + node1->md = tor_malloc(sizeof(microdesc_t)); + memset(node1->md, 0, sizeof(microdesc_t)); + node1->md->body = tor_strdup("md1\n"); + node1->md->bodylen = 4; + + node_t *node2 = tor_malloc(sizeof(node_t)); + memset(node2, 0, sizeof(node_t)); + node2->md = tor_malloc(sizeof(microdesc_t)); + memset(node2->md, 0, sizeof(microdesc_t)); + node2->md->body = tor_strdup("md2\n"); + node2->md->bodylen = 4; + + MOCK(nodelist_get_list, mock_nodelist_get_list); + + nodes = smartlist_new(); + + retval = getinfo_helper_dir(NULL, "md/all", &answer, &errmsg); + + tt_int_op(n_nodelist_get_list, OP_EQ, 1); + tt_int_op(retval, OP_EQ, 0); + tt_assert(answer != NULL); + tt_assert(errmsg == NULL); + tt_str_op(answer, OP_EQ, ""); + + tor_free(answer); + + smartlist_add(nodes, node1); + smartlist_add(nodes, node2); + + retval = getinfo_helper_dir(NULL, "md/all", &answer, &errmsg); + + tt_int_op(n_nodelist_get_list, OP_EQ, 2); + tt_int_op(retval, OP_EQ, 0); + tt_assert(answer != NULL); + tt_assert(errmsg == NULL); + + tt_str_op(answer, OP_EQ, "md1\nmd2\n"); + + done: + UNMOCK(nodelist_get_list); + tor_free(node1->md->body); + tor_free(node1->md); + tor_free(node1); + tor_free(node2->md->body); + tor_free(node2->md); + tor_free(node2); + tor_free(answer); + smartlist_free(nodes); + return; +} + struct testcase_t controller_tests[] = { { "add_onion_helper_keyarg_v2", test_add_onion_helper_keyarg_v2, 0, NULL, NULL }, @@ -1486,6 +1630,7 @@ struct testcase_t controller_tests[] = { NULL }, { "download_status_desc", test_download_status_desc, 0, NULL, NULL }, { "download_status_bridge", test_download_status_bridge, 0, NULL, NULL }, + { "current_time", test_current_time, 0, NULL, NULL }, + { "getinfo_md_all", test_getinfo_md_all, 0, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_controller_events.c b/src/test/test_controller_events.c index 901ad7ab3d..4c404876b0 100644 --- a/src/test/test_controller_events.c +++ b/src/test/test_controller_events.c @@ -1,88 +1,19 @@ -/* Copyright (c) 2013-2017, The Tor Project, Inc. */ +/* Copyright (c) 2013-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define CONNECTION_PRIVATE #define TOR_CHANNEL_INTERNAL_ #define CONTROL_PRIVATE -#include "or.h" -#include "channel.h" -#include "channeltls.h" -#include "connection.h" -#include "control.h" -#include "test.h" +#include "core/or/or.h" +#include "core/or/channel.h" +#include "core/or/channeltls.h" +#include "core/or/circuitlist.h" +#include "core/mainloop/connection.h" +#include "feature/control/control.h" +#include "test/test.h" -static void -help_test_bucket_note_empty(uint32_t expected_msec_since_midnight, - int tokens_before, size_t tokens_removed, - uint32_t msec_since_epoch) -{ - uint32_t timestamp_var = 0; - struct timeval tvnow; - tvnow.tv_sec = msec_since_epoch / 1000; - tvnow.tv_usec = (msec_since_epoch % 1000) * 1000; - connection_buckets_note_empty_ts(×tamp_var, tokens_before, - tokens_removed, &tvnow); - tt_int_op(expected_msec_since_midnight, OP_EQ, timestamp_var); - - done: - ; -} - -static void -test_cntev_bucket_note_empty(void *arg) -{ - (void)arg; - - /* Two cases with nothing to note, because bucket was empty before; - * 86442200 == 1970-01-02 00:00:42.200000 */ - help_test_bucket_note_empty(0, 0, 0, 86442200); - help_test_bucket_note_empty(0, -100, 100, 86442200); - - /* Nothing to note, because bucket has not been emptied. */ - help_test_bucket_note_empty(0, 101, 100, 86442200); - - /* Bucket was emptied, note 42200 msec since midnight. */ - help_test_bucket_note_empty(42200, 101, 101, 86442200); - help_test_bucket_note_empty(42200, 101, 102, 86442200); -} - -static void -test_cntev_bucket_millis_empty(void *arg) -{ - struct timeval tvnow; - (void)arg; - - /* 1970-01-02 00:00:42.200000 */ - tvnow.tv_sec = 86400 + 42; - tvnow.tv_usec = 200000; - - /* Bucket has not been refilled. */ - tt_int_op(0, OP_EQ, bucket_millis_empty(0, 42120, 0, 100, &tvnow)); - tt_int_op(0, OP_EQ, bucket_millis_empty(-10, 42120, -10, 100, &tvnow)); - - /* Bucket was not empty. */ - tt_int_op(0, OP_EQ, bucket_millis_empty(10, 42120, 20, 100, &tvnow)); - - /* Bucket has been emptied 80 msec ago and has just been refilled. */ - tt_int_op(80, OP_EQ, bucket_millis_empty(-20, 42120, -10, 100, &tvnow)); - tt_int_op(80, OP_EQ, bucket_millis_empty(-10, 42120, 0, 100, &tvnow)); - tt_int_op(80, OP_EQ, bucket_millis_empty(0, 42120, 10, 100, &tvnow)); - - /* Bucket has been emptied 180 msec ago, last refill was 100 msec ago - * which was insufficient to make it positive, so cap msec at 100. */ - tt_int_op(100, OP_EQ, bucket_millis_empty(0, 42020, 1, 100, &tvnow)); - - /* 1970-01-02 00:00:00:050000 */ - tvnow.tv_sec = 86400; - tvnow.tv_usec = 50000; - - /* Last emptied 30 msec before midnight, tvnow is 50 msec after - * midnight, that's 80 msec in total. */ - tt_int_op(80, OP_EQ, bucket_millis_empty(0, 86400000 - 30, 1, 100, &tvnow)); - - done: - ; -} +#include "core/or/or_circuit_st.h" +#include "core/or/origin_circuit_st.h" static void add_testing_cell_stats_entry(circuit_t *circ, uint8_t command, @@ -391,16 +322,81 @@ test_cntev_event_mask(void *arg) ; } +static char *saved_event_str = NULL; + +static void +mock_queue_control_event_string(uint16_t event, char *msg) +{ + (void)event; + + tor_free(saved_event_str); + saved_event_str = msg; +} + +/* Helper macro for checking bootstrap control event strings */ +#define assert_bootmsg(s) \ + tt_ptr_op(strstr(saved_event_str, "650 STATUS_CLIENT NOTICE " \ + "BOOTSTRAP PROGRESS=" s), OP_EQ, saved_event_str) + +/* Test deferral of directory bootstrap messages (requesting_descriptors) */ +static void +test_cntev_dirboot_defer_desc(void *arg) +{ + (void)arg; + + MOCK(queue_control_event_string, mock_queue_control_event_string); + control_testing_set_global_event_mask(EVENT_MASK_(EVENT_STATUS_CLIENT)); + control_event_bootstrap(BOOTSTRAP_STATUS_STARTING, 0); + assert_bootmsg("0 TAG=starting"); + /* This event should get deferred */ + control_event_boot_dir(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0); + assert_bootmsg("0 TAG=starting"); + control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DIR, 0); + assert_bootmsg("5 TAG=conn_dir"); + control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0); + assert_bootmsg("10 TAG=handshake_dir"); + /* The deferred event should appear */ + control_event_boot_first_orconn(); + assert_bootmsg("45 TAG=requesting_descriptors"); + done: + tor_free(saved_event_str); + UNMOCK(queue_control_event_string); +} + +/* Test deferral of directory bootstrap messages (conn_or) */ +static void +test_cntev_dirboot_defer_orconn(void *arg) +{ + (void)arg; + + MOCK(queue_control_event_string, mock_queue_control_event_string); + control_testing_set_global_event_mask(EVENT_MASK_(EVENT_STATUS_CLIENT)); + control_event_bootstrap(BOOTSTRAP_STATUS_STARTING, 0); + assert_bootmsg("0 TAG=starting"); + /* This event should get deferred */ + control_event_boot_dir(BOOTSTRAP_STATUS_CONN_OR, 0); + assert_bootmsg("0 TAG=starting"); + control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DIR, 0); + assert_bootmsg("5 TAG=conn_dir"); + control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0); + assert_bootmsg("10 TAG=handshake_dir"); + /* The deferred event should appear */ + control_event_boot_first_orconn(); + assert_bootmsg("80 TAG=conn_or"); + done: + tor_free(saved_event_str); + UNMOCK(queue_control_event_string); +} + #define TEST(name, flags) \ { #name, test_cntev_ ## name, flags, 0, NULL } struct testcase_t controller_event_tests[] = { - TEST(bucket_note_empty, TT_FORK), - TEST(bucket_millis_empty, TT_FORK), TEST(sum_up_cell_stats, TT_FORK), TEST(append_cell_stats, TT_FORK), TEST(format_cell_stats, TT_FORK), TEST(event_mask, TT_FORK), + TEST(dirboot_defer_desc, TT_FORK), + TEST(dirboot_defer_orconn, TT_FORK), END_OF_TESTCASES }; - diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index 83d97f2867..81d2fa6f33 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -1,19 +1,38 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" #define CRYPTO_CURVE25519_PRIVATE -#define CRYPTO_PRIVATE -#include "or.h" -#include "test.h" -#include "aes.h" -#include "util.h" +#define CRYPTO_RAND_PRIVATE +#include "core/or/or.h" +#include "test/test.h" +#include "lib/crypt_ops/aes.h" #include "siphash.h" -#include "crypto_curve25519.h" -#include "crypto_ed25519.h" +#include "lib/crypt_ops/crypto_curve25519.h" +#include "lib/crypt_ops/crypto_dh.h" +#include "lib/crypt_ops/crypto_ed25519.h" +#include "lib/crypt_ops/crypto_format.h" +#include "lib/crypt_ops/crypto_hkdf.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "lib/crypt_ops/crypto_init.h" #include "ed25519_vectors.inc" +#include "test/log_test_helpers.h" + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#if defined(ENABLE_OPENSSL) +#include "lib/crypt_ops/compat_openssl.h" +DISABLE_GCC_WARNING(redundant-decls) +#include <openssl/dh.h> +ENABLE_GCC_WARNING(redundant-decls) +#endif /** Run unit tests for Diffie-Hellman functionality. */ static void @@ -22,38 +41,45 @@ test_crypto_dh(void *arg) crypto_dh_t *dh1 = crypto_dh_new(DH_TYPE_CIRCUIT); crypto_dh_t *dh1_dup = NULL; crypto_dh_t *dh2 = crypto_dh_new(DH_TYPE_CIRCUIT); - char p1[DH_BYTES]; - char p2[DH_BYTES]; - char s1[DH_BYTES]; - char s2[DH_BYTES]; + char p1[DH1024_KEY_LEN]; + char p2[DH1024_KEY_LEN]; + char s1[DH1024_KEY_LEN]; + char s2[DH1024_KEY_LEN]; ssize_t s1len, s2len; +#ifdef ENABLE_OPENSSL + crypto_dh_t *dh3 = NULL; + DH *dh4 = NULL; + BIGNUM *pubkey_tmp = NULL; +#endif (void)arg; - tt_int_op(crypto_dh_get_bytes(dh1),OP_EQ, DH_BYTES); - tt_int_op(crypto_dh_get_bytes(dh2),OP_EQ, DH_BYTES); + tt_int_op(crypto_dh_get_bytes(dh1),OP_EQ, DH1024_KEY_LEN); + tt_int_op(crypto_dh_get_bytes(dh2),OP_EQ, DH1024_KEY_LEN); - memset(p1, 0, DH_BYTES); - memset(p2, 0, DH_BYTES); - tt_mem_op(p1,OP_EQ, p2, DH_BYTES); + memset(p1, 0, DH1024_KEY_LEN); + memset(p2, 0, DH1024_KEY_LEN); + tt_mem_op(p1,OP_EQ, p2, DH1024_KEY_LEN); tt_int_op(-1, OP_EQ, crypto_dh_get_public(dh1, p1, 6)); /* too short */ - tt_assert(! crypto_dh_get_public(dh1, p1, DH_BYTES)); - tt_mem_op(p1,OP_NE, p2, DH_BYTES); - tt_assert(! crypto_dh_get_public(dh2, p2, DH_BYTES)); - tt_mem_op(p1,OP_NE, p2, DH_BYTES); + tt_assert(! crypto_dh_get_public(dh1, p1, DH1024_KEY_LEN)); + tt_mem_op(p1,OP_NE, p2, DH1024_KEY_LEN); + tt_assert(! crypto_dh_get_public(dh2, p2, DH1024_KEY_LEN)); + tt_mem_op(p1,OP_NE, p2, DH1024_KEY_LEN); - memset(s1, 0, DH_BYTES); - memset(s2, 0xFF, DH_BYTES); - s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p2, DH_BYTES, s1, 50); - s2len = crypto_dh_compute_secret(LOG_WARN, dh2, p1, DH_BYTES, s2, 50); + memset(s1, 0, DH1024_KEY_LEN); + memset(s2, 0xFF, DH1024_KEY_LEN); + s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p2, DH1024_KEY_LEN, s1, 50); + s2len = crypto_dh_compute_secret(LOG_WARN, dh2, p1, DH1024_KEY_LEN, s2, 50); tt_assert(s1len > 0); tt_int_op(s1len,OP_EQ, s2len); tt_mem_op(s1,OP_EQ, s2, s1len); /* test dh_dup; make sure it works the same. */ dh1_dup = crypto_dh_dup(dh1); - s1len = crypto_dh_compute_secret(LOG_WARN, dh1_dup, p2, DH_BYTES, s1, 50); + s1len = crypto_dh_compute_secret(LOG_WARN, dh1_dup, p2, DH1024_KEY_LEN, + s1, 50); + tt_i64_op(s1len, OP_GE, 0); tt_mem_op(s1,OP_EQ, s2, s1len); { @@ -66,18 +92,24 @@ test_crypto_dh(void *arg) s1len = crypto_dh_compute_secret(LOG_WARN, dh1, "\x00", 1, s1, 50); tt_int_op(-1, OP_EQ, s1len); - memset(p1, 0, DH_BYTES); /* 0 with padding. */ - s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50); + memset(p1, 0, DH1024_KEY_LEN); /* 0 with padding. */ + s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN, + s1, 50); tt_int_op(-1, OP_EQ, s1len); - p1[DH_BYTES-1] = 1; /* 1 with padding*/ - s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50); + p1[DH1024_KEY_LEN-1] = 1; /* 1 with padding*/ + s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN, + s1, 50); tt_int_op(-1, OP_EQ, s1len); /* 2 is okay, though weird. */ s1len = crypto_dh_compute_secret(LOG_WARN, dh1, "\x02", 1, s1, 50); tt_int_op(50, OP_EQ, s1len); + /* 2 a second time is still okay, though weird. */ + s1len = crypto_dh_compute_secret(LOG_WARN, dh1, "\x02", 1, s1, 50); + tt_int_op(50, OP_EQ, s1len); + const char P[] = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" @@ -88,15 +120,18 @@ test_crypto_dh(void *arg) /* p-1, p, and so on are not okay. */ base16_decode(p1, sizeof(p1), P, strlen(P)); - s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50); + s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN, + s1, 50); tt_int_op(-1, OP_EQ, s1len); - p1[DH_BYTES-1] = 0xFE; /* p-1 */ - s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50); + p1[DH1024_KEY_LEN-1] = 0xFE; /* p-1 */ + s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN, + s1, 50); tt_int_op(-1, OP_EQ, s1len); - p1[DH_BYTES-1] = 0xFD; /* p-2 works fine */ - s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50); + p1[DH1024_KEY_LEN-1] = 0xFD; /* p-2 works fine */ + s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN, + s1, 50); tt_int_op(50, OP_EQ, s1len); const char P_plus_one[] = @@ -108,51 +143,103 @@ test_crypto_dh(void *arg) base16_decode(p1, sizeof(p1), P_plus_one, strlen(P_plus_one)); - s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50); + s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN, + s1, 50); tt_int_op(-1, OP_EQ, s1len); - p1[DH_BYTES-1] = 0x01; /* p+2 */ - s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50); + p1[DH1024_KEY_LEN-1] = 0x01; /* p+2 */ + s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN, + s1, 50); tt_int_op(-1, OP_EQ, s1len); - p1[DH_BYTES-1] = 0xff; /* p+256 */ - s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50); + p1[DH1024_KEY_LEN-1] = 0xff; /* p+256 */ + s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN, + s1, 50); tt_int_op(-1, OP_EQ, s1len); - memset(p1, 0xff, DH_BYTES), /* 2^1024-1 */ - s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH_BYTES, s1, 50); + memset(p1, 0xff, DH1024_KEY_LEN), /* 2^1024-1 */ + s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p1, DH1024_KEY_LEN, + s1, 50); tt_int_op(-1, OP_EQ, s1len); } { /* provoke an error in the openssl DH_compute_key function; make sure we * survive. */ - tt_assert(! crypto_dh_get_public(dh1, p1, DH_BYTES)); + tt_assert(! crypto_dh_get_public(dh1, p1, DH1024_KEY_LEN)); crypto_dh_free(dh2); dh2= crypto_dh_new(DH_TYPE_CIRCUIT); /* no private key set */ s1len = crypto_dh_compute_secret(LOG_WARN, dh2, - p1, DH_BYTES, + p1, DH1024_KEY_LEN, s1, 50); tt_int_op(s1len, OP_EQ, -1); } +#if defined(ENABLE_OPENSSL) + { + /* Make sure that our crypto library can handshake with openssl. */ + dh3 = crypto_dh_new(DH_TYPE_TLS); + tt_assert(!crypto_dh_get_public(dh3, p1, DH1024_KEY_LEN)); + + dh4 = crypto_dh_new_openssl_tls(); + tt_assert(DH_generate_key(dh4)); + const BIGNUM *pk=NULL; +#ifdef OPENSSL_1_1_API + const BIGNUM *sk=NULL; + DH_get0_key(dh4, &pk, &sk); +#else + pk = dh4->pub_key; +#endif + tt_assert(pk); + tt_int_op(BN_num_bytes(pk), OP_LE, DH1024_KEY_LEN); + tt_int_op(BN_num_bytes(pk), OP_GT, 0); + memset(p2, 0, sizeof(p2)); + /* right-pad. */ + BN_bn2bin(pk, (unsigned char *)(p2+DH1024_KEY_LEN-BN_num_bytes(pk))); + + s1len = crypto_dh_handshake(LOG_WARN, dh3, p2, DH1024_KEY_LEN, + (unsigned char *)s1, sizeof(s1)); + pubkey_tmp = BN_bin2bn((unsigned char *)p1, DH1024_KEY_LEN, NULL); + s2len = DH_compute_key((unsigned char *)s2, pubkey_tmp, dh4); + + tt_int_op(s1len, OP_EQ, s2len); + tt_int_op(s1len, OP_GT, 0); + tt_mem_op(s1, OP_EQ, s2, s1len); + } +#endif + done: crypto_dh_free(dh1); crypto_dh_free(dh2); crypto_dh_free(dh1_dup); +#ifdef ENABLE_OPENSSL + crypto_dh_free(dh3); + if (dh4) + DH_free(dh4); + if (pubkey_tmp) + BN_free(pubkey_tmp); +#endif } static void test_crypto_openssl_version(void *arg) { (void)arg; +#ifdef ENABLE_NSS + tt_skip(); +#else const char *version = crypto_openssl_get_version_str(); const char *h_version = crypto_openssl_get_header_version_str(); tt_assert(version); tt_assert(h_version); - tt_assert(!strcmpstart(version, h_version)); /* "-fips" suffix, etc */ - tt_assert(!strstr(version, "OpenSSL")); + if (strcmpstart(version, h_version)) { /* "-fips" suffix, etc */ + TT_DIE(("OpenSSL library version %s did not begin with header version %s.", + version, h_version)); + } + if (strstr(version, "OpenSSL")) { + TT_DIE(("assertion failed: !strstr(\"%s\", \"OpenSSL\")", version)); + } int a=-1,b=-1,c=-1; if (!strcmpstart(version, "LibreSSL") || !strcmpstart(version, "BoringSSL")) return; @@ -161,6 +248,7 @@ test_crypto_openssl_version(void *arg) tt_int_op(a, OP_GE, 0); tt_int_op(b, OP_GE, 0); tt_int_op(c, OP_GE, 0); +#endif done: ; @@ -189,10 +277,10 @@ test_crypto_rng(void *arg) j = crypto_rand_int(100); if (j < 0 || j >= 100) allok = 0; - big = crypto_rand_uint64(U64_LITERAL(1)<<40); - if (big >= (U64_LITERAL(1)<<40)) + big = crypto_rand_uint64(UINT64_C(1)<<40); + if (big >= (UINT64_C(1)<<40)) allok = 0; - big = crypto_rand_uint64(U64_LITERAL(5)); + big = crypto_rand_uint64(UINT64_C(5)); if (big >= 5) allok = 0; d = crypto_rand_double(); @@ -1338,22 +1426,22 @@ test_crypto_pk_base64(void *arg) /* Test Base64 encoding a key. */ pk1 = pk_generate(0); tt_assert(pk1); - tt_int_op(0, OP_EQ, crypto_pk_base64_encode(pk1, &encoded)); + tt_int_op(0, OP_EQ, crypto_pk_base64_encode_private(pk1, &encoded)); tt_assert(encoded); /* Test decoding a valid key. */ - pk2 = crypto_pk_base64_decode(encoded, strlen(encoded)); + pk2 = crypto_pk_base64_decode_private(encoded, strlen(encoded)); tt_assert(pk2); tt_int_op(crypto_pk_cmp_keys(pk1, pk2), OP_EQ, 0); crypto_pk_free(pk2); /* Test decoding a invalid key (not Base64). */ static const char *invalid_b64 = "The key is in another castle!"; - pk2 = crypto_pk_base64_decode(invalid_b64, strlen(invalid_b64)); + pk2 = crypto_pk_base64_decode_private(invalid_b64, strlen(invalid_b64)); tt_ptr_op(pk2, OP_EQ, NULL); /* Test decoding a truncated Base64 blob. */ - pk2 = crypto_pk_base64_decode(encoded, strlen(encoded)/2); + pk2 = crypto_pk_base64_decode_private(encoded, strlen(encoded)/2); tt_ptr_op(pk2, OP_EQ, NULL); done: @@ -1402,6 +1490,58 @@ test_crypto_pk_pem_encrypted(void *arg) done: crypto_pk_free(pk); } + +static void +test_crypto_pk_invalid_private_key(void *arg) +{ + (void)arg; + /* Here is a simple invalid private key: it was produced by making + * a regular private key, and then adding 2 to the modulus. */ + const char pem[] = + "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEpQIBAAKCAQEAskRyZrs+YAukvBmZlgo6/rCxyKF2xyUk073ap+2CgRUnSfGG\n" + "mflHlzqVq7tpH50DafpS+fFAbaEaNV/ac20QG0rUZi38HTB4qURWOu6n0Bws6E4l\n" + "UX/AkvDlWnuYH0pHHi2c3DGNFjwoJpjKuUTk+cRffVR8X3Kjr62SUDUaBNW0Kecz\n" + "3SYLbmgmZI16dFZ+g9sNM3znXZbhvb33WwPqpZSSPs37cPgF7eS6mAw/gUMx6zfE\n" + "HRmUnOQSzUdS05rvc/hsiCLhiIZ8hgfkD07XnTT1Ds8DwE55k7BUWY2wvwWCNLsH\n" + "qtqAxTr615XdkMxVkYgImpqPybarpfNYhFqkOwIDAQABAoIBACPC3VxEdbfYvhxJ\n" + "2mih9sG++nswAN7kUaX0cRe86rAwaShJPmJHApiQ1ROVTfpciiHJaLnhLraPWe2Z\n" + "I/6Bw3hmI4O399p3Lc1u+wlpdNqnvE6B1rSptx0DHE9xecvVH70rE0uM2Su7t6Y+\n" + "gnR2IKUGQs2mlCilm7aTUEWs0WJkkl4CG1dyxItuOSdNBjOEzXimJyiB10jEBFsp\n" + "SZeCF2FZ7AJbck5CVC42+oTsiDbZrHTHOn7v26rFGdONeHD1wOI1v7JwHFpCB923\n" + "aEHBzsPbMeq7DWG1rjzCYpcXHhTDBDBWSia4SEhyr2Nl7m7qxWWWwR+x4dqAj3rD\n" + "HeTmos0CgYEA6uf1CLpjPpOs5IaW1DQI8dJA/xFEAC/6GVgq4nFOGHZrm8G3L5o+\n" + "qvtQNMpDs2naWuZpqROFqv24o01DykHygR72GlPIY6uvmmf5tvJLoGnbFUay33L4\n" + "7b9dkNhuEIBNPzVDie0pgS77WgaPbYkVv5fnDwgPuVnkqfakEt7Pz2MCgYEAwkZ5\n" + "R1wLuTQEA2Poo6Gf4L8Bg6yNYI46LHDqDIs818iYLjtcnEEvbPfaoKNpOn7s7s4O\n" + "Pc+4HnT1aIQs0IKVLRTp+5a/9wfOkPZnobWOUHZk9UzBL3Hc1uy/qhp93iE3tSzx\n" + "v0O1pvR+hr3guTCZx8wZnDvaMgG3hlyPnVlHdrMCgYEAzQQxGbMC1ySv6quEjCP2\n" + "AogMbhE1lixJTUFj/EoDbNo9xKznIkauly/Lqqc1OysRhfA/G2+MY9YZBX1zwtyX\n" + "uBW7mPKynDrFgi9pBECnvJNmwET57Ic9ttIj6Tzbos83nAjyrzgr1zGX8dRz7ZeN\n" + "QbBj2vygLJbGOYinXkjUeh0CgYEAhN5aF9n2EqZmkEMGWtMxWy6HRJ0A3Cap1rcq\n" + "+4VHCXWhzwy+XAeg/e/N0MuyLlWcif7XcqLcE8h+BwtO8xQ8HmcNWApUJAls12wO\n" + "mGRpftJaXgIupdpD5aJpu1b++qrRRNIGTH9sf1D8L/8w8LcylZkbcuTkaAsQj45C\n" + "kqT64U0CgYEAq47IKS6xc3CDc17BqExR6t+1yRe+4ml+z1zcVbfUKony4pGvl1yo\n" + "rk0IYDN5Vd8h5xtXrkPdX9h+ywmohnelDKsayEuE+opyqEpSU4/96Bb22RZUoucb\n" + "LWkV5gZx5hFnDFtEd4vadMIiY4jVv/3JqiZDKwMVBJKlHRXJEEmIEBk=\n" + "-----END RSA PRIVATE KEY-----\n"; + + crypto_pk_t *pk = NULL; + + pk = crypto_pk_new(); + setup_capture_of_logs(LOG_WARN); + tt_int_op(-1, OP_EQ, + crypto_pk_read_private_key_from_string(pk, pem, strlen(pem))); +#ifdef ENABLE_NSS + expect_single_log_msg_containing("received bad data"); +#else + expect_single_log_msg_containing("while checking RSA key"); +#endif + done: + teardown_capture_of_logs(); + crypto_pk_free(pk); +} + #ifdef HAVE_TRUNCATE #define do_truncate truncate #else @@ -1437,7 +1577,8 @@ test_crypto_digests(void *arg) (void)arg; k = crypto_pk_new(); tt_assert(k); - r = crypto_pk_read_private_key_from_string(k, AUTHORITY_SIGNKEY_3, -1); + r = crypto_pk_read_private_key_from_string(k, AUTHORITY_SIGNKEY_3, + strlen(AUTHORITY_SIGNKEY_3)); tt_assert(!r); r = crypto_pk_get_digest(k, digest); @@ -1816,15 +1957,6 @@ test_crypto_hkdf_sha256(void *arg) key_material, 100) /* Test vectors generated with ntor_ref.py */ - memset(key_material, 0, sizeof(key_material)); - EXPAND(""); - tt_int_op(r, OP_EQ, 0); - test_memeq_hex(key_material, - "d3490ed48b12a48f9547861583573fe3f19aafe3f81dc7fc75" - "eeed96d741b3290f941576c1f9f0b2d463d1ec7ab2c6bf71cd" - "d7f826c6298c00dbfe6711635d7005f0269493edf6046cc7e7" - "dcf6abe0d20c77cf363e8ffe358927817a3d3e73712cee28d8"); - EXPAND("Tor"); tt_int_op(r, OP_EQ, 0); test_memeq_hex(key_material, @@ -2809,8 +2941,8 @@ test_crypto_siphash(void *arg) { 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, } }; - const struct sipkey K = { U64_LITERAL(0x0706050403020100), - U64_LITERAL(0x0f0e0d0c0b0a0908) }; + const struct sipkey K = { UINT64_C(0x0706050403020100), + UINT64_C(0x0f0e0d0c0b0a0908) }; uint8_t input[64]; int i, j; @@ -2865,12 +2997,12 @@ crypto_rand_check_failure_mode_identical(void) { /* just in case the buffer size isn't a multiple of sizeof(int64_t) */ #define FAILURE_MODE_BUFFER_SIZE_I64 \ - (FAILURE_MODE_BUFFER_SIZE/SIZEOF_INT64_T) + (FAILURE_MODE_BUFFER_SIZE/8) #define FAILURE_MODE_BUFFER_SIZE_I64_BYTES \ - (FAILURE_MODE_BUFFER_SIZE_I64*SIZEOF_INT64_T) + (FAILURE_MODE_BUFFER_SIZE_I64*8) #if FAILURE_MODE_BUFFER_SIZE_I64 < 2 -#error FAILURE_MODE_BUFFER_SIZE needs to be at least 2*SIZEOF_INT64_T +#error FAILURE_MODE_BUFFER_SIZE needs to be at least 2*8 #endif int64_t buf[FAILURE_MODE_BUFFER_SIZE_I64]; @@ -3031,6 +3163,8 @@ struct testcase_t crypto_tests[] = { { "pk_fingerprints", test_crypto_pk_fingerprints, TT_FORK, NULL, NULL }, { "pk_base64", test_crypto_pk_base64, TT_FORK, NULL, NULL }, { "pk_pem_encrypted", test_crypto_pk_pem_encrypted, TT_FORK, NULL, NULL }, + { "pk_invalid_private_key", test_crypto_pk_invalid_private_key, 0, + NULL, NULL }, CRYPTO_LEGACY(digests), { "digest_names", test_crypto_digest_names, 0, NULL, NULL }, { "sha3", test_crypto_sha3, TT_FORK, NULL, NULL}, @@ -3066,4 +3200,3 @@ struct testcase_t crypto_tests[] = { { "failure_modes", test_crypto_failure_modes, TT_FORK, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_crypto_ope.c b/src/test/test_crypto_ope.c new file mode 100644 index 0000000000..4e7b952327 --- /dev/null +++ b/src/test/test_crypto_ope.c @@ -0,0 +1,154 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2017, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" + +#define CRYPTO_OPE_PRIVATE + +#include "lib/cc/compat_compiler.h" +#include "lib/crypt_ops/crypto_ope.h" +#include "lib/crypt_ops/crypto_cipher.h" +#include "lib/encoding/binascii.h" +#include "lib/malloc/malloc.h" +#include "test/test.h" +#include "tinytest.h" + +#include <stddef.h> +#include <string.h> + +static void +test_crypto_ope_consistency(void *arg) +{ + (void)arg; + + crypto_ope_t *ope = NULL; + crypto_cipher_t *aes = NULL; + const int TEST_VALS[] = { 5, 500, 1023, 1024, 1025, 2046, 2047, 2048, 2049, + 10000, OPE_INPUT_MAX }; + unsigned i; + const uint8_t key[32] = "A fixed key, chosen arbitrarily."; + + ope = crypto_ope_new(key); + tt_assert(ope); + + uint64_t last_val = 0; + for (i = 0; i < ARRAY_LENGTH(TEST_VALS); ++i) { + aes = ope_get_cipher(ope, 0); + int val = TEST_VALS[i]; + uint64_t v1 = crypto_ope_encrypt(ope, val); + uint64_t v2 = sum_values_from_cipher(aes, val); + tt_u64_op(v1, OP_EQ, v2); + tt_u64_op(v2, OP_GT, last_val); + last_val = v2; + crypto_cipher_free(aes); + } + + done: + crypto_cipher_free(aes); + crypto_ope_free(ope); +} + +static void +test_crypto_ope_oob(void *arg) +{ + (void)arg; + + crypto_ope_t *ope = NULL; + const uint8_t key[32] = "A fixed key, chosen arbitrarily."; + ope = crypto_ope_new(key); + + tt_u64_op(UINT64_MAX, OP_EQ, crypto_ope_encrypt(ope,INT_MIN)); + tt_u64_op(UINT64_MAX, OP_EQ, crypto_ope_encrypt(ope,-100)); + tt_u64_op(UINT64_MAX, OP_EQ, crypto_ope_encrypt(ope,0)); + tt_u64_op(UINT64_MAX, OP_NE, crypto_ope_encrypt(ope,1)); + tt_u64_op(UINT64_MAX, OP_NE, crypto_ope_encrypt(ope,7000)); + tt_u64_op(UINT64_MAX, OP_NE, crypto_ope_encrypt(ope,OPE_INPUT_MAX)); + tt_u64_op(UINT64_MAX, OP_EQ, crypto_ope_encrypt(ope,OPE_INPUT_MAX+1)); + tt_u64_op(UINT64_MAX, OP_EQ, crypto_ope_encrypt(ope,INT_MAX)); + done: + crypto_ope_free(ope); +} + +static const char OPE_TEST_KEY[] = + "19e05891d55232c08c2cad91d612fdb9cbd6691949a0742434a76c80bc6992fe"; + +/* generated by a separate python implementation. */ +static const struct { + int v; + uint64_t r; +} OPE_TEST_VECTORS[] = { + { 121132, UINT64_C(3971694514) }, + { 82283, UINT64_C(2695743564) }, + { 72661, UINT64_C(2381548866) }, + { 72941, UINT64_C(2390408421) }, + { 123122, UINT64_C(4036781069) }, + { 12154, UINT64_C(402067100) }, + { 121574, UINT64_C(3986197593) }, + { 11391, UINT64_C(376696838) }, + { 65845, UINT64_C(2161801517) }, + { 86301, UINT64_C(2828270975) }, + { 61284, UINT64_C(2013616892) }, + { 70505, UINT64_C(2313368870) }, + { 30438, UINT64_C(1001394664) }, + { 60150, UINT64_C(1977329668) }, + { 114800, UINT64_C(3764946628) }, + { 109403, UINT64_C(3585352477) }, + { 21893, UINT64_C(721388468) }, + { 123569, UINT64_C(4051780471) }, + { 95617, UINT64_C(3134921876) }, + { 48561, UINT64_C(1597596985) }, + { 53334, UINT64_C(1753691710) }, + { 92746, UINT64_C(3040874493) }, + { 7110, UINT64_C(234966492) }, + { 9612, UINT64_C(318326551) }, + { 106958, UINT64_C(3506124249) }, + { 46889, UINT64_C(1542219146) }, + { 87790, UINT64_C(2877361609) }, + { 68878, UINT64_C(2260369112) }, + { 47917, UINT64_C(1576681737) }, + { 121128, UINT64_C(3971553290) }, + { 108602, UINT64_C(3559176081) }, + { 28217, UINT64_C(929692460) }, + { 69498, UINT64_C(2280554161) }, + { 63870, UINT64_C(2098322675) }, + { 57542, UINT64_C(1891698992) }, + { 122148, UINT64_C(4004515805) }, + { 46254, UINT64_C(1521227949) }, + { 42850, UINT64_C(1408996941) }, + { 92661, UINT64_C(3037901517) }, + { 57720, UINT64_C(1897369989) }, +}; + +static void +test_crypto_ope_vectors(void *arg) +{ + (void)arg; + uint8_t key[32]; + crypto_ope_t *ope = NULL, *ope2 = NULL; + + base16_decode((char*)key, 32, OPE_TEST_KEY, strlen(OPE_TEST_KEY)); + + ope = crypto_ope_new(key); + key[8] += 1; + ope2 = crypto_ope_new(key); + unsigned i; + for (i = 0; i < ARRAY_LENGTH(OPE_TEST_VECTORS); ++i) { + int val = OPE_TEST_VECTORS[i].v; + uint64_t res = OPE_TEST_VECTORS[i].r; + + tt_u64_op(crypto_ope_encrypt(ope, val), OP_EQ, res); + tt_u64_op(crypto_ope_encrypt(ope2, val), OP_NE, res); + } + done: + crypto_ope_free(ope); + crypto_ope_free(ope2); +} + +struct testcase_t crypto_ope_tests[] = { + { "consistency", test_crypto_ope_consistency, 0, NULL, NULL }, + { "oob", test_crypto_ope_oob, 0, NULL, NULL }, + { "vectors", test_crypto_ope_vectors, 0, NULL, NULL }, + END_OF_TESTCASES +}; diff --git a/src/test/test_crypto_openssl.c b/src/test/test_crypto_openssl.c index 090cb4242b..92f9cbab2f 100644 --- a/src/test/test_crypto_openssl.c +++ b/src/test/test_crypto_openssl.c @@ -1,21 +1,21 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" -#define CRYPTO_PRIVATE +#define CRYPTO_RAND_PRIVATE -#include "crypto.h" -#include "util.h" -#include "util_format.h" -#include "compat.h" -#include "test.h" +#include "lib/crypt_ops/compat_openssl.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "lib/encoding/binascii.h" +#include "lib/malloc/malloc.h" +#include "test/test.h" #include <openssl/evp.h> #include <openssl/rand.h> -#include "compat_openssl.h" +#include <string.h> /* Test for rectifying openssl RAND engine. */ static void @@ -104,4 +104,3 @@ struct testcase_t crypto_openssl_tests[] = { TT_FORK, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_crypto_slow.c b/src/test/test_crypto_slow.c index 2afb71ff5a..ca6b7b8d4d 100644 --- a/src/test/test_crypto_slow.c +++ b/src/test/test_crypto_slow.c @@ -1,21 +1,26 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" #define CRYPTO_S2K_PRIVATE -#include "or.h" -#include "test.h" -#include "crypto_s2k.h" -#include "crypto_pwbox.h" +#include "core/or/or.h" +#include "test/test.h" +#include "lib/crypt_ops/crypto_curve25519.h" +#include "lib/crypt_ops/crypto_ed25519.h" +#include "lib/crypt_ops/crypto_s2k.h" +#include "lib/crypt_ops/crypto_pwbox.h" +#include "lib/crypt_ops/crypto_rand.h" #if defined(HAVE_LIBSCRYPT_H) && defined(HAVE_LIBSCRYPT_SCRYPT) #define HAVE_LIBSCRYPT #include <libscrypt.h> #endif +#ifdef ENABLE_OPENSSL #include <openssl/evp.h> +#endif /** Run unit tests for our secret-to-key passphrase hashing functionality. */ static void @@ -614,4 +619,3 @@ struct testcase_t slow_crypto_tests[] = { ED25519_TEST(fuzz_donna, TT_FORK), END_OF_TESTCASES }; - diff --git a/src/test/test_data.c b/src/test/test_data.c index ce6c3394f6..be8153258b 100644 --- a/src/test/test_data.c +++ b/src/test/test_data.c @@ -1,9 +1,9 @@ /* Copyright 2001-2004 Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "test.h" +#include "test/test.h" /* Our unit test expect that the AUTHORITY_CERT_* public keys will sort * in this order. */ diff --git a/src/test/test_dir.c b/src/test/test_dir.c index a33b23bcc9..c18aa99fea 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -1,46 +1,96 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" #include <math.h> +#define BWAUTH_PRIVATE #define CONFIG_PRIVATE #define CONTROL_PRIVATE +#define DIRCACHE_PRIVATE +#define DIRCLIENT_PRIVATE #define DIRSERV_PRIVATE #define DIRVOTE_PRIVATE -#define ROUTER_PRIVATE -#define ROUTERLIST_PRIVATE -#define ROUTERPARSE_PRIVATE +#define DLSTATUS_PRIVATE #define HIBERNATE_PRIVATE #define NETWORKSTATUS_PRIVATE +#define NS_PARSE_PRIVATE +#define NODE_SELECT_PRIVATE #define RELAY_PRIVATE - -#include "or.h" -#include "bridges.h" -#include "confparse.h" -#include "config.h" -#include "control.h" -#include "crypto_ed25519.h" -#include "directory.h" -#include "dirserv.h" -#include "dirvote.h" -#include "entrynodes.h" -#include "hibernate.h" -#include "memarea.h" -#include "networkstatus.h" -#include "router.h" -#include "routerkeys.h" -#include "routerlist.h" -#include "routerparse.h" -#include "routerset.h" -#include "shared_random_state.h" -#include "test.h" -#include "test_dir_common.h" -#include "torcert.h" -#include "relay.h" -#include "log_test_helpers.h" +#define ROUTERLIST_PRIVATE +#define ROUTER_PRIVATE +#define UNPARSEABLE_PRIVATE +#define VOTEFLAGS_PRIVATE + +#include "core/or/or.h" +#include "app/config/config.h" +#include "app/config/confparse.h" +#include "core/mainloop/connection.h" +#include "core/or/relay.h" +#include "core/or/versions.h" +#include "feature/client/bridges.h" +#include "feature/client/entrynodes.h" +#include "feature/control/control.h" +#include "feature/dirauth/bwauth.h" +#include "feature/dirauth/dirvote.h" +#include "feature/dirauth/dsigs_parse.h" +#include "feature/dirauth/process_descs.h" +#include "feature/dirauth/recommend_pkg.h" +#include "feature/dirauth/shared_random_state.h" +#include "feature/dirauth/voteflags.h" +#include "feature/dircache/dircache.h" +#include "feature/dircache/dirserv.h" +#include "feature/dirclient/dirclient.h" +#include "feature/dirclient/dlstatus.h" +#include "feature/dircommon/directory.h" +#include "feature/dircommon/fp_pair.h" +#include "feature/dircommon/voting_schedule.h" +#include "feature/hibernate/hibernate.h" +#include "feature/nodelist/authcert.h" +#include "feature/nodelist/dirlist.h" +#include "feature/nodelist/networkstatus.h" +#include "feature/nodelist/nickname.h" +#include "feature/nodelist/node_select.h" +#include "feature/nodelist/routerlist.h" +#include "feature/dirparse/authcert_parse.h" +#include "feature/dirparse/ns_parse.h" +#include "feature/dirparse/routerparse.h" +#include "feature/dirparse/unparseable.h" +#include "feature/nodelist/routerset.h" +#include "feature/nodelist/torcert.h" +#include "feature/relay/router.h" +#include "feature/relay/routerkeys.h" +#include "feature/relay/routermode.h" +#include "lib/compress/compress.h" +#include "lib/crypt_ops/crypto_ed25519.h" +#include "lib/crypt_ops/crypto_format.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "lib/encoding/confline.h" +#include "lib/memarea/memarea.h" +#include "lib/osinfo/uname.h" +#include "test/log_test_helpers.h" +#include "test/test.h" +#include "test/test_dir_common.h" + +#include "core/or/addr_policy_st.h" +#include "feature/nodelist/authority_cert_st.h" +#include "feature/nodelist/document_signature_st.h" +#include "feature/nodelist/extrainfo_st.h" +#include "feature/nodelist/networkstatus_st.h" +#include "feature/nodelist/networkstatus_voter_info_st.h" +#include "feature/dirauth/ns_detached_signatures_st.h" +#include "core/or/port_cfg_st.h" +#include "feature/nodelist/routerinfo_st.h" +#include "feature/nodelist/routerlist_st.h" +#include "core/or/tor_version_st.h" +#include "feature/dirauth/vote_microdesc_hash_st.h" +#include "feature/nodelist/vote_routerstatus_st.h" + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif #define NS_MODULE dir @@ -140,7 +190,7 @@ test_dir_formats(void *arg) r1->supports_tunnelled_dir_requests = 1; tor_addr_parse(&r1->ipv6_addr, "1:2:3:4::"); r1->ipv6_orport = 9999; - r1->onion_pkey = crypto_pk_dup_key(pk1); + router_set_rsa_onion_pkey(pk1, &r1->onion_pkey, &r1->onion_pkey_len); /* Fake just enough of an ntor key to get by */ curve25519_keypair_t r1_onion_keypair; curve25519_keypair_generate(&r1_onion_keypair, 0); @@ -183,7 +233,7 @@ test_dir_formats(void *arg) r2->or_port = 9005; r2->dir_port = 0; r2->supports_tunnelled_dir_requests = 1; - r2->onion_pkey = crypto_pk_dup_key(pk2); + router_set_rsa_onion_pkey(pk2, &r2->onion_pkey, &r2->onion_pkey_len); curve25519_keypair_t r2_onion_keypair; curve25519_keypair_generate(&r2_onion_keypair, 0); r2->onion_curve25519_pkey = tor_memdup(&r2_onion_keypair.pubkey, @@ -276,7 +326,10 @@ test_dir_formats(void *arg) tt_int_op(rp1->bandwidthrate,OP_EQ, r1->bandwidthrate); tt_int_op(rp1->bandwidthburst,OP_EQ, r1->bandwidthburst); tt_int_op(rp1->bandwidthcapacity,OP_EQ, r1->bandwidthcapacity); - tt_int_op(crypto_pk_cmp_keys(rp1->onion_pkey, pk1), OP_EQ, 0); + crypto_pk_t *onion_pkey = router_get_rsa_onion_pkey(rp1->onion_pkey, + rp1->onion_pkey_len); + tt_int_op(crypto_pk_cmp_keys(onion_pkey, pk1), OP_EQ, 0); + crypto_pk_free(onion_pkey); tt_int_op(crypto_pk_cmp_keys(rp1->identity_pkey, pk2), OP_EQ, 0); tt_assert(rp1->supports_tunnelled_dir_requests); //tt_assert(rp1->exit_policy == NULL); @@ -393,7 +446,10 @@ test_dir_formats(void *arg) tt_mem_op(rp2->onion_curve25519_pkey->public_key,OP_EQ, r2->onion_curve25519_pkey->public_key, CURVE25519_PUBKEY_LEN); - tt_int_op(crypto_pk_cmp_keys(rp2->onion_pkey, pk2), OP_EQ, 0); + onion_pkey = router_get_rsa_onion_pkey(rp2->onion_pkey, + rp2->onion_pkey_len); + tt_int_op(crypto_pk_cmp_keys(onion_pkey, pk2), OP_EQ, 0); + crypto_pk_free(onion_pkey); tt_int_op(crypto_pk_cmp_keys(rp2->identity_pkey, pk1), OP_EQ, 0); tt_assert(rp2->supports_tunnelled_dir_requests); @@ -1499,6 +1555,13 @@ test_dir_measured_bw_kb(void *arg) "bw=1024 junk=007\n", "misc=junk node_id=$557365204145532d32353620696e73746561642e " "bw=1024 junk=007\n", + /* check whether node_id can be at the end */ + "bw=1024 node_id=$557365204145532d32353620696e73746561642e\n", + /* check whether node_id can be at the end and bw has something in front*/ + "foo=bar bw=1024 node_id=$557365204145532d32353620696e73746561642e\n", + /* check whether node_id can be at the end and something in the + * in the middle of bw and node_id */ + "bw=1024 foo=bar node_id=$557365204145532d32353620696e73746561642e\n", "end" }; const char *lines_fail[] = { @@ -1538,12 +1601,18 @@ test_dir_measured_bw_kb(void *arg) (void)arg; for (i = 0; strcmp(lines_fail[i], "end"); i++) { //fprintf(stderr, "Testing: %s\n", lines_fail[i]); - tt_int_op(measured_bw_line_parse(&mbwl, lines_fail[i]), OP_EQ, -1); + /* Testing only with line_is_after_headers = 1. Tests with + * line_is_after_headers = 0 in + * test_dir_measured_bw_kb_line_is_after_headers */ + tt_assert(measured_bw_line_parse(&mbwl, lines_fail[i], 1) == -1); } for (i = 0; strcmp(lines_pass[i], "end"); i++) { //fprintf(stderr, "Testing: %s %d\n", lines_pass[i], TOR_ISSPACE('\n')); - tt_int_op(measured_bw_line_parse(&mbwl, lines_pass[i]), OP_EQ, 0); + /* Testing only with line_is_after_headers = 1. Tests with + * line_is_after_headers = 0 in + * test_dir_measured_bw_kb_line_is_after_headers */ + tt_assert(measured_bw_line_parse(&mbwl, lines_pass[i], 1) == 0); tt_assert(mbwl.bw_kb == 1024); tt_assert(strcmp(mbwl.node_hex, "557365204145532d32353620696e73746561642e") == 0); @@ -1553,23 +1622,372 @@ test_dir_measured_bw_kb(void *arg) return; } -/* Test dirserv_read_measured_bandwidths */ +/* Unit tests for measured_bw_line_parse using line_is_after_headers flag. + * When the end of the header is detected (a first complete bw line is parsed), + * incomplete lines fail and give warnings, but do not give warnings if + * the header is not ended, allowing to ignore additional header lines. */ static void -test_dir_dirserv_read_measured_bandwidths(void *arg) +test_dir_measured_bw_kb_line_is_after_headers(void *arg) { - char *fname=NULL; (void)arg; + measured_bw_line_t mbwl; + const char *line_pass = \ + "node_id=$557365204145532d32353620696e73746561642e bw=1024\n"; + int i; + const char *lines_fail[] = { + "node_id=$557365204145532d32353620696e73746561642e \n", + "bw=1024\n", + "rtt=300\n", + "end" + }; + + setup_capture_of_logs(LOG_DEBUG); + + /* Test bw lines when header has ended */ + for (i = 0; strcmp(lines_fail[i], "end"); i++) { + tt_assert(measured_bw_line_parse(&mbwl, lines_fail[i], 1) == -1); + expect_log_msg_containing("Incomplete line in bandwidth file:"); + mock_clean_saved_logs(); + } - fname = tor_strdup(get_fname("V3BandwidthsFile")); - /* Test an empty file */ + tt_assert(measured_bw_line_parse(&mbwl, line_pass, 1) == 0); + + /* Test bw lines when header has not ended */ + for (i = 0; strcmp(lines_fail[i], "end"); i++) { + tt_assert(measured_bw_line_parse(&mbwl, lines_fail[i], 0) == -1); + expect_log_msg_containing("Missing bw or node_id in bandwidth file line:"); + mock_clean_saved_logs(); + } + + tt_assert(measured_bw_line_parse(&mbwl, line_pass, 0) == 0); + + done: + teardown_capture_of_logs(); +} + +/* Test dirserv_read_measured_bandwidths with headers and complete files. */ +static void +test_dir_dirserv_read_measured_bandwidths(void *arg) +{ + (void)arg; + char *content = NULL; + time_t timestamp = time(NULL); + char *fname = tor_strdup(get_fname("V3BandwidthsFile")); + smartlist_t *bw_file_headers = smartlist_new(); + /* bw file strings in vote */ + char *bw_file_headers_str = NULL; + char *bw_file_headers_str_v100 = NULL; + char *bw_file_headers_str_v110 = NULL; + char *bw_file_headers_str_bad = NULL; + char *bw_file_headers_str_extra = NULL; + char bw_file_headers_str_long[MAX_BW_FILE_HEADER_COUNT_IN_VOTE * 8 + 1] = ""; + /* string header lines in bw file */ + char *header_lines_v100 = NULL; + char *header_lines_v110_no_terminator = NULL; + char *header_lines_v110 = NULL; + char header_lines_long[MAX_BW_FILE_HEADER_COUNT_IN_VOTE * 8 + 1] = ""; + int i; + const char *header_lines_v110_no_terminator_no_timestamp = + "version=1.1.0\n" + "software=sbws\n" + "software_version=0.1.0\n" + "earliest_bandwidth=2018-05-08T16:13:26\n" + "file_created=2018-04-16T21:49:18\n" + "generator_started=2018-05-08T16:13:25\n" + "latest_bandwidth=2018-04-16T20:49:18\n"; + const char *bw_file_headers_str_v110_no_timestamp = + "version=1.1.0 software=sbws " + "software_version=0.1.0 " + "earliest_bandwidth=2018-05-08T16:13:26 " + "file_created=2018-04-16T21:49:18 " + "generator_started=2018-05-08T16:13:25 " + "latest_bandwidth=2018-04-16T20:49:18"; + const char *relay_lines_v100 = + "node_id=$557365204145532d32353620696e73746561642e bw=1024 " + "nick=Test measured_at=1523911725 updated_at=1523911725 " + "pid_error=4.11374090719 pid_error_sum=4.11374090719 " + "pid_bw=57136645 pid_delta=2.12168374577 circ_fail=0.2 " + "scanner=/filepath\n"; + const char *relay_lines_v110 = + "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A27F80 " + "master_key_ed25519=YaqV4vbvPYKucElk297eVdNArDz9HtIwUoIeo0+cVIpQ " + "bw=760 nick=Test rtt=380 time=2018-05-08T16:13:26\n"; + const char *relay_lines_bad = + "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A\n"; + + tor_asprintf(&header_lines_v100, "%ld\n", (long)timestamp); + tor_asprintf(&header_lines_v110_no_terminator, "%ld\n%s", (long)timestamp, + header_lines_v110_no_terminator_no_timestamp); + tor_asprintf(&header_lines_v110, "%s%s", + header_lines_v110_no_terminator, BW_FILE_HEADERS_TERMINATOR); + + tor_asprintf(&bw_file_headers_str_v100, "timestamp=%ld",(long)timestamp); + tor_asprintf(&bw_file_headers_str_v110, "timestamp=%ld %s", + (long)timestamp, bw_file_headers_str_v110_no_timestamp); + tor_asprintf(&bw_file_headers_str_bad, "%s " + "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A", + bw_file_headers_str_v110); + + for (i=0; i<MAX_BW_FILE_HEADER_COUNT_IN_VOTE; i++) { + strlcat(header_lines_long, "foo=bar\n", + sizeof(header_lines_long)); + } + /* 8 is the number of v110 lines in header_lines_v110 */ + for (i=0; i<MAX_BW_FILE_HEADER_COUNT_IN_VOTE - 8 - 1; i++) { + strlcat(bw_file_headers_str_long, "foo=bar ", + sizeof(bw_file_headers_str_long)); + } + strlcat(bw_file_headers_str_long, "foo=bar", + sizeof(bw_file_headers_str_long)); + tor_asprintf(&bw_file_headers_str_extra, + "%s %s", + bw_file_headers_str_v110, + bw_file_headers_str_long); + + /* Test an empty bandwidth file. bw_file_headers will be empty string */ write_str_to_file(fname, "", 0); setup_capture_of_logs(LOG_WARN); - tt_int_op(-1, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL)); + tt_int_op(-1, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, + bw_file_headers)); expect_log_msg("Empty bandwidth file\n"); + teardown_capture_of_logs(); + bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL); + tt_str_op("", OP_EQ, bw_file_headers_str); + SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c)); + smartlist_free(bw_file_headers); + tor_free(bw_file_headers_str); + + /* Test bandwidth file with only timestamp. + * bw_file_headers will be empty string */ + bw_file_headers = smartlist_new(); + tor_asprintf(&content, "%ld", (long)timestamp); + write_str_to_file(fname, content, 0); + tor_free(content); + tt_int_op(-1, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, + bw_file_headers)); + bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL); + tt_str_op("", OP_EQ, bw_file_headers_str); + SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c)); + smartlist_free(bw_file_headers); + tor_free(bw_file_headers_str); + + /* Test v1.0.0 bandwidth file headers */ + write_str_to_file(fname, header_lines_v100, 0); + bw_file_headers = smartlist_new(); + tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, + bw_file_headers)); + bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL); + tt_str_op(bw_file_headers_str_v100, OP_EQ, bw_file_headers_str); + SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c)); + smartlist_free(bw_file_headers); + tor_free(bw_file_headers_str); + + /* Test v1.0.0 complete bandwidth file */ + bw_file_headers = smartlist_new(); + tor_asprintf(&content, "%s%s", header_lines_v100, relay_lines_v100); + write_str_to_file(fname, content, 0); + tor_free(content); + tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, + bw_file_headers)); + bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL); + tt_str_op(bw_file_headers_str_v100, OP_EQ, bw_file_headers_str); + SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c)); + smartlist_free(bw_file_headers); + tor_free(bw_file_headers_str); + + /* Test v1.0.0 complete bandwidth file with NULL bw_file_headers. */ + tor_asprintf(&content, "%s%s", header_lines_v100, relay_lines_v100); + write_str_to_file(fname, content, 0); + tor_free(content); + tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, NULL)); + + /* Test bandwidth file including v1.1.0 bandwidth headers and + * v1.0.0 relay lines. bw_file_headers will contain the v1.1.0 headers. */ + bw_file_headers = smartlist_new(); + tor_asprintf(&content, "%s%s%s", header_lines_v100, header_lines_v110, + relay_lines_v100); + write_str_to_file(fname, content, 0); + tor_free(content); + tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, + bw_file_headers)); + bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL); + tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str); + SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c)); + smartlist_free(bw_file_headers); + tor_free(bw_file_headers_str); + + /* Test v1.0.0 complete bandwidth file with v1.1.0 headers at the end. + * bw_file_headers will contain only v1.0.0 headers and the additional + * headers will be interpreted as malformed relay lines. */ + bw_file_headers = smartlist_new(); + tor_asprintf(&content, "%s%s%s", header_lines_v100, relay_lines_v100, + header_lines_v110); + write_str_to_file(fname, content, 0); + tor_free(content); + tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, + bw_file_headers)); + bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL); + tt_str_op(bw_file_headers_str_v100, OP_EQ, bw_file_headers_str); + SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c)); + smartlist_free(bw_file_headers); + tor_free(bw_file_headers_str); + + /* Test v1.0.0 complete bandwidth file, the v1.1.0 headers and more relay + * lines. bw_file_headers will contain only v1.0.0 headers, the additional + * headers will be interpreted as malformed relay lines and the last relay + * lines will be correctly interpreted as relay lines. */ + bw_file_headers = smartlist_new(); + tor_asprintf(&content, "%s%s%s%s", header_lines_v100, relay_lines_v100, + header_lines_v110, relay_lines_v100); + write_str_to_file(fname, content, 0); + tor_free(content); + tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, + bw_file_headers)); + bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL); + tt_str_op(bw_file_headers_str_v100, OP_EQ, bw_file_headers_str); + SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c)); + smartlist_free(bw_file_headers); + tor_free(bw_file_headers_str); + + /* Test v1.1.0 bandwidth headers without terminator */ + bw_file_headers = smartlist_new(); + write_str_to_file(fname, header_lines_v110_no_terminator, 0); + tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, + bw_file_headers)); + bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL); + tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str); + SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c)); + smartlist_free(bw_file_headers); + tor_free(bw_file_headers_str); + + /* Test v1.1.0 bandwidth headers with terminator */ + bw_file_headers = smartlist_new(); + write_str_to_file(fname, header_lines_v110, 0); + tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, + bw_file_headers)); + bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL); + tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str); + SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c)); + smartlist_free(bw_file_headers); + tor_free(bw_file_headers_str); + + /* Test v1.1.0 bandwidth file without terminator, then relay lines. + * bw_file_headers will contain the v1.1.0 headers. */ + bw_file_headers = smartlist_new(); + tor_asprintf(&content, "%s%s", + header_lines_v110_no_terminator, relay_lines_v110); + write_str_to_file(fname, content, 0); + tor_free(content); + tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, + bw_file_headers)); + bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL); + tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str); + SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c)); + smartlist_free(bw_file_headers); + tor_free(bw_file_headers_str); + + /* Test v1.1.0 bandwidth headers with terminator, then relay lines + * bw_file_headers will contain the v1.1.0 headers. */ + bw_file_headers = smartlist_new(); + tor_asprintf(&content, "%s%s", + header_lines_v110, relay_lines_v110); + write_str_to_file(fname, content, 0); + tor_free(content); + tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, + bw_file_headers)); + bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL); + tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str); + SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c)); + smartlist_free(bw_file_headers); + tor_free(bw_file_headers_str); + + /* Test v1.1.0 bandwidth headers with terminator, then bad relay lines, + * then terminator, then relay_lines_bad. + * bw_file_headers will contain the v1.1.0 headers. */ + bw_file_headers = smartlist_new(); + tor_asprintf(&content, "%s%s%s%s", header_lines_v110, relay_lines_bad, + BW_FILE_HEADERS_TERMINATOR, relay_lines_bad); + write_str_to_file(fname, content, 0); + tor_free(content); + tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, + bw_file_headers)); + bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL); + tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str); + SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c)); + smartlist_free(bw_file_headers); + tor_free(bw_file_headers_str); + + /* Test v1.1.0 bandwidth headers without terminator, then bad relay lines, + * then relay lines. bw_file_headers will contain the v1.1.0 headers and + * the bad relay lines. */ + bw_file_headers = smartlist_new(); + tor_asprintf(&content, "%s%s%s", + header_lines_v110_no_terminator, relay_lines_bad, + relay_lines_v110); + write_str_to_file(fname, content, 0); + tor_free(content); + tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, + bw_file_headers)); + bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL); + tt_str_op(bw_file_headers_str_bad, OP_EQ, bw_file_headers_str); + SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c)); + smartlist_free(bw_file_headers); + tor_free(bw_file_headers_str); + + /* Test v1.1.0 bandwidth headers without terminator, + * then many bad relay lines, then relay lines. + * bw_file_headers will contain the v1.1.0 headers and the bad relay lines + * to a maximum of MAX_BW_FILE_HEADER_COUNT_IN_VOTE header lines. */ + bw_file_headers = smartlist_new(); + tor_asprintf(&content, "%s%s%s", + header_lines_v110_no_terminator, header_lines_long, + relay_lines_v110); + write_str_to_file(fname, content, 0); + tor_free(content); + tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, + bw_file_headers)); + tt_int_op(MAX_BW_FILE_HEADER_COUNT_IN_VOTE, OP_EQ, + smartlist_len(bw_file_headers)); + bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL); + tt_str_op(bw_file_headers_str_extra, OP_EQ, bw_file_headers_str); + SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c)); + smartlist_free(bw_file_headers); + tor_free(bw_file_headers_str); + + /* Test v1.1.0 bandwidth headers without terminator, + * then many bad relay lines, then relay lines. + * bw_file_headers will contain the v1.1.0 headers and the bad relay lines. + * Force bw_file_headers to have more than MAX_BW_FILE_HEADER_COUNT_IN_VOTE + * This test is needed while there is not dirvote test. */ + bw_file_headers = smartlist_new(); + tor_asprintf(&content, "%s%s%s", + header_lines_v110_no_terminator, header_lines_long, + relay_lines_v110); + write_str_to_file(fname, content, 0); + tor_free(content); + tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, + bw_file_headers)); + tt_int_op(MAX_BW_FILE_HEADER_COUNT_IN_VOTE, OP_EQ, + smartlist_len(bw_file_headers)); + /* force bw_file_headers to be bigger than + * MAX_BW_FILE_HEADER_COUNT_IN_VOTE */ + char line[8] = "foo=bar\0"; + smartlist_add_strdup(bw_file_headers, line); + tt_int_op(MAX_BW_FILE_HEADER_COUNT_IN_VOTE, OP_LT, + smartlist_len(bw_file_headers)); + SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c)); + smartlist_free(bw_file_headers); + tor_free(bw_file_headers_str); done: tor_free(fname); - teardown_capture_of_logs(); + tor_free(header_lines_v100); + tor_free(header_lines_v110_no_terminator); + tor_free(header_lines_v110); + tor_free(bw_file_headers_str_v100); + tor_free(bw_file_headers_str_v110); + tor_free(bw_file_headers_str_bad); + tor_free(bw_file_headers_str_extra); } #define MBWC_INIT_TIME 1000 @@ -1949,7 +2367,7 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now) tt_int_op(rs->or_port,OP_EQ, 443); tt_int_op(rs->dir_port,OP_EQ, 8000); /* no flags except "running" (16) and "v2dir" (64) and "valid" (128) */ - tt_u64_op(vrs->flags, OP_EQ, U64_LITERAL(0xd0)); + tt_u64_op(vrs->flags, OP_EQ, UINT64_C(0xd0)); } else if (tor_memeq(rs->identity_digest, "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5" "\x5\x5\x5\x5", @@ -1975,10 +2393,10 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now) tt_int_op(rs->ipv6_orport,OP_EQ, 4711); if (voter == 1) { /* all except "authority" (1) */ - tt_u64_op(vrs->flags, OP_EQ, U64_LITERAL(254)); + tt_u64_op(vrs->flags, OP_EQ, UINT64_C(254)); } else { /* 1023 - authority(1) - madeofcheese(16) - madeoftin(32) */ - tt_u64_op(vrs->flags, OP_EQ, U64_LITERAL(974)); + tt_u64_op(vrs->flags, OP_EQ, UINT64_C(974)); } } else if (tor_memeq(rs->identity_digest, "\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33" @@ -2398,7 +2816,7 @@ test_a_networkstatus( sign_skey_2 = crypto_pk_new(); sign_skey_3 = crypto_pk_new(); sign_skey_leg1 = pk_generate(4); - dirvote_recalculate_timing(get_options(), now); + voting_schedule_recalculate_timing(get_options(), now); sr_state_init(0, 0); tt_assert(!crypto_pk_read_private_key_from_string(sign_skey_1, @@ -2788,8 +3206,8 @@ test_dir_scale_bw(void *testdata) for (i=0; i<8; ++i) { total += vals_u64[i]; } - tt_assert(total >= (U64_LITERAL(1)<<60)); - tt_assert(total <= (U64_LITERAL(1)<<62)); + tt_assert(total >= (UINT64_C(1)<<60)); + tt_assert(total <= (UINT64_C(1)<<62)); for (i=0; i<8; ++i) { /* vals[2].u64 is the scaled value of 1.0 */ @@ -2936,8 +3354,9 @@ gen_routerstatus_for_umbw(int idx, time_t now) rs->addr = 0x99008801; rs->or_port = 443; rs->dir_port = 8000; - /* all flags but running cleared */ + /* all flags but running and valid cleared */ rs->is_flagged_running = 1; + rs->is_valid = 1; /* * This one has measured bandwidth below the clip cutoff, and * so shouldn't be clipped; we'll have to test that it isn't @@ -3010,8 +3429,9 @@ gen_routerstatus_for_umbw(int idx, time_t now) rs->addr = 0xC0000203; rs->or_port = 500; rs->dir_port = 1999; - /* all flags but running cleared */ + /* all flags but running and valid cleared */ rs->is_flagged_running = 1; + rs->is_valid = 1; /* * This one has unmeasured bandwidth below the clip cutoff, and * so shouldn't be clipped; we'll have to test that it isn't @@ -3033,7 +3453,7 @@ gen_routerstatus_for_umbw(int idx, time_t now) if (vrs) { vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t)); tor_asprintf(&vrs->microdesc->microdesc_hash_line, - "m 9,10,11,12,13,14,15,16,17 " + "m 25,26,27,28 " "sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa%d\n", idx); } @@ -3059,7 +3479,7 @@ vote_tweaks_for_umbw(networkstatus_t *v, int voter, time_t now) smartlist_clear(v->supported_methods); /* Method 17 is MIN_METHOD_TO_CLIP_UNMEASURED_BW_KB */ smartlist_split_string(v->supported_methods, - "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17", + "25 26 27 28", NULL, 0, -1); /* If we're using a non-default clip bandwidth, add it to net_params */ if (alternate_clip_bw > 0) { @@ -3221,9 +3641,9 @@ test_routerstatus_for_umbw(routerstatus_t *rs, time_t now) tt_assert(!rs->is_fast); tt_assert(!rs->is_possible_guard); tt_assert(!rs->is_stable); - /* (If it wasn't running it wouldn't be here) */ + /* (If it wasn't running and valid it wouldn't be here) */ tt_assert(rs->is_flagged_running); - tt_assert(!rs->is_valid); + tt_assert(rs->is_valid); tt_assert(!rs->is_named); /* This one should have measured bandwidth below the clip cutoff */ tt_assert(rs->has_bandwidth); @@ -4082,34 +4502,19 @@ test_dir_download_status_increment(void *arg) DL_WANT_ANY_DIRSERVER, DL_SCHED_INCREMENT_ATTEMPT, 0, 0 }; - int no_delay = 0; - int delay0 = -1; - int delay1 = -1; - int delay2 = -1; - smartlist_t *schedule = smartlist_new(); - smartlist_t *schedule_no_initial_delay = smartlist_new(); or_options_t test_options; time_t current_time = time(NULL); - /* Provide some values for the schedules */ - delay0 = 10; - delay1 = 99; - delay2 = 20; - - /* Make the schedules */ - smartlist_add(schedule, (void *)&delay0); - smartlist_add(schedule, (void *)&delay1); - smartlist_add(schedule, (void *)&delay2); - - smartlist_add(schedule_no_initial_delay, (void *)&no_delay); - smartlist_add(schedule_no_initial_delay, (void *)&delay1); - smartlist_add(schedule_no_initial_delay, (void *)&delay2); + const int delay0 = 10; + const int no_delay = 0; + const int schedule = 10; + const int schedule_no_initial_delay = 0; /* Put it in the options */ mock_options = &test_options; reset_options(mock_options, &mock_get_options_calls); - mock_options->TestingBridgeBootstrapDownloadSchedule = schedule; - mock_options->TestingClientDownloadSchedule = schedule; + mock_options->TestingBridgeBootstrapDownloadInitialDelay = schedule; + mock_options->TestingClientDownloadInitialDelay = schedule; MOCK(get_options, mock_get_options); @@ -4117,13 +4522,13 @@ test_dir_download_status_increment(void *arg) * whether or not it was reset before being used */ /* regression test for 17750: no initial delay */ - mock_options->TestingClientDownloadSchedule = schedule_no_initial_delay; + mock_options->TestingClientDownloadInitialDelay = schedule_no_initial_delay; mock_get_options_calls = 0; /* we really want to test that it's equal to time(NULL) + delay0, but that's * an unrealiable test, because time(NULL) might change. */ /* regression test for 17750: exponential, no initial delay */ - mock_options->TestingClientDownloadSchedule = schedule_no_initial_delay; + mock_options->TestingClientDownloadInitialDelay = schedule_no_initial_delay; mock_get_options_calls = 0; /* we really want to test that it's equal to time(NULL) + delay0, but that's * an unrealiable test, because time(NULL) might change. */ @@ -4136,7 +4541,7 @@ test_dir_download_status_increment(void *arg) tt_int_op(mock_get_options_calls, OP_GE, 1); /* regression test for 17750: exponential, initial delay */ - mock_options->TestingClientDownloadSchedule = schedule; + mock_options->TestingClientDownloadInitialDelay = schedule; mock_get_options_calls = 0; /* we really want to test that it's equal to time(NULL) + delay0, but that's * an unrealiable test, because time(NULL) might change. */ @@ -4149,9 +4554,6 @@ test_dir_download_status_increment(void *arg) tt_int_op(mock_get_options_calls, OP_GE, 1); done: - /* the pointers in schedule are allocated on the stack */ - smartlist_free(schedule); - smartlist_free(schedule_no_initial_delay); UNMOCK(get_options); mock_options = NULL; mock_get_options_calls = 0; @@ -5469,7 +5871,7 @@ mock_num_bridges_usable(int use_maybe_reachable) * fallbacks. */ static void -test_dir_find_dl_schedule(void* data) +test_dir_find_dl_min_delay(void* data) { const char *str = (const char *)data; @@ -5502,44 +5904,45 @@ test_dir_find_dl_schedule(void* data) mock_num_bridges_usable); download_status_t dls; - smartlist_t server, client, server_cons, client_cons; - smartlist_t client_boot_auth_only_cons, client_boot_auth_cons; - smartlist_t client_boot_fallback_cons, bridge, bridge_bootstrap; + + const int server=10, client=20, server_cons=30, client_cons=40; + const int client_boot_auth_only_cons=50, client_boot_auth_cons=60; + const int client_boot_fallback_cons=70, bridge=80, bridge_bootstrap=90; mock_options = tor_malloc(sizeof(or_options_t)); reset_options(mock_options, &mock_get_options_calls); MOCK(get_options, mock_get_options); - mock_options->TestingServerDownloadSchedule = &server; - mock_options->TestingClientDownloadSchedule = &client; - mock_options->TestingServerConsensusDownloadSchedule = &server_cons; - mock_options->TestingClientConsensusDownloadSchedule = &client_cons; - mock_options->ClientBootstrapConsensusAuthorityOnlyDownloadSchedule = - &client_boot_auth_only_cons; - mock_options->ClientBootstrapConsensusAuthorityDownloadSchedule = - &client_boot_auth_cons; - mock_options->ClientBootstrapConsensusFallbackDownloadSchedule = - &client_boot_fallback_cons; - mock_options->TestingBridgeDownloadSchedule = &bridge; - mock_options->TestingBridgeBootstrapDownloadSchedule = &bridge_bootstrap; + mock_options->TestingServerDownloadInitialDelay = server; + mock_options->TestingClientDownloadInitialDelay = client; + mock_options->TestingServerConsensusDownloadInitialDelay = server_cons; + mock_options->TestingClientConsensusDownloadInitialDelay = client_cons; + mock_options->ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay = + client_boot_auth_only_cons; + mock_options->ClientBootstrapConsensusAuthorityDownloadInitialDelay = + client_boot_auth_cons; + mock_options->ClientBootstrapConsensusFallbackDownloadInitialDelay = + client_boot_fallback_cons; + mock_options->TestingBridgeDownloadInitialDelay = bridge; + mock_options->TestingBridgeBootstrapDownloadInitialDelay = bridge_bootstrap; dls.schedule = DL_SCHED_GENERIC; /* client */ mock_options->ClientOnly = 1; - tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &client); + tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, client); mock_options->ClientOnly = 0; /* dir mode */ mock_options->DirPort_set = 1; mock_options->DirCache = 1; - tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &server); + tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, server); mock_options->DirPort_set = 0; mock_options->DirCache = 0; dls.schedule = DL_SCHED_CONSENSUS; /* public server mode */ mock_options->ORPort_set = 1; - tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &server_cons); + tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, server_cons); mock_options->ORPort_set = 0; /* client and bridge modes */ @@ -5548,30 +5951,30 @@ test_dir_find_dl_schedule(void* data) dls.want_authority = 1; /* client */ mock_options->ClientOnly = 1; - tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, - &client_boot_auth_cons); + tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, + client_boot_auth_cons); mock_options->ClientOnly = 0; /* bridge relay */ mock_options->ORPort_set = 1; mock_options->BridgeRelay = 1; - tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, - &client_boot_auth_cons); + tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, + client_boot_auth_cons); mock_options->ORPort_set = 0; mock_options->BridgeRelay = 0; dls.want_authority = 0; /* client */ mock_options->ClientOnly = 1; - tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, - &client_boot_fallback_cons); + tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, + client_boot_fallback_cons); mock_options->ClientOnly = 0; /* bridge relay */ mock_options->ORPort_set = 1; mock_options->BridgeRelay = 1; - tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, - &client_boot_fallback_cons); + tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, + client_boot_fallback_cons); mock_options->ORPort_set = 0; mock_options->BridgeRelay = 0; @@ -5579,30 +5982,30 @@ test_dir_find_dl_schedule(void* data) /* dls.want_authority is ignored */ /* client */ mock_options->ClientOnly = 1; - tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, - &client_boot_auth_only_cons); + tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, + client_boot_auth_only_cons); mock_options->ClientOnly = 0; /* bridge relay */ mock_options->ORPort_set = 1; mock_options->BridgeRelay = 1; - tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, - &client_boot_auth_only_cons); + tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, + client_boot_auth_only_cons); mock_options->ORPort_set = 0; mock_options->BridgeRelay = 0; } } else { /* client */ mock_options->ClientOnly = 1; - tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, - &client_cons); + tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, + client_cons); mock_options->ClientOnly = 0; /* bridge relay */ mock_options->ORPort_set = 1; mock_options->BridgeRelay = 1; - tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, - &client_cons); + tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, + client_cons); mock_options->ORPort_set = 0; mock_options->BridgeRelay = 0; } @@ -5612,9 +6015,9 @@ test_dir_find_dl_schedule(void* data) mock_options->ClientOnly = 1; mock_options->UseBridges = 1; if (num_bridges_usable(0) > 0) { - tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &bridge); + tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, bridge); } else { - tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &bridge_bootstrap); + tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, bridge_bootstrap); } done: @@ -5634,9 +6037,8 @@ test_dir_assumed_flags(void *arg) memarea_t *area = memarea_new(); routerstatus_t *rs = NULL; - /* First, we should always assume that the Running flag is set, even - * when it isn't listed, since the consensus method is always - * higher than 4. */ + /* We can assume that consensus method is higher than 24, so Running and + * Valid are always implicitly set */ const char *str1 = "r example hereiswhereyouridentitygoes 2015-08-30 12:00:00 " "192.168.0.1 9001 0\n" @@ -5645,17 +6047,6 @@ test_dir_assumed_flags(void *arg) const char *cp = str1; rs = routerstatus_parse_entry_from_string(area, &cp, tokens, NULL, NULL, - 23, FLAV_MICRODESC); - tt_assert(rs); - tt_assert(rs->is_flagged_running); - tt_assert(! rs->is_valid); - tt_assert(! rs->is_exit); - tt_assert(rs->is_fast); - routerstatus_free(rs); - - /* With method 24 or later, we can assume "valid" is set. */ - cp = str1; - rs = routerstatus_parse_entry_from_string(area, &cp, tokens, NULL, NULL, 24, FLAV_MICRODESC); tt_assert(rs); tt_assert(rs->is_flagged_running); @@ -5788,22 +6179,10 @@ test_dir_networkstatus_consensus_has_ipv6(void *arg) /* Test the bounds for A lines in the NS consensus */ mock_options->UseMicrodescriptors = 0; - mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES; + mock_networkstatus->consensus_method = MIN_SUPPORTED_CONSENSUS_METHOD; has_ipv6 = networkstatus_consensus_has_ipv6(get_options()); tt_assert(has_ipv6); - mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES + 1; - has_ipv6 = networkstatus_consensus_has_ipv6(get_options()); - tt_assert(has_ipv6); - - mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES + 20; - has_ipv6 = networkstatus_consensus_has_ipv6(get_options()); - tt_assert(has_ipv6); - - mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES - 1; - has_ipv6 = networkstatus_consensus_has_ipv6(get_options()); - tt_assert(!has_ipv6); - /* Test the bounds for A lines in the microdesc consensus */ mock_options->UseMicrodescriptors = 1; @@ -5812,6 +6191,10 @@ test_dir_networkstatus_consensus_has_ipv6(void *arg) has_ipv6 = networkstatus_consensus_has_ipv6(get_options()); tt_assert(has_ipv6); + mock_networkstatus->consensus_method = MAX_SUPPORTED_CONSENSUS_METHOD + 20; + has_ipv6 = networkstatus_consensus_has_ipv6(get_options()); + tt_assert(has_ipv6); + mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS + 1; has_ipv6 = networkstatus_consensus_has_ipv6(get_options()); @@ -5926,9 +6309,10 @@ struct testcase_t dir_tests[] = { DIR_LEGACY(versions), DIR_LEGACY(fp_pairs), DIR(split_fps, 0), - DIR_LEGACY(dirserv_read_measured_bandwidths), DIR_LEGACY(measured_bw_kb), + DIR_LEGACY(measured_bw_kb_line_is_after_headers), DIR_LEGACY(measured_bw_kb_cache), + DIR_LEGACY(dirserv_read_measured_bandwidths), DIR_LEGACY(param_voting), DIR(param_voting_lookup, 0), DIR_LEGACY(v3_networkstatus), @@ -5960,14 +6344,14 @@ struct testcase_t dir_tests[] = { DIR(dump_unparseable_descriptors, 0), DIR(populate_dump_desc_fifo, 0), DIR(populate_dump_desc_fifo_2, 0), - DIR_ARG(find_dl_schedule, TT_FORK, "bfd"), - DIR_ARG(find_dl_schedule, TT_FORK, "bad"), - DIR_ARG(find_dl_schedule, TT_FORK, "cfd"), - DIR_ARG(find_dl_schedule, TT_FORK, "cad"), - DIR_ARG(find_dl_schedule, TT_FORK, "bfr"), - DIR_ARG(find_dl_schedule, TT_FORK, "bar"), - DIR_ARG(find_dl_schedule, TT_FORK, "cfr"), - DIR_ARG(find_dl_schedule, TT_FORK, "car"), + DIR_ARG(find_dl_min_delay, TT_FORK, "bfd"), + DIR_ARG(find_dl_min_delay, TT_FORK, "bad"), + DIR_ARG(find_dl_min_delay, TT_FORK, "cfd"), + DIR_ARG(find_dl_min_delay, TT_FORK, "cad"), + DIR_ARG(find_dl_min_delay, TT_FORK, "bfr"), + DIR_ARG(find_dl_min_delay, TT_FORK, "bar"), + DIR_ARG(find_dl_min_delay, TT_FORK, "cfr"), + DIR_ARG(find_dl_min_delay, TT_FORK, "car"), DIR(assumed_flags, 0), DIR(networkstatus_compute_bw_weights_v10, 0), DIR(platform_str, 0), diff --git a/src/test/test_dir_common.c b/src/test/test_dir_common.c index fdf43533a8..86d2838944 100644 --- a/src/test/test_dir_common.c +++ b/src/test/test_dir_common.c @@ -1,18 +1,26 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" #define DIRVOTE_PRIVATE -#include "crypto.h" -#include "test.h" -#include "container.h" -#include "or.h" -#include "dirvote.h" -#include "nodelist.h" -#include "routerlist.h" -#include "test_dir_common.h" +#include "test/test.h" +#include "core/or/or.h" +#include "feature/dirauth/dirvote.h" +#include "feature/nodelist/nodelist.h" +#include "feature/nodelist/routerlist.h" +#include "feature/dirparse/authcert_parse.h" +#include "feature/dirparse/ns_parse.h" +#include "test/test_dir_common.h" +#include "feature/dircommon/voting_schedule.h" + +#include "feature/nodelist/authority_cert_st.h" +#include "feature/nodelist/networkstatus_st.h" +#include "feature/nodelist/networkstatus_voter_info_st.h" +#include "feature/nodelist/routerinfo_st.h" +#include "feature/dirauth/vote_microdesc_hash_st.h" +#include "feature/nodelist/vote_routerstatus_st.h" void dir_common_setup_vote(networkstatus_t **vote, time_t now); networkstatus_t * dir_common_add_rs_and_parse(networkstatus_t *vote, diff --git a/src/test/test_dir_common.h b/src/test/test_dir_common.h index 65b9cf6436..1e958a21ff 100644 --- a/src/test/test_dir_common.h +++ b/src/test/test_dir_common.h @@ -1,11 +1,10 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "or.h" -#include "networkstatus.h" -#include "routerparse.h" +#include "core/or/or.h" +#include "feature/nodelist/networkstatus.h" #define TEST_DIR_ROUTER_ID_1 3 #define TEST_DIR_ROUTER_ID_2 5 diff --git a/src/test/test_dir_handle_get.c b/src/test/test_dir_handle_get.c index ca64dce5fe..1d4a36d7fc 100644 --- a/src/test/test_dir_handle_get.c +++ b/src/test/test_dir_handle_get.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define RENDCOMMON_PRIVATE @@ -8,31 +8,43 @@ #define CONNECTION_PRIVATE #define CONFIG_PRIVATE #define RENDCACHE_PRIVATE - -#include "or.h" -#include "config.h" -#include "connection.h" -#include "consdiffmgr.h" -#include "directory.h" -#include "test.h" -#include "compress.h" -#include "connection.h" -#include "rendcommon.h" -#include "rendcache.h" -#include "router.h" -#include "routerlist.h" -#include "rend_test_helpers.h" -#include "microdesc.h" -#include "test_helpers.h" -#include "nodelist.h" -#include "entrynodes.h" -#include "routerparse.h" -#include "networkstatus.h" -#include "proto_http.h" -#include "geoip.h" -#include "dirserv.h" -#include "dirvote.h" -#include "log_test_helpers.h" +#define DIRCACHE_PRIVATE + +#include "core/or/or.h" +#include "app/config/config.h" +#include "core/mainloop/connection.h" +#include "feature/dircache/consdiffmgr.h" +#include "feature/dircommon/directory.h" +#include "feature/dircache/dircache.h" +#include "test/test.h" +#include "lib/compress/compress.h" +#include "feature/rend/rendcommon.h" +#include "feature/rend/rendcache.h" +#include "feature/relay/router.h" +#include "feature/nodelist/authcert.h" +#include "feature/nodelist/dirlist.h" +#include "feature/nodelist/routerlist.h" +#include "test/rend_test_helpers.h" +#include "feature/nodelist/microdesc.h" +#include "test/test_helpers.h" +#include "feature/nodelist/nodelist.h" +#include "feature/client/entrynodes.h" +#include "feature/dirparse/authcert_parse.h" +#include "feature/nodelist/networkstatus.h" +#include "core/proto/proto_http.h" +#include "lib/geoip/geoip.h" +#include "feature/stats/geoip_stats.h" +#include "feature/dircache/dirserv.h" +#include "feature/dirauth/dirvote.h" +#include "test/log_test_helpers.h" +#include "feature/dircommon/voting_schedule.h" + +#include "feature/dircommon/dir_connection_st.h" +#include "feature/dirclient/dir_server_st.h" +#include "feature/nodelist/networkstatus_st.h" +#include "feature/rend/rend_encoded_v2_service_descriptor_st.h" +#include "feature/nodelist/routerinfo_st.h" +#include "feature/nodelist/routerlist_st.h" #ifdef _WIN32 /* For mkdir() */ @@ -2057,7 +2069,7 @@ test_dir_handle_get_status_vote_d(void* data) mock_options->TestingV3AuthInitialDistDelay = 1; time_t now = 1441223455 -1; - dirvote_recalculate_timing(mock_options, now); + voting_schedule_recalculate_timing(mock_options, now); const char *msg_out = NULL; int status_out = 0; @@ -2095,6 +2107,7 @@ test_dir_handle_get_status_vote_d(void* data) clear_dir_servers(); dirvote_free_all(); + routerlist_free_all(); } static void @@ -2403,7 +2416,7 @@ test_dir_handle_get_status_vote_next_authority(void* data) mock_options->TestingV3AuthInitialDistDelay = 1; time_t now = 1441223455 -1; - dirvote_recalculate_timing(mock_options, now); + voting_schedule_recalculate_timing(mock_options, now); struct pending_vote_t *vote = dirvote_add_vote(VOTE_BODY_V3, &msg_out, &status_out); @@ -2482,7 +2495,7 @@ test_dir_handle_get_status_vote_current_authority(void* data) mock_options->TestingV3AuthInitialDistDelay = 1; time_t now = 1441223455; - dirvote_recalculate_timing(mock_options, now-1); + voting_schedule_recalculate_timing(mock_options, now-1); struct pending_vote_t *vote = dirvote_add_vote(VOTE_BODY_V3, &msg_out, &status_out); @@ -2631,4 +2644,3 @@ struct testcase_t dir_handle_get_tests[] = { DIR_HANDLE_CMD(parse_accept_encoding, 0), END_OF_TESTCASES }; - diff --git a/src/test/test_dns.c b/src/test/test_dns.c index 1fee01d2c0..8369f844f6 100644 --- a/src/test/test_dns.c +++ b/src/test/test_dns.c @@ -1,14 +1,18 @@ -/* Copyright (c) 2015-2017, The Tor Project, Inc. */ +/* Copyright (c) 2015-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "or.h" -#include "test.h" +#include "core/or/or.h" +#include "test/test.h" #define DNS_PRIVATE -#include "dns.h" -#include "connection.h" -#include "router.h" +#include "feature/relay/dns.h" +#include "core/mainloop/connection.h" +#include "core/or/connection_edge.h" +#include "feature/relay/router.h" + +#include "core/or/edge_connection_st.h" +#include "core/or/or_circuit_st.h" #define NS_MODULE dns @@ -745,4 +749,3 @@ struct testcase_t dns_tests[] = { }; #undef NS_MODULE - diff --git a/src/test/test_dos.c b/src/test/test_dos.c index cb9d9e559c..40a4c6ba29 100644 --- a/src/test/test_dos.c +++ b/src/test/test_dos.c @@ -5,17 +5,23 @@ #define TOR_CHANNEL_INTERNAL_ #define CIRCUITLIST_PRIVATE -#include "or.h" -#include "dos.h" -#include "circuitlist.h" -#include "geoip.h" -#include "channel.h" -#include "microdesc.h" -#include "networkstatus.h" -#include "nodelist.h" -#include "routerlist.h" -#include "test.h" -#include "log_test_helpers.h" +#include "core/or/or.h" +#include "core/or/dos.h" +#include "core/or/circuitlist.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "feature/stats/geoip_stats.h" +#include "core/or/channel.h" +#include "feature/nodelist/microdesc.h" +#include "feature/nodelist/networkstatus.h" +#include "feature/nodelist/nodelist.h" +#include "feature/nodelist/routerlist.h" + +#include "feature/nodelist/networkstatus_st.h" +#include "core/or/or_connection_st.h" +#include "feature/nodelist/routerstatus_st.h" + +#include "test/test.h" +#include "test/log_test_helpers.h" static networkstatus_t *dummy_ns = NULL; static networkstatus_t * @@ -494,4 +500,3 @@ struct testcase_t dos_tests[] = { NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_entryconn.c b/src/test/test_entryconn.c index 9d8a072c77..bec70090e6 100644 --- a/src/test/test_entryconn.c +++ b/src/test/test_entryconn.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" @@ -6,18 +6,23 @@ #define CONNECTION_PRIVATE #define CONNECTION_EDGE_PRIVATE -#include "or.h" -#include "test.h" +#include "core/or/or.h" +#include "test/test.h" -#include "addressmap.h" -#include "config.h" -#include "confparse.h" -#include "connection.h" -#include "connection_edge.h" -#include "nodelist.h" +#include "feature/client/addressmap.h" +#include "app/config/config.h" +#include "app/config/confparse.h" +#include "core/mainloop/connection.h" +#include "core/or/connection_edge.h" +#include "feature/nodelist/nodelist.h" -#include "hs_cache.h" -#include "rendcache.h" +#include "feature/hs/hs_cache.h" +#include "feature/rend/rendcache.h" + +#include "core/or/entry_connection_st.h" +#include "core/or/socks_request_st.h" + +#include "lib/encoding/confline.h" static void * entryconn_rewrite_setup(const struct testcase_t *tc) @@ -830,4 +835,3 @@ struct testcase_t entryconn_tests[] = { END_OF_TESTCASES }; - diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c index 505e09e36f..b67c9fae53 100644 --- a/src/test/test_entrynodes.c +++ b/src/test/test_entrynodes.c @@ -1,34 +1,50 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" #define CIRCUITLIST_PRIVATE +#define CIRCUITBUILD_PRIVATE #define STATEFILE_PRIVATE #define ENTRYNODES_PRIVATE #define ROUTERLIST_PRIVATE -#define DIRECTORY_PRIVATE - -#include "or.h" -#include "test.h" - -#include "bridges.h" -#include "circuitlist.h" -#include "config.h" -#include "confparse.h" -#include "directory.h" -#include "entrynodes.h" -#include "nodelist.h" -#include "networkstatus.h" -#include "policies.h" -#include "routerlist.h" -#include "routerparse.h" -#include "routerset.h" -#include "statefile.h" -#include "util.h" - -#include "test_helpers.h" -#include "log_test_helpers.h" +#define DIRCLIENT_PRIVATE + +#include "core/or/or.h" +#include "test/test.h" + +#include "feature/client/bridges.h" +#include "core/or/circuitlist.h" +#include "core/or/circuitbuild.h" +#include "app/config/config.h" +#include "app/config/confparse.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "feature/dircommon/directory.h" +#include "feature/dirclient/dirclient.h" +#include "feature/client/entrynodes.h" +#include "feature/nodelist/nodelist.h" +#include "feature/nodelist/networkstatus.h" +#include "core/or/policies.h" +#include "feature/nodelist/routerlist.h" +#include "feature/nodelist/routerset.h" +#include "app/config/statefile.h" + +#include "core/or/cpath_build_state_st.h" +#include "core/or/crypt_path_st.h" +#include "feature/dircommon/dir_connection_st.h" +#include "feature/nodelist/microdesc_st.h" +#include "feature/nodelist/networkstatus_st.h" +#include "feature/nodelist/node_st.h" +#include "core/or/origin_circuit_st.h" +#include "app/config/or_state_st.h" +#include "feature/nodelist/routerinfo_st.h" +#include "feature/nodelist/routerstatus_st.h" + +#include "test/test_helpers.h" +#include "test/log_test_helpers.h" + +#include "lib/container/bloomfilt.h" +#include "lib/encoding/confline.h" /* TODO: * choose_random_entry() test with state set. @@ -74,6 +90,17 @@ bfn_mock_node_get_by_id(const char *id) return NULL; } +/* Helper function to free a test node. */ +static void +test_node_free(node_t *n) +{ + tor_free(n->rs); + tor_free(n->md->onion_curve25519_pkey); + short_policy_free(n->md->exit_policy); + tor_free(n->md); + tor_free(n); +} + /* Unittest cleanup function: Cleanup the fake network. */ static int big_fake_network_cleanup(const struct testcase_t *testcase, void *ptr) @@ -83,9 +110,7 @@ big_fake_network_cleanup(const struct testcase_t *testcase, void *ptr) if (big_fake_net_nodes) { SMARTLIST_FOREACH(big_fake_net_nodes, node_t *, n, { - tor_free(n->rs); - tor_free(n->md); - tor_free(n); + test_node_free(n); }); smartlist_free(big_fake_net_nodes); } @@ -113,9 +138,18 @@ big_fake_network_setup(const struct testcase_t *testcase) big_fake_net_nodes = smartlist_new(); for (i = 0; i < N_NODES; ++i) { + curve25519_secret_key_t curve25519_secret_key; + node_t *n = tor_malloc_zero(sizeof(node_t)); n->md = tor_malloc_zero(sizeof(microdesc_t)); + /* Generate curve25519 key for this node */ + n->md->onion_curve25519_pkey = + tor_malloc_zero(sizeof(curve25519_public_key_t)); + curve25519_secret_key_generate(&curve25519_secret_key, 0); + curve25519_public_key_generate(n->md->onion_curve25519_pkey, + &curve25519_secret_key); + crypto_rand(n->identity, sizeof(n->identity)); n->rs = tor_malloc_zero(sizeof(routerstatus_t)); @@ -135,8 +169,8 @@ big_fake_network_setup(const struct testcase_t *testcase) { char nickname_binary[8]; crypto_rand(nickname_binary, sizeof(nickname_binary)); - base64_encode(n->rs->nickname, sizeof(n->rs->nickname), - nickname_binary, sizeof(nickname_binary), 0); + base32_encode(n->rs->nickname, sizeof(n->rs->nickname), + nickname_binary, sizeof(nickname_binary)); } /* Call half of the nodes a possible guard. */ @@ -144,6 +178,12 @@ big_fake_network_setup(const struct testcase_t *testcase) n->is_possible_guard = 1; n->rs->guardfraction_percentage = 100; n->rs->has_guardfraction = 1; + n->rs->is_possible_guard = 1; + } + + /* Make some of these nodes a possible exit */ + if (i % 7 == 0) { + n->md->exit_policy = parse_short_policy("accept 443"); } smartlist_add(big_fake_net_nodes, n); @@ -1075,9 +1115,7 @@ test_entry_guard_expand_sample_small_net(void *arg) /* Fun corner case: not enough guards to make up our whole sample size. */ SMARTLIST_FOREACH(big_fake_net_nodes, node_t *, n, { if (n_sl_idx >= 15) { - tor_free(n->rs); - tor_free(n->md); - tor_free(n); + test_node_free(n); SMARTLIST_DEL_CURRENT(big_fake_net_nodes, n); } else { n->rs->addr = 0; // make the filter reject this. @@ -1174,9 +1212,7 @@ test_entry_guard_update_from_consensus_status(void *arg) node_t *n = (node_t*) bfn_mock_node_get_by_id(g->identity); tt_assert(n); smartlist_remove(big_fake_net_nodes, n); - tor_free(n->rs); - tor_free(n->md); - tor_free(n); + test_node_free(n); } update_approx_time(start + 300); sampled_guards_update_from_consensus(gs); @@ -2685,6 +2721,23 @@ test_enty_guard_should_expire_waiting(void *arg) tor_free(fake_state); } +/** Test that the number of primary guards can be controlled using torrc */ +static void +test_entry_guard_number_of_primaries(void *arg) +{ + (void) arg; + + /* Get default value */ + tt_int_op(get_n_primary_guards(), OP_EQ, DFLT_N_PRIMARY_GUARDS); + + /* Set number of primaries using torrc */ + get_options_mutable()->NumPrimaryGuards = 42; + tt_int_op(get_n_primary_guards(), OP_EQ, 42); + + done: + ; +} + static void mock_directory_initiate_request(directory_request_t *req) { @@ -2793,6 +2846,161 @@ test_entry_guard_outdated_dirserver_exclusion(void *arg) } } +/** Test helper to extend the <b>oc</b> circuit path <b>n</b> times and then + * ensure that the circuit is now complete. */ +static void +helper_extend_circuit_path_n_times(origin_circuit_t *oc, int n) +{ + int retval; + int i; + + /* Extend path n times */ + for (i = 0 ; i < n ; i++) { + retval = onion_extend_cpath(oc); + tt_int_op(retval, OP_EQ, 0); + tt_int_op(circuit_get_cpath_len(oc), OP_EQ, i+1); + } + + /* Now do it one last time and see that circ is complete */ + retval = onion_extend_cpath(oc); + tt_int_op(retval, OP_EQ, 1); + + done: + ; +} + +/** Test for basic Tor path selection. Makes sure we build 3-hop circuits. */ +static void +test_entry_guard_basic_path_selection(void *arg) +{ + (void) arg; + + int retval; + + /* Enable entry guards */ + or_options_t *options = get_options_mutable(); + options->UseEntryGuards = 1; + + /* disables /16 check since all nodes have the same addr... */ + options->EnforceDistinctSubnets = 0; + + /* Create our circuit */ + circuit_t *circ = dummy_origin_circuit_new(30); + origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ); + oc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); + + /* First pick the exit and pin it on the build_state */ + retval = onion_pick_cpath_exit(oc, NULL, 0); + tt_int_op(retval, OP_EQ, 0); + + /* Extend path 3 times. First we pick guard, then middle, then exit. */ + helper_extend_circuit_path_n_times(oc, 3); + + done: + circuit_free_(circ); +} + +/** Test helper to build an L2 and L3 vanguard list. The vanguard lists + * produced should be completely disjoint. */ +static void +helper_setup_vanguard_list(or_options_t *options) +{ + int i = 0; + + /* Add some nodes to the vanguard L2 list */ + options->HSLayer2Nodes = routerset_new(); + for (i = 0; i < 10 ; i += 2) { + node_t *vanguard_node = smartlist_get(big_fake_net_nodes, i); + tt_assert(vanguard_node->is_possible_guard); + routerset_parse(options->HSLayer2Nodes, vanguard_node->rs->nickname, "l2"); + } + /* also add some nodes to vanguard L3 list + * (L2 list and L3 list should be disjoint for this test to work) */ + options->HSLayer3Nodes = routerset_new(); + for (i = 10; i < 20 ; i += 2) { + node_t *vanguard_node = smartlist_get(big_fake_net_nodes, i); + tt_assert(vanguard_node->is_possible_guard); + routerset_parse(options->HSLayer3Nodes, vanguard_node->rs->nickname, "l3"); + } + + done: + ; +} + +/** Test to ensure that vanguard path selection works properly. Ensures that + * default vanguard circuits are 4 hops, and that path selection works + * correctly given the vanguard settings. */ +static void +test_entry_guard_vanguard_path_selection(void *arg) +{ + (void) arg; + + int retval; + + /* Enable entry guards */ + or_options_t *options = get_options_mutable(); + options->UseEntryGuards = 1; + + /* XXX disables /16 check */ + options->EnforceDistinctSubnets = 0; + + /* Setup our vanguard list */ + helper_setup_vanguard_list(options); + + /* Create our circuit */ + circuit_t *circ = dummy_origin_circuit_new(30); + origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ); + oc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); + oc->build_state->is_internal = 1; + + /* Switch circuit purpose to vanguards */ + circ->purpose = CIRCUIT_PURPOSE_HS_VANGUARDS; + + /* First pick the exit and pin it on the build_state */ + tt_int_op(oc->build_state->desired_path_len, OP_EQ, 0); + retval = onion_pick_cpath_exit(oc, NULL, 0); + tt_int_op(retval, OP_EQ, 0); + + /* Ensure that vanguards make 4-hop circuits by default */ + tt_int_op(oc->build_state->desired_path_len, OP_EQ, 4); + + /* Extend path as many times as needed to have complete circ. */ + helper_extend_circuit_path_n_times(oc, oc->build_state->desired_path_len); + + /* Test that the cpath linked list is set correctly. */ + crypt_path_t *l1_node = oc->cpath; + crypt_path_t *l2_node = l1_node->next; + crypt_path_t *l3_node = l2_node->next; + crypt_path_t *l4_node = l3_node->next; + crypt_path_t *l1_node_again = l4_node->next; + tt_ptr_op(l1_node, OP_EQ, l1_node_again); + + /* Test that L2 is indeed HSLayer2Node */ + retval = routerset_contains_extendinfo(options->HSLayer2Nodes, + l2_node->extend_info); + tt_int_op(retval, OP_EQ, 4); + /* test that L3 node is _not_ contained in HSLayer2Node */ + retval = routerset_contains_extendinfo(options->HSLayer2Nodes, + l3_node->extend_info); + tt_int_op(retval, OP_LT, 4); + + /* Test that L3 is indeed HSLayer3Node */ + retval = routerset_contains_extendinfo(options->HSLayer3Nodes, + l3_node->extend_info); + tt_int_op(retval, OP_EQ, 4); + /* test that L2 node is _not_ contained in HSLayer3Node */ + retval = routerset_contains_extendinfo(options->HSLayer3Nodes, + l2_node->extend_info); + tt_int_op(retval, OP_LT, 4); + + /* TODO: Test that L1 can be the same as exit. To test this we need start + enforcing EnforceDistinctSubnets again, which means that we need to give + each test node a different address which currently breaks some tests. */ + + done: + circuit_free_(circ); +} + static const struct testcase_setup_t big_fake_network = { big_fake_network_setup, big_fake_network_cleanup }; @@ -2832,6 +3040,8 @@ struct testcase_t entrynodes_tests[] = { test_entry_guard_parse_from_state_broken, TT_FORK, NULL, NULL }, { "get_guard_selection_by_name", test_entry_guard_get_guard_selection_by_name, TT_FORK, NULL, NULL }, + { "number_of_primaries", + test_entry_guard_number_of_primaries, TT_FORK, NULL, NULL }, BFN_TEST(choose_selection_initial), BFN_TEST(add_single_guard), BFN_TEST(node_filter), @@ -2854,6 +3064,8 @@ struct testcase_t entrynodes_tests[] = { BFN_TEST(select_and_cancel), BFN_TEST(drop_guards), BFN_TEST(outdated_dirserver_exclusion), + BFN_TEST(basic_path_selection), + BFN_TEST(vanguard_path_selection), UPGRADE_TEST(upgrade_a_circuit, "c1-done c2-done"), UPGRADE_TEST(upgrade_blocked_by_live_primary_guards, "c1-done c2-done"), @@ -2871,4 +3083,3 @@ struct testcase_t entrynodes_tests[] = { END_OF_TESTCASES }; - diff --git a/src/test/test_extorport.c b/src/test/test_extorport.c index cadef257f1..71be9131c7 100644 --- a/src/test/test_extorport.c +++ b/src/test/test_extorport.c @@ -1,18 +1,27 @@ -/* Copyright (c) 2013-2017, The Tor Project, Inc. */ +/* Copyright (c) 2013-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define CONNECTION_PRIVATE #define EXT_ORPORT_PRIVATE -#define MAIN_PRIVATE -#include "or.h" -#include "buffers.h" -#include "connection.h" -#include "connection_or.h" -#include "config.h" -#include "control.h" -#include "ext_orport.h" -#include "main.h" -#include "test.h" +#define MAINLOOP_PRIVATE +#include "core/or/or.h" +#include "lib/container/buffers.h" +#include "core/mainloop/connection.h" +#include "core/or/connection_or.h" +#include "app/config/config.h" +#include "feature/control/control.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "feature/relay/ext_orport.h" +#include "core/mainloop/mainloop.h" + +#include "core/or/or_connection_st.h" + +#include "test/test.h" +#include "test/test_helpers.h" + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif /* Test connection_or_remove_from_ext_or_id_map and * connection_or_set_ext_or_identifier */ @@ -81,22 +90,6 @@ connection_write_to_buf_impl_replacement(const char *string, size_t len, buf_add(conn->outbuf, string, len); } -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 (buf_get_bytes(buf, out, (unsigned long)*sz_out) != 0) { - tor_free(out); - return NULL; - } - out[*sz_out] = '\0'; /* Hopefully gratuitous. */ - return out; -} - static void test_ext_or_write_command(void *arg) { @@ -455,7 +448,7 @@ test_ext_or_handshake(void *arg) memcpy(ext_or_auth_cookie, "Gliding wrapt in a brown mantle," , 32); ext_or_auth_cookie_is_set = 1; - init_connection_lists(); + tor_init_connection_lists(); conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET); tt_int_op(0, OP_EQ, connection_ext_or_start_auth(conn)); @@ -606,4 +599,3 @@ struct testcase_t extorport_tests[] = { { "handshake", test_ext_or_handshake, TT_FORK, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_geoip.c b/src/test/test_geoip.c new file mode 100644 index 0000000000..6f9c39063b --- /dev/null +++ b/src/test/test_geoip.c @@ -0,0 +1,580 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" + +/* These macros pull in declarations for some functions and structures that + * are typically file-private. */ +#define GEOIP_PRIVATE +#include "core/or/or.h" +#include "app/config/config.h" +#include "lib/geoip/geoip.h" +#include "feature/stats/geoip_stats.h" +#include "test/test.h" + + /* Record odd numbered fake-IPs using ipv6, even numbered fake-IPs + * using ipv4. Since our fake geoip database is the same between + * ipv4 and ipv6, we should get the same result no matter which + * address family we pick for each IP. */ +#define SET_TEST_ADDRESS(i) do { \ + if ((i) & 1) { \ + SET_TEST_IPV6(i); \ + tor_addr_from_in6(&addr, &in6); \ + } else { \ + tor_addr_from_ipv4h(&addr, (uint32_t) i); \ + } \ + } while (0) + + /* Make sure that country ID actually works. */ +#define SET_TEST_IPV6(i) \ + do { \ + set_uint32(in6.s6_addr + 12, htonl((uint32_t) (i))); \ + } while (0) +#define CHECK_COUNTRY(country, val) do { \ + /* test ipv4 country lookup */ \ + tt_str_op(country, OP_EQ, \ + geoip_get_country_name(geoip_get_country_by_ipv4(val))); \ + /* test ipv6 country lookup */ \ + SET_TEST_IPV6(val); \ + tt_str_op(country, OP_EQ, \ + geoip_get_country_name(geoip_get_country_by_ipv6(&in6))); \ + } while (0) + +/** Run unit tests for GeoIP code. */ +static void +test_geoip(void *arg) +{ + int i, j; + time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */ + char *s = NULL, *v = NULL; + const char *bridge_stats_1 = + "bridge-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "bridge-ips zz=24,xy=8\n" + "bridge-ip-versions v4=16,v6=16\n" + "bridge-ip-transports <OR>=24\n", + *dirreq_stats_1 = + "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "dirreq-v3-ips ab=8\n" + "dirreq-v3-reqs ab=8\n" + "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0," + "not-modified=0,busy=0\n" + "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" + "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n", + *dirreq_stats_2 = + "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "dirreq-v3-ips \n" + "dirreq-v3-reqs \n" + "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0," + "not-modified=0,busy=0\n" + "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" + "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n", + *dirreq_stats_3 = + "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "dirreq-v3-ips \n" + "dirreq-v3-reqs \n" + "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0," + "not-modified=0,busy=0\n" + "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" + "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n", + *dirreq_stats_4 = + "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "dirreq-v3-ips \n" + "dirreq-v3-reqs \n" + "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0," + "not-modified=0,busy=0\n" + "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" + "dirreq-v3-tunneled-dl complete=0,timeout=0,running=4\n", + *entry_stats_1 = + "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "entry-ips ab=8\n", + *entry_stats_2 = + "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "entry-ips \n"; + tor_addr_t addr; + struct in6_addr in6; + + /* Populate the DB a bit. Add these in order, since we can't do the final + * 'sort' step. These aren't very good IP addresses, but they're perfectly + * fine uint32_t values. */ + (void)arg; + tt_int_op(0,OP_EQ, geoip_parse_entry("10,50,AB", AF_INET)); + tt_int_op(0,OP_EQ, geoip_parse_entry("52,90,XY", AF_INET)); + tt_int_op(0,OP_EQ, geoip_parse_entry("95,100,AB", AF_INET)); + tt_int_op(0,OP_EQ, geoip_parse_entry("\"105\",\"140\",\"ZZ\"", AF_INET)); + tt_int_op(0,OP_EQ, geoip_parse_entry("\"150\",\"190\",\"XY\"", AF_INET)); + tt_int_op(0,OP_EQ, geoip_parse_entry("\"200\",\"250\",\"AB\"", AF_INET)); + + /* Populate the IPv6 DB equivalently with fake IPs in the same range */ + tt_int_op(0,OP_EQ, geoip_parse_entry("::a,::32,AB", AF_INET6)); + tt_int_op(0,OP_EQ, geoip_parse_entry("::34,::5a,XY", AF_INET6)); + tt_int_op(0,OP_EQ, geoip_parse_entry("::5f,::64,AB", AF_INET6)); + tt_int_op(0,OP_EQ, geoip_parse_entry("::69,::8c,ZZ", AF_INET6)); + tt_int_op(0,OP_EQ, geoip_parse_entry("::96,::be,XY", AF_INET6)); + tt_int_op(0,OP_EQ, geoip_parse_entry("::c8,::fa,AB", AF_INET6)); + + /* We should have 4 countries: ??, ab, xy, zz. */ + tt_int_op(4,OP_EQ, geoip_get_n_countries()); + memset(&in6, 0, sizeof(in6)); + + CHECK_COUNTRY("??", 3); + CHECK_COUNTRY("ab", 32); + CHECK_COUNTRY("??", 5); + CHECK_COUNTRY("??", 51); + CHECK_COUNTRY("xy", 150); + CHECK_COUNTRY("xy", 190); + CHECK_COUNTRY("??", 2000); + + tt_int_op(0,OP_EQ, geoip_get_country_by_ipv4(3)); + SET_TEST_IPV6(3); + tt_int_op(0,OP_EQ, geoip_get_country_by_ipv6(&in6)); + + get_options_mutable()->BridgeRelay = 1; + get_options_mutable()->BridgeRecordUsageByCountry = 1; + /* Put 9 observations in AB... */ + for (i=32; i < 40; ++i) { + SET_TEST_ADDRESS(i); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200); + } + SET_TEST_ADDRESS(225); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200); + /* and 3 observations in XY, several times. */ + for (j=0; j < 10; ++j) + for (i=52; i < 55; ++i) { + SET_TEST_ADDRESS(i); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-3600); + } + /* and 17 observations in ZZ... */ + for (i=110; i < 127; ++i) { + SET_TEST_ADDRESS(i); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now); + } + geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v); + tt_assert(s); + tt_assert(v); + tt_str_op("zz=24,ab=16,xy=8",OP_EQ, s); + tt_str_op("v4=16,v6=16",OP_EQ, v); + tor_free(s); + tor_free(v); + + /* Now clear out all the AB observations. */ + geoip_remove_old_clients(now-6000); + geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v); + tt_assert(s); + tt_assert(v); + tt_str_op("zz=24,xy=8",OP_EQ, s); + tt_str_op("v4=16,v6=16",OP_EQ, v); + tor_free(s); + tor_free(v); + + /* Start testing bridge statistics by making sure that we don't output + * bridge stats without initializing them. */ + s = geoip_format_bridge_stats(now + 86400); + tt_ptr_op(s, OP_EQ, NULL); + + /* Initialize stats and generate the bridge-stats history string out of + * the connecting clients added above. */ + geoip_bridge_stats_init(now); + s = geoip_format_bridge_stats(now + 86400); + tt_assert(s); + tt_str_op(bridge_stats_1,OP_EQ, s); + tor_free(s); + + /* Stop collecting bridge stats and make sure we don't write a history + * string anymore. */ + geoip_bridge_stats_term(); + s = geoip_format_bridge_stats(now + 86400); + tt_ptr_op(s, OP_EQ, NULL); + + /* Stop being a bridge and start being a directory mirror that gathers + * directory request statistics. */ + geoip_bridge_stats_term(); + get_options_mutable()->BridgeRelay = 0; + get_options_mutable()->BridgeRecordUsageByCountry = 0; + get_options_mutable()->DirReqStatistics = 1; + + /* Start testing dirreq statistics by making sure that we don't collect + * dirreq stats without initializing them. */ + SET_TEST_ADDRESS(100); + geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now); + s = geoip_format_dirreq_stats(now + 86400); + tt_ptr_op(s, OP_EQ, NULL); + + /* Initialize stats, note one connecting client, and generate the + * dirreq-stats history string. */ + geoip_dirreq_stats_init(now); + SET_TEST_ADDRESS(100); + geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now); + s = geoip_format_dirreq_stats(now + 86400); + tt_str_op(dirreq_stats_1,OP_EQ, s); + tor_free(s); + + /* Stop collecting stats, add another connecting client, and ensure we + * don't generate a history string. */ + geoip_dirreq_stats_term(); + SET_TEST_ADDRESS(101); + geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now); + s = geoip_format_dirreq_stats(now + 86400); + tt_ptr_op(s, OP_EQ, NULL); + + /* Re-start stats, add a connecting client, reset stats, and make sure + * that we get an all empty history string. */ + geoip_dirreq_stats_init(now); + SET_TEST_ADDRESS(100); + geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now); + geoip_reset_dirreq_stats(now); + s = geoip_format_dirreq_stats(now + 86400); + tt_str_op(dirreq_stats_2,OP_EQ, s); + tor_free(s); + + /* Note a successful network status response and make sure that it + * appears in the history string. */ + geoip_note_ns_response(GEOIP_SUCCESS); + s = geoip_format_dirreq_stats(now + 86400); + tt_str_op(dirreq_stats_3,OP_EQ, s); + tor_free(s); + + /* Start a tunneled directory request. */ + geoip_start_dirreq((uint64_t) 1, 1024, DIRREQ_TUNNELED); + s = geoip_format_dirreq_stats(now + 86400); + tt_str_op(dirreq_stats_4,OP_EQ, s); + tor_free(s); + + /* Stop collecting directory request statistics and start gathering + * entry stats. */ + geoip_dirreq_stats_term(); + get_options_mutable()->DirReqStatistics = 0; + get_options_mutable()->EntryStatistics = 1; + + /* Start testing entry statistics by making sure that we don't collect + * anything without initializing entry stats. */ + SET_TEST_ADDRESS(100); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now); + s = geoip_format_entry_stats(now + 86400); + tt_ptr_op(s, OP_EQ, NULL); + + /* Initialize stats, note one connecting client, and generate the + * entry-stats history string. */ + geoip_entry_stats_init(now); + SET_TEST_ADDRESS(100); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now); + s = geoip_format_entry_stats(now + 86400); + tt_str_op(entry_stats_1,OP_EQ, s); + tor_free(s); + + /* Stop collecting stats, add another connecting client, and ensure we + * don't generate a history string. */ + geoip_entry_stats_term(); + SET_TEST_ADDRESS(101); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now); + s = geoip_format_entry_stats(now + 86400); + tt_ptr_op(s, OP_EQ, NULL); + + /* Re-start stats, add a connecting client, reset stats, and make sure + * that we get an all empty history string. */ + geoip_entry_stats_init(now); + SET_TEST_ADDRESS(100); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now); + geoip_reset_entry_stats(now); + s = geoip_format_entry_stats(now + 86400); + tt_str_op(entry_stats_2,OP_EQ, s); + tor_free(s); + + /* Test the OOM handler. Add a client, run the OOM. */ + geoip_entry_stats_init(now); + SET_TEST_ADDRESS(100); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, + now - (12 * 60 * 60)); + /* We've seen this 12 hours ago. Run the OOM, it should clean the entry + * because it is above the minimum cutoff of 4 hours. */ + size_t bytes_removed = geoip_client_cache_handle_oom(now, 1000); + tt_size_op(bytes_removed, OP_GT, 0); + + /* Do it again but this time with an entry with a lower cutoff. */ + geoip_entry_stats_init(now); + SET_TEST_ADDRESS(100); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, + now - (3 * 60 * 60)); + bytes_removed = geoip_client_cache_handle_oom(now, 1000); + tt_size_op(bytes_removed, OP_EQ, 0); + + /* Stop collecting entry statistics. */ + geoip_entry_stats_term(); + get_options_mutable()->EntryStatistics = 0; + + done: + tor_free(s); + tor_free(v); +} + +static void +test_geoip_with_pt(void *arg) +{ + time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */ + char *s = NULL; + int i; + tor_addr_t addr; + struct in6_addr in6; + + (void)arg; + get_options_mutable()->BridgeRelay = 1; + get_options_mutable()->BridgeRecordUsageByCountry = 1; + + memset(&in6, 0, sizeof(in6)); + + /* No clients seen yet. */ + s = geoip_get_transport_history(); + tor_assert(!s); + + /* 4 connections without a pluggable transport */ + for (i=0; i < 4; ++i) { + SET_TEST_ADDRESS(i); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200); + } + + /* 9 connections with "alpha" */ + for (i=4; i < 13; ++i) { + SET_TEST_ADDRESS(i); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "alpha", now-7200); + } + + /* one connection with "beta" */ + SET_TEST_ADDRESS(13); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "beta", now-7200); + + /* 14 connections with "charlie" */ + for (i=14; i < 28; ++i) { + SET_TEST_ADDRESS(i); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "charlie", now-7200); + } + + /* 131 connections with "ddr" */ + for (i=28; i < 159; ++i) { + SET_TEST_ADDRESS(i); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "ddr", now-7200); + } + + /* 8 connections with "entropy" */ + for (i=159; i < 167; ++i) { + SET_TEST_ADDRESS(i); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "entropy", now-7200); + } + + /* 2 connections from the same IP with two different transports. */ + SET_TEST_ADDRESS(++i); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "fire", now-7200); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "google", now-7200); + + /* Test the transport history string. */ + s = geoip_get_transport_history(); + tor_assert(s); + tt_str_op(s,OP_EQ, "<OR>=8,alpha=16,beta=8,charlie=16,ddr=136," + "entropy=8,fire=8,google=8"); + + /* Stop collecting entry statistics. */ + geoip_entry_stats_term(); + get_options_mutable()->EntryStatistics = 0; + + done: + tor_free(s); +} + +#undef SET_TEST_ADDRESS +#undef SET_TEST_IPV6 +#undef CHECK_COUNTRY + +static const char GEOIP_CONTENT[] = + "134445936,134445939,MP\n" + "134445940,134447103,GU\n" + "134447104,134738943,US\n" + "134738944,134739199,CA\n" + "134739200,135192575,US\n" + "135192576,135200767,MX\n" + "135200768,135430143,US\n" + "135430144,135430399,CA\n" + "135430400,135432191,US\n"; + +static void +test_geoip_load_file(void *arg) +{ + (void)arg; + char *contents = NULL; + char *dhex = NULL; + + /* A nonexistant filename should fail. */ + tt_int_op(-1, OP_EQ, + geoip_load_file(AF_INET, "/you/did/not/put/a/file/here/I/hope", + LOG_INFO)); + + /* We start out with only "Ningunpartia" in the database. */ + tt_int_op(1, OP_EQ, geoip_get_n_countries()); + tt_str_op("??", OP_EQ, geoip_get_country_name(0)); + /* Any lookup attempt should say "-1" because we have no info */ + tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv4(0x01020304)); + /* There should be no 'digest' for a nonexistant file */ + tt_str_op("0000000000000000000000000000000000000000", OP_EQ, + geoip_db_digest(AF_INET)); + + const char *fname = get_fname("geoip"); + tt_int_op(0, OP_EQ, write_str_to_file(fname, GEOIP_CONTENT, 1)); + + int rv = geoip_load_file(AF_INET, fname, LOG_WARN); + if (rv != 0) { + TT_GRIPE(("Unable to load geoip from %s", escaped(fname))); + } + tt_int_op(0, OP_EQ, rv); + + /* Check that we loaded some countries; this will fail if there are ever + * fewer than 5 countries in our test above. */ + tt_int_op(geoip_get_n_countries(), OP_GE, 5); + + /* Let's see where 8.8.8.8 is. */ + int country = geoip_get_country_by_ipv4(0x08080808); + tt_int_op(country, OP_GE, 1); /* It shouldn't be 'unknown' or 'nowhere' */ + const char *cc = geoip_get_country_name(country); + tt_int_op(strlen(cc), OP_EQ, 2); + + /* The digest should be set.... */ + tt_str_op("0000000000000000000000000000000000000000", OP_NE, + geoip_db_digest(AF_INET)); + + /* And it should be set correctly */ + contents = read_file_to_str(fname, RFTS_BIN, NULL); + uint8_t d[DIGEST_LEN]; + crypto_digest((char*)d, contents, strlen(contents)); + dhex = tor_strdup(hex_str((char*)d, DIGEST_LEN)); + tt_str_op(dhex, OP_EQ, geoip_db_digest(AF_INET)); + + /* Make sure geoip_free_all() works. */ + geoip_free_all(); + tt_int_op(1, OP_EQ, geoip_get_n_countries()); + tt_str_op("??", OP_EQ, geoip_get_country_name(0)); + tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv4(0x01020304)); + tt_str_op("0000000000000000000000000000000000000000", OP_EQ, + geoip_db_digest(AF_INET)); // <--- nick bets this will fail. + + done: + tor_free(contents); + tor_free(dhex); +} + +static void +test_geoip6_load_file(void *arg) +{ + (void)arg; + struct in6_addr iaddr6; + char *contents = NULL; + char *dhex = NULL; + + /* A nonexistant filename should fail. */ + tt_int_op(-1, OP_EQ, + geoip_load_file(AF_INET6, "/you/did/not/put/a/file/here/I/hope", + LOG_INFO)); + + /* Any lookup attempt should say "-1" because we have no info */ + tor_inet_pton(AF_INET6, "2001:4860:4860::8888", &iaddr6); + tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv6(&iaddr6)); + + /* Load geiop6 file */ + const char *fname6 = get_fname("geoip6"); + const char CONTENT[] = + "2001:4830:6010::,2001:4830:601f:ffff:ffff:ffff:ffff:ffff,GB\n" + "2001:4830:6020::,2001:4830:ffff:ffff:ffff:ffff:ffff:ffff,US\n" + "2001:4838::,2001:4838:ffff:ffff:ffff:ffff:ffff:ffff,US\n" + "2001:4840::,2001:4840:ffff:ffff:ffff:ffff:ffff:ffff,XY\n" + "2001:4848::,2001:4848:ffff:ffff:ffff:ffff:ffff:ffff,ZD\n" + "2001:4850::,2001:4850:ffff:ffff:ffff:ffff:ffff:ffff,RO\n" + "2001:4858::,2001:4858:ffff:ffff:ffff:ffff:ffff:ffff,TC\n" + "2001:4860::,2001:4860:ffff:ffff:ffff:ffff:ffff:ffff,US\n" + "2001:4868::,2001:4868:ffff:ffff:ffff:ffff:ffff:ffff,US\n" + "2001:4870::,2001:4871:ffff:ffff:ffff:ffff:ffff:ffff,NB\n" + "2001:4878::,2001:4878:128:ffff:ffff:ffff:ffff:ffff,US\n" + "2001:4878:129::,2001:4878:129:ffff:ffff:ffff:ffff:ffff,CR\n" + "2001:4878:12a::,2001:4878:203:ffff:ffff:ffff:ffff:ffff,US\n" + "2001:4878:204::,2001:4878:204:ffff:ffff:ffff:ffff:ffff,DE\n" + "2001:4878:205::,2001:4878:214:ffff:ffff:ffff:ffff:ffff,US\n"; + tt_int_op(0, OP_EQ, write_str_to_file(fname6, CONTENT, 1)); + + tt_int_op(0, OP_EQ, geoip_load_file(AF_INET6, fname6, LOG_WARN)); + + /* Check that we loaded some countries; this will fail if there are ever + * fewer than 5 countries in our test data above. */ + tt_int_op(geoip_get_n_countries(), OP_GE, 5); + + /* Let's see where 2001:4860:4860::8888 (google dns) is. */ + const char *caddr6 = "2001:4860:4860::8888"; + tor_inet_pton(AF_INET6, caddr6, &iaddr6); + int country6 = geoip_get_country_by_ipv6(&iaddr6); + tt_int_op(country6, OP_GE, 1); + + const char *cc6 = geoip_get_country_name(country6); + tt_int_op(strlen(cc6), OP_EQ, 2); + + /* The digest should be set.... */ + tt_str_op("0000000000000000000000000000000000000000", OP_NE, + geoip_db_digest(AF_INET6)); + + /* And it should be set correctly */ + contents = read_file_to_str(fname6, RFTS_BIN, NULL); + uint8_t d[DIGEST_LEN]; + crypto_digest((char*)d, contents, strlen(contents)); + dhex = tor_strdup(hex_str((char*)d, DIGEST_LEN)); + tt_str_op(dhex, OP_EQ, geoip_db_digest(AF_INET6)); + + /* Make sure geoip_free_all() works. */ + geoip_free_all(); + tt_int_op(1, OP_EQ, geoip_get_n_countries()); + tt_str_op("??", OP_EQ, geoip_get_country_name(0)); + tor_inet_pton(AF_INET6, "::1:2:3:4", &iaddr6); + tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv6(&iaddr6)); + tt_str_op("0000000000000000000000000000000000000000", OP_EQ, + geoip_db_digest(AF_INET6)); + + done: + tor_free(contents); + tor_free(dhex); +} + +static void +test_geoip_load_2nd_file(void *arg) +{ + (void)arg; + + char *fname_geoip = tor_strdup(get_fname("geoip_data")); + char *fname_empty = tor_strdup(get_fname("geoip_empty")); + + tt_int_op(0, OP_EQ, write_str_to_file(fname_geoip, GEOIP_CONTENT, 1)); + tt_int_op(0, OP_EQ, write_str_to_file(fname_empty, "\n", 1)); + + /* Load 1st geoip file */ + tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, fname_geoip, LOG_WARN)); + + /* Load 2nd geoip (empty) file */ + /* It has to be the same IP address family */ + tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, fname_empty, LOG_WARN)); + + /* Check that there is no geoip information for 8.8.8.8, */ + /* since loading the empty 2nd file should have delete it. */ + int country = geoip_get_country_by_ipv4(0x08080808); + tt_int_op(country, OP_EQ, 0); + + done: + tor_free(fname_geoip); + tor_free(fname_empty); +} + +#define ENT(name) \ + { #name, test_ ## name , 0, NULL, NULL } +#define FORK(name) \ + { #name, test_ ## name , TT_FORK, NULL, NULL } + +struct testcase_t geoip_tests[] = { + { "geoip", test_geoip, TT_FORK, NULL, NULL }, + { "geoip_with_pt", test_geoip_with_pt, TT_FORK, NULL, NULL }, + { "load_file", test_geoip_load_file, TT_FORK, NULL, NULL }, + { "load_file6", test_geoip6_load_file, TT_FORK, NULL, NULL }, + { "load_2nd_file", test_geoip_load_2nd_file, TT_FORK, NULL, NULL }, + + END_OF_TESTCASES +}; diff --git a/src/test/test_guardfraction.c b/src/test/test_guardfraction.c index 51ca8f08ec..d6f4cd63f2 100644 --- a/src/test/test_guardfraction.c +++ b/src/test/test_guardfraction.c @@ -1,23 +1,25 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define DIRSERV_PRIVATE -#define ROUTERPARSE_PRIVATE +#define GUARDFRACTION_PRIVATE #define NETWORKSTATUS_PRIVATE +#define NS_PARSE_PRIVATE #include "orconfig.h" -#include "or.h" -#include "config.h" -#include "dirserv.h" -#include "container.h" -#include "entrynodes.h" -#include "util.h" -#include "routerparse.h" -#include "networkstatus.h" - -#include "test.h" -#include "test_helpers.h" -#include "log_test_helpers.h" +#include "core/or/or.h" +#include "app/config/config.h" +#include "feature/dirauth/guardfraction.h" +#include "feature/client/entrynodes.h" +#include "feature/dirparse/ns_parse.h" +#include "feature/nodelist/networkstatus.h" + +#include "feature/nodelist/networkstatus_st.h" +#include "feature/dirauth/vote_microdesc_hash_st.h" +#include "feature/nodelist/vote_routerstatus_st.h" + +#include "test/test.h" +#include "test/test_helpers.h" +#include "test/log_test_helpers.h" /** Generate a vote_routerstatus_t for a router with identity digest * <b>digest_in_hex</b>. */ @@ -420,4 +422,3 @@ struct testcase_t guardfraction_tests[] = { END_OF_TESTCASES }; - diff --git a/src/test/test_handles.c b/src/test/test_handles.c index eb1e1f1bbe..2910d7e18f 100644 --- a/src/test/test_handles.c +++ b/src/test/test_handles.c @@ -1,11 +1,13 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" -#include "test.h" +#include "test/test.h" -#include "util.h" -#include "handles.h" +#include "lib/container/handles.h" +#include "lib/log/util_bug.h" + +#include <stdio.h> typedef struct demo_t { HANDLE_ENTRY(demo, demo_t); @@ -94,4 +96,3 @@ struct testcase_t handle_tests[] = { HANDLE_TEST(basic, 0), END_OF_TESTCASES }; - diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c index 0da9cf64d0..6ac73bff5c 100644 --- a/src/test/test_helpers.c +++ b/src/test/test_helpers.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,23 +9,32 @@ #define ROUTERLIST_PRIVATE #define CONFIG_PRIVATE #define CONNECTION_PRIVATE -#define MAIN_PRIVATE +#define MAINLOOP_PRIVATE #include "orconfig.h" -#include "or.h" - -#include "buffers.h" -#include "config.h" -#include "confparse.h" -#include "connection.h" -#include "main.h" -#include "nodelist.h" -#include "relay.h" -#include "routerlist.h" - -#include "test.h" -#include "test_helpers.h" -#include "test_connection.h" +#include "core/or/or.h" + +#include "lib/container/buffers.h" +#include "app/config/config.h" +#include "app/config/confparse.h" +#include "core/mainloop/connection.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "core/mainloop/mainloop.h" +#include "feature/nodelist/nodelist.h" +#include "core/or/relay.h" +#include "feature/nodelist/routerlist.h" +#include "lib/encoding/confline.h" +#include "lib/net/resolve.h" + +#include "core/or/cell_st.h" +#include "core/or/connection_st.h" +#include "feature/nodelist/node_st.h" +#include "core/or/origin_circuit_st.h" +#include "feature/nodelist/routerlist_st.h" + +#include "test/test.h" +#include "test/test_helpers.h" +#include "test/test_connection.h" #ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS DISABLE_GCC_WARNING(overlength-strings) @@ -33,8 +42,7 @@ DISABLE_GCC_WARNING(overlength-strings) * at large. */ #endif #include "test_descriptors.inc" -#include "or.h" -#include "circuitlist.h" +#include "core/or/circuitlist.h" #ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS ENABLE_GCC_WARNING(overlength-strings) #endif @@ -117,6 +125,25 @@ connection_write_to_buf_mock(const char *string, size_t len, buf_add(conn->outbuf, string, len); } +char * +buf_get_contents(buf_t *buf, size_t *sz_out) +{ + tor_assert(buf); + tor_assert(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 (buf_get_bytes(buf, out, (unsigned long)*sz_out) != 0) { + tor_free(out); + return NULL; + } + out[*sz_out] = '\0'; /* Hopefully gratuitous. */ + return out; +} + /* Set up a fake origin circuit with the specified number of cells, * Return a pointer to the newly-created dummy circuit */ circuit_t * @@ -156,7 +183,7 @@ mock_tor_addr_lookup__fail_on_bad_addrs(const char *name, /* Helper for test_conn_get_connection() */ static int -fake_close_socket(evutil_socket_t sock) +fake_close_socket(tor_socket_t sock) { (void)sock; return 0; @@ -209,7 +236,7 @@ test_conn_get_connection(uint8_t state, uint8_t type, uint8_t purpose) mock_connection_connect_sockaddr); MOCK(tor_close_socket, fake_close_socket); - init_connection_lists(); + tor_init_connection_lists(); conn = connection_new(type, TEST_CONN_FAMILY); tt_assert(conn); @@ -276,4 +303,3 @@ helper_parse_options(const char *conf) } return opt; } - diff --git a/src/test/test_helpers.h b/src/test/test_helpers.h index 9bc8553257..72bf7f2f71 100644 --- a/src/test/test_helpers.h +++ b/src/test/test_helpers.h @@ -1,10 +1,12 @@ -/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #ifndef TOR_TEST_HELPERS_H #define TOR_TEST_HELPERS_H -#include "or.h" +#define BUFFERS_PRIVATE + +#include "core/or/or.h" const char *get_yesterday_date_str(void); @@ -18,6 +20,7 @@ void helper_setup_fake_routerlist(void); #define GET(path) "GET " path " HTTP/1.0\r\n\r\n" void connection_write_to_buf_mock(const char *string, size_t len, connection_t *conn, int compressed); +char *buf_get_contents(buf_t *buf, size_t *sz_out); int mock_tor_addr_lookup__fail_on_bad_addrs(const char *name, uint16_t family, tor_addr_t *out); diff --git a/src/test/test_hs.c b/src/test/test_hs.c index 07daebc164..e3599d5720 100644 --- a/src/test/test_hs.c +++ b/src/test/test_hs.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2007-2017, The Tor Project, Inc. */ +/* Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -12,16 +12,27 @@ #define RENDSERVICE_PRIVATE #define HS_SERVICE_PRIVATE -#include "or.h" -#include "test.h" -#include "control.h" -#include "config.h" -#include "hs_common.h" -#include "rendcommon.h" -#include "rendservice.h" -#include "routerset.h" -#include "circuitbuild.h" -#include "test_helpers.h" +#include "core/or/or.h" +#include "test/test.h" +#include "feature/control/control.h" +#include "app/config/config.h" +#include "feature/hs/hs_common.h" +#include "feature/rend/rendcommon.h" +#include "feature/rend/rendservice.h" +#include "feature/nodelist/routerlist.h" +#include "feature/nodelist/routerset.h" +#include "core/or/circuitbuild.h" + +#include "feature/nodelist/node_st.h" +#include "feature/rend/rend_encoded_v2_service_descriptor_st.h" +#include "feature/rend/rend_intro_point_st.h" +#include "feature/nodelist/routerinfo_st.h" + +#include "test/test_helpers.h" + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif /* mock ID digest and longname for node that's in nodelist */ #define HSDIR_EXIST_ID "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" \ @@ -343,76 +354,6 @@ test_hs_desc_event(void *arg) tor_free(received_msg); } -/* Make sure we always pick the right RP, given a well formatted - * Tor2webRendezvousPoints value. */ -static void -test_pick_tor2web_rendezvous_node(void *arg) -{ - or_options_t *options = get_options_mutable(); - const node_t *chosen_rp = NULL; - router_crn_flags_t flags = CRN_NEED_DESC; - int retval, i; - const char *tor2web_rendezvous_str = "test003r"; - - (void) arg; - - /* Setup fake routerlist. */ - helper_setup_fake_routerlist(); - - /* Parse Tor2webRendezvousPoints as a routerset. */ - options->Tor2webRendezvousPoints = routerset_new(); - options->UseMicrodescriptors = 0; - retval = routerset_parse(options->Tor2webRendezvousPoints, - tor2web_rendezvous_str, - "test_tor2web_rp"); - tt_int_op(retval, OP_GE, 0); - - /* Pick rendezvous point. Make sure the correct one is - picked. Repeat many times to make sure it works properly. */ - for (i = 0; i < 50 ; i++) { - chosen_rp = pick_tor2web_rendezvous_node(flags, options); - tt_assert(chosen_rp); - tt_str_op(chosen_rp->ri->nickname, OP_EQ, tor2web_rendezvous_str); - } - - done: - routerset_free(options->Tor2webRendezvousPoints); -} - -/* Make sure we never pick an RP if Tor2webRendezvousPoints doesn't - * correspond to an actual node. */ -static void -test_pick_bad_tor2web_rendezvous_node(void *arg) -{ - or_options_t *options = get_options_mutable(); - const node_t *chosen_rp = NULL; - router_crn_flags_t flags = CRN_NEED_DESC; - int retval, i; - const char *tor2web_rendezvous_str = "dummy"; - - (void) arg; - - /* Setup fake routerlist. */ - helper_setup_fake_routerlist(); - - /* Parse Tor2webRendezvousPoints as a routerset. */ - options->Tor2webRendezvousPoints = routerset_new(); - retval = routerset_parse(options->Tor2webRendezvousPoints, - tor2web_rendezvous_str, - "test_tor2web_rp"); - tt_int_op(retval, OP_GE, 0); - - /* Pick rendezvous point. Since Tor2webRendezvousPoints was set to a - dummy value, we shouldn't find any eligible RPs. */ - for (i = 0; i < 50 ; i++) { - chosen_rp = pick_tor2web_rendezvous_node(flags, options); - tt_ptr_op(chosen_rp, OP_EQ, NULL); - } - - done: - routerset_free(options->Tor2webRendezvousPoints); -} - /* Make sure rend_data_t is valid at creation, destruction and when * duplicated. */ static void @@ -1035,11 +976,6 @@ struct testcase_t hs_tests[] = { NULL, NULL }, { "hs_desc_event", test_hs_desc_event, TT_FORK, NULL, NULL }, - { "pick_tor2web_rendezvous_node", test_pick_tor2web_rendezvous_node, TT_FORK, - NULL, NULL }, - { "pick_bad_tor2web_rendezvous_node", - test_pick_bad_tor2web_rendezvous_node, TT_FORK, - NULL, NULL }, { "hs_auth_cookies", test_hs_auth_cookies, TT_FORK, NULL, NULL }, { "single_onion_poisoning_create_dir_none", test_single_onion_poisoning, @@ -1055,4 +991,3 @@ struct testcase_t hs_tests[] = { END_OF_TESTCASES }; - diff --git a/src/test/test_hs_cache.c b/src/test/test_hs_cache.c index 458ce1a92e..203a1d7039 100644 --- a/src/test/test_hs_cache.c +++ b/src/test/test_hs_cache.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -7,20 +7,26 @@ */ #define CONNECTION_PRIVATE -#define DIRECTORY_PRIVATE +#define DIRCACHE_PRIVATE +#define DIRCLIENT_PRIVATE #define HS_CACHE_PRIVATE -#include "ed25519_cert.h" -#include "hs_cache.h" -#include "rendcache.h" -#include "directory.h" -#include "networkstatus.h" -#include "connection.h" -#include "proto_http.h" +#include "trunnel/ed25519_cert.h" +#include "feature/hs/hs_cache.h" +#include "feature/rend/rendcache.h" +#include "feature/dircache/dircache.h" +#include "feature/dirclient/dirclient.h" +#include "feature/nodelist/networkstatus.h" +#include "core/mainloop/connection.h" +#include "core/proto/proto_http.h" +#include "lib/crypt_ops/crypto_format.h" -#include "hs_test_helpers.h" -#include "test_helpers.h" -#include "test.h" +#include "feature/dircommon/dir_connection_st.h" +#include "feature/nodelist/networkstatus_st.h" + +#include "test/hs_test_helpers.h" +#include "test/test_helpers.h" +#include "test/test.h" /* Static variable used to encoded the HSDir query. */ static char query_b64[256]; @@ -60,7 +66,7 @@ test_directory(void *arg) tt_int_op(ret, OP_EQ, 0); desc1 = hs_helper_build_hs_desc_with_ip(&signing_kp1); tt_assert(desc1); - ret = hs_desc_encode_descriptor(desc1, &signing_kp1, &desc1_str); + ret = hs_desc_encode_descriptor(desc1, &signing_kp1, NULL, &desc1_str); tt_int_op(ret, OP_EQ, 0); /* Very first basic test, should be able to be stored, survive a @@ -98,7 +104,7 @@ test_directory(void *arg) desc_zero_lifetime->plaintext_data.lifetime_sec = 0; char *desc_zero_lifetime_str; ret = hs_desc_encode_descriptor(desc_zero_lifetime, &signing_kp_zero, - &desc_zero_lifetime_str); + NULL, &desc_zero_lifetime_str); tt_int_op(ret, OP_EQ, 0); ret = hs_cache_store_as_dir(desc1_str); @@ -149,7 +155,7 @@ test_directory(void *arg) tt_int_op(ret, OP_EQ, 1); /* Bump revision counter. */ desc1->plaintext_data.revision_counter++; - ret = hs_desc_encode_descriptor(desc1, &signing_kp1, &new_desc_str); + ret = hs_desc_encode_descriptor(desc1, &signing_kp1, NULL, &new_desc_str); tt_int_op(ret, OP_EQ, 0); ret = hs_cache_store_as_dir(new_desc_str); tt_int_op(ret, OP_EQ, 0); @@ -183,7 +189,7 @@ test_clean_as_dir(void *arg) tt_int_op(ret, OP_EQ, 0); desc1 = hs_helper_build_hs_desc_with_ip(&signing_kp1); tt_assert(desc1); - ret = hs_desc_encode_descriptor(desc1, &signing_kp1, &desc1_str); + ret = hs_desc_encode_descriptor(desc1, &signing_kp1, NULL, &desc1_str); tt_int_op(ret, OP_EQ, 0); ret = hs_cache_store_as_dir(desc1_str); tt_int_op(ret, OP_EQ, 0); @@ -297,7 +303,7 @@ test_upload_and_download_hs_desc(void *arg) published_desc = hs_helper_build_hs_desc_with_ip(&signing_kp); tt_assert(published_desc); retval = hs_desc_encode_descriptor(published_desc, &signing_kp, - &published_desc_str); + NULL, &published_desc_str); tt_int_op(retval, OP_EQ, 0); } @@ -361,7 +367,7 @@ test_hsdir_revision_counter_check(void *arg) published_desc = hs_helper_build_hs_desc_with_ip(&signing_kp); tt_assert(published_desc); retval = hs_desc_encode_descriptor(published_desc, &signing_kp, - &published_desc_str); + NULL, &published_desc_str); tt_int_op(retval, OP_EQ, 0); } @@ -386,7 +392,7 @@ test_hsdir_revision_counter_check(void *arg) received_desc_str = helper_fetch_desc_from_hsdir(blinded_key); retval = hs_desc_decode_descriptor(received_desc_str, - subcredential, &received_desc); + subcredential, NULL, &received_desc); tt_int_op(retval, OP_EQ, 0); tt_assert(received_desc); @@ -403,7 +409,7 @@ test_hsdir_revision_counter_check(void *arg) published_desc->plaintext_data.revision_counter = 1313; tor_free(published_desc_str); retval = hs_desc_encode_descriptor(published_desc, &signing_kp, - &published_desc_str); + NULL, &published_desc_str); tt_int_op(retval, OP_EQ, 0); retval = handle_post_hs_descriptor("/tor/hs/3/publish",published_desc_str); @@ -419,7 +425,7 @@ test_hsdir_revision_counter_check(void *arg) received_desc_str = helper_fetch_desc_from_hsdir(blinded_key); retval = hs_desc_decode_descriptor(received_desc_str, - subcredential, &received_desc); + subcredential, NULL, &received_desc); tt_int_op(retval, OP_EQ, 0); tt_assert(received_desc); @@ -478,7 +484,7 @@ test_client_cache(void *arg) published_desc = hs_helper_build_hs_desc_with_ip(&signing_kp); tt_assert(published_desc); retval = hs_desc_encode_descriptor(published_desc, &signing_kp, - &published_desc_str); + NULL, &published_desc_str); tt_int_op(retval, OP_EQ, 0); memcpy(wanted_subcredential, published_desc->subcredential, DIGEST256_LEN); tt_assert(!tor_mem_is_zero((char*)wanted_subcredential, DIGEST256_LEN)); @@ -558,4 +564,3 @@ struct testcase_t hs_cache[] = { END_OF_TESTCASES }; - diff --git a/src/test/test_hs_cell.c b/src/test/test_hs_cell.c index aed28d3bd2..5b48dd3785 100644 --- a/src/test/test_hs_cell.c +++ b/src/test/test_hs_cell.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,17 +9,18 @@ #define HS_INTROPOINT_PRIVATE #define HS_SERVICE_PRIVATE -#include "test.h" -#include "test_helpers.h" -#include "log_test_helpers.h" +#include "test/test.h" +#include "test/test_helpers.h" +#include "test/log_test_helpers.h" -#include "crypto_ed25519.h" -#include "hs_cell.h" -#include "hs_intropoint.h" -#include "hs_service.h" +#include "lib/crypt_ops/crypto_ed25519.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "feature/hs/hs_cell.h" +#include "feature/hs/hs_intropoint.h" +#include "feature/hs/hs_service.h" /* Trunnel. */ -#include "hs/cell_establish_intro.h" +#include "trunnel/hs/cell_establish_intro.h" /** We simulate the creation of an outgoing ESTABLISH_INTRO cell, and then we * parse it from the receiver side. */ diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c index 7ee7210bc9..25cb991a79 100644 --- a/src/test/test_hs_client.c +++ b/src/test/test_hs_client.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -6,36 +6,50 @@ * \brief Test prop224 HS client functionality. */ +#define CONFIG_PRIVATE #define CRYPTO_PRIVATE -#define MAIN_PRIVATE +#define MAINLOOP_PRIVATE #define HS_CLIENT_PRIVATE #define TOR_CHANNEL_INTERNAL_ #define CIRCUITBUILD_PRIVATE #define CIRCUITLIST_PRIVATE #define CONNECTION_PRIVATE -#include "test.h" -#include "test_helpers.h" -#include "log_test_helpers.h" -#include "rend_test_helpers.h" -#include "hs_test_helpers.h" - -#include "config.h" -#include "crypto.h" -#include "channeltls.h" -#include "main.h" -#include "nodelist.h" -#include "routerset.h" - -#include "hs_circuit.h" -#include "hs_client.h" -#include "hs_ident.h" -#include "hs_cache.h" -#include "circuitlist.h" -#include "circuitbuild.h" -#include "connection.h" -#include "connection_edge.h" -#include "networkstatus.h" +#include "test/test.h" +#include "test/test_helpers.h" +#include "test/log_test_helpers.h" +#include "test/rend_test_helpers.h" +#include "test/hs_test_helpers.h" + +#include "app/config/config.h" +#include "lib/crypt_ops/crypto_cipher.h" +#include "lib/crypt_ops/crypto_dh.h" +#include "core/or/channeltls.h" +#include "feature/dircommon/directory.h" +#include "core/mainloop/mainloop.h" +#include "feature/nodelist/nodelist.h" +#include "feature/nodelist/routerset.h" + +#include "feature/hs/hs_circuit.h" +#include "feature/hs/hs_circuitmap.h" +#include "feature/hs/hs_client.h" +#include "feature/hs/hs_config.h" +#include "feature/hs/hs_ident.h" +#include "feature/hs/hs_cache.h" +#include "core/or/circuitlist.h" +#include "core/or/circuitbuild.h" +#include "core/mainloop/connection.h" +#include "core/or/connection_edge.h" +#include "feature/nodelist/networkstatus.h" + +#include "core/or/cpath_build_state_st.h" +#include "core/or/crypt_path_st.h" +#include "feature/dircommon/dir_connection_st.h" +#include "core/or/entry_connection_st.h" +#include "core/or/extend_info_st.h" +#include "feature/nodelist/networkstatus_st.h" +#include "core/or/origin_circuit_st.h" +#include "core/or/socks_request_st.h" static int mock_connection_ap_handshake_send_begin(entry_connection_t *ap_conn) @@ -61,6 +75,20 @@ mock_networkstatus_get_live_consensus(time_t now) return &mock_ns; } +static int +helper_config_client(const char *conf, int validate_only) +{ + int ret = 0; + or_options_t *options = NULL; + tt_assert(conf); + options = helper_parse_options(conf); + tt_assert(options); + ret = hs_config_client_auth_all(options, validate_only); + done: + or_options_free(options); + return ret; +} + /* Test helper function: Setup a circuit and a stream with the same hidden * service destination, and put them in <b>circ_out</b> and * <b>conn_out</b>. Make the stream wait for circuits to be established to the @@ -188,17 +216,17 @@ test_e2e_rend_circuit_setup_legacy(void *arg) /* Make a good RENDEZVOUS1 cell body because it needs to pass key exchange * digest verification... */ - uint8_t rend_cell_body[DH_KEY_LEN+DIGEST_LEN] = {2}; + uint8_t rend_cell_body[DH1024_KEY_LEN+DIGEST_LEN] = {2}; { char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN]; crypto_dh_t *dh_state = or_circ->build_state->pending_final_cpath->rend_dh_handshake_state; /* compute and overwrite digest of cell body with the right value */ retval = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh_state, - (char*)rend_cell_body, DH_KEY_LEN, + (char*)rend_cell_body, DH1024_KEY_LEN, keys, DIGEST_LEN+CPATH_KEY_MATERIAL_LEN); tt_int_op(retval, OP_GT, 0); - memcpy(rend_cell_body+DH_KEY_LEN, keys, DIGEST_LEN); + memcpy(rend_cell_body+DH1024_KEY_LEN, keys, DIGEST_LEN); } /* Setup the circuit */ @@ -213,12 +241,12 @@ test_e2e_rend_circuit_setup_legacy(void *arg) tt_int_op(retval, OP_EQ, 1); /* Check the digest algo */ - tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->f_digest), + tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.f_digest), OP_EQ, DIGEST_SHA1); - tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->b_digest), + tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.b_digest), OP_EQ, DIGEST_SHA1); - tt_assert(or_circ->cpath->f_crypto); - tt_assert(or_circ->cpath->b_crypto); + tt_assert(or_circ->cpath->crypto.f_crypto); + tt_assert(or_circ->cpath->crypto.b_crypto); /* Ensure that circ purpose was changed */ tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_C_REND_JOINED); @@ -283,12 +311,12 @@ test_e2e_rend_circuit_setup(void *arg) tt_int_op(retval, OP_EQ, 1); /* Check that the crypt path has prop224 algorithm parameters */ - tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->f_digest), + tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.f_digest), OP_EQ, DIGEST_SHA3_256); - tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->b_digest), + tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.b_digest), OP_EQ, DIGEST_SHA3_256); - tt_assert(or_circ->cpath->f_crypto); - tt_assert(or_circ->cpath->b_crypto); + tt_assert(or_circ->cpath->crypto.f_crypto); + tt_assert(or_circ->cpath->crypto.b_crypto); /* Ensure that circ purpose was changed */ tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_C_REND_JOINED); @@ -354,7 +382,7 @@ test_client_pick_intro(void *arg) { char *encoded = NULL; desc = hs_helper_build_hs_desc_with_ip(&service_kp); - ret = hs_desc_encode_descriptor(desc, &service_kp, &encoded); + ret = hs_desc_encode_descriptor(desc, &service_kp, NULL, &encoded); tt_int_op(ret, OP_EQ, 0); tt_assert(encoded); @@ -397,21 +425,25 @@ test_client_pick_intro(void *arg) } SMARTLIST_FOREACH_END(ip); /* Try to get a random intro: Should return the chosen one! */ - extend_info_t *ip = client_get_random_intro(&service_kp.pubkey); - tor_assert(ip); - tt_assert(!tor_mem_is_zero((char*)ip->identity_digest, DIGEST_LEN)); - tt_mem_op(ip->identity_digest, OP_EQ, chosen_intro_ei->identity_digest, - DIGEST_LEN); + /* (We try several times, to make sure this behavior is consistent, and to + * cover the different cases of client_get_random_intro().) */ + for (int i = 0; i < 64; ++i) { + extend_info_t *ip = client_get_random_intro(&service_kp.pubkey); + tor_assert(ip); + tt_assert(!tor_mem_is_zero((char*)ip->identity_digest, DIGEST_LEN)); + tt_mem_op(ip->identity_digest, OP_EQ, chosen_intro_ei->identity_digest, + DIGEST_LEN); + extend_info_free(ip); + } extend_info_free(chosen_intro_ei); - extend_info_free(ip); /* Now also mark the chosen one as failed: See that we can't get any intro points anymore. */ hs_cache_client_intro_state_note(&service_kp.pubkey, &chosen_intro_point->auth_key_cert->signed_key, INTRO_POINT_FAILURE_TIMEOUT); - ip = client_get_random_intro(&service_kp.pubkey); + extend_info_t *ip = client_get_random_intro(&service_kp.pubkey); tor_assert(!ip); } @@ -491,6 +523,9 @@ mock_connection_mark_unattached_ap_(entry_connection_t *conn, int endreason, (void) line; (void) file; conn->edge_.end_reason = endreason; + /* This function ultimately will flag this so make sure we do also in the + * MOCK one so we can assess closed connections vs open ones. */ + conn->edge_.base_.marked_for_close = 1; } static void @@ -585,6 +620,271 @@ test_descriptor_fetch(void *arg) hs_free_all(); } +static void +test_auth_key_filename_is_valid(void *arg) +{ + (void) arg; + + /* Valid file name. */ + tt_assert(auth_key_filename_is_valid("a.auth_private")); + /* Valid file name with special character. */ + tt_assert(auth_key_filename_is_valid("a-.auth_private")); + /* Invalid extension. */ + tt_assert(!auth_key_filename_is_valid("a.ath_private")); + /* Nothing before the extension. */ + tt_assert(!auth_key_filename_is_valid(".auth_private")); + + done: + ; +} + +static void +test_parse_auth_file_content(void *arg) +{ + hs_client_service_authorization_t *auth = NULL; + + (void) arg; + + /* Valid authorized client. */ + auth = parse_auth_file_content( + "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad:descriptor:" + "x25519:zdsyvn2jq534ugyiuzgjy4267jbtzcjbsgedhshzx5mforyxtryq"); + tt_assert(auth); + + /* Wrong number of fields. */ + tt_assert(!parse_auth_file_content("a:b")); + /* Wrong auth type. */ + tt_assert(!parse_auth_file_content( + "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad:x:" + "x25519:zdsyvn2jq534ugyiuzgjy4267jbtzcjbsgedhshzx5mforyxtryq")); + /* Wrong key type. */ + tt_assert(!parse_auth_file_content( + "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad:descriptor:" + "x:zdsyvn2jq534ugyiuzgjy4267jbtzcjbsgedhshzx5mforyxtryq")); + /* Some malformed string. */ + tt_assert(!parse_auth_file_content("xx:descriptor:x25519:aa==")); + /* Bigger key than it should be */ + tt_assert(!parse_auth_file_content("xx:descriptor:x25519:" + "vjqea4jbhwwc4hto7ekyvqfbeodghbaq6nxi45hz4wr3qvhqv3yqa")); + done: + tor_free(auth); +} + +static char * +mock_read_file_to_str(const char *filename, int flags, struct stat *stat_out) +{ + char *ret = NULL; + + (void) flags; + (void) stat_out; + + if (!strcmp(filename, get_fname("auth_keys" PATH_SEPARATOR + "client1.auth_private"))) { + ret = tor_strdup( + "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad:descriptor:" + "x25519:zdsyvn2jq534ugyiuzgjy4267jbtzcjbsgedhshzx5mforyxtryq"); + goto done; + } + + if (!strcmp(filename, get_fname("auth_keys" PATH_SEPARATOR "dummy.xxx"))) { + ret = tor_strdup( + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:descriptor:" + "x25519:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); + goto done; + } + + if (!strcmp(filename, get_fname("auth_keys" PATH_SEPARATOR + "client2.auth_private"))) { + ret = tor_strdup( + "25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid:descriptor:" + "x25519:fdreqzjqso7d2ac7qscrxfl5qfpamdvgy5d6cxejcgzc3hvhurmq"); + goto done; + } + + done: + return ret; +} + +static int +mock_check_private_dir(const char *dirname, cpd_check_t check, + const char *effective_user) +{ + (void) dirname; + (void) check; + (void) effective_user; + + return 0; +} + +static smartlist_t * +mock_tor_listdir(const char *dirname) +{ + smartlist_t *file_list = smartlist_new(); + + (void) dirname; + + smartlist_add(file_list, tor_strdup("client1.auth_private")); + smartlist_add(file_list, tor_strdup("dummy.xxx")); + smartlist_add(file_list, tor_strdup("client2.auth_private")); + + return file_list; +} + +static void +test_config_client_authorization(void *arg) +{ + int ret; + char *conf = NULL; + ed25519_public_key_t pk1, pk2; + digest256map_t *global_map = NULL; + char *key_dir = tor_strdup(get_fname("auth_keys")); + + (void) arg; + + MOCK(read_file_to_str, mock_read_file_to_str); + MOCK(tor_listdir, mock_tor_listdir); + MOCK(check_private_dir, mock_check_private_dir); + +#define conf_fmt \ + "ClientOnionAuthDir %s\n" + + tor_asprintf(&conf, conf_fmt, key_dir); + ret = helper_config_client(conf, 0); + tor_free(conf); + tt_int_op(ret, OP_EQ, 0); + +#undef conf_fmt + + global_map = get_hs_client_auths_map(); + tt_int_op(digest256map_size(global_map), OP_EQ, 2); + + hs_parse_address("4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad", + &pk1, NULL, NULL); + hs_parse_address("25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid", + &pk2, NULL, NULL); + + tt_assert(digest256map_get(global_map, pk1.pubkey)); + tt_assert(digest256map_get(global_map, pk2.pubkey)); + + done: + tor_free(key_dir); + hs_free_all(); + UNMOCK(read_file_to_str); + UNMOCK(tor_listdir); + UNMOCK(check_private_dir); +} + +static entry_connection_t * +helper_build_socks_connection(const ed25519_public_key_t *service_pk, + int conn_state) +{ + entry_connection_t *socks = entry_connection_new(CONN_TYPE_AP, AF_INET); + ENTRY_TO_EDGE_CONN(socks)->hs_ident = hs_ident_edge_conn_new(service_pk); + TO_CONN(ENTRY_TO_EDGE_CONN(socks))->state = conn_state; + smartlist_add(get_connection_array(), &socks->edge_.base_); + return socks; +} + +static void +test_desc_has_arrived_cleanup(void *arg) +{ + /* The goal of this test is to make sure we clean up everything in between + * two descriptors from the same .onion. Because intro points can change + * from one descriptor to another, once we received a new descriptor, we + * need to cleanup the remaining circuits so they aren't used or selected + * when establishing a connection with the newly stored descriptor. + * + * This test was created because of #27410. */ + + int ret; + char *desc_str = NULL; + hs_descriptor_t *desc = NULL; + const hs_descriptor_t *cached_desc; + ed25519_keypair_t signing_kp; + entry_connection_t *socks1 = NULL, *socks2 = NULL; + hs_ident_dir_conn_t hs_dir_ident; + + (void) arg; + + hs_init(); + + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus); + MOCK(connection_mark_unattached_ap_, + mock_connection_mark_unattached_ap_); + MOCK(router_have_minimum_dir_info, + mock_router_have_minimum_dir_info_true); + + /* Set consensus time before our time so the cache lookup can always + * validate that the entry is not expired. */ + parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC", &mock_ns.valid_after); + parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC", &mock_ns.fresh_until); + parse_rfc1123_time("Sat, 26 Oct 1985 16:00:00 UTC", &mock_ns.valid_until); + + /* Build a descriptor for a specific .onion. */ + ret = ed25519_keypair_generate(&signing_kp, 0); + tt_int_op(ret, OP_EQ, 0); + desc = hs_helper_build_hs_desc_with_ip(&signing_kp); + tt_assert(desc); + ret = hs_desc_encode_descriptor(desc, &signing_kp, NULL, &desc_str); + tt_int_op(ret, OP_EQ, 0); + + /* Store in the client cache. */ + ret = hs_cache_store_as_client(desc_str, &signing_kp.pubkey); + tt_int_op(ret, OP_EQ, 0); + cached_desc = hs_cache_lookup_as_client(&signing_kp.pubkey); + tt_assert(cached_desc); + hs_helper_desc_equal(desc, cached_desc); + + /* Create two SOCKS connection for the same .onion both in the waiting for a + * descriptor state. */ + socks1 = helper_build_socks_connection(&signing_kp.pubkey, + AP_CONN_STATE_RENDDESC_WAIT); + tt_assert(socks1); + socks2 = helper_build_socks_connection(&signing_kp.pubkey, + AP_CONN_STATE_RENDDESC_WAIT); + tt_assert(socks2); + + /* Now, we'll make the intro points in the current descriptor unusable so + * the hs_client_desc_has_arrived() will take the right code path that we + * want to test that is the fetched descriptor has bad intro points. */ + SMARTLIST_FOREACH_BEGIN(desc->encrypted_data.intro_points, + hs_desc_intro_point_t *, ip) { + hs_cache_client_intro_state_note(&signing_kp.pubkey, + &ip->auth_key_cert->signed_key, + INTRO_POINT_FAILURE_GENERIC); + } SMARTLIST_FOREACH_END(ip); + + /* Simulate that a new descriptor just arrived. We should have both of our + * SOCKS connection to be ended with a resolved failed. */ + hs_ident_dir_conn_init(&signing_kp.pubkey, + &desc->plaintext_data.blinded_pubkey, &hs_dir_ident); + hs_client_desc_has_arrived(&hs_dir_ident); + tt_int_op(socks1->edge_.end_reason, OP_EQ, END_STREAM_REASON_RESOLVEFAILED); + /* XXX: MUST work with OP_EQ. */ + tt_int_op(socks2->edge_.end_reason, OP_EQ, END_STREAM_REASON_RESOLVEFAILED); + + /* Now let say tor cleans up the intro state cache which resets all intro + * point failure count. */ + hs_cache_client_intro_state_purge(); + + /* Retrying all SOCKS which should basically do nothing since we don't have + * any pending SOCKS connection in AP_CONN_STATE_RENDDESC_WAIT state. */ + /* XXX: BUG() is triggered here, shouldn't if socks2 wasn't alive. */ + retry_all_socks_conn_waiting_for_desc(); + + done: + connection_free_minimal(ENTRY_TO_CONN(socks1)); + connection_free_minimal(ENTRY_TO_CONN(socks2)); + hs_descriptor_free(desc); + tor_free(desc_str); + hs_free_all(); + + UNMOCK(networkstatus_get_live_consensus); + UNMOCK(connection_mark_unattached_ap_); + UNMOCK(router_have_minimum_dir_info); +} + struct testcase_t hs_client_tests[] = { { "e2e_rend_circuit_setup_legacy", test_e2e_rend_circuit_setup_legacy, TT_FORK, NULL, NULL }, @@ -594,6 +894,14 @@ struct testcase_t hs_client_tests[] = { TT_FORK, NULL, NULL }, { "descriptor_fetch", test_descriptor_fetch, TT_FORK, NULL, NULL }, + { "auth_key_filename_is_valid", test_auth_key_filename_is_valid, TT_FORK, + NULL, NULL }, + { "parse_auth_file_content", test_parse_auth_file_content, TT_FORK, + NULL, NULL }, + { "config_client_authorization", test_config_client_authorization, + TT_FORK, NULL, NULL }, + { "desc_has_arrived_cleanup", test_desc_has_arrived_cleanup, + TT_FORK, NULL, NULL }, + END_OF_TESTCASES }; - diff --git a/src/test/test_hs_common.c b/src/test/test_hs_common.c index 16803dbd16..95f7ed14ba 100644 --- a/src/test/test_hs_common.c +++ b/src/test/test_hs_common.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -11,25 +11,34 @@ #define HS_SERVICE_PRIVATE #define NODELIST_PRIVATE -#include "test.h" -#include "test_helpers.h" -#include "log_test_helpers.h" -#include "hs_test_helpers.h" - -#include "connection_edge.h" -#include "hs_common.h" -#include "hs_client.h" -#include "hs_service.h" -#include "config.h" -#include "networkstatus.h" -#include "directory.h" -#include "dirvote.h" -#include "nodelist.h" -#include "routerlist.h" -#include "statefile.h" -#include "circuitlist.h" -#include "shared_random.h" -#include "util.h" +#include "test/test.h" +#include "test/test_helpers.h" +#include "test/log_test_helpers.h" +#include "test/hs_test_helpers.h" + +#include "core/or/connection_edge.h" +#include "lib/crypt_ops/crypto_format.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "feature/hs/hs_common.h" +#include "feature/hs/hs_client.h" +#include "feature/hs/hs_service.h" +#include "app/config/config.h" +#include "feature/nodelist/networkstatus.h" +#include "feature/dirclient/dirclient.h" +#include "feature/dirauth/dirvote.h" +#include "feature/nodelist/nodelist.h" +#include "feature/nodelist/routerlist.h" +#include "app/config/statefile.h" +#include "core/or/circuitlist.h" +#include "feature/dirauth/shared_random.h" +#include "feature/dircommon/voting_schedule.h" + +#include "feature/nodelist/microdesc_st.h" +#include "feature/nodelist/networkstatus_st.h" +#include "feature/nodelist/node_st.h" +#include "app/config/or_state_st.h" +#include "feature/nodelist/routerinfo_st.h" +#include "feature/nodelist/routerstatus_st.h" /** Test the validation of HS v3 addresses */ static void @@ -364,11 +373,8 @@ mock_networkstatus_get_live_consensus(time_t now) static void test_responsible_hsdirs(void *arg) { - time_t now = approx_time(); smartlist_t *responsible_dirs = smartlist_new(); networkstatus_t *ns = NULL; - int retval; - (void) arg; hs_init(); @@ -390,12 +396,12 @@ test_responsible_hsdirs(void *arg) helper_add_hsdir_to_networkstatus(ns, 3, "spyro", 0); } - ed25519_keypair_t kp; - retval = ed25519_keypair_generate(&kp, 0); - tt_int_op(retval, OP_EQ , 0); + /* Use a fixed time period and pub key so we always take the same path */ + ed25519_public_key_t pubkey; + uint64_t time_period_num = 17653; // 2 May, 2018, 14:00. + memset(&pubkey, 42, sizeof(pubkey)); - uint64_t time_period_num = hs_get_time_period_num(now); - hs_get_responsible_hsdirs(&kp.pubkey, time_period_num, + hs_get_responsible_hsdirs(&pubkey, time_period_num, 0, 0, responsible_dirs); /* Make sure that we only found 2 responsible HSDirs. @@ -422,11 +428,13 @@ mock_directory_initiate_request(directory_request_t *req) static int mock_hs_desc_encode_descriptor(const hs_descriptor_t *desc, - const ed25519_keypair_t *signing_kp, - char **encoded_out) + const ed25519_keypair_t *signing_kp, + const uint8_t *descriptor_cookie, + char **encoded_out) { (void)desc; (void)signing_kp; + (void)descriptor_cookie; tor_asprintf(encoded_out, "lulu"); return 0; @@ -817,7 +825,7 @@ test_time_between_tp_and_srv(void *arg) tt_int_op(ret, OP_EQ, 0); ret = parse_rfc1123_time("Sat, 26 Oct 1985 01:00:00 UTC", &ns.fresh_until); tt_int_op(ret, OP_EQ, 0); - dirvote_recalculate_timing(get_options(), ns.valid_after); + voting_schedule_recalculate_timing(get_options(), ns.valid_after); ret = hs_in_period_between_tp_and_srv(&ns, 0); tt_int_op(ret, OP_EQ, 0); @@ -825,7 +833,7 @@ test_time_between_tp_and_srv(void *arg) tt_int_op(ret, OP_EQ, 0); ret = parse_rfc1123_time("Sat, 26 Oct 1985 12:00:00 UTC", &ns.fresh_until); tt_int_op(ret, OP_EQ, 0); - dirvote_recalculate_timing(get_options(), ns.valid_after); + voting_schedule_recalculate_timing(get_options(), ns.valid_after); ret = hs_in_period_between_tp_and_srv(&ns, 0); tt_int_op(ret, OP_EQ, 0); @@ -833,7 +841,7 @@ test_time_between_tp_and_srv(void *arg) tt_int_op(ret, OP_EQ, 0); ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC", &ns.fresh_until); tt_int_op(ret, OP_EQ, 0); - dirvote_recalculate_timing(get_options(), ns.valid_after); + voting_schedule_recalculate_timing(get_options(), ns.valid_after); ret = hs_in_period_between_tp_and_srv(&ns, 0); tt_int_op(ret, OP_EQ, 1); @@ -841,7 +849,7 @@ test_time_between_tp_and_srv(void *arg) tt_int_op(ret, OP_EQ, 0); ret = parse_rfc1123_time("Sat, 27 Oct 1985 00:00:00 UTC", &ns.fresh_until); tt_int_op(ret, OP_EQ, 0); - dirvote_recalculate_timing(get_options(), ns.valid_after); + voting_schedule_recalculate_timing(get_options(), ns.valid_after); ret = hs_in_period_between_tp_and_srv(&ns, 0); tt_int_op(ret, OP_EQ, 1); @@ -849,7 +857,7 @@ test_time_between_tp_and_srv(void *arg) tt_int_op(ret, OP_EQ, 0); ret = parse_rfc1123_time("Sat, 27 Oct 1985 01:00:00 UTC", &ns.fresh_until); tt_int_op(ret, OP_EQ, 0); - dirvote_recalculate_timing(get_options(), ns.valid_after); + voting_schedule_recalculate_timing(get_options(), ns.valid_after); ret = hs_in_period_between_tp_and_srv(&ns, 0); tt_int_op(ret, OP_EQ, 0); @@ -1336,7 +1344,12 @@ run_reachability_scenario(const reachability_cfg_t *cfg, int num_scenario) &mock_service_ns->valid_until); set_consensus_times(cfg->service_valid_until, &mock_service_ns->fresh_until); - dirvote_recalculate_timing(get_options(), mock_service_ns->valid_after); + voting_schedule_recalculate_timing(get_options(), + mock_service_ns->valid_after); + /* Check that service is in the right time period point */ + tt_int_op(hs_in_period_between_tp_and_srv(mock_service_ns, 0), OP_EQ, + cfg->service_in_new_tp); + /* Set client consensus time. */ set_consensus_times(cfg->client_valid_after, &mock_client_ns->valid_after); @@ -1344,11 +1357,9 @@ run_reachability_scenario(const reachability_cfg_t *cfg, int num_scenario) &mock_client_ns->valid_until); set_consensus_times(cfg->client_valid_until, &mock_client_ns->fresh_until); - dirvote_recalculate_timing(get_options(), mock_client_ns->valid_after); - - /* New time period checks for this scenario. */ - tt_int_op(hs_in_period_between_tp_and_srv(mock_service_ns, 0), OP_EQ, - cfg->service_in_new_tp); + voting_schedule_recalculate_timing(get_options(), + mock_client_ns->valid_after); + /* Check that client is in the right time period point */ tt_int_op(hs_in_period_between_tp_and_srv(mock_client_ns, 0), OP_EQ, cfg->client_in_new_tp); @@ -1359,7 +1370,8 @@ run_reachability_scenario(const reachability_cfg_t *cfg, int num_scenario) mock_service_ns->sr_info.previous_srv = cfg->service_previous_srv; /* Initialize a service to get keys. */ - service = helper_init_service(time(NULL)); + update_approx_time(mock_service_ns->valid_after); + service = helper_init_service(mock_service_ns->valid_after+1); /* * === Client setup === @@ -1568,7 +1580,7 @@ helper_set_consensus_and_system_time(networkstatus_t *ns, int position) } else { tt_assert(0); } - dirvote_recalculate_timing(get_options(), ns->valid_after); + voting_schedule_recalculate_timing(get_options(), ns->valid_after); /* Set system time: pretend to be just 2 minutes before consensus expiry */ real_time = ns->valid_until - 120; @@ -1825,4 +1837,3 @@ struct testcase_t hs_common_tests[] = { END_OF_TESTCASES }; - diff --git a/src/test/test_hs_config.c b/src/test/test_hs_config.c index a76be301d3..553b96758a 100644 --- a/src/test/test_hs_config.c +++ b/src/test/test_hs_config.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,15 +9,15 @@ #define CONFIG_PRIVATE #define HS_SERVICE_PRIVATE -#include "test.h" -#include "test_helpers.h" -#include "log_test_helpers.h" +#include "test/test.h" +#include "test/test_helpers.h" +#include "test/log_test_helpers.h" -#include "config.h" -#include "hs_common.h" -#include "hs_config.h" -#include "hs_service.h" -#include "rendservice.h" +#include "app/config/config.h" +#include "feature/hs/hs_common.h" +#include "feature/hs/hs_config.h" +#include "feature/hs/hs_service.h" +#include "feature/rend/rendservice.h" static int helper_config_service(const char *conf, int validate_only) @@ -139,6 +139,20 @@ test_invalid_service(void *arg) teardown_capture_of_logs(); } + /* Bad target addr:port separation. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 2\n" + "HiddenServicePort 80 127.0.0.1 8000\n"; + setup_full_capture_of_logs(LOG_WARN); + ret = helper_config_service(conf, 1); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("HiddenServicePort parse error: " + "invalid port mapping"); + teardown_capture_of_logs(); + } + /* Out of order directives. */ { const char *conf = diff --git a/src/test/test_hs_control.c b/src/test/test_hs_control.c index 207a55de6d..48402030bf 100644 --- a/src/test/test_hs_control.c +++ b/src/test/test_hs_control.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -7,23 +7,20 @@ **/ #define CONTROL_PRIVATE -#define CIRCUITBUILD_PRIVATE -#define RENDCOMMON_PRIVATE -#define RENDSERVICE_PRIVATE -#define HS_SERVICE_PRIVATE - -#include "or.h" -#include "test.h" -#include "control.h" -#include "config.h" -#include "hs_common.h" -#include "hs_control.h" -#include "nodelist.h" -//#include "rendcommon.h" -//#include "rendservice.h" -//#include "routerset.h" -//#include "circuitbuild.h" -#include "test_helpers.h" + +#include "core/or/or.h" +#include "test/test.h" +#include "feature/control/control.h" +#include "app/config/config.h" +#include "feature/hs/hs_common.h" +#include "feature/hs/hs_control.h" +#include "feature/nodelist/nodelist.h" + +#include "feature/nodelist/node_st.h" +#include "feature/nodelist/routerstatus_st.h" +#include "lib/crypt_ops/crypto_format.h" + +#include "test/test_helpers.h" /* mock ID digest and longname for node that's in nodelist */ #define HSDIR_EXIST_ID \ @@ -76,9 +73,8 @@ mock_node_get_by_id(const char *digest) { static node_t node; memcpy(node.identity, digest, DIGEST_LEN); - node.hsdir_index = tor_malloc_zero(sizeof(hsdir_index_t)); - memset(node.hsdir_index->fetch, 'C', DIGEST256_LEN); - memset(node.hsdir_index->store_first, 'D', DIGEST256_LEN); + memset(node.hsdir_index.fetch, 'C', DIGEST256_LEN); + memset(node.hsdir_index.store_first, 'D', DIGEST256_LEN); return &node; } @@ -196,4 +192,3 @@ struct testcase_t hs_control_tests[] = { END_OF_TESTCASES }; - diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c index 8772461f90..428ca1024b 100644 --- a/src/test/test_hs_descriptor.c +++ b/src/test/test_hs_descriptor.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -8,16 +8,19 @@ #define HS_DESCRIPTOR_PRIVATE -#include "crypto_ed25519.h" -#include "ed25519_cert.h" -#include "or.h" -#include "hs_descriptor.h" -#include "test.h" -#include "torcert.h" +#include "lib/crypt_ops/crypto_ed25519.h" +#include "lib/crypt_ops/crypto_format.h" +#include "lib/crypt_ops/crypto_digest.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "trunnel/ed25519_cert.h" +#include "core/or/or.h" +#include "feature/hs/hs_descriptor.h" +#include "test/test.h" +#include "feature/nodelist/torcert.h" -#include "hs_test_helpers.h" -#include "test_helpers.h" -#include "log_test_helpers.h" +#include "test/hs_test_helpers.h" +#include "test/test_helpers.h" +#include "test/log_test_helpers.h" #ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS DISABLE_GCC_WARNING(overlength-strings) @@ -27,6 +30,13 @@ DISABLE_GCC_WARNING(overlength-strings) #include "test_hs_descriptor.inc" ENABLE_GCC_WARNING(overlength-strings) +/* Mock function to fill all bytes with 1 */ +static void +mock_crypto_strongest_rand(uint8_t *out, size_t out_len) +{ + memset(out, 1, out_len); +} + /* Test certificate encoding put in a descriptor. */ static void test_cert_encoding(void *arg) @@ -281,7 +291,6 @@ static void test_encode_descriptor(void *arg) { int ret; - char *encoded = NULL; ed25519_keypair_t signing_kp; hs_descriptor_t *desc = NULL; @@ -290,19 +299,38 @@ test_encode_descriptor(void *arg) ret = ed25519_keypair_generate(&signing_kp, 0); tt_int_op(ret, OP_EQ, 0); desc = hs_helper_build_hs_desc_with_ip(&signing_kp); - ret = hs_desc_encode_descriptor(desc, &signing_kp, &encoded); - tt_int_op(ret, OP_EQ, 0); - tt_assert(encoded); + { + char *encoded = NULL; + ret = hs_desc_encode_descriptor(desc, &signing_kp, NULL, &encoded); + tt_int_op(ret, OP_EQ, 0); + tt_assert(encoded); + + tor_free(encoded); + } + + { + char *encoded = NULL; + uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN]; + + crypto_strongest_rand(descriptor_cookie, sizeof(descriptor_cookie)); + + ret = hs_desc_encode_descriptor(desc, &signing_kp, + descriptor_cookie, &encoded); + tt_int_op(ret, OP_EQ, 0); + tt_assert(encoded); + + tor_free(encoded); + } done: hs_descriptor_free(desc); - tor_free(encoded); } static void test_decode_descriptor(void *arg) { int ret; + int i; char *encoded = NULL; ed25519_keypair_t signing_kp; hs_descriptor_t *desc = NULL; @@ -320,14 +348,15 @@ test_decode_descriptor(void *arg) subcredential); /* Give some bad stuff to the decoding function. */ - ret = hs_desc_decode_descriptor("hladfjlkjadf", subcredential, &decoded); + ret = hs_desc_decode_descriptor("hladfjlkjadf", subcredential, + NULL, &decoded); tt_int_op(ret, OP_EQ, -1); - ret = hs_desc_encode_descriptor(desc, &signing_kp, &encoded); + ret = hs_desc_encode_descriptor(desc, &signing_kp, NULL, &encoded); tt_int_op(ret, OP_EQ, 0); tt_assert(encoded); - ret = hs_desc_decode_descriptor(encoded, subcredential, &decoded); + ret = hs_desc_decode_descriptor(encoded, subcredential, NULL, &decoded); tt_int_op(ret, OP_EQ, 0); tt_assert(decoded); @@ -343,13 +372,84 @@ test_decode_descriptor(void *arg) desc_no_ip = hs_helper_build_hs_desc_no_ip(&signing_kp_no_ip); tt_assert(desc_no_ip); tor_free(encoded); - ret = hs_desc_encode_descriptor(desc_no_ip, &signing_kp_no_ip, &encoded); + ret = hs_desc_encode_descriptor(desc_no_ip, &signing_kp_no_ip, + NULL, &encoded); + tt_int_op(ret, OP_EQ, 0); + tt_assert(encoded); + hs_descriptor_free(decoded); + ret = hs_desc_decode_descriptor(encoded, subcredential, NULL, &decoded); + tt_int_op(ret, OP_EQ, 0); + tt_assert(decoded); + } + + /* Decode a descriptor with auth clients. */ + { + uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN]; + curve25519_keypair_t auth_ephemeral_kp; + curve25519_keypair_t client_kp, invalid_client_kp; + smartlist_t *clients; + hs_desc_authorized_client_t *client, *fake_client; + client = tor_malloc_zero(sizeof(hs_desc_authorized_client_t)); + + /* Prepare all the keys needed to build the auth client. */ + curve25519_keypair_generate(&auth_ephemeral_kp, 0); + curve25519_keypair_generate(&client_kp, 0); + curve25519_keypair_generate(&invalid_client_kp, 0); + crypto_strongest_rand(descriptor_cookie, HS_DESC_DESCRIPTOR_COOKIE_LEN); + + memcpy(&desc->superencrypted_data.auth_ephemeral_pubkey, + &auth_ephemeral_kp.pubkey, CURVE25519_PUBKEY_LEN); + + hs_helper_get_subcred_from_identity_keypair(&signing_kp, + subcredential); + + /* Build and add the auth client to the descriptor. */ + clients = desc->superencrypted_data.clients; + if (!clients) { + clients = smartlist_new(); + } + hs_desc_build_authorized_client(subcredential, + &client_kp.pubkey, + &auth_ephemeral_kp.seckey, + descriptor_cookie, client); + smartlist_add(clients, client); + + /* We need to add fake auth clients here. */ + for (i=0; i < 15; ++i) { + fake_client = hs_desc_build_fake_authorized_client(); + smartlist_add(clients, fake_client); + } + desc->superencrypted_data.clients = clients; + + /* Test the encoding/decoding in the following lines. */ + tor_free(encoded); + ret = hs_desc_encode_descriptor(desc, &signing_kp, + descriptor_cookie, &encoded); tt_int_op(ret, OP_EQ, 0); tt_assert(encoded); + + /* If we do not have the client secret key, the decoding must fail. */ + hs_descriptor_free(decoded); + ret = hs_desc_decode_descriptor(encoded, subcredential, + NULL, &decoded); + tt_int_op(ret, OP_LT, 0); + tt_assert(!decoded); + + /* If we have an invalid client secret key, the decoding must fail. */ hs_descriptor_free(decoded); - ret = hs_desc_decode_descriptor(encoded, subcredential, &decoded); + ret = hs_desc_decode_descriptor(encoded, subcredential, + &invalid_client_kp.seckey, &decoded); + tt_int_op(ret, OP_LT, 0); + tt_assert(!decoded); + + /* If we have the client secret key, the decoding must succeed and the + * decoded descriptor must be correct. */ + ret = hs_desc_decode_descriptor(encoded, subcredential, + &client_kp.seckey, &decoded); tt_int_op(ret, OP_EQ, 0); tt_assert(decoded); + + hs_helper_desc_equal(desc, decoded); } done: @@ -575,6 +675,8 @@ test_decode_bad_signature(void *arg) (void) arg; + memset(&desc_plaintext, 0, sizeof(desc_plaintext)); + /* Update approx time to dodge cert expiration */ update_approx_time(1502661599); @@ -585,7 +687,7 @@ test_decode_bad_signature(void *arg) teardown_capture_of_logs(); done: - desc_plaintext_data_free_contents(&desc_plaintext); + hs_desc_plaintext_data_free_contents(&desc_plaintext); } static void @@ -761,101 +863,69 @@ test_desc_signature(void *arg) tor_free(data); } -/* bad desc auth type */ -static const char bad_superencrypted_text1[] = "desc-auth-type scoobysnack\n" - "desc-auth-ephemeral-key A/O8DVtnUheb3r1JqoB8uJB7wxXL1XJX3eny4yB+eFA=\n" - "auth-client oiNrQB8WwKo S5D02W7vKgiWIMygrBl8RQ FB//SfOBmLEx1kViEWWL1g\n" - "encrypted\n" - "-----BEGIN MESSAGE-----\n" - "YmVpbmcgb24gbW91bnRhaW5zLCB0aGlua2luZyBhYm91dCBjb21wdXRlcnMsIGlzIG5vdC" - "BiYWQgYXQgYWxs\n" - "-----END MESSAGE-----\n"; - -/* bad ephemeral key */ -static const char bad_superencrypted_text2[] = "desc-auth-type x25519\n" - "desc-auth-ephemeral-key differentalphabet\n" - "auth-client oiNrQB8WwKo S5D02W7vKgiWIMygrBl8RQ FB//SfOBmLEx1kViEWWL1g\n" - "encrypted\n" - "-----BEGIN MESSAGE-----\n" - "YmVpbmcgb24gbW91bnRhaW5zLCB0aGlua2luZyBhYm91dCBjb21wdXRlcnMsIGlzIG5vdC" - "BiYWQgYXQgYWxs\n" - "-----END MESSAGE-----\n"; - -/* bad encrypted msg */ -static const char bad_superencrypted_text3[] = "desc-auth-type x25519\n" - "desc-auth-ephemeral-key A/O8DVtnUheb3r1JqoB8uJB7wxXL1XJX3eny4yB+eFA=\n" - "auth-client oiNrQB8WwKo S5D02W7vKgiWIMygrBl8RQ FB//SfOBmLEx1kViEWWL1g\n" - "encrypted\n" - "-----BEGIN MESSAGE-----\n" - "SO SMALL NOT GOOD\n" - "-----END MESSAGE-----\n"; - -static const char correct_superencrypted_text[] = "desc-auth-type x25519\n" - "desc-auth-ephemeral-key A/O8DVtnUheb3r1JqoB8uJB7wxXL1XJX3eny4yB+eFA=\n" - "auth-client oiNrQB8WwKo S5D02W7vKgiWIMygrBl8RQ FB//SfOBmLEx1kViEWWL1g\n" - "auth-client Od09Qu636Qo /PKLzqewAdS/+0+vZC+MvQ dpw4NFo13zDnuPz45rxrOg\n" - "auth-client JRr840iGYN0 8s8cxYqF7Lx23+NducC4Qg zAafl4wPLURkuEjJreZq1g\n" - "encrypted\n" - "-----BEGIN MESSAGE-----\n" - "YmVpbmcgb24gbW91bnRhaW5zLCB0aGlua2luZyBhYm91dCBjb21wdXRlcnMsIGlzIG5vdC" - "BiYWQgYXQgYWxs\n" - "-----END MESSAGE-----\n"; - -static const char correct_encrypted_plaintext[] = "being on mountains, " - "thinking about computers, is not bad at all"; - static void -test_parse_hs_desc_superencrypted(void *arg) +test_build_authorized_client(void *arg) { + int ret; + hs_desc_authorized_client_t *desc_client = NULL; + uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN]; + curve25519_secret_key_t auth_ephemeral_sk; + curve25519_secret_key_t client_auth_sk; + curve25519_public_key_t client_auth_pk; + const char ephemeral_sk_b16[] = + "d023b674d993a5c8446bd2ca97e9961149b3c0e88c7dc14e8777744dd3468d6a"; + const char descriptor_cookie_b16[] = + "07d087f1d8c68393721f6e70316d3b29"; + const char client_pubkey_b16[] = + "8c1298fa6050e372f8598f6deca32e27b0ad457741422c2629ebb132cf7fae37"; + uint8_t subcredential[DIGEST256_LEN]; + char *mem_op_hex_tmp=NULL; + (void) arg; - size_t retval; - uint8_t *encrypted_out = NULL; - { - setup_full_capture_of_logs(LOG_WARN); - retval = decode_superencrypted(bad_superencrypted_text1, - strlen(bad_superencrypted_text1), - &encrypted_out); - tt_u64_op(retval, OP_EQ, 0); - tt_ptr_op(encrypted_out, OP_EQ, NULL); - expect_log_msg_containing("Unrecognized desc auth type"); - teardown_capture_of_logs(); - } + ret = curve25519_secret_key_generate(&auth_ephemeral_sk, 0); + tt_int_op(ret, OP_EQ, 0); - { - setup_full_capture_of_logs(LOG_WARN); - retval = decode_superencrypted(bad_superencrypted_text2, - strlen(bad_superencrypted_text2), - &encrypted_out); - tt_u64_op(retval, OP_EQ, 0); - tt_ptr_op(encrypted_out, OP_EQ, NULL); - expect_log_msg_containing("Bogus desc auth key in HS desc"); - teardown_capture_of_logs(); - } + ret = curve25519_secret_key_generate(&client_auth_sk, 0); + tt_int_op(ret, OP_EQ, 0); + curve25519_public_key_generate(&client_auth_pk, &client_auth_sk); - { - setup_full_capture_of_logs(LOG_WARN); - retval = decode_superencrypted(bad_superencrypted_text3, - strlen(bad_superencrypted_text3), - &encrypted_out); - tt_u64_op(retval, OP_EQ, 0); - tt_ptr_op(encrypted_out, OP_EQ, NULL); - expect_log_msg_containing("Length of descriptor\'s encrypted data " - "is too small."); - teardown_capture_of_logs(); - } + memset(subcredential, 42, sizeof(subcredential)); + + desc_client = tor_malloc_zero(sizeof(hs_desc_authorized_client_t)); - /* Now finally the good one */ - retval = decode_superencrypted(correct_superencrypted_text, - strlen(correct_superencrypted_text), - &encrypted_out); + base16_decode((char *) &auth_ephemeral_sk, + sizeof(auth_ephemeral_sk), + ephemeral_sk_b16, + strlen(ephemeral_sk_b16)); - tt_u64_op(retval, OP_EQ, strlen(correct_encrypted_plaintext)); - tt_mem_op(encrypted_out, OP_EQ, correct_encrypted_plaintext, - strlen(correct_encrypted_plaintext)); + base16_decode((char *) descriptor_cookie, + sizeof(descriptor_cookie), + descriptor_cookie_b16, + strlen(descriptor_cookie_b16)); + + base16_decode((char *) &client_auth_pk, + sizeof(client_auth_pk), + client_pubkey_b16, + strlen(client_pubkey_b16)); + + MOCK(crypto_strongest_rand_, mock_crypto_strongest_rand); + + hs_desc_build_authorized_client(subcredential, + &client_auth_pk, &auth_ephemeral_sk, + descriptor_cookie, desc_client); + + test_memeq_hex((char *) desc_client->client_id, + "EC19B7FF4D2DDA13"); + test_memeq_hex((char *) desc_client->iv, + "01010101010101010101010101010101"); + test_memeq_hex((char *) desc_client->encrypted_cookie, + "B21222BE13F385F355BD07B2381F9F29"); done: - tor_free(encrypted_out); + tor_free(desc_client); + tor_free(mem_op_hex_tmp); + UNMOCK(crypto_strongest_rand_); } struct testcase_t hs_descriptor[] = { @@ -888,10 +958,8 @@ struct testcase_t hs_descriptor[] = { NULL, NULL }, { "desc_signature", test_desc_signature, TT_FORK, NULL, NULL }, - - { "parse_hs_desc_superencrypted", test_parse_hs_desc_superencrypted, - TT_FORK, NULL, NULL }, + { "build_authorized_client", test_build_authorized_client, TT_FORK, + NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_hs_intropoint.c b/src/test/test_hs_intropoint.c index ec4dcb4705..628d99bfde 100644 --- a/src/test/test_hs_intropoint.c +++ b/src/test/test_hs_intropoint.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -11,28 +11,29 @@ #define RENDSERVICE_PRIVATE #define CIRCUITLIST_PRIVATE -#include "test.h" -#include "log_test_helpers.h" -#include "crypto.h" -#include "log_test_helpers.h" +#include "test/test.h" +#include "test/log_test_helpers.h" +#include "lib/crypt_ops/crypto_rand.h" -#include "or.h" -#include "circuitlist.h" -#include "circuituse.h" +#include "core/or/or.h" +#include "core/or/circuitlist.h" +#include "core/or/circuituse.h" #include "ht.h" -#include "relay.h" -#include "rendservice.h" +#include "core/or/relay.h" +#include "feature/rend/rendservice.h" -#include "hs_cell.h" -#include "hs_circuitmap.h" -#include "hs_common.h" -#include "hs_intropoint.h" -#include "hs_service.h" +#include "feature/hs/hs_cell.h" +#include "feature/hs/hs_circuitmap.h" +#include "feature/hs/hs_common.h" +#include "feature/hs/hs_intropoint.h" +#include "feature/hs/hs_service.h" + +#include "core/or/or_circuit_st.h" /* Trunnel. */ -#include "hs/cell_establish_intro.h" -#include "hs/cell_introduce1.h" -#include "hs/cell_common.h" +#include "trunnel/hs/cell_establish_intro.h" +#include "trunnel/hs/cell_introduce1.h" +#include "trunnel/hs/cell_common.h" static size_t new_establish_intro_cell(const char *circ_nonce, diff --git a/src/test/test_hs_ntor.c b/src/test/test_hs_ntor.c index 8eee54d4b4..eeb0491657 100644 --- a/src/test/test_hs_ntor.c +++ b/src/test/test_hs_ntor.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -6,11 +6,13 @@ * \brief Test hidden service ntor functionality. */ -#include "test.h" -#include "test_helpers.h" -#include "log_test_helpers.h" +#include "test/test.h" +#include "test/test_helpers.h" +#include "test/log_test_helpers.h" +#include "lib/crypt_ops/crypto_curve25519.h" +#include "lib/crypt_ops/crypto_ed25519.h" -#include "hs_ntor.h" +#include "core/crypto/hs_ntor.h" /* Test the HS ntor handshake. Simulate the sending of an encrypted INTRODUCE1 * cell, and verify the proper derivation of decryption keys on the other end. @@ -111,4 +113,3 @@ struct testcase_t hs_ntor_tests[] = { END_OF_TESTCASES }; - diff --git a/src/test/test_hs_ntor_cl.c b/src/test/test_hs_ntor_cl.c index ed1eda58ea..a4915c4f8a 100644 --- a/src/test/test_hs_ntor_cl.c +++ b/src/test/test_hs_ntor_cl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** This is a wrapper over the little-t-tor HS ntor functions. The wrapper is @@ -13,13 +13,14 @@ #include <stdlib.h> #define ONION_NTOR_PRIVATE -#include "or.h" -#include "util.h" -#include "compat.h" -#include "crypto.h" -#include "crypto_curve25519.h" -#include "hs_ntor.h" -#include "onion_ntor.h" +#include "core/or/or.h" +#include "lib/crypt_ops/crypto_cipher.h" +#include "lib/crypt_ops/crypto_curve25519.h" +#include "lib/crypt_ops/crypto_ed25519.h" +#include "lib/crypt_ops/crypto_format.h" +#include "lib/crypt_ops/crypto_init.h" +#include "core/crypto/hs_ntor.h" +#include "core/crypto/onion_ntor.h" #define N_ARGS(n) STMT_BEGIN { \ if (argc < (n)) { \ @@ -240,7 +241,11 @@ main(int argc, char **argv) return 1; } + init_logging(1); curve25519_init(); + if (crypto_global_init(0, NULL, NULL) < 0) + return 1; + if (!strcmp(argv[1], "client1")) { return client1(argc, argv); } else if (!strcmp(argv[1], "server1")) { @@ -252,4 +257,3 @@ main(int argc, char **argv) return 1; } } - diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c index c1e9f3ced6..bfe50eb3c6 100644 --- a/src/test/test_hs_service.c +++ b/src/test/test_hs_service.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -10,51 +10,71 @@ #define CIRCUITLIST_PRIVATE #define CONFIG_PRIVATE #define CONNECTION_PRIVATE +#define CONNECTION_EDGE_PRIVATE #define CRYPTO_PRIVATE #define HS_COMMON_PRIVATE #define HS_SERVICE_PRIVATE #define HS_INTROPOINT_PRIVATE #define HS_CIRCUIT_PRIVATE -#define MAIN_PRIVATE +#define MAINLOOP_PRIVATE #define NETWORKSTATUS_PRIVATE #define STATEFILE_PRIVATE #define TOR_CHANNEL_INTERNAL_ #define HS_CLIENT_PRIVATE -#define ROUTERPARSE_PRIVATE - -#include "test.h" -#include "test_helpers.h" -#include "log_test_helpers.h" -#include "rend_test_helpers.h" -#include "hs_test_helpers.h" - -#include "or.h" -#include "config.h" -#include "circuitbuild.h" -#include "circuitlist.h" -#include "circuituse.h" -#include "crypto.h" -#include "dirvote.h" -#include "networkstatus.h" -#include "nodelist.h" -#include "relay.h" -#include "routerparse.h" - -#include "hs_common.h" -#include "hs_config.h" -#include "hs_ident.h" -#include "hs_intropoint.h" -#include "hs_ntor.h" -#include "hs_circuit.h" -#include "hs_service.h" -#include "hs_client.h" -#include "main.h" -#include "rendservice.h" -#include "statefile.h" -#include "shared_random_state.h" + +#include "test/test.h" +#include "test/test_helpers.h" +#include "test/log_test_helpers.h" +#include "test/rend_test_helpers.h" +#include "test/hs_test_helpers.h" + +#include "core/or/or.h" +#include "app/config/config.h" +#include "app/config/statefile.h" +#include "core/crypto/hs_ntor.h" +#include "core/mainloop/connection.h" +#include "core/mainloop/mainloop.h" +#include "core/or/circuitbuild.h" +#include "core/or/circuitlist.h" +#include "core/or/circuituse.h" +#include "core/or/connection_edge.h" +#include "core/or/edge_connection_st.h" +#include "core/or/relay.h" +#include "core/or/versions.h" +#include "feature/dirauth/dirvote.h" +#include "feature/dirauth/shared_random_state.h" +#include "feature/dircommon/voting_schedule.h" +#include "feature/hs/hs_circuit.h" +#include "feature/hs/hs_circuitmap.h" +#include "feature/hs/hs_client.h" +#include "feature/hs/hs_common.h" +#include "feature/hs/hs_config.h" +#include "feature/hs/hs_ident.h" +#include "feature/hs/hs_intropoint.h" +#include "feature/hs/hs_service.h" +#include "feature/nodelist/networkstatus.h" +#include "feature/nodelist/nodelist.h" +#include "feature/rend/rendservice.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "lib/fs/dir.h" + +#include "core/or/cpath_build_state_st.h" +#include "core/or/crypt_path_st.h" +#include "feature/nodelist/networkstatus_st.h" +#include "feature/nodelist/node_st.h" +#include "core/or/origin_circuit_st.h" +#include "app/config/or_state_st.h" +#include "feature/nodelist/routerinfo_st.h" /* Trunnel */ -#include "hs/cell_establish_intro.h" +#include "trunnel/hs/cell_establish_intro.h" + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif static networkstatus_t mock_ns; @@ -173,12 +193,12 @@ test_e2e_rend_circuit_setup(void *arg) tt_int_op(retval, OP_EQ, 1); /* Check the digest algo */ - tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->f_digest), + tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.f_digest), OP_EQ, DIGEST_SHA3_256); - tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->b_digest), + tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.b_digest), OP_EQ, DIGEST_SHA3_256); - tt_assert(or_circ->cpath->f_crypto); - tt_assert(or_circ->cpath->b_crypto); + tt_assert(or_circ->cpath->crypto.f_crypto); + tt_assert(or_circ->cpath->crypto.b_crypto); /* Ensure that circ purpose was changed */ tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_S_REND_JOINED); @@ -211,6 +231,40 @@ helper_create_origin_circuit(int purpose, int flags) return circ; } +/* Helper: Return a newly allocated authorized client object with + * and a newly generated public key. */ +static hs_service_authorized_client_t * +helper_create_authorized_client(void) +{ + int ret; + hs_service_authorized_client_t *client; + curve25519_secret_key_t seckey; + client = tor_malloc_zero(sizeof(hs_service_authorized_client_t)); + + ret = curve25519_secret_key_generate(&seckey, 0); + tt_int_op(ret, OP_EQ, 0); + curve25519_public_key_generate(&client->client_pk, &seckey); + + done: + return client; +} + +/* Helper: Return a newly allocated authorized client object with the + * same client name and the same public key as the given client. */ +static hs_service_authorized_client_t * +helper_clone_authorized_client(const hs_service_authorized_client_t *client) +{ + hs_service_authorized_client_t *client_out; + + tor_assert(client); + + client_out = tor_malloc_zero(sizeof(hs_service_authorized_client_t)); + memcpy(client_out->client_pk.public_key, + client->client_pk.public_key, CURVE25519_PUBKEY_LEN); + + return client_out; +} + /* Helper: Return a newly allocated service object with the identity keypair * sets and the current descriptor. Then register it to the global map. * Caller should us hs_free_all() to free this service or remove it from the @@ -235,6 +289,26 @@ helper_create_service(void) return service; } +/* Helper: Return a newly allocated service object with clients. */ +static hs_service_t * +helper_create_service_with_clients(int num_clients) +{ + int i; + hs_service_t *service = helper_create_service(); + tt_assert(service); + service->config.is_client_auth_enabled = 1; + service->config.clients = smartlist_new(); + + for (i = 0; i < num_clients; i++) { + hs_service_authorized_client_t *client; + client = helper_create_authorized_client(); + smartlist_add(service->config.clients, client); + } + + done: + return service; +} + /* Helper: Return a newly allocated service intro point with two link * specifiers, one IPv4 and one legacy ID set to As. */ static hs_service_intro_point_t * @@ -294,6 +368,8 @@ test_load_keys(void *arg) /* It's in staging? */ tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1); +#undef conf_fmt + /* Load the keys for these. After that, the v3 service should be registered * in the global map. */ hs_service_load_all_keys(); @@ -313,6 +389,9 @@ test_load_keys(void *arg) tt_int_op(hs_address_is_valid(addr), OP_EQ, 1); tt_str_op(addr, OP_EQ, s->onion_address); + /* Check that the is_client_auth_enabled is not set. */ + tt_assert(!s->config.is_client_auth_enabled); + done: tor_free(hsdir_v2); tor_free(hsdir_v3); @@ -320,6 +399,183 @@ test_load_keys(void *arg) } static void +test_client_filename_is_valid(void *arg) +{ + (void) arg; + + /* Valid file name. */ + tt_assert(client_filename_is_valid("a.auth")); + /* Valid file name with special character. */ + tt_assert(client_filename_is_valid("a-.auth")); + /* Invalid extension. */ + tt_assert(!client_filename_is_valid("a.ath")); + /* Nothing before the extension. */ + tt_assert(!client_filename_is_valid(".auth")); + + done: + ; +} + +static void +test_parse_authorized_client(void *arg) +{ + hs_service_authorized_client_t *client = NULL; + + (void) arg; + + /* Valid authorized client. */ + client = parse_authorized_client( + "descriptor:x25519:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"); + tt_assert(client); + + /* Wrong number of fields. */ + tt_assert(!parse_authorized_client("a:b:c:d:e")); + /* Wrong auth type. */ + tt_assert(!parse_authorized_client( + "x:x25519:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja")); + /* Wrong key type. */ + tt_assert(!parse_authorized_client( + "descriptor:x:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja")); + /* Some malformed string. */ + tt_assert(!parse_authorized_client("descriptor:x25519:aa==")); + tt_assert(!parse_authorized_client("descriptor:")); + tt_assert(!parse_authorized_client("descriptor:x25519")); + tt_assert(!parse_authorized_client("descriptor:x25519:")); + tt_assert(!parse_authorized_client("")); + + done: + service_authorized_client_free(client); +} + +static char * +mock_read_file_to_str(const char *filename, int flags, struct stat *stat_out) +{ + char *ret = NULL; + + (void) flags; + (void) stat_out; + + if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR + "authorized_clients" PATH_SEPARATOR + "client1.auth"))) { + ret = tor_strdup("descriptor:x25519:" + "dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"); + goto done; + } + + if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR + "authorized_clients" PATH_SEPARATOR + "dummy.xxx"))) { + ret = tor_strdup("descriptor:x25519:" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); + goto done; + } + + if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR + "authorized_clients" PATH_SEPARATOR + "client2.auth"))) { + ret = tor_strdup("descriptor:x25519:" + "okoi2gml3wd6x7jganlk5d66xxyjgg24sxw4y7javx4giqr66zta"); + goto done; + } + + done: + return ret; +} + +static smartlist_t * +mock_tor_listdir(const char *dirname) +{ + smartlist_t *file_list = smartlist_new(); + + (void) dirname; + + smartlist_add(file_list, tor_strdup("client1.auth")); + smartlist_add(file_list, tor_strdup("dummy.xxx")); + smartlist_add(file_list, tor_strdup("client2.auth")); + + return file_list; +} + +static void +test_load_keys_with_client_auth(void *arg) +{ + int ret; + char *conf = NULL; + smartlist_t *pubkey_b32_list = smartlist_new(); + char *hsdir_v3 = tor_strdup(get_fname("hs3")); + hs_service_t *service; + + (void) arg; + + hs_init(); + smartlist_add(pubkey_b32_list, tor_strdup( + "dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja")); + smartlist_add(pubkey_b32_list, tor_strdup( + "okoi2gml3wd6x7jganlk5d66xxyjgg24sxw4y7javx4giqr66zta")); + +#define conf_fmt \ + "HiddenServiceDir %s\n" \ + "HiddenServiceVersion %d\n" \ + "HiddenServicePort 65534\n" + + tor_asprintf(&conf, conf_fmt, hsdir_v3, HS_VERSION_THREE); + ret = helper_config_service(conf); + tor_free(conf); + tt_int_op(ret, OP_EQ, 0); + /* It's in staging? */ + tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1); + +#undef conf_fmt + + MOCK(read_file_to_str, mock_read_file_to_str); + MOCK(tor_listdir, mock_tor_listdir); + + /* Load the keys for these. After that, the v3 service should be registered + * in the global map. */ + hs_service_load_all_keys(); + tt_int_op(get_hs_service_map_size(), OP_EQ, 1); + + service = get_first_service(); + tt_assert(service); + tt_assert(service->config.clients); + tt_int_op(smartlist_len(service->config.clients), OP_EQ, + smartlist_len(pubkey_b32_list)); + + /* Test that the is_client_auth_enabled flag is set. */ + tt_assert(service->config.is_client_auth_enabled); + + /* Test that the keys in clients are correct. */ + SMARTLIST_FOREACH_BEGIN(pubkey_b32_list, char *, pubkey_b32) { + + curve25519_public_key_t pubkey; + /* This flag will be set if the key is found in clients. */ + int is_found = 0; + base32_decode((char *) pubkey.public_key, sizeof(pubkey.public_key), + pubkey_b32, strlen(pubkey_b32)); + + SMARTLIST_FOREACH_BEGIN(service->config.clients, + hs_service_authorized_client_t *, client) { + if (tor_memeq(&pubkey, &client->client_pk, sizeof(pubkey))) { + is_found = 1; + break; + } + } SMARTLIST_FOREACH_END(client); + + tt_assert(is_found); + + } SMARTLIST_FOREACH_END(pubkey_b32); + + done: + SMARTLIST_FOREACH(pubkey_b32_list, char *, s, tor_free(s)); + smartlist_free(pubkey_b32_list); + tor_free(hsdir_v3); + hs_free_all(); + UNMOCK(read_file_to_str); + UNMOCK(tor_listdir); +} + +static void test_access_service(void *arg) { int ret; @@ -492,6 +748,8 @@ test_helper_functions(void *arg) MOCK(node_get_by_id, mock_node_get_by_id); hs_service_init(); + time_t now = time(NULL); + update_approx_time(now); service = helper_create_service(); @@ -551,7 +809,6 @@ test_helper_functions(void *arg) /* Testing can_service_launch_intro_circuit() */ { - time_t now = time(NULL); /* Put the start of the retry period back in time, we should be allowed. * to launch intro circuit. */ service->state.num_intro_circ_launched = 2; @@ -575,7 +832,6 @@ test_helper_functions(void *arg) /* Testing intro_point_should_expire(). */ { - time_t now = time(NULL); /* Just some basic test of the current state. */ tt_u64_op(ip->introduce2_max, OP_GE, INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS); @@ -1035,7 +1291,7 @@ static void test_rotate_descriptors(void *arg) { int ret; - time_t next_rotation_time, now = time(NULL); + time_t next_rotation_time, now; hs_service_t *service; hs_service_descriptor_t *desc_next; @@ -1057,7 +1313,10 @@ test_rotate_descriptors(void *arg) ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC", &mock_ns.fresh_until); tt_int_op(ret, OP_EQ, 0); - dirvote_recalculate_timing(get_options(), mock_ns.valid_after); + voting_schedule_recalculate_timing(get_options(), mock_ns.valid_after); + + update_approx_time(mock_ns.valid_after+1); + now = mock_ns.valid_after+1; /* Create a service with a default descriptor and state. It's added to the * global map. */ @@ -1095,7 +1354,10 @@ test_rotate_descriptors(void *arg) ret = parse_rfc1123_time("Sat, 27 Oct 1985 02:00:00 UTC", &mock_ns.fresh_until); tt_int_op(ret, OP_EQ, 0); - dirvote_recalculate_timing(get_options(), mock_ns.valid_after); + voting_schedule_recalculate_timing(get_options(), mock_ns.valid_after); + + update_approx_time(mock_ns.valid_after+1); + now = mock_ns.valid_after+1; /* Note down what to expect for the next rotation time which is 01:00 + 23h * meaning 00:00:00. */ @@ -1157,7 +1419,10 @@ test_build_update_descriptors(void *arg) ret = parse_rfc1123_time("Sat, 26 Oct 1985 04:00:00 UTC", &mock_ns.fresh_until); tt_int_op(ret, OP_EQ, 0); - dirvote_recalculate_timing(get_options(), mock_ns.valid_after); + voting_schedule_recalculate_timing(get_options(), mock_ns.valid_after); + + update_approx_time(mock_ns.valid_after+1); + now = mock_ns.valid_after+1; /* Create a service without a current descriptor to trigger a build. */ service = helper_create_service(); @@ -1220,7 +1485,7 @@ test_build_update_descriptors(void *arg) tt_int_op(ret, OP_EQ, 0); ri.onion_curve25519_pkey = tor_malloc_zero(sizeof(curve25519_public_key_t)); - ri.onion_pkey = crypto_pk_new(); + ri.onion_pkey = tor_malloc_zero(140); curve25519_public_key_generate(ri.onion_curve25519_pkey, &curve25519_secret_key); memset(ri.cache_info.identity_digest, 'A', DIGEST_LEN); @@ -1237,7 +1502,7 @@ test_build_update_descriptors(void *arg) node->is_running = node->is_valid = node->is_fast = node->is_stable = 1; } - /* We have to set thise, or the lack of microdescriptors for these + /* We have to set this, or the lack of microdescriptors for these * nodes will make them unusable. */ get_options_mutable()->UseMicrodescriptors = 0; @@ -1246,7 +1511,7 @@ test_build_update_descriptors(void *arg) update_all_descriptors(now); tor_free(node->ri->onion_curve25519_pkey); /* Avoid memleak. */ tor_free(node->ri->cache_info.signing_key_cert); - crypto_pk_free(node->ri->onion_pkey); + tor_free(node->ri->onion_pkey); expect_log_msg_containing("just picked 1 intro points and wanted 3 for next " "descriptor. It currently has 0 intro points. " "Launching ESTABLISH_INTRO circuit shortly."); @@ -1300,6 +1565,9 @@ test_build_update_descriptors(void *arg) &mock_ns.fresh_until); tt_int_op(ret, OP_EQ, 0); + update_approx_time(mock_ns.valid_after+1); + now = mock_ns.valid_after+1; + /* Create a service without a current descriptor to trigger a build. */ service = helper_create_service(); tt_assert(service); @@ -1350,11 +1618,95 @@ test_build_update_descriptors(void *arg) nodelist_free_all(); } +/** Test building descriptors. We use this separate function instead of + * using test_build_update_descriptors because that function is too complex + * and also too interactive. */ static void -test_upload_descriptors(void *arg) +test_build_descriptors(void *arg) { int ret; time_t now = time(NULL); + + (void) arg; + + hs_init(); + + MOCK(get_or_state, + get_or_state_replacement); + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus); + + dummy_state = tor_malloc_zero(sizeof(or_state_t)); + + ret = parse_rfc1123_time("Sat, 26 Oct 1985 03:00:00 UTC", + &mock_ns.valid_after); + tt_int_op(ret, OP_EQ, 0); + ret = parse_rfc1123_time("Sat, 26 Oct 1985 04:00:00 UTC", + &mock_ns.fresh_until); + tt_int_op(ret, OP_EQ, 0); + voting_schedule_recalculate_timing(get_options(), mock_ns.valid_after); + + /* Generate a valid number of fake auth clients when a client authorization + * is disabled. */ + { + hs_service_t *service = helper_create_service(); + service_descriptor_free(service->desc_current); + service->desc_current = NULL; + + build_all_descriptors(now); + hs_desc_superencrypted_data_t *superencrypted; + superencrypted = &service->desc_current->desc->superencrypted_data; + tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 16); + } + + /* Generate a valid number of fake auth clients when the number of + * clients is zero. */ + { + hs_service_t *service = helper_create_service_with_clients(0); + service_descriptor_free(service->desc_current); + service->desc_current = NULL; + + build_all_descriptors(now); + hs_desc_superencrypted_data_t *superencrypted; + superencrypted = &service->desc_current->desc->superencrypted_data; + tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 16); + } + + /* Generate a valid number of fake auth clients when the number of + * clients is not a multiple of 16. */ + { + hs_service_t *service = helper_create_service_with_clients(20); + service_descriptor_free(service->desc_current); + service->desc_current = NULL; + + build_all_descriptors(now); + hs_desc_superencrypted_data_t *superencrypted; + superencrypted = &service->desc_current->desc->superencrypted_data; + tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 32); + } + + /* Do not generate any fake desc client when the number of clients is + * a multiple of 16 but not zero. */ + { + hs_service_t *service = helper_create_service_with_clients(32); + service_descriptor_free(service->desc_current); + service->desc_current = NULL; + + build_all_descriptors(now); + hs_desc_superencrypted_data_t *superencrypted; + superencrypted = &service->desc_current->desc->superencrypted_data; + tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 32); + } + + done: + hs_free_all(); +} + +static void +test_upload_descriptors(void *arg) +{ + int ret; + time_t now; hs_service_t *service; (void) arg; @@ -1373,6 +1725,10 @@ test_upload_descriptors(void *arg) ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC", &mock_ns.fresh_until); tt_int_op(ret, OP_EQ, 0); + voting_schedule_recalculate_timing(get_options(), mock_ns.valid_after); + + update_approx_time(mock_ns.valid_after+1); + now = mock_ns.valid_after+1; /* Create a service with no descriptor. It's added to the global map. */ service = hs_service_new(get_options()); @@ -1407,66 +1763,6 @@ test_upload_descriptors(void *arg) UNMOCK(get_or_state); } -/** Test the functions that save and load HS revision counters to state. */ -static void -test_revision_counter_state(void *arg) -{ - char *state_line_one = NULL; - char *state_line_two = NULL; - - hs_service_descriptor_t *desc_one = service_descriptor_new(); - hs_service_descriptor_t *desc_two = service_descriptor_new(); - - (void) arg; - - /* Prepare both descriptors */ - desc_one->desc->plaintext_data.revision_counter = 42; - desc_two->desc->plaintext_data.revision_counter = 240; - memset(&desc_one->blinded_kp.pubkey.pubkey, 66, - sizeof(desc_one->blinded_kp.pubkey.pubkey)); - memset(&desc_two->blinded_kp.pubkey.pubkey, 240, - sizeof(desc_one->blinded_kp.pubkey.pubkey)); - - /* Turn the descriptor rev counters into state lines */ - state_line_one = encode_desc_rev_counter_for_state(desc_one); - tt_str_op(state_line_one, OP_EQ, - "QkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkI 42"); - - state_line_two = encode_desc_rev_counter_for_state(desc_two); - tt_str_op(state_line_two, OP_EQ, - "8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PA 240"); - - /* Now let's test our state parsing function: */ - int service_found; - uint64_t cached_rev_counter; - - /* First's try with wrong pubkey and check that no service was found */ - cached_rev_counter =check_state_line_for_service_rev_counter(state_line_one, - &desc_two->blinded_kp.pubkey, - &service_found); - tt_int_op(service_found, OP_EQ, 0); - tt_u64_op(cached_rev_counter, OP_EQ, 0); - - /* Now let's try with the right pubkeys */ - cached_rev_counter =check_state_line_for_service_rev_counter(state_line_one, - &desc_one->blinded_kp.pubkey, - &service_found); - tt_int_op(service_found, OP_EQ, 1); - tt_u64_op(cached_rev_counter, OP_EQ, 42); - - cached_rev_counter =check_state_line_for_service_rev_counter(state_line_two, - &desc_two->blinded_kp.pubkey, - &service_found); - tt_int_op(service_found, OP_EQ, 1); - tt_u64_op(cached_rev_counter, OP_EQ, 240); - - done: - tor_free(state_line_one); - tor_free(state_line_two); - service_descriptor_free(desc_one); - service_descriptor_free(desc_two); -} - /** Global vars used by test_rendezvous1_parsing() */ static char rend1_payload[RELAY_PAYLOAD_SIZE]; static size_t rend1_payload_len = 0; @@ -1591,11 +1887,227 @@ test_rendezvous1_parsing(void *arg) UNMOCK(relay_send_command_from_edge_); } +static void +test_authorized_client_config_equal(void *arg) +{ + int ret; + hs_service_config_t *config1, *config2; + + (void) arg; + + config1 = tor_malloc_zero(sizeof(*config1)); + config2 = tor_malloc_zero(sizeof(*config2)); + + /* Both configs are empty. */ + { + config1->clients = smartlist_new(); + config2->clients = smartlist_new(); + + ret = service_authorized_client_config_equal(config1, config2); + tt_int_op(ret, OP_EQ, 1); + + service_clear_config(config1); + service_clear_config(config2); + } + + /* Both configs have exactly the same client config. */ + { + config1->clients = smartlist_new(); + config2->clients = smartlist_new(); + + hs_service_authorized_client_t *client1, *client2; + client1 = helper_create_authorized_client(); + client2 = helper_create_authorized_client(); + + smartlist_add(config1->clients, client1); + smartlist_add(config1->clients, client2); + + /* We should swap the order of clients here to test that the order + * does not matter. */ + smartlist_add(config2->clients, helper_clone_authorized_client(client2)); + smartlist_add(config2->clients, helper_clone_authorized_client(client1)); + + ret = service_authorized_client_config_equal(config1, config2); + tt_int_op(ret, OP_EQ, 1); + + service_clear_config(config1); + service_clear_config(config2); + } + + /* The numbers of clients in both configs are not equal. */ + { + config1->clients = smartlist_new(); + config2->clients = smartlist_new(); + + hs_service_authorized_client_t *client1, *client2; + client1 = helper_create_authorized_client(); + client2 = helper_create_authorized_client(); + + smartlist_add(config1->clients, client1); + smartlist_add(config1->clients, client2); + + smartlist_add(config2->clients, helper_clone_authorized_client(client1)); + + ret = service_authorized_client_config_equal(config1, config2); + tt_int_op(ret, OP_EQ, 0); + + service_clear_config(config1); + service_clear_config(config2); + } + + /* The first config has two distinct clients while the second config + * has two clients but they are duplicate. */ + { + config1->clients = smartlist_new(); + config2->clients = smartlist_new(); + + hs_service_authorized_client_t *client1, *client2; + client1 = helper_create_authorized_client(); + client2 = helper_create_authorized_client(); + + smartlist_add(config1->clients, client1); + smartlist_add(config1->clients, client2); + + smartlist_add(config2->clients, helper_clone_authorized_client(client1)); + smartlist_add(config2->clients, helper_clone_authorized_client(client1)); + + ret = service_authorized_client_config_equal(config1, config2); + tt_int_op(ret, OP_EQ, 0); + + service_clear_config(config1); + service_clear_config(config2); + } + + /* Both configs have totally distinct clients. */ + { + config1->clients = smartlist_new(); + config2->clients = smartlist_new(); + + hs_service_authorized_client_t *client1, *client2, *client3, *client4; + client1 = helper_create_authorized_client(); + client2 = helper_create_authorized_client(); + client3 = helper_create_authorized_client(); + client4 = helper_create_authorized_client(); + + smartlist_add(config1->clients, client1); + smartlist_add(config1->clients, client2); + + smartlist_add(config2->clients, client3); + smartlist_add(config2->clients, client4); + + ret = service_authorized_client_config_equal(config1, config2); + tt_int_op(ret, OP_EQ, 0); + + service_clear_config(config1); + service_clear_config(config2); + } + + done: + tor_free(config1); + tor_free(config2); +} + +/** Test that client circuit ID gets correctly exported */ +static void +test_export_client_circuit_id(void *arg) +{ + origin_circuit_t *or_circ = NULL; + size_t sz; + char *cp1=NULL, *cp2=NULL; + connection_t *conn = NULL; + + (void) arg; + + MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock); + + hs_service_init(); + + /* Create service */ + hs_service_t *service = helper_create_service(); + /* Check that export circuit ID detection works */ + service->config.circuit_id_protocol = HS_CIRCUIT_ID_PROTOCOL_NONE; + tt_int_op(0, OP_EQ, + hs_service_exports_circuit_id(&service->keys.identity_pk)); + service->config.circuit_id_protocol = HS_CIRCUIT_ID_PROTOCOL_HAPROXY; + tt_int_op(1, OP_EQ, + hs_service_exports_circuit_id(&service->keys.identity_pk)); + + /* Create client connection */ + conn = test_conn_get_connection(AP_CONN_STATE_CIRCUIT_WAIT, CONN_TYPE_AP, 0); + + /* Create client edge conn hs_ident */ + edge_connection_t *edge_conn = TO_EDGE_CONN(conn); + edge_conn->hs_ident = hs_ident_edge_conn_new(&service->keys.identity_pk); + edge_conn->hs_ident->orig_virtual_port = 42; + + /* Create rend circuit */ + or_circ = origin_circuit_new(); + or_circ->base_.purpose = CIRCUIT_PURPOSE_C_REND_JOINED; + edge_conn->on_circuit = TO_CIRCUIT(or_circ); + or_circ->global_identifier = 666; + + /* Export circuit ID */ + export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol); + + /* Check contents */ + cp1 = buf_get_contents(conn->outbuf, &sz); + tt_str_op(cp1, OP_EQ, + "PROXY TCP6 fc00:dead:beef:4dad::0:29a ::1 666 42\r\n"); + + /* Change circ GID and see that the reported circuit ID also changes */ + or_circ->global_identifier = 22; + + /* check changes */ + export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol); + cp2 = buf_get_contents(conn->outbuf, &sz); + tt_str_op(cp1, OP_NE, cp2); + tor_free(cp1); + + /* Check that GID with UINT32_MAX works. */ + or_circ->global_identifier = UINT32_MAX; + + export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol); + cp1 = buf_get_contents(conn->outbuf, &sz); + tt_str_op(cp1, OP_EQ, + "PROXY TCP6 fc00:dead:beef:4dad::ffff:ffff ::1 65535 42\r\n"); + tor_free(cp1); + + /* Check that GID with UINT16_MAX works. */ + or_circ->global_identifier = UINT16_MAX; + + export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol); + cp1 = buf_get_contents(conn->outbuf, &sz); + tt_str_op(cp1, OP_EQ, + "PROXY TCP6 fc00:dead:beef:4dad::0:ffff ::1 65535 42\r\n"); + tor_free(cp1); + + /* Check that GID with UINT16_MAX + 7 works. */ + or_circ->global_identifier = UINT16_MAX + 7; + + export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol); + cp1 = buf_get_contents(conn->outbuf, &sz); + tt_str_op(cp1, OP_EQ, "PROXY TCP6 fc00:dead:beef:4dad::1:6 ::1 6 42\r\n"); + + done: + UNMOCK(connection_write_to_buf_impl_); + circuit_free_(TO_CIRCUIT(or_circ)); + connection_free_minimal(conn); + hs_service_free(service); + tor_free(cp1); + tor_free(cp2); +} + struct testcase_t hs_service_tests[] = { { "e2e_rend_circuit_setup", test_e2e_rend_circuit_setup, TT_FORK, NULL, NULL }, { "load_keys", test_load_keys, TT_FORK, NULL, NULL }, + { "client_filename_is_valid", test_client_filename_is_valid, TT_FORK, + NULL, NULL }, + { "parse_authorized_client", test_parse_authorized_client, TT_FORK, + NULL, NULL }, + { "load_keys_with_client_auth", test_load_keys_with_client_auth, TT_FORK, + NULL, NULL }, { "access_service", test_access_service, TT_FORK, NULL, NULL }, { "service_intro_point", test_service_intro_point, TT_FORK, @@ -1618,13 +2130,16 @@ struct testcase_t hs_service_tests[] = { NULL, NULL }, { "build_update_descriptors", test_build_update_descriptors, TT_FORK, NULL, NULL }, - { "upload_descriptors", test_upload_descriptors, TT_FORK, + { "build_descriptors", test_build_descriptors, TT_FORK, NULL, NULL }, - { "revision_counter_state", test_revision_counter_state, TT_FORK, + { "upload_descriptors", test_upload_descriptors, TT_FORK, NULL, NULL }, { "rendezvous1_parsing", test_rendezvous1_parsing, TT_FORK, NULL, NULL }, + { "authorized_client_config_equal", test_authorized_client_config_equal, + TT_FORK, NULL, NULL }, + { "export_client_circuit_id", test_export_client_circuit_id, TT_FORK, + NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_introduce.c b/src/test/test_introduce.c index d502bdddb1..4d2d909945 100644 --- a/src/test/test_introduce.c +++ b/src/test/test_introduce.c @@ -1,13 +1,13 @@ -/* Copyright (c) 2012-2017, The Tor Project, Inc. */ +/* Copyright (c) 2012-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" -#include "crypto.h" -#include "or.h" -#include "test.h" +#include "lib/crypt_ops/crypto_cipher.h" +#include "core/or/or.h" +#include "test/test.h" #define RENDSERVICE_PRIVATE -#include "rendservice.h" +#include "feature/rend/rendservice.h" static uint8_t v0_test_plaintext[] = /* 20 bytes of rendezvous point nickname */ diff --git a/src/test/test_keypin.c b/src/test/test_keypin.c index 79d7bac902..9af12ff548 100644 --- a/src/test/test_keypin.c +++ b/src/test/test_keypin.c @@ -1,13 +1,12 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" #define KEYPIN_PRIVATE -#include "or.h" -#include "keypin.h" -#include "util.h" +#include "core/or/or.h" +#include "feature/dirauth/keypin.h" -#include "test.h" +#include "test/test.h" static void test_keypin_parse_line(void *arg) diff --git a/src/test/test_link_handshake.c b/src/test/test_link_handshake.c index 6840072d76..82a91a9ae2 100644 --- a/src/test/test_link_handshake.c +++ b/src/test/test_link_handshake.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" @@ -8,21 +8,28 @@ #define TOR_CHANNEL_INTERNAL_ #define TORTLS_PRIVATE -#include "compat.h" - -#include "or.h" -#include "config.h" -#include "connection.h" -#include "connection_or.h" -#include "channeltls.h" -#include "link_handshake.h" -#include "router.h" -#include "routerkeys.h" -#include "scheduler.h" -#include "torcert.h" - -#include "test.h" -#include "log_test_helpers.h" +#include "core/or/or.h" +#include "app/config/config.h" +#include "core/mainloop/connection.h" +#include "core/or/connection_or.h" +#include "core/or/channeltls.h" +#include "trunnel/link_handshake.h" +#include "feature/relay/router.h" +#include "feature/relay/routerkeys.h" +#include "core/or/scheduler.h" +#include "feature/nodelist/torcert.h" + +#include "core/or/or_connection_st.h" +#include "core/or/or_handshake_certs_st.h" +#include "core/or/or_handshake_state_st.h" +#include "core/or/var_cell_st.h" + +#define TOR_X509_PRIVATE +#include "lib/tls/tortls.h" +#include "lib/tls/x509.h" + +#include "test/test.h" +#include "test/log_test_helpers.h" static var_cell_t *mock_got_var_cell = NULL; @@ -788,11 +795,26 @@ CERTS_FAIL(bad_rsa_id_cert, /*ed25519*/ { require_failure_message = "legacy RSA ID certificate was not valid"; certs_cell_cert_t *cert = certs_cell_get_certs(d->ccell, 1); - uint8_t *body = certs_cell_cert_getarray_body(cert); - ssize_t body_len = certs_cell_cert_getlen_body(cert); - /* Frob a byte in the signature */ - body[body_len - 13] ^= 7; + uint8_t *body; + /* Frob a byte in the signature, after making a new cert. (NSS won't let + * us just frob the old cert, since it will see that the issuer & serial + * number are the same, which will make it fail at an earlier stage than + * signature verification.) */ + const tor_x509_cert_t *idc; + tor_x509_cert_t *newc; + tor_tls_get_my_certs(1, NULL, &idc); + time_t new_end = time(NULL) + 86400 * 10; + newc = tor_x509_cert_replace_expiration(idc, new_end, d->key2); + const uint8_t *encoded; + size_t encoded_len; + tor_x509_cert_get_der(newc, &encoded, &encoded_len); + certs_cell_cert_setlen_body(cert, encoded_len); + certs_cell_cert_set_cert_len(cert, encoded_len); + body = certs_cell_cert_getarray_body(cert); + memcpy(body, encoded, encoded_len); + body[encoded_len - 13] ^= 7; REENCODE(); + tor_x509_cert_free(newc); }) CERTS_FAIL(expired_rsa_id, /* both */ { @@ -804,9 +826,12 @@ CERTS_FAIL(expired_rsa_id, /* both */ tor_x509_cert_t *newc; time_t new_end = time(NULL) - 86400 * 10; newc = tor_x509_cert_replace_expiration(idc, new_end, d->key2); - certs_cell_cert_setlen_body(cert, newc->encoded_len); - memcpy(certs_cell_cert_getarray_body(cert), - newc->encoded, newc->encoded_len); + const uint8_t *encoded; + size_t encoded_len; + tor_x509_cert_get_der(newc, &encoded, &encoded_len); + certs_cell_cert_setlen_body(cert, encoded_len); + certs_cell_cert_set_cert_len(cert, encoded_len); + memcpy(certs_cell_cert_getarray_body(cert), encoded, encoded_len); REENCODE(); tor_x509_cert_free(newc); }) @@ -917,15 +942,25 @@ test_link_handshake_send_authchallenge(void *arg) cell1 = mock_got_var_cell; tt_int_op(0, OP_EQ, connection_or_send_auth_challenge_cell(c1)); cell2 = mock_got_var_cell; +#ifdef HAVE_WORKING_TOR_TLS_GET_TLSSECRETS tt_int_op(38, OP_EQ, cell1->payload_len); tt_int_op(38, OP_EQ, cell2->payload_len); +#else + tt_int_op(36, OP_EQ, cell1->payload_len); + tt_int_op(36, OP_EQ, cell2->payload_len); +#endif tt_int_op(0, OP_EQ, cell1->circ_id); tt_int_op(0, OP_EQ, cell2->circ_id); tt_int_op(CELL_AUTH_CHALLENGE, OP_EQ, cell1->command); tt_int_op(CELL_AUTH_CHALLENGE, OP_EQ, cell2->command); +#ifdef HAVE_WORKING_TOR_TLS_GET_TLSSECRETS tt_mem_op("\x00\x02\x00\x01\x00\x03", OP_EQ, cell1->payload + 32, 6); tt_mem_op("\x00\x02\x00\x01\x00\x03", OP_EQ, cell2->payload + 32, 6); +#else + tt_mem_op("\x00\x01\x00\x03", OP_EQ, cell1->payload + 32, 4); + tt_mem_op("\x00\x01\x00\x03", OP_EQ, cell2->payload + 32, 4); +#endif tt_mem_op(cell1->payload, OP_NE, cell2->payload, 32); done: @@ -967,6 +1002,8 @@ static void * recv_authchallenge_setup(const struct testcase_t *test) { (void)test; + + testing__connection_or_pretend_TLSSECRET_is_supported = 1; authchallenge_data_t *d = tor_malloc_zero(sizeof(*d)); d->c = or_connection_new(CONN_TYPE_OR, AF_INET); d->chan = tor_malloc_zero(sizeof(*d->chan)); @@ -1180,6 +1217,8 @@ authenticate_data_setup(const struct testcase_t *test) authenticate_data_t *d = tor_malloc_zero(sizeof(*d)); int is_ed = d->is_ed = (test->setup_data == (void*)3); + testing__connection_or_pretend_TLSSECRET_is_supported = 1; + scheduler_init(); MOCK(connection_or_write_var_cell_to_buf, mock_write_var_cell); @@ -1576,4 +1615,3 @@ struct testcase_t link_handshake_tests[] = { END_OF_TESTCASES }; - diff --git a/src/test/test_logging.c b/src/test/test_logging.c index e373158e34..cd685a4af7 100644 --- a/src/test/test_logging.c +++ b/src/test/test_logging.c @@ -1,10 +1,19 @@ -/* Copyright (c) 2013-2017, The Tor Project, Inc. */ +/* Copyright (c) 2013-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +#define CONFIG_PRIVATE + #include "orconfig.h" -#include "or.h" -#include "torlog.h" -#include "test.h" +#include "core/or/or.h" +#include "app/config/config.h" +#include "lib/err/torerr.h" +#include "lib/log/log.h" +#include "test/test.h" +#include "lib/process/subprocess.h" + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif static void dummy_cb_fn(int severity, uint32_t domain, const char *msg) @@ -89,7 +98,7 @@ test_sigsafe_err(void *arg) init_logging(1); mark_logs_temp(); - add_file_log(&include_bug, fn, 0); + open_and_add_file_log(&include_bug, fn, 0); tor_log_update_sigsafe_err_fds(); close_temp_logs(); @@ -170,4 +179,3 @@ struct testcase_t logging_tests[] = { { "ratelim", test_ratelim, 0, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_mainloop.c b/src/test/test_mainloop.c new file mode 100644 index 0000000000..92ce2e9918 --- /dev/null +++ b/src/test/test_mainloop.c @@ -0,0 +1,142 @@ +/* Copyright (c) 2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file test_mainloop.c + * \brief Tests for functions closely related to the Tor main loop + */ + +#include "test/test.h" +#include "test/log_test_helpers.h" + +#include "core/or/or.h" +#include "core/mainloop/mainloop.h" + +static const uint64_t BILLION = 1000000000; + +static void +test_mainloop_update_time_normal(void *arg) +{ + (void)arg; + + monotime_enable_test_mocking(); + /* This is arbitrary */ + uint64_t mt_now = UINT64_C(7493289274986); + /* This time is in the past as of when this test was written. */ + time_t now = 1525272090; + monotime_coarse_set_mock_time_nsec(mt_now); + reset_uptime(); + update_current_time(now); + tt_int_op(approx_time(), OP_EQ, now); + tt_int_op(get_uptime(), OP_EQ, 0); + + update_current_time(now); // Same time as before is a no-op. + tt_int_op(get_uptime(), OP_EQ, 0); + + now += 1; + mt_now += BILLION; + monotime_coarse_set_mock_time_nsec(mt_now); + update_current_time(now); + tt_int_op(approx_time(), OP_EQ, now); + tt_int_op(get_uptime(), OP_EQ, 1); + + now += 2; // two-second jump is unremarkable. + mt_now += 2*BILLION; + update_current_time(now); + monotime_coarse_set_mock_time_nsec(mt_now); + tt_int_op(approx_time(), OP_EQ, now); + tt_int_op(get_uptime(), OP_EQ, 3); + + now -= 1; // a one-second hop backwards is also unremarkable. + update_current_time(now); + tt_int_op(approx_time(), OP_EQ, now); // it changes the approx time... + tt_int_op(get_uptime(), OP_EQ, 3); // but it doesn't roll back our uptime + + done: + monotime_disable_test_mocking(); +} + +static void +test_mainloop_update_time_jumps(void *arg) +{ + (void)arg; + + monotime_enable_test_mocking(); + /* This is arbitrary */ + uint64_t mt_now = UINT64_C(7493289274986); + /* This time is in the past as of when this test was written. */ + time_t now = 220897152; + monotime_coarse_set_mock_time_nsec(mt_now); + reset_uptime(); + update_current_time(now); + tt_int_op(approx_time(), OP_EQ, now); + tt_int_op(get_uptime(), OP_EQ, 0); + + /* Put some uptime on the clock.. */ + now += 3; + mt_now += 3*BILLION; + monotime_coarse_set_mock_time_nsec(mt_now); + update_current_time(now); + tt_int_op(approx_time(), OP_EQ, now); + tt_int_op(get_uptime(), OP_EQ, 3); + + /* Now try jumping forward and backward, without updating the monotonic + * clock. */ + setup_capture_of_logs(LOG_NOTICE); + now += 1800; + update_current_time(now); + expect_single_log_msg_containing( + "Your system clock just jumped 1800 seconds forward"); + tt_int_op(approx_time(), OP_EQ, now); + tt_int_op(get_uptime(), OP_EQ, 3); // no uptime change. + mock_clean_saved_logs(); + + now -= 600; + update_current_time(now); + expect_single_log_msg_containing( + "Your system clock just jumped 600 seconds backward"); + tt_int_op(approx_time(), OP_EQ, now); + tt_int_op(get_uptime(), OP_EQ, 3); // no uptime change. + mock_clean_saved_logs(); + + /* uptime tracking should go normally now if the clock moves sensibly. */ + now += 2; + mt_now += 2*BILLION; + update_current_time(now); + tt_int_op(approx_time(), OP_EQ, now); + tt_int_op(get_uptime(), OP_EQ, 5); + + /* If we skip forward by a few minutes but the monotonic clock agrees, + * we've just been idle: that counts as not worth warning about. */ + now += 1800; + mt_now += 1800*BILLION; + monotime_coarse_set_mock_time_nsec(mt_now); + update_current_time(now); + expect_no_log_entry(); + tt_int_op(approx_time(), OP_EQ, now); + tt_int_op(get_uptime(), OP_EQ, 5); // this doesn't count to uptime, though. + + /* If we skip forward by a long time, even if the clock agrees, it's + * idnless that counts. */ + now += 4000; + mt_now += 4000*BILLION; + monotime_coarse_set_mock_time_nsec(mt_now); + update_current_time(now); + expect_single_log_msg_containing("Tor has been idle for 4000 seconds"); + tt_int_op(approx_time(), OP_EQ, now); + tt_int_op(get_uptime(), OP_EQ, 5); + + done: + teardown_capture_of_logs(); + monotime_disable_test_mocking(); +} + +#define MAINLOOP_TEST(name) \ + { #name, test_mainloop_## name , TT_FORK, NULL, NULL } + +struct testcase_t mainloop_tests[] = { + MAINLOOP_TEST(update_time_normal), + MAINLOOP_TEST(update_time_jumps), + END_OF_TESTCASES +}; + diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c index 59b28f7580..8ede2690ec 100644 --- a/src/test/test_microdesc.c +++ b/src/test/test_microdesc.c @@ -1,18 +1,29 @@ -/* Copyright (c) 2010-2017, The Tor Project, Inc. */ +/* Copyright (c) 2010-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" -#include "or.h" - -#include "config.h" -#include "dirvote.h" -#include "microdesc.h" -#include "networkstatus.h" -#include "routerlist.h" -#include "routerparse.h" -#include "torcert.h" - -#include "test.h" +#include "core/or/or.h" + +#define DIRVOTE_PRIVATE +#include "app/config/config.h" +#include "feature/dirauth/dirvote.h" +#include "feature/dirparse/microdesc_parse.h" +#include "feature/dirparse/routerparse.h" +#include "feature/nodelist/microdesc.h" +#include "feature/nodelist/networkstatus.h" +#include "feature/nodelist/routerlist.h" +#include "feature/nodelist/torcert.h" + +#include "feature/nodelist/microdesc_st.h" +#include "feature/nodelist/networkstatus_st.h" +#include "feature/nodelist/routerinfo_st.h" +#include "feature/nodelist/routerstatus_st.h" + +#include "test/test.h" + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif #ifdef _WIN32 /* For mkdir() */ @@ -385,25 +396,6 @@ static const char test_ri2[] = "cf34GXHv61XReJF3AlzNHFpbrPOYmowmhrTULKyMqow=\n" "-----END SIGNATURE-----\n"; -static const char test_md_8[] = - "onion-key\n" - "-----BEGIN RSA PUBLIC KEY-----\n" - "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n" - "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n" - "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n" - "-----END RSA PUBLIC KEY-----\n" - "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"; - -static const char test_md_16[] = - "onion-key\n" - "-----BEGIN RSA PUBLIC KEY-----\n" - "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n" - "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n" - "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n" - "-----END RSA PUBLIC KEY-----\n" - "ntor-onion-key Gg73xH7+kTfT6bi1uNVx9gwQdQas9pROIfmc4NpAdC4=\n" - "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"; - static const char test_md_18[] = "onion-key\n" "-----BEGIN RSA PUBLIC KEY-----\n" @@ -415,16 +407,6 @@ static const char test_md_18[] = "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n" "id rsa1024 Cd47okjCHD83YGzThGBDptXs9Z4\n"; -static const char test_md2_18[] = - "onion-key\n" - "-----BEGIN RSA PUBLIC KEY-----\n" - "MIGJAoGBAL2R8EfubUcahxha4u02P4VAR0llQIMwFAmrHPjzcK7apcQgDOf2ovOA\n" - "+YQnJFxlpBmCoCZC6ssCi+9G0mqo650lFuTMP5I90BdtjotfzESfTykHLiChyvhd\n" - "l0dlqclb2SU/GKem/fLRXH16aNi72CdSUu/1slKs/70ILi34QixRAgMBAAE=\n" - "-----END RSA PUBLIC KEY-----\n" - "ntor-onion-key hbxdRnfVUJJY7+KcT4E3Rs7/zuClbN3hJrjSBiEGMgI=\n" - "id rsa1024 t+J/EEITw28T5+mCkYKEXklZl6A\n"; - static const char test_md2_21[] = "onion-key\n" "-----BEGIN RSA PUBLIC KEY-----\n" @@ -444,17 +426,6 @@ test_md_generate(void *arg) ri = router_parse_entry_from_string(test_ri, NULL, 0, 0, NULL, NULL); tt_assert(ri); - md = dirvote_create_microdescriptor(ri, 8); - tt_str_op(md->body, OP_EQ, test_md_8); - - /* XXXX test family lines. */ - /* XXXX test method 14 for A lines. */ - /* XXXX test method 15 for P6 lines. */ - - microdesc_free(md); - md = NULL; - md = dirvote_create_microdescriptor(ri, 16); - tt_str_op(md->body, OP_EQ, test_md_16); microdesc_free(md); md = NULL; @@ -471,11 +442,6 @@ test_md_generate(void *arg) microdesc_free(md); md = NULL; - md = dirvote_create_microdescriptor(ri, 18); - tt_str_op(md->body, OP_EQ, test_md2_18); - - microdesc_free(md); - md = NULL; md = dirvote_create_microdescriptor(ri, 21); tt_str_op(md->body, OP_EQ, test_md2_21); tt_assert(ed25519_pubkey_eq(md->ed25519_identity_pkey, @@ -854,4 +820,3 @@ struct testcase_t microdesc_tests[] = { { "corrupt_desc", test_md_corrupt_desc, TT_FORK, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_nodelist.c b/src/test/test_nodelist.c index a873003d72..1af6db68ec 100644 --- a/src/test/test_nodelist.c +++ b/src/test/test_nodelist.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2007-2017, The Tor Project, Inc. */ +/* Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -6,11 +6,20 @@ * \brief Unit tests for nodelist related functions. **/ -#include "or.h" -#include "networkstatus.h" -#include "nodelist.h" -#include "torcert.h" -#include "test.h" +#include "core/or/or.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "feature/nodelist/networkstatus.h" +#include "feature/nodelist/nodelist.h" +#include "feature/nodelist/torcert.h" + +#include "feature/nodelist/microdesc_st.h" +#include "feature/nodelist/networkstatus_st.h" +#include "feature/nodelist/node_st.h" +#include "feature/nodelist/routerinfo_st.h" +#include "feature/nodelist/routerstatus_st.h" + +#include "test/test.h" +#include "test/log_test_helpers.h" /** Test the case when node_get_by_id() returns NULL, * node_get_verbose_nickname_by_id should return the base 16 encoding @@ -118,9 +127,10 @@ mock_networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f) static void test_nodelist_ed_id(void *arg) { - routerstatus_t *rs[4]; - microdesc_t *md[4]; - routerinfo_t *ri[4]; +#define N_NODES 5 + routerstatus_t *rs[N_NODES]; + microdesc_t *md[N_NODES]; + routerinfo_t *ri[N_NODES]; networkstatus_t *ns; int i; (void)arg; @@ -137,7 +147,7 @@ test_nodelist_ed_id(void *arg) /* Make a bunch of dummy objects that we can play around with. Only set the necessary fields */ - for (i = 0; i < 4; ++i) { + for (i = 0; i < N_NODES; ++i) { rs[i] = tor_malloc_zero(sizeof(*rs[i])); md[i] = tor_malloc_zero(sizeof(*md[i])); ri[i] = tor_malloc_zero(sizeof(*ri[i])); @@ -154,7 +164,7 @@ test_nodelist_ed_id(void *arg) memcpy(&ri[i]->cache_info.signing_key_cert->signing_key, md[i]->ed25519_identity_pkey, sizeof(ed25519_public_key_t)); - if (i != 3) + if (i < 3) smartlist_add(ns->routerstatus_list, rs[i]); } @@ -184,13 +194,30 @@ test_nodelist_ed_id(void *arg) /* Register the 4th by ri only -- we never put it into the networkstatus, * so it has to be independent */ - n = nodelist_set_routerinfo(ri[3], &ri_old); - tt_ptr_op(n, OP_EQ, node_get_by_ed25519_id(md[3]->ed25519_identity_pkey)); + node_t *n3 = nodelist_set_routerinfo(ri[3], &ri_old); + tt_ptr_op(n3, OP_EQ, node_get_by_ed25519_id(md[3]->ed25519_identity_pkey)); tt_ptr_op(ri_old, OP_EQ, NULL); tt_int_op(4, OP_EQ, smartlist_len(nodelist_get_list())); + /* Register the 5th by ri only, and rewrite its ed25519 pubkey to be + * the same as the 4th, to test the duplicate ed25519 key logging in + * nodelist.c */ + memcpy(md[4]->ed25519_identity_pkey, md[3]->ed25519_identity_pkey, + sizeof(ed25519_public_key_t)); + memcpy(&ri[4]->cache_info.signing_key_cert->signing_key, + md[3]->ed25519_identity_pkey, sizeof(ed25519_public_key_t)); + + setup_capture_of_logs(LOG_NOTICE); + node_t *n4 = nodelist_set_routerinfo(ri[4], &ri_old); + tt_ptr_op(ri_old, OP_EQ, NULL); + tt_int_op(5, OP_EQ, smartlist_len(nodelist_get_list())); + tt_ptr_op(n4, OP_NE, node_get_by_ed25519_id(md[3]->ed25519_identity_pkey)); + tt_ptr_op(n3, OP_EQ, node_get_by_ed25519_id(md[3]->ed25519_identity_pkey)); + expect_log_msg_containing("Reused ed25519_id"); + done: - for (i = 0; i < 4; ++i) { + teardown_capture_of_logs(); + for (i = 0; i < N_NODES; ++i) { tor_free(rs[i]); tor_free(md[i]->ed25519_identity_pkey); tor_free(md[i]); @@ -201,6 +228,7 @@ test_nodelist_ed_id(void *arg) networkstatus_vote_free(ns); UNMOCK(networkstatus_get_latest_consensus); UNMOCK(networkstatus_get_latest_consensus_by_flavor); +#undef N_NODES } #define NODE(name, flags) \ diff --git a/src/test/test_ntor_cl.c b/src/test/test_ntor_cl.c index d0eea85d6f..3f914523a3 100644 --- a/src/test/test_ntor_cl.c +++ b/src/test/test_ntor_cl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Tor Project, Inc. */ +/* Copyright (c) 2012-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" @@ -6,12 +6,11 @@ #include <stdlib.h> #define ONION_NTOR_PRIVATE -#include "or.h" -#include "util.h" -#include "compat.h" -#include "crypto.h" -#include "crypto_curve25519.h" -#include "onion_ntor.h" +#include "core/or/or.h" +#include "lib/crypt_ops/crypto_cipher.h" +#include "lib/crypt_ops/crypto_curve25519.h" +#include "lib/crypt_ops/crypto_init.h" +#include "core/crypto/onion_ntor.h" #define N_ARGS(n) STMT_BEGIN { \ if (argc < (n)) { \ @@ -155,7 +154,11 @@ main(int argc, char **argv) return 1; } + init_logging(1); curve25519_init(); + if (crypto_global_init(0, NULL, NULL) < 0) + return 1; + if (!strcmp(argv[1], "client1")) { return client1(argc, argv); } else if (!strcmp(argv[1], "server1")) { @@ -167,4 +170,3 @@ main(int argc, char **argv) return 1; } } - diff --git a/src/test/test_oom.c b/src/test/test_oom.c index c172fe60c7..313a6b3114 100644 --- a/src/test/test_oom.c +++ b/src/test/test_oom.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /* Unit tests for OOM handling logic */ @@ -7,15 +7,21 @@ #define BUFFERS_PRIVATE #define CIRCUITLIST_PRIVATE #define CONNECTION_PRIVATE -#include "or.h" -#include "buffers.h" -#include "circuitlist.h" -#include "compat_libevent.h" -#include "connection.h" -#include "config.h" -#include "relay.h" -#include "test.h" -#include "test_helpers.h" +#include "core/or/or.h" +#include "lib/container/buffers.h" +#include "core/or/circuitlist.h" +#include "lib/evloop/compat_libevent.h" +#include "core/mainloop/connection.h" +#include "app/config/config.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "core/or/relay.h" +#include "test/test.h" +#include "test/test_helpers.h" + +#include "core/or/cell_st.h" +#include "core/or/entry_connection_st.h" +#include "core/or/or_circuit_st.h" +#include "core/or/origin_circuit_st.h" /* small replacement mock for circuit_mark_for_close_ to avoid doing all * the other bookkeeping that comes with marking circuits. */ diff --git a/src/test/test_oos.c b/src/test/test_oos.c index e72fcf5de9..fb0daa7a8d 100644 --- a/src/test/test_oos.c +++ b/src/test/test_oos.c @@ -1,16 +1,20 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /* Unit tests for OOS handler */ #define CONNECTION_PRIVATE -#include "or.h" -#include "config.h" -#include "connection.h" -#include "connection_or.h" -#include "main.h" -#include "test.h" +#include "core/or/or.h" +#include "app/config/config.h" +#include "core/mainloop/connection.h" +#include "core/or/connection_or.h" +#include "feature/dircommon/directory.h" +#include "core/mainloop/mainloop.h" +#include "test/test.h" + +#include "feature/dircommon/dir_connection_st.h" +#include "core/or/or_connection_st.h" static or_options_t mock_options; @@ -453,4 +457,3 @@ struct testcase_t oos_tests[] = { { "pick_oos_victims", test_oos_pick_oos_victims, TT_FORK, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_options.c b/src/test/test_options.c index eaf5034397..f14e620eeb 100644 --- a/src/test/test_options.c +++ b/src/test/test_options.c @@ -1,24 +1,27 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define CONFIG_PRIVATE -#include "or.h" -#include "confparse.h" -#include "config.h" -#include "test.h" -#include "geoip.h" +#include "core/or/or.h" +#include "app/config/confparse.h" +#include "app/config/config.h" +#include "test/test.h" +#include "lib/geoip/geoip.h" #define ROUTERSET_PRIVATE -#include "routerset.h" -#include "main.h" -#include "log_test_helpers.h" - -#include "sandbox.h" -#include "memarea.h" -#include "policies.h" -#include "test_helpers.h" +#include "feature/nodelist/routerset.h" +#include "core/mainloop/mainloop.h" +#include "test/log_test_helpers.h" + +#include "lib/sandbox/sandbox.h" +#include "lib/memarea/memarea.h" +#include "lib/osinfo/uname.h" +#include "lib/encoding/confline.h" +#include "core/or/policies.h" +#include "test/test_helpers.h" +#include "lib/net/resolve.h" #define NS_MODULE test_options @@ -274,7 +277,7 @@ test_options_validate(void *arg) return; } -#define MEGABYTEIFY(mb) (U64_LITERAL(mb) << 20) +#define MEGABYTEIFY(mb) (UINT64_C(mb) << 20) static void test_have_enough_mem_for_dircache(void *arg) { @@ -470,6 +473,13 @@ test_options_validate__uname_for_server(void *ignored) { (void)ignored; char *msg; + +#ifndef _WIN32 + int unset_home_env = 0; + if (setenv("HOME", "/home/john", 0) == 0) + unset_home_env = 1; +#endif + options_test_data_t *tdata = get_options_test_data( "ORPort 127.0.0.1:5555"); setup_capture_of_logs(LOG_WARN); @@ -509,6 +519,10 @@ test_options_validate__uname_for_server(void *ignored) free_options_test_data(tdata); tor_free(msg); teardown_capture_of_logs(); +#ifndef _WIN32 + if (unset_home_env) + unsetenv("HOME"); +#endif } static void @@ -1410,6 +1424,13 @@ test_options_validate__paths_needed(void *ignored) (void)ignored; int ret; char *msg; + +#ifndef _WIN32 + int unset_home_env = 0; + if (setenv("HOME", "/home/john", 0) == 0) + unset_home_env = 1; +#endif + setup_capture_of_logs(LOG_WARN); options_test_data_t *tdata = get_options_test_data( "PathsNeededToBuildCircuits 0.1\n" @@ -1452,6 +1473,10 @@ test_options_validate__paths_needed(void *ignored) teardown_capture_of_logs(); free_options_test_data(tdata); tor_free(msg); +#ifndef _WIN32 + if (unset_home_env) + unsetenv("HOME"); +#endif } static void @@ -1631,6 +1656,18 @@ test_options_validate__reachable_addresses(void *ignored) tt_str_op(tdata->opt->ReachableAddresses->value, OP_EQ, "*:82"); tor_free(msg); + free_options_test_data(tdata); + mock_clean_saved_logs(); + tdata = get_options_test_data("FascistFirewall 1\n" + "ReachableAddresses *:82\n" + "MaxClientCircuitsPending 1\n" + "ConnLimit 1\n"); + + ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tt_int_op(ret, OP_EQ, -1); + tt_ptr_op(tdata->opt->ReachableAddresses->next, OP_EQ, NULL); + tor_free(msg); + #define SERVERS_REACHABLE_MSG "Servers must be able to freely connect to" \ " the rest of the Internet, so they must not set Reachable*Addresses or" \ " FascistFirewall or FirewallPorts or ClientUseIPv4 0." @@ -2067,12 +2104,12 @@ test_options_validate__testing(void *ignored) ENSURE_DEFAULT(TestingV3AuthVotingStartOffset, 3000); ENSURE_DEFAULT(TestingAuthDirTimeToLearnReachability, 3000); ENSURE_DEFAULT(TestingEstimatedDescriptorPropagationTime, 3000); - ENSURE_DEFAULT(TestingServerDownloadSchedule, 3000); - ENSURE_DEFAULT(TestingClientDownloadSchedule, 3000); - ENSURE_DEFAULT(TestingServerConsensusDownloadSchedule, 3000); - ENSURE_DEFAULT(TestingClientConsensusDownloadSchedule, 3000); - ENSURE_DEFAULT(TestingBridgeDownloadSchedule, 3000); - ENSURE_DEFAULT(TestingBridgeBootstrapDownloadSchedule, 3000); + ENSURE_DEFAULT(TestingServerDownloadInitialDelay, 3000); + ENSURE_DEFAULT(TestingClientDownloadInitialDelay, 3000); + ENSURE_DEFAULT(TestingServerConsensusDownloadInitialDelay, 3000); + ENSURE_DEFAULT(TestingClientConsensusDownloadInitialDelay, 3000); + ENSURE_DEFAULT(TestingBridgeDownloadInitialDelay, 3000); + ENSURE_DEFAULT(TestingBridgeBootstrapDownloadInitialDelay, 3000); ENSURE_DEFAULT(TestingClientMaxIntervalWithoutRequest, 3000); ENSURE_DEFAULT(TestingDirConnectionMaxStall, 3000); ENSURE_DEFAULT(TestingAuthKeyLifetime, 3000); @@ -2422,67 +2459,6 @@ test_options_validate__circuits(void *ignored) } static void -test_options_validate__port_forwarding(void *ignored) -{ - (void)ignored; - int ret; - char *msg; - options_test_data_t *tdata = NULL; - - free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "PortForwarding 1\nSandbox 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); - tt_str_op(msg, OP_EQ, "PortForwarding is not compatible with Sandbox;" - " at most one can be set"); - tor_free(msg); - - free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "PortForwarding 1\nSandbox 0\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, 0); - tt_assert(!msg); - tor_free(msg); - - done: - free_options_test_data(tdata); - policies_free_all(); - tor_free(msg); -} - -static void -test_options_validate__tor2web(void *ignored) -{ - (void)ignored; - int ret; - char *msg; - options_test_data_t *tdata = NULL; - - free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "Tor2webRendezvousPoints 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); - tt_str_op(msg, OP_EQ, - "Tor2webRendezvousPoints cannot be set without Tor2webMode."); - tor_free(msg); - - free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "Tor2webRendezvousPoints 1\nTor2webMode 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, 0); - tor_free(msg); - - done: - policies_free_all(); - free_options_test_data(tdata); - tor_free(msg); -} - -static void test_options_validate__rend(void *ignored) { (void)ignored; @@ -2595,13 +2571,11 @@ test_options_validate__single_onion(void *ignored) tt_ptr_op(msg, OP_EQ, NULL); free_options_test_data(tdata); - /* Test that SOCKSPort must come with Tor2webMode if - * HiddenServiceSingleHopMode is 1 */ + /* Test that SOCKSPort if HiddenServiceSingleHopMode is 1 */ tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "SOCKSPort 5000\n" "HiddenServiceSingleHopMode 1\n" "HiddenServiceNonAnonymousMode 1\n" - "Tor2webMode 0\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); @@ -2616,7 +2590,6 @@ test_options_validate__single_onion(void *ignored) "SOCKSPort 0\n" "HiddenServiceSingleHopMode 1\n" "HiddenServiceNonAnonymousMode 1\n" - "Tor2webMode 0\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); @@ -2626,27 +2599,13 @@ test_options_validate__single_onion(void *ignored) tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "SOCKSPort 5000\n" "HiddenServiceSingleHopMode 0\n" - "Tor2webMode 0\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "SOCKSPort 5000\n" - "HiddenServiceSingleHopMode 1\n" - "HiddenServiceNonAnonymousMode 1\n" - "Tor2webMode 1\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, 0); - tt_ptr_op(msg, OP_EQ, NULL); - free_options_test_data(tdata); - - /* Test that a hidden service can't be run with Tor2web - * Use HiddenServiceNonAnonymousMode instead of Tor2webMode, because - * Tor2webMode requires a compilation #define */ + /* Test that a hidden service can't be run in non anonymous mode. */ tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HiddenServiceNonAnonymousMode 1\n" "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" @@ -4135,16 +4094,6 @@ test_options_validate__testing_options(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "TestingEnableTbEmptyEvent 1\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); - tt_str_op(msg, OP_EQ, "TestingEnableTbEmptyEvent may only be changed " - "in testing Tor networks!"); - tor_free(msg); - - free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "TestingEnableTbEmptyEvent 1\n" VALID_DIR_AUTH "TestingTorNetwork 1\n" "___UsingTestNetworkDefaults 0\n" @@ -4261,8 +4210,6 @@ struct testcase_t options_tests[] = { LOCAL_VALIDATE_TEST(path_bias), LOCAL_VALIDATE_TEST(bandwidth), LOCAL_VALIDATE_TEST(circuits), - LOCAL_VALIDATE_TEST(port_forwarding), - LOCAL_VALIDATE_TEST(tor2web), LOCAL_VALIDATE_TEST(rend), LOCAL_VALIDATE_TEST(single_onion), LOCAL_VALIDATE_TEST(accounting), @@ -4279,4 +4226,3 @@ struct testcase_t options_tests[] = { LOCAL_VALIDATE_TEST(accel), END_OF_TESTCASES /* */ }; - diff --git a/src/test/test_pem.c b/src/test/test_pem.c new file mode 100644 index 0000000000..2bae286e25 --- /dev/null +++ b/src/test/test_pem.c @@ -0,0 +1,122 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" + +#include "lib/encoding/pem.h" +#include "lib/cc/compat_compiler.h" +#include "lib/malloc/malloc.h" + +#include "test/test.h" + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +static const char example_pre[] = + "Lest you get the wrong impression, we wombats " + "are not in the habit of tunneling madly about, without any supplies " + "or even a map."; /* -- Ursula Vernon, _Digger_ */ +static const char expected[] = + "-----BEGIN WOMBAT QUOTE-----\n" + "TGVzdCB5b3UgZ2V0IHRoZSB3cm9uZyBpbXByZXNzaW9uLCB3ZSB3b21iYXRzIGFy\n" + "ZSBub3QgaW4gdGhlIGhhYml0IG9mIHR1bm5lbGluZyBtYWRseSBhYm91dCwgd2l0\n" + "aG91dCBhbnkgc3VwcGxpZXMgb3IgZXZlbiBhIG1hcC4=\n" + "-----END WOMBAT QUOTE-----\n"; + +static void +test_crypto_pem_encode(void *arg) +{ + (void)arg; + + char buf[4096]; + + int n = (int) pem_encoded_size(strlen(example_pre), "WOMBAT QUOTE"); + + int n2 = pem_encode(buf, sizeof(buf), + (const unsigned char *)example_pre, strlen(example_pre), + "WOMBAT QUOTE"); + tt_int_op(strlen(buf)+1, OP_EQ, n); + tt_int_op(n2, OP_EQ, 0); + tt_str_op(buf, OP_EQ, expected); + + /* Now make sure it succeeds if the buffer is exactly the length we want. */ + memset(buf, 0, sizeof(buf)); + n2 = pem_encode(buf, n, (const unsigned char *)example_pre, + strlen(example_pre), "WOMBAT QUOTE"); + tt_int_op(n2, OP_EQ, 0); + tt_str_op(buf, OP_EQ, expected); + + /* Make sure it fails if the buffer is too short. */ + memset(buf, 0, sizeof(buf)); + n2 = pem_encode(buf, n - 1, (const unsigned char *)example_pre, + strlen(example_pre), "WOMBAT QUOTE"); + tt_int_op(n2, OP_EQ, -1); + + done: + ; +} + +static void +test_crypto_pem_decode(void *arg) +{ + (void)arg; + + unsigned char buf[4096]; + + /* Try a straightforward decoding. */ + int n = pem_decode(buf, sizeof(buf), + expected, strlen(expected), + "WOMBAT QUOTE"); + tt_int_op(n, OP_EQ, strlen(example_pre)); + tt_mem_op(buf, OP_EQ, example_pre, n); + + /* Succeed if the buffer is exactly the right size. */ + memset(buf, 0xff, sizeof(buf)); + n = pem_decode(buf, strlen(example_pre), + expected, strlen(expected), + "WOMBAT QUOTE"); + tt_int_op(n, OP_EQ, strlen(example_pre)); + tt_mem_op(buf, OP_EQ, example_pre, n); + tt_int_op(buf[n], OP_EQ, 0xff); + + /* Verify that it fails if the buffer is too small. */ + memset(buf, 0xff, sizeof(buf)); + n = pem_decode(buf, strlen(example_pre) - 1, + expected, strlen(expected), + "WOMBAT QUOTE"); + tt_int_op(n, OP_EQ, -1); + + /* Verify that it fails with an incorrect tag. */ + memset(buf, 0xff, sizeof(buf)); + n = pem_decode(buf, sizeof(buf), + expected, strlen(expected), + "QUOKKA VOTE"); + tt_int_op(n, OP_EQ, -1); + + /* Try truncated buffers of different sizes. */ + size_t i; + for (i = 0; i <= strlen(expected); ++i) { + char *truncated = tor_memdup(expected, i); + n = pem_decode(buf, sizeof(buf), + truncated, i, + "WOMBAT QUOTE"); + tor_free(truncated); + if (i < strlen(expected) - 1) { + tt_int_op(n, OP_EQ, -1); + } else { + tt_int_op(n, OP_EQ, strlen(example_pre)); + } + } + + done: + ; +} + +struct testcase_t pem_tests[] = { + { "encode", test_crypto_pem_encode, 0, NULL, NULL }, + { "decode", test_crypto_pem_decode, 0, NULL, NULL }, + END_OF_TESTCASES +}; diff --git a/src/test/test_periodic_event.c b/src/test/test_periodic_event.c new file mode 100644 index 0000000000..86dedd85d8 --- /dev/null +++ b/src/test/test_periodic_event.c @@ -0,0 +1,333 @@ +/* Copyright (c) 2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file test_periodic_event.c + * \brief Test the periodic events that Tor uses for different roles. They are + * part of the libevent mainloop + */ + +#define CONFIG_PRIVATE +#define HS_SERVICE_PRIVATE +#define MAINLOOP_PRIVATE + +#include "test/test.h" +#include "test/test_helpers.h" + +#include "core/or/or.h" +#include "app/config/config.h" +#include "feature/hibernate/hibernate.h" +#include "feature/hs/hs_service.h" +#include "core/mainloop/mainloop.h" +#include "core/mainloop/periodic.h" + +/** Helper function: This is replaced in some tests for the event callbacks so + * we don't actually go into the code path of those callbacks. */ +static int +dumb_event_fn(time_t now, const or_options_t *options) +{ + (void) now; + (void) options; + + /* Will get rescheduled in 300 seconds. It just can't be 0. */ + return 300; +} + +static void +register_dummy_hidden_service(hs_service_t *service) +{ + memset(service, 0, sizeof(hs_service_t)); + memset(&service->keys.identity_pk, 'A', sizeof(service->keys.identity_pk)); + (void) register_service(get_hs_service_map(), service); +} + +static void +test_pe_initialize(void *arg) +{ + (void) arg; + + /* Initialize the events but the callback won't get called since we would + * need to run the main loop and then wait for a second delaying the unit + * tests. Instead, we'll test the callback work indepedently elsewhere. */ + initialize_periodic_events(); + + /* Validate that all events have been set up. */ + for (int i = 0; periodic_events[i].name; ++i) { + periodic_event_item_t *item = &periodic_events[i]; + tt_assert(item->ev); + tt_assert(item->fn); + tt_u64_op(item->last_action_time, OP_EQ, 0); + /* Every event must have role(s) assign to it. This is done statically. */ + tt_u64_op(item->roles, OP_NE, 0); + tt_uint_op(periodic_event_is_enabled(item), OP_EQ, 0); + } + + done: + teardown_periodic_events(); +} + +static void +test_pe_launch(void *arg) +{ + hs_service_t service, *to_remove = NULL; + or_options_t *options; + + (void) arg; + + hs_init(); + /* We need to put tor in hibernation live state so the events requiring + * network gets enabled. */ + consider_hibernation(time(NULL)); + + /* Hack: We'll set a dumb fn() of each events so they don't get called when + * dispatching them. We just want to test the state of the callbacks, not + * the whole code path. */ + for (int i = 0; periodic_events[i].name; ++i) { + periodic_event_item_t *item = &periodic_events[i]; + item->fn = dumb_event_fn; + } + + options = get_options_mutable(); + options->SocksPort_set = 1; + periodic_events_on_new_options(options); +#if 0 + /* Lets make sure that before intialization, we can't scan the periodic + * events list and launch them. Lets try by being a Client. */ + /* XXXX We make sure these events are initialized now way earlier than we + * did before. */ + for (int i = 0; periodic_events[i].name; ++i) { + periodic_event_item_t *item = &periodic_events[i]; + tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0); + } +#endif + + initialize_periodic_events(); + + /* Now that we've initialized, rescan the list to launch. */ + periodic_events_on_new_options(options); + + for (int i = 0; periodic_events[i].name; ++i) { + periodic_event_item_t *item = &periodic_events[i]; + if (item->roles & PERIODIC_EVENT_ROLE_CLIENT) { + tt_int_op(periodic_event_is_enabled(item), OP_EQ, 1); + } else { + tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0); + } + // enabled or not, the event has not yet been run. + tt_u64_op(item->last_action_time, OP_EQ, 0); + } + + /* Remove Client but become a Relay. */ + options->SocksPort_set = 0; + options->ORPort_set = 1; + periodic_events_on_new_options(options); + + unsigned roles = get_my_roles(options); + tt_uint_op(roles, OP_EQ, + PERIODIC_EVENT_ROLE_RELAY|PERIODIC_EVENT_ROLE_DIRSERVER); + + for (int i = 0; periodic_events[i].name; ++i) { + periodic_event_item_t *item = &periodic_events[i]; + /* Only Client role should be disabled. */ + if (item->roles == PERIODIC_EVENT_ROLE_CLIENT) { + tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0); + } + if (item->roles & PERIODIC_EVENT_ROLE_RELAY) { + tt_int_op(periodic_event_is_enabled(item), OP_EQ, 1); + } + /* Non Relay role should be disabled, except for Dirserver. */ + if (!(item->roles & roles)) { + tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0); + } + } + + /* Disable everything and we'll enable them ALL. */ + options->SocksPort_set = 0; + options->ORPort_set = 0; + periodic_events_on_new_options(options); + + for (int i = 0; periodic_events[i].name; ++i) { + periodic_event_item_t *item = &periodic_events[i]; + tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0); + } + + /* Enable everything. */ + options->SocksPort_set = 1; options->ORPort_set = 1; + options->BridgeRelay = 1; options->AuthoritativeDir = 1; + options->V3AuthoritativeDir = 1; options->BridgeAuthoritativeDir = 1; + register_dummy_hidden_service(&service); + periodic_events_on_new_options(options); + /* Note down the reference because we need to remove this service from the + * global list before the hs_free_all() call so it doesn't try to free + * memory on the stack. Furthermore, we can't remove it now else it will + * trigger a rescan of the event disabling the HS service event. */ + to_remove = &service; + + for (int i = 0; periodic_events[i].name; ++i) { + periodic_event_item_t *item = &periodic_events[i]; + tt_int_op(periodic_event_is_enabled(item), OP_EQ, 1); + } + + done: + if (to_remove) { + remove_service(get_hs_service_map(), to_remove); + } + hs_free_all(); +} + +static void +test_pe_get_roles(void *arg) +{ + int roles; + + (void) arg; + + /* Just so the HS global map exists. */ + hs_init(); + + or_options_t *options = get_options_mutable(); + tt_assert(options); + + /* Nothing configured, should be no roles. */ + roles = get_my_roles(options); + tt_int_op(roles, OP_EQ, 0); + + /* Indicate we have a SocksPort, roles should be come Client. */ + options->SocksPort_set = 1; + roles = get_my_roles(options); + tt_int_op(roles, OP_EQ, PERIODIC_EVENT_ROLE_CLIENT); + + /* Now, we'll add a ORPort so should now be a Relay + Client. */ + options->ORPort_set = 1; + roles = get_my_roles(options); + tt_int_op(roles, OP_EQ, + (PERIODIC_EVENT_ROLE_CLIENT | PERIODIC_EVENT_ROLE_RELAY | + PERIODIC_EVENT_ROLE_DIRSERVER)); + + /* Now add a Bridge. */ + options->BridgeRelay = 1; + roles = get_my_roles(options); + tt_int_op(roles, OP_EQ, + (PERIODIC_EVENT_ROLE_CLIENT | PERIODIC_EVENT_ROLE_RELAY | + PERIODIC_EVENT_ROLE_BRIDGE | PERIODIC_EVENT_ROLE_DIRSERVER)); + tt_assert(roles & PERIODIC_EVENT_ROLE_ROUTER); + /* Unset client so we can solely test Router role. */ + options->SocksPort_set = 0; + roles = get_my_roles(options); + tt_int_op(roles, OP_EQ, + PERIODIC_EVENT_ROLE_ROUTER | PERIODIC_EVENT_ROLE_DIRSERVER); + + /* Reset options so we can test authorities. */ + options->SocksPort_set = 0; + options->ORPort_set = 0; + options->BridgeRelay = 0; + roles = get_my_roles(options); + tt_int_op(roles, OP_EQ, 0); + + /* Now upgrade to Dirauth. */ + options->DirPort_set = 1; + options->AuthoritativeDir = 1; + options->V3AuthoritativeDir = 1; + roles = get_my_roles(options); + tt_int_op(roles, OP_EQ, + PERIODIC_EVENT_ROLE_DIRAUTH|PERIODIC_EVENT_ROLE_DIRSERVER); + tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES); + + /* Now Bridge Authority. */ + options->V3AuthoritativeDir = 0; + options->BridgeAuthoritativeDir = 1; + roles = get_my_roles(options); + tt_int_op(roles, OP_EQ, + PERIODIC_EVENT_ROLE_BRIDGEAUTH|PERIODIC_EVENT_ROLE_DIRSERVER); + tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES); + + /* Move that bridge auth to become a relay. */ + options->ORPort_set = 1; + roles = get_my_roles(options); + tt_int_op(roles, OP_EQ, + (PERIODIC_EVENT_ROLE_BRIDGEAUTH | PERIODIC_EVENT_ROLE_RELAY + | PERIODIC_EVENT_ROLE_DIRSERVER)); + tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES); + + /* And now an Hidden service. */ + hs_service_t service; + register_dummy_hidden_service(&service); + roles = get_my_roles(options); + /* Remove it now so the hs_free_all() doesn't try to free stack memory. */ + remove_service(get_hs_service_map(), &service); + tt_int_op(roles, OP_EQ, + (PERIODIC_EVENT_ROLE_BRIDGEAUTH | PERIODIC_EVENT_ROLE_RELAY | + PERIODIC_EVENT_ROLE_HS_SERVICE | PERIODIC_EVENT_ROLE_DIRSERVER)); + tt_assert(roles & PERIODIC_EVENT_ROLE_AUTHORITIES); + + done: + hs_free_all(); +} + +static void +test_pe_hs_service(void *arg) +{ + hs_service_t service, *to_remove = NULL; + + (void) arg; + + hs_init(); + /* We need to put tor in hibernation live state so the events requiring + * network gets enabled. */ + consider_hibernation(time(NULL)); + /* Initialize the events so we can enable them */ + initialize_periodic_events(); + + /* Hack: We'll set a dumb fn() of each events so they don't get called when + * dispatching them. We just want to test the state of the callbacks, not + * the whole code path. */ + for (int i = 0; periodic_events[i].name; ++i) { + periodic_event_item_t *item = &periodic_events[i]; + item->fn = dumb_event_fn; + } + + /* This should trigger a rescan of the list and enable the HS service + * events. */ + register_dummy_hidden_service(&service); + /* Note down the reference because we need to remove this service from the + * global list before the hs_free_all() call so it doesn't try to free + * memory on the stack. Furthermore, we can't remove it now else it will + * trigger a rescan of the event disabling the HS service event. */ + to_remove = &service; + + for (int i = 0; periodic_events[i].name; ++i) { + periodic_event_item_t *item = &periodic_events[i]; + if (item->roles & PERIODIC_EVENT_ROLE_HS_SERVICE) { + tt_int_op(periodic_event_is_enabled(item), OP_EQ, 1); + } + } + to_remove = NULL; + + /* Remove the service from the global map, it should trigger a rescan and + * disable the HS service events. */ + remove_service(get_hs_service_map(), &service); + for (int i = 0; periodic_events[i].name; ++i) { + periodic_event_item_t *item = &periodic_events[i]; + if (item->roles & PERIODIC_EVENT_ROLE_HS_SERVICE) { + tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0); + } + } + + done: + if (to_remove) { + remove_service(get_hs_service_map(), to_remove); + } + hs_free_all(); +} + +#define PE_TEST(name) \ + { #name, test_pe_## name , TT_FORK, NULL, NULL } + +struct testcase_t periodic_event_tests[] = { + PE_TEST(initialize), + PE_TEST(launch), + PE_TEST(get_roles), + PE_TEST(hs_service), + + END_OF_TESTCASES +}; diff --git a/src/test/test_policy.c b/src/test/test_policy.c index f8aa8ac40b..afe608f5f7 100644 --- a/src/test/test_policy.c +++ b/src/test/test_policy.c @@ -1,14 +1,22 @@ -/* Copyright (c) 2013-2017, The Tor Project, Inc. */ +/* Copyright (c) 2013-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "or.h" #define CONFIG_PRIVATE -#include "config.h" -#include "router.h" -#include "routerparse.h" #define POLICIES_PRIVATE -#include "policies.h" -#include "test.h" + +#include "core/or/or.h" +#include "app/config/config.h" +#include "core/or/policies.h" +#include "feature/dirparse/policy_parse.h" +#include "feature/relay/router.h" +#include "lib/encoding/confline.h" +#include "test/test.h" + +#include "core/or/addr_policy_st.h" +#include "core/or/port_cfg_st.h" +#include "feature/nodelist/node_st.h" +#include "feature/nodelist/routerinfo_st.h" +#include "feature/nodelist/routerstatus_st.h" /* Helper: assert that short_policy parses and writes back out as itself, or as <b>expected</b> if that's provided. */ @@ -1496,9 +1504,21 @@ test_dump_exit_policy_to_string(void *arg) } static routerinfo_t *mock_desc_routerinfo = NULL; +static int routerinfo_err; + static const routerinfo_t * -mock_router_get_my_routerinfo(void) +mock_router_get_my_routerinfo_with_err(int *err) { + if (routerinfo_err) { + if (err) + *err = routerinfo_err; + + return NULL; + } + + if (err) + *err = 0; + return mock_desc_routerinfo; } @@ -1541,7 +1561,8 @@ test_policies_getinfo_helper_policies(void *arg) tor_free(answer); memset(&mock_my_routerinfo, 0, sizeof(routerinfo_t)); - MOCK(router_get_my_routerinfo, mock_router_get_my_routerinfo); + MOCK(router_get_my_routerinfo_with_err, + mock_router_get_my_routerinfo_with_err); mock_my_routerinfo.exit_policy = smartlist_new(); mock_desc_routerinfo = &mock_my_routerinfo; @@ -1658,6 +1679,55 @@ test_policies_getinfo_helper_policies(void *arg) tt_assert(strlen(answer) == ipv4_len + ipv6_len + 1); tor_free(answer); + routerinfo_err = TOR_ROUTERINFO_ERROR_NO_EXT_ADDR; + rv = getinfo_helper_policies(NULL, "exit-policy/full", &answer, + &errmsg); + tt_int_op(rv, OP_EQ, -1); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); + tt_str_op(errmsg, OP_EQ, "No known exit address yet"); + + routerinfo_err = TOR_ROUTERINFO_ERROR_CANNOT_PARSE; + rv = getinfo_helper_policies(NULL, "exit-policy/full", &answer, + &errmsg); + tt_int_op(rv, OP_EQ, -1); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); + tt_str_op(errmsg, OP_EQ, "Cannot parse descriptor"); + + routerinfo_err = TOR_ROUTERINFO_ERROR_NOT_A_SERVER; + rv = getinfo_helper_policies(NULL, "exit-policy/full", &answer, + &errmsg); + tt_int_op(rv, OP_EQ, 0); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); + tt_str_op(errmsg, OP_EQ, "Not running in server mode"); + + routerinfo_err = TOR_ROUTERINFO_ERROR_DIGEST_FAILED; + rv = getinfo_helper_policies(NULL, "exit-policy/full", &answer, + &errmsg); + + tt_int_op(rv, OP_EQ, -1); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); + tt_str_op(errmsg, OP_EQ, "Key digest failed"); + + routerinfo_err = TOR_ROUTERINFO_ERROR_CANNOT_GENERATE; + rv = getinfo_helper_policies(NULL, "exit-policy/full", &answer, + &errmsg); + tt_int_op(rv, OP_EQ, -1); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); + tt_str_op(errmsg, OP_EQ, "Cannot generate descriptor"); + + routerinfo_err = TOR_ROUTERINFO_ERROR_DESC_REBUILDING; + rv = getinfo_helper_policies(NULL, "exit-policy/full", &answer, + &errmsg); + tt_int_op(rv, OP_EQ, -1); + tt_ptr_op(answer, OP_EQ, NULL); + tt_ptr_op(errmsg, OP_NE, NULL); + tt_str_op(errmsg, OP_EQ, "Descriptor still rebuilding - not ready yet"); + done: tor_free(answer); UNMOCK(get_options); @@ -1923,11 +1993,8 @@ test_policies_fascist_firewall_allows_address(void *arg) tor_addr_port_t chosen_rs_ap; \ tor_addr_make_null(&chosen_rs_ap.addr, AF_INET); \ chosen_rs_ap.port = 0; \ - tt_int_op(fascist_firewall_choose_address_rs(&(fake_rs), \ - (fw_connection), \ - (pref_only), \ - &chosen_rs_ap), \ - OP_EQ, (expect_rv)); \ + fascist_firewall_choose_address_rs(&(fake_rs), (fw_connection), \ + (pref_only), &chosen_rs_ap); \ tt_assert(tor_addr_eq(&(expect_ap).addr, &chosen_rs_ap.addr)); \ tt_int_op((expect_ap).port, OP_EQ, chosen_rs_ap.port); \ STMT_END @@ -1940,11 +2007,8 @@ test_policies_fascist_firewall_allows_address(void *arg) tor_addr_port_t chosen_node_ap; \ tor_addr_make_null(&chosen_node_ap.addr, AF_INET); \ chosen_node_ap.port = 0; \ - tt_int_op(fascist_firewall_choose_address_node(&(fake_node), \ - (fw_connection), \ - (pref_only), \ - &chosen_node_ap), \ - OP_EQ, (expect_rv)); \ + fascist_firewall_choose_address_node(&(fake_node),(fw_connection), \ + (pref_only), &chosen_node_ap); \ tt_assert(tor_addr_eq(&(expect_ap).addr, &chosen_node_ap.addr)); \ tt_int_op((expect_ap).port, OP_EQ, chosen_node_ap.port); \ STMT_END @@ -2389,4 +2453,3 @@ struct testcase_t policy_tests[] = { test_policies_fascist_firewall_choose_address, 0, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_procmon.c b/src/test/test_procmon.c index 5c52af8693..2c7918f580 100644 --- a/src/test/test_procmon.c +++ b/src/test/test_procmon.c @@ -1,14 +1,14 @@ -/* Copyright (c) 2010-2017, The Tor Project, Inc. */ +/* Copyright (c) 2010-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define PROCMON_PRIVATE #include "orconfig.h" -#include "or.h" -#include "test.h" +#include "core/or/or.h" +#include "test/test.h" -#include "procmon.h" +#include "lib/evloop/procmon.h" -#include "log_test_helpers.h" +#include "test/log_test_helpers.h" #define NS_MODULE procmon diff --git a/src/test/test_proto_http.c b/src/test/test_proto_http.c index 2f36fbccd7..1cfa0a752c 100644 --- a/src/test/test_proto_http.c +++ b/src/test/test_proto_http.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -6,11 +6,11 @@ * \brief Tests for our HTTP protocol parser code */ -#include "or.h" -#include "test.h" -#include "buffers.h" -#include "proto_http.h" -#include "log_test_helpers.h" +#include "core/or/or.h" +#include "test/test.h" +#include "lib/container/buffers.h" +#include "core/proto/proto_http.h" +#include "test/log_test_helpers.h" #define S(str) str, sizeof(str)-1 diff --git a/src/test/test_proto_misc.c b/src/test/test_proto_misc.c index 263ca47447..1fcb763421 100644 --- a/src/test/test_proto_misc.c +++ b/src/test/test_proto_misc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -6,14 +6,16 @@ * \brief Test our smaller buffer-based protocol functions */ -#include "or.h" -#include "test.h" -#include "buffers.h" -#include "connection_or.h" -#include "ext_orport.h" -#include "proto_cell.h" -#include "proto_control0.h" -#include "proto_ext_or.h" +#include "core/or/or.h" +#include "test/test.h" +#include "lib/container/buffers.h" +#include "core/or/connection_or.h" +#include "feature/relay/ext_orport.h" +#include "core/proto/proto_cell.h" +#include "core/proto/proto_control0.h" +#include "core/proto/proto_ext_or.h" + +#include "core/or/var_cell_st.h" static void test_proto_var_cell(void *arg) diff --git a/src/test/test_protover.c b/src/test/test_protover.c index fb374c728b..b835e28ab5 100644 --- a/src/test/test_protover.c +++ b/src/test/test_protover.c @@ -1,15 +1,16 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define PROTOVER_PRIVATE #include "orconfig.h" -#include "test.h" +#include "test/test.h" -#include "protover.h" +#include "core/or/protover.h" -#include "or.h" -#include "connection_or.h" +#include "core/or/or.h" +#include "core/or/connection_or.h" +#include "lib/tls/tortls.h" static void test_protover_parse(void *arg) @@ -167,6 +168,14 @@ test_protover_vote(void *arg) tt_str_op(result, OP_EQ, ""); tor_free(result); + /* Don't count double-voting. */ + smartlist_clear(lst); + smartlist_add(lst, (void*) "Foo=1 Foo=1"); + smartlist_add(lst, (void*) "Bar=1-2,2-3"); + result = protover_compute_vote(lst, 2); + tt_str_op(result, OP_EQ, ""); + tor_free(result); + /* Bad votes: the result must be empty */ smartlist_clear(lst); smartlist_add(lst, (void*) "Faux=10-5"); @@ -229,8 +238,8 @@ test_protover_vote(void *arg) /* Protocol name too long */ smartlist_clear(lst); smartlist_add(lst, (void*) "DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); result = protover_compute_vote(lst, 1); tt_str_op(result, OP_EQ, ""); tor_free(result); @@ -320,10 +329,10 @@ test_protover_all_supported(void *arg) #ifndef HAVE_RUST // XXXXXX ????? tor_capture_bugs_(1); tt_assert(protover_all_supported( - "DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaa=1-65536", &msg)); + "DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaa=1-65536", &msg)); tor_end_capture_bugs_(); #endif @@ -444,10 +453,12 @@ test_protover_supported_protocols(void *arg) } } +#ifdef HAVE_WORKING_TOR_TLS_GET_TLSSECRETS /* Legacy LinkAuth does not appear anywhere in the code. */ tt_assert(protocol_list_supports_protocol(supported_protocols, PRT_LINKAUTH, PROTOVER_LINKAUTH_V1)); +#endif /* Latest LinkAuth is not exposed in the headers. */ tt_assert(protocol_list_supports_protocol(supported_protocols, PRT_LINKAUTH, @@ -543,6 +554,10 @@ test_protover_vote_roundtrip(void *args) const char *input; const char *expected_output; } examples[] = { + { "Risqu\u00e9=1", NULL }, + { ",,,=1", NULL }, + { "\xc1=1", NULL }, + { "Foo_Bar=1", NULL }, { "Fkrkljdsf", NULL }, { "Zn=4294967295", NULL }, { "Zn=4294967295-1", NULL }, @@ -575,6 +590,14 @@ test_protover_vote_roundtrip(void *args) { "Faux=-1", NULL }, { "Faux=-1-3", NULL }, { "Faux=1--1", NULL }, + { "Link=1-2-", NULL }, + { "Link=1-2-3", NULL }, + { "Faux=1-2-", NULL }, + { "Faux=1-2-3", NULL }, + { "Link=\t1,3", NULL }, + { "Link=1\n,3", NULL }, + { "Faux=1,\r3", NULL }, + { "Faux=1,3\f", NULL }, /* Large integers */ { "Link=4294967296", NULL }, /* Large range */ @@ -625,4 +648,3 @@ struct testcase_t protover_tests[] = { PV_TEST(vote_roundtrip, 0), END_OF_TESTCASES }; - diff --git a/src/test/test_pt.c b/src/test/test_pt.c index 07b6712ff9..d0160d1148 100644 --- a/src/test/test_pt.c +++ b/src/test/test_pt.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" @@ -8,15 +8,20 @@ #define UTIL_PRIVATE #define STATEFILE_PRIVATE #define CONTROL_PRIVATE -#include "or.h" -#include "config.h" -#include "confparse.h" -#include "control.h" -#include "transports.h" -#include "circuitbuild.h" -#include "util.h" -#include "statefile.h" -#include "test.h" +#define SUBPROCESS_PRIVATE +#include "core/or/or.h" +#include "app/config/config.h" +#include "app/config/confparse.h" +#include "feature/control/control.h" +#include "feature/client/transports.h" +#include "core/or/circuitbuild.h" +#include "app/config/statefile.h" +#include "test/test.h" +#include "lib/process/subprocess.h" +#include "lib/encoding/confline.h" +#include "lib/net/resolve.h" + +#include "app/config/or_state_st.h" static void reset_mp(managed_proxy_t *mp) @@ -544,4 +549,3 @@ struct testcase_t pt_tests[] = { NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_pubsub.c b/src/test/test_pubsub.c deleted file mode 100644 index 2f047d9f2c..0000000000 --- a/src/test/test_pubsub.c +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ - -/** - * \file test_pubsub.c - * \brief Unit tests for publish-subscribe abstraction. - **/ - -#include "or.h" -#include "test.h" -#include "pubsub.h" - -DECLARE_PUBSUB_STRUCT_TYPES(foobar) -DECLARE_PUBSUB_TOPIC(foobar) -DECLARE_NOTIFY_PUBSUB_TOPIC(static, foobar) -IMPLEMENT_PUBSUB_TOPIC(static, foobar) - -struct foobar_event_data_t { - unsigned u; - const char *s; -}; - -struct foobar_subscriber_data_t { - const char *name; - long l; -}; - -static int -foobar_sub1(foobar_event_data_t *ev, foobar_subscriber_data_t *mine) -{ - ev->u += 10; - mine->l += 100; - return 0; -} - -static int -foobar_sub2(foobar_event_data_t *ev, foobar_subscriber_data_t *mine) -{ - ev->u += 5; - mine->l += 50; - return 0; -} - -static void -test_pubsub_basic(void *arg) -{ - (void)arg; - foobar_subscriber_data_t subdata1 = { "hi", 0 }; - foobar_subscriber_data_t subdata2 = { "wow", 0 }; - const foobar_subscriber_t *sub1; - const foobar_subscriber_t *sub2; - foobar_event_data_t ed = { 0, "x" }; - foobar_event_data_t ed2 = { 0, "y" }; - sub1 = foobar_subscribe(foobar_sub1, &subdata1, SUBSCRIBE_ATSTART, 100); - tt_assert(sub1); - - foobar_notify(&ed, 0); - tt_int_op(subdata1.l, OP_EQ, 100); - tt_int_op(subdata2.l, OP_EQ, 0); - tt_int_op(ed.u, OP_EQ, 10); - - sub2 = foobar_subscribe(foobar_sub2, &subdata2, 0, 5); - tt_assert(sub2); - - foobar_notify(&ed2, 0); - tt_int_op(subdata1.l, OP_EQ, 200); - tt_int_op(subdata2.l, OP_EQ, 50); - tt_int_op(ed2.u, OP_EQ, 15); - - foobar_unsubscribe(sub1); - - foobar_notify(&ed, 0); - tt_int_op(subdata1.l, OP_EQ, 200); - tt_int_op(subdata2.l, OP_EQ, 100); - tt_int_op(ed.u, OP_EQ, 15); - - done: - foobar_clear(); -} - -struct testcase_t pubsub_tests[] = { - { "pubsub_basic", test_pubsub_basic, TT_FORK, NULL, NULL }, - END_OF_TESTCASES -}; - diff --git a/src/test/test_rebind.py b/src/test/test_rebind.py new file mode 100644 index 0000000000..7ba3a5796d --- /dev/null +++ b/src/test/test_rebind.py @@ -0,0 +1,93 @@ +from __future__ import print_function + +import sys +import subprocess +import socket +import os +import time +import random + +def try_connecting_to_socksport(): + socks_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + if socks_socket.connect_ex(('127.0.0.1', socks_port)): + tor_process.terminate() + print('FAIL') + sys.exit('Cannot connect to SOCKSPort') + socks_socket.close() + +def wait_for_log(s): + while True: + l = tor_process.stdout.readline() + if s in l.decode('utf8'): + return + +def pick_random_port(): + port = 0 + random.seed() + + for i in range(8): + port = random.randint(10000, 60000) + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + if s.connect_ex(('127.0.0.1', port)) == 0: + s.close() + else: + break + + return port + +if sys.hexversion < 0x02070000: + sys.exit("ERROR: unsupported Python version (should be >= 2.7)") + +if sys.hexversion > 0x03000000 and sys.hexversion < 0x03010000: + sys.exit("ERROR: unsupported Python3 version (should be >= 3.1)") + +control_port = pick_random_port() +socks_port = pick_random_port() + +assert control_port != 0 +assert socks_port != 0 + +if not os.path.exists(sys.argv[1]): + sys.exit('ERROR: cannot find tor at %s' % sys.argv[1]) + +tor_path = sys.argv[1] + +tor_process = subprocess.Popen([tor_path, + '-ControlPort', '127.0.0.1:{}'.format(control_port), + '-SOCKSPort', '127.0.0.1:{}'.format(socks_port), + '-FetchServerDescriptors', '0'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + +if tor_process == None: + sys.exit('ERROR: running tor failed') + +if len(sys.argv) < 2: + sys.exit('Usage: %s <path-to-tor>' % sys.argv[0]) + +wait_for_log('Opened Control listener on') + +try_connecting_to_socksport() + +control_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +if control_socket.connect_ex(('127.0.0.1', control_port)): + tor_process.terminate() + print('FAIL') + sys.exit('Cannot connect to ControlPort') + +control_socket.sendall('AUTHENTICATE \r\n'.encode('utf8')) +control_socket.sendall('SETCONF SOCKSPort=0.0.0.0:{}\r\n'.format(socks_port).encode('utf8')) +wait_for_log('Opened Socks listener') + +try_connecting_to_socksport() + +control_socket.sendall('SETCONF SOCKSPort=127.0.0.1:{}\r\n'.format(socks_port).encode('utf8')) +wait_for_log('Opened Socks listener') + +try_connecting_to_socksport() + +control_socket.sendall('SIGNAL HALT\r\n'.encode('utf8')) + +time.sleep(0.1) +print('OK') +tor_process.terminate() diff --git a/src/test/test_rebind.sh b/src/test/test_rebind.sh new file mode 100755 index 0000000000..76eb9f2e4d --- /dev/null +++ b/src/test/test_rebind.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +set -x + +UNAME_OS=$(uname -s | cut -d_ -f1) +if test "$UNAME_OS" = 'CYGWIN' || \ + test "$UNAME_OS" = 'MSYS' || \ + test "$UNAME_OS" = 'MINGW'; then + if test "$APPVEYOR" = 'True'; then + echo "This test is disabled on Windows CI, as it requires firewall examptions. Skipping." >&2 + exit 77 + fi +fi + +exitcode=0 + +"${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/test_rebind.py" "${TESTING_TOR_BINARY}" || exitcode=1 + +exit ${exitcode} diff --git a/src/test/test_relay.c b/src/test/test_relay.c index 73c0ed5586..4311392be8 100644 --- a/src/test/test_relay.c +++ b/src/test/test_relay.c @@ -1,17 +1,26 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "or.h" #define CIRCUITBUILD_PRIVATE -#include "circuitbuild.h" #define RELAY_PRIVATE -#include "relay.h" +#define REPHIST_PRIVATE +#include "core/or/or.h" +#include "core/or/circuitbuild.h" +#include "core/or/circuitlist.h" +#include "core/or/channeltls.h" +#include "feature/stats/rephist.h" +#include "core/or/relay.h" +#include "feature/stats/rephist.h" +#include "lib/container/order.h" /* For init/free stuff */ -#include "scheduler.h" +#include "core/or/scheduler.h" + +#include "core/or/cell_st.h" +#include "core/or/or_circuit_st.h" /* Test suite stuff */ -#include "test.h" -#include "fakechans.h" +#include "test/test.h" +#include "test/fakechans.h" static or_circuit_t * new_fake_orcirc(channel_t *nchan, channel_t *pchan); @@ -27,10 +36,9 @@ new_fake_orcirc(channel_t *nchan, channel_t *pchan) circ = &(orcirc->base_); circ->magic = OR_CIRCUIT_MAGIC; - circ->n_chan = nchan; - circ->n_circ_id = get_unique_circ_id_by_chan(nchan); - circ->n_mux = NULL; /* ?? */ + circuit_set_n_circid_chan(circ, get_unique_circ_id_by_chan(nchan), nchan); cell_queue_init(&(circ->n_chan_cells)); + circ->n_hop = NULL; circ->streams_blocked_on_n_chan = 0; circ->streams_blocked_on_p_chan = 0; @@ -43,14 +51,109 @@ new_fake_orcirc(channel_t *nchan, channel_t *pchan) circ->deliver_window = CIRCWINDOW_START_MAX; circ->n_chan_create_cell = NULL; - orcirc->p_chan = pchan; - orcirc->p_circ_id = get_unique_circ_id_by_chan(pchan); + circuit_set_p_circid_chan(orcirc, get_unique_circ_id_by_chan(pchan), pchan); cell_queue_init(&(orcirc->p_chan_cells)); return orcirc; } static void +assert_circuit_ok_mock(const circuit_t *c) +{ + (void) c; + return; +} + +static void +test_relay_close_circuit(void *arg) +{ + channel_t *nchan = NULL, *pchan = NULL; + or_circuit_t *orcirc = NULL; + cell_t *cell = NULL; + int old_count, new_count; + + (void)arg; + + /* Make fake channels to be nchan and pchan for the circuit */ + nchan = new_fake_channel(); + tt_assert(nchan); + + pchan = new_fake_channel(); + tt_assert(pchan); + + /* Make a fake orcirc */ + orcirc = new_fake_orcirc(nchan, pchan); + tt_assert(orcirc); + circuitmux_attach_circuit(nchan->cmux, TO_CIRCUIT(orcirc), + CELL_DIRECTION_OUT); + circuitmux_attach_circuit(pchan->cmux, TO_CIRCUIT(orcirc), + CELL_DIRECTION_IN); + + /* Make a cell */ + cell = tor_malloc_zero(sizeof(cell_t)); + make_fake_cell(cell); + + MOCK(scheduler_channel_has_waiting_cells, + scheduler_channel_has_waiting_cells_mock); + MOCK(assert_circuit_ok, + assert_circuit_ok_mock); + + /* Append it */ + old_count = get_mock_scheduler_has_waiting_cells_count(); + append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), nchan, cell, + CELL_DIRECTION_OUT, 0); + new_count = get_mock_scheduler_has_waiting_cells_count(); + tt_int_op(new_count, OP_EQ, old_count + 1); + + /* Now try the reverse direction */ + old_count = get_mock_scheduler_has_waiting_cells_count(); + append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), pchan, cell, + CELL_DIRECTION_IN, 0); + new_count = get_mock_scheduler_has_waiting_cells_count(); + tt_int_op(new_count, OP_EQ, old_count + 1); + + /* Ensure our write totals are 0 */ + tt_u64_op(find_largest_max(write_array), OP_EQ, 0); + + /* Mark the circuit for close */ + circuit_mark_for_close(TO_CIRCUIT(orcirc), 0); + + /* Check our write totals. */ + advance_obs(write_array); + commit_max(write_array); + /* Check for two cells plus overhead */ + tt_u64_op(find_largest_max(write_array), OP_EQ, + 2*(get_cell_network_size(nchan->wide_circ_ids) + +TLS_PER_CELL_OVERHEAD)); + + UNMOCK(scheduler_channel_has_waiting_cells); + + /* Get rid of the fake channels */ + MOCK(scheduler_release_channel, scheduler_release_channel_mock); + channel_mark_for_close(nchan); + channel_mark_for_close(pchan); + UNMOCK(scheduler_release_channel); + + /* Shut down channels */ + channel_free_all(); + + done: + tor_free(cell); + if (orcirc) { + circuitmux_detach_circuit(nchan->cmux, TO_CIRCUIT(orcirc)); + circuitmux_detach_circuit(pchan->cmux, TO_CIRCUIT(orcirc)); + cell_queue_clear(&orcirc->base_.n_chan_cells); + cell_queue_clear(&orcirc->p_chan_cells); + } + tor_free(orcirc); + free_fake_channel(nchan); + free_fake_channel(pchan); + UNMOCK(assert_circuit_ok); + + return; +} + +static void test_relay_append_cell_to_circuit_queue(void *arg) { channel_t *nchan = NULL, *pchan = NULL; @@ -125,6 +228,7 @@ test_relay_append_cell_to_circuit_queue(void *arg) struct testcase_t relay_tests[] = { { "append_cell_to_circuit_queue", test_relay_append_cell_to_circuit_queue, TT_FORK, NULL, NULL }, + { "close_circ_rephist", test_relay_close_circuit, + TT_FORK, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_relaycell.c b/src/test/test_relaycell.c index eea1f5dc80..3d3addfb9e 100644 --- a/src/test/test_relaycell.c +++ b/src/test/test_relaycell.c @@ -1,15 +1,35 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /* Unit tests for handling different kinds of relay cell */ #define RELAY_PRIVATE -#include "or.h" -#include "config.h" -#include "connection.h" -#include "connection_edge.h" -#include "relay.h" -#include "test.h" +#define CIRCUITLIST_PRIVATE +#define CONNECTION_EDGE_PRIVATE +#define CONNECTION_PRIVATE + +#include "core/or/or.h" +#include "core/mainloop/mainloop.h" +#include "app/config/config.h" +#include "core/mainloop/connection.h" +#include "lib/crypt_ops/crypto_cipher.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "core/or/circuitbuild.h" +#include "core/or/circuitlist.h" +#include "core/or/connection_edge.h" +#include "core/or/relay.h" +#include "test/test.h" +#include "test/log_test_helpers.h" + +#include "core/or/cell_st.h" +#include "core/or/crypt_path_st.h" +#include "core/or/entry_connection_st.h" +#include "core/or/origin_circuit_st.h" +#include "core/or/socks_request_st.h" +#include "core/or/half_edge_st.h" + +#include "feature/client/circpathbias.h" +#include "core/or/connection_edge.h" static int srm_ncalls; static entry_connection_t *srm_conn; @@ -60,6 +80,805 @@ mark_unattached_mock(entry_connection_t *conn, int endreason, (void) file; } +/* Helper: Return a newly allocated and initialized origin circuit with + * purpose and flags. A default HS identifier is set to an ed25519 + * authentication key for introduction point. */ +static origin_circuit_t * +helper_create_origin_circuit(int purpose, int flags) +{ + origin_circuit_t *circ = NULL; + + circ = origin_circuit_init(purpose, flags); + tor_assert(circ); + circ->cpath = tor_malloc_zero(sizeof(crypt_path_t)); + circ->cpath->magic = CRYPT_PATH_MAGIC; + circ->cpath->state = CPATH_STATE_OPEN; + circ->cpath->package_window = circuit_initial_package_window(); + circ->cpath->deliver_window = CIRCWINDOW_START; + circ->cpath->prev = circ->cpath; + /* Create a default HS identifier. */ + circ->hs_ident = tor_malloc_zero(sizeof(hs_ident_circuit_t)); + + return circ; +} + +static void +mock_connection_mark_unattached_ap_(entry_connection_t *conn, int endreason, + int line, const char *file) +{ + (void) line; + (void) file; + conn->edge_.end_reason = endreason; +} + +static void +mock_mark_circ_for_close(circuit_t *circ, int reason, int line, + const char *file) +{ + (void)reason; (void)line; (void)file; + + circ->marked_for_close = 1; + return; +} + +static void +mock_mark_for_close(connection_t *conn, + int line, const char *file) +{ + (void)line; + (void)file; + + conn->marked_for_close = 1; + return; +} + +static void +mock_start_reading(connection_t *conn) +{ + (void)conn; + return; +} + +static int +mock_send_command(streamid_t stream_id, circuit_t *circ, + uint8_t relay_command, const char *payload, + size_t payload_len, crypt_path_t *cpath_layer, + const char *filename, int lineno) +{ + (void)stream_id; (void)circ; + (void)relay_command; (void)payload; + (void)payload_len; (void)cpath_layer; + (void)filename; (void)lineno; + + return 0; +} + +static entry_connection_t * +fake_entry_conn(origin_circuit_t *oncirc, streamid_t id) +{ + edge_connection_t *edgeconn; + entry_connection_t *entryconn; + + entryconn = entry_connection_new(CONN_TYPE_AP, AF_INET); + edgeconn = ENTRY_TO_EDGE_CONN(entryconn); + edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT; + edgeconn->deliver_window = STREAMWINDOW_START; + edgeconn->package_window = STREAMWINDOW_START; + + edgeconn->stream_id = id; + edgeconn->on_circuit = TO_CIRCUIT(oncirc); + edgeconn->cpath_layer = oncirc->cpath; + + return entryconn; +} + +#define PACK_CELL(id, cmd, body_s) do { \ + memset(&cell, 0, sizeof(cell)); \ + memset(&rh, 0, sizeof(rh)); \ + memcpy(cell.payload+RELAY_HEADER_SIZE, (body_s), sizeof((body_s))-1); \ + rh.length = sizeof((body_s))-1; \ + rh.command = (cmd); \ + rh.stream_id = (id); \ + relay_header_pack((uint8_t*)&cell.payload, &rh); \ + } while (0) +#define ASSERT_COUNTED_BW() do { \ + tt_int_op(circ->n_delivered_read_circ_bw, OP_EQ, delivered+rh.length); \ + tt_int_op(circ->n_overhead_read_circ_bw, OP_EQ, \ + overhead+RELAY_PAYLOAD_SIZE-rh.length); \ + delivered = circ->n_delivered_read_circ_bw; \ + overhead = circ->n_overhead_read_circ_bw; \ + } while (0) +#define ASSERT_UNCOUNTED_BW() do { \ + tt_int_op(circ->n_delivered_read_circ_bw, OP_EQ, delivered); \ + tt_int_op(circ->n_overhead_read_circ_bw, OP_EQ, overhead); \ + } while (0) + +static int +subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) +{ + cell_t cell; + relay_header_t rh; + edge_connection_t *edgeconn; + entry_connection_t *entryconn2=NULL; + entry_connection_t *entryconn3=NULL; + entry_connection_t *entryconn4=NULL; + int delivered = circ->n_delivered_read_circ_bw; + int overhead = circ->n_overhead_read_circ_bw; + + /* Make new entryconns */ + entryconn2 = fake_entry_conn(circ, init_id); + entryconn2->socks_request->has_finished = 1; + entryconn3 = fake_entry_conn(circ, init_id+1); + entryconn3->socks_request->has_finished = 1; + entryconn4 = fake_entry_conn(circ, init_id+2); + entryconn4->socks_request->has_finished = 1; + edgeconn = ENTRY_TO_EDGE_CONN(entryconn2); + edgeconn->package_window = 23; + edgeconn->base_.state = AP_CONN_STATE_OPEN; + + int data_cells = edgeconn->deliver_window; + int sendme_cells = (STREAMWINDOW_START-edgeconn->package_window) + /STREAMWINDOW_INCREMENT; + ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0; + connection_edge_reached_eof(edgeconn); + + /* Data cell not in the half-opened list */ + PACK_CELL(4000, RELAY_COMMAND_DATA, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Sendme cell not in the half-opened list */ + PACK_CELL(4000, RELAY_COMMAND_SENDME, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Connected cell not in the half-opened list */ + PACK_CELL(4000, RELAY_COMMAND_CONNECTED, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Resolved cell not in the half-opened list */ + PACK_CELL(4000, RELAY_COMMAND_RESOLVED, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Connected cell: not counted -- we were open */ + edgeconn = ENTRY_TO_EDGE_CONN(entryconn2); + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* DATA cells up to limit */ + while (data_cells > 0) { + ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_COUNTED_BW(); + data_cells--; + } + ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* SENDME cells up to limit */ + while (sendme_cells > 0) { + ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_COUNTED_BW(); + sendme_cells--; + } + ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Only one END cell */ + ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_COUNTED_BW(); + + ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + edgeconn = ENTRY_TO_EDGE_CONN(entryconn3); + edgeconn->base_.state = AP_CONN_STATE_OPEN; + ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0; + /* sendme cell on open entryconn with full window */ + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234"); + int ret = + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + tt_int_op(ret, OP_EQ, -END_CIRC_REASON_TORPROTOCOL); + ASSERT_UNCOUNTED_BW(); + + /* connected cell on a after EOF */ + ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0; + edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT; + connection_edge_reached_eof(edgeconn); + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_COUNTED_BW(); + + ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* DATA and SENDME after END cell */ + ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_COUNTED_BW(); + + ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234"); + ret = + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + tt_int_op(ret, OP_NE, -END_CIRC_REASON_TORPROTOCOL); + ASSERT_UNCOUNTED_BW(); + + ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Resolved: 1 counted, more not */ + edgeconn = ENTRY_TO_EDGE_CONN(entryconn4); + entryconn4->socks_request->command = SOCKS_COMMAND_RESOLVE; + edgeconn->base_.state = AP_CONN_STATE_RESOLVE_WAIT; + edgeconn->on_circuit = TO_CIRCUIT(circ); + ENTRY_TO_CONN(entryconn4)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0; + connection_edge_reached_eof(edgeconn); + + ENTRY_TO_CONN(entryconn4)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_RESOLVED, + "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_COUNTED_BW(); + + ENTRY_TO_CONN(entryconn4)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_RESOLVED, + "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Data not counted after resolved */ + ENTRY_TO_CONN(entryconn4)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* End not counted after resolved */ + ENTRY_TO_CONN(entryconn4)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + connection_free_minimal(ENTRY_TO_CONN(entryconn2)); + connection_free_minimal(ENTRY_TO_CONN(entryconn3)); + connection_free_minimal(ENTRY_TO_CONN(entryconn4)); + return 1; + done: + connection_free_minimal(ENTRY_TO_CONN(entryconn2)); + connection_free_minimal(ENTRY_TO_CONN(entryconn3)); + connection_free_minimal(ENTRY_TO_CONN(entryconn4)); + return 0; +} + +static int +halfstream_insert(origin_circuit_t *circ, edge_connection_t *edgeconn, + streamid_t *streams, int num, int random) +{ + int inserted = 0; + + /* Insert num random elements */ + while (inserted < num) { + streamid_t id; + + if (random) + id = (streamid_t)crypto_rand_int(65535)+1; + else + id = get_unique_stream_id_by_circ(circ); + + edgeconn->stream_id = id; + + /* Ensure it isn't there */ + if (connection_half_edge_find_stream_id(circ->half_streams, id)) { + continue; + } + + connection_half_edge_add(edgeconn, circ); + if (streams) + streams[inserted] = id; + inserted++; + } + + return inserted; +} + +static void +subtest_halfstream_insertremove(int num) +{ + origin_circuit_t *circ = + helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL, 0); + edge_connection_t *edgeconn; + entry_connection_t *entryconn; + streamid_t *streams = tor_malloc_zero(num*sizeof(streamid_t)); + int i = 0; + + circ->cpath->state = CPATH_STATE_AWAITING_KEYS; + circ->cpath->deliver_window = CIRCWINDOW_START; + + entryconn = fake_entry_conn(circ, 23); + edgeconn = ENTRY_TO_EDGE_CONN(entryconn); + + /* Explicity test all operations on an absent stream list */ + tt_int_op(connection_half_edge_is_valid_data(circ->half_streams, + 23), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams, + 23), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams, + 23), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams, + 23), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_end(circ->half_streams, + 23), OP_EQ, 0); + + /* Insert a duplicate element; verify that other elements absent; + * ensure removing it once works */ + edgeconn->stream_id = 23; + connection_half_edge_add(edgeconn, circ); + connection_half_edge_add(edgeconn, circ); + connection_half_edge_add(edgeconn, circ); + + /* Verify that other elements absent */ + tt_int_op(connection_half_edge_is_valid_data(circ->half_streams, + 22), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams, + 22), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams, + 22), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams, + 22), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_end(circ->half_streams, + 22), OP_EQ, 0); + + tt_int_op(connection_half_edge_is_valid_data(circ->half_streams, + 24), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams, + 24), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams, + 24), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams, + 24), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_end(circ->half_streams, + 24), OP_EQ, 0); + + /* Verify we only remove it once */ + tt_int_op(connection_half_edge_is_valid_end(circ->half_streams, + 23), OP_EQ, 1); + tt_int_op(connection_half_edge_is_valid_end(circ->half_streams, + 23), OP_EQ, 0); + + halfstream_insert(circ, edgeconn, streams, num, 1); + + /* Remove half of them */ + for (i = 0; i < num/2; i++) { + tt_int_op(connection_half_edge_is_valid_end(circ->half_streams, + streams[i]), + OP_EQ, 1); + } + + /* Verify first half of list is gone */ + for (i = 0; i < num/2; i++) { + tt_ptr_op(connection_half_edge_find_stream_id(circ->half_streams, + streams[i]), + OP_EQ, NULL); + } + + /* Verify second half of list is present */ + for (; i < num; i++) { + tt_ptr_op(connection_half_edge_find_stream_id(circ->half_streams, + streams[i]), + OP_NE, NULL); + } + + /* Remove other half. Verify list is empty. */ + for (i = num/2; i < num; i++) { + tt_int_op(connection_half_edge_is_valid_end(circ->half_streams, + streams[i]), + OP_EQ, 1); + } + tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 0); + + /* Explicity test all operations on an empty stream list */ + tt_int_op(connection_half_edge_is_valid_data(circ->half_streams, + 23), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams, + 23), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams, + 23), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams, + 23), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_end(circ->half_streams, + 23), OP_EQ, 0); + + /* For valgrind, leave some around then free the circ */ + halfstream_insert(circ, edgeconn, NULL, 10, 0); + + done: + tor_free(streams); + circuit_free_(TO_CIRCUIT(circ)); + connection_free_minimal(ENTRY_TO_CONN(entryconn)); +} + +static void +test_halfstream_insertremove(void *arg) +{ + (void)arg; + + /* Suppress the WARN message we generate in this test */ + setup_full_capture_of_logs(LOG_WARN); + + /* Test insertion and removal with a few different sizes */ + subtest_halfstream_insertremove(10); + subtest_halfstream_insertremove(100); + subtest_halfstream_insertremove(1000); +} + +static void +test_halfstream_wrap(void *arg) +{ + origin_circuit_t *circ = + helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL, 0); + edge_connection_t *edgeconn; + entry_connection_t *entryconn; + + circ->cpath->state = CPATH_STATE_AWAITING_KEYS; + circ->cpath->deliver_window = CIRCWINDOW_START; + + entryconn = fake_entry_conn(circ, 23); + edgeconn = ENTRY_TO_EDGE_CONN(entryconn); + + (void)arg; + + /* Suppress the WARN message we generate in this test */ + setup_full_capture_of_logs(LOG_WARN); + MOCK(connection_mark_for_close_internal_, mock_mark_for_close); + + /* Verify that get_unique_stream_id_by_circ() can wrap uint16_t */ + circ->next_stream_id = 65530; + halfstream_insert(circ, edgeconn, NULL, 7, 0); + tt_int_op(circ->next_stream_id, OP_EQ, 2); + tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 7); + + /* Insert full-1 */ + halfstream_insert(circ, edgeconn, NULL, + 65534-smartlist_len(circ->half_streams), 0); + tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 65534); + + /* Verify that we can get_unique_stream_id_by_circ() successfully */ + edgeconn->stream_id = get_unique_stream_id_by_circ(circ); + tt_int_op(edgeconn->stream_id, OP_NE, 0); /* 0 is failure */ + + /* Insert an opened stream on the circ with that id */ + ENTRY_TO_CONN(entryconn)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn)->outbuf_flushlen = 0; + edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT; + circ->p_streams = edgeconn; + + /* Verify that get_unique_stream_id_by_circ() fails */ + tt_int_op(get_unique_stream_id_by_circ(circ), OP_EQ, 0); /* 0 is failure */ + + /* eof the one opened stream. Verify it is now in half-closed */ + tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 65534); + connection_edge_reached_eof(edgeconn); + tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 65535); + + /* Verify get_unique_stream_id_by_circ() fails due to full half-closed */ + circ->p_streams = NULL; + tt_int_op(get_unique_stream_id_by_circ(circ), OP_EQ, 0); /* 0 is failure */ + + done: + circuit_free_(TO_CIRCUIT(circ)); + connection_free_minimal(ENTRY_TO_CONN(entryconn)); + UNMOCK(connection_mark_for_close_internal_); +} + +static void +test_circbw_relay(void *arg) +{ + cell_t cell; + relay_header_t rh; + tor_addr_t addr; + edge_connection_t *edgeconn; + entry_connection_t *entryconn1=NULL; + origin_circuit_t *circ; + int delivered = 0; + int overhead = 0; + + (void)arg; + + MOCK(connection_mark_unattached_ap_, mock_connection_mark_unattached_ap_); + MOCK(connection_start_reading, mock_start_reading); + MOCK(connection_mark_for_close_internal_, mock_mark_for_close); + MOCK(relay_send_command_from_edge_, mock_send_command); + MOCK(circuit_mark_for_close_, mock_mark_circ_for_close); + + circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL, 0); + circ->cpath->state = CPATH_STATE_AWAITING_KEYS; + circ->cpath->deliver_window = CIRCWINDOW_START; + + entryconn1 = fake_entry_conn(circ, 1); + edgeconn = ENTRY_TO_EDGE_CONN(entryconn1); + + /* Stream id 0: Not counted */ + PACK_CELL(0, RELAY_COMMAND_END, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Stream id 1: Counted */ + PACK_CELL(1, RELAY_COMMAND_END, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + ASSERT_COUNTED_BW(); + + /* Properly formatted connect cell: counted */ + PACK_CELL(1, RELAY_COMMAND_CONNECTED, "Data1234"); + tor_addr_parse(&addr, "30.40.50.60"); + rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE, + &addr, 1024); + relay_header_pack((uint8_t*)&cell.payload, &rh); \ + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + ASSERT_COUNTED_BW(); + + /* Properly formatted resolved cell in correct state: counted */ + edgeconn->base_.state = AP_CONN_STATE_RESOLVE_WAIT; + entryconn1->socks_request->command = SOCKS_COMMAND_RESOLVE; + edgeconn->on_circuit = TO_CIRCUIT(circ); + PACK_CELL(1, RELAY_COMMAND_RESOLVED, + "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + ASSERT_COUNTED_BW(); + + edgeconn->base_.state = AP_CONN_STATE_OPEN; + entryconn1->socks_request->has_finished = 1; + + /* Connected cell after open: not counted */ + PACK_CELL(1, RELAY_COMMAND_CONNECTED, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Resolved cell after open: not counted */ + PACK_CELL(1, RELAY_COMMAND_RESOLVED, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Drop cell: not counted */ + PACK_CELL(1, RELAY_COMMAND_DROP, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Data cell on stream 0: not counted */ + PACK_CELL(0, RELAY_COMMAND_DATA, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Data cell on open connection: counted */ + ENTRY_TO_CONN(entryconn1)->marked_for_close = 0; + PACK_CELL(1, RELAY_COMMAND_DATA, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + ASSERT_COUNTED_BW(); + + /* Empty Data cell on open connection: not counted */ + ENTRY_TO_CONN(entryconn1)->marked_for_close = 0; + PACK_CELL(1, RELAY_COMMAND_DATA, ""); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Sendme on valid stream: counted */ + edgeconn->package_window -= STREAMWINDOW_INCREMENT; + ENTRY_TO_CONN(entryconn1)->outbuf_flushlen = 0; + PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + ASSERT_COUNTED_BW(); + + /* Sendme on valid stream with full window: not counted */ + ENTRY_TO_CONN(entryconn1)->outbuf_flushlen = 0; + PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234"); + edgeconn->package_window = STREAMWINDOW_START; + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Sendme on unknown stream: not counted */ + ENTRY_TO_CONN(entryconn1)->outbuf_flushlen = 0; + PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Sendme on circuit with full window: not counted */ + PACK_CELL(0, RELAY_COMMAND_SENDME, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Sendme on circuit with non-full window: counted */ + PACK_CELL(0, RELAY_COMMAND_SENDME, "Data1234"); + circ->cpath->package_window = 900; + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + ASSERT_COUNTED_BW(); + + /* Invalid extended cell: not counted */ + PACK_CELL(1, RELAY_COMMAND_EXTENDED2, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Invalid extended cell: not counted */ + PACK_CELL(1, RELAY_COMMAND_EXTENDED, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Invalid HS cell: not counted */ + PACK_CELL(1, RELAY_COMMAND_ESTABLISH_INTRO, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* "Valid" HS cell in expected state: counted */ + TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_C_ESTABLISH_REND; + PACK_CELL(1, RELAY_COMMAND_RENDEZVOUS_ESTABLISHED, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_COUNTED_BW(); + + /* End cell on non-closed connection: counted */ + PACK_CELL(1, RELAY_COMMAND_END, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + ASSERT_COUNTED_BW(); + + /* End cell on connection that already got one: not counted */ + PACK_CELL(1, RELAY_COMMAND_END, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Simulate closed stream on entryconn, then test: */ + if (!subtest_circbw_halfclosed(circ, 2)) + goto done; + + circ->base_.purpose = CIRCUIT_PURPOSE_PATH_BIAS_TESTING; + if (!subtest_circbw_halfclosed(circ, 6)) + goto done; + + /* Path bias: truncated */ + tt_int_op(circ->base_.marked_for_close, OP_EQ, 0); + PACK_CELL(0, RELAY_COMMAND_TRUNCATED, "Data1234"); + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + tt_int_op(circ->base_.marked_for_close, OP_EQ, 1); + + done: + UNMOCK(connection_start_reading); + UNMOCK(connection_mark_unattached_ap_); + UNMOCK(connection_mark_for_close_internal_); + UNMOCK(relay_send_command_from_edge_); + UNMOCK(circuit_mark_for_close_); + circuit_free_(TO_CIRCUIT(circ)); + connection_free_minimal(ENTRY_TO_CONN(entryconn1)); +} + /* Tests for connection_edge_process_resolved_cell(). The point of ..process_resolved_cell() is to handle an incoming cell @@ -244,6 +1063,8 @@ test_relaycell_resolved(void *arg) struct testcase_t relaycell_tests[] = { { "resolved", test_relaycell_resolved, TT_FORK, NULL, NULL }, + { "circbw", test_circbw_relay, TT_FORK, NULL, NULL }, + { "halfstream", test_halfstream_insertremove, TT_FORK, NULL, NULL }, + { "streamwrap", test_halfstream_wrap, TT_FORK, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_relaycrypt.c b/src/test/test_relaycrypt.c new file mode 100644 index 0000000000..c3cfb7d10b --- /dev/null +++ b/src/test/test_relaycrypt.c @@ -0,0 +1,190 @@ +/* Copyright 2001-2004 Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "core/or/or.h" +#include "core/or/circuitbuild.h" +#define CIRCUITLIST_PRIVATE +#include "core/or/circuitlist.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "core/or/relay.h" +#include "core/crypto/relay_crypto.h" + +#include "core/or/cell_st.h" +#include "core/or/or_circuit_st.h" +#include "core/or/origin_circuit_st.h" + +#include "test/test.h" + +static const char KEY_MATERIAL[3][CPATH_KEY_MATERIAL_LEN] = { + " 'My public key is in this signed x509 object', said Tom assertively.", + "'Let's chart the pedal phlanges in the tomb', said Tom cryptographically", + " 'Segmentation fault bugs don't _just happen_', said Tom seethingly.", +}; + +typedef struct testing_circuitset_t { + or_circuit_t *or_circ[3]; + origin_circuit_t *origin_circ; +} testing_circuitset_t; + +static int testing_circuitset_teardown(const struct testcase_t *testcase, + void *ptr); + +static void * +testing_circuitset_setup(const struct testcase_t *testcase) +{ + testing_circuitset_t *cs = tor_malloc_zero(sizeof(testing_circuitset_t)); + int i; + + for (i=0; i<3; ++i) { + cs->or_circ[i] = or_circuit_new(0, NULL); + tt_int_op(0, OP_EQ, + relay_crypto_init(&cs->or_circ[i]->crypto, + KEY_MATERIAL[i], sizeof(KEY_MATERIAL[i]), + 0, 0)); + } + + cs->origin_circ = origin_circuit_new(); + cs->origin_circ->base_.purpose = CIRCUIT_PURPOSE_C_GENERAL; + for (i=0; i<3; ++i) { + crypt_path_t *hop = tor_malloc_zero(sizeof(*hop)); + relay_crypto_init(&hop->crypto, KEY_MATERIAL[i], sizeof(KEY_MATERIAL[i]), + 0, 0); + hop->state = CPATH_STATE_OPEN; + onion_append_to_cpath(&cs->origin_circ->cpath, hop); + tt_ptr_op(hop, OP_EQ, cs->origin_circ->cpath->prev); + } + + return cs; + done: + testing_circuitset_teardown(testcase, cs); + return NULL; +} + +static int +testing_circuitset_teardown(const struct testcase_t *testcase, void *ptr) +{ + (void)testcase; + testing_circuitset_t *cs = ptr; + int i; + for (i=0; i<3; ++i) { + circuit_free_(TO_CIRCUIT(cs->or_circ[i])); + } + circuit_free_(TO_CIRCUIT(cs->origin_circ)); + tor_free(cs); + return 1; +} + +static const struct testcase_setup_t relaycrypt_setup = { + testing_circuitset_setup, testing_circuitset_teardown +}; + +/* Test encrypting a cell to the final hop on a circuit, decrypting it + * at each hop, and recognizing it at the other end. Then do it again + * and again as the state evolves. */ +static void +test_relaycrypt_outbound(void *arg) +{ + testing_circuitset_t *cs = arg; + tt_assert(cs); + + relay_header_t rh; + cell_t orig; + cell_t encrypted; + int i, j; + + for (i = 0; i < 50; ++i) { + crypto_rand((char *)&orig, sizeof(orig)); + + relay_header_unpack(&rh, orig.payload); + rh.recognized = 0; + memset(rh.integrity, 0, sizeof(rh.integrity)); + relay_header_pack(orig.payload, &rh); + + memcpy(&encrypted, &orig, sizeof(orig)); + + /* Encrypt the cell to the last hop */ + relay_encrypt_cell_outbound(&encrypted, cs->origin_circ, + cs->origin_circ->cpath->prev); + + for (j = 0; j < 3; ++j) { + crypt_path_t *layer_hint = NULL; + char recognized = 0; + int r = relay_decrypt_cell(TO_CIRCUIT(cs->or_circ[j]), + &encrypted, + CELL_DIRECTION_OUT, + &layer_hint, &recognized); + tt_int_op(r, OP_EQ, 0); + tt_ptr_op(layer_hint, OP_EQ, NULL); + tt_int_op(recognized != 0, OP_EQ, j == 2); + } + + tt_mem_op(orig.payload, OP_EQ, encrypted.payload, CELL_PAYLOAD_SIZE); + } + + done: + ; +} + +/* As above, but simulate inbound cells from the last hop. */ +static void +test_relaycrypt_inbound(void *arg) +{ + testing_circuitset_t *cs = arg; + tt_assert(cs); + + relay_header_t rh; + cell_t orig; + cell_t encrypted; + int i, j; + + for (i = 0; i < 50; ++i) { + crypto_rand((char *)&orig, sizeof(orig)); + + relay_header_unpack(&rh, orig.payload); + rh.recognized = 0; + memset(rh.integrity, 0, sizeof(rh.integrity)); + relay_header_pack(orig.payload, &rh); + + memcpy(&encrypted, &orig, sizeof(orig)); + + /* Encrypt the cell to the last hop */ + relay_encrypt_cell_inbound(&encrypted, cs->or_circ[2]); + + crypt_path_t *layer_hint = NULL; + char recognized = 0; + int r; + for (j = 1; j >= 0; --j) { + r = relay_decrypt_cell(TO_CIRCUIT(cs->or_circ[j]), + &encrypted, + CELL_DIRECTION_IN, + &layer_hint, &recognized); + tt_int_op(r, OP_EQ, 0); + tt_ptr_op(layer_hint, OP_EQ, NULL); + tt_int_op(recognized, OP_EQ, 0); + } + + relay_decrypt_cell(TO_CIRCUIT(cs->origin_circ), + &encrypted, + CELL_DIRECTION_IN, + &layer_hint, &recognized); + tt_int_op(r, OP_EQ, 0); + tt_int_op(recognized, OP_EQ, 1); + tt_ptr_op(layer_hint, OP_EQ, cs->origin_circ->cpath->prev); + + tt_mem_op(orig.payload, OP_EQ, encrypted.payload, CELL_PAYLOAD_SIZE); + } + done: + ; +} + +#define TEST(name) \ + { # name, test_relaycrypt_ ## name, 0, &relaycrypt_setup, NULL } + +struct testcase_t relaycrypt_tests[] = { + TEST(outbound), + TEST(inbound), + END_OF_TESTCASES +}; + diff --git a/src/test/test_rendcache.c b/src/test/test_rendcache.c index 9f6cfc4a22..394e28d785 100644 --- a/src/test/test_rendcache.c +++ b/src/test/test_rendcache.c @@ -1,18 +1,25 @@ -/* Copyright (c) 2010-2017, The Tor Project, Inc. */ +/* Copyright (c) 2010-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" -#include "or.h" +#include "core/or/or.h" -#include "test.h" +#include "test/test.h" #define RENDCACHE_PRIVATE -#include "rendcache.h" -#include "router.h" -#include "routerlist.h" -#include "config.h" -#include "hs_common.h" -#include "rend_test_helpers.h" -#include "log_test_helpers.h" +#include "feature/rend/rendcache.h" +#include "feature/relay/router.h" +#include "feature/nodelist/routerlist.h" +#include "app/config/config.h" +#include "feature/hs/hs_common.h" + +#include "core/or/extend_info_st.h" +#include "feature/rend/rend_encoded_v2_service_descriptor_st.h" +#include "feature/rend/rend_intro_point_st.h" +#include "feature/rend/rend_service_descriptor_st.h" +#include "feature/nodelist/routerinfo_st.h" + +#include "test/rend_test_helpers.h" +#include "test/log_test_helpers.h" #define NS_MODULE rend_cache diff --git a/src/test/test_replay.c b/src/test/test_replay.c index d8dcc7370c..bca3a6660a 100644 --- a/src/test/test_replay.c +++ b/src/test/test_replay.c @@ -1,12 +1,12 @@ -/* Copyright (c) 2012-2017, The Tor Project, Inc. */ +/* Copyright (c) 2012-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define REPLAYCACHE_PRIVATE #include "orconfig.h" -#include "or.h" -#include "replaycache.h" -#include "test.h" +#include "core/or/or.h" +#include "feature/hs_common/replaycache.h" +#include "test/test.h" static const char *test_buffer = "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed do eiusmod" diff --git a/src/test/test_router.c b/src/test/test_router.c index 4e96e24534..921ec42904 100644 --- a/src/test/test_router.c +++ b/src/test/test_router.c @@ -1,21 +1,26 @@ -/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* Copyright (c) 2017, isis agora lovecruft */ /* See LICENSE for licensing information */ /** * \file test_router.c - * \brief Unittests for code in src/or/router.c + * \brief Unittests for code in router.c **/ -#include "or.h" -#include "config.h" -#include "crypto_curve25519.h" -#include "crypto_ed25519.h" -#include "router.h" -#include "routerlist.h" +#include "core/or/or.h" +#include "app/config/config.h" +#include "core/mainloop/mainloop.h" +#include "feature/hibernate/hibernate.h" +#include "feature/nodelist/routerinfo_st.h" +#include "feature/nodelist/routerlist.h" +#include "feature/relay/router.h" +#include "feature/stats/rephist.h" +#include "lib/crypt_ops/crypto_curve25519.h" +#include "lib/crypt_ops/crypto_ed25519.h" /* Test suite stuff */ -#include "test.h" +#include "test/test.h" +#include "test/log_test_helpers.h" NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void)); @@ -47,9 +52,12 @@ NS(router_get_my_routerinfo)(void) mock_routerinfo->platform = tor_strdup("unittest"); mock_routerinfo->cache_info.published_on = now; mock_routerinfo->identity_pkey = crypto_pk_dup_key(ident_key); - mock_routerinfo->onion_pkey = crypto_pk_dup_key(tap_key); + router_set_rsa_onion_pkey(tap_key, &mock_routerinfo->onion_pkey, + &mock_routerinfo->onion_pkey_len); mock_routerinfo->bandwidthrate = 9001; mock_routerinfo->bandwidthburst = 9002; + crypto_pk_free(ident_key); + crypto_pk_free(tap_key); } return mock_routerinfo; @@ -87,11 +95,14 @@ test_router_dump_router_to_string_no_bridge_distribution_method(void *arg) /* Generate our server descriptor and ensure that the substring * "bridge-distribution-request any" occurs somewhere within it. */ + crypto_pk_t *onion_pkey = router_get_rsa_onion_pkey(router->onion_pkey, + router->onion_pkey_len); desc = router_dump_router_to_string(router, router->identity_pkey, - router->onion_pkey, + onion_pkey, &ntor_keypair, &signing_keypair); + crypto_pk_free(onion_pkey); tt_ptr_op(desc, !=, NULL); found = strstr(desc, needle); tt_ptr_op(found, !=, NULL); @@ -102,11 +113,129 @@ test_router_dump_router_to_string_no_bridge_distribution_method(void *arg) tor_free(desc); } +static routerinfo_t *mock_router_get_my_routerinfo_result = NULL; + +static const routerinfo_t * +mock_router_get_my_routerinfo(void) +{ + return mock_router_get_my_routerinfo_result; +} + +static long +mock_get_uptime_3h(void) +{ + return 3*60*60; +} + +static long +mock_get_uptime_1d(void) +{ + return 24*60*60; +} + +static int +mock_rep_hist_bandwidth_assess(void) +{ + return 20001; +} + +static int +mock_we_are_not_hibernating(void) +{ + return 0; +} + +static int +mock_we_are_hibernating(void) +{ + return 0; +} + +static void +test_router_check_descriptor_bandwidth_changed(void *arg) +{ + (void)arg; + routerinfo_t routerinfo; + memset(&routerinfo, 0, sizeof(routerinfo)); + mock_router_get_my_routerinfo_result = NULL; + + MOCK(we_are_hibernating, mock_we_are_not_hibernating); + MOCK(router_get_my_routerinfo, mock_router_get_my_routerinfo); + mock_router_get_my_routerinfo_result = &routerinfo; + + /* When uptime is less than 24h, no previous bandwidth, no last_changed + * Uptime: 10800, last_changed: 0, Previous bw: 0, Current bw: 0 */ + routerinfo.bandwidthcapacity = 0; + MOCK(get_uptime, mock_get_uptime_3h); + setup_full_capture_of_logs(LOG_INFO); + check_descriptor_bandwidth_changed(time(NULL)); + expect_log_msg_not_containing( + "Measured bandwidth has changed; rebuilding descriptor."); + teardown_capture_of_logs(); + + /* When uptime is less than 24h, previous bandwidth, + * last_changed more than 3h ago + * Uptime: 10800, last_changed: 0, Previous bw: 10000, Current bw: 0 */ + routerinfo.bandwidthcapacity = 10000; + setup_full_capture_of_logs(LOG_INFO); + check_descriptor_bandwidth_changed(time(NULL)); + expect_log_msg_containing( + "Measured bandwidth has changed; rebuilding descriptor."); + teardown_capture_of_logs(); + + /* When uptime is less than 24h, previous bandwidth, + * last_changed more than 3h ago, and hibernating + * Uptime: 10800, last_changed: 0, Previous bw: 10000, Current bw: 0 */ + + UNMOCK(we_are_hibernating); + MOCK(we_are_hibernating, mock_we_are_hibernating); + routerinfo.bandwidthcapacity = 10000; + setup_full_capture_of_logs(LOG_INFO); + check_descriptor_bandwidth_changed(time(NULL)); + expect_log_msg_not_containing( + "Measured bandwidth has changed; rebuilding descriptor."); + teardown_capture_of_logs(); + UNMOCK(we_are_hibernating); + MOCK(we_are_hibernating, mock_we_are_not_hibernating); + + /* When uptime is less than 24h, last_changed is not more than 3h ago + * Uptime: 10800, last_changed: x, Previous bw: 10000, Current bw: 0 */ + setup_full_capture_of_logs(LOG_INFO); + check_descriptor_bandwidth_changed(time(NULL)); + expect_log_msg_not_containing( + "Measured bandwidth has changed; rebuilding descriptor."); + teardown_capture_of_logs(); + + /* When uptime is less than 24h and bandwidthcapacity does not change + * Uptime: 10800, last_changed: x, Previous bw: 10000, Current bw: 20001 */ + MOCK(rep_hist_bandwidth_assess, mock_rep_hist_bandwidth_assess); + setup_full_capture_of_logs(LOG_INFO); + check_descriptor_bandwidth_changed(time(NULL) + 6*60*60 + 1); + expect_log_msg_containing( + "Measured bandwidth has changed; rebuilding descriptor."); + UNMOCK(get_uptime); + UNMOCK(rep_hist_bandwidth_assess); + teardown_capture_of_logs(); + + /* When uptime is more than 24h */ + MOCK(get_uptime, mock_get_uptime_1d); + setup_full_capture_of_logs(LOG_INFO); + check_descriptor_bandwidth_changed(time(NULL)); + expect_log_msg_not_containing( + "Measured bandwidth has changed; rebuilding descriptor."); + teardown_capture_of_logs(); + + done: + UNMOCK(get_uptime); + UNMOCK(router_get_my_routerinfo); + UNMOCK(we_are_hibernating); +} + #define ROUTER_TEST(name, flags) \ { #name, test_router_ ## name, flags, NULL, NULL } struct testcase_t router_tests[] = { + ROUTER_TEST(check_descriptor_bandwidth_changed, TT_FORK), ROUTER_TEST(dump_router_to_string_no_bridge_distribution_method, TT_FORK), END_OF_TESTCASES }; - diff --git a/src/test/test_routerkeys.c b/src/test/test_routerkeys.c index e4abcdb92d..f05401ba0d 100644 --- a/src/test/test_routerkeys.c +++ b/src/test/test_routerkeys.c @@ -1,24 +1,32 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" #define ROUTER_PRIVATE -#include "or.h" -#include "config.h" -#include "router.h" -#include "routerkeys.h" -#include "util.h" -#include "crypto.h" -#include "torcert.h" -#include "test.h" +#include "core/or/or.h" +#include "app/config/config.h" +#include "feature/relay/router.h" +#include "feature/relay/routerkeys.h" +#include "lib/crypt_ops/crypto_cipher.h" +#include "lib/crypt_ops/crypto_format.h" +#include "feature/keymgt/loadkey.h" +#include "feature/nodelist/torcert.h" +#include "test/test.h" #ifdef _WIN32 /* For mkdir() */ #include <direct.h> #endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + static void test_routerkeys_write_fingerprint(void *arg) { @@ -255,13 +263,14 @@ test_routerkeys_ed_key_init_basic(void *arg) unlink(fname2); /* Fail to load a key that isn't there. */ - kp1 = ed_key_init_from_file(fname1, 0, LOG_INFO, NULL, now, 0, 7, &cert); + kp1 = ed_key_init_from_file(fname1, 0, LOG_INFO, NULL, now, 0, 7, &cert, + NULL); tt_assert(kp1 == NULL); tt_assert(cert == NULL); /* Create the key if requested to do so. */ kp1 = ed_key_init_from_file(fname1, INIT_ED_KEY_CREATE, LOG_INFO, - NULL, now, 0, 7, &cert); + NULL, now, 0, 7, &cert, NULL); tt_assert(kp1 != NULL); tt_assert(cert == NULL); tt_int_op(stat(get_fname("test_ed_key_1_cert"), &st), OP_LT, 0); @@ -269,24 +278,24 @@ test_routerkeys_ed_key_init_basic(void *arg) /* Fail to load if we say we need a cert */ kp2 = ed_key_init_from_file(fname1, INIT_ED_KEY_NEEDCERT, LOG_INFO, - NULL, now, 0, 7, &cert); + NULL, now, 0, 7, &cert, NULL); tt_assert(kp2 == NULL); /* Fail to load if we say the wrong key type */ kp2 = ed_key_init_from_file(fname1, 0, LOG_INFO, - NULL, now, 0, 6, &cert); + NULL, now, 0, 6, &cert, NULL); tt_assert(kp2 == NULL); /* Load successfully if we're not picky, whether we say "create" or not. */ kp2 = ed_key_init_from_file(fname1, INIT_ED_KEY_CREATE, LOG_INFO, - NULL, now, 0, 7, &cert); + NULL, now, 0, 7, &cert, NULL); tt_assert(kp2 != NULL); tt_assert(cert == NULL); tt_mem_op(kp1, OP_EQ, kp2, sizeof(*kp1)); ed25519_keypair_free(kp2); kp2 = NULL; kp2 = ed_key_init_from_file(fname1, 0, LOG_INFO, - NULL, now, 0, 7, &cert); + NULL, now, 0, 7, &cert, NULL); tt_assert(kp2 != NULL); tt_assert(cert == NULL); tt_mem_op(kp1, OP_EQ, kp2, sizeof(*kp1)); @@ -295,7 +304,7 @@ test_routerkeys_ed_key_init_basic(void *arg) /* Now create a key with a cert. */ kp2 = ed_key_init_from_file(fname2, (INIT_ED_KEY_CREATE| INIT_ED_KEY_NEEDCERT), - LOG_INFO, kp1, now, 7200, 7, &cert); + LOG_INFO, kp1, now, 7200, 7, &cert, NULL); tt_assert(kp2 != NULL); tt_assert(cert != NULL); tt_mem_op(kp1, OP_NE, kp2, sizeof(*kp1)); @@ -308,7 +317,7 @@ test_routerkeys_ed_key_init_basic(void *arg) /* Now verify we can load the cert... */ kp3 = ed_key_init_from_file(fname2, (INIT_ED_KEY_CREATE| INIT_ED_KEY_NEEDCERT), - LOG_INFO, kp1, now, 7200, 7, &cert2); + LOG_INFO, kp1, now, 7200, 7, &cert2, NULL); tt_mem_op(kp2, OP_EQ, kp3, sizeof(*kp2)); tt_mem_op(cert2->encoded, OP_EQ, cert->encoded, cert->encoded_len); ed25519_keypair_free(kp3); kp3 = NULL; @@ -316,7 +325,7 @@ test_routerkeys_ed_key_init_basic(void *arg) /* ... even without create... */ kp3 = ed_key_init_from_file(fname2, INIT_ED_KEY_NEEDCERT, - LOG_INFO, kp1, now, 7200, 7, &cert2); + LOG_INFO, kp1, now, 7200, 7, &cert2, NULL); tt_mem_op(kp2, OP_EQ, kp3, sizeof(*kp2)); tt_mem_op(cert2->encoded, OP_EQ, cert->encoded, cert->encoded_len); ed25519_keypair_free(kp3); kp3 = NULL; @@ -324,13 +333,13 @@ test_routerkeys_ed_key_init_basic(void *arg) /* ... but that we don't crash or anything if we say we don't want it. */ kp3 = ed_key_init_from_file(fname2, INIT_ED_KEY_NEEDCERT, - LOG_INFO, kp1, now, 7200, 7, NULL); + LOG_INFO, kp1, now, 7200, 7, NULL, NULL); tt_mem_op(kp2, OP_EQ, kp3, sizeof(*kp2)); ed25519_keypair_free(kp3); kp3 = NULL; /* Fail if we're told the wrong signing key */ kp3 = ed_key_init_from_file(fname2, INIT_ED_KEY_NEEDCERT, - LOG_INFO, kp2, now, 7200, 7, &cert2); + LOG_INFO, kp2, now, 7200, 7, &cert2, NULL); tt_assert(kp3 == NULL); tt_assert(cert2 == NULL); @@ -361,13 +370,14 @@ test_routerkeys_ed_key_init_split(void *arg) unlink(fname2); /* Can't load key that isn't there. */ - kp1 = ed_key_init_from_file(fname1, flags, LOG_INFO, NULL, now, 0, 7, &cert); + kp1 = ed_key_init_from_file(fname1, flags, LOG_INFO, NULL, now, 0, 7, &cert, + NULL); tt_assert(kp1 == NULL); tt_assert(cert == NULL); /* Create a split key */ kp1 = ed_key_init_from_file(fname1, flags|INIT_ED_KEY_CREATE, - LOG_INFO, NULL, now, 0, 7, &cert); + LOG_INFO, NULL, now, 0, 7, &cert, NULL); tt_assert(kp1 != NULL); tt_assert(cert == NULL); tt_int_op(stat(get_fname("test_ed_key_3_cert"), &st), OP_LT, 0); @@ -376,7 +386,7 @@ test_routerkeys_ed_key_init_split(void *arg) /* Load it. */ kp2 = ed_key_init_from_file(fname1, flags|INIT_ED_KEY_CREATE, - LOG_INFO, NULL, now, 0, 7, &cert); + LOG_INFO, NULL, now, 0, 7, &cert, NULL); tt_assert(kp2 != NULL); tt_assert(cert == NULL); tt_mem_op(kp1, OP_EQ, kp2, sizeof(*kp2)); @@ -385,7 +395,7 @@ test_routerkeys_ed_key_init_split(void *arg) /* Okay, try killing the secret key and loading it. */ unlink(get_fname("test_ed_key_3_secret_key")); kp2 = ed_key_init_from_file(fname1, flags, - LOG_INFO, NULL, now, 0, 7, &cert); + LOG_INFO, NULL, now, 0, 7, &cert, NULL); tt_assert(kp2 != NULL); tt_assert(cert == NULL); tt_mem_op(&kp1->pubkey, OP_EQ, &kp2->pubkey, sizeof(kp2->pubkey)); @@ -395,7 +405,7 @@ test_routerkeys_ed_key_init_split(void *arg) /* Even when we're told to "create", don't create if there's a public key */ kp2 = ed_key_init_from_file(fname1, flags|INIT_ED_KEY_CREATE, - LOG_INFO, NULL, now, 0, 7, &cert); + LOG_INFO, NULL, now, 0, 7, &cert, NULL); tt_assert(kp2 != NULL); tt_assert(cert == NULL); tt_mem_op(&kp1->pubkey, OP_EQ, &kp2->pubkey, sizeof(kp2->pubkey)); @@ -405,7 +415,7 @@ test_routerkeys_ed_key_init_split(void *arg) /* Make sure we fail on a tag mismatch, though */ kp2 = ed_key_init_from_file(fname1, flags, - LOG_INFO, NULL, now, 0, 99, &cert); + LOG_INFO, NULL, now, 0, 99, &cert, NULL); tt_assert(kp2 == NULL); done: @@ -695,4 +705,3 @@ struct testcase_t routerkeys_tests[] = { TEST(rsa_ed_crosscert, 0), END_OF_TESTCASES }; - diff --git a/src/test/test_routerlist.c b/src/test/test_routerlist.c index c19d66ef9d..67af2fd484 100644 --- a/src/test/test_routerlist.c +++ b/src/test/test_routerlist.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" @@ -6,37 +6,53 @@ #include <time.h> #define CONNECTION_PRIVATE -#define DIRECTORY_PRIVATE +#define DIRCLIENT_PRIVATE #define DIRVOTE_PRIVATE #define ENTRYNODES_PRIVATE #define HIBERNATE_PRIVATE #define NETWORKSTATUS_PRIVATE #define ROUTERLIST_PRIVATE +#define NODE_SELECT_PRIVATE #define TOR_UNIT_TESTING -#include "or.h" -#include "config.h" -#include "connection.h" -#include "container.h" -#include "control.h" -#include "directory.h" -#include "dirvote.h" -#include "entrynodes.h" -#include "hibernate.h" -#include "microdesc.h" -#include "networkstatus.h" -#include "nodelist.h" -#include "policies.h" -#include "router.h" -#include "routerlist.h" -#include "routerset.h" -#include "routerparse.h" -#include "shared_random.h" -#include "statefile.h" -#include "test.h" -#include "test_dir_common.h" -#include "log_test_helpers.h" - -void construct_consensus(char **consensus_text_md); +#include "core/or/or.h" +#include "app/config/config.h" +#include "core/mainloop/connection.h" +#include "feature/control/control.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "feature/dircommon/directory.h" +#include "feature/dirclient/dirclient.h" +#include "feature/dirauth/dirvote.h" +#include "feature/client/entrynodes.h" +#include "feature/hibernate/hibernate.h" +#include "feature/nodelist/microdesc.h" +#include "feature/nodelist/networkstatus.h" +#include "feature/nodelist/nodelist.h" +#include "core/or/policies.h" +#include "feature/relay/router.h" +#include "feature/nodelist/authcert.h" +#include "feature/nodelist/node_select.h" +#include "feature/nodelist/routerlist.h" +#include "feature/nodelist/routerset.h" +#include "feature/dirparse/authcert_parse.h" +#include "feature/dirparse/ns_parse.h" +#include "feature/dirauth/shared_random.h" +#include "app/config/statefile.h" + +#include "feature/nodelist/authority_cert_st.h" +#include "feature/dircommon/dir_connection_st.h" +#include "feature/nodelist/networkstatus_st.h" +#include "feature/nodelist/node_st.h" +#include "app/config/or_state_st.h" +#include "feature/nodelist/routerstatus_st.h" + +#include "lib/encoding/confline.h" +#include "lib/container/buffers.h" + +#include "test/test.h" +#include "test/test_dir_common.h" +#include "test/log_test_helpers.h" + +void construct_consensus(char **consensus_text_md, time_t now); static authority_cert_t *mock_cert; @@ -135,7 +151,7 @@ test_routerlist_launch_descriptor_downloads(void *arg) } void -construct_consensus(char **consensus_text_md) +construct_consensus(char **consensus_text_md, time_t now) { networkstatus_t *vote = NULL; networkstatus_t *v1 = NULL, *v2 = NULL, *v3 = NULL; @@ -143,7 +159,6 @@ construct_consensus(char **consensus_text_md) authority_cert_t *cert1=NULL, *cert2=NULL, *cert3=NULL; crypto_pk_t *sign_skey_1=NULL, *sign_skey_2=NULL, *sign_skey_3=NULL; crypto_pk_t *sign_skey_leg=NULL; - time_t now = time(NULL); smartlist_t *votes = NULL; int n_vrs; @@ -258,7 +273,7 @@ test_router_pick_directory_server_impl(void *arg) rs = router_pick_directory_server_impl(V3_DIRINFO, (const int) 0, NULL); tt_ptr_op(rs, OP_EQ, NULL); - construct_consensus(&consensus_text_md); + construct_consensus(&consensus_text_md, now); tt_assert(consensus_text_md); con_md = networkstatus_parse_vote_from_string(consensus_text_md, NULL, NS_TYPE_CONSENSUS); @@ -452,6 +467,7 @@ test_directory_guard_fetch_with_no_dirinfo(void *arg) int retval; char *consensus_text_md = NULL; or_options_t *options = get_options_mutable(); + time_t now = time(NULL); (void) arg; @@ -495,7 +511,7 @@ test_directory_guard_fetch_with_no_dirinfo(void *arg) conn->requested_resource = tor_strdup("ns"); /* Construct a consensus */ - construct_consensus(&consensus_text_md); + construct_consensus(&consensus_text_md, now); tt_assert(consensus_text_md); /* Place the consensus in the dirconn */ @@ -506,7 +522,7 @@ test_directory_guard_fetch_with_no_dirinfo(void *arg) args.body_len = strlen(consensus_text_md); /* Update approx time so that the consensus is considered live */ - update_approx_time(time(NULL)+1010); + update_approx_time(now+1010); setup_capture_of_logs(LOG_DEBUG); @@ -598,11 +614,167 @@ test_routerlist_router_is_already_dir_fetching(void *arg) #undef TEST_ADDR_STR #undef TEST_DIR_PORT +static long mock_apparent_skew = 0; + +/** Store apparent_skew and assert that the other arguments are as + * expected. */ +static void +mock_clock_skew_warning(const connection_t *conn, long apparent_skew, + int trusted, log_domain_mask_t domain, + const char *received, const char *source) +{ + (void)conn; + mock_apparent_skew = apparent_skew; + tt_int_op(trusted, OP_EQ, 1); + tt_int_op(domain, OP_EQ, LD_GENERAL); + tt_str_op(received, OP_EQ, "microdesc flavor consensus"); + tt_str_op(source, OP_EQ, "CONSENSUS"); + done: + ; +} + +/** Do common setup for test_timely_consensus() and + * test_early_consensus(). Call networkstatus_set_current_consensus() + * on a constructed consensus and with an appropriately-modified + * approx_time. Callers expect presence or absence of appropriate log + * messages and control events. */ +static int +test_skew_common(void *arg, time_t now, unsigned long *offset) +{ + char *consensus = NULL; + int retval = 0; + + *offset = strtoul(arg, NULL, 10); + + /* Initialize the SRV subsystem */ + MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m); + mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL); + sr_init(0); + UNMOCK(get_my_v3_authority_cert); + + construct_consensus(&consensus, now); + tt_assert(consensus); + + update_approx_time(now + *offset); + + mock_apparent_skew = 0; + /* Caller will call UNMOCK() */ + MOCK(clock_skew_warning, mock_clock_skew_warning); + /* Caller will call teardown_capture_of_logs() */ + setup_capture_of_logs(LOG_WARN); + retval = networkstatus_set_current_consensus(consensus, "microdesc", 0, + NULL); + + done: + tor_free(consensus); + return retval; +} + +/** Test non-early consensus */ +static void +test_timely_consensus(void *arg) +{ + time_t now = time(NULL); + unsigned long offset = 0; + int retval = 0; + + retval = test_skew_common(arg, now, &offset); + (void)offset; + expect_no_log_msg_containing("behind the time published in the consensus"); + tt_int_op(retval, OP_EQ, 0); + tt_int_op(mock_apparent_skew, OP_EQ, 0); + done: + teardown_capture_of_logs(); + UNMOCK(clock_skew_warning); +} + +/** Test early consensus */ +static void +test_early_consensus(void *arg) +{ + time_t now = time(NULL); + unsigned long offset = 0; + int retval = 0; + + retval = test_skew_common(arg, now, &offset); + /* Can't use expect_single_log_msg() because of unrecognized authorities */ + expect_log_msg_containing("behind the time published in the consensus"); + tt_int_op(retval, OP_EQ, 0); + /* This depends on construct_consensus() setting valid_after=now+1000 */ + tt_int_op(mock_apparent_skew, OP_EQ, offset - 1000); + done: + teardown_capture_of_logs(); + UNMOCK(clock_skew_warning); +} + +/** Test warn_early_consensus(), expecting no warning */ +static void +test_warn_early_consensus_no(const networkstatus_t *c, time_t now, + long offset) +{ + mock_apparent_skew = 0; + setup_capture_of_logs(LOG_WARN); + warn_early_consensus(c, "microdesc", now + offset); + expect_no_log_msg_containing("behind the time published in the consensus"); + tt_int_op(mock_apparent_skew, OP_EQ, 0); + done: + teardown_capture_of_logs(); +} + +/** Test warn_early_consensus(), expecting a warning */ +static void +test_warn_early_consensus_yes(const networkstatus_t *c, time_t now, + long offset) +{ + mock_apparent_skew = 0; + setup_capture_of_logs(LOG_WARN); + warn_early_consensus(c, "microdesc", now + offset); + /* Can't use expect_single_log_msg() because of unrecognized authorities */ + expect_log_msg_containing("behind the time published in the consensus"); + tt_int_op(mock_apparent_skew, OP_EQ, offset); + done: + teardown_capture_of_logs(); +} + +/** + * Test warn_early_consensus() directly, checking both the non-warning + * case (consensus is not early) and the warning case (consensus is + * early). Depends on EARLY_CONSENSUS_NOTICE_SKEW=60. + */ +static void +test_warn_early_consensus(void *arg) +{ + networkstatus_t *c = NULL; + time_t now = time(NULL); + + (void)arg; + c = tor_malloc_zero(sizeof *c); + c->valid_after = now; + c->dist_seconds = 300; + mock_apparent_skew = 0; + MOCK(clock_skew_warning, mock_clock_skew_warning); + test_warn_early_consensus_no(c, now, 60); + test_warn_early_consensus_no(c, now, 0); + test_warn_early_consensus_no(c, now, -60); + test_warn_early_consensus_no(c, now, -360); + test_warn_early_consensus_yes(c, now, -361); + test_warn_early_consensus_yes(c, now, -600); + UNMOCK(clock_skew_warning); + tor_free(c); +} + #define NODE(name, flags) \ { #name, test_routerlist_##name, (flags), NULL, NULL } #define ROUTER(name,flags) \ { #name, test_router_##name, (flags), NULL, NULL } +#define TIMELY(name, arg) \ + { name, test_timely_consensus, TT_FORK, &passthrough_setup, \ + (char *)(arg) } +#define EARLY(name, arg) \ + { name, test_early_consensus, TT_FORK, &passthrough_setup, \ + (char *)(arg) } + struct testcase_t routerlist_tests[] = { NODE(initiate_descriptor_downloads, 0), NODE(launch_descriptor_downloads, 0), @@ -610,6 +782,12 @@ struct testcase_t routerlist_tests[] = { ROUTER(pick_directory_server_impl, TT_FORK), { "directory_guard_fetch_with_no_dirinfo", test_directory_guard_fetch_with_no_dirinfo, TT_FORK, NULL, NULL }, + /* These depend on construct_consensus() setting + * valid_after=now+1000 and dist_seconds=250 */ + TIMELY("timely_consensus1", "1010"), + TIMELY("timely_consensus2", "1000"), + TIMELY("timely_consensus3", "690"), + EARLY("early_consensus1", "689"), + { "warn_early_consensus", test_warn_early_consensus, 0, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_routerset.c b/src/test/test_routerset.c index c541324674..86f9c0fa82 100644 --- a/src/test/test_routerset.c +++ b/src/test/test_routerset.c @@ -1,15 +1,22 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define ROUTERSET_PRIVATE -#include "or.h" -#include "geoip.h" -#include "routerset.h" -#include "routerparse.h" -#include "policies.h" -#include "nodelist.h" -#include "test.h" +#include "core/or/or.h" +#include "core/or/policies.h" +#include "feature/dirparse/policy_parse.h" +#include "feature/nodelist/nodelist.h" +#include "feature/nodelist/routerset.h" +#include "lib/geoip/geoip.h" + +#include "core/or/addr_policy_st.h" +#include "core/or/extend_info_st.h" +#include "feature/nodelist/node_st.h" +#include "feature/nodelist/routerinfo_st.h" +#include "feature/nodelist/routerstatus_st.h" + +#include "test/test.h" #define NS_MODULE routerset @@ -1489,6 +1496,7 @@ NS(test_main)(void *arg) int r; (void)arg; + memset(&NS(mock_node), 0, sizeof(NS(mock_node))); NS(mock_node).ri = NULL; NS(mock_node).rs = NULL; @@ -1522,6 +1530,7 @@ NS(test_main)(void *arg) strncpy(rs.nickname, nickname, sizeof(rs.nickname) - 1); rs.nickname[sizeof(rs.nickname) - 1] = '\0'; + memset(&NS(mock_node), 0, sizeof(NS(mock_node))); NS(mock_node).ri = NULL; NS(mock_node).rs = &rs; @@ -1553,6 +1562,7 @@ NS(test_main)(void *arg) strmap_set_lc(set->names, nickname, (void *)1); ri.nickname = (char *)nickname; + memset(&mock_node, 0, sizeof(mock_node)); mock_node.ri = &ri; mock_node.rs = NULL; @@ -2221,4 +2231,3 @@ struct testcase_t routerset_tests[] = { TEST_CASE(routerset_free), END_OF_TESTCASES }; - diff --git a/src/test/test_rust.sh b/src/test/test_rust.sh index 5405af436b..a1a56af480 100755 --- a/src/test/test_rust.sh +++ b/src/test/test_rust.sh @@ -9,7 +9,8 @@ for cargo_toml_dir in "${abs_top_srcdir:-../../..}"/src/rust/*; do if [ -e "${cargo_toml_dir}/Cargo.toml" ]; then cd "${abs_top_builddir:-../../..}/src/rust" && \ CARGO_TARGET_DIR="${abs_top_builddir:-../../..}/src/rust/target" \ - "${CARGO:-cargo}" test --all-features ${CARGO_ONLINE-"--frozen"} \ + "${CARGO:-cargo}" test ${CARGO_ONLINE-"--frozen"} \ + --features "test_linking_hack" \ ${EXTRA_CARGO_OPTIONS} \ --manifest-path "${cargo_toml_dir}/Cargo.toml" || exitcode=1 fi diff --git a/src/test/test_scheduler.c b/src/test/test_scheduler.c index ebba71266c..2d562299ab 100644 --- a/src/test/test_scheduler.c +++ b/src/test/test_scheduler.c @@ -1,27 +1,26 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" #include <math.h> -#include <event2/event.h> #define SCHEDULER_KIST_PRIVATE #define TOR_CHANNEL_INTERNAL_ #define CHANNEL_PRIVATE_ -#include "or.h" -#include "config.h" -#include "compat_libevent.h" -#include "channel.h" -#include "channeltls.h" -#include "connection.h" -#include "networkstatus.h" +#include "core/or/or.h" +#include "app/config/config.h" +#include "lib/evloop/compat_libevent.h" +#include "core/or/channel.h" +#include "core/or/channeltls.h" +#include "core/mainloop/connection.h" +#include "feature/nodelist/networkstatus.h" #define SCHEDULER_PRIVATE_ -#include "scheduler.h" +#include "core/or/scheduler.h" /* Test suite stuff */ -#include "test.h" -#include "fakechans.h" +#include "test/test.h" +#include "test/fakechans.h" /* Shamelessly stolen from compat_libevent.c */ #define V(major, minor, patch) \ @@ -101,62 +100,6 @@ mock_kist_networkstatus_get_param( return 12; } -/* Event base for scheduelr tests */ -static struct event_base *mock_event_base = NULL; -/* Setup for mock event stuff */ -static void mock_event_free_all(void); -static void mock_event_init(void); -static void -mock_event_free_all(void) -{ - tt_ptr_op(mock_event_base, OP_NE, NULL); - - if (mock_event_base) { - event_base_free(mock_event_base); - mock_event_base = NULL; - } - - tt_ptr_op(mock_event_base, OP_EQ, NULL); - - done: - return; -} - -static void -mock_event_init(void) -{ - struct event_config *cfg = NULL; - - tt_ptr_op(mock_event_base, OP_EQ, NULL); - - /* - * Really cut down from tor_libevent_initialize of - * src/common/compat_libevent.c to kill config dependencies - */ - - if (!mock_event_base) { - cfg = event_config_new(); -#if LIBEVENT_VERSION_NUMBER >= V(2,0,9) - /* We can enable changelist support with epoll, since we don't give - * Libevent any dup'd fds. This lets us avoid some syscalls. */ - event_config_set_flag(cfg, EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST); -#endif - mock_event_base = event_base_new_with_config(cfg); - event_config_free(cfg); - } - - tt_ptr_op(mock_event_base, OP_NE, NULL); - - done: - return; -} - -static struct event_base * -tor_libevent_get_base_mock(void) -{ - return mock_event_base; -} - static int scheduler_compare_channels_mock(const void *c1_v, const void *c2_v) @@ -417,9 +360,7 @@ perform_channel_state_tests(int KISTSchedRunInterval, int sched_type) mocked_options.KISTSchedRunInterval = KISTSchedRunInterval; set_scheduler_options(sched_type); - /* Set up libevent and scheduler */ - mock_event_init(); - MOCK(tor_libevent_get_base, tor_libevent_get_base_mock); + /* Set up scheduler */ scheduler_init(); /* * Install the compare channels mock so we can test @@ -523,14 +464,12 @@ perform_channel_state_tests(int KISTSchedRunInterval, int sched_type) channel_free_all(); scheduler_free_all(); - mock_event_free_all(); done: tor_free(ch1); tor_free(ch2); UNMOCK(scheduler_compare_channels); - UNMOCK(tor_libevent_get_base); UNMOCK(get_options); cleanup_scheduler_options(); @@ -635,10 +574,7 @@ test_scheduler_loop_vanilla(void *arg) set_scheduler_options(SCHEDULER_VANILLA); mocked_options.KISTSchedRunInterval = 0; - /* Set up libevent and scheduler */ - - mock_event_init(); - MOCK(tor_libevent_get_base, tor_libevent_get_base_mock); + /* Set up scheduler */ scheduler_init(); /* * Install the compare channels mock so we can test @@ -786,7 +722,6 @@ test_scheduler_loop_vanilla(void *arg) channel_flush_some_cells_mock_free_all(); channel_free_all(); scheduler_free_all(); - mock_event_free_all(); done: tor_free(ch1); @@ -795,7 +730,6 @@ test_scheduler_loop_vanilla(void *arg) UNMOCK(channel_flush_some_cells); UNMOCK(scheduler_compare_channels); - UNMOCK(tor_libevent_get_base); UNMOCK(get_options); } @@ -917,8 +851,6 @@ test_scheduler_initfree(void *arg) tt_ptr_op(channels_pending, ==, NULL); tt_ptr_op(run_sched_ev, ==, NULL); - mock_event_init(); - MOCK(tor_libevent_get_base, tor_libevent_get_base_mock); MOCK(get_options, mock_get_options); set_scheduler_options(SCHEDULER_KIST); set_scheduler_options(SCHEDULER_KIST_LITE); @@ -935,9 +867,6 @@ test_scheduler_initfree(void *arg) scheduler_free_all(); - UNMOCK(tor_libevent_get_base); - mock_event_free_all(); - tt_ptr_op(channels_pending, ==, NULL); tt_ptr_op(run_sched_ev, ==, NULL); diff --git a/src/test/test_shared_random.c b/src/test/test_shared_random.c index 437fc38deb..8a7fb95cc1 100644 --- a/src/test/test_shared_random.c +++ b/src/test/test_shared_random.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Tor Project, Inc. */ +/* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define SHARED_RANDOM_PRIVATE @@ -6,18 +6,35 @@ #define CONFIG_PRIVATE #define DIRVOTE_PRIVATE -#include "or.h" -#include "test.h" -#include "config.h" -#include "dirvote.h" -#include "shared_random.h" -#include "shared_random_state.h" -#include "routerkeys.h" -#include "routerlist.h" -#include "router.h" -#include "routerparse.h" -#include "networkstatus.h" -#include "log_test_helpers.h" +#include "core/or/or.h" +#include "test/test.h" +#include "app/config/config.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "feature/dirauth/dirvote.h" +#include "feature/dirauth/shared_random.h" +#include "feature/dirauth/shared_random_state.h" +#include "test/log_test_helpers.h" +#include "feature/nodelist/networkstatus.h" +#include "feature/relay/router.h" +#include "feature/relay/routerkeys.h" +#include "feature/nodelist/authcert.h" +#include "feature/nodelist/dirlist.h" +#include "feature/dirparse/authcert_parse.h" +#include "feature/hs_common/shared_random_client.h" +#include "feature/dircommon/voting_schedule.h" + +#include "feature/dirclient/dir_server_st.h" +#include "feature/nodelist/networkstatus_st.h" +#include "app/config/or_state_st.h" + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +#ifdef _WIN32 +/* For mkdir */ +#include <direct.h> +#endif static authority_cert_t *mock_cert; @@ -170,7 +187,7 @@ test_get_state_valid_until_time(void *arg) retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:00:01 UTC", ¤t_time); tt_int_op(retval, OP_EQ, 0); - dirvote_recalculate_timing(get_options(), current_time); + voting_schedule_recalculate_timing(get_options(), current_time); valid_until_time = get_state_valid_until_time(current_time); /* Compare it with the correct result */ @@ -182,7 +199,7 @@ test_get_state_valid_until_time(void *arg) retval = parse_rfc1123_time("Mon, 20 Apr 2015 19:22:00 UTC", ¤t_time); tt_int_op(retval, OP_EQ, 0); - dirvote_recalculate_timing(get_options(), current_time); + voting_schedule_recalculate_timing(get_options(), current_time); valid_until_time = get_state_valid_until_time(current_time); format_iso_time(tbuf, valid_until_time); @@ -193,7 +210,7 @@ test_get_state_valid_until_time(void *arg) retval = parse_rfc1123_time("Mon, 20 Apr 2015 23:59:00 UTC", ¤t_time); tt_int_op(retval, OP_EQ, 0); - dirvote_recalculate_timing(get_options(), current_time); + voting_schedule_recalculate_timing(get_options(), current_time); valid_until_time = get_state_valid_until_time(current_time); format_iso_time(tbuf, valid_until_time); @@ -204,7 +221,7 @@ test_get_state_valid_until_time(void *arg) retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:00:00 UTC", ¤t_time); tt_int_op(retval, OP_EQ, 0); - dirvote_recalculate_timing(get_options(), current_time); + voting_schedule_recalculate_timing(get_options(), current_time); valid_until_time = get_state_valid_until_time(current_time); format_iso_time(tbuf, valid_until_time); @@ -242,9 +259,8 @@ test_get_start_time_of_current_run(void *arg) retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:00:01 UTC", ¤t_time); tt_int_op(retval, OP_EQ, 0); - dirvote_recalculate_timing(get_options(), current_time); - run_start_time = - sr_state_get_start_time_of_current_protocol_run(current_time); + voting_schedule_recalculate_timing(get_options(), current_time); + run_start_time = sr_state_get_start_time_of_current_protocol_run(); /* Compare it with the correct result */ format_iso_time(tbuf, run_start_time); @@ -255,9 +271,8 @@ test_get_start_time_of_current_run(void *arg) retval = parse_rfc1123_time("Mon, 20 Apr 2015 23:59:59 UTC", ¤t_time); tt_int_op(retval, OP_EQ, 0); - dirvote_recalculate_timing(get_options(), current_time); - run_start_time = - sr_state_get_start_time_of_current_protocol_run(current_time); + voting_schedule_recalculate_timing(get_options(), current_time); + run_start_time = sr_state_get_start_time_of_current_protocol_run(); /* Compare it with the correct result */ format_iso_time(tbuf, run_start_time); @@ -268,15 +283,48 @@ test_get_start_time_of_current_run(void *arg) retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:00:00 UTC", ¤t_time); tt_int_op(retval, OP_EQ, 0); - dirvote_recalculate_timing(get_options(), current_time); - run_start_time = - sr_state_get_start_time_of_current_protocol_run(current_time); + voting_schedule_recalculate_timing(get_options(), current_time); + run_start_time = sr_state_get_start_time_of_current_protocol_run(); /* Compare it with the correct result */ format_iso_time(tbuf, run_start_time); tt_str_op("2015-04-20 00:00:00", OP_EQ, tbuf); } + { + /* We want the local time to be past midnight, but the current consensus to + * have valid-after 23:00 (e.g. this can happen if we fetch a new consensus + * at 00:08 before dircaches have a chance to get the midnight consensus). + * + * Basically, we want to cause a desynch between ns->valid_after (23:00) + * and the voting_schedule.interval_starts (01:00), to make sure that + * sr_state_get_start_time_of_current_protocol_run() handles it gracefully: + * It should actually follow the local consensus time and not the voting + * schedule (which is designed for authority voting purposes). */ + retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:00:00 UTC", + &mock_consensus.fresh_until); + tt_int_op(retval, OP_EQ, 0); + + retval = parse_rfc1123_time("Mon, 19 Apr 2015 23:00:00 UTC", + &mock_consensus.valid_after); + + retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:08:00 UTC", + ¤t_time); + tt_int_op(retval, OP_EQ, 0); + update_approx_time(current_time); + voting_schedule_recalculate_timing(get_options(), current_time); + + run_start_time = sr_state_get_start_time_of_current_protocol_run(); + + /* Compare it with the correct result */ + format_iso_time(tbuf, run_start_time); + tt_str_op("2015-04-19 00:00:00", OP_EQ, tbuf); + /* Check that voting_schedule.interval_starts is at 01:00 (see above) */ + time_t interval_starts = voting_schedule_get_next_valid_after_time(); + format_iso_time(tbuf, interval_starts); + tt_str_op("2015-04-20 01:00:00", OP_EQ, tbuf); + } + /* Next test is testing it without a consensus to use the testing voting * interval . */ UNMOCK(networkstatus_get_live_consensus); @@ -291,9 +339,8 @@ test_get_start_time_of_current_run(void *arg) retval = parse_rfc1123_time("Mon, 20 Apr 2015 00:15:32 UTC", ¤t_time); tt_int_op(retval, OP_EQ, 0); - dirvote_recalculate_timing(get_options(), current_time); - run_start_time = - sr_state_get_start_time_of_current_protocol_run(current_time); + voting_schedule_recalculate_timing(get_options(), current_time); + run_start_time = sr_state_get_start_time_of_current_protocol_run(); /* Compare it with the correct result */ format_iso_time(tbuf, run_start_time); @@ -324,9 +371,9 @@ test_get_start_time_functions(void *arg) tt_int_op(retval, OP_EQ, 0); time_t now = mock_consensus.valid_after; - dirvote_recalculate_timing(get_options(), now); + voting_schedule_recalculate_timing(get_options(), now); time_t start_time_of_protocol_run = - sr_state_get_start_time_of_current_protocol_run(now); + sr_state_get_start_time_of_current_protocol_run(); tt_assert(start_time_of_protocol_run); /* Check that the round start time of the beginning of the run, is itself */ @@ -1272,7 +1319,7 @@ test_keep_commit(void *arg) expect_log_msg_containing("doesn't match the commit value."); expect_log_msg_containing("has an invalid reveal value."); assert_log_predicate(mock_saved_log_n_entries() == 2, - "expected 2 log entries"); + ("expected 2 log entries")); teardown_capture_of_logs(); memcpy(commit->hashed_reveal, place_holder.hashed_reveal, sizeof(commit->hashed_reveal)); @@ -1387,4 +1434,3 @@ struct testcase_t sr_tests[] = { NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_slow.c b/src/test/test_slow.c index e640702499..0b665363ab 100644 --- a/src/test/test_slow.c +++ b/src/test/test_slow.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -15,8 +15,8 @@ #include <fcntl.h> #endif -#include "or.h" -#include "test.h" +#include "core/or/or.h" +#include "test/test.h" struct testgroup_t testgroups[] = { { "slow/crypto/", slow_crypto_tests }, diff --git a/src/test/test_socks.c b/src/test/test_socks.c index 8da7191e82..7f6d8a48f1 100644 --- a/src/test/test_socks.c +++ b/src/test/test_socks.c @@ -1,14 +1,17 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "or.h" -#include "buffers.h" -#include "config.h" -#include "proto_socks.h" -#include "test.h" -#include "log_test_helpers.h" +#include "core/or/or.h" +#include "lib/container/buffers.h" +#include "app/config/config.h" +#include "core/mainloop/connection.h" +#include "core/proto/proto_socks.h" +#include "test/test.h" +#include "test/log_test_helpers.h" +#include "core/or/socks_request_st.h" +#include "lib/net/socks5_status.h" typedef struct socks_test_data_t { socks_request_t *req; @@ -81,7 +84,7 @@ test_socks_4_supported_commands(void *ptr) tt_int_op(0,OP_EQ, buf_datalen(buf)); - /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4370 */ + /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.3:4370 */ ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x03\x00"); tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, get_options()->SafeSocks), @@ -97,7 +100,7 @@ test_socks_4_supported_commands(void *ptr) tt_int_op(0,OP_EQ, buf_datalen(buf)); socks_request_clear(socks); - /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4369 with userid*/ + /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.4:4369 with userid*/ ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x04me\x00"); tt_int_op(fetch_from_buf_socks(buf, socks, 1, 0), OP_EQ, 1); @@ -163,7 +166,7 @@ test_socks_4_bad_arguments(void *ptr) tt_int_op(fetch_from_buf_socks(buf, socks, 1, 0), OP_EQ, -1); buf_clear(buf); - expect_log_msg_containing("user name too long; rejecting."); + expect_log_msg_containing("socks4: parsing failed - invalid request."); mock_clean_saved_logs(); /* Try with 2000-byte hostname */ @@ -191,7 +194,7 @@ test_socks_4_bad_arguments(void *ptr) tt_int_op(fetch_from_buf_socks(buf, socks, 1, 0), OP_EQ, -1); buf_clear(buf); - expect_log_msg_containing("Destaddr too long."); + expect_log_msg_containing("parsing failed - invalid request."); mock_clean_saved_logs(); /* Socks4, bogus hostname */ @@ -645,7 +648,8 @@ test_socks_5_malformed_commands(void *ptr) tt_int_op(5,OP_EQ,socks->socks_version); tt_int_op(10,OP_EQ,socks->replylen); tt_int_op(5,OP_EQ,socks->reply[0]); - tt_int_op(SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED,OP_EQ,socks->reply[1]); + /* trunnel parsing will fail with -1 */ + tt_int_op(SOCKS5_GENERAL_ERROR,OP_EQ,socks->reply[1]); tt_int_op(1,OP_EQ,socks->reply[3]); done: @@ -1046,4 +1050,3 @@ struct testcase_t socks_tests[] = { END_OF_TESTCASES }; - diff --git a/src/test/test_status.c b/src/test/test_status.c index b4ca17891b..3ceba77a84 100644 --- a/src/test/test_status.c +++ b/src/test/test_status.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Tor Project, Inc. */ +/* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define STATUS_PRIVATE @@ -11,20 +11,27 @@ #include <float.h> #include <math.h> -#include "or.h" -#include "torlog.h" +#include "core/or/or.h" +#include "lib/log/log.h" #include "tor_queue.h" -#include "status.h" -#include "circuitlist.h" -#include "config.h" -#include "hibernate.h" -#include "rephist.h" -#include "relay.h" -#include "router.h" -#include "main.h" -#include "nodelist.h" -#include "statefile.h" -#include "test.h" +#include "core/or/status.h" +#include "core/or/circuitlist.h" +#include "app/config/config.h" +#include "feature/hibernate/hibernate.h" +#include "feature/stats/rephist.h" +#include "core/or/relay.h" +#include "feature/relay/router.h" +#include "feature/relay/routermode.h" +#include "core/mainloop/mainloop.h" +#include "feature/nodelist/nodelist.h" +#include "app/config/statefile.h" +#include "lib/tls/tortls.h" + +#include "core/or/origin_circuit_st.h" +#include "app/config/or_state_st.h" +#include "feature/nodelist/routerinfo_st.h" + +#include "test/test.h" #define NS_MODULE status @@ -226,7 +233,7 @@ NS(test_main)(void *arg) tor_free(actual); expected = "10.00 GB"; - actual = bytes_to_usage((U64_LITERAL(1) << 30) * 10L); + actual = bytes_to_usage((UINT64_C(1) << 30) * 10L); tt_str_op(actual, OP_EQ, expected); tor_free(actual); @@ -1093,4 +1100,3 @@ struct testcase_t status_tests[] = { TEST_CASE_ASPECT(log_heartbeat, tls_write_overhead), END_OF_TESTCASES }; - diff --git a/src/test/test_storagedir.c b/src/test/test_storagedir.c index a27074c21f..76aae7e033 100644 --- a/src/test/test_storagedir.c +++ b/src/test/test_storagedir.c @@ -1,9 +1,11 @@ -/* Copyright (c) 2017, The Tor Project, Inc. */ +/* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "or.h" -#include "storagedir.h" -#include "test.h" +#include "core/or/or.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "lib/fs/storagedir.h" +#include "lib/encoding/confline.h" +#include "test/test.h" #ifdef HAVE_UTIME_H #include <utime.h> @@ -281,7 +283,7 @@ test_storagedir_save_labeled(void *arg) int r = storage_dir_save_labeled_to_file(d, labels, inp, 8192, &fname); tt_int_op(r, OP_EQ, 0); - size_t n; + size_t n = 0; saved = storage_dir_read(d, fname, 1, &n); tt_assert(memchr(saved, '\0', n)); tt_str_op((char*)saved, OP_EQ, expected); /* NUL guarantees strcmp works */ @@ -372,4 +374,3 @@ struct testcase_t storagedir_tests[] = { ENT(read_labeled), END_OF_TESTCASES }; - diff --git a/src/test/test_switch_id.c b/src/test/test_switch_id.c index fe36d8c6e6..d8a1d15e4e 100644 --- a/src/test/test_switch_id.c +++ b/src/test/test_switch_id.c @@ -1,11 +1,15 @@ -/* Copyright (c) 2015-2017, The Tor Project, Inc. */ +/* Copyright (c) 2015-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "or.h" +#include "core/or/or.h" +#include "lib/process/setuid.h" #ifdef HAVE_SYS_CAPABILITY_H #include <sys/capability.h> #endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif #define TEST_BUILT_WITH_CAPS 0 #define TEST_HAVE_CAPS 1 @@ -189,4 +193,3 @@ main(int argc, char **argv) return (okay ? 0 : 1); #endif /* defined(_WIN32) */ } - diff --git a/src/test/test_threads.c b/src/test/test_threads.c index ed6d8f04aa..2bf5026061 100644 --- a/src/test/test_threads.c +++ b/src/test/test_threads.c @@ -1,12 +1,12 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" -#include "or.h" -#include "compat_threads.h" -#include "test.h" +#include "core/or/or.h" +#include "lib/thread/threads.h" +#include "test/test.h" /** mutex for thread test to stop the threads hitting data at the same time. */ static tor_mutex_t *thread_test_mutex_ = NULL; @@ -234,25 +234,33 @@ test_threads_conditionvar(void *arg) if (timeout) { ti->tv = &msec100; } + +#define SPIN_UNTIL(condition,sleep_msec) \ + while (1) { \ + tor_mutex_acquire(ti->mutex); \ + if (condition) { \ + break; \ + } \ + tor_mutex_release(ti->mutex); \ + tor_sleep_msec(sleep_msec); \ + } + spawn_func(cv_test_thr_fn_, ti); spawn_func(cv_test_thr_fn_, ti); spawn_func(cv_test_thr_fn_, ti); spawn_func(cv_test_thr_fn_, ti); - tor_mutex_acquire(ti->mutex); + SPIN_UNTIL(ti->n_threads == 4, 10); + + time_t started_at = time(NULL); + ti->addend = 7; ti->shutdown = 1; tor_cond_signal_one(ti->cond); tor_mutex_release(ti->mutex); #define SPIN() \ - while (1) { \ - tor_mutex_acquire(ti->mutex); \ - if (ti->addend == 0) { \ - break; \ - } \ - tor_mutex_release(ti->mutex); \ - } + SPIN_UNTIL(ti->addend == 0, 0) SPIN(); @@ -279,8 +287,9 @@ test_threads_conditionvar(void *arg) if (!timeout) { tt_int_op(ti->n_shutdown, OP_EQ, 4); } else { - tor_sleep_msec(200); - tor_mutex_acquire(ti->mutex); + const int GIVE_UP_AFTER_SEC = 30; + SPIN_UNTIL((ti->n_timeouts == 2 || + time(NULL) >= started_at + GIVE_UP_AFTER_SEC), 10); tt_int_op(ti->n_shutdown, OP_EQ, 2); tt_int_op(ti->n_timeouts, OP_EQ, 2); tor_mutex_release(ti->mutex); @@ -301,4 +310,3 @@ struct testcase_t thread_tests[] = { &passthrough_setup, (void*)"tv" }, END_OF_TESTCASES }; - diff --git a/src/test/test_tortls.c b/src/test/test_tortls.c index a661eb5c5d..79b52437f8 100644 --- a/src/test/test_tortls.c +++ b/src/test/test_tortls.c @@ -1,8 +1,8 @@ -/* Copyright (c) 2010-2017, The Tor Project, Inc. */ +/* Copyright (c) 2010-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define TORTLS_PRIVATE -#define TORTLS_OPENSSL_PRIVATE +#define TOR_X509_PRIVATE #define LOG_PRIVATE #include "orconfig.h" @@ -10,60 +10,138 @@ #include <winsock2.h> #endif #include <math.h> +#include <stddef.h> -#include "compat.h" +#include "lib/cc/compat_compiler.h" -/* Some versions of OpenSSL declare SSL_get_selected_srtp_profile twice in - * srtp.h. Suppress the GCC warning so we can build with -Wredundant-decl. */ -DISABLE_GCC_WARNING(redundant-decls) +#include "core/or/or.h" +#include "lib/log/log.h" +#include "app/config/config.h" +#include "lib/crypt_ops/compat_openssl.h" +#include "lib/tls/x509.h" +#include "lib/tls/x509_internal.h" +#include "lib/tls/tortls.h" +#include "lib/tls/tortls_st.h" +#include "lib/tls/tortls_internal.h" +#include "lib/encoding/pem.h" +#include "app/config/or_state_st.h" -#include <openssl/opensslv.h> +#include "test/test.h" +#include "test/log_test_helpers.h" +#include "test/test_tortls.h" -#include <openssl/ssl.h> -#include <openssl/ssl3.h> -#include <openssl/err.h> -#include <openssl/asn1t.h> -#include <openssl/x509.h> -#include <openssl/rsa.h> -#include <openssl/evp.h> -#include <openssl/bn.h> +#include "tinytest.h" -ENABLE_GCC_WARNING(redundant-decls) - -#include "or.h" -#include "torlog.h" -#include "config.h" -#include "tortls.h" - -#include "test.h" -#include "log_test_helpers.h" -#define NS_MODULE tortls +const char* notCompletelyValidCertString = + "-----BEGIN CERTIFICATE-----\n" + "MIICVjCCAb8CAg37MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG\n" + "A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE\n" + "MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl\n" + "YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw\n" + "ODIyMDUyNzIzWhcNMTcwODIxMDUyNzIzWjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE\n" + "CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs\n" + "ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMYBBrx5PlP0WNI/ZdzD\n" + "+6Pktmurn+F2kQYbtc7XQh8/LTBvCo+P6iZoLEmUA9e7EXLRxgU1CVqeAi7QcAn9\n" + "MwBlc8ksFJHB0rtf9pmf8Oza9E0Bynlq/4/Kb1x+d+AyhL7oK9tQwB24uHOueHi1\n" + "C/iVv8CSWKiYe6hzN1txYe8rAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAASPdjigJ\n" + "kXCqKWpnZ/Oc75EUcMi6HztaW8abUMlYXPIgkV2F7YanHOB7K4f7OOLjiz8DTPFf\n" + "jC9UeuErhaA/zzWi8ewMTFZW/WshOrm3fNvcMrMLKtH534JKvcdMg6qIdjTFINIr\n" + "evnAhf0cwULaebn+lMs8Pdl7y37+sfluVok=\n" + "-----END CERTIFICATE-----\n"; -#ifndef HAVE_SSL_STATE -#define OPENSSL_OPAQUE -#endif +const char* validCertString = "-----BEGIN CERTIFICATE-----\n" + "MIIDpTCCAY0CAg3+MA0GCSqGSIb3DQEBBQUAMF4xCzAJBgNVBAYTAlVTMREwDwYD\n" + "VQQIDAhJbGxpbm9pczEQMA4GA1UEBwwHQ2hpY2FnbzEUMBIGA1UECgwLVG9yIFRl\n" + "c3RpbmcxFDASBgNVBAMMC1RvciBUZXN0aW5nMB4XDTE1MDkwNjEzMzk1OVoXDTQz\n" + "MDEyMjEzMzk1OVowVjELMAkGA1UEBhMCVVMxEDAOBgNVBAcMB0NoaWNhZ28xFDAS\n" + "BgNVBAoMC1RvciBUZXN0aW5nMR8wHQYDVQQDDBZ0ZXN0aW5nLnRvcnByb2plY3Qu\n" + "b3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDoT6uyVVhWyOF3wkHjjYbd\n" + "nKaykyRv4JVtKQdZ4OpEErmX1zw4MmyzpQNV6iR4bQnWiyLfzyVJMZDIC/WILBfX\n" + "w2Pza/yuLgUvDc3twMuhOACzOQVO8PrEF/aVv2+hbCCy2udXvKhnYn+CCXl3ozc8\n" + "XcKYvujTXDyvGWY3xwAjlQIDAQABMA0GCSqGSIb3DQEBBQUAA4ICAQCUvnhzQWuQ\n" + "MrN+pERkE+zcTI/9dGS90rUMMLgu8VDNqTa0TUQh8uO0EQ6uDvI8Js6e8tgwS0BR\n" + "UBahqb7ZHv+rejGCBr5OudqD+x4STiiuPNJVs86JTLN8SpM9CHjIBH5WCCN2KOy3\n" + "mevNoRcRRyYJzSFULCunIK6FGulszigMYGscrO4oiTkZiHPh9KvWT40IMiHfL+Lw\n" + "EtEWiLex6064LcA2YQ1AMuSZyCexks63lcfaFmQbkYOKqXa1oLkIRuDsOaSVjTfe\n" + "vec+X6jvf12cFTKS5WIeqkKF2Irt+dJoiHEGTe5RscUMN/f+gqHPzfFz5dR23sxo\n" + "g+HC6MZHlFkLAOx3wW6epPS8A/m1mw3zMPoTnb2U2YYt8T0dJMMlUn/7Y1sEAa+a\n" + "dSTMaeUf6VnJ//11m454EZl1to9Z7oJOgqmFffSrdD4BGIWe8f7hhW6L1Enmqe/J\n" + "BKL3wbzZh80O1W0bndAwhnEEhlzneFY84cbBo9pmVxpODHkUcStpr5Z7pBDrcL21\n" + "Ss/aB/1YrsVXhdvJdOGxl3Mnl9dUY57CympLGlT8f0pPS6GAKOelECOhFMHmJd8L\n" + "dj3XQSmKtYHevZ6IvuMXSlB/fJvSjSlkCuLo5+kJoaqPuRu+i/S1qxeRy3CBwmnE\n" + "LdSNdcX4N79GQJ996PA8+mUCQG7YRtK+WA==\n" + "-----END CERTIFICATE-----\n"; -#if defined(OPENSSL_OPAQUE) && !defined(LIBRESSL_VERSION_NUMBER) -#define SSL_STATE_STR "before SSL initialization" -#else -#define SSL_STATE_STR "before/accept initialization" -#endif +const char* caCertString = "-----BEGIN CERTIFICATE-----\n" + "MIIFjzCCA3egAwIBAgIJAKd5WgyfPMYRMA0GCSqGSIb3DQEBCwUAMF4xCzAJBgNV\n" + "BAYTAlVTMREwDwYDVQQIDAhJbGxpbm9pczEQMA4GA1UEBwwHQ2hpY2FnbzEUMBIG\n" + "A1UECgwLVG9yIFRlc3RpbmcxFDASBgNVBAMMC1RvciBUZXN0aW5nMB4XDTE1MDkw\n" + "NjEzMzc0MVoXDTQzMDEyMjEzMzc0MVowXjELMAkGA1UEBhMCVVMxETAPBgNVBAgM\n" + "CElsbGlub2lzMRAwDgYDVQQHDAdDaGljYWdvMRQwEgYDVQQKDAtUb3IgVGVzdGlu\n" + "ZzEUMBIGA1UEAwwLVG9yIFRlc3RpbmcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw\n" + "ggIKAoICAQCpLMUEiLW5leUgBZoEJms2V7lZRhIAjnJBhVMHD0e3UubNknmaQoxf\n" + "ARz3rvqOaRd0JlV+qM9qE0DjiYcCVP1cAfqAo9d83uS1vwY3YMVJzADlaIiHfyVW\n" + "uEgBy0vvkeUBqaua24dYlcwsemOiXYLu41yM1wkcGHW1AhBNHppY6cznb8TyLgNM\n" + "2x3SGUdzc5XMyAFx51faKGBA3wjs+Hg1PLY7d30nmCgEOBavpm5I1disM/0k+Mcy\n" + "YmAKEo/iHJX/rQzO4b9znP69juLlR8PDBUJEVIG/CYb6+uw8MjjUyiWXYoqfVmN2\n" + "hm/lH8b6rXw1a2Aa3VTeD0DxaWeacMYHY/i01fd5n7hCoDTRNdSw5KJ0L3Z0SKTu\n" + "0lzffKzDaIfyZGlpW5qdouACkWYzsaitQOePVE01PIdO30vUfzNTFDfy42ccx3Di\n" + "59UCu+IXB+eMtrBfsok0Qc63vtF1linJgjHW1z/8ujk8F7/qkOfODhk4l7wngc2A\n" + "EmwWFIFoGaiTEZHB9qteXr4unbXZ0AHpM02uGGwZEGohjFyebEb73M+J57WKKAFb\n" + "PqbLcGUksL1SHNBNAJcVLttX55sO4nbidOS/kA3m+F1R04MBTyQF9qA6YDDHqdI3\n" + "h/3pw0Z4fxVouTYT4/NfRnX4JTP4u+7Mpcoof28VME0qWqD1LnRhFQIDAQABo1Aw\n" + "TjAdBgNVHQ4EFgQUMoAgIXH7pZ3QMRwTjT+DM9Yo/v0wHwYDVR0jBBgwFoAUMoAg\n" + "IXH7pZ3QMRwTjT+DM9Yo/v0wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC\n" + "AgEAUJxacjXR9sT+Xs6ISFiUsyd0T6WVKMnV46xrYJHirGfx+krWHrjxMY+ZtxYD\n" + "DBDGlo11Qc4v6QrclNf5QUBfIiGQsP9Cm6hHcQ+Tpg9HHCgSqG1YNPwCPReCR4br\n" + "BLvLfrfkcBL2IWM0PdQdCze+59DBfipsULD2mEn9fjYRXQEwb2QWtQ9qRc20Yb/x\n" + "Q4b/+CvUodLkaq7B8MHz0BV8HHcBoph6DYaRmO/N+hPauIuSp6XyaGYcEefGKVKj\n" + "G2+fcsdyXsoijNdL8vNKwm4j2gVwCBnw16J00yfFoV46YcbfqEdJB2je0XSvwXqt\n" + "14AOTngxso2h9k9HLtrfpO1ZG/B5AcCMs1lzbZ2fp5DPHtjvvmvA2RJqgo3yjw4W\n" + "4DHAuTglYFlC3mDHNfNtcGP20JvepcQNzNP2UzwcpOc94hfKikOFw+gf9Vf1qd0y\n" + "h/Sk6OZHn2+JVUPiWHIQV98Vtoh4RmUZDJD+b55ia3fQGTGzt4z1XFzQYSva5sfs\n" + "wocS/papthqWldQU7x+3wofNd5CNU1x6WKXG/yw30IT/4F8ADJD6GeygNT8QJYvt\n" + "u/8lAkbOy6B9xGmSvr0Kk1oq9P2NshA6kalxp1Oz/DTNDdL4AeBXV3JmM6WWCjGn\n" + "Yy1RT69d0rwYc5u/vnqODz1IjvT90smsrkBumGt791FAFeg=\n" + "-----END CERTIFICATE-----\n"; -#ifndef OPENSSL_OPAQUE -static SSL_METHOD * -give_me_a_test_method(void) +tor_x509_cert_impl_t * +read_cert_from(const char *str) { - SSL_METHOD *method = tor_malloc_zero(sizeof(SSL_METHOD)); - memcpy(method, TLSv1_method(), sizeof(SSL_METHOD)); - return method; + size_t len = strlen(str); + uint8_t *raw_cert = tor_malloc(len); + ssize_t true_len = pem_decode(raw_cert, len, str, len, "CERTIFICATE"); + if (true_len < 0) { + tor_free(raw_cert); + return NULL; + } + tor_x509_cert_t *cert = tor_x509_cert_decode(raw_cert, true_len); + tor_free(raw_cert); + if (! cert) { + return NULL; + } + tor_x509_cert_impl_t *res = tor_x509_cert_impl_dup_(cert->cert); + tor_x509_cert_free(cert); + return res; } -static int -fake_num_ciphers(void) +static tor_x509_cert_impl_t * + fixed_try_to_extract_certs_from_tls_cert_out_result = NULL; +static tor_x509_cert_impl_t * + fixed_try_to_extract_certs_from_tls_id_cert_out_result = NULL; + +static void +fixed_try_to_extract_certs_from_tls(int severity, tor_tls_t *tls, + tor_x509_cert_impl_t **cert_out, + tor_x509_cert_impl_t **id_cert_out) { - return 0; + (void) severity; + (void) tls; + *cert_out = tor_x509_cert_impl_dup_( + fixed_try_to_extract_certs_from_tls_cert_out_result); + *id_cert_out = tor_x509_cert_impl_dup_( + fixed_try_to_extract_certs_from_tls_id_cert_out_result); } -#endif /* !defined(OPENSSL_OPAQUE) */ static void test_tortls_errno_to_tls_error(void *data) @@ -107,6 +185,7 @@ test_tortls_err_to_string(void *data) (void)1; } +#ifdef ENABLE_OPENSSL static int mock_tls_cert_matches_key(const tor_tls_t *tls, const tor_x509_cert_t *cert) { @@ -116,66 +195,6 @@ mock_tls_cert_matches_key(const tor_tls_t *tls, const tor_x509_cert_t *cert) } static void -test_tortls_tor_tls_new(void *data) -{ - (void) data; - MOCK(tor_tls_cert_matches_key, mock_tls_cert_matches_key); - crypto_pk_t *key1 = NULL, *key2 = NULL; - SSL_METHOD *method = NULL; - - key1 = pk_generate(2); - key2 = pk_generate(3); - - tor_tls_t *tls = NULL; - tt_int_op(tor_tls_context_init(TOR_TLS_CTX_IS_PUBLIC_SERVER, - key1, key2, 86400), OP_EQ, 0); - tls = tor_tls_new(-1, 0); - tt_want(tls); - tor_tls_free(tls); tls = NULL; - - SSL_CTX_free(client_tls_context->ctx); - client_tls_context->ctx = NULL; - tls = tor_tls_new(-1, 0); - tt_ptr_op(tls, OP_EQ, NULL); - -#ifndef OPENSSL_OPAQUE - method = give_me_a_test_method(); - SSL_CTX *ctx = SSL_CTX_new(method); - method->num_ciphers = fake_num_ciphers; - client_tls_context->ctx = ctx; - tls = tor_tls_new(-1, 0); - tt_ptr_op(tls, OP_EQ, NULL); -#endif /* !defined(OPENSSL_OPAQUE) */ - - done: - UNMOCK(tor_tls_cert_matches_key); - crypto_pk_free(key1); - crypto_pk_free(key2); - tor_tls_free(tls); - tor_free(method); - tor_tls_free_all(); -} - -#define NS_MODULE tortls -NS_DECL(void, logv, (int severity, log_domain_mask_t domain, - const char *funcname, const char *suffix, - const char *format, va_list ap)); - -static void -NS(logv)(int severity, log_domain_mask_t domain, - const char *funcname, const char *suffix, const char *format, - va_list ap) -{ - (void) severity; - (void) domain; - (void) funcname; - (void) suffix; - (void) format; - (void) ap; // XXXX look at this. - CALLED(logv)++; -} - -static void test_tortls_tor_tls_get_error(void *data) { (void) data; @@ -188,11 +207,10 @@ test_tortls_tor_tls_get_error(void *data) tt_int_op(tor_tls_context_init(TOR_TLS_CTX_IS_PUBLIC_SERVER, key1, key2, 86400), OP_EQ, 0); tls = tor_tls_new(-1, 0); - NS_MOCK(logv); - tt_int_op(CALLED(logv), OP_EQ, 0); + setup_capture_of_logs(LOG_WARN); tor_tls_get_error(tls, 0, 0, - (const char *)"test", 0, 0); - tt_int_op(CALLED(logv), OP_EQ, 1); + (const char *)"in unit test", LOG_WARN, LD_GENERAL); + expect_single_log_msg_containing("unexpected close while in unit test"); done: UNMOCK(tor_tls_cert_matches_key); @@ -201,326 +219,7 @@ test_tortls_tor_tls_get_error(void *data) crypto_pk_free(key2); tor_tls_free(tls); } - -static void -test_tortls_get_state_description(void *ignored) -{ - (void)ignored; - tor_tls_t *tls; - char *buf; - SSL_CTX *ctx; - - SSL_library_init(); - SSL_load_error_strings(); - - ctx = SSL_CTX_new(SSLv23_method()); - - buf = tor_malloc_zero(1000); - tls = tor_malloc_zero(sizeof(tor_tls_t)); - - tor_tls_get_state_description(NULL, buf, 20); - tt_str_op(buf, OP_EQ, "(No SSL object)"); - - SSL_free(tls->ssl); - tls->ssl = NULL; - tor_tls_get_state_description(tls, buf, 20); - tt_str_op(buf, OP_EQ, "(No SSL object)"); - - tls->ssl = SSL_new(ctx); - tor_tls_get_state_description(tls, buf, 200); - tt_str_op(buf, OP_EQ, SSL_STATE_STR " in HANDSHAKE"); - - tls->state = TOR_TLS_ST_OPEN; - tor_tls_get_state_description(tls, buf, 200); - tt_str_op(buf, OP_EQ, SSL_STATE_STR " in OPEN"); - - tls->state = TOR_TLS_ST_GOTCLOSE; - tor_tls_get_state_description(tls, buf, 200); - tt_str_op(buf, OP_EQ, SSL_STATE_STR " in GOTCLOSE"); - - tls->state = TOR_TLS_ST_SENTCLOSE; - tor_tls_get_state_description(tls, buf, 200); - tt_str_op(buf, OP_EQ, SSL_STATE_STR " in SENTCLOSE"); - - tls->state = TOR_TLS_ST_CLOSED; - tor_tls_get_state_description(tls, buf, 200); - tt_str_op(buf, OP_EQ, SSL_STATE_STR " in CLOSED"); - - tls->state = TOR_TLS_ST_RENEGOTIATE; - tor_tls_get_state_description(tls, buf, 200); - tt_str_op(buf, OP_EQ, SSL_STATE_STR " in RENEGOTIATE"); - - tls->state = TOR_TLS_ST_BUFFEREVENT; - tor_tls_get_state_description(tls, buf, 200); - tt_str_op(buf, OP_EQ, SSL_STATE_STR); - - tls->state = 7; - tor_tls_get_state_description(tls, buf, 200); - tt_str_op(buf, OP_EQ, SSL_STATE_STR " in unknown TLS state"); - - done: - SSL_CTX_free(ctx); - SSL_free(tls->ssl); - tor_free(buf); - tor_free(tls); -} - -static void -test_tortls_get_by_ssl(void *ignored) -{ - (void)ignored; - tor_tls_t *tls; - tor_tls_t *res; - SSL_CTX *ctx; - SSL *ssl; - - SSL_library_init(); - SSL_load_error_strings(); - tor_tls_allocate_tor_tls_object_ex_data_index(); - - ctx = SSL_CTX_new(SSLv23_method()); - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->magic = TOR_TLS_MAGIC; - - ssl = SSL_new(ctx); - - res = tor_tls_get_by_ssl(ssl); - tt_assert(!res); - - SSL_set_ex_data(ssl, tor_tls_object_ex_data_index, tls); - - res = tor_tls_get_by_ssl(ssl); - tt_assert(res == tls); - - done: - SSL_free(ssl); - SSL_CTX_free(ctx); - tor_free(tls); -} - -static void -test_tortls_allocate_tor_tls_object_ex_data_index(void *ignored) -{ - (void)ignored; - int first; - - tor_tls_allocate_tor_tls_object_ex_data_index(); - - first = tor_tls_object_ex_data_index; - tor_tls_allocate_tor_tls_object_ex_data_index(); - tt_int_op(first, OP_EQ, tor_tls_object_ex_data_index); - - done: - (void)0; -} - -static void -test_tortls_log_one_error(void *ignored) -{ - (void)ignored; - tor_tls_t *tls; - SSL_CTX *ctx; - SSL *ssl = NULL; - - SSL_library_init(); - SSL_load_error_strings(); - - ctx = SSL_CTX_new(SSLv23_method()); - tls = tor_malloc_zero(sizeof(tor_tls_t)); - setup_capture_of_logs(LOG_INFO); - - tor_tls_log_one_error(NULL, 0, LOG_WARN, 0, "something"); - expect_log_msg("TLS error while something: " - "(null) (in (null):(null):---)\n"); - - mock_clean_saved_logs(); - tor_tls_log_one_error(tls, 0, LOG_WARN, 0, NULL); - expect_log_msg("TLS error: (null) " - "(in (null):(null):---)\n"); - - mock_clean_saved_logs(); - tls->address = tor_strdup("127.hello"); - tor_tls_log_one_error(tls, 0, LOG_WARN, 0, NULL); - expect_log_msg("TLS error with 127.hello: " - "(null) (in (null):(null):---)\n"); - tor_free(tls->address); - - mock_clean_saved_logs(); - tls->address = tor_strdup("127.hello"); - tor_tls_log_one_error(tls, 0, LOG_WARN, 0, "blarg"); - expect_log_msg("TLS error while blarg with " - "127.hello: (null) (in (null):(null):---)\n"); - - mock_clean_saved_logs(); - tor_tls_log_one_error(tls, ERR_PACK(1, 2, 3), LOG_WARN, 0, NULL); - expect_log_msg("TLS error with 127.hello: " - "BN lib (in unknown library:(null):---)\n"); - - mock_clean_saved_logs(); - tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_HTTP_REQUEST), - LOG_WARN, 0, NULL); - expect_log_severity(LOG_INFO); - - mock_clean_saved_logs(); - tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_HTTPS_PROXY_REQUEST), - LOG_WARN, 0, NULL); - expect_log_severity(LOG_INFO); - - mock_clean_saved_logs(); - tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_RECORD_LENGTH_MISMATCH), - LOG_WARN, 0, NULL); - expect_log_severity(LOG_INFO); - -#ifndef OPENSSL_1_1_API - mock_clean_saved_logs(); - tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_RECORD_TOO_LARGE), - LOG_WARN, 0, NULL); - expect_log_severity(LOG_INFO); -#endif /* !defined(OPENSSL_1_1_API) */ - - mock_clean_saved_logs(); - tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_UNKNOWN_PROTOCOL), - LOG_WARN, 0, NULL); - expect_log_severity(LOG_INFO); - - mock_clean_saved_logs(); - tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_UNSUPPORTED_PROTOCOL), - LOG_WARN, 0, NULL); - expect_log_severity(LOG_INFO); - - tls->ssl = SSL_new(ctx); - - mock_clean_saved_logs(); - tor_tls_log_one_error(tls, 0, LOG_WARN, 0, NULL); - expect_log_msg("TLS error with 127.hello: (null)" - " (in (null):(null):" SSL_STATE_STR ")\n"); - - done: - teardown_capture_of_logs(); - SSL_free(ssl); - SSL_CTX_free(ctx); - if (tls && tls->ssl) - SSL_free(tls->ssl); - if (tls) - tor_free(tls->address); - tor_free(tls); -} - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_get_error(void *ignored) -{ - (void)ignored; - tor_tls_t *tls; - int ret; - SSL_CTX *ctx; - - SSL_library_init(); - SSL_load_error_strings(); - - ctx = SSL_CTX_new(SSLv23_method()); - setup_capture_of_logs(LOG_INFO); - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = SSL_new(ctx); - SSL_set_bio(tls->ssl, BIO_new(BIO_s_mem()), NULL); - - ret = tor_tls_get_error(tls, 0, 0, "something", LOG_WARN, 0); - tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_IO); - expect_log_msg("TLS error: unexpected close while" - " something (before/accept initialization)\n"); - - mock_clean_saved_logs(); - ret = tor_tls_get_error(tls, 2, 0, "something", LOG_WARN, 0); - tt_int_op(ret, OP_EQ, 0); - expect_no_log_entry(); - - mock_clean_saved_logs(); - ret = tor_tls_get_error(tls, 0, 1, "something", LOG_WARN, 0); - tt_int_op(ret, OP_EQ, -11); - expect_no_log_entry(); - - mock_clean_saved_logs(); - ERR_clear_error(); - ERR_put_error(ERR_LIB_BN, 2, -1, "somewhere.c", 99); - ret = tor_tls_get_error(tls, 0, 0, "something", LOG_WARN, 0); - tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_MISC); - expect_log_msg("TLS error while something: (null)" - " (in bignum routines:(null):before/accept initialization)\n"); - - mock_clean_saved_logs(); - ERR_clear_error(); - tls->ssl->rwstate = SSL_READING; - SSL_get_rbio(tls->ssl)->flags = BIO_FLAGS_READ; - ret = tor_tls_get_error(tls, -1, 0, "something", LOG_WARN, 0); - tt_int_op(ret, OP_EQ, TOR_TLS_WANTREAD); - expect_no_log_entry(); - - mock_clean_saved_logs(); - ERR_clear_error(); - tls->ssl->rwstate = SSL_READING; - SSL_get_rbio(tls->ssl)->flags = BIO_FLAGS_WRITE; - ret = tor_tls_get_error(tls, -1, 0, "something", LOG_WARN, 0); - tt_int_op(ret, OP_EQ, TOR_TLS_WANTWRITE); - expect_no_log_entry(); - - mock_clean_saved_logs(); - ERR_clear_error(); - tls->ssl->rwstate = 0; - tls->ssl->shutdown = SSL_RECEIVED_SHUTDOWN; - tls->ssl->s3->warn_alert =SSL_AD_CLOSE_NOTIFY; - ret = tor_tls_get_error(tls, 0, 0, "something", LOG_WARN, 0); - tt_int_op(ret, OP_EQ, TOR_TLS_CLOSE); - expect_log_entry(); - - mock_clean_saved_logs(); - ret = tor_tls_get_error(tls, 0, 2, "something", LOG_WARN, 0); - tt_int_op(ret, OP_EQ, -10); - expect_no_log_entry(); - - mock_clean_saved_logs(); - ERR_put_error(ERR_LIB_SYS, 2, -1, "somewhere.c", 99); - ret = tor_tls_get_error(tls, -1, 0, "something", LOG_WARN, 0); - tt_int_op(ret, OP_EQ, -9); - expect_log_msg("TLS error while something: (null) (in system library:" - "connect:before/accept initialization)\n"); - - done: - teardown_capture_of_logs(); - SSL_free(tls->ssl); - tor_free(tls); - SSL_CTX_free(ctx); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -static void -test_tortls_always_accept_verify_cb(void *ignored) -{ - (void)ignored; - int ret; - - ret = always_accept_verify_cb(0, NULL); - tt_int_op(ret, OP_EQ, 1); - - done: - (void)0; -} - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_x509_cert_free(void *ignored) -{ - (void)ignored; - tor_x509_cert_t *cert; - - cert = tor_malloc_zero(sizeof(tor_x509_cert_t)); - tor_x509_cert_free(cert); - - cert = tor_malloc_zero(sizeof(tor_x509_cert_t)); - cert->cert = tor_malloc_zero(sizeof(X509)); - cert->encoded = tor_malloc_zero(1); - tor_x509_cert_free(cert); -} -#endif /* !defined(OPENSSL_OPAQUE) */ +#endif static void test_tortls_x509_cert_get_id_digests(void *ignored) @@ -539,6 +238,7 @@ test_tortls_x509_cert_get_id_digests(void *ignored) cert->pkey_digests_set = 1; cert->pkey_digests = *d; res = tor_x509_cert_get_id_digests(cert); + tt_assert(res); tt_int_op(res->d[0][0], OP_EQ, 42); done: @@ -546,152 +246,6 @@ test_tortls_x509_cert_get_id_digests(void *ignored) tor_free(d); } -#ifndef OPENSSL_OPAQUE -static void -fake_x509_free(X509 *cert) -{ - if (cert) { - if (cert->cert_info) { - if (cert->cert_info->key) { - if (cert->cert_info->key->pkey) { - tor_free(cert->cert_info->key->pkey); - } - tor_free(cert->cert_info->key); - } - tor_free(cert->cert_info); - } - tor_free(cert); - } -} -#endif - -static tor_x509_cert_t *fixed_x509_cert = NULL; -static tor_x509_cert_t * -get_peer_cert_mock_return_fixed(tor_tls_t *tls) -{ - (void)tls; - if (fixed_x509_cert) - return tor_x509_cert_dup(fixed_x509_cert); - else - return NULL; -} - -static void -test_tortls_cert_matches_key(void *ignored) -{ - (void)ignored; - - X509 *cert1 = NULL, *cert2 = NULL, *cert3 = NULL, *cert4 = NULL; - tor_x509_cert_t *c1 = NULL, *c2 = NULL, *c3 = NULL, *c4 = NULL; - crypto_pk_t *k1 = NULL, *k2 = NULL, *k3 = NULL; - - k1 = pk_generate(1); - k2 = pk_generate(2); - k3 = pk_generate(3); - - cert1 = tor_tls_create_certificate(k1, k2, "A", "B", 1000); - cert2 = tor_tls_create_certificate(k1, k3, "C", "D", 1000); - cert3 = tor_tls_create_certificate(k2, k3, "C", "D", 1000); - cert4 = tor_tls_create_certificate(k3, k2, "E", "F", 1000); - - tt_assert(cert1 && cert2 && cert3 && cert4); - - c1 = tor_x509_cert_new(cert1); cert1 = NULL; - c2 = tor_x509_cert_new(cert2); cert2 = NULL; - c3 = tor_x509_cert_new(cert3); cert3 = NULL; - c4 = tor_x509_cert_new(cert4); cert4 = NULL; - - tt_assert(c1 && c2 && c3 && c4); - - MOCK(tor_tls_get_peer_cert, get_peer_cert_mock_return_fixed); - - fixed_x509_cert = NULL; - /* If the peer has no certificate, it shouldn't match anything. */ - tt_assert(! tor_tls_cert_matches_key(NULL, c1)); - tt_assert(! tor_tls_cert_matches_key(NULL, c2)); - tt_assert(! tor_tls_cert_matches_key(NULL, c3)); - tt_assert(! tor_tls_cert_matches_key(NULL, c4)); - fixed_x509_cert = c1; - /* If the peer has a certificate, it should match every cert with the same - * subject key. */ - tt_assert(tor_tls_cert_matches_key(NULL, c1)); - tt_assert(tor_tls_cert_matches_key(NULL, c2)); - tt_assert(! tor_tls_cert_matches_key(NULL, c3)); - tt_assert(! tor_tls_cert_matches_key(NULL, c4)); - - done: - tor_x509_cert_free(c1); - tor_x509_cert_free(c2); - tor_x509_cert_free(c3); - tor_x509_cert_free(c4); - if (cert1) X509_free(cert1); - if (cert2) X509_free(cert2); - if (cert3) X509_free(cert3); - if (cert4) X509_free(cert4); - crypto_pk_free(k1); - crypto_pk_free(k2); - crypto_pk_free(k3); - UNMOCK(tor_tls_get_peer_cert); -} - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_cert_get_key(void *ignored) -{ - (void)ignored; - tor_x509_cert_t *cert = NULL; - crypto_pk_t *res = NULL; - cert = tor_malloc_zero(sizeof(tor_x509_cert_t)); - X509 *key = NULL; - key = tor_malloc_zero(sizeof(X509)); - key->references = 1; - - res = tor_tls_cert_get_key(cert); - tt_assert(!res); - - cert->cert = key; - key->cert_info = tor_malloc_zero(sizeof(X509_CINF)); - key->cert_info->key = tor_malloc_zero(sizeof(X509_PUBKEY)); - key->cert_info->key->pkey = tor_malloc_zero(sizeof(EVP_PKEY)); - key->cert_info->key->pkey->references = 1; - key->cert_info->key->pkey->type = 2; - res = tor_tls_cert_get_key(cert); - tt_assert(!res); - - done: - fake_x509_free(key); - tor_free(cert); - crypto_pk_free(res); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -static void -test_tortls_get_my_client_auth_key(void *ignored) -{ - (void)ignored; - crypto_pk_t *ret; - crypto_pk_t *expected; - tor_tls_context_t *ctx; - RSA *k = RSA_new(); - - ctx = tor_malloc_zero(sizeof(tor_tls_context_t)); - expected = crypto_new_pk_from_rsa_(k); - ctx->auth_key = expected; - - client_tls_context = NULL; - ret = tor_tls_get_my_client_auth_key(); - tt_assert(!ret); - - client_tls_context = ctx; - ret = tor_tls_get_my_client_auth_key(); - tt_assert(ret == expected); - - done: - RSA_free(k); - tor_free(expected); - tor_free(ctx); -} - static void test_tortls_get_my_certs(void *ignored) { @@ -727,438 +281,7 @@ test_tortls_get_my_certs(void *ignored) (void)1; } -#ifndef HAVE_SSL_GET_CLIENT_CIPHERS -static SSL_CIPHER * -get_cipher_by_name(const char *name) -{ - int i; - const SSL_METHOD *method = SSLv23_method(); - int num = method->num_ciphers(); - - for (i = 0; i < num; ++i) { - const SSL_CIPHER *cipher = method->get_cipher(i); - const char *ciphername = SSL_CIPHER_get_name(cipher); - if (!strcmp(ciphername, name)) { - return (SSL_CIPHER *)cipher; - } - } - - return NULL; -} -#endif /* !defined(HAVE_SSL_GET_CLIENT_CIPHERS) */ - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_get_ciphersuite_name(void *ignored) -{ - (void)ignored; - const char *ret; - tor_tls_t *ctx; - ctx = tor_malloc_zero(sizeof(tor_tls_t)); - ctx->ssl = tor_malloc_zero(sizeof(SSL)); - - ret = tor_tls_get_ciphersuite_name(ctx); - tt_str_op(ret, OP_EQ, "(NONE)"); - - done: - tor_free(ctx->ssl); - tor_free(ctx); -} - -static SSL_CIPHER * -get_cipher_by_id(uint16_t id) -{ - int i; - const SSL_METHOD *method = SSLv23_method(); - int num = method->num_ciphers(); - for (i = 0; i < num; ++i) { - const SSL_CIPHER *cipher = method->get_cipher(i); - if (id == (SSL_CIPHER_get_id(cipher) & 0xffff)) { - return (SSL_CIPHER *)cipher; - } - } - - return NULL; -} - -static void -test_tortls_classify_client_ciphers(void *ignored) -{ - (void)ignored; - int i; - int ret; - SSL_CTX *ctx; - SSL *ssl; - tor_tls_t *tls; - STACK_OF(SSL_CIPHER) *ciphers; - SSL_CIPHER *tmp_cipher; - - SSL_library_init(); - SSL_load_error_strings(); - tor_tls_allocate_tor_tls_object_ex_data_index(); - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->magic = TOR_TLS_MAGIC; - - ctx = SSL_CTX_new(TLSv1_method()); - ssl = SSL_new(ctx); - tls->ssl = ssl; - - ciphers = sk_SSL_CIPHER_new_null(); - - ret = tor_tls_classify_client_ciphers(ssl, NULL); - tt_int_op(ret, OP_EQ, -1); - - SSL_set_ex_data(ssl, tor_tls_object_ex_data_index, tls); - tls->client_cipher_list_type = 42; - - ret = tor_tls_classify_client_ciphers(ssl, NULL); - tt_int_op(ret, OP_EQ, 42); - - tls->client_cipher_list_type = 0; - ret = tor_tls_classify_client_ciphers(ssl, ciphers); - tt_int_op(ret, OP_EQ, 1); - tt_int_op(tls->client_cipher_list_type, OP_EQ, 1); - - tls->client_cipher_list_type = 0; - ret = tor_tls_classify_client_ciphers(ssl, SSL_get_ciphers(ssl)); - tt_int_op(ret, OP_EQ, 3); - tt_int_op(tls->client_cipher_list_type, OP_EQ, 3); - - SSL_CIPHER *one = get_cipher_by_name(TLS1_TXT_DHE_RSA_WITH_AES_128_SHA), - *two = get_cipher_by_name(TLS1_TXT_DHE_RSA_WITH_AES_256_SHA), - *three = get_cipher_by_name(SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA), - *four = NULL; - sk_SSL_CIPHER_push(ciphers, one); - sk_SSL_CIPHER_push(ciphers, two); - sk_SSL_CIPHER_push(ciphers, three); - sk_SSL_CIPHER_push(ciphers, four); - - tls->client_cipher_list_type = 0; - ret = tor_tls_classify_client_ciphers(ssl, ciphers); - tt_int_op(ret, OP_EQ, 1); - tt_int_op(tls->client_cipher_list_type, OP_EQ, 1); - - sk_SSL_CIPHER_zero(ciphers); - - one = get_cipher_by_name("ECDHE-RSA-AES256-GCM-SHA384"); - tt_assert(one); - one->id = 0x00ff; - two = get_cipher_by_name("ECDHE-RSA-AES128-GCM-SHA256"); - tt_assert(two); - two->id = 0x0000; - sk_SSL_CIPHER_push(ciphers, one); - tls->client_cipher_list_type = 0; - ret = tor_tls_classify_client_ciphers(ssl, ciphers); - tt_int_op(ret, OP_EQ, 3); - tt_int_op(tls->client_cipher_list_type, OP_EQ, 3); - - sk_SSL_CIPHER_push(ciphers, two); - tls->client_cipher_list_type = 0; - ret = tor_tls_classify_client_ciphers(ssl, ciphers); - tt_int_op(ret, OP_EQ, 3); - tt_int_op(tls->client_cipher_list_type, OP_EQ, 3); - - one->id = 0xC00A; - tls->client_cipher_list_type = 0; - ret = tor_tls_classify_client_ciphers(ssl, ciphers); - tt_int_op(ret, OP_EQ, 3); - tt_int_op(tls->client_cipher_list_type, OP_EQ, 3); - - sk_SSL_CIPHER_zero(ciphers); - for (i=0; v2_cipher_list[i]; i++) { - tmp_cipher = get_cipher_by_id(v2_cipher_list[i]); - tt_assert(tmp_cipher); - sk_SSL_CIPHER_push(ciphers, tmp_cipher); - } - tls->client_cipher_list_type = 0; - ret = tor_tls_classify_client_ciphers(ssl, ciphers); - tt_int_op(ret, OP_EQ, 2); - tt_int_op(tls->client_cipher_list_type, OP_EQ, 2); - - done: - sk_SSL_CIPHER_free(ciphers); - SSL_free(tls->ssl); - tor_free(tls); - SSL_CTX_free(ctx); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -static void -test_tortls_client_is_using_v2_ciphers(void *ignored) -{ - (void)ignored; - -#ifdef HAVE_SSL_GET_CLIENT_CIPHERS - tt_skip(); - done: - (void)1; -#else - int ret; - SSL_CTX *ctx; - SSL *ssl; - SSL_SESSION *sess; - STACK_OF(SSL_CIPHER) *ciphers; - - SSL_library_init(); - SSL_load_error_strings(); - - ctx = SSL_CTX_new(TLSv1_method()); - ssl = SSL_new(ctx); - sess = SSL_SESSION_new(); - - ret = tor_tls_client_is_using_v2_ciphers(ssl); - tt_int_op(ret, OP_EQ, -1); - - ssl->session = sess; - ret = tor_tls_client_is_using_v2_ciphers(ssl); - tt_int_op(ret, OP_EQ, 0); - - ciphers = sk_SSL_CIPHER_new_null(); - SSL_CIPHER *one = get_cipher_by_name("ECDHE-RSA-AES256-GCM-SHA384"); - tt_assert(one); - one->id = 0x00ff; - sk_SSL_CIPHER_push(ciphers, one); - sess->ciphers = ciphers; - ret = tor_tls_client_is_using_v2_ciphers(ssl); - tt_int_op(ret, OP_EQ, 1); - done: - SSL_free(ssl); - SSL_CTX_free(ctx); -#endif /* defined(HAVE_SSL_GET_CLIENT_CIPHERS) */ -} - -#ifndef OPENSSL_OPAQUE -static X509 *fixed_try_to_extract_certs_from_tls_cert_out_result = NULL; -static X509 *fixed_try_to_extract_certs_from_tls_id_cert_out_result = NULL; - -static void -fixed_try_to_extract_certs_from_tls(int severity, tor_tls_t *tls, - X509 **cert_out, X509 **id_cert_out) -{ - (void) severity; - (void) tls; - *cert_out = fixed_try_to_extract_certs_from_tls_cert_out_result; - *id_cert_out = fixed_try_to_extract_certs_from_tls_id_cert_out_result; -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -static const char* notCompletelyValidCertString = - "-----BEGIN CERTIFICATE-----\n" - "MIICVjCCAb8CAg37MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG\n" - "A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE\n" - "MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl\n" - "YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw\n" - "ODIyMDUyNzIzWhcNMTcwODIxMDUyNzIzWjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE\n" - "CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs\n" - "ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMYBBrx5PlP0WNI/ZdzD\n" - "+6Pktmurn+F2kQYbtc7XQh8/LTBvCo+P6iZoLEmUA9e7EXLRxgU1CVqeAi7QcAn9\n" - "MwBlc8ksFJHB0rtf9pmf8Oza9E0Bynlq/4/Kb1x+d+AyhL7oK9tQwB24uHOueHi1\n" - "C/iVv8CSWKiYe6hzN1txYe8rAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAASPdjigJ\n" - "kXCqKWpnZ/Oc75EUcMi6HztaW8abUMlYXPIgkV2F7YanHOB7K4f7OOLjiz8DTPFf\n" - "jC9UeuErhaA/zzWi8ewMTFZW/WshOrm3fNvcMrMLKtH534JKvcdMg6qIdjTFINIr\n" - "evnAhf0cwULaebn+lMs8Pdl7y37+sfluVok=\n" - "-----END CERTIFICATE-----\n"; -#endif /* !defined(OPENSSL_OPAQUE) */ - -static const char* validCertString = "-----BEGIN CERTIFICATE-----\n" - "MIIDpTCCAY0CAg3+MA0GCSqGSIb3DQEBBQUAMF4xCzAJBgNVBAYTAlVTMREwDwYD\n" - "VQQIDAhJbGxpbm9pczEQMA4GA1UEBwwHQ2hpY2FnbzEUMBIGA1UECgwLVG9yIFRl\n" - "c3RpbmcxFDASBgNVBAMMC1RvciBUZXN0aW5nMB4XDTE1MDkwNjEzMzk1OVoXDTQz\n" - "MDEyMjEzMzk1OVowVjELMAkGA1UEBhMCVVMxEDAOBgNVBAcMB0NoaWNhZ28xFDAS\n" - "BgNVBAoMC1RvciBUZXN0aW5nMR8wHQYDVQQDDBZ0ZXN0aW5nLnRvcnByb2plY3Qu\n" - "b3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDoT6uyVVhWyOF3wkHjjYbd\n" - "nKaykyRv4JVtKQdZ4OpEErmX1zw4MmyzpQNV6iR4bQnWiyLfzyVJMZDIC/WILBfX\n" - "w2Pza/yuLgUvDc3twMuhOACzOQVO8PrEF/aVv2+hbCCy2udXvKhnYn+CCXl3ozc8\n" - "XcKYvujTXDyvGWY3xwAjlQIDAQABMA0GCSqGSIb3DQEBBQUAA4ICAQCUvnhzQWuQ\n" - "MrN+pERkE+zcTI/9dGS90rUMMLgu8VDNqTa0TUQh8uO0EQ6uDvI8Js6e8tgwS0BR\n" - "UBahqb7ZHv+rejGCBr5OudqD+x4STiiuPNJVs86JTLN8SpM9CHjIBH5WCCN2KOy3\n" - "mevNoRcRRyYJzSFULCunIK6FGulszigMYGscrO4oiTkZiHPh9KvWT40IMiHfL+Lw\n" - "EtEWiLex6064LcA2YQ1AMuSZyCexks63lcfaFmQbkYOKqXa1oLkIRuDsOaSVjTfe\n" - "vec+X6jvf12cFTKS5WIeqkKF2Irt+dJoiHEGTe5RscUMN/f+gqHPzfFz5dR23sxo\n" - "g+HC6MZHlFkLAOx3wW6epPS8A/m1mw3zMPoTnb2U2YYt8T0dJMMlUn/7Y1sEAa+a\n" - "dSTMaeUf6VnJ//11m454EZl1to9Z7oJOgqmFffSrdD4BGIWe8f7hhW6L1Enmqe/J\n" - "BKL3wbzZh80O1W0bndAwhnEEhlzneFY84cbBo9pmVxpODHkUcStpr5Z7pBDrcL21\n" - "Ss/aB/1YrsVXhdvJdOGxl3Mnl9dUY57CympLGlT8f0pPS6GAKOelECOhFMHmJd8L\n" - "dj3XQSmKtYHevZ6IvuMXSlB/fJvSjSlkCuLo5+kJoaqPuRu+i/S1qxeRy3CBwmnE\n" - "LdSNdcX4N79GQJ996PA8+mUCQG7YRtK+WA==\n" - "-----END CERTIFICATE-----\n"; - -static const char* caCertString = "-----BEGIN CERTIFICATE-----\n" - "MIIFjzCCA3egAwIBAgIJAKd5WgyfPMYRMA0GCSqGSIb3DQEBCwUAMF4xCzAJBgNV\n" - "BAYTAlVTMREwDwYDVQQIDAhJbGxpbm9pczEQMA4GA1UEBwwHQ2hpY2FnbzEUMBIG\n" - "A1UECgwLVG9yIFRlc3RpbmcxFDASBgNVBAMMC1RvciBUZXN0aW5nMB4XDTE1MDkw\n" - "NjEzMzc0MVoXDTQzMDEyMjEzMzc0MVowXjELMAkGA1UEBhMCVVMxETAPBgNVBAgM\n" - "CElsbGlub2lzMRAwDgYDVQQHDAdDaGljYWdvMRQwEgYDVQQKDAtUb3IgVGVzdGlu\n" - "ZzEUMBIGA1UEAwwLVG9yIFRlc3RpbmcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw\n" - "ggIKAoICAQCpLMUEiLW5leUgBZoEJms2V7lZRhIAjnJBhVMHD0e3UubNknmaQoxf\n" - "ARz3rvqOaRd0JlV+qM9qE0DjiYcCVP1cAfqAo9d83uS1vwY3YMVJzADlaIiHfyVW\n" - "uEgBy0vvkeUBqaua24dYlcwsemOiXYLu41yM1wkcGHW1AhBNHppY6cznb8TyLgNM\n" - "2x3SGUdzc5XMyAFx51faKGBA3wjs+Hg1PLY7d30nmCgEOBavpm5I1disM/0k+Mcy\n" - "YmAKEo/iHJX/rQzO4b9znP69juLlR8PDBUJEVIG/CYb6+uw8MjjUyiWXYoqfVmN2\n" - "hm/lH8b6rXw1a2Aa3VTeD0DxaWeacMYHY/i01fd5n7hCoDTRNdSw5KJ0L3Z0SKTu\n" - "0lzffKzDaIfyZGlpW5qdouACkWYzsaitQOePVE01PIdO30vUfzNTFDfy42ccx3Di\n" - "59UCu+IXB+eMtrBfsok0Qc63vtF1linJgjHW1z/8ujk8F7/qkOfODhk4l7wngc2A\n" - "EmwWFIFoGaiTEZHB9qteXr4unbXZ0AHpM02uGGwZEGohjFyebEb73M+J57WKKAFb\n" - "PqbLcGUksL1SHNBNAJcVLttX55sO4nbidOS/kA3m+F1R04MBTyQF9qA6YDDHqdI3\n" - "h/3pw0Z4fxVouTYT4/NfRnX4JTP4u+7Mpcoof28VME0qWqD1LnRhFQIDAQABo1Aw\n" - "TjAdBgNVHQ4EFgQUMoAgIXH7pZ3QMRwTjT+DM9Yo/v0wHwYDVR0jBBgwFoAUMoAg\n" - "IXH7pZ3QMRwTjT+DM9Yo/v0wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC\n" - "AgEAUJxacjXR9sT+Xs6ISFiUsyd0T6WVKMnV46xrYJHirGfx+krWHrjxMY+ZtxYD\n" - "DBDGlo11Qc4v6QrclNf5QUBfIiGQsP9Cm6hHcQ+Tpg9HHCgSqG1YNPwCPReCR4br\n" - "BLvLfrfkcBL2IWM0PdQdCze+59DBfipsULD2mEn9fjYRXQEwb2QWtQ9qRc20Yb/x\n" - "Q4b/+CvUodLkaq7B8MHz0BV8HHcBoph6DYaRmO/N+hPauIuSp6XyaGYcEefGKVKj\n" - "G2+fcsdyXsoijNdL8vNKwm4j2gVwCBnw16J00yfFoV46YcbfqEdJB2je0XSvwXqt\n" - "14AOTngxso2h9k9HLtrfpO1ZG/B5AcCMs1lzbZ2fp5DPHtjvvmvA2RJqgo3yjw4W\n" - "4DHAuTglYFlC3mDHNfNtcGP20JvepcQNzNP2UzwcpOc94hfKikOFw+gf9Vf1qd0y\n" - "h/Sk6OZHn2+JVUPiWHIQV98Vtoh4RmUZDJD+b55ia3fQGTGzt4z1XFzQYSva5sfs\n" - "wocS/papthqWldQU7x+3wofNd5CNU1x6WKXG/yw30IT/4F8ADJD6GeygNT8QJYvt\n" - "u/8lAkbOy6B9xGmSvr0Kk1oq9P2NshA6kalxp1Oz/DTNDdL4AeBXV3JmM6WWCjGn\n" - "Yy1RT69d0rwYc5u/vnqODz1IjvT90smsrkBumGt791FAFeg=\n" - "-----END CERTIFICATE-----\n"; - -static X509 * -read_cert_from(const char *str) -{ - BIO *bio = BIO_new(BIO_s_mem()); - BIO_write(bio, str, (int) strlen(str)); - X509 *res = PEM_read_bio_X509(bio, NULL, NULL, NULL); - BIO_free(bio); - return res; -} - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_verify(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_t *tls; - crypto_pk_t *k = NULL; - X509 *cert1 = NULL, *cert2 = NULL, *invalidCert = NULL, - *validCert = NULL, *caCert = NULL; - - cert1 = tor_malloc_zero(sizeof(X509)); - cert1->references = 10; - - cert2 = tor_malloc_zero(sizeof(X509)); - cert2->references = 10; - - validCert = read_cert_from(validCertString); - caCert = read_cert_from(caCertString); - invalidCert = read_cert_from(notCompletelyValidCertString); - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - ret = tor_tls_verify(LOG_WARN, tls, &k); - tt_int_op(ret, OP_EQ, -1); - - MOCK(try_to_extract_certs_from_tls, fixed_try_to_extract_certs_from_tls); - - fixed_try_to_extract_certs_from_tls_cert_out_result = cert1; - ret = tor_tls_verify(LOG_WARN, tls, &k); - tt_int_op(ret, OP_EQ, -1); - - fixed_try_to_extract_certs_from_tls_id_cert_out_result = cert2; - ret = tor_tls_verify(LOG_WARN, tls, &k); - tt_int_op(ret, OP_EQ, -1); - - fixed_try_to_extract_certs_from_tls_cert_out_result = invalidCert; - fixed_try_to_extract_certs_from_tls_id_cert_out_result = invalidCert; - - ret = tor_tls_verify(LOG_WARN, tls, &k); - tt_int_op(ret, OP_EQ, -1); - - fixed_try_to_extract_certs_from_tls_cert_out_result = validCert; - fixed_try_to_extract_certs_from_tls_id_cert_out_result = caCert; - - ret = tor_tls_verify(LOG_WARN, tls, &k); - tt_int_op(ret, OP_EQ, 0); - tt_assert(k); - - done: - UNMOCK(try_to_extract_certs_from_tls); - tor_free(cert1); - tor_free(cert2); - tor_free(tls); - tor_free(k); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_check_lifetime(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_t *tls; - X509 *validCert = read_cert_from(validCertString); - time_t now = time(NULL); - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - ret = tor_tls_check_lifetime(LOG_WARN, tls, time(NULL), 0, 0); - tt_int_op(ret, OP_EQ, -1); - - tls->ssl = tor_malloc_zero(sizeof(SSL)); - tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION)); - tls->ssl->session->peer = validCert; - ret = tor_tls_check_lifetime(LOG_WARN, tls, time(NULL), 0, 0); - tt_int_op(ret, OP_EQ, 0); - - ASN1_STRING_free(validCert->cert_info->validity->notBefore); - validCert->cert_info->validity->notBefore = ASN1_TIME_set(NULL, now-10); - ASN1_STRING_free(validCert->cert_info->validity->notAfter); - validCert->cert_info->validity->notAfter = ASN1_TIME_set(NULL, now+60); - - ret = tor_tls_check_lifetime(LOG_WARN, tls, time(NULL), 0, -1000); - tt_int_op(ret, OP_EQ, -1); - - ret = tor_tls_check_lifetime(LOG_WARN, tls, time(NULL), -1000, 0); - tt_int_op(ret, OP_EQ, -1); - - done: - tor_free(tls->ssl->session); - tor_free(tls->ssl); - tor_free(tls); - X509_free(validCert); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -static int fixed_ssl_pending_result = 0; - -static int -fixed_ssl_pending(const SSL *ignored) -{ - (void)ignored; - return fixed_ssl_pending_result; -} - -static void -test_tortls_get_pending_bytes(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_t *tls; - SSL_METHOD *method; - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - method = tor_malloc_zero(sizeof(SSL_METHOD)); - method->ssl_pending = fixed_ssl_pending; - tls->ssl->method = method; - - fixed_ssl_pending_result = 42; - ret = tor_tls_get_pending_bytes(tls); - tt_int_op(ret, OP_EQ, 42); - - done: - tor_free(method); - tor_free(tls->ssl); - tor_free(tls); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - +#ifdef ENABLE_OPENSSL static void test_tortls_get_forced_write_size(void *ignored) { @@ -1177,30 +300,6 @@ test_tortls_get_forced_write_size(void *ignored) } static void -test_tortls_get_write_overhead_ratio(void *ignored) -{ - (void)ignored; - double ret; - - total_bytes_written_over_tls = 0; - ret = tls_get_write_overhead_ratio(); - tt_double_op(fabs(ret - 1.0), OP_LT, 1E-12); - - total_bytes_written_by_tls = 10; - total_bytes_written_over_tls = 1; - ret = tls_get_write_overhead_ratio(); - tt_double_op(fabs(ret - 10.0), OP_LT, 1E-12); - - total_bytes_written_by_tls = 10; - total_bytes_written_over_tls = 2; - ret = tls_get_write_overhead_ratio(); - tt_double_op(fabs(ret - 5.0), OP_LT, 1E-12); - - done: - (void)0; -} - -static void test_tortls_used_v1_handshake(void *ignored) { (void)ignored; @@ -1222,23 +321,6 @@ test_tortls_used_v1_handshake(void *ignored) } static void -test_tortls_get_num_server_handshakes(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_t *tls; - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - - tls->server_handshake_count = 3; - ret = tor_tls_get_num_server_handshakes(tls); - tt_int_op(ret, OP_EQ, 3); - - done: - tor_free(tls); -} - -static void test_tortls_server_got_renegotiate(void *ignored) { (void)ignored; @@ -1254,116 +336,7 @@ test_tortls_server_got_renegotiate(void *ignored) done: tor_free(tls); } - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_SSL_SESSION_get_master_key(void *ignored) -{ - (void)ignored; - size_t ret; - tor_tls_t *tls; - uint8_t *out; - out = tor_malloc_zero(1); - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION)); - tls->ssl->session->master_key_length = 1; - -#ifndef HAVE_SSL_SESSION_GET_MASTER_KEY - tls->ssl->session->master_key[0] = 43; - ret = SSL_SESSION_get_master_key(tls->ssl->session, out, 0); - tt_int_op(ret, OP_EQ, 1); - tt_int_op(out[0], OP_EQ, 0); - - ret = SSL_SESSION_get_master_key(tls->ssl->session, out, 1); - tt_int_op(ret, OP_EQ, 1); - tt_int_op(out[0], OP_EQ, 43); - - done: -#endif /* !defined(HAVE_SSL_SESSION_GET_MASTER_KEY) */ - tor_free(tls->ssl->session); - tor_free(tls->ssl); - tor_free(tls); - tor_free(out); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_get_tlssecrets(void *ignored) -{ - (void)ignored; - int ret; - uint8_t *secret_out = tor_malloc_zero(DIGEST256_LEN); - tor_tls_t *tls; - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION)); - tls->ssl->session->master_key_length = 1; - tls->ssl->s3 = tor_malloc_zero(sizeof(SSL3_STATE)); - - ret = tor_tls_get_tlssecrets(tls, secret_out); - tt_int_op(ret, OP_EQ, 0); - - done: - tor_free(secret_out); - tor_free(tls->ssl->s3); - tor_free(tls->ssl->session); - tor_free(tls->ssl); - tor_free(tls); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_get_buffer_sizes(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_t *tls; - size_t rbuf_c=-1, rbuf_b=-1, wbuf_c=-1, wbuf_b=-1; - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - tls->ssl->s3 = tor_malloc_zero(sizeof(SSL3_STATE)); - - tls->ssl->s3->rbuf.buf = NULL; - tls->ssl->s3->rbuf.len = 1; - tls->ssl->s3->rbuf.offset = 0; - tls->ssl->s3->rbuf.left = 42; - - tls->ssl->s3->wbuf.buf = NULL; - tls->ssl->s3->wbuf.len = 2; - tls->ssl->s3->wbuf.offset = 0; - tls->ssl->s3->wbuf.left = 43; - - ret = tor_tls_get_buffer_sizes(tls, &rbuf_c, &rbuf_b, &wbuf_c, &wbuf_b); -#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) - tt_int_op(ret, OP_EQ, -1); -#else - tt_int_op(ret, OP_EQ, 0); - tt_int_op(rbuf_c, OP_EQ, 0); - tt_int_op(wbuf_c, OP_EQ, 0); - tt_int_op(rbuf_b, OP_EQ, 42); - tt_int_op(wbuf_b, OP_EQ, 43); - - tls->ssl->s3->rbuf.buf = tor_malloc_zero(1); - tls->ssl->s3->wbuf.buf = tor_malloc_zero(1); - ret = tor_tls_get_buffer_sizes(tls, &rbuf_c, &rbuf_b, &wbuf_c, &wbuf_b); - tt_int_op(ret, OP_EQ, 0); - tt_int_op(rbuf_c, OP_EQ, 1); - tt_int_op(wbuf_c, OP_EQ, 2); - -#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) */ - - done: - tor_free(tls->ssl->s3->rbuf.buf); - tor_free(tls->ssl->s3->wbuf.buf); - tor_free(tls->ssl->s3); - tor_free(tls->ssl); - tor_free(tls); -} -#endif /* !defined(OPENSSL_OPAQUE) */ +#endif static void test_tortls_evaluate_ecgroup_for_tls(void *ignored) @@ -1388,1443 +361,177 @@ test_tortls_evaluate_ecgroup_for_tls(void *ignored) (void)0; } -#ifndef OPENSSL_OPAQUE -typedef struct cert_pkey_st_local -{ - X509 *x509; - EVP_PKEY *privatekey; - const EVP_MD *digest; -} CERT_PKEY_local; - -typedef struct sess_cert_st_local -{ - STACK_OF(X509) *cert_chain; - int peer_cert_type; - CERT_PKEY_local *peer_key; - CERT_PKEY_local peer_pkeys[8]; - int references; -} SESS_CERT_local; - -static void -test_tortls_try_to_extract_certs_from_tls(void *ignored) -{ - (void)ignored; - tor_tls_t *tls; - X509 *cert = NULL, *id_cert = NULL, *c1 = NULL, *c2 = NULL; - SESS_CERT_local *sess = NULL; - - c1 = read_cert_from(validCertString); - c2 = read_cert_from(caCertString); - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION)); - sess = tor_malloc_zero(sizeof(SESS_CERT_local)); - tls->ssl->session->sess_cert = (void *)sess; - - try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert); - tt_assert(!cert); - tt_assert(!id_cert); - - tls->ssl->session->peer = c1; - try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert); - tt_assert(cert == c1); - tt_assert(!id_cert); - X509_free(cert); /* decrease refcnt */ - - sess->cert_chain = sk_X509_new_null(); - try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert); - tt_assert(cert == c1); - tt_assert(!id_cert); - X509_free(cert); /* decrease refcnt */ - - sk_X509_push(sess->cert_chain, c1); - sk_X509_push(sess->cert_chain, c2); - - try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert); - tt_assert(cert == c1); - tt_assert(id_cert); - X509_free(cert); /* decrease refcnt */ - - done: - sk_X509_free(sess->cert_chain); - tor_free(sess); - tor_free(tls->ssl->session); - tor_free(tls->ssl); - tor_free(tls); - X509_free(c1); - X509_free(c2); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_get_peer_cert(void *ignored) -{ - (void)ignored; - tor_x509_cert_t *ret; - tor_tls_t *tls; - X509 *cert = NULL; - - cert = read_cert_from(validCertString); - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION)); - - ret = tor_tls_get_peer_cert(tls); - tt_assert(!ret); - - tls->ssl->session->peer = cert; - ret = tor_tls_get_peer_cert(tls); - tt_assert(ret); - tt_assert(ret->cert == cert); - - done: - tor_x509_cert_free(ret); - tor_free(tls->ssl->session); - tor_free(tls->ssl); - tor_free(tls); - X509_free(cert); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE static void -test_tortls_peer_has_cert(void *ignored) +test_tortls_double_init(void *arg) { - (void)ignored; - int ret; - tor_tls_t *tls; - X509 *cert = NULL; - - cert = read_cert_from(validCertString); - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION)); - - ret = tor_tls_peer_has_cert(tls); - tt_assert(!ret); - - tls->ssl->session->peer = cert; - ret = tor_tls_peer_has_cert(tls); - tt_assert(ret); - - done: - tor_free(tls->ssl->session); - tor_free(tls->ssl); - tor_free(tls); - X509_free(cert); -} -#endif /* !defined(OPENSSL_OPAQUE) */ + (void) arg; + /* If we call tor_tls_context_init() a second time, nothing should go + * wrong. + */ + crypto_pk_t *pk1 = NULL, *pk2 = NULL; + pk1 = pk_generate(2); + pk2 = pk_generate(0); -static void -test_tortls_is_server(void *ignored) -{ - (void)ignored; - tor_tls_t *tls; - int ret; + int r = tor_tls_context_init(TOR_TLS_CTX_IS_PUBLIC_SERVER, + pk1, pk2, 86400); + tt_int_op(r, OP_EQ, 0); - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->isServer = 1; - ret = tor_tls_is_server(tls); - tt_int_op(ret, OP_EQ, 1); + r = tor_tls_context_init(TOR_TLS_CTX_IS_PUBLIC_SERVER, + pk2, pk1, 86400); + tt_int_op(r, OP_EQ, 0); + /* For a public server context, these are the same */ + tt_ptr_op(tor_tls_context_get(0), OP_EQ, tor_tls_context_get(1)); done: - tor_free(tls); -} - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_session_secret_cb(void *ignored) -{ - (void)ignored; - tor_tls_t *tls; - SSL_CTX *ctx; - STACK_OF(SSL_CIPHER) *ciphers = NULL; - SSL_CIPHER *one; - - SSL_library_init(); - SSL_load_error_strings(); - tor_tls_allocate_tor_tls_object_ex_data_index(); - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - - tls->magic = TOR_TLS_MAGIC; - - ctx = SSL_CTX_new(TLSv1_method()); - tls->ssl = SSL_new(ctx); - SSL_set_ex_data(tls->ssl, tor_tls_object_ex_data_index, tls); - - SSL_set_session_secret_cb(tls->ssl, tor_tls_session_secret_cb, NULL); - - tor_tls_session_secret_cb(tls->ssl, NULL, NULL, NULL, NULL, NULL); - tt_assert(!tls->ssl->tls_session_secret_cb); - - one = get_cipher_by_name("ECDHE-RSA-AES256-GCM-SHA384"); - one->id = 0x00ff; - ciphers = sk_SSL_CIPHER_new_null(); - sk_SSL_CIPHER_push(ciphers, one); - - tls->client_cipher_list_type = 0; - tor_tls_session_secret_cb(tls->ssl, NULL, NULL, ciphers, NULL, NULL); - tt_assert(!tls->ssl->tls_session_secret_cb); - - done: - sk_SSL_CIPHER_free(ciphers); - SSL_free(tls->ssl); - SSL_CTX_free(ctx); - tor_free(tls); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -/* TODO: It seems block_renegotiation and unblock_renegotiation and - * using different blags. This might not be correct */ -static void -test_tortls_block_renegotiation(void *ignored) -{ - (void)ignored; - tor_tls_t *tls; - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - tls->ssl->s3 = tor_malloc_zero(sizeof(SSL3_STATE)); -#ifndef SUPPORT_UNSAFE_RENEGOTIATION_FLAG -#define SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0 -#endif - - tls->ssl->s3->flags = SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; - - tor_tls_block_renegotiation(tls); - -#ifndef OPENSSL_1_1_API - tt_assert(!(tls->ssl->s3->flags & - SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)); -#endif - - done: - tor_free(tls->ssl->s3); - tor_free(tls->ssl); - tor_free(tls); -} - -static void -test_tortls_unblock_renegotiation(void *ignored) -{ - (void)ignored; - tor_tls_t *tls; - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - tor_tls_unblock_renegotiation(tls); - - tt_uint_op(SSL_get_options(tls->ssl) & - SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION, OP_EQ, - SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); - - done: - tor_free(tls->ssl); - tor_free(tls); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_assert_renegotiation_unblocked(void *ignored) -{ - (void)ignored; - tor_tls_t *tls; - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - tor_tls_unblock_renegotiation(tls); - tor_tls_assert_renegotiation_unblocked(tls); - /* No assertion here - this test will fail if tor_assert is turned on - * and things are bad. */ - - tor_free(tls->ssl); - tor_free(tls); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -static void -test_tortls_set_logged_address(void *ignored) -{ - (void)ignored; - tor_tls_t *tls; - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - - tor_tls_set_logged_address(tls, "foo bar"); - - tt_str_op(tls->address, OP_EQ, "foo bar"); - - tor_tls_set_logged_address(tls, "foo bar 2"); - tt_str_op(tls->address, OP_EQ, "foo bar 2"); - - done: - tor_free(tls->address); - tor_free(tls); + crypto_pk_free(pk1); + crypto_pk_free(pk2); } -#ifndef OPENSSL_OPAQUE static void -example_cb(tor_tls_t *t, void *arg) +test_tortls_bridge_init(void *arg) { - (void)t; (void)arg; -} + crypto_pk_t *pk1 = NULL, *pk2 = NULL; + pk1 = pk_generate(2); + pk2 = pk_generate(0); -static void -test_tortls_set_renegotiate_callback(void *ignored) -{ - (void)ignored; - tor_tls_t *tls; - const char *arg = "hello"; - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - - tor_tls_set_renegotiate_callback(tls, example_cb, (void*)arg); - tt_assert(tls->negotiated_callback == example_cb); - tt_assert(tls->callback_arg == arg); - tt_assert(!tls->got_renegotiate); - - /* Assumes V2_HANDSHAKE_SERVER */ - tt_assert(tls->ssl->info_callback == tor_tls_server_info_callback); - - tor_tls_set_renegotiate_callback(tls, NULL, (void*)arg); - tt_assert(tls->ssl->info_callback == tor_tls_debug_state_callback); + /* If we pass in a server identity key but not the + TOR_TLS_CTX_IS_PUBLIC_SERVER flag, we should get a bridge-style + configuration, with two distinct contexts. */ + int r = tor_tls_context_init(0 /* flags */, pk1, pk2, 86400); + tt_int_op(r, OP_EQ, 0); + tt_ptr_op(tor_tls_context_get(0), OP_NE, tor_tls_context_get(1)); done: - tor_free(tls->ssl); - tor_free(tls); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -static SSL_CIPHER *fixed_cipher1 = NULL; -static SSL_CIPHER *fixed_cipher2 = NULL; -static const SSL_CIPHER * -fake_get_cipher(unsigned ncipher) -{ - - switch (ncipher) { - case 1: - return fixed_cipher1; - case 2: - return fixed_cipher2; - default: - return NULL; - } -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_find_cipher_by_id(void *ignored) -{ - (void)ignored; - int ret; - SSL *ssl; - SSL_CTX *ctx; - const SSL_METHOD *m = TLSv1_method(); - SSL_METHOD *empty_method = tor_malloc_zero(sizeof(SSL_METHOD)); - - fixed_cipher1 = tor_malloc_zero(sizeof(SSL_CIPHER)); - fixed_cipher2 = tor_malloc_zero(sizeof(SSL_CIPHER)); - fixed_cipher2->id = 0xC00A; - - SSL_library_init(); - SSL_load_error_strings(); - - ctx = SSL_CTX_new(m); - ssl = SSL_new(ctx); - - ret = find_cipher_by_id(ssl, NULL, 0xC00A); - tt_int_op(ret, OP_EQ, 1); - - ret = find_cipher_by_id(ssl, m, 0xC00A); - tt_int_op(ret, OP_EQ, 1); - - ret = find_cipher_by_id(ssl, m, 0xFFFF); - tt_int_op(ret, OP_EQ, 0); - - ret = find_cipher_by_id(ssl, empty_method, 0xC00A); - tt_int_op(ret, OP_EQ, 1); - - ret = find_cipher_by_id(ssl, empty_method, 0xFFFF); -#ifdef HAVE_SSL_CIPHER_FIND - tt_int_op(ret, OP_EQ, 0); -#else - tt_int_op(ret, OP_EQ, 1); -#endif - - empty_method->get_cipher = fake_get_cipher; - ret = find_cipher_by_id(ssl, empty_method, 0xC00A); - tt_int_op(ret, OP_EQ, 1); - - empty_method->get_cipher = m->get_cipher; - empty_method->num_ciphers = m->num_ciphers; - ret = find_cipher_by_id(ssl, empty_method, 0xC00A); - tt_int_op(ret, OP_EQ, 1); - - empty_method->get_cipher = fake_get_cipher; - empty_method->num_ciphers = m->num_ciphers; - ret = find_cipher_by_id(ssl, empty_method, 0xC00A); - tt_int_op(ret, OP_EQ, 1); - - empty_method->num_ciphers = fake_num_ciphers; - ret = find_cipher_by_id(ssl, empty_method, 0xC00A); -#ifdef HAVE_SSL_CIPHER_FIND - tt_int_op(ret, OP_EQ, 1); -#else - tt_int_op(ret, OP_EQ, 0); -#endif - - done: - tor_free(empty_method); - SSL_free(ssl); - SSL_CTX_free(ctx); - tor_free(fixed_cipher1); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_debug_state_callback(void *ignored) -{ - (void)ignored; - SSL *ssl; - char *buf = tor_malloc_zero(1000); - int n; - - setup_capture_of_logs(LOG_DEBUG); - - ssl = tor_malloc_zero(sizeof(SSL)); - - tor_tls_debug_state_callback(ssl, 32, 45); - - n = tor_snprintf(buf, 1000, "SSL %p is now in state unknown" - " state [type=32,val=45].\n", ssl); - /* tor's snprintf returns -1 on error */ - tt_int_op(n, OP_NE, -1); - expect_log_msg(buf); - - done: - teardown_capture_of_logs(); - tor_free(buf); - tor_free(ssl); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_server_info_callback(void *ignored) -{ - (void)ignored; - tor_tls_t *tls; - SSL_CTX *ctx; - SSL *ssl; - - SSL_library_init(); - SSL_load_error_strings(); - - ctx = SSL_CTX_new(TLSv1_method()); - ssl = SSL_new(ctx); - - tor_tls_allocate_tor_tls_object_ex_data_index(); - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->magic = TOR_TLS_MAGIC; - tls->ssl = ssl; - - setup_full_capture_of_logs(LOG_WARN); - SSL_set_state(ssl, SSL3_ST_SW_SRVR_HELLO_A); - mock_clean_saved_logs(); - tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0); - expect_single_log_msg("Couldn't look up the tls for an SSL*. How odd!\n"); - - SSL_set_state(ssl, SSL3_ST_SW_SRVR_HELLO_B); - mock_clean_saved_logs(); - tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0); - expect_single_log_msg("Couldn't look up the tls for an SSL*. How odd!\n"); - - SSL_set_state(ssl, 99); - mock_clean_saved_logs(); - tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0); - expect_no_log_entry(); - teardown_capture_of_logs(); - - SSL_set_ex_data(tls->ssl, tor_tls_object_ex_data_index, tls); - SSL_set_state(ssl, SSL3_ST_SW_SRVR_HELLO_B); - tls->negotiated_callback = 0; - tls->server_handshake_count = 120; - tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0); - tt_int_op(tls->server_handshake_count, OP_EQ, 121); - - tls->server_handshake_count = 127; - tls->negotiated_callback = (void *)1; - tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0); - tt_int_op(tls->server_handshake_count, OP_EQ, 127); - tt_int_op(tls->got_renegotiate, OP_EQ, 1); - - tls->ssl->session = SSL_SESSION_new(); - tls->wasV2Handshake = 0; - tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0); - tt_int_op(tls->wasV2Handshake, OP_EQ, 0); - - done: - teardown_capture_of_logs(); - SSL_free(ssl); - SSL_CTX_free(ctx); - tor_free(tls); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -static int fixed_ssl_read_result_index; -static int fixed_ssl_read_result[5]; -static int fixed_ssl_shutdown_result; - -static int -fixed_ssl_read(SSL *s, void *buf, int len) -{ - (void)s; - (void)buf; - (void)len; - return fixed_ssl_read_result[fixed_ssl_read_result_index++]; -} - -static int -fixed_ssl_shutdown(SSL *s) -{ - (void)s; - return fixed_ssl_shutdown_result; -} - -#ifndef LIBRESSL_VERSION_NUMBER -static int fixed_ssl_state_to_set; -static tor_tls_t *fixed_tls; - -static int -setting_version_ssl_shutdown(SSL *s) -{ - s->version = SSL2_VERSION; - return fixed_ssl_shutdown_result; -} - -static int -setting_version_and_state_ssl_shutdown(SSL *s) -{ - fixed_tls->state = fixed_ssl_state_to_set; - s->version = SSL2_VERSION; - return fixed_ssl_shutdown_result; -} -#endif /* !defined(LIBRESSL_VERSION_NUMBER) */ - -static int -dummy_handshake_func(SSL *s) -{ - (void)s; - return 1; -} - -static void -test_tortls_shutdown(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_t *tls; - SSL_METHOD *method = give_me_a_test_method(); - setup_capture_of_logs(LOG_WARN); - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - tls->ssl->method = method; - method->ssl_read = fixed_ssl_read; - method->ssl_shutdown = fixed_ssl_shutdown; - - ret = tor_tls_shutdown(tls); - tt_int_op(ret, OP_EQ, -9); - - tls->state = TOR_TLS_ST_SENTCLOSE; - fixed_ssl_read_result_index = 0; - fixed_ssl_read_result[0] = 10; - fixed_ssl_read_result[1] = -1; - ret = tor_tls_shutdown(tls); - tt_int_op(ret, OP_EQ, -9); - -#ifndef LIBRESSL_VERSION_NUMBER - tls->ssl->handshake_func = dummy_handshake_func; - - fixed_ssl_read_result_index = 0; - fixed_ssl_read_result[0] = 10; - fixed_ssl_read_result[1] = 42; - fixed_ssl_read_result[2] = 0; - fixed_ssl_shutdown_result = 1; - ERR_clear_error(); - tls->ssl->version = SSL2_VERSION; - ret = tor_tls_shutdown(tls); - tt_int_op(ret, OP_EQ, TOR_TLS_DONE); - tt_int_op(tls->state, OP_EQ, TOR_TLS_ST_CLOSED); - - fixed_ssl_read_result_index = 0; - fixed_ssl_read_result[0] = 10; - fixed_ssl_read_result[1] = 42; - fixed_ssl_read_result[2] = 0; - fixed_ssl_shutdown_result = 0; - ERR_clear_error(); - tls->ssl->version = 0; - ret = tor_tls_shutdown(tls); - tt_int_op(ret, OP_EQ, TOR_TLS_DONE); - tt_int_op(tls->state, OP_EQ, TOR_TLS_ST_CLOSED); - - fixed_ssl_read_result_index = 0; - fixed_ssl_read_result[0] = 10; - fixed_ssl_read_result[1] = 42; - fixed_ssl_read_result[2] = 0; - fixed_ssl_shutdown_result = 0; - ERR_clear_error(); - tls->ssl->version = 0; - method->ssl_shutdown = setting_version_ssl_shutdown; - ret = tor_tls_shutdown(tls); - tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_MISC); - - fixed_ssl_read_result_index = 0; - fixed_ssl_read_result[0] = 10; - fixed_ssl_read_result[1] = 42; - fixed_ssl_read_result[2] = 0; - fixed_ssl_shutdown_result = 0; - fixed_tls = tls; - fixed_ssl_state_to_set = TOR_TLS_ST_GOTCLOSE; - ERR_clear_error(); - tls->ssl->version = 0; - method->ssl_shutdown = setting_version_and_state_ssl_shutdown; - ret = tor_tls_shutdown(tls); - tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_MISC); - - fixed_ssl_read_result_index = 0; - fixed_ssl_read_result[0] = 10; - fixed_ssl_read_result[1] = 42; - fixed_ssl_read_result[2] = 0; - fixed_ssl_read_result[3] = -1; - fixed_ssl_shutdown_result = 0; - fixed_tls = tls; - fixed_ssl_state_to_set = 0; - ERR_clear_error(); - tls->ssl->version = 0; - method->ssl_shutdown = setting_version_and_state_ssl_shutdown; - ret = tor_tls_shutdown(tls); - tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_MISC); -#endif /* !defined(LIBRESSL_VERSION_NUMBER) */ - - done: - teardown_capture_of_logs(); - tor_free(method); - tor_free(tls->ssl); - tor_free(tls); + crypto_pk_free(pk1); + crypto_pk_free(pk2); } -static int negotiated_callback_called; - static void -negotiated_callback_setter(tor_tls_t *t, void *arg) +test_tortls_address(void *arg) { - (void)t; (void)arg; - negotiated_callback_called++; -} - -static void -test_tortls_read(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_t *tls; - char buf[100]; - SSL_METHOD *method = give_me_a_test_method(); - setup_capture_of_logs(LOG_WARN); - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - tls->state = TOR_TLS_ST_OPEN; - - ret = tor_tls_read(tls, buf, 10); - tt_int_op(ret, OP_EQ, -9); - - /* These tests assume that V2_HANDSHAKE_SERVER is set */ - tls->ssl->handshake_func = dummy_handshake_func; - tls->ssl->method = method; - method->ssl_read = fixed_ssl_read; - fixed_ssl_read_result_index = 0; - fixed_ssl_read_result[0] = 42; - tls->state = TOR_TLS_ST_OPEN; - ERR_clear_error(); - ret = tor_tls_read(tls, buf, 10); - tt_int_op(ret, OP_EQ, 42); - - tls->state = TOR_TLS_ST_OPEN; - tls->got_renegotiate = 1; - fixed_ssl_read_result_index = 0; - ERR_clear_error(); - ret = tor_tls_read(tls, buf, 10); - tt_int_op(tls->got_renegotiate, OP_EQ, 0); - - tls->state = TOR_TLS_ST_OPEN; - tls->got_renegotiate = 1; - negotiated_callback_called = 0; - tls->negotiated_callback = negotiated_callback_setter; - fixed_ssl_read_result_index = 0; - ERR_clear_error(); - ret = tor_tls_read(tls, buf, 10); - tt_int_op(negotiated_callback_called, OP_EQ, 1); - -#ifndef LIBRESSL_VERSION_NUMBER - fixed_ssl_read_result_index = 0; - fixed_ssl_read_result[0] = 0; - tls->ssl->version = SSL2_VERSION; - ERR_clear_error(); - ret = tor_tls_read(tls, buf, 10); - tt_int_op(ret, OP_EQ, TOR_TLS_CLOSE); - tt_int_op(tls->state, OP_EQ, TOR_TLS_ST_CLOSED); -#endif /* !defined(LIBRESSL_VERSION_NUMBER) */ - // TODO: fill up - - done: - teardown_capture_of_logs(); - tor_free(tls->ssl); - tor_free(tls); - tor_free(method); -} - -static int fixed_ssl_write_result; - -static int -fixed_ssl_write(SSL *s, const void *buf, int len) -{ - (void)s; - (void)buf; - (void)len; - return fixed_ssl_write_result; -} + tor_tls_t *tls = NULL; + crypto_pk_t *pk1=NULL, *pk2=NULL; + pk1 = pk_generate(2); + pk2 = pk_generate(0); -static void -test_tortls_write(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_t *tls; - SSL_METHOD *method = give_me_a_test_method(); - char buf[100]; - setup_capture_of_logs(LOG_WARN); + int r = tor_tls_context_init(TOR_TLS_CTX_IS_PUBLIC_SERVER, + pk1, pk2, 86400); + tt_int_op(r, OP_EQ, 0); - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); + tls = tor_tls_new(-1, 0); tls->state = TOR_TLS_ST_OPEN; + tor_tls_set_logged_address(tls, "zombo.com"); - ret = tor_tls_write(tls, buf, 0); - tt_int_op(ret, OP_EQ, 0); - - ret = tor_tls_write(tls, buf, 10); - tt_int_op(ret, OP_EQ, -9); - - tls->ssl->method = method; - tls->wantwrite_n = 1; - ret = tor_tls_write(tls, buf, 10); - tt_int_op(tls->wantwrite_n, OP_EQ, 0); - - method->ssl_write = fixed_ssl_write; - tls->ssl->handshake_func = dummy_handshake_func; - fixed_ssl_write_result = 1; - ERR_clear_error(); - ret = tor_tls_write(tls, buf, 10); - tt_int_op(ret, OP_EQ, 1); - - fixed_ssl_write_result = -1; - ERR_clear_error(); - tls->ssl->rwstate = SSL_READING; - SSL_set_bio(tls->ssl, BIO_new(BIO_s_mem()), NULL); - SSL_get_rbio(tls->ssl)->flags = BIO_FLAGS_READ; - ret = tor_tls_write(tls, buf, 10); - tt_int_op(ret, OP_EQ, TOR_TLS_WANTREAD); - - ERR_clear_error(); - tls->ssl->rwstate = SSL_READING; - SSL_set_bio(tls->ssl, BIO_new(BIO_s_mem()), NULL); - SSL_get_rbio(tls->ssl)->flags = BIO_FLAGS_WRITE; - ret = tor_tls_write(tls, buf, 10); - tt_int_op(ret, OP_EQ, TOR_TLS_WANTWRITE); - - done: - teardown_capture_of_logs(); - BIO_free(tls->ssl->rbio); - tor_free(tls->ssl); - tor_free(tls); - tor_free(method); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -static int fixed_ssl_accept_result; -static int fixed_ssl_connect_result; - -static int -setting_error_ssl_accept(SSL *ssl) -{ - (void)ssl; - ERR_put_error(ERR_LIB_BN, 2, -1, "somewhere.c", 99); - ERR_put_error(ERR_LIB_SYS, 2, -1, "somewhere.c", 99); - return fixed_ssl_accept_result; -} - -static int -setting_error_ssl_connect(SSL *ssl) -{ - (void)ssl; - ERR_put_error(ERR_LIB_BN, 2, -1, "somewhere.c", 99); - ERR_put_error(ERR_LIB_SYS, 2, -1, "somewhere.c", 99); - return fixed_ssl_connect_result; -} - -static int -fixed_ssl_accept(SSL *ssl) -{ - (void) ssl; - return fixed_ssl_accept_result; -} - -static void -test_tortls_handshake(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_t *tls; - SSL_CTX *ctx; - SSL_METHOD *method = give_me_a_test_method(); + /* This write should fail, since the fd is -1. */ setup_capture_of_logs(LOG_INFO); - - SSL_library_init(); - SSL_load_error_strings(); - - ctx = SSL_CTX_new(TLSv1_method()); - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = SSL_new(ctx); - tls->state = TOR_TLS_ST_HANDSHAKE; - - ret = tor_tls_handshake(tls); - tt_int_op(ret, OP_EQ, -9); - - tls->isServer = 1; - tls->state = TOR_TLS_ST_HANDSHAKE; - ret = tor_tls_handshake(tls); - tt_int_op(ret, OP_EQ, -9); - - tls->ssl->method = method; - method->ssl_accept = fixed_ssl_accept; - fixed_ssl_accept_result = 2; - ERR_clear_error(); - tls->state = TOR_TLS_ST_HANDSHAKE; - ret = tor_tls_handshake(tls); - tt_int_op(tls->state, OP_EQ, TOR_TLS_ST_OPEN); - - method->ssl_accept = setting_error_ssl_accept; - fixed_ssl_accept_result = 1; - ERR_clear_error(); - mock_clean_saved_logs(); - tls->state = TOR_TLS_ST_HANDSHAKE; - ret = tor_tls_handshake(tls); - tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_MISC); - expect_log_entry(); - /* This fails on jessie. Investigate why! */ -#if 0 - expect_log_msg("TLS error while handshaking: (null) (in bignum routines:" - "(null):SSLv3 write client hello B)\n"); - expect_log_msg("TLS error while handshaking: (null) (in system library:" - "connect:SSLv3 write client hello B)\n"); -#endif /* 0 */ - expect_log_severity(LOG_INFO); - - tls->isServer = 0; - method->ssl_connect = setting_error_ssl_connect; - fixed_ssl_connect_result = 1; - ERR_clear_error(); - mock_clean_saved_logs(); - tls->state = TOR_TLS_ST_HANDSHAKE; - ret = tor_tls_handshake(tls); - tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_MISC); - expect_log_entry(); -#if 0 - /* See above */ - expect_log_msg("TLS error while handshaking: " - "(null) (in bignum routines:(null):SSLv3 write client hello B)\n"); - expect_log_msg("TLS error while handshaking: " - "(null) (in system library:connect:SSLv3 write client hello B)\n"); -#endif /* 0 */ - expect_log_severity(LOG_WARN); + int n = tor_tls_write(tls, "welcome", 7); + tt_int_op(n, OP_LT, 0); + expect_log_msg_containing("with zombo.com"); done: teardown_capture_of_logs(); - SSL_free(tls->ssl); - SSL_CTX_free(ctx); - tor_free(tls); - tor_free(method); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_finish_handshake(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_t *tls; - SSL_CTX *ctx; - SSL_METHOD *method = give_me_a_test_method(); - SSL_library_init(); - SSL_load_error_strings(); - - X509 *c1 = read_cert_from(validCertString); - SESS_CERT_local *sess = NULL; - - ctx = SSL_CTX_new(method); - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = SSL_new(ctx); - tls->state = TOR_TLS_ST_OPEN; - - ret = tor_tls_finish_handshake(tls); - tt_int_op(ret, OP_EQ, 0); - - tls->isServer = 1; - tls->wasV2Handshake = 0; - setup_full_capture_of_logs(LOG_WARN); - ret = tor_tls_finish_handshake(tls); - tt_int_op(ret, OP_EQ, 0); - tt_int_op(tls->wasV2Handshake, OP_EQ, 1); - expect_single_log_msg_containing("For some reason, wasV2Handshake didn't " - "get set."); - teardown_capture_of_logs(); - - tls->wasV2Handshake = 1; - ret = tor_tls_finish_handshake(tls); - tt_int_op(ret, OP_EQ, 0); - tt_int_op(tls->wasV2Handshake, OP_EQ, 1); - - tls->wasV2Handshake = 1; - tls->ssl->session = SSL_SESSION_new(); - ret = tor_tls_finish_handshake(tls); - tt_int_op(ret, OP_EQ, 0); - tt_int_op(tls->wasV2Handshake, OP_EQ, 0); - - tls->isServer = 0; - - sess = tor_malloc_zero(sizeof(SESS_CERT_local)); - tls->ssl->session->sess_cert = (void *)sess; - sess->cert_chain = sk_X509_new_null(); - sk_X509_push(sess->cert_chain, c1); - tls->ssl->session->peer = c1; - tls->wasV2Handshake = 0; - ret = tor_tls_finish_handshake(tls); - tt_int_op(ret, OP_EQ, 0); - tt_int_op(tls->wasV2Handshake, OP_EQ, 1); - - method->num_ciphers = fake_num_ciphers; - ret = tor_tls_finish_handshake(tls); - tt_int_op(ret, OP_EQ, -9); - - done: - if (sess) - sk_X509_free(sess->cert_chain); - if (tls->ssl && tls->ssl->session) { - tor_free(tls->ssl->session->sess_cert); - } - SSL_free(tls->ssl); - tor_free(tls); - SSL_CTX_free(ctx); - tor_free(method); - teardown_capture_of_logs(); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -static int fixed_crypto_pk_new_result_index; -static crypto_pk_t *fixed_crypto_pk_new_result[5]; - -static crypto_pk_t * -fixed_crypto_pk_new(void) -{ - return fixed_crypto_pk_new_result[fixed_crypto_pk_new_result_index++]; -} - -#ifndef OPENSSL_OPAQUE -static int fixed_crypto_pk_generate_key_with_bits_result_index; -static int fixed_crypto_pk_generate_key_with_bits_result[5]; -static int fixed_tor_tls_create_certificate_result_index; -static X509 *fixed_tor_tls_create_certificate_result[5]; -static int fixed_tor_x509_cert_new_result_index; -static tor_x509_cert_t *fixed_tor_x509_cert_new_result[5]; - -static int -fixed_crypto_pk_generate_key_with_bits(crypto_pk_t *env, int bits) -{ - (void)env; - (void)bits; - return fixed_crypto_pk_generate_key_with_bits_result[ - fixed_crypto_pk_generate_key_with_bits_result_index++]; -} - -static X509 * -fixed_tor_tls_create_certificate(crypto_pk_t *rsa, - crypto_pk_t *rsa_sign, - const char *cname, - const char *cname_sign, - unsigned int cert_lifetime) -{ - (void)rsa; - (void)rsa_sign; - (void)cname; - (void)cname_sign; - (void)cert_lifetime; - return fixed_tor_tls_create_certificate_result[ - fixed_tor_tls_create_certificate_result_index++]; -} - -static tor_x509_cert_t * -fixed_tor_x509_cert_new(X509 *x509_cert) -{ - (void) x509_cert; - return fixed_tor_x509_cert_new_result[ - fixed_tor_x509_cert_new_result_index++]; + tor_tls_free(tls); + crypto_pk_free(pk1); + crypto_pk_free(pk2); } static void -test_tortls_context_new(void *ignored) +test_tortls_is_server(void *arg) { - (void)ignored; - tor_tls_context_t *ret; - crypto_pk_t *pk1, *pk2, *pk3, *pk4, *pk5, *pk6, *pk7, *pk8, *pk9, *pk10, - *pk11, *pk12, *pk13, *pk14, *pk15, *pk16, *pk17, *pk18; - - pk1 = crypto_pk_new(); - pk2 = crypto_pk_new(); - pk3 = crypto_pk_new(); - pk4 = crypto_pk_new(); - pk5 = crypto_pk_new(); - pk6 = crypto_pk_new(); - pk7 = crypto_pk_new(); - pk8 = crypto_pk_new(); - pk9 = crypto_pk_new(); - pk10 = crypto_pk_new(); - pk11 = crypto_pk_new(); - pk12 = crypto_pk_new(); - pk13 = crypto_pk_new(); - pk14 = crypto_pk_new(); - pk15 = crypto_pk_new(); - pk16 = crypto_pk_new(); - pk17 = crypto_pk_new(); - pk18 = crypto_pk_new(); - - fixed_crypto_pk_new_result_index = 0; - fixed_crypto_pk_new_result[0] = NULL; - MOCK(crypto_pk_new, fixed_crypto_pk_new); - ret = tor_tls_context_new(NULL, 0, 0, 0); - tt_assert(!ret); - - /* note: we already override this in testing_common.c, so we - * run this unit test in a subprocess. */ - MOCK(crypto_pk_generate_key_with_bits, - fixed_crypto_pk_generate_key_with_bits); - fixed_crypto_pk_new_result_index = 0; - fixed_crypto_pk_new_result[0] = pk1; - fixed_crypto_pk_new_result[1] = NULL; - fixed_crypto_pk_generate_key_with_bits_result[0] = -1; - fixed_crypto_pk_generate_key_with_bits_result_index = 0; - ret = tor_tls_context_new(NULL, 0, 0, 0); - tt_assert(!ret); - - fixed_crypto_pk_new_result_index = 0; - fixed_crypto_pk_new_result[0] = pk2; - fixed_crypto_pk_new_result[1] = NULL; - fixed_crypto_pk_generate_key_with_bits_result[0] = 0; - fixed_crypto_pk_generate_key_with_bits_result_index = 0; - ret = tor_tls_context_new(NULL, 0, 0, 0); - tt_assert(!ret); - - fixed_crypto_pk_new_result_index = 0; - fixed_crypto_pk_new_result[0] = pk3; - fixed_crypto_pk_new_result[1] = pk4; - fixed_crypto_pk_new_result[2] = NULL; - fixed_crypto_pk_generate_key_with_bits_result[0] = 0; - fixed_crypto_pk_generate_key_with_bits_result[1] = -1; - fixed_crypto_pk_generate_key_with_bits_result_index = 0; - ret = tor_tls_context_new(NULL, 0, 0, 0); - tt_assert(!ret); - - MOCK(tor_tls_create_certificate, fixed_tor_tls_create_certificate); - - fixed_crypto_pk_new_result_index = 0; - fixed_crypto_pk_new_result[0] = pk5; - fixed_crypto_pk_new_result[1] = pk6; - fixed_crypto_pk_new_result[2] = NULL; - fixed_crypto_pk_generate_key_with_bits_result_index = 0; - fixed_crypto_pk_generate_key_with_bits_result[1] = 0; - fixed_tor_tls_create_certificate_result_index = 0; - fixed_tor_tls_create_certificate_result[0] = NULL; - fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509)); - fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509)); - ret = tor_tls_context_new(NULL, 0, 0, 0); - tt_assert(!ret); - - fixed_crypto_pk_new_result_index = 0; - fixed_crypto_pk_new_result[0] = pk7; - fixed_crypto_pk_new_result[1] = pk8; - fixed_crypto_pk_new_result[2] = NULL; - fixed_crypto_pk_generate_key_with_bits_result_index = 0; - fixed_tor_tls_create_certificate_result_index = 0; - fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509)); - fixed_tor_tls_create_certificate_result[1] = NULL; - fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509)); - ret = tor_tls_context_new(NULL, 0, 0, 0); - tt_assert(!ret); - - fixed_crypto_pk_new_result_index = 0; - fixed_crypto_pk_new_result[0] = pk9; - fixed_crypto_pk_new_result[1] = pk10; - fixed_crypto_pk_new_result[2] = NULL; - fixed_crypto_pk_generate_key_with_bits_result_index = 0; - fixed_tor_tls_create_certificate_result_index = 0; - fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509)); - fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509)); - fixed_tor_tls_create_certificate_result[2] = NULL; - ret = tor_tls_context_new(NULL, 0, 0, 0); - tt_assert(!ret); - - MOCK(tor_x509_cert_new, fixed_tor_x509_cert_new); - fixed_crypto_pk_new_result_index = 0; - fixed_crypto_pk_new_result[0] = pk11; - fixed_crypto_pk_new_result[1] = pk12; - fixed_crypto_pk_new_result[2] = NULL; - fixed_crypto_pk_generate_key_with_bits_result_index = 0; - fixed_tor_tls_create_certificate_result_index = 0; - fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509)); - fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509)); - fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509)); - fixed_tor_x509_cert_new_result_index = 0; - fixed_tor_x509_cert_new_result[0] = NULL; - fixed_tor_x509_cert_new_result[1] = NULL; - fixed_tor_x509_cert_new_result[2] = NULL; - ret = tor_tls_context_new(NULL, 0, 0, 0); - tt_assert(!ret); - - fixed_crypto_pk_new_result_index = 0; - fixed_crypto_pk_new_result[0] = pk13; - fixed_crypto_pk_new_result[1] = pk14; - fixed_crypto_pk_new_result[2] = NULL; - fixed_crypto_pk_generate_key_with_bits_result_index = 0; - fixed_tor_tls_create_certificate_result_index = 0; - fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509)); - fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509)); - fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509)); - fixed_tor_x509_cert_new_result_index = 0; - fixed_tor_x509_cert_new_result[0] = tor_malloc_zero(sizeof(tor_x509_cert_t)); - fixed_tor_x509_cert_new_result[1] = NULL; - fixed_tor_x509_cert_new_result[2] = NULL; - ret = tor_tls_context_new(NULL, 0, 0, 0); - tt_assert(!ret); - - fixed_crypto_pk_new_result_index = 0; - fixed_crypto_pk_new_result[0] = pk15; - fixed_crypto_pk_new_result[1] = pk16; - fixed_crypto_pk_new_result[2] = NULL; - fixed_crypto_pk_generate_key_with_bits_result_index = 0; - fixed_tor_tls_create_certificate_result_index = 0; - fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509)); - fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509)); - fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509)); - fixed_tor_x509_cert_new_result_index = 0; - fixed_tor_x509_cert_new_result[0] = tor_malloc_zero(sizeof(tor_x509_cert_t)); - fixed_tor_x509_cert_new_result[1] = tor_malloc_zero(sizeof(tor_x509_cert_t)); - fixed_tor_x509_cert_new_result[2] = NULL; - ret = tor_tls_context_new(NULL, 0, 0, 0); - tt_assert(!ret); - - fixed_crypto_pk_new_result_index = 0; - fixed_crypto_pk_new_result[0] = pk17; - fixed_crypto_pk_new_result[1] = pk18; - fixed_crypto_pk_new_result[2] = NULL; - fixed_crypto_pk_generate_key_with_bits_result_index = 0; - fixed_tor_tls_create_certificate_result_index = 0; - fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509)); - fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509)); - fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509)); - fixed_tor_x509_cert_new_result_index = 0; - fixed_tor_x509_cert_new_result[0] = tor_malloc_zero(sizeof(tor_x509_cert_t)); - fixed_tor_x509_cert_new_result[1] = tor_malloc_zero(sizeof(tor_x509_cert_t)); - fixed_tor_x509_cert_new_result[2] = tor_malloc_zero(sizeof(tor_x509_cert_t)); - ret = tor_tls_context_new(NULL, 0, 0, 0); - tt_assert(!ret); - - done: - UNMOCK(tor_x509_cert_new); - UNMOCK(tor_tls_create_certificate); - UNMOCK(crypto_pk_generate_key_with_bits); - UNMOCK(crypto_pk_new); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -static int fixed_crypto_pk_get_evp_pkey_result_index = 0; -static EVP_PKEY *fixed_crypto_pk_get_evp_pkey_result[5]; + (void)arg; + crypto_pk_t *pk1=NULL, *pk2=NULL; + tor_tls_t *tls1=NULL, *tls2=NULL; + pk1 = pk_generate(2); + pk2 = pk_generate(0); -static EVP_PKEY * -fixed_crypto_pk_get_evp_pkey_(crypto_pk_t *env, int private) -{ - (void) env; - (void) private; - return fixed_crypto_pk_get_evp_pkey_result[ - fixed_crypto_pk_get_evp_pkey_result_index++]; -} + int r = tor_tls_context_init(TOR_TLS_CTX_IS_PUBLIC_SERVER, + pk1, pk2, 86400); + tt_int_op(r, OP_EQ, 0); + tls1 = tor_tls_new(-1, 0); + tls2 = tor_tls_new(-1, 1); -static void -test_tortls_create_certificate(void *ignored) -{ - (void)ignored; - X509 *ret; - crypto_pk_t *pk1, *pk2; - - pk1 = crypto_pk_new(); - pk2 = crypto_pk_new(); - - MOCK(crypto_pk_get_evp_pkey_, fixed_crypto_pk_get_evp_pkey_); - fixed_crypto_pk_get_evp_pkey_result_index = 0; - fixed_crypto_pk_get_evp_pkey_result[0] = NULL; - ret = tor_tls_create_certificate(pk1, pk2, "hello", "hello2", 1); - tt_assert(!ret); - - fixed_crypto_pk_get_evp_pkey_result_index = 0; - fixed_crypto_pk_get_evp_pkey_result[0] = EVP_PKEY_new(); - fixed_crypto_pk_get_evp_pkey_result[1] = NULL; - ret = tor_tls_create_certificate(pk1, pk2, "hello", "hello2", 1); - tt_assert(!ret); - - fixed_crypto_pk_get_evp_pkey_result_index = 0; - fixed_crypto_pk_get_evp_pkey_result[0] = EVP_PKEY_new(); - fixed_crypto_pk_get_evp_pkey_result[1] = EVP_PKEY_new(); - ret = tor_tls_create_certificate(pk1, pk2, "hello", "hello2", 1); - tt_assert(!ret); + tt_assert(! tor_tls_is_server(tls1)); + tt_assert(tor_tls_is_server(tls2)); done: - UNMOCK(crypto_pk_get_evp_pkey_); + tor_tls_free(tls1); + tor_tls_free(tls2); crypto_pk_free(pk1); crypto_pk_free(pk2); } static void -test_tortls_cert_new(void *ignored) -{ - (void)ignored; - tor_x509_cert_t *ret; - X509 *cert = read_cert_from(validCertString); - - ret = tor_x509_cert_new(NULL); - tt_assert(!ret); - - ret = tor_x509_cert_new(cert); - tt_assert(ret); - tor_x509_cert_free(ret); - ret = NULL; - -#if 0 - cert = read_cert_from(validCertString); - /* XXX this doesn't do what you think: it alters a copy of the pubkey. */ - X509_get_pubkey(cert)->type = EVP_PKEY_DSA; - ret = tor_x509_cert_new(cert); - tt_assert(ret); -#endif /* 0 */ - -#ifndef OPENSSL_OPAQUE - cert = read_cert_from(validCertString); - X509_CINF_free(cert->cert_info); - cert->cert_info = NULL; - ret = tor_x509_cert_new(cert); - tt_assert(ret); -#endif /* !defined(OPENSSL_OPAQUE) */ - - done: - tor_x509_cert_free(ret); -} - -static void -test_tortls_cert_is_valid(void *ignored) +test_tortls_verify(void *ignored) { (void)ignored; int ret; - tor_x509_cert_t *cert = NULL, *scert = NULL; + tor_tls_t *tls; + crypto_pk_t *k = NULL; + tor_x509_cert_impl_t *cert1 = NULL, *cert2 = NULL, *invalidCert = NULL, + *validCert = NULL, *caCert = NULL; - scert = tor_malloc_zero(sizeof(tor_x509_cert_t)); - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); - tt_int_op(ret, OP_EQ, 0); + validCert = read_cert_from(validCertString); + caCert = read_cert_from(caCertString); + invalidCert = read_cert_from(notCompletelyValidCertString); - cert = tor_malloc_zero(sizeof(tor_x509_cert_t)); - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); - tt_int_op(ret, OP_EQ, 0); - tor_free(scert); - tor_free(cert); + tls = tor_malloc_zero(sizeof(tor_tls_t)); - cert = tor_x509_cert_new(read_cert_from(validCertString)); - scert = tor_x509_cert_new(read_cert_from(caCertString)); - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); - tt_int_op(ret, OP_EQ, 1); + MOCK(try_to_extract_certs_from_tls, fixed_try_to_extract_certs_from_tls); -#ifndef OPENSSL_OPAQUE - tor_x509_cert_free(cert); - tor_x509_cert_free(scert); - cert = tor_x509_cert_new(read_cert_from(validCertString)); - scert = tor_x509_cert_new(read_cert_from(caCertString)); - ASN1_TIME_free(cert->cert->cert_info->validity->notAfter); - cert->cert->cert_info->validity->notAfter = - ASN1_TIME_set(NULL, time(NULL)-1000000); - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); - tt_int_op(ret, OP_EQ, 0); + fixed_try_to_extract_certs_from_tls_cert_out_result = cert1; + ret = tor_tls_verify(LOG_WARN, tls, &k); + tt_int_op(ret, OP_EQ, -1); - tor_x509_cert_free(cert); - tor_x509_cert_free(scert); - cert = tor_x509_cert_new(read_cert_from(validCertString)); - scert = tor_x509_cert_new(read_cert_from(caCertString)); - X509_PUBKEY_free(cert->cert->cert_info->key); - cert->cert->cert_info->key = NULL; - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 1); - tt_int_op(ret, OP_EQ, 0); -#endif /* !defined(OPENSSL_OPAQUE) */ + fixed_try_to_extract_certs_from_tls_id_cert_out_result = cert2; + ret = tor_tls_verify(LOG_WARN, tls, &k); + tt_int_op(ret, OP_EQ, -1); -#if 0 - tor_x509_cert_free(cert); - tor_x509_cert_free(scert); - cert = tor_x509_cert_new(read_cert_from(validCertString)); - scert = tor_x509_cert_new(read_cert_from(caCertString)); - /* This doesn't actually change the key in the cert. XXXXXX */ - BN_one(EVP_PKEY_get1_RSA(X509_get_pubkey(cert->cert))->n); - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 1); - tt_int_op(ret, OP_EQ, 0); + fixed_try_to_extract_certs_from_tls_cert_out_result = invalidCert; + fixed_try_to_extract_certs_from_tls_id_cert_out_result = invalidCert; - tor_x509_cert_free(cert); - tor_x509_cert_free(scert); - cert = tor_x509_cert_new(read_cert_from(validCertString)); - scert = tor_x509_cert_new(read_cert_from(caCertString)); - /* This doesn't actually change the key in the cert. XXXXXX */ - X509_get_pubkey(cert->cert)->type = EVP_PKEY_EC; - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 1); - tt_int_op(ret, OP_EQ, 0); + ret = tor_tls_verify(LOG_WARN, tls, &k); + tt_int_op(ret, OP_EQ, -1); - tor_x509_cert_free(cert); - tor_x509_cert_free(scert); - cert = tor_x509_cert_new(read_cert_from(validCertString)); - scert = tor_x509_cert_new(read_cert_from(caCertString)); - /* This doesn't actually change the key in the cert. XXXXXX */ - X509_get_pubkey(cert->cert)->type = EVP_PKEY_EC; - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); - tt_int_op(ret, OP_EQ, 1); + fixed_try_to_extract_certs_from_tls_cert_out_result = validCert; + fixed_try_to_extract_certs_from_tls_id_cert_out_result = caCert; - tor_x509_cert_free(cert); - tor_x509_cert_free(scert); - cert = tor_x509_cert_new(read_cert_from(validCertString)); - scert = tor_x509_cert_new(read_cert_from(caCertString)); - /* This doesn't actually change the key in the cert. XXXXXX */ - X509_get_pubkey(cert->cert)->type = EVP_PKEY_EC; - X509_get_pubkey(cert->cert)->ameth = NULL; - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); + ret = tor_tls_verify(LOG_WARN, tls, &k); tt_int_op(ret, OP_EQ, 0); -#endif /* 0 */ + tt_assert(k); done: - tor_x509_cert_free(cert); - tor_x509_cert_free(scert); -} - -static void -test_tortls_context_init_one(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_context_t *old = NULL; - - MOCK(crypto_pk_new, fixed_crypto_pk_new); - - fixed_crypto_pk_new_result_index = 0; - fixed_crypto_pk_new_result[0] = NULL; - ret = tor_tls_context_init_one(&old, NULL, 0, 0, 0); - tt_int_op(ret, OP_EQ, -1); + UNMOCK(try_to_extract_certs_from_tls); + tor_x509_cert_impl_free(cert1); + tor_x509_cert_impl_free(cert2); + tor_x509_cert_impl_free(validCert); + tor_x509_cert_impl_free(invalidCert); + tor_x509_cert_impl_free(caCert); - done: - UNMOCK(crypto_pk_new); + tor_free(tls); + crypto_pk_free(k); } -#define LOCAL_TEST_CASE(name, flags) \ +#define LOCAL_TEST_CASE(name, flags) \ { #name, test_tortls_##name, (flags|TT_FORK), NULL, NULL } -#ifdef OPENSSL_OPAQUE -#define INTRUSIVE_TEST_CASE(name, flags) \ - { #name, NULL, TT_SKIP, NULL, NULL } -#else -#define INTRUSIVE_TEST_CASE(name, flags) LOCAL_TEST_CASE(name, flags) -#endif /* defined(OPENSSL_OPAQUE) */ - struct testcase_t tortls_tests[] = { LOCAL_TEST_CASE(errno_to_tls_error, 0), LOCAL_TEST_CASE(err_to_string, 0), - LOCAL_TEST_CASE(tor_tls_new, TT_FORK), - LOCAL_TEST_CASE(tor_tls_get_error, 0), - LOCAL_TEST_CASE(get_state_description, TT_FORK), - LOCAL_TEST_CASE(get_by_ssl, TT_FORK), - LOCAL_TEST_CASE(allocate_tor_tls_object_ex_data_index, TT_FORK), - LOCAL_TEST_CASE(log_one_error, TT_FORK), - INTRUSIVE_TEST_CASE(get_error, TT_FORK), - LOCAL_TEST_CASE(always_accept_verify_cb, 0), - INTRUSIVE_TEST_CASE(x509_cert_free, 0), LOCAL_TEST_CASE(x509_cert_get_id_digests, 0), - LOCAL_TEST_CASE(cert_matches_key, 0), - INTRUSIVE_TEST_CASE(cert_get_key, 0), - LOCAL_TEST_CASE(get_my_client_auth_key, TT_FORK), LOCAL_TEST_CASE(get_my_certs, TT_FORK), - INTRUSIVE_TEST_CASE(get_ciphersuite_name, 0), - INTRUSIVE_TEST_CASE(classify_client_ciphers, 0), - LOCAL_TEST_CASE(client_is_using_v2_ciphers, 0), - INTRUSIVE_TEST_CASE(verify, 0), - INTRUSIVE_TEST_CASE(check_lifetime, 0), - INTRUSIVE_TEST_CASE(get_pending_bytes, 0), +#ifdef ENABLE_OPENSSL + LOCAL_TEST_CASE(tor_tls_get_error, 0), LOCAL_TEST_CASE(get_forced_write_size, 0), - LOCAL_TEST_CASE(get_write_overhead_ratio, TT_FORK), LOCAL_TEST_CASE(used_v1_handshake, TT_FORK), - LOCAL_TEST_CASE(get_num_server_handshakes, 0), LOCAL_TEST_CASE(server_got_renegotiate, 0), - INTRUSIVE_TEST_CASE(SSL_SESSION_get_master_key, 0), - INTRUSIVE_TEST_CASE(get_tlssecrets, 0), - INTRUSIVE_TEST_CASE(get_buffer_sizes, 0), +#endif LOCAL_TEST_CASE(evaluate_ecgroup_for_tls, 0), - INTRUSIVE_TEST_CASE(try_to_extract_certs_from_tls, 0), - INTRUSIVE_TEST_CASE(get_peer_cert, 0), - INTRUSIVE_TEST_CASE(peer_has_cert, 0), - INTRUSIVE_TEST_CASE(shutdown, 0), - INTRUSIVE_TEST_CASE(finish_handshake, 0), - INTRUSIVE_TEST_CASE(handshake, 0), - INTRUSIVE_TEST_CASE(write, 0), - INTRUSIVE_TEST_CASE(read, 0), - INTRUSIVE_TEST_CASE(server_info_callback, 0), + LOCAL_TEST_CASE(double_init, TT_FORK), + LOCAL_TEST_CASE(address, TT_FORK), LOCAL_TEST_CASE(is_server, 0), - INTRUSIVE_TEST_CASE(assert_renegotiation_unblocked, 0), - INTRUSIVE_TEST_CASE(block_renegotiation, 0), - INTRUSIVE_TEST_CASE(unblock_renegotiation, 0), - INTRUSIVE_TEST_CASE(set_renegotiate_callback, 0), - LOCAL_TEST_CASE(set_logged_address, 0), - INTRUSIVE_TEST_CASE(find_cipher_by_id, 0), - INTRUSIVE_TEST_CASE(session_secret_cb, 0), - INTRUSIVE_TEST_CASE(debug_state_callback, 0), - INTRUSIVE_TEST_CASE(context_new, TT_FORK /* redundant */), - LOCAL_TEST_CASE(create_certificate, 0), - LOCAL_TEST_CASE(cert_new, 0), - LOCAL_TEST_CASE(cert_is_valid, 0), - LOCAL_TEST_CASE(context_init_one, 0), + LOCAL_TEST_CASE(bridge_init, TT_FORK), + LOCAL_TEST_CASE(verify, TT_FORK), END_OF_TESTCASES }; diff --git a/src/test/test_tortls.h b/src/test/test_tortls.h new file mode 100644 index 0000000000..c997934ebc --- /dev/null +++ b/src/test/test_tortls.h @@ -0,0 +1,13 @@ +/* Copyright (c) 2010-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TEST_TORTLS_H +#define TEST_TORTLS_H + +tor_x509_cert_impl_t *read_cert_from(const char *str); + +extern const char *notCompletelyValidCertString; +extern const char *validCertString; +extern const char *caCertString; + +#endif diff --git a/src/test/test_tortls_openssl.c b/src/test/test_tortls_openssl.c new file mode 100644 index 0000000000..abe1fb7889 --- /dev/null +++ b/src/test/test_tortls_openssl.c @@ -0,0 +1,2316 @@ +/* Copyright (c) 2010-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#define TORTLS_PRIVATE +#define TORTLS_OPENSSL_PRIVATE +#define TOR_X509_PRIVATE +#define LOG_PRIVATE +#include "orconfig.h" + +#ifdef _WIN32 +#include <winsock2.h> +#endif +#include <math.h> + +#include "lib/cc/compat_compiler.h" + +/* Some versions of OpenSSL declare SSL_get_selected_srtp_profile twice in + * srtp.h. Suppress the GCC warning so we can build with -Wredundant-decl. */ +DISABLE_GCC_WARNING(redundant-decls) + +#include <openssl/opensslv.h> + +#include <openssl/ssl.h> +#include <openssl/ssl3.h> +#include <openssl/err.h> +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include <openssl/rsa.h> +#include <openssl/evp.h> +#include <openssl/bn.h> + +ENABLE_GCC_WARNING(redundant-decls) + +#include "core/or/or.h" +#include "lib/log/log.h" +#include "app/config/config.h" +#include "lib/crypt_ops/compat_openssl.h" +#include "lib/tls/x509.h" +#include "lib/tls/x509_internal.h" +#include "lib/tls/tortls.h" +#include "lib/tls/tortls_st.h" +#include "lib/tls/tortls_internal.h" +#include "app/config/or_state_st.h" + +#include "test/test.h" +#include "test/log_test_helpers.h" +#include "test/test_tortls.h" + +#define NS_MODULE tortls + +#ifndef HAVE_SSL_STATE +#define OPENSSL_OPAQUE +#endif + +#if defined(OPENSSL_OPAQUE) && !defined(LIBRESSL_VERSION_NUMBER) +#define SSL_STATE_STR "before SSL initialization" +#else +#define SSL_STATE_STR "before/accept initialization" +#endif + +#ifndef OPENSSL_OPAQUE +static SSL_METHOD * +give_me_a_test_method(void) +{ + SSL_METHOD *method = tor_malloc_zero(sizeof(SSL_METHOD)); + memcpy(method, TLSv1_method(), sizeof(SSL_METHOD)); + return method; +} + +static int +fake_num_ciphers(void) +{ + return 0; +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +static int +mock_tls_cert_matches_key(const tor_tls_t *tls, const tor_x509_cert_t *cert) +{ + (void) tls; + (void) cert; // XXXX look at this. + return 1; +} + +static void +test_tortls_tor_tls_new(void *data) +{ + (void) data; + MOCK(tor_tls_cert_matches_key, mock_tls_cert_matches_key); + crypto_pk_t *key1 = NULL, *key2 = NULL; + SSL_METHOD *method = NULL; + + key1 = pk_generate(2); + key2 = pk_generate(3); + + tor_tls_t *tls = NULL; + tt_int_op(tor_tls_context_init(TOR_TLS_CTX_IS_PUBLIC_SERVER, + key1, key2, 86400), OP_EQ, 0); + tls = tor_tls_new(-1, 0); + tt_want(tls); + tor_tls_free(tls); tls = NULL; + + SSL_CTX_free(client_tls_context->ctx); + client_tls_context->ctx = NULL; + tls = tor_tls_new(-1, 0); + tt_ptr_op(tls, OP_EQ, NULL); + +#ifndef OPENSSL_OPAQUE + method = give_me_a_test_method(); + SSL_CTX *ctx = SSL_CTX_new(method); + method->num_ciphers = fake_num_ciphers; + client_tls_context->ctx = ctx; + tls = tor_tls_new(-1, 0); + tt_ptr_op(tls, OP_EQ, NULL); +#endif /* !defined(OPENSSL_OPAQUE) */ + + done: + UNMOCK(tor_tls_cert_matches_key); + crypto_pk_free(key1); + crypto_pk_free(key2); + tor_tls_free(tls); + tor_free(method); + tor_tls_free_all(); +} + +#define NS_MODULE tortls + +static void +library_init(void) +{ +#ifdef OPENSSL_1_1_API + OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); +#else + SSL_library_init(); + SSL_load_error_strings(); +#endif +} + +static void +test_tortls_get_state_description(void *ignored) +{ + (void)ignored; + tor_tls_t *tls; + char *buf; + SSL_CTX *ctx; + + library_init(); + ctx = SSL_CTX_new(SSLv23_method()); + + buf = tor_malloc_zero(1000); + tls = tor_malloc_zero(sizeof(tor_tls_t)); + + tor_tls_get_state_description(NULL, buf, 20); + tt_str_op(buf, OP_EQ, "(No SSL object)"); + + SSL_free(tls->ssl); + tls->ssl = NULL; + tor_tls_get_state_description(tls, buf, 20); + tt_str_op(buf, OP_EQ, "(No SSL object)"); + + tls->ssl = SSL_new(ctx); + tor_tls_get_state_description(tls, buf, 200); + tt_str_op(buf, OP_EQ, SSL_STATE_STR " in HANDSHAKE"); + + tls->state = TOR_TLS_ST_OPEN; + tor_tls_get_state_description(tls, buf, 200); + tt_str_op(buf, OP_EQ, SSL_STATE_STR " in OPEN"); + + tls->state = TOR_TLS_ST_GOTCLOSE; + tor_tls_get_state_description(tls, buf, 200); + tt_str_op(buf, OP_EQ, SSL_STATE_STR " in GOTCLOSE"); + + tls->state = TOR_TLS_ST_SENTCLOSE; + tor_tls_get_state_description(tls, buf, 200); + tt_str_op(buf, OP_EQ, SSL_STATE_STR " in SENTCLOSE"); + + tls->state = TOR_TLS_ST_CLOSED; + tor_tls_get_state_description(tls, buf, 200); + tt_str_op(buf, OP_EQ, SSL_STATE_STR " in CLOSED"); + + tls->state = TOR_TLS_ST_RENEGOTIATE; + tor_tls_get_state_description(tls, buf, 200); + tt_str_op(buf, OP_EQ, SSL_STATE_STR " in RENEGOTIATE"); + + tls->state = TOR_TLS_ST_BUFFEREVENT; + tor_tls_get_state_description(tls, buf, 200); + tt_str_op(buf, OP_EQ, SSL_STATE_STR); + + tls->state = 7; + tor_tls_get_state_description(tls, buf, 200); + tt_str_op(buf, OP_EQ, SSL_STATE_STR " in unknown TLS state"); + + done: + SSL_CTX_free(ctx); + SSL_free(tls->ssl); + tor_free(buf); + tor_free(tls); +} + +static void +test_tortls_get_by_ssl(void *ignored) +{ + (void)ignored; + tor_tls_t *tls; + tor_tls_t *res; + SSL_CTX *ctx; + SSL *ssl; + + library_init(); + tor_tls_allocate_tor_tls_object_ex_data_index(); + + ctx = SSL_CTX_new(SSLv23_method()); + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->magic = TOR_TLS_MAGIC; + + ssl = SSL_new(ctx); + + res = tor_tls_get_by_ssl(ssl); + tt_assert(!res); + + SSL_set_ex_data(ssl, tor_tls_object_ex_data_index, tls); + + res = tor_tls_get_by_ssl(ssl); + tt_assert(res == tls); + + done: + SSL_free(ssl); + SSL_CTX_free(ctx); + tor_free(tls); +} + +static void +test_tortls_allocate_tor_tls_object_ex_data_index(void *ignored) +{ + (void)ignored; + int first; + + tor_tls_allocate_tor_tls_object_ex_data_index(); + + first = tor_tls_object_ex_data_index; + tor_tls_allocate_tor_tls_object_ex_data_index(); + tt_int_op(first, OP_EQ, tor_tls_object_ex_data_index); + + done: + (void)0; +} + +static void +test_tortls_log_one_error(void *ignored) +{ + (void)ignored; + tor_tls_t *tls; + SSL_CTX *ctx; + SSL *ssl = NULL; + + library_init(); + + ctx = SSL_CTX_new(SSLv23_method()); + tls = tor_malloc_zero(sizeof(tor_tls_t)); + setup_capture_of_logs(LOG_INFO); + + tor_tls_log_one_error(NULL, 0, LOG_WARN, 0, "something"); + expect_log_msg("TLS error while something: " + "(null) (in (null):(null):---)\n"); + + mock_clean_saved_logs(); + tor_tls_log_one_error(tls, 0, LOG_WARN, 0, NULL); + expect_log_msg("TLS error: (null) " + "(in (null):(null):---)\n"); + + mock_clean_saved_logs(); + tls->address = tor_strdup("127.hello"); + tor_tls_log_one_error(tls, 0, LOG_WARN, 0, NULL); + expect_log_msg("TLS error with 127.hello: " + "(null) (in (null):(null):---)\n"); + tor_free(tls->address); + + mock_clean_saved_logs(); + tls->address = tor_strdup("127.hello"); + tor_tls_log_one_error(tls, 0, LOG_WARN, 0, "blarg"); + expect_log_msg("TLS error while blarg with " + "127.hello: (null) (in (null):(null):---)\n"); + + mock_clean_saved_logs(); + tor_tls_log_one_error(tls, ERR_PACK(1, 2, 3), LOG_WARN, 0, NULL); + expect_log_msg("TLS error with 127.hello: " + "BN lib (in unknown library:(null):---)\n"); + + mock_clean_saved_logs(); + tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_HTTP_REQUEST), + LOG_WARN, 0, NULL); + expect_log_severity(LOG_INFO); + + mock_clean_saved_logs(); + tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_HTTPS_PROXY_REQUEST), + LOG_WARN, 0, NULL); + expect_log_severity(LOG_INFO); + + mock_clean_saved_logs(); + tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_RECORD_LENGTH_MISMATCH), + LOG_WARN, 0, NULL); + expect_log_severity(LOG_INFO); + +#ifndef OPENSSL_1_1_API + mock_clean_saved_logs(); + tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_RECORD_TOO_LARGE), + LOG_WARN, 0, NULL); + expect_log_severity(LOG_INFO); +#endif /* !defined(OPENSSL_1_1_API) */ + + mock_clean_saved_logs(); + tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_UNKNOWN_PROTOCOL), + LOG_WARN, 0, NULL); + expect_log_severity(LOG_INFO); + + mock_clean_saved_logs(); + tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_UNSUPPORTED_PROTOCOL), + LOG_WARN, 0, NULL); + expect_log_severity(LOG_INFO); + + tls->ssl = SSL_new(ctx); + + mock_clean_saved_logs(); + tor_tls_log_one_error(tls, 0, LOG_WARN, 0, NULL); + expect_log_msg("TLS error with 127.hello: (null)" + " (in (null):(null):" SSL_STATE_STR ")\n"); + + done: + teardown_capture_of_logs(); + SSL_free(ssl); + SSL_CTX_free(ctx); + if (tls && tls->ssl) + SSL_free(tls->ssl); + if (tls) + tor_free(tls->address); + tor_free(tls); +} + +#ifndef OPENSSL_OPAQUE +static void +test_tortls_get_error(void *ignored) +{ + (void)ignored; + tor_tls_t *tls; + int ret; + SSL_CTX *ctx; + + library_init(); + + ctx = SSL_CTX_new(SSLv23_method()); + setup_capture_of_logs(LOG_INFO); + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->ssl = SSL_new(ctx); + SSL_set_bio(tls->ssl, BIO_new(BIO_s_mem()), NULL); + + ret = tor_tls_get_error(tls, 0, 0, "something", LOG_WARN, 0); + tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_IO); + expect_log_msg("TLS error: unexpected close while" + " something (before/accept initialization)\n"); + + mock_clean_saved_logs(); + ret = tor_tls_get_error(tls, 2, 0, "something", LOG_WARN, 0); + tt_int_op(ret, OP_EQ, 0); + expect_no_log_entry(); + + mock_clean_saved_logs(); + ret = tor_tls_get_error(tls, 0, 1, "something", LOG_WARN, 0); + tt_int_op(ret, OP_EQ, -11); + expect_no_log_entry(); + + mock_clean_saved_logs(); + ERR_clear_error(); + ERR_put_error(ERR_LIB_BN, 2, -1, "somewhere.c", 99); + ret = tor_tls_get_error(tls, 0, 0, "something", LOG_WARN, 0); + tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_MISC); + expect_log_msg("TLS error while something: (null)" + " (in bignum routines:(null):before/accept initialization)\n"); + + mock_clean_saved_logs(); + ERR_clear_error(); + tls->ssl->rwstate = SSL_READING; + SSL_get_rbio(tls->ssl)->flags = BIO_FLAGS_READ; + ret = tor_tls_get_error(tls, -1, 0, "something", LOG_WARN, 0); + tt_int_op(ret, OP_EQ, TOR_TLS_WANTREAD); + expect_no_log_entry(); + + mock_clean_saved_logs(); + ERR_clear_error(); + tls->ssl->rwstate = SSL_READING; + SSL_get_rbio(tls->ssl)->flags = BIO_FLAGS_WRITE; + ret = tor_tls_get_error(tls, -1, 0, "something", LOG_WARN, 0); + tt_int_op(ret, OP_EQ, TOR_TLS_WANTWRITE); + expect_no_log_entry(); + + mock_clean_saved_logs(); + ERR_clear_error(); + tls->ssl->rwstate = 0; + tls->ssl->shutdown = SSL_RECEIVED_SHUTDOWN; + tls->ssl->s3->warn_alert =SSL_AD_CLOSE_NOTIFY; + ret = tor_tls_get_error(tls, 0, 0, "something", LOG_WARN, 0); + tt_int_op(ret, OP_EQ, TOR_TLS_CLOSE); + expect_log_entry(); + + mock_clean_saved_logs(); + ret = tor_tls_get_error(tls, 0, 2, "something", LOG_WARN, 0); + tt_int_op(ret, OP_EQ, -10); + expect_no_log_entry(); + + mock_clean_saved_logs(); + ERR_put_error(ERR_LIB_SYS, 2, -1, "somewhere.c", 99); + ret = tor_tls_get_error(tls, -1, 0, "something", LOG_WARN, 0); + tt_int_op(ret, OP_EQ, -9); + expect_log_msg("TLS error while something: (null) (in system library:" + "connect:before/accept initialization)\n"); + + done: + teardown_capture_of_logs(); + SSL_free(tls->ssl); + tor_free(tls); + SSL_CTX_free(ctx); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +static void +test_tortls_always_accept_verify_cb(void *ignored) +{ + (void)ignored; + int ret; + + ret = always_accept_verify_cb(0, NULL); + tt_int_op(ret, OP_EQ, 1); + + done: + (void)0; +} + +#ifndef OPENSSL_OPAQUE +static void +test_tortls_x509_cert_free(void *ignored) +{ + (void)ignored; + tor_x509_cert_t *cert; + + cert = tor_malloc_zero(sizeof(tor_x509_cert_t)); + tor_x509_cert_free(cert); + + cert = tor_malloc_zero(sizeof(tor_x509_cert_t)); + cert->cert = X509_new(); + cert->encoded = tor_malloc_zero(1); + tor_x509_cert_free(cert); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +#ifndef OPENSSL_OPAQUE +/* + * Use only for the matching fake_x509_free() call + */ +static X509 * +fake_x509_malloc(void) +{ + return tor_malloc_zero(sizeof(X509)); +} + +static void +fake_x509_free(X509 *cert) +{ + if (cert) { + if (cert->cert_info) { + if (cert->cert_info->key) { + if (cert->cert_info->key->pkey) { + tor_free(cert->cert_info->key->pkey); + } + tor_free(cert->cert_info->key); + } + tor_free(cert->cert_info); + } + tor_free(cert); + } +} +#endif + +static tor_x509_cert_t *fixed_x509_cert = NULL; +static tor_x509_cert_t * +get_peer_cert_mock_return_fixed(tor_tls_t *tls) +{ + (void)tls; + if (fixed_x509_cert) + return tor_x509_cert_dup(fixed_x509_cert); + else + return NULL; +} + +static void +test_tortls_cert_matches_key(void *ignored) +{ + (void)ignored; + + X509 *cert1 = NULL, *cert2 = NULL, *cert3 = NULL, *cert4 = NULL; + tor_x509_cert_t *c1 = NULL, *c2 = NULL, *c3 = NULL, *c4 = NULL; + crypto_pk_t *k1 = NULL, *k2 = NULL, *k3 = NULL; + + k1 = pk_generate(1); + k2 = pk_generate(2); + k3 = pk_generate(3); + + cert1 = tor_tls_create_certificate(k1, k2, "A", "B", 1000); + cert2 = tor_tls_create_certificate(k1, k3, "C", "D", 1000); + cert3 = tor_tls_create_certificate(k2, k3, "C", "D", 1000); + cert4 = tor_tls_create_certificate(k3, k2, "E", "F", 1000); + + tt_assert(cert1 && cert2 && cert3 && cert4); + + c1 = tor_x509_cert_new(cert1); cert1 = NULL; + c2 = tor_x509_cert_new(cert2); cert2 = NULL; + c3 = tor_x509_cert_new(cert3); cert3 = NULL; + c4 = tor_x509_cert_new(cert4); cert4 = NULL; + + tt_assert(c1 && c2 && c3 && c4); + + MOCK(tor_tls_get_peer_cert, get_peer_cert_mock_return_fixed); + + fixed_x509_cert = NULL; + /* If the peer has no certificate, it shouldn't match anything. */ + tt_assert(! tor_tls_cert_matches_key(NULL, c1)); + tt_assert(! tor_tls_cert_matches_key(NULL, c2)); + tt_assert(! tor_tls_cert_matches_key(NULL, c3)); + tt_assert(! tor_tls_cert_matches_key(NULL, c4)); + fixed_x509_cert = c1; + /* If the peer has a certificate, it should match every cert with the same + * subject key. */ + tt_assert(tor_tls_cert_matches_key(NULL, c1)); + tt_assert(tor_tls_cert_matches_key(NULL, c2)); + tt_assert(! tor_tls_cert_matches_key(NULL, c3)); + tt_assert(! tor_tls_cert_matches_key(NULL, c4)); + + done: + tor_x509_cert_free(c1); + tor_x509_cert_free(c2); + tor_x509_cert_free(c3); + tor_x509_cert_free(c4); + if (cert1) X509_free(cert1); + if (cert2) X509_free(cert2); + if (cert3) X509_free(cert3); + if (cert4) X509_free(cert4); + crypto_pk_free(k1); + crypto_pk_free(k2); + crypto_pk_free(k3); + UNMOCK(tor_tls_get_peer_cert); +} + +#ifndef OPENSSL_OPAQUE +static void +test_tortls_cert_get_key(void *ignored) +{ + (void)ignored; + tor_x509_cert_t *cert = NULL; + crypto_pk_t *res = NULL; + cert = tor_malloc_zero(sizeof(tor_x509_cert_t)); + X509 *key = NULL; + key = fake_x509_malloc(); + key->references = 1; + + res = tor_tls_cert_get_key(cert); + tt_assert(!res); + + cert->cert = key; + key->cert_info = tor_malloc_zero(sizeof(X509_CINF)); + key->cert_info->key = tor_malloc_zero(sizeof(X509_PUBKEY)); + key->cert_info->key->pkey = tor_malloc_zero(sizeof(EVP_PKEY)); + key->cert_info->key->pkey->references = 1; + key->cert_info->key->pkey->type = 2; + res = tor_tls_cert_get_key(cert); + tt_assert(!res); + + done: + fake_x509_free(key); + tor_free(cert); + crypto_pk_free(res); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +static void +test_tortls_get_my_client_auth_key(void *ignored) +{ + (void)ignored; + crypto_pk_t *ret; + crypto_pk_t *expected; + tor_tls_context_t *ctx; + RSA *k = RSA_new(); + + ctx = tor_malloc_zero(sizeof(tor_tls_context_t)); + expected = crypto_new_pk_from_openssl_rsa_(k); + ctx->auth_key = expected; + + client_tls_context = NULL; + ret = tor_tls_get_my_client_auth_key(); + tt_assert(!ret); + + client_tls_context = ctx; + ret = tor_tls_get_my_client_auth_key(); + tt_assert(ret == expected); + + done: + crypto_pk_free(expected); + tor_free(ctx); +} + +#ifndef HAVE_SSL_GET_CLIENT_CIPHERS +static SSL_CIPHER * +get_cipher_by_name(const char *name) +{ + int i; + const SSL_METHOD *method = SSLv23_method(); + int num = method->num_ciphers(); + + for (i = 0; i < num; ++i) { + const SSL_CIPHER *cipher = method->get_cipher(i); + const char *ciphername = SSL_CIPHER_get_name(cipher); + if (!strcmp(ciphername, name)) { + return (SSL_CIPHER *)cipher; + } + } + + return NULL; +} +#endif /* !defined(HAVE_SSL_GET_CLIENT_CIPHERS) */ + +#ifndef OPENSSL_OPAQUE +static void +test_tortls_get_ciphersuite_name(void *ignored) +{ + (void)ignored; + const char *ret; + tor_tls_t *ctx; + ctx = tor_malloc_zero(sizeof(tor_tls_t)); + ctx->ssl = tor_malloc_zero(sizeof(SSL)); + + ret = tor_tls_get_ciphersuite_name(ctx); + tt_str_op(ret, OP_EQ, "(NONE)"); + + done: + tor_free(ctx->ssl); + tor_free(ctx); +} + +static SSL_CIPHER * +get_cipher_by_id(uint16_t id) +{ + int i; + const SSL_METHOD *method = SSLv23_method(); + int num = method->num_ciphers(); + for (i = 0; i < num; ++i) { + const SSL_CIPHER *cipher = method->get_cipher(i); + if (id == (SSL_CIPHER_get_id(cipher) & 0xffff)) { + return (SSL_CIPHER *)cipher; + } + } + + return NULL; +} + +static void +test_tortls_classify_client_ciphers(void *ignored) +{ + (void)ignored; + int i; + int ret; + SSL_CTX *ctx; + SSL *ssl; + tor_tls_t *tls; + STACK_OF(SSL_CIPHER) *ciphers; + SSL_CIPHER *tmp_cipher; + + library_init(); + + tor_tls_allocate_tor_tls_object_ex_data_index(); + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->magic = TOR_TLS_MAGIC; + + ctx = SSL_CTX_new(TLSv1_method()); + ssl = SSL_new(ctx); + tls->ssl = ssl; + + ciphers = sk_SSL_CIPHER_new_null(); + + ret = tor_tls_classify_client_ciphers(ssl, NULL); + tt_int_op(ret, OP_EQ, -1); + + SSL_set_ex_data(ssl, tor_tls_object_ex_data_index, tls); + tls->client_cipher_list_type = 42; + + ret = tor_tls_classify_client_ciphers(ssl, NULL); + tt_int_op(ret, OP_EQ, 42); + + tls->client_cipher_list_type = 0; + ret = tor_tls_classify_client_ciphers(ssl, ciphers); + tt_int_op(ret, OP_EQ, 1); + tt_int_op(tls->client_cipher_list_type, OP_EQ, 1); + + tls->client_cipher_list_type = 0; + ret = tor_tls_classify_client_ciphers(ssl, SSL_get_ciphers(ssl)); + tt_int_op(ret, OP_EQ, 3); + tt_int_op(tls->client_cipher_list_type, OP_EQ, 3); + + SSL_CIPHER *one = get_cipher_by_name(TLS1_TXT_DHE_RSA_WITH_AES_128_SHA), + *two = get_cipher_by_name(TLS1_TXT_DHE_RSA_WITH_AES_256_SHA), + *three = get_cipher_by_name(SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA), + *four = NULL; + sk_SSL_CIPHER_push(ciphers, one); + sk_SSL_CIPHER_push(ciphers, two); + sk_SSL_CIPHER_push(ciphers, three); + sk_SSL_CIPHER_push(ciphers, four); + + tls->client_cipher_list_type = 0; + ret = tor_tls_classify_client_ciphers(ssl, ciphers); + tt_int_op(ret, OP_EQ, 1); + tt_int_op(tls->client_cipher_list_type, OP_EQ, 1); + + sk_SSL_CIPHER_zero(ciphers); + + one = get_cipher_by_name("ECDHE-RSA-AES256-GCM-SHA384"); + tt_assert(one); + one->id = 0x00ff; + two = get_cipher_by_name("ECDHE-RSA-AES128-GCM-SHA256"); + tt_assert(two); + two->id = 0x0000; + sk_SSL_CIPHER_push(ciphers, one); + tls->client_cipher_list_type = 0; + ret = tor_tls_classify_client_ciphers(ssl, ciphers); + tt_int_op(ret, OP_EQ, 3); + tt_int_op(tls->client_cipher_list_type, OP_EQ, 3); + + sk_SSL_CIPHER_push(ciphers, two); + tls->client_cipher_list_type = 0; + ret = tor_tls_classify_client_ciphers(ssl, ciphers); + tt_int_op(ret, OP_EQ, 3); + tt_int_op(tls->client_cipher_list_type, OP_EQ, 3); + + one->id = 0xC00A; + tls->client_cipher_list_type = 0; + ret = tor_tls_classify_client_ciphers(ssl, ciphers); + tt_int_op(ret, OP_EQ, 3); + tt_int_op(tls->client_cipher_list_type, OP_EQ, 3); + + sk_SSL_CIPHER_zero(ciphers); + for (i=0; v2_cipher_list[i]; i++) { + tmp_cipher = get_cipher_by_id(v2_cipher_list[i]); + tt_assert(tmp_cipher); + sk_SSL_CIPHER_push(ciphers, tmp_cipher); + } + tls->client_cipher_list_type = 0; + ret = tor_tls_classify_client_ciphers(ssl, ciphers); + tt_int_op(ret, OP_EQ, 2); + tt_int_op(tls->client_cipher_list_type, OP_EQ, 2); + + done: + sk_SSL_CIPHER_free(ciphers); + SSL_free(tls->ssl); + tor_free(tls); + SSL_CTX_free(ctx); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +static void +test_tortls_client_is_using_v2_ciphers(void *ignored) +{ + (void)ignored; + +#ifdef HAVE_SSL_GET_CLIENT_CIPHERS + tt_skip(); + done: + (void)1; +#else + int ret; + SSL_CTX *ctx; + SSL *ssl; + SSL_SESSION *sess; + STACK_OF(SSL_CIPHER) *ciphers; + + library_init(); + + ctx = SSL_CTX_new(TLSv1_method()); + ssl = SSL_new(ctx); + sess = SSL_SESSION_new(); + + ret = tor_tls_client_is_using_v2_ciphers(ssl); + tt_int_op(ret, OP_EQ, -1); + + ssl->session = sess; + ret = tor_tls_client_is_using_v2_ciphers(ssl); + tt_int_op(ret, OP_EQ, 0); + + ciphers = sk_SSL_CIPHER_new_null(); + SSL_CIPHER *one = get_cipher_by_name("ECDHE-RSA-AES256-GCM-SHA384"); + tt_assert(one); + one->id = 0x00ff; + sk_SSL_CIPHER_push(ciphers, one); + sess->ciphers = ciphers; + ret = tor_tls_client_is_using_v2_ciphers(ssl); + tt_int_op(ret, OP_EQ, 1); + done: + SSL_free(ssl); + SSL_CTX_free(ctx); +#endif /* defined(HAVE_SSL_GET_CLIENT_CIPHERS) */ +} + +#ifndef OPENSSL_OPAQUE +static int fixed_ssl_pending_result = 0; + +static int +fixed_ssl_pending(const SSL *ignored) +{ + (void)ignored; + return fixed_ssl_pending_result; +} + +static void +test_tortls_get_pending_bytes(void *ignored) +{ + (void)ignored; + int ret; + tor_tls_t *tls; + SSL_METHOD *method; + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->ssl = tor_malloc_zero(sizeof(SSL)); + method = tor_malloc_zero(sizeof(SSL_METHOD)); + method->ssl_pending = fixed_ssl_pending; + tls->ssl->method = method; + + fixed_ssl_pending_result = 42; + ret = tor_tls_get_pending_bytes(tls); + tt_int_op(ret, OP_EQ, 42); + + done: + tor_free(method); + tor_free(tls->ssl); + tor_free(tls); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +#ifndef OPENSSL_OPAQUE +static void +test_tortls_SSL_SESSION_get_master_key(void *ignored) +{ + (void)ignored; + size_t ret; + tor_tls_t *tls; + uint8_t *out; + out = tor_malloc_zero(1); + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->ssl = tor_malloc_zero(sizeof(SSL)); + tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION)); + tls->ssl->session->master_key_length = 1; + +#ifndef HAVE_SSL_SESSION_GET_MASTER_KEY + tls->ssl->session->master_key[0] = 43; + ret = SSL_SESSION_get_master_key(tls->ssl->session, out, 0); + tt_int_op(ret, OP_EQ, 1); + tt_int_op(out[0], OP_EQ, 0); + + ret = SSL_SESSION_get_master_key(tls->ssl->session, out, 1); + tt_int_op(ret, OP_EQ, 1); + tt_int_op(out[0], OP_EQ, 43); + + done: +#endif /* !defined(HAVE_SSL_SESSION_GET_MASTER_KEY) */ + tor_free(tls->ssl->session); + tor_free(tls->ssl); + tor_free(tls); + tor_free(out); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +#ifndef OPENSSL_OPAQUE +static void +test_tortls_get_tlssecrets(void *ignored) +{ + (void)ignored; + int ret; + uint8_t *secret_out = tor_malloc_zero(DIGEST256_LEN); + tor_tls_t *tls; + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->ssl = tor_malloc_zero(sizeof(SSL)); + tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION)); + tls->ssl->session->master_key_length = 1; + tls->ssl->s3 = tor_malloc_zero(sizeof(SSL3_STATE)); + + ret = tor_tls_get_tlssecrets(tls, secret_out); + tt_int_op(ret, OP_EQ, 0); + + done: + tor_free(secret_out); + tor_free(tls->ssl->s3); + tor_free(tls->ssl->session); + tor_free(tls->ssl); + tor_free(tls); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +#ifndef OPENSSL_OPAQUE +static void +test_tortls_get_buffer_sizes(void *ignored) +{ + (void)ignored; + int ret; + tor_tls_t *tls; + size_t rbuf_c=-1, rbuf_b=-1, wbuf_c=-1, wbuf_b=-1; + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->ssl = tor_malloc_zero(sizeof(SSL)); + tls->ssl->s3 = tor_malloc_zero(sizeof(SSL3_STATE)); + + tls->ssl->s3->rbuf.buf = NULL; + tls->ssl->s3->rbuf.len = 1; + tls->ssl->s3->rbuf.offset = 0; + tls->ssl->s3->rbuf.left = 42; + + tls->ssl->s3->wbuf.buf = NULL; + tls->ssl->s3->wbuf.len = 2; + tls->ssl->s3->wbuf.offset = 0; + tls->ssl->s3->wbuf.left = 43; + + ret = tor_tls_get_buffer_sizes(tls, &rbuf_c, &rbuf_b, &wbuf_c, &wbuf_b); +#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) + tt_int_op(ret, OP_EQ, -1); +#else + tt_int_op(ret, OP_EQ, 0); + tt_int_op(rbuf_c, OP_EQ, 0); + tt_int_op(wbuf_c, OP_EQ, 0); + tt_int_op(rbuf_b, OP_EQ, 42); + tt_int_op(wbuf_b, OP_EQ, 43); + + tls->ssl->s3->rbuf.buf = tor_malloc_zero(1); + tls->ssl->s3->wbuf.buf = tor_malloc_zero(1); + ret = tor_tls_get_buffer_sizes(tls, &rbuf_c, &rbuf_b, &wbuf_c, &wbuf_b); + tt_int_op(ret, OP_EQ, 0); + tt_int_op(rbuf_c, OP_EQ, 1); + tt_int_op(wbuf_c, OP_EQ, 2); + +#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) */ + + done: + tor_free(tls->ssl->s3->rbuf.buf); + tor_free(tls->ssl->s3->wbuf.buf); + tor_free(tls->ssl->s3); + tor_free(tls->ssl); + tor_free(tls); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +#ifndef OPENSSL_OPAQUE +typedef struct cert_pkey_st_local +{ + X509 *x509; + EVP_PKEY *privatekey; + const EVP_MD *digest; +} CERT_PKEY_local; + +typedef struct sess_cert_st_local +{ + STACK_OF(X509) *cert_chain; + int peer_cert_type; + CERT_PKEY_local *peer_key; + CERT_PKEY_local peer_pkeys[8]; + int references; +} SESS_CERT_local; + +static void +test_tortls_try_to_extract_certs_from_tls(void *ignored) +{ + (void)ignored; + tor_tls_t *tls; + X509 *cert = NULL, *id_cert = NULL, *c1 = NULL, *c2 = NULL; + SESS_CERT_local *sess = NULL; + + c1 = read_cert_from(validCertString); + c2 = read_cert_from(caCertString); + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->ssl = tor_malloc_zero(sizeof(SSL)); + tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION)); + sess = tor_malloc_zero(sizeof(SESS_CERT_local)); + tls->ssl->session->sess_cert = (void *)sess; + + try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert); + tt_assert(!cert); + tt_assert(!id_cert); + + tls->ssl->session->peer = c1; + try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert); + tt_assert(cert == c1); + tt_assert(!id_cert); + X509_free(cert); /* decrease refcnt */ + + sess->cert_chain = sk_X509_new_null(); + try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert); + tt_assert(cert == c1); + tt_assert(!id_cert); + X509_free(cert); /* decrease refcnt */ + + sk_X509_push(sess->cert_chain, c1); + sk_X509_push(sess->cert_chain, c2); + + try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert); + tt_assert(cert == c1); + tt_assert(id_cert); + X509_free(cert); /* decrease refcnt */ + X509_free(id_cert); /* decrease refcnt */ + + done: + sk_X509_free(sess->cert_chain); + tor_free(sess); + tor_free(tls->ssl->session); + tor_free(tls->ssl); + tor_free(tls); + X509_free(c1); + X509_free(c2); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +#ifndef OPENSSL_OPAQUE +static void +test_tortls_get_peer_cert(void *ignored) +{ + (void)ignored; + tor_x509_cert_t *ret; + tor_tls_t *tls; + X509 *cert = NULL; + + cert = read_cert_from(validCertString); + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->ssl = tor_malloc_zero(sizeof(SSL)); + tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION)); + + ret = tor_tls_get_peer_cert(tls); + tt_assert(!ret); + + tls->ssl->session->peer = cert; + ret = tor_tls_get_peer_cert(tls); + tt_assert(ret); + tt_assert(ret->cert == cert); + + done: + tor_x509_cert_free(ret); + tor_free(tls->ssl->session); + tor_free(tls->ssl); + tor_free(tls); + X509_free(cert); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +#ifndef OPENSSL_OPAQUE +static void +test_tortls_peer_has_cert(void *ignored) +{ + (void)ignored; + int ret; + tor_tls_t *tls; + X509 *cert = NULL; + + cert = read_cert_from(validCertString); + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->ssl = tor_malloc_zero(sizeof(SSL)); + tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION)); + + ret = tor_tls_peer_has_cert(tls); + tt_assert(!ret); + + tls->ssl->session->peer = cert; + ret = tor_tls_peer_has_cert(tls); + tt_assert(ret); + + done: + tor_free(tls->ssl->session); + tor_free(tls->ssl); + tor_free(tls); + X509_free(cert); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +static void +test_tortls_get_write_overhead_ratio(void *ignored) +{ + (void)ignored; + double ret; + + total_bytes_written_over_tls = 0; + ret = tls_get_write_overhead_ratio(); + tt_double_op(fabs(ret - 1.0), OP_LT, 1E-12); + + total_bytes_written_by_tls = 10; + total_bytes_written_over_tls = 1; + ret = tls_get_write_overhead_ratio(); + tt_double_op(fabs(ret - 10.0), OP_LT, 1E-12); + + total_bytes_written_by_tls = 10; + total_bytes_written_over_tls = 2; + ret = tls_get_write_overhead_ratio(); + tt_double_op(fabs(ret - 5.0), OP_LT, 1E-12); + + done: + (void)0; +} + +static void +test_tortls_is_server(void *ignored) +{ + (void)ignored; + tor_tls_t *tls; + int ret; + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->isServer = 1; + ret = tor_tls_is_server(tls); + tt_int_op(ret, OP_EQ, 1); + + done: + tor_free(tls); +} + +#ifndef OPENSSL_OPAQUE +static void +test_tortls_session_secret_cb(void *ignored) +{ + (void)ignored; + tor_tls_t *tls; + SSL_CTX *ctx; + STACK_OF(SSL_CIPHER) *ciphers = NULL; + SSL_CIPHER *one; + + library_init(); + + tor_tls_allocate_tor_tls_object_ex_data_index(); + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + + tls->magic = TOR_TLS_MAGIC; + + ctx = SSL_CTX_new(TLSv1_method()); + tls->ssl = SSL_new(ctx); + SSL_set_ex_data(tls->ssl, tor_tls_object_ex_data_index, tls); + + SSL_set_session_secret_cb(tls->ssl, tor_tls_session_secret_cb, NULL); + + tor_tls_session_secret_cb(tls->ssl, NULL, NULL, NULL, NULL, NULL); + tt_assert(!tls->ssl->tls_session_secret_cb); + + one = get_cipher_by_name("ECDHE-RSA-AES256-GCM-SHA384"); + one->id = 0x00ff; + ciphers = sk_SSL_CIPHER_new_null(); + sk_SSL_CIPHER_push(ciphers, one); + + tls->client_cipher_list_type = 0; + tor_tls_session_secret_cb(tls->ssl, NULL, NULL, ciphers, NULL, NULL); + tt_assert(!tls->ssl->tls_session_secret_cb); + + done: + sk_SSL_CIPHER_free(ciphers); + SSL_free(tls->ssl); + SSL_CTX_free(ctx); + tor_free(tls); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +#ifndef OPENSSL_OPAQUE +/* TODO: It seems block_renegotiation and unblock_renegotiation and + * using different blags. This might not be correct */ +static void +test_tortls_block_renegotiation(void *ignored) +{ + (void)ignored; + tor_tls_t *tls; + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->ssl = tor_malloc_zero(sizeof(SSL)); + tls->ssl->s3 = tor_malloc_zero(sizeof(SSL3_STATE)); +#ifndef SUPPORT_UNSAFE_RENEGOTIATION_FLAG +#define SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0 +#endif + + tls->ssl->s3->flags = SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; + + tor_tls_block_renegotiation(tls); + +#ifndef OPENSSL_1_1_API + tt_assert(!(tls->ssl->s3->flags & + SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)); +#endif + + done: + tor_free(tls->ssl->s3); + tor_free(tls->ssl); + tor_free(tls); +} + +static void +test_tortls_unblock_renegotiation(void *ignored) +{ + (void)ignored; + tor_tls_t *tls; + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->ssl = tor_malloc_zero(sizeof(SSL)); + tor_tls_unblock_renegotiation(tls); + + tt_uint_op(SSL_get_options(tls->ssl) & + SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION, OP_EQ, + SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); + + done: + tor_free(tls->ssl); + tor_free(tls); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +#ifndef OPENSSL_OPAQUE +static void +test_tortls_assert_renegotiation_unblocked(void *ignored) +{ + (void)ignored; + tor_tls_t *tls; + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->ssl = tor_malloc_zero(sizeof(SSL)); + tor_tls_unblock_renegotiation(tls); + tor_tls_assert_renegotiation_unblocked(tls); + /* No assertion here - this test will fail if tor_assert is turned on + * and things are bad. */ + + tor_free(tls->ssl); + tor_free(tls); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +static void +test_tortls_set_logged_address(void *ignored) +{ + (void)ignored; + tor_tls_t *tls; + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + + tor_tls_set_logged_address(tls, "foo bar"); + + tt_str_op(tls->address, OP_EQ, "foo bar"); + + tor_tls_set_logged_address(tls, "foo bar 2"); + tt_str_op(tls->address, OP_EQ, "foo bar 2"); + + done: + tor_free(tls->address); + tor_free(tls); +} + +#ifndef OPENSSL_OPAQUE +static void +example_cb(tor_tls_t *t, void *arg) +{ + (void)t; + (void)arg; +} + +static void +test_tortls_set_renegotiate_callback(void *ignored) +{ + (void)ignored; + tor_tls_t *tls; + const char *arg = "hello"; + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->ssl = tor_malloc_zero(sizeof(SSL)); + + tor_tls_set_renegotiate_callback(tls, example_cb, (void*)arg); + tt_assert(tls->negotiated_callback == example_cb); + tt_assert(tls->callback_arg == arg); + tt_assert(!tls->got_renegotiate); + + /* Assumes V2_HANDSHAKE_SERVER */ + tt_assert(tls->ssl->info_callback == tor_tls_server_info_callback); + + tor_tls_set_renegotiate_callback(tls, NULL, (void*)arg); + tt_assert(tls->ssl->info_callback == tor_tls_debug_state_callback); + + done: + tor_free(tls->ssl); + tor_free(tls); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +#ifndef OPENSSL_OPAQUE +static SSL_CIPHER *fixed_cipher1 = NULL; +static SSL_CIPHER *fixed_cipher2 = NULL; +static const SSL_CIPHER * +fake_get_cipher(unsigned ncipher) +{ + + switch (ncipher) { + case 1: + return fixed_cipher1; + case 2: + return fixed_cipher2; + default: + return NULL; + } +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +#ifndef OPENSSL_OPAQUE +static void +test_tortls_find_cipher_by_id(void *ignored) +{ + (void)ignored; + int ret; + SSL *ssl; + SSL_CTX *ctx; + const SSL_METHOD *m = TLSv1_method(); + SSL_METHOD *empty_method = tor_malloc_zero(sizeof(SSL_METHOD)); + + fixed_cipher1 = tor_malloc_zero(sizeof(SSL_CIPHER)); + fixed_cipher2 = tor_malloc_zero(sizeof(SSL_CIPHER)); + fixed_cipher2->id = 0xC00A; + + library_init(); + + ctx = SSL_CTX_new(m); + ssl = SSL_new(ctx); + + ret = find_cipher_by_id(ssl, NULL, 0xC00A); + tt_int_op(ret, OP_EQ, 1); + + ret = find_cipher_by_id(ssl, m, 0xC00A); + tt_int_op(ret, OP_EQ, 1); + + ret = find_cipher_by_id(ssl, m, 0xFFFF); + tt_int_op(ret, OP_EQ, 0); + + ret = find_cipher_by_id(ssl, empty_method, 0xC00A); + tt_int_op(ret, OP_EQ, 1); + + ret = find_cipher_by_id(ssl, empty_method, 0xFFFF); +#ifdef HAVE_SSL_CIPHER_FIND + tt_int_op(ret, OP_EQ, 0); +#else + tt_int_op(ret, OP_EQ, 1); +#endif + + empty_method->get_cipher = fake_get_cipher; + ret = find_cipher_by_id(ssl, empty_method, 0xC00A); + tt_int_op(ret, OP_EQ, 1); + + empty_method->get_cipher = m->get_cipher; + empty_method->num_ciphers = m->num_ciphers; + ret = find_cipher_by_id(ssl, empty_method, 0xC00A); + tt_int_op(ret, OP_EQ, 1); + + empty_method->get_cipher = fake_get_cipher; + empty_method->num_ciphers = m->num_ciphers; + ret = find_cipher_by_id(ssl, empty_method, 0xC00A); + tt_int_op(ret, OP_EQ, 1); + + empty_method->num_ciphers = fake_num_ciphers; + ret = find_cipher_by_id(ssl, empty_method, 0xC00A); +#ifdef HAVE_SSL_CIPHER_FIND + tt_int_op(ret, OP_EQ, 1); +#else + tt_int_op(ret, OP_EQ, 0); +#endif + + done: + tor_free(empty_method); + SSL_free(ssl); + SSL_CTX_free(ctx); + tor_free(fixed_cipher1); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +#ifndef OPENSSL_OPAQUE +static void +test_tortls_debug_state_callback(void *ignored) +{ + (void)ignored; + SSL *ssl; + char *buf = tor_malloc_zero(1000); + int n; + + setup_capture_of_logs(LOG_DEBUG); + + ssl = tor_malloc_zero(sizeof(SSL)); + + tor_tls_debug_state_callback(ssl, 32, 45); + + n = tor_snprintf(buf, 1000, "SSL %p is now in state unknown" + " state [type=32,val=45].\n", ssl); + /* tor's snprintf returns -1 on error */ + tt_int_op(n, OP_NE, -1); + expect_log_msg(buf); + + done: + teardown_capture_of_logs(); + tor_free(buf); + tor_free(ssl); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +#ifndef OPENSSL_OPAQUE +static void +test_tortls_server_info_callback(void *ignored) +{ + (void)ignored; + tor_tls_t *tls; + SSL_CTX *ctx; + SSL *ssl; + + library_init(); + + ctx = SSL_CTX_new(TLSv1_method()); + ssl = SSL_new(ctx); + + tor_tls_allocate_tor_tls_object_ex_data_index(); + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->magic = TOR_TLS_MAGIC; + tls->ssl = ssl; + + setup_full_capture_of_logs(LOG_WARN); + SSL_set_state(ssl, SSL3_ST_SW_SRVR_HELLO_A); + mock_clean_saved_logs(); + tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0); + expect_single_log_msg("Couldn't look up the tls for an SSL*. How odd!\n"); + + SSL_set_state(ssl, SSL3_ST_SW_SRVR_HELLO_B); + mock_clean_saved_logs(); + tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0); + expect_single_log_msg("Couldn't look up the tls for an SSL*. How odd!\n"); + + SSL_set_state(ssl, 99); + mock_clean_saved_logs(); + tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0); + expect_no_log_entry(); + teardown_capture_of_logs(); + + SSL_set_ex_data(tls->ssl, tor_tls_object_ex_data_index, tls); + SSL_set_state(ssl, SSL3_ST_SW_SRVR_HELLO_B); + tls->negotiated_callback = 0; + //tls->server_handshake_count = 120; + tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0); + //tt_int_op(tls->server_handshake_count, OP_EQ, 121); + + //tls->server_handshake_count = 127; + tls->negotiated_callback = (void *)1; + tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0); + //tt_int_op(tls->server_handshake_count, OP_EQ, 127); + tt_int_op(tls->got_renegotiate, OP_EQ, 1); + + tls->ssl->session = SSL_SESSION_new(); + tls->wasV2Handshake = 0; + tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0); + tt_int_op(tls->wasV2Handshake, OP_EQ, 0); + + done: + teardown_capture_of_logs(); + SSL_free(ssl); + SSL_CTX_free(ctx); + tor_free(tls); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +#ifndef OPENSSL_OPAQUE +static int fixed_ssl_read_result_index; +static int fixed_ssl_read_result[5]; + +static int +fixed_ssl_read(SSL *s, void *buf, int len) +{ + (void)s; + (void)buf; + (void)len; + return fixed_ssl_read_result[fixed_ssl_read_result_index++]; +} + +static int +dummy_handshake_func(SSL *s) +{ + (void)s; + return 1; +} + +static int negotiated_callback_called; + +static void +negotiated_callback_setter(tor_tls_t *t, void *arg) +{ + (void)t; + (void)arg; + negotiated_callback_called++; +} + +static void +test_tortls_read(void *ignored) +{ + (void)ignored; + int ret; + tor_tls_t *tls; + char buf[100]; + SSL_METHOD *method = give_me_a_test_method(); + setup_capture_of_logs(LOG_WARN); + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->ssl = tor_malloc_zero(sizeof(SSL)); + tls->state = TOR_TLS_ST_OPEN; + + ret = tor_tls_read(tls, buf, 10); + tt_int_op(ret, OP_EQ, -9); + + /* These tests assume that V2_HANDSHAKE_SERVER is set */ + tls->ssl->handshake_func = dummy_handshake_func; + tls->ssl->method = method; + method->ssl_read = fixed_ssl_read; + fixed_ssl_read_result_index = 0; + fixed_ssl_read_result[0] = 42; + tls->state = TOR_TLS_ST_OPEN; + ERR_clear_error(); + ret = tor_tls_read(tls, buf, 10); + tt_int_op(ret, OP_EQ, 42); + + tls->state = TOR_TLS_ST_OPEN; + tls->got_renegotiate = 1; + fixed_ssl_read_result_index = 0; + ERR_clear_error(); + ret = tor_tls_read(tls, buf, 10); + tt_int_op(tls->got_renegotiate, OP_EQ, 0); + + tls->state = TOR_TLS_ST_OPEN; + tls->got_renegotiate = 1; + negotiated_callback_called = 0; + tls->negotiated_callback = negotiated_callback_setter; + fixed_ssl_read_result_index = 0; + ERR_clear_error(); + ret = tor_tls_read(tls, buf, 10); + tt_int_op(negotiated_callback_called, OP_EQ, 1); + +#ifndef LIBRESSL_VERSION_NUMBER + fixed_ssl_read_result_index = 0; + fixed_ssl_read_result[0] = 0; + tls->ssl->version = SSL2_VERSION; + ERR_clear_error(); + ret = tor_tls_read(tls, buf, 10); + tt_int_op(ret, OP_EQ, TOR_TLS_CLOSE); + tt_int_op(tls->state, OP_EQ, TOR_TLS_ST_CLOSED); +#endif /* !defined(LIBRESSL_VERSION_NUMBER) */ + // TODO: fill up + + done: + teardown_capture_of_logs(); + tor_free(tls->ssl); + tor_free(tls); + tor_free(method); +} + +static int fixed_ssl_write_result; + +static int +fixed_ssl_write(SSL *s, const void *buf, int len) +{ + (void)s; + (void)buf; + (void)len; + return fixed_ssl_write_result; +} + +static void +test_tortls_write(void *ignored) +{ + (void)ignored; + int ret; + tor_tls_t *tls; + SSL_METHOD *method = give_me_a_test_method(); + char buf[100]; + setup_capture_of_logs(LOG_WARN); + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->ssl = tor_malloc_zero(sizeof(SSL)); + tls->state = TOR_TLS_ST_OPEN; + + ret = tor_tls_write(tls, buf, 0); + tt_int_op(ret, OP_EQ, 0); + + ret = tor_tls_write(tls, buf, 10); + tt_int_op(ret, OP_EQ, -9); + + tls->ssl->method = method; + tls->wantwrite_n = 1; + ret = tor_tls_write(tls, buf, 10); + tt_int_op(tls->wantwrite_n, OP_EQ, 0); + + method->ssl_write = fixed_ssl_write; + tls->ssl->handshake_func = dummy_handshake_func; + fixed_ssl_write_result = 1; + ERR_clear_error(); + ret = tor_tls_write(tls, buf, 10); + tt_int_op(ret, OP_EQ, 1); + + fixed_ssl_write_result = -1; + ERR_clear_error(); + tls->ssl->rwstate = SSL_READING; + SSL_set_bio(tls->ssl, BIO_new(BIO_s_mem()), NULL); + SSL_get_rbio(tls->ssl)->flags = BIO_FLAGS_READ; + ret = tor_tls_write(tls, buf, 10); + tt_int_op(ret, OP_EQ, TOR_TLS_WANTREAD); + + ERR_clear_error(); + tls->ssl->rwstate = SSL_READING; + SSL_set_bio(tls->ssl, BIO_new(BIO_s_mem()), NULL); + SSL_get_rbio(tls->ssl)->flags = BIO_FLAGS_WRITE; + ret = tor_tls_write(tls, buf, 10); + tt_int_op(ret, OP_EQ, TOR_TLS_WANTWRITE); + + done: + teardown_capture_of_logs(); + BIO_free(tls->ssl->rbio); + tor_free(tls->ssl); + tor_free(tls); + tor_free(method); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +#ifndef OPENSSL_OPAQUE +static int fixed_ssl_accept_result; +static int fixed_ssl_connect_result; + +static int +setting_error_ssl_accept(SSL *ssl) +{ + (void)ssl; + ERR_put_error(ERR_LIB_BN, 2, -1, "somewhere.c", 99); + ERR_put_error(ERR_LIB_SYS, 2, -1, "somewhere.c", 99); + return fixed_ssl_accept_result; +} + +static int +setting_error_ssl_connect(SSL *ssl) +{ + (void)ssl; + ERR_put_error(ERR_LIB_BN, 2, -1, "somewhere.c", 99); + ERR_put_error(ERR_LIB_SYS, 2, -1, "somewhere.c", 99); + return fixed_ssl_connect_result; +} + +static int +fixed_ssl_accept(SSL *ssl) +{ + (void) ssl; + return fixed_ssl_accept_result; +} + +static void +test_tortls_handshake(void *ignored) +{ + (void)ignored; + int ret; + tor_tls_t *tls; + SSL_CTX *ctx; + SSL_METHOD *method = give_me_a_test_method(); + setup_capture_of_logs(LOG_INFO); + + SSL_library_init(); + SSL_load_error_strings(); + + ctx = SSL_CTX_new(TLSv1_method()); + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->ssl = SSL_new(ctx); + tls->state = TOR_TLS_ST_HANDSHAKE; + + ret = tor_tls_handshake(tls); + tt_int_op(ret, OP_EQ, -9); + + tls->isServer = 1; + tls->state = TOR_TLS_ST_HANDSHAKE; + ret = tor_tls_handshake(tls); + tt_int_op(ret, OP_EQ, -9); + + tls->ssl->method = method; + method->ssl_accept = fixed_ssl_accept; + fixed_ssl_accept_result = 2; + ERR_clear_error(); + tls->state = TOR_TLS_ST_HANDSHAKE; + ret = tor_tls_handshake(tls); + tt_int_op(tls->state, OP_EQ, TOR_TLS_ST_OPEN); + + method->ssl_accept = setting_error_ssl_accept; + fixed_ssl_accept_result = 1; + ERR_clear_error(); + mock_clean_saved_logs(); + tls->state = TOR_TLS_ST_HANDSHAKE; + ret = tor_tls_handshake(tls); + tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_MISC); + expect_log_entry(); + /* This fails on jessie. Investigate why! */ +#if 0 + expect_log_msg("TLS error while handshaking: (null) (in bignum routines:" + "(null):SSLv3 write client hello B)\n"); + expect_log_msg("TLS error while handshaking: (null) (in system library:" + "connect:SSLv3 write client hello B)\n"); +#endif /* 0 */ + expect_log_severity(LOG_INFO); + + tls->isServer = 0; + method->ssl_connect = setting_error_ssl_connect; + fixed_ssl_connect_result = 1; + ERR_clear_error(); + mock_clean_saved_logs(); + tls->state = TOR_TLS_ST_HANDSHAKE; + ret = tor_tls_handshake(tls); + tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_MISC); + expect_log_entry(); +#if 0 + /* See above */ + expect_log_msg("TLS error while handshaking: " + "(null) (in bignum routines:(null):SSLv3 write client hello B)\n"); + expect_log_msg("TLS error while handshaking: " + "(null) (in system library:connect:SSLv3 write client hello B)\n"); +#endif /* 0 */ + expect_log_severity(LOG_WARN); + + done: + teardown_capture_of_logs(); + SSL_free(tls->ssl); + SSL_CTX_free(ctx); + tor_free(tls); + tor_free(method); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +#ifndef OPENSSL_OPAQUE +static void +test_tortls_finish_handshake(void *ignored) +{ + (void)ignored; + int ret; + tor_tls_t *tls; + SSL_CTX *ctx; + SSL_METHOD *method = give_me_a_test_method(); + SSL_library_init(); + SSL_load_error_strings(); + + X509 *c1 = read_cert_from(validCertString); + SESS_CERT_local *sess = NULL; + + ctx = SSL_CTX_new(method); + + tls = tor_malloc_zero(sizeof(tor_tls_t)); + tls->ssl = SSL_new(ctx); + tls->state = TOR_TLS_ST_OPEN; + + ret = tor_tls_finish_handshake(tls); + tt_int_op(ret, OP_EQ, 0); + + tls->isServer = 1; + tls->wasV2Handshake = 0; + setup_full_capture_of_logs(LOG_WARN); + ret = tor_tls_finish_handshake(tls); + tt_int_op(ret, OP_EQ, 0); + tt_int_op(tls->wasV2Handshake, OP_EQ, 1); + expect_single_log_msg_containing("For some reason, wasV2Handshake didn't " + "get set."); + teardown_capture_of_logs(); + + tls->wasV2Handshake = 1; + ret = tor_tls_finish_handshake(tls); + tt_int_op(ret, OP_EQ, 0); + tt_int_op(tls->wasV2Handshake, OP_EQ, 1); + + tls->wasV2Handshake = 1; + tls->ssl->session = SSL_SESSION_new(); + ret = tor_tls_finish_handshake(tls); + tt_int_op(ret, OP_EQ, 0); + tt_int_op(tls->wasV2Handshake, OP_EQ, 0); + + tls->isServer = 0; + + sess = tor_malloc_zero(sizeof(SESS_CERT_local)); + tls->ssl->session->sess_cert = (void *)sess; + sess->cert_chain = sk_X509_new_null(); + sk_X509_push(sess->cert_chain, c1); + tls->ssl->session->peer = c1; + tls->wasV2Handshake = 0; + ret = tor_tls_finish_handshake(tls); + tt_int_op(ret, OP_EQ, 0); + tt_int_op(tls->wasV2Handshake, OP_EQ, 1); + + method->num_ciphers = fake_num_ciphers; + ret = tor_tls_finish_handshake(tls); + tt_int_op(ret, OP_EQ, -9); + + done: + if (sess) + sk_X509_free(sess->cert_chain); + if (tls->ssl && tls->ssl->session) { + tor_free(tls->ssl->session->sess_cert); + } + SSL_free(tls->ssl); + tor_free(tls); + SSL_CTX_free(ctx); + tor_free(method); + teardown_capture_of_logs(); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +static int fixed_crypto_pk_new_result_index; +static crypto_pk_t *fixed_crypto_pk_new_result[5]; + +static crypto_pk_t * +fixed_crypto_pk_new(void) +{ + return fixed_crypto_pk_new_result[fixed_crypto_pk_new_result_index++]; +} + +#ifndef OPENSSL_OPAQUE +static int fixed_crypto_pk_generate_key_with_bits_result_index; +static int fixed_crypto_pk_generate_key_with_bits_result[5]; +static int fixed_tor_tls_create_certificate_result_index; +static X509 *fixed_tor_tls_create_certificate_result[5]; +static int fixed_tor_x509_cert_new_result_index; +static tor_x509_cert_t *fixed_tor_x509_cert_new_result[5]; + +static int +fixed_crypto_pk_generate_key_with_bits(crypto_pk_t *env, int bits) +{ + (void)env; + (void)bits; + return fixed_crypto_pk_generate_key_with_bits_result[ + fixed_crypto_pk_generate_key_with_bits_result_index++]; +} + +static X509 * +fixed_tor_tls_create_certificate(crypto_pk_t *rsa, + crypto_pk_t *rsa_sign, + const char *cname, + const char *cname_sign, + unsigned int cert_lifetime) +{ + (void)rsa; + (void)rsa_sign; + (void)cname; + (void)cname_sign; + (void)cert_lifetime; + X509 *result = fixed_tor_tls_create_certificate_result[ + fixed_tor_tls_create_certificate_result_index++]; + if (result) + return X509_dup(result); + else + return NULL; +} + +static void +fixed_tor_tls_create_certificate_results_free(void) +{ + unsigned i; + for (i = 0; i < ARRAY_LENGTH(fixed_tor_tls_create_certificate_result); ++i) { + X509 *cert = fixed_tor_tls_create_certificate_result[i]; + if (cert) + X509_free(cert); + fixed_tor_tls_create_certificate_result[i] = NULL; + } +} + +static void +fixed_tor_x509_cert_new_results_free(void) +{ + unsigned i; + for (i = 0; i < ARRAY_LENGTH(fixed_tor_x509_cert_new_result); ++i) { + tor_x509_cert_free(fixed_tor_x509_cert_new_result[i]); + } +} + +static tor_x509_cert_t * +fixed_tor_x509_cert_new(tor_x509_cert_impl_t *x509_cert) +{ + (void) x509_cert; + tor_x509_cert_t **certp = + &fixed_tor_x509_cert_new_result[fixed_tor_x509_cert_new_result_index++]; + tor_x509_cert_t *cert = *certp; + *certp = NULL; + return cert; +} + +static void +test_tortls_context_new(void *ignored) +{ + (void)ignored; + tor_tls_context_t *ret; + crypto_pk_t *pk1, *pk2, *pk3, *pk4, *pk5, *pk6, *pk7, *pk8, *pk9, *pk10, + *pk11, *pk12, *pk13, *pk14, *pk15, *pk16, *pk17, *pk18; + + pk1 = crypto_pk_new(); + pk2 = crypto_pk_new(); + pk3 = crypto_pk_new(); + pk4 = crypto_pk_new(); + pk5 = crypto_pk_new(); + pk6 = crypto_pk_new(); + pk7 = crypto_pk_new(); + pk8 = crypto_pk_new(); + pk9 = crypto_pk_new(); + pk10 = crypto_pk_new(); + pk11 = crypto_pk_new(); + pk12 = crypto_pk_new(); + pk13 = crypto_pk_new(); + pk14 = crypto_pk_new(); + pk15 = crypto_pk_new(); + pk16 = crypto_pk_new(); + pk17 = crypto_pk_new(); + pk18 = crypto_pk_new(); + + fixed_crypto_pk_new_result_index = 0; + fixed_crypto_pk_new_result[0] = NULL; + MOCK(crypto_pk_new, fixed_crypto_pk_new); + ret = tor_tls_context_new(NULL, 0, 0, 0); + tt_assert(!ret); + + /* note: we already override this in testing_common.c, so we + * run this unit test in a subprocess. */ + MOCK(crypto_pk_generate_key_with_bits, + fixed_crypto_pk_generate_key_with_bits); + fixed_crypto_pk_new_result_index = 0; + fixed_crypto_pk_new_result[0] = pk1; + fixed_crypto_pk_new_result[1] = NULL; + fixed_crypto_pk_generate_key_with_bits_result[0] = -1; + fixed_crypto_pk_generate_key_with_bits_result_index = 0; + ret = tor_tls_context_new(NULL, 0, 0, 0); + tt_assert(!ret); + + fixed_crypto_pk_new_result_index = 0; + fixed_crypto_pk_new_result[0] = pk2; + fixed_crypto_pk_new_result[1] = NULL; + fixed_crypto_pk_generate_key_with_bits_result[0] = 0; + fixed_crypto_pk_generate_key_with_bits_result_index = 0; + ret = tor_tls_context_new(NULL, 0, 0, 0); + tt_assert(!ret); + + fixed_crypto_pk_new_result_index = 0; + fixed_crypto_pk_new_result[0] = pk3; + fixed_crypto_pk_new_result[1] = pk4; + fixed_crypto_pk_new_result[2] = NULL; + fixed_crypto_pk_generate_key_with_bits_result[0] = 0; + fixed_crypto_pk_generate_key_with_bits_result[1] = -1; + fixed_crypto_pk_generate_key_with_bits_result_index = 0; + ret = tor_tls_context_new(NULL, 0, 0, 0); + tt_assert(!ret); + + MOCK(tor_tls_create_certificate, fixed_tor_tls_create_certificate); + + fixed_crypto_pk_new_result_index = 0; + fixed_crypto_pk_new_result[0] = pk5; + fixed_crypto_pk_new_result[1] = pk6; + fixed_crypto_pk_new_result[2] = NULL; + fixed_crypto_pk_generate_key_with_bits_result_index = 0; + fixed_crypto_pk_generate_key_with_bits_result[1] = 0; + fixed_tor_tls_create_certificate_result_index = 0; + fixed_tor_tls_create_certificate_result[0] = NULL; + fixed_tor_tls_create_certificate_result[1] = X509_new(); + fixed_tor_tls_create_certificate_result[2] = X509_new(); + ret = tor_tls_context_new(NULL, 0, 0, 0); + tt_assert(!ret); + fixed_tor_tls_create_certificate_results_free(); + + fixed_crypto_pk_new_result_index = 0; + fixed_crypto_pk_new_result[0] = pk7; + fixed_crypto_pk_new_result[1] = pk8; + fixed_crypto_pk_new_result[2] = NULL; + fixed_crypto_pk_generate_key_with_bits_result_index = 0; + fixed_tor_tls_create_certificate_result_index = 0; + fixed_tor_tls_create_certificate_result[0] = X509_new(); + fixed_tor_tls_create_certificate_result[1] = NULL; + fixed_tor_tls_create_certificate_result[2] = X509_new(); + ret = tor_tls_context_new(NULL, 0, 0, 0); + tt_assert(!ret); + fixed_tor_tls_create_certificate_results_free(); + + fixed_crypto_pk_new_result_index = 0; + fixed_crypto_pk_new_result[0] = pk9; + fixed_crypto_pk_new_result[1] = pk10; + fixed_crypto_pk_new_result[2] = NULL; + fixed_crypto_pk_generate_key_with_bits_result_index = 0; + fixed_tor_tls_create_certificate_result_index = 0; + fixed_tor_tls_create_certificate_result[0] = X509_new(); + fixed_tor_tls_create_certificate_result[1] = X509_new(); + fixed_tor_tls_create_certificate_result[2] = NULL; + ret = tor_tls_context_new(NULL, 0, 0, 0); + tt_assert(!ret); + fixed_tor_tls_create_certificate_results_free(); + + MOCK(tor_x509_cert_new, fixed_tor_x509_cert_new); + fixed_crypto_pk_new_result_index = 0; + fixed_crypto_pk_new_result[0] = pk11; + fixed_crypto_pk_new_result[1] = pk12; + fixed_crypto_pk_new_result[2] = NULL; + fixed_crypto_pk_generate_key_with_bits_result_index = 0; + fixed_tor_tls_create_certificate_result_index = 0; + fixed_tor_tls_create_certificate_result[0] = X509_new(); + fixed_tor_tls_create_certificate_result[1] = X509_new(); + fixed_tor_tls_create_certificate_result[2] = X509_new(); + fixed_tor_x509_cert_new_result_index = 0; + fixed_tor_x509_cert_new_result[0] = NULL; + fixed_tor_x509_cert_new_result[1] = NULL; + fixed_tor_x509_cert_new_result[2] = NULL; + ret = tor_tls_context_new(NULL, 0, 0, 0); + tt_assert(!ret); + fixed_tor_tls_create_certificate_results_free(); + + fixed_crypto_pk_new_result_index = 0; + fixed_crypto_pk_new_result[0] = pk13; + fixed_crypto_pk_new_result[1] = pk14; + fixed_crypto_pk_new_result[2] = NULL; + fixed_crypto_pk_generate_key_with_bits_result_index = 0; + fixed_tor_tls_create_certificate_result_index = 0; + fixed_tor_tls_create_certificate_result[0] = X509_new(); + fixed_tor_tls_create_certificate_result[1] = X509_new(); + fixed_tor_tls_create_certificate_result[2] = X509_new(); + fixed_tor_x509_cert_new_result_index = 0; + fixed_tor_x509_cert_new_result[0] = tor_malloc_zero(sizeof(tor_x509_cert_t)); + fixed_tor_x509_cert_new_result[1] = NULL; + fixed_tor_x509_cert_new_result[2] = NULL; + ret = tor_tls_context_new(NULL, 0, 0, 0); + tt_assert(!ret); + fixed_tor_tls_create_certificate_results_free(); + fixed_tor_x509_cert_new_results_free(); + + fixed_crypto_pk_new_result_index = 0; + fixed_crypto_pk_new_result[0] = pk15; + fixed_crypto_pk_new_result[1] = pk16; + fixed_crypto_pk_new_result[2] = NULL; + fixed_crypto_pk_generate_key_with_bits_result_index = 0; + fixed_tor_tls_create_certificate_result_index = 0; + fixed_tor_tls_create_certificate_result[0] = X509_new(); + fixed_tor_tls_create_certificate_result[1] = X509_new(); + fixed_tor_tls_create_certificate_result[2] = X509_new(); + fixed_tor_x509_cert_new_result_index = 0; + fixed_tor_x509_cert_new_result[0] = tor_malloc_zero(sizeof(tor_x509_cert_t)); + fixed_tor_x509_cert_new_result[1] = tor_malloc_zero(sizeof(tor_x509_cert_t)); + fixed_tor_x509_cert_new_result[2] = NULL; + ret = tor_tls_context_new(NULL, 0, 0, 0); + tt_assert(!ret); + fixed_tor_tls_create_certificate_results_free(); + fixed_tor_x509_cert_new_results_free(); + + fixed_crypto_pk_new_result_index = 0; + fixed_crypto_pk_new_result[0] = pk17; + fixed_crypto_pk_new_result[1] = pk18; + fixed_crypto_pk_new_result[2] = NULL; + fixed_crypto_pk_generate_key_with_bits_result_index = 0; + fixed_tor_tls_create_certificate_result_index = 0; + fixed_tor_tls_create_certificate_result[0] = X509_new(); + fixed_tor_tls_create_certificate_result[1] = X509_new(); + fixed_tor_tls_create_certificate_result[2] = X509_new(); + fixed_tor_x509_cert_new_result_index = 0; + fixed_tor_x509_cert_new_result[0] = tor_malloc_zero(sizeof(tor_x509_cert_t)); + fixed_tor_x509_cert_new_result[1] = tor_malloc_zero(sizeof(tor_x509_cert_t)); + fixed_tor_x509_cert_new_result[2] = tor_malloc_zero(sizeof(tor_x509_cert_t)); + ret = tor_tls_context_new(NULL, 0, 0, 0); + tt_assert(!ret); + + done: + fixed_tor_tls_create_certificate_results_free(); + fixed_tor_x509_cert_new_results_free(); + UNMOCK(tor_x509_cert_new); + UNMOCK(tor_tls_create_certificate); + UNMOCK(crypto_pk_generate_key_with_bits); + UNMOCK(crypto_pk_new); +} +#endif /* !defined(OPENSSL_OPAQUE) */ + +static int fixed_crypto_pk_get_evp_pkey_result_index = 0; +static EVP_PKEY *fixed_crypto_pk_get_evp_pkey_result[5]; + +static EVP_PKEY * +fixed_crypto_pk_get_evp_pkey_(crypto_pk_t *env, int private) +{ + (void) env; + (void) private; + return fixed_crypto_pk_get_evp_pkey_result[ + fixed_crypto_pk_get_evp_pkey_result_index++]; +} + +static void +test_tortls_create_certificate(void *ignored) +{ + (void)ignored; + X509 *ret; + crypto_pk_t *pk1, *pk2; + + pk1 = crypto_pk_new(); + pk2 = crypto_pk_new(); + + MOCK(crypto_pk_get_openssl_evp_pkey_, fixed_crypto_pk_get_evp_pkey_); + fixed_crypto_pk_get_evp_pkey_result_index = 0; + fixed_crypto_pk_get_evp_pkey_result[0] = NULL; + ret = tor_tls_create_certificate(pk1, pk2, "hello", "hello2", 1); + tt_assert(!ret); + + fixed_crypto_pk_get_evp_pkey_result_index = 0; + fixed_crypto_pk_get_evp_pkey_result[0] = EVP_PKEY_new(); + fixed_crypto_pk_get_evp_pkey_result[1] = NULL; + ret = tor_tls_create_certificate(pk1, pk2, "hello", "hello2", 1); + tt_assert(!ret); + + fixed_crypto_pk_get_evp_pkey_result_index = 0; + fixed_crypto_pk_get_evp_pkey_result[0] = EVP_PKEY_new(); + fixed_crypto_pk_get_evp_pkey_result[1] = EVP_PKEY_new(); + ret = tor_tls_create_certificate(pk1, pk2, "hello", "hello2", 1); + tt_assert(!ret); + + done: + UNMOCK(crypto_pk_get_openssl_evp_pkey_); + crypto_pk_free(pk1); + crypto_pk_free(pk2); +} + +static void +test_tortls_cert_new(void *ignored) +{ + (void)ignored; + tor_x509_cert_t *ret; + X509 *cert = read_cert_from(validCertString); + + ret = tor_x509_cert_new(NULL); + tt_assert(!ret); + + ret = tor_x509_cert_new(cert); + tt_assert(ret); + tor_x509_cert_free(ret); + ret = NULL; + +#if 0 + cert = read_cert_from(validCertString); + /* XXX this doesn't do what you think: it alters a copy of the pubkey. */ + X509_get_pubkey(cert)->type = EVP_PKEY_DSA; + ret = tor_x509_cert_new(cert); + tt_assert(ret); +#endif /* 0 */ + +#ifndef OPENSSL_OPAQUE + cert = read_cert_from(validCertString); + X509_CINF_free(cert->cert_info); + cert->cert_info = NULL; + ret = tor_x509_cert_new(cert); + tt_assert(ret); +#endif /* !defined(OPENSSL_OPAQUE) */ + + done: + tor_x509_cert_free(ret); +} + +static void +test_tortls_cert_is_valid(void *ignored) +{ + (void)ignored; + int ret; + tor_x509_cert_t *cert = NULL, *scert = NULL; + + scert = tor_malloc_zero(sizeof(tor_x509_cert_t)); + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); + tt_int_op(ret, OP_EQ, 0); + + cert = tor_malloc_zero(sizeof(tor_x509_cert_t)); + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); + tt_int_op(ret, OP_EQ, 0); + tor_free(scert); + tor_free(cert); + + cert = tor_x509_cert_new(read_cert_from(validCertString)); + scert = tor_x509_cert_new(read_cert_from(caCertString)); + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); + tt_int_op(ret, OP_EQ, 1); + +#ifndef OPENSSL_OPAQUE + tor_x509_cert_free(cert); + tor_x509_cert_free(scert); + cert = tor_x509_cert_new(read_cert_from(validCertString)); + scert = tor_x509_cert_new(read_cert_from(caCertString)); + ASN1_TIME_free(cert->cert->cert_info->validity->notAfter); + cert->cert->cert_info->validity->notAfter = + ASN1_TIME_set(NULL, time(NULL)-1000000); + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); + tt_int_op(ret, OP_EQ, 0); + + tor_x509_cert_free(cert); + tor_x509_cert_free(scert); + cert = tor_x509_cert_new(read_cert_from(validCertString)); + scert = tor_x509_cert_new(read_cert_from(caCertString)); + X509_PUBKEY_free(cert->cert->cert_info->key); + cert->cert->cert_info->key = NULL; + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 1); + tt_int_op(ret, OP_EQ, 0); +#endif /* !defined(OPENSSL_OPAQUE) */ + +#if 0 + tor_x509_cert_free(cert); + tor_x509_cert_free(scert); + cert = tor_x509_cert_new(read_cert_from(validCertString)); + scert = tor_x509_cert_new(read_cert_from(caCertString)); + /* This doesn't actually change the key in the cert. XXXXXX */ + BN_one(EVP_PKEY_get1_RSA(X509_get_pubkey(cert->cert))->n); + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 1); + tt_int_op(ret, OP_EQ, 0); + + tor_x509_cert_free(cert); + tor_x509_cert_free(scert); + cert = tor_x509_cert_new(read_cert_from(validCertString)); + scert = tor_x509_cert_new(read_cert_from(caCertString)); + /* This doesn't actually change the key in the cert. XXXXXX */ + X509_get_pubkey(cert->cert)->type = EVP_PKEY_EC; + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 1); + tt_int_op(ret, OP_EQ, 0); + + tor_x509_cert_free(cert); + tor_x509_cert_free(scert); + cert = tor_x509_cert_new(read_cert_from(validCertString)); + scert = tor_x509_cert_new(read_cert_from(caCertString)); + /* This doesn't actually change the key in the cert. XXXXXX */ + X509_get_pubkey(cert->cert)->type = EVP_PKEY_EC; + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); + tt_int_op(ret, OP_EQ, 1); + + tor_x509_cert_free(cert); + tor_x509_cert_free(scert); + cert = tor_x509_cert_new(read_cert_from(validCertString)); + scert = tor_x509_cert_new(read_cert_from(caCertString)); + /* This doesn't actually change the key in the cert. XXXXXX */ + X509_get_pubkey(cert->cert)->type = EVP_PKEY_EC; + X509_get_pubkey(cert->cert)->ameth = NULL; + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); + tt_int_op(ret, OP_EQ, 0); +#endif /* 0 */ + + done: + tor_x509_cert_free(cert); + tor_x509_cert_free(scert); +} + +static void +test_tortls_context_init_one(void *ignored) +{ + (void)ignored; + int ret; + tor_tls_context_t *old = NULL; + + MOCK(crypto_pk_new, fixed_crypto_pk_new); + + fixed_crypto_pk_new_result_index = 0; + fixed_crypto_pk_new_result[0] = NULL; + ret = tor_tls_context_init_one(&old, NULL, 0, 0, 0); + tt_int_op(ret, OP_EQ, -1); + + done: + UNMOCK(crypto_pk_new); +} + +#define LOCAL_TEST_CASE(name, flags) \ + { #name, test_tortls_##name, (flags|TT_FORK), NULL, NULL } + +#ifdef OPENSSL_OPAQUE +#define INTRUSIVE_TEST_CASE(name, flags) \ + { #name, NULL, TT_SKIP, NULL, NULL } +#else +#define INTRUSIVE_TEST_CASE(name, flags) LOCAL_TEST_CASE(name, flags) +#endif /* defined(OPENSSL_OPAQUE) */ + +struct testcase_t tortls_openssl_tests[] = { + LOCAL_TEST_CASE(tor_tls_new, TT_FORK), + LOCAL_TEST_CASE(get_state_description, TT_FORK), + LOCAL_TEST_CASE(get_by_ssl, TT_FORK), + LOCAL_TEST_CASE(allocate_tor_tls_object_ex_data_index, TT_FORK), + LOCAL_TEST_CASE(log_one_error, TT_FORK), + INTRUSIVE_TEST_CASE(get_error, TT_FORK), + LOCAL_TEST_CASE(always_accept_verify_cb, 0), + INTRUSIVE_TEST_CASE(x509_cert_free, 0), + LOCAL_TEST_CASE(cert_matches_key, 0), + INTRUSIVE_TEST_CASE(cert_get_key, 0), + LOCAL_TEST_CASE(get_my_client_auth_key, TT_FORK), + INTRUSIVE_TEST_CASE(get_ciphersuite_name, 0), + INTRUSIVE_TEST_CASE(classify_client_ciphers, 0), + LOCAL_TEST_CASE(client_is_using_v2_ciphers, 0), + INTRUSIVE_TEST_CASE(get_pending_bytes, 0), + INTRUSIVE_TEST_CASE(SSL_SESSION_get_master_key, 0), + INTRUSIVE_TEST_CASE(get_tlssecrets, 0), + INTRUSIVE_TEST_CASE(get_buffer_sizes, 0), + INTRUSIVE_TEST_CASE(try_to_extract_certs_from_tls, 0), + INTRUSIVE_TEST_CASE(get_peer_cert, 0), + INTRUSIVE_TEST_CASE(peer_has_cert, 0), + INTRUSIVE_TEST_CASE(finish_handshake, 0), + INTRUSIVE_TEST_CASE(handshake, 0), + INTRUSIVE_TEST_CASE(write, 0), + INTRUSIVE_TEST_CASE(read, 0), + INTRUSIVE_TEST_CASE(server_info_callback, 0), + LOCAL_TEST_CASE(get_write_overhead_ratio, TT_FORK), + LOCAL_TEST_CASE(is_server, 0), + INTRUSIVE_TEST_CASE(assert_renegotiation_unblocked, 0), + INTRUSIVE_TEST_CASE(block_renegotiation, 0), + INTRUSIVE_TEST_CASE(unblock_renegotiation, 0), + INTRUSIVE_TEST_CASE(set_renegotiate_callback, 0), + LOCAL_TEST_CASE(set_logged_address, 0), + INTRUSIVE_TEST_CASE(find_cipher_by_id, 0), + INTRUSIVE_TEST_CASE(session_secret_cb, 0), + INTRUSIVE_TEST_CASE(debug_state_callback, 0), + INTRUSIVE_TEST_CASE(context_new, TT_FORK /* redundant */), + LOCAL_TEST_CASE(create_certificate, 0), + LOCAL_TEST_CASE(cert_new, 0), + LOCAL_TEST_CASE(cert_is_valid, 0), + LOCAL_TEST_CASE(context_init_one, 0), + END_OF_TESTCASES +}; diff --git a/src/test/test_util.c b/src/test/test_util.c index 036f739b89..7bc1b7921a 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" @@ -8,14 +8,37 @@ #define COMPAT_TIME_PRIVATE #define CONTROL_PRIVATE #define UTIL_PRIVATE -#include "or.h" -#include "buffers.h" -#include "config.h" -#include "control.h" -#include "test.h" -#include "memarea.h" -#include "util_process.h" -#include "log_test_helpers.h" +#define UTIL_MALLOC_PRIVATE +#define SOCKET_PRIVATE +#define SUBPROCESS_PRIVATE +#include "lib/testsupport/testsupport.h" +#include "core/or/or.h" +#include "lib/container/buffers.h" +#include "app/config/config.h" +#include "feature/control/control.h" +#include "feature/client/transports.h" +#include "lib/crypt_ops/crypto_format.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "test/test.h" +#include "lib/memarea/memarea.h" +#include "lib/process/waitpid.h" +#include "test/log_test_helpers.h" +#include "lib/compress/compress.h" +#include "lib/compress/compress_zstd.h" +#include "lib/encoding/keyval.h" +#include "lib/fdio/fdio.h" +#include "lib/fs/winlib.h" +#include "lib/process/env.h" +#include "lib/process/pidfile.h" +#include "lib/process/subprocess.h" +#include "lib/intmath/weakrng.h" +#include "lib/thread/numcpus.h" +#include "lib/math/fp.h" +#include "lib/math/laplace.h" +#include "lib/meminfo/meminfo.h" +#include "lib/time/tvdiff.h" +#include "lib/encoding/confline.h" +#include "lib/net/socketpair.h" #ifdef HAVE_PWD_H #include <pwd.h> @@ -26,6 +49,16 @@ #ifdef HAVE_UTIME_H #include <utime.h> #endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + #ifdef _WIN32 #include <tchar.h> #endif @@ -890,6 +923,32 @@ test_util_time(void *arg) teardown_capture_of_logs(); } } + { + /* As above, but with localtime. */ + t_res = -9223372036854775LL; + tor_localtime_r(&t_res, &b_time); + tt_assert(b_time.tm_year == (1970-1900) || + b_time.tm_year == (1-1900)); + + /* while unlikely, the system's gmtime(_r) could return + * a "correct" retrospective gregorian negative year value, + * which I'm pretty sure is: + * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657 + * 730485 is the number of days in two millennia, including leap days + * (int64_t)b_time.tm_year == (-292277022657LL-1900LL) without clamping */ + t_res = INT64_MIN; + CAPTURE(); + tor_localtime_r(&t_res, &b_time); + if (! (b_time.tm_year == (1970-1900) || + b_time.tm_year == (1-1900))) { + tt_int_op(b_time.tm_year, OP_EQ, 1970-1900); + } + if (b_time.tm_year != 1970-1900) { + CHECK_TIMEGM_WARNING("Rounding up to "); + } else { + teardown_capture_of_logs(); + } + } #endif /* SIZEOF_TIME_T == 8 */ /* time_t >= INT_MAX yields a year clamped to 2037 or 9999, @@ -906,6 +965,17 @@ test_util_time(void *arg) tt_assert(b_time.tm_year == (2037-1900) || b_time.tm_year == (2038-1900)); } + { + /* as above but with localtime. */ + t_res = 3*(1 << 29); + tor_localtime_r(&t_res, &b_time); + tt_assert(b_time.tm_year == (2021-1900)); + + t_res = INT32_MAX; + tor_localtime_r(&t_res, &b_time); + tt_assert(b_time.tm_year == (2037-1900) || + b_time.tm_year == (2038-1900)); + } #endif /* SIZEOF_TIME_T == 4 || SIZEOF_TIME_T == 8 */ #if SIZEOF_TIME_T == 8 @@ -931,6 +1001,27 @@ test_util_time(void *arg) tt_assert(b_time.tm_year == (2037-1900) || b_time.tm_year == (9999-1900)); } + { + /* As above but with localtime. */ + t_res = 9223372036854775LL; + tor_localtime_r(&t_res, &b_time); + tt_assert(b_time.tm_year == (2037-1900) || + b_time.tm_year == (9999-1900)); + + /* while unlikely, the system's gmtime(_r) could return + * a "correct" proleptic gregorian year value, + * which I'm pretty sure is: + * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596 + * 730485 is the number of days in two millennia, including leap days + * (int64_t)b_time.tm_year == (292277026596L-1900L) without clamping */ + t_res = INT64_MAX; + CAPTURE(); + tor_localtime_r(&t_res, &b_time); + CHECK_TIMEGM_WARNING("Rounding down to "); + + tt_assert(b_time.tm_year == (2037-1900) || + b_time.tm_year == (9999-1900)); + } #endif /* SIZEOF_TIME_T == 8 */ /* Test {format,parse}_rfc1123_time */ @@ -1899,8 +1990,8 @@ test_util_strmisc(void *arg) tor_snprintf(buf, 10, "abcdef"); tt_int_op(0,OP_EQ, buf[6]); /* uint64 */ - tor_snprintf(buf, sizeof(buf), "x!"U64_FORMAT"!x", - U64_PRINTF_ARG(U64_LITERAL(12345678901))); + tor_snprintf(buf, sizeof(buf), "x!%"PRIu64"!x", + (UINT64_C(12345678901))); tt_str_op("x!12345678901!x",OP_EQ, buf); /* Test str{,case}cmpstart */ @@ -2113,20 +2204,10 @@ test_util_parse_integer(void *arg) tt_int_op(1,OP_EQ, i); tt_str_op(cp,OP_EQ, " plus garbage"); /* Illogical min max */ - tor_capture_bugs_(1); tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,4,&i,NULL)); tt_int_op(0,OP_EQ, i); - tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_())); - tt_str_op("!(max < min)", OP_EQ, - smartlist_get(tor_get_captured_bug_log_(), 0)); - tor_end_capture_bugs_(); - tor_capture_bugs_(1); tt_int_op(0L,OP_EQ, tor_parse_long("-50",10,100,-100,&i,NULL)); tt_int_op(0,OP_EQ, i); - tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_())); - tt_str_op("!(max < min)", OP_EQ, - smartlist_get(tor_get_captured_bug_log_(), 0)); - tor_end_capture_bugs_(); /* Out of bounds */ tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,100,&i,NULL)); tt_int_op(0,OP_EQ, i); @@ -2137,11 +2218,8 @@ test_util_parse_integer(void *arg) tt_int_op(0L,OP_EQ, tor_parse_long("2",2,0,100,NULL,NULL)); tt_int_op(68284L,OP_EQ, tor_parse_long("10abc",16,0,70000,NULL,NULL)); tt_int_op(68284L,OP_EQ, tor_parse_long("10ABC",16,0,70000,NULL,NULL)); - tor_capture_bugs_(2); tt_int_op(0L,OP_EQ, tor_parse_long("10",-2,0,100,NULL,NULL)); tt_int_op(0,OP_EQ, tor_parse_long("10ABC",-1,0,70000,&i,NULL)); - tt_int_op(2, OP_EQ, smartlist_len(tor_get_captured_bug_log_())); - tor_end_capture_bugs_(); tt_int_op(i,OP_EQ, 0); /* Test parse_ulong */ @@ -2154,40 +2232,34 @@ test_util_parse_integer(void *arg) tt_int_op(0UL,OP_EQ, tor_parse_ulong("8",8,0,100,NULL,NULL)); tt_int_op(50UL,OP_EQ, tor_parse_ulong("50",10,50,100,NULL,NULL)); tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,NULL,NULL)); - tor_capture_bugs_(1); tt_int_op(0UL,OP_EQ, tor_parse_ulong("50",-1,50,100,&i,NULL)); - tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_())); - tor_end_capture_bugs_(); tt_int_op(0,OP_EQ, i); tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,&i,NULL)); tt_int_op(0,OP_EQ, i); /* Test parse_uint64 */ - tt_assert(U64_LITERAL(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp)); + tt_assert(UINT64_C(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp)); tt_int_op(1,OP_EQ, i); tt_str_op(cp,OP_EQ, " x"); - tt_assert(U64_LITERAL(12345678901) == + tt_assert(UINT64_C(12345678901) == tor_parse_uint64("12345678901",10,0,UINT64_MAX, &i, &cp)); tt_int_op(1,OP_EQ, i); tt_str_op(cp,OP_EQ, ""); - tt_assert(U64_LITERAL(0) == + tt_assert(UINT64_C(0) == tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp)); tt_int_op(0,OP_EQ, i); - tor_capture_bugs_(1); - tt_assert(U64_LITERAL(0) == + tt_assert(UINT64_C(0) == tor_parse_uint64("123",-1,0,INT32_MAX, &i, &cp)); - tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_())); - tor_end_capture_bugs_(); tt_int_op(0,OP_EQ, i); { /* Test parse_double */ double d = tor_parse_double("10", 0, (double)UINT64_MAX,&i,NULL); tt_int_op(1,OP_EQ, i); - tt_assert(DBL_TO_U64(d) == 10); + tt_assert(((uint64_t)d) == 10); d = tor_parse_double("0", 0, (double)UINT64_MAX,&i,NULL); tt_int_op(1,OP_EQ, i); - tt_assert(DBL_TO_U64(d) == 0); + tt_assert(((uint64_t)d) == 0); d = tor_parse_double(" ", 0, (double)UINT64_MAX,&i,NULL); tt_double_op(fabs(d), OP_LT, 1e-10); tt_int_op(0,OP_EQ, i); @@ -2199,7 +2271,7 @@ test_util_parse_integer(void *arg) tt_int_op(1,OP_EQ, i); d = tor_parse_double("-.0", 0, (double)UINT64_MAX,&i,NULL); tt_int_op(1,OP_EQ, i); - tt_assert(DBL_TO_U64(d) == 0); + tt_assert(((uint64_t)d) == 0); d = tor_parse_double("-10", -100.0, 100.0,&i,NULL); tt_int_op(1,OP_EQ, i); tt_double_op(fabs(d - -10.0),OP_LT, 1E-12); @@ -2217,12 +2289,12 @@ test_util_parse_integer(void *arg) tt_int_op(i,OP_EQ, 0); tt_int_op(0UL,OP_EQ, tor_parse_ulong(TOOBIG, 10, 0, ULONG_MAX, &i, NULL)); tt_int_op(i,OP_EQ, 0); - tt_u64_op(U64_LITERAL(0), OP_EQ, tor_parse_uint64(TOOBIG, 10, + tt_u64_op(UINT64_C(0), OP_EQ, tor_parse_uint64(TOOBIG, 10, 0, UINT64_MAX, &i, NULL)); tt_int_op(i,OP_EQ, 0); } done: - tor_end_capture_bugs_(); + ; } static void @@ -2240,17 +2312,17 @@ test_util_pow2(void *arg) tt_int_op(tor_log2(3),OP_EQ, 1); tt_int_op(tor_log2(4),OP_EQ, 2); tt_int_op(tor_log2(5),OP_EQ, 2); - tt_int_op(tor_log2(U64_LITERAL(40000000000000000)),OP_EQ, 55); + tt_int_op(tor_log2(UINT64_C(40000000000000000)),OP_EQ, 55); tt_int_op(tor_log2(UINT64_MAX),OP_EQ, 63); /* Test round_to_power_of_2 */ tt_u64_op(round_to_power_of_2(120), OP_EQ, 128); tt_u64_op(round_to_power_of_2(128), OP_EQ, 128); tt_u64_op(round_to_power_of_2(130), OP_EQ, 128); - tt_u64_op(round_to_power_of_2(U64_LITERAL(40000000000000000)), OP_EQ, - U64_LITERAL(1)<<55); - tt_u64_op(round_to_power_of_2(U64_LITERAL(0xffffffffffffffff)), OP_EQ, - U64_LITERAL(1)<<63); + tt_u64_op(round_to_power_of_2(UINT64_C(40000000000000000)), OP_EQ, + UINT64_C(1)<<55); + tt_u64_op(round_to_power_of_2(UINT64_C(0xffffffffffffffff)), OP_EQ, + UINT64_C(1)<<63); tt_u64_op(round_to_power_of_2(0), OP_EQ, 1); tt_u64_op(round_to_power_of_2(1), OP_EQ, 1); tt_u64_op(round_to_power_of_2(2), OP_EQ, 2); @@ -2396,6 +2468,37 @@ test_util_compress_stream_impl(compress_method_t method, tor_free(buf3); } +/** Setup function for compression tests: handles x-zstd:nostatic + */ +static void * +compression_test_setup(const struct testcase_t *testcase) +{ + tor_assert(testcase->setup_data); + tor_assert(testcase->setup_data != (void*)TT_SKIP); + const char *methodname = testcase->setup_data; + + if (!strcmp(methodname, "x-zstd:nostatic")) { + methodname = "x-zstd"; + tor_zstd_set_static_apis_disabled_for_testing(1); + } + + return (void *)methodname; +} + +/** Cleanup for compression tests: disables nostatic */ +static int +compression_test_cleanup(const struct testcase_t *testcase, void *ptr) +{ + (void)testcase; + (void)ptr; + tor_zstd_set_static_apis_disabled_for_testing(0); + return 1; +} + +static const struct testcase_setup_t compress_setup = { + compression_test_setup, compression_test_cleanup +}; + /** Run unit tests for compression functions */ static void test_util_compress(void *arg) @@ -3119,6 +3222,21 @@ test_util_sscanf(void *arg) test_feq(d3, -900123123.2000787); test_feq(d4, 3.2); + /* missing float */ + r = tor_sscanf("3 ", "%d %lf", &int1, &d1); + tt_int_op(r, OP_EQ, 1); + tt_int_op(int1, OP_EQ, 3); + + /* not a float */ + r = tor_sscanf("999 notafloat", "%d %lf", &int1, &d1); + tt_int_op(r, OP_EQ, 1); + tt_int_op(int1, OP_EQ, 999); + + /* %s but no buffer. */ + char *nullbuf = NULL; + r = tor_sscanf("hello", "%3s", nullbuf); + tt_int_op(r, OP_EQ, 0); + done: tor_free(huge); } @@ -3895,6 +4013,53 @@ test_util_string_is_C_identifier(void *ptr) } static void +test_util_string_is_utf8(void *ptr) +{ + (void)ptr; + + tt_int_op(1, OP_EQ, string_is_utf8(NULL, 0)); + tt_int_op(1, OP_EQ, string_is_utf8("", 1)); + tt_int_op(1, OP_EQ, string_is_utf8("\uFEFF", 3)); + tt_int_op(1, OP_EQ, string_is_utf8("\uFFFE", 3)); + tt_int_op(1, OP_EQ, string_is_utf8("ascii\x7f\n", 7)); + tt_int_op(1, OP_EQ, string_is_utf8("Risqu\u00e9=1", 9)); + + // Validate exactly 'len' bytes. + tt_int_op(0, OP_EQ, string_is_utf8("\0\x80", 2)); + tt_int_op(0, OP_EQ, string_is_utf8("Risqu\u00e9=1", 6)); + + // Reject sequences with missing bytes. + tt_int_op(0, OP_EQ, string_is_utf8("\x80", 1)); + tt_int_op(0, OP_EQ, string_is_utf8("\xc2", 1)); + tt_int_op(0, OP_EQ, string_is_utf8("\xc2 ", 2)); + tt_int_op(0, OP_EQ, string_is_utf8("\xe1\x80", 2)); + tt_int_op(0, OP_EQ, string_is_utf8("\xe1\x80 ", 3)); + tt_int_op(0, OP_EQ, string_is_utf8("\xf1\x80\x80", 3)); + tt_int_op(0, OP_EQ, string_is_utf8("\xf1\x80\x80 ", 4)); + + // Reject encodings that are overly long. + tt_int_op(0, OP_EQ, string_is_utf8("\xc1\xbf", 2)); + tt_int_op(1, OP_EQ, string_is_utf8("\xc2\x80", 2)); + tt_int_op(0, OP_EQ, string_is_utf8("\xe0\x9f\xbf", 3)); + tt_int_op(1, OP_EQ, string_is_utf8("\xe0\xa0\x80", 3)); + tt_int_op(0, OP_EQ, string_is_utf8("\xf0\x8f\xbf\xbf", 4)); + tt_int_op(1, OP_EQ, string_is_utf8("\xf0\x90\x80\x80", 4)); + + // Reject UTF-16 surrogate halves. + tt_int_op(1, OP_EQ, string_is_utf8("\xed\x9f\xbf", 3)); + tt_int_op(0, OP_EQ, string_is_utf8("\xed\xa0\x80", 3)); + tt_int_op(0, OP_EQ, string_is_utf8("\xed\xbf\xbf", 3)); + tt_int_op(1, OP_EQ, string_is_utf8("\xee\x80\x80", 3)); + + // The maximum legal codepoint, 10FFFF. + tt_int_op(1, OP_EQ, string_is_utf8("\xf4\x8f\xbf\xbf", 4)); + tt_int_op(0, OP_EQ, string_is_utf8("\xf4\x90\x80\x80", 4)); + + done: + ; +} + +static void test_util_asprintf(void *ptr) { #define LOREMIPSUM \ @@ -4069,7 +4234,8 @@ test_util_ftruncate(void *ptr) tt_int_op(fd, OP_GE, 0); /* Make the file be there. */ - tt_int_op(strlen(message), OP_EQ, write_all(fd, message, strlen(message),0)); + tt_int_op(strlen(message), OP_EQ, + write_all_to_fd(fd, message, strlen(message))); tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message)); tt_int_op(0, OP_EQ, fstat(fd, &st)); tt_int_op((int)st.st_size, OP_EQ, strlen(message)); @@ -4082,7 +4248,7 @@ test_util_ftruncate(void *ptr) /* Replace, and see if it got replaced */ tt_int_op(strlen(message2), OP_EQ, - write_all(fd, message2, strlen(message2), 0)); + write_all_to_fd(fd, message2, strlen(message2))); tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message2)); tt_int_op(0, OP_EQ, fstat(fd, &st)); tt_int_op((int)st.st_size, OP_EQ, strlen(message2)); @@ -5494,10 +5660,13 @@ test_util_socketpair(void *arg) tt_assert(SOCKET_OK(fds[0])); tt_assert(SOCKET_OK(fds[1])); - tt_int_op(get_n_open_sockets(), OP_EQ, n + 2); + if (ersatz) + tt_int_op(get_n_open_sockets(), OP_EQ, n); + else + tt_int_op(get_n_open_sockets(), OP_EQ, n + 2); #ifdef CAN_CHECK_CLOEXEC - tt_int_op(fd_is_cloexec(fds[0]), OP_EQ, 1); - tt_int_op(fd_is_cloexec(fds[1]), OP_EQ, 1); + tt_int_op(fd_is_cloexec(fds[0]), OP_EQ, !ersatz); + tt_int_op(fd_is_cloexec(fds[1]), OP_EQ, !ersatz); #endif #ifdef CAN_CHECK_NONBLOCK tt_int_op(fd_is_nonblocking(fds[0]), OP_EQ, 0); @@ -5505,10 +5674,17 @@ test_util_socketpair(void *arg) #endif done: - if (SOCKET_OK(fds[0])) - tor_close_socket(fds[0]); - if (SOCKET_OK(fds[1])) - tor_close_socket(fds[1]); + if (ersatz) { + if (SOCKET_OK(fds[0])) + tor_close_socket_simple(fds[0]); + if (SOCKET_OK(fds[1])) + tor_close_socket_simple(fds[1]); + } else { + if (SOCKET_OK(fds[0])) + tor_close_socket(fds[0]); + if (SOCKET_OK(fds[1])) + tor_close_socket(fds[1]); + } } #undef SOCKET_EPROTO @@ -5525,15 +5701,15 @@ test_util_max_mem(void *arg) tt_int_op(r, OP_EQ, r2); tt_uint_op(memory2, OP_EQ, memory1); - TT_BLATHER(("System memory: "U64_FORMAT, U64_PRINTF_ARG(memory1))); + TT_BLATHER(("System memory: %"TOR_PRIuSZ, (memory1))); if (r==0) { /* You have at least a megabyte. */ tt_uint_op(memory1, OP_GT, (1<<20)); } else { /* You do not have a petabyte. */ -#if SIZEOF_SIZE_T == SIZEOF_UINT64_T - tt_u64_op(memory1, OP_LT, (U64_LITERAL(1)<<50)); +#if SIZEOF_SIZE_T >= 8 + tt_u64_op(memory1, OP_LT, (UINT64_C(1)<<50)); #endif } @@ -5875,6 +6051,13 @@ test_util_monotonic_time(void *arg) tt_u64_op(coarse_stamp_diff, OP_GE, 120); tt_u64_op(coarse_stamp_diff, OP_LE, 1200); + { + uint64_t units = monotime_msec_to_approx_coarse_stamp_units(5000); + uint64_t ms = monotime_coarse_stamp_units_to_approx_msec(units); + tt_u64_op(ms, OP_GE, 4950); + tt_u64_op(ms, OP_LT, 5050); + } + done: ; } @@ -5996,6 +6179,9 @@ test_util_monotonic_time_add_msec(void *arg) monotime_coarse_add_msec(&ct2, &ct1, 1337); tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 1337); tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 1337); + // The 32-bit variant must be within 1% of the regular one. + tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_GT, 1323); + tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_LT, 1350); /* Add 1337 msec twice more; make sure that any second rollover issues * worked. */ @@ -6005,6 +6191,25 @@ test_util_monotonic_time_add_msec(void *arg) monotime_coarse_add_msec(&ct2, &ct2, 1337); tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 1337*3); tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 1337*3); + tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_GT, 3970); + tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_LT, 4051); + + done: + ; +} + +static void +test_util_nowrap_math(void *arg) +{ + (void)arg; + + tt_u64_op(0, OP_EQ, tor_add_u32_nowrap(0, 0)); + tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(0, 1)); + tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(1, 0)); + tt_u64_op(4, OP_EQ, tor_add_u32_nowrap(2, 2)); + tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX-1, 2)); + tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(2, UINT32_MAX-1)); + tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX, UINT32_MAX)); done: ; @@ -6115,6 +6320,57 @@ test_util_get_unquoted_path(void *arg) tor_free(r); } +static void +test_util_log_mallinfo(void *arg) +{ + (void)arg; + char *log1 = NULL, *log2 = NULL, *mem = NULL; +#ifdef HAVE_MALLINFO + setup_capture_of_logs(LOG_INFO); + tor_log_mallinfo(LOG_INFO); + expect_single_log_msg_containing("mallinfo() said: "); + mock_saved_log_entry_t *lg = smartlist_get(mock_saved_logs(), 0); + log1 = tor_strdup(lg->generated_msg); + + mock_clean_saved_logs(); + mem = tor_malloc(8192); + tor_log_mallinfo(LOG_INFO); + expect_single_log_msg_containing("mallinfo() said: "); + lg = smartlist_get(mock_saved_logs(), 0); + log2 = tor_strdup(lg->generated_msg); + + /* Make sure that the amount of used memory increased. */ + const char *used1 = strstr(log1, "uordblks="); + const char *used2 = strstr(log2, "uordblks="); + tt_assert(used1); + tt_assert(used2); + used1 += strlen("uordblks="); + used2 += strlen("uordblks="); + + int ok1, ok2; + char *next1 = NULL, *next2 = NULL; + uint64_t mem1 = tor_parse_uint64(used1, 10, 0, UINT64_MAX, &ok1, &next1); + uint64_t mem2 = tor_parse_uint64(used2, 10, 0, UINT64_MAX, &ok2, &next2); + tt_assert(ok1); + tt_assert(ok2); + tt_assert(next1); + tt_assert(next2); + if (mem2 == 0) { + /* This is a fake mallinfo that doesn't actually fill in its outputs. */ + tt_u64_op(mem1, OP_EQ, 0); + } else { + tt_u64_op(mem1, OP_LT, mem2); + } +#else + tt_skip(); +#endif + done: + teardown_capture_of_logs(); + tor_free(log1); + tor_free(log2); + tor_free(mem); +} + #define UTIL_LEGACY(name) \ { #name, test_util_ ## name , 0, NULL, NULL } @@ -6122,22 +6378,22 @@ test_util_get_unquoted_path(void *arg) { #name, test_util_ ## name, flags, NULL, NULL } #define COMPRESS(name, identifier) \ - { "compress/" #name, test_util_compress, 0, &passthrough_setup, \ + { "compress/" #name, test_util_compress, 0, &compress_setup, \ (char*)(identifier) } #define COMPRESS_CONCAT(name, identifier) \ { "compress_concat/" #name, test_util_decompress_concatenated, 0, \ - &passthrough_setup, \ + &compress_setup, \ (char*)(identifier) } #define COMPRESS_JUNK(name, identifier) \ { "compress_junk/" #name, test_util_decompress_junk, 0, \ - &passthrough_setup, \ + &compress_setup, \ (char*)(identifier) } #define COMPRESS_DOS(name, identifier) \ { "compress_dos/" #name, test_util_decompress_dos, 0, \ - &passthrough_setup, \ + &compress_setup, \ (char*)(identifier) } #ifdef _WIN32 @@ -6168,11 +6424,13 @@ struct testcase_t util_tests[] = { COMPRESS(gzip, "gzip"), COMPRESS(lzma, "x-tor-lzma"), COMPRESS(zstd, "x-zstd"), + COMPRESS(zstd_nostatic, "x-zstd:nostatic"), COMPRESS(none, "identity"), COMPRESS_CONCAT(zlib, "deflate"), COMPRESS_CONCAT(gzip, "gzip"), COMPRESS_CONCAT(lzma, "x-tor-lzma"), COMPRESS_CONCAT(zstd, "x-zstd"), + COMPRESS_CONCAT(zstd_nostatic, "x-zstd:nostatic"), COMPRESS_CONCAT(none, "identity"), COMPRESS_JUNK(zlib, "deflate"), COMPRESS_JUNK(gzip, "gzip"), @@ -6181,6 +6439,7 @@ struct testcase_t util_tests[] = { COMPRESS_DOS(gzip, "gzip"), COMPRESS_DOS(lzma, "x-tor-lzma"), COMPRESS_DOS(zstd, "x-zstd"), + COMPRESS_DOS(zstd_nostatic, "x-zstd:nostatic"), UTIL_TEST(gzip_compression_bomb, TT_FORK), UTIL_LEGACY(datadir), UTIL_LEGACY(memarea), @@ -6197,10 +6456,12 @@ struct testcase_t util_tests[] = { UTIL_TEST(clamp_double_to_int64, 0), UTIL_TEST(find_str_at_start_of_line, 0), UTIL_TEST(string_is_C_identifier, 0), + UTIL_TEST(string_is_utf8, 0), UTIL_TEST(asprintf, 0), UTIL_TEST(listdir, 0), UTIL_TEST(parent_dir, 0), UTIL_TEST(ftruncate, 0), + UTIL_TEST(nowrap_math, 0), UTIL_TEST(num_cpus, 0), UTIL_TEST_WIN_ONLY(load_win_lib, 0), UTIL_TEST_NO_WIN(exit_status, 0), @@ -6248,6 +6509,6 @@ struct testcase_t util_tests[] = { UTIL_TEST(monotonic_time_add_msec, 0), UTIL_TEST(htonll, 0), UTIL_TEST(get_unquoted_path, 0), + UTIL_TEST(log_mallinfo, 0), END_OF_TESTCASES }; - diff --git a/src/test/test_util_format.c b/src/test/test_util_format.c index 683d5fdac1..85d8a8e62e 100644 --- a/src/test/test_util_format.c +++ b/src/test/test_util_format.c @@ -1,13 +1,14 @@ -/* Copyright (c) 2010-2017, The Tor Project, Inc. */ +/* Copyright (c) 2010-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" -#include "or.h" +#include "core/or/or.h" -#include "test.h" +#include "test/test.h" +#include "lib/crypt_ops/crypto_rand.h" #define UTIL_FORMAT_PRIVATE -#include "util_format.h" +#include "lib/encoding/binascii.h" #define NS_MODULE util_format @@ -18,7 +19,7 @@ test_util_format_unaligned_accessors(void *ignored) char buf[9] = "onionsoup"; // 6f6e696f6e736f7570 tt_u64_op(get_uint64(buf+1), OP_EQ, - tor_htonll(U64_LITERAL(0x6e696f6e736f7570))); + tor_htonll(UINT64_C(0x6e696f6e736f7570))); tt_uint_op(get_uint32(buf+1), OP_EQ, htonl(0x6e696f6e)); tt_uint_op(get_uint16(buf+1), OP_EQ, htons(0x6e69)); tt_uint_op(get_uint8(buf+1), OP_EQ, 0x6e); @@ -32,7 +33,7 @@ test_util_format_unaligned_accessors(void *ignored) set_uint32(buf+1, htonl(0x78696465)); tt_mem_op(buf, OP_EQ, "oxidestop", 9); - set_uint64(buf+1, tor_htonll(U64_LITERAL(0x6266757363617465))); + set_uint64(buf+1, tor_htonll(UINT64_C(0x6266757363617465))); tt_mem_op(buf, OP_EQ, "obfuscate", 9); done: ; diff --git a/src/test/test_util_process.c b/src/test/test_util_process.c index 68ce6cfd40..44c4da9169 100644 --- a/src/test/test_util_process.c +++ b/src/test/test_util_process.c @@ -1,15 +1,15 @@ -/* Copyright (c) 2010-2017, The Tor Project, Inc. */ +/* Copyright (c) 2010-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define UTIL_PROCESS_PRIVATE #include "orconfig.h" -#include "or.h" +#include "core/or/or.h" -#include "test.h" +#include "test/test.h" -#include "util_process.h" +#include "lib/process/waitpid.h" -#include "log_test_helpers.h" +#include "test/log_test_helpers.h" #ifndef _WIN32 #define NS_MODULE util_process diff --git a/src/test/test_util_slow.c b/src/test/test_util_slow.c index 2cd68cf118..c7b3e3e2a4 100644 --- a/src/test/test_util_slow.c +++ b/src/test/test_util_slow.c @@ -1,15 +1,21 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" #define UTIL_PRIVATE -#include "util.h" -#include "util_process.h" -#include "crypto.h" -#include "torlog.h" -#include "test.h" +#define SUBPROCESS_PRIVATE +#include "lib/crypt_ops/crypto_cipher.h" +#include "lib/log/log.h" +#include "lib/process/subprocess.h" +#include "lib/process/waitpid.h" +#include "lib/string/printf.h" +#include "lib/time/compat_time.h" +#include "test/test.h" + +#include <errno.h> +#include <string.h> #ifndef BUILDDIR #define BUILDDIR "." @@ -388,4 +394,3 @@ struct testcase_t slow_util_tests[] = { UTIL_TEST(spawn_background_waitpid_notify, 0), END_OF_TESTCASES }; - diff --git a/src/test/test_voting_schedule.c b/src/test/test_voting_schedule.c new file mode 100644 index 0000000000..c3a581cf21 --- /dev/null +++ b/src/test/test_voting_schedule.c @@ -0,0 +1,64 @@ +/* Copyright (c) 2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" + +#include "core/or/or.h" +#include "feature/dircommon/voting_schedule.h" + +#include "test/test.h" + +static void +test_voting_schedule_interval_start(void *arg) +{ +#define next_interval voting_schedule_get_start_of_next_interval + (void)arg; + char buf[ISO_TIME_LEN+1]; + + // Midnight UTC tonight (as I am writing this test) + const time_t midnight = 1525651200; + format_iso_time(buf, midnight); + tt_str_op(buf, OP_EQ, "2018-05-07 00:00:00"); + + /* Some simple tests with a 50-minute voting interval */ + + tt_i64_op(next_interval(midnight, 3000, 0), OP_EQ, + midnight+3000); + + tt_i64_op(next_interval(midnight+100, 3000, 0), OP_EQ, + midnight+3000); + + tt_i64_op(next_interval(midnight+3000, 3000, 0), OP_EQ, + midnight+6000); + + tt_i64_op(next_interval(midnight+3001, 3000, 0), OP_EQ, + midnight+6000); + + /* Make sure that we roll around properly at midnight */ + tt_i64_op(next_interval(midnight+83000, 3000, 0), OP_EQ, + midnight+84000); + + /* We start fresh at midnight UTC, even if there are leftover seconds. */ + tt_i64_op(next_interval(midnight+84005, 3000, 0), OP_EQ, + midnight+86400); + + /* Now try with offsets. (These are only used for test networks.) */ + tt_i64_op(next_interval(midnight, 3000, 99), OP_EQ, + midnight+99); + + tt_i64_op(next_interval(midnight+100, 3000, 99), OP_EQ, + midnight+3099); + + done: + ; +#undef next_interval +} + +#define VS(name,flags) \ + { #name, test_voting_schedule_##name, (flags), NULL, NULL } + +struct testcase_t voting_schedule_tests[] = { + VS(interval_start, 0), + END_OF_TESTCASES +}; + diff --git a/src/test/test_workqueue.c b/src/test/test_workqueue.c index 2b03173717..28fbd6fb9f 100644 --- a/src/test/test_workqueue.c +++ b/src/test/test_workqueue.c @@ -1,18 +1,20 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "or.h" -#include "compat_threads.h" -#include "onion.h" -#include "workqueue.h" -#include "crypto.h" -#include "crypto_curve25519.h" -#include "compat_libevent.h" +#include "core/or/or.h" +#include "lib/thread/threads.h" +#include "core/or/onion.h" +#include "lib/evloop/workqueue.h" +#include "lib/crypt_ops/crypto_curve25519.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "lib/net/alertsock.h" +#include "lib/evloop/compat_libevent.h" +#include "lib/intmath/weakrng.h" +#include "lib/crypt_ops/crypto_init.h" #include <stdio.h> -#include <event2/event.h> #define MAX_INFLIGHT (1<<16) @@ -159,6 +161,7 @@ static tor_weak_rng_t weak_rng; static int n_sent = 0; static int rsa_sent = 0; static int ecdh_sent = 0; +static int n_received_previously = 0; static int n_received = 0; static int no_shutdown = 0; @@ -224,18 +227,24 @@ add_n_work_items(threadpool_t *tp, int n) workqueue_entry_t **to_cancel; workqueue_entry_t *ent; - to_cancel = tor_malloc(sizeof(workqueue_entry_t*) * opt_n_cancel); + // We'll choose randomly which entries to cancel. + to_cancel = tor_calloc(opt_n_cancel, sizeof(workqueue_entry_t*)); while (n_queued++ < n) { ent = add_work(tp); if (! ent) { puts("Z"); - tor_event_base_loopexit(tor_libevent_get_base(), NULL); + tor_libevent_exit_loop_after_delay(tor_libevent_get_base(), NULL); return -1; } - if (n_try_cancel < opt_n_cancel && - tor_weak_random_range(&weak_rng, n) < opt_n_cancel) { + + if (n_try_cancel < opt_n_cancel) { to_cancel[n_try_cancel++] = ent; + } else { + int p = tor_weak_random_range(&weak_rng, n_queued); + if (p < n_try_cancel) { + to_cancel[p] = ent; + } } } @@ -256,19 +265,13 @@ add_n_work_items(threadpool_t *tp, int n) static int shutting_down = 0; static void -replysock_readable_cb(tor_socket_t sock, short what, void *arg) +replysock_readable_cb(threadpool_t *tp) { - threadpool_t *tp = arg; - replyqueue_t *rq = threadpool_get_replyqueue(tp); - - int old_r = n_received; - (void) sock; - (void) what; - - replyqueue_process(rq); - if (old_r == n_received) + if (n_received_previously == n_received) return; + n_received_previously = n_received; + if (opt_verbose) { printf("%d / %d", n_received, n_sent); if (opt_n_cancel) @@ -308,7 +311,7 @@ replysock_readable_cb(tor_socket_t sock, short what, void *arg) handle_reply_shutdown, NULL); { struct timeval limit = { 2, 0 }; - tor_event_base_loopexit(tor_libevent_get_base(), &limit); + tor_libevent_exit_loop_after_delay(tor_libevent_get_base(), &limit); } } } @@ -337,7 +340,6 @@ main(int argc, char **argv) threadpool_t *tp; int i; tor_libevent_cfg evcfg; - struct event *ev; uint32_t as_flags = 0; for (i = 1; i < argc; ++i) { @@ -411,11 +413,11 @@ main(int argc, char **argv) memset(&evcfg, 0, sizeof(evcfg)); tor_libevent_initialize(&evcfg); - ev = tor_event_new(tor_libevent_get_base(), - replyqueue_get_socket(rq), EV_READ|EV_PERSIST, - replysock_readable_cb, tp); - - event_add(ev, NULL); + { + int r = threadpool_register_reply_event(tp, + replysock_readable_cb); + tor_assert(r == 0); + } #ifdef TRACK_RESPONSES handled = bitarray_init_zero(opt_n_items); @@ -433,10 +435,10 @@ main(int argc, char **argv) { struct timeval limit = { 180, 0 }; - tor_event_base_loopexit(tor_libevent_get_base(), &limit); + tor_libevent_exit_loop_after_delay(tor_libevent_get_base(), &limit); } - event_base_loop(tor_libevent_get_base(), 0); + tor_libevent_run_event_loop(tor_libevent_get_base(), 0); if (n_sent != opt_n_items || n_received+n_successful_cancel != n_sent) { printf("%d vs %d\n", n_sent, opt_n_items); @@ -451,4 +453,3 @@ main(int argc, char **argv) return 0; } } - diff --git a/src/test/test_x509.c b/src/test/test_x509.c new file mode 100644 index 0000000000..9128958492 --- /dev/null +++ b/src/test/test_x509.c @@ -0,0 +1,205 @@ +/* Copyright (c) 2010-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#define TOR_X509_PRIVATE +#include "orconfig.h" + +#ifdef _WIN32 +#include <winsock2.h> +#endif +#include <math.h> +#include <stddef.h> + +#include "lib/cc/compat_compiler.h" + +#include "core/or/or.h" +#include "lib/log/log.h" +#include "app/config/config.h" +#include "lib/tls/x509.h" +#include "lib/tls/x509_internal.h" +#include "app/config/or_state_st.h" + +#include "test/test.h" +#include "test/log_test_helpers.h" + +#include "tinytest.h" + +/* A mock replacement for crypto_digest that always fails. */ +static int +mock_failing_digest(char *digest, const char *m, size_t len) +{ + (void)digest; + (void)m; + (void)len; + return -1; +} + +static void +test_x509_cert_new_failing_digest(void *arg) +{ + (void)arg; + crypto_pk_t *pk1=NULL, *pk2=NULL; + tor_x509_cert_impl_t *impl = NULL; + tor_x509_cert_t *cert = NULL; + pk1 = pk_generate(0); + pk2 = pk_generate(1); + + impl = tor_tls_create_certificate(pk1, pk2, "hello", "world", 86400*100); + tt_assert(impl); + MOCK(crypto_digest, mock_failing_digest); + + setup_full_capture_of_logs(LOG_WARN); + cert = tor_x509_cert_new(impl); + tt_assert(!cert); + expect_log_msg_containing("Couldn't wrap encoded X509 certificate"); + expect_log_msg_containing("unable to compute digests of certificate key"); + + done: + crypto_pk_free(pk1); + crypto_pk_free(pk2); + UNMOCK(crypto_digest); + teardown_capture_of_logs(); +} + +static tor_x509_cert_t * +cert_from_der64(const char *der64) +{ + size_t der64len = strlen(der64); + unsigned char *der = tor_malloc_zero(der64len); + int derlen; + tor_x509_cert_t *cert = NULL; + + derlen = base64_decode((char*)der, der64len, + der64, der64len); + if (derlen >= 0) + cert = tor_x509_cert_decode(der, derlen); + tor_free(der); + return cert; +} + +static void +test_x509_consume_ec_cert(void *arg) +{ + (void)arg; + /* This is a small self-signed EC certificate. */ + const char certificate[] = + "MIIBEzCBugIJAIdl5svgOZ0OMAoGCCqGSM49BAMCMBIxEDAOBgNVBAMMB1Rlc3Rp\n" + "bmcwHhcNMTgwODIzMTcyMzI1WhcNMTkwODIzMTcyMzI1WjASMRAwDgYDVQQDDAdU\n" + "ZXN0aW5nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExMDpnRc0Btic3tIyCKNE\n" + "iNY4j4gzcaYzS2sTYRoVK3RAukG29Qg6/c8e8XcnsSquU4fItYxDRbi/3nhYk4CP\n" + "GDAKBggqhkjOPQQDAgNIADBFAiA0h1q03C2xlONUgAOonJLrlV1SUtMeKDxNsxsU\n" + "+FSPvQIhAM7kY9Tlt0ELmyMnORPp1VJieXn/qhL5VoxGxSedTbny\n"; + const time_t now = 1535045321; /* when I'm writing this test. */ + tor_x509_cert_t *cert = cert_from_der64(certificate); + crypto_pk_t *key = NULL; + tt_assert(cert); + + key = tor_tls_cert_get_key(cert); + tt_ptr_op(NULL, OP_EQ, key); // Can't get an RSA key out of an EC cert. + + /* It's a self-signed cert -- make sure it signed itself. */ + tt_assert(tor_tls_cert_is_valid(LOG_ERR, cert, cert, now, 0)); + + /* Make sure we detect its key as non-RSA1024 */ + setup_capture_of_logs(LOG_INFO); + tt_assert(! tor_tls_cert_is_valid(LOG_INFO, cert, cert, now, 1)); + expect_log_msg_containing("Key is not RSA1024"); + + done: + tor_x509_cert_free(cert); + crypto_pk_free(key); + teardown_capture_of_logs(); +} + +static void +test_x509_reject_tiny_keys(void *arg) +{ + (void)arg; + const char *certificates[] = { + /* Self-signed RSA512 */ + "MIIBXDCCAQYCCQDKikjJYZI5uDANBgkqhkiG9w0BAQsFADA1MRUwEwYDVQQHDAxE\n" + "ZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQwHhcNMTgw\n" + "ODIzMTczNjQ4WhcNMTkwODIzMTczNjQ4WjA1MRUwEwYDVQQHDAxEZWZhdWx0IENp\n" + "dHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQwXDANBgkqhkiG9w0BAQEF\n" + "AANLADBIAkEAqOvVKzrSpmKOTNqDzBG/iZrUdhCrMRsymFXyIScJcdsyn7jB8RMy\n" + "fbHqG8EqB8HHLU/eqt/+zhh2w08Lx3+5QwIDAQABMA0GCSqGSIb3DQEBCwUAA0EA\n" + "RSCq0sNbD9uWfcBqF0U4MtfFjU5x+RQQCeBVtAzwC9bggSILKZfB9XUvtGh6vqig\n", + /* Self-signed secp112r2 */ + "MIIBLTCB+QIJAI0LtN9uWxy3MAoGCCqGSM49BAMCMEUxCzAJBgNVBAYTAkFVMRMw\n" + "EQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0\n" + "eSBMdGQwHhcNMTgwODIzMTc0MTQ4WhcNMTkwODIzMTc0MTQ4WjBFMQswCQYDVQQG\n" + "EwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lk\n" + "Z2l0cyBQdHkgTHRkMDIwEAYHKoZIzj0CAQYFK4EEAAcDHgAEf7dFHo7xhCtIcgyo\n" + "Px+IDcUUlntZCtar6V4O0zAKBggqhkjOPQQDAgMjADAgAg4yhBJMEmpkNbZU95Zf\n" + "uwIOJAan4J1ETxUII1RrGmw=\n" + }; + const time_t now = 1535046182; + tor_x509_cert_t *cert = NULL; + + unsigned i; + for (i = 0; i < ARRAY_LENGTH(certificates); ++i) { + cert = cert_from_der64(certificates[i]); + /* It might parse okay, depending on our version of NSS or OpenSSL. */ + if (cert == NULL) + continue; + /* But it should not validate. */ + tt_assert(! tor_tls_cert_is_valid(LOG_INFO, cert, cert, now, 0)); + tor_x509_cert_free(cert); + } + + done: + tor_x509_cert_free(cert); +} + +static void +test_x509_expiration(void *arg) +{ + (void)arg; + /* a 365-day RSA2048 cert, created between 0 and 60 minutes before "now" */ + const char certificate[] = + "MIICzjCCAbYCCQDxIONWIQ9OGDANBgkqhkiG9w0BAQsFADApMQswCQYDVQQGEwJV\n" + "UzEaMBgGA1UEAwwRSW50ZXJlc3RpbmcgdGltZXMwHhcNMTgwODIzMTc1NTE4WhcN\n" + "MTkwODIzMTc1NTE4WjApMQswCQYDVQQGEwJVUzEaMBgGA1UEAwwRSW50ZXJlc3Rp\n" + "bmcgdGltZXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD0Blz1fBii\n" + "OffpFlzMrmfPah/vkPcNrwoyx5YiosbHErYUpqdCtfNb7rbBM5xcac1LmF9kjnOQ\n" + "uAw1jsCNE82QHwWMlXOqaZCEJsnttNo0Y7yaSR/ChbGJ54XCp+Lx2acyTeH9cBWU\n" + "de8/sKAQ4NqpbEP01pBH4+1mPu2MYWjVWVicUxmw0mJ3cfkJCWUzt0nC4ls8+Itk\n" + "7XliKb216Z9uQXu/zD/JGkxAljnFs1jXCX4NyWz46xnJFzXbYCeyQnBz0tUbAvgg\n" + "uRdryYtHzD46hd8LTXH6oK2gV64ILAhDnRb1aBjnCXxbex24XoW3hjSrKGTdNsXA\n" + "RMWU/8QZaoiBAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAFIYDBcbit2kOMrHECZK\n" + "ctem40A3s+0ZifzZ2KLhW8dTr/2Zb6DnlqVm2iUOV4cG/o1RAn/HzkQQuWEq+oBG\n" + "yOPVHudvCyGs+2ZQWudgAv9xq8N7KtZwJhnn42c2YSoreqRXDQgJqGFatyr+XdR7\n" + "gdQapLI4BFbZToeXp49Nl+q9330hKaSmIYmWEZ7R/33R64PU2el7X9/apYEcuZQT\n" + "+FjEqcO1lJ8/dTwM/2C1BJZqUeFTAu+ac1M+4//qyJRUUc6xSJLhiens8atWaxwL\n" + "eBCT8fCY8oPOwA1eImc/yWWmWXpv8bBWVe8OeLCMKM/OZoIdFqQpqSdcyGoh/kIW\n" + "Dws=\n"; + const time_t now = 1535046996; + + tor_x509_cert_t *cert = cert_from_der64(certificate); + tt_assert(cert); + + tt_assert(tor_tls_cert_is_valid(LOG_ERR, cert, cert, now, 0)); + + tt_assert(tor_tls_cert_is_valid(LOG_ERR, cert, cert, + now-TOR_X509_FUTURE_SLOP, 0)); + tt_assert(tor_tls_cert_is_valid(LOG_ERR, cert, cert, + now+365*86400+TOR_X509_PAST_SLOP - 3600, 0)); + + tt_assert(! tor_tls_cert_is_valid(LOG_INFO, cert, cert, + now-TOR_X509_FUTURE_SLOP - 3600, 0)); + tt_assert(! tor_tls_cert_is_valid(LOG_INFO, cert, cert, + now+365*86400+TOR_X509_FUTURE_SLOP, 0)); + + done: + tor_x509_cert_free(cert); +} + +#define TEST(name) { #name, test_x509_ ## name, TT_FORK, 0, NULL } + +struct testcase_t x509_tests[] = { + TEST(cert_new_failing_digest), + TEST(consume_ec_cert), + TEST(reject_tiny_keys), + TEST(expiration), + END_OF_TESTCASES +}; diff --git a/src/test/test_zero_length_keys.sh b/src/test/test_zero_length_keys.sh index f85edb68db..84ca513b0a 100755 --- a/src/test/test_zero_length_keys.sh +++ b/src/test/test_zero_length_keys.sh @@ -3,8 +3,8 @@ exitcode=0 -"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/or/tor" -z || exitcode=1 -"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/or/tor" -d || exitcode=1 -"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/or/tor" -e || exitcode=1 +"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/app/tor" -z || exitcode=1 +"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/app/tor" -d || exitcode=1 +"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/app/tor" -e || exitcode=1 exit ${exitcode} diff --git a/src/test/testing_common.c b/src/test/testing_common.c index 52729147b2..c52683afca 100644 --- a/src/test/testing_common.c +++ b/src/test/testing_common.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -8,19 +8,34 @@ * \brief Common pieces to implement unit tests. **/ +#define MAINLOOP_PRIVATE #include "orconfig.h" -#include "or.h" -#include "control.h" -#include "config.h" -#include "rephist.h" -#include "backtrace.h" -#include "test.h" -#include "channelpadding.h" +#include "core/or/or.h" +#include "feature/control/control.h" +#include "app/config/config.h" +#include "lib/crypt_ops/crypto_dh.h" +#include "lib/crypt_ops/crypto_ed25519.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "feature/stats/predict_ports.h" +#include "feature/stats/rephist.h" +#include "lib/err/backtrace.h" +#include "test/test.h" +#include "core/or/channelpadding.h" +#include "core/mainloop/mainloop.h" +#include "lib/compress/compress.h" +#include "lib/evloop/compat_libevent.h" +#include "lib/crypt_ops/crypto_init.h" #include <stdio.h> #ifdef HAVE_FCNTL_H #include <fcntl.h> #endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif #ifdef _WIN32 /* For mkdir() */ @@ -29,13 +44,6 @@ #include <dirent.h> #endif /* defined(_WIN32) */ -#include "or.h" - -#ifdef USE_DMALLOC -#include <dmalloc.h> -#include "main.h" -#endif - /** Temporary directory (set up by setup_directory) under which we store all * our files during testing. */ static char temp_dir[256]; @@ -106,8 +114,8 @@ get_fname_suffix(const char *name, const char *suffix) setup_directory(); if (!name) return temp_dir; - tor_snprintf(buf,sizeof(buf),"%s/%s%s%s",temp_dir,name,suffix ? "_" : "", - suffix ? suffix : ""); + tor_snprintf(buf,sizeof(buf),"%s%s%s%s%s", temp_dir, PATH_SEPARATOR, name, + suffix ? "_" : "", suffix ? suffix : ""); return buf; } @@ -216,6 +224,21 @@ an_assertion_failed(void) tinytest_set_test_failed_(); } +void tinytest_prefork(void); +void tinytest_postfork(void); +void +tinytest_prefork(void) +{ + free_pregenerated_keys(); + crypto_prefork(); +} +void +tinytest_postfork(void) +{ + crypto_postfork(); + init_pregenerated_keys(); +} + /** Main entry point for unit test code: parse the command line, and run * some unit tests. */ int @@ -230,13 +253,6 @@ main(int c, const char **v) /* We must initialise logs before we call tor_assert() */ init_logging(1); -#ifdef USE_DMALLOC - { - int r = crypto_use_tor_alloc_functions(); - tor_assert(r == 0); - } -#endif /* defined(USE_DMALLOC) */ - update_approx_time(time(NULL)); options = options_new(); tor_threads_init(); @@ -285,13 +301,13 @@ main(int c, const char **v) printf("Can't initialize crypto subsystem; exiting.\n"); return 1; } - crypto_set_tls_dh_prime(); if (crypto_seed_rng() < 0) { printf("Couldn't seed RNG; exiting.\n"); return 1; } rep_hist_init(); setup_directory(); + initialize_mainloop_events(); options_init(options); options->DataDirectory = tor_strdup(temp_dir); tor_asprintf(&options->KeyDirectory, "%s"PATH_SEPARATOR"keys", @@ -317,10 +333,7 @@ main(int c, const char **v) int have_failed = (tinytest_main(c, v, testgroups) != 0); free_pregenerated_keys(); -#ifdef USE_DMALLOC - tor_free_all(0); - dmalloc_log_unfreed(); -#endif + crypto_global_cleanup(); if (have_failed) @@ -328,4 +341,3 @@ main(int c, const char **v) else return 0; } - diff --git a/src/test/testing_rsakeys.c b/src/test/testing_rsakeys.c index 7a24c0ed14..c8062b82d5 100644 --- a/src/test/testing_rsakeys.c +++ b/src/test/testing_rsakeys.c @@ -1,11 +1,12 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2017, The Tor Project, Inc. */ + * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +#include "lib/crypt_ops/crypto_rand.h" #include "orconfig.h" -#include "or.h" -#include "test.h" +#include "core/or/or.h" +#include "test/test.h" /** Define this if unit tests spend too much time generating public keys. * This module is meant to save time by using a bunch of pregenerated RSA @@ -489,7 +490,7 @@ crypto_pk_generate_key_with_bits__get_cached(crypto_pk_t *env, int bits) { if (bits == 1024 || bits == 2048) { crypto_pk_t *newkey = pk_generate_internal(bits); - crypto_pk_assign_(env, newkey); + crypto_pk_assign_private(env, newkey); crypto_pk_free(newkey); } else { return crypto_pk_generate_key_with_bits__real(env, bits); @@ -543,4 +544,3 @@ init_pregenerated_keys(void) crypto_pk_generate_key_with_bits__get_cached); #endif /* defined(USE_PREGENERATED_RSA_KEYS) */ } - |