Browse Source

Merge branch 'maint-0.3.3' of https://git.torproject.org/tor into maint-0.3.3

David Goulet 6 years ago
parent
commit
0431bb61ca
100 changed files with 1336 additions and 1432 deletions
  1. 165 112
      .travis.yml
  2. 2 1
      Makefile.am
  3. 4 0
      changes/27286
  4. 4 0
      changes/bug20424_029_minimal
  5. 5 0
      changes/bug25440
  6. 3 0
      changes/bug25505
  7. 5 0
      changes/bug25512
  8. 5 0
      changes/bug25705
  9. 5 0
      changes/bug26269
  10. 4 0
      changes/bug26485
  11. 3 0
      changes/bug26497
  12. 3 0
      changes/bug26497-backport
  13. 4 0
      changes/bug26497-cd
  14. 7 0
      changes/bug26627
  15. 4 0
      changes/bug26779
  16. 4 0
      changes/bug26785
  17. 3 0
      changes/bug26787
  18. 3 0
      changes/bug26830
  19. 3 0
      changes/bug26853
  20. 4 0
      changes/bug26873
  21. 4 0
      changes/bug26876
  22. 4 0
      changes/bug26924
  23. 4 0
      changes/bug26927
  24. 3 0
      changes/bug26932
  25. 4 0
      changes/bug26948
  26. 4 0
      changes/bug27081
  27. 5 0
      changes/bug27088
  28. 3 0
      changes/bug27090
  29. 3 0
      changes/bug27093
  30. 4 0
      changes/bug27164
  31. 4 0
      changes/bug27177
  32. 3 0
      changes/bug27185
  33. 4 0
      changes/bug27206
  34. 5 0
      changes/bug27226
  35. 3 0
      changes/bug27295
  36. 4 0
      changes/bug27335
  37. 4 0
      changes/bug27344
  38. 5 0
      changes/bug27345
  39. 3 0
      changes/bug27418
  40. 3 0
      changes/bug27453
  41. 5 0
      changes/bug27461
  42. 3 0
      changes/bug27463
  43. 5 0
      changes/bug27465
  44. 4 0
      changes/bug27649
  45. 6 0
      changes/bug27658
  46. 4 0
      changes/bug27687
  47. 4 0
      changes/bug27708
  48. 4 0
      changes/geoip-2018-07-03
  49. 4 0
      changes/geoip-2018-08-07
  50. 4 0
      changes/geoip-2018-09-06
  51. 4 0
      changes/task26771
  52. 3 0
      changes/ticket24629
  53. 3 0
      changes/ticket24629-backport
  54. 3 0
      changes/ticket26560
  55. 4 0
      changes/ticket26647
  56. 3 0
      changes/ticket26952-cargo
  57. 3 0
      changes/ticket26952-ccache
  58. 3 0
      changes/ticket27087
  59. 6 0
      changes/ticket27252
  60. 5 0
      changes/ticket27252-032
  61. 62 6
      configure.ac
  62. 1 1
      contrib/win32build/tor-mingw.nsi.in
  63. 5 3
      doc/HACKING/GettingStartedRust.md
  64. 4 1
      src/common/address.c
  65. 2 3
      src/common/compat_threads.c
  66. 11 8
      src/common/compat_threads.h
  67. 4 0
      src/common/compress_zstd.c
  68. 1 1
      src/common/sandbox.c
  69. 12 5
      src/common/tortls.c
  70. 225 505
      src/config/geoip
  71. 212 650
      src/config/geoip6
  72. 10 2
      src/ext/tinytest.c
  73. 2 2
      src/or/auth_dirs.inc
  74. 7 2
      src/or/channelpadding.c
  75. 34 11
      src/or/circuituse.c
  76. 9 1
      src/or/config.c
  77. 0 1
      src/or/connection_edge.c
  78. 9 5
      src/or/connection_or.c
  79. 12 1
      src/or/control.c
  80. 41 10
      src/or/dirserv.c
  81. 1 2
      src/or/dirserv.h
  82. 8 1
      src/or/dirvote.c
  83. 14 6
      src/or/hs_circuit.c
  84. 24 12
      src/or/hs_service.c
  85. 3 2
      src/or/hs_service.h
  86. 13 4
      src/or/main.c
  87. 9 0
      src/or/rendclient.c
  88. 9 6
      src/or/router.c
  89. 3 0
      src/rust/protover/errors.rs
  90. 67 28
      src/rust/protover/protoset.rs
  91. 36 6
      src/rust/protover/protover.rs
  92. 7 7
      src/rust/protover/tests/protover.rs
  93. 0 2
      src/rust/tor_rust/include.am
  94. 1 1
      src/test/include.am
  95. 2 8
      src/test/test.c
  96. 2 0
      src/test/test_bt.sh
  97. 18 13
      src/test/test_config.c
  98. 52 1
      src/test/test_dir.c
  99. 6 0
      src/test/test_entrynodes.c
  100. 2 2
      src/test/test_hs_cell.c

+ 165 - 112
.travis.yml

@@ -1,75 +1,60 @@
 language: c
 language: c
 
 
-## Comment out the compiler list for now to allow an explicit build
-## matrix.
-# compiler:
-#   - gcc
-#   - clang
+cache:
+  ccache: true
+  ## cargo: true
+  directories:
+    - $HOME/.cargo
+    ## where we point CARGO_TARGET_DIR in all our cargo invocations
+    - $TRAVIS_BUILD_DIR/src/rust/target
 
 
-notifications:
-  irc:
-    channels:
-      - "irc.oftc.net#tor-ci"
-    template:
-      - "%{repository} %{branch} %{commit} - %{author}: %{commit_subject}"
-      - "Build #%{build_number} %{result}. Details: %{build_url}"
-    on_success: change
-    on_failure: change
-  email:
-    on_success: never
-    on_failure: change
+compiler:
+  - gcc
+  - clang
 
 
 os:
 os:
   - linux
   - linux
-  ## Uncomment the following line to also run the entire build matrix on OSX.
-  ## This will make your CI builds take roughly ten times longer to finish.
-  # - osx
-
-## Use the Ubuntu Trusty images.
-dist: trusty
-
-## We don't need sudo. (The "apt:" stanza after this allows us to not need sudo;
-## otherwise, we would need it for getting dependencies.)
-##
-## We override this in the explicit build matrix to work around a
-## Travis CI environment regression
-## https://github.com/travis-ci/travis-ci/issues/9033
-sudo: false
+  - osx
 
 
-## (Linux only) Download our dependencies
-addons:
-  apt:
-    packages:
-      ## Required dependencies
-      - libevent-dev
-      - libseccomp2
-      - zlib1g-dev
-      ## Optional dependencies
-      - liblzma-dev
-      - libscrypt-dev
-      ## zstd doesn't exist in Ubuntu Trusty
-      #- libzstd
-
-## The build matrix in the following two stanzas expands into four builds (per OS):
-##
-##  * with GCC, with Rust
-##  * with GCC, without Rust
-##  * with Clang, with Rust
-##  * with Clang, without Rust
+## The build matrix in the following stanza expands into builds for each
+## OS and compiler.
 env:
 env:
   global:
   global:
     ## The Travis CI environment allows us two cores, so let's use both.
     ## The Travis CI environment allows us two cores, so let's use both.
     - MAKEFLAGS="-j 2"
     - MAKEFLAGS="-j 2"
+    ## We turn on hardening by default
+    ## Also known as --enable-fragile-hardening in 0.3.0.3-alpha and later
+    - HARDENING_OPTIONS="--enable-expensive-hardening"
+    ## We turn off asciidoc by default, because it's slow
+    - ASCIIDOC_OPTIONS="--disable-asciidoc"
   matrix:
   matrix:
-    ## Leave at least one entry here or Travis seems to generate a
-    ## matrix entry with empty matrix environment variables.  Leaving
-    ## more than one entry causes unwanted matrix entries with
-    ## unspecified compilers.
-    - RUST_OPTIONS="--enable-rust --enable-cargo-online-mode"
-    # - RUST_OPTIONS="--enable-rust" TOR_RUST_DEPENDENCIES=true
-    # - RUST_OPTIONS=""
+    ## We want to use each build option at least once
+    ##
+    ## We don't list default variable values, because we set the defaults
+    ## in global (or the default is unset)
+    -
+    ## We turn off hardening for Rust builds, because they are incompatible,
+    ## and it's going to take a while for them to be fixed. See:
+    ##   https:/trac.torproject.org/projects/tor/ticket/25386
+    ##   https:/trac.torproject.org/projects/tor/ticket/26398
+    ## TOR_RUST_DEPENDENCIES is spelt RUST_DEPENDENCIES in 0.3.2
+    - RUST_OPTIONS="--enable-rust" TOR_RUST_DEPENDENCIES=true HARDENING_OPTIONS=""
 
 
 matrix:
 matrix:
+  ## include creates builds with gcc, linux, sudo: false
+  include:
+    ## We include a single coverage build with the best options for coverage
+    - env: COVERAGE_OPTIONS="--enable-coverage" HARDENING_OPTIONS=""
+    ## We only want to check these build option combinations once
+    ## (they shouldn't vary by compiler or OS)
+    ## We run rust and coverage with hardening off, which seems like enough
+    # - env: HARDENING_OPTIONS=""
+    ## We check asciidoc with distcheck, to make sure we remove doc products
+    - env: DISTCHECK="yes" ASCIIDOC_OPTIONS=""
+    ## Check rust online with distcheck, to make sure we remove rust products
+    ## But without hardening (see above)
+    - env: DISTCHECK="yes" RUST_OPTIONS="--enable-rust --enable-cargo-online-mode" HARDENING_OPTIONS=""
+
   ## Uncomment to allow the build to report success (with non-required
   ## Uncomment to allow the build to report success (with non-required
   ## sub-builds continuing to run) if all required sub-builds have
   ## sub-builds continuing to run) if all required sub-builds have
   ## succeeded.  This is somewhat buggy currently: it can cause
   ## succeeded.  This is somewhat buggy currently: it can cause
@@ -78,87 +63,155 @@ matrix:
   ## https://github.com/travis-ci/travis-ci/issues/1696
   ## https://github.com/travis-ci/travis-ci/issues/1696
   # fast_finish: true
   # fast_finish: true
 
 
-  ## Uncomment the appropriate lines below to allow the build to
-  ## report success even if some less-critical sub-builds fail and it
-  ## seems likely to take a while for someone to fix it.  Currently
-  ## Travis CI doesn't distinguish "all builds succeeded" from "some
-  ## non-required sub-builds failed" except on the individual build's
-  ## page, which makes it somewhat annoying to detect from the
-  ## branches and build history pages.  See
-  ## https://github.com/travis-ci/travis-ci/issues/8716
-  allow_failures:
-    # - env: RUST_OPTIONS="--enable-rust" TOR_RUST_DEPENDENCIES=true
-    # - env: RUST_OPTIONS="--enable-rust --enable-cargo-online-mode
-    # - compiler: clang
-
-  ## Create explicit matrix entries to work around a Travis CI
-  ## environment issue.  Missing keys inherit from the first list
-  ## entry under that key outside the "include" clause.
-  include:
-    - compiler: gcc
-    - compiler: gcc
-      env: RUST_OPTIONS="--enable-rust" TOR_RUST_DEPENDENCIES=true
+  ## Careful! We use global envs, which makes it hard to exclude or
+  ## allow failures by env:
+  ## https://docs.travis-ci.com/user/customizing-the-build#matching-jobs-with-allow_failures
+  exclude:
+    ## Clang doesn't work in containerized builds, see below.
+    - compiler: clang
+      sudo: false
+    ## Non-containerized gcc are slow and redundant.
     - compiler: gcc
     - compiler: gcc
-      env: RUST_OPTIONS=""
+      sudo: required
+    ## gcc on OSX is less useful, because the default compiler is clang.
     - compiler: gcc
     - compiler: gcc
-      env: COVERAGE_OPTIONS="--enable-coverage"
+      os: osx
+    ## gcc on Linux with no env is redundant, because all the custom builds use
+    ## gcc on Linux
     - compiler: gcc
     - compiler: gcc
-      env: DISTCHECK="yes" RUST_OPTIONS=""
+      os: linux
+      env:
+    ## offline rust builds for gcc on Linux are redundant, because we do an
+    ## online rust build for gcc on Linux
     - compiler: gcc
     - compiler: gcc
-      env: DISTCHECK="yes" RUST_OPTIONS="--enable-rust --enable-cargo-online-mode"
-    ## The "sudo: required" forces non-containerized builds, working
-    ## around a Travis CI environment issue: clang LeakAnalyzer fails
-    ## because it requires ptrace and the containerized environment no
-    ## longer allows ptrace.
-    - compiler: clang
-      sudo: required
-    - compiler: clang
-      sudo: required
-      env: RUST_OPTIONS="--enable-rust" TOR_RUST_DEPENDENCIES=true
-    - compiler: clang
-      sudo: required
-      env: RUST_OPTIONS=""
+      os: linux
+      ## TOR_RUST_DEPENDENCIES is spelt RUST_DEPENDENCIES in 0.3.2
+      env: RUST_OPTIONS="--enable-rust" TOR_RUST_DEPENDENCIES=true HARDENING_OPTIONS=""
+
+## We don't need sudo. (The "apt:" stanza after this allows us to not need
+## sudo; otherwise, we would need it for getting dependencies.)
+##
+## But we use "sudo: required" to force non-containerized builds, working
+## around a Travis CI environment issue: clang LeakAnalyzer fails
+## because it requires ptrace and the containerized environment no
+## longer allows ptrace.
+## https://github.com/travis-ci/travis-ci/issues/9033
+##
+## In the matrix above, we exclude redundant combinations.
+sudo:
+  - false
+  - required
+
+## (Linux only) Use the latest Linux image (Ubuntu Trusty)
+dist: trusty
+
+## (Linux only) Download our dependencies
+addons:
+  apt:
+    packages:
+      ## Required dependencies
+      - libevent-dev
+      - zlib1g-dev
+      ## Optional dependencies
+      - libcap-dev
+      - liblzma-dev
+      - libscrypt-dev
+      - libseccomp-dev
+      ## zstd doesn't exist in Ubuntu Trusty
+      #- libzstd
+      ## Conditional dependencies
+      ## Always installed, so we don't need sudo
+      - asciidoc
+      - docbook-xsl
+      - docbook-xml
+      - xmlto
+
+## (OSX only) Use the default OSX image
+## See https://docs.travis-ci.com/user/reference/osx#os-x-version
+## Default is Xcode 9.4 on macOS 10.13 as of August 2018
+#osx_image: xcode9.4
 
 
 before_install:
 before_install:
-  ## If we're on OSX, homebrew usually needs to updated first
-  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
-  ## Download rustup
-  - if [[ "$RUST_OPTIONS" != "" ]]; then curl -Ssf -o rustup.sh https://sh.rustup.rs; fi
-  - if [[ "$COVERAGE_OPTIONS" != "" ]]; then pip install --user cpp-coveralls; fi
+  ## If we're on OSX, homebrew usually needs to be updated first
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
+  ## We might be upgrading some useless packages, but that's better than missing an upgrade
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade; fi
+  ## Create empty rust directories for non-Rust builds, so caching succeeds
+  - if [[ "$RUST_OPTIONS" == "" ]]; then mkdir -p $HOME/.cargo $TRAVIS_BUILD_DIR/src/rust/target; fi
 
 
 install:
 install:
+  ## If we're on OSX use brew to install ccache (ccache is automatically installed on Linux)
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install ccache; fi
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export PATH="/usr/local/opt/ccache/libexec:$PATH"; fi
   ## If we're on OSX use brew to install required dependencies (for Linux, see the "apt:" section above)
   ## If we're on OSX use brew to install required dependencies (for Linux, see the "apt:" section above)
-  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then { brew outdated openssl    || brew upgrade openssl;    }; fi
-  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then { brew outdated libevent   || brew upgrade libevent;   }; fi
-  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then { brew outdated pkg-config || brew upgrade pkg-config; }; fi
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install libevent; fi
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install openssl; fi
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install pkg-config; fi
+  ## macOS comes with zlib by default, so the homebrew install is keg-only
+  # - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install zlib; fi
   ## If we're on OSX also install the optional dependencies
   ## If we're on OSX also install the optional dependencies
-  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then { brew outdated xz         || brew upgrade xz;         }; fi
-  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then { brew outdated libscrypt  || brew upgrade libscrypt;  }; fi
-  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then { brew outdated zstd       || brew upgrade zstd;       }; fi
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install libscrypt; fi
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install xz; fi
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install zstd; fi
+  ## If we're on OSX, OpenSSL is keg-only, so tor 0.2.9 and later need to be configured --with-openssl-dir= to build
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then OPENSSL_OPTIONS=--with-openssl-dir=`brew --prefix openssl`; fi
+  ## Install conditional features
+  ## Install coveralls
+  - if [[ "$COVERAGE_OPTIONS" != "" ]]; then pip install --user cpp-coveralls; fi
+  ## If we're on OSX, and using asciidoc, install asciidoc
+  - if [[ "$ASCIIDOC_OPTIONS" == "" ]] && [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install asciidoc; fi
+  - if [[ "$ASCIIDOC_OPTIONS" == "" ]] && [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install xmlto; fi
+  - if [[ "$ASCIIDOC_OPTIONS" == "" ]] && [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export XML_CATALOG_FILES="/usr/local/etc/xml/catalog"; fi
+  ## If we're using Rust, download rustup
+  - if [[ "$RUST_OPTIONS" != "" ]]; then curl -Ssf -o rustup.sh https://sh.rustup.rs; fi
   ## Install the stable channels of rustc and cargo and setup our toolchain environment
   ## Install the stable channels of rustc and cargo and setup our toolchain environment
   - if [[ "$RUST_OPTIONS" != "" ]]; then sh rustup.sh -y --default-toolchain stable; fi
   - if [[ "$RUST_OPTIONS" != "" ]]; then sh rustup.sh -y --default-toolchain stable; fi
   - if [[ "$RUST_OPTIONS" != "" ]]; then source $HOME/.cargo/env; fi
   - if [[ "$RUST_OPTIONS" != "" ]]; then source $HOME/.cargo/env; fi
-  ## Get some info about rustc and cargo
+  ## If we're testing rust builds in offline-mode, then set up our vendored dependencies
+  - if [[ "$TOR_RUST_DEPENDENCIES" == "true" ]]; then export TOR_RUST_DEPENDENCIES=$PWD/src/ext/rust/crates; fi
+  ##
+  ## Finally, list installed package versions
+  - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then dpkg-query --show; fi
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew list --versions; fi
+  ## Get some info about rustup, rustc and cargo
+  - if [[ "$RUST_OPTIONS" != "" ]]; then which rustup; fi
   - if [[ "$RUST_OPTIONS" != "" ]]; then which rustc; fi
   - if [[ "$RUST_OPTIONS" != "" ]]; then which rustc; fi
   - if [[ "$RUST_OPTIONS" != "" ]]; then which cargo; fi
   - if [[ "$RUST_OPTIONS" != "" ]]; then which cargo; fi
+  - if [[ "$RUST_OPTIONS" != "" ]]; then rustup --version; fi
   - if [[ "$RUST_OPTIONS" != "" ]]; then rustc --version; fi
   - if [[ "$RUST_OPTIONS" != "" ]]; then rustc --version; fi
   - if [[ "$RUST_OPTIONS" != "" ]]; then cargo --version; fi
   - if [[ "$RUST_OPTIONS" != "" ]]; then cargo --version; fi
-  ## If we're testing rust builds in offline-mode, then set up our vendored dependencies
-  - if [[ "$TOR_RUST_DEPENDENCIES" == "true" ]]; then export TOR_RUST_DEPENDENCIES=$PWD/src/ext/rust/crates; fi
 
 
 script:
 script:
   - ./autogen.sh
   - ./autogen.sh
-  - ./configure $RUST_OPTIONS $COVERAGE_OPTIONS --disable-asciidoc --enable-fatal-warnings --disable-silent-rules --enable-fragile-hardening
+  - CONFIGURE_FLAGS="$ASCIIDOC_OPTIONS $COVERAGE_OPTIONS $HARDENING_OPTIONS $OPENSSL_OPTIONS $RUST_OPTIONS --enable-fatal-warnings --disable-silent-rules"
+  - echo "Configure flags are $CONFIGURE_FLAGS"
+  - ./configure $CONFIGURE_FLAGS
   ## We run `make check` because that's what https://jenkins.torproject.org does.
   ## We run `make check` because that's what https://jenkins.torproject.org does.
   - if [[ "$DISTCHECK" == "" ]]; then make check; fi
   - if [[ "$DISTCHECK" == "" ]]; then make check; fi
-  - if [[ "$DISTCHECK" != "" ]]; then make distcheck DISTCHECK_CONFIGURE_FLAGS="$RUST_OPTIONS $COVERAGE_OPTIONS --disable-asciidoc --enable-fatal-warnings --disable-silent-rules --enable-fragile-hardening"; fi
+  - if [[ "$DISTCHECK" != "" ]]; then make distcheck DISTCHECK_CONFIGURE_FLAGS="$CONFIGURE_FLAGS"; fi
 
 
 after_failure:
 after_failure:
+  ## configure will leave a log file with more details of config failures.
+  ## But the log is too long for travis' rendered view, so tail it.
+  - tail -1000 config.log || echo "tail failed"
   ## `make check` will leave a log file with more details of test failures.
   ## `make check` will leave a log file with more details of test failures.
-  - if [[ "$DISTCHECK" == "" ]]; then cat test-suite.log; fi
+  - if [[ "$DISTCHECK" == "" ]]; then cat test-suite.log || echo "cat failed"; fi
   ## `make distcheck` puts it somewhere different.
   ## `make distcheck` puts it somewhere different.
-  - if [[ "$DISTCHECK" != "" ]]; then make show-distdir-testlog; fi
+  - if [[ "$DISTCHECK" != "" ]]; then make show-distdir-testlog || echo "make failed"; fi
 
 
 after_success:
 after_success:
   ## If this build was one that produced coverage, upload it.
   ## If this build was one that produced coverage, upload it.
   - if [[ "$COVERAGE_OPTIONS" != "" ]]; then coveralls -b . --exclude src/test --exclude src/trunnel --gcov-options '\-p'; fi
   - if [[ "$COVERAGE_OPTIONS" != "" ]]; then coveralls -b . --exclude src/test --exclude src/trunnel --gcov-options '\-p'; fi
+
+notifications:
+  irc:
+    channels:
+      - "irc.oftc.net#tor-ci"
+    template:
+      - "%{repository} %{branch} %{commit} - %{author}: %{commit_subject}"
+      - "Build #%{build_number} %{result}. Details: %{build_url}"
+    on_success: change
+    on_failure: change
+  email:
+    on_success: never
+    on_failure: change

+ 2 - 1
Makefile.am

@@ -125,6 +125,7 @@ test-network: need-chutney-path $(TESTING_TOR_BINARY) src/tools/tor-gencert
 # because they're incompatible
 # because they're incompatible
 test-network-all: need-chutney-path test-driver $(TESTING_TOR_BINARY) src/tools/tor-gencert
 test-network-all: need-chutney-path test-driver $(TESTING_TOR_BINARY) src/tools/tor-gencert
 	mkdir -p $(TEST_NETWORK_ALL_LOG_DIR)
 	mkdir -p $(TEST_NETWORK_ALL_LOG_DIR)
+	rm -f $(TEST_NETWORK_ALL_LOG_DIR)/*.log $(TEST_NETWORK_ALL_LOG_DIR)/*.trs
 	@flavors="$(TEST_CHUTNEY_FLAVORS)"; \
 	@flavors="$(TEST_CHUTNEY_FLAVORS)"; \
 	if ping6 -q -c 1 -o ::1 >/dev/null 2>&1 || ping6 -q -c 1 -W 1 ::1 >/dev/null 2>&1 || ping -6 -c 1 -W 1 ::1 >/dev/null 2>&1; then \
 	if ping6 -q -c 1 -o ::1 >/dev/null 2>&1 || ping6 -q -c 1 -W 1 ::1 >/dev/null 2>&1 || ping -6 -c 1 -W 1 ::1 >/dev/null 2>&1; then \
 		echo "ping6 ::1 or ping ::1 succeeded, running IPv6 flavors: $(TEST_CHUTNEY_FLAVORS_IPV6)."; \
 		echo "ping6 ::1 or ping ::1 succeeded, running IPv6 flavors: $(TEST_CHUTNEY_FLAVORS_IPV6)."; \
@@ -148,7 +149,7 @@ test-network-all: need-chutney-path test-driver $(TESTING_TOR_BINARY) src/tools/
 		$(top_srcdir)/src/test/test-network.sh $(TEST_NETWORK_WARNING_FLAGS); \
 		$(top_srcdir)/src/test/test-network.sh $(TEST_NETWORK_WARNING_FLAGS); \
 	done; \
 	done; \
 	echo "Log and result files are available in $(TEST_NETWORK_ALL_LOG_DIR)."; \
 	echo "Log and result files are available in $(TEST_NETWORK_ALL_LOG_DIR)."; \
-	! grep -q FAIL test_network_log/*.trs
+	! grep -q FAIL $(TEST_NETWORK_ALL_LOG_DIR)/*.trs
 
 
 need-stem-path:
 need-stem-path:
 	@if test ! -d "$$STEM_SOURCE_DIR"; then \
 	@if test ! -d "$$STEM_SOURCE_DIR"; then \

+ 4 - 0
changes/27286

@@ -0,0 +1,4 @@
+  o Minor features (directory authorities):
+    - Authorities no longer vote to make the subprotocol version "LinkAuth=1"
+      a requirement: it is unsupportable with NSS, and hasn't been needed
+      since Tor 0.3.0.1-alpha. Closes ticket 27286.

+ 4 - 0
changes/bug20424_029_minimal

@@ -0,0 +1,4 @@
+  o Minor bugfixes (compilation):
+    - When compiling with --enable-openbsd-malloc or --enable-tcmalloc, tell
+      the compiler not to include the system malloc implementation. Fixes bug
+      20424; bugfix on 0.2.0.20-rc.

+ 5 - 0
changes/bug25440

@@ -0,0 +1,5 @@
+  o Minor bugfixes (linux seccomp2 sandbox):
+    - Fix a bug in out sandboxing rules for the openat() syscall.
+      Previously, no openat() call would be permitted, which would break
+      filesystem operations on recent glibc versions. Fixes bug 25440;
+      bugfix on 0.2.9.15. Diagnosis and patch from Daniel Pinto.

+ 3 - 0
changes/bug25505

@@ -0,0 +1,3 @@
+  o Minor bugfixes (netflow padding):
+    - Ensure circuitmux queues are empty before scheduling or sending padding.
+      Fixes bug 25505; bugfix on 0.3.1.1-alpha.

+ 5 - 0
changes/bug25512

@@ -0,0 +1,5 @@
+  o Minor bugfixes (restart-in-process):
+    - When shutting down, Tor now clears all the flags in the control.c
+      module. This should prevent a bug where authentication cookies
+      are not generated on restart. Fixes bug 25512; bugfix on 0.3.3.1-alpha.
+

+ 5 - 0
changes/bug25705

@@ -0,0 +1,5 @@
+  o Minor bugfixes (circuit path selection):
+    - Don't count path selection failures as circuit build failures. This
+      should eliminate cases where Tor blames its guard or the network
+      for situations like insufficient microdescriptors and/or overly
+      restrictive torrc settings. Fixes bug 25705; bugfix on 0.3.3.1-alpha.

+ 5 - 0
changes/bug26269

@@ -0,0 +1,5 @@
+  o Minor bugfixes (compilation):
+    - Fix a compilation warning on some versions of GCC when
+      building code that calls routerinfo_get_my_routerinfo() twice,
+      assuming that the second call will succeed if the first one did.
+      Fixes bug 26269; bugfix on 0.2.8.2-alpha.

+ 4 - 0
changes/bug26485

@@ -0,0 +1,4 @@
+  o Minor bugfixes (directory authority):
+    - When voting for recommended versions, make sure that all of the
+      versions are well-formed and parsable. Fixes bug 26485; bugfix on
+      0.1.1.6-alpha.

+ 3 - 0
changes/bug26497

@@ -0,0 +1,3 @@
+  o Minor bugfixes (rust):
+    - Stop setting $CARGO_HOME. cargo will use the user's $CARGO_HOME, or
+      $HOME/.cargo by default. Fixes bug 26497; bugfix on 0.3.1.5-alpha.

+ 3 - 0
changes/bug26497-backport

@@ -0,0 +1,3 @@
+  o Minor bugfixes (rust):
+    - Backport test_rust.sh from master.
+      Fixes bug 26497; bugfix on 0.3.1.5-alpha.

+ 4 - 0
changes/bug26497-cd

@@ -0,0 +1,4 @@
+  o Minor bugfixes (rust):
+    - cd to ${abs_top_builddir}/src/rust before running cargo in
+      src/test/test_rust.sh. This makes the working directory consistent
+      between builds and tests. Fixes bug 26497; bugfix on 0.3.3.2-alpha.

+ 7 - 0
changes/bug26627

@@ -0,0 +1,7 @@
+  o Minor bugfixes (v3 onion services):
+    - Stop sending ed25519 link specifiers in v3 onion service introduce
+      cells, when the rendezvous point doesn't support ed25519 link
+      authentication. Fixes bug 26627; bugfix on 0.3.2.4-alpha.
+    - Stop putting ed25519 link specifiers in v3 onion service descriptors,
+      when the intro point doesn't support ed25519 link authentication.
+      Fixes bug 26627; bugfix on 0.3.2.4-alpha.

+ 4 - 0
changes/bug26779

@@ -0,0 +1,4 @@
+  o Minor features (bug workaround):
+    - Compile correctly on systems that provide the C11 stdatomic.h header,
+      but where C11 atomic functions don't actually compile.
+      Closes ticket 26779; workaround for Debian issue 903709.

+ 4 - 0
changes/bug26785

@@ -0,0 +1,4 @@
+  o Minor bugfixes (compilation, portability):
+    - Don't try to use a pragma to temporarily disable
+      -Wunused-const-variable if the compiler doesn't support it.
+      Fixes bug 26785; bugfix on 0.3.2.11.

+ 3 - 0
changes/bug26787

@@ -0,0 +1,3 @@
+  o Minor bugfixes (testing):
+    - Disable core dumps in test_bt.sh, to avoid failures in "make
+      distcheck". Fixes bug 26787; bugfix on 0.2.5.2-alpha.

+ 3 - 0
changes/bug26830

@@ -0,0 +1,3 @@
+  o Minor bugfixes (continuous integration):
+    - Skip an unreliable key generation test on Windows, until the underlying
+      issue in bug 26076 is resolved. Fixes bug 26830; bugfix on 0.2.7.3-rc.

+ 3 - 0
changes/bug26853

@@ -0,0 +1,3 @@
+  o Minor bugfixes (continuous integration):
+    - Skip an unreliable key expiration test on Windows, until the underlying
+      issue in bug 26076 is resolved. Fixes bug 26853; bugfix on 0.3.2.1-alpha.

+ 4 - 0
changes/bug26873

@@ -0,0 +1,4 @@
+  o Minor bugfixes (portability):
+    - Fix compilation of the unit tests on GNU/Hurd, which does not
+      define PATH_MAX. Fixes bug 26873; bugfix on 0.3.3.1-alpha.
+      Patch from "paulusASol".

+ 4 - 0
changes/bug26876

@@ -0,0 +1,4 @@
+  o Minor bugfixes (portability):
+    - Work around two different bugs in the OS X 10.10 and later SDKs that
+      would prevent us from successfully targeting earlier versions of OS X.
+      Fixes bug 26876; bugfix on 0.3.3.1-alpha.

+ 4 - 0
changes/bug26924

@@ -0,0 +1,4 @@
+  o Minor bugfixes (single onion services, Tor2web):
+    - Log a protocol warning when single onion services or Tor2web clients
+      fail to authenticate direct connections to relays.
+      Fixes bug 26924; bugfix on 0.2.9.1-alpha.

+ 4 - 0
changes/bug26927

@@ -0,0 +1,4 @@
+  o Minor bugfixes (logging):
+    - Improve the log message when connection initiators fail to authenticate
+      direct connections to relays.
+      Fixes bug 26927; bugfix on 0.3.0.1-alpha.

+ 3 - 0
changes/bug26932

@@ -0,0 +1,3 @@
+  o Minor bugfixes (onion services):
+    - Fix bug that causes services to not ever rotate their descriptors if they
+      were getting SIGHUPed often. Fixes bug 26932; bugfix on 0.3.2.1-alpha.

+ 4 - 0
changes/bug26948

@@ -0,0 +1,4 @@
+  o Minor bugfixes (in-process restart):
+    - Always call tor_free_all() when leaving tor_run_main(). When we
+      did not, restarting tor in-process would cause an assertion failure.
+      Fixes bug 26948; bugfix on 0.3.3.1-alpha.

+ 4 - 0
changes/bug27081

@@ -0,0 +1,4 @@
+  o Minor bugfixes (compilation, windows):
+    - Don't link or search for pthreads when building for Windows, even if we
+      are using build environment (like mingw) that provides a pthreads
+      library. Fixes bug 27081; bugfix on 0.1.0.1-rc.

+ 5 - 0
changes/bug27088

@@ -0,0 +1,5 @@
+  o Minor bugfixes (continuous integration):
+    - Pass the module flags to distcheck configure, and
+      log the flags before running configure. (Backported
+      to 0.2.9 and later as a precaution.)
+      Fixes bug 27088; bugfix on 0.3.4.1-alpha.

+ 3 - 0
changes/bug27090

@@ -0,0 +1,3 @@
+  o Minor bugfixes (continuous integration):
+    - Build with zstd on macOS.
+      Fixes bug 27090; bugfix on 0.3.1.5-alpha.

+ 3 - 0
changes/bug27093

@@ -0,0 +1,3 @@
+  o Minor bugfixes (rust):
+    - Consistently use ../../.. as a fallback for $abs_top_srcdir in
+      test_rust.sh. Fixes bug 27093; bugfix on 0.3.4.3-alpha.

+ 4 - 0
changes/bug27164

@@ -0,0 +1,4 @@
+  o Minor bugfixes (rust):
+    - Protover parsing was ignoring a 2nd hyphen and everything after it,
+      accepting entries like "Link=1-5-foo". Fixes bug 27164; bugfix on
+      0.3.3.1-alpha.

+ 4 - 0
changes/bug27177

@@ -0,0 +1,4 @@
+  o Minor bugfixes (rust):
+    - Protover parsing was accepting the presence of whitespace in version
+      strings, which the C implementation would choke on, e.g. "Desc=1\t,2".
+      Fixes bug 27177; bugfix on 0.3.3.5-rc.

+ 3 - 0
changes/bug27185

@@ -0,0 +1,3 @@
+  o Minor bugfixes (Windows, compilation):
+    - Silence a compilation warning on MSVC 2017 and clang-cl.
+      Fixes bug 27185; bugfix on 0.2.2.2-alpha.

+ 4 - 0
changes/bug27206

@@ -0,0 +1,4 @@
+  o Minor bugfixes (rust):
+    - protover_all_supported() would attempt to allocate up to 16GB on some
+      inputs, leading to a potential memory DoS. Fixes bug 27206; bugfix on
+      0.3.3.5-rc.

+ 5 - 0
changes/bug27226

@@ -0,0 +1,5 @@
+  o Minor bugfixes (testing, openssl compatibility):
+    - Our "tortls/cert_matches_key" unit test no longer relies on OpenSSL
+      internals.  Previously, it relied on unsupported OpenSSL behavior in
+      a way that caused it to crash with OpenSSL 1.0.2p. Fixes bug 27226;
+      bugfix on 0.2.5.1-alpha.

+ 3 - 0
changes/bug27295

@@ -0,0 +1,3 @@
+  o Minor bugfixes (testing, chutney):
+    - Before running make test-network-all, delete old logs and test result
+      files, to avoid spurious failures. Fixes bug 27295; bugfix on 0.2.7.3-rc.

+ 4 - 0
changes/bug27335

@@ -0,0 +1,4 @@
+  o Minor bugfixes (hidden service v3):
+    - In case the hidden service directory can't be created or has wrong
+      permissions, do not BUG() on it which lead to a non fatal stacktrace.
+      Fixes bug 27335; bugfix on 0.3.2.1.

+ 4 - 0
changes/bug27344

@@ -0,0 +1,4 @@
+  o Minor features (compatibility):
+    - Tell OpenSSL to maintain backward compatibility with previous
+      RSA1024/DH1024 users in Tor. With OpenSSL 1.1.1-pre6, these ciphers
+      are disabled by default. Closes ticket 27344.

+ 5 - 0
changes/bug27345

@@ -0,0 +1,5 @@
+  o Minor bugfixes (testing):
+    - When running make test-network-all, use the mixed+hs-v2 network.
+      (A previous fix to chutney removed v3 onion services from the
+      mixed+hs-v23 network, so seeing "mixed+hs-v23" in tests is
+      confusing.) Fixes bug 27345; bugfix on 0.3.2.1-alpha.

+ 3 - 0
changes/bug27418

@@ -0,0 +1,3 @@
+  o Minor bugfixes (continuous integration):
+    - When we use echo in Travis, don't pass a --flag as the first argument.
+      Fixes bug 27418; bugfix on 0.3.4.7-rc.

+ 3 - 0
changes/bug27453

@@ -0,0 +1,3 @@
+  o Minor bugfixes (continuous integration):
+    - When a Travis build fails, and showing a log fails, keep trying to
+      show the other logs. Fixes bug 27453; bugfix on 0.3.4.7-rc.

+ 5 - 0
changes/bug27461

@@ -0,0 +1,5 @@
+  o Minor bugfixes (compilation):
+    - Stop calling SetProcessDEPPolicy() on 64-bit Windows. It is not
+      supported, and always fails. Some compilers warn about the function
+      pointer cast on 64-bit Windows.
+      Fixes bug 27461; bugfix on 0.2.2.23-alpha.

+ 3 - 0
changes/bug27463

@@ -0,0 +1,3 @@
+  o Minor bugfixes (onion services):
+    - Silence a spurious compiler warning in rend_client_send_introduction().
+      Fixes bug 27463; bugfix on 0.1.1.2-alpha.

+ 5 - 0
changes/bug27465

@@ -0,0 +1,5 @@
+  o Minor bugfixes (compilation):
+    - Silence a spurious compiler warning on the GetAdaptersAddresses
+      function pointer cast. This issue is already fixed by 26481 in
+      0.3.5 and later, by removing the lookup and cast.
+      Fixes bug 27465; bugfix on 0.2.3.11-alpha.

+ 4 - 0
changes/bug27649

@@ -0,0 +1,4 @@
+  o Minor bugfixes (rust):
+    - The protover rewrite in 24031 allowed repeated votes from the same
+      voter for the same protocol version to be counted multiple times in
+      protover_compute_vote(). Fixes bug 27649; bugfix on 0.3.3.5-rc.

+ 6 - 0
changes/bug27658

@@ -0,0 +1,6 @@
+  o Minor bugfixes (testing):
+    - If a unit test running in a subprocess exits abnormally or with a
+      nonzero status code, treat the test as having failed, even if
+      the test reported success. Without this fix, memory leaks don't cause
+      cause the tests to fail, even with LeakSanitizer. Fixes bug 27658;
+      bugfix on 0.2.2.4-alpha.

+ 4 - 0
changes/bug27687

@@ -0,0 +1,4 @@
+  o Minor bugfixes (rust):
+    - protover parsed and accepted unknown protocol names containing invalid
+      characters outside the range [A-Za-z0-9-]. Fixes bug 27687; bugfix on
+      0.3.3.1-alpha.

+ 4 - 0
changes/bug27708

@@ -0,0 +1,4 @@
+  o Major bugfixes (restart-in-process):
+    - Fix a use-after-free error that could be caused by passing Tor an
+      impossible set of options that would fail during options_act().
+      Fixes bug 27708; bugfix on 0.3.3.1-alpha.

+ 4 - 0
changes/geoip-2018-07-03

@@ -0,0 +1,4 @@
+  o Minor features (geoip):
+    - Update geoip and geoip6 to the July 3 2018 Maxmind GeoLite2
+      Country database. Closes ticket 26674.
+

+ 4 - 0
changes/geoip-2018-08-07

@@ -0,0 +1,4 @@
+  o Minor features (geoip):
+    - Update geoip and geoip6 to the August 7 2018 Maxmind GeoLite2
+      Country database. Closes ticket 27089.
+

+ 4 - 0
changes/geoip-2018-09-06

@@ -0,0 +1,4 @@
+  o Minor features (geoip):
+    - Update geoip and geoip6 to the September 6 2018 Maxmind GeoLite2
+      Country database. Closes ticket 27631.
+

+ 4 - 0
changes/task26771

@@ -0,0 +1,4 @@
+  o Directory authority changes:
+    - The "Bifroest" bridge authority has been retired; the new bridge
+      authority is "Serge", and it is operated by George from the
+      TorBSD project. Closes ticket 26771.

+ 3 - 0
changes/ticket24629

@@ -0,0 +1,3 @@
+  o Minor features (continuous integration):
+    - Enable macOS builds in our Travis CI configuration.
+      Closes ticket 24629.

+ 3 - 0
changes/ticket24629-backport

@@ -0,0 +1,3 @@
+  o Minor features (continuous integration):
+    - Backport Travis rust distcheck to 0.3.3.
+      Closes ticket 24629.

+ 3 - 0
changes/ticket26560

@@ -0,0 +1,3 @@
+  o Minor features (continuous integration):
+    - Install libcap-dev and libseccomp2-dev so these optional
+      dependencies get tested on Travis CI.  Closes ticket 26560.

+ 4 - 0
changes/ticket26647

@@ -0,0 +1,4 @@
+  o Minor features (controller):
+    - The control port now exposes the list of HTTPTunnelPorts and
+      ExtOrPorts via GETINFO net/listeners/httptunnel and net/listeners/extor
+      respectively.  Closes ticket 26647.

+ 3 - 0
changes/ticket26952-cargo

@@ -0,0 +1,3 @@
+  o Minor features (continuous integration, rust):
+    - Use cargo cache in our Travis CI configuration.
+      Closes ticket 26952.

+ 3 - 0
changes/ticket26952-ccache

@@ -0,0 +1,3 @@
+  o Minor features (continuous integration):
+    - Use ccache in our Travis CI configuration.
+      Closes ticket 26952.

+ 3 - 0
changes/ticket27087

@@ -0,0 +1,3 @@
+  o Minor features (continuous integration):
+    - Run asciidoc during Travis CI.
+      Implements ticket 27087.

+ 6 - 0
changes/ticket27252

@@ -0,0 +1,6 @@
+  o Minor features (continuous integration):
+    - Skip gcc on OSX in Travis CI, it's rarely used.
+      Skip a duplicate hardening-off build in Travis on Tor 0.2.9.
+      Skip gcc on Linux with default settings, because all the non-default
+      builds use gcc on Linux.
+      Implements ticket 27252.

+ 5 - 0
changes/ticket27252-032

@@ -0,0 +1,5 @@
+  o Minor features (continuous integration):
+    - Only run one online rust build in Travis, to reduce network errors.
+      Skip offline rust builds on Travis for Linux gcc, because they're
+      redundant.
+      Implements ticket 27252.

+ 62 - 6
configure.ac

@@ -4,7 +4,7 @@ dnl Copyright (c) 2007-2017, The Tor Project, Inc.
 dnl See LICENSE for licensing information
 dnl See LICENSE for licensing information
 
 
 AC_PREREQ([2.63])
 AC_PREREQ([2.63])
-AC_INIT([tor],[0.3.3.7-dev])
+AC_INIT([tor],[0.3.3.10-dev])
 AC_CONFIG_SRCDIR([src/or/main.c])
 AC_CONFIG_SRCDIR([src/or/main.c])
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_MACRO_DIR([m4])
 
 
@@ -515,8 +515,10 @@ if test "$LIBS" != "$saved_LIBS"; then
    have_rt=yes
    have_rt=yes
 fi
 fi
 
 
-AC_SEARCH_LIBS(pthread_create, [pthread])
-AC_SEARCH_LIBS(pthread_detach, [pthread])
+if test "$bwin32" = "false"; then
+  AC_SEARCH_LIBS(pthread_create, [pthread])
+  AC_SEARCH_LIBS(pthread_detach, [pthread])
+fi
 
 
 AM_CONDITIONAL(THREADS_WIN32, test "$bwin32" = "true")
 AM_CONDITIONAL(THREADS_WIN32, test "$bwin32" = "true")
 AM_CONDITIONAL(THREADS_PTHREADS, test "$bwin32" = "false")
 AM_CONDITIONAL(THREADS_PTHREADS, test "$bwin32" = "false")
@@ -548,7 +550,6 @@ AC_CHECK_FUNCS(
         llround \
         llround \
         localtime_r \
         localtime_r \
         lround \
         lround \
-	mach_approximate_time \
         memmem \
         memmem \
         memset_s \
         memset_s \
 	pipe \
 	pipe \
@@ -574,9 +575,36 @@ AC_CHECK_FUNCS(
 	_vscprintf
 	_vscprintf
 )
 )
 
 
-# Apple messed up when they added two functions functions in Sierra: they
+# Apple messed up when they added some functions: they
 # forgot to decorate them with appropriate AVAILABLE_MAC_OS_VERSION
 # forgot to decorate them with appropriate AVAILABLE_MAC_OS_VERSION
-# checks. So we should only probe for those functions if we are sure that we
+# checks.
+
+# We should only probe for these functions if we are sure that we
+# are not targeting OS X 10.9 or earlier.
+AC_MSG_CHECKING([for a pre-Yosemite OS X build target])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#ifdef __APPLE__
+#  include <AvailabilityMacros.h>
+#  ifndef MAC_OS_X_VERSION_10_10
+#    define MAC_OS_X_VERSION_10_10 101000
+#  endif
+#  if defined(MAC_OS_X_VERSION_MIN_REQUIRED)
+#    if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10
+#      error "Running on Mac OS X 10.9 or earlier"
+#    endif
+#  endif
+#endif
+]], [[]])],
+   [on_macos_pre_10_10=no ; AC_MSG_RESULT([no])],
+   [on_macos_pre_10_10=yes; AC_MSG_RESULT([yes])])
+
+if test "$on_macos_pre_10_10" = "no"; then
+  AC_CHECK_FUNCS(
+        mach_approximate_time \
+  )
+fi
+
+# We should only probe for these functions if we are sure that we
 # are not targeting OSX 10.11 or earlier.
 # are not targeting OSX 10.11 or earlier.
 AC_MSG_CHECKING([for a pre-Sierra OSX build target])
 AC_MSG_CHECKING([for a pre-Sierra OSX build target])
 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
@@ -828,6 +856,7 @@ AC_CHECK_FUNCS([ \
                 SSL_get_client_ciphers \
                 SSL_get_client_ciphers \
                 SSL_get_client_random \
                 SSL_get_client_random \
 		SSL_CIPHER_find \
 		SSL_CIPHER_find \
+                SSL_CTX_set_security_level \
 		TLS_method
 		TLS_method
 	       ])
 	       ])
 
 
@@ -1531,6 +1560,26 @@ AC_CHECK_SIZEOF(socklen_t, , [AC_INCLUDES_DEFAULT()
 
 
 AC_CHECK_SIZEOF(cell_t)
 AC_CHECK_SIZEOF(cell_t)
 
 
+# Let's see if stdatomic works. (There are some debian clangs that screw it
+# up; see Tor bug #26779 and debian bug 903709.)
+AC_CACHE_CHECK([whether C11 stdatomic.h actually works],
+               tor_cv_stdatomic_works,
+[AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#include <stdatomic.h>
+struct x { atomic_size_t y; };
+void try_atomic_init(struct x *xx)
+{
+  atomic_init(&xx->y, 99);
+  atomic_fetch_add(&xx->y, 1);
+}
+]])], [tor_cv_stdatomic_works=yes], [tor_cv_stdatomic_works=no])])
+
+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
+   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
+
 # Now make sure that NULL can be represented as zero bytes.
 # Now make sure that NULL can be represented as zero bytes.
 AC_CACHE_CHECK([whether memset(0) sets pointers to NULL], tor_cv_null_is_zero,
 AC_CACHE_CHECK([whether memset(0) sets pointers to NULL], tor_cv_null_is_zero,
 [AC_RUN_IFELSE([AC_LANG_SOURCE(
 [AC_RUN_IFELSE([AC_LANG_SOURCE(
@@ -1698,6 +1747,10 @@ fi
 if test "$using_custom_malloc" = "no"; then
 if test "$using_custom_malloc" = "no"; then
    AC_CHECK_FUNCS(mallinfo)
    AC_CHECK_FUNCS(mallinfo)
 fi
 fi
+if test "$using_custom_malloc" = "yes"; then
+  # Tell the C compiler not to use the system allocator functions.
+  TOR_CHECK_CFLAGS([-fno-builtin-malloc -fno-builtin-realloc -fno-builtin-calloc -fno-builtin-free])
+fi
 
 
 # By default, we're going to assume we don't have mlockall()
 # By default, we're going to assume we don't have mlockall()
 # bionic and other platforms have various broken mlockall subsystems.
 # bionic and other platforms have various broken mlockall subsystems.
@@ -2172,6 +2225,9 @@ dnl     -Wthread-safety-precise
   if test "$tor_cv_cflags__Woverlength_strings" = "yes"; then
   if test "$tor_cv_cflags__Woverlength_strings" = "yes"; then
     AC_DEFINE([HAVE_CFLAG_WOVERLENGTH_STRINGS], 1, [True if we have -Woverlength-strings])
     AC_DEFINE([HAVE_CFLAG_WOVERLENGTH_STRINGS], 1, [True if we have -Woverlength-strings])
   fi
   fi
+  if test "$tor_cv_cflags__warn_unused_const_variable_2" = "yes"; then
+    AC_DEFINE([HAVE_CFLAG_WUNUSED_CONST_VARIABLE], 1, [True if we have -Wunused-const-variable])
+  fi
 
 
   if test "x$enable_fatal_warnings" = "xyes"; then
   if test "x$enable_fatal_warnings" = "xyes"; then
     # I'd like to use TOR_CHECK_CFLAGS here, but I can't, since the
     # I'd like to use TOR_CHECK_CFLAGS here, but I can't, since the

+ 1 - 1
contrib/win32build/tor-mingw.nsi.in

@@ -8,7 +8,7 @@
 !include "LogicLib.nsh"
 !include "LogicLib.nsh"
 !include "FileFunc.nsh"
 !include "FileFunc.nsh"
 !insertmacro GetParameters
 !insertmacro GetParameters
-!define VERSION "0.3.3.7-dev"
+!define VERSION "0.3.3.10-dev"
 !define INSTALLER "tor-${VERSION}-win32.exe"
 !define INSTALLER "tor-${VERSION}-win32.exe"
 !define WEBSITE "https://www.torproject.org/"
 !define WEBSITE "https://www.torproject.org/"
 !define LICENSE "LICENSE"
 !define LICENSE "LICENSE"

+ 5 - 3
doc/HACKING/GettingStartedRust.md

@@ -122,9 +122,10 @@ the module calls.  Modules which call fewer other modules are better targets.
 
 
 Strive to change the C API as little as possible.
 Strive to change the C API as little as possible.
 
 
-We are currently targeting Rust nightly, *for now*. We expect this to
-change moving forward, as we understand more about which nightly
-features we need. It is on our TODO list to try to cultivate good
+We are currently targetting Rust stable. (See CodingStandardsRust.md for more
+details.)
+
+It is on our TODO list to try to cultivate good
 standing with various distro maintainers of `rustc` and `cargo`, in
 standing with various distro maintainers of `rustc` and `cargo`, in
 order to ensure that whatever version we solidify on is readily
 order to ensure that whatever version we solidify on is readily
 available.
 available.
@@ -139,6 +140,7 @@ Where <name_of_c_object> can be an enum, struct, constant, etc.  Then,
 do the same in the C code, to note that rust will need to be changed
 do the same in the C code, to note that rust will need to be changed
 when the C does.
 when the C does.
 
 
+
  Adding your Rust module to Tor's build system
  Adding your Rust module to Tor's build system
 -----------------------------------------------
 -----------------------------------------------
 
 

+ 4 - 1
src/common/address.c

@@ -1496,7 +1496,10 @@ get_interface_addresses_win32(int severity, sa_family_t family)
     goto done;
     goto done;
   }
   }
 
 
-  if (!(fn = (GetAdaptersAddresses_fn_t)
+  /* Cast through a void function pointer, to silence a spurious compiler
+   * warning on 64-bit Windows. This cast is safe, because we are casting to
+   * the correct type for GetAdaptersAddresses(). */
+  if (!(fn = (GetAdaptersAddresses_fn_t)(void(*)(void))
                   GetProcAddress(lib, "GetAdaptersAddresses"))) {
                   GetProcAddress(lib, "GetAdaptersAddresses"))) {
     log_fn(severity, LD_NET, "Unable to obtain pointer to "
     log_fn(severity, LD_NET, "Unable to obtain pointer to "
            "GetAdaptersAddresses");
            "GetAdaptersAddresses");

+ 2 - 3
src/common/compat_threads.c

@@ -352,7 +352,7 @@ alert_sockets_close(alert_sockets_t *socks)
   socks->read_fd = socks->write_fd = -1;
   socks->read_fd = socks->write_fd = -1;
 }
 }
 
 
-#ifndef HAVE_STDATOMIC_H
+#ifndef HAVE_WORKING_STDATOMIC
 /** Initialize a new atomic counter with the value 0 */
 /** Initialize a new atomic counter with the value 0 */
 void
 void
 atomic_counter_init(atomic_counter_t *counter)
 atomic_counter_init(atomic_counter_t *counter)
@@ -403,5 +403,4 @@ atomic_counter_exchange(atomic_counter_t *counter, size_t newval)
   tor_mutex_release(&counter->mutex);
   tor_mutex_release(&counter->mutex);
   return oldval;
   return oldval;
 }
 }
-#endif /* !defined(HAVE_STDATOMIC_H) */
-
+#endif /* !defined(HAVE_WORKING_STDATOMIC) */

+ 11 - 8
src/common/compat_threads.h

@@ -14,7 +14,11 @@
 #include <pthread.h>
 #include <pthread.h>
 #endif
 #endif
 
 
-#ifdef HAVE_STDATOMIC_H
+#if defined(HAVE_STDATOMIC_H) && defined(STDATOMIC_WORKS)
+#define HAVE_WORKING_STDATOMIC
+#endif
+
+#ifdef HAVE_WORKING_STDATOMIC
 #include <stdatomic.h>
 #include <stdatomic.h>
 #endif
 #endif
 
 
@@ -156,18 +160,18 @@ void tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value);
 /**
 /**
  * Atomic counter type; holds a size_t value.
  * Atomic counter type; holds a size_t value.
  */
  */
-#ifdef HAVE_STDATOMIC_H
+#ifdef HAVE_WORKING_STDATOMIC
 typedef struct atomic_counter_t {
 typedef struct atomic_counter_t {
   atomic_size_t val;
   atomic_size_t val;
 } atomic_counter_t;
 } atomic_counter_t;
 #define ATOMIC_LINKAGE static
 #define ATOMIC_LINKAGE static
-#else /* !(defined(HAVE_STDATOMIC_H)) */
+#else /* !(defined(HAVE_WORKING_STDATOMIC)) */
 typedef struct atomic_counter_t {
 typedef struct atomic_counter_t {
   tor_mutex_t mutex;
   tor_mutex_t mutex;
   size_t val;
   size_t val;
 } atomic_counter_t;
 } atomic_counter_t;
 #define ATOMIC_LINKAGE
 #define ATOMIC_LINKAGE
-#endif /* defined(HAVE_STDATOMIC_H) */
+#endif /* defined(HAVE_WORKING_STDATOMIC) */
 
 
 ATOMIC_LINKAGE void atomic_counter_init(atomic_counter_t *counter);
 ATOMIC_LINKAGE void atomic_counter_init(atomic_counter_t *counter);
 ATOMIC_LINKAGE void atomic_counter_destroy(atomic_counter_t *counter);
 ATOMIC_LINKAGE void atomic_counter_destroy(atomic_counter_t *counter);
@@ -178,7 +182,7 @@ ATOMIC_LINKAGE size_t atomic_counter_exchange(atomic_counter_t *counter,
                                               size_t newval);
                                               size_t newval);
 #undef ATOMIC_LINKAGE
 #undef ATOMIC_LINKAGE
 
 
-#ifdef HAVE_STDATOMIC_H
+#ifdef HAVE_WORKING_STDATOMIC
 /** Initialize a new atomic counter with the value 0 */
 /** Initialize a new atomic counter with the value 0 */
 static inline void
 static inline void
 atomic_counter_init(atomic_counter_t *counter)
 atomic_counter_init(atomic_counter_t *counter)
@@ -216,8 +220,7 @@ atomic_counter_exchange(atomic_counter_t *counter, size_t newval)
   return atomic_exchange(&counter->val, newval);
   return atomic_exchange(&counter->val, newval);
 }
 }
 
 
-#else /* !(defined(HAVE_STDATOMIC_H)) */
-#endif /* defined(HAVE_STDATOMIC_H) */
+#else /* !(defined(HAVE_WORKING_STDATOMIC)) */
+#endif /* defined(HAVE_WORKING_STDATOMIC) */
 
 
 #endif /* !defined(TOR_COMPAT_THREADS_H) */
 #endif /* !defined(TOR_COMPAT_THREADS_H) */
-

+ 4 - 0
src/common/compress_zstd.c

@@ -19,10 +19,14 @@
 #include "compress_zstd.h"
 #include "compress_zstd.h"
 
 
 #ifdef HAVE_ZSTD
 #ifdef HAVE_ZSTD
+#ifdef HAVE_CFLAG_WUNUSED_CONST_VARIABLE
 DISABLE_GCC_WARNING(unused-const-variable)
 DISABLE_GCC_WARNING(unused-const-variable)
+#endif
 #include <zstd.h>
 #include <zstd.h>
+#ifdef HAVE_CFLAG_WUNUSED_CONST_VARIABLE
 ENABLE_GCC_WARNING(unused-const-variable)
 ENABLE_GCC_WARNING(unused-const-variable)
 #endif
 #endif
+#endif
 
 
 /** Total number of bytes allocated for Zstandard state. */
 /** Total number of bytes allocated for Zstandard state. */
 static atomic_counter_t total_zstd_allocation;
 static atomic_counter_t total_zstd_allocation;

+ 1 - 1
src/common/sandbox.c

@@ -450,7 +450,7 @@ allow_file_open(scmp_filter_ctx ctx, int use_openat, const char *file)
 {
 {
   if (use_openat) {
   if (use_openat) {
     return seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
     return seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
-                              SCMP_CMP_STR(0, SCMP_CMP_EQ, AT_FDCWD),
+                              SCMP_CMP(0, SCMP_CMP_EQ, (unsigned int)AT_FDCWD),
                               SCMP_CMP_STR(1, SCMP_CMP_EQ, file));
                               SCMP_CMP_STR(1, SCMP_CMP_EQ, file));
   } else {
   } else {
     return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open),
     return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open),

+ 12 - 5
src/common/tortls.c

@@ -896,18 +896,20 @@ tor_tls_cert_get_key(tor_x509_cert_t *cert)
 MOCK_IMPL(int,
 MOCK_IMPL(int,
 tor_tls_cert_matches_key,(const tor_tls_t *tls, const tor_x509_cert_t *cert))
 tor_tls_cert_matches_key,(const tor_tls_t *tls, const tor_x509_cert_t *cert))
 {
 {
-  X509 *peercert = SSL_get_peer_certificate(tls->ssl);
+  tor_x509_cert_t *peer = tor_tls_get_peer_cert((tor_tls_t *)tls);
+  if (!peer)
+    return 0;
+
+  X509 *peercert = peer->cert;
   EVP_PKEY *link_key = NULL, *cert_key = NULL;
   EVP_PKEY *link_key = NULL, *cert_key = NULL;
   int result;
   int result;
 
 
-  if (!peercert)
-    return 0;
   link_key = X509_get_pubkey(peercert);
   link_key = X509_get_pubkey(peercert);
   cert_key = X509_get_pubkey(cert->cert);
   cert_key = X509_get_pubkey(cert->cert);
 
 
   result = link_key && cert_key && EVP_PKEY_cmp(cert_key, link_key) == 1;
   result = link_key && cert_key && EVP_PKEY_cmp(cert_key, link_key) == 1;
 
 
-  X509_free(peercert);
+  tor_x509_cert_free(peer);
   if (link_key)
   if (link_key)
     EVP_PKEY_free(link_key);
     EVP_PKEY_free(link_key);
   if (cert_key)
   if (cert_key)
@@ -1170,6 +1172,12 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime,
   if (!(result->ctx = SSL_CTX_new(SSLv23_method())))
   if (!(result->ctx = SSL_CTX_new(SSLv23_method())))
     goto error;
     goto error;
 #endif /* defined(HAVE_TLS_METHOD) */
 #endif /* defined(HAVE_TLS_METHOD) */
+
+#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
+  /* Level 1 re-enables RSA1024 and DH1024 for compatibility with old tors */
+  SSL_CTX_set_security_level(result->ctx, 1);
+#endif
+
   SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv2);
   SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv2);
   SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv3);
   SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv3);
 
 
@@ -2639,4 +2647,3 @@ evaluate_ecgroup_for_tls(const char *ecgroup)
 
 
   return ret;
   return ret;
 }
 }
-

File diff suppressed because it is too large
+ 225 - 505
src/config/geoip


File diff suppressed because it is too large
+ 212 - 650
src/config/geoip6


+ 10 - 2
src/ext/tinytest.c

@@ -207,12 +207,20 @@ testcase_run_forked_(const struct testgroup_t *group,
 		r = (int)read(outcome_pipe[0], b, 1);
 		r = (int)read(outcome_pipe[0], b, 1);
 		if (r == 0) {
 		if (r == 0) {
 			printf("[Lost connection!] ");
 			printf("[Lost connection!] ");
-			return 0;
+			return FAIL;
 		} else if (r != 1) {
 		} else if (r != 1) {
 			perror("read outcome from pipe");
 			perror("read outcome from pipe");
 		}
 		}
-		waitpid(pid, &status, 0);
+		r = waitpid(pid, &status, 0);
 		close(outcome_pipe[0]);
 		close(outcome_pipe[0]);
+		if (r == -1) {
+			perror("waitpid");
+			return FAIL;
+		}
+                if (! WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+			printf("[did not exit cleanly.]");
+			return FAIL;
+                }
 		return b[0]=='Y' ? OK : (b[0]=='S' ? SKIP : FAIL);
 		return b[0]=='Y' ? OK : (b[0]=='S' ? SKIP : FAIL);
 	}
 	}
 #endif
 #endif

+ 2 - 2
src/or/auth_dirs.inc

@@ -8,8 +8,8 @@
 "dizum orport=443 "
 "dizum orport=443 "
   "v3ident=E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58 "
   "v3ident=E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58 "
   "194.109.206.212:80 7EA6 EAD6 FD83 083C 538F 4403 8BBF A077 587D D755",
   "194.109.206.212:80 7EA6 EAD6 FD83 083C 538F 4403 8BBF A077 587D D755",
-"Bifroest orport=443 bridge "
-  "37.218.247.217:80 1D8F 3A91 C37C 5D1C 4C19 B1AD 1D0C FBE8 BF72 D8E1",
+"Serge orport=9001 bridge "
+  "66.111.2.131:9030 BA44 A889 E64B 93FA A2B1 14E0 2C2A 279A 8555 C533",
 "gabelmoo orport=443 "
 "gabelmoo orport=443 "
   "v3ident=ED03BB616EB2F60BEC80151114BB25CEF515B226 "
   "v3ident=ED03BB616EB2F60BEC80151114BB25CEF515B226 "
   "ipv6=[2001:638:a000:4140::ffff:189]:443 "
   "ipv6=[2001:638:a000:4140::ffff:189]:443 "

+ 7 - 2
src/or/channelpadding.c

@@ -379,7 +379,8 @@ channelpadding_send_padding_cell_for_callback(channel_t *chan)
   chan->pending_padding_callback = 0;
   chan->pending_padding_callback = 0;
 
 
   if (monotime_coarse_is_zero(&chan->next_padding_time) ||
   if (monotime_coarse_is_zero(&chan->next_padding_time) ||
-      chan->has_queued_writes(chan)) {
+      chan->has_queued_writes(chan) ||
+      (chan->cmux && circuitmux_num_cells(chan->cmux))) {
     /* We must have been active before the timer fired */
     /* We must have been active before the timer fired */
     monotime_coarse_zero(&chan->next_padding_time);
     monotime_coarse_zero(&chan->next_padding_time);
     return;
     return;
@@ -755,7 +756,11 @@ channelpadding_decide_to_pad_channel(channel_t *chan)
     return CHANNELPADDING_WONTPAD;
     return CHANNELPADDING_WONTPAD;
   }
   }
 
 
-  if (!chan->has_queued_writes(chan)) {
+  /* There should always be a cmux on the circuit. After that,
+   * only schedule padding if there are no queued writes and no
+   * queued cells in circuitmux queues. */
+  if (chan->cmux && !chan->has_queued_writes(chan) &&
+      !circuitmux_num_cells(chan->cmux)) {
     int is_client_channel = 0;
     int is_client_channel = 0;
 
 
     if (CHANNEL_IS_CLIENT(chan, options)) {
     if (CHANNEL_IS_CLIENT(chan, options)) {

+ 34 - 11
src/or/circuituse.c

@@ -1757,6 +1757,39 @@ circuit_build_failed(origin_circuit_t *circ)
    * the last hop or an earlier hop. then use this info below.
    * the last hop or an earlier hop. then use this info below.
    */
    */
   int failed_at_last_hop = 0;
   int failed_at_last_hop = 0;
+
+  /* First, check to see if this was a path failure, rather than build
+   * failure.
+   *
+   * Note that we deliberately use circuit_get_cpath_len() (and not
+   * circuit_get_cpath_opened_len()) because we only want to ensure
+   * that a full path is *chosen*. This is different than a full path
+   * being *built*. We only want to count *build* failures below.
+   *
+   * Path selection failures can happen spuriously for a number
+   * of reasons (such as aggressive/invalid user-specified path
+   * restrictions in the torrc, insufficient microdescriptors, and
+   * non-user reasons like exitpolicy issues), and so should not be
+   * counted as failures below.
+   */
+  if (circuit_get_cpath_len(circ) < circ->build_state->desired_path_len) {
+    static ratelim_t pathfail_limit = RATELIM_INIT(3600);
+    log_fn_ratelim(&pathfail_limit, LOG_NOTICE, LD_CIRC,
+             "Our circuit %u (id: %" PRIu32 ") died due to an invalid "
+             "selected path, purpose %s. This may be a torrc "
+             "configuration issue, or a bug.",
+              TO_CIRCUIT(circ)->n_circ_id, circ->global_identifier,
+              circuit_purpose_to_string(TO_CIRCUIT(circ)->purpose));
+
+    /* If the path failed on an RP, retry it. */
+    if (TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND)
+      hs_circ_retry_service_rendezvous_point(circ);
+
+    /* In all other cases, just bail. The rest is just failure accounting
+     * that we don't want to do */
+    return;
+  }
+
   /* If the last hop isn't open, and the second-to-last is, we failed
   /* If the last hop isn't open, and the second-to-last is, we failed
    * at the last hop. */
    * at the last hop. */
   if (circ->cpath &&
   if (circ->cpath &&
@@ -1806,18 +1839,8 @@ circuit_build_failed(origin_circuit_t *circ)
        * If we have guard state (new guard API) and our path selection
        * If we have guard state (new guard API) and our path selection
        * code actually chose a full path, then blame the failure of this
        * code actually chose a full path, then blame the failure of this
        * circuit on the guard.
        * circuit on the guard.
-       *
-       * Note that we deliberately use circuit_get_cpath_len() (and not
-       * circuit_get_cpath_opened_len()) because we only want to ensure
-       * that a full path is *chosen*. This is different than a full path
-       * being *built*. We only want to blame *build* failures on this
-       * guard. Path selection failures can happen spuriously for a number
-       * of reasons (such as aggressive/invalid user-specified path
-       * restrictions in the torrc, as well as non-user reasons like
-       * exitpolicy issues), and so should not be counted here.
        */
        */
-      if (circ->guard_state &&
-          circuit_get_cpath_len(circ) >= circ->build_state->desired_path_len)
+      if (circ->guard_state)
         entry_guard_failed(&circ->guard_state);
         entry_guard_failed(&circ->guard_state);
       /* if there are any one-hop streams waiting on this circuit, fail
       /* if there are any one-hop streams waiting on this circuit, fail
        * them now so they can retry elsewhere. */
        * them now so they can retry elsewhere. */

+ 9 - 1
src/or/config.c

@@ -868,6 +868,7 @@ set_options(or_options_t *new_val, char **msg)
               "Acting on config options left us in a broken state. Dying.");
               "Acting on config options left us in a broken state. Dying.");
       tor_shutdown_event_loop_and_exit(1);
       tor_shutdown_event_loop_and_exit(1);
     }
     }
+    global_options = old_options;
     return -1;
     return -1;
   }
   }
   /* Issues a CONF_CHANGED event to notify controller of the change. If Tor is
   /* Issues a CONF_CHANGED event to notify controller of the change. If Tor is
@@ -3472,6 +3473,14 @@ options_validate(or_options_t *old_options, or_options_t *options,
          !options->RecommendedServerVersions))
          !options->RecommendedServerVersions))
       REJECT("Versioning authoritative dir servers must set "
       REJECT("Versioning authoritative dir servers must set "
              "Recommended*Versions.");
              "Recommended*Versions.");
+
+    char *t;
+    /* Call these functions to produce warnings only. */
+    t = format_recommended_version_list(options->RecommendedClientVersions, 1);
+    tor_free(t);
+    t = format_recommended_version_list(options->RecommendedServerVersions, 1);
+    tor_free(t);
+
     if (options->UseEntryGuards) {
     if (options->UseEntryGuards) {
       log_info(LD_CONFIG, "Authoritative directory servers can't set "
       log_info(LD_CONFIG, "Authoritative directory servers can't set "
                "UseEntryGuards. Disabling.");
                "UseEntryGuards. Disabling.");
@@ -8399,4 +8408,3 @@ init_cookie_authentication(const char *fname, const char *header,
   tor_free(cookie_file_str);
   tor_free(cookie_file_str);
   return retval;
   return retval;
 }
 }
-

+ 0 - 1
src/or/connection_edge.c

@@ -4166,4 +4166,3 @@ connection_edge_free_all(void)
   smartlist_free(pending_entry_connections);
   smartlist_free(pending_entry_connections);
   pending_entry_connections = NULL;
   pending_entry_connections = NULL;
 }
 }
-

+ 9 - 5
src/or/connection_or.c

@@ -50,6 +50,7 @@
 #include "proto_cell.h"
 #include "proto_cell.h"
 #include "reasons.h"
 #include "reasons.h"
 #include "relay.h"
 #include "relay.h"
+#include "rendcommon.h"
 #include "rephist.h"
 #include "rephist.h"
 #include "router.h"
 #include "router.h"
 #include "routerkeys.h"
 #include "routerkeys.h"
@@ -1923,10 +1924,13 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
                                                    conn->identity_digest);
                                                    conn->identity_digest);
     const int is_authority_fingerprint = router_digest_is_trusted_dir(
     const int is_authority_fingerprint = router_digest_is_trusted_dir(
                                                    conn->identity_digest);
                                                    conn->identity_digest);
+    const int non_anonymous_mode = rend_non_anonymous_mode_enabled(options);
     int severity;
     int severity;
     const char *extra_log = "";
     const char *extra_log = "";
 
 
-    if (server_mode(options)) {
+    /* Relays, Single Onion Services, and Tor2web make direct connections using
+     * untrusted authentication keys. */
+    if (server_mode(options) || non_anonymous_mode) {
       severity = LOG_PROTOCOL_WARN;
       severity = LOG_PROTOCOL_WARN;
     } else {
     } else {
       if (using_hardcoded_fingerprints) {
       if (using_hardcoded_fingerprints) {
@@ -1950,8 +1954,8 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
     }
     }
 
 
     log_fn(severity, LD_HANDSHAKE,
     log_fn(severity, LD_HANDSHAKE,
-           "Tried connecting to router at %s:%d, but RSA identity key was not "
-           "as expected: wanted %s + %s but got %s + %s.%s",
+           "Tried connecting to router at %s:%d, but RSA + ed25519 identity "
+           "keys were not as expected: wanted %s + %s but got %s + %s.%s",
            conn->base_.address, conn->base_.port,
            conn->base_.address, conn->base_.port,
            expected_rsa, expected_ed, seen_rsa, seen_ed, extra_log);
            expected_rsa, expected_ed, seen_rsa, seen_ed, extra_log);
 
 
@@ -1968,8 +1972,8 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
   }
   }
 
 
   if (!expected_ed_key && ed_peer_id) {
   if (!expected_ed_key && ed_peer_id) {
-    log_info(LD_HANDSHAKE, "(we had no Ed25519 ID in mind when we made this "
-             "connection.");
+    log_info(LD_HANDSHAKE, "(We had no Ed25519 ID in mind when we made this "
+             "connection.)");
     connection_or_set_identity_digest(conn,
     connection_or_set_identity_digest(conn,
                                       (const char*)rsa_peer_id, ed_peer_id);
                                       (const char*)rsa_peer_id, ed_peer_id);
     changed_identity = 1;
     changed_identity = 1;

+ 12 - 1
src/or/control.c

@@ -1896,6 +1896,8 @@ getinfo_helper_listeners(control_connection_t *control_conn,
 
 
   if (!strcmp(question, "net/listeners/or"))
   if (!strcmp(question, "net/listeners/or"))
     type = CONN_TYPE_OR_LISTENER;
     type = CONN_TYPE_OR_LISTENER;
+  else if (!strcmp(question, "net/listeners/extor"))
+    type = CONN_TYPE_EXT_OR_LISTENER;
   else if (!strcmp(question, "net/listeners/dir"))
   else if (!strcmp(question, "net/listeners/dir"))
     type = CONN_TYPE_DIR_LISTENER;
     type = CONN_TYPE_DIR_LISTENER;
   else if (!strcmp(question, "net/listeners/socks"))
   else if (!strcmp(question, "net/listeners/socks"))
@@ -1904,6 +1906,8 @@ getinfo_helper_listeners(control_connection_t *control_conn,
     type = CONN_TYPE_AP_TRANS_LISTENER;
     type = CONN_TYPE_AP_TRANS_LISTENER;
   else if (!strcmp(question, "net/listeners/natd"))
   else if (!strcmp(question, "net/listeners/natd"))
     type = CONN_TYPE_AP_NATD_LISTENER;
     type = CONN_TYPE_AP_NATD_LISTENER;
+  else if (!strcmp(question, "net/listeners/httptunnel"))
+    type = CONN_TYPE_AP_HTTP_CONNECT_LISTENER;
   else if (!strcmp(question, "net/listeners/dns"))
   else if (!strcmp(question, "net/listeners/dns"))
     type = CONN_TYPE_AP_DNS_LISTENER;
     type = CONN_TYPE_AP_DNS_LISTENER;
   else if (!strcmp(question, "net/listeners/control"))
   else if (!strcmp(question, "net/listeners/control"))
@@ -7610,6 +7614,14 @@ control_free_all(void)
     tor_event_free(flush_queued_events_event);
     tor_event_free(flush_queued_events_event);
     flush_queued_events_event = NULL;
     flush_queued_events_event = NULL;
   }
   }
+  bootstrap_percent = BOOTSTRAP_STATUS_UNDEF;
+  notice_bootstrap_percent = 0;
+  bootstrap_problems = 0;
+  authentication_cookie_is_set = 0;
+  global_event_mask = 0;
+  disable_log_messages = 0;
+  memset(last_sent_bootstrap_message, 0, sizeof(last_sent_bootstrap_message));
+  flush_queued_event_pending = 0;
 }
 }
 
 
 #ifdef TOR_UNIT_TESTS
 #ifdef TOR_UNIT_TESTS
@@ -7620,4 +7632,3 @@ control_testing_set_global_event_mask(uint64_t mask)
   global_event_mask = mask;
   global_event_mask = mask;
 }
 }
 #endif /* defined(TOR_UNIT_TESTS) */
 #endif /* defined(TOR_UNIT_TESTS) */
-

+ 41 - 10
src/or/dirserv.c

@@ -74,7 +74,6 @@
 static int routers_with_measured_bw = 0;
 static int routers_with_measured_bw = 0;
 
 
 static void directory_remove_invalid(void);
 static void directory_remove_invalid(void);
-static char *format_versions_list(config_line_t *ln);
 struct authdir_config_t;
 struct authdir_config_t;
 static uint32_t
 static uint32_t
 dirserv_get_status_impl(const char *fp, const char *nickname,
 dirserv_get_status_impl(const char *fp, const char *nickname,
@@ -1061,8 +1060,8 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
  * allocate and return a new string containing the version numbers, in order,
  * allocate and return a new string containing the version numbers, in order,
  * separated by commas.  Used to generate Recommended(Client|Server)?Versions
  * separated by commas.  Used to generate Recommended(Client|Server)?Versions
  */
  */
-static char *
-format_versions_list(config_line_t *ln)
+char *
+format_recommended_version_list(const config_line_t *ln, int warn)
 {
 {
   smartlist_t *versions;
   smartlist_t *versions;
   char *result;
   char *result;
@@ -1071,6 +1070,37 @@ format_versions_list(config_line_t *ln)
     smartlist_split_string(versions, ln->value, ",",
     smartlist_split_string(versions, ln->value, ",",
                            SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
                            SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
   }
   }
+
+  /* Handle the case where a dirauth operator has accidentally made some
+   * versions space-separated instead of comma-separated. */
+  smartlist_t *more_versions = smartlist_new();
+  SMARTLIST_FOREACH_BEGIN(versions, char *, v) {
+    if (strchr(v, ' ')) {
+      if (warn)
+        log_warn(LD_DIRSERV, "Unexpected space in versions list member %s. "
+                 "(These are supposed to be comma-separated; I'll pretend you "
+                 "used commas instead.)", escaped(v));
+      SMARTLIST_DEL_CURRENT(versions, v);
+      smartlist_split_string(more_versions, v, NULL,
+                             SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+      tor_free(v);
+    }
+  } SMARTLIST_FOREACH_END(v);
+  smartlist_add_all(versions, more_versions);
+  smartlist_free(more_versions);
+
+  /* Check to make sure everything looks like a version. */
+  if (warn) {
+    SMARTLIST_FOREACH_BEGIN(versions, const char *, v) {
+      tor_version_t ver;
+      if (tor_version_parse(v, &ver) < 0) {
+        log_warn(LD_DIRSERV, "Recommended version %s does not look valid. "
+                 " (I'll include it anyway, since you told me to.)",
+                 escaped(v));
+      }
+    } SMARTLIST_FOREACH_END(v);
+  }
+
   sort_version_list(versions, 1);
   sort_version_list(versions, 1);
   result = smartlist_join_strings(versions,",",0,NULL);
   result = smartlist_join_strings(versions,",",0,NULL);
   SMARTLIST_FOREACH(versions,char *,s,tor_free(s));
   SMARTLIST_FOREACH(versions,char *,s,tor_free(s));
@@ -2911,8 +2941,10 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
   }
   }
 
 
   if (options->VersioningAuthoritativeDir) {
   if (options->VersioningAuthoritativeDir) {
-    client_versions = format_versions_list(options->RecommendedClientVersions);
-    server_versions = format_versions_list(options->RecommendedServerVersions);
+    client_versions =
+      format_recommended_version_list(options->RecommendedClientVersions, 0);
+    server_versions =
+      format_recommended_version_list(options->RecommendedServerVersions, 0);
   }
   }
 
 
   contact = get_options()->ContactInfo;
   contact = get_options()->ContactInfo;
@@ -3076,16 +3108,16 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
   /* These are hardwired, to avoid disaster. */
   /* These are hardwired, to avoid disaster. */
   v3_out->recommended_relay_protocols =
   v3_out->recommended_relay_protocols =
     tor_strdup("Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 "
     tor_strdup("Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 "
-               "Link=4 LinkAuth=1 Microdesc=1-2 Relay=2");
+               "Link=4 Microdesc=1-2 Relay=2");
   v3_out->recommended_client_protocols =
   v3_out->recommended_client_protocols =
     tor_strdup("Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 "
     tor_strdup("Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 "
-               "Link=4 LinkAuth=1 Microdesc=1-2 Relay=2");
+               "Link=4 Microdesc=1-2 Relay=2");
   v3_out->required_client_protocols =
   v3_out->required_client_protocols =
     tor_strdup("Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 "
     tor_strdup("Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 "
-               "Link=4 LinkAuth=1 Microdesc=1-2 Relay=2");
+               "Link=4 Microdesc=1-2 Relay=2");
   v3_out->required_relay_protocols =
   v3_out->required_relay_protocols =
     tor_strdup("Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 "
     tor_strdup("Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 "
-               "Link=3-4 LinkAuth=1 Microdesc=1 Relay=1-2");
+               "Link=3-4 Microdesc=1 Relay=1-2");
 
 
   /* We are not allowed to vote to require anything we don't have. */
   /* We are not allowed to vote to require anything we don't have. */
   tor_assert(protover_all_supported(v3_out->required_relay_protocols, NULL));
   tor_assert(protover_all_supported(v3_out->required_relay_protocols, NULL));
@@ -4062,4 +4094,3 @@ dirserv_free_all(void)
 
 
   dirserv_clear_measured_bw_cache();
   dirserv_clear_measured_bw_cache();
 }
 }
-

+ 1 - 2
src/or/dirserv.h

@@ -155,7 +155,7 @@ char *routerstatus_format_entry(
 void dirserv_free_all(void);
 void dirserv_free_all(void);
 void cached_dir_decref(cached_dir_t *d);
 void cached_dir_decref(cached_dir_t *d);
 cached_dir_t *new_cached_dir(char *s, time_t published);
 cached_dir_t *new_cached_dir(char *s, time_t published);
-
+char *format_recommended_version_list(const config_line_t *line, int warn);
 int validate_recommended_package_line(const char *line);
 int validate_recommended_package_line(const char *line);
 
 
 #ifdef DIRSERV_PRIVATE
 #ifdef DIRSERV_PRIVATE
@@ -208,4 +208,3 @@ void dirserv_spool_sort(dir_connection_t *conn);
 void dir_conn_clear_spool(dir_connection_t *conn);
 void dir_conn_clear_spool(dir_connection_t *conn);
 
 
 #endif /* !defined(TOR_DIRSERV_H) */
 #endif /* !defined(TOR_DIRSERV_H) */
-

+ 8 - 1
src/or/dirvote.c

@@ -707,6 +707,14 @@ compute_consensus_versions_list(smartlist_t *lst, int n_versioning)
   int min = n_versioning / 2;
   int min = n_versioning / 2;
   smartlist_t *good = smartlist_new();
   smartlist_t *good = smartlist_new();
   char *result;
   char *result;
+  SMARTLIST_FOREACH_BEGIN(lst, const char *, v) {
+    if (strchr(v, ' ')) {
+      log_warn(LD_DIR, "At least one authority has voted for a version %s "
+               "that contains a space. This probably wasn't intentional, and "
+               "is likely to cause trouble. Please tell them to stop it.",
+               escaped(v));
+    }
+  } SMARTLIST_FOREACH_END(v);
   sort_version_list(lst, 0);
   sort_version_list(lst, 0);
   get_frequent_members(good, lst, min);
   get_frequent_members(good, lst, min);
   result = smartlist_join_strings(good, ",", 0, NULL);
   result = smartlist_join_strings(good, ",", 0, NULL);
@@ -4077,4 +4085,3 @@ vote_routerstatus_find_microdesc_hash(char *digest256_out,
   }
   }
   return -1;
   return -1;
 }
 }
-

+ 14 - 6
src/or/hs_circuit.c

@@ -559,10 +559,14 @@ retry_service_rendezvous_point(const origin_circuit_t *circ)
   return;
   return;
 }
 }
 
 
-/* Add all possible link specifiers in node to lspecs.
- * legacy ID is mandatory thus MUST be present in node. If the primary address
- * is not IPv4, log a BUG() warning, and return an empty smartlist.
- * Includes ed25519 id and IPv6 link specifiers if present in the node. */
+/* Add all possible link specifiers in node to lspecs:
+ *  - legacy ID is mandatory thus MUST be present in node;
+ *  - include ed25519 link specifier if present in the node, and the node
+ *    supports ed25519 link authentication, even if its link versions are not
+ *    compatible with us;
+ *  - include IPv4 link specifier, if the primary address is not IPv4, log a
+ *    BUG() warning, and return an empty smartlist;
+ *  - include IPv6 link specifier if present in the node. */
 static void
 static void
 get_lspecs_from_node(const node_t *node, smartlist_t *lspecs)
 get_lspecs_from_node(const node_t *node, smartlist_t *lspecs)
 {
 {
@@ -600,8 +604,12 @@ get_lspecs_from_node(const node_t *node, smartlist_t *lspecs)
   link_specifier_set_ls_len(ls, link_specifier_getlen_un_legacy_id(ls));
   link_specifier_set_ls_len(ls, link_specifier_getlen_un_legacy_id(ls));
   smartlist_add(lspecs, ls);
   smartlist_add(lspecs, ls);
 
 
-  /* ed25519 ID is only included if the node has it. */
-  if (!ed25519_public_key_is_zero(&node->ed25519_id)) {
+  /* ed25519 ID is only included if the node has it, and the node declares a
+     protocol version that supports ed25519 link authentication, even if that
+     link version is not compatible with us. (We are sending the ed25519 key
+     to another tor, which may support different link versions.) */
+  if (!ed25519_public_key_is_zero(&node->ed25519_id) &&
+      node_supports_ed25519_link_authentication(node, 0)) {
     ls = link_specifier_new();
     ls = link_specifier_new();
     link_specifier_set_ls_type(ls, LS_ED25519_ID);
     link_specifier_set_ls_type(ls, LS_ED25519_ID);
     memcpy(link_specifier_getarray_un_ed25519_id(ls), &node->ed25519_id,
     memcpy(link_specifier_getarray_un_ed25519_id(ls), &node->ed25519_id,

+ 24 - 12
src/or/hs_service.c

@@ -376,17 +376,21 @@ service_intro_point_free_void(void *obj)
 }
 }
 
 
 /* Return a newly allocated service intro point and fully initialized from the
 /* Return a newly allocated service intro point and fully initialized from the
- * given extend_info_t ei if non NULL. If is_legacy is true, we also generate
- * the legacy key. On error, NULL is returned.
+ * given extend_info_t ei if non NULL.
+ * If is_legacy is true, we also generate the legacy key.
+ * If supports_ed25519_link_handshake_any is true, we add the relay's ed25519
+ * key to the link specifiers.
  *
  *
  * If ei is NULL, returns a hs_service_intro_point_t with an empty link
  * If ei is NULL, returns a hs_service_intro_point_t with an empty link
  * specifier list and no onion key. (This is used for testing.)
  * specifier list and no onion key. (This is used for testing.)
+ * On any other error, NULL is returned.
  *
  *
  * ei must be an extend_info_t containing an IPv4 address. (We will add supoort
  * ei must be an extend_info_t containing an IPv4 address. (We will add supoort
  * for IPv6 in a later release.) When calling extend_info_from_node(), pass
  * for IPv6 in a later release.) When calling extend_info_from_node(), pass
  * 0 in for_direct_connection to make sure ei always has an IPv4 address. */
  * 0 in for_direct_connection to make sure ei always has an IPv4 address. */
 STATIC hs_service_intro_point_t *
 STATIC hs_service_intro_point_t *
-service_intro_point_new(const extend_info_t *ei, unsigned int is_legacy)
+service_intro_point_new(const extend_info_t *ei, unsigned int is_legacy,
+                        unsigned int supports_ed25519_link_handshake_any)
 {
 {
   hs_desc_link_specifier_t *ls;
   hs_desc_link_specifier_t *ls;
   hs_service_intro_point_t *ip;
   hs_service_intro_point_t *ip;
@@ -453,10 +457,13 @@ service_intro_point_new(const extend_info_t *ei, unsigned int is_legacy)
   }
   }
   smartlist_add(ip->base.link_specifiers, ls);
   smartlist_add(ip->base.link_specifiers, ls);
 
 
-  /* ed25519 identity key is optional for intro points */
-  ls = hs_desc_link_specifier_new(ei, LS_ED25519_ID);
-  if (ls) {
-    smartlist_add(ip->base.link_specifiers, ls);
+  /* ed25519 identity key is optional for intro points. If the node supports
+   * ed25519 link authentication, we include it. */
+  if (supports_ed25519_link_handshake_any) {
+    ls = hs_desc_link_specifier_new(ei, LS_ED25519_ID);
+    if (ls) {
+      smartlist_add(ip->base.link_specifiers, ls);
+    }
   }
   }
 
 
   /* IPv6 is not supported in this release. */
   /* IPv6 is not supported in this release. */
@@ -847,6 +854,7 @@ move_hs_state(hs_service_t *src_service, hs_service_t *dst_service)
     replaycache_free(dst->replay_cache_rend_cookie);
     replaycache_free(dst->replay_cache_rend_cookie);
   }
   }
   dst->replay_cache_rend_cookie = src->replay_cache_rend_cookie;
   dst->replay_cache_rend_cookie = src->replay_cache_rend_cookie;
+  dst->next_rotation_time = src->next_rotation_time;
 
 
   src->replay_cache_rend_cookie = NULL; /* steal pointer reference */
   src->replay_cache_rend_cookie = NULL; /* steal pointer reference */
 }
 }
@@ -975,9 +983,9 @@ load_service_keys(hs_service_t *service)
    * files to that directory so make sure it exists and has the right
    * files to that directory so make sure it exists and has the right
    * permissions. We do this here because at this stage we know that Tor is
    * permissions. We do this here because at this stage we know that Tor is
    * actually running and the service we have has been validated. */
    * actually running and the service we have has been validated. */
-  if (BUG(hs_check_service_private_dir(get_options()->User,
-                                       config->directory_path,
-                                       config->dir_group_readable, 1) < 0)) {
+  if (hs_check_service_private_dir(get_options()->User,
+                                   config->directory_path,
+                                   config->dir_group_readable, 1) < 0) {
     goto end;
     goto end;
   }
   }
 
 
@@ -1586,8 +1594,12 @@ pick_intro_point(unsigned int direct_conn, smartlist_t *exclude_nodes)
     tor_assert_nonfatal(!ed25519_public_key_is_zero(&info->ed_identity));
     tor_assert_nonfatal(!ed25519_public_key_is_zero(&info->ed_identity));
   }
   }
 
 
-  /* Create our objects and populate them with the node information. */
-  ip = service_intro_point_new(info, !node_supports_ed25519_hs_intro(node));
+  /* Create our objects and populate them with the node information.
+   * We don't care if the intro's link auth is compatible with us, because
+   * we are sending the ed25519 key to a remote client via the descriptor. */
+  ip = service_intro_point_new(info, !node_supports_ed25519_hs_intro(node),
+                               node_supports_ed25519_link_authentication(node,
+                                                                         0));
   if (ip == NULL) {
   if (ip == NULL) {
     goto err;
     goto err;
   }
   }

+ 3 - 2
src/or/hs_service.h

@@ -307,8 +307,9 @@ STATIC void remove_service(hs_service_ht *map, hs_service_t *service);
 STATIC int register_service(hs_service_ht *map, hs_service_t *service);
 STATIC int register_service(hs_service_ht *map, hs_service_t *service);
 /* Service introduction point functions. */
 /* Service introduction point functions. */
 STATIC hs_service_intro_point_t *service_intro_point_new(
 STATIC hs_service_intro_point_t *service_intro_point_new(
-                                         const extend_info_t *ei,
-                                         unsigned int is_legacy);
+                            const extend_info_t *ei,
+                            unsigned int is_legacy,
+                            unsigned int supports_ed25519_link_handshake_any);
 STATIC void service_intro_point_free_(hs_service_intro_point_t *ip);
 STATIC void service_intro_point_free_(hs_service_intro_point_t *ip);
 #define service_intro_point_free(ip)                            \
 #define service_intro_point_free(ip)                            \
   FREE_AND_NULL(hs_service_intro_point_t,             \
   FREE_AND_NULL(hs_service_intro_point_t,             \

+ 13 - 4
src/or/main.c

@@ -3995,6 +3995,13 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
 #endif
 #endif
   /* On heap corruption, just give up; don't try to play along. */
   /* On heap corruption, just give up; don't try to play along. */
   HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
   HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
+
+  /* SetProcessDEPPolicy is only supported on 32-bit Windows.
+   * (On 64-bit Windows it always fails, and some compilers don't like the
+   * PSETDEP cast.)
+   * 32-bit Windows defines _WIN32.
+   * 64-bit Windows defines _WIN32 and _WIN64. */
+#ifndef _WIN64
   /* Call SetProcessDEPPolicy to permanently enable DEP.
   /* Call SetProcessDEPPolicy to permanently enable DEP.
      The function will not resolve on earlier versions of Windows,
      The function will not resolve on earlier versions of Windows,
      and failure is not dangerous. */
      and failure is not dangerous. */
@@ -4008,6 +4015,7 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
       setdeppolicy(3);
       setdeppolicy(3);
     }
     }
   }
   }
+#endif /* !defined(_WIN64) */
 #endif /* defined(_WIN32) */
 #endif /* defined(_WIN32) */
 
 
   configure_backtrace_handler(get_version());
   configure_backtrace_handler(get_version());
@@ -4035,10 +4043,10 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
 #endif /* defined(NT_SERVICE) */
 #endif /* defined(NT_SERVICE) */
   {
   {
     int init_rv = tor_init(argc, argv);
     int init_rv = tor_init(argc, argv);
-    if (init_rv < 0)
-      return -1;
-    else if (init_rv > 0)
-      return 0;
+    if (init_rv) {
+      tor_free_all(0);
+      return (init_rv < 0) ? -1 : 0;
+    }
   }
   }
 
 
   if (get_options()->Sandbox && get_options()->command == CMD_RUN_TOR) {
   if (get_options()->Sandbox && get_options()->command == CMD_RUN_TOR) {
@@ -4046,6 +4054,7 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
 
 
     if (sandbox_init(cfg)) {
     if (sandbox_init(cfg)) {
       log_err(LD_BUG,"Failed to create syscall sandbox filter");
       log_err(LD_BUG,"Failed to create syscall sandbox filter");
+      tor_free_all(0);
       return -1;
       return -1;
     }
     }
 
 

+ 9 - 0
src/or/rendclient.c

@@ -238,6 +238,15 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
     dh_offset = v3_shift+7+DIGEST_LEN+2+klen+REND_COOKIE_LEN;
     dh_offset = v3_shift+7+DIGEST_LEN+2+klen+REND_COOKIE_LEN;
   } else {
   } else {
     /* Version 0. */
     /* Version 0. */
+
+    /* Some compilers are smart enough to work out that nickname can be more
+     * than 19 characters, when it's a hexdigest. They warn that strncpy()
+     * will truncate hexdigests without NUL-terminating them. But we only put
+     * hexdigests in HSDir and general circuit exits. */
+    if (BUG(strlen(rendcirc->build_state->chosen_exit->nickname)
+            > MAX_NICKNAME_LEN)) {
+      goto perm_err;
+    }
     strncpy(tmp, rendcirc->build_state->chosen_exit->nickname,
     strncpy(tmp, rendcirc->build_state->chosen_exit->nickname,
             (MAX_NICKNAME_LEN+1)); /* nul pads */
             (MAX_NICKNAME_LEN+1)); /* nul pads */
     memcpy(tmp+MAX_NICKNAME_LEN+1, rendcirc->rend_data->rend_cookie,
     memcpy(tmp+MAX_NICKNAME_LEN+1, rendcirc->rend_data->rend_cookie,

+ 9 - 6
src/or/router.c

@@ -1950,10 +1950,11 @@ router_compare_to_my_exit_policy(const tor_addr_t *addr, uint16_t port)
 MOCK_IMPL(int,
 MOCK_IMPL(int,
 router_my_exit_policy_is_reject_star,(void))
 router_my_exit_policy_is_reject_star,(void))
 {
 {
-  if (!router_get_my_routerinfo()) /* make sure routerinfo exists */
+  const routerinfo_t *me = router_get_my_routerinfo();
+  if (!me) /* make sure routerinfo exists */
     return -1;
     return -1;
 
 
-  return router_get_my_routerinfo()->policy_is_reject_star;
+  return me->policy_is_reject_star;
 }
 }
 
 
 /** Return true iff I'm a server and <b>digest</b> is equal to
 /** Return true iff I'm a server and <b>digest</b> is equal to
@@ -2522,10 +2523,11 @@ check_descriptor_bandwidth_changed(time_t now)
 {
 {
   static time_t last_changed = 0;
   static time_t last_changed = 0;
   uint64_t prev, cur;
   uint64_t prev, cur;
-  if (!router_get_my_routerinfo())
+  const routerinfo_t *my_ri = router_get_my_routerinfo();
+  if (!my_ri) /* make sure routerinfo exists */
     return;
     return;
 
 
-  prev = router_get_my_routerinfo()->bandwidthcapacity;
+  prev = my_ri->bandwidthcapacity;
   cur = we_are_hibernating() ? 0 : rep_hist_bandwidth_assess();
   cur = we_are_hibernating() ? 0 : rep_hist_bandwidth_assess();
   if ((prev != cur && (!prev || !cur)) ||
   if ((prev != cur && (!prev || !cur)) ||
       cur > prev*2 ||
       cur > prev*2 ||
@@ -2576,14 +2578,15 @@ check_descriptor_ipaddress_changed(time_t now)
   const or_options_t *options = get_options();
   const or_options_t *options = get_options();
   const char *method = NULL;
   const char *method = NULL;
   char *hostname = NULL;
   char *hostname = NULL;
+  const routerinfo_t *my_ri = router_get_my_routerinfo();
 
 
   (void) now;
   (void) now;
 
 
-  if (router_get_my_routerinfo() == NULL)
+  if (my_ri == NULL) /* make sure routerinfo exists */
     return;
     return;
 
 
   /* XXXX ipv6 */
   /* XXXX ipv6 */
-  prev = router_get_my_routerinfo()->addr;
+  prev = my_ri->addr;
   if (resolve_my_address(LOG_INFO, options, &cur, &method, &hostname) < 0) {
   if (resolve_my_address(LOG_INFO, options, &cur, &method, &hostname) < 0) {
     log_info(LD_CONFIG,"options->Address didn't resolve into an IP.");
     log_info(LD_CONFIG,"options->Address didn't resolve into an IP.");
     return;
     return;

+ 3 - 0
src/rust/protover/errors.rs

@@ -18,6 +18,7 @@ pub enum ProtoverError {
     ExceedsExpansionLimit,
     ExceedsExpansionLimit,
     UnknownProtocol,
     UnknownProtocol,
     ExceedsNameLimit,
     ExceedsNameLimit,
+    InvalidProtocol,
 }
 }
 
 
 /// Descriptive error messages for `ProtoverError` variants.
 /// Descriptive error messages for `ProtoverError` variants.
@@ -38,6 +39,8 @@ impl Display for ProtoverError {
                 => write!(f, "A protocol in the protover string we attempted to parse is unknown."),
                 => write!(f, "A protocol in the protover string we attempted to parse is unknown."),
             ProtoverError::ExceedsNameLimit
             ProtoverError::ExceedsNameLimit
                 => write!(f, "An unrecognised protocol name was too long."),
                 => write!(f, "An unrecognised protocol name was too long."),
+            ProtoverError::InvalidProtocol
+                => write!(f, "A protocol name includes invalid characters."),
         }
         }
     }
     }
 }
 }

+ 67 - 28
src/rust/protover/protoset.rs

@@ -4,6 +4,8 @@
 
 
 //! Sets for lazily storing ordered, non-overlapping ranges of integers.
 //! Sets for lazily storing ordered, non-overlapping ranges of integers.
 
 
+use std::cmp;
+use std::iter;
 use std::slice;
 use std::slice;
 use std::str::FromStr;
 use std::str::FromStr;
 use std::u32;
 use std::u32;
@@ -174,7 +176,7 @@ impl ProtoSet {
             if low == u32::MAX || high == u32::MAX {
             if low == u32::MAX || high == u32::MAX {
                 return Err(ProtoverError::ExceedsMax);
                 return Err(ProtoverError::ExceedsMax);
             }
             }
-            if low < last_high {
+            if low <= last_high {
                 return Err(ProtoverError::Overlap);
                 return Err(ProtoverError::Overlap);
             } else if low > high {
             } else if low > high {
                 return Err(ProtoverError::LowGreaterThanHigh);
                 return Err(ProtoverError::LowGreaterThanHigh);
@@ -240,8 +242,8 @@ impl ProtoSet {
         false
         false
     }
     }
 
 
-    /// Retain only the `Version`s in this `ProtoSet` for which the predicate
-    /// `F` returns `true`.
+    /// Returns all the `Version`s in `self` which are not also in the `other`
+    /// `ProtoSet`.
     ///
     ///
     /// # Examples
     /// # Examples
     ///
     ///
@@ -250,24 +252,45 @@ impl ProtoSet {
     /// use protover::protoset::ProtoSet;
     /// use protover::protoset::ProtoSet;
     ///
     ///
     /// # fn do_test() -> Result<bool, ProtoverError> {
     /// # fn do_test() -> Result<bool, ProtoverError> {
-    /// let mut protoset: ProtoSet = "1,3-5,9".parse()?;
+    /// let protoset: ProtoSet = "1,3-6,10-12,15-16".parse()?;
+    /// let other: ProtoSet = "2,5-7,9-11,14-20".parse()?;
     ///
     ///
-    /// // Keep only versions less than or equal to 8:
-    /// protoset.retain(|x| x <= &8);
+    /// let subset: ProtoSet = protoset.and_not_in(&other);
     ///
     ///
-    /// assert_eq!(protoset.expand(), vec![1, 3, 4, 5]);
+    /// assert_eq!(subset.expand(), vec![1, 3, 4, 12]);
     /// #
     /// #
     /// # Ok(true)
     /// # Ok(true)
     /// # }
     /// # }
     /// # fn main() { do_test(); }  // wrap the test so we can use the ? operator
     /// # fn main() { do_test(); }  // wrap the test so we can use the ? operator
     /// ```
     /// ```
-    // XXX we could probably do something more efficient here. —isis
-    pub fn retain<F>(&mut self, f: F)
-        where F: FnMut(&Version) -> bool
-    {
-        let mut expanded: Vec<Version> = self.clone().expand();
-        expanded.retain(f);
-        *self = expanded.into();
+    pub fn and_not_in(&self, other: &Self) -> Self {
+        if self.is_empty() || other.is_empty() {
+            return self.clone();
+        }
+
+        let pairs = self.iter().flat_map(|&(lo, hi)| {
+            let the_end = (hi + 1, hi + 1); // special case to mark the end of the range.
+            let excluded_ranges = other
+                .iter()
+                .cloned() // have to be owned tuples, to match iter::once(the_end).
+                .skip_while(move|&(_, hi2)| hi2 < lo) // skip the non-overlapping ranges.
+                .take_while(move|&(lo2, _)| lo2 <= hi) // take all the overlapping ones.
+                .chain(iter::once(the_end));
+
+            let mut nextlo = lo;
+            excluded_ranges.filter_map(move |(excluded_lo, excluded_hi)| {
+                let pair = if nextlo < excluded_lo {
+                    Some((nextlo, excluded_lo - 1))
+                } else {
+                    None
+                };
+                nextlo = cmp::min(excluded_hi, u32::MAX - 1) + 1;
+                pair
+            })
+        });
+
+        let pairs = pairs.collect();
+        ProtoSet::is_ok(ProtoSet{ pairs }).expect("should be already sorted")
     }
     }
 }
 }
 
 
@@ -340,15 +363,13 @@ impl FromStr for ProtoSet {
     /// ```
     /// ```
     fn from_str(version_string: &str) -> Result<Self, Self::Err> {
     fn from_str(version_string: &str) -> Result<Self, Self::Err> {
         let mut pairs: Vec<(Version, Version)> = Vec::new();
         let mut pairs: Vec<(Version, Version)> = Vec::new();
-        let pieces: ::std::str::Split<char> = version_string.trim().split(',');
-
-        for piece in pieces {
-            let p: &str = piece.trim();
+        let pieces: ::std::str::Split<char> = version_string.split(',');
 
 
+        for p in pieces {
             if p.is_empty() {
             if p.is_empty() {
                 continue;
                 continue;
             } else if p.contains('-') {
             } else if p.contains('-') {
-                let mut pair = p.split('-');
+                let mut pair = p.splitn(2, '-');
 
 
                 let low  = pair.next().ok_or(ProtoverError::Unparseable)?;
                 let low  = pair.next().ok_or(ProtoverError::Unparseable)?;
                 let high = pair.next().ok_or(ProtoverError::Unparseable)?;
                 let high = pair.next().ok_or(ProtoverError::Unparseable)?;
@@ -369,7 +390,7 @@ impl FromStr for ProtoSet {
                 pairs.push((v, v));
                 pairs.push((v, v));
             }
             }
         }
         }
-        // If we were passed in an empty string, or a bunch of whitespace, or
+        // If we were passed in an empty string, or
         // simply a comma, or a pile of commas, then return an empty ProtoSet.
         // simply a comma, or a pile of commas, then return an empty ProtoSet.
         if pairs.len() == 0 {
         if pairs.len() == 0 {
             return Ok(ProtoSet::default());
             return Ok(ProtoSet::default());
@@ -522,7 +543,6 @@ mod test {
         test_protoset_contains_versions!(&[1], "1");
         test_protoset_contains_versions!(&[1], "1");
         test_protoset_contains_versions!(&[1, 2], "1,2");
         test_protoset_contains_versions!(&[1, 2], "1,2");
         test_protoset_contains_versions!(&[1, 2, 3], "1-3");
         test_protoset_contains_versions!(&[1, 2, 3], "1-3");
-        test_protoset_contains_versions!(&[0, 1], "0-1");
         test_protoset_contains_versions!(&[1, 2, 5], "1-2,5");
         test_protoset_contains_versions!(&[1, 2, 5], "1-2,5");
         test_protoset_contains_versions!(&[1, 3, 4, 5], "1,3-5");
         test_protoset_contains_versions!(&[1, 3, 4, 5], "1,3-5");
         test_protoset_contains_versions!(&[42, 55, 56, 57, 58], "42,55-58");
         test_protoset_contains_versions!(&[42, 55, 56, 57, 58], "42,55-58");
@@ -538,6 +558,18 @@ mod test {
         assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("-1"));
         assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("-1"));
     }
     }
 
 
+    #[test]
+    fn test_versions_from_str_hyphens() {
+        assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("--1"));
+        assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("-1-2"));
+        assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("1--2"));
+    }
+
+    #[test]
+    fn test_versions_from_str_triple() {
+        assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("1-2-3"));
+    }
+
     #[test]
     #[test]
     fn test_versions_from_str_1exclam() {
     fn test_versions_from_str_1exclam() {
         assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("1,!"));
         assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("1,!"));
@@ -548,6 +580,13 @@ mod test {
         assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("%="));
         assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("%="));
     }
     }
 
 
+    #[test]
+    fn test_versions_from_str_whitespace() {
+        assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("1,2\n"));
+        assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("1\r,2"));
+        assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("1,\t2"));
+    }
+
     #[test]
     #[test]
     fn test_versions_from_str_overlap() {
     fn test_versions_from_str_overlap() {
         assert_eq!(Err(ProtoverError::Overlap), ProtoSet::from_str("1-3,2-4"));
         assert_eq!(Err(ProtoverError::Overlap), ProtoSet::from_str("1-3,2-4"));
@@ -570,9 +609,9 @@ mod test {
 
 
     #[test]
     #[test]
     fn test_protoset_contains() {
     fn test_protoset_contains() {
-        let protoset: ProtoSet = ProtoSet::from_slice(&[(0, 5), (7, 9), (13, 14)]).unwrap();
+        let protoset: ProtoSet = ProtoSet::from_slice(&[(1, 5), (7, 9), (13, 14)]).unwrap();
 
 
-        for x in 0..6   { assert!(protoset.contains(&x), format!("should contain {}", x)); }
+        for x in 1..6   { assert!(protoset.contains(&x), format!("should contain {}", x)); }
         for x in 7..10  { assert!(protoset.contains(&x), format!("should contain {}", x)); }
         for x in 7..10  { assert!(protoset.contains(&x), format!("should contain {}", x)); }
         for x in 13..15 { assert!(protoset.contains(&x), format!("should contain {}", x)); }
         for x in 13..15 { assert!(protoset.contains(&x), format!("should contain {}", x)); }
 
 
@@ -582,10 +621,10 @@ mod test {
     }
     }
 
 
     #[test]
     #[test]
-    fn test_protoset_contains_0_3() {
-        let protoset: ProtoSet = ProtoSet::from_slice(&[(0, 3)]).unwrap();
+    fn test_protoset_contains_1_3() {
+        let protoset: ProtoSet = ProtoSet::from_slice(&[(1, 3)]).unwrap();
 
 
-        for x in 0..4 { assert!(protoset.contains(&x), format!("should contain {}", x)); }
+        for x in 1..4 { assert!(protoset.contains(&x), format!("should contain {}", x)); }
     }
     }
 
 
     macro_rules! assert_protoset_from_vec_contains_all {
     macro_rules! assert_protoset_from_vec_contains_all {
@@ -605,8 +644,8 @@ mod test {
     }
     }
 
 
     #[test]
     #[test]
-    fn test_protoset_from_vec_0_315() {
-        assert_protoset_from_vec_contains_all!(0, 1, 2, 3, 15);
+    fn test_protoset_from_vec_1_315() {
+        assert_protoset_from_vec_contains_all!(1, 2, 3, 15);
     }
     }
 
 
     #[test]
     #[test]

+ 36 - 6
src/rust/protover/protover.rs

@@ -113,11 +113,17 @@ impl fmt::Display for UnknownProtocol {
     }
     }
 }
 }
 
 
+fn is_valid_proto(s: &str) -> bool {
+    s.chars().all(|c| c.is_ascii_alphanumeric() || c == '-')
+}
+
 impl FromStr for UnknownProtocol {
 impl FromStr for UnknownProtocol {
     type Err = ProtoverError;
     type Err = ProtoverError;
 
 
     fn from_str(s: &str) -> Result<Self, Self::Err> {
     fn from_str(s: &str) -> Result<Self, Self::Err> {
-        if s.len() <= MAX_PROTOCOL_NAME_LENGTH {
+        if !is_valid_proto(s) {
+            Err(ProtoverError::InvalidProtocol)
+        } else if s.len() <= MAX_PROTOCOL_NAME_LENGTH {
             Ok(UnknownProtocol(s.to_string()))
             Ok(UnknownProtocol(s.to_string()))
         } else {
         } else {
             Err(ProtoverError::ExceedsNameLimit)
             Err(ProtoverError::ExceedsNameLimit)
@@ -129,6 +135,9 @@ impl UnknownProtocol {
     /// Create an `UnknownProtocol`, ignoring whether or not it
     /// Create an `UnknownProtocol`, ignoring whether or not it
     /// exceeds MAX_PROTOCOL_NAME_LENGTH.
     /// exceeds MAX_PROTOCOL_NAME_LENGTH.
     fn from_str_any_len(s: &str) -> Result<Self, ProtoverError> {
     fn from_str_any_len(s: &str) -> Result<Self, ProtoverError> {
+        if !is_valid_proto(s) {
+            return Err(ProtoverError::InvalidProtocol);
+        }
         Ok(UnknownProtocol(s.to_string()))
         Ok(UnknownProtocol(s.to_string()))
     }
     }
 }
 }
@@ -356,7 +365,6 @@ impl UnvalidatedProtoEntry {
 
 
             let maybe_supported_versions: Option<&ProtoSet> = supported.get(&supported_protocol);
             let maybe_supported_versions: Option<&ProtoSet> = supported.get(&supported_protocol);
             let supported_versions: &ProtoSet;
             let supported_versions: &ProtoSet;
-            let mut unsupported_versions: ProtoSet;
 
 
             // If the protocol wasn't in the map, then we don't know about it
             // If the protocol wasn't in the map, then we don't know about it
             // and don't support any of its versions.  Add its versions to the
             // and don't support any of its versions.  Add its versions to the
@@ -369,8 +377,7 @@ impl UnvalidatedProtoEntry {
             } else {
             } else {
                 supported_versions = maybe_supported_versions.unwrap();
                 supported_versions = maybe_supported_versions.unwrap();
             }
             }
-            unsupported_versions = versions.clone();
-            unsupported_versions.retain(|x| !supported_versions.contains(x));
+            let unsupported_versions = versions.and_not_in(supported_versions);
 
 
             if !unsupported_versions.is_empty() {
             if !unsupported_versions.is_empty() {
                 unsupported.insert(protocol.clone(), unsupported_versions);
                 unsupported.insert(protocol.clone(), unsupported_versions);
@@ -777,6 +784,29 @@ mod test {
 
 
     use super::*;
     use super::*;
 
 
+    macro_rules! parse_proto {
+        ($e:expr) => {{
+            let proto: Result<UnknownProtocol, _> = $e.parse();
+            let proto2 = UnknownProtocol::from_str_any_len($e);
+            assert_eq!(proto, proto2);
+            proto
+        }};
+    }
+
+    #[test]
+    fn test_protocol_from_str() {
+        assert!(parse_proto!("Cons").is_ok());
+        assert!(parse_proto!("123").is_ok());
+        assert!(parse_proto!("1-2-3").is_ok());
+
+        let err = Err(ProtoverError::InvalidProtocol);
+        assert_eq!(err, parse_proto!("a_b_c"));
+        assert_eq!(err, parse_proto!("a b"));
+        assert_eq!(err, parse_proto!("a,"));
+        assert_eq!(err, parse_proto!("b."));
+        assert_eq!(err, parse_proto!("é"));
+    }
+
     macro_rules! assert_protoentry_is_parseable {
     macro_rules! assert_protoentry_is_parseable {
         ($e:expr) => (
         ($e:expr) => (
             let protoentry: Result<ProtoEntry, ProtoverError> = $e.parse();
             let protoentry: Result<ProtoEntry, ProtoverError> = $e.parse();
@@ -867,10 +897,10 @@ mod test {
 
 
     #[test]
     #[test]
     fn test_protoentry_all_supported_unsupported_low_version() {
     fn test_protoentry_all_supported_unsupported_low_version() {
-        let protocols: UnvalidatedProtoEntry = "Cons=0-1".parse().unwrap();
+        let protocols: UnvalidatedProtoEntry = "HSIntro=2-3".parse().unwrap();
         let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported();
         let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported();
         assert_eq!(true, unsupported.is_some());
         assert_eq!(true, unsupported.is_some());
-        assert_eq!("Cons=0", &unsupported.unwrap().to_string());
+        assert_eq!("HSIntro=2", &unsupported.unwrap().to_string());
     }
     }
 
 
     #[test]
     #[test]

+ 7 - 7
src/rust/protover/tests/protover.rs

@@ -106,10 +106,10 @@ fn protocol_all_supported_with_unsupported_versions() {
 
 
 #[test]
 #[test]
 fn protocol_all_supported_with_unsupported_low_version() {
 fn protocol_all_supported_with_unsupported_low_version() {
-    let protocols: UnvalidatedProtoEntry = "Cons=0-1".parse().unwrap();
+    let protocols: UnvalidatedProtoEntry = "HSIntro=2-3".parse().unwrap();
     let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported();
     let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported();
     assert_eq!(true, unsupported.is_some());
     assert_eq!(true, unsupported.is_some());
-    assert_eq!("Cons=0", &unsupported.unwrap().to_string());
+    assert_eq!("HSIntro=2", &unsupported.unwrap().to_string());
 }
 }
 
 
 #[test]
 #[test]
@@ -354,18 +354,18 @@ fn protover_all_supported_should_exclude_some_versions_and_entire_protocols() {
 
 
 #[test]
 #[test]
 fn protover_all_supported_should_not_dos_anyones_computer() {
 fn protover_all_supported_should_not_dos_anyones_computer() {
-    let proto: UnvalidatedProtoEntry = "Sleen=0-2147483648".parse().unwrap();
+    let proto: UnvalidatedProtoEntry = "Link=1-2147483648".parse().unwrap();
     let result: String = proto.all_supported().unwrap().to_string();
     let result: String = proto.all_supported().unwrap().to_string();
 
 
-    assert_eq!(result, "Sleen=0-2147483648".to_string());
+    assert_eq!(result, "Link=6-2147483648".to_string());
 }
 }
 
 
 #[test]
 #[test]
 fn protover_all_supported_should_not_dos_anyones_computer_max_versions() {
 fn protover_all_supported_should_not_dos_anyones_computer_max_versions() {
-    let proto: UnvalidatedProtoEntry = "Sleen=0-4294967294".parse().unwrap();
+    let proto: UnvalidatedProtoEntry = "Link=1-4294967294".parse().unwrap();
     let result: String = proto.all_supported().unwrap().to_string();
     let result: String = proto.all_supported().unwrap().to_string();
 
 
-    assert_eq!(result, "Sleen=0-4294967294".to_string());
+    assert_eq!(result, "Link=6-4294967294".to_string());
 }
 }
 
 
 #[test]
 #[test]
@@ -388,7 +388,7 @@ fn protover_unvalidatedprotoentry_should_err_entirely_unparseable_things() {
 
 
 #[test]
 #[test]
 fn protover_all_supported_over_maximum_limit() {
 fn protover_all_supported_over_maximum_limit() {
-    let proto: Result<UnvalidatedProtoEntry, ProtoverError> = "Sleen=0-4294967295".parse();
+    let proto: Result<UnvalidatedProtoEntry, ProtoverError> = "Sleen=1-4294967295".parse();
 
 
     assert_eq!(Err(ProtoverError::ExceedsMax), proto);
     assert_eq!(Err(ProtoverError::ExceedsMax), proto);
 }
 }

+ 0 - 2
src/rust/tor_rust/include.am

@@ -7,7 +7,6 @@ EXTRA_CARGO_OPTIONS=
 src/rust/target/release/@TOR_RUST_STATIC_NAME@: FORCE
 src/rust/target/release/@TOR_RUST_STATIC_NAME@: FORCE
 	( cd "$(abs_top_builddir)/src/rust" ; \
 	( cd "$(abs_top_builddir)/src/rust" ; \
 		CARGO_TARGET_DIR="$(abs_top_builddir)/src/rust/target" \
 		CARGO_TARGET_DIR="$(abs_top_builddir)/src/rust/target" \
-		CARGO_HOME="$(abs_top_builddir)/src/rust" \
 		$(CARGO) build --release $(EXTRA_CARGO_OPTIONS) \
 		$(CARGO) build --release $(EXTRA_CARGO_OPTIONS) \
 	        $(CARGO_ONLINE) \
 	        $(CARGO_ONLINE) \
                 --manifest-path "$(abs_top_srcdir)/src/rust/tor_rust/Cargo.toml" )
                 --manifest-path "$(abs_top_srcdir)/src/rust/tor_rust/Cargo.toml" )
@@ -15,7 +14,6 @@ src/rust/target/release/@TOR_RUST_STATIC_NAME@: FORCE
 distclean-rust:
 distclean-rust:
 	( cd "$(abs_top_builddir)/src/rust" ; \
 	( cd "$(abs_top_builddir)/src/rust" ; \
 		CARGO_TARGET_DIR="$(abs_top_builddir)/src/rust/target" \
 		CARGO_TARGET_DIR="$(abs_top_builddir)/src/rust/target" \
-		CARGO_HOME="$(abs_top_builddir)/src/rust" \
 		$(CARGO) clean $(EXTRA_CARGO_OPTIONS) \
 		$(CARGO) clean $(EXTRA_CARGO_OPTIONS) \
 	        $(CARGO_ONLINE) \
 	        $(CARGO_ONLINE) \
                 --manifest-path "$(abs_top_srcdir)/src/rust/tor_rust/Cargo.toml" )
                 --manifest-path "$(abs_top_srcdir)/src/rust/tor_rust/Cargo.toml" )

+ 1 - 1
src/test/include.am

@@ -48,7 +48,7 @@ TEST_CHUTNEY_FLAVORS = basic-min bridges-min hs-v2-min hs-v3-min \
 TEST_CHUTNEY_FLAVORS_IPV6 = bridges+ipv6-min ipv6-exit-min hs-v23-ipv6-md \
 TEST_CHUTNEY_FLAVORS_IPV6 = bridges+ipv6-min ipv6-exit-min hs-v23-ipv6-md \
 	single-onion-ipv6-md
 	single-onion-ipv6-md
 # only run if we can find a stable (or simply another) version of tor
 # only run if we can find a stable (or simply another) version of tor
-TEST_CHUTNEY_FLAVORS_MIXED = mixed+hs-v23
+TEST_CHUTNEY_FLAVORS_MIXED = mixed+hs-v2
 
 
 ### This is a lovely feature, but it requires automake >= 1.12, and Tor
 ### This is a lovely feature, but it requires automake >= 1.12, and Tor
 ###  doesn't require that yet.
 ###  doesn't require that yet.

+ 2 - 8
src/test/test.c

@@ -22,6 +22,8 @@
 #include <dirent.h>
 #include <dirent.h>
 #endif /* defined(_WIN32) */
 #endif /* defined(_WIN32) */
 
 
+#include <math.h>
+
 /* These macros pull in declarations for some functions and structures that
 /* These macros pull in declarations for some functions and structures that
  * are typically file-private. */
  * are typically file-private. */
 #define GEOIP_PRIVATE
 #define GEOIP_PRIVATE
@@ -31,14 +33,6 @@
 #define MAIN_PRIVATE
 #define MAIN_PRIVATE
 #define STATEFILE_PRIVATE
 #define STATEFILE_PRIVATE
 
 
-/*
- * Linux doesn't provide lround in math.h by default, but mac os does...
- * It's best just to leave math.h out of the picture entirely.
- */
-//#include <math.h>
-long int lround(double x);
-double fabs(double x);
-
 #include "or.h"
 #include "or.h"
 #include "backtrace.h"
 #include "backtrace.h"
 #include "buffers.h"
 #include "buffers.h"

+ 2 - 0
src/test/test_bt.sh

@@ -3,6 +3,8 @@
 
 
 exitcode=0
 exitcode=0
 
 
+ulimit -c 0
+
 export ASAN_OPTIONS="handle_segv=0:allow_user_segv_handler=1"
 export ASAN_OPTIONS="handle_segv=0:allow_user_segv_handler=1"
 "${builddir:-.}/src/test/test-bt-cl" backtraces || exit $?
 "${builddir:-.}/src/test/test-bt-cl" backtraces || exit $?
 "${builddir:-.}/src/test/test-bt-cl" assert 2>&1 | "${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/bt_test.py" || exitcode="$?"
 "${builddir:-.}/src/test/test-bt-cl" assert 2>&1 | "${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/bt_test.py" || exitcode="$?"

+ 18 - 13
src/test/test_config.c

@@ -5540,6 +5540,12 @@ test_config_include_opened_file_list(void *data)
 
 
   config_line_t *result = NULL;
   config_line_t *result = NULL;
   smartlist_t *opened_files = smartlist_new();
   smartlist_t *opened_files = smartlist_new();
+  char *torrcd = NULL;
+  char *subfolder = NULL;
+  char *path = NULL;
+  char *empty = NULL;
+  char *file = NULL;
+  char *dot = NULL;
   char *dir = tor_strdup(get_fname("test_include_opened_file_list"));
   char *dir = tor_strdup(get_fname("test_include_opened_file_list"));
   tt_ptr_op(dir, OP_NE, NULL);
   tt_ptr_op(dir, OP_NE, NULL);
 
 
@@ -5549,8 +5555,7 @@ test_config_include_opened_file_list(void *data)
   tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
   tt_int_op(mkdir(dir, 0700), OP_EQ, 0);
 #endif
 #endif
 
 
-  char torrcd[PATH_MAX+1];
-  tor_snprintf(torrcd, sizeof(torrcd), "%s"PATH_SEPARATOR"%s", dir, "torrc.d");
+  tor_asprintf(&torrcd, "%s"PATH_SEPARATOR"%s", dir, "torrc.d");
 
 
 #ifdef _WIN32
 #ifdef _WIN32
   tt_int_op(mkdir(torrcd), OP_EQ, 0);
   tt_int_op(mkdir(torrcd), OP_EQ, 0);
@@ -5558,9 +5563,7 @@ test_config_include_opened_file_list(void *data)
   tt_int_op(mkdir(torrcd, 0700), OP_EQ, 0);
   tt_int_op(mkdir(torrcd, 0700), OP_EQ, 0);
 #endif
 #endif
 
 
-  char subfolder[PATH_MAX+1];
-  tor_snprintf(subfolder, sizeof(subfolder), "%s"PATH_SEPARATOR"%s", torrcd,
-               "subfolder");
+  tor_asprintf(&subfolder, "%s"PATH_SEPARATOR"%s", torrcd, "subfolder");
 
 
 #ifdef _WIN32
 #ifdef _WIN32
   tt_int_op(mkdir(subfolder), OP_EQ, 0);
   tt_int_op(mkdir(subfolder), OP_EQ, 0);
@@ -5568,21 +5571,17 @@ test_config_include_opened_file_list(void *data)
   tt_int_op(mkdir(subfolder, 0700), OP_EQ, 0);
   tt_int_op(mkdir(subfolder, 0700), OP_EQ, 0);
 #endif
 #endif
 
 
-  char path[PATH_MAX+1];
-  tor_snprintf(path, sizeof(path), "%s"PATH_SEPARATOR"%s", subfolder,
+  tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", subfolder,
                "01_file_in_subfolder");
                "01_file_in_subfolder");
   tt_int_op(write_str_to_file(path, "Test 1\n", 0), OP_EQ, 0);
   tt_int_op(write_str_to_file(path, "Test 1\n", 0), OP_EQ, 0);
 
 
-  char empty[PATH_MAX+1];
-  tor_snprintf(empty, sizeof(empty), "%s"PATH_SEPARATOR"%s", torrcd, "empty");
+  tor_asprintf(&empty, "%s"PATH_SEPARATOR"%s", torrcd, "empty");
   tt_int_op(write_str_to_file(empty, "", 0), OP_EQ, 0);
   tt_int_op(write_str_to_file(empty, "", 0), OP_EQ, 0);
 
 
-  char file[PATH_MAX+1];
-  tor_snprintf(file, sizeof(file), "%s"PATH_SEPARATOR"%s", torrcd, "file");
+  tor_asprintf(&file, "%s"PATH_SEPARATOR"%s", torrcd, "file");
   tt_int_op(write_str_to_file(file, "Test 2\n", 0), OP_EQ, 0);
   tt_int_op(write_str_to_file(file, "Test 2\n", 0), OP_EQ, 0);
 
 
-  char dot[PATH_MAX+1];
-  tor_snprintf(dot, sizeof(dot), "%s"PATH_SEPARATOR"%s", torrcd, ".dot");
+  tor_asprintf(&dot, "%s"PATH_SEPARATOR"%s", torrcd, ".dot");
   tt_int_op(write_str_to_file(dot, "Test 3\n", 0), OP_EQ, 0);
   tt_int_op(write_str_to_file(dot, "Test 3\n", 0), OP_EQ, 0);
 
 
   char torrc_contents[1000];
   char torrc_contents[1000];
@@ -5609,6 +5608,12 @@ test_config_include_opened_file_list(void *data)
   SMARTLIST_FOREACH(opened_files, char *, f, tor_free(f));
   SMARTLIST_FOREACH(opened_files, char *, f, tor_free(f));
   smartlist_free(opened_files);
   smartlist_free(opened_files);
   config_free_lines(result);
   config_free_lines(result);
+  tor_free(torrcd);
+  tor_free(subfolder);
+  tor_free(path);
+  tor_free(empty);
+  tor_free(file);
+  tor_free(dot);
   tor_free(dir);
   tor_free(dir);
 }
 }
 
 

+ 52 - 1
src/test/test_dir.c

@@ -5853,6 +5853,57 @@ test_dir_networkstatus_consensus_has_ipv6(void *arg)
   UNMOCK(networkstatus_get_latest_consensus_by_flavor);
   UNMOCK(networkstatus_get_latest_consensus_by_flavor);
 }
 }
 
 
+static void
+test_dir_format_versions_list(void *arg)
+{
+  (void)arg;
+  char *s = NULL;
+  config_line_t *lines = NULL;
+
+  setup_capture_of_logs(LOG_WARN);
+  s = format_recommended_version_list(lines, 1);
+  tt_str_op(s, OP_EQ, "");
+
+  tor_free(s);
+  config_line_append(&lines, "ignored", "0.3.4.1, 0.2.9.111-alpha, 4.4.4-rc");
+  s = format_recommended_version_list(lines, 1);
+  tt_str_op(s, OP_EQ,  "0.2.9.111-alpha,0.3.4.1,4.4.4-rc");
+
+  tor_free(s);
+  config_line_append(&lines, "ignored", "0.1.2.3,0.2.9.10   ");
+  s = format_recommended_version_list(lines, 1);
+  tt_str_op(s, OP_EQ,  "0.1.2.3,0.2.9.10,0.2.9.111-alpha,0.3.4.1,4.4.4-rc");
+
+  /* There should be no warnings so far. */
+  expect_no_log_entry();
+
+  /* Now try a line with a space in it. */
+  tor_free(s);
+  config_line_append(&lines, "ignored", "1.3.3.8 1.3.3.7");
+  s = format_recommended_version_list(lines, 1);
+  tt_str_op(s, OP_EQ,  "0.1.2.3,0.2.9.10,0.2.9.111-alpha,0.3.4.1,"
+            "1.3.3.7,1.3.3.8,4.4.4-rc");
+
+  expect_single_log_msg_containing(
+          "Unexpected space in versions list member \"1.3.3.8 1.3.3.7\"." );
+
+  /* Start over, with a line containing a bogus version */
+  config_free_lines(lines);
+  lines = NULL;
+  tor_free(s);
+  mock_clean_saved_logs();
+  config_line_append(&lines, "ignored", "0.1.2.3, alpha-complex, 0.1.1.8-rc");
+  s = format_recommended_version_list(lines,1);
+  tt_str_op(s, OP_EQ, "0.1.1.8-rc,0.1.2.3,alpha-complex");
+  expect_single_log_msg_containing(
+        "Recommended version \"alpha-complex\" does not look valid.");
+
+ done:
+  tor_free(s);
+  config_free_lines(lines);
+  teardown_capture_of_logs();
+}
+
 #define DIR_LEGACY(name)                             \
 #define DIR_LEGACY(name)                             \
   { #name, test_dir_ ## name , TT_FORK, NULL, NULL }
   { #name, test_dir_ ## name , TT_FORK, NULL, NULL }
 
 
@@ -5921,6 +5972,6 @@ struct testcase_t dir_tests[] = {
   DIR(networkstatus_compute_bw_weights_v10, 0),
   DIR(networkstatus_compute_bw_weights_v10, 0),
   DIR(platform_str, 0),
   DIR(platform_str, 0),
   DIR(networkstatus_consensus_has_ipv6, TT_FORK),
   DIR(networkstatus_consensus_has_ipv6, TT_FORK),
+  DIR(format_versions_list, TT_FORK),
   END_OF_TESTCASES
   END_OF_TESTCASES
 };
 };
-

+ 6 - 0
src/test/test_entrynodes.c

@@ -1125,6 +1125,7 @@ test_entry_guard_update_from_consensus_status(void *arg)
   for (i = 0; i < 5; ++i) {
   for (i = 0; i < 5; ++i) {
     entry_guard_t *g = smartlist_get(gs->sampled_entry_guards, i);
     entry_guard_t *g = smartlist_get(gs->sampled_entry_guards, i);
     node_t *n = (node_t*) bfn_mock_node_get_by_id(g->identity);
     node_t *n = (node_t*) bfn_mock_node_get_by_id(g->identity);
+    tt_assert(n);
     n->is_possible_guard = 0;
     n->is_possible_guard = 0;
   }
   }
 
 
@@ -1163,6 +1164,7 @@ test_entry_guard_update_from_consensus_status(void *arg)
   {
   {
     entry_guard_t *g = smartlist_get(gs->sampled_entry_guards, 0);
     entry_guard_t *g = smartlist_get(gs->sampled_entry_guards, 0);
     node_t *n = (node_t*) bfn_mock_node_get_by_id(g->identity);
     node_t *n = (node_t*) bfn_mock_node_get_by_id(g->identity);
+    tt_assert(n);
     n->is_possible_guard = 1;
     n->is_possible_guard = 1;
   }
   }
   {
   {
@@ -1170,6 +1172,7 @@ test_entry_guard_update_from_consensus_status(void *arg)
      */
      */
     entry_guard_t *g = smartlist_get(gs->sampled_entry_guards, 5);
     entry_guard_t *g = smartlist_get(gs->sampled_entry_guards, 5);
     node_t *n = (node_t*) bfn_mock_node_get_by_id(g->identity);
     node_t *n = (node_t*) bfn_mock_node_get_by_id(g->identity);
+    tt_assert(n);
     smartlist_remove(big_fake_net_nodes, n);
     smartlist_remove(big_fake_net_nodes, n);
     tor_free(n->rs);
     tor_free(n->rs);
     tor_free(n->md);
     tor_free(n->md);
@@ -1228,6 +1231,7 @@ test_entry_guard_update_from_consensus_repair(void *arg)
     /* these will get a date. */
     /* these will get a date. */
     entry_guard_t *g = smartlist_get(gs->sampled_entry_guards, i);
     entry_guard_t *g = smartlist_get(gs->sampled_entry_guards, i);
     node_t *n = (node_t*) bfn_mock_node_get_by_id(g->identity);
     node_t *n = (node_t*) bfn_mock_node_get_by_id(g->identity);
+    tt_assert(n);
     n->is_possible_guard = 0;
     n->is_possible_guard = 0;
     g->currently_listed = 0;
     g->currently_listed = 0;
   }
   }
@@ -1293,6 +1297,7 @@ test_entry_guard_update_from_consensus_remove(void *arg)
   {
   {
     entry_guard_t *g = smartlist_get(gs->sampled_entry_guards, 0);
     entry_guard_t *g = smartlist_get(gs->sampled_entry_guards, 0);
     node_t *n = (node_t*) bfn_mock_node_get_by_id(g->identity);
     node_t *n = (node_t*) bfn_mock_node_get_by_id(g->identity);
+    tt_assert(n);
     n->is_possible_guard = 0;
     n->is_possible_guard = 0;
     g->currently_listed = 0;
     g->currently_listed = 0;
     g->unlisted_since_date = one_day_ago;
     g->unlisted_since_date = one_day_ago;
@@ -1302,6 +1307,7 @@ test_entry_guard_update_from_consensus_remove(void *arg)
   {
   {
     entry_guard_t *g = smartlist_get(gs->sampled_entry_guards, 1);
     entry_guard_t *g = smartlist_get(gs->sampled_entry_guards, 1);
     node_t *n = (node_t*) bfn_mock_node_get_by_id(g->identity);
     node_t *n = (node_t*) bfn_mock_node_get_by_id(g->identity);
+    tt_assert(n);
     n->is_possible_guard = 0;
     n->is_possible_guard = 0;
     g->currently_listed = 0;
     g->currently_listed = 0;
     g->unlisted_since_date = one_year_ago;
     g->unlisted_since_date = one_year_ago;

+ 2 - 2
src/test/test_hs_cell.c

@@ -38,7 +38,7 @@ test_gen_establish_intro_cell(void *arg)
      attempt to parse it. */
      attempt to parse it. */
   {
   {
     /* We only need the auth key pair here. */
     /* We only need the auth key pair here. */
-    hs_service_intro_point_t *ip = service_intro_point_new(NULL, 0);
+    hs_service_intro_point_t *ip = service_intro_point_new(NULL, 0, 0);
     /* Auth key pair is generated in the constructor so we are all set for
     /* Auth key pair is generated in the constructor so we are all set for
      * using this IP object. */
      * using this IP object. */
     ret = hs_cell_build_establish_intro(circ_nonce, ip, buf);
     ret = hs_cell_build_establish_intro(circ_nonce, ip, buf);
@@ -106,7 +106,7 @@ test_gen_establish_intro_cell_bad(void *arg)
      ed25519_sign_prefixed() function and make it fail. */
      ed25519_sign_prefixed() function and make it fail. */
   cell = trn_cell_establish_intro_new();
   cell = trn_cell_establish_intro_new();
   tt_assert(cell);
   tt_assert(cell);
-  ip = service_intro_point_new(NULL, 0);
+  ip = service_intro_point_new(NULL, 0, 0);
   cell_len = hs_cell_build_establish_intro(circ_nonce, ip, NULL);
   cell_len = hs_cell_build_establish_intro(circ_nonce, ip, NULL);
   service_intro_point_free(ip);
   service_intro_point_free(ip);
   expect_log_msg_containing("Unable to make signature for "
   expect_log_msg_containing("Unable to make signature for "

Some files were not shown because too many files changed in this diff