aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml61
-rw-r--r--ChangeLog2
-rw-r--r--ReleaseNotes2
-rw-r--r--changes/bug326714
-rw-r--r--changes/bug401133
-rw-r--r--changes/bug401294
-rw-r--r--changes/bug401414
-rw-r--r--changes/bug53046
-rw-r--r--changes/ticket250616
-rw-r--r--changes/ticket321814
-rw-r--r--changes/ticket400535
-rw-r--r--changes/ticket400733
-rw-r--r--changes/ticket401243
-rw-r--r--changes/ticket401353
-rw-r--r--changes/ticket401376
-rw-r--r--changes/ticket401386
-rw-r--r--changes/ticket401397
-rw-r--r--changes/ticket401592
-rw-r--r--changes/ticket71935
-rw-r--r--configure.ac64
-rw-r--r--doc/man/tor-gencert.1.txt7
-rw-r--r--doc/man/tor-print-ed-signing-cert.1.txt4
-rw-r--r--doc/man/tor-resolve.1.txt4
-rw-r--r--doc/man/tor.1.txt37
-rw-r--r--doc/man/torify.1.txt4
-rw-r--r--doc/state-contents.txt225
-rw-r--r--doc/ticket401363
-rwxr-xr-xscripts/ci/ci-driver.sh20
-rw-r--r--scripts/maint/practracker/exceptions.txt4
-rw-r--r--src/app/config/config.c50
-rw-r--r--src/app/config/or_options_st.h34
-rw-r--r--src/app/config/or_state_st.h8
-rw-r--r--src/app/config/resolve_addr.c4
-rw-r--r--src/app/config/statefile.c77
-rw-r--r--src/app/config/statefile.h1
-rw-r--r--src/app/main/main.c2
-rw-r--r--src/app/main/subsysmgr.c2
-rw-r--r--src/core/mainloop/connection.c17
-rw-r--r--src/core/or/channel.c13
-rw-r--r--src/core/or/channel.h2
-rw-r--r--src/core/or/channeltls.c25
-rw-r--r--src/core/or/circuitbuild.c28
-rw-r--r--src/core/or/circuitpadding.c1
-rw-r--r--src/core/or/circuituse.c25
-rw-r--r--src/core/or/or_connection_st.h5
-rw-r--r--src/feature/client/transports.c74
-rw-r--r--src/feature/client/transports.h2
-rw-r--r--src/feature/control/control_bootstrap.c12
-rw-r--r--src/feature/dirauth/dirvote.c174
-rw-r--r--src/feature/dirauth/dirvote.h18
-rw-r--r--src/feature/dircache/dircache_stub.c2
-rw-r--r--src/feature/dirclient/dirclient.c29
-rw-r--r--src/feature/hs/hs_circuitmap.c2
-rw-r--r--src/feature/hs/hs_service.c9
-rw-r--r--src/feature/hs_common/shared_random_client.c4
-rw-r--r--src/feature/keymgt/loadkey.c4
-rw-r--r--src/feature/nodelist/dirlist.c4
-rw-r--r--src/feature/nodelist/dirlist.h5
-rw-r--r--src/feature/nodelist/networkstatus.c7
-rw-r--r--src/feature/nodelist/nodelist.c2
-rw-r--r--src/feature/nodelist/torcert.c12
-rw-r--r--src/feature/nodelist/torcert.h12
-rw-r--r--src/feature/relay/circuitbuild_relay.c1
-rw-r--r--src/feature/relay/router.c7
-rw-r--r--src/feature/relay/routerkeys.c14
-rw-r--r--src/lib/fs/path.c13
-rw-r--r--src/lib/log/log.c81
-rw-r--r--src/lib/log/log.h4
-rw-r--r--src/lib/net/address.c4
-rw-r--r--src/test/conf_examples/large_1/expected2
-rw-r--r--src/test/conf_examples/large_1/expected_no_dirauth2
-rw-r--r--src/test/conf_examples/large_1/torrc1
-rw-r--r--src/test/hs_test_helpers.c8
-rw-r--r--src/test/include.am2
-rw-r--r--src/test/test.c2
-rw-r--r--src/test/test.h2
-rw-r--r--src/test/test_channel.c20
-rw-r--r--src/test/test_circuitbuild.c2
-rw-r--r--src/test/test_connection.c13
-rw-r--r--src/test/test_dir.c4
-rw-r--r--src/test/test_dirvote.c671
-rw-r--r--src/test/test_hs_descriptor.c9
-rw-r--r--src/test/test_link_handshake.c2
-rw-r--r--src/test/test_routerkeys.c2
-rw-r--r--src/test/test_statefile.c56
85 files changed, 1695 insertions, 401 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 48bcf6b000..ba61c71b2b 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -37,7 +37,7 @@ variables:
paths:
- artifacts/
-# This template
+# This template should be usable on any system that's based on apt.
.apt-template: &apt-template |
export LC_ALL=C.UTF-8
echo Etc/UTC > /etc/timezone
@@ -54,6 +54,7 @@ variables:
apt-get update -qq
apt-get upgrade -qy
+# This template sets us up for Debian system in particular.
.debian-template: &debian-template
<<: *artifacts-template
variables:
@@ -88,6 +89,7 @@ variables:
- if [ "$DOXYGEN" = yes ]; then apt-get install doxygen; fi
- if [ "$STEM" = yes ]; then apt-get install timelimit; fi
- if [ "$CC" = clang ]; then apt-get install clang; fi
+ - if [ "$NSS" = yes ]; then apt-get install libnss3 libnss3-dev; fi
# TODO: This next line should not be debian-only.
- if [ "$STEM" = yes ]; then git clone --depth 1 https://git.torproject.org/stem.git ; export STEM_PATH="$(pwd)/stem"; fi
# TODO: This next line should not be debian-only.
@@ -111,6 +113,7 @@ debian-hardened:
image: debian:testing
<<: *debian-template
variables:
+ ALL_BUGS_ARE_FATAL: "yes"
HARDENING: "yes"
CC: "clang"
script:
@@ -153,7 +156,9 @@ debian-integration:
variables:
CHECK: "no"
CHUTNEY: "yes"
+ CHUTNEY_MAKE_TARGET: "test-network-all"
STEM: "yes"
+ ALL_BUGS_ARE_FATAL: "yes"
script:
- ./scripts/ci/ci-driver.sh
@@ -167,3 +172,57 @@ debian-tracing:
CHECK: "no"
script:
- ./scripts/ci/ci-driver.sh
+ # Ensure that we only run tracing when it's implemented.
+ #
+ # Once versions before 0.4.5 are obsolete, we can remove this test.
+ rules:
+ # This first "if" check prevents us from running a duplicate version of
+ # this pipeline whenever we push and create an MR. I don't understand why
+ # it is necessary, though the following URL purports to explain:
+ #
+ # https://docs.gitlab.com/ee/ci/yaml/#prevent-duplicate-pipelines
+ - if: '$CI_PIPELINE_SOURCE == "push"'
+ exists:
+ - src/lib/trace/trace_sys.c
+
+#####
+# No-authority mode
+debian-disable-dirauth:
+ image: debian:stable
+ <<: *debian-template
+ variables:
+ DISABLE_DIRAUTH: "yes"
+ script:
+ - ./scripts/ci/ci-driver.sh
+
+#####
+# No-relay mode
+debian-disable-relay:
+ image: debian:stable
+ <<: *debian-template
+ variables:
+ DISABLE_RELAY: "yes"
+ script:
+ - ./scripts/ci/ci-driver.sh
+ # Ensure that we only run tracing when it's implemented.
+ #
+ # Once versions before 0.4.3 are obsolete, we can remove this test.
+ rules:
+ # This first "if" check prevents us from running a duplicate version of
+ # this pipeline whenever we push and create an MR. I don't understand why
+ # it is necessary, though the following URL purports to explain:
+ #
+ # https://docs.gitlab.com/ee/ci/yaml/#prevent-duplicate-pipelines
+ - if: '$CI_PIPELINE_SOURCE == "push"'
+ exists:
+ - src/feature/relay/relay_stub.c
+
+#####
+# NSS check on debian
+debian-nss:
+ image: debian:stable
+ <<: *debian-template
+ variables:
+ NSS: "yes"
+ script:
+ - ./scripts/ci/ci-driver.sh
diff --git a/ChangeLog b/ChangeLog
index d4c764fa21..0420bd715c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -28794,7 +28794,7 @@ Changes in version 0.2.0.33 - 2009-01-21
- Implement the 0x20 hack to better resist DNS poisoning: set the
case on outgoing DNS requests randomly, and reject responses that do
not match the case correctly. This logic can be disabled with the
- ServerDNSRamdomizeCase setting, if you are using one of the 0.3%
+ ServerDNSRandomizeCase setting, if you are using one of the 0.3%
of servers that do not reliably preserve case in replies. See
"Increased DNS Forgery Resistance through 0x20-Bit Encoding"
for more info.
diff --git a/ReleaseNotes b/ReleaseNotes
index 8755024e9e..3febaaa853 100644
--- a/ReleaseNotes
+++ b/ReleaseNotes
@@ -22188,7 +22188,7 @@ Changes in version 0.2.0.33 - 2009-01-21
- Implement the 0x20 hack to better resist DNS poisoning: set the
case on outgoing DNS requests randomly, and reject responses that do
not match the case correctly. This logic can be disabled with the
- ServerDNSRamdomizeCase setting, if you are using one of the 0.3%
+ ServerDNSRandomizeCase setting, if you are using one of the 0.3%
of servers that do not reliably preserve case in replies. See
"Increased DNS Forgery Resistance through 0x20-Bit Encoding"
for more info.
diff --git a/changes/bug32671 b/changes/bug32671
new file mode 100644
index 0000000000..aa43d46543
--- /dev/null
+++ b/changes/bug32671
@@ -0,0 +1,4 @@
+ o Minor bugfixes (circuit padding):
+ - When circpad_send_padding_cell_for_callback is called,
+ `is_padding_timer_scheduled` flag was not reset. Now it is set to 0 at
+ the top of that function. Fixes bug 32671; bugfix on 0.4.0.1-alpha.
diff --git a/changes/bug40113 b/changes/bug40113
new file mode 100644
index 0000000000..adf4634097
--- /dev/null
+++ b/changes/bug40113
@@ -0,0 +1,3 @@
+ o Minor bugfixes (compilation):
+ - Resolve a compilation warning that could occur in test_connection.c.
+ Fixes bug 40113; bugfix on 0.2.9.3-alpha.
diff --git a/changes/bug40129 b/changes/bug40129
new file mode 100644
index 0000000000..80de5ef355
--- /dev/null
+++ b/changes/bug40129
@@ -0,0 +1,4 @@
+ o Minor bugfixes (compilation):
+ - Fix compiler warnings that would occur when building with
+ "--enable-all-bugs-are-fatal" and "--disable-module-relay"
+ at the same time. Fixes bug 40129; bugfix on 0.4.4.1-alpha.
diff --git a/changes/bug40141 b/changes/bug40141
new file mode 100644
index 0000000000..a766993b32
--- /dev/null
+++ b/changes/bug40141
@@ -0,0 +1,4 @@
+ o Minor bugfixes (configuration):
+ - Fix bug where %including a pattern ending with */ would include files
+ and folders (instead of folders only) in versions of glibc < 2.19.
+ Fixes bug 40141; bugfix on 0.4.5.0-alpha-dev. Patch by Daniel Pinto.
diff --git a/changes/bug5304 b/changes/bug5304
new file mode 100644
index 0000000000..9afa838129
--- /dev/null
+++ b/changes/bug5304
@@ -0,0 +1,6 @@
+ o Minor features (pluggable transports):
+ - Added option OutboundBindAddressPT to torrc. This option allows users to
+ specify which IPv4 and IPv6 address they want pluggable transports to use
+ for outgoing IP packets. Tor does not have a way to enforce that the pluggable
+ transport honors this option so each pluggable transport will have to
+ implement support for this feature. Closes ticket 5304.
diff --git a/changes/ticket25061 b/changes/ticket25061
new file mode 100644
index 0000000000..9ab0e660bb
--- /dev/null
+++ b/changes/ticket25061
@@ -0,0 +1,6 @@
+ o Minor features (bootstrap reporting):
+ - When reporting bootstrapping status on a relay, do not consider
+ connections that have never been the target of an origin circuit.
+ Previously, all connection failures were treated as potential
+ bootstrapping failures, including those that had been opened because of
+ client requests. Closes ticket 25061.
diff --git a/changes/ticket32181 b/changes/ticket32181
new file mode 100644
index 0000000000..c0bf3d50e1
--- /dev/null
+++ b/changes/ticket32181
@@ -0,0 +1,4 @@
+ o Removed features:
+ - We no longer ship support for the Android logging API. Modern
+ versions of Android can use the syslog API instead.
+ Closes ticket 32181.
diff --git a/changes/ticket40053 b/changes/ticket40053
new file mode 100644
index 0000000000..ec46ff269b
--- /dev/null
+++ b/changes/ticket40053
@@ -0,0 +1,5 @@
+ o Minor features (logging):
+ - Consider 301 as an error like a 404 when processing the response to a
+ request for a group of server descriptors or an extrainfo documents.
+ Closes ticket 40053.
+
diff --git a/changes/ticket40073 b/changes/ticket40073
new file mode 100644
index 0000000000..30b028c042
--- /dev/null
+++ b/changes/ticket40073
@@ -0,0 +1,3 @@
+ o Minor bugfixes (relay configuration, crash):
+ - Avoid a fatal assert() when failing to create a listener connection for an
+ address that was in use. Fixes bug 40073; bugfix on 0.3.5.1-alpha.
diff --git a/changes/ticket40124 b/changes/ticket40124
new file mode 100644
index 0000000000..e412c401df
--- /dev/null
+++ b/changes/ticket40124
@@ -0,0 +1,3 @@
+ o Minor bugfixes (spec conformance):
+ - Use the correct key type when generating signing->link
+ certificates. Fixes bug 40124; bugfix on 0.2.7.2-alpha.
diff --git a/changes/ticket40135 b/changes/ticket40135
new file mode 100644
index 0000000000..9b60b4f655
--- /dev/null
+++ b/changes/ticket40135
@@ -0,0 +1,3 @@
+ o Minor bugfix (logging):
+ - Remove a debug logging statement that uselessly spam the logs. Fixes bug
+ 40135; bugfix on 0.3.5.0-alpha.
diff --git a/changes/ticket40137 b/changes/ticket40137
new file mode 100644
index 0000000000..056f1bc4a5
--- /dev/null
+++ b/changes/ticket40137
@@ -0,0 +1,6 @@
+ o Minor features (state):
+ - When loading the state file, remove entries from the statefile that
+ have been obsolete for a long time. Ordinarily Tor preserves
+ unrecognized entries in order to keep forward-compatibility, but
+ these statefile entries have not actually been used in any release
+ since before the 0.3.5.x. Closes ticket 40137.
diff --git a/changes/ticket40138 b/changes/ticket40138
new file mode 100644
index 0000000000..6facbb819f
--- /dev/null
+++ b/changes/ticket40138
@@ -0,0 +1,6 @@
+ o Minor features (build):
+ - When running the configure script, try to detect version mismatches
+ between the openssl headers and libraries, and suggest that the
+ user should try "--with-openssl-dir". Closes 40138.
+ - If the configure script has given any warnings, remind the user about
+ them at the end of the script. Related to 40138.
diff --git a/changes/ticket40139 b/changes/ticket40139
new file mode 100644
index 0000000000..fce29233ef
--- /dev/null
+++ b/changes/ticket40139
@@ -0,0 +1,7 @@
+ o Removed features (network parameters):
+ - The "optimistic data" feature is now always on; there is no longer an
+ option to disable it from the torrc file or from the consensus
+ directory.
+ Closes part of 40139.
+ - The "usecreatefast" network parameter is now removed; there is no
+ longer an option for authorities to turn it off. Closes part of 40139.
diff --git a/changes/ticket40159 b/changes/ticket40159
new file mode 100644
index 0000000000..6484097544
--- /dev/null
+++ b/changes/ticket40159
@@ -0,0 +1,2 @@
+ o Minor features (logging):
+ - Print directory fetch information a single line. Closes ticket 40159.
diff --git a/changes/ticket7193 b/changes/ticket7193
new file mode 100644
index 0000000000..27faffa498
--- /dev/null
+++ b/changes/ticket7193
@@ -0,0 +1,5 @@
+ o Minor features (directory authority):
+ - When looking for possible sybil attacks, also consider IPv6 addresses.
+ Two routers are considered to have "the same" address by this metric
+ if they are in the same /64 network. Patch from Maurice Pibouin. Closes
+ ticket 7193.
diff --git a/configure.ac b/configure.ac
index 41c23e964c..9abc1e530a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -24,6 +24,11 @@ AC_DEFINE(APPROX_RELEASE_DATE, ["2020-06-09"], # for 0.4.5.0-alpha-dev
# "subdir-objects" means put .o files in the same directory as the .c files
AM_INIT_AUTOMAKE([foreign 1.11 subdir-objects -Wall -Werror])
+tor_ac_n_warnings=0
+tor_incr_n_warnings() {
+ tor_ac_n_warnings=`expr $tor_ac_n_warnings + 1`
+}
+
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_CONFIG_HEADERS([orconfig.h])
@@ -328,10 +333,6 @@ AM_CONDITIONAL([USE_ANDROID], [test "x$enable_android" = "xyes"])
if test "x$enable_android" = "xyes"; then
AC_DEFINE([USE_ANDROID], [1], [Compile with Android specific features enabled])
- dnl Check if the Android log library is available.
- AC_CHECK_HEADERS([android/log.h])
- AC_SEARCH_LIBS(__android_log_write, [log])
-
fi
dnl ---
@@ -432,6 +433,7 @@ AC_SUBST([PYTHON], [$tor_cv_PYTHON])
PYTHON="$tor_cv_PYTHON"
if test "x$PYTHON" = "x"; then
+ tor_incr_n_warnings
AC_MSG_WARN([Python 3 unavailable; some tests will not be run.])
fi
@@ -1044,8 +1046,6 @@ TOR_SEARCH_LIBRARY(openssl, $tryssldir, [-lssl -lcrypto $TOR_LIB_GDI $TOR_LIB_WS
[if (getenv("THIS_SHOULDNT_BE_SET_X201803")) SSL_CIPHER_get_id((void *)0);], [],
[/usr/local/opt/openssl /usr/local/openssl /usr/lib/openssl /usr/local/ssl /usr/lib/ssl /usr/local /opt/openssl])
-dnl XXXX check for OPENSSL_VERSION_NUMBER == SSLeay()
-
if test "$enable_static_openssl" = "yes"; then
if test "$tor_cv_library_openssl_dir" = "(system)"; then
AC_MSG_ERROR("You must specify an explicit --with-openssl-dir=x option when using --enable-static-openssl")
@@ -1057,7 +1057,7 @@ else
fi
AC_SUBST(TOR_OPENSSL_LIBS)
-dnl Now check for particular openssl functions.
+dnl Now validate openssl, and check for particular openssl functions.
save_LIBS="$LIBS"
save_LDFLAGS="$LDFLAGS"
save_CPPFLAGS="$CPPFLAGS"
@@ -1087,6 +1087,28 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
[ : ],
[ AC_MSG_ERROR([OpenSSL is built without full ECC support, including curves P256 and P224. You can specify a path to one with ECC support with --with-openssl-dir.]) ])
+dnl Let's see if we have a version mismatch between includes and libs.
+AC_MSG_CHECKING([for significant mismatch between openssl headers and libraries])
+ac_retval=foo
+AC_RUN_IFELSE([AC_LANG_SOURCE([AC_LANG_PROGRAM([[
+ #include <openssl/opensslv.h>
+ #include <openssl/crypto.h>
+]], [[
+ /* Include major, minor, and fix, but not patch or status. */
+ unsigned long mask = 0xfffff000;
+ unsigned long linking = OpenSSL_version_num() & mask;
+ unsigned long running = OPENSSL_VERSION_NUMBER & mask;
+ return !(linking==running);
+]])])], [openssl_ver_mismatch=no], [
+ # This is a kludge to figure out whether compilation failed, or whether
+ # running the program failed.
+ if test "$ac_retval" == "1"; then
+ openssl_ver_mismatch=inconclusive
+ else
+ openssl_ver_mismatch=yes
+ fi], [openssl_ver_mismatch=cross])
+AC_MSG_RESULT([$openssl_ver_mismatch])
+
AC_CHECK_MEMBERS([struct ssl_method_st.get_cipher_by_char], , ,
[#include <openssl/ssl.h>
])
@@ -1209,6 +1231,7 @@ else
have_lzma=no)
if test "x$have_lzma" = "xno" ; then
+ tor_incr_n_warnings
AC_MSG_WARN([Unable to find liblzma, $pkg_config_user_action, or set LZMA_CFLAGS and LZMA_LIBS.])
fi
fi
@@ -1241,6 +1264,7 @@ else
have_zstd=no)
if test "x$have_zstd" = "xno" ; then
+ tor_incr_n_warnings
AC_MSG_WARN([Unable to find libzstd, $pkg_config_user_action, or set ZSTD_CFLAGS and ZSTD_LIBS.])
fi
fi
@@ -1345,6 +1369,7 @@ fi
if test "$fragile_hardening" = "yes"; then
TOR_TRY_COMPILE_WITH_CFLAGS(-ftrapv, also_link, CFLAGS_FTRAPV="-ftrapv", true)
if test "$tor_cv_cflags__ftrapv" = "yes" && test "$tor_can_link__ftrapv" != "yes"; then
+ tor_incr_n_warnings
AC_MSG_WARN([The compiler supports -ftrapv, but for some reason I was not able to link with -ftrapv. Are you missing run-time support? Run-time hardening will not work as well as it should.])
fi
@@ -1885,6 +1910,7 @@ void try_atomic_init(struct x *xx)
if test "$tor_cv_stdatomic_works" = "yes"; then
AC_DEFINE(STDATOMIC_WORKS, 1, [Set to 1 if we can compile a simple stdatomic example.])
elif test "$ac_cv_header_stdatomic_h" = "yes"; then
+ tor_incr_n_warnings
AC_MSG_WARN([Your compiler provides the stdatomic.h header, but it doesn't seem to work. I'll pretend it isn't there. If you are using Clang on Debian, maybe this is because of https://bugs.debian.org/903709 ])
fi
@@ -2068,6 +2094,7 @@ AS_CASE([$malloc],
],
[openbsd], [
+ tor_incr_n_warnings
AC_MSG_WARN([The openbsd malloc port is deprecated in Tor 0.3.5 and will be removed in a future version.])
enable_openbsd_malloc=yes
],
@@ -2596,6 +2623,7 @@ TOR_TRY_COMPILE_WITH_CFLAGS([@warning_flags], [],
if test "$enable_coverage" = "yes" && test "$have_clang" = "no"; then
case "$host_os" in
darwin*)
+ tor_incr_n_warnings
AC_MSG_WARN([Tried to enable coverage on OSX without using the clang compiler. This might not work! If coverage fails, use CC=clang when configuring with --enable-coverage.])
esac
fi
@@ -2633,6 +2661,7 @@ if test "x$asciidoc" = "xtrue" && test "$ASCIIDOC" = "none"; then
fi
if test "$fragile_hardening" = "yes"; then
+ tor_incr_n_warnings
AC_MSG_WARN([
============
@@ -2649,6 +2678,20 @@ fi
AC_OUTPUT
+if test "$openssl_ver_mismatch" = "yes"; then
+ tor_incr_n_warnings
+ AC_MSG_WARN([
+============
+Warning! The version OpenSSL headers we get from compiling with
+ "${TOR_CPPFLAGS_OPENSSL:-(no extra options)}"
+do not match version of the OpenSSL library we get when linking with
+ "$TOR_LDFLAGS_OPENSSL $TOR_OPENSSL_LIBS".
+This might cause compilation to fail. Try using --with-openssl-dir to specify
+the exact OpenSSL path you want.
+============
+])
+fi
+
#
# Mini-report on what will be built.
#
@@ -2798,3 +2841,10 @@ PPRINT_PROP_STRING([Man Pages], [$report_mandir])
AS_ECHO
AS_ECHO(["Configure Line: ./configure $configure_flags"])
+
+if test "$tor_ac_n_warnings" != "0"; then
+ AS_ECHO
+ PPRINT_WARN([
+Encountered $tor_ac_n_warnings warning(s). See messages above for more info.
+ ])
+fi
diff --git a/doc/man/tor-gencert.1.txt b/doc/man/tor-gencert.1.txt
index 26f68b29c0..9262c4a39a 100644
--- a/doc/man/tor-gencert.1.txt
+++ b/doc/man/tor-gencert.1.txt
@@ -6,7 +6,6 @@
:man manual: Tor Manual
tor-gencert(1)
==============
-Nick Mathewson
NAME
----
@@ -14,7 +13,7 @@ tor-gencert - Generate certs and keys for Tor directory authorities
SYNOPSIS
--------
-**tor-gencert** [-h|--help] [-v] [-r|--reuse] [--create-identity-key] [-i __id_file__] [-c
+**tor-gencert** [-h|--help] [-v] [-r|--reuse] [--create-identity-key] [-i __id_file__] [-c
__cert_file__] [-m __num__] [-a __address__:__port__]
DESCRIPTION
@@ -86,7 +85,3 @@ SEE ALSO
**tor**(1) +
See also the "dir-spec.txt" file, distributed with Tor.
-
-AUTHORS
--------
- Roger Dingledine <arma@mit.edu>, Nick Mathewson <nickm@alum.mit.edu>.
diff --git a/doc/man/tor-print-ed-signing-cert.1.txt b/doc/man/tor-print-ed-signing-cert.1.txt
index 71c8b67ec4..2ce10d7cbd 100644
--- a/doc/man/tor-print-ed-signing-cert.1.txt
+++ b/doc/man/tor-print-ed-signing-cert.1.txt
@@ -32,7 +32,3 @@ SEE ALSO
**tor**(1) +
https://spec.torproject.org/cert-spec
-
-AUTHORS
--------
-Roger Dingledine <arma@mit.edu>, Nick Mathewson <nickm@alum.mit.edu>.
diff --git a/doc/man/tor-resolve.1.txt b/doc/man/tor-resolve.1.txt
index 17a77e482f..c944d75650 100644
--- a/doc/man/tor-resolve.1.txt
+++ b/doc/man/tor-resolve.1.txt
@@ -48,7 +48,3 @@ SEE ALSO
**tor**(1), **torify**(1). +
For protocol details, see: https://spec.torproject.org/socks-extensions
-
-AUTHORS
--------
-Roger Dingledine <arma@mit.edu>, Nick Mathewson <nickm@alum.mit.edu>.
diff --git a/doc/man/tor.1.txt b/doc/man/tor.1.txt
index 4b37548b07..860e1db33a 100644
--- a/doc/man/tor.1.txt
+++ b/doc/man/tor.1.txt
@@ -150,7 +150,7 @@ The following options in this section are only recognized on the
+
Use the **`--newpass`** option with **`--keygen`** only when you
need to add, change, or remove a passphrase on an existing ed25519
- master identity key. You will be prompted for the old passphase
+ master identity key. You will be prompted for the old passphrase
(if any), and the new passphrase (if any).
+
[NOTE]
@@ -276,11 +276,6 @@ forward slash (/) in the configuration file and on the command line.
AlternateBridgeAuthority replaces the default bridge authority,
but leaves the directory authorities alone.
-[[AndroidIdentityTag]] **AndroidIdentityTag** __tag__::
- When logging to Android's logging subsystem, adds a tag to the log identity
- such that log entries are marked with "Tor-__tag__". Can not be changed while
- tor is running. (Default: none)
-
[[AvoidDiskWrites]] **AvoidDiskWrites** **0**|**1**::
If non-zero, try to write to disk less frequently than we would otherwise.
This is useful when running on flash memory or other media that support
@@ -621,7 +616,7 @@ forward slash (/) in the configuration file and on the command line.
**DirCache** fetches and serves all documents except extrainfo
descriptors, **DownloadExtraInfo*** fetches extrainfo documents, and serves
them if **DirCache** is on, and **UseMicrodescriptors** changes the
- flavour of consensues and descriptors that is fetched and used for
+ flavor of consensuses and descriptors that is fetched and used for
building circuits. (Default: 0)
[[HardwareAccel]] **HardwareAccel** **0**|**1**::
@@ -688,7 +683,7 @@ forward slash (/) in the configuration file and on the command line.
Signal-safe logs are always sent to stderr or stdout. They are also sent to
a limited number of log files that are configured to log messages at error
severity from the bug or general domains. They are never sent as syslogs,
- android logs, control port log events, or to any API-based log
+ control port log events, or to any API-based log
destinations.
[[Log2]] **Log** __minSeverity__[-__maxSeverity__] **file** __FILENAME__::
@@ -797,6 +792,17 @@ forward slash (/) in the configuration file and on the command line.
field, Tor will use it for separate rate limiting for each connection
from a non-relay. (Default: 0)
+[[OutboundBindAddressPT]] **OutboundBindAddressPT** __IP__::
+ Request that pluggable transports makes all outbound connections
+ originate from the IP address specified. Because outgoing connections
+ are handled by the pluggable transport itself, it is not possible for
+ Tor to enforce whether the pluggable transport honors this option. This
+ option overrides **OutboundBindAddress** for the same IP version. This
+ option may be used twice, once with an IPv4 address and once with an
+ IPv6 address. IPv6 addresses should be wrapped in square brackets. This
+ setting will be ignored for connections to the loopback addresses
+ (127.0.0.0/8 and ::1).
+
[[PidFile]] **PidFile** __FILE__::
On startup, write our PID to FILE. On clean shutdown, remove
FILE. Can not be changed while tor is running.
@@ -1303,15 +1309,6 @@ The following options are useful only for clients (that is, if
Every NUM seconds consider whether to build a new circuit. (Default: 30
seconds)
-[[OptimisticData]] **OptimisticData** **0**|**1**|**auto**::
- When this option is set, and Tor is using an exit node that supports
- the feature, it will try optimistically to send data to the exit node
- without waiting for the exit node to report whether the connection
- succeeded. This can save a round-trip time for protocols like HTTP
- where the client talks first. If OptimisticData is set to **auto**,
- Tor will look at the UseOptimisticData parameter in the networkstatus.
- (Default: auto)
-
// These are out of order because they logically belong together
[[PathBiasCircThreshold]] **PathBiasCircThreshold** __NUM__ +
@@ -1822,7 +1819,7 @@ The following options control when Tor enters and leaves dormant mode:
this option only with great caution: it has the potential to
create spurious traffic on the network. This option should only
be used if Tor is started by an affirmative user activity (like
- clicking on an applcation or running a command), and not if Tor
+ clicking on an application or running a command), and not if Tor
is launched for some other reason (for example, by a startup
process, or by an application that launches itself on every login.)
@@ -3855,7 +3852,3 @@ https://spec.torproject.org. See also **torsocks**(1) and **torify**(1).
Because Tor is still under development, there may be plenty of bugs. Please
report them at https://bugs.torproject.org/.
-
-== AUTHORS
-
-Roger Dingledine [arma at mit.edu], Nick Mathewson [nickm at alum.mit.edu].
diff --git a/doc/man/torify.1.txt b/doc/man/torify.1.txt
index 716625f92d..46b13e18e5 100644
--- a/doc/man/torify.1.txt
+++ b/doc/man/torify.1.txt
@@ -34,7 +34,3 @@ different circuits.
SEE ALSO
--------
**tor**(1), **torsocks**(1)
-
-AUTHORS
--------
-Peter Palfrader and Jacob Appelbaum wrote this manual.
diff --git a/doc/state-contents.txt b/doc/state-contents.txt
index 44716efc0c..772e108377 100644
--- a/doc/state-contents.txt
+++ b/doc/state-contents.txt
@@ -14,6 +14,21 @@ Recognized fields are:
Time when this state file was written.
Given in ISO format (YYYY-MM-DD HH:MM:SS)
+
+ MinutesSinceUserActivity (integer)
+ Dormant (0, 1, or "auto")
+
+ These values are used to keep track of how long Tor has been idle,
+ for the purpose of becoming 'dormant' after a long period without
+ any user-initiated requests.
+
+ "MinutesSinceUserActivity" is the number of minutes since the last
+ time the user asked us to do something. It is set to zero if we're
+ dormant.
+
+ "Dormant" is 1 if Tor was dormant when it wrote its state file, 0 if
+ Tor was active, and "auto" if Tor was starting for the first time.
+
AccountingBytesReadInInterval (memory unit)
AccountingBytesWrittenInInterval (memory unit)
AccountingExpectedUsage (memory unit)
@@ -36,26 +51,6 @@ Recognized fields are:
BytesAtSoftLimit. If we hit the soft limit already, we did so at
SoftLimitHitAt.
- EntryGuard
- EntryGuardDownSince
- EntryGuardUnlistedSince
- EntryGuardAddedBy
-
- These lines form sections related to entry guards. Each section
- starts with a single EntryGuard line, and is then followed by
- information on the state of the Entry guard.
-
- The EntryGuard line contains a nickname, then an identity digest, of
- the guard.
-
- The EntryGuardDownSince and EntryGuardUnlistedSince lines are present
- if the entry guard is believed to be non-running or non-listed. If
- present, they contain a line in ISO format (YYYY-MM-DD HH:MM:SS).
-
- The EntryGuardAddedBy line is optional. It contains three
- space-separated fields: the identity of the entry guard, the version of
- Tor that added it, and the ISO time at which it was added.
-
TransportProxy
One or more of these may be present.
@@ -65,41 +60,183 @@ Recognized fields are:
this information to spawn pluggable transport listeners in the
same IP address and TCP port even after tor client restarts.
- BWHistoryReadEnds (ISO time)
- BWHistoryReadInterval (integer, number of seconds)
- BWHistoryReadValues (comma-separated list of integer)
- BWHistoryReadMaxima (comma-separated list of integer)
- BWHistoryWriteEnds
- BWHistoryWriteInterval
- BWHistoryWriteValues
- BWHistoryWriteMaxima
- BWHistoryDirReadEnds
- BWHistoryDirReadInterval
- BWHistoryDirReadValues
- BWHistoryDirReadMaxima
- BWHistoryDirWriteEnds
- BWHistoryDirWriteInterval
- BWHistoryDirWriteValues
- BWHistoryDirWriteMaxima
-
- These values record bandwidth history. The "Values" fields are a list, for
- some number of "Intervals", of the total amount read/written during that
- integer. The "Maxima" are the highest burst for each interval.
+ BWHistory___Ends (ISO time)
+ BWHistory___Interval (integer, number of seconds)
+ BWHistory___Values (comma-separated list of integer)
+ BWHistory___Maxima (comma-separated list of integer)
+
+ These values record bandwidth history. The "Values" fields are a list,
+ for some number of "Intervals", of the total amount read/written during
+ that integer. The "Maxima" are the highest burst for each interval.
Interval duration is set by the "Interval" field, in seconds. The
"Ends" field is the ending time of the last interval in each list.
- The *Read* and *Write* fields are the total amount read and
- written; the *DirRead* and *DirWrite* variants are for directory
- traffic only.
+ Recognized values for "___" are:
+ Read -- total bytes read
+ Write -- total bytes written
+ DirRead -- total bytes read for directory connections.
+ DirWrite -- total bytes written for directory connections.
+ IPv6Read -- total bytes read on IPv6 connections
+ IPv6Write -- total bytes written on IPv6 connections
LastRotatedOnionKey
The last time that we changed our onion key for a new one.
Given in ISO format (YYYY-MM-DD HH:MM:SS)
+ This field is used to ensure that onion key rotations happen with the
+ appropriate frequency.
+
TotalBuildTimes
CircuitBuildAbandonedCount
CircuitBuildTimeBin
- XXXX writeme.
+ These fields are used by the Circuit Build Timeout code, which
+ tries to learn what times are reasonable for circuit construction,
+ so that it can reject circuits that take too long to build.
+
+ CircuitBuildTimeBin is a count of circuits that were build
+ successfully in some timeframe. This entry can repeat; each of
+ these represents some bar on a histogram. The first integer is a
+ number of milliseconds; it tells the position of the center of the
+ histogram bin on the time axis. The second number is a count of
+ circuits in that bin.
+
+ CircuitBuildTimeAbandonedCount is a count of circuits that we
+ simply gave up on building because they were taking far too long.
+
+ TotalBuildTimes is the number of circuit build times that we
+ observed in order to build the above measurements fields. If it
+ reaches a cap, then older measurements get thrown away.
+
+ Guard [key=value] [key=value]...
+
+ Describes a single entry guard used by the client. Key=value
+ entries with unrecognized keys are persisted. Order is not
+ significant. For more information about terminology used here,
+ system, see guard-spec.txt in the tor specifications repository.
+
+ Recognized keys are:
+
+ in (string)
+
+ The name of a guard selection that this guard is in.
+
+ rsa_id (string)
+
+ RSA fingerprint of this guard, without spaces.
+
+ nickname (string)
+
+ Declared nickname of this guard.
+
+ sampled_on (Time in ISO YYYY-MM-DDTHH:MM:SS format)
+
+ When was this guard added to the Guard sample?
+
+ sampled_by (tor version)
+
+ Which version of Tor added this Guard to the sample?
+ (Used to help with debugging.)
+
+ sampled_idx (integer)
+
+ Index of this guard among sampled guards.
+
+ listed (boolean)
+
+ Did this guard appear in the most recent consensus?
+
+ unlisted_since (Time in ISO YYYY-MM-DDTHH:MM:SS format)
+
+ If this guard is not listed, when is the earliest
+ consensus in which we found it unlisted?
+
+ confirmed_on (Time in ISO YYYY-MM-DDTHH:MM:SS format)
+
+ When did this guard become confirmed?
+
+ confirmed_idx (integer)
+
+ Index of this guard among confirmed guards.
+
+ bridge_addr (address)
+
+ If this guard is a bridge, its current address.
+
+ pb_use_attempts
+ pb_use_successes
+ pb_circ_attempts
+ pb_successful_circuits_closed
+ pb_collapsed_circuits
+ pb_unusable_circuits
+ pb_timeouts
+
+ Used by the pathbias subsystem to keep a record of the
+ behavior of circuits built through this guard, in hopes of
+ detecting guards try to that interfere with traffic.
+
+ All of these fields are floating-point integers which
+ represent a count of circuits that have been trated in
+ various ways. These counts decay with time.
+
+ "use_attempts" is a count of the circuits that we've built
+ and tried to use for traffic.
+
+ "successful_circuits_closed" is a count of circuits that
+ have closed "naturally" without timeout or error.
+
+ "use_successes" is a count of circuits that we've sent
+ traffic on, and which closed "naturally" without timeout
+ or error.
+
+ "circ_attempts" is a count of circuits we've tried to
+ build through this guard.
+
+ "collapsed_circuits" is a count of circuits that failed
+ after having been built, but before sending traffic.
+
+ "unusable_circuits" is a count of circuits that we
+ built, but where streams or probes but which failed,
+ or which encountered questionable errors.
+
+ "timeouts" is a count of circuits that encountered a
+ timeout while we were building them.
+
+Obsolete fields include:
+
+ EntryGuard
+ EntryGuardDownSince
+ EntryGuardUnlistedSince
+ EntryGuardAddedBy
+
+ These lines formed sections related to entry guards. Each section
+ starts with a single EntryGuard line, and is then followed by
+ information on the state of the Entry guard.
+
+ The EntryGuard line contains a nickname, then an identity digest, of
+ the guard.
+
+ The EntryGuardDownSince and EntryGuardUnlistedSince lines are present
+ if the entry guard is believed to be non-running or non-listed. If
+ present, they contain a line in ISO format (YYYY-MM-DD HH:MM:SS).
+
+ The EntryGuardAddedBy line is optional. It contains three
+ space-separated fields: the identity of the entry guard, the version of
+ Tor that added it, and the ISO time at which it was added.
+
+ EntryGuardPathBias and EntryGuardPathUseBias are superseded by
+ the `pb_...` elements in the Guard flag, and served a similar purpose.
+
+ These entries have all been superseded by the Guard line type,
+ since Tor 0.3.0.1-alpha.
+
+ HidServRevCounter
+
+ It was once used to ensure that v3 onion service directory revision
+ numbers were strictly increasing; we now use an order-preserving
+ encryption scheme for that purpose.
+
+ This option could appear multiple times; each time it does, it
+ applies to a different hidden service.
diff --git a/doc/ticket40136 b/doc/ticket40136
new file mode 100644
index 0000000000..cd1c0682f6
--- /dev/null
+++ b/doc/ticket40136
@@ -0,0 +1,3 @@
+ o Documentation:
+ - Update doc/state-contents.txt to more accurately explain the
+ current contents of a Tor state file. Closes ticket 40136.
diff --git a/scripts/ci/ci-driver.sh b/scripts/ci/ci-driver.sh
index cd91a91bbf..67a95a1f61 100755
--- a/scripts/ci/ci-driver.sh
+++ b/scripts/ci/ci-driver.sh
@@ -34,6 +34,10 @@ RUST="${RUST:-no}"
DOXYGEN="${DOXYGEN:-no}"
ASCIIDOC="${ASCIIDOC:-no}"
TRACING="${TRACING:-no}"
+ALL_BUGS_ARE_FATAL="${ALL_BUGS_ARE_FATAL:-no}"
+DISABLE_DIRAUTH="${DISABLE_DIRAUTH:-no}"
+DISABLE_RELAY="${DISABLE_RELAY:-no}"
+NSS="${NSS:-no}"
# Options for which tests to run. All should be yes/no.
CHECK="${CHECK:-yes}"
@@ -193,6 +197,10 @@ yes_or_no RUST
yes_or_no DOXYGEN
yes_or_no ASCIIDOC
yes_or_no TRACING
+yes_or_no ALL_BUGS_ARE_FATAL
+yes_or_no DISABLE_DIRAUTH
+yes_or_no DISABLE_RELAY
+yes_or_no NSS
yes_or_no RUN_STAGE_CONFIGURE
yes_or_no RUN_STAGE_BUILD
@@ -246,6 +254,18 @@ fi
if [[ "$TRACING" == "yes" ]]; then
configure_options+=("--enable-tracing-instrumentation-lttng")
fi
+if [[ "$ALL_BUGS_ARE_FATAL" == "yes" ]]; then
+ configure_options+=("--enable-all-bugs-are-fatal")
+fi
+if [[ "$DISABLE_DIRAUTH" == "yes" ]]; then
+ configure_options+=("--disable-module-dirauth")
+fi
+if [[ "$DISABLE_RELAY" == "yes" ]]; then
+ configure_options+=("--disable-module-relay")
+fi
+if [[ "$NSS" == "yes" ]]; then
+ configure_options+=("--enable-nss")
+fi
#############################################################################
# Tell the user about our versions of different tools and packages.
diff --git a/scripts/maint/practracker/exceptions.txt b/scripts/maint/practracker/exceptions.txt
index 6eb315d0eb..0373641b60 100644
--- a/scripts/maint/practracker/exceptions.txt
+++ b/scripts/maint/practracker/exceptions.txt
@@ -189,7 +189,7 @@ problem function-size /src/feature/client/entrynodes.c:entry_guard_parse_from_st
problem file-size /src/feature/client/entrynodes.h 700
problem function-size /src/feature/client/transports.c:handle_proxy_line() 108
problem function-size /src/feature/client/transports.c:parse_method_line_helper() 110
-problem function-size /src/feature/client/transports.c:create_managed_proxy_environment() 111
+problem function-size /src/feature/client/transports.c:create_managed_proxy_environment() 140
problem function-size /src/feature/control/control.c:connection_control_process_inbuf() 113
problem function-size /src/feature/control/control_auth.c:handle_control_authenticate() 186
problem function-size /src/feature/control/control_cmd.c:handle_control_extendcircuit() 150
@@ -201,7 +201,7 @@ problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_misc
problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_dir() 297
problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_events() 237
problem function-size /src/feature/dirauth/bwauth.c:dirserv_read_measured_bandwidths() 121
-problem file-size /src/feature/dirauth/dirvote.c 4734
+problem file-size /src/feature/dirauth/dirvote.c 4900
problem include-count /src/feature/dirauth/dirvote.c 55
problem function-size /src/feature/dirauth/dirvote.c:format_networkstatus_vote() 230
problem function-size /src/feature/dirauth/dirvote.c:networkstatus_compute_bw_weights_v10() 233
diff --git a/src/app/config/config.c b/src/app/config/config.c
index 5c8a3792ee..6c17bb0d8c 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -548,7 +548,7 @@ static const config_var_t option_vars_[] = {
V(LogTimeGranularity, MSEC_INTERVAL, "1 second"),
V(TruncateLogFile, BOOL, "0"),
V_IMMUTABLE(SyslogIdentityTag, STRING, NULL),
- V_IMMUTABLE(AndroidIdentityTag,STRING, NULL),
+ OBSOLETE("AndroidIdentityTag"),
V(LongLivedPorts, CSV,
"21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"),
VAR("MapAddress", LINELIST, AddressMap, NULL),
@@ -580,6 +580,7 @@ static const config_var_t option_vars_[] = {
V(OutboundBindAddress, LINELIST, NULL),
V(OutboundBindAddressOR, LINELIST, NULL),
V(OutboundBindAddressExit, LINELIST, NULL),
+ V(OutboundBindAddressPT, LINELIST, NULL),
OBSOLETE("PathBiasDisableRate"),
V(PathBiasCircThreshold, INT, "-1"),
@@ -609,7 +610,7 @@ static const config_var_t option_vars_[] = {
V(TestingAuthKeySlop, INTERVAL, "3 hours"),
V(TestingSigningKeySlop, INTERVAL, "1 day"),
- V(OptimisticData, AUTOBOOL, "auto"),
+ OBSOLETE("OptimisticData"),
OBSOLETE("PortForwarding"),
OBSOLETE("PortForwardingHelper"),
OBSOLETE("PreferTunneledDirConns"),
@@ -2104,6 +2105,16 @@ options_act,(const or_options_t *old_options))
"in a non-anonymous mode. It will provide NO ANONYMITY.");
}
+ /* 31851: OutboundBindAddressExit is relay-only */
+ if (parse_outbound_addresses(options, 0, &msg) < 0) {
+ // LCOV_EXCL_START
+ log_warn(LD_BUG, "Failed parsing previously validated outbound "
+ "bind addresses: %s", msg);
+ tor_free(msg);
+ return -1;
+ // LCOV_EXCL_STOP
+ }
+
if (options->Bridges) {
mark_bridge_list();
for (cl = options->Bridges; cl; cl = cl->next) {
@@ -2265,16 +2276,6 @@ options_act,(const or_options_t *old_options))
tor_free(http_authenticator);
}
- /* 31851: OutboundBindAddressExit is relay-only */
- if (parse_outbound_addresses(options, 0, &msg) < 0) {
- // LCOV_EXCL_START
- log_warn(LD_BUG, "Failed parsing previously validated outbound "
- "bind addresses: %s", msg);
- tor_free(msg);
- return -1;
- // LCOV_EXCL_STOP
- }
-
config_maybe_load_geoip_files_(options, old_options);
if (geoip_is_loaded(AF_INET) && options->GeoIPExcludeUnknown) {
@@ -4934,15 +4935,19 @@ options_init_logs(const or_options_t *old_options, const or_options_t *options,
goto cleanup;
}
+ /* We added this workaround in 0.4.5.x; we can remove it in 0.4.6 or
+ * later */
if (!strcasecmp(smartlist_get(elts, 0), "android")) {
-#ifdef HAVE_ANDROID_LOG_H
+#ifdef HAVE_SYSLOG_H
+ log_warn(LD_CONFIG, "The android logging API is no longer supported;"
+ " adding a syslog instead. The 'android' logging "
+ " type will no longer work in the future.");
if (!validate_only) {
- add_android_log(severity, options->AndroidIdentityTag);
+ add_syslog_log(severity, options->SyslogIdentityTag);
}
#else
- log_warn(LD_CONFIG, "Android logging is not supported"
- " on this system. Sorry.");
-#endif /* defined(HAVE_ANDROID_LOG_H) */
+ log_warn(LD_CONFIG, "The android logging API is no longer supported.");
+#endif
goto cleanup;
}
}
@@ -7180,7 +7185,8 @@ parse_outbound_address_lines(const config_line_t *lines, outbound_addr_t type,
"configured: %s",
family==AF_INET?" IPv4":(family==AF_INET6?" IPv6":""),
type==OUTBOUND_ADDR_OR?" OR":
- (type==OUTBOUND_ADDR_EXIT?" exit":""), lines->value);
+ (type==OUTBOUND_ADDR_EXIT?" exit":
+ (type==OUTBOUND_ADDR_PT?" PT":"")), lines->value);
return -1;
}
lines = lines->next;
@@ -7203,7 +7209,7 @@ parse_outbound_addresses(or_options_t *options, int validate_only, char **msg)
}
if (parse_outbound_address_lines(options->OutboundBindAddress,
- OUTBOUND_ADDR_EXIT_AND_OR, options,
+ OUTBOUND_ADDR_ANY, options,
validate_only, msg) < 0) {
goto err;
}
@@ -7220,6 +7226,12 @@ parse_outbound_addresses(or_options_t *options, int validate_only, char **msg)
goto err;
}
+ if (parse_outbound_address_lines(options->OutboundBindAddressPT,
+ OUTBOUND_ADDR_PT, options, validate_only,
+ msg) < 0) {
+ goto err;
+ }
+
return 0;
err:
return -1;
diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h
index 3b84e5e1f2..3ccd2c9761 100644
--- a/src/app/config/or_options_st.h
+++ b/src/app/config/or_options_st.h
@@ -24,10 +24,29 @@ struct config_suite_t;
struct routerset_t;
/** Enumeration of outbound address configuration types:
- * Exit-only, OR-only, or both */
-typedef enum {OUTBOUND_ADDR_EXIT, OUTBOUND_ADDR_OR,
- OUTBOUND_ADDR_EXIT_AND_OR,
- OUTBOUND_ADDR_MAX} outbound_addr_t;
+ * Exit-only, OR-only, PT-only, or any of them */
+typedef enum {
+ /** Outbound IP address for Exit connections. Controlled by the
+ * `OutboundBindAddressExit` configuration entry in torrc. */
+ OUTBOUND_ADDR_EXIT,
+
+ /** Outbound IP address for OR connections. Controlled by the
+ * `OutboundBindAddressOR` configuration entry in torrc. */
+ OUTBOUND_ADDR_OR,
+
+ /** Outbound IP address for PT connections. Controlled by the
+ * `OutboundBindAddressPT` configuration entry in torrc. */
+ OUTBOUND_ADDR_PT,
+
+ /** Outbound IP address for any outgoing connections. Controlled by the
+ * OutboundBindAddress configuration entry in torrc. This value is used as
+ * fallback if the more specific OUTBOUND_ADDR_EXIT, OUTBOUND_ADDR_OR, and
+ * OUTBOUND_ADDR_PT are unset. */
+ OUTBOUND_ADDR_ANY,
+
+ /** Max value for this enum. Must be the last element in this enum. */
+ OUTBOUND_ADDR_MAX
+} outbound_addr_t;
/** Which protocol to use for TCPProxy. */
typedef enum {
@@ -58,7 +77,6 @@ struct or_options_t {
int TruncateLogFile; /**< Boolean: Should we truncate the log file
before we start writing? */
char *SyslogIdentityTag; /**< Identity tag to add for syslog logging. */
- char *AndroidIdentityTag; /**< Identity tag to add for Android logging. */
char *DebugLogFile; /**< Where to send verbose log messages. */
char *DataDirectory_option; /**< Where to store long-term data, as
@@ -131,6 +149,8 @@ struct or_options_t {
struct config_line_t *OutboundBindAddressOR;
/** Local address to bind outbound exit sockets */
struct config_line_t *OutboundBindAddressExit;
+ /** Local address to bind outbound PT sockets */
+ struct config_line_t *OutboundBindAddressPT;
/** Addresses derived from the various OutboundBindAddress lines.
* [][0] is IPv4, [][1] is IPv6
*/
@@ -848,10 +868,6 @@ struct or_options_t {
* once. */
int MaxClientCircuitsPending;
- /** If 1, we always send optimistic data when it's supported. If 0, we
- * never use it. If -1, we do what the consensus says. */
- int OptimisticData;
-
/** If 1, we accept and launch no external network connections, except on
* control ports. */
int DisableNetwork;
diff --git a/src/app/config/or_state_st.h b/src/app/config/or_state_st.h
index 31b7f8a983..6769ef7b87 100644
--- a/src/app/config/or_state_st.h
+++ b/src/app/config/or_state_st.h
@@ -38,17 +38,11 @@ struct or_state_t {
uint64_t AccountingBytesAtSoftLimit;
uint64_t AccountingExpectedUsage;
- /** A list of Entry Guard-related configuration lines. (pre-prop271) */
- struct config_line_t *EntryGuards;
-
- /** A list of guard-related configuration lines. (post-prop271) */
+ /** A list of guard-related configuration lines. */
struct config_line_t *Guard;
struct config_line_t *TransportProxies;
- /** Cached revision counters for active hidden services on this host */
- struct config_line_t *HidServRevCounter;
-
/** These fields hold information on the history of bandwidth usage for
* servers. The "Ends" fields hold the time when we last updated the
* bandwidth usage. The "Interval" fields hold the granularity, in seconds,
diff --git a/src/app/config/resolve_addr.c b/src/app/config/resolve_addr.c
index b37707d2da..b811a68b8c 100644
--- a/src/app/config/resolve_addr.c
+++ b/src/app/config/resolve_addr.c
@@ -652,12 +652,12 @@ static const size_t fn_address_table_auth_len =
* method_out is set to RESOLVED_ADDR_RESOLVED and hostname_out is set
* to the resolved hostname. On failure to resolve, an error is returned.
*
- * If no given Address, fallback to the local hostname (see section 2).
+ * If no given Address, fallback to the network interface (see section 2).
*
* 2. Look at the network interface.
*
* Attempt to find the first public usable address from the list of
- * network interface returned by the OS.
+ * network interfaces returned by the OS.
*
* On failure, we attempt to look at the local hostname (3).
*
diff --git a/src/app/config/statefile.c b/src/app/config/statefile.c
index b25167d2ec..22b15fcf24 100644
--- a/src/app/config/statefile.c
+++ b/src/app/config/statefile.c
@@ -58,16 +58,38 @@
/** A list of state-file "abbreviations," for compatibility. */
static config_abbrev_t state_abbrevs_[] = {
- { "AccountingBytesReadInterval", "AccountingBytesReadInInterval", 0, 0 },
- { "HelperNode", "EntryGuard", 0, 0 },
- { "HelperNodeDownSince", "EntryGuardDownSince", 0, 0 },
- { "HelperNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 },
- { "EntryNode", "EntryGuard", 0, 0 },
- { "EntryNodeDownSince", "EntryGuardDownSince", 0, 0 },
- { "EntryNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 },
{ NULL, NULL, 0, 0},
};
+/** A list of obsolete keys that we do not and should not preserve.
+ *
+ * We could just let these live in ExtraLines indefinitely, but they're
+ * never going to be used again, and every version that used them
+ * has been obsolete for a long time.
+ * */
+static const char *obsolete_state_keys[] = {
+ /* These were renamed in 0.1.1.11-alpha */
+ "AccountingBytesReadInterval",
+ "HelperNode",
+ "HelperNodeDownSince",
+ "HelperNodeUnlistedSince",
+ "EntryNode",
+ "HelperNodeDownSince",
+ "EntryNodeUnlistedSince",
+ /* These were replaced by "Guard" in 0.3.0.1-alpha. */
+ "EntryGuard",
+ "EntryGuardDownSince",
+ "EntryGuardUnlistedSince",
+ "EntryGuardAddedBy",
+ "EntryGuardPathBias",
+ "EntryGuardPathUseBias",
+ /* This was replaced by OPE-based revision numbers in 0.3.5.1-alpha,
+ * and was never actually used in a released version. */
+ "HidServRevCounter",
+
+ NULL,
+};
+
/** dummy instance of or_state_t, used for type-checking its
* members with CONF_CHECK_VAR_TYPE. */
DUMMY_TYPECHECK_INSTANCE(or_state_t);
@@ -91,19 +113,9 @@ static const config_var_t state_vars_[] = {
V(AccountingSoftLimitHitAt, ISOTIME, NULL),
V(AccountingBytesAtSoftLimit, MEMUNIT, NULL),
- VAR("EntryGuard", LINELIST_S, EntryGuards, NULL),
- VAR("EntryGuardDownSince", LINELIST_S, EntryGuards, NULL),
- VAR("EntryGuardUnlistedSince", LINELIST_S, EntryGuards, NULL),
- VAR("EntryGuardAddedBy", LINELIST_S, EntryGuards, NULL),
- VAR("EntryGuardPathBias", LINELIST_S, EntryGuards, NULL),
- VAR("EntryGuardPathUseBias", LINELIST_S, EntryGuards, NULL),
- V(EntryGuards, LINELIST_V, NULL),
-
VAR("TransportProxy", LINELIST_S, TransportProxies, NULL),
V(TransportProxies, LINELIST_V, NULL),
- V(HidServRevCounter, LINELIST, NULL),
-
V(BWHistoryReadEnds, ISOTIME, NULL),
V(BWHistoryReadInterval, POSINT, "900"),
V(BWHistoryReadValues, CSV, ""),
@@ -475,6 +487,7 @@ or_state_load(void)
} else {
log_info(LD_GENERAL, "Initialized state");
}
+ or_state_remove_obsolete_lines(&new_state->ExtraLines);
if (or_state_set(new_state) == -1) {
or_state_save_broken(fname);
}
@@ -494,6 +507,36 @@ or_state_load(void)
return r;
}
+/** Remove from `extra_lines` every element whose key appears in
+ * `obsolete_state_keys`. */
+STATIC void
+or_state_remove_obsolete_lines(config_line_t **extra_lines)
+{
+ /* make a strmap for the obsolete state names, so we can have O(1)
+ lookup. */
+ strmap_t *bad_keys = strmap_new();
+ for (unsigned i = 0; obsolete_state_keys[i] != NULL; ++i) {
+ strmap_set_lc(bad_keys, obsolete_state_keys[i], (void*)"rmv");
+ }
+
+ config_line_t **line = extra_lines;
+ while (*line) {
+ if (strmap_get_lc(bad_keys, (*line)->key) != NULL) {
+ /* This key is obsolete; remove it. */
+ config_line_t *victim = *line;
+ *line = (*line)->next;
+
+ victim->next = NULL; // prevent double-free.
+ config_free_lines(victim);
+ } else {
+ /* This is just an unrecognized key; keep it. */
+ line = &(*line)->next;
+ }
+ }
+
+ strmap_free(bad_keys, NULL);
+}
+
/** Did the last time we tried to write the state file fail? If so, we
* should consider disabling such features as preemptive circuit generation
* to compute circuit-build-time. */
diff --git a/src/app/config/statefile.h b/src/app/config/statefile.h
index 98d9d2dda1..89b10560f3 100644
--- a/src/app/config/statefile.h
+++ b/src/app/config/statefile.h
@@ -33,6 +33,7 @@ STATIC void or_state_free_(or_state_t *state);
STATIC or_state_t *or_state_new(void);
struct config_mgr_t;
STATIC const struct config_mgr_t *get_state_mgr(void);
+STATIC void or_state_remove_obsolete_lines(struct config_line_t **extra_lines);
#endif /* defined(STATEFILE_PRIVATE) */
#endif /* !defined(TOR_STATEFILE_H) */
diff --git a/src/app/main/main.c b/src/app/main/main.c
index 31a4f141ad..ff530c0ad0 100644
--- a/src/app/main/main.c
+++ b/src/app/main/main.c
@@ -298,7 +298,7 @@ process_signal(int sig)
}
#ifdef _WIN32
-/** Activate SIGINT on reciving a control signal in console */
+/** Activate SIGINT on receiving a control signal in console. */
static BOOL WINAPI
process_win32_console_ctrl(DWORD ctrl_type)
{
diff --git a/src/app/main/subsysmgr.c b/src/app/main/subsysmgr.c
index de601d28cd..349803cd46 100644
--- a/src/app/main/subsysmgr.c
+++ b/src/app/main/subsysmgr.c
@@ -300,7 +300,7 @@ subsystems_thread_cleanup(void)
void
subsystems_dump_list(void)
{
- for (unsigned i = 0; i < n_tor_subsystems - 1; ++i) {
+ for (unsigned i = 0; i < n_tor_subsystems; ++i) {
const subsys_fns_t *sys = tor_subsystems[i];
printf("% 4d\t%16s\t%s\n", sys->level, sys->name,
sys->location?sys->location:"");
diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c
index 82886ccd0b..c043b1ccec 100644
--- a/src/core/mainloop/connection.c
+++ b/src/core/mainloop/connection.c
@@ -2331,9 +2331,9 @@ conn_get_outbound_address(sa_family_t family,
ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT]
[fam_index];
} else if (!tor_addr_is_null(
- &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT_AND_OR]
+ &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY]
[fam_index])) {
- ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT_AND_OR]
+ ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY]
[fam_index];
}
} else { // All non-exit connections
@@ -2342,9 +2342,9 @@ conn_get_outbound_address(sa_family_t family,
ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_OR]
[fam_index];
} else if (!tor_addr_is_null(
- &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT_AND_OR]
+ &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY]
[fam_index])) {
- ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT_AND_OR]
+ ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY]
[fam_index];
}
}
@@ -3224,7 +3224,14 @@ retry_all_listeners(smartlist_t *new_conns, int close_all_noncontrol)
&skip, &addr_in_use);
}
- tor_assert(new_conn);
+ /* There are many reasons why we can't open a new listener port so in case
+ * we hit those, bail early so tor can stop. */
+ if (!new_conn) {
+ log_warn(LD_NET, "Unable to create listener port: %s:%d",
+ fmt_addr(&r->new_port->addr), r->new_port->port);
+ retval = -1;
+ break;
+ }
smartlist_add(new_conns, new_conn);
diff --git a/src/core/or/channel.c b/src/core/or/channel.c
index d082174dc8..c163f53488 100644
--- a/src/core/or/channel.c
+++ b/src/core/or/channel.c
@@ -2395,12 +2395,16 @@ channel_is_better(channel_t *a, channel_t *b)
* *msg_out to a message describing the channel's state and our next action,
* and set *launch_out to a boolean indicated whether the caller should try to
* launch a new channel with channel_connect().
+ *
+ * If `for_origin_circ` is set, mark the channel as interesting for origin
+ * circuits, and therefore interesting for our bootstrapping reports.
*/
MOCK_IMPL(channel_t *,
channel_get_for_extend,(const char *rsa_id_digest,
const ed25519_public_key_t *ed_id,
const tor_addr_t *target_ipv4_addr,
const tor_addr_t *target_ipv6_addr,
+ bool for_origin_circ,
const char **msg_out,
int *launch_out))
{
@@ -2440,8 +2444,15 @@ channel_get_for_extend,(const char *rsa_id_digest,
if (!CHANNEL_IS_OPEN(chan)) {
/* If the address matches, don't launch a new connection for this
* circuit. */
- if (matches_target)
+ if (matches_target) {
++n_inprogress_goodaddr;
+ if (for_origin_circ) {
+ /* We were looking for a connection for an origin circuit; this one
+ * matches, so we'll note that we decided to use it for an origin
+ * circuit. */
+ channel_mark_as_used_for_origin_circuit(chan);
+ }
+ }
continue;
}
diff --git a/src/core/or/channel.h b/src/core/or/channel.h
index 606b0730b8..206d0fdc97 100644
--- a/src/core/or/channel.h
+++ b/src/core/or/channel.h
@@ -526,6 +526,7 @@ void channel_mark_for_close(channel_t *chan);
int channel_write_packed_cell(channel_t *chan, packed_cell_t *cell);
void channel_listener_mark_for_close(channel_listener_t *chan_l);
+void channel_mark_as_used_for_origin_circuit(channel_t *chan);
/* Channel callback registrations */
@@ -661,6 +662,7 @@ MOCK_DECL(channel_t *, channel_get_for_extend,(
const struct ed25519_public_key_t *ed_id,
const tor_addr_t *target_ipv4_addr,
const tor_addr_t *target_ipv6_addr,
+ bool for_origin_circ,
const char **msg_out,
int *launch_out));
diff --git a/src/core/or/channeltls.c b/src/core/or/channeltls.c
index a0debf8d22..32723fed1e 100644
--- a/src/core/or/channeltls.c
+++ b/src/core/or/channeltls.c
@@ -360,6 +360,31 @@ channel_tls_handle_incoming(or_connection_t *orconn)
return chan;
}
+/**
+ * Set the `potentially_used_for_bootstrapping` flag on the or_connection_t
+ * corresponding to the provided channel.
+ *
+ * This flag indicates that if the connection fails, it might be interesting
+ * to the bootstrapping subsystem. (The bootstrapping system only cares about
+ * channels that we have tried to use for our own circuits. Other channels
+ * may have been launched in response to EXTEND cells from somebody else, and
+ * if they fail, it won't necessarily indicate a bootstrapping problem.)
+ **/
+void
+channel_mark_as_used_for_origin_circuit(channel_t *chan)
+{
+ if (BUG(!chan))
+ return;
+ if (chan->magic != TLS_CHAN_MAGIC)
+ return;
+ channel_tls_t *tlschan = channel_tls_from_base(chan);
+ if (BUG(!tlschan))
+ return;
+
+ if (tlschan->conn)
+ tlschan->conn->potentially_used_for_bootstrapping = 1;
+}
+
/*********
* Casts *
********/
diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c
index ab4ce9f784..a3a7a8cf58 100644
--- a/src/core/or/circuitbuild.c
+++ b/src/core/or/circuitbuild.c
@@ -574,6 +574,7 @@ circuit_handle_first_hop(origin_circuit_t *circ)
&firsthop->extend_info->ed_identity,
orport4 ? &orport4->addr : NULL,
orport6 ? &orport6->addr : NULL,
+ true,
&msg,
&should_launch);
@@ -590,6 +591,11 @@ circuit_handle_first_hop(origin_circuit_t *circ)
log_info(LD_CIRC,"connect to firsthop failed. Closing.");
return -END_CIRC_REASON_CONNECTFAILED;
}
+ /* We didn't find a channel, but we're launching one for an origin
+ * circuit. (If we decided not to launch a channel, then we found at
+ * least one once good in-progress channel use for this circuit, and
+ * marked it in channel_get_for_extend().) */
+ channel_mark_as_used_for_origin_circuit(n_chan);
circuit_chan_publish(circ, n_chan);
}
@@ -602,6 +608,8 @@ circuit_handle_first_hop(origin_circuit_t *circ)
} else { /* it's already open. use it. */
tor_assert(!circ->base_.n_hop);
circ->base_.n_chan = n_chan;
+ /* We found a channel, and we're using it for an origin circuit. */
+ channel_mark_as_used_for_origin_circuit(n_chan);
circuit_chan_publish(circ, n_chan);
log_debug(LD_CIRC,"Conn open for %s. Delivering first onion skin.",
safe_str_client(extend_info_describe(firsthop->extend_info)));
@@ -770,27 +778,15 @@ circuit_deliver_create_cell,(circuit_t *circ,
return -1;
}
-/** Return true iff we should send a create_fast cell to start building a given
- * circuit */
-static inline int
+/** Return true iff we should send a create_fast cell to start building a
+ * given circuit */
+static inline bool
should_use_create_fast_for_circuit(origin_circuit_t *circ)
{
- const or_options_t *options = get_options();
tor_assert(circ->cpath);
tor_assert(circ->cpath->extend_info);
- if (!circuit_has_usable_onion_key(circ)) {
- /* We don't have ntor, and we don't have or can't use TAP,
- * so our hand is forced: only a create_fast will work. */
- return 1;
- }
- if (public_server_mode(options)) {
- /* We're a server, and we have a usable onion key. We can choose.
- * Prefer to blend our circuit into the other circuits we are
- * creating on behalf of others. */
- return 0;
- }
- return networkstatus_get_param(NULL, "usecreatefast", 0, 0, 1);
+ return ! circuit_has_usable_onion_key(circ);
}
/**
diff --git a/src/core/or/circuitpadding.c b/src/core/or/circuitpadding.c
index 889ffb03f1..e6daba5469 100644
--- a/src/core/or/circuitpadding.c
+++ b/src/core/or/circuitpadding.c
@@ -1226,6 +1226,7 @@ circpad_send_padding_cell_for_callback(circpad_machine_runtime_t *mi)
circuit_t *circ = mi->on_circ;
int machine_idx = mi->machine_index;
mi->padding_scheduled_at_usec = 0;
+ mi->is_padding_timer_scheduled = 0;
circpad_statenum_t state = mi->current_state;
/* Make sure circuit didn't close on us */
diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c
index df23c63cff..9b506e67a1 100644
--- a/src/core/or/circuituse.c
+++ b/src/core/or/circuituse.c
@@ -2632,22 +2632,6 @@ cpath_is_on_circuit(origin_circuit_t *circ, crypt_path_t *crypt_path)
return 0;
}
-/** Return true iff client-side optimistic data is supported. */
-static int
-optimistic_data_enabled(void)
-{
- const or_options_t *options = get_options();
- if (options->OptimisticData < 0) {
- /* Note: this default was 0 before #18815 was merged. We can't take the
- * parameter out of the consensus until versions before that are all
- * obsolete. */
- const int32_t enabled =
- networkstatus_get_param(NULL, "UseOptimisticData", /*default*/ 1, 0, 1);
- return (int)enabled;
- }
- return options->OptimisticData;
-}
-
/** Attach the AP stream <b>apconn</b> to circ's linked list of
* p_streams. Also set apconn's cpath_layer to <b>cpath</b>, or to the last
* hop in circ's cpath if <b>cpath</b> is NULL.
@@ -2700,11 +2684,10 @@ link_apconn_to_circ(entry_connection_t *apconn, origin_circuit_t *circ,
exitnode = node_get_by_id(cpath->extend_info->identity_digest);
/* See if we can use optimistic data on this circuit */
- if (optimistic_data_enabled() &&
- (circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL ||
- circ->base_.purpose == CIRCUIT_PURPOSE_C_HSDIR_GET ||
- circ->base_.purpose == CIRCUIT_PURPOSE_S_HSDIR_POST ||
- circ->base_.purpose == CIRCUIT_PURPOSE_C_REND_JOINED))
+ if (circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL ||
+ circ->base_.purpose == CIRCUIT_PURPOSE_C_HSDIR_GET ||
+ circ->base_.purpose == CIRCUIT_PURPOSE_S_HSDIR_POST ||
+ circ->base_.purpose == CIRCUIT_PURPOSE_C_REND_JOINED)
apconn->may_use_optimistic_data = 1;
else
apconn->may_use_optimistic_data = 0;
diff --git a/src/core/or/or_connection_st.h b/src/core/or/or_connection_st.h
index 8e012a6b85..253fe67020 100644
--- a/src/core/or/or_connection_st.h
+++ b/src/core/or/or_connection_st.h
@@ -74,6 +74,11 @@ struct or_connection_t {
unsigned int is_outgoing:1;
unsigned int proxy_type:3; /**< One of PROXY_NONE...PROXY_HAPROXY */
unsigned int wide_circ_ids:1;
+ /** True iff a failure on this connection indicates a posssible
+ * bootstrapping problem. We set this as true if we notice that this
+ * connection could handle a pending origin circuit, or if we launch it to
+ * handle an origin circuit. */
+ unsigned int potentially_used_for_bootstrapping:1;
/** True iff this connection has had its bootstrap failure logged with
* control_event_bootstrap_problem. */
unsigned int have_noted_bootstrap_problem:1;
diff --git a/src/feature/client/transports.c b/src/feature/client/transports.c
index 2eb05d6a67..0e4361a210 100644
--- a/src/feature/client/transports.c
+++ b/src/feature/client/transports.c
@@ -1447,6 +1447,37 @@ create_managed_proxy_environment(const managed_proxy_t *mp)
*/
smartlist_add_asprintf(envs, "TOR_PT_EXIT_ON_STDIN_CLOSE=1");
+ /* Specify which IPv4 and IPv6 addresses the PT should make its outgoing
+ * connections from. See: https://bugs.torproject.org/5304 for more
+ * information about this. */
+ {
+ /* Set TOR_PT_OUTBOUND_BIND_ADDRESS_V4. */
+ const tor_addr_t *ipv4_addr = managed_proxy_outbound_address(options,
+ AF_INET);
+
+ /* managed_proxy_outbound_address() only returns a non-NULL value if
+ * tor_addr_is_null() was false, which means we don't have to check that
+ * here. */
+ if (ipv4_addr) {
+ char *ipv4_addr_str = tor_addr_to_str_dup(ipv4_addr);
+ smartlist_add_asprintf(envs,
+ "TOR_PT_OUTBOUND_BIND_ADDRESS_V4=%s",
+ ipv4_addr_str);
+ tor_free(ipv4_addr_str);
+ }
+
+ /* Set TOR_PT_OUTBOUND_BIND_ADDRESS_V6. */
+ const tor_addr_t *ipv6_addr = managed_proxy_outbound_address(options,
+ AF_INET6);
+ if (ipv6_addr) {
+ char *ipv6_addr_str = tor_addr_to_str_dup(ipv6_addr);
+ smartlist_add_asprintf(envs,
+ "TOR_PT_OUTBOUND_BIND_ADDRESS_V6=[%s]",
+ ipv6_addr_str);
+ tor_free(ipv6_addr_str);
+ }
+ }
+
SMARTLIST_FOREACH_BEGIN(envs, const char *, env_var) {
set_environment_variable_in_smartlist(merged_env_vars, env_var,
tor_free_, 1);
@@ -1919,3 +1950,46 @@ managed_proxy_severity_parse(const char *severity)
return -1;
}
+
+/** Return the outbound address from the given <b>family</b>. Returns NULL if
+ * the user haven't specified a specific outbound address in either
+ * OutboundBindAddress or OutboundBindAddressPT. */
+STATIC const tor_addr_t *
+managed_proxy_outbound_address(const or_options_t *options, sa_family_t family)
+{
+ tor_assert(options);
+
+ const tor_addr_t *address = NULL;
+ int family_index;
+
+ switch (family) {
+ case AF_INET:
+ family_index = 0;
+ break;
+ case AF_INET6:
+ family_index = 1;
+ break;
+ default:
+ /* LCOV_EXCL_START */
+ tor_assert_unreached();
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ /* We start by checking if the user specified an address in
+ * OutboundBindAddressPT. */
+ address = &options->OutboundBindAddresses[OUTBOUND_ADDR_PT][family_index];
+
+ if (! tor_addr_is_null(address))
+ return address;
+
+ /* We fallback to check if the user specified an address in
+ * OutboundBindAddress. */
+ address = &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY][family_index];
+
+ if (! tor_addr_is_null(address))
+ return address;
+
+ /* The user have not specified a preference for outgoing connections. */
+ return NULL;
+}
diff --git a/src/feature/client/transports.h b/src/feature/client/transports.h
index 1ed942c175..3aff1cb248 100644
--- a/src/feature/client/transports.h
+++ b/src/feature/client/transports.h
@@ -149,6 +149,8 @@ STATIC void managed_proxy_stderr_callback(process_t *, const char *, size_t);
STATIC bool managed_proxy_exit_callback(process_t *, process_exit_code_t);
STATIC int managed_proxy_severity_parse(const char *);
+STATIC const tor_addr_t *managed_proxy_outbound_address(const or_options_t *,
+ sa_family_t);
#endif /* defined(PT_PRIVATE) */
diff --git a/src/feature/control/control_bootstrap.c b/src/feature/control/control_bootstrap.c
index d4f2adde81..d6dfdad94e 100644
--- a/src/feature/control/control_bootstrap.c
+++ b/src/feature/control/control_bootstrap.c
@@ -348,6 +348,18 @@ control_event_bootstrap_prob_or, (const char *warn, int reason,
{
int dowarn = 0;
+ if (! or_conn->potentially_used_for_bootstrapping) {
+ /* We never decided that this channel was a good match for one of our
+ * origin_circuit_t objects. That means that we probably launched it
+ * for somebody else, most likely in response to an EXTEND cell.
+ *
+ * Since EXTEND cells can contain arbitrarily broken descriptions of
+ * relays, a failure on this connection here won't necessarily indicate a
+ * bootstrapping problem.
+ */
+ return;
+ }
+
if (or_conn->have_noted_bootstrap_problem)
return;
diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c
index 8676df76ab..f56d3ef0a0 100644
--- a/src/feature/dirauth/dirvote.c
+++ b/src/feature/dirauth/dirvote.c
@@ -4,6 +4,7 @@
/* See LICENSE for licensing information */
#define DIRVOTE_PRIVATE
+
#include "core/or/or.h"
#include "app/config/config.h"
#include "app/config/resolve_addr.h"
@@ -4177,8 +4178,8 @@ dirvote_dirreq_get_status_vote(const char *url, smartlist_t *items,
/** Get the best estimate of a router's bandwidth for dirauth purposes,
* preferring measured to advertised values if available. */
-static uint32_t
-dirserv_get_bandwidth_for_router_kb(const routerinfo_t *ri)
+MOCK_IMPL(uint32_t,dirserv_get_bandwidth_for_router_kb,
+ (const routerinfo_t *ri))
{
uint32_t bw_kb = 0;
/*
@@ -4207,33 +4208,73 @@ dirserv_get_bandwidth_for_router_kb(const routerinfo_t *ri)
return bw_kb;
}
-/** Helper for sorting: compares two routerinfos first by address, and then by
- * descending order of "usefulness". (An authority is more useful than a
- * non-authority; a running router is more useful than a non-running router;
- * and a router with more bandwidth is more useful than one with less.)
+/**
+ * Helper: compare the address of family `family` in `a` with the address in
+ * `b`. The family must be one of `AF_INET` and `AF_INET6`.
**/
static int
-compare_routerinfo_by_ip_and_bw_(const void **a, const void **b)
+compare_routerinfo_addrs_by_family(const routerinfo_t *a,
+ const routerinfo_t *b,
+ int family)
+{
+ const tor_addr_t *addr1 = (family==AF_INET) ? &a->ipv4_addr : &a->ipv6_addr;
+ const tor_addr_t *addr2 = (family==AF_INET) ? &b->ipv4_addr : &b->ipv6_addr;
+ const int maskbits = (family==AF_INET) ? 32 : 64;
+ return tor_addr_compare_masked(addr1, addr2, maskbits, CMP_EXACT);
+}
+
+/** Helper for sorting: compares two ipv4 routerinfos first by ipv4 address,
+ * and then by descending order of "usefulness"
+ * (see compare_routerinfo_usefulness)
+ **/
+STATIC int
+compare_routerinfo_by_ipv4(const void **a, const void **b)
+{
+ const routerinfo_t *first = *(const routerinfo_t **)a;
+ const routerinfo_t *second = *(const routerinfo_t **)b;
+ int comparison = compare_routerinfo_addrs_by_family(first, second, AF_INET);
+ if (comparison == 0) {
+ // If addresses are equal, use other comparison criteria
+ return compare_routerinfo_usefulness(first, second);
+ } else {
+ return comparison;
+ }
+}
+
+/** Helper for sorting: compares two ipv6 routerinfos first by ipv6 address,
+ * and then by descending order of "usefulness"
+ * (see compare_routerinfo_usefulness)
+ **/
+STATIC int
+compare_routerinfo_by_ipv6(const void **a, const void **b)
+{
+ const routerinfo_t *first = *(const routerinfo_t **)a;
+ const routerinfo_t *second = *(const routerinfo_t **)b;
+ int comparison = compare_routerinfo_addrs_by_family(first, second, AF_INET6);
+ // If addresses are equal, use other comparison criteria
+ if (comparison == 0)
+ return compare_routerinfo_usefulness(first, second);
+ else
+ return comparison;
+}
+
+/**
+* Compare routerinfos by descending order of "usefulness" :
+* An authority is more useful than a non-authority; a running router is
+* more useful than a non-running router; and a router with more bandwidth
+* is more useful than one with less.
+**/
+STATIC int
+compare_routerinfo_usefulness(const routerinfo_t *first,
+ const routerinfo_t *second)
{
- routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b;
int first_is_auth, second_is_auth;
- uint32_t bw_kb_first, bw_kb_second;
const node_t *node_first, *node_second;
int first_is_running, second_is_running;
- uint32_t first_ipv4h = tor_addr_to_ipv4h(&first->ipv4_addr);
- uint32_t second_ipv4h = tor_addr_to_ipv4h(&second->ipv4_addr);
-
- /* we return -1 if first should appear before second... that is,
- * if first is a better router. */
- if (first_ipv4h < second_ipv4h)
- return -1;
- else if (first_ipv4h > second_ipv4h)
- return 1;
-
+ uint32_t bw_kb_first, bw_kb_second;
/* Potentially, this next bit could cause k n lg n memeq calls. But in
* reality, we will almost never get here, since addresses will usually be
* different. */
-
first_is_auth =
router_digest_is_trusted_dir(first->cache_info.identity_digest);
second_is_auth =
@@ -4248,7 +4289,6 @@ compare_routerinfo_by_ip_and_bw_(const void **a, const void **b)
node_second = node_get_by_id(second->cache_info.identity_digest);
first_is_running = node_first && node_first->is_running;
second_is_running = node_second && node_second->is_running;
-
if (first_is_running && !second_is_running)
return -1;
else if (!first_is_running && second_is_running)
@@ -4269,40 +4309,89 @@ compare_routerinfo_by_ip_and_bw_(const void **a, const void **b)
DIGEST_LEN);
}
-/** Given a list of routerinfo_t in <b>routers</b>, return a new digestmap_t
- * whose keys are the identity digests of those routers that we're going to
- * exclude for Sybil-like appearance. */
-static digestmap_t *
-get_possible_sybil_list(const smartlist_t *routers)
+/** Given a list of routerinfo_t in <b>routers</b> that all use the same
+ * IP version, specified in <b>family</b>, return a new digestmap_t whose keys
+ * are the identity digests of those routers that we're going to exclude for
+ * Sybil-like appearance.
+ */
+STATIC digestmap_t *
+get_sybil_list_by_ip_version(const smartlist_t *routers, sa_family_t family)
{
const dirauth_options_t *options = dirauth_get_options();
- digestmap_t *omit_as_sybil;
+ digestmap_t *omit_as_sybil = digestmap_new();
smartlist_t *routers_by_ip = smartlist_new();
- tor_addr_t last_addr = TOR_ADDR_NULL;
- int addr_count;
+ int addr_count = 0;
+ routerinfo_t *last_ri = NULL;
/* Allow at most this number of Tor servers on a single IP address, ... */
int max_with_same_addr = options->AuthDirMaxServersPerAddr;
if (max_with_same_addr <= 0)
max_with_same_addr = INT_MAX;
smartlist_add_all(routers_by_ip, routers);
- smartlist_sort(routers_by_ip, compare_routerinfo_by_ip_and_bw_);
- omit_as_sybil = digestmap_new();
+ if (family == AF_INET6)
+ smartlist_sort(routers_by_ip, compare_routerinfo_by_ipv6);
+ else
+ smartlist_sort(routers_by_ip, compare_routerinfo_by_ipv4);
- addr_count = 0;
SMARTLIST_FOREACH_BEGIN(routers_by_ip, routerinfo_t *, ri) {
- if (!tor_addr_eq(&last_addr, &ri->ipv4_addr)) {
- tor_addr_copy(&last_addr, &ri->ipv4_addr);
+ bool addrs_equal;
+ if (last_ri)
+ addrs_equal = !compare_routerinfo_addrs_by_family(last_ri, ri, family);
+ else
+ addrs_equal = false;
+
+ if (! addrs_equal) {
+ last_ri = ri;
addr_count = 1;
} else if (++addr_count > max_with_same_addr) {
digestmap_set(omit_as_sybil, ri->cache_info.identity_digest, ri);
}
} SMARTLIST_FOREACH_END(ri);
-
smartlist_free(routers_by_ip);
return omit_as_sybil;
}
+/** Given a list of routerinfo_t in <b>routers</b>, return a new digestmap_t
+ * whose keys are the identity digests of those routers that we're going to
+ * exclude for Sybil-like appearance. */
+STATIC digestmap_t *
+get_all_possible_sybil(const smartlist_t *routers)
+{
+ smartlist_t *routers_ipv6, *routers_ipv4;
+ routers_ipv6 = smartlist_new();
+ routers_ipv4 = smartlist_new();
+ digestmap_t *omit_as_sybil_ipv4;
+ digestmap_t *omit_as_sybil_ipv6;
+ digestmap_t *omit_as_sybil = digestmap_new();
+ // Sort the routers in two lists depending on their IP version
+ SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) {
+ // If the router has an IPv6 address
+ if (tor_addr_family(&(ri->ipv6_addr)) == AF_INET6) {
+ smartlist_add(routers_ipv6, ri);
+ }
+ // If the router has an IPv4 address
+ if (tor_addr_family(&(ri->ipv4_addr)) == AF_INET) {
+ smartlist_add(routers_ipv4, ri);
+ }
+ } SMARTLIST_FOREACH_END(ri);
+ omit_as_sybil_ipv4 = get_sybil_list_by_ip_version(routers_ipv4, AF_INET);
+ omit_as_sybil_ipv6 = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6);
+
+ // Add all possible sybils to the common digestmap
+ DIGESTMAP_FOREACH (omit_as_sybil_ipv4, sybil_id, routerinfo_t *, ri) {
+ digestmap_set(omit_as_sybil, ri->cache_info.identity_digest, ri);
+ } DIGESTMAP_FOREACH_END;
+ DIGESTMAP_FOREACH (omit_as_sybil_ipv6, sybil_id, routerinfo_t *, ri) {
+ digestmap_set(omit_as_sybil, ri->cache_info.identity_digest, ri);
+ } DIGESTMAP_FOREACH_END;
+ // Clean the temp variables
+ smartlist_free(routers_ipv4);
+ smartlist_free(routers_ipv6);
+ digestmap_free(omit_as_sybil_ipv4, NULL);
+ digestmap_free(omit_as_sybil_ipv6, NULL);
+ // Return the digestmap: it now contains all the possible sybils
+ return omit_as_sybil;
+}
/** Given a platform string as in a routerinfo_t (possibly null), return a
* newly allocated version string for a networkstatus document, or NULL if the
* platform doesn't give a Tor version. */
@@ -4477,7 +4566,6 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
networkstatus_voter_info_t *voter = NULL;
vote_timing_t timing;
- digestmap_t *omit_as_sybil = NULL;
const int vote_on_reachability = running_long_enough_to_decide_unreachable();
smartlist_t *microdescriptors = NULL;
smartlist_t *bw_file_headers = NULL;
@@ -4547,19 +4635,16 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
routers_make_ed_keys_unique(routers);
/* After this point, don't use rl->routers; use 'routers' instead. */
routers_sort_by_identity(routers);
- omit_as_sybil = get_possible_sybil_list(routers);
-
- DIGESTMAP_FOREACH(omit_as_sybil, sybil_id, void *, ignore) {
- (void) ignore;
+ /* Get a digestmap of possible sybil routers, IPv4 or IPv6 */
+ digestmap_t *omit_as_sybil = get_all_possible_sybil(routers);
+ DIGESTMAP_FOREACH (omit_as_sybil, sybil_id, void *, ignore) {
+ (void)ignore;
rep_hist_make_router_pessimal(sybil_id, now);
- } DIGESTMAP_FOREACH_END;
-
+ } DIGESTMAP_FOREACH_END
/* Count how many have measured bandwidths so we know how to assign flags;
* this must come before dirserv_compute_performance_thresholds() */
dirserv_count_measured_bws(routers);
-
dirserv_compute_performance_thresholds(omit_as_sybil);
-
routerstatuses = smartlist_new();
microdescriptors = smartlist_new();
@@ -4587,7 +4672,6 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
ri->cache_info.signing_key_cert->signing_key.pubkey,
ED25519_PUBKEY_LEN);
}
-
if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
clear_status_flags_on_sybil(rs);
diff --git a/src/feature/dirauth/dirvote.h b/src/feature/dirauth/dirvote.h
index 9cc87489b4..a4f1b8bfe9 100644
--- a/src/feature/dirauth/dirvote.h
+++ b/src/feature/dirauth/dirvote.h
@@ -183,6 +183,8 @@ dirvote_add_signatures(const char *detached_signatures_body,
/* Item access */
MOCK_DECL(const char*, dirvote_get_pending_consensus,
(consensus_flavor_t flav));
+MOCK_DECL(uint32_t,dirserv_get_bandwidth_for_router_kb,
+ (const routerinfo_t *ri));
MOCK_DECL(const char*, dirvote_get_pending_detached_signatures, (void));
const cached_dir_t *dirvote_get_vote(const char *fp, int flags);
@@ -234,6 +236,22 @@ int networkstatus_add_detached_signatures(networkstatus_t *target,
const char *source,
int severity,
const char **msg_out);
+STATIC int
+compare_routerinfo_usefulness(const routerinfo_t *first,
+ const routerinfo_t *second);
+STATIC
+int compare_routerinfo_by_ipv4(const void **a, const void **b);
+
+STATIC
+int compare_routerinfo_by_ipv6(const void **a, const void **b);
+
+STATIC
+digestmap_t * get_sybil_list_by_ip_version(
+ const smartlist_t *routers, sa_family_t family);
+
+STATIC
+digestmap_t * get_all_possible_sybil(const smartlist_t *routers);
+
STATIC
char *networkstatus_get_detached_signatures(smartlist_t *consensuses);
STATIC microdesc_t *dirvote_create_microdescriptor(const routerinfo_t *ri,
diff --git a/src/feature/dircache/dircache_stub.c b/src/feature/dircache/dircache_stub.c
index 87811597d1..725c44bd4d 100644
--- a/src/feature/dircache/dircache_stub.c
+++ b/src/feature/dircache/dircache_stub.c
@@ -14,6 +14,7 @@
#include "feature/dircache/dirserv.h"
#include "feature/dircommon/dir_connection_st.h"
+DISABLE_GCC_WARNING("-Wmissing-noreturn")
int
directory_handle_command(dir_connection_t *conn)
{
@@ -29,6 +30,7 @@ connection_dirserv_flushed_some(dir_connection_t *conn)
tor_assert_nonfatal_unreached_once();
return -1;
}
+ENABLE_GCC_WARNING("-Wmissing-noreturn")
void
dir_conn_clear_spool(dir_connection_t *conn)
diff --git a/src/feature/dirclient/dirclient.c b/src/feature/dirclient/dirclient.c
index f088ef8283..74e68ac6be 100644
--- a/src/feature/dirclient/dirclient.c
+++ b/src/feature/dirclient/dirclient.c
@@ -1987,7 +1987,7 @@ dirclient_dump_total_dls(void)
{
const or_options_t *options = get_options();
for (int bootstrapped = 0; bootstrapped < 2; ++bootstrapped) {
- bool first_time = true;
+ smartlist_t *lines = smartlist_new();
for (int i=0; i < DIR_PURPOSE_MAX_; ++i) {
uint64_t n = total_dl[i][bootstrapped];
if (n == 0)
@@ -1995,15 +1995,19 @@ dirclient_dump_total_dls(void)
if (options->SafeLogging_ != SAFELOG_SCRUB_NONE &&
purpose_needs_anonymity(i, ROUTER_PURPOSE_GENERAL, NULL))
continue;
- if (first_time) {
- log_notice(LD_NET,
- "While %sbootstrapping, fetched this many bytes: ",
- bootstrapped?"not ":"");
- first_time = false;
- }
- log_notice(LD_NET, " %"PRIu64" (%s)",
- n, dir_conn_purpose_to_string(i));
+ smartlist_add_asprintf(lines, "%"PRIu64" (%s)",
+ n, dir_conn_purpose_to_string(i));
+ }
+
+ if (smartlist_len(lines) > 0) {
+ char *log_line = smartlist_join_strings(lines, "; ", 0, NULL);
+ log_notice(LD_NET, "While %sbootstrapping, fetched this many bytes: %s",
+ bootstrapped?"not ":"", log_line);
+ tor_free(log_line);
+
+ SMARTLIST_FOREACH(lines, char *, s, tor_free(s));
}
+ smartlist_free(lines);
}
}
@@ -2505,9 +2509,12 @@ handle_response_fetch_desc(dir_connection_t *conn,
}
if (status_code != 200) {
int dir_okay = status_code == 404 ||
- (status_code == 400 && !strcmp(reason, "Servers unavailable."));
+ (status_code == 400 && !strcmp(reason, "Servers unavailable.")) ||
+ status_code == 301;
/* 404 means that it didn't have them; no big deal.
- * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
+ * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead.
+ * 301 is considered as an error since Tor does not follow redirects,
+ * which means we failed to reach the server we wanted. */
log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
"Received http status code %d (%s) from server %s "
"while fetching \"/tor/server/%s\". I'll try again soon.",
diff --git a/src/feature/hs/hs_circuitmap.c b/src/feature/hs/hs_circuitmap.c
index 466a02de39..e46b008a5c 100644
--- a/src/feature/hs/hs_circuitmap.c
+++ b/src/feature/hs/hs_circuitmap.c
@@ -275,7 +275,7 @@ hs_circuitmap_get_or_circuit(hs_token_type_t type,
/** Public function: Return v2 and v3 introduction circuit to this relay.
* Always return a newly allocated list for which it is the caller's
- * responsability to free it. */
+ * responsibility to free it. */
smartlist_t *
hs_circuitmap_get_all_intro_circ_relay_side(void)
{
diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c
index 3e264b4686..f2a8898b2c 100644
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -1587,7 +1587,7 @@ setup_desc_intro_point(const ed25519_keypair_t *signing_kp,
memcpy(&desc_ip->onion_key, &ip->onion_key, sizeof(desc_ip->onion_key));
/* Key and certificate material. */
- desc_ip->auth_key_cert = tor_cert_create(signing_kp,
+ desc_ip->auth_key_cert = tor_cert_create_ed25519(signing_kp,
CERT_TYPE_AUTH_HS_IP_KEY,
&ip->auth_key_kp.pubkey,
nearest_hour,
@@ -1638,7 +1638,7 @@ setup_desc_intro_point(const ed25519_keypair_t *signing_kp,
ed25519_public_key_from_curve25519_public_key(&ed25519_pubkey,
&ip->enc_key_kp.pubkey,
0);
- desc_ip->enc_key_cert = tor_cert_create(signing_kp,
+ desc_ip->enc_key_cert = tor_cert_create_ed25519(signing_kp,
CERT_TYPE_CROSS_HS_IP_KEYS,
&ed25519_pubkey, nearest_hour,
HS_DESC_CERT_LIFETIME,
@@ -1712,12 +1712,13 @@ build_desc_signing_key_cert(hs_service_descriptor_t *desc, time_t now)
/* Fresh certificate for the signing key. */
plaintext->signing_key_cert =
- tor_cert_create(&desc->blinded_kp, CERT_TYPE_SIGNING_HS_DESC,
+ tor_cert_create_ed25519(&desc->blinded_kp, CERT_TYPE_SIGNING_HS_DESC,
&desc->signing_kp.pubkey, now, HS_DESC_CERT_LIFETIME,
CERT_FLAG_INCLUDE_SIGNING_KEY);
/* If the cert creation fails, the descriptor encoding will fail and thus
* ultimately won't be uploaded. We'll get a stack trace to help us learn
- * where the call came from and the tor_cert_create() will log the error. */
+ * where the call came from and the tor_cert_create_ed25519() will log the
+ * error. */
tor_assert_nonfatal(plaintext->signing_key_cert);
}
diff --git a/src/feature/hs_common/shared_random_client.c b/src/feature/hs_common/shared_random_client.c
index 3f46321be4..c2ea5afe32 100644
--- a/src/feature/hs_common/shared_random_client.c
+++ b/src/feature/hs_common/shared_random_client.c
@@ -274,10 +274,6 @@ sr_state_get_start_time_of_current_protocol_run(void)
protocol run */
time_t time_elapsed_since_start_of_run = curr_round_slot * voting_interval;
- log_debug(LD_GENERAL, "Current SRV proto run: Start of current round: %u. "
- "Time elapsed: %u (%d)", (unsigned) beginning_of_curr_round,
- (unsigned) time_elapsed_since_start_of_run, voting_interval);
-
return beginning_of_curr_round - time_elapsed_since_start_of_run;
}
diff --git a/src/feature/keymgt/loadkey.c b/src/feature/keymgt/loadkey.c
index 7958bd964f..9b8f2f018a 100644
--- a/src/feature/keymgt/loadkey.c
+++ b/src/feature/keymgt/loadkey.c
@@ -661,7 +661,7 @@ ed_key_init_from_file(const char *fname, uint32_t flags,
uint32_t cert_flags = 0;
if (flags & INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT)
cert_flags |= CERT_FLAG_INCLUDE_SIGNING_KEY;
- cert = tor_cert_create(signing_key, cert_type,
+ cert = tor_cert_create_ed25519(signing_key, cert_type,
&keypair->pubkey,
now, lifetime,
cert_flags);
@@ -739,7 +739,7 @@ ed_key_new(const ed25519_keypair_t *signing_key,
uint32_t cert_flags = 0;
if (flags & INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT)
cert_flags |= CERT_FLAG_INCLUDE_SIGNING_KEY;
- tor_cert_t *cert = tor_cert_create(signing_key, cert_type,
+ tor_cert_t *cert = tor_cert_create_ed25519(signing_key, cert_type,
&keypair->pubkey,
now, lifetime,
cert_flags);
diff --git a/src/feature/nodelist/dirlist.c b/src/feature/nodelist/dirlist.c
index cd2921e653..f6e4662a0f 100644
--- a/src/feature/nodelist/dirlist.c
+++ b/src/feature/nodelist/dirlist.c
@@ -236,8 +236,8 @@ mark_all_dirservers_up(smartlist_t *server_list)
/** Return true iff <b>digest</b> is the digest of the identity key of a
* trusted directory matching at least one bit of <b>type</b>. If <b>type</b>
* is zero (NO_DIRINFO), or ALL_DIRINFO, any authority is okay. */
-int
-router_digest_is_trusted_dir_type(const char *digest, dirinfo_type_t type)
+MOCK_IMPL(int, router_digest_is_trusted_dir_type,
+ (const char *digest, dirinfo_type_t type))
{
if (!trusted_dir_servers)
return 0;
diff --git a/src/feature/nodelist/dirlist.h b/src/feature/nodelist/dirlist.h
index c9310ff357..ae3debf4e5 100644
--- a/src/feature/nodelist/dirlist.h
+++ b/src/feature/nodelist/dirlist.h
@@ -25,13 +25,14 @@ int router_digest_is_fallback_dir(const char *digest);
MOCK_DECL(dir_server_t *, trusteddirserver_get_by_v3_auth_digest,
(const char *d));
+MOCK_DECL(int, router_digest_is_trusted_dir_type,
+ (const char *digest, dirinfo_type_t type));
+
bool router_addr_is_trusted_dir_type(const tor_addr_t *addr,
dirinfo_type_t type);
#define router_addr_is_trusted_dir(d) \
router_addr_is_trusted_dir_type((d), NO_DIRINFO)
-int router_digest_is_trusted_dir_type(const char *digest,
- dirinfo_type_t type);
#define router_digest_is_trusted_dir(d) \
router_digest_is_trusted_dir_type((d), NO_DIRINFO)
diff --git a/src/feature/nodelist/networkstatus.c b/src/feature/nodelist/networkstatus.c
index 9210518de0..ece3c9e059 100644
--- a/src/feature/nodelist/networkstatus.c
+++ b/src/feature/nodelist/networkstatus.c
@@ -2444,7 +2444,12 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now)
return answer;
}
-/* DOCDOC get_net_param_from_list */
+/**
+ * Search through a smartlist of "key=int32" strings for a value beginning
+ * with "param_name=". If one is found, clip it to be between min_val and
+ * max_val inclusive and return it. If one is not found, return
+ * default_val.
+ ***/
static int32_t
get_net_param_from_list(smartlist_t *net_params, const char *param_name,
int32_t default_val, int32_t min_val, int32_t max_val)
diff --git a/src/feature/nodelist/nodelist.c b/src/feature/nodelist/nodelist.c
index 7edc1fc51c..c9928d2f9b 100644
--- a/src/feature/nodelist/nodelist.c
+++ b/src/feature/nodelist/nodelist.c
@@ -1947,7 +1947,7 @@ node_get_curve25519_onion_key(const node_t *node)
/* 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 responsability to free the returned object. */
+ * the caller responsibility to free the returned object. */
crypto_pk_t *
node_get_rsa_onion_key(const node_t *node)
{
diff --git a/src/feature/nodelist/torcert.c b/src/feature/nodelist/torcert.c
index 89cc9c88fb..dc36626122 100644
--- a/src/feature/nodelist/torcert.c
+++ b/src/feature/nodelist/torcert.c
@@ -37,11 +37,11 @@
#include "core/or/or_handshake_certs_st.h"
-/** Helper for tor_cert_create(): signs any 32 bytes, not just an ed25519
- * key.
+/** As tor_cert_create(), but accept an arbitrary signed_key_type as the
+ * subject key -- not just an ed25519 key.
*/
-static tor_cert_t *
-tor_cert_sign_impl(const ed25519_keypair_t *signing_key,
+tor_cert_t *
+tor_cert_create_raw(const ed25519_keypair_t *signing_key,
uint8_t cert_type,
uint8_t signed_key_type,
const uint8_t signed_key_info[32],
@@ -128,13 +128,13 @@ tor_cert_sign_impl(const ed25519_keypair_t *signing_key,
* the public part of <b>signing_key</b> in the certificate.
*/
tor_cert_t *
-tor_cert_create(const ed25519_keypair_t *signing_key,
+tor_cert_create_ed25519(const ed25519_keypair_t *signing_key,
uint8_t cert_type,
const ed25519_public_key_t *signed_key,
time_t now, time_t lifetime,
uint32_t flags)
{
- return tor_cert_sign_impl(signing_key, cert_type,
+ return tor_cert_create_raw(signing_key, cert_type,
SIGNED_KEY_TYPE_ED25519, signed_key->pubkey,
now, lifetime, flags);
}
diff --git a/src/feature/nodelist/torcert.h b/src/feature/nodelist/torcert.h
index f8fba2b794..3314ee2550 100644
--- a/src/feature/nodelist/torcert.h
+++ b/src/feature/nodelist/torcert.h
@@ -11,7 +11,9 @@
#include "lib/crypt_ops/crypto_ed25519.h"
-#define SIGNED_KEY_TYPE_ED25519 0x01
+#define SIGNED_KEY_TYPE_ED25519 0x01
+#define SIGNED_KEY_TYPE_SHA256_OF_RSA 0x02
+#define SIGNED_KEY_TYPE_SHA256_OF_X509 0x03
#define CERT_TYPE_ID_SIGNING 0x04
#define CERT_TYPE_SIGNING_LINK 0x05
@@ -56,11 +58,17 @@ typedef struct tor_cert_st {
struct tor_tls_t;
-tor_cert_t *tor_cert_create(const ed25519_keypair_t *signing_key,
+tor_cert_t *tor_cert_create_ed25519(const ed25519_keypair_t *signing_key,
uint8_t cert_type,
const ed25519_public_key_t *signed_key,
time_t now, time_t lifetime,
uint32_t flags);
+tor_cert_t * tor_cert_create_raw(const ed25519_keypair_t *signing_key,
+ uint8_t cert_type,
+ uint8_t signed_key_type,
+ const uint8_t signed_key_info[32],
+ time_t now, time_t lifetime,
+ uint32_t flags);
tor_cert_t *tor_cert_parse(const uint8_t *cert, size_t certlen);
diff --git a/src/feature/relay/circuitbuild_relay.c b/src/feature/relay/circuitbuild_relay.c
index 64f3c341ae..289a5be557 100644
--- a/src/feature/relay/circuitbuild_relay.c
+++ b/src/feature/relay/circuitbuild_relay.c
@@ -475,6 +475,7 @@ circuit_extend(struct cell_t *cell, struct circuit_t *circ)
&ec.ed_pubkey,
ipv4_valid ? &ec.orport_ipv4.addr : NULL,
ipv6_valid ? &ec.orport_ipv6.addr : NULL,
+ false,
&msg,
&should_launch);
diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c
index 11847a2616..5ca21964b6 100644
--- a/src/feature/relay/router.c
+++ b/src/feature/relay/router.c
@@ -2607,6 +2607,10 @@ check_descriptor_bandwidth_changed(time_t now)
}
}
+// This function can be "noreturn" if relay mode is disabled and
+// ALL_BUGS_ARE_FATAL is set.
+DISABLE_GCC_WARNING("-Wmissing-noreturn")
+
/** Note at log level severity that our best guess of address has changed from
* <b>prev</b> to <b>cur</b>. */
void
@@ -2636,6 +2640,7 @@ log_addr_has_changed(int severity,
"Guessed our IP address as %s (source: %s).",
addrbuf_cur, source);
}
+ENABLE_GCC_WARNING("-Wmissing-noreturn")
/** Check whether our own address has changed versus the one we have in our
* current descriptor.
@@ -3570,7 +3575,7 @@ router_set_rsa_onion_pkey(const crypto_pk_t *pk, char **onion_pkey_out,
}
/* From an ASN-1 encoded onion pkey, return a newly allocated RSA key object.
- * It is the caller responsability to free the returned object.
+ * It is the caller's responsibility to free the returned object.
*
* Return NULL if the pkey is NULL, malformed or if the length is 0. */
crypto_pk_t *
diff --git a/src/feature/relay/routerkeys.c b/src/feature/relay/routerkeys.c
index 744a73d936..116f0b4e3d 100644
--- a/src/feature/relay/routerkeys.c
+++ b/src/feature/relay/routerkeys.c
@@ -387,12 +387,10 @@ generate_ed_link_cert(const or_options_t *options, time_t now,
return 0;
}
- ed25519_public_key_t dummy_key;
- memcpy(dummy_key.pubkey, digests->d[DIGEST_SHA256], DIGEST256_LEN);
-
- link_cert = tor_cert_create(get_master_signing_keypair(),
+ link_cert = tor_cert_create_raw(get_master_signing_keypair(),
CERT_TYPE_SIGNING_LINK,
- &dummy_key,
+ SIGNED_KEY_TYPE_SHA256_OF_X509,
+ (const uint8_t*)digests->d[DIGEST_SHA256],
now,
options->TestingLinkCertLifetime, 0);
@@ -466,7 +464,7 @@ init_mock_ed_keys(const crypto_pk_t *rsa_identity_key)
MAKEKEY(master_signing_key);
MAKEKEY(current_auth_key);
#define MAKECERT(cert, signing, signed_, type, flags) \
- cert = tor_cert_create(signing, \
+ cert = tor_cert_create_ed25519(signing, \
type, \
&signed_->pubkey, \
time(NULL), 86400, \
@@ -699,8 +697,8 @@ make_ntor_onion_key_crosscert(const curve25519_keypair_t *onion_key,
onion_key) < 0)
goto end;
- cert = tor_cert_create(&ed_onion_key, CERT_TYPE_ONION_ID, master_id_key,
- now, lifetime, 0);
+ cert = tor_cert_create_ed25519(&ed_onion_key, CERT_TYPE_ONION_ID,
+ master_id_key, now, lifetime, 0);
end:
memwipe(&ed_onion_key, 0, sizeof(ed_onion_key));
diff --git a/src/lib/fs/path.c b/src/lib/fs/path.c
index 1a15969419..2eef4bded7 100644
--- a/src/lib/fs/path.c
+++ b/src/lib/fs/path.c
@@ -598,6 +598,12 @@ tor_glob(const char *pattern)
return NULL;
}
+ // #40141: workaround for bug in glibc < 2.19 where patterns ending in path
+ // separator match files and folders instead of folders only
+ size_t pattern_len = strlen(pattern);
+ bool dir_only = has_glob(pattern) &&
+ pattern_len > 0 && pattern[pattern_len-1] == *PATH_SEPARATOR;
+
result = smartlist_new();
size_t i;
for (i = 0; i < matches.gl_pathc; i++) {
@@ -606,7 +612,12 @@ tor_glob(const char *pattern)
if (len > 0 && match[len-1] == *PATH_SEPARATOR) {
match[len-1] = '\0';
}
- smartlist_add(result, match);
+
+ if (!dir_only || (dir_only && is_dir(file_status(match)))) {
+ smartlist_add(result, match);
+ } else {
+ tor_free(match);
+ }
}
globfree(&matches);
#else
diff --git a/src/lib/log/log.c b/src/lib/log/log.c
index cd848fdd73..12e4dbaaa2 100644
--- a/src/lib/log/log.c
+++ b/src/lib/log/log.c
@@ -51,10 +51,6 @@
#include "lib/fdio/fdio.h"
#include "lib/cc/ctassert.h"
-#ifdef HAVE_ANDROID_LOG_H
-#include <android/log.h>
-#endif // HAVE_ANDROID_LOG_H.
-
/** @{ */
/** The string we stick at the end of a log message when it is too long,
* and its length. */
@@ -78,8 +74,6 @@ typedef struct logfile_t {
int needs_close; /**< Boolean: true if the stream gets closed on shutdown. */
int is_temporary; /**< Boolean: close after initializing logging subsystem.*/
int is_syslog; /**< Boolean: send messages to syslog. */
- int is_android; /**< Boolean: send messages to Android's log subsystem. */
- char *android_tag; /**< Identity Tag used in Android's log subsystem. */
log_callback callback; /**< If not NULL, send messages to this function. */
log_severity_list_t *severities; /**< Which severity of messages should we
* log for each log domain? */
@@ -126,33 +120,6 @@ should_log_function_name(log_domain_mask_t domain, int severity)
}
}
-#ifdef HAVE_ANDROID_LOG_H
-/** Helper function to convert Tor's log severity into the matching
- * Android log priority.
- */
-static int
-severity_to_android_log_priority(int severity)
-{
- switch (severity) {
- case LOG_DEBUG:
- return ANDROID_LOG_VERBOSE;
- case LOG_INFO:
- return ANDROID_LOG_DEBUG;
- case LOG_NOTICE:
- return ANDROID_LOG_INFO;
- case LOG_WARN:
- return ANDROID_LOG_WARN;
- case LOG_ERR:
- return ANDROID_LOG_ERROR;
- default:
- // LCOV_EXCL_START
- raw_assert(0);
- return 0;
- // LCOV_EXCL_STOP
- }
-}
-#endif /* defined(HAVE_ANDROID_LOG_H) */
-
/** A mutex to guard changes to logfiles and logging. */
static tor_mutex_t log_mutex;
/** True iff we have initialized log_mutex */
@@ -475,13 +442,13 @@ pending_log_message_free_(pending_log_message_t *msg)
}
/** Helper function: returns true iff the log file, given in <b>lf</b>, is
- * handled externally via the system log API, the Android logging API, or is an
+ * handled externally via the system log API, or is an
* external callback function. */
static inline int
logfile_is_external(const logfile_t *lf)
{
raw_assert(lf);
- return lf->is_syslog || lf->is_android || lf->callback;
+ return lf->is_syslog || lf->callback;
}
/** Return true iff <b>lf</b> would like to receive a message with the
@@ -537,11 +504,6 @@ logfile_deliver(logfile_t *lf, const char *buf, size_t msg_len,
syslog(severity, "%s", msg_after_prefix);
#endif /* defined(MAXLINE) */
#endif /* defined(HAVE_SYSLOG_H) */
- } else if (lf->is_android) {
-#ifdef HAVE_ANDROID_LOG_H
- int priority = severity_to_android_log_priority(severity);
- __android_log_write(priority, lf->android_tag, msg_after_prefix);
-#endif // HAVE_ANDROID_LOG_H.
} else if (lf->callback) {
if (domain & LD_NOCB) {
if (!*callbacks_deferred && pending_cb_messages) {
@@ -677,7 +639,7 @@ tor_log_update_sigsafe_err_fds(void)
n_fds = 1;
for (lf = logfiles; lf; lf = lf->next) {
- /* Don't try callback to the control port, syslogs, android logs, or any
+ /* Don't try callback to the control port, syslogs, or any
* other non-file descriptor log: We can't call arbitrary functions from a
* signal handler.
*/
@@ -775,7 +737,6 @@ log_free_(logfile_t *victim)
return;
tor_free(victim->severities);
tor_free(victim->filename);
- tor_free(victim->android_tag);
tor_free(victim);
}
@@ -1247,39 +1208,6 @@ add_syslog_log(const log_severity_list_t *severity,
}
#endif /* defined(HAVE_SYSLOG_H) */
-#ifdef HAVE_ANDROID_LOG_H
-/**
- * Add a log handler to send messages to the Android platform log facility.
- */
-int
-add_android_log(const log_severity_list_t *severity,
- const char *android_tag)
-{
- logfile_t *lf = NULL;
-
- lf = tor_malloc_zero(sizeof(logfile_t));
- lf->fd = -1;
- lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
- lf->filename = tor_strdup("<android>");
- lf->is_android = 1;
-
- if (android_tag == NULL)
- lf->android_tag = tor_strdup("Tor");
- else {
- char buf[256];
- tor_snprintf(buf, sizeof(buf), "Tor-%s", android_tag);
- lf->android_tag = tor_strdup(buf);
- }
-
- LOCK_LOGS();
- lf->next = logfiles;
- logfiles = lf;
- log_global_min_severity_ = get_min_log_level();
- UNLOCK_LOGS();
- return 0;
-}
-#endif /* defined(HAVE_ANDROID_LOG_H) */
-
/** If <b>level</b> is a valid log severity, return the corresponding
* numeric value. Otherwise, return -1. */
int
@@ -1457,8 +1385,7 @@ parse_log_severity_config(const char **cfg_ptr,
if (!strcasecmpstart(cfg, "file") ||
!strcasecmpstart(cfg, "stderr") ||
!strcasecmpstart(cfg, "stdout") ||
- !strcasecmpstart(cfg, "syslog") ||
- !strcasecmpstart(cfg, "android")) {
+ !strcasecmpstart(cfg, "syslog")) {
goto done;
}
if (got_an_unqualified_range > 1)
diff --git a/src/lib/log/log.h b/src/lib/log/log.h
index aafbf9be2f..fb8a5a28a6 100644
--- a/src/lib/log/log.h
+++ b/src/lib/log/log.h
@@ -175,10 +175,6 @@ MOCK_DECL(int, add_file_log,(const log_severity_list_t *severity,
int add_syslog_log(const log_severity_list_t *severity,
const char* syslog_identity_tag);
#endif // HAVE_SYSLOG_H.
-#ifdef HAVE_ANDROID_LOG_H
-int add_android_log(const log_severity_list_t *severity,
- const char *android_identity_tag);
-#endif // HAVE_ANDROID_LOG_H.
int add_callback_log(const log_severity_list_t *severity, log_callback cb);
typedef void (*pending_callback_callback)(void);
void logs_set_pending_callback_callback(pending_callback_callback cb);
diff --git a/src/lib/net/address.c b/src/lib/net/address.c
index 5a32533610..ea6c29db9f 100644
--- a/src/lib/net/address.c
+++ b/src/lib/net/address.c
@@ -1731,8 +1731,8 @@ get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr))
/* Get a list of public or internal IPs in arbitrary order */
addrs = get_interface_address6_list(severity, family, 1);
- /* Find the first non-internal address, or the last internal address
- * Ideally, we want the default route, see #12377 for details */
+ /* Find the first non-internal address, or the last internal address.
+ * Ideally, we want the default route; see #12377 for details. */
SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a) {
tor_addr_copy(addr, a);
const bool is_internal = tor_addr_is_internal(a, 0);
diff --git a/src/test/conf_examples/large_1/expected b/src/test/conf_examples/large_1/expected
index 99a12ffc84..fcd19db3df 100644
--- a/src/test/conf_examples/large_1/expected
+++ b/src/test/conf_examples/large_1/expected
@@ -3,7 +3,6 @@ AccountingRule sum
AccountingStart day 05:15
Address 128.66.8.8
AllowNonRFC953Hostnames 1
-AndroidIdentityTag droidy
AutomapHostsOnResolve 1
AutomapHostsSuffixes .onions
AvoidDiskWrites 1
@@ -111,7 +110,6 @@ NumDirectoryGuards 4
NumEntryGuards 5
NumPrimaryGuards 8
OfflineMasterKey 1
-OptimisticData 1
ORPort 2222
OutboundBindAddress 10.0.0.7
OutboundBindAddressExit 10.0.0.8
diff --git a/src/test/conf_examples/large_1/expected_no_dirauth b/src/test/conf_examples/large_1/expected_no_dirauth
index 26a33bdc7c..4a19bc546c 100644
--- a/src/test/conf_examples/large_1/expected_no_dirauth
+++ b/src/test/conf_examples/large_1/expected_no_dirauth
@@ -3,7 +3,6 @@ AccountingRule sum
AccountingStart day 05:15
Address 128.66.8.8
AllowNonRFC953Hostnames 1
-AndroidIdentityTag droidy
AutomapHostsOnResolve 1
AutomapHostsSuffixes .onions
AvoidDiskWrites 1
@@ -110,7 +109,6 @@ NumDirectoryGuards 4
NumEntryGuards 5
NumPrimaryGuards 8
OfflineMasterKey 1
-OptimisticData 1
ORPort 2222
OutboundBindAddress 10.0.0.7
OutboundBindAddressExit 10.0.0.8
diff --git a/src/test/conf_examples/large_1/torrc b/src/test/conf_examples/large_1/torrc
index 20ddf00e16..3f5b1e179f 100644
--- a/src/test/conf_examples/large_1/torrc
+++ b/src/test/conf_examples/large_1/torrc
@@ -3,7 +3,6 @@ AccountingRule sum
AccountingStart day 05:15
Address 128.66.8.8
AllowNonRFC953Hostnames 1
-AndroidIdentityTag droidy
AutomapHostsOnResolve 1
AutomapHostsSuffixes .onions
AvoidDiskWrites 1
diff --git a/src/test/hs_test_helpers.c b/src/test/hs_test_helpers.c
index 5116fc7169..e9aafa4760 100644
--- a/src/test/hs_test_helpers.c
+++ b/src/test/hs_test_helpers.c
@@ -75,7 +75,8 @@ hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now,
ret = ed25519_keypair_generate(&auth_kp, 0);
tt_int_op(ret, OP_EQ, 0);
}
- ip->auth_key_cert = tor_cert_create(signing_kp, CERT_TYPE_AUTH_HS_IP_KEY,
+ ip->auth_key_cert = tor_cert_create_ed25519(signing_kp,
+ CERT_TYPE_AUTH_HS_IP_KEY,
&auth_kp.pubkey, now,
HS_DESC_CERT_LIFETIME,
CERT_FLAG_INCLUDE_SIGNING_KEY);
@@ -110,7 +111,8 @@ hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now,
}
ed25519_keypair_from_curve25519_keypair(&ed25519_kp, &signbit,
&curve25519_kp);
- cross_cert = tor_cert_create(signing_kp, CERT_TYPE_CROSS_HS_IP_KEYS,
+ cross_cert = tor_cert_create_ed25519(signing_kp,
+ CERT_TYPE_CROSS_HS_IP_KEYS,
&ed25519_kp.pubkey, time(NULL),
HS_DESC_CERT_LIFETIME,
CERT_FLAG_INCLUDE_SIGNING_KEY);
@@ -155,7 +157,7 @@ hs_helper_build_hs_desc_impl(unsigned int no_ip,
sizeof(ed25519_public_key_t));
desc->plaintext_data.signing_key_cert =
- tor_cert_create(&blinded_kp, CERT_TYPE_SIGNING_HS_DESC,
+ tor_cert_create_ed25519(&blinded_kp, CERT_TYPE_SIGNING_HS_DESC,
&signing_kp->pubkey, now, 3600,
CERT_FLAG_INCLUDE_SIGNING_KEY);
tt_assert(desc->plaintext_data.signing_key_cert);
diff --git a/src/test/include.am b/src/test/include.am
index fe55991f82..cb3a498f74 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -171,6 +171,7 @@ src_test_test_SOURCES += \
src/test/test_crypto_rng.c \
src/test/test_data.c \
src/test/test_dir.c \
+ src/test/test_dirvote.c \
src/test/test_dir_common.c \
src/test/test_dir_handle_get.c \
src/test/test_dispatch.c \
@@ -234,6 +235,7 @@ src_test_test_SOURCES += \
src/test/test_sendme.c \
src/test/test_shared_random.c \
src/test/test_socks.c \
+ src/test/test_statefile.c \
src/test/test_stats.c \
src/test/test_status.c \
src/test/test_storagedir.c \
diff --git a/src/test/test.c b/src/test/test.c
index 2961669c46..77aa6db975 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -709,6 +709,7 @@ struct testgroup_t testgroups[] = {
{ "dir/", dir_tests },
{ "dir/auth/process_descs/", process_descs_tests },
{ "dir/md/", microdesc_tests },
+ { "dirauth/dirvote/", dirvote_tests},
{ "dir/voting/flags/", voting_flags_tests },
{ "dir/voting/schedule/", voting_schedule_tests },
{ "dir_handle_get/", dir_handle_get_tests },
@@ -769,6 +770,7 @@ struct testgroup_t testgroups[] = {
{ "sendme/", sendme_tests },
{ "shared-random/", sr_tests },
{ "socks/", socks_tests },
+ { "statefile/", statefile_tests },
{ "stats/", stats_tests },
{ "status/" , status_tests },
{ "storagedir/", storagedir_tests },
diff --git a/src/test/test.h b/src/test/test.h
index 18987719d0..bd3a4102f5 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -122,6 +122,7 @@ extern struct testcase_t crypto_rng_tests[];
extern struct testcase_t crypto_tests[];
extern struct testcase_t dir_handle_get_tests[];
extern struct testcase_t dir_tests[];
+extern struct testcase_t dirvote_tests[];
extern struct testcase_t dispatch_tests[];
extern struct testcase_t dns_tests[];
extern struct testcase_t dos_tests[];
@@ -186,6 +187,7 @@ extern struct testcase_t scheduler_tests[];
extern struct testcase_t sendme_tests[];
extern struct testcase_t socks_tests[];
extern struct testcase_t sr_tests[];
+extern struct testcase_t statefile_tests[];
extern struct testcase_t stats_tests[];
extern struct testcase_t status_tests[];
extern struct testcase_t storagedir_tests[];
diff --git a/src/test/test_channel.c b/src/test/test_channel.c
index 042eb27d9d..c86327ceb4 100644
--- a/src/test/test_channel.c
+++ b/src/test/test_channel.c
@@ -1382,7 +1382,7 @@ test_channel_for_extend(void *arg)
/* The expected result is chan2 because it is older than chan1. */
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(ret_chan);
tt_ptr_op(ret_chan, OP_EQ, chan2);
tt_int_op(launch, OP_EQ, 0);
@@ -1391,7 +1391,7 @@ test_channel_for_extend(void *arg)
/* Switch that around from previous test. */
chan2->timestamp_created = chan1->timestamp_created + 1;
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(ret_chan);
tt_ptr_op(ret_chan, OP_EQ, chan1);
tt_int_op(launch, OP_EQ, 0);
@@ -1401,7 +1401,7 @@ test_channel_for_extend(void *arg)
* channel 2 should be picked due to how channel_is_better() works. */
chan2->timestamp_created = chan1->timestamp_created;
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(ret_chan);
tt_ptr_op(ret_chan, OP_EQ, chan1);
tt_int_op(launch, OP_EQ, 0);
@@ -1413,7 +1413,7 @@ test_channel_for_extend(void *arg)
/* Condemned the older channel. */
chan1->state = CHANNEL_STATE_CLOSING;
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(ret_chan);
tt_ptr_op(ret_chan, OP_EQ, chan2);
tt_int_op(launch, OP_EQ, 0);
@@ -1423,7 +1423,7 @@ test_channel_for_extend(void *arg)
/* Make the older channel a client one. */
channel_mark_client(chan1);
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(ret_chan);
tt_ptr_op(ret_chan, OP_EQ, chan2);
tt_int_op(launch, OP_EQ, 0);
@@ -1435,7 +1435,7 @@ test_channel_for_extend(void *arg)
memset(&dumb_ed_id, 0, sizeof(dumb_ed_id));
ret_chan = channel_get_for_extend(digest, &dumb_ed_id,
&ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(!ret_chan);
tt_str_op(msg, OP_EQ, "Not connected. Connecting.");
tt_int_op(launch, OP_EQ, 1);
@@ -1445,7 +1445,7 @@ test_channel_for_extend(void *arg)
chan1->state = CHANNEL_STATE_OPENING;
chan2->state = CHANNEL_STATE_OPENING;
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(!ret_chan);
tt_str_op(msg, OP_EQ, "Connection in progress; waiting.");
tt_int_op(launch, OP_EQ, 0);
@@ -1455,7 +1455,7 @@ test_channel_for_extend(void *arg)
/* Mark channel 1 as bad for circuits. */
channel_mark_bad_for_new_circs(chan1);
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(ret_chan);
tt_ptr_op(ret_chan, OP_EQ, chan2);
tt_int_op(launch, OP_EQ, 0);
@@ -1466,7 +1466,7 @@ test_channel_for_extend(void *arg)
channel_mark_bad_for_new_circs(chan1);
channel_mark_bad_for_new_circs(chan2);
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(!ret_chan);
tt_str_op(msg, OP_EQ, "Connections all too old, or too non-canonical. "
" Launching a new one.");
@@ -1478,7 +1478,7 @@ test_channel_for_extend(void *arg)
test_chan_should_be_canonical = 0;
test_chan_should_match_target = 0;
ret_chan = channel_get_for_extend(digest, &ed_id, &ipv4_addr, &ipv6_addr,
- &msg, &launch);
+ false, &msg, &launch);
tt_assert(!ret_chan);
tt_str_op(msg, OP_EQ, "Connections all too old, or too non-canonical. "
" Launching a new one.");
diff --git a/src/test/test_circuitbuild.c b/src/test/test_circuitbuild.c
index 74824a1bc1..299908ce82 100644
--- a/src/test/test_circuitbuild.c
+++ b/src/test/test_circuitbuild.c
@@ -1214,6 +1214,7 @@ mock_channel_get_for_extend(const char *rsa_id_digest,
const ed25519_public_key_t *ed_id,
const tor_addr_t *target_ipv4_addr,
const tor_addr_t *target_ipv6_addr,
+ bool for_origin_circ,
const char **msg_out,
int *launch_out)
{
@@ -1221,6 +1222,7 @@ mock_channel_get_for_extend(const char *rsa_id_digest,
(void)ed_id;
(void)target_ipv4_addr;
(void)target_ipv6_addr;
+ (void)for_origin_circ;
/* channel_get_for_extend() requires non-NULL arguments */
tt_ptr_op(msg_out, OP_NE, NULL);
diff --git a/src/test/test_connection.c b/src/test/test_connection.c
index 954aeb82e3..178a37adf6 100644
--- a/src/test/test_connection.c
+++ b/src/test/test_connection.c
@@ -617,7 +617,8 @@ test_conn_download_status(void *arg)
connection_t *ap_conn = NULL;
const struct testcase_t *tc = arg;
- consensus_flavor_t usable_flavor = (consensus_flavor_t)tc->setup_data;
+ consensus_flavor_t usable_flavor =
+ networkstatus_parse_flavor_name((const char*) tc->setup_data);
/* The "other flavor" trick only works if there are two flavors */
tor_assert(N_CONSENSUS_FLAVORS == 2);
@@ -1093,17 +1094,17 @@ struct testcase_t connection_tests[] = {
CONNECTION_TESTCASE(get_rend, TT_FORK, test_conn_get_rend_st),
CONNECTION_TESTCASE(get_rsrc, TT_FORK, test_conn_get_rsrc_st),
- CONNECTION_TESTCASE_ARG(download_status, TT_FORK,
- test_conn_download_status_st, FLAV_MICRODESC),
- CONNECTION_TESTCASE_ARG(download_status, TT_FORK,
- test_conn_download_status_st, FLAV_NS),
+ CONNECTION_TESTCASE_ARG(download_status, TT_FORK,
+ test_conn_download_status_st, "microdesc"),
+ CONNECTION_TESTCASE_ARG(download_status, TT_FORK,
+ test_conn_download_status_st, "ns"),
CONNECTION_TESTCASE_ARG(https_proxy_connect, TT_FORK,
test_conn_proxy_connect_st, &PROXY_CONNECT_ARG),
CONNECTION_TESTCASE_ARG(haproxy_proxy_connect, TT_FORK,
test_conn_proxy_connect_st, &PROXY_HAPROXY_ARG),
-//CONNECTION_TESTCASE(func_suffix, TT_FORK, setup_func_pair),
+ //CONNECTION_TESTCASE(func_suffix, TT_FORK, setup_func_pair),
{ "failed_orconn_tracker", test_failed_orconn_tracker, TT_FORK, NULL, NULL },
{ "describe", test_conn_describe, TT_FORK, NULL, NULL },
END_OF_TESTCASES
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index ab0315aa2d..88fbd5ca7d 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -943,7 +943,7 @@ test_dir_formats_rsa_ed25519(void *arg)
ed25519_secret_key_from_seed(&kp2.seckey,
(const uint8_t*)"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
ed25519_public_key_generate(&kp2.pubkey, &kp2.seckey);
- r2->cache_info.signing_key_cert = tor_cert_create(&kp1,
+ r2->cache_info.signing_key_cert = tor_cert_create_ed25519(&kp1,
CERT_TYPE_ID_SIGNING,
&kp2.pubkey,
now, 86400,
@@ -7290,7 +7290,7 @@ test_dir_dirserv_router_get_status(void *arg)
ed25519_secret_key_from_seed(&kp2.seckey,
(const uint8_t*)"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
ed25519_public_key_generate(&kp2.pubkey, &kp2.seckey);
- ri->cache_info.signing_key_cert = tor_cert_create(&kp1,
+ ri->cache_info.signing_key_cert = tor_cert_create_ed25519(&kp1,
CERT_TYPE_ID_SIGNING,
&kp2.pubkey,
now, 86400,
diff --git a/src/test/test_dirvote.c b/src/test/test_dirvote.c
new file mode 100644
index 0000000000..bc2d1150d6
--- /dev/null
+++ b/src/test/test_dirvote.c
@@ -0,0 +1,671 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file test_dirvote.c
+ * \brief Unit tests for dirvote related functions
+ */
+#define DIRVOTE_PRIVATE
+
+#include "core/or/or.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/nodelist/dirlist.h"
+#include "feature/nodelist/node_st.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/signed_descriptor_st.h"
+
+#include "test/test.h"
+
+/**
+ * This struct holds the various informations that are needed for router
+ * comparison. Each router in the test function has one, and they are all
+ * put in a global digestmap, router_properties
+ */
+typedef struct router_values_t {
+ int is_running;
+ int is_auth;
+ int bw_kb;
+ char digest[DIGEST_LEN];
+} router_values_t;
+/**
+ * This typedef makes declaring digests easier and less verbose
+ */
+typedef char sha1_digest_t[DIGEST_LEN];
+
+// Use of global variable is justified because the functions that have to be
+// mocked take as arguments objects we have no control over
+static digestmap_t *router_properties = NULL;
+// Use of global variable is justified by its use in nodelist.c
+// and is necessary to avoid memory leaks when mocking the
+// function node_get_by_id
+static node_t *running_node;
+static node_t *non_running_node;
+
+/* Allocate memory to the global variables that represent a running
+ * and non-running node
+ */
+#define ALLOCATE_MOCK_NODES() \
+ running_node = tor_malloc(sizeof(node_t)); \
+ running_node->is_running = 1; \
+ non_running_node = tor_malloc(sizeof(node_t)); \
+ non_running_node->is_running = 0;
+
+/* Free the memory allocated to the mock nodes */
+#define FREE_MOCK_NODES() \
+ tor_free(running_node); \
+ tor_free(non_running_node);
+
+static int
+mock_router_digest_is_trusted(const char *digest, dirinfo_type_t type)
+{
+ (void)type;
+ router_values_t *mock_status;
+ mock_status = digestmap_get(router_properties, digest);
+ if (!mock_status) {
+ return -1;
+ }
+ return mock_status->is_auth;
+}
+
+static const node_t *
+mock_node_get_by_id(const char *identity_digest)
+{
+ router_values_t *status;
+ status = digestmap_get(router_properties, identity_digest);
+ if (!status) {
+ return NULL;
+ }
+ if (status->is_running)
+ return running_node;
+ else
+ return non_running_node;
+}
+
+static uint32_t
+mock_dirserv_get_bw(const routerinfo_t *ri)
+{
+ const char *digest = ri->cache_info.identity_digest;
+ router_values_t *status;
+ status = digestmap_get(router_properties, digest);
+ if (!status) {
+ return -1;
+ }
+ return status->bw_kb;
+}
+
+/** Generate a pointer to a router_values_t struct with the arguments as
+ * field values, and return it
+ * The returned pointer has to be freed by the caller.
+ */
+static router_values_t *
+router_values_new(int running, int auth, int bw, char *digest)
+{
+ router_values_t *status = tor_malloc(sizeof(router_values_t));
+ memcpy(status->digest, digest, sizeof(status->digest));
+ status->is_running = running;
+ status->bw_kb = bw;
+ status->is_auth = auth;
+ return status;
+}
+
+/** Given a router_values_t struct, generate a pointer to a routerinfo struct.
+ * In the cache_info member, put the identity digest, and depending on
+ * the family argument, fill the IPv4 or IPv6 address. Return the pointer.
+ * The returned pointer has to be freed by the caller.
+ */
+static routerinfo_t *
+routerinfo_new(router_values_t *status, int family, int addr)
+{
+ routerinfo_t *ri = tor_malloc(sizeof(routerinfo_t));
+ signed_descriptor_t cache_info;
+ memcpy(cache_info.identity_digest, status->digest,
+ sizeof(cache_info.identity_digest));
+ ri->cache_info = cache_info;
+ tor_addr_t ipv6, ipv4;
+ ipv6.family = family;
+ ipv4.family = family;
+ // Set the address of the other IP version to 0
+ if (family == AF_INET) {
+ ipv4.addr.in_addr.s_addr = addr;
+ for (size_t i = 0; i < 16; i++) {
+ ipv6.addr.in6_addr.s6_addr[i] = 0;
+ }
+ } else {
+ for (size_t i = 0; i < 16; i++) {
+ ipv6.addr.in6_addr.s6_addr[i] = addr;
+ }
+ ipv4.addr.in_addr.s_addr = 0;
+ }
+ ri->ipv6_addr = ipv6;
+ ri->ipv4_addr = ipv4;
+ return ri;
+}
+
+static void
+test_dirvote_compare_routerinfo_usefulness(void *arg)
+{
+ (void)arg;
+ MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted);
+ MOCK(node_get_by_id, mock_node_get_by_id);
+ MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw);
+ ALLOCATE_MOCK_NODES();
+ router_properties = digestmap_new();
+
+ // The router one is the "least useful" router, every router is compared to
+ // it
+ sha1_digest_t digest_one = "aaaa";
+ router_values_t *status_one = router_values_new(0, 0, 0, digest_one);
+ digestmap_set(router_properties, status_one->digest, status_one);
+ sha1_digest_t digest_two = "bbbb";
+ router_values_t *status_two = router_values_new(0, 1, 0, digest_two);
+ digestmap_set(router_properties, status_two->digest, status_two);
+ sha1_digest_t digest_three = "cccc";
+ router_values_t *status_three = router_values_new(1, 0, 0, digest_three);
+ digestmap_set(router_properties, status_three->digest, status_three);
+ sha1_digest_t digest_four = "dddd";
+ router_values_t *status_four = router_values_new(0, 0, 128, digest_four);
+ digestmap_set(router_properties, status_four->digest, status_four);
+ sha1_digest_t digest_five = "9999";
+ router_values_t *status_five = router_values_new(0, 0, 0, digest_five);
+ digestmap_set(router_properties, status_five->digest, status_five);
+
+ // A router that has auth status is more useful than a non-auth one
+ routerinfo_t *first = routerinfo_new(status_one, AF_INET, 0xf);
+ routerinfo_t *second = routerinfo_new(status_two, AF_INET, 0xf);
+ int a = compare_routerinfo_usefulness(first, second);
+ tt_assert(a == 1);
+ tor_free(second);
+
+ // A running router is more useful than a non running one
+ routerinfo_t *third = routerinfo_new(status_three, AF_INET, 0xf);
+ a = compare_routerinfo_usefulness(first, third);
+ tt_assert(a == 1);
+ tor_free(third);
+
+ // A higher bandwidth is more useful
+ routerinfo_t *fourth = routerinfo_new(status_four, AF_INET, 0xf);
+ a = compare_routerinfo_usefulness(first, fourth);
+ tt_assert(a == 1);
+ tor_free(fourth);
+
+ // In case of tie, the digests are compared
+ routerinfo_t *fifth = routerinfo_new(status_five, AF_INET, 0xf);
+ a = compare_routerinfo_usefulness(first, fifth);
+ tt_assert(a > 0);
+ tor_free(fifth);
+
+done:
+ UNMOCK(router_digest_is_trusted_dir_type);
+ UNMOCK(node_get_by_id);
+ UNMOCK(dirserv_get_bandwidth_for_router_kb);
+ FREE_MOCK_NODES();
+ digestmap_free(router_properties, NULL);
+ tor_free(status_one);
+ tor_free(status_two);
+ tor_free(status_three);
+ tor_free(status_four);
+ tor_free(status_five);
+ tor_free(first);
+}
+
+static void
+test_dirvote_compare_routerinfo_by_ipv4(void *arg)
+{
+ (void)arg;
+ MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted);
+ MOCK(node_get_by_id, mock_node_get_by_id);
+ MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw);
+
+ ALLOCATE_MOCK_NODES();
+ router_properties = digestmap_new();
+ sha1_digest_t digest_one = "aaaa";
+ router_values_t *status_one = router_values_new(0, 0, 0, digest_one);
+ digestmap_set(router_properties, status_one->digest, status_one);
+ sha1_digest_t digest_two = "bbbb";
+ router_values_t *status_two = router_values_new(0, 1, 0, digest_two);
+ digestmap_set(router_properties, status_two->digest, status_two);
+
+ // Both routers have an IPv4 address
+ routerinfo_t *first = routerinfo_new(status_one, AF_INET, 1);
+ routerinfo_t *second = routerinfo_new(status_two, AF_INET, 0xf);
+
+ // The first argument's address precedes the seconds' one
+ int a = compare_routerinfo_by_ipv4((const void **)&first,
+ (const void **)&second);
+ tt_assert(a < 0);
+ // The second argument's address precedes the first' one
+ a = compare_routerinfo_by_ipv4((const void **)&second,
+ (const void **)&first);
+ tt_assert(a > 0);
+ tor_addr_copy(&(second->ipv4_addr), &(first->ipv6_addr));
+ // The addresses are equal, they are compared by usefulness,
+ // and first is less useful than second
+ a = compare_routerinfo_by_ipv4((const void **)&first,
+ (const void **)&second);
+ tt_assert(a == 1);
+done:
+ UNMOCK(router_digest_is_trusted_dir_type);
+ UNMOCK(node_get_by_id);
+ UNMOCK(dirserv_get_bandwidth_for_router_kb);
+ FREE_MOCK_NODES();
+ digestmap_free(router_properties, NULL);
+ tor_free(status_one);
+ tor_free(status_two);
+ tor_free(first);
+ tor_free(second);
+}
+
+static void
+test_dirvote_compare_routerinfo_by_ipv6(void *arg)
+{
+ (void)arg;
+ MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted);
+ MOCK(node_get_by_id, mock_node_get_by_id);
+ MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw);
+
+ ALLOCATE_MOCK_NODES();
+ router_properties = digestmap_new();
+ char digest_one[DIGEST_LEN] = "aaaa";
+ router_values_t *status_one = router_values_new(0, 0, 0, digest_one);
+ digestmap_set(router_properties, status_one->digest, status_one);
+ char digest_two[DIGEST_LEN] = "bbbb";
+ router_values_t *status_two = router_values_new(0, 1, 0, digest_two);
+ digestmap_set(router_properties, status_two->digest, status_two);
+
+ // Both routers have an IPv6 address
+ routerinfo_t *first = routerinfo_new(status_one, AF_INET6, 1);
+ routerinfo_t *second = routerinfo_new(status_two, AF_INET6, 0xf);
+
+ // The first argument's address precedes the seconds' one
+ int a = compare_routerinfo_by_ipv6((const void **)&first,
+ (const void **)&second);
+ tt_assert(a < 0);
+ // The second argument's address precedes the first' one
+ a = compare_routerinfo_by_ipv6((const void **)&second,
+ (const void **)&first);
+ tt_assert(a > 0);
+ tor_addr_copy(&(first->ipv6_addr), &(second->ipv6_addr));
+ // The addresses are equal, they are compared by usefulness,
+ // and first is less useful than second
+ a = compare_routerinfo_by_ipv6((const void **)&first,
+ (const void **)&second);
+ tt_assert(a == 1);
+done:
+ UNMOCK(router_digest_is_trusted_dir_type);
+ UNMOCK(node_get_by_id);
+ UNMOCK(dirserv_get_bandwidth_for_router_kb);
+ FREE_MOCK_NODES();
+ digestmap_free(router_properties, NULL);
+ tor_free(status_one);
+ tor_free(status_two);
+ tor_free(first);
+ tor_free(second);
+}
+
+/** Create routers values and routerinfos that always have the same
+ * characteristics, and add them to the global digestmap. This macro is here to
+ * avoid duplicated code fragments.
+ * The created name##_val pointer should be freed by the caller (and cannot
+ * be freed in the macro as it causes a heap-after-free error)
+ */
+#define CREATE_ROUTER(digest, name, addr, ip_version) \
+ sha1_digest_t name##_digest = digest; \
+ name##_val = router_values_new(1, 1, 1, name##_digest); \
+ digestmap_set(router_properties, name##_digest, name##_val); \
+ name##_ri = routerinfo_new(name##_val, ip_version, addr);
+
+#define ROUTER_FREE(name) \
+ tor_free(name##_val); \
+ tor_free(name##_ri);
+
+/** Test to see if the returned routers are exactly the ones that should be
+ * flagged as sybils : we test for inclusion then for number of elements
+ */
+#define TEST_SYBIL(true_sybil, possible_sybil) \
+ DIGESTMAP_FOREACH (true_sybil, sybil_id, void *, ignore) { \
+ (void)ignore; \
+ tt_assert(digestmap_get(possible_sybil, sybil_id)); \
+ } \
+ DIGESTMAP_FOREACH_END; \
+ tt_assert(digestmap_size(true_sybil) == digestmap_size(possible_sybil));
+
+static void
+test_dirvote_get_sybil_by_ip_version_ipv4(void *arg)
+{
+ // It is assumed that global_dirauth_options.AuthDirMaxServersPerAddr == 2
+ (void)arg;
+ router_values_t *aaaa_val=NULL, *bbbb_val=NULL, *cccc_val=NULL,
+ *dddd_val=NULL, *eeee_val=NULL, *ffff_val=NULL, *gggg_val=NULL,
+ *hhhh_val=NULL;
+ routerinfo_t *aaaa_ri=NULL, *bbbb_ri=NULL, *cccc_ri=NULL,
+ *dddd_ri=NULL, *eeee_ri=NULL, *ffff_ri=NULL, *gggg_ri=NULL,
+ *hhhh_ri=NULL;
+
+ MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted);
+ MOCK(node_get_by_id, mock_node_get_by_id);
+ MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw);
+ ALLOCATE_MOCK_NODES();
+ router_properties = digestmap_new();
+ smartlist_t *routers_ipv4;
+ routers_ipv4 = smartlist_new();
+ digestmap_t *true_sybil_routers = NULL;
+ true_sybil_routers = digestmap_new();
+ digestmap_t *omit_as_sybil;
+
+ CREATE_ROUTER("aaaa", aaaa, 123, AF_INET);
+ smartlist_add(routers_ipv4, aaaa_ri);
+ CREATE_ROUTER("bbbb", bbbb, 123, AF_INET);
+ smartlist_add(routers_ipv4, bbbb_ri);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET);
+ tt_assert(digestmap_isempty(omit_as_sybil) == 1);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("cccc", cccc, 123, AF_INET);
+ smartlist_add(routers_ipv4, cccc_ri);
+ digestmap_set(true_sybil_routers, cccc_digest, cccc_digest);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("dddd", dddd, 123, AF_INET);
+ smartlist_add(routers_ipv4, dddd_ri);
+ digestmap_set(true_sybil_routers, dddd_digest, dddd_digest);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("eeee", eeee, 456, AF_INET);
+ smartlist_add(routers_ipv4, eeee_ri);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("ffff", ffff, 456, AF_INET);
+ smartlist_add(routers_ipv4, ffff_ri);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("gggg", gggg, 456, AF_INET);
+ smartlist_add(routers_ipv4, gggg_ri);
+ digestmap_set(true_sybil_routers, gggg_digest, gggg_digest);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("hhhh", hhhh, 456, AF_INET);
+ smartlist_add(routers_ipv4, hhhh_ri);
+ digestmap_set(true_sybil_routers, hhhh_digest, hhhh_digest);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv4, AF_INET);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+
+done:
+ UNMOCK(router_digest_is_trusted_dir_type);
+ UNMOCK(node_get_by_id);
+ UNMOCK(dirserv_get_bandwidth_for_router_kb);
+ FREE_MOCK_NODES();
+ digestmap_free(router_properties, NULL);
+ smartlist_free(routers_ipv4);
+ digestmap_free(omit_as_sybil, NULL);
+ digestmap_free(true_sybil_routers, NULL);
+ ROUTER_FREE(aaaa);
+ ROUTER_FREE(bbbb);
+ ROUTER_FREE(cccc);
+ ROUTER_FREE(dddd);
+ ROUTER_FREE(eeee);
+ ROUTER_FREE(ffff);
+ ROUTER_FREE(gggg);
+ ROUTER_FREE(hhhh);
+}
+
+static void
+test_dirvote_get_sybil_by_ip_version_ipv6(void *arg)
+{
+ router_values_t *aaaa_val=NULL, *bbbb_val=NULL, *cccc_val=NULL,
+ *dddd_val=NULL, *eeee_val=NULL, *ffff_val=NULL, *gggg_val=NULL,
+ *hhhh_val=NULL;
+ routerinfo_t *aaaa_ri=NULL, *bbbb_ri=NULL, *cccc_ri=NULL,
+ *dddd_ri=NULL, *eeee_ri=NULL, *ffff_ri=NULL, *gggg_ri=NULL,
+ *hhhh_ri=NULL;
+
+ // It is assumed that global_dirauth_options.AuthDirMaxServersPerAddr == 2
+ (void)arg;
+ MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted);
+ MOCK(node_get_by_id, mock_node_get_by_id);
+ MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw);
+ ALLOCATE_MOCK_NODES();
+ router_properties = digestmap_new();
+ smartlist_t *routers_ipv6;
+ routers_ipv6 = smartlist_new();
+ digestmap_t *true_sybil_routers = NULL;
+ true_sybil_routers = digestmap_new();
+ digestmap_t *omit_as_sybil;
+
+ CREATE_ROUTER("aaaa", aaaa, 123, AF_INET6);
+ smartlist_add(routers_ipv6, aaaa_ri);
+ CREATE_ROUTER("bbbb", bbbb, 123, AF_INET6);
+ smartlist_add(routers_ipv6, bbbb_ri);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("cccc", cccc, 123, AF_INET6);
+ smartlist_add(routers_ipv6, cccc_ri);
+ digestmap_set(true_sybil_routers, cccc_digest, cccc_digest);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("dddd", dddd, 123, AF_INET6);
+ smartlist_add(routers_ipv6, dddd_ri);
+ digestmap_set(true_sybil_routers, dddd_digest, dddd_digest);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("eeee", eeee, 456, AF_INET6);
+ smartlist_add(routers_ipv6, eeee_ri);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("ffff", ffff, 456, AF_INET6);
+ smartlist_add(routers_ipv6, ffff_ri);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("gggg", gggg, 456, AF_INET6);
+ smartlist_add(routers_ipv6, gggg_ri);
+ digestmap_set(true_sybil_routers, gggg_digest, gggg_digest);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("hhhh", hhhh, 456, AF_INET6);
+ smartlist_add(routers_ipv6, hhhh_ri);
+ digestmap_set(true_sybil_routers, hhhh_digest, hhhh_digest);
+ omit_as_sybil = get_sybil_list_by_ip_version(routers_ipv6, AF_INET6);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+done:
+ UNMOCK(router_digest_is_trusted_dir_type);
+ UNMOCK(node_get_by_id);
+ UNMOCK(dirserv_get_bandwidth_for_router_kb);
+ FREE_MOCK_NODES();
+ digestmap_free(router_properties, NULL);
+ digestmap_free(true_sybil_routers, NULL);
+ smartlist_free(routers_ipv6);
+ digestmap_free(omit_as_sybil, NULL);
+ ROUTER_FREE(aaaa);
+ ROUTER_FREE(bbbb);
+ ROUTER_FREE(cccc);
+ ROUTER_FREE(dddd);
+ ROUTER_FREE(eeee);
+ ROUTER_FREE(ffff);
+ ROUTER_FREE(gggg);
+ ROUTER_FREE(hhhh);
+}
+
+static void
+test_dirvote_get_all_possible_sybil(void *arg)
+{
+ router_values_t *aaaa_val=NULL, *bbbb_val=NULL, *cccc_val=NULL,
+ *dddd_val=NULL, *eeee_val=NULL, *ffff_val=NULL, *gggg_val=NULL,
+ *hhhh_val=NULL, *iiii_val=NULL, *jjjj_val=NULL, *kkkk_val=NULL,
+ *llll_val=NULL, *mmmm_val=NULL, *nnnn_val=NULL, *oooo_val=NULL,
+ *pppp_val=NULL;
+ routerinfo_t *aaaa_ri=NULL, *bbbb_ri=NULL, *cccc_ri=NULL,
+ *dddd_ri=NULL, *eeee_ri=NULL, *ffff_ri=NULL, *gggg_ri=NULL,
+ *hhhh_ri=NULL, *iiii_ri=NULL, *jjjj_ri=NULL, *kkkk_ri=NULL,
+ *llll_ri=NULL, *mmmm_ri=NULL, *nnnn_ri=NULL, *oooo_ri=NULL,
+ *pppp_ri=NULL;
+
+ // It is assumed that global_dirauth_options.AuthDirMaxServersPerAddr == 2
+ (void)arg;
+ MOCK(router_digest_is_trusted_dir_type, mock_router_digest_is_trusted);
+ MOCK(node_get_by_id, mock_node_get_by_id);
+ MOCK(dirserv_get_bandwidth_for_router_kb, mock_dirserv_get_bw);
+ ALLOCATE_MOCK_NODES();
+ router_properties = digestmap_new();
+ smartlist_t *routers;
+ routers = smartlist_new();
+ digestmap_t *true_sybil_routers = NULL;
+ true_sybil_routers = digestmap_new();
+ digestmap_t *omit_as_sybil;
+
+ CREATE_ROUTER("aaaa", aaaa, 123, AF_INET);
+ smartlist_add(routers, aaaa_ri);
+ CREATE_ROUTER("bbbb", bbbb, 123, AF_INET);
+ smartlist_add(routers, bbbb_ri);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("cccc", cccc, 123, AF_INET);
+ smartlist_add(routers, cccc_ri);
+ digestmap_set(true_sybil_routers, cccc_digest, cccc_digest);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("dddd", dddd, 123, AF_INET);
+ smartlist_add(routers, dddd_ri);
+ digestmap_set(true_sybil_routers, dddd_digest, dddd_digest);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("eeee", eeee, 456, AF_INET);
+ smartlist_add(routers, eeee_ri);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("ffff", ffff, 456, AF_INET);
+ smartlist_add(routers, ffff_ri);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("gggg", gggg, 456, AF_INET);
+ smartlist_add(routers, gggg_ri);
+ digestmap_set(true_sybil_routers, gggg_digest, gggg_digest);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("hhhh", hhhh, 456, AF_INET);
+ smartlist_add(routers, hhhh_ri);
+ digestmap_set(true_sybil_routers, hhhh_digest, hhhh_digest);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("iiii", iiii, 123, AF_INET6);
+ smartlist_add(routers, iiii_ri);
+ CREATE_ROUTER("jjjj", jjjj, 123, AF_INET6);
+ smartlist_add(routers, jjjj_ri);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("kkkk", kkkk, 123, AF_INET6);
+ smartlist_add(routers, kkkk_ri);
+ digestmap_set(true_sybil_routers, kkkk_digest, kkkk_digest);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil,NULL);
+
+ CREATE_ROUTER("llll", llll, 123, AF_INET6);
+ smartlist_add(routers, llll_ri);
+ digestmap_set(true_sybil_routers, llll_digest, llll_digest);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil,NULL);
+
+ CREATE_ROUTER("mmmm", mmmm, 456, AF_INET6);
+ smartlist_add(routers, mmmm_ri);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("nnnn", nnnn, 456, AF_INET6);
+ smartlist_add(routers, nnnn_ri);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("oooo", oooo, 456, AF_INET6);
+ smartlist_add(routers, oooo_ri);
+ digestmap_set(true_sybil_routers, oooo_digest, oooo_digest);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+ digestmap_free(omit_as_sybil, NULL);
+
+ CREATE_ROUTER("pppp", pppp, 456, AF_INET6);
+ smartlist_add(routers, pppp_ri);
+ digestmap_set(true_sybil_routers, pppp_digest, pppp_digest);
+ omit_as_sybil = get_all_possible_sybil(routers);
+ TEST_SYBIL(true_sybil_routers, omit_as_sybil);
+
+done:
+ UNMOCK(router_digest_is_trusted_dir_type);
+ UNMOCK(node_get_by_id);
+ UNMOCK(dirserv_get_bandwidth_for_router_kb);
+ FREE_MOCK_NODES();
+ digestmap_free(router_properties, NULL);
+ smartlist_free(routers);
+ digestmap_free(omit_as_sybil, NULL);
+ digestmap_free(true_sybil_routers, NULL);
+ ROUTER_FREE(aaaa);
+ ROUTER_FREE(bbbb);
+ ROUTER_FREE(cccc);
+ ROUTER_FREE(dddd);
+ ROUTER_FREE(eeee);
+ ROUTER_FREE(ffff);
+ ROUTER_FREE(gggg);
+ ROUTER_FREE(hhhh);
+ ROUTER_FREE(iiii);
+ ROUTER_FREE(jjjj);
+ ROUTER_FREE(kkkk);
+ ROUTER_FREE(llll);
+ ROUTER_FREE(mmmm);
+ ROUTER_FREE(nnnn);
+ ROUTER_FREE(oooo);
+ ROUTER_FREE(pppp);
+}
+
+#define NODE(name, flags) \
+ { \
+ #name, test_dirvote_##name, (flags), NULL, NULL \
+ }
+
+struct testcase_t dirvote_tests[] = {
+ NODE(compare_routerinfo_usefulness, TT_FORK),
+ NODE(compare_routerinfo_by_ipv6, TT_FORK),
+ NODE(compare_routerinfo_by_ipv4, TT_FORK),
+ 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),
+ END_OF_TESTCASES};
diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c
index 782b78306c..b6e13c79a8 100644
--- a/src/test/test_hs_descriptor.c
+++ b/src/test/test_hs_descriptor.c
@@ -56,7 +56,7 @@ test_cert_encoding(void *arg)
ret = ed25519_public_key_generate(&signed_key, &secret_key);
tt_int_op(ret, == , 0);
- cert = tor_cert_create(&kp, CERT_TYPE_SIGNING_AUTH, &signed_key,
+ cert = tor_cert_create_ed25519(&kp, CERT_TYPE_SIGNING_AUTH, &signed_key,
now, 3600 * 2, CERT_FLAG_INCLUDE_SIGNING_KEY);
tt_assert(cert);
@@ -706,7 +706,7 @@ test_validate_cert(void *arg)
tt_int_op(ret, OP_EQ, 0);
/* Cert of type CERT_TYPE_AUTH_HS_IP_KEY. */
- cert = tor_cert_create(&kp, CERT_TYPE_AUTH_HS_IP_KEY,
+ cert = tor_cert_create_ed25519(&kp, CERT_TYPE_AUTH_HS_IP_KEY,
&kp.pubkey, now, 3600,
CERT_FLAG_INCLUDE_SIGNING_KEY);
tt_assert(cert);
@@ -726,8 +726,9 @@ test_validate_cert(void *arg)
tor_cert_free(cert);
/* Try a cert without including the signing key. */
- cert = tor_cert_create(&kp, CERT_TYPE_AUTH_HS_IP_KEY, &kp.pubkey, now,
- 3600, 0);
+ cert = tor_cert_create_ed25519(&kp, CERT_TYPE_AUTH_HS_IP_KEY,
+ &kp.pubkey, now, 3600, 0);
+
tt_assert(cert);
/* Test with a bad type. */
ret = cert_is_valid(cert, CERT_TYPE_AUTH_HS_IP_KEY, "unicorn");
diff --git a/src/test/test_link_handshake.c b/src/test/test_link_handshake.c
index 1566b349ed..06af299056 100644
--- a/src/test/test_link_handshake.c
+++ b/src/test/test_link_handshake.c
@@ -710,7 +710,7 @@ CERTS_FAIL(missing_signing_key, /* ed25519 */
* signing key. */
const ed25519_keypair_t *mk = get_master_identity_keypair();
const ed25519_keypair_t *sk = get_master_signing_keypair();
- tor_cert_t *bad_cert = tor_cert_create(mk, CERT_TYPE_ID_SIGNING,
+ tor_cert_t *bad_cert = tor_cert_create_ed25519(mk, CERT_TYPE_ID_SIGNING,
&sk->pubkey, time(NULL), 86400,
0 /* don't include signer */);
certs_cell_cert_setlen_body(cert, bad_cert->encoded_len);
diff --git a/src/test/test_routerkeys.c b/src/test/test_routerkeys.c
index 8d653e44a2..e5314046b9 100644
--- a/src/test/test_routerkeys.c
+++ b/src/test/test_routerkeys.c
@@ -151,7 +151,7 @@ test_routerkeys_ed_certs(void *args)
for (int i = 0; i <= 1; ++i) {
uint32_t flags = i ? CERT_FLAG_INCLUDE_SIGNING_KEY : 0;
- cert[i] = tor_cert_create(&kp1, 5, &kp2.pubkey, now, 10000, flags);
+ cert[i] = tor_cert_create_ed25519(&kp1, 5, &kp2.pubkey, now, 10000, flags);
tt_assert(cert[i]);
tt_uint_op(cert[i]->sig_bad, OP_EQ, 0);
diff --git a/src/test/test_statefile.c b/src/test/test_statefile.c
new file mode 100644
index 0000000000..dc9ecfee3e
--- /dev/null
+++ b/src/test/test_statefile.c
@@ -0,0 +1,56 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+
+#define STATEFILE_PRIVATE
+
+#include "core/or/or.h"
+#include "lib/encoding/confline.h"
+#include "app/config/statefile.h"
+
+#include "test/test.h"
+
+static void
+test_statefile_remove_obsolete(void *arg)
+{
+ (void)arg;
+ config_line_t *inp = NULL;
+ /* try empty config */
+ or_state_remove_obsolete_lines(&inp);
+ tt_assert(!inp);
+
+ /* try removing every line */
+ config_line_append(&inp, "EntryGuard", "doesn't matter");
+ config_line_append(&inp, "HidServRevCounter", "ignore");
+ config_line_append(&inp, "hidservrevcounter", "foobar"); // note case
+ or_state_remove_obsolete_lines(&inp);
+ tt_assert(!inp);
+
+ /* Now try removing a subset of lines. */
+ config_line_append(&inp, "EntryGuard", "doesn't matter");
+ config_line_append(&inp, "Guard", "in use");
+ config_line_append(&inp, "HidServRevCounter", "ignore");
+ config_line_append(&inp, "TorVersion", "this test doesn't care");
+ or_state_remove_obsolete_lines(&inp);
+ tt_assert(inp);
+ tt_str_op(inp->key, OP_EQ, "Guard");
+ tt_str_op(inp->value, OP_EQ, "in use");
+ tt_assert(inp->next);
+ tt_str_op(inp->next->key, OP_EQ, "TorVersion");
+ tt_str_op(inp->next->value, OP_EQ, "this test doesn't care");
+ tt_assert(! inp->next->next);
+
+ done:
+ config_free_lines(inp);
+}
+
+#define T(name) \
+ { #name, test_statefile_##name, 0, NULL, NULL }
+
+struct testcase_t statefile_tests[] = {
+ T(remove_obsolete),
+ END_OF_TESTCASES
+};