aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml24
-rw-r--r--ChangeLog168
-rw-r--r--ReleaseNotes168
-rw-r--r--changes/bug219004
-rw-r--r--changes/bug230824
-rw-r--r--changes/bug243936
-rw-r--r--changes/bug277073
-rw-r--r--changes/bug277415
-rw-r--r--changes/bug279486
-rw-r--r--changes/bug27963_timeradd4
-rw-r--r--changes/bug281277
-rw-r--r--changes/bug282024
-rw-r--r--changes/feature272445
-rw-r--r--changes/rust_asan8
-rw-r--r--changes/ticket278384
-rw-r--r--changes/ticket279133
-rw-r--r--changes/ticket279954
-rw-r--r--changes/ticket280063
-rw-r--r--changes/ticket280103
-rw-r--r--changes/ticket280263
-rw-r--r--configure.ac11
-rw-r--r--doc/HACKING/Maintaining.md113
-rw-r--r--doc/HACKING/ReleasingTor.md10
-rw-r--r--doc/tor.1.txt37
-rw-r--r--link_rust.sh.in10
-rwxr-xr-xscripts/codegen/run_trunnel.sh4
-rwxr-xr-xscripts/test/chutney-git-bisect.sh6
-rw-r--r--src/feature/control/control.c6
-rw-r--r--src/feature/dirauth/dirvote.c19
-rw-r--r--src/feature/dircache/consdiffmgr.c83
-rw-r--r--src/feature/dircache/consdiffmgr.h11
-rw-r--r--src/feature/dircache/dirserv.c5
-rw-r--r--src/feature/dircache/dirserv.h1
-rw-r--r--src/feature/dirclient/dirclient.c22
-rw-r--r--src/feature/dircommon/consdiff.c42
-rw-r--r--src/feature/dircommon/consdiff.h15
-rw-r--r--src/feature/dirparse/authcert_parse.c16
-rw-r--r--src/feature/dirparse/authcert_parse.h1
-rw-r--r--src/feature/dirparse/microdesc_parse.c6
-rw-r--r--src/feature/dirparse/ns_parse.c55
-rw-r--r--src/feature/dirparse/ns_parse.h10
-rw-r--r--src/feature/dirparse/parsecommon.c2
-rw-r--r--src/feature/hs/hs_config.c30
-rw-r--r--src/feature/hs/hs_descriptor.c32
-rw-r--r--src/feature/hs/hs_service.c148
-rw-r--r--src/feature/hs/hs_service.h75
-rw-r--r--src/feature/nodelist/authcert.c3
-rw-r--r--src/feature/nodelist/networkstatus.c96
-rw-r--r--src/feature/nodelist/networkstatus.h4
-rw-r--r--src/feature/nodelist/nodelist.c18
-rw-r--r--src/feature/relay/dns.c91
-rw-r--r--src/feature/relay/dns.h5
-rw-r--r--src/feature/relay/router.c2
-rw-r--r--src/lib/net/address.c12
-rw-r--r--src/lib/net/inaddr.c8
-rw-r--r--src/lib/thread/.may_include1
-rw-r--r--src/lib/thread/compat_pthreads.c1
-rw-r--r--src/rust/Cargo.lock1
-rw-r--r--src/rust/Cargo.toml16
-rw-r--r--src/rust/crypto/Cargo.toml1
-rw-r--r--src/rust/external/Cargo.toml6
-rw-r--r--src/rust/external/lib.rs2
-rw-r--r--src/rust/protover/Cargo.toml1
-rw-r--r--src/rust/protover/ffi.rs19
-rw-r--r--src/rust/smartlist/Cargo.toml1
-rw-r--r--src/rust/smartlist/lib.rs9
-rw-r--r--src/rust/tor_allocate/Cargo.toml1
-rw-r--r--src/rust/tor_allocate/lib.rs5
-rw-r--r--src/rust/tor_log/Cargo.toml1
-rw-r--r--src/rust/tor_rust/Cargo.toml2
-rw-r--r--src/rust/tor_util/Cargo.toml1
-rw-r--r--src/test/bench.c6
-rwxr-xr-xsrc/test/bt_test.py10
-rw-r--r--src/test/fuzz/fuzz_consensus.c6
-rw-r--r--src/test/fuzz/fuzz_diff.c32
-rw-r--r--src/test/fuzz/fuzz_diff_apply.c13
-rw-r--r--src/test/fuzz/fuzz_vrs.c16
-rw-r--r--src/test/include.am3
-rw-r--r--src/test/test_addr.c56
-rw-r--r--src/test/test_address.c75
-rw-r--r--src/test/test_consdiff.c94
-rw-r--r--src/test/test_consdiffmgr.c41
-rw-r--r--src/test/test_dir.c44
-rw-r--r--src/test/test_dir_common.c17
-rw-r--r--src/test/test_dir_handle_get.c18
-rw-r--r--src/test/test_dns.c66
-rw-r--r--src/test/test_hs_config.c16
-rw-r--r--src/test/test_hs_service.c4
-rw-r--r--src/test/test_routerlist.c19
-rwxr-xr-xsrc/test/test_rust.sh10
-rw-r--r--src/test/test_shared_random.c12
-rw-r--r--src/test/test_util.c13
92 files changed, 1599 insertions, 485 deletions
diff --git a/.travis.yml b/.travis.yml
index ec1748e67b..b5713d6933 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -33,12 +33,8 @@ env:
## We don't list default variable values, because we set the defaults
## in global (or the default is unset)
-
- ## We turn off hardening for Rust builds, because they are incompatible,
- ## and it's going to take a while for them to be fixed. See:
- ## https:/trac.torproject.org/projects/tor/ticket/25386
- ## https:/trac.torproject.org/projects/tor/ticket/26398
## TOR_RUST_DEPENDENCIES is spelt RUST_DEPENDENCIES in 0.3.2
- - RUST_OPTIONS="--enable-rust" TOR_RUST_DEPENDENCIES=true HARDENING_OPTIONS=""
+ - RUST_OPTIONS="--enable-rust" TOR_RUST_DEPENDENCIES=true
matrix:
## include creates builds with gcc, linux, sudo: false
@@ -51,11 +47,12 @@ matrix:
# - env: HARDENING_OPTIONS=""
## We check asciidoc with distcheck, to make sure we remove doc products
- env: DISTCHECK="yes" ASCIIDOC_OPTIONS=""
+ # We clone our stem repo and run `make test-stem`
+ - env: TEST_STEM="yes"
## Check rust online with distcheck, to make sure we remove rust products
- ## But without hardening (see above)
- - env: DISTCHECK="yes" RUST_OPTIONS="--enable-rust --enable-cargo-online-mode" HARDENING_OPTIONS=""
+ - env: DISTCHECK="yes" RUST_OPTIONS="--enable-rust --enable-cargo-online-mode"
## Check disable module dirauth with and without rust
- - env: MODULES_OPTIONS="--disable-module-dirauth" RUST_OPTIONS="--enable-rust" TOR_RUST_DEPENDENCIES=true HARDENING_OPTIONS=""
+ - env: MODULES_OPTIONS="--disable-module-dirauth" RUST_OPTIONS="--enable-rust" TOR_RUST_DEPENDENCIES=true
- env: MODULES_OPTIONS="--disable-module-dirauth"
## Check NSS
- env: NSS_OPTIONS="--enable-nss"
@@ -179,11 +176,12 @@ install:
- if [[ "$ASCIIDOC_OPTIONS" == "" ]] && [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export XML_CATALOG_FILES="/usr/local/etc/xml/catalog"; fi
## If we're using Rust, download rustup
- if [[ "$RUST_OPTIONS" != "" ]]; then curl -Ssf -o rustup.sh https://sh.rustup.rs; fi
- ## Install the stable channels of rustc and cargo and setup our toolchain environment
- - if [[ "$RUST_OPTIONS" != "" ]]; then sh rustup.sh -y --default-toolchain stable; fi
+ ## Install the nightly channels of rustc and cargo and setup our toolchain environment
+ - if [[ "$RUST_OPTIONS" != "" ]]; then sh rustup.sh -y --default-toolchain nightly; fi
- if [[ "$RUST_OPTIONS" != "" ]]; then source $HOME/.cargo/env; fi
## If we're testing rust builds in offline-mode, then set up our vendored dependencies
- if [[ "$TOR_RUST_DEPENDENCIES" == "true" ]]; then export TOR_RUST_DEPENDENCIES=$PWD/src/ext/rust/crates; fi
+ - if [[ "$TEST_STEM" != "" ]]; then git clone --depth 1 https://github.com/torproject/stem.git ; export STEM_SOURCE_DIR=`pwd`/stem; fi
##
## Finally, list installed package versions
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then dpkg-query --show; fi
@@ -195,6 +193,7 @@ install:
- if [[ "$RUST_OPTIONS" != "" ]]; then rustup --version; fi
- if [[ "$RUST_OPTIONS" != "" ]]; then rustc --version; fi
- if [[ "$RUST_OPTIONS" != "" ]]; then cargo --version; fi
+ - if [[ "$TEST_STEM" != "" ]]; then pushd stem; python -c "from stem import stem; print(stem.__version__);"; git log -1; popd; fi
script:
- ./autogen.sh
@@ -202,8 +201,9 @@ script:
- echo "Configure flags are $CONFIGURE_FLAGS"
- ./configure $CONFIGURE_FLAGS
## We run `make check` because that's what https://jenkins.torproject.org does.
- - if [[ "$DISTCHECK" == "" ]]; then make check; fi
- - if [[ "$DISTCHECK" != "" ]]; then make distcheck DISTCHECK_CONFIGURE_FLAGS="$CONFIGURE_FLAGS"; fi
+ - if [[ "$DISTCHECK" == "" && "$TEST_STEM" == "" ]]; then make check; fi
+ - if [[ "$TEST_STEM" != "" ]]; then make src/app/tor test-stem; fi
+ - if [[ "$DISTCHECK" != "" && "$TEST_STEM" == "" ]]; then make distcheck DISTCHECK_CONFIGURE_FLAGS="$CONFIGURE_FLAGS"; fi
after_failure:
## configure will leave a log file with more details of config failures.
diff --git a/ChangeLog b/ChangeLog
index 6c043638bf..b296480253 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,171 @@
+Changes in version 0.3.4.9 - 2018-11-02
+ Tor 0.3.4.9 is the second stable release in its series; it backports
+ numerous fixes, including a fix for a bandwidth management bug that
+ was causing memory exhaustion on relays. Anyone running an earlier
+ version of Tor 0.3.4.9 should upgrade.
+
+ o Major bugfixes (compilation, backport from 0.3.5.3-alpha):
+ - Fix compilation on ARM (and other less-used CPUs) when compiling
+ with OpenSSL before 1.1. Fixes bug 27781; bugfix on 0.3.4.1-alpha.
+
+ o Major bugfixes (mainloop, bootstrap, backport from 0.3.5.3-alpha):
+ - Make sure Tor bootstraps and works properly if only the
+ ControlPort is set. Prior to this fix, Tor would only bootstrap
+ when a client port was set (Socks, Trans, NATD, DNS or HTTPTunnel
+ port). Fixes bug 27849; bugfix on 0.3.4.1-alpha.
+
+ o Major bugfixes (relay, backport from 0.3.5.3-alpha):
+ - When our write bandwidth limit is exhausted, stop writing on the
+ connection. Previously, we had a typo in the code that would make
+ us stop reading instead, leading to relay connections being stuck
+ indefinitely and consuming kernel RAM. Fixes bug 28089; bugfix
+ on 0.3.4.1-alpha.
+
+ o Major bugfixes (restart-in-process, backport from 0.3.5.1-alpha):
+ - Fix a use-after-free error that could be caused by passing Tor an
+ impossible set of options that would fail during options_act().
+ Fixes bug 27708; bugfix on 0.3.3.1-alpha.
+
+ o Minor features (continuous integration, backport from 0.3.5.1-alpha):
+ - Don't do a distcheck with --disable-module-dirauth in Travis.
+ Implements ticket 27252.
+ - Only run one online rust build in Travis, to reduce network
+ errors. Skip offline rust builds on Travis for Linux gcc, because
+ they're redundant. Implements ticket 27252.
+ - Skip gcc on OSX in Travis CI, because it's rarely used. Skip a
+ duplicate hardening-off build in Travis on Tor 0.2.9. Skip gcc on
+ Linux with default settings, because all the non-default builds
+ use gcc on Linux. Implements ticket 27252.
+
+ o Minor features (continuous integration, backport from 0.3.5.3-alpha):
+ - Use the Travis Homebrew addon to install packages on macOS during
+ Travis CI. The package list is the same, but the Homebrew addon
+ does not do a `brew update` by default. Implements ticket 27738.
+
+ o Minor features (geoip):
+ - Update geoip and geoip6 to the October 9 2018 Maxmind GeoLite2
+ Country database. Closes ticket 27991.
+
+ o Minor bugfixes (32-bit OSX and iOS, timing, backport from 0.3.5.2-alpha):
+ - Fix an integer overflow bug in our optimized 32-bit millisecond-
+ difference algorithm for 32-bit Apple platforms. Previously, it
+ would overflow when calculating the difference between two times
+ more than 47 days apart. Fixes part of bug 27139; bugfix
+ on 0.3.4.1-alpha.
+ - Improve the precision of our 32-bit millisecond difference
+ algorithm for 32-bit Apple platforms. Fixes part of bug 27139;
+ bugfix on 0.3.4.1-alpha.
+ - Relax the tolerance on the mainloop/update_time_jumps test when
+ running on 32-bit Apple platforms. Fixes part of bug 27139; bugfix
+ on 0.3.4.1-alpha.
+
+ o Minor bugfixes (C correctness, to appear in 0.3.5.4-alpha):
+ - Avoid undefined behavior in an end-of-string check when parsing
+ the BEGIN line in a directory object. Fixes bug 28202; bugfix
+ on 0.2.0.3-alpha.
+
+ o Minor bugfixes (CI, appveyor, to appear in 0.3.5.4-alpha):
+ - Only install the necessary mingw packages during our appveyor
+ builds. This change makes the build a little faster, and prevents
+ a conflict with a preinstalled mingw openssl that appveyor now
+ ships. Fixes bugs 27943 and 27765; bugfix on 0.3.4.2-alpha.
+
+ o Minor bugfixes (code safety, backport from 0.3.5.3-alpha):
+ - Rewrite our assertion macros so that they no longer suppress the
+ compiler's -Wparentheses warnings. Fixes bug 27709; bugfix
+
+ o Minor bugfixes (continuous integration, backport from 0.3.5.1-alpha):
+ - Stop reinstalling identical packages in our Windows CI. Fixes bug
+ 27464; bugfix on 0.3.4.1-alpha.
+
+ o Minor bugfixes (directory authority, to appear in 0.3.5.4-alpha):
+ - Log additional info when we get a relay that shares an ed25519 ID
+ with a different relay, instead making a BUG() warning. Fixes bug
+ 27800; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (directory connection shutdown, backport from 0.3.5.1-alpha):
+ - Avoid a double-close when shutting down a stalled directory
+ connection. Fixes bug 26896; bugfix on 0.3.4.1-alpha.
+
+ o Minor bugfixes (HTTP tunnel, backport from 0.3.5.1-alpha):
+ - Fix a bug warning when closing an HTTP tunnel connection due to an
+ HTTP request we couldn't handle. Fixes bug 26470; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor bugfixes (netflow padding, backport from 0.3.5.1-alpha):
+ - Ensure circuitmux queues are empty before scheduling or sending
+ padding. Fixes bug 25505; bugfix on 0.3.1.1-alpha.
+
+ o Minor bugfixes (onion service v3, backport from 0.3.5.1-alpha):
+ - When the onion service directory can't be created or has the wrong
+ permissions, do not log a stack trace. Fixes bug 27335; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor bugfixes (onion service v3, backport from 0.3.5.2-alpha):
+ - Close all SOCKS request (for the same .onion) if the newly fetched
+ descriptor is unusable. Before that, we would close only the first
+ one leaving the other hanging and let to time out by themselves.
+ Fixes bug 27410; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (onion service v3, backport from 0.3.5.3-alpha):
+ - When selecting a v3 rendezvous point, don't only look at the
+ protover, but also check whether the curve25519 onion key is
+ present. This way we avoid picking a relay that supports the v3
+ rendezvous but for which we don't have the microdescriptor. Fixes
+ bug 27797; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (protover, backport from 0.3.5.3-alpha):
+ - Reject protocol names containing bytes other than alphanumeric
+ characters and hyphens ([A-Za-z0-9-]). Fixes bug 27316; bugfix
+ on 0.2.9.4-alpha.
+
+ o Minor bugfixes (rust, backport from 0.3.5.1-alpha):
+ - Compute protover votes correctly in the rust version of the
+ protover code. Previously, the protover rewrite in 24031 allowed
+ repeated votes from the same voter for the same protocol version
+ to be counted multiple times in protover_compute_vote(). Fixes bug
+ 27649; bugfix on 0.3.3.5-rc.
+ - Reject protover names that contain invalid characters. Fixes bug
+ 27687; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (rust, backport from 0.3.5.2-alpha):
+ - protover_all_supported() would attempt to allocate up to 16GB on
+ some inputs, leading to a potential memory DoS. Fixes bug 27206;
+ bugfix on 0.3.3.5-rc.
+
+ o Minor bugfixes (rust, directory authority, to appear in 0.3.5.4-alpha):
+ - Fix an API mismatch in the rust implementation of
+ protover_compute_vote(). This bug could have caused crashes on any
+ directory authorities running Tor with Rust (which we do not yet
+ recommend). Fixes bug 27741; bugfix on 0.3.3.6.
+
+ o Minor bugfixes (rust, to appear in 0.3.5.4-alpha):
+ - Fix a potential null dereference in protover_all_supported(). Add
+ a test for it. Fixes bug 27804; bugfix on 0.3.3.1-alpha.
+ - Return a string that can be safely freed by C code, not one
+ created by the rust allocator, in protover_all_supported(). Fixes
+ bug 27740; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (testing, backport from 0.3.5.1-alpha):
+ - If a unit test running in a subprocess exits abnormally or with a
+ nonzero status code, treat the test as having failed, even if the
+ test reported success. Without this fix, memory leaks don't cause
+ the tests to fail, even with LeakSanitizer. Fixes bug 27658;
+ bugfix on 0.2.2.4-alpha.
+
+ o Minor bugfixes (testing, backport from 0.3.5.3-alpha):
+ - Make the hs_service tests use the same time source when creating
+ the introduction point and when testing it. Now tests work better
+ on very slow systems like ARM or Travis. Fixes bug 27810; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor bugfixes (testing, to appear in 0.3.5.4-alpha):
+ - Treat backtrace test failures as expected on BSD-derived systems
+ (NetBSD, OpenBSD, and macOS/Darwin) until we solve bug 17808.
+ (FreeBSD failures have been treated as expected since 18204 in
+ 0.2.8.) Fixes bug 27948; bugfix on 0.2.5.2-alpha.
+
+
Changes in version 0.3.5.3-alpha - 2018-10-17
Tor 0.3.5.3-alpha fixes several bugs, mostly from previous 0.3.5.x
versions. One important fix for relays addresses a problem with rate-
diff --git a/ReleaseNotes b/ReleaseNotes
index dd7e823215..e0a25a74b7 100644
--- a/ReleaseNotes
+++ b/ReleaseNotes
@@ -2,6 +2,174 @@ This document summarizes new features and bugfixes in each stable
release of Tor. If you want to see more detailed descriptions of the
changes in each development snapshot, see the ChangeLog file.
+Changes in version 0.3.4.9 - 2018-11-02
+ Tor 0.3.4.9 is the second stable release in its series; it backports
+ numerous fixes, including a fix for a bandwidth management bug that
+ was causing memory exhaustion on relays. Anyone running an earlier
+ version of Tor 0.3.4.9 should upgrade.
+
+ o Major bugfixes (compilation, backport from 0.3.5.3-alpha):
+ - Fix compilation on ARM (and other less-used CPUs) when compiling
+ with OpenSSL before 1.1. Fixes bug 27781; bugfix on 0.3.4.1-alpha.
+
+ o Major bugfixes (mainloop, bootstrap, backport from 0.3.5.3-alpha):
+ - Make sure Tor bootstraps and works properly if only the
+ ControlPort is set. Prior to this fix, Tor would only bootstrap
+ when a client port was set (Socks, Trans, NATD, DNS or HTTPTunnel
+ port). Fixes bug 27849; bugfix on 0.3.4.1-alpha.
+
+ o Major bugfixes (relay, backport from 0.3.5.3-alpha):
+ - When our write bandwidth limit is exhausted, stop writing on the
+ connection. Previously, we had a typo in the code that would make
+ us stop reading instead, leading to relay connections being stuck
+ indefinitely and consuming kernel RAM. Fixes bug 28089; bugfix
+ on 0.3.4.1-alpha.
+
+ o Major bugfixes (restart-in-process, backport from 0.3.5.1-alpha):
+ - Fix a use-after-free error that could be caused by passing Tor an
+ impossible set of options that would fail during options_act().
+ Fixes bug 27708; bugfix on 0.3.3.1-alpha.
+
+ o Minor features (continuous integration, backport from 0.3.5.1-alpha):
+ - Don't do a distcheck with --disable-module-dirauth in Travis.
+ Implements ticket 27252.
+ - Only run one online rust build in Travis, to reduce network
+ errors. Skip offline rust builds on Travis for Linux gcc, because
+ they're redundant. Implements ticket 27252.
+ - Skip gcc on OSX in Travis CI, because it's rarely used. Skip a
+ duplicate hardening-off build in Travis on Tor 0.2.9. Skip gcc on
+ Linux with default settings, because all the non-default builds
+ use gcc on Linux. Implements ticket 27252.
+
+ o Minor features (continuous integration, backport from 0.3.5.3-alpha):
+ - Use the Travis Homebrew addon to install packages on macOS during
+ Travis CI. The package list is the same, but the Homebrew addon
+ does not do a `brew update` by default. Implements ticket 27738.
+
+ o Minor features (geoip):
+ - Update geoip and geoip6 to the October 9 2018 Maxmind GeoLite2
+ Country database. Closes ticket 27991.
+
+ o Minor bugfixes (32-bit OSX and iOS, timing, backport from 0.3.5.2-alpha):
+ - Fix an integer overflow bug in our optimized 32-bit millisecond-
+ difference algorithm for 32-bit Apple platforms. Previously, it
+ would overflow when calculating the difference between two times
+ more than 47 days apart. Fixes part of bug 27139; bugfix
+ on 0.3.4.1-alpha.
+ - Improve the precision of our 32-bit millisecond difference
+ algorithm for 32-bit Apple platforms. Fixes part of bug 27139;
+ bugfix on 0.3.4.1-alpha.
+ - Relax the tolerance on the mainloop/update_time_jumps test when
+ running on 32-bit Apple platforms. Fixes part of bug 27139; bugfix
+ on 0.3.4.1-alpha.
+
+ o Minor bugfixes (C correctness, to appear in 0.3.5.4-alpha):
+ - Avoid undefined behavior in an end-of-string check when parsing
+ the BEGIN line in a directory object. Fixes bug 28202; bugfix
+ on 0.2.0.3-alpha.
+
+ o Minor bugfixes (CI, appveyor, to appear in 0.3.5.4-alpha):
+ - Only install the necessary mingw packages during our appveyor
+ builds. This change makes the build a little faster, and prevents
+ a conflict with a preinstalled mingw openssl that appveyor now
+ ships. Fixes bugs 27943 and 27765; bugfix on 0.3.4.2-alpha.
+
+ o Minor bugfixes (code safety, backport from 0.3.5.3-alpha):
+ - Rewrite our assertion macros so that they no longer suppress the
+ compiler's -Wparentheses warnings. Fixes bug 27709; bugfix
+
+ o Minor bugfixes (continuous integration, backport from 0.3.5.1-alpha):
+ - Stop reinstalling identical packages in our Windows CI. Fixes bug
+ 27464; bugfix on 0.3.4.1-alpha.
+
+ o Minor bugfixes (directory authority, to appear in 0.3.5.4-alpha):
+ - Log additional info when we get a relay that shares an ed25519 ID
+ with a different relay, instead making a BUG() warning. Fixes bug
+ 27800; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (directory connection shutdown, backport from 0.3.5.1-alpha):
+ - Avoid a double-close when shutting down a stalled directory
+ connection. Fixes bug 26896; bugfix on 0.3.4.1-alpha.
+
+ o Minor bugfixes (HTTP tunnel, backport from 0.3.5.1-alpha):
+ - Fix a bug warning when closing an HTTP tunnel connection due to an
+ HTTP request we couldn't handle. Fixes bug 26470; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor bugfixes (netflow padding, backport from 0.3.5.1-alpha):
+ - Ensure circuitmux queues are empty before scheduling or sending
+ padding. Fixes bug 25505; bugfix on 0.3.1.1-alpha.
+
+ o Minor bugfixes (onion service v3, backport from 0.3.5.1-alpha):
+ - When the onion service directory can't be created or has the wrong
+ permissions, do not log a stack trace. Fixes bug 27335; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor bugfixes (onion service v3, backport from 0.3.5.2-alpha):
+ - Close all SOCKS request (for the same .onion) if the newly fetched
+ descriptor is unusable. Before that, we would close only the first
+ one leaving the other hanging and let to time out by themselves.
+ Fixes bug 27410; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (onion service v3, backport from 0.3.5.3-alpha):
+ - When selecting a v3 rendezvous point, don't only look at the
+ protover, but also check whether the curve25519 onion key is
+ present. This way we avoid picking a relay that supports the v3
+ rendezvous but for which we don't have the microdescriptor. Fixes
+ bug 27797; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (protover, backport from 0.3.5.3-alpha):
+ - Reject protocol names containing bytes other than alphanumeric
+ characters and hyphens ([A-Za-z0-9-]). Fixes bug 27316; bugfix
+ on 0.2.9.4-alpha.
+
+ o Minor bugfixes (rust, backport from 0.3.5.1-alpha):
+ - Compute protover votes correctly in the rust version of the
+ protover code. Previously, the protover rewrite in 24031 allowed
+ repeated votes from the same voter for the same protocol version
+ to be counted multiple times in protover_compute_vote(). Fixes bug
+ 27649; bugfix on 0.3.3.5-rc.
+ - Reject protover names that contain invalid characters. Fixes bug
+ 27687; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (rust, backport from 0.3.5.2-alpha):
+ - protover_all_supported() would attempt to allocate up to 16GB on
+ some inputs, leading to a potential memory DoS. Fixes bug 27206;
+ bugfix on 0.3.3.5-rc.
+
+ o Minor bugfixes (rust, directory authority, to appear in 0.3.5.4-alpha):
+ - Fix an API mismatch in the rust implementation of
+ protover_compute_vote(). This bug could have caused crashes on any
+ directory authorities running Tor with Rust (which we do not yet
+ recommend). Fixes bug 27741; bugfix on 0.3.3.6.
+
+ o Minor bugfixes (rust, to appear in 0.3.5.4-alpha):
+ - Fix a potential null dereference in protover_all_supported(). Add
+ a test for it. Fixes bug 27804; bugfix on 0.3.3.1-alpha.
+ - Return a string that can be safely freed by C code, not one
+ created by the rust allocator, in protover_all_supported(). Fixes
+ bug 27740; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (testing, backport from 0.3.5.1-alpha):
+ - If a unit test running in a subprocess exits abnormally or with a
+ nonzero status code, treat the test as having failed, even if the
+ test reported success. Without this fix, memory leaks don't cause
+ the tests to fail, even with LeakSanitizer. Fixes bug 27658;
+ bugfix on 0.2.2.4-alpha.
+
+ o Minor bugfixes (testing, backport from 0.3.5.3-alpha):
+ - Make the hs_service tests use the same time source when creating
+ the introduction point and when testing it. Now tests work better
+ on very slow systems like ARM or Travis. Fixes bug 27810; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor bugfixes (testing, to appear in 0.3.5.4-alpha):
+ - Treat backtrace test failures as expected on BSD-derived systems
+ (NetBSD, OpenBSD, and macOS/Darwin) until we solve bug 17808.
+ (FreeBSD failures have been treated as expected since 18204 in
+ 0.2.8.) Fixes bug 27948; bugfix on 0.2.5.2-alpha.
+
+
Changes in version 0.2.9.17 - 2018-09-10
Tor 0.2.9.17 backports numerous bugfixes from later versions of Tor.
diff --git a/changes/bug21900 b/changes/bug21900
new file mode 100644
index 0000000000..686cb6c584
--- /dev/null
+++ b/changes/bug21900
@@ -0,0 +1,4 @@
+ o Minor bugfixes (DNS):
+ - Gracefully handle empty or absent resolve.conf file by falling
+ back to using localhost DNS service and hoping it works. Fixes
+ bug 21900; bugfix on 0.2.1.10-alpha.
diff --git a/changes/bug23082 b/changes/bug23082
new file mode 100644
index 0000000000..fc4b52c364
--- /dev/null
+++ b/changes/bug23082
@@ -0,0 +1,4 @@
+ o Minor bugfixes (networking):
+ - Introduce additional checks into tor_addr_parse() to
+ reject certain incorrect inputs that previously were
+ not detected. Fixes bug 23082; bugfix on 0.2.0.10-alpha.
diff --git a/changes/bug24393 b/changes/bug24393
new file mode 100644
index 0000000000..e190192319
--- /dev/null
+++ b/changes/bug24393
@@ -0,0 +1,6 @@
+ o Minor features (ipv6):
+ - When using addrs_in_same_network_family(), check IPv6 subnets as well as
+ IPv4 ones where possible when a client chooses circuit paths. Previously,
+ we used this function only for IPv4 subnets. Closes ticket 24393. Patch
+ by Neel Chauhan.
+
diff --git a/changes/bug27707 b/changes/bug27707
new file mode 100644
index 0000000000..e114222741
--- /dev/null
+++ b/changes/bug27707
@@ -0,0 +1,3 @@
+ o Minor features (log messages):
+ - Improve log message in HSv3 service that could print out negative
+ revision counters. Closes ticket 27707. Patch by "ffmancera". \ No newline at end of file
diff --git a/changes/bug27741 b/changes/bug27741
new file mode 100644
index 0000000000..531e264b63
--- /dev/null
+++ b/changes/bug27741
@@ -0,0 +1,5 @@
+ o Minor bugfixes (rust, directory authority):
+ - Fix an API mismatch in the rust implementation of
+ protover_compute_vote(). This bug could have caused crashes on any
+ directory authorities running Tor with Rust (which we do not yet
+ recommend). Fixes bug 27741; bugfix on 0.3.3.6.
diff --git a/changes/bug27948 b/changes/bug27948
new file mode 100644
index 0000000000..fea16f3d0f
--- /dev/null
+++ b/changes/bug27948
@@ -0,0 +1,6 @@
+ o Minor bugfixes (tests):
+ - Treat backtrace test failures as expected on BSD-derived systems
+ (NetBSD, OpenBSD, and macOS/Darwin) until we solve bug 17808.
+ (FreeBSD failures have been treated as expected since 18204 in 0.2.8.)
+ Fixes bug 27948; bugfix on 0.2.5.2-alpha.
+
diff --git a/changes/bug27963_timeradd b/changes/bug27963_timeradd
new file mode 100644
index 0000000000..34b361cf8d
--- /dev/null
+++ b/changes/bug27963_timeradd
@@ -0,0 +1,4 @@
+ o Minor bugfixes (compilation, opensolaris):
+ - Add a missing include to compat_pthreads.c, to fix compilation
+ on OpenSolaris and its descendants. Fixes bug 27963; bugfix
+ on 0.3.5.1-alpha.
diff --git a/changes/bug28127 b/changes/bug28127
new file mode 100644
index 0000000000..541128c88e
--- /dev/null
+++ b/changes/bug28127
@@ -0,0 +1,7 @@
+ o Minor bugfixes (onion services):
+ - Unless we have explicitly set HiddenServiceVersion, detect the onion
+ service version and then look for invalid options. Previously, we
+ did the reverse, but that broke existing configs which were pointed
+ to a v2 hidden service and had options like HiddenServiceAuthorizeClient
+ set Fixes bug 28127; bugfix on 0.3.5.1-alpha. Patch by Neel Chauhan.
+
diff --git a/changes/bug28202 b/changes/bug28202
new file mode 100644
index 0000000000..182daac4f1
--- /dev/null
+++ b/changes/bug28202
@@ -0,0 +1,4 @@
+ o Minor bugfixes (C correctness):
+ - Avoid undefined behavior in an end-of-string check when parsing the
+ BEGIN line in a directory object. Fixes bug 28202; bugfix on
+ 0.2.0.3-alpha.
diff --git a/changes/feature27244 b/changes/feature27244
new file mode 100644
index 0000000000..a4debbbe53
--- /dev/null
+++ b/changes/feature27244
@@ -0,0 +1,5 @@
+ o Minor features (memory usage):
+ - Tor clients no longer need to keep the full text of a consensus in
+ memory in order to parse it, or apply a diff to it. Instead, they
+ use mmap() to read the consensus files from disk. Closes ticket
+ 27244.
diff --git a/changes/rust_asan b/changes/rust_asan
new file mode 100644
index 0000000000..1ca7ae6888
--- /dev/null
+++ b/changes/rust_asan
@@ -0,0 +1,8 @@
+ o Major bugfixes (compilation, rust):
+ - Rust tests can now build and run successfully with the
+ --enable-fragile-hardening option enabled.
+ Doing this currently requires the rust beta channel; it will
+ be possible with stable rust as of rust version 1.31 is out.
+ Patch from Alex Crichton.
+ Fixes bugs 27272, 27273, and 27274.
+ Bugfix on 0.3.1.1-alpha.
diff --git a/changes/ticket27838 b/changes/ticket27838
new file mode 100644
index 0000000000..1699730d7a
--- /dev/null
+++ b/changes/ticket27838
@@ -0,0 +1,4 @@
+ o Minor bugfixes (hidden service v3):
+ - Build the service descriptor signing key certificate before uploading so
+ we always have a fresh one leaving no chances for it to expire service
+ side. Fixes bug 27838; bugfix on 0.3.2.1-alpha.
diff --git a/changes/ticket27913 b/changes/ticket27913
new file mode 100644
index 0000000000..81ce725932
--- /dev/null
+++ b/changes/ticket27913
@@ -0,0 +1,3 @@
+ o Testing:
+ - Add new CI job to Travis configuration that runs stem-based
+ integration tests. Closes ticket 27913.
diff --git a/changes/ticket27995 b/changes/ticket27995
new file mode 100644
index 0000000000..8c75425749
--- /dev/null
+++ b/changes/ticket27995
@@ -0,0 +1,4 @@
+ o Minor bugfixes (hidden service v3, client authorization):
+ - Fix an assert() when adding a client authorization for the first time
+ and then sending a HUP signal to the service. Before that, tor would
+ stop abruptly. Fixes bug 27995; bugfix on 0.3.5.1-alpha.
diff --git a/changes/ticket28006 b/changes/ticket28006
new file mode 100644
index 0000000000..95a4b2cae4
--- /dev/null
+++ b/changes/ticket28006
@@ -0,0 +1,3 @@
+ o Code simplification and refactoring:
+ - Fix issues that shellcheck found in chutney-git-bisect.sh.
+ Resolves ticket 28006.
diff --git a/changes/ticket28010 b/changes/ticket28010
new file mode 100644
index 0000000000..4fca17d022
--- /dev/null
+++ b/changes/ticket28010
@@ -0,0 +1,3 @@
+ o Code simplification and refactoring:
+ - Fix shellcheck warnings in run_trunnel.sh. Resolves issue
+ 28010.
diff --git a/changes/ticket28026 b/changes/ticket28026
new file mode 100644
index 0000000000..a6911c2cab
--- /dev/null
+++ b/changes/ticket28026
@@ -0,0 +1,3 @@
+ o Documentation (hidden service manpage):
+ - Improve HSv3 client authorization by making some options more explicit
+ and detailed. Closes ticket 28026. Patch by "mtigas".
diff --git a/configure.ac b/configure.ac
index 292244f56f..b80aa821ad 100644
--- a/configure.ac
+++ b/configure.ac
@@ -812,6 +812,8 @@ fi
dnl Now check for particular libevent functions.
AC_CHECK_FUNCS([evutil_secure_rng_set_urandom_device_file \
evutil_secure_rng_add_bytes \
+ evdns_base_get_nameserver_addr \
+
])
LIBS="$save_LIBS"
@@ -1210,17 +1212,17 @@ dnl variable.
RUST_LINKER_OPTIONS=""
if test "x$have_clang" = "xyes"; then
if test "x$CFLAGS_ASAN" != "x"; then
- RUST_LINKER_OPTIONS="$RUST_LINKER_OPTIONS $CFLAGS_ASAN"
+ RUST_LINKER_OPTIONS="$RUST_LINKER_OPTIONS -Clink-arg=$CFLAGS_ASAN -Cdefault-linker-libraries"
fi
if test "x$CFLAGS_UBSAN" != "x"; then
- RUST_LINKER_OPTIONS="$RUST_LINKER_OPTIONS $CFLAGS_UBSAN"
+ RUST_LINKER_OPTIONS="$RUST_LINKER_OPTIONS -Clink-arg=$CFLAGS_UBSAN -Cdefault-linker-libraries"
fi
else
if test "x$CFLAGS_ASAN" != "x"; then
- RUST_LINKER_OPTIONS="$RUST_LINKER_OPTIONS -lasan"
+ RUST_LINKER_OPTIONS="$RUST_LINKER_OPTIONS -Clink-arg=-fsanitize=address -Cdefault-linker-libraries"
fi
if test "x$CFLAGS_UBSAN" != "x"; then
- RUST_LINKER_OPTIONS="$RUST_LINKER_OPTIONS -lubsan"
+ RUST_LINKER_OPTIONS="$RUST_LINKER_OPTIONS -Clink-arg=-fsanitize=undefined -Cdefault-linker-libraries"
fi
fi
AC_SUBST(RUST_LINKER_OPTIONS)
@@ -2416,7 +2418,6 @@ AC_CONFIG_FILES([
Doxyfile
Makefile
config.rust
- link_rust.sh
contrib/dist/suse/tor.sh
contrib/operator-tools/tor.logrotate
contrib/dist/tor.sh
diff --git a/doc/HACKING/Maintaining.md b/doc/HACKING/Maintaining.md
new file mode 100644
index 0000000000..22d62b5471
--- /dev/null
+++ b/doc/HACKING/Maintaining.md
@@ -0,0 +1,113 @@
+# Maintaining Tor
+
+This document details the duties and processes on maintaining the Tor code
+base.
+
+The first section describes who is the current Tor maintainer and what are the
+responsabilities. Tor has one main single maintainer but does have many
+committers and subsystem maintainers.
+
+The second third section describes how the **alpha and master** branches are
+maintained and by whom.
+
+Finally, the last section describes how the **stable** branches are maintained
+and by whom.
+
+This document does not cover how Tor is released, please see
+[ReleasingTor.md](ReleasingTor.md) for that information.
+
+## Tor Maintainer
+
+The current maintainer is Nick Mathewson <nickm@torproject.org>.
+
+The maintainer takes final decisions in terms of engineering, architecture and
+protocol design. Releasing Tor falls under their responsability.
+
+## Alpha and Master Branches
+
+The Tor repository always has at all time a **master** branch which contains
+the upstream ongoing development.
+
+It may also contains a branch for a released feature freezed version which is
+called the **alpha** branch. The git tag and version number is always
+postfixed with `-alpha[-dev]`. For example: `tor-0.3.5.0-alpha-dev` or
+`tor-0.3.5.3-alpha`.
+
+Tor is separated into subsystems and some of those are maintained by other
+developers than the main maintainer. Those people have commit access to the
+code base but only commit (in most cases) into the subsystem they maintain.
+
+Upstream merges are restricted to the alpha and master branches. Subsystem
+maintainers should never push a patch into a stable branch which is the
+responsability of the [stable branch maintainer](#stable-branches).
+
+### Who
+
+In alphabetical order, the following people have upstream commit access and
+maintain the following subsystems:
+
+- David Goulet <dgoulet@torproject.org>
+ * Onion Service (including Shared Random).
+ ***keywords:*** *[tor-hs]*
+ * Channels, Circuitmux, Connection, Scheduler.
+ ***keywords:*** *[tor-chan, tor-cmux, tor-sched, tor-conn]*
+ * Cell Logic (Handling/Parsing).
+ ***keywords:*** *[tor-cell]*
+ * Threading backend.
+ ***keywords:*** *[tor-thread]*
+
+- George Kadianakis <asn@torproject.org>
+ * Onion Service (including Shared Random).
+ ***keywords:*** *[tor-hs]*
+ * Guard.
+ ***keywords:*** *[tor-guard]*
+ * Pluggable Transport (excluding Bridge networking).
+ ***keywords:*** *[tor-pt]*
+
+### Tasks
+
+These are the tasks of a subsystem maintainer:
+
+1. Regurlarly go over `merge_ready` tickets relevant to the related subsystem
+ and for the current alpha or development (master branch) Milestone.
+
+2. A subsystem maintainer is expected to contribute to any design changes
+ (including proposals) or large patch set about the subsystem.
+
+3. Leave their ego at the door. Mistakes will be made but they have to be
+ taking care of seriously. Learn and move on quickly.
+
+### Merging Policy
+
+These are few important items to follow when merging code upstream:
+
+1. To merge code upstream, the patch must have passed our CI (currently
+ github.com/torproject), have a corresponding ticket and reviewed by
+ **at least** one person that is not the original coder.
+
+ Example A: If Alice writes a patch then Bob, a Tor network team member,
+ reviews it and flags it `merge_ready`. Then, the maintainter is required
+ to look at the patch and makes a decision.
+
+ Example B: If the maintainer writes a patch then Bob, a Tor network
+ team member, reviews it and flags it `merge_ready`, then the maintainer
+ can merge the code upstream.
+
+2. Maintainer makes sure the commit message should describe what was fixed
+ and, if it applies, how was it fixed. It should also always refer to
+ the ticket number.
+
+3. Trivial patches such as comment change, documentation, syntax issues or
+ typos can be merged without a ticket or reviewers.
+
+4. Tor uses the "merge forward" method that is if a patch applies to the
+ alpha branch, it has to be merged there first and then merged forward
+ into master.
+
+5. Maintainer should always consult with the network team about any doubts,
+ mis-understandings or unknowns of a patch. Final word will always go to the
+ main Tor maintainer.
+
+## Stable Branches
+
+(Currently being drafted and reviewed by the network team.)
diff --git a/doc/HACKING/ReleasingTor.md b/doc/HACKING/ReleasingTor.md
index 55a40fc89b..b5444afa96 100644
--- a/doc/HACKING/ReleasingTor.md
+++ b/doc/HACKING/ReleasingTor.md
@@ -36,10 +36,10 @@ new Tor release:
What about clang scan-build?
- Does 'make distcheck' complain?
+ Does `make distcheck` complain?
- How about 'make test-stem' and 'make test-network' and
- `make test-network-full`?
+ How about `make test-stem` and `make test-network` and
+ `make test-network-all`?
- Are all those tests still happy with --enable-expensive-hardening ?
@@ -79,7 +79,7 @@ new Tor release:
Present and imperative tense: not past.
- 'Relays', not 'servers' or 'nodes' or 'Tor relays'.
+ "Relays", not "servers" or "nodes" or "Tor relays".
"Stop FOOing", not "Fix a bug where we would FOO".
@@ -100,7 +100,7 @@ new Tor release:
For stable releases that backport things from later, we try to compose
their releases, we try to make sure that we keep the changelog entries
- identical to their original versions, with a 'backport from 0.x.y.z'
+ identical to their original versions, with a "backport from 0.x.y.z"
note added to each section. So in this case, once you have the items
from the changes files copied together, don't use them to build a new
changelog: instead, look up the corrected versions that were merged
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 406372433f..2f7a039cc4 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -1090,14 +1090,16 @@ The following options are useful only for clients (that is, if
**HiddenServiceAuthorizeClient** option.
[[ClientOnionAuthDir]] **ClientOnionAuthDir** __path__::
- Path to the directory containing the hidden service authorization file. The
- files MUST have the suffix ".auth_private". Each file is for a single
- onion address and their format is:
+ Path to the directory containing v3 hidden service authorization files.
+ Each file is for a single onion address, and the files MUST have the suffix
+ ".auth_private" (i.e. "bob_onion.auth_private"). The content format MUST be:
+
<onion-address>:descriptor:x25519:<base32-encoded-privkey>
+
- The <onion-address> MUST NOT have the ".onion" suffix. See the
- rend-spec-v3.txt Appendix G for more information.
+ The <onion-address> MUST NOT have the ".onion" suffix. The
+ <base32-encoded-privkey> is the base32 representation of the raw key bytes
+ only (32 bytes for x25519). See Appendix G in the rend-spec-v3.txt file of
+ https://spec.torproject.org/[torspec] for more information.
[[LongLivedPorts]] **LongLivedPorts** __PORTS__::
A list of ports for services that tend to have long-running connections
@@ -2211,7 +2213,8 @@ is non-zero):
__filename__. The file format is the same as the standard Unix
"**resolv.conf**" file (7). This option, like all other ServerDNS options,
only affects name lookups that your server does on behalf of clients.
- (Defaults to use the system DNS configuration.)
+ (Defaults to use the system DNS configuration or a localhost DNS service
+ in case no nameservers are found in a given configuration.)
[[ServerDNSAllowBrokenConfig]] **ServerDNSAllowBrokenConfig** **0**|**1**::
If this option is false, Tor exits immediately if there are problems
@@ -2839,7 +2842,8 @@ The following options are used to configure a hidden service.
clients without authorization any more. Generated authorization data can be
found in the hostname file. Clients need to put this authorization data in
their configuration file using **HidServAuth**. This option is only for v2
- services.
+ services; v3 services configure client authentication in a subdirectory of
+ HiddenServiceDir instead (see the **Client Authorization** section).
[[HiddenServiceAllowUnknownPorts]] **HiddenServiceAllowUnknownPorts** **0**|**1**::
If set to 1, then connections to unrecognized ports do not cause the
@@ -2941,19 +2945,26 @@ Client Authorization
(Version 3 only)
To configure client authorization on the service side, the
-"<HiddenServiceDir>/authorized_clients/" needs to exists. Each file in that
-directory should be suffixed with ".auth" (the file name is irrelevant) and
-its content format MUST be:
+"<HiddenServiceDir>/authorized_clients/" directory needs to exist. Each file
+in that directory should be suffixed with ".auth" (i.e. "alice.auth"; the
+file name is irrelevant) and its content format MUST be:
<auth-type>:<key-type>:<base32-encoded-public-key>
The supported <auth-type> are: "descriptor". The supported <key-type> are:
-"x25519". Each file MUST contain one line only. Any malformed file will be
-ignored.
+"x25519". The <base32-encoded-privkey> is the base32 representation of the raw
+key bytes only (32 bytes for x25519).
+
+Each file MUST contain one line only. Any malformed file will be
+ignored. Client authorization will only be enabled for the service if tor
+successfully loads at least one authorization file.
Note that once you've configured client authorization, anyone else with the
address won't be able to access it from this point on. If no authorization is
-configured, the service will be accessible to all.
+configured, the service will be accessible to anyone with the onion address.
+
+See the Appendix G in the rend-spec-v3.txt file of
+https://spec.torproject.org/[torspec] for more information.
TESTING NETWORK OPTIONS
-----------------------
diff --git a/link_rust.sh.in b/link_rust.sh.in
deleted file mode 100644
index 59f4142baa..0000000000
--- a/link_rust.sh.in
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-#
-# A linker script used when building Rust tests. Autoconf makes link_rust.sh
-# from link_rust_sh.in, and uses it to pass extra options to the linker
-# when linking Rust stuff.
-#
-# We'd like to remove the need for this, but build.rs doesn't let us pass
-# -static-libasan and -static-libubsan to the linker.
-
-$CCLD @RUST_LINKER_OPTIONS@ "$@"
diff --git a/scripts/codegen/run_trunnel.sh b/scripts/codegen/run_trunnel.sh
index 428804342a..645b3c2158 100755
--- a/scripts/codegen/run_trunnel.sh
+++ b/scripts/codegen/run_trunnel.sh
@@ -9,9 +9,7 @@ OPTIONS="--require-version=1.5.1"
# Get all .trunnel files recursively from that directory so we can support
# multiple sub-directories.
-for file in `find ./src/trunnel/ -name '*.trunnel'`; do
- python -m trunnel ${OPTIONS} $file
-done
+find ./src/trunnel/ -name '*.trunnel' -exec python -m trunnel ${OPTIONS} {} \;
python -m trunnel ${OPTIONS} --write-c-files --target-dir=./src/ext/trunnel/
diff --git a/scripts/test/chutney-git-bisect.sh b/scripts/test/chutney-git-bisect.sh
index 8a3f2c70c8..dc1319a27a 100755
--- a/scripts/test/chutney-git-bisect.sh
+++ b/scripts/test/chutney-git-bisect.sh
@@ -20,7 +20,7 @@ if [ ! -z "$1" ]; then
fi
if [ ! -z "$2" ]; then
- cd "$2"
+ cd "$2" || exit
fi
CHUTNEY_TEST_CMD="make test-network-all"
@@ -54,9 +54,9 @@ while [ "$i" -le "$CHUTNEY_TRIES" ]; do
echo "test '$CHUTNEY_TEST_CMD' succeeded after $i/$CHUTNEY_TRIES attempts, good"
exit 0
fi
- i=$[$i+1]
+ i=$((i+1))
done
-i=$[$i-1]
+i=$((i-1))
echo "test '$CHUTNEY_TEST_CMD' failed $i/$CHUTNEY_TRIES attempts, bad"
exit 1
diff --git a/src/feature/control/control.c b/src/feature/control/control.c
index f0db97dc89..3fa47747eb 100644
--- a/src/feature/control/control.c
+++ b/src/feature/control/control.c
@@ -2352,7 +2352,11 @@ getinfo_helper_dir(control_connection_t *control_conn,
*answer = tor_strdup(consensus->dir);
}
if (!*answer) { /* try loading it from disk */
- *answer = networkstatus_read_cached_consensus("ns");
+ tor_mmap_t *mapped = networkstatus_map_cached_consensus("ns");
+ if (mapped) {
+ *answer = tor_memdup_nulterm(mapped->data, mapped->size);
+ tor_munmap_file(mapped);
+ }
if (!*answer) { /* generate an error */
*errmsg = "Could not open cached consensus. "
"Make sure FetchUselessDescriptors is set to 1.";
diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c
index 80a5b54737..066a9e6e8a 100644
--- a/src/feature/dirauth/dirvote.c
+++ b/src/feature/dirauth/dirvote.c
@@ -413,7 +413,8 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
{
networkstatus_t *v;
- if (!(v = networkstatus_parse_vote_from_string(status, NULL,
+ if (!(v = networkstatus_parse_vote_from_string(status, strlen(status),
+ NULL,
v3_ns->type))) {
log_err(LD_BUG,"Generated a networkstatus %s we couldn't parse: "
"<<%s>>",
@@ -2410,7 +2411,8 @@ networkstatus_compute_consensus(smartlist_t *votes,
{
networkstatus_t *c;
- if (!(c = networkstatus_parse_vote_from_string(result, NULL,
+ if (!(c = networkstatus_parse_vote_from_string(result, strlen(result),
+ NULL,
NS_TYPE_CONSENSUS))) {
log_err(LD_BUG, "Generated a networkstatus consensus we couldn't "
"parse.");
@@ -3133,7 +3135,8 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out)
*msg_out = NULL;
again:
- vote = networkstatus_parse_vote_from_string(vote_body, &end_of_vote,
+ vote = networkstatus_parse_vote_from_string(vote_body, strlen(vote_body),
+ &end_of_vote,
NS_TYPE_VOTE);
if (!end_of_vote)
end_of_vote = vote_body + strlen(vote_body);
@@ -3391,7 +3394,9 @@ dirvote_compute_consensuses(void)
flavor_name);
continue;
}
- consensus = networkstatus_parse_vote_from_string(consensus_body, NULL,
+ consensus = networkstatus_parse_vote_from_string(consensus_body,
+ strlen(consensus_body),
+ NULL,
NS_TYPE_CONSENSUS);
if (!consensus) {
log_warn(LD_DIR, "Couldn't parse %s consensus we generated!",
@@ -3530,7 +3535,7 @@ dirvote_add_signatures_to_pending_consensus(
* just in case we break detached signature processing at some point. */
{
networkstatus_t *v = networkstatus_parse_vote_from_string(
- pc->body, NULL,
+ pc->body, strlen(pc->body), NULL,
NS_TYPE_CONSENSUS);
tor_assert(v);
networkstatus_vote_free(v);
@@ -3655,7 +3660,9 @@ dirvote_publish_consensus(void)
continue;
}
- if (networkstatus_set_current_consensus(pending->body, name, 0, NULL))
+ if (networkstatus_set_current_consensus(pending->body,
+ strlen(pending->body),
+ name, 0, NULL))
log_warn(LD_DIR, "Error publishing %s consensus", name);
else
log_notice(LD_DIR, "Published %s consensus", name);
diff --git a/src/feature/dircache/consdiffmgr.c b/src/feature/dircache/consdiffmgr.c
index e79aad6efb..8ecab5ca69 100644
--- a/src/feature/dircache/consdiffmgr.c
+++ b/src/feature/dircache/consdiffmgr.c
@@ -189,6 +189,7 @@ static consdiff_cfg_t consdiff_cfg = {
static int consdiffmgr_ensure_space_for_files(int n);
static int consensus_queue_compression_work(const char *consensus,
+ size_t consensus_len,
const networkstatus_t *as_parsed);
static int consensus_diff_queue_diff_work(consensus_cache_entry_t *diff_from,
consensus_cache_entry_t *diff_to);
@@ -509,8 +510,25 @@ get_max_age_to_cache(void)
MAX_MAX_AGE_TO_CACHE);
}
+#ifdef TOR_UNIT_TESTS
+/** As consdiffmgr_add_consensus, but requires a nul-terminated input. For
+ * testing. */
+int
+consdiffmgr_add_consensus_nulterm(const char *consensus,
+ const networkstatus_t *as_parsed)
+{
+ size_t len = strlen(consensus);
+ /* make a non-nul-terminated copy so that we can have a better chance
+ * of catching errors. */
+ char *ctmp = tor_memdup(consensus, len);
+ int r = consdiffmgr_add_consensus(ctmp, len, as_parsed);
+ tor_free(ctmp);
+ return r;
+}
+#endif
+
/**
- * Given a string containing a networkstatus consensus, and the results of
+ * Given a buffer containing a networkstatus consensus, and the results of
* having parsed that consensus, add that consensus to the cache if it is not
* already present and not too old. Create new consensus diffs from or to
* that consensus as appropriate.
@@ -519,6 +537,7 @@ get_max_age_to_cache(void)
*/
int
consdiffmgr_add_consensus(const char *consensus,
+ size_t consensus_len,
const networkstatus_t *as_parsed)
{
if (BUG(consensus == NULL) || BUG(as_parsed == NULL))
@@ -544,7 +563,7 @@ consdiffmgr_add_consensus(const char *consensus,
}
/* We don't have it. Add it to the cache. */
- return consensus_queue_compression_work(consensus, as_parsed);
+ return consensus_queue_compression_work(consensus, consensus_len, as_parsed);
}
/**
@@ -1387,19 +1406,21 @@ typedef struct consensus_diff_worker_job_t {
} consensus_diff_worker_job_t;
/** Given a consensus_cache_entry_t, check whether it has a label claiming
- * that it was compressed. If so, uncompress its contents into <b>out</b> and
- * set <b>outlen</b> to hold their size. If not, just copy the body into
- * <b>out</b> and set <b>outlen</b> to its length. Return 0 on success,
- * -1 on failure.
- *
- * In all cases, the output is nul-terminated. */
+ * that it was compressed. If so, uncompress its contents into *<b>out</b> and
+ * set <b>outlen</b> to hold their size, and set *<b>owned_out</b> to a pointer
+ * that the caller will need to free. If not, just set *<b>out</b> and
+ * <b>outlen</b> to its extent in memory. Return 0 on success, -1 on failure.
+ **/
STATIC int
-uncompress_or_copy(char **out, size_t *outlen,
- consensus_cache_entry_t *ent)
+uncompress_or_set_ptr(const char **out, size_t *outlen,
+ char **owned_out,
+ consensus_cache_entry_t *ent)
{
const uint8_t *body;
size_t bodylen;
+ *owned_out = NULL;
+
if (consensus_cache_entry_get_body(ent, &body, &bodylen) < 0)
return -1;
@@ -1410,8 +1431,17 @@ uncompress_or_copy(char **out, size_t *outlen,
if (lv_compression)
method = compression_method_get_by_name(lv_compression);
- return tor_uncompress(out, outlen, (const char *)body, bodylen,
+ int rv;
+ if (method == NO_METHOD) {
+ *out = (const char *)body;
+ *outlen = bodylen;
+ rv = 0;
+ } else {
+ rv = tor_uncompress(owned_out, outlen, (const char *)body, bodylen,
method, 1, LOG_WARN);
+ *out = *owned_out;
+ }
+ return rv;
}
/**
@@ -1478,16 +1508,17 @@ consensus_diff_worker_threadfn(void *state_, void *work_)
char *consensus_diff;
{
- char *diff_from_nt = NULL, *diff_to_nt = NULL;
+ const char *diff_from_nt = NULL, *diff_to_nt = NULL;
+ char *owned1 = NULL, *owned2 = NULL;
size_t diff_from_nt_len, diff_to_nt_len;
- if (uncompress_or_copy(&diff_from_nt, &diff_from_nt_len,
- job->diff_from) < 0) {
+ if (uncompress_or_set_ptr(&diff_from_nt, &diff_from_nt_len, &owned1,
+ job->diff_from) < 0) {
return WQ_RPL_REPLY;
}
- if (uncompress_or_copy(&diff_to_nt, &diff_to_nt_len,
- job->diff_to) < 0) {
- tor_free(diff_from_nt);
+ if (uncompress_or_set_ptr(&diff_to_nt, &diff_to_nt_len, &owned2,
+ job->diff_to) < 0) {
+ tor_free(owned1);
return WQ_RPL_REPLY;
}
tor_assert(diff_from_nt);
@@ -1496,9 +1527,12 @@ consensus_diff_worker_threadfn(void *state_, void *work_)
// XXXX ugh; this is going to calculate the SHA3 of both its
// XXXX inputs again, even though we already have that. Maybe it's time
// XXXX to change the API here?
- consensus_diff = consensus_diff_generate(diff_from_nt, diff_to_nt);
- tor_free(diff_from_nt);
- tor_free(diff_to_nt);
+ consensus_diff = consensus_diff_generate(diff_from_nt,
+ diff_from_nt_len,
+ diff_to_nt,
+ diff_to_nt_len);
+ tor_free(owned1);
+ tor_free(owned2);
}
if (!consensus_diff) {
/* Couldn't generate consensus; we'll leave the reply blank. */
@@ -1746,8 +1780,8 @@ consensus_compress_worker_threadfn(void *state_, void *work_)
(const uint8_t *)consensus, bodylen);
{
const char *start, *end;
- if (router_get_networkstatus_v3_signed_boundaries(consensus,
- &start, &end) < 0) {
+ if (router_get_networkstatus_v3_signed_boundaries(consensus, bodylen,
+ &start, &end) < 0) {
start = consensus;
end = consensus+bodylen;
}
@@ -1811,14 +1845,15 @@ static int background_compression = 0;
*/
static int
consensus_queue_compression_work(const char *consensus,
+ size_t consensus_len,
const networkstatus_t *as_parsed)
{
tor_assert(consensus);
tor_assert(as_parsed);
consensus_compress_worker_job_t *job = tor_malloc_zero(sizeof(*job));
- job->consensus = tor_strdup(consensus);
- job->consensus_len = strlen(consensus);
+ job->consensus = tor_memdup_nulterm(consensus, consensus_len);
+ job->consensus_len = strlen(job->consensus);
job->flavor = as_parsed->flavor;
char va_str[ISO_TIME_LEN+1];
diff --git a/src/feature/dircache/consdiffmgr.h b/src/feature/dircache/consdiffmgr.h
index 66c3d65002..011c8799d6 100644
--- a/src/feature/dircache/consdiffmgr.h
+++ b/src/feature/dircache/consdiffmgr.h
@@ -22,6 +22,7 @@ typedef struct consdiff_cfg_t {
struct consensus_cache_entry_t; // from conscache.h
int consdiffmgr_add_consensus(const char *consensus,
+ size_t consensus_len,
const networkstatus_t *as_parsed);
consdiff_status_t consdiffmgr_find_consensus(
@@ -68,8 +69,14 @@ STATIC consensus_cache_entry_t *cdm_cache_lookup_consensus(
STATIC int cdm_entry_get_sha3_value(uint8_t *digest_out,
consensus_cache_entry_t *ent,
const char *label);
-STATIC int uncompress_or_copy(char **out, size_t *outlen,
- consensus_cache_entry_t *ent);
+STATIC int uncompress_or_set_ptr(const char **out, size_t *outlen,
+ char **owned_out,
+ consensus_cache_entry_t *ent);
#endif /* defined(CONSDIFFMGR_PRIVATE) */
+#ifdef TOR_UNIT_TESTS
+int consdiffmgr_add_consensus_nulterm(const char *consensus,
+ const networkstatus_t *as_parsed);
+#endif
+
#endif /* !defined(TOR_CONSDIFFMGR_H) */
diff --git a/src/feature/dircache/dirserv.c b/src/feature/dircache/dirserv.c
index 57178cd506..4366000e2e 100644
--- a/src/feature/dircache/dirserv.c
+++ b/src/feature/dircache/dirserv.c
@@ -234,6 +234,7 @@ free_cached_dir_(void *_d)
* validation is performed. */
void
dirserv_set_cached_consensus_networkstatus(const char *networkstatus,
+ size_t networkstatus_len,
const char *flavor_name,
const common_digests_t *digests,
const uint8_t *sha3_as_signed,
@@ -244,7 +245,9 @@ dirserv_set_cached_consensus_networkstatus(const char *networkstatus,
if (!cached_consensuses)
cached_consensuses = strmap_new();
- new_networkstatus = new_cached_dir(tor_strdup(networkstatus), published);
+ new_networkstatus =
+ new_cached_dir(tor_memdup_nulterm(networkstatus, networkstatus_len),
+ published);
memcpy(&new_networkstatus->digests, digests, sizeof(common_digests_t));
memcpy(&new_networkstatus->digest_sha3_as_signed, sha3_as_signed,
DIGEST256_LEN);
diff --git a/src/feature/dircache/dirserv.h b/src/feature/dircache/dirserv.h
index 41e1376688..aa1e2494ca 100644
--- a/src/feature/dircache/dirserv.h
+++ b/src/feature/dircache/dirserv.h
@@ -84,6 +84,7 @@ int directory_too_idle_to_fetch_descriptors(const or_options_t *options,
cached_dir_t *dirserv_get_consensus(const char *flavor_name);
void dirserv_set_cached_consensus_networkstatus(const char *consensus,
+ size_t consensus_len,
const char *flavor_name,
const common_digests_t *digests,
const uint8_t *sha3_as_signed,
diff --git a/src/feature/dirclient/dirclient.c b/src/feature/dirclient/dirclient.c
index f6a712e429..705bf75e5c 100644
--- a/src/feature/dirclient/dirclient.c
+++ b/src/feature/dirclient/dirclient.c
@@ -2205,13 +2205,18 @@ handle_response_fetch_consensus(dir_connection_t *conn,
if (looks_like_a_consensus_diff(body, body_len)) {
/* First find our previous consensus. Maybe it's in ram, maybe not. */
cached_dir_t *cd = dirserv_get_consensus(flavname);
- const char *consensus_body;
- char *owned_consensus = NULL;
+ const char *consensus_body = NULL;
+ size_t consensus_body_len;
+ tor_mmap_t *mapped_consensus = NULL;
if (cd) {
consensus_body = cd->dir;
+ consensus_body_len = cd->dir_len;
} else {
- owned_consensus = networkstatus_read_cached_consensus(flavname);
- consensus_body = owned_consensus;
+ mapped_consensus = networkstatus_map_cached_consensus(flavname);
+ if (mapped_consensus) {
+ consensus_body = mapped_consensus->data;
+ consensus_body_len = mapped_consensus->size;
+ }
}
if (!consensus_body) {
log_warn(LD_DIR, "Received a consensus diff, but we can't find "
@@ -2221,8 +2226,9 @@ handle_response_fetch_consensus(dir_connection_t *conn,
return -1;
}
- new_consensus = consensus_diff_apply(consensus_body, body);
- tor_free(owned_consensus);
+ new_consensus = consensus_diff_apply(consensus_body, consensus_body_len,
+ body, body_len);
+ tor_munmap_file(mapped_consensus);
if (new_consensus == NULL) {
log_warn(LD_DIR, "Could not apply consensus diff received from server "
"'%s:%d'", conn->base_.address, conn->base_.port);
@@ -2244,7 +2250,9 @@ handle_response_fetch_consensus(dir_connection_t *conn,
sourcename = "downloaded";
}
- if ((r=networkstatus_set_current_consensus(consensus, flavname, 0,
+ if ((r=networkstatus_set_current_consensus(consensus,
+ strlen(consensus),
+ flavname, 0,
conn->identity_digest))<0) {
log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
"Unable to load %s consensus directory %s from "
diff --git a/src/feature/dircommon/consdiff.c b/src/feature/dircommon/consdiff.c
index f8ced8503f..15266f77bf 100644
--- a/src/feature/dircommon/consdiff.c
+++ b/src/feature/dircommon/consdiff.c
@@ -101,11 +101,11 @@ smartlist_add_linecpy(smartlist_t *lst, memarea_t *area, const char *s)
/* This is a separate, mockable function so that we can override it when
* fuzzing. */
MOCK_IMPL(STATIC int,
-consensus_compute_digest,(const char *cons,
+consensus_compute_digest,(const char *cons, size_t len,
consensus_digest_t *digest_out))
{
int r = crypto_digest256((char*)digest_out->sha3_256,
- cons, strlen(cons), DIGEST_SHA3_256);
+ cons, len, DIGEST_SHA3_256);
return r;
}
@@ -114,11 +114,11 @@ consensus_compute_digest,(const char *cons,
/* This is a separate, mockable function so that we can override it when
* fuzzing. */
MOCK_IMPL(STATIC int,
-consensus_compute_digest_as_signed,(const char *cons,
+consensus_compute_digest_as_signed,(const char *cons, size_t len,
consensus_digest_t *digest_out))
{
return router_get_networkstatus_v3_sha3_as_signed(digest_out->sha3_256,
- cons);
+ cons, len);
}
/** Return true iff <b>d1</b> and <b>d2</b> contain the same digest */
@@ -1229,7 +1229,8 @@ consdiff_apply_diff(const smartlist_t *cons1,
cons2_str = consensus_join_lines(cons2);
consensus_digest_t cons2_digests;
- if (consensus_compute_digest(cons2_str, &cons2_digests) < 0) {
+ if (consensus_compute_digest(cons2_str, strlen(cons2_str),
+ &cons2_digests) < 0) {
/* LCOV_EXCL_START -- digest can't fail */
log_warn(LD_CONSDIFF, "Could not compute digests of the consensus "
"resulting from applying a consensus diff.");
@@ -1283,12 +1284,13 @@ consdiff_apply_diff(const smartlist_t *cons1,
* generated cdlines will become invalid.
*/
STATIC int
-consensus_split_lines(smartlist_t *out, const char *s, memarea_t *area)
+consensus_split_lines(smartlist_t *out,
+ const char *s, size_t len,
+ memarea_t *area)
{
- const char *end_of_str = s + strlen(s);
- tor_assert(*end_of_str == '\0');
+ const char *end_of_str = s + len;
- while (*s) {
+ while (s < end_of_str) {
const char *eol = memchr(s, '\n', end_of_str - s);
if (!eol) {
/* File doesn't end with newline. */
@@ -1334,25 +1336,25 @@ consensus_join_lines(const smartlist_t *inp)
* success, retun a newly allocated string containing that diff. On failure,
* return NULL. */
char *
-consensus_diff_generate(const char *cons1,
- const char *cons2)
+consensus_diff_generate(const char *cons1, size_t cons1len,
+ const char *cons2, size_t cons2len)
{
consensus_digest_t d1, d2;
smartlist_t *lines1 = NULL, *lines2 = NULL, *result_lines = NULL;
int r1, r2;
char *result = NULL;
- r1 = consensus_compute_digest_as_signed(cons1, &d1);
- r2 = consensus_compute_digest(cons2, &d2);
+ r1 = consensus_compute_digest_as_signed(cons1, cons1len, &d1);
+ r2 = consensus_compute_digest(cons2, cons2len, &d2);
if (BUG(r1 < 0 || r2 < 0))
return NULL; // LCOV_EXCL_LINE
memarea_t *area = memarea_new();
lines1 = smartlist_new();
lines2 = smartlist_new();
- if (consensus_split_lines(lines1, cons1, area) < 0)
+ if (consensus_split_lines(lines1, cons1, cons1len, area) < 0)
goto done;
- if (consensus_split_lines(lines2, cons2, area) < 0)
+ if (consensus_split_lines(lines2, cons2, cons2len, area) < 0)
goto done;
result_lines = consdiff_gen_diff(lines1, lines2, &d1, &d2, area);
@@ -1375,7 +1377,9 @@ consensus_diff_generate(const char *cons1,
* consensus. On failure, return NULL. */
char *
consensus_diff_apply(const char *consensus,
- const char *diff)
+ size_t consensus_len,
+ const char *diff,
+ size_t diff_len)
{
consensus_digest_t d1;
smartlist_t *lines1 = NULL, *lines2 = NULL;
@@ -1383,15 +1387,15 @@ consensus_diff_apply(const char *consensus,
char *result = NULL;
memarea_t *area = memarea_new();
- r1 = consensus_compute_digest_as_signed(consensus, &d1);
+ r1 = consensus_compute_digest_as_signed(consensus, consensus_len, &d1);
if (BUG(r1 < 0))
return NULL; // LCOV_EXCL_LINE
lines1 = smartlist_new();
lines2 = smartlist_new();
- if (consensus_split_lines(lines1, consensus, area) < 0)
+ if (consensus_split_lines(lines1, consensus, consensus_len, area) < 0)
goto done;
- if (consensus_split_lines(lines2, diff, area) < 0)
+ if (consensus_split_lines(lines2, diff, diff_len, area) < 0)
goto done;
result = consdiff_apply_diff(lines1, lines2, &d1);
diff --git a/src/feature/dircommon/consdiff.h b/src/feature/dircommon/consdiff.h
index a5e4ba5cbf..eb7c9f9fe0 100644
--- a/src/feature/dircommon/consdiff.h
+++ b/src/feature/dircommon/consdiff.h
@@ -7,10 +7,10 @@
#include "core/or/or.h"
-char *consensus_diff_generate(const char *cons1,
- const char *cons2);
-char *consensus_diff_apply(const char *consensus,
- const char *diff);
+char *consensus_diff_generate(const char *cons1, size_t cons1len,
+ const char *cons2, size_t cons2len);
+char *consensus_diff_apply(const char *consensus, size_t consensus_len,
+ const char *diff, size_t diff_len);
int looks_like_a_consensus_diff(const char *document, size_t len);
@@ -78,7 +78,8 @@ STATIC int smartlist_slice_string_pos(const smartlist_slice_t *slice,
STATIC void set_changed(bitarray_t *changed1, bitarray_t *changed2,
const smartlist_slice_t *slice1,
const smartlist_slice_t *slice2);
-STATIC int consensus_split_lines(smartlist_t *out, const char *s,
+STATIC int consensus_split_lines(smartlist_t *out,
+ const char *s, size_t len,
struct memarea_t *area);
STATIC void smartlist_add_linecpy(smartlist_t *lst, struct memarea_t *area,
const char *s);
@@ -86,10 +87,10 @@ STATIC int lines_eq(const cdline_t *a, const cdline_t *b);
STATIC int line_str_eq(const cdline_t *a, const char *b);
MOCK_DECL(STATIC int,
- consensus_compute_digest,(const char *cons,
+ consensus_compute_digest,(const char *cons, size_t len,
consensus_digest_t *digest_out));
MOCK_DECL(STATIC int,
- consensus_compute_digest_as_signed,(const char *cons,
+ consensus_compute_digest_as_signed,(const char *cons, size_t len,
consensus_digest_t *digest_out));
MOCK_DECL(STATIC int,
consensus_digest_eq,(const uint8_t *d1,
diff --git a/src/feature/dirparse/authcert_parse.c b/src/feature/dirparse/authcert_parse.c
index 2ba46bb8fa..334baf8b1a 100644
--- a/src/feature/dirparse/authcert_parse.c
+++ b/src/feature/dirparse/authcert_parse.c
@@ -24,7 +24,8 @@ static token_rule_t dir_key_certificate_table[] = {
/** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
* the first character after the certificate. */
authority_cert_t *
-authority_cert_parse_from_string(const char *s, const char **end_of_string)
+authority_cert_parse_from_string(const char *s, size_t maxlen,
+ const char **end_of_string)
{
/** Reject any certificate at least this big; it is probably an overflow, an
* attack, a bug, or some other nonsense. */
@@ -35,24 +36,25 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string)
char digest[DIGEST_LEN];
directory_token_t *tok;
char fp_declared[DIGEST_LEN];
- char *eos;
+ const char *eos;
size_t len;
int found;
memarea_t *area = NULL;
+ const char *end_of_s = s + maxlen;
const char *s_dup = s;
- s = eat_whitespace(s);
- eos = strstr(s, "\ndir-key-certification");
+ s = eat_whitespace_eos(s, end_of_s);
+ eos = tor_memstr(s, end_of_s - s, "\ndir-key-certification");
if (! eos) {
log_warn(LD_DIR, "No signature found on key certificate");
return NULL;
}
- eos = strstr(eos, "\n-----END SIGNATURE-----\n");
+ eos = tor_memstr(eos, end_of_s - eos, "\n-----END SIGNATURE-----\n");
if (! eos) {
log_warn(LD_DIR, "No end-of-signature found on key certificate");
return NULL;
}
- eos = strchr(eos+2, '\n');
+ eos = memchr(eos+2, '\n', end_of_s - (eos+2));
tor_assert(eos);
++eos;
len = eos - s;
@@ -69,7 +71,7 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string)
log_warn(LD_DIR, "Error tokenizing key certificate");
goto err;
}
- if (router_get_hash_impl(s, strlen(s), digest, "dir-key-certificate-version",
+ if (router_get_hash_impl(s, eos - s, digest, "dir-key-certificate-version",
"\ndir-key-certification", '\n', DIGEST_SHA1) < 0)
goto err;
tok = smartlist_get(tokens, 0);
diff --git a/src/feature/dirparse/authcert_parse.h b/src/feature/dirparse/authcert_parse.h
index f63525e04d..e4e9fec993 100644
--- a/src/feature/dirparse/authcert_parse.h
+++ b/src/feature/dirparse/authcert_parse.h
@@ -13,6 +13,7 @@
#define TOR_AUTHCERT_PARSE_H
authority_cert_t *authority_cert_parse_from_string(const char *s,
+ size_t maxlen,
const char **end_of_string);
#endif /* !defined(TOR_AUTHCERT_PARSE_H) */
diff --git a/src/feature/dirparse/microdesc_parse.c b/src/feature/dirparse/microdesc_parse.c
index 005d2c53d0..aebff5a35f 100644
--- a/src/feature/dirparse/microdesc_parse.c
+++ b/src/feature/dirparse/microdesc_parse.c
@@ -50,13 +50,13 @@ find_start_of_next_microdesc(const char *s, const char *eos)
return NULL;
#define CHECK_LENGTH() STMT_BEGIN \
- if (s+32 > eos) \
+ if (eos - s < 32) \
return NULL; \
STMT_END
#define NEXT_LINE() STMT_BEGIN \
s = memchr(s, '\n', eos-s); \
- if (!s || s+1 >= eos) \
+ if (!s || eos - s <= 1) \
return NULL; \
s++; \
STMT_END
@@ -80,7 +80,7 @@ find_start_of_next_microdesc(const char *s, const char *eos)
/* Okay, now we're pointed at the first line of the microdescriptor which is
not an annotation or onion-key. The next line that _is_ an annotation or
onion-key is the start of the next microdescriptor. */
- while (s+32 < eos) {
+ while (eos - s > 32) {
if (*s == '@' || !strcmpstart(s, "onion-key"))
return s;
NEXT_LINE();
diff --git a/src/feature/dirparse/ns_parse.c b/src/feature/dirparse/ns_parse.c
index 72299e8071..3fccec1540 100644
--- a/src/feature/dirparse/ns_parse.c
+++ b/src/feature/dirparse/ns_parse.c
@@ -151,10 +151,11 @@ static token_rule_t networkstatus_vote_footer_token_table[] = {
* -1. */
int
router_get_networkstatus_v3_signed_boundaries(const char *s,
+ size_t len,
const char **start_out,
const char **end_out)
{
- return router_get_hash_impl_helper(s, strlen(s),
+ return router_get_hash_impl_helper(s, len,
"network-status-version",
"\ndirectory-signature",
' ', LOG_INFO,
@@ -166,12 +167,13 @@ router_get_networkstatus_v3_signed_boundaries(const char *s,
* signed portion can be identified. Return 0 on success, -1 on failure. */
int
router_get_networkstatus_v3_sha3_as_signed(uint8_t *digest_out,
- const char *s)
+ const char *s, size_t len)
{
const char *start, *end;
- if (router_get_networkstatus_v3_signed_boundaries(s, &start, &end) < 0) {
+ if (router_get_networkstatus_v3_signed_boundaries(s, len,
+ &start, &end) < 0) {
start = s;
- end = s + strlen(s);
+ end = s + len;
}
tor_assert(start);
tor_assert(end);
@@ -182,9 +184,10 @@ router_get_networkstatus_v3_sha3_as_signed(uint8_t *digest_out,
/** Set <b>digests</b> to all the digests of the consensus document in
* <b>s</b> */
int
-router_get_networkstatus_v3_hashes(const char *s, common_digests_t *digests)
+router_get_networkstatus_v3_hashes(const char *s, size_t len,
+ common_digests_t *digests)
{
- return router_get_hashes_impl(s,strlen(s),digests,
+ return router_get_hashes_impl(s, len, digests,
"network-status-version",
"\ndirectory-signature",
' ');
@@ -195,13 +198,13 @@ router_get_networkstatus_v3_hashes(const char *s, common_digests_t *digests)
* return the start of the directory footer, or the next directory signature.
* If none is found, return the end of the string. */
static inline const char *
-find_start_of_next_routerstatus(const char *s)
+find_start_of_next_routerstatus(const char *s, const char *s_eos)
{
const char *eos, *footer, *sig;
- if ((eos = strstr(s, "\nr ")))
+ if ((eos = tor_memstr(s, s_eos - s, "\nr ")))
++eos;
else
- eos = s + strlen(s);
+ eos = s_eos;
footer = tor_memstr(s, eos-s, "\ndirectory-footer");
sig = tor_memstr(s, eos-s, "\ndirectory-signature");
@@ -289,7 +292,8 @@ routerstatus_parse_guardfraction(const char *guardfraction_str,
**/
STATIC routerstatus_t *
routerstatus_parse_entry_from_string(memarea_t *area,
- const char **s, smartlist_t *tokens,
+ const char **s, const char *s_eos,
+ smartlist_t *tokens,
networkstatus_t *vote,
vote_routerstatus_t *vote_rs,
int consensus_method,
@@ -308,7 +312,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
flav = FLAV_NS;
tor_assert(flav == FLAV_NS || flav == FLAV_MICRODESC);
- eos = find_start_of_next_routerstatus(*s);
+ eos = find_start_of_next_routerstatus(*s, s_eos);
if (tokenize_string(area,*s, eos, tokens, rtrstatus_token_table,0)) {
log_warn(LD_DIR, "Error tokenizing router status");
@@ -1051,7 +1055,9 @@ extract_shared_random_srvs(networkstatus_t *ns, smartlist_t *tokens)
/** Parse a v3 networkstatus vote, opinion, or consensus (depending on
* ns_type), from <b>s</b>, and return the result. Return NULL on failure. */
networkstatus_t *
-networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
+networkstatus_parse_vote_from_string(const char *s,
+ size_t s_len,
+ const char **eos_out,
networkstatus_type_t ns_type)
{
smartlist_t *tokens = smartlist_new();
@@ -1067,20 +1073,22 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
memarea_t *area = NULL, *rs_area = NULL;
consensus_flavor_t flav = FLAV_NS;
char *last_kwd=NULL;
+ const char *eos = s + s_len;
tor_assert(s);
if (eos_out)
*eos_out = NULL;
- if (router_get_networkstatus_v3_hashes(s, &ns_digests) ||
- router_get_networkstatus_v3_sha3_as_signed(sha3_as_signed, s)<0) {
+ if (router_get_networkstatus_v3_hashes(s, s_len, &ns_digests) ||
+ router_get_networkstatus_v3_sha3_as_signed(sha3_as_signed,
+ s, s_len)<0) {
log_warn(LD_DIR, "Unable to compute digest of network-status");
goto err;
}
area = memarea_new();
- end_of_header = find_start_of_next_routerstatus(s);
+ end_of_header = find_start_of_next_routerstatus(s, eos);
if (tokenize_string(area, s, end_of_header, tokens,
(ns_type == NS_TYPE_CONSENSUS) ?
networkstatus_consensus_token_table :
@@ -1111,10 +1119,12 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
if (ns_type != NS_TYPE_CONSENSUS) {
const char *end_of_cert = NULL;
- if (!(cert = strstr(s, "\ndir-key-certificate-version")))
+ if (!(cert = tor_memstr(s, end_of_header - s,
+ "\ndir-key-certificate-version")))
goto err;
++cert;
- ns->cert = authority_cert_parse_from_string(cert, &end_of_cert);
+ ns->cert = authority_cert_parse_from_string(cert, end_of_header - cert,
+ &end_of_cert);
if (!ns->cert || !end_of_cert || end_of_cert > end_of_header)
goto err;
}
@@ -1424,10 +1434,10 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
s = end_of_header;
ns->routerstatus_list = smartlist_new();
- while (!strcmpstart(s, "r ")) {
+ while (eos - s >= 2 && fast_memeq(s, "r ", 2)) {
if (ns->type != NS_TYPE_CONSENSUS) {
vote_routerstatus_t *rs = tor_malloc_zero(sizeof(vote_routerstatus_t));
- if (routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens, ns,
+ if (routerstatus_parse_entry_from_string(rs_area, &s, eos, rs_tokens, ns,
rs, 0, 0)) {
smartlist_add(ns->routerstatus_list, rs);
} else {
@@ -1435,7 +1445,8 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
}
} else {
routerstatus_t *rs;
- if ((rs = routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens,
+ if ((rs = routerstatus_parse_entry_from_string(rs_area, &s, eos,
+ rs_tokens,
NULL, NULL,
ns->consensus_method,
flav))) {
@@ -1480,10 +1491,10 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
/* Parse footer; check signature. */
footer_tokens = smartlist_new();
- if ((end_of_footer = strstr(s, "\nnetwork-status-version ")))
+ if ((end_of_footer = tor_memstr(s, eos-s, "\nnetwork-status-version ")))
++end_of_footer;
else
- end_of_footer = s + strlen(s);
+ end_of_footer = eos;
if (tokenize_string(area,s, end_of_footer, footer_tokens,
networkstatus_vote_footer_token_table, 0)) {
log_warn(LD_DIR, "Error tokenizing network-status vote footer.");
diff --git a/src/feature/dirparse/ns_parse.h b/src/feature/dirparse/ns_parse.h
index 22438d73a7..85d9ded685 100644
--- a/src/feature/dirparse/ns_parse.h
+++ b/src/feature/dirparse/ns_parse.h
@@ -12,18 +12,19 @@
#ifndef TOR_NS_PARSE_H
#define TOR_NS_PARSE_H
-int router_get_networkstatus_v3_hashes(const char *s,
+int router_get_networkstatus_v3_hashes(const char *s, size_t len,
common_digests_t *digests);
-int router_get_networkstatus_v3_signed_boundaries(const char *s,
+int router_get_networkstatus_v3_signed_boundaries(const char *s, size_t len,
const char **start_out,
const char **end_out);
int router_get_networkstatus_v3_sha3_as_signed(uint8_t *digest_out,
- const char *s);
+ const char *s, size_t len);
int compare_vote_routerstatus_entries(const void **_a, const void **_b);
int networkstatus_verify_bw_weights(networkstatus_t *ns, int);
enum networkstatus_type_t;
networkstatus_t *networkstatus_parse_vote_from_string(const char *s,
+ size_t len,
const char **eos_out,
enum networkstatus_type_t ns_type);
@@ -35,7 +36,8 @@ STATIC int routerstatus_parse_guardfraction(const char *guardfraction_str,
struct memarea_t;
STATIC routerstatus_t *routerstatus_parse_entry_from_string(
struct memarea_t *area,
- const char **s, smartlist_t *tokens,
+ const char **s, const char *eos,
+ smartlist_t *tokens,
networkstatus_t *vote,
vote_routerstatus_t *vote_rs,
int consensus_method,
diff --git a/src/feature/dirparse/parsecommon.c b/src/feature/dirparse/parsecommon.c
index c12f199e4e..e00af0eea2 100644
--- a/src/feature/dirparse/parsecommon.c
+++ b/src/feature/dirparse/parsecommon.c
@@ -353,7 +353,7 @@ get_next_token(memarea_t *area,
goto check_object;
obstart = *s; /* Set obstart to start of object spec */
- if (*s+16 >= eol || memchr(*s+11,'\0',eol-*s-16) || /* no short lines, */
+ if (eol - *s <= 16 || memchr(*s+11,'\0',eol-*s-16) || /* no short lines, */
strcmp_len(eol-5, "-----", 5) || /* nuls or invalid endings */
(eol-*s) > MAX_UNPARSED_OBJECT_SIZE) { /* name too long */
RET_ERR("Malformed object: bad begin line");
diff --git a/src/feature/hs/hs_config.c b/src/feature/hs/hs_config.c
index 93d7403dfb..497e31fbb4 100644
--- a/src/feature/hs/hs_config.c
+++ b/src/feature/hs/hs_config.c
@@ -419,7 +419,7 @@ config_generic_service(const config_line_t *line_,
dup_opt_seen = line->key;
goto err;
}
- have_version = 1;
+ have_version = service->config.hs_version_explicitly_set = 1;
continue;
}
/* Virtual port. */
@@ -534,18 +534,15 @@ config_service(const config_line_t *line, const or_options_t *options,
/* We have a new hidden service. */
service = hs_service_new(options);
+
/* We'll configure that service as a generic one and then pass it to a
* specific function according to the configured version number. */
if (config_generic_service(line, options, service) < 0) {
goto err;
}
+
tor_assert(service->config.version <= HS_VERSION_MAX);
- /* Before we configure the service on a per-version basis, we'll make
- * sure that this set of options for a service are valid that is for
- * instance an option only for v2 is not used for v3. */
- if (config_has_invalid_options(line->next, service)) {
- goto err;
- }
+
/* Check permission on service directory that was just parsed. And this must
* be done regardless of the service version. Do not ask for the directory
* to be created, this is done when the keys are loaded because we could be
@@ -556,11 +553,19 @@ config_service(const config_line_t *line, const or_options_t *options,
0) < 0) {
goto err;
}
+
/* We'll try to learn the service version here by loading the key(s) if
- * present. Depending on the key format, we can figure out the service
- * version. If we can't find a key, the configuration version will be used
- * which has been set previously. */
- service->config.version = config_learn_service_version(service);
+ * present and we did not set HiddenServiceVersion. Depending on the key
+ * format, we can figure out the service version. */
+ if (!service->config.hs_version_explicitly_set) {
+ service->config.version = config_learn_service_version(service);
+ }
+
+ /* We make sure that this set of options for a service are valid that is for
+ * instance an option only for v2 is not used for v3. */
+ if (config_has_invalid_options(line->next, service)) {
+ goto err;
+ }
/* Different functions are in charge of specific options for a version. We
* start just after the service directory line so once we hit another
@@ -580,13 +585,16 @@ config_service(const config_line_t *line, const or_options_t *options,
if (ret < 0) {
goto err;
}
+
/* We'll check if this service can be kept depending on the others
* configured previously. */
if (service_is_duplicate_in_list(service_list, service)) {
goto err;
}
+
/* Passes, add it to the given list. */
smartlist_add(service_list, service);
+
return 0;
err:
diff --git a/src/feature/hs/hs_descriptor.c b/src/feature/hs/hs_descriptor.c
index 0e3c761bf6..1b2008c804 100644
--- a/src/feature/hs/hs_descriptor.c
+++ b/src/feature/hs/hs_descriptor.c
@@ -1406,10 +1406,10 @@ encrypted_data_length_is_valid(size_t len)
* SECRET_SEED = x25519(sk, pk)
* KEYS = KDF(subcredential | SECRET_SEED, 40)
*
- * The keys_out parameter will points to the buffer containing the KEYS. The
- * caller should wipe and free its content once done with it. This function
- * can't fail. */
-static void
+ * Set the <b>keys_out</b> argument to point to the buffer containing the KEYS,
+ * and return the buffer's length. The caller should wipe and free its content
+ * once done with it. This function can't fail. */
+static size_t
build_descriptor_cookie_keys(const uint8_t *subcredential,
size_t subcredential_len,
const curve25519_secret_key_t *sk,
@@ -1441,6 +1441,7 @@ build_descriptor_cookie_keys(const uint8_t *subcredential,
memwipe(secret_seed, 0, sizeof(secret_seed));
*keys_out = keystream;
+ return keystream_len;
}
/* Decrypt the descriptor cookie given the descriptor, the auth client,
@@ -1456,6 +1457,7 @@ decrypt_descriptor_cookie(const hs_descriptor_t *desc,
{
int ret = -1;
uint8_t *keystream = NULL;
+ size_t keystream_length = 0;
uint8_t *descriptor_cookie = NULL;
const uint8_t *cookie_key = NULL;
crypto_cipher_t *cipher = NULL;
@@ -1471,10 +1473,12 @@ decrypt_descriptor_cookie(const hs_descriptor_t *desc,
tor_assert(!tor_mem_is_zero((char *) desc->subcredential, DIGEST256_LEN));
/* Get the KEYS component to derive the CLIENT-ID and COOKIE-KEY. */
- build_descriptor_cookie_keys(desc->subcredential, DIGEST256_LEN,
- client_auth_sk,
- &desc->superencrypted_data.auth_ephemeral_pubkey,
- &keystream);
+ keystream_length =
+ build_descriptor_cookie_keys(desc->subcredential, DIGEST256_LEN,
+ client_auth_sk,
+ &desc->superencrypted_data.auth_ephemeral_pubkey,
+ &keystream);
+ tor_assert(keystream_length > 0);
/* If the client id of auth client is not the same as the calculcated
* client id, it means that this auth client is invaild according to the
@@ -1500,7 +1504,7 @@ decrypt_descriptor_cookie(const hs_descriptor_t *desc,
if (cipher) {
crypto_cipher_free(cipher);
}
- memwipe(keystream, 0, sizeof(keystream));
+ memwipe(keystream, 0, keystream_length);
tor_free(keystream);
return ret;
}
@@ -2915,6 +2919,7 @@ hs_desc_build_authorized_client(const uint8_t *subcredential,
hs_desc_authorized_client_t *client_out)
{
uint8_t *keystream = NULL;
+ size_t keystream_length = 0;
const uint8_t *cookie_key;
crypto_cipher_t *cipher;
@@ -2933,8 +2938,11 @@ hs_desc_build_authorized_client(const uint8_t *subcredential,
DIGEST256_LEN));
/* Get the KEYS part so we can derive the CLIENT-ID and COOKIE-KEY. */
- build_descriptor_cookie_keys(subcredential, DIGEST256_LEN,
- auth_ephemeral_sk, client_auth_pk, &keystream);
+ keystream_length =
+ build_descriptor_cookie_keys(subcredential, DIGEST256_LEN,
+ auth_ephemeral_sk, client_auth_pk,
+ &keystream);
+ tor_assert(keystream_length > 0);
/* Extract the CLIENT-ID and COOKIE-KEY from the KEYS. */
memcpy(client_out->client_id, keystream, HS_DESC_CLIENT_ID_LEN);
@@ -2951,7 +2959,7 @@ hs_desc_build_authorized_client(const uint8_t *subcredential,
(const char *) descriptor_cookie,
HS_DESC_DESCRIPTOR_COOKIE_LEN);
- memwipe(keystream, 0, sizeof(keystream));
+ memwipe(keystream, 0, keystream_length);
tor_free(keystream);
crypto_cipher_free(cipher);
diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c
index 78654bfb23..c288e28e80 100644
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -1696,6 +1696,32 @@ build_desc_intro_points(const hs_service_t *service,
} DIGEST256MAP_FOREACH_END;
}
+/* Build the descriptor signing key certificate. */
+static void
+build_desc_signing_key_cert(hs_service_descriptor_t *desc, time_t now)
+{
+ hs_desc_plaintext_data_t *plaintext;
+
+ tor_assert(desc);
+ tor_assert(desc->desc);
+
+ /* Ease our life a bit. */
+ plaintext = &desc->desc->plaintext_data;
+
+ /* Get rid of what we have right now. */
+ tor_cert_free(plaintext->signing_key_cert);
+
+ /* Fresh certificate for the signing key. */
+ plaintext->signing_key_cert =
+ tor_cert_create(&desc->blinded_kp, CERT_TYPE_SIGNING_HS_DESC,
+ &desc->signing_kp.pubkey, now, HS_DESC_CERT_LIFETIME,
+ CERT_FLAG_INCLUDE_SIGNING_KEY);
+ /* If the cert creation fails, the descriptor encoding will fail and thus
+ * ultimately won't be uploaded. We'll get a stack trace to help us learn
+ * where the call came from and the tor_cert_create() will log the error. */
+ tor_assert_nonfatal(plaintext->signing_key_cert);
+}
+
/* Populate the descriptor encrypted section from the given service object.
* This will generate a valid list of introduction points that can be used
* after for circuit creation. Return 0 on success else -1 on error. */
@@ -1811,17 +1837,15 @@ build_service_desc_superencrypted(const hs_service_t *service,
/* Populate the descriptor plaintext section from the given service object.
* The caller must make sure that the keys in the descriptors are valid that
- * is are non-zero. Return 0 on success else -1 on error. */
-static int
+ * is are non-zero. This can't fail. */
+static void
build_service_desc_plaintext(const hs_service_t *service,
- hs_service_descriptor_t *desc, time_t now)
+ hs_service_descriptor_t *desc)
{
- int ret = -1;
hs_desc_plaintext_data_t *plaintext;
tor_assert(service);
tor_assert(desc);
- /* XXX: Use a "assert_desc_ok()" ? */
tor_assert(!tor_mem_is_zero((char *) &desc->blinded_kp,
sizeof(desc->blinded_kp)));
tor_assert(!tor_mem_is_zero((char *) &desc->signing_kp,
@@ -1835,24 +1859,13 @@ build_service_desc_plaintext(const hs_service_t *service,
plaintext->version = service->config.version;
plaintext->lifetime_sec = HS_DESC_DEFAULT_LIFETIME;
- plaintext->signing_key_cert =
- tor_cert_create(&desc->blinded_kp, CERT_TYPE_SIGNING_HS_DESC,
- &desc->signing_kp.pubkey, now, HS_DESC_CERT_LIFETIME,
- CERT_FLAG_INCLUDE_SIGNING_KEY);
- if (plaintext->signing_key_cert == NULL) {
- log_warn(LD_REND, "Unable to create descriptor signing certificate for "
- "service %s",
- safe_str_client(service->onion_address));
- goto end;
- }
/* Copy public key material to go in the descriptor. */
ed25519_pubkey_copy(&plaintext->signing_pubkey, &desc->signing_kp.pubkey);
ed25519_pubkey_copy(&plaintext->blinded_pubkey, &desc->blinded_kp.pubkey);
- /* Success. */
- ret = 0;
- end:
- return ret;
+ /* Create the signing key certificate. This will be updated before each
+ * upload but we create it here so we don't complexify our unit tests. */
+ build_desc_signing_key_cert(desc, approx_time());
}
/** Compute the descriptor's OPE cipher for encrypting revision counters. */
@@ -1924,12 +1937,10 @@ build_service_desc_keys(const hs_service_t *service,
goto end;
}
- /* Random a descriptor cookie to be used as a part of a key to encrypt the
- * descriptor, if the client auth is enabled. */
- if (service->config.is_client_auth_enabled) {
- crypto_strongest_rand(desc->descriptor_cookie,
- sizeof(desc->descriptor_cookie));
- }
+ /* Random descriptor cookie to be used as a part of a key to encrypt the
+ * descriptor, only if the client auth is enabled will it be used. */
+ crypto_strongest_rand(desc->descriptor_cookie,
+ sizeof(desc->descriptor_cookie));
/* Success. */
ret = 0;
@@ -1944,8 +1955,7 @@ build_service_desc_keys(const hs_service_t *service,
*
* This can error if we are unable to create keys or certificate. */
static void
-build_service_descriptor(hs_service_t *service, time_t now,
- uint64_t time_period_num,
+build_service_descriptor(hs_service_t *service, uint64_t time_period_num,
hs_service_descriptor_t **desc_out)
{
char *encoded_desc;
@@ -1964,9 +1974,8 @@ build_service_descriptor(hs_service_t *service, time_t now,
goto err;
}
/* Setup plaintext descriptor content. */
- if (build_service_desc_plaintext(service, desc, now) < 0) {
- goto err;
- }
+ build_service_desc_plaintext(service, desc);
+
/* Setup superencrypted descriptor content. */
if (build_service_desc_superencrypted(service, desc) < 0) {
goto err;
@@ -2039,10 +2048,8 @@ build_descriptors_for_new_service(hs_service_t *service, time_t now)
}
/* Build descriptors. */
- build_service_descriptor(service, now, current_desc_tp,
- &service->desc_current);
- build_service_descriptor(service, now, next_desc_tp,
- &service->desc_next);
+ build_service_descriptor(service, current_desc_tp, &service->desc_current);
+ build_service_descriptor(service, next_desc_tp, &service->desc_next);
log_info(LD_REND, "Hidden service %s has just started. Both descriptors "
"built. Now scheduled for upload.",
safe_str_client(service->onion_address));
@@ -2072,7 +2079,7 @@ build_all_descriptors(time_t now)
}
if (service->desc_next == NULL) {
- build_service_descriptor(service, now, hs_get_next_time_period_num(0),
+ build_service_descriptor(service, hs_get_next_time_period_num(0),
&service->desc_next);
log_info(LD_REND, "Hidden service %s next descriptor successfully "
"built. Now scheduled for upload.",
@@ -2284,12 +2291,9 @@ service_desc_schedule_upload(hs_service_descriptor_t *desc,
}
}
-/* Update the given descriptor from the given service. The possible update
- * actions includes:
- * - Picking missing intro points if needed.
- */
+/* Pick missing intro points for this descriptor if needed. */
static void
-update_service_descriptor(hs_service_t *service,
+update_service_descriptor_intro_points(hs_service_t *service,
hs_service_descriptor_t *desc, time_t now)
{
unsigned int num_intro_points;
@@ -2328,15 +2332,17 @@ update_service_descriptor(hs_service_t *service,
}
}
-/* Update descriptors for each service if needed. */
+/* Update descriptor intro points for each service if needed. We do this as
+ * part of the periodic event because we need to establish intro point circuits
+ * before we publish descriptors. */
STATIC void
-update_all_descriptors(time_t now)
+update_all_descriptors_intro_points(time_t now)
{
FOR_EACH_SERVICE_BEGIN(service) {
/* We'll try to update each descriptor that is if certain conditions apply
* in order for the descriptor to be updated. */
FOR_EACH_DESCRIPTOR_BEGIN(service, desc) {
- update_service_descriptor(service, desc, now);
+ update_service_descriptor_intro_points(service, desc, now);
} FOR_EACH_DESCRIPTOR_END;
} FOR_EACH_SERVICE_END;
}
@@ -2621,10 +2627,10 @@ run_build_descriptor_event(time_t now)
* been rotated or we just started up. */
build_all_descriptors(now);
- /* Finally, we'll check if we should update the descriptors. Missing
- * introduction points will be picked in this function which is useful for
- * newly built descriptors. */
- update_all_descriptors(now);
+ /* Finally, we'll check if we should update the descriptors' intro
+ * points. Missing introduction points will be picked in this function which
+ * is useful for newly built descriptors. */
+ update_all_descriptors_intro_points(now);
}
/* For the given service, launch any intro point circuits that could be
@@ -2925,8 +2931,8 @@ set_descriptor_revision_counter(hs_service_descriptor_t *hs_desc, time_t now,
/* The OPE module returns CRYPTO_OPE_ERROR in case of errors. */
tor_assert_nonfatal(rev_counter < CRYPTO_OPE_ERROR);
- log_info(LD_REND, "Encrypted revision counter %d to %ld",
- (int) seconds_since_start_of_srv, (long int) rev_counter);
+ log_info(LD_REND, "Encrypted revision counter %d to %" PRIu64,
+ (int) seconds_since_start_of_srv, rev_counter);
hs_desc->desc->plaintext_data.revision_counter = rev_counter;
}
@@ -3085,6 +3091,37 @@ should_service_upload_descriptor(const hs_service_t *service,
return 0;
}
+/* Refresh the given service descriptor meaning this will update every mutable
+ * field that needs to be updated before we upload.
+ *
+ * This should ONLY be called before uploading a descriptor. It assumes that
+ * the descriptor has been built (desc->desc) and that all intro point
+ * circuits have been established. */
+static void
+refresh_service_descriptor(const hs_service_t *service,
+ hs_service_descriptor_t *desc, time_t now)
+{
+ /* There are few fields that we consider "mutable" in the descriptor meaning
+ * we need to update them regurlarly over the lifetime fo the descriptor.
+ * The rest are set once and should not be modified.
+ *
+ * - Signing key certificate.
+ * - Revision counter.
+ * - Introduction points which includes many thing. See
+ * hs_desc_intro_point_t. and the setup_desc_intro_point() function.
+ */
+
+ /* Create the signing key certificate. */
+ build_desc_signing_key_cert(desc, now);
+
+ /* Build the intro points descriptor section. The refresh step is just
+ * before we upload so all circuits have been properly established. */
+ build_desc_intro_points(service, desc, now);
+
+ /* Set the desc revision counter right before uploading */
+ set_descriptor_revision_counter(desc, now, service->desc_current == desc);
+}
+
/* Scheduled event run from the main loop. Try to upload the descriptor for
* each service. */
STATIC void
@@ -3120,15 +3157,12 @@ run_upload_descriptor_event(time_t now)
service->config.num_intro_points,
(desc->missing_intro_points) ? " (couldn't pick more)" : "");
- /* At this point, we have to upload the descriptor so start by building
- * the intro points descriptor section which we are now sure to be
- * accurate because all circuits have been established. */
- build_desc_intro_points(service, desc, now);
-
- /* Set the desc revision counter right before uploading */
- set_descriptor_revision_counter(desc, approx_time(),
- service->desc_current == desc);
+ /* We are about to upload so we need to do one last step which is to
+ * update the service's descriptor mutable fields in order to upload a
+ * coherent descriptor. */
+ refresh_service_descriptor(service, desc, now);
+ /* Proceed with the upload, the descriptor is ready to be encoded. */
upload_descriptor_to_all(service, desc);
} FOR_EACH_DESCRIPTOR_END;
} FOR_EACH_SERVICE_END;
diff --git a/src/feature/hs/hs_service.h b/src/feature/hs/hs_service.h
index 6fb15b9d37..a8a9faaea9 100644
--- a/src/feature/hs/hs_service.h
+++ b/src/feature/hs/hs_service.h
@@ -99,49 +99,65 @@ typedef struct hs_service_intropoints_t {
digestmap_t *failed_id;
} hs_service_intropoints_t;
-/* Representation of a service descriptor. */
+/* Representation of a service descriptor.
+ *
+ * Some elements of the descriptor are mutable whereas others are immutable:
+
+ * Immutable elements are initialized once when the descriptor is built (when
+ * service descriptors gets rotated). This means that these elements are
+ * initialized once and then they don't change for the lifetime of the
+ * descriptor. See build_service_descriptor().
+ *
+ * Mutable elements are initialized when we build the descriptor but they are
+ * also altered during the lifetime of the descriptor. They could be
+ * _refreshed_ everytime we upload the descriptor (which happens multiple times
+ * over the lifetime of the descriptor), or through periodic events. We do this
+ * for elements like the descriptor revision counter and various
+ * certificates. See refresh_service_descriptor() and
+ * update_service_descriptor_intro_points().
+ */
typedef struct hs_service_descriptor_t {
- /* Decoded descriptor. This object is used for encoding when the service
- * publishes the descriptor. */
- hs_descriptor_t *desc;
-
- /* Client authorization ephemeral keypair. */
+ /* Immutable: Client authorization ephemeral keypair. */
curve25519_keypair_t auth_ephemeral_kp;
- /* Descriptor cookie used to encrypt the descriptor, when the client
- * authorization is enabled */
+ /* Immutable: Descriptor cookie used to encrypt the descriptor, when the
+ * client authorization is enabled */
uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN];
- /* Descriptor signing keypair. */
+ /* Immutable: Descriptor signing keypair. */
ed25519_keypair_t signing_kp;
- /* Blinded keypair derived from the master identity public key. */
+ /* Immutable: Blinded keypair derived from the master identity public key. */
ed25519_keypair_t blinded_kp;
- /* When is the next time when we should upload the descriptor. */
+ /* Immutable: The time period number this descriptor has been created for. */
+ uint64_t time_period_num;
+
+ /** Immutable: The OPE cipher for encrypting revision counters for this
+ * descriptor. Tied to the descriptor blinded key. */
+ struct crypto_ope_t *ope_cipher;
+
+ /* Mutable: Decoded descriptor. This object is used for encoding when the
+ * service publishes the descriptor. */
+ hs_descriptor_t *desc;
+
+ /* Mutable: When is the next time when we should upload the descriptor. */
time_t next_upload_time;
- /* Introduction points assign to this descriptor which contains
- * hs_service_intropoints_t object indexed by authentication key (the RSA
- * key if the node is legacy). */
+ /* Mutable: Introduction points assign to this descriptor which contains
+ * hs_service_intropoints_t object indexed by authentication key (the RSA key
+ * if the node is legacy). */
hs_service_intropoints_t intro_points;
- /* The time period number this descriptor has been created for. */
- uint64_t time_period_num;
-
- /* True iff we have missing intro points for this descriptor because we
- * couldn't pick any nodes. */
+ /* Mutable: True iff we have missing intro points for this descriptor because
+ * we couldn't pick any nodes. */
unsigned int missing_intro_points : 1;
- /** List of the responsible HSDirs (their b64ed identity digest) last time we
- * uploaded this descriptor. If the set of responsible HSDirs is different
- * from this list, this means we received new dirinfo and we need to
- * reupload our descriptor. */
+ /** Mutable: List of the responsible HSDirs (their b64ed identity digest)
+ * last time we uploaded this descriptor. If the set of responsible HSDirs
+ * is different from this list, this means we received new dirinfo and we
+ * need to reupload our descriptor. */
smartlist_t *previous_hsdirs;
-
- /** The OPE cipher for encrypting revision counters for this descriptor.
- * Tied to the descriptor blinded key. */
- struct crypto_ope_t *ope_cipher;
} hs_service_descriptor_t;
/* Service key material. */
@@ -178,6 +194,9 @@ typedef struct hs_service_config_t {
* option. */
uint32_t version;
+ /* Have we explicitly set HiddenServiceVersion? */
+ unsigned int hs_version_explicitly_set : 1;
+
/* List of rend_service_port_config_t */
smartlist_t *ports;
@@ -387,7 +406,7 @@ STATIC int intro_point_should_expire(const hs_service_intro_point_t *ip,
STATIC void run_housekeeping_event(time_t now);
STATIC void rotate_all_descriptors(time_t now);
STATIC void build_all_descriptors(time_t now);
-STATIC void update_all_descriptors(time_t now);
+STATIC void update_all_descriptors_intro_points(time_t now);
STATIC void run_upload_descriptor_event(time_t now);
STATIC void service_descriptor_free_(hs_service_descriptor_t *desc);
diff --git a/src/feature/nodelist/authcert.c b/src/feature/nodelist/authcert.c
index b111422d0d..2c4915e913 100644
--- a/src/feature/nodelist/authcert.c
+++ b/src/feature/nodelist/authcert.c
@@ -380,7 +380,8 @@ trusted_dirs_load_certs_from_string(const char *contents, int source,
int added_trusted_cert = 0;
for (s = contents; *s; s = eos) {
- authority_cert_t *cert = authority_cert_parse_from_string(s, &eos);
+ authority_cert_t *cert = authority_cert_parse_from_string(s, strlen(s),
+ &eos);
cert_list_t *cl;
if (!cert) {
failure_code = -1;
diff --git a/src/feature/nodelist/networkstatus.c b/src/feature/nodelist/networkstatus.c
index de2451b79c..ec1a69b9e2 100644
--- a/src/feature/nodelist/networkstatus.c
+++ b/src/feature/nodelist/networkstatus.c
@@ -116,8 +116,6 @@ STATIC networkstatus_t *current_md_consensus = NULL;
typedef struct consensus_waiting_for_certs_t {
/** The consensus itself. */
networkstatus_t *consensus;
- /** The encoded version of the consensus, nul-terminated. */
- char *body;
/** When did we set the current value of consensus_waiting_for_certs? If
* this is too recent, we shouldn't try to fetch a new consensus for a
* little while, to give ourselves time to get certificates for this one. */
@@ -210,14 +208,11 @@ networkstatus_reset_download_failures(void)
download_status_reset(&consensus_bootstrap_dl_status[i]);
}
-/**
- * Read and and return the cached consensus of type <b>flavorname</b>. If
- * <b>unverified</b> is true, get the one we haven't verified. Return NULL if
- * the file isn't there. */
+/** Return the filename used to cache the consensus of a given flavor */
static char *
-networkstatus_read_cached_consensus_impl(int flav,
- const char *flavorname,
- int unverified_consensus)
+networkstatus_get_cache_fname(int flav,
+ const char *flavorname,
+ int unverified_consensus)
{
char buf[128];
const char *prefix;
@@ -232,21 +227,35 @@ networkstatus_read_cached_consensus_impl(int flav,
tor_snprintf(buf, sizeof(buf), "%s-%s-consensus", prefix, flavorname);
}
- char *filename = get_cachedir_fname(buf);
- char *result = read_file_to_str(filename, RFTS_IGNORE_MISSING, NULL);
+ return get_cachedir_fname(buf);
+}
+
+/**
+ * Read and and return the cached consensus of type <b>flavorname</b>. If
+ * <b>unverified</b> is false, get the one we haven't verified. Return NULL if
+ * the file isn't there. */
+static tor_mmap_t *
+networkstatus_map_cached_consensus_impl(int flav,
+ const char *flavorname,
+ int unverified_consensus)
+{
+ char *filename = networkstatus_get_cache_fname(flav,
+ flavorname,
+ unverified_consensus);
+ tor_mmap_t *result = tor_mmap_file(filename);
tor_free(filename);
return result;
}
-/** Return a new string containing the current cached consensus of flavor
- * <b>flavorname</b>. */
-char *
-networkstatus_read_cached_consensus(const char *flavorname)
- {
+/** Map the file containing the current cached consensus of flavor
+ * <b>flavorname</b> */
+tor_mmap_t *
+networkstatus_map_cached_consensus(const char *flavorname)
+{
int flav = networkstatus_parse_flavor_name(flavorname);
if (flav < 0)
return NULL;
- return networkstatus_read_cached_consensus_impl(flav, flavorname, 0);
+ return networkstatus_map_cached_consensus_impl(flav, flavorname, 0);
}
/** Read every cached v3 consensus networkstatus from the disk. */
@@ -259,24 +268,26 @@ router_reload_consensus_networkstatus(void)
/* FFFF Suppress warnings if cached consensus is bad? */
for (flav = 0; flav < N_CONSENSUS_FLAVORS; ++flav) {
const char *flavor = networkstatus_get_flavor_name(flav);
- char *s = networkstatus_read_cached_consensus_impl(flav, flavor, 0);
- if (s) {
- if (networkstatus_set_current_consensus(s, flavor, flags, NULL) < -1) {
+ tor_mmap_t *m = networkstatus_map_cached_consensus_impl(flav, flavor, 0);
+ if (m) {
+ if (networkstatus_set_current_consensus(m->data, m->size,
+ flavor, flags, NULL) < -1) {
log_warn(LD_FS, "Couldn't load consensus %s networkstatus from cache",
flavor);
}
- tor_free(s);
+ tor_munmap_file(m);
}
- s = networkstatus_read_cached_consensus_impl(flav, flavor, 1);
- if (s) {
- if (networkstatus_set_current_consensus(s, flavor,
+ m = networkstatus_map_cached_consensus_impl(flav, flavor, 1);
+ if (m) {
+ if (networkstatus_set_current_consensus(m->data, m->size,
+ flavor,
flags | NSSET_WAS_WAITING_FOR_CERTS,
NULL)) {
log_info(LD_FS, "Couldn't load unverified consensus %s networkstatus "
"from cache", flavor);
}
- tor_free(s);
+ tor_munmap_file(m);
}
}
@@ -1844,6 +1855,7 @@ warn_early_consensus(const networkstatus_t *c, const char *flavor,
*/
int
networkstatus_set_current_consensus(const char *consensus,
+ size_t consensus_len,
const char *flavor,
unsigned flags,
const char *source_dir)
@@ -1872,7 +1884,9 @@ networkstatus_set_current_consensus(const char *consensus,
}
/* Make sure it's parseable. */
- c = networkstatus_parse_vote_from_string(consensus, NULL, NS_TYPE_CONSENSUS);
+ c = networkstatus_parse_vote_from_string(consensus,
+ consensus_len,
+ NULL, NS_TYPE_CONSENSUS);
if (!c) {
log_warn(LD_DIR, "Unable to parse networkstatus consensus");
result = -2;
@@ -1960,14 +1974,12 @@ networkstatus_set_current_consensus(const char *consensus,
c->valid_after > current_valid_after) {
waiting = &consensus_waiting_for_certs[flav];
networkstatus_vote_free(waiting->consensus);
- tor_free(waiting->body);
waiting->consensus = c;
free_consensus = 0;
- waiting->body = tor_strdup(consensus);
waiting->set_at = now;
waiting->dl_failed = 0;
if (!from_cache) {
- write_str_to_file(unverified_fname, consensus, 0);
+ write_bytes_to_file(unverified_fname, consensus, consensus_len, 0);
}
if (dl_certs)
authority_certs_fetch_missing(c, now, source_dir);
@@ -2058,10 +2070,6 @@ networkstatus_set_current_consensus(const char *consensus,
waiting->consensus->valid_after <= c->valid_after) {
networkstatus_vote_free(waiting->consensus);
waiting->consensus = NULL;
- if (consensus != waiting->body)
- tor_free(waiting->body);
- else
- waiting->body = NULL;
waiting->set_at = 0;
waiting->dl_failed = 0;
if (unlink(unverified_fname) != 0) {
@@ -2111,17 +2119,18 @@ networkstatus_set_current_consensus(const char *consensus,
if (we_want_to_fetch_flavor(options, flav)) {
if (dir_server_mode(get_options())) {
dirserv_set_cached_consensus_networkstatus(consensus,
+ consensus_len,
flavor,
&c->digests,
c->digest_sha3_as_signed,
c->valid_after);
- consdiffmgr_add_consensus(consensus, c);
+ consdiffmgr_add_consensus(consensus, consensus_len, c);
}
}
if (!from_cache) {
- write_str_to_file(consensus_fname, consensus, 0);
+ write_bytes_to_file(consensus_fname, consensus, consensus_len, 0);
}
warn_early_consensus(c, flavor, now);
@@ -2157,14 +2166,16 @@ networkstatus_note_certs_arrived(const char *source_dir)
if (!waiting->consensus)
continue;
if (networkstatus_check_consensus_signature(waiting->consensus, 0)>=0) {
- char *waiting_body = waiting->body;
- if (!networkstatus_set_current_consensus(
- waiting_body,
- flavor_name,
- NSSET_WAS_WAITING_FOR_CERTS,
- source_dir)) {
- tor_free(waiting_body);
+ tor_mmap_t *mapping = networkstatus_map_cached_consensus_impl(
+ i, flavor_name, 1);
+ if (mapping) {
+ networkstatus_set_current_consensus(mapping->data,
+ mapping->size,
+ flavor_name,
+ NSSET_WAS_WAITING_FOR_CERTS,
+ source_dir);
}
+ tor_munmap_file(mapping);
}
}
}
@@ -2721,6 +2732,5 @@ networkstatus_free_all(void)
networkstatus_vote_free(waiting->consensus);
waiting->consensus = NULL;
}
- tor_free(waiting->body);
}
}
diff --git a/src/feature/nodelist/networkstatus.h b/src/feature/nodelist/networkstatus.h
index 6f8b2dc964..8802de2d65 100644
--- a/src/feature/nodelist/networkstatus.h
+++ b/src/feature/nodelist/networkstatus.h
@@ -16,7 +16,7 @@
void networkstatus_reset_warnings(void);
void networkstatus_reset_download_failures(void);
-char *networkstatus_read_cached_consensus(const char *flavorname);
+tor_mmap_t *networkstatus_map_cached_consensus(const char *flavorname);
int router_reload_consensus_networkstatus(void);
void routerstatus_free_(routerstatus_t *rs);
#define routerstatus_free(rs) \
@@ -105,6 +105,7 @@ int networkstatus_consensus_has_ipv6(const or_options_t* options);
#define NSSET_ACCEPT_OBSOLETE 8
#define NSSET_REQUIRE_FLAVOR 16
int networkstatus_set_current_consensus(const char *consensus,
+ size_t consensus_len,
const char *flavor,
unsigned flags,
const char *source_dir);
@@ -156,4 +157,3 @@ extern networkstatus_t *current_md_consensus;
#endif /* defined(NETWORKSTATUS_PRIVATE) */
#endif /* !defined(TOR_NETWORKSTATUS_H) */
-
diff --git a/src/feature/nodelist/nodelist.c b/src/feature/nodelist/nodelist.c
index a98a5c8655..a1a1b0ea37 100644
--- a/src/feature/nodelist/nodelist.c
+++ b/src/feature/nodelist/nodelist.c
@@ -1867,6 +1867,9 @@ int
addrs_in_same_network_family(const tor_addr_t *a1,
const tor_addr_t *a2)
{
+ if (tor_addr_is_null(a1) || tor_addr_is_null(a2))
+ return 0;
+
switch (tor_addr_family(a1)) {
case AF_INET:
return 0 == tor_addr_compare_masked(a1, a2, 16, CMP_SEMANTIC);
@@ -1917,7 +1920,13 @@ nodes_in_same_family(const node_t *node1, const node_t *node2)
tor_addr_t a1, a2;
node_get_addr(node1, &a1);
node_get_addr(node2, &a2);
- if (addrs_in_same_network_family(&a1, &a2))
+
+ tor_addr_port_t ap6_1, ap6_2;
+ node_get_pref_ipv6_orport(node1, &ap6_1);
+ node_get_pref_ipv6_orport(node2, &ap6_2);
+
+ if (addrs_in_same_network_family(&a1, &a2) ||
+ addrs_in_same_network_family(&ap6_1.addr, &ap6_2.addr))
return 1;
}
@@ -1974,12 +1983,17 @@ nodelist_add_node_and_family(smartlist_t *sl, const node_t *node)
/* First, add any nodes with similar network addresses. */
if (options->EnforceDistinctSubnets) {
tor_addr_t node_addr;
+ tor_addr_port_t node_ap6;
node_get_addr(node, &node_addr);
+ node_get_pref_ipv6_orport(node, &node_ap6);
SMARTLIST_FOREACH_BEGIN(all_nodes, const node_t *, node2) {
tor_addr_t a;
+ tor_addr_port_t ap6;
node_get_addr(node2, &a);
- if (addrs_in_same_network_family(&a, &node_addr))
+ node_get_pref_ipv6_orport(node2, &ap6);
+ if (addrs_in_same_network_family(&a, &node_addr) ||
+ addrs_in_same_network_family(&ap6.addr, &node_ap6.addr))
smartlist_add(sl, (void*)node2);
} SMARTLIST_FOREACH_END(node2);
}
diff --git a/src/feature/relay/dns.c b/src/feature/relay/dns.c
index bc507d47f6..701719af95 100644
--- a/src/feature/relay/dns.c
+++ b/src/feature/relay/dns.c
@@ -1357,6 +1357,42 @@ evdns_err_is_transient(int err)
}
}
+/**
+ * Return number of configured nameservers in <b>the_evdns_base</b>.
+ */
+size_t
+number_of_configured_nameservers(void)
+{
+ return evdns_base_count_nameservers(the_evdns_base);
+}
+
+#ifdef HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR
+/**
+ * Return address of configured nameserver in <b>the_evdns_base</b>
+ * at index <b>idx</b>.
+ */
+tor_addr_t *
+configured_nameserver_address(const size_t idx)
+{
+ struct sockaddr_storage sa;
+ ev_socklen_t sa_len = sizeof(sa);
+
+ if (evdns_base_get_nameserver_addr(the_evdns_base, (int)idx,
+ (struct sockaddr *)&sa,
+ sa_len) > 0) {
+ tor_addr_t *tor_addr = tor_malloc(sizeof(tor_addr_t));
+ if (tor_addr_from_sockaddr(tor_addr,
+ (const struct sockaddr *)&sa,
+ NULL) == 0) {
+ return tor_addr;
+ }
+ tor_free(tor_addr);
+ }
+
+ return NULL;
+}
+#endif
+
/** Configure eventdns nameservers if force is true, or if the configuration
* has changed since the last time we called this function, or if we failed on
* our last attempt. On Unix, this reads from /etc/resolv.conf or
@@ -1388,16 +1424,23 @@ configure_nameservers(int force)
evdns_set_log_fn(evdns_log_cb);
if (conf_fname) {
log_debug(LD_FS, "stat()ing %s", conf_fname);
- if (stat(sandbox_intern_string(conf_fname), &st)) {
+ int missing_resolv_conf = 0;
+ int stat_res = stat(sandbox_intern_string(conf_fname), &st);
+
+ if (stat_res) {
log_warn(LD_EXIT, "Unable to stat resolver configuration in '%s': %s",
conf_fname, strerror(errno));
- goto err;
- }
- if (!force && resolv_conf_fname && !strcmp(conf_fname,resolv_conf_fname)
+ missing_resolv_conf = 1;
+ } else if (!force && resolv_conf_fname &&
+ !strcmp(conf_fname,resolv_conf_fname)
&& st.st_mtime == resolv_conf_mtime) {
log_info(LD_EXIT, "No change to '%s'", conf_fname);
return 0;
}
+
+ if (stat_res == 0 && st.st_size == 0)
+ missing_resolv_conf = 1;
+
if (nameservers_configured) {
evdns_base_search_clear(the_evdns_base);
evdns_base_clear_nameservers_and_suspend(the_evdns_base);
@@ -1410,20 +1453,34 @@ configure_nameservers(int force)
sandbox_intern_string("/etc/hosts"));
}
#endif /* defined(DNS_OPTION_HOSTSFILE) && defined(USE_LIBSECCOMP) */
- log_info(LD_EXIT, "Parsing resolver configuration in '%s'", conf_fname);
- if ((r = evdns_base_resolv_conf_parse(the_evdns_base, flags,
- sandbox_intern_string(conf_fname)))) {
- log_warn(LD_EXIT, "Unable to parse '%s', or no nameservers in '%s' (%d)",
- conf_fname, conf_fname, r);
- goto err;
- }
- if (evdns_base_count_nameservers(the_evdns_base) == 0) {
- log_warn(LD_EXIT, "Unable to find any nameservers in '%s'.", conf_fname);
- goto err;
+
+ if (!missing_resolv_conf) {
+ log_info(LD_EXIT, "Parsing resolver configuration in '%s'", conf_fname);
+ if ((r = evdns_base_resolv_conf_parse(the_evdns_base, flags,
+ sandbox_intern_string(conf_fname)))) {
+ log_warn(LD_EXIT, "Unable to parse '%s', or no nameservers "
+ "in '%s' (%d)", conf_fname, conf_fname, r);
+
+ if (r != 6) // "r = 6" means "no DNS servers were in resolv.conf" -
+ goto err; // in which case we expect libevent to add 127.0.0.1 as
+ // fallback.
+ }
+ if (evdns_base_count_nameservers(the_evdns_base) == 0) {
+ log_warn(LD_EXIT, "Unable to find any nameservers in '%s'.",
+ conf_fname);
+ }
+
+ tor_free(resolv_conf_fname);
+ resolv_conf_fname = tor_strdup(conf_fname);
+ resolv_conf_mtime = st.st_mtime;
+ } else {
+ log_warn(LD_EXIT, "Could not read your DNS config from '%s' - "
+ "please investigate your DNS configuration. "
+ "This is possibly a problem. Meanwhile, falling"
+ " back to local DNS at 127.0.0.1.", conf_fname);
+ evdns_base_nameserver_ip_add(the_evdns_base, "127.0.0.1");
}
- tor_free(resolv_conf_fname);
- resolv_conf_fname = tor_strdup(conf_fname);
- resolv_conf_mtime = st.st_mtime;
+
if (nameservers_configured)
evdns_base_resume(the_evdns_base);
}
diff --git a/src/feature/relay/dns.h b/src/feature/relay/dns.h
index 1dd6f903d1..5758ea4363 100644
--- a/src/feature/relay/dns.h
+++ b/src/feature/relay/dns.h
@@ -45,6 +45,11 @@ size_t dns_cache_handle_oom(time_t now, size_t min_remove_bytes);
#ifdef DNS_PRIVATE
#include "feature/relay/dns_structs.h"
+size_t number_of_configured_nameservers(void);
+#ifdef HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR
+tor_addr_t *configured_nameserver_address(const size_t idx);
+#endif
+
MOCK_DECL(STATIC int,dns_resolve_impl,(edge_connection_t *exitconn,
int is_resolve,or_circuit_t *oncirc, char **hostname_out,
int *made_connection_pending_out, cached_resolve_t **resolve_out));
diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c
index 4afcddc675..3a819f592c 100644
--- a/src/feature/relay/router.c
+++ b/src/feature/relay/router.c
@@ -636,7 +636,7 @@ load_authority_keyset(int legacy, crypto_pk_t **key_out,
fname);
goto done;
}
- parsed = authority_cert_parse_from_string(cert, &eos);
+ parsed = authority_cert_parse_from_string(cert, strlen(cert), &eos);
if (!parsed) {
log_warn(LD_DIR, "Unable to parse certificate in %s", fname);
goto done;
diff --git a/src/lib/net/address.c b/src/lib/net/address.c
index 03767e2950..c97a17037a 100644
--- a/src/lib/net/address.c
+++ b/src/lib/net/address.c
@@ -1187,14 +1187,22 @@ tor_addr_parse(tor_addr_t *addr, const char *src)
int result;
struct in_addr in_tmp;
struct in6_addr in6_tmp;
+ int brackets_detected = 0;
+
tor_assert(addr && src);
- if (src[0] == '[' && src[1])
+
+ size_t len = strlen(src);
+
+ if (len && src[0] == '[' && src[len - 1] == ']') {
+ brackets_detected = 1;
src = tmp = tor_strndup(src+1, strlen(src)-2);
+ }
if (tor_inet_pton(AF_INET6, src, &in6_tmp) > 0) {
result = AF_INET6;
tor_addr_from_in6(addr, &in6_tmp);
- } else if (tor_inet_pton(AF_INET, src, &in_tmp) > 0) {
+ } else if (!brackets_detected &&
+ tor_inet_pton(AF_INET, src, &in_tmp) > 0) {
result = AF_INET;
tor_addr_from_in(addr, &in_tmp);
} else {
diff --git a/src/lib/net/inaddr.c b/src/lib/net/inaddr.c
index dcd8fcdd65..0960d323c5 100644
--- a/src/lib/net/inaddr.c
+++ b/src/lib/net/inaddr.c
@@ -168,6 +168,13 @@ tor_inet_pton(int af, const char *src, void *dst)
if (af == AF_INET) {
return tor_inet_aton(src, dst);
} else if (af == AF_INET6) {
+ ssize_t len = strlen(src);
+
+ /* Reject if src has needless trailing ':'. */
+ if (len > 2 && src[len - 1] == ':' && src[len - 2] != ':') {
+ return 0;
+ }
+
struct in6_addr *out = dst;
uint16_t words[8];
int gapPos = -1, i, setWords=0;
@@ -207,7 +214,6 @@ tor_inet_pton(int af, const char *src, void *dst)
return 0;
if (TOR_ISXDIGIT(*src)) {
char *next;
- ssize_t len;
long r = strtol(src, &next, 16);
if (next == NULL || next == src) {
/* The 'next == src' error case can happen on versions of openbsd
diff --git a/src/lib/thread/.may_include b/src/lib/thread/.may_include
index 93ad0cd734..fc56f46836 100644
--- a/src/lib/thread/.may_include
+++ b/src/lib/thread/.may_include
@@ -4,3 +4,4 @@ lib/lock/*.h
lib/log/*.h
lib/testsupport/*.h
lib/thread/*.h
+lib/wallclock/*.h
diff --git a/src/lib/thread/compat_pthreads.c b/src/lib/thread/compat_pthreads.c
index 934067e4c1..e5c8805ddc 100644
--- a/src/lib/thread/compat_pthreads.c
+++ b/src/lib/thread/compat_pthreads.c
@@ -12,6 +12,7 @@
#include "orconfig.h"
#include "lib/thread/threads.h"
+#include "lib/wallclock/timeval.h"
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock
index 1d2a7359aa..7d6a6635c5 100644
--- a/src/rust/Cargo.lock
+++ b/src/rust/Cargo.lock
@@ -26,6 +26,7 @@ version = "0.0.1"
dependencies = [
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
"smartlist 0.0.1",
+ "tor_allocate 0.0.1",
]
[[package]]
diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml
index e399dbb33a..83f9629660 100644
--- a/src/rust/Cargo.toml
+++ b/src/rust/Cargo.toml
@@ -13,19 +13,3 @@ members = [
[profile.release]
debug = true
panic = "abort"
-
-[features]
-default = []
-# If this feature is enabled, test code which calls Tor C code from Rust will
-# execute with `cargo test`. Due to numerous linker issues (#25386), this is
-# currently disabled by default. Crates listed here are those which, in their
-# unittests, doctests, and/or integration tests, call C code.
-test-c-from-rust = [
- "crypto/test-c-from-rust",
-]
-
-# We have to define a feature here because doctests don't get cfg(test),
-# and we need to disable some C dependencies when running the doctests
-# because of the various linker issues. See
-# https://github.com/rust-lang/rust/issues/45599
-test_linking_hack = []
diff --git a/src/rust/crypto/Cargo.toml b/src/rust/crypto/Cargo.toml
index 6ebfe0dc11..a7ff7f78d9 100644
--- a/src/rust/crypto/Cargo.toml
+++ b/src/rust/crypto/Cargo.toml
@@ -9,7 +9,6 @@ build = "../build.rs"
[lib]
name = "crypto"
path = "lib.rs"
-crate_type = ["rlib", "staticlib"]
[dependencies]
libc = "=0.2.39"
diff --git a/src/rust/external/Cargo.toml b/src/rust/external/Cargo.toml
index 4735144ee6..5f443645bb 100644
--- a/src/rust/external/Cargo.toml
+++ b/src/rust/external/Cargo.toml
@@ -5,14 +5,12 @@ name = "external"
[dependencies]
libc = "=0.2.39"
-
-[dependencies.smartlist]
-path = "../smartlist"
+smartlist = { path = "../smartlist" }
+tor_allocate = { path = "../tor_allocate" }
[lib]
name = "external"
path = "lib.rs"
-crate_type = ["rlib", "staticlib"]
[features]
# We have to define a feature here because doctests don't get cfg(test),
diff --git a/src/rust/external/lib.rs b/src/rust/external/lib.rs
index b72a4f6e4c..d68036fcad 100644
--- a/src/rust/external/lib.rs
+++ b/src/rust/external/lib.rs
@@ -8,7 +8,7 @@
//! module implementing this functionality repeatedly.
extern crate libc;
-
+extern crate tor_allocate;
extern crate smartlist;
pub mod crypto_digest;
diff --git a/src/rust/protover/Cargo.toml b/src/rust/protover/Cargo.toml
index 2f7783e76c..84a7c71c1a 100644
--- a/src/rust/protover/Cargo.toml
+++ b/src/rust/protover/Cargo.toml
@@ -31,4 +31,3 @@ path = "../tor_log"
[lib]
name = "protover"
path = "lib.rs"
-crate_type = ["rlib", "staticlib"]
diff --git a/src/rust/protover/ffi.rs b/src/rust/protover/ffi.rs
index f17f30127d..ac149fbbbc 100644
--- a/src/rust/protover/ffi.rs
+++ b/src/rust/protover/ffi.rs
@@ -187,11 +187,7 @@ pub extern "C" fn protover_get_supported_protocols() -> *const c_char {
//
// Why is the threshold a signed integer? —isis
#[no_mangle]
-pub extern "C" fn protover_compute_vote(
- list: *const Stringlist,
- threshold: c_int,
- allow_long_proto_names: bool,
-) -> *mut c_char {
+pub extern "C" fn protover_compute_vote(list: *const Stringlist, threshold: c_int) -> *mut c_char {
if list.is_null() {
return allocate_and_copy_string("");
}
@@ -203,16 +199,9 @@ pub extern "C" fn protover_compute_vote(
let mut proto_entries: Vec<UnvalidatedProtoEntry> = Vec::new();
for datum in data {
- let entry: UnvalidatedProtoEntry = if allow_long_proto_names {
- match UnvalidatedProtoEntry::from_str_any_len(datum.as_str()) {
- Ok(n) => n,
- Err(_) => continue,
- }
- } else {
- match datum.parse() {
- Ok(n) => n,
- Err(_) => continue,
- }
+ let entry: UnvalidatedProtoEntry = match datum.parse() {
+ Ok(n) => n,
+ Err(_) => continue,
};
proto_entries.push(entry);
}
diff --git a/src/rust/smartlist/Cargo.toml b/src/rust/smartlist/Cargo.toml
index 4ecdf50869..a5afe7bf74 100644
--- a/src/rust/smartlist/Cargo.toml
+++ b/src/rust/smartlist/Cargo.toml
@@ -9,7 +9,6 @@ libc = "0.2.39"
[lib]
name = "smartlist"
path = "lib.rs"
-crate_type = ["rlib", "staticlib"]
[features]
# We have to define a feature here because doctests don't get cfg(test),
diff --git a/src/rust/smartlist/lib.rs b/src/rust/smartlist/lib.rs
index 2716842af2..34d0b907ed 100644
--- a/src/rust/smartlist/lib.rs
+++ b/src/rust/smartlist/lib.rs
@@ -6,3 +6,12 @@ extern crate libc;
mod smartlist;
pub use smartlist::*;
+
+// When testing we may be compiled with sanitizers which are incompatible with
+// Rust's default allocator, jemalloc (unsure why at this time). Most crates
+// link to `tor_allocate` which switches by default to a non-jemalloc allocator,
+// but we don't already depend on `tor_allocate` so make sure that while testing
+// we don't use jemalloc. (but rather malloc/free)
+#[global_allocator]
+#[cfg(test)]
+static A: std::alloc::System = std::alloc::System;
diff --git a/src/rust/tor_allocate/Cargo.toml b/src/rust/tor_allocate/Cargo.toml
index 7bb3b9887f..06ac605f17 100644
--- a/src/rust/tor_allocate/Cargo.toml
+++ b/src/rust/tor_allocate/Cargo.toml
@@ -9,7 +9,6 @@ libc = "=0.2.39"
[lib]
name = "tor_allocate"
path = "lib.rs"
-crate_type = ["rlib", "staticlib"]
[features]
# We have to define a feature here because doctests don't get cfg(test),
diff --git a/src/rust/tor_allocate/lib.rs b/src/rust/tor_allocate/lib.rs
index 5a355bc8d6..1cfa0b5178 100644
--- a/src/rust/tor_allocate/lib.rs
+++ b/src/rust/tor_allocate/lib.rs
@@ -11,5 +11,10 @@
extern crate libc;
+use std::alloc::System;
+
mod tor_allocate;
pub use tor_allocate::*;
+
+#[global_allocator]
+static A: System = System;
diff --git a/src/rust/tor_log/Cargo.toml b/src/rust/tor_log/Cargo.toml
index 1aa9be0612..14d9ae803a 100644
--- a/src/rust/tor_log/Cargo.toml
+++ b/src/rust/tor_log/Cargo.toml
@@ -6,7 +6,6 @@ authors = ["The Tor Project"]
[lib]
name = "tor_log"
path = "lib.rs"
-crate_type = ["rlib", "staticlib"]
[features]
# We have to define a feature here because doctests don't get cfg(test),
diff --git a/src/rust/tor_rust/Cargo.toml b/src/rust/tor_rust/Cargo.toml
index 1523ee0dd1..35c629882e 100644
--- a/src/rust/tor_rust/Cargo.toml
+++ b/src/rust/tor_rust/Cargo.toml
@@ -6,7 +6,7 @@ version = "0.1.0"
[lib]
name = "tor_rust"
path = "lib.rs"
-crate_type = ["rlib", "staticlib"]
+crate_type = ["staticlib"]
[dependencies.tor_util]
path = "../tor_util"
diff --git a/src/rust/tor_util/Cargo.toml b/src/rust/tor_util/Cargo.toml
index 51e4bd9c5d..9ffaeda8a6 100644
--- a/src/rust/tor_util/Cargo.toml
+++ b/src/rust/tor_util/Cargo.toml
@@ -6,7 +6,6 @@ version = "0.0.1"
[lib]
name = "tor_util"
path = "lib.rs"
-crate_type = ["rlib", "staticlib"]
[dependencies.tor_allocate]
path = "../tor_allocate"
diff --git a/src/test/bench.c b/src/test/bench.c
index 959d4374b1..9da1b46a1b 100644
--- a/src/test/bench.c
+++ b/src/test/bench.c
@@ -702,11 +702,13 @@ main(int argc, const char **argv)
perror("X");
return 1;
}
+ size_t f1len = strlen(f1);
+ size_t f2len = strlen(f2);
for (i = 0; i < N; ++i) {
- char *diff = consensus_diff_generate(f1, f2);
+ char *diff = consensus_diff_generate(f1, f1len, f2, f2len);
tor_free(diff);
}
- char *diff = consensus_diff_generate(f1, f2);
+ char *diff = consensus_diff_generate(f1, f1len, f2, f2len);
printf("%s", diff);
tor_free(f1);
tor_free(f2);
diff --git a/src/test/bt_test.py b/src/test/bt_test.py
index 0eeb58c16c..f8894aac0b 100755
--- a/src/test/bt_test.py
+++ b/src/test/bt_test.py
@@ -44,10 +44,12 @@ print("BAD")
for l in LINES:
print("{}".format(l), end="")
-if sys.platform.startswith('freebsd'):
- # See bug #17808 if you know how to fix this.
- print("Test failed; but FreeBSD is known to have backtrace problems.\n"
- "Treating as 'SKIP'.")
+if (sys.platform.startswith('freebsd') or sys.platform.startswith('netbsd') or
+ sys.platform.startswith('openbsd') or sys.platform.startswith('darwin')):
+ # See bug #17808 if you know how to fix backtraces on BSD-derived systems
+ print("Test failed; but {} is known to have backtrace problems."
+ .format(sys.platform))
+ print("Treating as 'SKIP'.")
sys.exit(77)
sys.exit(1)
diff --git a/src/test/fuzz/fuzz_consensus.c b/src/test/fuzz/fuzz_consensus.c
index b56702a650..1a4195b418 100644
--- a/src/test/fuzz/fuzz_consensus.c
+++ b/src/test/fuzz/fuzz_consensus.c
@@ -61,13 +61,13 @@ int
fuzz_main(const uint8_t *data, size_t sz)
{
networkstatus_t *ns;
- char *str = tor_memdup_nulterm(data, sz);
const char *eos = NULL;
networkstatus_type_t tp = NS_TYPE_CONSENSUS;
if (tor_memstr(data, MIN(sz, 1024), "tus vote"))
tp = NS_TYPE_VOTE;
const char *what = (tp == NS_TYPE_CONSENSUS) ? "consensus" : "vote";
- ns = networkstatus_parse_vote_from_string(str,
+ ns = networkstatus_parse_vote_from_string((const char *)data,
+ sz,
&eos,
tp);
if (ns) {
@@ -76,6 +76,6 @@ fuzz_main(const uint8_t *data, size_t sz)
} else {
log_debug(LD_GENERAL, "Parsing as %s failed", what);
}
- tor_free(str);
+
return 0;
}
diff --git a/src/test/fuzz/fuzz_diff.c b/src/test/fuzz/fuzz_diff.c
index 1079856fdb..64aecc8a64 100644
--- a/src/test/fuzz/fuzz_diff.c
+++ b/src/test/fuzz/fuzz_diff.c
@@ -10,9 +10,11 @@
#include "test/fuzz/fuzzing.h"
static int
-mock_consensus_compute_digest_(const char *c, consensus_digest_t *d)
+mock_consensus_compute_digest_(const char *c, size_t len,
+ consensus_digest_t *d)
{
(void)c;
+ (void)len;
memset(d->sha3_256, 3, sizeof(d->sha3_256));
return 0;
}
@@ -42,28 +44,34 @@ fuzz_main(const uint8_t *stdin_buf, size_t data_size)
if (! separator)
return 0;
size_t c1_len = separator - stdin_buf;
- char *c1 = tor_memdup_nulterm(stdin_buf, c1_len);
+ const char *c1 = (const char *)stdin_buf;
size_t c2_len = data_size - c1_len - SEPLEN;
- char *c2 = tor_memdup_nulterm(separator + SEPLEN, c2_len);
+ const char *c2 = (const char *)separator + SEPLEN;
- char *c3 = consensus_diff_generate(c1, c2);
+ const char *cp = memchr(c1, 0, c1_len);
+ if (cp)
+ c1_len = cp - c1;
+
+ cp = memchr(c2, 0, c2_len);
+ if (cp)
+ c2_len = cp - c2;
+
+ char *c3 = consensus_diff_generate(c1, c1_len, c2, c2_len);
if (c3) {
- char *c4 = consensus_diff_apply(c1, c3);
+ char *c4 = consensus_diff_apply(c1, c1_len, c3, strlen(c3));
tor_assert(c4);
- if (strcmp(c2, c4)) {
- printf("%s\n", escaped(c1));
- printf("%s\n", escaped(c2));
+ int equal = (c2_len == strlen(c4)) && fast_memeq(c2, c4, c2_len);
+ if (! equal) {
+ //printf("%s\n", escaped(c1));
+ //printf("%s\n", escaped(c2));
printf("%s\n", escaped(c3));
printf("%s\n", escaped(c4));
}
- tor_assert(! strcmp(c2, c4));
+ tor_assert(equal);
tor_free(c3);
tor_free(c4);
}
- tor_free(c1);
- tor_free(c2);
return 0;
}
-
diff --git a/src/test/fuzz/fuzz_diff_apply.c b/src/test/fuzz/fuzz_diff_apply.c
index 165d0e6126..9b25185225 100644
--- a/src/test/fuzz/fuzz_diff_apply.c
+++ b/src/test/fuzz/fuzz_diff_apply.c
@@ -10,9 +10,11 @@
#include "test/fuzz/fuzzing.h"
static int
-mock_consensus_compute_digest_(const char *c, consensus_digest_t *d)
+mock_consensus_compute_digest_(const char *c, size_t len,
+ consensus_digest_t *d)
{
(void)c;
+ (void)len;
memset(d->sha3_256, 3, sizeof(d->sha3_256));
return 0;
}
@@ -50,16 +52,13 @@ fuzz_main(const uint8_t *stdin_buf, size_t data_size)
if (! separator)
return 0;
size_t c1_len = separator - stdin_buf;
- char *c1 = tor_memdup_nulterm(stdin_buf, c1_len);
+ const char *c1 = (const char *)stdin_buf;
size_t c2_len = data_size - c1_len - SEPLEN;
- char *c2 = tor_memdup_nulterm(separator + SEPLEN, c2_len);
+ const char *c2 = (const char *)separator + SEPLEN;
- char *c3 = consensus_diff_apply(c1, c2);
+ char *c3 = consensus_diff_apply(c1, c1_len, c2, c2_len);
- tor_free(c1);
- tor_free(c2);
tor_free(c3);
return 0;
}
-
diff --git a/src/test/fuzz/fuzz_vrs.c b/src/test/fuzz/fuzz_vrs.c
index 0b869aa5c0..3c6d205a3f 100644
--- a/src/test/fuzz/fuzz_vrs.c
+++ b/src/test/fuzz/fuzz_vrs.c
@@ -53,24 +53,24 @@ fuzz_cleanup(void)
int
fuzz_main(const uint8_t *data, size_t sz)
{
- char *str = tor_memdup_nulterm(data, sz);
const char *s;
routerstatus_t *rs_ns = NULL, *rs_md = NULL, *rs_vote = NULL;
vote_routerstatus_t *vrs = tor_malloc_zero(sizeof(*vrs));
smartlist_t *tokens = smartlist_new();
+ const char *eos = (const char *)data + sz;
- s = str;
- rs_ns = routerstatus_parse_entry_from_string(area, &s, tokens,
+ s = (const char *)data;
+ rs_ns = routerstatus_parse_entry_from_string(area, &s, eos, tokens,
NULL, NULL, 26, FLAV_NS);
tor_assert(smartlist_len(tokens) == 0);
- s = str;
- rs_md = routerstatus_parse_entry_from_string(area, &s, tokens,
+ s = (const char *)data;
+ rs_md = routerstatus_parse_entry_from_string(area, &s, eos, tokens,
NULL, NULL, 26, FLAV_MICRODESC);
tor_assert(smartlist_len(tokens) == 0);
- s = str;
- rs_vote = routerstatus_parse_entry_from_string(area, &s, tokens,
+ s = (const char *)data;
+ rs_vote = routerstatus_parse_entry_from_string(area, &s, eos, tokens,
dummy_vote, vrs, 26, FLAV_NS);
tor_assert(smartlist_len(tokens) == 0);
@@ -82,6 +82,6 @@ fuzz_main(const uint8_t *data, size_t sz)
vote_routerstatus_free(vrs);
memarea_clear(area);
smartlist_free(tokens);
- tor_free(str);
+
return 0;
}
diff --git a/src/test/include.am b/src/test/include.am
index dd2986c67c..e5eae56e25 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -12,8 +12,7 @@ TESTS_ENVIRONMENT = \
export EXTRA_CARGO_OPTIONS="$(EXTRA_CARGO_OPTIONS)"; \
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";
+ export RUSTFLAGS="-C linker=`echo '$(CC)' | cut -d' ' -f 1` $(RUST_LINKER_OPTIONS)";
TESTSCRIPTS = \
src/test/fuzz_static_testcases.sh \
diff --git a/src/test/test_addr.c b/src/test/test_addr.c
index a9004048a5..1d97db52a6 100644
--- a/src/test/test_addr.c
+++ b/src/test/test_addr.c
@@ -723,7 +723,7 @@ test_addr_ip6_helpers(void *arg)
;
}
-/** Test tor_addr_port_parse(). */
+/** Test tor_addr_parse() and tor_addr_port_parse(). */
static void
test_addr_parse(void *arg)
{
@@ -734,6 +734,60 @@ test_addr_parse(void *arg)
/* Correct call. */
(void)arg;
+ r= tor_addr_parse(&addr, "192.0.2.1");
+ tt_int_op(r,OP_EQ, AF_INET);
+ tor_addr_to_str(buf, &addr, sizeof(buf), 0);
+ tt_str_op(buf,OP_EQ, "192.0.2.1");
+
+ r= tor_addr_parse(&addr, "11:22::33:44");
+ tt_int_op(r,OP_EQ, AF_INET6);
+ tor_addr_to_str(buf, &addr, sizeof(buf), 0);
+ tt_str_op(buf,OP_EQ, "11:22::33:44");
+
+ r= tor_addr_parse(&addr, "[11:22::33:44]");
+ tt_int_op(r,OP_EQ, AF_INET6);
+ tor_addr_to_str(buf, &addr, sizeof(buf), 0);
+ tt_str_op(buf,OP_EQ, "11:22::33:44");
+
+ r= tor_addr_parse(&addr, "11:22:33:44:55:66:1.2.3.4");
+ tt_int_op(r,OP_EQ, AF_INET6);
+ tor_addr_to_str(buf, &addr, sizeof(buf), 0);
+ tt_str_op(buf,OP_EQ, "11:22:33:44:55:66:102:304");
+
+ r= tor_addr_parse(&addr, "11:22::33:44:1.2.3.4");
+ tt_int_op(r,OP_EQ, AF_INET6);
+ tor_addr_to_str(buf, &addr, sizeof(buf), 0);
+ tt_str_op(buf,OP_EQ, "11:22::33:44:102:304");
+
+ /* Empty string. */
+ r= tor_addr_parse(&addr, "");
+ tt_int_op(r,OP_EQ, -1);
+
+ /* Square brackets around IPv4 address. */
+ r= tor_addr_parse(&addr, "[192.0.2.1]");
+ tt_int_op(r,OP_EQ, -1);
+
+ /* Only left square bracket. */
+ r= tor_addr_parse(&addr, "[11:22::33:44");
+ tt_int_op(r,OP_EQ, -1);
+
+ /* Only right square bracket. */
+ r= tor_addr_parse(&addr, "11:22::33:44]");
+ tt_int_op(r,OP_EQ, -1);
+
+ /* Leading colon. */
+ r= tor_addr_parse(&addr, ":11:22::33:44");
+ tt_int_op(r,OP_EQ, -1);
+
+ /* Trailing colon. */
+ r= tor_addr_parse(&addr, "11:22::33:44:");
+ tt_int_op(r,OP_EQ, -1);
+
+ /* Too many hex words in IPv4-mapped IPv6 address. */
+ r= tor_addr_parse(&addr, "11:22:33:44:55:66:77:88:1.2.3.4");
+ tt_int_op(r,OP_EQ, -1);
+
+ /* Correct call. */
r= tor_addr_port_parse(LOG_DEBUG,
"192.0.2.1:1234",
&addr, &port, -1);
diff --git a/src/test/test_address.c b/src/test/test_address.c
index e99220f838..69de072cfa 100644
--- a/src/test/test_address.c
+++ b/src/test/test_address.c
@@ -24,6 +24,8 @@
#endif /* defined(HAVE_IFCONF_TO_SMARTLIST) */
#include "core/or/or.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/node_st.h"
#include "feature/nodelist/nodelist.h"
#include "lib/net/address.h"
#include "test/test.h"
@@ -1170,6 +1172,78 @@ test_address_tor_addr_in_same_network_family(void *ignored)
return;
}
+static node_t *
+helper_create_mock_node(char id_char)
+{
+ node_t *node = tor_malloc_zero(sizeof(node_t));
+ routerinfo_t *ri = tor_malloc_zero(sizeof(routerinfo_t));
+ tor_addr_make_null(&ri->ipv6_addr, AF_INET6);
+ node->ri = ri;
+ memset(node->identity, id_char, sizeof(node->identity));
+ return node;
+}
+
+static void
+helper_free_mock_node(node_t *node)
+{
+ tor_free(node->ri);
+ tor_free(node);
+}
+
+#define NODE_SET_IPV4(node, ipv4_addr, ipv4_port) { \
+ tor_addr_t addr; \
+ tor_addr_parse(&addr, ipv4_addr); \
+ node->ri->addr = tor_addr_to_ipv4h(&addr); \
+ node->ri->or_port = ipv4_port; \
+ }
+
+#define NODE_CLEAR_IPV4(node) { \
+ node->ri->addr = 0; \
+ node->ri->or_port = 0; \
+ }
+
+#define NODE_SET_IPV6(node, ipv6_addr_str, ipv6_port) { \
+ tor_addr_parse(&node->ri->ipv6_addr, ipv6_addr_str); \
+ node->ri->ipv6_orport = ipv6_port; \
+ }
+
+static void
+test_address_tor_node_in_same_network_family(void *ignored)
+{
+ (void)ignored;
+ node_t *node_a = helper_create_mock_node('a');
+ node_t *node_b = helper_create_mock_node('b');
+
+ NODE_SET_IPV4(node_a, "8.8.8.8", 1);
+ NODE_SET_IPV4(node_b, "8.8.4.4", 1);
+
+ tt_int_op(nodes_in_same_family(node_a, node_b), OP_EQ, 1);
+
+ NODE_SET_IPV4(node_a, "8.8.8.8", 1);
+ NODE_SET_IPV4(node_b, "1.1.1.1", 1);
+
+ tt_int_op(nodes_in_same_family(node_a, node_b), OP_EQ, 0);
+
+ NODE_CLEAR_IPV4(node_a);
+ NODE_SET_IPV6(node_a, "2001:470:20::2", 1);
+
+ tt_int_op(nodes_in_same_family(node_a, node_b), OP_EQ, 0);
+
+ NODE_CLEAR_IPV4(node_b);
+ NODE_SET_IPV6(node_b, "2606:4700:4700::1111", 1);
+
+ tt_int_op(nodes_in_same_family(node_a, node_b), OP_EQ, 0);
+
+ NODE_SET_IPV6(node_a, "2606:4700:4700::1001", 1);
+ tt_int_op(nodes_in_same_family(node_a, node_b), OP_EQ, 1);
+
+ helper_free_mock_node(node_a);
+ helper_free_mock_node(node_b);
+
+ done:
+ return;
+}
+
#define ADDRESS_TEST(name, flags) \
{ #name, test_address_ ## name, flags, NULL, NULL }
@@ -1202,6 +1276,7 @@ struct testcase_t address_tests[] = {
ADDRESS_TEST(tor_addr_to_mapped_ipv4h, 0),
ADDRESS_TEST(tor_addr_eq_ipv4h, 0),
ADDRESS_TEST(tor_addr_in_same_network_family, 0),
+ ADDRESS_TEST(tor_node_in_same_network_family, 0),
END_OF_TESTCASES
};
diff --git a/src/test/test_consdiff.c b/src/test/test_consdiff.c
index b836befd22..23e8f7167e 100644
--- a/src/test/test_consdiff.c
+++ b/src/test/test_consdiff.c
@@ -14,6 +14,39 @@
#define tt_str_eq_line(a,b) \
tt_assert(line_str_eq((b),(a)))
+static int
+consensus_split_lines_(smartlist_t *out, const char *s, memarea_t *area)
+{
+ size_t len = strlen(s);
+ return consensus_split_lines(out, s, len, area);
+}
+
+static int
+consensus_compute_digest_(const char *cons,
+ consensus_digest_t *digest_out)
+{
+ size_t len = strlen(cons);
+ char *tmp = tor_memdup(cons, len);
+ // We use memdup here to ensure that the input is NOT nul-terminated.
+ // This makes it likelier for us to spot bugs.
+ int r = consensus_compute_digest(tmp, len, digest_out);
+ tor_free(tmp);
+ return r;
+}
+
+static int
+consensus_compute_digest_as_signed_(const char *cons,
+ consensus_digest_t *digest_out)
+{
+ size_t len = strlen(cons);
+ char *tmp = tor_memdup(cons, len);
+ // We use memdup here to ensure that the input is NOT nul-terminated.
+ // This makes it likelier for us to spot bugs.
+ int r = consensus_compute_digest_as_signed(tmp, len, digest_out);
+ tor_free(tmp);
+ return r;
+}
+
static void
test_consdiff_smartlist_slice(void *arg)
{
@@ -58,7 +91,7 @@ test_consdiff_smartlist_slice_string_pos(void *arg)
/* Create a regular smartlist. */
(void)arg;
- consensus_split_lines(sl, "a\nd\nc\na\nb\n", area);
+ consensus_split_lines_(sl, "a\nd\nc\na\nb\n", area);
/* See that smartlist_slice_string_pos respects the bounds of the slice. */
sls = smartlist_slice(sl, 2, 5);
@@ -87,8 +120,8 @@ test_consdiff_lcs_lengths(void *arg)
int e_lengths2[] = { 0, 1, 1, 2, 3, 4 };
(void)arg;
- consensus_split_lines(sl1, "a\nb\nc\nd\ne\n", area);
- consensus_split_lines(sl2, "a\nc\nd\ni\ne\n", area);
+ consensus_split_lines_(sl1, "a\nb\nc\nd\ne\n", area);
+ consensus_split_lines_(sl2, "a\nc\nd\ni\ne\n", area);
sls1 = smartlist_slice(sl1, 0, -1);
sls2 = smartlist_slice(sl2, 0, -1);
@@ -119,10 +152,10 @@ test_consdiff_trim_slices(void *arg)
memarea_t *area = memarea_new();
(void)arg;
- consensus_split_lines(sl1, "a\nb\nb\nb\nd\n", area);
- consensus_split_lines(sl2, "a\nc\nc\nc\nd\n", area);
- consensus_split_lines(sl3, "a\nb\nb\nb\na\n", area);
- consensus_split_lines(sl4, "c\nb\nb\nb\nc\n", area);
+ consensus_split_lines_(sl1, "a\nb\nb\nb\nd\n", area);
+ consensus_split_lines_(sl2, "a\nc\nc\nc\nd\n", area);
+ consensus_split_lines_(sl3, "a\nb\nb\nb\na\n", area);
+ consensus_split_lines_(sl4, "c\nb\nb\nb\nc\n", area);
sls1 = smartlist_slice(sl1, 0, -1);
sls2 = smartlist_slice(sl2, 0, -1);
sls3 = smartlist_slice(sl3, 0, -1);
@@ -165,8 +198,8 @@ test_consdiff_set_changed(void *arg)
memarea_t *area = memarea_new();
(void)arg;
- consensus_split_lines(sl1, "a\nb\na\na\n", area);
- consensus_split_lines(sl2, "a\na\na\na\n", area);
+ consensus_split_lines_(sl1, "a\nb\na\na\n", area);
+ consensus_split_lines_(sl2, "a\na\na\na\n", area);
/* Length of sls1 is 0. */
sls1 = smartlist_slice(sl1, 0, 0);
@@ -240,8 +273,8 @@ test_consdiff_calc_changes(void *arg)
memarea_t *area = memarea_new();
(void)arg;
- consensus_split_lines(sl1, "a\na\na\na\n", area);
- consensus_split_lines(sl2, "a\na\na\na\n", area);
+ consensus_split_lines_(sl1, "a\na\na\na\n", area);
+ consensus_split_lines_(sl2, "a\na\na\na\n", area);
sls1 = smartlist_slice(sl1, 0, -1);
sls2 = smartlist_slice(sl2, 0, -1);
@@ -259,7 +292,7 @@ test_consdiff_calc_changes(void *arg)
tt_assert(!bitarray_is_set(changed2, 3));
smartlist_clear(sl2);
- consensus_split_lines(sl2, "a\nb\na\nb\n", area);
+ consensus_split_lines_(sl2, "a\nb\na\nb\n", area);
tor_free(sls1);
tor_free(sls2);
sls1 = smartlist_slice(sl1, 0, -1);
@@ -282,7 +315,7 @@ test_consdiff_calc_changes(void *arg)
bitarray_clear(changed1, 3);
smartlist_clear(sl2);
- consensus_split_lines(sl2, "b\nb\nb\nb\n", area);
+ consensus_split_lines_(sl2, "b\nb\nb\nb\n", area);
tor_free(sls1);
tor_free(sls2);
sls1 = smartlist_slice(sl1, 0, -1);
@@ -610,8 +643,8 @@ test_consdiff_gen_ed_diff(void *arg)
/* Test 'a', 'c' and 'd' together. See that it is done in reverse order. */
smartlist_clear(cons1);
smartlist_clear(cons2);
- consensus_split_lines(cons1, "A\nB\nC\nD\nE\n", area);
- consensus_split_lines(cons2, "A\nC\nO\nE\nU\n", area);
+ consensus_split_lines_(cons1, "A\nB\nC\nD\nE\n", area);
+ consensus_split_lines_(cons2, "A\nC\nO\nE\nU\n", area);
diff = gen_ed_diff(cons1, cons2, area);
tt_ptr_op(NULL, OP_NE, diff);
tt_int_op(7, OP_EQ, smartlist_len(diff));
@@ -627,8 +660,8 @@ test_consdiff_gen_ed_diff(void *arg)
smartlist_clear(cons1);
smartlist_clear(cons2);
- consensus_split_lines(cons1, "B\n", area);
- consensus_split_lines(cons2, "A\nB\n", area);
+ consensus_split_lines_(cons1, "B\n", area);
+ consensus_split_lines_(cons2, "A\nB\n", area);
diff = gen_ed_diff(cons1, cons2, area);
tt_ptr_op(NULL, OP_NE, diff);
tt_int_op(3, OP_EQ, smartlist_len(diff));
@@ -656,7 +689,7 @@ test_consdiff_apply_ed_diff(void *arg)
diff = smartlist_new();
setup_capture_of_logs(LOG_WARN);
- consensus_split_lines(cons1, "A\nB\nC\nD\nE\n", area);
+ consensus_split_lines_(cons1, "A\nB\nC\nD\nE\n", area);
/* Command without range. */
smartlist_add_linecpy(diff, area, "a");
@@ -829,7 +862,7 @@ test_consdiff_apply_ed_diff(void *arg)
smartlist_clear(diff);
/* Test appending text, 'a'. */
- consensus_split_lines(diff, "3a\nU\nO\n.\n0a\nV\n.\n", area);
+ consensus_split_lines_(diff, "3a\nU\nO\n.\n0a\nV\n.\n", area);
cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_NE, cons2);
tt_int_op(8, OP_EQ, smartlist_len(cons2));
@@ -846,7 +879,7 @@ test_consdiff_apply_ed_diff(void *arg)
smartlist_free(cons2);
/* Test deleting text, 'd'. */
- consensus_split_lines(diff, "4d\n1,2d\n", area);
+ consensus_split_lines_(diff, "4d\n1,2d\n", area);
cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_NE, cons2);
tt_int_op(2, OP_EQ, smartlist_len(cons2));
@@ -857,7 +890,7 @@ test_consdiff_apply_ed_diff(void *arg)
smartlist_free(cons2);
/* Test changing text, 'c'. */
- consensus_split_lines(diff, "4c\nT\nX\n.\n1,2c\nM\n.\n", area);
+ consensus_split_lines_(diff, "4c\nT\nX\n.\n1,2c\nM\n.\n", area);
cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_NE, cons2);
tt_int_op(5, OP_EQ, smartlist_len(cons2));
@@ -871,7 +904,7 @@ test_consdiff_apply_ed_diff(void *arg)
smartlist_free(cons2);
/* Test 'a', 'd' and 'c' together. */
- consensus_split_lines(diff, "4c\nT\nX\n.\n2d\n0a\nM\n.\n", area);
+ consensus_split_lines_(diff, "4c\nT\nX\n.\n2d\n0a\nM\n.\n", area);
cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_NE, cons2);
tt_int_op(6, OP_EQ, smartlist_len(cons2));
@@ -918,12 +951,12 @@ test_consdiff_gen_diff(void *arg)
);
tt_int_op(0, OP_EQ,
- consensus_compute_digest_as_signed(cons1_str, &digests1));
+ consensus_compute_digest_as_signed_(cons1_str, &digests1));
tt_int_op(0, OP_EQ,
- consensus_compute_digest(cons2_str, &digests2));
+ consensus_compute_digest_(cons2_str, &digests2));
- consensus_split_lines(cons1, cons1_str, area);
- consensus_split_lines(cons2, cons2_str, area);
+ consensus_split_lines_(cons1, cons1_str, area);
+ consensus_split_lines_(cons2, cons2_str, area);
diff = consdiff_gen_diff(cons1, cons2, &digests1, &digests2, area);
tt_ptr_op(NULL, OP_EQ, diff);
@@ -937,9 +970,9 @@ test_consdiff_gen_diff(void *arg)
"directory-signature foo bar\nbar\n"
);
tt_int_op(0, OP_EQ,
- consensus_compute_digest_as_signed(cons1_str, &digests1));
+ consensus_compute_digest_as_signed_(cons1_str, &digests1));
smartlist_clear(cons1);
- consensus_split_lines(cons1, cons1_str, area);
+ consensus_split_lines_(cons1, cons1_str, area);
diff = consdiff_gen_diff(cons1, cons2, &digests1, &digests2, area);
tt_ptr_op(NULL, OP_NE, diff);
tt_int_op(11, OP_EQ, smartlist_len(diff));
@@ -991,8 +1024,8 @@ test_consdiff_apply_diff(void *arg)
"directory-signature foo bar\nbar\n"
);
tt_int_op(0, OP_EQ,
- consensus_compute_digest(cons1_str, &digests1));
- consensus_split_lines(cons1, cons1_str, area);
+ consensus_compute_digest_(cons1_str, &digests1));
+ consensus_split_lines_(cons1, cons1_str, area);
/* diff doesn't have enough lines. */
cons2 = consdiff_apply_diff(cons1, diff, &digests1);
@@ -1182,4 +1215,3 @@ struct testcase_t consdiff_tests[] = {
CONSDIFF_LEGACY(apply_diff),
END_OF_TESTCASES
};
-
diff --git a/src/test/test_consdiffmgr.c b/src/test/test_consdiffmgr.c
index 6c451da685..b84753ff83 100644
--- a/src/test/test_consdiffmgr.c
+++ b/src/test/test_consdiffmgr.c
@@ -21,6 +21,23 @@
#include "test/test.h"
#include "test/log_test_helpers.h"
+#define consdiffmgr_add_consensus consdiffmgr_add_consensus_nulterm
+
+static char *
+consensus_diff_apply_(const char *c, const char *d)
+{
+ size_t c_len = strlen(c);
+ size_t d_len = strlen(d);
+ // We use memdup here to ensure that the input is NOT nul-terminated.
+ // This makes it likelier for us to spot bugs.
+ char *c_tmp = tor_memdup(c, c_len);
+ char *d_tmp = tor_memdup(d, d_len);
+ char *result = consensus_diff_apply(c_tmp, c_len, d_tmp, d_len);
+ tor_free(c_tmp);
+ tor_free(d_tmp);
+ return result;
+}
+
// ============================== Setup/teardown the consdiffmgr
// These functions get run before/after each test in this module
@@ -153,7 +170,8 @@ lookup_diff_from(consensus_cache_entry_t **out,
const char *str1)
{
uint8_t digest[DIGEST256_LEN];
- if (router_get_networkstatus_v3_sha3_as_signed(digest, str1)<0) {
+ if (router_get_networkstatus_v3_sha3_as_signed(digest,
+ str1, strlen(str1))<0) {
TT_FAIL(("Unable to compute sha3-as-signed"));
return CONSDIFF_NOT_FOUND;
}
@@ -175,14 +193,15 @@ lookup_apply_and_verify_diff(consensus_flavor_t flav,
consensus_cache_entry_incref(ent);
size_t size;
- char *diff_string = NULL;
- int r = uncompress_or_copy(&diff_string, &size, ent);
+ const char *diff_string = NULL;
+ char *diff_owned = NULL;
+ int r = uncompress_or_set_ptr(&diff_string, &size, &diff_owned, ent);
consensus_cache_entry_decref(ent);
if (diff_string == NULL || r < 0)
return -1;
- char *applied = consensus_diff_apply(str1, diff_string);
- tor_free(diff_string);
+ char *applied = consensus_diff_apply(str1, strlen(str1), diff_string, size);
+ tor_free(diff_owned);
if (applied == NULL)
return -1;
@@ -282,7 +301,8 @@ test_consdiffmgr_add(void *arg)
(void) arg;
time_t now = approx_time();
- char *body = NULL;
+ const char *body = NULL;
+ char *body_owned = NULL;
consensus_cache_entry_t *ent = NULL;
networkstatus_t *ns_tmp = fake_ns_new(FLAV_NS, now);
@@ -324,7 +344,7 @@ test_consdiffmgr_add(void *arg)
tt_assert(ent);
consensus_cache_entry_incref(ent);
size_t s;
- r = uncompress_or_copy(&body, &s, ent);
+ r = uncompress_or_set_ptr(&body, &s, &body_owned, ent);
tt_int_op(r, OP_EQ, 0);
tt_int_op(s, OP_EQ, 4);
tt_mem_op(body, OP_EQ, "quux", 4);
@@ -337,7 +357,7 @@ test_consdiffmgr_add(void *arg)
networkstatus_vote_free(ns_tmp);
teardown_capture_of_logs();
consensus_cache_entry_decref(ent);
- tor_free(body);
+ tor_free(body_owned);
}
static void
@@ -370,7 +390,8 @@ test_consdiffmgr_make_diffs(void *arg)
ns = fake_ns_new(FLAV_MICRODESC, now-3600);
md_ns_body = fake_ns_body_new(FLAV_MICRODESC, now-3600);
r = consdiffmgr_add_consensus(md_ns_body, ns);
- router_get_networkstatus_v3_sha3_as_signed(md_ns_sha3, md_ns_body);
+ router_get_networkstatus_v3_sha3_as_signed(md_ns_sha3, md_ns_body,
+ strlen(md_ns_body));
networkstatus_vote_free(ns);
tt_int_op(r, OP_EQ, 0);
@@ -414,7 +435,7 @@ test_consdiffmgr_make_diffs(void *arg)
r = consensus_cache_entry_get_body(diff, &diff_body, &diff_size);
tt_int_op(r, OP_EQ, 0);
diff_text = tor_memdup_nulterm(diff_body, diff_size);
- applied = consensus_diff_apply(md_ns_body, diff_text);
+ applied = consensus_diff_apply_(md_ns_body, diff_text);
tt_assert(applied);
tt_str_op(applied, OP_EQ, md_ns_body_2);
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index c18aa99fea..26ba269abd 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -94,6 +94,23 @@
#define NS_MODULE dir
+static networkstatus_t *
+networkstatus_parse_vote_from_string_(const char *s,
+ const char **eos_out,
+ enum networkstatus_type_t ns_type)
+{
+ size_t len = strlen(s);
+ // memdup so that it won't be nul-terminated.
+ char *tmp = tor_memdup(s, len);
+ networkstatus_t *result =
+ networkstatus_parse_vote_from_string(tmp, len, eos_out, ns_type);
+ if (eos_out && *eos_out) {
+ *eos_out = s + (*eos_out - tmp);
+ }
+ tor_free(tmp);
+ return result;
+}
+
static void
test_dir_nicknames(void *arg)
{
@@ -2806,11 +2823,17 @@ test_a_networkstatus(
MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
/* Parse certificates and keys. */
- cert1 = mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL);
+ cert1 = mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1,
+ strlen(AUTHORITY_CERT_1),
+ NULL);
tt_assert(cert1);
- cert2 = authority_cert_parse_from_string(AUTHORITY_CERT_2, NULL);
+ cert2 = authority_cert_parse_from_string(AUTHORITY_CERT_2,
+ strlen(AUTHORITY_CERT_2),
+ NULL);
tt_assert(cert2);
- cert3 = authority_cert_parse_from_string(AUTHORITY_CERT_3, NULL);
+ cert3 = authority_cert_parse_from_string(AUTHORITY_CERT_3,
+ strlen(AUTHORITY_CERT_3),
+ NULL);
tt_assert(cert3);
sign_skey_1 = crypto_pk_new();
sign_skey_2 = crypto_pk_new();
@@ -2912,7 +2935,7 @@ test_a_networkstatus(
sign_skey_leg1,
FLAV_NS);
tt_assert(consensus_text);
- con = networkstatus_parse_vote_from_string(consensus_text, NULL,
+ con = networkstatus_parse_vote_from_string_(consensus_text, NULL,
NS_TYPE_CONSENSUS);
tt_assert(con);
//log_notice(LD_GENERAL, "<<%s>>\n<<%s>>\n<<%s>>\n",
@@ -2924,7 +2947,7 @@ test_a_networkstatus(
sign_skey_leg1,
FLAV_MICRODESC);
tt_assert(consensus_text_md);
- con_md = networkstatus_parse_vote_from_string(consensus_text_md, NULL,
+ con_md = networkstatus_parse_vote_from_string_(consensus_text_md, NULL,
NS_TYPE_CONSENSUS);
tt_assert(con_md);
tt_int_op(con_md->flavor,OP_EQ, FLAV_MICRODESC);
@@ -3023,13 +3046,13 @@ test_a_networkstatus(
tt_assert(consensus_text3);
tt_assert(consensus_text_md2);
tt_assert(consensus_text_md3);
- con2 = networkstatus_parse_vote_from_string(consensus_text2, NULL,
+ con2 = networkstatus_parse_vote_from_string_(consensus_text2, NULL,
NS_TYPE_CONSENSUS);
- con3 = networkstatus_parse_vote_from_string(consensus_text3, NULL,
+ con3 = networkstatus_parse_vote_from_string_(consensus_text3, NULL,
NS_TYPE_CONSENSUS);
- con_md2 = networkstatus_parse_vote_from_string(consensus_text_md2, NULL,
+ con_md2 = networkstatus_parse_vote_from_string_(consensus_text_md2, NULL,
NS_TYPE_CONSENSUS);
- con_md3 = networkstatus_parse_vote_from_string(consensus_text_md3, NULL,
+ con_md3 = networkstatus_parse_vote_from_string_(consensus_text_md3, NULL,
NS_TYPE_CONSENSUS);
tt_assert(con2);
tt_assert(con3);
@@ -6044,9 +6067,10 @@ test_dir_assumed_flags(void *arg)
"192.168.0.1 9001 0\n"
"m thisoneislongerbecauseitisa256bitmddigest33\n"
"s Fast Guard Stable\n";
+ const char *eos = str1 + strlen(str1);
const char *cp = str1;
- rs = routerstatus_parse_entry_from_string(area, &cp, tokens, NULL, NULL,
+ rs = routerstatus_parse_entry_from_string(area, &cp, eos, tokens, NULL, NULL,
24, FLAV_MICRODESC);
tt_assert(rs);
tt_assert(rs->is_flagged_running);
diff --git a/src/test/test_dir_common.c b/src/test/test_dir_common.c
index 86d2838944..eadeb11921 100644
--- a/src/test/test_dir_common.c
+++ b/src/test/test_dir_common.c
@@ -42,14 +42,20 @@ dir_common_authority_pk_init(authority_cert_t **cert1,
{
/* Parse certificates and keys. */
authority_cert_t *cert;
- cert = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL);
+ cert = authority_cert_parse_from_string(AUTHORITY_CERT_1,
+ strlen(AUTHORITY_CERT_1),
+ NULL);
tt_assert(cert);
tt_assert(cert->identity_key);
*cert1 = cert;
tt_assert(*cert1);
- *cert2 = authority_cert_parse_from_string(AUTHORITY_CERT_2, NULL);
+ *cert2 = authority_cert_parse_from_string(AUTHORITY_CERT_2,
+ strlen(AUTHORITY_CERT_2),
+ NULL);
tt_assert(*cert2);
- *cert3 = authority_cert_parse_from_string(AUTHORITY_CERT_3, NULL);
+ *cert3 = authority_cert_parse_from_string(AUTHORITY_CERT_3,
+ strlen(AUTHORITY_CERT_3),
+ NULL);
tt_assert(*cert3);
*sign_skey_1 = crypto_pk_new();
*sign_skey_2 = crypto_pk_new();
@@ -266,7 +272,9 @@ dir_common_add_rs_and_parse(networkstatus_t *vote, networkstatus_t **vote_out,
/* dump the vote and try to parse it. */
v_text = format_networkstatus_vote(sign_skey, vote);
tt_assert(v_text);
- *vote_out = networkstatus_parse_vote_from_string(v_text, NULL, NS_TYPE_VOTE);
+ *vote_out = networkstatus_parse_vote_from_string(v_text,
+ strlen(v_text),
+ NULL, NS_TYPE_VOTE);
done:
if (v_text)
@@ -424,4 +432,3 @@ dir_common_construct_vote_3(networkstatus_t **vote, authority_cert_t *cert,
return 0;
}
-
diff --git a/src/test/test_dir_handle_get.c b/src/test/test_dir_handle_get.c
index 1d4a36d7fc..2ce98769af 100644
--- a/src/test/test_dir_handle_get.c
+++ b/src/test/test_dir_handle_get.c
@@ -72,6 +72,8 @@ ENABLE_GCC_WARNING(overlength-strings)
#define NOT_ENOUGH_CONSENSUS_SIGNATURES "HTTP/1.0 404 " \
"Consensus not signed by sufficient number of requested authorities\r\n\r\n"
+#define consdiffmgr_add_consensus consdiffmgr_add_consensus_nulterm
+
static dir_connection_t *
new_dir_conn(void)
{
@@ -1275,7 +1277,9 @@ test_dir_handle_get_server_keys_authority(void* data)
size_t body_used = 0;
(void) data;
- mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE, NULL);
+ mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE,
+ strlen(TEST_CERTIFICATE),
+ NULL);
MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
@@ -1425,7 +1429,9 @@ test_dir_handle_get_server_keys_sk(void* data)
size_t body_used = 0;
(void) data;
- mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE, NULL);
+ mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE,
+ strlen(TEST_CERTIFICATE),
+ NULL);
MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
@@ -2393,7 +2399,9 @@ test_dir_handle_get_status_vote_next_authority(void* data)
routerlist_free_all();
dirvote_free_all();
- mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE, NULL);
+ mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE,
+ strlen(TEST_CERTIFICATE),
+ NULL);
/* create a trusted ds */
ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
@@ -2471,7 +2479,9 @@ test_dir_handle_get_status_vote_current_authority(void* data)
routerlist_free_all();
dirvote_free_all();
- mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE, NULL);
+ mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE,
+ strlen(TEST_CERTIFICATE),
+ NULL);
/* create a trusted ds */
ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
diff --git a/src/test/test_dns.c b/src/test/test_dns.c
index 8369f844f6..ea0fcf8c5e 100644
--- a/src/test/test_dns.c
+++ b/src/test/test_dns.c
@@ -1,6 +1,7 @@
/* Copyright (c) 2015-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+#include "orconfig.h"
#include "core/or/or.h"
#include "test/test.h"
@@ -13,9 +14,71 @@
#include "core/or/edge_connection_st.h"
#include "core/or/or_circuit_st.h"
+#include "app/config/or_options_st.h"
+#include "app/config/config.h"
+
+#include <event2/event.h>
+#include <event2/dns.h>
#define NS_MODULE dns
+#ifdef HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR
+#define NS_SUBMODULE configure_nameservers_fallback
+
+static or_options_t options = {
+ .ORPort_set = 1,
+};
+
+static const or_options_t *
+mock_get_options(void)
+{
+ return &options;
+}
+
+static void
+NS(test_main)(void *arg)
+{
+ (void)arg;
+ tor_addr_t *nameserver_addr = NULL;
+
+ MOCK(get_options, mock_get_options);
+
+ options.ServerDNSResolvConfFile = (char *)"no_such_file!!!";
+
+ dns_init(); // calls configure_nameservers()
+
+ tt_int_op(number_of_configured_nameservers(), OP_EQ, 1);
+
+ nameserver_addr = configured_nameserver_address(0);
+
+ tt_assert(tor_addr_family(nameserver_addr) == AF_INET);
+ tt_assert(tor_addr_eq_ipv4h(nameserver_addr, 0x7f000001));
+
+#ifndef _WIN32
+ tor_free(nameserver_addr);
+
+ options.ServerDNSResolvConfFile = (char *)"/dev/null";
+
+ dns_init();
+
+ tt_int_op(number_of_configured_nameservers(), OP_EQ, 1);
+
+ nameserver_addr = configured_nameserver_address(0);
+
+ tt_assert(tor_addr_family(nameserver_addr) == AF_INET);
+ tt_assert(tor_addr_eq_ipv4h(nameserver_addr, 0x7f000001));
+#endif
+
+ UNMOCK(get_options);
+
+ done:
+ tor_free(nameserver_addr);
+ return;
+}
+
+#undef NS_SUBMODULE
+#endif
+
#define NS_SUBMODULE clip_ttl
static void
@@ -736,6 +799,9 @@ NS(test_main)(void *arg)
#undef NS_SUBMODULE
struct testcase_t dns_tests[] = {
+#ifdef HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR
+ TEST_CASE(configure_nameservers_fallback),
+#endif
TEST_CASE(clip_ttl),
TEST_CASE(resolve),
TEST_CASE_ASPECT(resolve_impl, addr_is_ip_no_need_to_resolve),
diff --git a/src/test/test_hs_config.c b/src/test/test_hs_config.c
index 553b96758a..b6ab0c21f9 100644
--- a/src/test/test_hs_config.c
+++ b/src/test/test_hs_config.c
@@ -366,6 +366,22 @@ test_invalid_service_v3(void *arg)
teardown_capture_of_logs();
}
+ /* v2-specific HiddenServiceAuthorizeClient set. */
+ {
+ const char *conf =
+ "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
+ "HiddenServiceVersion 3\n"
+ "HiddenServiceAuthorizeClient stealth client1\n";
+ setup_full_capture_of_logs(LOG_WARN);
+ ret = helper_config_service(conf, validate_only);
+ tt_int_op(ret, OP_EQ, -1);
+ expect_log_msg_containing("Hidden service option "
+ "HiddenServiceAuthorizeClient is incompatible "
+ "with version 3 of service in "
+ "/tmp/tor-test-hs-RANDOM/hs1");
+ teardown_capture_of_logs();
+ }
+
done:
;
}
diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c
index bfe50eb3c6..ee2d71aa75 100644
--- a/src/test/test_hs_service.c
+++ b/src/test/test_hs_service.c
@@ -1457,7 +1457,7 @@ test_build_update_descriptors(void *arg)
/* Time to test the update of those descriptors. At first, we have no node
* in the routerlist so this will find NO suitable node for the IPs. */
setup_full_capture_of_logs(LOG_INFO);
- update_all_descriptors(now);
+ update_all_descriptors_intro_points(now);
expect_log_msg_containing("Unable to find a suitable node to be an "
"introduction point for service");
teardown_capture_of_logs();
@@ -1508,7 +1508,7 @@ test_build_update_descriptors(void *arg)
/* We expect to pick only one intro point from the node above. */
setup_full_capture_of_logs(LOG_INFO);
- update_all_descriptors(now);
+ update_all_descriptors_intro_points(now);
tor_free(node->ri->onion_curve25519_pkey); /* Avoid memleak. */
tor_free(node->ri->cache_info.signing_key_cert);
tor_free(node->ri->onion_pkey);
diff --git a/src/test/test_routerlist.c b/src/test/test_routerlist.c
index 67af2fd484..1071a095fe 100644
--- a/src/test/test_routerlist.c
+++ b/src/test/test_routerlist.c
@@ -265,7 +265,9 @@ test_router_pick_directory_server_impl(void *arg)
/* Init SR subsystem. */
MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
- mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL);
+ mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1,
+ strlen(AUTHORITY_CERT_1),
+ NULL);
sr_init(0);
UNMOCK(get_my_v3_authority_cert);
@@ -275,7 +277,9 @@ test_router_pick_directory_server_impl(void *arg)
construct_consensus(&consensus_text_md, now);
tt_assert(consensus_text_md);
- con_md = networkstatus_parse_vote_from_string(consensus_text_md, NULL,
+ con_md = networkstatus_parse_vote_from_string(consensus_text_md,
+ strlen(consensus_text_md),
+ NULL,
NS_TYPE_CONSENSUS);
tt_assert(con_md);
tt_int_op(con_md->flavor,OP_EQ, FLAV_MICRODESC);
@@ -475,7 +479,9 @@ test_directory_guard_fetch_with_no_dirinfo(void *arg)
/* 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);
+ mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1,
+ strlen(AUTHORITY_CERT_1),
+ NULL);
sr_init(0);
UNMOCK(get_my_v3_authority_cert);
@@ -648,7 +654,9 @@ test_skew_common(void *arg, time_t now, unsigned long *offset)
/* 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);
+ mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1,
+ strlen(AUTHORITY_CERT_1),
+ NULL);
sr_init(0);
UNMOCK(get_my_v3_authority_cert);
@@ -662,7 +670,8 @@ test_skew_common(void *arg, time_t now, unsigned long *offset)
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,
+ retval = networkstatus_set_current_consensus(consensus, strlen(consensus),
+ "microdesc", 0,
NULL);
done:
diff --git a/src/test/test_rust.sh b/src/test/test_rust.sh
index a1a56af480..00b3e88d37 100755
--- a/src/test/test_rust.sh
+++ b/src/test/test_rust.sh
@@ -5,12 +5,20 @@ set -e
export LSAN_OPTIONS=suppressions=${abs_top_srcdir:-../../..}/src/test/rust_supp.txt
+# When testing Cargo we pass a number of very specific linker flags down
+# through Cargo. We do not, however, want these flags to affect things like
+# build scripts, only the tests that we're compiling. To ensure this happens
+# we unconditionally pass `--target` into Cargo, ensuring that `RUSTFLAGS` in
+# the environment won't make their way into build scripts.
+rustc_host=$(rustc -vV | grep host | sed 's/host: //')
+
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 ${CARGO_ONLINE-"--frozen"} \
- --features "test_linking_hack" \
+ --features "test_linking_hack" \
+ --target $rustc_host \
${EXTRA_CARGO_OPTIONS} \
--manifest-path "${cargo_toml_dir}/Cargo.toml" || exitcode=1
fi
diff --git a/src/test/test_shared_random.c b/src/test/test_shared_random.c
index 8a7fb95cc1..433661f128 100644
--- a/src/test/test_shared_random.c
+++ b/src/test/test_shared_random.c
@@ -65,7 +65,9 @@ init_authority_state(void)
MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
or_options_t *options = get_options_mutable();
- mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL);
+ mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1,
+ strlen(AUTHORITY_CERT_1),
+ NULL);
tt_assert(mock_cert);
options->AuthoritativeDir = 1;
tt_int_op(load_ed_keys(options, time(NULL)), OP_GE, 0);
@@ -421,7 +423,9 @@ test_sr_commit(void *arg)
{ /* Setup a minimal dirauth environment for this test */
or_options_t *options = get_options_mutable();
- auth_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL);
+ auth_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1,
+ strlen(AUTHORITY_CERT_1),
+ NULL);
tt_assert(auth_cert);
options->AuthoritativeDir = 1;
@@ -824,7 +828,9 @@ test_sr_setup_commits(void)
{ /* Setup a minimal dirauth environment for this test */
or_options_t *options = get_options_mutable();
- auth_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL);
+ auth_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1,
+ strlen(AUTHORITY_CERT_1),
+ NULL);
tt_assert(auth_cert);
options->AuthoritativeDir = 1;
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 7bc1b7921a..1a71da2794 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -5808,6 +5808,18 @@ test_util_ipv4_validation(void *arg)
}
static void
+test_util_ipv6_validation(void *arg)
+{
+ (void)arg;
+
+ tt_assert(string_is_valid_ipv6_address("2a00:1450:401b:800::200e"));
+ tt_assert(!string_is_valid_ipv6_address("11:22::33:44:"));
+
+ done:
+ return;
+}
+
+static void
test_util_writepid(void *arg)
{
(void) arg;
@@ -6498,6 +6510,7 @@ struct testcase_t util_tests[] = {
UTIL_TEST(hostname_validation, 0),
UTIL_TEST(dest_validation_edgecase, 0),
UTIL_TEST(ipv4_validation, 0),
+ UTIL_TEST(ipv6_validation, 0),
UTIL_TEST(writepid, 0),
UTIL_TEST(get_avail_disk_space, 0),
UTIL_TEST(touch_file, 0),