aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--CODE_OF_CONDUCT3
-rw-r--r--ChangeLog197
-rw-r--r--README.md13
-rw-r--r--ReleaseNotes197
-rw-r--r--changes/bug404656
-rw-r--r--changes/bug408843
-rw-r--r--changes/bug409115
-rw-r--r--changes/bug409225
-rw-r--r--changes/bug409333
-rw-r--r--changes/mr7604
-rw-r--r--changes/prop3016
-rw-r--r--changes/prop3517
-rw-r--r--changes/tap-out-part-112
-rw-r--r--changes/ticket402482
-rw-r--r--changes/ticket404873
-rw-r--r--changes/ticket406384
-rw-r--r--changes/ticket406764
-rw-r--r--changes/ticket407365
-rw-r--r--changes/ticket408164
-rw-r--r--changes/ticket408174
-rw-r--r--changes/ticket408353
-rw-r--r--changes/ticket408543
-rw-r--r--changes/ticket408704
-rw-r--r--changes/ticket409183
-rw-r--r--configure.ac4
-rw-r--r--contrib/win32build/tor-mingw.nsi.in2
-rw-r--r--doc/man/tor.1.txt59
-rw-r--r--m4/ax_check_compile_flag.m476
-rwxr-xr-xscripts/codegen/get_mozilla_ciphers.py4
-rwxr-xr-xscripts/maint/format_changelog.py2
-rwxr-xr-xscripts/maint/geoip/update_and_commit_geoip.sh2
-rw-r--r--src/app/config/config.c18
-rw-r--r--src/app/config/or_options_st.h2
-rw-r--r--src/app/main/main.c5
-rw-r--r--src/app/main/shutdown.c1
-rw-r--r--src/config/torrc.sample.in4
-rw-r--r--src/core/crypto/include.am2
-rw-r--r--src/core/crypto/onion_crypto.c50
-rw-r--r--src/core/crypto/onion_tap.c246
-rw-r--r--src/core/crypto/onion_tap.h40
-rw-r--r--src/core/or/circuitbuild.c70
-rw-r--r--src/core/or/circuitbuild.h1
-rw-r--r--src/core/or/circuitlist.c10
-rw-r--r--src/core/or/circuitlist.h1
-rw-r--r--src/core/or/circuituse.c2
-rw-r--r--src/core/or/command.c8
-rw-r--r--src/core/or/conflux_pool.c43
-rw-r--r--src/core/or/conflux_pool.h2
-rw-r--r--src/core/or/connection_edge.c110
-rw-r--r--src/core/or/connection_edge.h2
-rw-r--r--src/core/or/connection_or.c4
-rw-r--r--src/core/or/crypt_path_st.h1
-rw-r--r--src/core/or/dos.c127
-rw-r--r--src/core/or/dos.h34
-rw-r--r--src/core/or/dos_options.inc13
-rw-r--r--src/core/or/extend_info_st.h2
-rw-r--r--src/core/or/extendinfo.c22
-rw-r--r--src/core/or/extendinfo.h2
-rw-r--r--src/core/or/half_edge_st.h4
-rw-r--r--src/core/or/onion.c119
-rw-r--r--src/core/or/or.h1
-rw-r--r--src/core/or/or_circuit_st.h4
-rw-r--r--src/core/or/policies.c2
-rw-r--r--src/core/or/protover.c6
-rw-r--r--src/core/or/relay.c5
-rw-r--r--src/core/or/scheduler_kist.c14
-rw-r--r--src/core/proto/proto_socks.c18
-rw-r--r--src/feature/client/bridges.c6
-rw-r--r--src/feature/client/dnsserv.c3
-rw-r--r--src/feature/client/entrynodes.c2
-rw-r--r--src/feature/dirauth/dirauth_config.c55
-rw-r--r--src/feature/dirauth/dirauth_options.inc3
-rw-r--r--src/feature/dirauth/dirvote.c109
-rw-r--r--src/feature/dirauth/dirvote.h32
-rw-r--r--src/feature/dirauth/process_descs.c14
-rw-r--r--src/feature/dirauth/voteflags.c17
-rw-r--r--src/feature/dirparse/microdesc_parse.c7
-rw-r--r--src/feature/dirparse/parsecommon.c13
-rw-r--r--src/feature/dirparse/parsecommon.h1
-rw-r--r--src/feature/dirparse/routerparse.c128
-rw-r--r--src/feature/hs/hs_common.c2
-rw-r--r--src/feature/hs/hs_service.c21
-rw-r--r--src/feature/hs/hs_service.h2
-rw-r--r--src/feature/nodelist/microdesc.c2
-rw-r--r--src/feature/nodelist/microdesc_st.h8
-rw-r--r--src/feature/nodelist/nodelist.c31
-rw-r--r--src/feature/nodelist/nodelist.h1
-rw-r--r--src/feature/nodelist/routerinfo_st.h9
-rw-r--r--src/feature/nodelist/routerlist.c25
-rw-r--r--src/feature/relay/circuitbuild_relay.c7
-rw-r--r--src/feature/relay/dns.c10
-rw-r--r--src/feature/relay/dns.h4
-rw-r--r--src/feature/relay/onion_queue.c90
-rw-r--r--src/feature/relay/relay_config.c4
-rw-r--r--src/feature/relay/relay_metrics.c71
-rw-r--r--src/feature/relay/relay_metrics.h6
-rw-r--r--src/feature/relay/router.c60
-rw-r--r--src/feature/relay/selftest.c6
-rw-r--r--src/feature/stats/rephist.c35
-rw-r--r--src/feature/stats/rephist.h6
-rw-r--r--src/lib/crypt_ops/crypto_openssl_mgt.c5
-rw-r--r--src/lib/crypt_ops/crypto_openssl_mgt.h5
-rw-r--r--src/lib/fs/files.c10
-rw-r--r--src/lib/log/.may_include2
-rw-r--r--src/lib/log/log.c6
-rw-r--r--src/lib/log/log_sys.c29
-rw-r--r--src/lib/log/util_bug.c27
-rw-r--r--src/lib/log/util_bug.h29
-rw-r--r--src/lib/sandbox/sandbox.c241
-rw-r--r--src/lib/string/util_string.c2
-rw-r--r--src/test/bench.c71
-rw-r--r--src/test/test.c207
-rw-r--r--src/test/test_cell_formats.c127
-rw-r--r--src/test/test_circuitpadding.c2
-rw-r--r--src/test/test_conflux_pool.c6
-rw-r--r--src/test/test_dir.c92
-rw-r--r--src/test/test_dirvote.c25
-rw-r--r--src/test/test_entrynodes.c2
-rw-r--r--src/test/test_hs_client.c8
-rw-r--r--src/test/test_hs_service.c2
-rw-r--r--src/test/test_microdesc.c70
-rw-r--r--src/test/test_protover.c4
-rw-r--r--src/test/test_relaycell.c2
-rw-r--r--src/test/test_router.c4
-rw-r--r--src/test/test_sandbox.c20
-rw-r--r--src/test/test_socks.c65
-rw-r--r--src/test/test_status.c13
128 files changed, 1981 insertions, 1531 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3f4a9b7af5..5e0c7ec842 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -270,4 +270,4 @@ rust-latest:
- rustup show
- cargo clippy --all-features --all-targets -- -D warnings
after_script:
- - cargo clean \ No newline at end of file
+ - cargo clean
diff --git a/CODE_OF_CONDUCT b/CODE_OF_CONDUCT
index d8d160a22a..aca978dbb7 100644
--- a/CODE_OF_CONDUCT
+++ b/CODE_OF_CONDUCT
@@ -3,5 +3,4 @@ where people feel safe to engage, share their points of view, and
participate. For the latest version of our Code of Conduct, please
see
-https://gitweb.torproject.org/community/policies.git/plain/code_of_conduct.txt
-
+https://community.torproject.org/policies/code_of_conduct/
diff --git a/ChangeLog b/ChangeLog
index ddac73e784..55b02340fb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,200 @@
+Changes in version 0.4.8.11 - 2024-04-10
+ This is a minor release mostly to upgrade the fallbackdir list.
+ Directory authorities running this version will now automatically
+ reject relays running the end of life 0.4.7.x version.
+
+ o Minor features (directory authorities):
+ - Reject 0.4.7.x series at the authority level. Closes ticket 40896.
+ - New IP address and keys for tor26.
+ - Allow BandwidthFiles "node_id" KeyValue without the dollar sign at
+ the start of the hexdigit, in order to easier database queries
+ combining Tor documents in which the relays fingerprint does not
+ include it. Fixes bug 40891; bugfix on 0.4.7 (all supported
+ versions of Tor).
+
+ o Minor features (fallbackdir):
+ - Regenerate fallback directories generated on April 10, 2024.
+
+ o Minor features (geoip data):
+ - Update the geoip files to match the IPFire Location Database, as
+ retrieved on 2024/04/10.
+
+ o Minor bugfixes (directory authorities):
+ - Add a warning when publishing a vote or signatures to another
+ directory authority fails. Fixes bug 40910; bugfix on 0.2.0.3-alpha.
+
+
+Changes in version 0.4.8.10 - 2023-12-08
+ This is a security release fixing a high severity bug (TROVE-2023-007)
+ affecting Exit relays supporting Conflux. We strongly recommend to update as
+ soon as possible.
+
+ o Major bugfixes (TROVE-2023-007, exit):
+ - Improper error propagation from a safety check in conflux leg
+ linking led to a desynchronization of which legs were part of a
+ conflux set, ultimately causing a UAF and NULL pointer dereference
+ crash on Exit relays. Fixes bug 40897; bugfix on 0.4.8.1-alpha.
+
+ o Minor features (fallbackdir):
+ - Regenerate fallback directories generated on December 08, 2023.
+
+ o Minor features (geoip data):
+ - Update the geoip files to match the IPFire Location Database, as
+ retrieved on 2023/12/08.
+
+ o Minor bugfixes (bridges, statistics):
+ - Correctly report statistics for client count over pluggable
+ transports. Fixes bug 40871; bugfix on 0.4.8.4.
+
+
+Changes in version 0.4.8.9 - 2023-11-09
+ This is another security release fixing a high severity bug affecting onion
+ services which is tracked by TROVE-2023-006. We are also releasing a guard
+ major bugfix as well. If you are an onion service operator, we strongly
+ recommend to update as soon as possible.
+
+ o Major bugfixes (guard usage):
+ - When Tor excluded a guard due to temporary circuit restrictions,
+ it considered *additional* primary guards for potential usage by
+ that circuit. This could result in more than the specified number
+ of guards (currently 2) being used, long-term, by the tor client.
+ This could happen when a Guard was also selected as an Exit node,
+ but it was exacerbated by the Conflux guard restrictions. Both
+ instances have been fixed. Fixes bug 40876; bugfix
+ on 0.3.0.1-alpha.
+
+ o Major bugfixes (onion service, TROVE-2023-006):
+ - Fix a possible hard assert on a NULL pointer when recording a
+ failed rendezvous circuit on the service side for the MetricsPort.
+ Fixes bug 40883; bugfix on 0.4.8.1-alpha.
+
+ o Minor features (fallbackdir):
+ - Regenerate fallback directories generated on November 09, 2023.
+
+ o Minor features (geoip data):
+ - Update the geoip files to match the IPFire Location Database, as
+ retrieved on 2023/11/09.
+
+
+Changes in version 0.4.8.8 - 2023-11-03
+ We are releasing today a fix for a high security issue, TROVE-2023-004, that
+ is affecting relays. Also a few minor bugfixes detailed below. Please upgrade
+ as soon as posssible.
+
+ o Major bugfixes (TROVE-2023-004, relay):
+ - Mitigate an issue when Tor compiled with OpenSSL can crash during
+ handshake with a remote relay. Fixes bug 40874; bugfix
+ on 0.2.7.2-alpha.
+
+ o Minor features (fallbackdir):
+ - Regenerate fallback directories generated on November 03, 2023.
+
+ o Minor features (geoip data):
+ - Update the geoip files to match the IPFire Location Database, as
+ retrieved on 2023/11/03.
+
+ o Minor bugfixes (directory authority):
+ - Look at the network parameter "maxunmeasuredbw" with the correct
+ spelling. Fixes bug 40869; bugfix on 0.4.6.1-alpha.
+
+ o Minor bugfixes (vanguards addon support):
+ - Count the conflux linked cell as valid when it is successfully
+ processed. This will quiet a spurious warn in the vanguards addon.
+ Fixes bug 40878; bugfix on 0.4.8.1-alpha.
+
+
+Changes in version 0.4.8.7 - 2023-09-25
+ This version fixes a single major bug in the Conflux subsystem on the client
+ side. See below for more information. The upcoming Tor Browser 13 stable will
+ pick this up.
+
+ o Major bugfixes (conflux):
+ - Fix an issue that prevented us from pre-building more conflux sets
+ after existing sets had been used. Fixes bug 40862; bugfix
+ on 0.4.8.1-alpha.
+
+ o Minor features (fallbackdir):
+ - Regenerate fallback directories generated on September 25, 2023.
+
+ o Minor features (geoip data):
+ - Update the geoip files to match the IPFire Location Database, as
+ retrieved on 2023/09/25.
+
+
+Changes in version 0.4.8.6 - 2023-09-18
+ This version contains an important fix for onion service regarding congestion
+ control and its reliability. Apart from that, unneeded BUG warnings have been
+ suppressed especially about a compression bomb seen on relays. We strongly
+ recommend, in particular onion service operators, to upgrade as soon as
+ possible to this latest stable.
+
+ o Major bugfixes (onion service):
+ - Fix a reliability issue where services were expiring their
+ introduction points every consensus update. This caused
+ connectivity issues for clients caching the old descriptor and
+ intro points. Bug reported and fixed by gitlab user
+ @hyunsoo.kim676. Fixes bug 40858; bugfix on 0.4.7.5-alpha.
+
+ o Minor features (debugging, compression):
+ - Log the input and output buffer sizes when we detect a potential
+ compression bomb. Diagnostic for ticket 40739.
+
+ o Minor features (fallbackdir):
+ - Regenerate fallback directories generated on September 18, 2023.
+
+ o Minor features (geoip data):
+ - Update the geoip files to match the IPFire Location Database, as
+ retrieved on 2023/09/18.
+
+ o Minor bugfix (defensive programming):
+ - Disable multiple BUG warnings of a missing relay identity key when
+ starting an instance of Tor compiled without relay support. Fixes
+ bug 40848; bugfix on 0.4.3.1-alpha.
+
+ o Minor bugfixes (bridge authority):
+ - When reporting a pseudo-networkstatus as a bridge authority, or
+ answering "ns/purpose/*" controller requests, include accurate
+ published-on dates from our list of router descriptors. Fixes bug
+ 40855; bugfix on 0.4.8.1-alpha.
+
+ o Minor bugfixes (compression, zstd):
+ - Use less frightening language and lower the log-level of our run-
+ time ABI compatibility check message in our Zstd compression
+ subsystem. Fixes bug 40815; bugfix on 0.4.3.1-alpha.
+
+
+Changes in version 0.4.8.5 - 2023-08-30
+ Quick second release after the first stable few days ago fixing minor
+ annoying bugfixes creating log BUG stacktrace. We also fix BSD compilation
+ failures and PoW unit test.
+
+ o Minor features (fallbackdir):
+ - Regenerate fallback directories generated on August 30, 2023.
+
+ o Minor features (geoip data):
+ - Update the geoip files to match the IPFire Location Database, as
+ retrieved on 2023/08/30.
+
+ o Minor bugfix (NetBSD, compilation):
+ - Fix compilation issue on NetBSD by avoiding an unnecessary
+ dependency on "huge" page mappings in Equi-X. Fixes bug 40843;
+ bugfix on 0.4.8.1-alpha.
+
+ o Minor bugfix (NetBSD, testing):
+ - Fix test failures in "crypto/hashx" and "slow/crypto/equix" on
+ x86_64 and aarch64 NetBSD hosts, by adding support for
+ PROT_MPROTECT() flags. Fixes bug 40844; bugfix on 0.4.8.1-alpha.
+
+ o Minor bugfixes (conflux):
+ - Demote a relay-side warn about too many legs to ProtocolWarn, as
+ there are conditions that it can briefly happen during set
+ construction. Also add additional set logging details for all
+ error cases. Fixes bug 40841; bugfix on 0.4.8.1-alpha.
+ - Prevent non-fatal assert stacktrace caused by using conflux sets
+ during their teardown process. Fixes bug 40842; bugfix
+ on 0.4.8.1-alpha.
+
+
Changes in version 0.4.8.4 - 2023-08-23
Finally, this is the very first stable release of the 0.4.8.x series making
Proof-of-Work (prop#327) and Conflux (prop#329) available to the entire
diff --git a/README.md b/README.md
index 4a8db49e53..dc22c52951 100644
--- a/README.md
+++ b/README.md
@@ -58,13 +58,16 @@ Home page:
Download new versions:
-- https://www.torproject.org/download/download.html
+- https://www.torproject.org/download/tor
-Documentation, including links to installation and setup instructions:
+How to verify Tor source:
-- https://www.torproject.org/docs/documentation.html
+- https://support.torproject.org/little-t-tor/
-Frequently Asked Questions:
+Documentation and Frequently Asked Questions:
-- https://www.torproject.org/docs/faq.html
+- https://support.torproject.org/
+How to run a Tor relay:
+
+- https://community.torproject.org/relay/
diff --git a/ReleaseNotes b/ReleaseNotes
index 827ef7d5e5..151236620d 100644
--- a/ReleaseNotes
+++ b/ReleaseNotes
@@ -2,6 +2,203 @@ 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.4.8.11 - 2024-04-10
+ This is a minor release mostly to upgrade the fallbackdir list.
+ Directory authorities running this version will now automatically
+ reject relays running the end of life 0.4.7.x version.
+
+ o Minor features (directory authorities):
+ - Reject 0.4.7.x series at the authority level. Closes ticket 40896.
+ - New IP address and keys for tor26.
+ - Allow BandwidthFiles "node_id" KeyValue without the dollar sign at
+ the start of the hexdigit, in order to easier database queries
+ combining Tor documents in which the relays fingerprint does not
+ include it. Fixes bug 40891; bugfix on 0.4.7 (all supported
+ versions of Tor).
+
+ o Minor features (fallbackdir):
+ - Regenerate fallback directories generated on April 10, 2024.
+
+ o Minor features (geoip data):
+ - Update the geoip files to match the IPFire Location Database, as
+ retrieved on 2024/04/10.
+
+ o Minor bugfixes (directory authorities):
+ - Add a warning when publishing a vote or signatures to another
+ directory authority fails. Fixes bug 40910; bugfix on 0.2.0.3-alpha.
+
+
+Changes in version 0.4.8.10 - 2023-12-08
+ This is a security release fixing a high severity bug (TROVE-2023-007)
+ affecting Exit relays supporting Conflux. We strongly recommend to update as
+ soon as possible.
+
+ o Major bugfixes (TROVE-2023-007, exit):
+ - Improper error propagation from a safety check in conflux leg
+ linking led to a desynchronization of which legs were part of a
+ conflux set, ultimately causing a UAF and NULL pointer dereference
+ crash on Exit relays. Fixes bug 40897; bugfix on 0.4.8.1-alpha.
+
+ o Minor features (fallbackdir):
+ - Regenerate fallback directories generated on December 08, 2023.
+
+ o Minor features (geoip data):
+ - Update the geoip files to match the IPFire Location Database, as
+ retrieved on 2023/12/08.
+
+ o Minor bugfixes (bridges, statistics):
+ - Correctly report statistics for client count over pluggable
+ transports. Fixes bug 40871; bugfix on 0.4.8.4.
+
+
+Changes in version 0.4.8.9 - 2023-11-09
+ This is another security release fixing a high severity bug affecting onion
+ services which is tracked by TROVE-2023-006. We are also releasing a guard
+ major bugfix as well. If you are an onion service operator, we strongly
+ recommend to update as soon as possible.
+
+ o Major bugfixes (guard usage):
+ - When Tor excluded a guard due to temporary circuit restrictions,
+ it considered *additional* primary guards for potential usage by
+ that circuit. This could result in more than the specified number
+ of guards (currently 2) being used, long-term, by the tor client.
+ This could happen when a Guard was also selected as an Exit node,
+ but it was exacerbated by the Conflux guard restrictions. Both
+ instances have been fixed. Fixes bug 40876; bugfix
+ on 0.3.0.1-alpha.
+
+ o Major bugfixes (onion service, TROVE-2023-006):
+ - Fix a possible hard assert on a NULL pointer when recording a
+ failed rendezvous circuit on the service side for the MetricsPort.
+ Fixes bug 40883; bugfix on 0.4.8.1-alpha.
+
+ o Minor features (fallbackdir):
+ - Regenerate fallback directories generated on November 09, 2023.
+
+ o Minor features (geoip data):
+ - Update the geoip files to match the IPFire Location Database, as
+ retrieved on 2023/11/09.
+
+
+Changes in version 0.4.8.8 - 2023-11-03
+ We are releasing today a fix for a high security issue, TROVE-2023-004, that
+ is affecting relays. Also a few minor bugfixes detailed below. Please upgrade
+ as soon as posssible.
+
+ o Major bugfixes (TROVE-2023-004, relay):
+ - Mitigate an issue when Tor compiled with OpenSSL can crash during
+ handshake with a remote relay. Fixes bug 40874; bugfix
+ on 0.2.7.2-alpha.
+
+ o Minor features (fallbackdir):
+ - Regenerate fallback directories generated on November 03, 2023.
+
+ o Minor features (geoip data):
+ - Update the geoip files to match the IPFire Location Database, as
+ retrieved on 2023/11/03.
+
+ o Minor bugfixes (directory authority):
+ - Look at the network parameter "maxunmeasuredbw" with the correct
+ spelling. Fixes bug 40869; bugfix on 0.4.6.1-alpha.
+
+ o Minor bugfixes (vanguards addon support):
+ - Count the conflux linked cell as valid when it is successfully
+ processed. This will quiet a spurious warn in the vanguards addon.
+ Fixes bug 40878; bugfix on 0.4.8.1-alpha.
+
+
+Changes in version 0.4.8.7 - 2023-09-25
+ This version fixes a single major bug in the Conflux subsystem on the client
+ side. See below for more information. The upcoming Tor Browser 13 stable will
+ pick this up.
+
+ o Major bugfixes (conflux):
+ - Fix an issue that prevented us from pre-building more conflux sets
+ after existing sets had been used. Fixes bug 40862; bugfix
+ on 0.4.8.1-alpha.
+
+ o Minor features (fallbackdir):
+ - Regenerate fallback directories generated on September 25, 2023.
+
+ o Minor features (geoip data):
+ - Update the geoip files to match the IPFire Location Database, as
+ retrieved on 2023/09/25.
+
+
+Changes in version 0.4.8.6 - 2023-09-18
+ This version contains an important fix for onion service regarding congestion
+ control and its reliability. Apart from that, unneeded BUG warnings have been
+ suppressed especially about a compression bomb seen on relays. We strongly
+ recommend, in particular onion service operators, to upgrade as soon as
+ possible to this latest stable.
+
+ o Major bugfixes (onion service):
+ - Fix a reliability issue where services were expiring their
+ introduction points every consensus update. This caused
+ connectivity issues for clients caching the old descriptor and
+ intro points. Bug reported and fixed by gitlab user
+ @hyunsoo.kim676. Fixes bug 40858; bugfix on 0.4.7.5-alpha.
+
+ o Minor features (debugging, compression):
+ - Log the input and output buffer sizes when we detect a potential
+ compression bomb. Diagnostic for ticket 40739.
+
+ o Minor features (fallbackdir):
+ - Regenerate fallback directories generated on September 18, 2023.
+
+ o Minor features (geoip data):
+ - Update the geoip files to match the IPFire Location Database, as
+ retrieved on 2023/09/18.
+
+ o Minor bugfix (defensive programming):
+ - Disable multiple BUG warnings of a missing relay identity key when
+ starting an instance of Tor compiled without relay support. Fixes
+ bug 40848; bugfix on 0.4.3.1-alpha.
+
+ o Minor bugfixes (bridge authority):
+ - When reporting a pseudo-networkstatus as a bridge authority, or
+ answering "ns/purpose/*" controller requests, include accurate
+ published-on dates from our list of router descriptors. Fixes bug
+ 40855; bugfix on 0.4.8.1-alpha.
+
+ o Minor bugfixes (compression, zstd):
+ - Use less frightening language and lower the log-level of our run-
+ time ABI compatibility check message in our Zstd compression
+ subsystem. Fixes bug 40815; bugfix on 0.4.3.1-alpha.
+
+
+Changes in version 0.4.8.5 - 2023-08-30
+ Quick second release after the first stable few days ago fixing minor
+ annoying bugfixes creating log BUG stacktrace. We also fix BSD compilation
+ failures and PoW unit test.
+
+ o Minor features (fallbackdir):
+ - Regenerate fallback directories generated on August 30, 2023.
+
+ o Minor features (geoip data):
+ - Update the geoip files to match the IPFire Location Database, as
+ retrieved on 2023/08/30.
+
+ o Minor bugfix (NetBSD, compilation):
+ - Fix compilation issue on NetBSD by avoiding an unnecessary
+ dependency on "huge" page mappings in Equi-X. Fixes bug 40843;
+ bugfix on 0.4.8.1-alpha.
+
+ o Minor bugfix (NetBSD, testing):
+ - Fix test failures in "crypto/hashx" and "slow/crypto/equix" on
+ x86_64 and aarch64 NetBSD hosts, by adding support for
+ PROT_MPROTECT() flags. Fixes bug 40844; bugfix on 0.4.8.1-alpha.
+
+ o Minor bugfixes (conflux):
+ - Demote a relay-side warn about too many legs to ProtocolWarn, as
+ there are conditions that it can briefly happen during set
+ construction. Also add additional set logging details for all
+ error cases. Fixes bug 40841; bugfix on 0.4.8.1-alpha.
+ - Prevent non-fatal assert stacktrace caused by using conflux sets
+ during their teardown process. Fixes bug 40842; bugfix
+ on 0.4.8.1-alpha.
+
+
Changes in version 0.4.8.4 - 2023-08-23
Finally, this is the very first stable release of the 0.4.8.x series making,
among other features, Proof-of-Work (prop#327) and Conflux (prop#329)
diff --git a/changes/bug40465 b/changes/bug40465
new file mode 100644
index 0000000000..d07470f18f
--- /dev/null
+++ b/changes/bug40465
@@ -0,0 +1,6 @@
+ o Major bugfixes (sandbox):
+ - Fix sandbox to work on architectures that use Linux's generic syscall
+ interface, extending support for AArch64 (ARM64) and adding support for
+ RISC-V, allowing test_include.sh and the sandbox unit tests to pass on
+ these systems even when building with fragile hardening enabled. Fixes
+ bugs 40465 and 40599; bugfix on 0.2.5.1-alpha.
diff --git a/changes/bug40884 b/changes/bug40884
new file mode 100644
index 0000000000..8f2af04fcb
--- /dev/null
+++ b/changes/bug40884
@@ -0,0 +1,3 @@
+ o Minor bugfixes (bridge):
+ - Don't warn when BridgeRelay is 1 and ExitRelay is explicitly set to 0.
+ Fixes bug 40884; bugfix on 0.4.8.3-rc.
diff --git a/changes/bug40911 b/changes/bug40911
new file mode 100644
index 0000000000..c938b56225
--- /dev/null
+++ b/changes/bug40911
@@ -0,0 +1,5 @@
+ o Minor bugfixes (compiler warnings):
+ - Make sure the two bitfields in the half-closed edge struct are
+ unsigned, as we're using them for boolean values and assign 1 to
+ them. Fixes bug 40911; bugfix on 0.4.7.2-alpha.
+
diff --git a/changes/bug40922 b/changes/bug40922
new file mode 100644
index 0000000000..e47e4f1461
--- /dev/null
+++ b/changes/bug40922
@@ -0,0 +1,5 @@
+ o Minor bugfixes (testing):
+ - Enabling TestingTorNetwork no longer forces fast hidden service
+ intro point rotation. This reduces noise and errors when
+ using hidden services with TestingTorNetwork enabled.
+ Fixes bug 40922; bugfix on 0.3.2.1-alpha.
diff --git a/changes/bug40933 b/changes/bug40933
new file mode 100644
index 0000000000..c4f9eb085f
--- /dev/null
+++ b/changes/bug40933
@@ -0,0 +1,3 @@
+ o Minor bugfixes (sandbox, bwauth):
+ - Fix sandbox to work for bandwidth authority. Fixes bug 40933; bugfix on
+ 0.2.2.1-alpha
diff --git a/changes/mr760 b/changes/mr760
new file mode 100644
index 0000000000..845e1031f7
--- /dev/null
+++ b/changes/mr760
@@ -0,0 +1,4 @@
+ o Minor feature (metrics port):
+ - New metrics on the MetricsPort for the number of BUG() that occurred at
+ runtime. Closes MR 760.
+
diff --git a/changes/prop301 b/changes/prop301
new file mode 100644
index 0000000000..1b270e8cc5
--- /dev/null
+++ b/changes/prop301
@@ -0,0 +1,6 @@
+ o Removed features (directory authority):
+ - We include a new consensus method that removes support for
+ computing "package" lines in consensus documents. This feature was
+ never used, and support for
+ including it in our votes was removed in 0.4.2.1-alpha.
+ Finishes implementation of proposal 301.
diff --git a/changes/prop351 b/changes/prop351
new file mode 100644
index 0000000000..fca604f1a1
--- /dev/null
+++ b/changes/prop351
@@ -0,0 +1,7 @@
+ o Minor features (SOCKS):
+ - Detect invalid SOCKS5 username/password combinations according to
+ new extended parameters syntax. (Currently, this rejects any
+ SOCKS5 username beginning with "<torS0X>", except for the username
+ "<torS0X>0". Such usernames are now reserved to communicate additional
+ parameters with other Tor implementations.)
+ Implements proposal 351.
diff --git a/changes/tap-out-part-1 b/changes/tap-out-part-1
new file mode 100644
index 0000000000..3d8a445f12
--- /dev/null
+++ b/changes/tap-out-part-1
@@ -0,0 +1,12 @@
+ o Removed features (obsolete):
+ - Relays no longer support the obsolete TAP circuit extension
+ protocol. (For backward compatibility, however, relays still continue to
+ include TAP keys in their descriptors.) Implements part
+ of proposal 350.
+ - Removed some vestigial code for selecting the TAP circuit extension
+ protocol.
+
+ o Minor features (forward-compatibility):
+ - We now correctly parse microdescriptors and router descriptors
+ that do not include TAP onion keys. (For backward compatibility,
+ authorities continue to require these keys.) Implements part of proposal 350.
diff --git a/changes/ticket40248 b/changes/ticket40248
new file mode 100644
index 0000000000..3e8dd96cda
--- /dev/null
+++ b/changes/ticket40248
@@ -0,0 +1,2 @@
+ o Minor feature (DNS, client):
+ - Add 0xF2 returned code in case of an empty DNS response. Closes ticket 40248
diff --git a/changes/ticket40487 b/changes/ticket40487
new file mode 100644
index 0000000000..bd64d475b8
--- /dev/null
+++ b/changes/ticket40487
@@ -0,0 +1,3 @@
+ o Minor features (portability, android):
+ - Use /data/local/tmp for data storage on Android by default. Closes ticket
+ 40487. Patch from Hans-Christoph Steiner.
diff --git a/changes/ticket40638 b/changes/ticket40638
new file mode 100644
index 0000000000..98114b8136
--- /dev/null
+++ b/changes/ticket40638
@@ -0,0 +1,4 @@
+ o Minor bugfix (MetricsPort, relay):
+ - Handle rephist tracking of ntor and ntor_v3 handshakes individually such
+ that MetricsPort exposes the correct values. Fixes bug 40638; bugfix on 0.4.7.11.
+
diff --git a/changes/ticket40676 b/changes/ticket40676
new file mode 100644
index 0000000000..5a025d79b6
--- /dev/null
+++ b/changes/ticket40676
@@ -0,0 +1,4 @@
+ o Minor feature (exit policies):
+ - Implement reevaluating new exit policy against existing connections. This
+ is controlled by new config option ReevaluateExitPolicy, defaulting to 0.
+ Closes ticket 40676.
diff --git a/changes/ticket40736 b/changes/ticket40736
new file mode 100644
index 0000000000..8f233308a4
--- /dev/null
+++ b/changes/ticket40736
@@ -0,0 +1,5 @@
+ o Minor feature (exit relay, DoS(resitance):
+ - Implement a token-bucket based rate limiter for stream creation and
+ resolve request. It is configured by the DoSStream* family of
+ configuration options.
+ Closes ticket 40736.
diff --git a/changes/ticket40816 b/changes/ticket40816
new file mode 100644
index 0000000000..509b11ad7e
--- /dev/null
+++ b/changes/ticket40816
@@ -0,0 +1,4 @@
+ o Minor feature (metrics port, relay):
+ - Add new metrics for relays on the MetricsPort namely the count of drop
+ cell, destroy cell and the number of circuit protocol violation seen that
+ lead to a circuit close. Closes ticket 40816.
diff --git a/changes/ticket40817 b/changes/ticket40817
new file mode 100644
index 0000000000..c99e866d62
--- /dev/null
+++ b/changes/ticket40817
@@ -0,0 +1,4 @@
+ o Minor feature (directory authority):
+ - Introduce MinimalAcceptedServerVersion to allow modification of minimal
+ accepted version for relays without requiring a new tor release.
+ Closes ticket 40817.
diff --git a/changes/ticket40835 b/changes/ticket40835
new file mode 100644
index 0000000000..cda51a5d28
--- /dev/null
+++ b/changes/ticket40835
@@ -0,0 +1,3 @@
+ o Removed features:
+ - Directory authorities no longer support consensus methods
+ before method 32. Closes ticket 40835.
diff --git a/changes/ticket40854 b/changes/ticket40854
new file mode 100644
index 0000000000..1a5850cca0
--- /dev/null
+++ b/changes/ticket40854
@@ -0,0 +1,3 @@
+ o Minor feature (defense in depth):
+ - verify needle is smaller than haystack before calling memmem.
+ Closes ticket 40854.
diff --git a/changes/ticket40870 b/changes/ticket40870
new file mode 100644
index 0000000000..c33c83e1a6
--- /dev/null
+++ b/changes/ticket40870
@@ -0,0 +1,4 @@
+ o Minor bugfixes (conflux, client):
+ - Avoid a non fatal assert caused by data coming in on a conflux set that is
+ being freed during shutdown. Fixes bug 40870; bugfix on 0.4.8.1-alpha.
+
diff --git a/changes/ticket40918 b/changes/ticket40918
new file mode 100644
index 0000000000..7d5e549eef
--- /dev/null
+++ b/changes/ticket40918
@@ -0,0 +1,3 @@
+ o Minor bugfix (relay, sandbox):
+ - Disable a sandbox unit test that is failing on Debian Sid breaking our
+ nightly packages. Fixes bug 40918; bugfix on 0.3.5.1-alpha.
diff --git a/configure.ac b/configure.ac
index adb473e60b..b218a59ce2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@ dnl Copyright (c) 2007-2019, The Tor Project, Inc.
dnl See LICENSE for licensing information
AC_PREREQ([2.63])
-AC_INIT([tor],[0.4.8.12-dev])
+AC_INIT([tor],[0.4.9.0-alpha-dev])
AC_CONFIG_SRCDIR([src/app/main/tor_main.c])
AC_CONFIG_MACRO_DIR([m4])
@@ -18,7 +18,7 @@ AC_DEFINE_UNQUOTED([CONFIG_FLAGS], ["$configure_flags"], [Flags passed to config
# version number changes. Tor uses it to make sure that it
# only shuts down for missing "required protocols" when those protocols
# are listed as required by a consensus after this date.
-AC_DEFINE(APPROX_RELEASE_DATE, ["2024-06-06"], # for 0.4.8.12-dev
+AC_DEFINE(APPROX_RELEASE_DATE, ["2023-08-23"], # for 0.4.9.0-alpha-dev
[Approximate date when this software was released. (Updated when the version changes.)])
# "foreign" means we don't follow GNU package layout standards
diff --git a/contrib/win32build/tor-mingw.nsi.in b/contrib/win32build/tor-mingw.nsi.in
index 64be12dede..165f4e2fe2 100644
--- a/contrib/win32build/tor-mingw.nsi.in
+++ b/contrib/win32build/tor-mingw.nsi.in
@@ -8,7 +8,7 @@
!include "LogicLib.nsh"
!include "FileFunc.nsh"
!insertmacro GetParameters
-!define VERSION "0.4.8.12-dev"
+!define VERSION "0.4.9.0-alpha-dev"
!define INSTALLER "tor-${VERSION}-win32.exe"
!define WEBSITE "https://www.torproject.org/"
!define LICENSE "LICENSE"
diff --git a/doc/man/tor.1.txt b/doc/man/tor.1.txt
index ad6ec8ba8d..2a936f6702 100644
--- a/doc/man/tor.1.txt
+++ b/doc/man/tor.1.txt
@@ -1010,7 +1010,7 @@ forward slash (/) in the configuration file and on the command line.
equivalent option for directory connections, because all Tor client versions
that support this option download directory documents via OR connections. +
+
- The only protocol supported right now 'haproxy'. This option is only for
+ The only protocol supported right now is 'haproxy'. This option is only for
clients. (Default: none) +
+
The HAProxy version 1 proxy protocol is described in detail at
@@ -2385,6 +2385,16 @@ is non-zero):
policy options are set, Tor behaves as if ExitRelay were set to 0.
(Default: auto)
+[[ReevaluateExitPolicy]] **ReevaluateExitPolicy** **0**|**1**::
+ If set, reevaluate the exit policy on existing connections when reloading
+ configuration. +
+ +
+ When the exit policy of an exit node change while reloading configuration,
+ connections made prior to this change could violate the new policy. By
+ setting this to 1, Tor will check if such connections exist, and mark them
+ for termination.
+ (Default: 0)
+
[[ExtendAllowPrivateAddresses]] **ExtendAllowPrivateAddresses** **0**|**1**::
When this option is enabled, Tor will connect to relays on localhost,
RFC1918 addresses, and so on. In particular, Tor will make direct OR
@@ -3026,6 +3036,44 @@ Denial of Service mitigation subsystem described above.
consensus parameter. If not defined in the consensus, the value is 0.
(Default: auto)
+The following options are useful only for a exit relay.
+
+[[DoSStreamCreationEnabled]] **DoSStreamCreationEnabled** **0**|**1**|**auto**::
+
+ Enable the stream DoS mitigation. If set to 1 (enabled), tor will apply
+ rate limit on the creation of new streams and dns requests per circuit.
+ "auto" means use the consensus parameter. If not defined in the consensus,
+ the value is 0. (Default: auto)
+
+[[DoSStreamCreationDefenseType]] **DoSStreamCreationDefenseType** __NUM__::
+
+ This is the type of defense applied to a detected circuit or stream for the
+ stream mitigation. The possible values are:
+ +
+ 1: No defense.
+ +
+ 2: Reject the stream or resolve request.
+ +
+ 3: Close the circuit creating too many streams.
+ +
+ "0" means use the consensus parameter. If not defined in the consensus, the value is 2.
+ (Default: 0)
+
+[[DoSStreamCreationRate]] **DoSStreamCreationRate** __NUM__::
+
+ The allowed rate of stream creation from a single circuit per second. Coupled
+ with the burst (see below), if the limit is reached, actions can be taken
+ against the stream or circuit (DoSStreamCreationDefenseType). If not defined or
+ set to 0, it is controlled by a consensus parameter. If not defined in the
+ consensus, the value is 100. (Default: 0)
+
+[[DoSStreamCreationBurst]] **DoSStreamCreationBurst** __NUM__::
+
+ The allowed burst of stream creation from a circuit per second.
+ See the DoSStreamCreationRate for more details on this detection. If
+ not defined or set to 0, it is controlled by a consensus parameter. If not
+ defined in the consensus, the value is 300. (Default: 0)
+
For onion services, mitigations are a work in progress and multiple options
are currently available.
@@ -3080,7 +3128,7 @@ hard and are likely different for each service operator.
Why is this not helping reachability of the service? Because the defenses are
at the introduction point, an attacker can easily flood all introduction point
rendering the service unavailable due to no client being able to pass through.
-But, the service itself is not overwhelmed with connetions allowing it to
+But, the service itself is not overwhelmed with connections allowing it to
function properly for the few clients that were able to go through or other any
services running on the same tor instance.
@@ -3370,6 +3418,11 @@ on the public Tor network.
multiple times: the values from multiple lines are spliced together. When
this is set then **VersioningAuthoritativeDirectory** should be set too.
+[[MinimalAcceptedServerVersion]] **MinimalAcceptedServerVersion** __STRING__::
+ STRING is the oldest Tor version accepted by the directory authority for
+ relays and bridge. Any older version will be rejected.
+ (Default: 0.4.7.0-alpha-dev)
+
[[V3AuthDistDelay]] **V3AuthDistDelay** __N__ **seconds**|**minutes**|**hours**::
V3 authoritative directories only. Configures the server's preferred delay
between publishing its consensus and signature and assuming it has all the
@@ -4064,7 +4117,7 @@ __DataDirectory__/**`stats/hidserv-stats`**::
of what fraction of the traffic is hidden service rendezvous traffic, and
approximately how many hidden services the relay has seen.
-__DataDirectory__/**networkstatus-bridges`**::
+__DataDirectory__/**`networkstatus-bridges`**::
Only used by authoritative bridge directories. Contains information
about bridges that have self-reported themselves to the bridge
authority.
diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4
index 95df39679e..68fd43d5dd 100644
--- a/m4/ax_check_compile_flag.m4
+++ b/m4/ax_check_compile_flag.m4
@@ -1,43 +1,45 @@
- # Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
- # Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
- #
- # This program is free software: you can redistribute it and/or modify it
- # under the terms of the GNU General Public License as published by the
- # Free Software Foundation, either version 3 of the License, or (at your
- # option) any later version.
- #
- # This program is distributed in the hope that it will be useful, but
- # WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- # Public License for more details.
- #
- # You should have received a copy of the GNU General Public License along
- # with this program. If not, see <https://www.gnu.org/licenses/>.
- #
- # As a special exception, the respective Autoconf Macro's copyright owner
- # gives unlimited permission to copy, distribute and modify the configure
- # scripts that are the output of Autoconf when processing the Macro. You
- # need not follow the terms of the GNU General Public License when using
- # or distributing such scripts, even though portions of the text of the
- # Macro appear in them. The GNU General Public License (GPL) does govern
- # all other use of the material that constitutes the Autoconf Macro.
- #
- # This special exception to the GPL applies to versions of the Autoconf
- # Macro released by the Autoconf Archive. When you make and distribute a
- # modified version of the Autoconf Macro, you may extend this special
- # exception to the GPL to apply to your modified version as well.
- # Copying and distribution of this file, with or without modification, are
- # permitted in any medium without royalty provided the copyright notice
- # and this notice are preserved. This file is offered as-is, without any
- # warranty.
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+# Check whether the given FLAG works with the current language's compiler
+# or gives an error. (Warnings, however, are ignored)
+#
+# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+# success/failure.
+#
+# If EXTRA-FLAGS is defined, it is added to the current language's default
+# flags (e.g. CFLAGS) when the check is done. The check is thus made with
+# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
+# force the compiler to issue an error when a bad flag is given.
+#
+# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
- #serial 5
- #serial 6
+#serial 7
- AC_DEFUN([AX_CHECK_COMPILE_FLAG],
- [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AC_DEFUN([AX_CHECK_COMPILE_FLAG],
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
-AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
+AC_CACHE_CHECK([whether the _AC_LANG compiler accepts $1], CACHEVAR, [
ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
diff --git a/scripts/codegen/get_mozilla_ciphers.py b/scripts/codegen/get_mozilla_ciphers.py
index ff01dd8719..65ef1aca2f 100755
--- a/scripts/codegen/get_mozilla_ciphers.py
+++ b/scripts/codegen/get_mozilla_ciphers.py
@@ -144,7 +144,7 @@ sslProto = open(ff('security/nss/lib/ssl/sslproto.h'), 'r')
sslProtoD = {}
for line in sslProto:
- m = re.match('#define\s+(\S+)\s+(\S+)', line)
+ m = re.match(r'#define\s+(\S+)\s+(\S+)', line)
if m:
key, value = m.groups()
sslProtoD[key] = value
@@ -165,7 +165,7 @@ for fl in oSSLinclude:
continue
fp = open(fname, 'r')
for line in fp.readlines():
- m = re.match('# *define\s+(\S+)\s+(\S+)', line)
+ m = re.match(r'# *define\s+(\S+)\s+(\S+)', line)
if m:
value,key = m.groups()
if key.startswith('0x') and "_CK_" in value:
diff --git a/scripts/maint/format_changelog.py b/scripts/maint/format_changelog.py
index 32b47ffcbb..cab34ab751 100755
--- a/scripts/maint/format_changelog.py
+++ b/scripts/maint/format_changelog.py
@@ -416,7 +416,7 @@ ISSUE_PREFIX_MAP = {
}
# Let's turn bugs to html.
-BUG_PAT = re.compile('(bug|ticket|issue|feature)\s+([\w/]+#)?(\d{4,6})', re.I)
+BUG_PAT = re.compile(r'(bug|ticket|issue|feature)\s+([\w/]+#)?(\d{4,6})', re.I)
def bug_html(m):
kind = m.group(1)
prefix = m.group(2) or ""
diff --git a/scripts/maint/geoip/update_and_commit_geoip.sh b/scripts/maint/geoip/update_and_commit_geoip.sh
index a83f82433e..4fbd030628 100755
--- a/scripts/maint/geoip/update_and_commit_geoip.sh
+++ b/scripts/maint/geoip/update_and_commit_geoip.sh
@@ -32,3 +32,5 @@ EOF
git add "$CHANGESFILE"
git commit -a -m "Update geoip files to match ipfire location db, $SLASH_DATE."
+
+exit 0
diff --git a/src/app/config/config.c b/src/app/config/config.c
index a10329c552..102d1bbc04 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -483,6 +483,13 @@ static const config_var_t option_vars_[] = {
#ifdef _WIN32
V(GeoIPFile, FILENAME, "<default>"),
V(GeoIPv6File, FILENAME, "<default>"),
+#elif defined(__ANDROID__)
+ /* Android apps use paths that are configured at runtime.
+ * /data/local/tmp is guaranteed to exist, but will only be
+ * usable by the 'shell' and 'root' users, so this fallback is
+ * for debugging only. */
+ V(GeoIPFile, FILENAME, "/data/local/tmp/geoip"),
+ V(GeoIPv6File, FILENAME, "/data/local/tmp/geoip6"),
#else
V(GeoIPFile, FILENAME,
SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip"),
@@ -637,6 +644,7 @@ static const config_var_t option_vars_[] = {
V(RephistTrackTime, INTERVAL, "24 hours"),
V_IMMUTABLE(RunAsDaemon, BOOL, "0"),
V(ReducedExitPolicy, BOOL, "0"),
+ V(ReevaluateExitPolicy, BOOL, "0"),
OBSOLETE("RunTesting"), // currently unused
V_IMMUTABLE(Sandbox, BOOL, "0"),
V(SafeLogging, STRING, "1"),
@@ -996,6 +1004,7 @@ set_options(or_options_t *new_val, char **msg)
config_line_t *changes =
config_get_changes(get_options_mgr(), old_options, new_val);
control_event_conf_changed(changes);
+ connection_reapply_exit_policy(changes);
config_free_lines(changes);
}
@@ -6898,6 +6907,15 @@ get_data_directory(const char *val)
} else {
return tor_strdup(get_windows_conf_root());
}
+#elif defined(__ANDROID__)
+ /* Android apps can only use paths that are configured at runtime.
+ * /data/local/tmp is guaranteed to exist, but is only usable by the
+ * 'shell' and 'root' users, so this fallback is for debugging only. */
+ if (val) {
+ return tor_strdup(val);
+ } else {
+ return tor_strdup("/data/local/tmp");
+ }
#else /* !defined(_WIN32) */
const char *d = val;
if (!d)
diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h
index 36b00662b5..624dc61bc5 100644
--- a/src/app/config/or_options_st.h
+++ b/src/app/config/or_options_st.h
@@ -141,6 +141,8 @@ struct or_options_t {
* Includes OutboundBindAddresses and
* configured ports. */
int ReducedExitPolicy; /**<Should we use the Reduced Exit Policy? */
+ int ReevaluateExitPolicy; /**<Should we re-evaluate Exit Policy on existing
+ * connections when it changes? */
struct config_line_t *SocksPolicy; /**< Lists of socks policy components */
struct config_line_t *DirPolicy; /**< Lists of dir policy components */
/** Local address to bind outbound sockets */
diff --git a/src/app/main/main.c b/src/app/main/main.c
index a50a0aad6f..6d05bd1f5e 100644
--- a/src/app/main/main.c
+++ b/src/app/main/main.c
@@ -926,6 +926,11 @@ sandbox_init_filter(void)
OPEN_DATADIR("approved-routers");
OPEN_DATADIR_SUFFIX("my-consensus-microdesc", ".tmp");
OPEN_DATADIR_SUFFIX("my-consensus-ns", ".tmp");
+ if (options->V3BandwidthsFile) {
+ log_notice(LD_GENERAL, "Adding V3BandwidthsFile %s to sandboxing set.",
+ options->V3BandwidthsFile);
+ OPEN(options->V3BandwidthsFile);
+ }
}
if (options->ServerDNSResolvConfFile)
diff --git a/src/app/main/shutdown.c b/src/app/main/shutdown.c
index 325cb27134..ddbc2ea584 100644
--- a/src/app/main/shutdown.c
+++ b/src/app/main/shutdown.c
@@ -122,6 +122,7 @@ tor_free_all(int postfork)
dirserv_free_all();
rep_hist_free_all();
bwhist_free_all();
+ conflux_notify_shutdown();
circuit_free_all();
conflux_pool_free_all();
circpad_machines_free();
diff --git a/src/config/torrc.sample.in b/src/config/torrc.sample.in
index 639d7c4d68..97ff941459 100644
--- a/src/config/torrc.sample.in
+++ b/src/config/torrc.sample.in
@@ -225,6 +225,10 @@
#ExitPolicy accept6 *6:119 # accept nntp ports on IPv6 only as well as default exit policy
#ExitPolicy reject *:* # no exits allowed
+## Uncomment this if you want your exit relay to reevaluate its exit policy on
+## existing connections when the exit policy is modified.
+#ReevaluateExitPolicy 1
+
## Bridge relays (or "bridges") are Tor relays that aren't listed in the
## main directory. Since there is no complete public list of them, even an
## ISP that filters connections to all the known Tor relays probably
diff --git a/src/core/crypto/include.am b/src/core/crypto/include.am
index 2d53b3cb0b..651e8803d4 100644
--- a/src/core/crypto/include.am
+++ b/src/core/crypto/include.am
@@ -6,7 +6,6 @@ LIBTOR_APP_A_SOURCES += \
src/core/crypto/onion_fast.c \
src/core/crypto/onion_ntor.c \
src/core/crypto/onion_ntor_v3.c \
- src/core/crypto/onion_tap.c \
src/core/crypto/relay_crypto.c
# ADD_C_FILE: INSERT HEADERS HERE.
@@ -16,5 +15,4 @@ noinst_HEADERS += \
src/core/crypto/onion_fast.h \
src/core/crypto/onion_ntor.h \
src/core/crypto/onion_ntor_v3.h \
- src/core/crypto/onion_tap.h \
src/core/crypto/relay_crypto.h
diff --git a/src/core/crypto/onion_crypto.c b/src/core/crypto/onion_crypto.c
index 0839d8903f..232dbcc5df 100644
--- a/src/core/crypto/onion_crypto.c
+++ b/src/core/crypto/onion_crypto.c
@@ -9,9 +9,9 @@
* \brief Functions to handle different kinds of circuit extension crypto.
*
* In this module, we provide a set of abstractions to create a uniform
- * interface over the three circuit extension handshakes that Tor has used
- * over the years (TAP, CREATE_FAST, and ntor). These handshakes are
- * implemented in onion_tap.c, onion_fast.c, and onion_ntor.c respectively.
+ * interface over the circuit extension handshakes that Tor has used
+ * over the years (CREATE_FAST, ntor, hs_ntor, and ntorv3).
+ * These handshakes are implemented in the onion_*.c modules.
*
* All[*] of these handshakes follow a similar pattern: a client, knowing
* some key from the relay it wants to extend through, generates the
@@ -36,7 +36,6 @@
#include "core/crypto/onion_fast.h"
#include "core/crypto/onion_ntor.h"
#include "core/crypto/onion_ntor_v3.h"
-#include "core/crypto/onion_tap.h"
#include "feature/relay/router.h"
#include "lib/crypt_ops/crypto_dh.h"
#include "lib/crypt_ops/crypto_util.h"
@@ -98,8 +97,6 @@ onion_handshake_state_release(onion_handshake_state_t *state)
{
switch (state->tag) {
case ONION_HANDSHAKE_TYPE_TAP:
- crypto_dh_free(state->u.tap);
- state->u.tap = NULL;
break;
case ONION_HANDSHAKE_TYPE_FAST:
fast_handshake_state_free(state->u.fast);
@@ -139,18 +136,7 @@ onion_skin_create(int type,
switch (type) {
case ONION_HANDSHAKE_TYPE_TAP:
- if (onion_skin_out_maxlen < TAP_ONIONSKIN_CHALLENGE_LEN)
- return -1;
- if (!node->onion_key)
- return -1;
-
- if (onion_skin_TAP_create(node->onion_key,
- &state_out->u.tap,
- (char*)onion_skin_out) < 0)
- return -1;
-
- r = TAP_ONIONSKIN_CHALLENGE_LEN;
- break;
+ return -1;
case ONION_HANDSHAKE_TYPE_FAST:
if (fast_onionskin_create(&state_out->u.fast, onion_skin_out) < 0)
return -1;
@@ -288,18 +274,7 @@ onion_skin_server_handshake(int type,
switch (type) {
case ONION_HANDSHAKE_TYPE_TAP:
- if (reply_out_maxlen < TAP_ONIONSKIN_REPLY_LEN)
- return -1;
- if (onionskin_len != TAP_ONIONSKIN_CHALLENGE_LEN)
- return -1;
- if (onion_skin_TAP_server_handshake((const char*)onion_skin,
- keys->onion_key, keys->last_onion_key,
- (char*)reply_out,
- (char*)keys_out, keys_out_len)<0)
- return -1;
- r = TAP_ONIONSKIN_REPLY_LEN;
- memcpy(rend_nonce_out, reply_out+DH1024_KEY_LEN, DIGEST_LEN);
- break;
+ return -1;
case ONION_HANDSHAKE_TYPE_FAST:
if (reply_out_maxlen < CREATED_FAST_LEN)
return -1;
@@ -474,20 +449,7 @@ onion_skin_client_handshake(int type,
switch (type) {
case ONION_HANDSHAKE_TYPE_TAP:
- if (reply_len != TAP_ONIONSKIN_REPLY_LEN) {
- if (msg_out)
- *msg_out = "TAP reply was not of the correct length.";
- return -1;
- }
- if (onion_skin_TAP_client_handshake(handshake_state->u.tap,
- (const char*)reply,
- (char *)keys_out, keys_out_len,
- msg_out) < 0)
- return -1;
-
- memcpy(rend_authenticator_out, reply+DH1024_KEY_LEN, DIGEST_LEN);
-
- return 0;
+ return -1;
case ONION_HANDSHAKE_TYPE_FAST:
if (reply_len != CREATED_FAST_LEN) {
if (msg_out)
diff --git a/src/core/crypto/onion_tap.c b/src/core/crypto/onion_tap.c
deleted file mode 100644
index 08ec3ec936..0000000000
--- a/src/core/crypto/onion_tap.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/* Copyright (c) 2001 Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2021, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file onion_tap.c
- * \brief Functions to implement the original Tor circuit extension handshake
- * (a.k.a TAP).
- *
- * The "TAP" handshake is the first one that was widely used in Tor: It
- * combines RSA1024-OAEP and AES128-CTR to perform a hybrid encryption over
- * the first message DH1024 key exchange. (The RSA-encrypted part of the
- * encryption is authenticated; the AES-encrypted part isn't. This was
- * not a smart choice.)
- *
- * We didn't call it "TAP" ourselves -- Ian Goldberg named it in "On the
- * Security of the Tor Authentication Protocol". (Spoiler: it's secure, but
- * its security is kind of fragile and implementation dependent. Never modify
- * this implementation without reading and understanding that paper at least.)
- *
- * We have deprecated TAP since the ntor handshake came into general use. It
- * is still used for hidden service IP and RP connections, however.
- *
- * This handshake, like the other circuit-extension handshakes, is
- * invoked from onion.c.
- **/
-
-#include "core/or/or.h"
-#include "app/config/config.h"
-#include "lib/crypt_ops/crypto_dh.h"
-#include "lib/crypt_ops/crypto_rand.h"
-#include "lib/crypt_ops/crypto_util.h"
-#include "core/crypto/onion_tap.h"
-#include "feature/stats/rephist.h"
-
-/*----------------------------------------------------------------------*/
-
-/** Given a router's 128 byte public key,
- * stores the following in onion_skin_out:
- * - [42 bytes] OAEP padding
- * - [16 bytes] Symmetric key for encrypting blob past RSA
- * - [70 bytes] g^x part 1 (inside the RSA)
- * - [58 bytes] g^x part 2 (symmetrically encrypted)
- *
- * Stores the DH private key into handshake_state_out for later completion
- * of the handshake.
- *
- * The meeting point/cookies and auth are zeroed out for now.
- */
-int
-onion_skin_TAP_create(crypto_pk_t *dest_router_key,
- crypto_dh_t **handshake_state_out,
- char *onion_skin_out) /* TAP_ONIONSKIN_CHALLENGE_LEN bytes */
-{
- char challenge[DH1024_KEY_LEN];
- crypto_dh_t *dh = NULL;
- int dhbytes, pkbytes;
-
- tor_assert(dest_router_key);
- tor_assert(handshake_state_out);
- tor_assert(onion_skin_out);
- *handshake_state_out = NULL;
- memset(onion_skin_out, 0, TAP_ONIONSKIN_CHALLENGE_LEN);
-
- if (!(dh = crypto_dh_new(DH_TYPE_CIRCUIT)))
- goto err;
-
- dhbytes = crypto_dh_get_bytes(dh);
- pkbytes = (int) crypto_pk_keysize(dest_router_key);
- tor_assert(dhbytes == 128);
- tor_assert(pkbytes == 128);
-
- if (crypto_dh_get_public(dh, challenge, dhbytes))
- goto err;
-
- /* set meeting point, meeting cookie, etc here. Leave zero for now. */
- if (crypto_pk_obsolete_public_hybrid_encrypt(dest_router_key, onion_skin_out,
- TAP_ONIONSKIN_CHALLENGE_LEN,
- challenge, DH1024_KEY_LEN,
- PK_PKCS1_OAEP_PADDING, 1)<0)
- goto err;
-
- memwipe(challenge, 0, sizeof(challenge));
- *handshake_state_out = dh;
-
- return 0;
- err:
- /* LCOV_EXCL_START
- * We only get here if RSA encryption fails or DH keygen fails. Those
- * shouldn't be possible. */
- memwipe(challenge, 0, sizeof(challenge));
- if (dh) crypto_dh_free(dh);
- return -1;
- /* LCOV_EXCL_STOP */
-}
-
-/** Given an encrypted DH public key as generated by onion_skin_create,
- * and the private key for this onion router, generate the reply (128-byte
- * DH plus the first 20 bytes of shared key material), and store the
- * next key_out_len bytes of key material in key_out.
- */
-int
-onion_skin_TAP_server_handshake(
- /*TAP_ONIONSKIN_CHALLENGE_LEN*/
- const char *onion_skin,
- crypto_pk_t *private_key,
- crypto_pk_t *prev_private_key,
- /*TAP_ONIONSKIN_REPLY_LEN*/
- char *handshake_reply_out,
- char *key_out,
- size_t key_out_len)
-{
- char challenge[TAP_ONIONSKIN_CHALLENGE_LEN];
- crypto_dh_t *dh = NULL;
- ssize_t len;
- char *key_material=NULL;
- size_t key_material_len=0;
- int i;
- crypto_pk_t *k;
-
- len = -1;
- for (i=0;i<2;++i) {
- k = i==0?private_key:prev_private_key;
- if (!k)
- break;
- len = crypto_pk_obsolete_private_hybrid_decrypt(k, challenge,
- TAP_ONIONSKIN_CHALLENGE_LEN,
- onion_skin,
- TAP_ONIONSKIN_CHALLENGE_LEN,
- PK_PKCS1_OAEP_PADDING,0);
- if (len>0)
- break;
- }
- if (len<0) {
- log_info(LD_PROTOCOL,
- "Couldn't decrypt onionskin: client may be using old onion key");
- goto err;
- } else if (len != DH1024_KEY_LEN) {
- log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Unexpected onionskin length after decryption: %ld",
- (long)len);
- goto err;
- }
-
- dh = crypto_dh_new(DH_TYPE_CIRCUIT);
- if (!dh) {
- /* LCOV_EXCL_START
- * Failure to allocate a DH key should be impossible.
- */
- log_warn(LD_BUG, "Couldn't allocate DH key");
- goto err;
- /* LCOV_EXCL_STOP */
- }
- if (crypto_dh_get_public(dh, handshake_reply_out, DH1024_KEY_LEN)) {
- /* LCOV_EXCL_START
- * This can only fail if the length of the key we just allocated is too
- * big. That should be impossible. */
- log_info(LD_GENERAL, "crypto_dh_get_public failed.");
- goto err;
- /* LCOV_EXCL_STOP */
- }
-
- key_material_len = DIGEST_LEN+key_out_len;
- key_material = tor_malloc(key_material_len);
- len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh, challenge,
- DH1024_KEY_LEN, key_material,
- key_material_len);
- if (len < 0) {
- log_info(LD_GENERAL, "crypto_dh_compute_secret failed.");
- goto err;
- }
-
- /* send back H(K|0) as proof that we learned K. */
- memcpy(handshake_reply_out+DH1024_KEY_LEN, key_material, DIGEST_LEN);
-
- /* use the rest of the key material for our shared keys, digests, etc */
- memcpy(key_out, key_material+DIGEST_LEN, key_out_len);
-
- memwipe(challenge, 0, sizeof(challenge));
- memwipe(key_material, 0, key_material_len);
- tor_free(key_material);
- crypto_dh_free(dh);
- return 0;
- err:
- memwipe(challenge, 0, sizeof(challenge));
- if (key_material) {
- memwipe(key_material, 0, key_material_len);
- tor_free(key_material);
- }
- if (dh) crypto_dh_free(dh);
-
- return -1;
-}
-
-/** Finish the client side of the DH handshake.
- * Given the 128 byte DH reply + 20 byte hash as generated by
- * onion_skin_server_handshake and the handshake state generated by
- * onion_skin_create, verify H(K) with the first 20 bytes of shared
- * key material, then generate key_out_len more bytes of shared key
- * material and store them in key_out.
- *
- * After the invocation, call crypto_dh_free on handshake_state.
- */
-int
-onion_skin_TAP_client_handshake(crypto_dh_t *handshake_state,
- const char *handshake_reply, /* TAP_ONIONSKIN_REPLY_LEN bytes */
- char *key_out,
- size_t key_out_len,
- const char **msg_out)
-{
- ssize_t len;
- char *key_material=NULL;
- size_t key_material_len;
- tor_assert(crypto_dh_get_bytes(handshake_state) == DH1024_KEY_LEN);
-
- key_material_len = DIGEST_LEN + key_out_len;
- key_material = tor_malloc(key_material_len);
- len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, handshake_state,
- handshake_reply, DH1024_KEY_LEN, key_material,
- key_material_len);
- if (len < 0) {
- if (msg_out)
- *msg_out = "DH computation failed.";
- goto err;
- }
-
- if (tor_memneq(key_material, handshake_reply+DH1024_KEY_LEN, DIGEST_LEN)) {
- /* H(K) does *not* match. Something fishy. */
- if (msg_out)
- *msg_out = "Digest DOES NOT MATCH on onion handshake. Bug or attack.";
- goto err;
- }
-
- /* use the rest of the key material for our shared keys, digests, etc */
- memcpy(key_out, key_material+DIGEST_LEN, key_out_len);
-
- memwipe(key_material, 0, key_material_len);
- tor_free(key_material);
- return 0;
- err:
- memwipe(key_material, 0, key_material_len);
- tor_free(key_material);
- return -1;
-}
diff --git a/src/core/crypto/onion_tap.h b/src/core/crypto/onion_tap.h
deleted file mode 100644
index 341270c981..0000000000
--- a/src/core/crypto/onion_tap.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Copyright (c) 2001 Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2021, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file onion_tap.h
- * \brief Header file for onion_tap.c.
- **/
-
-#ifndef TOR_ONION_TAP_H
-#define TOR_ONION_TAP_H
-
-#define TAP_ONIONSKIN_CHALLENGE_LEN (PKCS1_OAEP_PADDING_OVERHEAD+\
- CIPHER_KEY_LEN+\
- DH1024_KEY_LEN)
-#define TAP_ONIONSKIN_REPLY_LEN (DH1024_KEY_LEN+DIGEST_LEN)
-
-struct crypto_dh_t;
-struct crypto_pk_t;
-
-int onion_skin_TAP_create(struct crypto_pk_t *router_key,
- struct crypto_dh_t **handshake_state_out,
- char *onion_skin_out);
-
-int onion_skin_TAP_server_handshake(const char *onion_skin,
- struct crypto_pk_t *private_key,
- struct crypto_pk_t *prev_private_key,
- char *handshake_reply_out,
- char *key_out,
- size_t key_out_len);
-
-int onion_skin_TAP_client_handshake(struct crypto_dh_t *handshake_state,
- const char *handshake_reply,
- char *key_out,
- size_t key_out_len,
- const char **msg_out);
-
-#endif /* !defined(TOR_ONION_TAP_H) */
diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c
index dc1912294b..bcf44ca248 100644
--- a/src/core/or/circuitbuild.c
+++ b/src/core/or/circuitbuild.c
@@ -33,7 +33,6 @@
#include "core/crypto/hs_ntor.h"
#include "core/crypto/onion_crypto.h"
#include "core/crypto/onion_fast.h"
-#include "core/crypto/onion_tap.h"
#include "core/mainloop/connection.h"
#include "core/mainloop/mainloop.h"
#include "core/or/channel.h"
@@ -412,13 +411,6 @@ onion_populate_cpath(origin_circuit_t *circ)
/* We would like every path to support ntor, but we have to allow for some
* edge cases. */
tor_assert(circuit_get_cpath_len(circ));
- if (circuit_can_use_tap(circ)) {
- /* Circuits from clients to intro points, and hidden services to rend
- * points do not support ntor, because the hidden service protocol does
- * not include ntor onion keys. This is also true for Single Onion
- * Services. */
- return 0;
- }
if (circuit_get_cpath_len(circ) == 1) {
/* Allow for bootstrapping: when we're fetching directly from a fallback,
@@ -890,20 +882,14 @@ circuit_pick_create_handshake(uint8_t *cell_type_out,
{
/* torspec says: In general, clients SHOULD use CREATE whenever they are
* using the TAP handshake, and CREATE2 otherwise. */
- if (extend_info_supports_ntor(ei)) {
- *cell_type_out = CELL_CREATE2;
- /* Only use ntor v3 with exits that support congestion control,
- * and only when it is enabled. */
- if (ei->exit_supports_congestion_control &&
- congestion_control_enabled())
- *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR_V3;
- else
- *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR;
- } else {
- /* XXXX030 Remove support for deciding to use TAP and EXTEND. */
- *cell_type_out = CELL_CREATE;
- *handshake_type_out = ONION_HANDSHAKE_TYPE_TAP;
- }
+ *cell_type_out = CELL_CREATE2;
+ /* Only use ntor v3 with exits that support congestion control,
+ * and only when it is enabled. */
+ if (ei->exit_supports_congestion_control &&
+ congestion_control_enabled())
+ *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR_V3;
+ else
+ *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR;
}
/** Decide whether to use a TAP or ntor handshake for extending to <b>ei</b>
@@ -924,16 +910,8 @@ circuit_pick_extend_handshake(uint8_t *cell_type_out,
uint8_t t;
circuit_pick_create_handshake(&t, handshake_type_out, ei);
- /* torspec says: Clients SHOULD use the EXTEND format whenever sending a TAP
- * handshake... In other cases, clients SHOULD use EXTEND2. */
- if (*handshake_type_out != ONION_HANDSHAKE_TYPE_TAP) {
- *cell_type_out = RELAY_COMMAND_EXTEND2;
- *create_cell_type_out = CELL_CREATE2;
- } else {
- /* XXXX030 Remove support for deciding to use TAP and EXTEND. */
- *cell_type_out = RELAY_COMMAND_EXTEND;
- *create_cell_type_out = CELL_CREATE;
- }
+ *cell_type_out = RELAY_COMMAND_EXTEND2;
+ *create_cell_type_out = CELL_CREATE2;
}
/**
@@ -1343,7 +1321,7 @@ circuit_finish_handshake(origin_circuit_t *circ,
hop->ccontrol = congestion_control_new(&params, CC_PATH_EXIT);
} else {
/* This is likely directory requests, which should block on orconn
- * before congestion control, but lets give them the lower sbws
+ * before congestion control, but let's give them the lower sbws
* param set anyway just in case. */
log_info(LD_CIRC,
"Unexpected path length %d for exit circuit %d, purpose %d",
@@ -2641,29 +2619,6 @@ build_state_get_exit_nickname(cpath_build_state_t *state)
return state->chosen_exit->nickname;
}
-/* Is circuit purpose allowed to use the deprecated TAP encryption protocol?
- * The hidden service protocol still uses TAP for some connections, because
- * ntor onion keys aren't included in HS descriptors or INTRODUCE cells. */
-static int
-circuit_purpose_can_use_tap_impl(uint8_t purpose)
-{
- return (purpose == CIRCUIT_PURPOSE_S_CONNECT_REND ||
- purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
-}
-
-/* Is circ allowed to use the deprecated TAP encryption protocol?
- * The hidden service protocol still uses TAP for some connections, because
- * ntor onion keys aren't included in HS descriptors or INTRODUCE cells. */
-int
-circuit_can_use_tap(const origin_circuit_t *circ)
-{
- tor_assert(circ);
- tor_assert(circ->cpath);
- tor_assert(circ->cpath->extend_info);
- return (circuit_purpose_can_use_tap_impl(circ->base_.purpose) &&
- extend_info_supports_tap(circ->cpath->extend_info));
-}
-
/* Does circ have an onion key which it's allowed to use? */
int
circuit_has_usable_onion_key(const origin_circuit_t *circ)
@@ -2671,8 +2626,7 @@ circuit_has_usable_onion_key(const origin_circuit_t *circ)
tor_assert(circ);
tor_assert(circ->cpath);
tor_assert(circ->cpath->extend_info);
- return (extend_info_supports_ntor(circ->cpath->extend_info) ||
- circuit_can_use_tap(circ));
+ return extend_info_supports_ntor(circ->cpath->extend_info);
}
/** Find the circuits that are waiting to find out whether their guards are
diff --git a/src/core/or/circuitbuild.h b/src/core/or/circuitbuild.h
index c76259fc29..ac3bf52135 100644
--- a/src/core/or/circuitbuild.h
+++ b/src/core/or/circuitbuild.h
@@ -48,7 +48,6 @@ MOCK_DECL(int, circuit_all_predicted_ports_handled, (time_t now,
int circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info);
int circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info);
-int circuit_can_use_tap(const origin_circuit_t *circ);
int circuit_has_usable_onion_key(const origin_circuit_t *circ);
const uint8_t *build_state_get_exit_rsa_id(cpath_build_state_t *state);
MOCK_DECL(const node_t *,
diff --git a/src/core/or/circuitlist.c b/src/core/or/circuitlist.c
index b90c7ebb58..8f8ed915fb 100644
--- a/src/core/or/circuitlist.c
+++ b/src/core/or/circuitlist.c
@@ -65,6 +65,7 @@
#include "core/or/conflux.h"
#include "core/or/conflux_pool.h"
#include "core/or/crypt_path.h"
+#include "core/or/dos.h"
#include "core/or/extendinfo.h"
#include "core/or/status.h"
#include "core/or/trace_probes_circuit.h"
@@ -159,6 +160,10 @@ double cc_stats_circ_close_ss_cwnd_ma = 0;
uint64_t cc_stats_circs_closed = 0;
+/** Total number of circuit protocol violation. This is incremented when the
+ * END_CIRC_REASON_TORPROTOCOL is used to close a circuit. */
+uint64_t circ_n_proto_violation = 0;
+
/********* END VARIABLES ************/
/* Implement circuit handle helpers. */
@@ -1130,6 +1135,7 @@ or_circuit_new(circid_t p_circ_id, channel_t *p_chan)
cell_queue_init(&circ->p_chan_cells);
init_circuit_base(TO_CIRCUIT(circ));
+ dos_stream_init_circ_tbf(circ);
tor_trace(TR_SUBSYS(circuit), TR_EV(new_or), circ);
return circ;
@@ -2195,6 +2201,10 @@ circuit_mark_for_close_, (circuit_t *circ, int reason, int line,
tor_assert(line);
tor_assert(file);
+ if (reason == END_CIRC_REASON_TORPROTOCOL) {
+ circ_n_proto_violation++;
+ }
+
/* Check whether the circuitpadding subsystem wants to block this close */
if (circpad_marked_circuit_for_padding(circ, reason)) {
return;
diff --git a/src/core/or/circuitlist.h b/src/core/or/circuitlist.h
index ca3c5bd0ee..0c8f958d2a 100644
--- a/src/core/or/circuitlist.h
+++ b/src/core/or/circuitlist.h
@@ -172,6 +172,7 @@
extern double cc_stats_circ_close_cwnd_ma;
extern double cc_stats_circ_close_ss_cwnd_ma;
extern uint64_t cc_stats_circs_closed;
+extern uint64_t circ_n_proto_violation;
/** Convert a circuit_t* to a pointer to the enclosing or_circuit_t. Assert
* if the cast is impossible. */
diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c
index ac9005e1d4..33886e9919 100644
--- a/src/core/or/circuituse.c
+++ b/src/core/or/circuituse.c
@@ -2473,7 +2473,7 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
extend_info = extend_info_new(conn->chosen_exit_name+1,
digest,
NULL, /* Ed25519 ID */
- NULL, NULL, /* onion keys */
+ NULL, /* onion keys */
&addr, conn->socks_request->port,
NULL,
false);
diff --git a/src/core/or/command.c b/src/core/or/command.c
index cad7a173b6..c35400d7a1 100644
--- a/src/core/or/command.c
+++ b/src/core/or/command.c
@@ -331,6 +331,14 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
return;
}
+ /* We no longer accept TAP, for any reason. */
+ if (create_cell->handshake_type == ONION_HANDSHAKE_TYPE_TAP) {
+ tor_free(create_cell);
+ /* TODO: Should we collect statistics here? Should we log? */
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
+ return;
+ }
+
/* Mark whether this circuit used TAP in case we need to use this
* information for onion service statistics later on. */
if (create_cell->handshake_type == ONION_HANDSHAKE_TYPE_FAST ||
diff --git a/src/core/or/conflux_pool.c b/src/core/or/conflux_pool.c
index 74781b307a..82043d607f 100644
--- a/src/core/or/conflux_pool.c
+++ b/src/core/or/conflux_pool.c
@@ -1624,7 +1624,22 @@ linked_circuit_free(circuit_t *circ, bool is_client)
/* Circuit can be freed without being closed and so we try to delete this leg
* so we can learn if this circuit is the last leg or not. */
- cfx_del_leg(circ->conflux, circ);
+ if (cfx_del_leg(circ->conflux, circ)) {
+ /* Check for instances of bug #40870, which we suspect happen
+ * during exit. If any happen outside of exit, BUG and warn. */
+ if (!circ->conflux->in_full_teardown) {
+ /* We should bug and warn if we're not in a shutdown process; that
+ * means we got here somehow without a close. */
+ if (BUG(!shutting_down)) {
+ log_warn(LD_BUG,
+ "Conflux circuit %p being freed without being marked for "
+ "full teardown via close, with shutdown state %d. "
+ "Please report this.", circ, shutting_down);
+ conflux_log_set(LOG_WARN, circ->conflux, is_client);
+ }
+ circ->conflux->in_full_teardown = true;
+ }
+ }
if (CONFLUX_NUM_LEGS(circ->conflux) > 0) {
/* The last leg will free the streams but until then, we nullify to avoid
@@ -2146,14 +2161,36 @@ conflux_log_set(int loglevel, const conflux_t *cfx, bool is_client)
}
}
+/**
+ * Conflux needs a notification when tor_shutdown() begins, so that
+ * when circuits are freed, new legs are not launched.
+ *
+ * This needs a separate notification from conflux_pool_free_all(),
+ * because circuits must be freed before that function.
+ */
+void
+conflux_notify_shutdown(void)
+{
+ shutting_down = true;
+}
+
+#ifdef TOR_UNIT_TESTS
+/**
+ * For unit tests: Clear the shutting down state so we resume building legs.
+ */
+void
+conflux_clear_shutdown(void)
+{
+ shutting_down = false;
+}
+#endif
+
/** Free and clean up the conflux pool subsystem. This is called by the subsys
* manager AFTER all circuits have been freed which implies that all objects in
* the pools aren't referenced anymore. */
void
conflux_pool_free_all(void)
{
- shutting_down = true;
-
digest256map_free(client_linked_pool, free_conflux_void_);
digest256map_free(server_linked_pool, free_conflux_void_);
digest256map_free(client_unlinked_pool, free_unlinked_void_);
diff --git a/src/core/or/conflux_pool.h b/src/core/or/conflux_pool.h
index afa4d9d058..eba726b03a 100644
--- a/src/core/or/conflux_pool.h
+++ b/src/core/or/conflux_pool.h
@@ -12,6 +12,7 @@
#include "core/or/or.h"
void conflux_pool_init(void);
+void conflux_notify_shutdown(void);
void conflux_pool_free_all(void);
origin_circuit_t *conflux_get_circ_for_conn(const entry_connection_t *conn,
@@ -41,6 +42,7 @@ void conflux_log_set(int loglevel, const conflux_t *cfx, bool is_client);
#ifdef TOR_UNIT_TESTS
bool launch_new_set(int num_legs);
+void conflux_clear_shutdown(void);
digest256map_t *get_linked_pool(bool is_client);
digest256map_t *get_unlinked_pool(bool is_client);
extern uint8_t DEFAULT_CLIENT_UX;
diff --git a/src/core/or/connection_edge.c b/src/core/or/connection_edge.c
index f21779a80c..b36d0d9013 100644
--- a/src/core/or/connection_edge.c
+++ b/src/core/or/connection_edge.c
@@ -73,6 +73,7 @@
#include "core/or/conflux_util.h"
#include "core/or/circuitstats.h"
#include "core/or/connection_or.h"
+#include "core/or/dos.h"
#include "core/or/extendinfo.h"
#include "core/or/policies.h"
#include "core/or/reasons.h"
@@ -105,6 +106,7 @@
#include "lib/buf/buffers.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
+#include "lib/encoding/confline.h"
#include "core/or/cell_st.h"
#include "core/or/cpath_build_state_st.h"
@@ -3989,6 +3991,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
begin_cell_t bcell;
int rv;
uint8_t end_reason=0;
+ dos_stream_defense_type_t dos_defense_type;
assert_circuit_ok(circ);
if (!CIRCUIT_IS_ORIGIN(circ)) {
@@ -4147,6 +4150,24 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
log_debug(LD_EXIT,"about to start the dns_resolve().");
+ // in the future we may want to have a similar defense for BEGIN_DIR and
+ // BEGIN sent to OS.
+ dos_defense_type = dos_stream_new_begin_or_resolve_cell(or_circ);
+ switch (dos_defense_type) {
+ case DOS_STREAM_DEFENSE_NONE:
+ break;
+ case DOS_STREAM_DEFENSE_REFUSE_STREAM:
+ // we don't use END_STREAM_REASON_RESOURCELIMIT because it would make a
+ // client mark us as non-functional until they get a new consensus.
+ relay_send_end_cell_from_edge(rh.stream_id, circ, END_STREAM_REASON_MISC,
+ layer_hint);
+ connection_free_(TO_CONN(n_stream));
+ return 0;
+ case DOS_STREAM_DEFENSE_CLOSE_CIRCUIT:
+ connection_free_(TO_CONN(n_stream));
+ return -END_CIRC_REASON_RESOURCELIMIT;
+ }
+
/* send it off to the gethostbyname farm */
switch (dns_resolve(n_stream)) {
case 1: /* resolve worked; now n_stream is attached to circ. */
@@ -4170,17 +4191,21 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
* Called when we receive a RELAY_COMMAND_RESOLVE cell 'cell' along the
* circuit <b>circ</b>;
* begin resolving the hostname, and (eventually) reply with a RESOLVED cell.
+ *
+ * Return -(some circuit end reason) if we want to tear down <b>circ</b>.
+ * Else return 0.
*/
int
connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
{
edge_connection_t *dummy_conn;
relay_header_t rh;
+ dos_stream_defense_type_t dos_defense_type;
assert_circuit_ok(TO_CIRCUIT(circ));
relay_header_unpack(&rh, cell->payload);
if (rh.length > RELAY_PAYLOAD_SIZE)
- return -1;
+ return 0;
/* Note the RESOLVE stream as seen. */
rep_hist_note_exit_stream(RELAY_COMMAND_RESOLVE);
@@ -4203,6 +4228,19 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
dummy_conn->on_circuit = TO_CIRCUIT(circ);
+ dos_defense_type = dos_stream_new_begin_or_resolve_cell(circ);
+ switch (dos_defense_type) {
+ case DOS_STREAM_DEFENSE_NONE:
+ break;
+ case DOS_STREAM_DEFENSE_REFUSE_STREAM:
+ dns_send_resolved_error_cell(dummy_conn, RESOLVED_TYPE_ERROR_TRANSIENT);
+ connection_free_(TO_CONN(dummy_conn));
+ return 0;
+ case DOS_STREAM_DEFENSE_CLOSE_CIRCUIT:
+ connection_free_(TO_CONN(dummy_conn));
+ return -END_CIRC_REASON_RESOURCELIMIT;
+ }
+
/* send it off to the gethostbyname farm */
switch (dns_resolve(dummy_conn)) {
case -1: /* Impossible to resolve; a resolved cell was sent. */
@@ -4237,6 +4275,76 @@ my_exit_policy_rejects(const tor_addr_t *addr,
return 0;
}
+/* Reapply exit policy to existing connections, possibly terminating
+ * connections
+ * no longer allowed by the policy.
+ */
+void
+connection_reapply_exit_policy(config_line_t *changes)
+{
+ int marked_for_close = 0;
+ smartlist_t *conn_list = NULL;
+ smartlist_t *policy = NULL;
+ int config_change_relevant = 0;
+
+ if (get_options()->ReevaluateExitPolicy == 0) {
+ return;
+ }
+
+ for (const config_line_t *line = changes;
+ line && !config_change_relevant;
+ line = line->next) {
+ const char* exit_policy_options[] = {
+ "ExitRelay",
+ "ExitPolicy",
+ "ReducedExitPolicy",
+ "ReevaluateExitPolicy",
+ "IPv6Exit",
+ NULL
+ };
+ for (unsigned int i = 0; exit_policy_options[i] != NULL; ++i) {
+ if (strcmp(line->key, exit_policy_options[i]) == 0) {
+ config_change_relevant = 1;
+ break;
+ }
+ }
+ }
+
+ if (!config_change_relevant) {
+ /* Policy did not change: no need to iterate over connections */
+ return;
+ }
+
+ // we can't use router_compare_to_my_exit_policy as it depend on the
+ // descriptor, which is regenerated asynchronously, so we have to parse the
+ // policy ourselves.
+ // We don't verify for our own IP, it's not part of the configuration.
+ if (BUG(policies_parse_exit_policy_from_options(get_options(), NULL, NULL,
+ &policy) != 0)) {
+ return;
+ }
+
+ conn_list = connection_list_by_type_purpose(CONN_TYPE_EXIT,
+ EXIT_PURPOSE_CONNECT);
+
+ SMARTLIST_FOREACH_BEGIN(conn_list, connection_t *, conn) {
+ addr_policy_result_t verdict = compare_tor_addr_to_addr_policy(&conn->addr,
+ conn->port,
+ policy);
+ if (verdict != ADDR_POLICY_ACCEPTED) {
+ connection_edge_end(TO_EDGE_CONN(conn), END_STREAM_REASON_EXITPOLICY);
+ connection_mark_for_close(conn);
+ ++marked_for_close;
+ }
+ } SMARTLIST_FOREACH_END(conn);
+
+ smartlist_free(conn_list);
+ smartlist_free(policy);
+
+ log_info(LD_GENERAL, "Marked %d connections to be closed as no longer "
+ "allowed per ExitPolicy", marked_for_close);
+}
+
/** Return true iff the consensus allows network reentry. The default value is
* false if the parameter is not found. */
static bool
diff --git a/src/core/or/connection_edge.h b/src/core/or/connection_edge.h
index 59fc17dea5..1bb0e6d368 100644
--- a/src/core/or/connection_edge.h
+++ b/src/core/or/connection_edge.h
@@ -13,6 +13,7 @@
#define TOR_CONNECTION_EDGE_H
#include "lib/testsupport/testsupport.h"
+#include "lib/encoding/confline.h"
#include "feature/hs/hs_service.h"
@@ -101,6 +102,7 @@ void connection_entry_set_controller_wait(entry_connection_t *conn);
void connection_ap_about_to_close(entry_connection_t *edge_conn);
void connection_exit_about_to_close(edge_connection_t *edge_conn);
+void connection_reapply_exit_policy(config_line_t *changes);
MOCK_DECL(int,
connection_ap_handshake_send_begin,(entry_connection_t *ap_conn));
diff --git a/src/core/or/connection_or.c b/src/core/or/connection_or.c
index 343c1a67ed..30ce5e0c57 100644
--- a/src/core/or/connection_or.c
+++ b/src/core/or/connection_or.c
@@ -104,7 +104,7 @@ static void connection_or_check_canonicity(or_connection_t *conn,
/**
* Cast a `connection_t *` to an `or_connection_t *`.
*
- * Exit with an assertion failure if the input is not an `or_connnection_t`.
+ * Exit with an assertion failure if the input is not an `or_connection_t`.
**/
or_connection_t *
TO_OR_CONN(connection_t *c)
@@ -116,7 +116,7 @@ TO_OR_CONN(connection_t *c)
/**
* Cast a `const connection_t *` to a `const or_connection_t *`.
*
- * Exit with an assertion failure if the input is not an `or_connnection_t`.
+ * Exit with an assertion failure if the input is not an `or_connection_t`.
**/
const or_connection_t *
CONST_TO_OR_CONN(const connection_t *c)
diff --git a/src/core/or/crypt_path_st.h b/src/core/or/crypt_path_st.h
index fdc6b6fbb2..fc6391f2f8 100644
--- a/src/core/or/crypt_path_st.h
+++ b/src/core/or/crypt_path_st.h
@@ -26,7 +26,6 @@ struct onion_handshake_state_t {
uint16_t tag;
union {
struct fast_handshake_state_t *fast;
- struct crypto_dh_t *tap;
struct ntor_handshake_state_t *ntor;
struct ntor3_handshake_state_t *ntor3;
} u;
diff --git a/src/core/or/dos.c b/src/core/or/dos.c
index ccdb30dbee..b789f87aae 100644
--- a/src/core/or/dos.c
+++ b/src/core/or/dos.c
@@ -79,6 +79,24 @@ static uint64_t conn_num_addr_connect_rejected;
static uint32_t dos_num_circ_max_outq;
/*
+ * Stream denial of service mitigation.
+ *
+ * Namespace used for this mitigation framework is "dos_stream_".
+ */
+
+/* Is the connection DoS mitigation enabled? */
+static unsigned int dos_stream_enabled = 0;
+
+/* Consensus parameters. They can be changed when a new consensus arrives.
+ * They are initialized with the hardcoded default values. */
+static dos_stream_defense_type_t dos_stream_defense_type;
+static uint32_t dos_stream_rate = DOS_STREAM_RATE_DEFAULT;
+static uint32_t dos_stream_burst = DOS_STREAM_BURST_DEFAULT;
+
+/* Keep some stats for the heartbeat so we can report out. */
+static uint64_t stream_num_rejected;
+
+/*
* General interface of the denial of service mitigation subsystem.
*/
@@ -258,6 +276,59 @@ get_param_conn_connect_defense_time_period(const networkstatus_t *ns)
INT32_MAX);
}
+/* Return true iff the stream creation mitigation is enabled. We look at the
+ * consensus for this else a default value is returned. */
+MOCK_IMPL(STATIC unsigned int,
+get_param_stream_enabled, (const networkstatus_t *ns))
+{
+ if (dos_get_options()->DoSStreamCreationEnabled != -1) {
+ return dos_get_options()->DoSStreamCreationEnabled;
+ }
+
+ return !!networkstatus_get_param(ns, "DoSStreamCreationEnabled",
+ DOS_STREAM_ENABLED_DEFAULT, 0, 1);
+}
+
+/* Return the parameter for the time rate that is how many stream per circuit
+ * over this time span. */
+static uint32_t
+get_param_stream_rate(const networkstatus_t *ns)
+{
+ /* This is in seconds. */
+ if (dos_get_options()->DoSStreamCreationRate) {
+ return dos_get_options()->DoSStreamCreationRate;
+ }
+ return networkstatus_get_param(ns, "DoSStreamCreationRate",
+ DOS_STREAM_RATE_DEFAULT,
+ 1, INT32_MAX);
+}
+
+/* Return the parameter for the maximum circuit count for the circuit time
+ * rate. */
+static uint32_t
+get_param_stream_burst(const networkstatus_t *ns)
+{
+ if (dos_get_options()->DoSStreamCreationBurst) {
+ return dos_get_options()->DoSStreamCreationBurst;
+ }
+ return networkstatus_get_param(ns, "DoSStreamCreationBurst",
+ DOS_STREAM_BURST_DEFAULT,
+ 1, INT32_MAX);
+}
+
+/* Return the consensus parameter of the circuit creation defense type. */
+static uint32_t
+get_param_stream_defense_type(const networkstatus_t *ns)
+{
+ if (dos_get_options()->DoSStreamCreationDefenseType) {
+ return dos_get_options()->DoSStreamCreationDefenseType;
+ }
+ return networkstatus_get_param(ns, "DoSStreamCreationDefenseType",
+ DOS_STREAM_DEFENSE_TYPE_DEFAULT,
+ DOS_STREAM_DEFENSE_NONE,
+ DOS_STREAM_DEFENSE_MAX);
+}
+
/* Set circuit creation parameters located in the consensus or their default
* if none are present. Called at initialization or when the consensus
* changes. */
@@ -283,6 +354,12 @@ set_dos_parameters(const networkstatus_t *ns)
/* Circuit. */
dos_num_circ_max_outq = get_param_dos_num_circ_max_outq(ns);
+
+ /* Stream. */
+ dos_stream_enabled = get_param_stream_enabled(ns);
+ dos_stream_defense_type = get_param_stream_defense_type(ns);
+ dos_stream_rate = get_param_stream_rate(ns);
+ dos_stream_burst = get_param_stream_burst(ns);
}
/* Free everything for the circuit creation DoS mitigation subsystem. */
@@ -760,6 +837,48 @@ dos_conn_addr_get_defense_type(const tor_addr_t *addr)
return DOS_CONN_DEFENSE_NONE;
}
+/* Stream creation public API. */
+
+/** Return the number of rejected stream and resolve. */
+uint64_t
+dos_get_num_stream_rejected(void)
+{
+ return stream_num_rejected;
+}
+
+/* Return the action to take against a BEGIN or RESOLVE cell. Return
+ * DOS_STREAM_DEFENSE_NONE when no action should be taken.
+ * Increment the appropriate counter when the cell was found to go over a
+ * limit. */
+dos_stream_defense_type_t
+dos_stream_new_begin_or_resolve_cell(or_circuit_t *circ)
+{
+ if (!dos_stream_enabled || circ == NULL)
+ return DOS_STREAM_DEFENSE_NONE;
+
+ token_bucket_ctr_refill(&circ->stream_limiter,
+ (uint32_t) monotime_coarse_absolute_sec());
+
+ if (token_bucket_ctr_get(&circ->stream_limiter) > 0) {
+ token_bucket_ctr_dec(&circ->stream_limiter, 1);
+ return DOS_STREAM_DEFENSE_NONE;
+ }
+ /* if defense type is DOS_STREAM_DEFENSE_NONE but DoSStreamEnabled is true,
+ * we count offending cells as rejected, despite them being actually
+ * accepted. */
+ ++stream_num_rejected;
+ return dos_stream_defense_type;
+}
+
+/* Initialize the token bucket for stream rate limit on a circuit. */
+void
+dos_stream_init_circ_tbf(or_circuit_t *circ)
+{
+ token_bucket_ctr_init(&circ->stream_limiter, dos_stream_rate,
+ dos_stream_burst,
+ (uint32_t) monotime_coarse_absolute_sec());
+}
+
/* General API */
/* Take any appropriate actions for the given geoip entry that is about to get
@@ -945,6 +1064,14 @@ dos_log_heartbeat(void)
"[DoSRefuseSingleHopClientRendezvous disabled]");
}
+ if (dos_stream_enabled) {
+ smartlist_add_asprintf(elems,
+ "%" PRIu64 " stream rejected",
+ stream_num_rejected);
+ } else {
+ smartlist_add_asprintf(elems, "[DoSStreamCreationEnabled disabled]");
+ }
+
/* HS DoS stats. */
smartlist_add_asprintf(elems,
"%" PRIu64 " INTRODUCE2 rejected",
diff --git a/src/core/or/dos.h b/src/core/or/dos.h
index 4a2227f132..03606287d1 100644
--- a/src/core/or/dos.h
+++ b/src/core/or/dos.h
@@ -90,6 +90,7 @@ uint64_t dos_get_num_cc_rejected(void);
uint64_t dos_get_num_conn_addr_rejected(void);
uint64_t dos_get_num_conn_addr_connect_rejected(void);
uint64_t dos_get_num_single_hop_refused(void);
+uint64_t dos_get_num_stream_rejected(void);
/*
* Circuit creation DoS mitigation subsystemn interface.
@@ -159,6 +160,37 @@ typedef enum dos_conn_defense_type_t {
dos_conn_defense_type_t dos_conn_addr_get_defense_type(const tor_addr_t *addr);
+/*
+ * Stream creation DoS mitigation subsystem interface.
+ */
+
+/* DoSStreamCreationEnabled default. Disabled by deault. */
+#define DOS_STREAM_ENABLED_DEFAULT 0
+/* DoSStreamCreationDefenseType maps to the dos_stream_defense_type_t enum */
+#define DOS_STREAM_DEFENSE_TYPE_DEFAULT DOS_STREAM_DEFENSE_REFUSE_STREAM
+/* DosStreamCreationRate is 100 per seconds. */
+#define DOS_STREAM_RATE_DEFAULT 100
+/* DosStreamCreationBurst default. */
+#define DOS_STREAM_BURST_DEFAULT 300
+
+/* Type of defense that we can use for the stream creation DoS mitigation. */
+typedef enum dos_stream_defense_type_t {
+ /* No defense used. */
+ DOS_STREAM_DEFENSE_NONE = 1,
+ /* Reject the stream */
+ DOS_STREAM_DEFENSE_REFUSE_STREAM = 2,
+ /* Close the circuit */
+ DOS_STREAM_DEFENSE_CLOSE_CIRCUIT = 3,
+
+ /* Maximum value that can be used. Useful for the boundaries of the
+ * consensus parameter. */
+ DOS_STREAM_DEFENSE_MAX = 3,
+} dos_stream_defense_type_t;
+
+dos_stream_defense_type_t dos_stream_new_begin_or_resolve_cell(
+ or_circuit_t *circ);
+void dos_stream_init_circ_tbf(or_circuit_t *circ);
+
#ifdef DOS_PRIVATE
STATIC uint32_t get_param_conn_max_concurrent_count(
@@ -176,6 +208,8 @@ MOCK_DECL(STATIC unsigned int, get_param_cc_enabled,
(const networkstatus_t *ns));
MOCK_DECL(STATIC unsigned int, get_param_conn_enabled,
(const networkstatus_t *ns));
+MOCK_DECL(STATIC unsigned int, get_param_stream_enabled,
+ (const networkstatus_t *ns));
#endif /* defined(DOS_PRIVATE) */
diff --git a/src/core/or/dos_options.inc b/src/core/or/dos_options.inc
index 9baa7a35b8..4d15c33f3d 100644
--- a/src/core/or/dos_options.inc
+++ b/src/core/or/dos_options.inc
@@ -50,6 +50,19 @@ CONF_VAR(DoSConnectionConnectBurst, POSINT, 0, "0")
/** Allowed rate of client connection allowed per address. */
CONF_VAR(DoSConnectionConnectRate, POSINT, 0, "0")
+/** Autobool: Is the stream creation DoS mitigation subsystem enabled? */
+CONF_VAR(DoSStreamCreationEnabled, AUTOBOOL, 0, "auto")
+
+/** Stream rate used to refill the token bucket. */
+CONF_VAR(DoSStreamCreationRate, POSINT, 0, "0")
+
+/** Maximum allowed burst of stream. */
+CONF_VAR(DoSStreamCreationBurst, POSINT, 0, "0")
+
+/** When an circuit is detected as malicious, what defense should be used
+ * against it. See the dos_stream_defense_type_t enum. */
+CONF_VAR(DoSStreamCreationDefenseType, INT, 0, "0")
+
/** For how much time (in seconds) the connection connect rate defense is
* applicable for a malicious address. A random time delta is added to the
* defense time of an address which will be between 1 second and half of this
diff --git a/src/core/or/extend_info_st.h b/src/core/or/extend_info_st.h
index 2ab0beb7e6..5f59bd2299 100644
--- a/src/core/or/extend_info_st.h
+++ b/src/core/or/extend_info_st.h
@@ -34,8 +34,6 @@ struct extend_info_t {
/** IP/Port values for this hop's ORPort(s). Any unused values are set
* to a null address. */
tor_addr_port_t orports[EXTEND_INFO_MAX_ADDRS];
- /** TAP onion key for this hop. */
- crypto_pk_t *onion_key;
/** Ntor onion key for this hop. */
curve25519_public_key_t curve25519_onion_key;
/** True if this hop is to be used as an _exit_,
diff --git a/src/core/or/extendinfo.c b/src/core/or/extendinfo.c
index ca623f09ce..6954335cc2 100644
--- a/src/core/or/extendinfo.c
+++ b/src/core/or/extendinfo.c
@@ -33,7 +33,6 @@ extend_info_t *
extend_info_new(const char *nickname,
const char *rsa_id_digest,
const ed25519_public_key_t *ed_id,
- crypto_pk_t *onion_key,
const curve25519_public_key_t *ntor_key,
const tor_addr_t *addr, uint16_t port,
const protover_summary_flags_t *pv,
@@ -46,8 +45,6 @@ extend_info_new(const char *nickname,
memcpy(&info->ed_identity, ed_id, sizeof(ed25519_public_key_t));
if (nickname)
strlcpy(info->nickname, nickname, sizeof(info->nickname));
- if (onion_key)
- info->onion_key = crypto_pk_dup_key(onion_key);
if (ntor_key)
memcpy(&info->curve25519_onion_key, ntor_key,
sizeof(curve25519_public_key_t));
@@ -100,7 +97,6 @@ extend_info_t *
extend_info_from_node(const node_t *node, int for_direct_connect,
bool for_exit)
{
- crypto_pk_t *rsa_pubkey = NULL;
extend_info_t *info = NULL;
tor_addr_port_t ap;
int valid_addr = 0;
@@ -149,13 +145,11 @@ extend_info_from_node(const node_t *node, int for_direct_connect,
/* Retrieve the curve25519 pubkey. */
const curve25519_public_key_t *curve_pubkey =
node_get_curve25519_onion_key(node);
- rsa_pubkey = node_get_rsa_onion_key(node);
if (valid_addr && node->ri) {
info = extend_info_new(node->ri->nickname,
node->identity,
ed_pubkey,
- rsa_pubkey,
curve_pubkey,
&ap.addr,
ap.port,
@@ -165,7 +159,6 @@ extend_info_from_node(const node_t *node, int for_direct_connect,
info = extend_info_new(node->rs->nickname,
node->identity,
ed_pubkey,
- rsa_pubkey,
curve_pubkey,
&ap.addr,
ap.port,
@@ -173,7 +166,6 @@ extend_info_from_node(const node_t *node, int for_direct_connect,
for_exit);
}
- crypto_pk_free(rsa_pubkey);
return info;
}
@@ -183,7 +175,6 @@ extend_info_free_(extend_info_t *info)
{
if (!info)
return;
- crypto_pk_free(info->onion_key);
tor_free(info);
}
@@ -196,22 +187,9 @@ extend_info_dup(extend_info_t *info)
tor_assert(info);
newinfo = tor_malloc(sizeof(extend_info_t));
memcpy(newinfo, info, sizeof(extend_info_t));
- if (info->onion_key)
- newinfo->onion_key = crypto_pk_dup_key(info->onion_key);
- else
- newinfo->onion_key = NULL;
return newinfo;
}
-/* Does ei have a valid TAP key? */
-int
-extend_info_supports_tap(const extend_info_t* ei)
-{
- tor_assert(ei);
- /* Valid TAP keys are not NULL */
- return ei->onion_key != NULL;
-}
-
/* Does ei have a valid ntor key? */
int
extend_info_supports_ntor(const extend_info_t* ei)
diff --git a/src/core/or/extendinfo.h b/src/core/or/extendinfo.h
index 6d1f20597b..3419a4e043 100644
--- a/src/core/or/extendinfo.h
+++ b/src/core/or/extendinfo.h
@@ -15,7 +15,6 @@
extend_info_t *extend_info_new(const char *nickname,
const char *rsa_id_digest,
const struct ed25519_public_key_t *ed_id,
- crypto_pk_t *onion_key,
const struct curve25519_public_key_t *ntor_key,
const tor_addr_t *addr, uint16_t port,
const struct protover_summary_flags_t *pv,
@@ -27,7 +26,6 @@ void extend_info_free_(extend_info_t *info);
#define extend_info_free(info) \
FREE_AND_NULL(extend_info_t, extend_info_free_, (info))
int extend_info_addr_is_allowed(const tor_addr_t *addr);
-int extend_info_supports_tap(const extend_info_t* ei);
int extend_info_supports_ntor(const extend_info_t* ei);
int extend_info_supports_ntor_v3(const extend_info_t *ei);
int extend_info_has_preferred_onion_key(const extend_info_t* ei);
diff --git a/src/core/or/half_edge_st.h b/src/core/or/half_edge_st.h
index 642d8e1ea5..d8c183a93c 100644
--- a/src/core/or/half_edge_st.h
+++ b/src/core/or/half_edge_st.h
@@ -41,10 +41,10 @@ typedef struct half_edge_t {
/**
* Did this edge use congestion control? If so, use
* timer instead of pending data approach */
- int used_ccontrol : 1;
+ unsigned int used_ccontrol : 1;
/** Is there a connected cell pending? */
- int connected_pending : 1;
+ unsigned int connected_pending : 1;
} half_edge_t;
#endif /* !defined(HALF_EDGE_ST_H) */
diff --git a/src/core/or/onion.c b/src/core/or/onion.c
index 0bdd2a6d35..07c26a80e8 100644
--- a/src/core/or/onion.c
+++ b/src/core/or/onion.c
@@ -44,7 +44,6 @@
#include "core/crypto/onion_crypto.h"
#include "core/crypto/onion_fast.h"
#include "core/crypto/onion_ntor.h"
-#include "core/crypto/onion_tap.h"
#include "core/or/onion.h"
#include "feature/nodelist/networkstatus.h"
@@ -61,10 +60,7 @@ check_create_cell(const create_cell_t *cell, int unknown_ok)
{
switch (cell->cell_type) {
case CELL_CREATE:
- if (cell->handshake_type != ONION_HANDSHAKE_TYPE_TAP &&
- cell->handshake_type != ONION_HANDSHAKE_TYPE_NTOR)
- return -1;
- break;
+ return -1;
case CELL_CREATE_FAST:
if (cell->handshake_type != ONION_HANDSHAKE_TYPE_FAST)
return -1;
@@ -77,9 +73,7 @@ check_create_cell(const create_cell_t *cell, int unknown_ok)
switch (cell->handshake_type) {
case ONION_HANDSHAKE_TYPE_TAP:
- if (cell->handshake_len != TAP_ONIONSKIN_CHALLENGE_LEN)
- return -1;
- break;
+ return -1;
case ONION_HANDSHAKE_TYPE_FAST:
if (cell->handshake_len != CREATE_FAST_LEN)
return -1;
@@ -160,14 +154,7 @@ create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in)
{
switch (cell_in->command) {
case CELL_CREATE:
- if (tor_memeq(cell_in->payload, NTOR_CREATE_MAGIC, 16)) {
- create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR,
- NTOR_ONIONSKIN_LEN, cell_in->payload+16);
- } else {
- create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP,
- TAP_ONIONSKIN_CHALLENGE_LEN, cell_in->payload);
- }
- break;
+ return -1;
case CELL_CREATE_FAST:
create_cell_init(cell_out, CELL_CREATE_FAST, ONION_HANDSHAKE_TYPE_FAST,
CREATE_FAST_LEN, cell_in->payload);
@@ -190,10 +177,7 @@ check_created_cell(const created_cell_t *cell)
{
switch (cell->cell_type) {
case CELL_CREATED:
- if (cell->handshake_len != TAP_ONIONSKIN_REPLY_LEN &&
- cell->handshake_len != NTOR_REPLY_LEN)
- return -1;
- break;
+ return -1;
case CELL_CREATED_FAST:
if (cell->handshake_len != CREATED_FAST_LEN)
return -1;
@@ -216,10 +200,7 @@ created_cell_parse(created_cell_t *cell_out, const cell_t *cell_in)
switch (cell_in->command) {
case CELL_CREATED:
- cell_out->cell_type = CELL_CREATED;
- cell_out->handshake_len = TAP_ONIONSKIN_REPLY_LEN;
- memcpy(cell_out->reply, cell_in->payload, TAP_ONIONSKIN_REPLY_LEN);
- break;
+ return -1;
case CELL_CREATED_FAST:
cell_out->cell_type = CELL_CREATED_FAST;
cell_out->handshake_len = CREATED_FAST_LEN;
@@ -260,53 +241,22 @@ check_extend_cell(const extend_cell_t *cell)
}
}
if (cell->create_cell.cell_type == CELL_CREATE) {
- if (cell->cell_type != RELAY_COMMAND_EXTEND)
- return -1;
+ return -1;
} else if (cell->create_cell.cell_type == CELL_CREATE2) {
- if (cell->cell_type != RELAY_COMMAND_EXTEND2 &&
- cell->cell_type != RELAY_COMMAND_EXTEND)
+ if (cell->cell_type != RELAY_COMMAND_EXTEND2)
return -1;
} else {
/* In particular, no CREATE_FAST cells are allowed */
return -1;
}
- if (cell->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_FAST)
+ if (cell->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_FAST ||
+ cell->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_TAP)
return -1;
return check_create_cell(&cell->create_cell, 1);
}
static int
-extend_cell_from_extend1_cell_body(extend_cell_t *cell_out,
- const extend1_cell_body_t *cell)
-{
- tor_assert(cell_out);
- tor_assert(cell);
- memset(cell_out, 0, sizeof(*cell_out));
- tor_addr_make_unspec(&cell_out->orport_ipv4.addr);
- tor_addr_make_unspec(&cell_out->orport_ipv6.addr);
-
- cell_out->cell_type = RELAY_COMMAND_EXTEND;
- tor_addr_from_ipv4h(&cell_out->orport_ipv4.addr, cell->ipv4addr);
- cell_out->orport_ipv4.port = cell->port;
- if (tor_memeq(cell->onionskin, NTOR_CREATE_MAGIC, 16)) {
- cell_out->create_cell.cell_type = CELL_CREATE2;
- cell_out->create_cell.handshake_type = ONION_HANDSHAKE_TYPE_NTOR;
- cell_out->create_cell.handshake_len = NTOR_ONIONSKIN_LEN;
- memcpy(cell_out->create_cell.onionskin, cell->onionskin + 16,
- NTOR_ONIONSKIN_LEN);
- } else {
- cell_out->create_cell.cell_type = CELL_CREATE;
- cell_out->create_cell.handshake_type = ONION_HANDSHAKE_TYPE_TAP;
- cell_out->create_cell.handshake_len = TAP_ONIONSKIN_CHALLENGE_LEN;
- memcpy(cell_out->create_cell.onionskin, cell->onionskin,
- TAP_ONIONSKIN_CHALLENGE_LEN);
- }
- memcpy(cell_out->node_id, cell->identity, DIGEST_LEN);
- return 0;
-}
-
-static int
create_cell_from_create2_cell_body(create_cell_t *cell_out,
const create2_cell_body_t *cell)
{
@@ -408,19 +358,7 @@ extend_cell_parse,(extend_cell_t *cell_out,
switch (command) {
case RELAY_COMMAND_EXTEND:
- {
- extend1_cell_body_t *cell = NULL;
- if (extend1_cell_body_parse(&cell, payload, payload_length)<0 ||
- cell == NULL) {
- if (cell)
- extend1_cell_body_free(cell);
- return -1;
- }
- int r = extend_cell_from_extend1_cell_body(cell_out, cell);
- extend1_cell_body_free(cell);
- if (r < 0)
- return r;
- }
+ return -1;
break;
case RELAY_COMMAND_EXTEND2:
{
@@ -479,13 +417,7 @@ extended_cell_parse(extended_cell_t *cell_out,
switch (command) {
case RELAY_COMMAND_EXTENDED:
- if (payload_len != TAP_ONIONSKIN_REPLY_LEN)
- return -1;
- cell_out->cell_type = RELAY_COMMAND_EXTENDED;
- cell_out->created_cell.cell_type = CELL_CREATED;
- cell_out->created_cell.handshake_len = TAP_ONIONSKIN_REPLY_LEN;
- memcpy(cell_out->created_cell.reply, payload, TAP_ONIONSKIN_REPLY_LEN);
- break;
+ return -1;
case RELAY_COMMAND_EXTENDED2:
{
cell_out->cell_type = RELAY_COMMAND_EXTENDED2;
@@ -627,26 +559,7 @@ extend_cell_format(uint8_t *command_out, uint16_t *len_out,
switch (cell_in->cell_type) {
case RELAY_COMMAND_EXTEND:
- {
- if (BUG(cell_in->create_cell.handshake_type ==
- ONION_HANDSHAKE_TYPE_NTOR_V3)) {
- log_warn(LD_BUG, "Extend cells cannot contain ntorv3!");
- return -1;
- }
- *command_out = RELAY_COMMAND_EXTEND;
- *len_out = 6 + TAP_ONIONSKIN_CHALLENGE_LEN + DIGEST_LEN;
- set_uint32(p, tor_addr_to_ipv4n(&cell_in->orport_ipv4.addr));
- set_uint16(p+4, htons(cell_in->orport_ipv4.port));
- if (cell_in->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_NTOR) {
- memcpy(p+6, NTOR_CREATE_MAGIC, 16);
- memcpy(p+22, cell_in->create_cell.onionskin, NTOR_ONIONSKIN_LEN);
- } else {
- memcpy(p+6, cell_in->create_cell.onionskin,
- TAP_ONIONSKIN_CHALLENGE_LEN);
- }
- memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, cell_in->node_id, DIGEST_LEN);
- }
- break;
+ return -1;
case RELAY_COMMAND_EXTEND2:
{
uint8_t n_specifiers = 1;
@@ -737,13 +650,7 @@ extended_cell_format(uint8_t *command_out, uint16_t *len_out,
switch (cell_in->cell_type) {
case RELAY_COMMAND_EXTENDED:
- {
- *command_out = RELAY_COMMAND_EXTENDED;
- *len_out = TAP_ONIONSKIN_REPLY_LEN;
- memcpy(payload_out, cell_in->created_cell.reply,
- TAP_ONIONSKIN_REPLY_LEN);
- }
- break;
+ return -1;
case RELAY_COMMAND_EXTENDED2:
{
*command_out = RELAY_COMMAND_EXTENDED2;
diff --git a/src/core/or/or.h b/src/core/or/or.h
index 088c45342b..c736d37fb9 100644
--- a/src/core/or/or.h
+++ b/src/core/or/or.h
@@ -301,6 +301,7 @@ struct curve25519_public_key_t;
#define RESOLVED_TYPE_IPV6 6
#define RESOLVED_TYPE_ERROR_TRANSIENT 0xF0
#define RESOLVED_TYPE_ERROR 0xF1
+#define RESOLVED_TYPE_NOERROR 0xF2
/* Negative reasons are internal: we never send them in a DESTROY or TRUNCATE
* call; they only go to the controller for tracking */
diff --git a/src/core/or/or_circuit_st.h b/src/core/or/or_circuit_st.h
index d5a7007928..28e357338a 100644
--- a/src/core/or/or_circuit_st.h
+++ b/src/core/or/or_circuit_st.h
@@ -102,6 +102,10 @@ struct or_circuit_t {
* used if this is a service introduction circuit at the intro point
* (purpose = CIRCUIT_PURPOSE_INTRO_POINT). */
token_bucket_ctr_t introduce2_bucket;
+
+ /** RELAY_BEGIN and RELAY_RESOLVE cell bucket controlling how much can go on
+ * this circuit. Only used if this is the end of a circuit on an exit node.*/
+ token_bucket_ctr_t stream_limiter;
};
#endif /* !defined(OR_CIRCUIT_ST_H) */
diff --git a/src/core/or/policies.c b/src/core/or/policies.c
index 1864b84d5e..4641632b60 100644
--- a/src/core/or/policies.c
+++ b/src/core/or/policies.c
@@ -1066,7 +1066,7 @@ socks_policy_permits_address(const tor_addr_t *addr)
}
/** Return 1 if <b>addr</b> is permitted to connect to our metrics port,
- * based on <b>socks_policy</b>. Else return 0.
+ * based on <b>metrics_policy</b>. Else return 0.
*/
int
metrics_policy_permits_address(const tor_addr_t *addr)
diff --git a/src/core/or/protover.c b/src/core/or/protover.c
index 175bfbdab0..1ac32bf06c 100644
--- a/src/core/or/protover.c
+++ b/src/core/or/protover.c
@@ -389,7 +389,7 @@ protocol_list_supports_protocol_or_later(const char *list,
/* All protocol version that this relay version supports. */
#define PR_CONFLUX_V "1"
#define PR_CONS_V "1-2"
-#define PR_DESC_V "1-2"
+#define PR_DESC_V "1-3"
#define PR_DIRCACHE_V "2"
#define PR_FLOWCTRL_V "1-2"
#define PR_HSDIR_V "2"
@@ -401,9 +401,9 @@ protocol_list_supports_protocol_or_later(const char *list,
#else
#define PR_LINKAUTH_V "3"
#endif
-#define PR_MICRODESC_V "1-2"
+#define PR_MICRODESC_V "1-3"
#define PR_PADDING_V "2"
-#define PR_RELAY_V "1-4"
+#define PR_RELAY_V "2-4"
/** Return the string containing the supported version for the given protocol
* type. */
diff --git a/src/core/or/relay.c b/src/core/or/relay.c
index 3670353ad3..9e62538421 100644
--- a/src/core/or/relay.c
+++ b/src/core/or/relay.c
@@ -1343,7 +1343,7 @@ connection_ap_handshake_socks_got_resolved_cell(entry_connection_t *conn,
/* Now convert it to the ugly old interface */
if (! addr_best) {
connection_ap_handshake_socks_resolved(conn,
- RESOLVED_TYPE_ERROR,0,NULL,-1,-1);
+ RESOLVED_TYPE_NOERROR,0,NULL,-1,-1);
return;
}
@@ -2030,8 +2030,7 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ,
circ->purpose);
return 0;
}
- connection_exit_begin_resolve(cell, TO_OR_CIRCUIT(circ));
- return 0;
+ return connection_exit_begin_resolve(cell, TO_OR_CIRCUIT(circ));
case RELAY_COMMAND_RESOLVED:
if (conn) {
log_fn(LOG_PROTOCOL_WARN, domain,
diff --git a/src/core/or/scheduler_kist.c b/src/core/or/scheduler_kist.c
index 69804247c8..c4b15a9950 100644
--- a/src/core/or/scheduler_kist.c
+++ b/src/core/or/scheduler_kist.c
@@ -447,10 +447,16 @@ update_socket_written(socket_table_t *table, channel_t *chan, size_t bytes)
* by only writing a channel's outbuf to the kernel if it has 8 cells or more
* in it.
*
- * Note: The number 8 has been picked for no particular reasons except that it
- * is 4096 bytes which is a common number for buffering. A TLS record can hold
- * up to 16KiB thus using 8 cells means that a relay will at most send a TLS
- * record of 4KiB or 1/4 of the maximum capacity of a TLS record.
+ * Note: The number 8 was picked so that, when using 512-byte cells, it
+ * would produce 4096 bytes: a common number for buffering. A TLS
+ * record can hold up to 16KiB; thus, using 8 512-byte cells means that
+ * a relay will at most send a TLS record of 4KiB or 1/4 of the maximum
+ * capacity of a TLS record.
+ *
+ * Of course, the above calculation became incorrect when we moved to
+ * 514-byte cells in order to accommodate a 4-byte circuit ID; we may
+ * want to consider profiling with '7' to see if it produces better
+ * results. (TODO)
*/
MOCK_IMPL(int, channel_should_write_to_kernel,
(outbuf_table_t *table, channel_t *chan))
diff --git a/src/core/proto/proto_socks.c b/src/core/proto/proto_socks.c
index 78767a94ff..8c53bf6210 100644
--- a/src/core/proto/proto_socks.c
+++ b/src/core/proto/proto_socks.c
@@ -451,6 +451,19 @@ parse_socks5_userpass_auth(const uint8_t *raw_data, socks_request_t *req,
const char *password =
socks5_client_userpass_auth_getconstarray_passwd(trunnel_req);
+ /* Detect invalid SOCKS5 extended-parameter requests. */
+ if (usernamelen >= 8 &&
+ tor_memeq(username, "<torS0X>", 8)) {
+ /* This is indeed an extended-parameter request. */
+ if (usernamelen != 9 ||
+ tor_memneq(username, "<torS0X>0", 9)) {
+ /* This request is an unrecognized version, or it includes an Arti RPC
+ * object ID (which we do not recognize). */
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ }
+ }
+
if (usernamelen && username) {
tor_free(req->username);
req->username = tor_memdup_nulterm(username, usernamelen);
@@ -919,11 +932,12 @@ static const char SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG[] =
"<title>This is a SOCKS Proxy, Not An HTTP Proxy</title>\n"
"</head>\n"
"<body>\n"
- "<h1>This is a SOCKs proxy, not an HTTP proxy.</h1>\n"
+ "<h1>This is a SOCKS proxy, not an HTTP proxy.</h1>\n"
"<p>\n"
"It appears you have configured your web browser to use this Tor port as\n"
"an HTTP proxy.\n"
- "</p><p>\n"
+ "</p>\n"
+ "<p>\n"
"This is not correct: This port is configured as a SOCKS proxy, not\n"
"an HTTP proxy. If you need an HTTP proxy tunnel, use the HTTPTunnelPort\n"
"configuration option in place of, or in addition to, SOCKSPort.\n"
diff --git a/src/feature/client/bridges.c b/src/feature/client/bridges.c
index a0375828a7..f4f7ac23a3 100644
--- a/src/feature/client/bridges.c
+++ b/src/feature/client/bridges.c
@@ -316,7 +316,8 @@ addr_is_a_configured_bridge(const tor_addr_t *addr,
/** If we have a bridge configured whose digest matches
* <b>ei->identity_digest</b>, or a bridge with no known digest whose address
* matches <b>ei->addr</b>:<b>ei->port</b>, return 1. Else return 0.
- * If <b>ei->onion_key</b> is NULL, check for address/port matches only.
+ * If <b>ei</b> has no onion key configured, check for address/port matches
+ * only.
*
* Note that if the extend_info_t contains multiple addresses, we return true
* only if _every_ address is a bridge.
@@ -324,7 +325,8 @@ addr_is_a_configured_bridge(const tor_addr_t *addr,
int
extend_info_is_a_configured_bridge(const extend_info_t *ei)
{
- const char *digest = ei->onion_key ? ei->identity_digest : NULL;
+ const char *digest = curve25519_public_key_is_ok(&ei->curve25519_onion_key)
+ ? ei->identity_digest : NULL;
const tor_addr_port_t *ap1 = NULL, *ap2 = NULL;
if (! tor_addr_is_null(&ei->orports[0].addr))
ap1 = &ei->orports[0];
diff --git a/src/feature/client/dnsserv.c b/src/feature/client/dnsserv.c
index f0bb0af100..237a6ee3d3 100644
--- a/src/feature/client/dnsserv.c
+++ b/src/feature/client/dnsserv.c
@@ -319,6 +319,7 @@ evdns_get_orig_address(const struct evdns_server_request *req,
break;
case RESOLVED_TYPE_ERROR:
case RESOLVED_TYPE_ERROR_TRANSIENT:
+ case RESOLVED_TYPE_NOERROR:
/* Addr doesn't matter, since we're not sending it back in the reply.*/
return addr;
default:
@@ -379,6 +380,8 @@ dnsserv_resolved(entry_connection_t *conn,
tor_free(ans);
} else if (answer_type == RESOLVED_TYPE_ERROR) {
err = DNS_ERR_NOTEXIST;
+ } else if (answer_type == RESOLVED_TYPE_NOERROR) {
+ err = DNS_ERR_NONE;
} else { /* answer_type == RESOLVED_TYPE_ERROR_TRANSIENT */
err = DNS_ERR_SERVERFAILED;
}
diff --git a/src/feature/client/entrynodes.c b/src/feature/client/entrynodes.c
index 7c469ea84a..dee41fefa8 100644
--- a/src/feature/client/entrynodes.c
+++ b/src/feature/client/entrynodes.c
@@ -2169,7 +2169,7 @@ select_primary_guard_for_circuit(guard_selection_t *gs,
static ratelim_t guardlog = RATELIM_INIT(60);
log_fn_ratelim(&guardlog, LOG_NOTICE, LD_GUARD,
"All current guards excluded by path restriction "
- "type %d; using an additonal guard.",
+ "type %d; using an additional guard.",
rst->type);
} else {
break;
diff --git a/src/feature/dirauth/dirauth_config.c b/src/feature/dirauth/dirauth_config.c
index f98513ef75..9378b0ffe6 100644
--- a/src/feature/dirauth/dirauth_config.c
+++ b/src/feature/dirauth/dirauth_config.c
@@ -16,9 +16,12 @@
#include "lib/encoding/confline.h"
#include "lib/confmgt/confmgt.h"
#include "lib/conf/confdecl.h"
+#include "lib/version/torversion.h"
/* Required for dirinfo_type_t in or_options_t */
#include "core/or/or.h"
+#include "core/or/tor_version_st.h"
+#include "core/or/versions.h"
#include "app/config/config.h"
#include "app/config/resolve_addr.h"
@@ -426,6 +429,7 @@ static int
dirauth_options_validate(const void *arg, char **msg)
{
const dirauth_options_t *options = arg;
+ tor_version_t minimal_accepted_server_version, recommended_version;
if (options->VersioningAuthoritativeDirectory &&
(!options->RecommendedClientVersions ||
@@ -439,12 +443,53 @@ dirauth_options_validate(const void *arg, char **msg)
REJECT("Guard bandwdith threshold fraction is invalid.");
}
- char *t;
+ if (tor_version_parse(options->MinimalAcceptedServerVersion,
+ &minimal_accepted_server_version) != 0) {
+ REJECT("Invalid MinimalAcceptedServerVersion");
+ }
+
+ tor_assertf(tor_version_parse(get_short_version(),
+ &recommended_version) == 0,
+ "We failed to parse our own version");
+ if (tor_version_compare(&recommended_version,
+ &minimal_accepted_server_version) < 0) {
+ REJECT("MinimalAcceptedServerVersion wants to reject the version "
+ "this node is running");
+ }
+
+ char *recommended_versions;
+ int found_recommended_rejected_version = 0;
/* Call these functions to produce warnings only. */
- t = format_recommended_version_list(options->RecommendedClientVersions, 1);
- tor_free(t);
- t = format_recommended_version_list(options->RecommendedServerVersions, 1);
- tor_free(t);
+ recommended_versions = format_recommended_version_list(
+ options->RecommendedClientVersions, 1);
+ tor_free(recommended_versions);
+
+ recommended_versions = format_recommended_version_list(
+ options->RecommendedServerVersions, 1);
+
+ smartlist_t *version_sl = smartlist_new();
+ smartlist_split_string(version_sl, recommended_versions, ",",
+ SPLIT_SKIP_SPACE, 0);
+ SMARTLIST_FOREACH_BEGIN(version_sl, const char *, version) {
+ if (version[0] != '\0' && tor_version_parse(version,
+ &recommended_version) != 0) {
+ COMPLAIN("Found unparseable version in RecommendedServerVersions");
+ continue;
+ }
+
+ if (tor_version_compare(&recommended_version,
+ &minimal_accepted_server_version) < 0) {
+ found_recommended_rejected_version = 1;
+ break;
+ }
+ } SMARTLIST_FOREACH_END(version);
+
+ SMARTLIST_FOREACH(version_sl, char *, version, tor_free(version));
+ smartlist_free(version_sl);
+ tor_free(recommended_versions);
+ if (found_recommended_rejected_version)
+ REJECT("MinimalAcceptedServerVersion wants to reject a recommended "
+ "version");
if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) {
COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high.");
diff --git a/src/feature/dirauth/dirauth_options.inc b/src/feature/dirauth/dirauth_options.inc
index e2056c9cc7..c6f9c09213 100644
--- a/src/feature/dirauth/dirauth_options.inc
+++ b/src/feature/dirauth/dirauth_options.inc
@@ -76,6 +76,9 @@ CONF_VAR(RecommendedClientVersions, LINELIST, 0, NULL)
/** Which versions of tor should we tell users to run on relays? */
CONF_VAR(RecommendedServerVersions, LINELIST, 0, NULL)
+/** Which minimal version of tor do we accept relay descriptors from? */
+CONF_VAR(MinimalAcceptedServerVersion, STRING, 0, "0.4.8.0-alpha-dev")
+
/** Relays which should be voted Guard regardless of uptime and bandwidth. */
CONF_VAR(AuthDirVoteGuard, ROUTERSET, 0, NULL)
diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c
index 0783fb1e91..42c0802433 100644
--- a/src/feature/dirauth/dirvote.c
+++ b/src/feature/dirauth/dirvote.c
@@ -1631,7 +1631,11 @@ networkstatus_compute_consensus(smartlist_t *votes,
n_versioning_servers);
client_versions = compute_consensus_versions_list(combined_client_versions,
n_versioning_clients);
- packages = compute_consensus_package_lines(votes);
+
+ if (consensus_method < MIN_METHOD_TO_OMIT_PACKAGE_FINGERPRINTS)
+ packages = tor_strdup("");
+ else
+ packages = compute_consensus_package_lines(votes);
SMARTLIST_FOREACH(combined_server_versions, char *, cp, tor_free(cp));
SMARTLIST_FOREACH(combined_client_versions, char *, cp, tor_free(cp));
@@ -1776,15 +1780,10 @@ networkstatus_compute_consensus(smartlist_t *votes,
}
{
- if (consensus_method < MIN_METHOD_FOR_CORRECT_BWWEIGHTSCALE) {
- max_unmeasured_bw_kb = (int32_t) extract_param_buggy(
- params, "maxunmeasuredbw", DEFAULT_MAX_UNMEASURED_BW_KB);
- } else {
- max_unmeasured_bw_kb = dirvote_get_intermediate_param_value(
- param_list, "maxunmeasuredbw", DEFAULT_MAX_UNMEASURED_BW_KB);
- if (max_unmeasured_bw_kb < 1)
- max_unmeasured_bw_kb = 1;
- }
+ max_unmeasured_bw_kb = dirvote_get_intermediate_param_value(
+ param_list, "maxunmeasuredbw", DEFAULT_MAX_UNMEASURED_BW_KB);
+ if (max_unmeasured_bw_kb < 1)
+ max_unmeasured_bw_kb = 1;
}
/* Add the actual router entries. */
@@ -2130,7 +2129,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
/* Starting with consensus method 32, we handle the middle-only
* flag specially: when it is present, we clear some flags, and
* set others. */
- if (is_middle_only && consensus_method >= MIN_METHOD_FOR_MIDDLEONLY) {
+ if (is_middle_only) {
remove_flag(chosen_flags, "Exit");
remove_flag(chosen_flags, "V2Dir");
remove_flag(chosen_flags, "Guard");
@@ -2367,15 +2366,10 @@ networkstatus_compute_consensus(smartlist_t *votes,
{
int64_t weight_scale;
- if (consensus_method < MIN_METHOD_FOR_CORRECT_BWWEIGHTSCALE) {
- weight_scale = extract_param_buggy(params, "bwweightscale",
- BW_WEIGHT_SCALE);
- } else {
- weight_scale = dirvote_get_intermediate_param_value(
- param_list, "bwweightscale", BW_WEIGHT_SCALE);
- if (weight_scale < 1)
- weight_scale = 1;
- }
+ weight_scale = dirvote_get_intermediate_param_value(
+ param_list, "bwweightscale", BW_WEIGHT_SCALE);
+ if (weight_scale < 1)
+ weight_scale = 1;
added_weights = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D,
T, weight_scale);
}
@@ -2477,53 +2471,6 @@ networkstatus_compute_consensus(smartlist_t *votes,
return result;
}
-/** Extract the value of a parameter from a string encoding a list of
- * parameters, badly.
- *
- * This is a deliberately buggy implementation, for backward compatibility
- * with versions of Tor affected by #19011. Once all authorities have
- * upgraded to consensus method 31 or later, then we can throw away this
- * function. */
-STATIC int64_t
-extract_param_buggy(const char *params,
- const char *param_name,
- int64_t default_value)
-{
- int64_t value = default_value;
- const char *param_str = NULL;
-
- if (params) {
- char *prefix1 = NULL, *prefix2=NULL;
- tor_asprintf(&prefix1, "%s=", param_name);
- tor_asprintf(&prefix2, " %s=", param_name);
- if (strcmpstart(params, prefix1) == 0)
- param_str = params;
- else
- param_str = strstr(params, prefix2);
- tor_free(prefix1);
- tor_free(prefix2);
- }
-
- if (param_str) {
- int ok=0;
- char *eq = strchr(param_str, '=');
- if (eq) {
- value = tor_parse_long(eq+1, 10, 1, INT32_MAX, &ok, NULL);
- if (!ok) {
- log_warn(LD_DIR, "Bad element '%s' in %s",
- escaped(param_str), param_name);
- value = default_value;
- }
- } else {
- log_warn(LD_DIR, "Bad element '%s' in %s",
- escaped(param_str), param_name);
- value = default_value;
- }
- }
-
- return value;
-}
-
/** Given a list of networkstatus_t for each vote, return a newly allocated
* string containing the "package" lines for the vote. */
STATIC char *
@@ -3919,13 +3866,18 @@ dirvote_get_vote(const char *fp, int flags)
STATIC microdesc_t *
dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method)
{
+ (void) consensus_method; // Currently unneeded...
microdesc_t *result = NULL;
char *key = NULL, *summary = NULL, *family = NULL;
size_t keylen;
smartlist_t *chunks = smartlist_new();
char *output = NULL;
- crypto_pk_t *rsa_pubkey = router_get_rsa_onion_pkey(ri->onion_pkey,
- ri->onion_pkey_len);
+ crypto_pk_t *rsa_pubkey = router_get_rsa_onion_pkey(ri->tap_onion_pkey,
+ ri->tap_onion_pkey_len);
+ if (!rsa_pubkey) {
+ /* We do not yet support creating MDs for relays without TAP onion keys. */
+ goto done;
+ }
if (crypto_pk_write_public_key_to_string(rsa_pubkey, &key, &keylen)<0)
goto done;
@@ -3937,20 +3889,15 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method)
if (ri->onion_curve25519_pkey) {
char kbuf[CURVE25519_BASE64_PADDED_LEN + 1];
- bool add_padding = (consensus_method < MIN_METHOD_FOR_UNPADDED_NTOR_KEY);
- curve25519_public_to_base64(kbuf, ri->onion_curve25519_pkey, add_padding);
+ curve25519_public_to_base64(kbuf, ri->onion_curve25519_pkey, false);
smartlist_add_asprintf(chunks, "ntor-onion-key %s\n", kbuf);
}
if (family) {
- if (consensus_method < MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS) {
- smartlist_add_asprintf(chunks, "family %s\n", family);
- } else {
- const uint8_t *id = (const uint8_t *)ri->cache_info.identity_digest;
- char *canonical_family = nodefamily_canonicalize(family, id, 0);
- smartlist_add_asprintf(chunks, "family %s\n", canonical_family);
- tor_free(canonical_family);
- }
+ const uint8_t *id = (const uint8_t *)ri->cache_info.identity_digest;
+ char *canonical_family = nodefamily_canonicalize(family, id, 0);
+ smartlist_add_asprintf(chunks, "family %s\n", canonical_family);
+ tor_free(canonical_family);
}
if (summary && strcmp(summary, "reject 1-65535"))
@@ -4048,10 +3995,6 @@ static const struct consensus_method_range_t {
int high;
} microdesc_consensus_methods[] = {
{MIN_SUPPORTED_CONSENSUS_METHOD,
- MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS - 1},
- {MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS,
- MIN_METHOD_FOR_UNPADDED_NTOR_KEY - 1},
- {MIN_METHOD_FOR_UNPADDED_NTOR_KEY,
MAX_SUPPORTED_CONSENSUS_METHOD},
{-1, -1}
};
diff --git a/src/feature/dirauth/dirvote.h b/src/feature/dirauth/dirvote.h
index ae8d43a6f0..6ac07f171a 100644
--- a/src/feature/dirauth/dirvote.h
+++ b/src/feature/dirauth/dirvote.h
@@ -50,29 +50,10 @@
((MIN_VOTE_SECONDS_TESTING)+(MIN_DIST_SECONDS_TESTING)+1)
/** The lowest consensus method that we currently support. */
-#define MIN_SUPPORTED_CONSENSUS_METHOD 28
+#define MIN_SUPPORTED_CONSENSUS_METHOD 32
/** The highest consensus method that we currently support. */
-#define MAX_SUPPORTED_CONSENSUS_METHOD 33
-
-/**
- * Lowest consensus method where microdescriptor lines are put in canonical
- * form for improved compressibility and ease of storage. See proposal 298.
- **/
-#define MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS 29
-
-/** Lowest consensus method where an unpadded base64 onion-key-ntor is allowed
- * See #7869 */
-#define MIN_METHOD_FOR_UNPADDED_NTOR_KEY 30
-
-/** Lowest consensus method for which we use the correct algorithm for
- * extracting the bwweightscale= and maxunmeasuredbw= parameters. See #19011.
- */
-#define MIN_METHOD_FOR_CORRECT_BWWEIGHTSCALE 31
-
-/** Lowest consensus method for which we handle the MiddleOnly flag specially.
- */
-#define MIN_METHOD_FOR_MIDDLEONLY 32
+#define MAX_SUPPORTED_CONSENSUS_METHOD 34
/**
* Lowest consensus method for which we suppress the published time in
@@ -80,6 +61,12 @@
*/
#define MIN_METHOD_TO_SUPPRESS_MD_PUBLISHED 33
+/**
+ * Lowest (supported) consensus method for which we do not include
+ * any "package" lines.
+ **/
+#define MIN_METHOD_TO_OMIT_PACKAGE_FINGERPRINTS 34
+
/** Default bandwidth to clip unmeasured bandwidths to using method >=
* MIN_METHOD_TO_CLIP_UNMEASURED_BW. (This is not a consensus method; do not
* get confused with the above macros.) */
@@ -274,9 +261,6 @@ STATIC
char *networkstatus_get_detached_signatures(smartlist_t *consensuses);
STATIC microdesc_t *dirvote_create_microdescriptor(const routerinfo_t *ri,
int consensus_method);
-STATIC int64_t extract_param_buggy(const char *params,
- const char *param_name,
- int64_t default_value);
#endif /* defined(DIRVOTE_PRIVATE) */
diff --git a/src/feature/dirauth/process_descs.c b/src/feature/dirauth/process_descs.c
index fafb781330..5b76e937ab 100644
--- a/src/feature/dirauth/process_descs.c
+++ b/src/feature/dirauth/process_descs.c
@@ -404,8 +404,8 @@ dirserv_rejects_tor_version(const char *platform,
static const char please_upgrade_string[] =
"Tor version is insecure or unsupported. Please upgrade!";
- /* Anything before 0.4.8.0 is unsupported. Reject them. */
- if (!tor_version_as_new_as(platform,"0.4.8.0-alpha-dev")) {
+ if (!tor_version_as_new_as(platform,
+ dirauth_get_options()->MinimalAcceptedServerVersion)) {
if (msg) {
*msg = please_upgrade_string;
}
@@ -762,6 +762,16 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
log_info(LD_DIR, "Assessing new descriptor: %s: %s",
ri->nickname, ri->platform);
+ /* For now, TAP keys are still required. */
+ if (! ri->tap_onion_pkey) {
+ log_info(LD_DIRSERV, "Rejecting descriptor from %s (source: %s); "
+ "it has no TAP key.",
+ router_describe(ri), source);
+ *msg = "Missing TAP key in descriptor.";
+ r = ROUTER_AUTHDIR_REJECTS;
+ goto fail;
+ }
+
/* Check whether this descriptor is semantically identical to the last one
* from this server. (We do this here and not in router_add_to_routerlist
* because we want to be able to accept the newest router descriptor that
diff --git a/src/feature/dirauth/voteflags.c b/src/feature/dirauth/voteflags.c
index 71ee03e265..2fbac47b30 100644
--- a/src/feature/dirauth/voteflags.c
+++ b/src/feature/dirauth/voteflags.c
@@ -112,8 +112,7 @@ dirserv_thinks_router_is_unreliable(time_t now,
}
/** Return 1 if <b>ri</b>'s descriptor is "active" -- running, valid,
- * not hibernating, having observed bw greater 0, and not too old. Else
- * return 0.
+ * not hibernating, and not too old. Else return 0.
*/
static int
router_is_active(const routerinfo_t *ri, const node_t *node, time_t now)
@@ -125,20 +124,6 @@ router_is_active(const routerinfo_t *ri, const node_t *node, time_t now)
if (!node->is_running || !node->is_valid || ri->is_hibernating) {
return 0;
}
- /* Only require bandwidth capacity in non-test networks, or
- * if TestingTorNetwork, and TestingMinExitFlagThreshold is non-zero */
- if (!ri->bandwidthcapacity) {
- if (get_options()->TestingTorNetwork) {
- if (dirauth_get_options()->TestingMinExitFlagThreshold > 0) {
- /* If we're in a TestingTorNetwork, and TestingMinExitFlagThreshold is,
- * then require bandwidthcapacity */
- return 0;
- }
- } else {
- /* If we're not in a TestingTorNetwork, then require bandwidthcapacity */
- return 0;
- }
- }
return 1;
}
diff --git a/src/feature/dirparse/microdesc_parse.c b/src/feature/dirparse/microdesc_parse.c
index beb38bda30..eef52f14f3 100644
--- a/src/feature/dirparse/microdesc_parse.c
+++ b/src/feature/dirparse/microdesc_parse.c
@@ -30,7 +30,7 @@
/** List of tokens recognized in microdescriptors */
// clang-format off
static token_rule_t microdesc_token_table[] = {
- T1_START("onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024),
+ T1_START("onion-key", K_ONION_KEY, NO_ARGS, OPT_KEY_1024),
T1("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ),
T0N("id", K_ID, GE(2), NO_OBJ ),
T0N("a", K_A, GE(1), NO_OBJ ),
@@ -200,14 +200,11 @@ microdesc_parse_fields(microdesc_t *md,
}
tok = find_by_keyword(tokens, K_ONION_KEY);
- if (!crypto_pk_public_exponent_ok(tok->key)) {
+ if (tok && tok->key && !crypto_pk_public_exponent_ok(tok->key)) {
log_warn(LD_DIR,
"Relay's onion key had invalid exponent.");
goto err;
}
- md->onion_pkey = tor_memdup(tok->object_body, tok->object_size);
- md->onion_pkey_len = tok->object_size;
- crypto_pk_free(tok->key);
if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) {
curve25519_public_key_t k;
diff --git a/src/feature/dirparse/parsecommon.c b/src/feature/dirparse/parsecommon.c
index d7a6d65346..be1457b730 100644
--- a/src/feature/dirparse/parsecommon.c
+++ b/src/feature/dirparse/parsecommon.c
@@ -215,6 +215,16 @@ token_check_object(memarea_t *area, const char *kwd,
RET_ERR(ebuf);
}
break;
+ case OPT_KEY_1024:
+ /* If there is anything, it must be a 1024-bit RSA key. */
+ if (tok->object_body && !tok->key) {
+ tor_snprintf(ebuf, sizeof(ebuf), "Unexpected object for %s", kwd);
+ RET_ERR(ebuf);
+ }
+ if (!tok->key) {
+ break;
+ }
+ FALLTHROUGH;
case NEED_KEY_1024: /* There must be a 1024-bit public key. */
if (tok->key && crypto_pk_num_bits(tok->key) != PK_BYTES*8) {
tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits",
@@ -395,7 +405,8 @@ get_next_token(memarea_t *area,
}
if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) { /* If it's a public key */
- if (o_syn != NEED_KEY && o_syn != NEED_KEY_1024 && o_syn != OBJ_OK) {
+ if (o_syn != OPT_KEY_1024 && o_syn != NEED_KEY &&
+ o_syn != NEED_KEY_1024 && o_syn != OBJ_OK) {
RET_ERR("Unexpected public key.");
}
tok->key = crypto_pk_asn1_decode(tok->object_body, tok->object_size);
diff --git a/src/feature/dirparse/parsecommon.h b/src/feature/dirparse/parsecommon.h
index 9333ec4b27..d48d27499f 100644
--- a/src/feature/dirparse/parsecommon.h
+++ b/src/feature/dirparse/parsecommon.h
@@ -220,6 +220,7 @@ typedef struct directory_token_t {
typedef enum {
NO_OBJ, /**< No object, ever. */
NEED_OBJ, /**< Object is required. */
+ OPT_KEY_1024, /**< If object is present, it must be a 1024 bit public key */
NEED_KEY_1024, /**< Object is required, and must be a 1024 bit public key */
NEED_KEY, /**< Object is required, and must be a public key. */
OBJ_OK, /**< Object is optional. */
diff --git a/src/feature/dirparse/routerparse.c b/src/feature/dirparse/routerparse.c
index 844057c47e..6289b4c018 100644
--- a/src/feature/dirparse/routerparse.c
+++ b/src/feature/dirparse/routerparse.c
@@ -90,7 +90,7 @@ const token_rule_t routerdesc_token_table[] = {
T1_START( "router", K_ROUTER, GE(5), NO_OBJ ),
T01("ipv6-policy", K_IPV6_POLICY, CONCAT_ARGS, NO_OBJ),
T1( "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
- T1( "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ),
+ T01("onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ),
T1("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ),
T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
@@ -107,7 +107,7 @@ const token_rule_t routerdesc_token_table[] = {
T1("identity-ed25519", K_IDENTITY_ED25519, NO_ARGS, NEED_OBJ ),
T1("master-key-ed25519", K_MASTER_KEY_ED25519, GE(1), NO_OBJ ),
T1("router-sig-ed25519", K_ROUTER_SIG_ED25519, GE(1), NO_OBJ ),
- T1("onion-key-crosscert", K_ONION_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),
+ T01("onion-key-crosscert", K_ONION_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),
T1("ntor-onion-key-crosscert", K_NTOR_ONION_KEY_CROSSCERT,
EQ(1), NEED_OBJ ),
@@ -595,15 +595,17 @@ router_parse_entry_from_string(const char *s, const char *end,
if (parse_iso_time(tok->args[0], &router->cache_info.published_on) < 0)
goto err;
- tok = find_by_keyword(tokens, K_ONION_KEY);
- if (!crypto_pk_public_exponent_ok(tok->key)) {
- log_warn(LD_DIR,
- "Relay's onion key had invalid exponent.");
- goto err;
+ tok = find_opt_by_keyword(tokens, K_ONION_KEY);
+ if (tok) {
+ if (!crypto_pk_public_exponent_ok(tok->key)) {
+ log_warn(LD_DIR,
+ "Relay's onion key had invalid exponent.");
+ goto err;
+ }
+ router->tap_onion_pkey = tor_memdup(tok->object_body, tok->object_size);
+ router->tap_onion_pkey_len = tok->object_size;
+ crypto_pk_free(tok->key);
}
- router->onion_pkey = tor_memdup(tok->object_body, tok->object_size);
- router->onion_pkey_len = tok->object_size;
- crypto_pk_free(tok->key);
if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) {
curve25519_public_key_t k;
@@ -627,26 +629,68 @@ router_parse_entry_from_string(const char *s, const char *end,
{
directory_token_t *ed_sig_tok, *ed_cert_tok, *cc_tap_tok, *cc_ntor_tok,
*master_key_tok;
- ed_sig_tok = find_opt_by_keyword(tokens, K_ROUTER_SIG_ED25519);
- ed_cert_tok = find_opt_by_keyword(tokens, K_IDENTITY_ED25519);
- master_key_tok = find_opt_by_keyword(tokens, K_MASTER_KEY_ED25519);
+ ed_sig_tok = find_by_keyword(tokens, K_ROUTER_SIG_ED25519);
+ ed_cert_tok = find_by_keyword(tokens, K_IDENTITY_ED25519);
+ master_key_tok = find_by_keyword(tokens, K_MASTER_KEY_ED25519);
+ cc_ntor_tok = find_by_keyword(tokens, K_NTOR_ONION_KEY_CROSSCERT);
+ /* This, and only this, is optional. */
cc_tap_tok = find_opt_by_keyword(tokens, K_ONION_KEY_CROSSCERT);
- cc_ntor_tok = find_opt_by_keyword(tokens, K_NTOR_ONION_KEY_CROSSCERT);
- int n_ed_toks = !!ed_sig_tok + !!ed_cert_tok +
- !!cc_tap_tok + !!cc_ntor_tok;
- if ((n_ed_toks != 0 && n_ed_toks != 4) ||
- (n_ed_toks == 4 && !router->onion_curve25519_pkey)) {
- log_warn(LD_DIR, "Router descriptor with only partial ed25519/"
- "cross-certification support");
+
+ if (bool_neq(cc_tap_tok==NULL, router->tap_onion_pkey==NULL)) {
+ log_warn(LD_DIR, "Router descriptor had only one of (onion-key, "
+ "onion-key-crosscert).");
goto err;
}
- if (master_key_tok && !ed_sig_tok) {
- log_warn(LD_DIR, "Router descriptor has ed25519 master key but no "
- "certificate");
+
+ IF_BUG_ONCE(! (ed_sig_tok && ed_cert_tok&& cc_ntor_tok &&master_key_tok)) {
goto err;
}
- if (ed_sig_tok) {
- tor_assert(ed_cert_tok && cc_tap_tok && cc_ntor_tok);
+
+ tor_cert_t *cert;
+ {
+ /* Parse the identity certificate */
+ cert = tor_cert_parse(
+ (const uint8_t*)ed_cert_tok->object_body,
+ ed_cert_tok->object_size);
+ if (! cert) {
+ log_warn(LD_DIR, "Couldn't parse ed25519 cert");
+ goto err;
+ }
+ /* makes sure it gets freed. */
+ router->cache_info.signing_key_cert = cert;
+
+ if (cert->cert_type != CERT_TYPE_ID_SIGNING ||
+ ! cert->signing_key_included) {
+ log_warn(LD_DIR, "Invalid form for ed25519 cert");
+ goto err;
+ }
+ }
+
+ if (cc_tap_tok) {
+ rsa_pubkey = router_get_rsa_onion_pkey(router->tap_onion_pkey,
+ router->tap_onion_pkey_len);
+ if (rsa_pubkey == NULL) {
+ log_warn(LD_DIR, "No pubkey for TAP cross-verification.");
+ goto err;
+ }
+ if (strcmp(cc_tap_tok->object_type, "CROSSCERT")) {
+ log_warn(LD_DIR, "Wrong object type on onion-key-crosscert "
+ "in descriptor");
+ goto err;
+ }
+ if (check_tap_onion_key_crosscert(
+ (const uint8_t*)cc_tap_tok->object_body,
+ (int)cc_tap_tok->object_size,
+ rsa_pubkey,
+ &cert->signing_key,
+ (const uint8_t*)router->cache_info.identity_digest)<0) {
+ log_warn(LD_DIR, "Incorrect TAP cross-verification");
+ goto err;
+ }
+ }
+
+ {
+ tor_assert(ed_sig_tok && ed_cert_tok && cc_ntor_tok);
const int ed_cert_token_pos = smartlist_pos(tokens, ed_cert_tok);
if (ed_cert_token_pos == -1 || router_token_pos == -1 ||
(ed_cert_token_pos != router_token_pos + 1 &&
@@ -668,35 +712,14 @@ router_parse_entry_from_string(const char *s, const char *end,
"in descriptor");
goto err;
}
- if (strcmp(cc_tap_tok->object_type, "CROSSCERT")) {
- log_warn(LD_DIR, "Wrong object type on onion-key-crosscert "
- "in descriptor");
- goto err;
- }
if (strcmp(cc_ntor_tok->args[0], "0") &&
strcmp(cc_ntor_tok->args[0], "1")) {
log_warn(LD_DIR, "Bad sign bit on ntor-onion-key-crosscert");
goto err;
}
int ntor_cc_sign_bit = !strcmp(cc_ntor_tok->args[0], "1");
-
uint8_t d256[DIGEST256_LEN];
const char *signed_start, *signed_end;
- tor_cert_t *cert = tor_cert_parse(
- (const uint8_t*)ed_cert_tok->object_body,
- ed_cert_tok->object_size);
- if (! cert) {
- log_warn(LD_DIR, "Couldn't parse ed25519 cert");
- goto err;
- }
- /* makes sure it gets freed. */
- router->cache_info.signing_key_cert = cert;
-
- if (cert->cert_type != CERT_TYPE_ID_SIGNING ||
- ! cert->signing_key_included) {
- log_warn(LD_DIR, "Invalid form for ed25519 cert");
- goto err;
- }
if (master_key_tok) {
/* This token is optional, but if it's present, it must match
@@ -746,6 +769,7 @@ router_parse_entry_from_string(const char *s, const char *end,
crypto_digest_add_bytes(d, ED_DESC_SIGNATURE_PREFIX,
strlen(ED_DESC_SIGNATURE_PREFIX));
crypto_digest_add_bytes(d, signed_start, signed_end-signed_start);
+
crypto_digest_get_digest(d, (char*)d256, sizeof(d256));
crypto_digest_free(d);
@@ -776,18 +800,6 @@ router_parse_entry_from_string(const char *s, const char *end,
goto err;
}
- rsa_pubkey = router_get_rsa_onion_pkey(router->onion_pkey,
- router->onion_pkey_len);
- if (check_tap_onion_key_crosscert(
- (const uint8_t*)cc_tap_tok->object_body,
- (int)cc_tap_tok->object_size,
- rsa_pubkey,
- &cert->signing_key,
- (const uint8_t*)router->cache_info.identity_digest)<0) {
- log_warn(LD_DIR, "Incorrect TAP cross-verification");
- goto err;
- }
-
/* We check this before adding it to the routerlist. */
router->cert_expiration_time = expires;
}
diff --git a/src/feature/hs/hs_common.c b/src/feature/hs/hs_common.c
index cd7e4890d1..e16ec89ccb 100644
--- a/src/feature/hs/hs_common.c
+++ b/src/feature/hs/hs_common.c
@@ -1686,7 +1686,7 @@ hs_get_extend_info_from_lspecs(const smartlist_t *lspecs,
/* We do have everything for which we think we can connect successfully. */
info = extend_info_new(NULL, legacy_id,
- (have_ed25519_id) ? &ed25519_pk : NULL, NULL,
+ (have_ed25519_id) ? &ed25519_pk : NULL,
onion_key, &ap.addr, ap.port, NULL, false);
done:
return info;
diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c
index 3cc8c23e0b..3fb0220cc0 100644
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -410,11 +410,6 @@ get_intro_point_max_introduce2(void)
static int32_t
get_intro_point_min_lifetime(void)
{
-#define MIN_INTRO_POINT_LIFETIME_TESTING 10
- if (get_options()->TestingTorNetwork) {
- return MIN_INTRO_POINT_LIFETIME_TESTING;
- }
-
/* The [0, 2147483647] range is quite large to accommodate anything we decide
* in the future. */
return networkstatus_get_param(NULL, "hs_intro_min_lifetime",
@@ -427,11 +422,6 @@ get_intro_point_min_lifetime(void)
static int32_t
get_intro_point_max_lifetime(void)
{
-#define MAX_INTRO_POINT_LIFETIME_TESTING 30
- if (get_options()->TestingTorNetwork) {
- return MAX_INTRO_POINT_LIFETIME_TESTING;
- }
-
/* The [0, 2147483647] range is quite large to accommodate anything we decide
* in the future. */
return networkstatus_get_param(NULL, "hs_intro_max_lifetime",
@@ -2163,7 +2153,7 @@ build_all_descriptors(time_t now)
continue;
}
- /* Reaching this point means we are pass bootup so at runtime. We should
+ /* Reaching this point means we are past bootup so at runtime. We should
* *never* have an empty current descriptor. If the next descriptor is
* empty, we'll try to build it for the next time period. This only
* happens when we rotate meaning that we are guaranteed to have a new SRV
@@ -2185,7 +2175,7 @@ build_all_descriptors(time_t now)
/** Randomly pick a node to become an introduction point but not present in the
* given exclude_nodes list. The chosen node is put in the exclude list
* regardless of success or not because in case of failure, the node is simply
- * unsusable from that point on.
+ * unusable from that point on.
*
* If direct_conn is set, try to pick a node that our local firewall/policy
* allows us to connect to directly. If we can't find any, return NULL.
@@ -3039,13 +3029,6 @@ get_max_intro_circ_per_period(const hs_service_t *service)
tor_assert(service->config.num_intro_points <=
HS_CONFIG_V3_MAX_INTRO_POINTS);
-/** For a testing network, allow to do it for the maximum amount so circuit
- * creation and rotation and so on can actually be tested without limit. */
-#define MAX_INTRO_POINT_CIRCUIT_RETRIES_TESTING -1
- if (get_options()->TestingTorNetwork) {
- return MAX_INTRO_POINT_CIRCUIT_RETRIES_TESTING;
- }
-
num_wanted_ip = service->config.num_intro_points;
/* The calculation is as follow. We have a number of intro points that we
diff --git a/src/feature/hs/hs_service.h b/src/feature/hs/hs_service.h
index 36d67719ca..b3a4117461 100644
--- a/src/feature/hs/hs_service.h
+++ b/src/feature/hs/hs_service.h
@@ -113,7 +113,7 @@ typedef struct hs_service_intropoints_t {
digest256map_t *map;
/** Contains node's identity key digest that were introduction point for this
- * descriptor but were retried to many times. We keep those so we avoid
+ * descriptor but were retried too many times. We keep those so we avoid
* re-picking them over and over for a circuit retry period.
* XXX: Once we have #22173, change this to only use ed25519 identity. */
digestmap_t *failed_id;
diff --git a/src/feature/nodelist/microdesc.c b/src/feature/nodelist/microdesc.c
index 9e5f0bb9a4..3fd0f23fb5 100644
--- a/src/feature/nodelist/microdesc.c
+++ b/src/feature/nodelist/microdesc.c
@@ -909,8 +909,6 @@ microdesc_free_(microdesc_t *md, const char *fname, int lineno)
//tor_assert(md->held_in_map == 0);
//tor_assert(md->held_by_nodes == 0);
- if (md->onion_pkey)
- tor_free(md->onion_pkey);
tor_free(md->onion_curve25519_pkey);
tor_free(md->ed25519_identity_pkey);
if (md->body && md->saved_location != SAVED_IN_CACHE)
diff --git a/src/feature/nodelist/microdesc_st.h b/src/feature/nodelist/microdesc_st.h
index ad56b6d6c2..c642e6e12b 100644
--- a/src/feature/nodelist/microdesc_st.h
+++ b/src/feature/nodelist/microdesc_st.h
@@ -63,14 +63,6 @@ struct microdesc_t {
/* Fields in the microdescriptor. */
- /**
- * Public RSA TAP key for onions, ASN.1 encoded. We store this
- * in its encoded format since storing it as a crypto_pk_t uses
- * significantly more memory. */
- char *onion_pkey;
- /** Length of onion_pkey, in bytes. */
- size_t onion_pkey_len;
-
/** As routerinfo_t.onion_curve25519_pkey */
struct curve25519_public_key_t *onion_curve25519_pkey;
/** Ed25519 identity key, if included. */
diff --git a/src/feature/nodelist/nodelist.c b/src/feature/nodelist/nodelist.c
index bbaa51a407..735361d417 100644
--- a/src/feature/nodelist/nodelist.c
+++ b/src/feature/nodelist/nodelist.c
@@ -2034,37 +2034,6 @@ node_get_curve25519_onion_key(const node_t *node)
return NULL;
}
-/* Return a newly allocacted RSA onion public key taken from the given node.
- *
- * Return NULL if node is NULL or no RSA onion public key can be found. It is
- * the caller responsibility to free the returned object. */
-crypto_pk_t *
-node_get_rsa_onion_key(const node_t *node)
-{
- crypto_pk_t *pk = NULL;
- const char *onion_pkey;
- size_t onion_pkey_len;
-
- if (!node) {
- goto end;
- }
-
- if (node->ri) {
- onion_pkey = node->ri->onion_pkey;
- onion_pkey_len = node->ri->onion_pkey_len;
- } else if (node->rs && node->md) {
- onion_pkey = node->md->onion_pkey;
- onion_pkey_len = node->md->onion_pkey_len;
- } else {
- /* No descriptor or microdescriptor. */
- goto end;
- }
- pk = router_get_rsa_onion_pkey(onion_pkey, onion_pkey_len);
-
- end:
- return pk;
-}
-
/** Refresh the country code of <b>ri</b>. This function MUST be called on
* each router when the GeoIP database is reloaded, and on all new routers. */
void
diff --git a/src/feature/nodelist/nodelist.h b/src/feature/nodelist/nodelist.h
index 3d5ad9c0ea..948a293f0c 100644
--- a/src/feature/nodelist/nodelist.h
+++ b/src/feature/nodelist/nodelist.h
@@ -109,7 +109,6 @@ void node_get_pref_ipv6_dirport(const node_t *node, tor_addr_port_t *ap_out);
int node_has_curve25519_onion_key(const node_t *node);
const struct curve25519_public_key_t *node_get_curve25519_onion_key(
const node_t *node);
-crypto_pk_t *node_get_rsa_onion_key(const node_t *node);
MOCK_DECL(const smartlist_t *, nodelist_get_list, (void));
diff --git a/src/feature/nodelist/routerinfo_st.h b/src/feature/nodelist/routerinfo_st.h
index 50134b2b96..a5c00c85c5 100644
--- a/src/feature/nodelist/routerinfo_st.h
+++ b/src/feature/nodelist/routerinfo_st.h
@@ -33,10 +33,13 @@ struct routerinfo_t {
/**
* Public RSA TAP key for onions, ASN.1 encoded. We store this
* in its encoded format since storing it as a crypto_pk_t uses
- * significantly more memory. */
- char *onion_pkey;
+ * significantly more memory.
+ *
+ * This may be absent.
+ */
+ char *tap_onion_pkey;
/** Length of onion_pkey, in bytes. */
- size_t onion_pkey_len;
+ size_t tap_onion_pkey_len;
crypto_pk_t *identity_pkey; /**< Public RSA key for signing. */
/** Public curve25519 key for onions */
diff --git a/src/feature/nodelist/routerlist.c b/src/feature/nodelist/routerlist.c
index 63de68dda7..7904f7d032 100644
--- a/src/feature/nodelist/routerlist.c
+++ b/src/feature/nodelist/routerlist.c
@@ -930,8 +930,8 @@ routerinfo_free_(routerinfo_t *router)
tor_free(router->platform);
tor_free(router->protocol_list);
tor_free(router->contact_info);
- if (router->onion_pkey)
- tor_free(router->onion_pkey);
+ if (router->tap_onion_pkey)
+ tor_free(router->tap_onion_pkey);
tor_free(router->onion_curve25519_pkey);
if (router->identity_pkey)
crypto_pk_free(router->identity_pkey);
@@ -2957,6 +2957,24 @@ router_reset_descriptor_download_failures(void)
/** We allow uptime to vary from how much it ought to be by this much. */
#define ROUTER_ALLOW_UPTIME_DRIFT (6*60*60)
+/** Return true iff r1 and r2 have the same TAP onion keys. */
+static int
+router_tap_onion_keys_eq(const routerinfo_t *r1, const routerinfo_t *r2)
+{
+ if (r1->tap_onion_pkey_len != r2->tap_onion_pkey_len)
+ return 0;
+
+ if ((r1->tap_onion_pkey == NULL) && (r2->tap_onion_pkey == NULL)) {
+ return 1;
+ } else if ((r1->tap_onion_pkey != NULL) && (r2->tap_onion_pkey != NULL)) {
+ return tor_memeq(r1->tap_onion_pkey, r2->tap_onion_pkey,
+ r1->tap_onion_pkey_len);
+ } else {
+ /* One is NULL; one is not. */
+ return 0;
+ }
+}
+
/** Return true iff the only differences between r1 and r2 are such that
* would not cause a recent (post 0.1.1.6) dirserver to republish.
*/
@@ -2982,8 +3000,7 @@ router_differences_are_cosmetic(const routerinfo_t *r1, const routerinfo_t *r2)
r1->ipv6_orport != r2->ipv6_orport ||
r1->ipv4_dirport != r2->ipv4_dirport ||
r1->purpose != r2->purpose ||
- r1->onion_pkey_len != r2->onion_pkey_len ||
- !tor_memeq(r1->onion_pkey, r2->onion_pkey, r1->onion_pkey_len) ||
+ !router_tap_onion_keys_eq(r1,r2) ||
!crypto_pk_eq_keys(r1->identity_pkey, r2->identity_pkey) ||
strcasecmp(r1->platform, r2->platform) ||
(r1->contact_info && !r2->contact_info) || /* contact_info is optional */
diff --git a/src/feature/relay/circuitbuild_relay.c b/src/feature/relay/circuitbuild_relay.c
index ce6cbe6df4..5ece5b4adc 100644
--- a/src/feature/relay/circuitbuild_relay.c
+++ b/src/feature/relay/circuitbuild_relay.c
@@ -389,7 +389,6 @@ circuit_open_connection_for_extend(const struct extend_cell_t *ec,
circ->n_hop = extend_info_new(NULL /*nickname*/,
(const char*)ec->node_id,
&ec->ed_pubkey,
- NULL, /*onion_key*/
NULL, /*curve25519_key*/
&chosen_ap->addr,
chosen_ap->port,
@@ -443,6 +442,12 @@ circuit_extend(struct cell_t *cell, struct circuit_t *circ)
relay_header_unpack(&rh, cell->payload);
+ /* We no longer accept EXTEND messages; only EXTEND2. */
+ if (rh.command == RELAY_COMMAND_EXTEND) {
+ /* TODO: Should we log this? */
+ return -1;
+ }
+
if (extend_cell_parse(&ec, rh.command,
cell->payload+RELAY_HEADER_SIZE,
rh.length) < 0) {
diff --git a/src/feature/relay/dns.c b/src/feature/relay/dns.c
index f6a020d061..eb31678189 100644
--- a/src/feature/relay/dns.c
+++ b/src/feature/relay/dns.c
@@ -563,6 +563,12 @@ send_resolved_cell,(edge_connection_t *conn, uint8_t answer_type,
connection_edge_send_command(conn, RELAY_COMMAND_RESOLVED, buf, buflen);
}
+void
+dns_send_resolved_error_cell(edge_connection_t *conn, uint8_t answer_type)
+{
+ send_resolved_cell(conn, answer_type, NULL);
+}
+
/** Send a response to the RESOLVE request of a connection for an in-addr.arpa
* address on connection <b>conn</b> which yielded the result <b>hostname</b>.
* The answer type will be RESOLVED_HOSTNAME.
@@ -1178,8 +1184,8 @@ dns_found_answer(const char *address, uint8_t query_type,
* resolution.
*
* Do this by sending a RELAY_RESOLVED cell (if the pending stream had sent us
- * RELAY_RESOLVE cell), or by launching an exit connection (if the pending
- * stream had send us a RELAY_BEGIN cell).
+ * a RELAY_RESOLVE cell), or by launching an exit connection (if the pending
+ * stream had sent us a RELAY_BEGIN cell).
*/
static void
inform_pending_connections(cached_resolve_t *resolve)
diff --git a/src/feature/relay/dns.h b/src/feature/relay/dns.h
index 3f8519bd97..5de70039d4 100644
--- a/src/feature/relay/dns.h
+++ b/src/feature/relay/dns.h
@@ -20,6 +20,8 @@ int dns_reset(void);
void connection_dns_remove(edge_connection_t *conn);
void assert_connection_edge_not_dns_pending(edge_connection_t *conn);
int dns_resolve(edge_connection_t *exitconn);
+void dns_send_resolved_error_cell(edge_connection_t *conn,
+ uint8_t answer_type);
int dns_seems_to_be_broken(void);
int dns_seems_to_be_broken_for_ipv6(void);
void dns_reset_correctness_checks(void);
@@ -36,6 +38,8 @@ void dns_launch_correctness_checks(void);
#else /* !defined(HAVE_MODULE_RELAY) */
#define dns_init() (0)
+#define dns_send_resolved_error_cell(conn, answer_type) \
+ ((void)(conn), (void)(answer_type))
#define dns_seems_to_be_broken() (0)
#define has_dns_init_failed() (0)
#define dns_cache_total_allocation() (0)
diff --git a/src/feature/relay/onion_queue.c b/src/feature/relay/onion_queue.c
index f3f4b169f4..9632b51063 100644
--- a/src/feature/relay/onion_queue.c
+++ b/src/feature/relay/onion_queue.c
@@ -50,10 +50,6 @@
#define ONION_QUEUE_MAX_DELAY_MIN 1
#define ONION_QUEUE_MAX_DELAY_MAX INT32_MAX
-#define NUM_NTORS_PER_TAP_DEFAULT 10
-#define NUM_NTORS_PER_TAP_MIN 1
-#define NUM_NTORS_PER_TAP_MAX 100000
-
/** Type for a linked list of circuits that are waiting for a free CPU worker
* to process a waiting onion handshake. */
typedef struct onion_queue_t {
@@ -84,17 +80,9 @@ static int ol_entries[MAX_QUEUE_IDX+1];
static void onion_queue_entry_remove(onion_queue_t *victim);
/** Consensus parameters. */
-static int32_t ns_num_ntors_per_tap = NUM_NTORS_PER_TAP_DEFAULT;
static time_t ns_onion_queue_wait_cutoff = ONION_QUEUE_WAIT_CUTOFF_DEFAULT;
static uint32_t ns_onion_queue_max_delay = ONION_QUEUE_MAX_DELAY_DEFAULT;
-/** Return the number of ntors per tap from the cached parameter. */
-static inline int32_t
-get_num_ntors_per_tap(void)
-{
- return ns_num_ntors_per_tap;
-}
-
/** Return the onion queue wait cutoff value from the cached parameter. */
static inline time_t
get_onion_queue_wait_cutoff(void)
@@ -146,8 +134,12 @@ have_room_for_onionskin(uint16_t type)
const or_options_t *options = get_options();
int num_cpus;
uint64_t max_onion_queue_delay;
- uint64_t tap_usec, ntor_usec;
- uint64_t ntor_during_tap_usec, tap_during_ntor_usec;
+ uint64_t ntor_usec;
+
+ /* We never allow TAP. */
+ if (type == ONION_HANDSHAKE_TYPE_TAP) {
+ return 0;
+ }
/* If we've got fewer than 50 entries, we always have room for one more. */
if (ol_entries[type] < 50)
@@ -164,44 +156,15 @@ have_room_for_onionskin(uint16_t type)
/* Compute how many microseconds we'd expect to need to clear all
* onionskins in various combinations of the queues. */
- /* How long would it take to process all the TAP cells in the queue? */
- tap_usec = estimated_usec_for_onionskins(
- ol_entries[ONION_HANDSHAKE_TYPE_TAP],
- ONION_HANDSHAKE_TYPE_TAP) / num_cpus;
-
/* How long would it take to process all the NTor cells in the queue? */
ntor_usec = estimated_usec_for_onionskins(
ol_entries[ONION_HANDSHAKE_TYPE_NTOR],
ONION_HANDSHAKE_TYPE_NTOR) / num_cpus;
- /* How long would it take to process the tap cells that we expect to
- * process while draining the ntor queue? */
- tap_during_ntor_usec = estimated_usec_for_onionskins(
- MIN(ol_entries[ONION_HANDSHAKE_TYPE_TAP],
- ol_entries[ONION_HANDSHAKE_TYPE_NTOR] / get_num_ntors_per_tap()),
- ONION_HANDSHAKE_TYPE_TAP) / num_cpus;
-
- /* How long would it take to process the ntor cells that we expect to
- * process while draining the tap queue? */
- ntor_during_tap_usec = estimated_usec_for_onionskins(
- MIN(ol_entries[ONION_HANDSHAKE_TYPE_NTOR],
- ol_entries[ONION_HANDSHAKE_TYPE_TAP] * get_num_ntors_per_tap()),
- ONION_HANDSHAKE_TYPE_NTOR) / num_cpus;
-
/* See whether that exceeds MaxOnionQueueDelay. If so, we can't queue
* this. */
if (type == ONION_HANDSHAKE_TYPE_NTOR &&
- (ntor_usec + tap_during_ntor_usec) / 1000 > max_onion_queue_delay)
- return 0;
-
- if (type == ONION_HANDSHAKE_TYPE_TAP &&
- (tap_usec + ntor_during_tap_usec) / 1000 > max_onion_queue_delay)
- return 0;
-
- /* If we support the ntor handshake, then don't let TAP handshakes use
- * more than 2/3 of the space on the queue. */
- if (type == ONION_HANDSHAKE_TYPE_TAP &&
- tap_usec / 1000 > max_onion_queue_delay * 2 / 3)
+ (ntor_usec / 1000) > max_onion_queue_delay)
return 0;
return 1;
@@ -292,38 +255,7 @@ onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin)
static uint16_t
decide_next_handshake_type(void)
{
- /* The number of times we've chosen ntor lately when both were available. */
- static int recently_chosen_ntors = 0;
-
- if (!ol_entries[ONION_HANDSHAKE_TYPE_NTOR])
- return ONION_HANDSHAKE_TYPE_TAP; /* no ntors? try tap */
-
- if (!ol_entries[ONION_HANDSHAKE_TYPE_TAP]) {
-
- /* Nick wants us to prioritize new tap requests when there aren't
- * any in the queue and we've processed k ntor cells since the last
- * tap cell. This strategy is maybe a good idea, since it starves tap
- * less in the case where tap is rare, or maybe a poor idea, since it
- * makes the new tap cell unfairly jump in front of ntor cells that
- * got here first. In any case this edge case will only become relevant
- * once tap is rare. We should reevaluate whether we like this decision
- * once tap gets more rare. */
- if (ol_entries[ONION_HANDSHAKE_TYPE_NTOR] &&
- recently_chosen_ntors <= get_num_ntors_per_tap())
- ++recently_chosen_ntors;
-
- return ONION_HANDSHAKE_TYPE_NTOR; /* no taps? try ntor */
- }
-
- /* They both have something queued. Pick ntor if we haven't done that
- * too much lately. */
- if (++recently_chosen_ntors <= get_num_ntors_per_tap()) {
- return ONION_HANDSHAKE_TYPE_NTOR;
- }
-
- /* Else, it's time to let tap have its turn. */
- recently_chosen_ntors = 0;
- return ONION_HANDSHAKE_TYPE_TAP;
+ return ONION_HANDSHAKE_TYPE_NTOR;
}
/** Remove the highest priority item from ol_list[] and return it, or
@@ -445,10 +377,4 @@ onion_consensus_has_changed(const networkstatus_t *ns)
ONION_QUEUE_WAIT_CUTOFF_DEFAULT,
ONION_QUEUE_WAIT_CUTOFF_MIN,
ONION_QUEUE_WAIT_CUTOFF_MAX);
-
- ns_num_ntors_per_tap =
- networkstatus_get_param(ns, "NumNTorsPerTAP",
- NUM_NTORS_PER_TAP_DEFAULT,
- NUM_NTORS_PER_TAP_MIN,
- NUM_NTORS_PER_TAP_MAX);
}
diff --git a/src/feature/relay/relay_config.c b/src/feature/relay/relay_config.c
index 0b02461318..320ce8d13a 100644
--- a/src/feature/relay/relay_config.c
+++ b/src/feature/relay/relay_config.c
@@ -1151,8 +1151,8 @@ options_validate_relay_mode(const or_options_t *old_options,
REJECT("BridgeRelay is 1, ORPort is not set. This is an invalid "
"combination.");
- if (options->BridgeRelay == 1 && (options->ExitRelay == 1 ||
- !policy_using_default_exit_options(options))) {
+ if (options->BridgeRelay == 1 && !(options->ExitRelay == 0 ||
+ policy_using_default_exit_options(options))) {
log_warn(LD_CONFIG, "BridgeRelay is 1, but ExitRelay is 1 or an "
"ExitPolicy is configured. Tor will start, but it will not "
"function as an exit relay.");
diff --git a/src/feature/relay/relay_metrics.c b/src/feature/relay/relay_metrics.c
index 8f3b82bd96..492a5945b8 100644
--- a/src/feature/relay/relay_metrics.c
+++ b/src/feature/relay/relay_metrics.c
@@ -13,6 +13,7 @@
#include "core/or/or.h"
#include "core/mainloop/connection.h"
#include "core/mainloop/mainloop.h"
+#include "core/or/command.h"
#include "core/or/congestion_control_common.h"
#include "core/or/congestion_control_vegas.h"
#include "core/or/congestion_control_flow.h"
@@ -54,6 +55,9 @@ static void fill_socket_values(void);
static void fill_onionskins_values(void);
static void fill_oom_values(void);
static void fill_streams_values(void);
+static void fill_relay_circ_proto_violation(void);
+static void fill_relay_destroy_cell(void);
+static void fill_relay_drop_cell(void);
static void fill_relay_flags(void);
static void fill_tcp_exhaustion_values(void);
static void fill_traffic_values(void);
@@ -217,6 +221,27 @@ static const relay_metrics_entry_t base_metrics[] =
.help = "Total number of REND1 cells we received",
.fill_fn = fill_rend1_cells,
},
+ {
+ .key = RELAY_METRICS_CIRC_DESTROY_CELL,
+ .type = METRICS_TYPE_COUNTER,
+ .name = METRICS_NAME(relay_destroy_cell_total),
+ .help = "Total number of DESTROY cell we received",
+ .fill_fn = fill_relay_destroy_cell,
+ },
+ {
+ .key = RELAY_METRICS_CIRC_PROTO_VIOLATION,
+ .type = METRICS_TYPE_COUNTER,
+ .name = METRICS_NAME(relay_circ_proto_violation_total),
+ .help = "Total number of circuit protocol violation",
+ .fill_fn = fill_relay_circ_proto_violation,
+ },
+ {
+ .key = RELAY_METRICS_CIRC_DROP_CELL,
+ .type = METRICS_TYPE_COUNTER,
+ .name = METRICS_NAME(relay_drop_cell_total),
+ .help = "Total number of DROP cell we received",
+ .fill_fn = fill_relay_drop_cell,
+ },
};
static const size_t num_base_metrics = ARRAY_LENGTH(base_metrics);
@@ -433,6 +458,12 @@ fill_dos_values(void)
metrics_store_entry_add_label(sentry,
metrics_format_label("type", "introduce2_rejected"));
metrics_store_entry_update(sentry, hs_dos_get_intro2_rejected_count());
+
+ sentry = metrics_store_add(the_store, rentry->type, rentry->name,
+ rentry->help, 0, NULL);
+ metrics_store_entry_add_label(sentry,
+ metrics_format_label("type", "stream_rejected"));
+ metrics_store_entry_update(sentry, dos_get_num_stream_rejected());
}
/** Fill function for the RELAY_METRICS_CC_COUNTERS metric. */
@@ -1200,6 +1231,46 @@ fill_rend1_cells(void)
}
}
+/** Fill the metrics store for the RELAY_METRICS_CIRC_DESTROY_CELL counter. */
+static void
+fill_relay_destroy_cell(void)
+{
+ metrics_store_entry_t *sentry;
+ const relay_metrics_entry_t *rentry =
+ &base_metrics[RELAY_METRICS_CIRC_DESTROY_CELL];
+
+ sentry = metrics_store_add(the_store, rentry->type, rentry->name,
+ rentry->help, 0, NULL);
+ metrics_store_entry_update(sentry,
+ (int64_t) stats_n_destroy_cells_processed);
+}
+
+/** Fill the metrics store for the RELAY_METRICS_CIRC_DROP_CELL counter. */
+static void
+fill_relay_drop_cell(void)
+{
+ metrics_store_entry_t *sentry;
+ const relay_metrics_entry_t *rentry =
+ &base_metrics[RELAY_METRICS_CIRC_DROP_CELL];
+
+ sentry = metrics_store_add(the_store, rentry->type, rentry->name,
+ rentry->help, 0, NULL);
+ metrics_store_entry_update(sentry, rep_hist_get_drop_cell_received_count());
+}
+
+/** Fill the metrics store for the RELAY_METRICS_CIRC_PROTO_VIOLATION. */
+static void
+fill_relay_circ_proto_violation(void)
+{
+ metrics_store_entry_t *sentry;
+ const relay_metrics_entry_t *rentry =
+ &base_metrics[RELAY_METRICS_CIRC_PROTO_VIOLATION];
+
+ sentry = metrics_store_add(the_store, rentry->type, rentry->name,
+ rentry->help, 0, NULL);
+ metrics_store_entry_update(sentry, circ_n_proto_violation);
+}
+
/** Reset the global store and fill it with all the metrics from base_metrics
* and their associated values.
*
diff --git a/src/feature/relay/relay_metrics.h b/src/feature/relay/relay_metrics.h
index cf9dddf955..e7b5b660fa 100644
--- a/src/feature/relay/relay_metrics.h
+++ b/src/feature/relay/relay_metrics.h
@@ -57,6 +57,12 @@ typedef enum {
RELAY_METRICS_NUM_INTRO1_CELLS,
/** Number of times we received a REND1 cell */
RELAY_METRICS_NUM_REND1_CELLS,
+ /** Number of circuit closed by receiving a DESTROY cell. */
+ RELAY_METRICS_CIRC_DESTROY_CELL,
+ /** Number of circuits closed due to protocol violation. */
+ RELAY_METRICS_CIRC_PROTO_VIOLATION,
+ /** Number of drop cell seen. */
+ RELAY_METRICS_CIRC_DROP_CELL,
} relay_metrics_key_t;
/** The metadata of a relay metric. */
diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c
index 1ed9630e09..ab5fe697bc 100644
--- a/src/feature/relay/router.c
+++ b/src/feature/relay/router.c
@@ -211,8 +211,13 @@ set_onion_key(crypto_pk_t *k)
mark_my_descriptor_dirty("set onion key");
}
-/** Return the current onion key. Requires that the onion key has been
- * loaded or generated. */
+/** Return the current TAP onion key. Requires that the onion key has been
+ * loaded or generated.
+ *
+ * Note that this key is no longer used for anything; we only keep it around
+ * because (as of June 2024) other Tor instances all expect to find it in
+ * our routerdescs.
+ **/
MOCK_IMPL(crypto_pk_t *,
get_onion_key,(void))
{
@@ -220,6 +225,25 @@ get_onion_key,(void))
return onionkey;
}
+/**
+ * Return true iff we should include our TAP onion key in our router
+ * descriptor.
+ */
+static int
+should_publish_tap_onion_key(void)
+{
+#define SHOULD_PUBLISH_TAP_MIN 0
+#define SHOULD_PUBLISH_TAP_MAX 1
+ /* Note that we err on the side of publishing. */
+#define SHOULD_PUBLISH_TAP_DFLT 1
+
+ return networkstatus_get_param(NULL,
+ "publish-dummy-tap-key",
+ SHOULD_PUBLISH_TAP_DFLT,
+ SHOULD_PUBLISH_TAP_MIN,
+ SHOULD_PUBLISH_TAP_MAX);
+}
+
/** Store a full copy of the current onion key into *<b>key</b>, and a full
* copy of the most recent onion key into *<b>last</b>. Store NULL into
* a pointer if the corresponding key does not exist.
@@ -2138,9 +2162,12 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
ri->supports_tunnelled_dir_requests =
directory_permits_begindir_requests(options);
ri->cache_info.published_on = time(NULL);
- /* get_onion_key() must invoke from main thread */
- router_set_rsa_onion_pkey(get_onion_key(), &ri->onion_pkey,
- &ri->onion_pkey_len);
+
+ if (should_publish_tap_onion_key()) {
+ /* get_onion_key() must invoke from main thread */
+ router_set_rsa_onion_pkey(get_onion_key(), &ri->tap_onion_pkey,
+ &ri->tap_onion_pkey_len);
+ }
ri->onion_curve25519_pkey =
tor_memdup(&get_current_curve25519_keypair()->pubkey,
@@ -2777,7 +2804,7 @@ router_dump_router_to_string(routerinfo_t *router,
char published[ISO_TIME_LEN+1];
char fingerprint[FINGERPRINT_LEN+1];
char *extra_info_line = NULL;
- size_t onion_pkeylen, identity_pkeylen;
+ size_t onion_pkeylen=0, identity_pkeylen;
char *family_line = NULL;
char *extra_or_address = NULL;
const or_options_t *options = get_options();
@@ -2835,12 +2862,14 @@ router_dump_router_to_string(routerinfo_t *router,
}
/* PEM-encode the onion key */
- rsa_pubkey = router_get_rsa_onion_pkey(router->onion_pkey,
- router->onion_pkey_len);
- if (crypto_pk_write_public_key_to_string(rsa_pubkey,
- &onion_pkey,&onion_pkeylen)<0) {
- log_warn(LD_BUG,"write onion_pkey to string failed!");
- goto err;
+ rsa_pubkey = router_get_rsa_onion_pkey(router->tap_onion_pkey,
+ router->tap_onion_pkey_len);
+ if (rsa_pubkey) {
+ if (crypto_pk_write_public_key_to_string(rsa_pubkey,
+ &onion_pkey,&onion_pkeylen)<0) {
+ log_warn(LD_BUG,"write onion_pkey to string failed!");
+ goto err;
+ }
}
/* PEM-encode the identity key */
@@ -2851,7 +2880,7 @@ router_dump_router_to_string(routerinfo_t *router,
}
/* Cross-certify with RSA key */
- if (tap_key && router->cache_info.signing_key_cert &&
+ if (tap_key && rsa_pubkey && router->cache_info.signing_key_cert &&
router->cache_info.signing_key_cert->signing_key_included) {
char buf[256];
int tap_cc_len = 0;
@@ -2976,7 +3005,7 @@ router_dump_router_to_string(routerinfo_t *router,
"uptime %ld\n"
"bandwidth %d %d %d\n"
"%s%s"
- "onion-key\n%s"
+ "%s%s"
"signing-key\n%s"
"%s%s"
"%s%s%s",
@@ -2997,7 +3026,8 @@ router_dump_router_to_string(routerinfo_t *router,
extra_info_line ? extra_info_line : "",
(options->DownloadExtraInfo || options->V3AuthoritativeDir) ?
"caches-extra-info\n" : "",
- onion_pkey, identity_pkey,
+ onion_pkey?"onion-key\n":"", onion_pkey?onion_pkey:"",
+ identity_pkey,
rsa_tap_cc_line ? rsa_tap_cc_line : "",
ntor_cc_line ? ntor_cc_line : "",
family_line,
diff --git a/src/feature/relay/selftest.c b/src/feature/relay/selftest.c
index 399b6bca6e..0a80a5d47e 100644
--- a/src/feature/relay/selftest.c
+++ b/src/feature/relay/selftest.c
@@ -201,7 +201,6 @@ have_orport_for_family(int family)
static extend_info_t *
extend_info_from_router(const routerinfo_t *r, int family)
{
- crypto_pk_t *rsa_pubkey;
extend_info_t *info;
tor_addr_port_t ap;
@@ -224,15 +223,14 @@ extend_info_from_router(const routerinfo_t *r, int family)
/* We don't have an ORPort for the requested family. */
return NULL;
}
- rsa_pubkey = router_get_rsa_onion_pkey(r->onion_pkey, r->onion_pkey_len);
info = extend_info_new(r->nickname, r->cache_info.identity_digest,
ed_id_key,
- rsa_pubkey, r->onion_curve25519_pkey,
+ r->onion_curve25519_pkey,
&ap.addr, ap.port,
/* TODO-324: Should self-test circuits use
* congestion control? */
NULL, false);
- crypto_pk_free(rsa_pubkey);
+
return info;
}
diff --git a/src/feature/stats/rephist.c b/src/feature/stats/rephist.c
index 8f4f33151a..055081fc7c 100644
--- a/src/feature/stats/rephist.c
+++ b/src/feature/stats/rephist.c
@@ -280,6 +280,9 @@ static dns_stats_t dns_AAAA_stats;
/** DNS query statistics store. It covers all type of queries. */
static dns_stats_t dns_all_stats;
+/** Counter of the total number of DROP cell received. */
+static uint64_t relay_circ_n_drop_cell_received = 0;
+
/** Return the point to the DNS statistics store. Ignore the type for now
* because of a libevent problem. */
static inline dns_stats_t *
@@ -2290,19 +2293,14 @@ typedef struct {
/** Keep track of the onionskin requests for an assessment period. */
static overload_onionskin_assessment_t overload_onionskin_assessment;
-/**
- * We combine ntorv3 and ntor into the same stat, so we must
- * use this function to convert the cell type to a stat index.
+/** This function ensures that we clamp the maximum value of the given input
+ * <b>type</b> to NTOR in case the input is out of range.
*/
static inline uint16_t
onionskin_type_to_stat(uint16_t type)
{
- if (type == ONION_HANDSHAKE_TYPE_NTOR_V3) {
- return ONION_HANDSHAKE_TYPE_NTOR;
- }
-
if (BUG(type > MAX_ONION_STAT_TYPE)) {
- return MAX_ONION_STAT_TYPE; // use ntor if out of range
+ return MAX_ONION_STAT_TYPE; // use ntor_v3 if out of range
}
return type;
@@ -2371,7 +2369,8 @@ rep_hist_note_circuit_handshake_requested(uint16_t type)
onion_handshakes_requested[stat]++;
/* Only relays get to record requested onionskins. */
- if (stat == ONION_HANDSHAKE_TYPE_NTOR) {
+ if (stat == ONION_HANDSHAKE_TYPE_NTOR ||
+ stat == ONION_HANDSHAKE_TYPE_NTOR_V3) {
/* Assess if we've reached the overload general signal. */
overload_general_onionskin_assessment();
@@ -2398,7 +2397,8 @@ rep_hist_note_circuit_handshake_dropped(uint16_t type)
stats_n_onionskin_dropped[stat]++;
/* Only relays get to record requested onionskins. */
- if (stat == ONION_HANDSHAKE_TYPE_NTOR) {
+ if (stat == ONION_HANDSHAKE_TYPE_NTOR ||
+ stat == ONION_HANDSHAKE_TYPE_NTOR_V3) {
/* Note the dropped ntor in the overload assessment object. */
overload_onionskin_assessment.n_ntor_dropped++;
}
@@ -2438,11 +2438,13 @@ rep_hist_log_circuit_handshake_stats(time_t now)
{
(void)now;
log_notice(LD_HEARTBEAT, "Circuit handshake stats since last time: "
- "%d/%d TAP, %d/%d NTor.",
+ "%d/%d TAP, %d/%d NTor, %d/%d NTor (v3).",
onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_TAP],
onion_handshakes_requested[ONION_HANDSHAKE_TYPE_TAP],
onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR],
- onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR]);
+ onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR],
+ onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR_V3],
+ onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR_V3]);
memset(onion_handshakes_assigned, 0, sizeof(onion_handshakes_assigned));
memset(onion_handshakes_requested, 0, sizeof(onion_handshakes_requested));
}
@@ -2816,6 +2818,8 @@ rep_hist_padding_count_write(padding_type_t type)
switch (type) {
case PADDING_TYPE_DROP:
padding_current.write_drop_cell_count++;
+ /* Padding stats get reset thus why we have two counters. */
+ relay_circ_n_drop_cell_received++;
break;
case PADDING_TYPE_CELL:
padding_current.write_pad_cell_count++;
@@ -3023,6 +3027,13 @@ rep_hist_consensus_has_changed(const networkstatus_t *ns)
OVERLOAD_ONIONSKIN_NTOR_PERIOD_SECS_MAX);
}
+/** Relay Only: return the total number of DROP cell received. */
+uint64_t
+rep_hist_get_drop_cell_received_count(void)
+{
+ return relay_circ_n_drop_cell_received;
+}
+
#ifdef TOR_UNIT_TESTS
/* only exists for unit tests: get HSv2 stats object */
const hs_v2_stats_t *
diff --git a/src/feature/stats/rephist.h b/src/feature/stats/rephist.h
index fbfab4c451..f595459580 100644
--- a/src/feature/stats/rephist.h
+++ b/src/feature/stats/rephist.h
@@ -102,8 +102,8 @@ void rep_hist_note_dns_error(int type, uint8_t error);
void rep_hist_consensus_has_changed(const networkstatus_t *ns);
/** We combine ntor and ntorv3 stats, so we have 3 stat types:
- * tap, fast, and ntor. The max type is ntor (2) */
-#define MAX_ONION_STAT_TYPE ONION_HANDSHAKE_TYPE_NTOR
+ * tap, fast, and ntor. The max type is ntor_v3 (3) */
+#define MAX_ONION_STAT_TYPE MAX_ONION_HANDSHAKE_TYPE
extern uint64_t rephist_total_alloc;
extern uint32_t rephist_total_num;
@@ -192,6 +192,8 @@ uint64_t rep_hist_get_n_tcp_exhaustion(void);
uint64_t rep_hist_get_n_read_limit_reached(void);
uint64_t rep_hist_get_n_write_limit_reached(void);
+uint64_t rep_hist_get_drop_cell_received_count(void);
+
#ifdef TOR_UNIT_TESTS
struct hs_v2_stats_t;
const struct hs_v2_stats_t *rep_hist_get_hs_v2_stats(void);
diff --git a/src/lib/crypt_ops/crypto_openssl_mgt.c b/src/lib/crypt_ops/crypto_openssl_mgt.c
index 6c01cb6aa8..ca12a82518 100644
--- a/src/lib/crypt_ops/crypto_openssl_mgt.c
+++ b/src/lib/crypt_ops/crypto_openssl_mgt.c
@@ -40,6 +40,11 @@ ENABLE_GCC_WARNING("-Wredundant-decls")
#include <string.h>
+#ifdef OPENSSL_NO_ENGINE
+/* Android's OpenSSL seems to have removed all of its Engine support. */
+#define DISABLE_ENGINES
+#endif
+
#ifndef NEW_THREAD_API
/** A number of preallocated mutexes for use by OpenSSL. */
static tor_mutex_t **openssl_mutexes_ = NULL;
diff --git a/src/lib/crypt_ops/crypto_openssl_mgt.h b/src/lib/crypt_ops/crypto_openssl_mgt.h
index 96a37721dd..eac0ec1977 100644
--- a/src/lib/crypt_ops/crypto_openssl_mgt.h
+++ b/src/lib/crypt_ops/crypto_openssl_mgt.h
@@ -49,11 +49,6 @@
#define OPENSSL_V_SERIES(a,b,c) \
OPENSSL_VER((a),(b),(c),0,0)
-#ifdef OPENSSL_NO_ENGINE
-/* Android's OpenSSL seems to have removed all of its Engine support. */
-#define DISABLE_ENGINES
-#endif
-
#if OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5)
/* OpenSSL as of 1.1.0pre4 has an "new" thread API, which doesn't require
* setting up various callbacks.
diff --git a/src/lib/fs/files.c b/src/lib/fs/files.c
index 55f20dd49e..914a8b8e72 100644
--- a/src/lib/fs/files.c
+++ b/src/lib/fs/files.c
@@ -85,7 +85,8 @@ tor_open_cloexec(const char *path, int flags, unsigned mode)
FILE *
tor_fopen_cloexec(const char *path, const char *mode)
{
- FILE *result = fopen(path, mode);
+ const char *p = sandbox_intern_string(path);
+ FILE *result = fopen(p, mode);
#ifdef FD_CLOEXEC
if (result != NULL) {
if (fcntl(fileno(result), F_SETFD, FD_CLOEXEC) == -1) {
@@ -572,9 +573,10 @@ write_bytes_to_new_file(const char *fname, const char *str, size_t len,
/**
* Read the contents of the open file <b>fd</b> presuming it is a FIFO
* (or similar) file descriptor for which the size of the file isn't
- * known ahead of time. Return NULL on failure, and a NUL-terminated
- * string on success. On success, set <b>sz_out</b> to the number of
- * bytes read.
+ * known ahead of time.
+ * Return NULL on failure, and a NUL-terminated string on success.
+ * On success, set <b>sz_out</b> to the number of bytes read (not including
+ * the final NULL, which wasn't read from <b>fd</fd>).
*/
char *
read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out)
diff --git a/src/lib/log/.may_include b/src/lib/log/.may_include
index 54d96324db..09e2b90282 100644
--- a/src/lib/log/.may_include
+++ b/src/lib/log/.may_include
@@ -9,8 +9,10 @@ lib/intmath/*.h
lib/lock/*.h
lib/log/*.h
lib/malloc/*.h
+lib/metrics/*.h
lib/string/*.h
lib/subsys/*.h
lib/testsupport/*.h
+lib/thread/threads.h
lib/version/*.h
lib/wallclock/*.h
diff --git a/src/lib/log/log.c b/src/lib/log/log.c
index db57ee61a2..aecd838c5d 100644
--- a/src/lib/log/log.c
+++ b/src/lib/log/log.c
@@ -33,6 +33,7 @@
#define LOG_PRIVATE
#include "lib/log/log.h"
#include "lib/log/log_sys.h"
+#include "lib/log/util_bug.h"
#include "lib/version/git_revision.h"
#include "lib/log/ratelim.h"
#include "lib/lock/compat_mutex.h"
@@ -706,6 +707,8 @@ log_fn_(int severity, log_domain_mask_t domain, const char *fn,
const char *format, ...)
{
va_list ap;
+ if (domain & LD_BUG)
+ tor_bug_increment_count_();
if (severity > log_global_min_severity_)
return;
va_start(ap,format);
@@ -718,6 +721,8 @@ log_fn_ratelim_(ratelim_t *ratelim, int severity, log_domain_mask_t domain,
{
va_list ap;
char *m;
+ if (domain & LD_BUG)
+ tor_bug_increment_count_();
if (severity > log_global_min_severity_)
return;
m = rate_limit_log(ratelim, approx_time());
@@ -912,6 +917,7 @@ init_logging(int disable_startup_queue)
{
if (!log_mutex_initialized) {
tor_mutex_init(&log_mutex);
+ tor_bug_init_counter();
log_mutex_initialized = 1;
}
#ifdef __GNUC__
diff --git a/src/lib/log/log_sys.c b/src/lib/log/log_sys.c
index 33609f5288..ac76d9bdbb 100644
--- a/src/lib/log/log_sys.c
+++ b/src/lib/log/log_sys.c
@@ -11,11 +11,16 @@
#include "lib/log/escape.h"
#include "lib/log/log.h"
#include "lib/log/log_sys.h"
+#include "lib/log/util_bug.h"
+#include "lib/metrics/metrics_store.h"
+
+static metrics_store_t *the_store;
static int
subsys_logging_initialize(void)
{
init_logging(0);
+ the_store = metrics_store_new();
return 0;
}
@@ -26,6 +31,29 @@ subsys_logging_shutdown(void)
escaped(NULL);
}
+static const smartlist_t *
+logging_metrics_get_stores(void)
+{
+ static smartlist_t *stores_list = NULL;
+
+ metrics_store_reset(the_store);
+
+ metrics_store_entry_t *sentry = metrics_store_add(
+ the_store,
+ METRICS_TYPE_COUNTER,
+ METRICS_NAME(bug_reached_count),
+ "Total number of BUG() and similar assertion reached",
+ 0, NULL);
+ metrics_store_entry_update(sentry, tor_bug_get_count());
+
+ if (!stores_list) {
+ stores_list = smartlist_new();
+ smartlist_add(stores_list, the_store);
+ }
+
+ return stores_list;
+}
+
const subsys_fns_t sys_logging = {
.name = "log",
SUBSYS_DECLARE_LOCATION(),
@@ -35,4 +63,5 @@ const subsys_fns_t sys_logging = {
.level = -90,
.initialize = subsys_logging_initialize,
.shutdown = subsys_logging_shutdown,
+ .get_metrics = logging_metrics_get_stores,
};
diff --git a/src/lib/log/util_bug.c b/src/lib/log/util_bug.c
index 34b41324af..d2dbb0a7a5 100644
--- a/src/lib/log/util_bug.c
+++ b/src/lib/log/util_bug.c
@@ -18,6 +18,7 @@
#endif
#include "lib/malloc/malloc.h"
#include "lib/string/printf.h"
+#include "lib/thread/threads.h"
#include <string.h>
#include <stdlib.h>
@@ -101,6 +102,27 @@ tor_assertion_failed_(const char *fname, unsigned int line,
tor_free(buf);
}
+static atomic_counter_t total_bug_reached;
+
+void
+tor_bug_init_counter(void)
+{
+ atomic_counter_init(&total_bug_reached);
+}
+
+/** Helper to update BUG count in metrics. */
+void
+tor_bug_increment_count_(void)
+{
+ atomic_counter_add(&total_bug_reached, 1);
+}
+
+size_t
+tor_bug_get_count(void)
+{
+ return atomic_counter_get(&total_bug_reached);
+}
+
/** Helper for tor_assert_nonfatal: report the assertion failure. */
void
tor_bug_occurred_(const char *fname, unsigned int line,
@@ -110,6 +132,11 @@ tor_bug_occurred_(const char *fname, unsigned int line,
char *buf = NULL;
const char *once_str = once ?
" (Future instances of this warning will be silenced.)": "";
+ if (! once) {
+ // _once assertions count from the macro directly so we count them as many
+ // time as they are reached, and not just once.
+ tor_bug_increment_count_();
+ }
if (! expr) {
if (capturing_bugs()) {
add_captured_bug("This line should not have been reached.");
diff --git a/src/lib/log/util_bug.h b/src/lib/log/util_bug.h
index dd82981e08..5ea198f7ff 100644
--- a/src/lib/log/util_bug.h
+++ b/src/lib/log/util_bug.h
@@ -39,6 +39,7 @@
#include "orconfig.h"
#include "lib/cc/compat_compiler.h"
#include "lib/log/log.h"
+#include "lib/smartlist_core/smartlist_core.h"
#include "lib/testsupport/testsupport.h"
/* Replace assert() with a variant that sends failures to the log before
@@ -191,6 +192,7 @@
STMT_END
#define tor_assert_nonfatal_unreached_once() STMT_BEGIN \
static int warning_logged__ = 0; \
+ tor_bug_increment_count_(); \
if (!warning_logged__) { \
warning_logged__ = 1; \
tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, NULL, 1, NULL); \
@@ -198,10 +200,12 @@
STMT_END
#define tor_assert_nonfatal_once(cond) STMT_BEGIN \
static int warning_logged__ = 0; \
- if (ASSERT_PREDICT_LIKELY_(cond)) { \
- } else if (!warning_logged__) { \
- warning_logged__ = 1; \
- tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 1, NULL);\
+ if (!ASSERT_PREDICT_LIKELY_(cond)) { \
+ tor_bug_increment_count_(); \
+ if (!warning_logged__) { \
+ warning_logged__ = 1; \
+ tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 1, NULL);\
+ } \
} \
STMT_END
#define BUG(cond) \
@@ -215,18 +219,22 @@
if (( { \
static int var = 0; \
int bool_result = !!(cond); \
- if (bool_result && !var) { \
- var = 1; \
- tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
- ("!("#cond")"), 1, NULL); \
+ if (bool_result) { \
+ tor_bug_increment_count_(); \
+ if (!var) { \
+ var = 1; \
+ tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
+ ("!("#cond")"), 1, NULL); \
+ } \
} \
bool_result; } ))
#else /* !defined(__GNUC__) */
#define IF_BUG_ONCE__(cond,var) \
static int var = 0; \
if ((cond) ? \
- (var ? 1 : \
+ (var ? (tor_bug_increment_count_(), 1) : \
(var=1, \
+ tor_bug_increment_count_(), \
tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
("!("#cond")"), 1, NULL), \
1)) \
@@ -273,12 +281,15 @@ void tor_assertion_failed_(const char *fname, unsigned int line,
const char *func, const char *expr,
const char *fmt, ...)
CHECK_PRINTF(5,6);
+void tor_bug_increment_count_(void);
+size_t tor_bug_get_count(void);
void tor_bug_occurred_(const char *fname, unsigned int line,
const char *func, const char *expr,
int once, const char *fmt, ...)
CHECK_PRINTF(6,7);
void tor_abort_(void) ATTR_NORETURN;
+void tor_bug_init_counter(void);
#ifdef _WIN32
#define SHORT_FILE__ (tor_fix_source_file(__FILE__))
diff --git a/src/lib/sandbox/sandbox.c b/src/lib/sandbox/sandbox.c
index 8ac07abfc9..08322e17d4 100644
--- a/src/lib/sandbox/sandbox.c
+++ b/src/lib/sandbox/sandbox.c
@@ -125,6 +125,15 @@
#define SYSCALL_NAME_DEBUGGING
#endif
+/**
+ * On newer architectures Linux provides a standardized, generic set of system
+ * calls (defined in Linux's include/uapi/asm-generic/unistd.h), which omits a
+ * number of legacy calls used by glibc on other platforms.
+ */
+#if defined(__aarch64__) || defined(__riscv)
+#define ARCH_USES_GENERIC_SYSCALLS
+#endif
+
/**Determines if at least one sandbox is active.*/
static int sandbox_active = 0;
/** Holds the parameter list configuration for the sandbox.*/
@@ -263,8 +272,9 @@ static int filter_nopar_gen[] = {
#ifdef __NR_sigreturn
SCMP_SYS(sigreturn),
#endif
+#if defined(__NR_stat)
SCMP_SYS(stat),
-#if defined(__i386__) && defined(__NR_statx)
+#elif defined(__i386__) && defined(__NR_statx)
SCMP_SYS(statx),
#endif
SCMP_SYS(uname),
@@ -335,6 +345,8 @@ static int filter_nopar_gen[] = {
seccomp_rule_add((ctx),(act),(call),3,(f1),(f2),(f3))
#define seccomp_rule_add_4(ctx,act,call,f1,f2,f3,f4) \
seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4))
+#define seccomp_rule_add_5(ctx,act,call,f1,f2,f3,f4,f5) \
+ seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4),(f5))
static const char *sandbox_get_interned_string(const char *str);
@@ -516,18 +528,33 @@ is_libc_at_least(int major, int minor)
static int
libc_uses_openat_for_open(void)
{
+#ifdef __NR_open
return is_libc_at_least(2, 26);
+#else
+ return 1;
+#endif /* defined(__NR_open) */
}
+/* Calls to opendir() cannot be filtered by the sandbox when built with fragile
+ * hardening for an architecture that uses Linux's generic syscall interface,
+ * so prevent a compiler warning by omitting this function along with
+ * sb_opendir(). */
+#if !(defined(ENABLE_FRAGILE_HARDENING) && defined(ARCH_USES_GENERIC_SYSCALLS))
/* Return true if we think we're running with a libc that uses openat for the
* opendir function on linux. */
static int
libc_uses_openat_for_opendir(void)
{
+#ifdef __NR_open
// libc 2.27 and above or between 2.15 (inclusive) and 2.22 (exclusive)
return is_libc_at_least(2, 27) ||
(is_libc_at_least(2, 15) && !is_libc_at_least(2, 22));
+#else
+ return 1;
+#endif /* defined(__NR_open) */
}
+#endif /* !(defined(ENABLE_FRAGILE_HARDENING) &&
+ defined(ARCH_USES_GENERIC_SYSCALLS)) */
/** Allow a single file to be opened. If <b>use_openat</b> is true,
* we're using a libc that remaps all the opens into openats. */
@@ -557,10 +584,25 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
int use_openat = libc_uses_openat_for_open();
#ifdef ENABLE_FRAGILE_HARDENING
- /* AddressSanitizer uses the "open" syscall to access information about the
- * running process via the filesystem, so that call must be allowed without
+ /* AddressSanitizer uses either the "open" or the "openat" syscall (depending
+ * on the architecture) to access information about the running process via
+ * the filesystem, so the appropriate call must be allowed without
* restriction or the sanitizer will be unable to execute normally when the
* process terminates. */
+#ifdef ARCH_USES_GENERIC_SYSCALLS
+ rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
+ SCMP_CMP_LOWER32_EQ(0, AT_FDCWD));
+ if (rc != 0) {
+ log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received "
+ "libseccomp error %d", rc);
+ return rc;
+ }
+
+ /* The "open" syscall is not defined on this architecture, so any other
+ * requests to open files will necessarily use "openat" as well and there is
+ * no need to consider any additional rules. */
+ return 0;
+#else
rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open));
if (rc != 0) {
log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
@@ -572,7 +614,8 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
* there is no need to consider any additional rules. */
if (!use_openat)
return 0;
-#endif
+#endif /* defined(ARCH_USES_GENERIC_SYSCALLS) */
+#endif /* defined(ENABLE_FRAGILE_HARDENING) */
// for each dynamic parameter filters
for (elem = filter; elem != NULL; elem = elem->next) {
@@ -592,6 +635,33 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
+#ifdef ARCH_USES_GENERIC_SYSCALLS
+static int
+sb_fchmodat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
+{
+ int rc;
+ sandbox_cfg_t *elem = NULL;
+
+ // for each dynamic parameter filters
+ for (elem = filter; elem != NULL; elem = elem->next) {
+ smp_param_t *param = elem->param;
+
+ if (param != NULL && param->prot == 1 && param->syscall
+ == SCMP_SYS(fchmodat)) {
+ rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchmodat),
+ SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
+ SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value));
+ if (rc != 0) {
+ log_err(LD_BUG,"(Sandbox) failed to add fchmodat syscall, received "
+ "libseccomp error %d", rc);
+ return rc;
+ }
+ }
+ }
+
+ return 0;
+}
+#else
static int
sb_chmod(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
@@ -616,9 +686,11 @@ sb_chmod(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
+#endif /* defined(ARCH_USES_GENERIC_SYSCALLS) */
+#if defined(ARCH_USES_GENERIC_SYSCALLS)
static int
-sb_fchmodat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
+sb_fchownat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
int rc;
sandbox_cfg_t *elem = NULL;
@@ -628,12 +700,12 @@ sb_fchmodat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
smp_param_t *param = elem->param;
if (param != NULL && param->prot == 1 && param->syscall
- == SCMP_SYS(fchmodat)) {
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchmodat),
+ == SCMP_SYS(fchownat)) {
+ rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchownat),
SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value));
if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add fchmodat syscall, received "
+ log_err(LD_BUG,"(Sandbox) failed to add fchownat syscall, received "
"libseccomp error %d", rc);
return rc;
}
@@ -642,8 +714,7 @@ sb_fchmodat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
-
-#ifdef __i386__
+#elif defined(__i386__)
static int
sb_chown32(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
@@ -693,10 +764,15 @@ sb_chown(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
-#endif /* defined(__i386__) */
+#endif /* defined(ARCH_USES_GENERIC_SYSCALLS) || defined(__i386__) */
+#if defined(__NR_rename)
+/**
+ * Function responsible for setting up the rename syscall for
+ * the seccomp filter sandbox.
+ */
static int
-sb_fchownat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
+sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
int rc;
sandbox_cfg_t *elem = NULL;
@@ -705,13 +781,14 @@ sb_fchownat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
for (elem = filter; elem != NULL; elem = elem->next) {
smp_param_t *param = elem->param;
- if (param != NULL && param->prot == 1 && param->syscall
- == SCMP_SYS(fchownat)) {
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchownat),
- SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
- SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value));
+ if (param != NULL && param->prot == 1 &&
+ param->syscall == SCMP_SYS(rename)) {
+
+ rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename),
+ SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value),
+ SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value2));
if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add fchownat syscall, received "
+ log_err(LD_BUG,"(Sandbox) failed to add rename syscall, received "
"libseccomp error %d", rc);
return rc;
}
@@ -720,13 +797,13 @@ sb_fchownat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
-
+#elif defined(__NR_renameat)
/**
- * Function responsible for setting up the rename syscall for
+ * Function responsible for setting up the renameat syscall for
* the seccomp filter sandbox.
*/
static int
-sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
+sb_renameat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
int rc;
sandbox_cfg_t *elem = NULL;
@@ -736,13 +813,15 @@ sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
smp_param_t *param = elem->param;
if (param != NULL && param->prot == 1 &&
- param->syscall == SCMP_SYS(rename)) {
+ param->syscall == SCMP_SYS(renameat)) {
- rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename),
- SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value),
- SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value2));
+ rc = seccomp_rule_add_4(ctx, SCMP_ACT_ALLOW, SCMP_SYS(renameat),
+ SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
+ SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value),
+ SCMP_CMP_LOWER32_EQ(2, AT_FDCWD),
+ SCMP_CMP_STR(3, SCMP_CMP_EQ, param->value2));
if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add rename syscall, received "
+ log_err(LD_BUG,"(Sandbox) failed to add renameat syscall, received "
"libseccomp error %d", rc);
return rc;
}
@@ -751,13 +830,13 @@ sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
-
+#else
/**
- * Function responsible for setting up the renameat syscall for
+ * Function responsible for setting up the renameat2 syscall for
* the seccomp filter sandbox.
*/
static int
-sb_renameat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
+sb_renameat2(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
int rc;
sandbox_cfg_t *elem = NULL;
@@ -767,15 +846,16 @@ sb_renameat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
smp_param_t *param = elem->param;
if (param != NULL && param->prot == 1 &&
- param->syscall == SCMP_SYS(renameat)) {
+ param->syscall == SCMP_SYS(renameat2)) {
- rc = seccomp_rule_add_4(ctx, SCMP_ACT_ALLOW, SCMP_SYS(renameat),
+ rc = seccomp_rule_add_5(ctx, SCMP_ACT_ALLOW, SCMP_SYS(renameat2),
SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value),
SCMP_CMP_LOWER32_EQ(2, AT_FDCWD),
- SCMP_CMP_STR(3, SCMP_CMP_EQ, param->value2));
+ SCMP_CMP_STR(3, SCMP_CMP_EQ, param->value2),
+ SCMP_CMP(4, SCMP_CMP_EQ, 0));
if (rc != 0) {
- log_err(LD_BUG,"(Sandbox) failed to add renameat syscall, received "
+ log_err(LD_BUG,"(Sandbox) failed to add renameat2 syscall, received "
"libseccomp error %d", rc);
return rc;
}
@@ -784,7 +864,19 @@ sb_renameat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
+#endif /* defined(__NR_rename) || defined(__NR_renameat) */
+/* If Tor is built with fragile hardening for an architecture that uses Linux's
+ * generic syscall interface a rule allowing the "openat" syscall without
+ * restriction will have already been added by sb_open(), so there is no need
+ * to consider adding additional, more restrictive rules here as they will
+ * simply be ignored.
+ *
+ * Also, since the "open" syscall is not defined on these architectures, glibc
+ * will necessarily use "openat" for its implementation of opendir() as well.
+ * This means neither of the following two functions will have any effect and
+ * both can be omitted. */
+#if !(defined(ENABLE_FRAGILE_HARDENING) && defined(ARCH_USES_GENERIC_SYSCALLS))
/**
* Function responsible for setting up the openat syscall for
* the seccomp filter sandbox.
@@ -840,6 +932,8 @@ sb_opendir(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
+#endif /* !(defined(ENABLE_FRAGILE_HARDENING) &&
+ defined(ARCH_USES_GENERIC_SYSCALLS)) */
#ifdef ENABLE_FRAGILE_HARDENING
/**
@@ -859,9 +953,17 @@ sb_ptrace(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
if (rc)
return rc;
+ /* AddressSanitizer uses "PTRACE_GETREGSET" on AArch64 (ARM64) and
+ * System/390, "PTRACE_GETREGS" everywhere else. */
+#if defined(__aarch64__) || defined(__s390__)
+ rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ptrace),
+ SCMP_CMP(0, SCMP_CMP_EQ, PTRACE_GETREGSET),
+ SCMP_CMP(1, SCMP_CMP_EQ, pid));
+#else
rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ptrace),
SCMP_CMP(0, SCMP_CMP_EQ, PTRACE_GETREGS),
SCMP_CMP(1, SCMP_CMP_EQ, pid));
+#endif /* defined(__aarch64__) || defined(__s390__) */
if (rc)
return rc;
@@ -1351,6 +1453,40 @@ sb_mremap(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
+#ifdef ARCH_USES_GENERIC_SYSCALLS
+/**
+ * Function responsible for setting up the newfstatat syscall for
+ * the seccomp filter sandbox.
+ */
+static int
+sb_newfstatat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
+{
+ int rc = 0;
+
+ sandbox_cfg_t *elem = NULL;
+
+ // for each dynamic parameter filters
+ for (elem = filter; elem != NULL; elem = elem->next) {
+ smp_param_t *param = elem->param;
+
+ if (param != NULL && param->prot == 1 && (param->syscall == SCMP_SYS(open)
+ || param->syscall == PHONY_OPENDIR_SYSCALL
+ || param->syscall == SCMP_SYS(newfstatat))) {
+ rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(newfstatat),
+ SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
+ SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value));
+ if (rc != 0) {
+ log_err(LD_BUG,"(Sandbox) failed to add newfstatat syscall, received "
+ "libseccomp error %d", rc);
+ return rc;
+ }
+ }
+ }
+
+ return 0;
+}
+#endif /* defined(ARCH_USES_GENERIC_SYSCALLS) */
+
#ifdef __NR_stat64
/**
* Function responsible for setting up the stat64 syscall for
@@ -1409,22 +1545,33 @@ static sandbox_filter_func_t filter_func[] = {
#ifdef __NR_mmap2
sb_mmap2,
#endif
-#ifdef __i386__
+#if defined(ARCH_USES_GENERIC_SYSCALLS)
+ sb_fchownat,
+#elif defined(__i386__)
sb_chown32,
#else
sb_chown,
#endif
- sb_fchownat,
- sb_chmod,
+#if defined(ARCH_USES_GENERIC_SYSCALLS)
sb_fchmodat,
+#else
+ sb_chmod,
+#endif
sb_open,
+#if !(defined(ENABLE_FRAGILE_HARDENING) && defined(ARCH_USES_GENERIC_SYSCALLS))
sb_openat,
sb_opendir,
+#endif
#ifdef ENABLE_FRAGILE_HARDENING
sb_ptrace,
#endif
+#if defined(__NR_rename)
sb_rename,
+#elif defined(__NR_renameat)
sb_renameat,
+#else
+ sb_renameat2,
+#endif
#ifdef __NR_fcntl64
sb_fcntl64,
#endif
@@ -1434,7 +1581,9 @@ static sandbox_filter_func_t filter_func[] = {
sb_flock,
sb_futex,
sb_mremap,
-#ifdef __NR_stat64
+#if defined(ARCH_USES_GENERIC_SYSCALLS)
+ sb_newfstatat,
+#elif defined(__NR_stat64)
sb_stat64,
#endif
@@ -1690,27 +1839,31 @@ new_element(int syscall, char *value)
return new_element2(syscall, value, NULL);
}
-#ifdef __i386__
-#define SCMP_chown SCMP_SYS(chown32)
-#elif defined(__aarch64__) && defined(__LP64__)
+#if defined(ARCH_USES_GENERIC_SYSCALLS)
#define SCMP_chown SCMP_SYS(fchownat)
+#elif defined(__i386__)
+#define SCMP_chown SCMP_SYS(chown32)
#else
#define SCMP_chown SCMP_SYS(chown)
#endif
-#if defined(__aarch64__) && defined(__LP64__)
+#if defined(ARCH_USES_GENERIC_SYSCALLS)
#define SCMP_chmod SCMP_SYS(fchmodat)
#else
#define SCMP_chmod SCMP_SYS(chmod)
#endif
-#if defined(__aarch64__) && defined(__LP64__)
+#if defined(__NR_rename)
+#define SCMP_rename SCMP_SYS(rename)
+#elif defined(__NR_renameat)
#define SCMP_rename SCMP_SYS(renameat)
#else
-#define SCMP_rename SCMP_SYS(rename)
+#define SCMP_rename SCMP_SYS(renameat2)
#endif
-#ifdef __NR_stat64
+#if defined(ARCH_USES_GENERIC_SYSCALLS)
+#define SCMP_stat SCMP_SYS(newfstatat)
+#elif defined(__NR_stat64)
#define SCMP_stat SCMP_SYS(stat64)
#else
#define SCMP_stat SCMP_SYS(stat)
diff --git a/src/lib/string/util_string.c b/src/lib/string/util_string.c
index b1c0a11439..60b5933e4d 100644
--- a/src/lib/string/util_string.c
+++ b/src/lib/string/util_string.c
@@ -31,6 +31,8 @@ tor_memmem(const void *_haystack, size_t hlen,
{
#if defined(HAVE_MEMMEM) && (!defined(__GNUC__) || __GNUC__ >= 2)
raw_assert(nlen);
+ if (nlen > hlen)
+ return NULL;
return memmem(_haystack, hlen, _needle, nlen);
#else
/* This isn't as fast as the GLIBC implementation, but it doesn't need to
diff --git a/src/test/bench.c b/src/test/bench.c
index a76e600cfa..044351b4be 100644
--- a/src/test/bench.c
+++ b/src/test/bench.c
@@ -11,7 +11,6 @@
#include "orconfig.h"
#include "core/or/or.h"
-#include "core/crypto/onion_tap.h"
#include "core/crypto/relay_crypto.h"
#include "lib/intmath/weakrng.h"
@@ -127,75 +126,6 @@ bench_aes(void)
}
static void
-bench_onion_TAP(void)
-{
- const int iters = 1<<9;
- int i;
- crypto_pk_t *key, *key2;
- uint64_t start, end;
- char os[TAP_ONIONSKIN_CHALLENGE_LEN];
- char or[TAP_ONIONSKIN_REPLY_LEN];
- crypto_dh_t *dh_out = NULL;
-
- key = crypto_pk_new();
- key2 = crypto_pk_new();
- if (crypto_pk_generate_key_with_bits(key, 1024) < 0)
- goto done;
- if (crypto_pk_generate_key_with_bits(key2, 1024) < 0)
- goto done;
-
- reset_perftime();
- start = perftime();
- for (i = 0; i < iters; ++i) {
- onion_skin_TAP_create(key, &dh_out, os);
- crypto_dh_free(dh_out);
- }
- end = perftime();
- printf("Client-side, part 1: %f usec.\n", NANOCOUNT(start, end, iters)/1e3);
-
- onion_skin_TAP_create(key, &dh_out, os);
- start = perftime();
- for (i = 0; i < iters; ++i) {
- char key_out[CPATH_KEY_MATERIAL_LEN];
- onion_skin_TAP_server_handshake(os, key, NULL, or,
- key_out, sizeof(key_out));
- }
- end = perftime();
- printf("Server-side, key guessed right: %f usec\n",
- NANOCOUNT(start, end, iters)/1e3);
-
- start = perftime();
- for (i = 0; i < iters; ++i) {
- char key_out[CPATH_KEY_MATERIAL_LEN];
- onion_skin_TAP_server_handshake(os, key2, key, or,
- key_out, sizeof(key_out));
- }
- end = perftime();
- printf("Server-side, key guessed wrong: %f usec.\n",
- NANOCOUNT(start, end, iters)/1e3);
-
- start = perftime();
- for (i = 0; i < iters; ++i) {
- crypto_dh_t *dh;
- char key_out[CPATH_KEY_MATERIAL_LEN];
- int s;
- dh = crypto_dh_dup(dh_out);
- s = onion_skin_TAP_client_handshake(dh, or, key_out, sizeof(key_out),
- NULL);
- crypto_dh_free(dh);
- tor_assert(s == 0);
- }
- end = perftime();
- printf("Client-side, part 2: %f usec.\n",
- NANOCOUNT(start, end, iters)/1e3);
-
- done:
- crypto_dh_free(dh_out);
- crypto_pk_free(key);
- crypto_pk_free(key2);
-}
-
-static void
bench_onion_ntor_impl(void)
{
const int iters = 1<<10;
@@ -754,7 +684,6 @@ static struct benchmark_t benchmarks[] = {
ENT(siphash),
ENT(digest),
ENT(aes),
- ENT(onion_TAP),
ENT(onion_ntor),
ENT(ed25519),
ENT(rand),
diff --git a/src/test/test.c b/src/test/test.c
index 2030a8336e..317b570d8e 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -50,7 +50,6 @@
#include "core/or/onion.h"
#include "core/crypto/onion_ntor.h"
#include "core/crypto/onion_fast.h"
-#include "core/crypto/onion_tap.h"
#include "core/or/policies.h"
#include "lib/sandbox/sandbox.h"
#include "app/config/statefile.h"
@@ -61,150 +60,6 @@
#include "core/or/or_circuit_st.h"
#include "feature/relay/onion_queue.h"
-/** Run unit tests for the onion handshake code. */
-static void
-test_onion_handshake(void *arg)
-{
- /* client-side */
- crypto_dh_t *c_dh = NULL;
- char c_buf[TAP_ONIONSKIN_CHALLENGE_LEN];
- char c_keys[40];
- /* server-side */
- char s_buf[TAP_ONIONSKIN_REPLY_LEN];
- char s_keys[40];
- int i;
- /* shared */
- crypto_pk_t *pk = NULL, *pk2 = NULL;
-
- (void)arg;
- pk = pk_generate(0);
- pk2 = pk_generate(1);
-
- /* client handshake 1. */
- memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN);
- tt_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf));
-
- for (i = 1; i <= 3; ++i) {
- crypto_pk_t *k1, *k2;
- if (i==1) {
- /* server handshake: only one key known. */
- k1 = pk; k2 = NULL;
- } else if (i==2) {
- /* server handshake: try the right key first. */
- k1 = pk; k2 = pk2;
- } else {
- /* server handshake: try the right key second. */
- k1 = pk2; k2 = pk;
- }
-
- memset(s_buf, 0, TAP_ONIONSKIN_REPLY_LEN);
- memset(s_keys, 0, 40);
- tt_assert(! onion_skin_TAP_server_handshake(c_buf, k1, k2,
- s_buf, s_keys, 40));
-
- /* client handshake 2 */
- memset(c_keys, 0, 40);
- tt_assert(! onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys,
- 40, NULL));
-
- tt_mem_op(c_keys,OP_EQ, s_keys, 40);
- memset(s_buf, 0, 40);
- tt_mem_op(c_keys,OP_NE, s_buf, 40);
- }
- done:
- crypto_dh_free(c_dh);
- crypto_pk_free(pk);
- crypto_pk_free(pk2);
-}
-
-static void
-test_bad_onion_handshake(void *arg)
-{
- char junk_buf[TAP_ONIONSKIN_CHALLENGE_LEN];
- char junk_buf2[TAP_ONIONSKIN_CHALLENGE_LEN];
- /* client-side */
- crypto_dh_t *c_dh = NULL;
- char c_buf[TAP_ONIONSKIN_CHALLENGE_LEN];
- char c_keys[40];
- /* server-side */
- char s_buf[TAP_ONIONSKIN_REPLY_LEN];
- char s_keys[40];
- /* shared */
- crypto_pk_t *pk = NULL, *pk2 = NULL;
-
- (void)arg;
-
- pk = pk_generate(0);
- pk2 = pk_generate(1);
-
- /* Server: Case 1: the encrypted data is degenerate. */
- memset(junk_buf, 0, sizeof(junk_buf));
- crypto_pk_obsolete_public_hybrid_encrypt(pk,
- junk_buf2, TAP_ONIONSKIN_CHALLENGE_LEN,
- junk_buf, DH1024_KEY_LEN,
- PK_PKCS1_OAEP_PADDING, 1);
- tt_int_op(-1, OP_EQ,
- onion_skin_TAP_server_handshake(junk_buf2, pk, NULL,
- s_buf, s_keys, 40));
-
- /* Server: Case 2: the encrypted data is not long enough. */
- memset(junk_buf, 0, sizeof(junk_buf));
- memset(junk_buf2, 0, sizeof(junk_buf2));
- crypto_pk_public_encrypt(pk, junk_buf2, sizeof(junk_buf2),
- junk_buf, 48, PK_PKCS1_OAEP_PADDING);
- tt_int_op(-1, OP_EQ,
- onion_skin_TAP_server_handshake(junk_buf2, pk, NULL,
- s_buf, s_keys, 40));
-
- /* client handshake 1: do it straight. */
- memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN);
- tt_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf));
-
- /* Server: Case 3: we just don't have the right key. */
- tt_int_op(-1, OP_EQ,
- onion_skin_TAP_server_handshake(c_buf, pk2, NULL,
- s_buf, s_keys, 40));
-
- /* Server: Case 4: The RSA-encrypted portion is corrupt. */
- c_buf[64] ^= 33;
- tt_int_op(-1, OP_EQ,
- onion_skin_TAP_server_handshake(c_buf, pk, NULL,
- s_buf, s_keys, 40));
- c_buf[64] ^= 33;
-
- /* (Let the server proceed) */
- tt_int_op(0, OP_EQ,
- onion_skin_TAP_server_handshake(c_buf, pk, NULL,
- s_buf, s_keys, 40));
-
- /* Client: Case 1: The server sent back junk. */
- const char *msg = NULL;
- s_buf[64] ^= 33;
- tt_int_op(-1, OP_EQ,
- onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg));
- s_buf[64] ^= 33;
- tt_str_op(msg, OP_EQ, "Digest DOES NOT MATCH on onion handshake. "
- "Bug or attack.");
-
- /* Let the client finish; make sure it can. */
- msg = NULL;
- tt_int_op(0, OP_EQ,
- onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg));
- tt_mem_op(s_keys,OP_EQ, c_keys, 40);
- tt_ptr_op(msg, OP_EQ, NULL);
-
- /* Client: Case 2: The server sent back a degenerate DH. */
- memset(s_buf, 0, sizeof(s_buf));
- tt_int_op(-1, OP_EQ,
- onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg));
- tt_str_op(msg, OP_EQ, "DH computation failed.");
-
- done:
- crypto_dh_free(c_dh);
- crypto_pk_free(pk);
- crypto_pk_free(pk2);
-}
-
static void
test_ntor_handshake(void *arg)
{
@@ -306,37 +161,35 @@ test_fast_handshake(void *arg)
static void
test_onion_queues(void *arg)
{
- uint8_t buf1[TAP_ONIONSKIN_CHALLENGE_LEN] = {0};
+ uint8_t buf1[NTOR_ONIONSKIN_LEN] = {0};
uint8_t buf2[NTOR_ONIONSKIN_LEN] = {0};
or_circuit_t *circ1 = or_circuit_new(0, NULL);
or_circuit_t *circ2 = or_circuit_new(0, NULL);
- create_cell_t *onionskin = NULL, *create2_ptr;
+ create_cell_t *onionskin = NULL, *create1_ptr;
create_cell_t *create1 = tor_malloc_zero(sizeof(create_cell_t));
create_cell_t *create2 = tor_malloc_zero(sizeof(create_cell_t));
(void)arg;
- create2_ptr = create2; /* remember, but do not free */
+ create1_ptr = create1; /* remember, but do not free */
- create_cell_init(create1, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP,
- TAP_ONIONSKIN_CHALLENGE_LEN, buf1);
+ create_cell_init(create1, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR,
+ NTOR_ONIONSKIN_LEN, buf1);
create_cell_init(create2, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR,
NTOR_ONIONSKIN_LEN, buf2);
- tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(0,OP_EQ, onion_pending_add(circ1, create1));
create1 = NULL;
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
- tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(0,OP_EQ, onion_pending_add(circ2, create2));
create2 = NULL;
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
+ tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
- tt_ptr_op(circ2,OP_EQ, onion_next_task(&onionskin));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
- tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
- tt_ptr_op(onionskin, OP_EQ, create2_ptr);
+ tt_ptr_op(circ1,OP_EQ, onion_next_task(&onionskin));
+ tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
+ tt_ptr_op(onionskin, OP_EQ, create1_ptr);
clear_pending_onions();
tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
@@ -365,24 +218,19 @@ test_onion_queues(void *arg)
static void
test_onion_queue_order(void *arg)
{
- uint8_t buf_tap[TAP_ONIONSKIN_CHALLENGE_LEN] = {0};
uint8_t buf_ntor[NTOR_ONIONSKIN_LEN] = {0};
uint8_t buf_ntor3[CELL_PAYLOAD_SIZE] = {0};
- or_circuit_t *circ_tap = or_circuit_new(0, NULL);
or_circuit_t *circ_ntor = or_circuit_new(0, NULL);
or_circuit_t *circ_ntor3 = or_circuit_new(0, NULL);
create_cell_t *onionskin = NULL;
- create_cell_t *create_tap1 = tor_malloc_zero(sizeof(create_cell_t));
create_cell_t *create_ntor1 = tor_malloc_zero(sizeof(create_cell_t));
create_cell_t *create_ntor2 = tor_malloc_zero(sizeof(create_cell_t));
create_cell_t *create_v3ntor1 = tor_malloc_zero(sizeof(create_cell_t));
create_cell_t *create_v3ntor2 = tor_malloc_zero(sizeof(create_cell_t));
(void)arg;
- create_cell_init(create_tap1, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP,
- TAP_ONIONSKIN_CHALLENGE_LEN, buf_tap);
create_cell_init(create_ntor1, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR,
NTOR_ONIONSKIN_LEN, buf_ntor);
create_cell_init(create_ntor2, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR,
@@ -393,78 +241,63 @@ test_onion_queue_order(void *arg)
NTOR_ONIONSKIN_LEN, buf_ntor3);
/* sanity check queue init */
- tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
- tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
- tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
-
- /* Add tap first so we can ensure it comes out last */
- tt_int_op(0,OP_EQ, onion_pending_add(circ_tap, create_tap1));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
/* Now add interleaving ntor2 and ntor3, to ensure they share
* the same queue and come out in this order */
tt_int_op(0,OP_EQ, onion_pending_add(circ_ntor, create_ntor1));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
tt_int_op(0,OP_EQ, onion_pending_add(circ_ntor3, create_v3ntor1));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
tt_int_op(0,OP_EQ, onion_pending_add(circ_ntor, create_ntor2));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(3,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(3,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
tt_int_op(0,OP_EQ, onion_pending_add(circ_ntor3, create_v3ntor2));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(4,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(4,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
/* Now remove 5 tasks, ensuring order and queue sizes */
tt_ptr_op(circ_ntor, OP_EQ, onion_next_task(&onionskin));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(3,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(3,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
tt_ptr_op(onionskin, OP_EQ, create_ntor1);
tt_ptr_op(circ_ntor3, OP_EQ, onion_next_task(&onionskin));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
tt_ptr_op(onionskin, OP_EQ, create_v3ntor1);
tt_ptr_op(circ_ntor, OP_EQ, onion_next_task(&onionskin));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
tt_ptr_op(onionskin, OP_EQ, create_ntor2);
tt_ptr_op(circ_ntor3, OP_EQ, onion_next_task(&onionskin));
- tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
- tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
- tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
- tt_ptr_op(onionskin, OP_EQ, create_v3ntor2);
-
- tt_ptr_op(circ_tap, OP_EQ, onion_next_task(&onionskin));
tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3));
- tt_ptr_op(onionskin, OP_EQ, create_tap1);
+ tt_ptr_op(onionskin, OP_EQ, create_v3ntor2);
clear_pending_onions();
tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
done:
- circuit_free_(TO_CIRCUIT(circ_tap));
circuit_free_(TO_CIRCUIT(circ_ntor));
circuit_free_(TO_CIRCUIT(circ_ntor3));
- tor_free(create_tap1);
tor_free(create_ntor1);
tor_free(create_ntor2);
tor_free(create_v3ntor1);
@@ -740,8 +573,6 @@ test_circuit_timeout(void *arg)
{ #name, test_ ## name , TT_FORK, NULL, NULL }
static struct testcase_t test_array[] = {
- ENT(onion_handshake),
- { "bad_onion_handshake", test_bad_onion_handshake, 0, NULL, NULL },
ENT(onion_queues),
ENT(onion_queue_order),
{ "ntor_handshake", test_ntor_handshake, 0, NULL, NULL },
diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c
index b7b149cd66..e01a3461fc 100644
--- a/src/test/test_cell_formats.c
+++ b/src/test/test_cell_formats.c
@@ -14,7 +14,6 @@
#include "app/config/config.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "core/or/onion.h"
-#include "core/crypto/onion_tap.h"
#include "core/crypto/onion_fast.h"
#include "core/crypto/onion_ntor.h"
#include "core/or/relay.h"
@@ -399,21 +398,6 @@ test_cfmt_create_cells(void *arg)
/* === Let's try parsing some good cells! */
- /* A valid create cell. */
- memset(&cell, 0, sizeof(cell));
- memset(b, 0, sizeof(b));
- crypto_rand((char*)b, TAP_ONIONSKIN_CHALLENGE_LEN);
- cell.command = CELL_CREATE;
- memcpy(cell.payload, b, TAP_ONIONSKIN_CHALLENGE_LEN);
- tt_int_op(0, OP_EQ, create_cell_parse(&cc, &cell));
- tt_int_op(CELL_CREATE, OP_EQ, cc.cell_type);
- tt_int_op(ONION_HANDSHAKE_TYPE_TAP, OP_EQ, cc.handshake_type);
- tt_int_op(TAP_ONIONSKIN_CHALLENGE_LEN, OP_EQ, cc.handshake_len);
- tt_mem_op(cc.onionskin,OP_EQ, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10);
- tt_int_op(0, OP_EQ, create_cell_format(&cell2, &cc));
- tt_int_op(cell.command, OP_EQ, cell2.command);
- tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE);
-
/* A valid create_fast cell. */
memset(&cell, 0, sizeof(cell));
memset(b, 0, sizeof(b));
@@ -429,22 +413,6 @@ test_cfmt_create_cells(void *arg)
tt_int_op(cell.command, OP_EQ, cell2.command);
tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE);
- /* A valid create2 cell with a TAP payload */
- memset(&cell, 0, sizeof(cell));
- memset(b, 0, sizeof(b));
- crypto_rand((char*)b, TAP_ONIONSKIN_CHALLENGE_LEN);
- cell.command = CELL_CREATE2;
- memcpy(cell.payload, "\x00\x00\x00\xBA", 4); /* TAP, 186 bytes long */
- memcpy(cell.payload+4, b, TAP_ONIONSKIN_CHALLENGE_LEN);
- tt_int_op(0, OP_EQ, create_cell_parse(&cc, &cell));
- tt_int_op(CELL_CREATE2, OP_EQ, cc.cell_type);
- tt_int_op(ONION_HANDSHAKE_TYPE_TAP, OP_EQ, cc.handshake_type);
- tt_int_op(TAP_ONIONSKIN_CHALLENGE_LEN, OP_EQ, cc.handshake_len);
- tt_mem_op(cc.onionskin,OP_EQ, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10);
- tt_int_op(0, OP_EQ, create_cell_format(&cell2, &cc));
- tt_int_op(cell.command, OP_EQ, cell2.command);
- tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE);
-
/* A valid create2 cell with an ntor payload */
memset(&cell, 0, sizeof(cell));
memset(b, 0, sizeof(b));
@@ -461,22 +429,6 @@ test_cfmt_create_cells(void *arg)
tt_int_op(cell.command, OP_EQ, cell2.command);
tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE);
- /* A valid create cell with an ntor payload, in legacy format. */
- memset(&cell, 0, sizeof(cell));
- memset(b, 0, sizeof(b));
- crypto_rand((char*)b, NTOR_ONIONSKIN_LEN);
- cell.command = CELL_CREATE;
- memcpy(cell.payload, "ntorNTORntorNTOR", 16);
- memcpy(cell.payload+16, b, NTOR_ONIONSKIN_LEN);
- tt_int_op(0, OP_EQ, create_cell_parse(&cc, &cell));
- tt_int_op(CELL_CREATE, OP_EQ, cc.cell_type);
- tt_int_op(ONION_HANDSHAKE_TYPE_NTOR, OP_EQ, cc.handshake_type);
- tt_int_op(NTOR_ONIONSKIN_LEN, OP_EQ, cc.handshake_len);
- tt_mem_op(cc.onionskin,OP_EQ, b, NTOR_ONIONSKIN_LEN + 10);
- tt_int_op(0, OP_EQ, create_cell_format(&cell2, &cc));
- tt_int_op(cell.command, OP_EQ, cell2.command);
- tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE);
-
/* == Okay, now let's try to parse some impossible stuff. */
/* It has to be some kind of a create cell! */
@@ -517,20 +469,6 @@ test_cfmt_created_cells(void *arg)
(void)arg;
- /* A good CREATED cell */
- memset(&cell, 0, sizeof(cell));
- memset(b, 0, sizeof(b));
- crypto_rand((char*)b, TAP_ONIONSKIN_REPLY_LEN);
- cell.command = CELL_CREATED;
- memcpy(cell.payload, b, TAP_ONIONSKIN_REPLY_LEN);
- tt_int_op(0, OP_EQ, created_cell_parse(&cc, &cell));
- tt_int_op(CELL_CREATED, OP_EQ, cc.cell_type);
- tt_int_op(TAP_ONIONSKIN_REPLY_LEN, OP_EQ, cc.handshake_len);
- tt_mem_op(cc.reply,OP_EQ, b, TAP_ONIONSKIN_REPLY_LEN + 10);
- tt_int_op(0, OP_EQ, created_cell_format(&cell2, &cc));
- tt_int_op(cell.command, OP_EQ, cell2.command);
- tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE);
-
/* A good CREATED_FAST cell */
memset(&cell, 0, sizeof(cell));
memset(b, 0, sizeof(b));
@@ -606,54 +544,6 @@ test_cfmt_extend_cells(void *arg)
(void) arg;
- /* Let's start with a simple EXTEND cell. */
- memset(p, 0, sizeof(p));
- memset(b, 0, sizeof(b));
- crypto_rand((char*)b, TAP_ONIONSKIN_CHALLENGE_LEN);
- memcpy(p, "\x12\xf4\x00\x01\x01\x02", 6); /* 18 244 0 1 : 258 */
- memcpy(p+6,b,TAP_ONIONSKIN_CHALLENGE_LEN);
- memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, "electroencephalogram", 20);
- tt_int_op(0, OP_EQ, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND,
- p, 26+TAP_ONIONSKIN_CHALLENGE_LEN));
- tt_int_op(RELAY_COMMAND_EXTEND, OP_EQ, ec.cell_type);
- tt_str_op("18.244.0.1", OP_EQ, fmt_addr(&ec.orport_ipv4.addr));
- tt_int_op(258, OP_EQ, ec.orport_ipv4.port);
- tt_int_op(AF_UNSPEC, OP_EQ, tor_addr_family(&ec.orport_ipv6.addr));
- tt_mem_op(ec.node_id,OP_EQ, "electroencephalogram", 20);
- tt_int_op(cc->cell_type, OP_EQ, CELL_CREATE);
- tt_int_op(cc->handshake_type, OP_EQ, ONION_HANDSHAKE_TYPE_TAP);
- tt_int_op(cc->handshake_len, OP_EQ, TAP_ONIONSKIN_CHALLENGE_LEN);
- tt_mem_op(cc->onionskin,OP_EQ, b, TAP_ONIONSKIN_CHALLENGE_LEN+20);
- tt_int_op(0, OP_EQ, extend_cell_format(&p2_cmd, &p2_len, p2, &ec));
- tt_int_op(p2_cmd, OP_EQ, RELAY_COMMAND_EXTEND);
- tt_int_op(p2_len, OP_EQ, 26+TAP_ONIONSKIN_CHALLENGE_LEN);
- tt_mem_op(p2,OP_EQ, p, RELAY_PAYLOAD_SIZE);
-
- /* Let's do an ntor stuffed in a legacy EXTEND cell */
- memset(p, 0, sizeof(p));
- memset(b, 0, sizeof(b));
- crypto_rand((char*)b, NTOR_ONIONSKIN_LEN);
- memcpy(p, "\x12\xf4\x00\x01\x01\x02", 6); /* 18 244 0 1 : 258 */
- memcpy(p+6,"ntorNTORntorNTOR", 16);
- memcpy(p+22, b, NTOR_ONIONSKIN_LEN);
- memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, "electroencephalogram", 20);
- tt_int_op(0, OP_EQ, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND,
- p, 26+TAP_ONIONSKIN_CHALLENGE_LEN));
- tt_int_op(RELAY_COMMAND_EXTEND, OP_EQ, ec.cell_type);
- tt_str_op("18.244.0.1", OP_EQ, fmt_addr(&ec.orport_ipv4.addr));
- tt_int_op(258, OP_EQ, ec.orport_ipv4.port);
- tt_int_op(AF_UNSPEC, OP_EQ, tor_addr_family(&ec.orport_ipv6.addr));
- tt_mem_op(ec.node_id,OP_EQ, "electroencephalogram", 20);
- tt_int_op(cc->cell_type, OP_EQ, CELL_CREATE2);
- tt_int_op(cc->handshake_type, OP_EQ, ONION_HANDSHAKE_TYPE_NTOR);
- tt_int_op(cc->handshake_len, OP_EQ, NTOR_ONIONSKIN_LEN);
- tt_mem_op(cc->onionskin,OP_EQ, b, NTOR_ONIONSKIN_LEN+20);
- tt_int_op(0, OP_EQ, extend_cell_format(&p2_cmd, &p2_len, p2, &ec));
- tt_int_op(p2_cmd, OP_EQ, RELAY_COMMAND_EXTEND);
- tt_int_op(p2_len, OP_EQ, 26+TAP_ONIONSKIN_CHALLENGE_LEN);
- tt_mem_op(p2,OP_EQ, p, RELAY_PAYLOAD_SIZE);
- tt_int_op(0, OP_EQ, create_cell_format_relayed(&cell, cc));
-
/* Now let's do a minimal ntor EXTEND2 cell. */
memset(&ec, 0xff, sizeof(ec));
memset(p, 0, sizeof(p));
@@ -896,23 +786,6 @@ test_cfmt_extended_cells(void *arg)
(void) arg;
- /* Try a regular EXTENDED cell. */
- memset(&ec, 0xff, sizeof(ec));
- memset(p, 0, sizeof(p));
- memset(b, 0, sizeof(b));
- crypto_rand((char*)b, TAP_ONIONSKIN_REPLY_LEN);
- memcpy(p,b,TAP_ONIONSKIN_REPLY_LEN);
- tt_int_op(0, OP_EQ, extended_cell_parse(&ec, RELAY_COMMAND_EXTENDED, p,
- TAP_ONIONSKIN_REPLY_LEN));
- tt_int_op(RELAY_COMMAND_EXTENDED, OP_EQ, ec.cell_type);
- tt_int_op(cc->cell_type, OP_EQ, CELL_CREATED);
- tt_int_op(cc->handshake_len, OP_EQ, TAP_ONIONSKIN_REPLY_LEN);
- tt_mem_op(cc->reply,OP_EQ, b, TAP_ONIONSKIN_REPLY_LEN);
- tt_int_op(0, OP_EQ, extended_cell_format(&p2_cmd, &p2_len, p2, &ec));
- tt_int_op(RELAY_COMMAND_EXTENDED, OP_EQ, p2_cmd);
- tt_int_op(TAP_ONIONSKIN_REPLY_LEN, OP_EQ, p2_len);
- tt_mem_op(p2,OP_EQ, p, sizeof(p2));
-
/* Try an EXTENDED2 cell */
memset(&ec, 0xff, sizeof(ec));
memset(p, 0, sizeof(p));
diff --git a/src/test/test_circuitpadding.c b/src/test/test_circuitpadding.c
index 63b7136a11..95401465c1 100644
--- a/src/test/test_circuitpadding.c
+++ b/src/test/test_circuitpadding.c
@@ -1608,7 +1608,7 @@ simulate_single_hop_extend(circuit_t *client, circuit_t *mid_relay,
hop->extend_info = extend_info_new(
padding ? "padding" : "non-padding",
- digest, NULL, NULL, NULL,
+ digest, NULL, NULL,
&addr, padding, NULL, false);
cpath_init_circuit_crypto(hop, whatevs_key, sizeof(whatevs_key), 0, 0);
diff --git a/src/test/test_conflux_pool.c b/src/test/test_conflux_pool.c
index fc30677377..6fe3c8b65b 100644
--- a/src/test/test_conflux_pool.c
+++ b/src/test/test_conflux_pool.c
@@ -349,7 +349,7 @@ simulate_single_hop_extend(origin_circuit_t *client, int exit)
hop->extend_info = extend_info_new(
exit ? "exit" : "non-exit",
- digest, NULL, NULL, NULL,
+ digest, NULL, NULL,
&addr, exit, NULL, exit);
cpath_init_circuit_crypto(hop, whatevs_key, sizeof(whatevs_key), 0, 0);
@@ -396,6 +396,7 @@ test_setup(void)
static void
test_clear_circs(void)
{
+ conflux_notify_shutdown();
SMARTLIST_FOREACH(circ_pairs, circ_pair_t *, circ_pair, {
tor_free(circ_pair);
});
@@ -430,6 +431,9 @@ test_clear_circs(void)
tor_assert(smartlist_len(mock_cell_delivery) == 0);
(void)free_fake_origin_circuit;
+
+ /* Clear shutdown flag so we can resume testing again. */
+ conflux_clear_shutdown();
}
static void
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index d09afcb9e6..b34711dcad 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -217,7 +217,7 @@ basic_routerinfo_new(const char *nickname, uint32_t ipv4_addr,
r1->ipv4_dirport = dir_port;
r1->supports_tunnelled_dir_requests = 1;
- router_set_rsa_onion_pkey(pk1, &r1->onion_pkey, &r1->onion_pkey_len);
+ router_set_rsa_onion_pkey(pk1, &r1->tap_onion_pkey, &r1->tap_onion_pkey_len);
r1->identity_pkey = pk2;
r1->bandwidthrate = bandwidthrate;
@@ -382,8 +382,8 @@ get_new_onion_key_block(const routerinfo_t *r1)
{
char *block = NULL;
tor_assert(r1);
- crypto_pk_t *pk_tmp = router_get_rsa_onion_pkey(r1->onion_pkey,
- r1->onion_pkey_len);
+ crypto_pk_t *pk_tmp = router_get_rsa_onion_pkey(r1->tap_onion_pkey,
+ r1->tap_onion_pkey_len);
block = get_new_rsa_key_block("onion-key", pk_tmp);
crypto_pk_free(pk_tmp);
return block;
@@ -587,8 +587,8 @@ setup_mocks_for_fresh_descriptor(const routerinfo_t *r1,
if (rsa_onion_keypair) {
mocked_onionkey = crypto_pk_dup_key(rsa_onion_keypair);
} else {
- mocked_onionkey = router_get_rsa_onion_pkey(r1->onion_pkey,
- r1->onion_pkey_len);
+ mocked_onionkey = router_get_rsa_onion_pkey(r1->tap_onion_pkey,
+ r1->tap_onion_pkey_len);
}
MOCK(get_onion_key, mock_get_onion_key);
}
@@ -643,10 +643,12 @@ STMT_BEGIN \
tt_int_op(rp1->bandwidthrate,OP_EQ, r1->bandwidthrate); \
tt_int_op(rp1->bandwidthburst,OP_EQ, r1->bandwidthburst); \
tt_int_op(rp1->bandwidthcapacity,OP_EQ, r1->bandwidthcapacity); \
- crypto_pk_t *rp1_onion_pkey = router_get_rsa_onion_pkey(rp1->onion_pkey, \
- rp1->onion_pkey_len); \
- crypto_pk_t *r1_onion_pkey = router_get_rsa_onion_pkey(r1->onion_pkey, \
- r1->onion_pkey_len); \
+ crypto_pk_t *rp1_onion_pkey = router_get_rsa_onion_pkey( \
+ rp1->tap_onion_pkey, \
+ rp1->tap_onion_pkey_len); \
+ crypto_pk_t *r1_onion_pkey = router_get_rsa_onion_pkey( \
+ r1->tap_onion_pkey, \
+ r1->tap_onion_pkey_len); \
tt_int_op(crypto_pk_cmp_keys(rp1_onion_pkey, r1_onion_pkey), OP_EQ, 0); \
crypto_pk_free(rp1_onion_pkey); \
crypto_pk_free(r1_onion_pkey); \
@@ -1303,6 +1305,72 @@ test_dir_parse_router_list(void *arg)
#undef ADD
}
+/* Made with chutney and a patched tor: Has no onion-key or
+ * onion-key-crosscert */
+static const char ROUTERDESC_NO_ONION_KEY[] =
+"router test001a 127.0.0.1 5001 0 7001\n"
+"identity-ed25519\n"
+"-----BEGIN ED25519 CERT-----\n"
+"AQQAB0xWARbCJfDrX0OTtpM0fDxU9cLweMnZeUq/KBfAN1wwWHtMAQAgBADBQJ1o\n"
+"ClrXUenWC90FYEUQDpMSdxdxKlrR83rYy+keGe61WQHYP0ebowJC19UvPnYryLeA\n"
+"Gnhko2WwmbUDGicdnY4j2VSFU15oxBjln65IznZJyiZM4zGE1GkNZzKGmQY=\n"
+"-----END ED25519 CERT-----\n"
+"master-key-ed25519 wUCdaApa11Hp1gvdBWBFEA6TEncXcSpa0fN62MvpHhk\n"
+"or-address [::]:5001\n"
+"platform Tor 0.4.9.0-alpha-dev on Linux\n"
+"proto Conflux=1 Cons=1-2 Desc=1-2 DirCache=2 FlowCtrl=1-2 HSDir=2 "
+ "HSIntro=4-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Padding=2 "
+ "Relay=1-4\n"
+"published 2024-06-24 21:34:22\n"
+"fingerprint FD3A 6FA4 E716 C379 3CBA FEC3 39EA 01C8 B49D 7189\n"
+"uptime 0\n"
+"bandwidth 1073741824 1073741824 0\n"
+"extra-info-digest 9946CAC41485EDFFDD83F7DAF1A088C30563126C "
+ "lpAMRlRTy9QR2xVCu1nnnxOHA2I05TTKvCSPPcr1geo\n"
+"caches-extra-info\n"
+"signing-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBALcIIij7gNpvSZPvaCLDDNyyQZq7fR0aXiHgmiIc5hYVcBl+zF5sTX6a\n"
+"jQF+GQdbSHcRzA1IMWPXnA7+nGOxSNayrQwExuf7ESsBaQHU81/dmV+rgTwtcd3K\n"
+"9lobTQUm+idLvGjVF5P1XJkduPvURIgpIfXT1ZHJUQhwxWSw8MmnAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"ntor-onion-key-crosscert 1\n"
+"-----BEGIN ED25519 CERT-----\n"
+"AQoAB0wmAcFAnWgKWtdR6dYL3QVgRRAOkxJ3F3EqWtHzetjL6R4ZAFPSCMLyQ82v\n"
+"dvcpZDa7C/qp8TsJn2Z8v77RjRc2QD1KYDzGfg5euwlB1lu8+IR38l3mmC1PXXhe\n"
+"ZB84q4aUdAA=\n"
+"-----END ED25519 CERT-----\n"
+"hidden-service-dir\n"
+"contact auth1@test.test\n"
+"ntor-onion-key m0dedSB2vjtvz08bNu+LCdIApVuspRlzXbsphXZ62zQ\n"
+"reject *:*\n"
+"tunnelled-dir-server\n"
+"router-sig-ed25519 VMwmiN9KhWWFSFSuVZxG1g46mb2QhMhv0UlatvPKyAV+1jPl"
+ "EbDFaO1Qur0335Rn0ToysC6UqB1p78pefX67Aw\n"
+"router-signature\n"
+"-----BEGIN SIGNATURE-----\n"
+"q9Hxy4FJVIK2ks/ByBv8P1p7Pc68ie/TTlDN+tce9opPlijy9+ze9/Gd2SKonRm1\n"
+"J+WBj/kKYKw+YoUExIT0qMfa6QTCOe/ecp1sNmgeW0YfloP4Nv8goi3S0k4yrPk/\n"
+"qw6TIXGYJpvrdR1Qe7+MEl2K1Okqsy5amtOU400lYRA=\n"
+"-----END SIGNATURE-----\n"
+ ;
+
+static void
+test_dir_parse_no_onion_keyrouter_list(void *arg)
+{
+ (void) arg;
+
+ routerinfo_t *ri =
+ router_parse_entry_from_string(ROUTERDESC_NO_ONION_KEY, NULL,
+ 0, 1, 0, NULL);
+
+ tt_assert(ri);
+ tt_assert(ri->tap_onion_pkey == NULL);
+
+ done:
+ routerinfo_free(ri);
+}
+
static download_status_t dls_minimal;
static download_status_t dls_maximal;
static download_status_t dls_bad_fingerprint;
@@ -4079,7 +4147,7 @@ gen_routerstatus_for_umbw(int idx, time_t now)
if (vrs) {
vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t));
tor_asprintf(&vrs->microdesc->microdesc_hash_line,
- "m 25,26,27,28 "
+ "m 32,33 "
"sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa%d\n",
idx);
}
@@ -4103,9 +4171,8 @@ vote_tweaks_for_umbw(networkstatus_t *v, int voter, time_t now)
tt_assert(v->supported_methods);
SMARTLIST_FOREACH(v->supported_methods, char *, c, tor_free(c));
smartlist_clear(v->supported_methods);
- /* Method 17 is MIN_METHOD_TO_CLIP_UNMEASURED_BW_KB */
smartlist_split_string(v->supported_methods,
- "25 26 27 28",
+ "32 33",
NULL, 0, -1);
/* If we're using a non-default clip bandwidth, add it to net_params */
if (alternate_clip_bw > 0) {
@@ -7228,6 +7295,7 @@ struct testcase_t dir_tests[] = {
DIR(routerinfo_parsing, 0),
DIR(extrainfo_parsing, 0),
DIR(parse_router_list, TT_FORK),
+ DIR(parse_no_onion_keyrouter_list, TT_FORK),
DIR(load_routers, TT_FORK),
DIR(load_extrainfo, TT_FORK),
DIR(getinfo_extra, 0),
diff --git a/src/test/test_dirvote.c b/src/test/test_dirvote.c
index 2b53955107..bb7e6fdf10 100644
--- a/src/test/test_dirvote.c
+++ b/src/test/test_dirvote.c
@@ -656,30 +656,6 @@ done:
ROUTER_FREE(pppp);
}
-static void
-test_dirvote_parse_param_buggy(void *arg)
-{
- (void)arg;
-
- /* Tests for behavior with bug emulation to migrate away from bug 19011. */
- tt_i64_op(extract_param_buggy("blah blah", "bwweightscale", 10000),
- OP_EQ, 10000);
- tt_i64_op(extract_param_buggy("bwweightscale=7", "bwweightscale", 10000),
- OP_EQ, 7);
- tt_i64_op(extract_param_buggy("bwweightscale=7 foo=9",
- "bwweightscale", 10000),
- OP_EQ, 10000);
- tt_i64_op(extract_param_buggy("foo=7 bwweightscale=777 bar=9",
- "bwweightscale", 10000),
- OP_EQ, 10000);
- tt_i64_op(extract_param_buggy("foo=7 bwweightscale=1234",
- "bwweightscale", 10000),
- OP_EQ, 1234);
-
- done:
- ;
-}
-
#define NODE(name, flags) \
{ \
#name, test_dirvote_##name, (flags), NULL, NULL \
@@ -692,5 +668,4 @@ struct testcase_t dirvote_tests[] = {
NODE(get_sybil_by_ip_version_ipv4, TT_FORK),
NODE(get_sybil_by_ip_version_ipv6, TT_FORK),
NODE(get_all_possible_sybil, TT_FORK),
- NODE(parse_param_buggy, 0),
END_OF_TESTCASES};
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index 118b66dfa7..7184e49c8c 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -1942,8 +1942,10 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg)
tt_ptr_op(g2, OP_EQ, g);
/* But if we impose a restriction, we don't get the same guard */
+ get_options_mutable()->EnforceDistinctSubnets = 0;
rst = guard_create_exit_restriction((uint8_t*)g->identity);
g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, rst, &state);
+ tt_assert(g2);
tt_ptr_op(g2, OP_NE, g);
done:
diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c
index a02dca1b60..ac6f940cc7 100644
--- a/src/test/test_hs_client.c
+++ b/src/test/test_hs_client.c
@@ -1192,7 +1192,7 @@ test_socks_hs_errors(void *arg)
ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
/* Code path will log this exit so build it. */
ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest,
- NULL, NULL, NULL, &addr,
+ NULL, NULL, &addr,
4242, NULL, false);
/* Attach socks connection to this rendezvous circuit. */
ocirc->p_streams = ENTRY_TO_EDGE_CONN(socks_conn);
@@ -1287,7 +1287,7 @@ test_close_intro_circuit_failure(void *arg)
ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
/* Code path will log this exit so build it. */
ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest,
- NULL, NULL, NULL, &addr,
+ NULL, NULL, &addr,
4242, NULL, false);
ed25519_pubkey_copy(&ocirc->hs_ident->intro_auth_pk, &intro_kp.pubkey);
@@ -1314,7 +1314,7 @@ test_close_intro_circuit_failure(void *arg)
ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
/* Code path will log this exit so build it. */
ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest,
- NULL, NULL, NULL, &addr,
+ NULL, NULL, &addr,
4242, NULL, false);
ed25519_pubkey_copy(&ocirc->hs_ident->intro_auth_pk, &intro_kp.pubkey);
@@ -1337,7 +1337,7 @@ test_close_intro_circuit_failure(void *arg)
ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
/* Code path will log this exit so build it. */
ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest,
- NULL, NULL, NULL, &addr,
+ NULL, NULL, &addr,
4242, NULL, false);
ed25519_pubkey_copy(&ocirc->hs_ident->intro_auth_pk, &intro_kp.pubkey);
diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c
index dc60c7ca29..6f254f16e8 100644
--- a/src/test/test_hs_service.c
+++ b/src/test/test_hs_service.c
@@ -1605,7 +1605,6 @@ test_build_update_descriptors(void *arg)
tt_int_op(ret, OP_EQ, 0);
ri.onion_curve25519_pkey =
tor_malloc_zero(sizeof(curve25519_public_key_t));
- ri.onion_pkey = tor_malloc_zero(140);
curve25519_public_key_generate(ri.onion_curve25519_pkey,
&curve25519_secret_key);
memset(ri.cache_info.identity_digest, 'A', DIGEST_LEN);
@@ -1631,7 +1630,6 @@ test_build_update_descriptors(void *arg)
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);
expect_log_msg_containing("just picked 1 intro points and wanted 3 for next "
"descriptor. It currently has 0 intro points. "
"Launching ESTABLISH_INTRO circuit shortly.");
diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c
index c564805ecf..1209811fb9 100644
--- a/src/test/test_microdesc.c
+++ b/src/test/test_microdesc.c
@@ -366,37 +366,14 @@ static const char test_ri[] =
"iFJkKxxDx7ksxX0zdl7aPT4ORFEuRhCYS6el7YJmoyg=\n"
"-----END SIGNATURE-----\n";
-static const char test_md2_25[] =
+static const char test_md2_withfamily_33[] =
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n"
"83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n"
"nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA=\n"
- "p accept 1-65535\n"
- "id ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n";
-
-static const char test_md2_withfamily_28[] =
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n"
- "83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n"
- "nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA=\n"
- "family OtherNode !Strange\n"
- "p accept 1-65535\n"
- "id ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n";
-
-static const char test_md2_withfamily_29[] =
- "onion-key\n"
- "-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n"
- "83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n"
- "nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n"
- "-----END RSA PUBLIC KEY-----\n"
- "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA=\n"
+ "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA\n"
"family !Strange $D219590AC9513BCDEBBA9AB721007A4CC01BBAE3 othernode\n"
"p accept 1-65535\n"
"id ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n";
@@ -411,21 +388,12 @@ test_md_generate(void *arg)
ri = router_parse_entry_from_string(test_ri, NULL, 0, 0, NULL, NULL);
tt_assert(ri);
- md = dirvote_create_microdescriptor(ri, 25);
- tt_str_op(md->body, OP_EQ, test_md2_25);
- tt_assert(ed25519_pubkey_eq(md->ed25519_identity_pkey,
- &ri->cache_info.signing_key_cert->signing_key));
-
// Try family encoding.
microdesc_free(md);
ri->declared_family = smartlist_new();
smartlist_add_strdup(ri->declared_family, "OtherNode !Strange");
- md = dirvote_create_microdescriptor(ri, 28);
- tt_str_op(md->body, OP_EQ, test_md2_withfamily_28);
-
- microdesc_free(md);
- md = dirvote_create_microdescriptor(ri, 29);
- tt_str_op(md->body, OP_EQ, test_md2_withfamily_29);
+ md = dirvote_create_microdescriptor(ri, 33);
+ tt_str_op(md->body, OP_EQ, test_md2_withfamily_33);
done:
microdesc_free(md);
@@ -792,6 +760,35 @@ test_md_parse_id_ed25519(void *arg)
teardown_capture_of_logs();
}
+static void
+test_md_parse_no_onion_key(void *arg)
+{
+ (void)arg;
+
+ /* A correct MD with no onion key. */
+ const char GOOD_MD[] =
+ "onion-key\n"
+ "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n"
+ "id ed25519 VGhpcyBpc24ndCBhY3R1YWxseSBhIHB1YmxpYyBrZXk\n";
+
+ smartlist_t *mds = NULL;
+
+ mds = microdescs_parse_from_string(GOOD_MD,
+ NULL, 1, SAVED_NOWHERE, NULL);
+ tt_assert(mds);
+ tt_int_op(smartlist_len(mds), OP_EQ, 1);
+ const microdesc_t *md = smartlist_get(mds, 0);
+ tt_mem_op(md->ed25519_identity_pkey, OP_EQ,
+ "This isn't actually a public key", ED25519_PUBKEY_LEN);
+
+ done:
+ if (mds) {
+ SMARTLIST_FOREACH(mds, microdesc_t *, m, microdesc_free(m));
+ smartlist_free(mds);
+ }
+ teardown_capture_of_logs();
+}
+
static int mock_rgsbd_called = 0;
static routerstatus_t *mock_rgsbd_val_a = NULL;
static routerstatus_t *mock_rgsbd_val_b = NULL;
@@ -926,6 +923,7 @@ struct testcase_t microdesc_tests[] = {
{ "generate", test_md_generate, 0, NULL, NULL },
{ "parse", test_md_parse, 0, NULL, NULL },
{ "parse_id_ed25519", test_md_parse_id_ed25519, 0, NULL, NULL },
+ { "parse_no_onion_key", test_md_parse_no_onion_key, 0, NULL, NULL },
{ "reject_cache", test_md_reject_cache, TT_FORK, NULL, NULL },
{ "corrupt_desc", test_md_corrupt_desc, TT_FORK, NULL, NULL },
END_OF_TESTCASES
diff --git a/src/test/test_protover.c b/src/test/test_protover.c
index 9d14fd678a..9a10cf649f 100644
--- a/src/test/test_protover.c
+++ b/src/test/test_protover.c
@@ -329,7 +329,7 @@ test_protover_supports_version(void *arg)
* headers. */
#define PROTOVER_LINKAUTH_V1 1
#define PROTOVER_LINKAUTH_V2 2
-#define PROTOVER_RELAY_V1 1
+#define PROTOVER_RELAY_V2 2
/* Deprecated HSIntro versions */
#define PROTOVER_HS_INTRO_DEPRECATED_1 1
@@ -397,7 +397,7 @@ test_protover_supported_protocols(void *arg)
/* Relay protovers do not appear anywhere in the code. */
tt_assert(protocol_list_supports_protocol(supported_protocols,
PRT_RELAY,
- PROTOVER_RELAY_V1));
+ PROTOVER_RELAY_V2));
tt_assert(protocol_list_supports_protocol(supported_protocols,
PRT_RELAY,
PROTOVER_RELAY_EXTEND2));
diff --git a/src/test/test_relaycell.c b/src/test/test_relaycell.c
index 05e2b2e347..6edc1030f9 100644
--- a/src/test/test_relaycell.c
+++ b/src/test/test_relaycell.c
@@ -988,7 +988,7 @@ test_relaycell_resolved(void *arg)
tt_int_op(r, OP_EQ, 0);
ASSERT_MARK_CALLED(END_STREAM_REASON_DONE|
END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
- ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_ERROR, NULL, -1, -1);
+ ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_NOERROR, NULL, -1, -1);
/* If we wanted hostnames, we report nothing, since we only had IPs. */
MOCK_RESET();
diff --git a/src/test/test_router.c b/src/test/test_router.c
index 47084bba01..64efedfa46 100644
--- a/src/test/test_router.c
+++ b/src/test/test_router.c
@@ -60,8 +60,8 @@ rtr_tests_gen_routerinfo(crypto_pk_t *ident_key, crypto_pk_t *tap_key)
mock_routerinfo->identity_pkey = crypto_pk_dup_key(ident_key);
mock_routerinfo->protocol_list =
tor_strdup("Cons=1-2 Desc=1-2 DirCache=1-2");
- router_set_rsa_onion_pkey(tap_key, &mock_routerinfo->onion_pkey,
- &mock_routerinfo->onion_pkey_len);
+ router_set_rsa_onion_pkey(tap_key, &mock_routerinfo->tap_onion_pkey,
+ &mock_routerinfo->tap_onion_pkey_len);
mock_routerinfo->bandwidthrate = 9001;
mock_routerinfo->bandwidthburst = 9002;
diff --git a/src/test/test_sandbox.c b/src/test/test_sandbox.c
index 64182ecc91..edb5c0c232 100644
--- a/src/test/test_sandbox.c
+++ b/src/test/test_sandbox.c
@@ -364,22 +364,32 @@ test_sandbox_crypto_equix(void *arg)
struct testcase_t sandbox_tests[] = {
SANDBOX_TEST(is_active, TT_FORK),
-/* When Tor is built with fragile compiler-hardening the sandbox is unable to
- * filter requests to open files or directories (on systems where glibc uses
- * the "open" system call to provide this functionality), as doing so would
+/* When Tor is built with fragile compiler-hardening the sandbox is usually
+ * unable to filter requests to open files or directories, as doing so would
* interfere with the address sanitizer as it retrieves information about the
* running process via the filesystem. Skip these tests in that case as the
* corresponding functions are likely to have no effect and this will cause the
* tests to fail. */
#ifdef ENABLE_FRAGILE_HARDENING
SANDBOX_TEST_SKIPPED(open_filename),
+ SANDBOX_TEST_SKIPPED(openat_filename),
SANDBOX_TEST_SKIPPED(opendir_dirname),
#else
SANDBOX_TEST_IN_SANDBOX(open_filename),
- SANDBOX_TEST_IN_SANDBOX(opendir_dirname),
+ SANDBOX_TEST_IN_SANDBOX(openat_filename),
#endif /* defined(ENABLE_FRAGILE_HARDENING) */
- SANDBOX_TEST_IN_SANDBOX(openat_filename),
+ /* Ok why... Quick answer is #40918. This has been failing on Debian SID
+ * making us unable to have nightly packages which is a problem as we have
+ * several relay operators using them and actively reporting us issues with
+ * them. This test fails due to the sandbox denying it.
+ *
+ * We are deprecating C-tor slowly and honestly, the Sandbox feature has
+ * always been a source of pain and unhappiness. Disable this as finding why,
+ * fixing it and hoping it doesn't come back will mostly be a waste of our
+ * time at this point. */
+ SANDBOX_TEST_SKIPPED(opendir_dirname),
+
SANDBOX_TEST_IN_SANDBOX(chmod_filename),
SANDBOX_TEST_IN_SANDBOX(chown_filename),
SANDBOX_TEST_IN_SANDBOX(rename_filename),
diff --git a/src/test/test_socks.c b/src/test/test_socks.c
index 94c772419b..b642d24a8b 100644
--- a/src/test/test_socks.c
+++ b/src/test/test_socks.c
@@ -596,6 +596,70 @@ test_socks_5_authenticate_with_data(void *ptr)
;
}
+/** Perform SOCKS 5 authentication and send data all in one go */
+static void
+test_socks_5_authenticate_with_rpc_objectid(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ /* SOCKS 5 Negotiate username/password authentication */
+ ADD_DATA(buf, "\x05\x01\x02");
+ tt_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ /* SOCKS 5 Send username/password as a RPC ObjectID (see prop351). This
+ * should be invalid as in only the objectID prefix without a version. */
+ ADD_DATA(buf, "\x01\x08<torS0X>\x08password");
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), OP_EQ, -1);
+
+ buf_clear(buf);
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Negotiate username/password authentication */
+ ADD_DATA(buf, "\x05\x01\x02");
+ tt_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ /* SOCKS 5 Send username/password as a RPC ObjectID (see prop351). This
+ * should be valid because it is exactly the prefix and version without an
+ * object ID. */
+ ADD_DATA(buf, "\x01\x09<torS0X>0\x08password");
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), OP_EQ, 0);
+
+ buf_clear(buf);
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Negotiate username/password authentication */
+ ADD_DATA(buf, "\x05\x01\x02");
+ tt_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ /* SOCKS 5 Send username/password as a RPC ObjectID (see prop351). This
+ * should be invalid as an unknown version per prop351. */
+ ADD_DATA(buf, "\x01\x09<torS0X>1\x08password");
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), OP_EQ, -1);
+
+ buf_clear(buf);
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Negotiate username/password authentication */
+ ADD_DATA(buf, "\x05\x01\x02");
+ tt_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ /* SOCKS 5 Send username/password as a RPC ObjectID (see prop351). This
+ * should be invalid because there is an objectID after the prefix. */
+ ADD_DATA(buf, "\x01\x0C<torS0X>0abc\x08password");
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), OP_EQ, -1);
+
+ done:
+ ;
+}
+
/** Try to negotiate an unsupported authentication type */
static void
test_socks_5_auth_unsupported_type(void *ptr)
@@ -1112,6 +1176,7 @@ struct testcase_t socks_tests[] = {
SOCKSENT(5_authenticate),
SOCKSENT(5_authenticate_empty_user_pass),
SOCKSENT(5_authenticate_with_data),
+ SOCKSENT(5_authenticate_with_rpc_objectid),
SOCKSENT(5_malformed_commands),
SOCKSENT(5_bad_arguments),
diff --git a/src/test/test_status.c b/src/test/test_status.c
index 1d371645ae..4ceb81f3a5 100644
--- a/src/test/test_status.c
+++ b/src/test/test_status.c
@@ -333,10 +333,12 @@ test_status_hb_not_in_consensus(void *arg)
status_hb_not_in_consensus_server_mode);
log_global_min_severity_ = LOG_DEBUG;
- onion_handshakes_requested[ONION_HANDSHAKE_TYPE_TAP] = 1;
onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_TAP] = 1;
- onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR] = 1;
- onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR] = 1;
+ onion_handshakes_requested[ONION_HANDSHAKE_TYPE_TAP] = 2;
+ onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR] = 3;
+ onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR] = 4;
+ onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR_V3] = 5;
+ onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR_V3] = 6;
expected = 0;
setup_capture_of_logs(LOG_INFO);
@@ -352,8 +354,8 @@ test_status_hb_not_in_consensus(void *arg)
"I've made 0 connections with IPv4 and 0 with IPv6.\n");
expect_log_msg("Average packaged cell fullness: 100.000%. "
"TLS write overhead: 0%\n");
- expect_log_msg("Circuit handshake stats since last time: 1/1 TAP, "
- "1/1 NTor.\n");
+ expect_log_msg("Circuit handshake stats since last time: 1/2 TAP, "
+ "3/4 NTor, 5/6 NTor (v3).\n");
expect_log_msg("Since startup we initiated 0 and received 0 v1 "
"connections; initiated 0 and received 0 v2 connections; "
"initiated 0 and received 0 v3 connections; "
@@ -363,6 +365,7 @@ test_status_hb_not_in_consensus(void *arg)
"with too many cells, [DoSCircuitCreationEnabled disabled], "
"[DoSConnectionEnabled disabled], "
"[DoSRefuseSingleHopClientRendezvous disabled], "
+ "[DoSStreamCreationEnabled disabled], "
"0 INTRODUCE2 rejected.\n");
tt_int_op(mock_saved_log_n_entries(), OP_EQ, 6);