Compare commits

..

111 Commits

Author SHA1 Message Date
Nick Mathewson 79c56a6e31 Merge branch 'maint-0.3.3' into release-0.3.3 2018-06-08 10:12:57 -04:00
Nick Mathewson 0c9d617762 Merge branch 'maint-0.3.3' into release-0.3.3 2018-06-02 10:42:06 -07:00
Nick Mathewson db9ca07c46 Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-27 10:04:42 -04:00
Nick Mathewson c8dad04924 Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-24 09:40:06 -04:00
Nick Mathewson c11c851b39 Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-22 18:05:55 -04:00
Roger Dingledine 7dd0813e78 and put those in the release notes too 2018-05-22 16:14:39 -04:00
Roger Dingledine 6a7d650b37 0.3.1.10 and 0.2.9.15 changelogs got left out too 2018-05-22 16:13:29 -04:00
Roger Dingledine 568cb0ee8f run nickm's format_changelog.py script 2018-05-22 15:51:54 -04:00
Roger Dingledine 35956bce49 a few more changelog fixes 2018-05-22 15:47:18 -04:00
Roger Dingledine 78fcfc7bcd light cleanup, give them new blurbs 2018-05-22 15:03:00 -04:00
Roger Dingledine 37b7eadb57 include 0.3.2.10 blurbs in 0.3.3 changelogs
so they aren't mysteriously missing from the tarballs/etc
2018-05-22 14:29:26 -04:00
Roger Dingledine 00e7e324d1 remove items from 0.3.3.6 that are already in 0.3.2.10 2018-05-22 14:22:51 -04:00
Nick Mathewson 67da2d9411 Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-22 14:13:28 -04:00
Nick Mathewson 0256702362 Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-22 13:35:33 -04:00
Nick Mathewson 20f8fead9c Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-22 12:54:31 -04:00
Nick Mathewson 0b8de7b3c3 Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-22 12:40:27 -04:00
Nick Mathewson b6a88173bb add TROVE-2018-005 to changelog and releasenotes 2018-05-22 12:37:49 -04:00
Nick Mathewson f177ec2142 Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-22 12:33:54 -04:00
Nick Mathewson 2b2634339b Move bug25145 entry into ChangeLog
(It doesn't go into ReleaseNotes, since it's a bugfix on 0.3.3.2-alpha)
2018-05-22 10:20:15 -04:00
Nick Mathewson c91c4e9bb6 Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-22 08:35:41 -04:00
Nick Mathewson f15e1e65cb Write a blurb for 0.3.3.6 2018-05-21 09:28:00 -04:00
Nick Mathewson 7760162b8c 033 releasenotes: minor sorting 2018-05-21 09:16:28 -04:00
Nick Mathewson b9aa9e6012 Sort the entries in the 0.3.3.7 CL and RNs 2018-05-17 13:06:37 -04:00
Nick Mathewson 731d4dbc56 Start on releasenotes for 0.3.3.6
Here I've just concatenated the changelogs and removed the "bugfix
on 0.3.3.x" entries.
2018-05-17 13:04:56 -04:00
Nick Mathewson d0def59108 Begin work on a ChangeLog for 0.3.3.6 2018-05-17 12:59:33 -04:00
Nick Mathewson ad5b4c4085 Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-16 12:11:45 -04:00
Nick Mathewson ca63a66604 Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-15 09:32:45 -04:00
Nick Mathewson 1118536142 Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-10 09:22:32 -04:00
Nick Mathewson f36fea697e Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-10 09:19:28 -04:00
Nick Mathewson 62b224f724 Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-10 08:20:38 -04:00
Nick Mathewson ff46d08fd4 Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-09 11:53:18 -04:00
Nick Mathewson 582f784548 Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-09 08:26:08 -04:00
Roger Dingledine 6db0c006b2 Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-08 13:49:34 -04:00
Nick Mathewson 0e4f7b56a2 Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-07 13:33:19 -04:00
Nick Mathewson 40456054ea Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-03 13:38:54 -04:00
Nick Mathewson f6890422aa Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-03 13:37:37 -04:00
Nick Mathewson 8e81d329ee Merge branch 'maint-0.3.3' into release-0.3.3 2018-05-02 08:46:28 -04:00
Nick Mathewson 3a53b0c9a2 Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-27 13:26:17 -04:00
Nick Mathewson 19bed6f936 Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-25 08:01:54 -04:00
Nick Mathewson 148540c505 Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-24 10:38:37 -04:00
Nick Mathewson d8114a1f57 Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-24 10:37:36 -04:00
Nick Mathewson 08fca9414d Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-24 08:51:58 -04:00
Nick Mathewson 5807656f8f Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-23 09:24:33 -04:00
Nick Mathewson 84ff776893 Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-20 14:39:48 -04:00
Nick Mathewson d8a9c9f2c8 Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-17 10:48:18 -04:00
Nick Mathewson fb35918747 Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-17 10:45:58 -04:00
Nick Mathewson 6c4e10c936 Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-16 13:48:23 -04:00
Nick Mathewson 8ae9ed6287 Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-16 10:06:21 -04:00
Nick Mathewson d17ddb8393 Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-15 15:41:24 -04:00
Nick Mathewson 81d71f0d41 More small changelog edits 2018-04-15 15:10:57 -04:00
Nick Mathewson 420840434c Edit changelog for 0.3.3.5-rc 2018-04-15 13:54:21 -04:00
Nick Mathewson 1856f3e11e Begin work on 0.3.3.5-rc changelog 2018-04-14 12:23:51 -04:00
Nick Mathewson 74882c781c Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-14 12:22:00 -04:00
Nick Mathewson f95f6a4498 Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-13 13:09:15 -04:00
Nick Mathewson 50406c2720 Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-13 13:05:53 -04:00
Nick Mathewson 6963aca6ac Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-12 12:31:41 -04:00
Nick Mathewson be3d8cb176 Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-12 12:25:51 -04:00
Nick Mathewson 85db0c46eb Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-12 11:14:42 -04:00
Nick Mathewson 572077b7fd Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-11 15:38:00 -04:00
Nick Mathewson 6a0b31e5a7 Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-11 10:48:46 -04:00
Nick Mathewson 3230814d2b Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-10 14:26:32 -04:00
Nick Mathewson f467771634 Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-06 16:18:47 -04:00
Nick Mathewson 98a0498490 Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-05 12:09:00 -04:00
Nick Mathewson ad0bc6e54c Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-05 08:36:13 -04:00
Nick Mathewson 876b4b168a Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-05 08:22:34 -04:00
Nick Mathewson 8a8b4ae69b Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-05 08:21:43 -04:00
Nick Mathewson 01037c106d Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-04 08:57:24 -04:00
Nick Mathewson 753840a8a7 Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-03 19:03:38 -04:00
Nick Mathewson 5bdc18b2df Merge branch 'maint-0.3.3' into release-0.3.3 2018-04-02 08:51:47 -04:00
Nick Mathewson e47080a4d7 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-29 15:00:46 -04:00
Nick Mathewson 720f044a29 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-29 14:59:01 -04:00
Nick Mathewson 2f173ce442 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-29 11:24:22 -04:00
Nick Mathewson a204a919f3 add a word. 2018-03-29 10:58:08 -04:00
Nick Mathewson 7b1eda3f67 Draft changelog for 0.3.3.4-alpha. 2018-03-29 08:16:15 -04:00
Nick Mathewson 36d1250a01 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-29 08:01:55 -04:00
Nick Mathewson 2504c2d4ae Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-28 14:23:06 -04:00
Nick Mathewson e31487b4ed Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-28 08:11:46 -04:00
Nick Mathewson 08cd7a1bf2 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-28 07:50:47 -04:00
Nick Mathewson f2027d5bf8 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-27 18:25:52 -04:00
Nick Mathewson d5580d9a27 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-27 07:05:15 -04:00
Nick Mathewson 1f3e0f157c Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-26 19:47:48 -04:00
Nick Mathewson 08cc2cc692 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-26 10:32:53 -04:00
Nick Mathewson 7ebb1ba2c3 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-26 10:29:29 -04:00
Nick Mathewson a4190d44fa Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-23 17:49:29 -04:00
Nick Mathewson 7c360ee758 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-23 11:18:23 -04:00
Nick Mathewson f1a88ec11b Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-21 17:10:10 -04:00
Nick Mathewson 76d14aabd4 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-21 17:04:41 -04:00
Nick Mathewson 5b32475fb0 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-20 12:55:46 -04:00
Nick Mathewson 0aff795b78 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-20 07:59:13 -04:00
Nick Mathewson 87c7e96eaa Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-20 07:50:46 -04:00
Nick Mathewson 19421ffcf3 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-19 16:59:49 -04:00
Nick Mathewson f5f4a68610 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-19 05:42:43 -04:00
Nick Mathewson 3bda8ab0ae Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-19 05:39:56 -04:00
Nick Mathewson f5f377ecb2 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-19 05:36:06 -04:00
Nick Mathewson 5ee93047cb Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-13 11:03:08 -04:00
Nick Mathewson 504dc5a93c Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-13 10:59:30 -04:00
Nick Mathewson 09612b19c5 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-13 10:58:03 -04:00
Nick Mathewson 0456ec2153 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-13 13:44:09 +01:00
Nick Mathewson ed73b086b7 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-13 10:01:30 +01:00
Nick Mathewson 6d44cf66c7 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-03 11:59:27 -05:00
Nick Mathewson ac93889ee8 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-03 11:53:05 -05:00
Nick Mathewson 2a20f8e51a Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-03 11:34:10 -05:00
Nick Mathewson d15a7a27bb final (?) changelog tweaks 2018-03-03 07:48:53 -05:00
Nick Mathewson 5c6b706c61 Add a changelog entry for 25250. 2018-03-01 16:52:44 -05:00
Nick Mathewson 10206b25d3 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-01 16:44:31 -05:00
Nick Mathewson 1bc35c59fb Draft changelog for 0.3.3.3-alpha 2018-03-01 16:41:56 -05:00
Nick Mathewson bffa158414 Merge branch 'maint-0.3.3' into release-0.3.3 2018-03-01 16:10:47 -05:00
Nick Mathewson c0c487073a defer the mystery date to thu or fri. 2018-02-27 18:39:08 -05:00
Roger Dingledine dc603be908 tiny tweaks to upcoming 0.3.3.3 changelog 2018-02-27 17:21:10 -05:00
Nick Mathewson 7d3d9a4fac light editing for 0.3.3.3-alpha changelog 2018-02-22 10:20:28 -05:00
Nick Mathewson 2286c92803 Start an 0.3.3.3-alpha changelog 2018-02-22 09:24:47 -05:00
299 changed files with 7802 additions and 14221 deletions

View File

@ -1,62 +0,0 @@
version: 1.0.{build}
clone_depth: 50
environment:
compiler: mingw
matrix:
- target: i686-w64-mingw32
compiler_path: mingw32
openssl_path: /c/OpenSSL-Win32
- target: x86_64-w64-mingw32
compiler_path: mingw64
openssl_path: /c/OpenSSL-Win64
install:
- ps: >-
Function Execute-Command ($commandPath)
{
& $commandPath $args 2>&1
if ( $LastExitCode -ne 0 ) {
$host.SetShouldExit( $LastExitCode )
}
}
Function Execute-Bash ()
{
Execute-Command 'c:\msys64\usr\bin\bash' '-e' '-c' $args
}
Execute-Command "C:\msys64\usr\bin\pacman" -Sy --noconfirm openssl-devel openssl libevent-devel libevent mingw-w64-i686-libevent mingw-w64-x86_64-libevent mingw-w64-i686-openssl mingw-w64-x86_64-openssl mingw-w64-i686-zstd mingw-w64-x86_64-zstd
build_script:
- ps: >-
if ($env:compiler -eq "mingw") {
$oldpath = ${env:Path} -split ';'
$buildpath = @("C:\msys64\${env:compiler_path}\bin", "C:\msys64\usr\bin") + $oldpath
$env:Path = @($buildpath) -join ';'
$env:build = @("${env:APPVEYOR_BUILD_FOLDER}", $env:target) -join '\'
Set-Location "${env:APPVEYOR_BUILD_FOLDER}"
Execute-Bash 'autoreconf -i'
mkdir "${env:build}"
Set-Location "${env:build}"
Execute-Bash "../configure --prefix=/${env:compiler_path} --build=${env:target} --host=${env:target} --disable-asciidoc --enable-fatal-warnings --with-openssl-dir=${env:openssl_path}"
Execute-Bash "V=1 make -j2"
Execute-Bash "V=1 make -j2 install"
}
test_script:
- ps: >-
if ($env:compiler -eq "mingw") {
$oldpath = ${env:Path} -split ';'
$buildpath = @("C:\msys64\${env:compiler_path}\bin") + $oldpath
$env:Path = $buildpath -join ';'
Set-Location "${env:build}"
Execute-Bash "VERBOSE=1 make -j2 check"
}
on_success:
- cmd: C:\Python27\python.exe %APPVEYOR_BUILD_FOLDER%\scripts\test\appveyor-irc-notify.py irc.oftc.net:6697 tor-ci success
on_failure:
- cmd: C:\Python27\python.exe %APPVEYOR_BUILD_FOLDER%\scripts\test\appveyor-irc-notify.py irc.oftc.net:6697 tor-ci failure

View File

@ -106,8 +106,6 @@ matrix:
env: DISTCHECK="yes" RUST_OPTIONS=""
- compiler: gcc
env: DISTCHECK="yes" RUST_OPTIONS="--enable-rust --enable-cargo-online-mode"
- compiler: gcc
env: MODULES_OPTIONS="--disable-module-dirauth"
## 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
@ -120,9 +118,6 @@ matrix:
- compiler: clang
sudo: required
env: RUST_OPTIONS=""
- compiler: clang
sudo: required
env: MODULES_OPTIONS="--disable-module-dirauth"
before_install:
## If we're on OSX, homebrew usually needs to updated first
@ -153,7 +148,7 @@ install:
script:
- ./autogen.sh
- ./configure $RUST_OPTIONS $COVERAGE_OPTIONS $MODULES_OPTIONS --disable-asciidoc --enable-fatal-warnings --disable-silent-rules --enable-fragile-hardening
- ./configure $RUST_OPTIONS $COVERAGE_OPTIONS --disable-asciidoc --enable-fatal-warnings --disable-silent-rules --enable-fragile-hardening
## We run `make check` because that's what https://jenkins.torproject.org does.
- if [[ "$DISTCHECK" == "" ]]; then make check; fi
- if [[ "$DISTCHECK" != "" ]]; then make distcheck DISTCHECK_CONFIGURE_FLAGS="$RUST_OPTIONS $COVERAGE_OPTIONS --disable-asciidoc --enable-fatal-warnings --disable-silent-rules --enable-fragile-hardening"; fi

View File

@ -1,39 +0,0 @@
Contributing to Tor
-------------------
### Getting started
Welcome!
We have a bunch of documentation about how to develop Tor in the
doc/HACKING/ directory. We recommend that you start with
doc/HACKING/README.1st.md , and then go from there. It will tell
you how to find your way around the source code, how to get
involved with the Tor community, how to write patches, and much
more!
You don't have to be a C developer to help with Tor: have a look
at https://www.torproject.org/getinvolved/volunteer !
The Tor Project is committed to fostering a inclusive community
where people feel safe to engage, share their points of view, and
participate. For the latest version of our Code of Conduct, please
see
https://gitweb.torproject.org/community/policies.git/plain/code_of_conduct.txt
### License issues
Tor is distributed under the license terms in the LICENSE -- in
brief, the "3-clause BSD license". If you send us code to
distribute with Tor, it needs to be code that we can distribute
under those terms. Please don't send us patches unless you agree
to allow this.
Some compatible licenses include:
- 3-clause BSD
- 2-clause BSD
- CC0 Public Domain Dedication

450
ChangeLog
View File

@ -97,456 +97,6 @@ Changes in version 0.3.3.6 - 2018-05-22
ticket 25857. Patch from "CTassisF".
Changes in version 0.3.4.1-alpha - 2018-05-17
Tor 0.3.4.1-alpha is the first release in the 0.3.4.x series. It
includes refactoring to begin reducing Tor's binary size and idle CPU
usage on mobile, along with prep work for new bandwidth scanners,
improvements to the experimental "vanguards" feature, and numerous
other small features and bugfixes.
o New system requirements:
- Tor no longer tries to support old operating systems without
mmap() or some local equivalent. Apparently, compilation on such
systems has been broken for some time, without anybody noticing or
complaining. Closes ticket 25398.
o Major feature (directory authority, modularization):
- The directory authority subsystem has been modularized. The code
is now located in src/or/dirauth/, and is compiled in by default.
To disable the module, the configure option
--disable-module-dirauth has been added. This module may be
disabled by default in some future release. Closes ticket 25610.
o Major features (main loop, CPU usage):
- When Tor is disabled (via DisableNetwork or via hibernation), it
no longer needs to run any per-second events. This change should
make it easier for mobile applications to disable Tor while the
device is sleeping, or Tor is not running. Closes ticket 26063.
- Tor no longer enables all of its periodic events by default.
Previously, Tor would enable all possible main loop events,
regardless of whether it needed them. Furthermore, many of these
events are now disabled with Tor is hibernating or DisableNetwork
is set. This is a big step towards reducing client CPU usage by
reducing the amount of wake-ups the daemon does. Closes ticket
25376 and 25762.
- The bandwidth-limitation logic has been refactored so that
bandwidth calculations are performed on-demand, rather than every
TokenBucketRefillInterval milliseconds. This change should improve
the granularity of our bandwidth calculations, and limit the
number of times that the Tor process needs to wake up when it is
idle. Closes ticket 25373.
- Move responsibility for many operations from a once-per-second
callback to a callback that is only scheduled as needed. Moving
this functionality has allowed us to disable the callback when
Tor's network is disabled. Once enough items are removed from our
once-per-second callback, we can eliminate it entirely to conserve
CPU when idle. The functionality removed includes: closing
connections, circuits, and channels (ticket 25932); consensus
voting (25937); flushing log callbacks (25951); honoring delayed
SIGNEWNYM requests (25949); rescanning the consensus cache
(25931); saving the state file to disk (25948); warning relay
operators about unreachable ports (25952); and keeping track of
Tor's uptime (26009).
o Major bugfixes (directory authorities, security):
- When directory authorities read a zero-byte bandwidth file, they
would previously log a warning with the contents of an
uninitialised buffer. They now log a warning about the empty file
instead. Fixes bug 26007; bugfix on 0.2.2.1-alpha.
o Major bugfixes (crash):
- Avoid a rare assertion failure in the circuit build timeout code
if we fail to allow any circuits to actually complete. Fixes bug
25733; bugfix on 0.2.2.2-alpha.
o Major bugfixes (directory authority):
- Avoid a crash when testing router reachability on a router that
could have an ed25519 ID, but which does not. Fixes bug 25415;
bugfix on 0.3.3.2-alpha.
o Major bugfixes (onion service):
- Correctly detect when onion services get disabled after HUP. Fixes
bug 25761; bugfix on 0.3.2.1.
o Major bugfixes (protover, voting):
- Revise Rust implementation of protover to use a more memory-
efficient voting algorithm and corresponding data structures, thus
avoiding a potential (but small impact) DoS attack where specially
crafted protocol strings would expand to several potential
megabytes in memory. In the process, several portions of code were
revised to be methods on new, custom types, rather than functions
taking interchangeable types, thus increasing type safety of the
module. Custom error types and handling were added as well, in
order to facilitate better error dismissal/handling in outside
crates and avoid mistakenly passing an internal error string to C
over the FFI boundary. Many tests were added, and some previous
differences between the C and Rust implementations have been
remedied. Fixes bug 24031; bugfix on 0.3.3.1-alpha.
o Major bugfixes (relay, denial of service):
- Impose a limit on circuit cell queue size. The limit can be
controlled by a consensus parameter. Fixes bug 25226; bugfix
on 0.2.4.14-alpha.
o Minor features (accounting):
- When Tor becomes dormant, it now uses a scheduled event to wake up
at the right time. Previously, we would use the per-second timer
to check whether to wake up, but we no longer have any per-second
timers enabled when the network is disabled. Closes ticket 26064.
o Minor features (code quality):
- Add optional spell-checking for the Tor codebase, using the
"misspell" program. To use this feature, run "make check-typos".
Closes ticket 25024.
o Minor features (compatibility):
- Tor now detects versions of OpenSSL 1.1.0 and later compiled with
the no-deprecated option, and builds correctly with them. Closes
tickets 19429, 19981, and 25353.
- Avoid some compilation warnings with recent versions of LibreSSL.
Closes ticket 26006.
o Minor features (compression, zstd):
- When running with zstd, Tor now considers using advanced functions
that the zstd maintainers have labeled as potentially unstable. To
prevent breakage, Tor will only use this functionality when the
runtime version of the zstd library matches the version with which
Tor was compiled. Closes ticket 25162.
o Minor features (configuration):
- The "DownloadSchedule" options have been renamed to end with
"DownloadInitialDelay". The old names are still allowed, but will
produce a warning. Comma-separated lists are still permitted for
these options, but all values after the first are ignored (as they
have been since 0.2.9). Closes ticket 23354.
o Minor features (continuous integration):
- Our .travis.yml configuration now includes support for testing the
results of "make distcheck". (It's not uncommon for "make check"
to pass but "make distcheck" to fail.) Closes ticket 25814.
- Our Travis CI configuration now integrates with the Coveralls
coverage analysis tool. Closes ticket 25818.
o Minor features (control port):
- Introduce GETINFO "current-time/{local,utc}" to return the local
and UTC times respectively in ISO format. This helps a controller
like Tor Browser detect a time-related error. Closes ticket 25511.
Patch by Neel Chauhan.
- Introduce new fields to the CIRC_BW event. There are two new
fields in each of the read and written directions. The DELIVERED
fields report the total valid data on the circuit, as measured by
the payload sizes of verified and error-checked relay command
cells. The OVERHEAD fields report the total unused bytes in each
of these cells. Closes ticket 25903.
o Minor features (directory authority):
- Directory authorities now open their key-pinning files as O_SYNC,
to limit their chances of accidentally writing partial lines.
Closes ticket 23909.
o Minor features (directory authority, forward compatibility):
- Make the lines of the measured bandwidth file able to contain
their entries in any order. Previously, the node_id entry needed
to come first. Closes ticket 26004.
o Minor features (entry guards):
- Introduce a new torrc option NumPrimaryGuards for controlling the
number of primary guards. Closes ticket 25843.
o Minor features (geoip):
- Update geoip and geoip6 to the May 1 2018 Maxmind GeoLite2 Country
database. Closes ticket 26104.
o Minor features (performance):
- Avoid a needless call to malloc() when processing an incoming
relay cell. Closes ticket 24914.
- Make our timing-wheel code run a tiny bit faster on 32-bit
platforms, by preferring 32-bit math to 64-bit. Closes
ticket 24688.
- Avoid a needless malloc()/free() pair every time we handle an ntor
handshake. Closes ticket 25150.
o Minor features (testing):
- Add a unit test for voting_schedule_get_start_of_next_interval().
Closes ticket 26014, and helps make unit test coverage
more deterministic.
- A new unittests module specifically for testing the functions in
the (new-ish) bridges.c module has been created with new
unittests, raising the code coverage percentages. Closes 25425.
- We now have improved testing for addressmap_get_virtual_address()
function. This should improve our test coverage, and make our test
coverage more deterministic. Closes ticket 25993.
o Minor features (timekeeping, circuit scheduling):
- When keeping track of how busy each circuit have been recently on
a given connection, use coarse-grained monotonic timers rather
than gettimeofday(). This change should marginally increase
accuracy and performance. Implements part of ticket 25927.
o Minor bugfixes (bandwidth management):
- Consider ourselves "low on write bandwidth" if we have exhausted
our write bandwidth some time in the last second. This was the
documented behavior before, but the actual behavior was to change
this value every TokenBucketRefillInterval. Fixes bug 25828;
bugfix on 0.2.3.5-alpha.
o Minor bugfixes (C correctness):
- Add a missing lock acquisition in the shutdown code of the control
subsystem. Fixes bug 25675; bugfix on 0.2.7.3-rc. Found by
Coverity; this is CID 1433643.
o Minor bugfixes (circuit path selection):
- Don't count path selection failures as circuit build failures.
This change 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.
o Minor bugfixes (client):
- Don't consider Tor running as a client if the ControlPort is open,
but no actual client ports are open. Fixes bug 26062; bugfix
on 0.2.9.4-alpha.
o Minor bugfixes (code style):
- Fixed multiple includes of transports.h in src/or/connection.c
Fixes bug 25261; bugfix on 0.2.5.1-alpha.
- Remove the unused variable n_possible from the function
channel_get_for_extend(). Fixes bug 25645; bugfix on 0.2.4.4-alpha
o Minor bugfixes (control interface):
- Respond with more human-readable error messages to GETINFO exit-
policy/* requests. Also, let controller know if an error is
transient (response code 551) or not (response code 552). Fixes
bug 25852; bugfix on 0.2.8.1-alpha.
o Minor bugfixes (controller):
- Make CIRC_BW event reflect the total of all data sent on a
circuit, including padding and dropped cells. Also fix a mis-
counting bug when STREAM_BW events were enabled. Fixes bug 25400;
bugfix on 0.2.5.2-alpha.
o Minor bugfixes (correctness, client):
- Upon receiving a malformed connected cell, stop processing the cell
immediately. Previously we would mark the connection for close, but
continue processing the cell as if the connection were open. Fixes bug
26072; bugfix on 0.2.4.7-alpha.
o Minor bugfixes (directory client):
- When unverified-consensus is verified, rename it to cached-
consenus. Fixes bug 4187; bugfix on 0.2.0.3-alpha.
- Fixed launching a certificate fetch always during the scheduled
periodic consensus fetch by fetching only in those cases when
consensus are waiting for certs. Fixes bug 24740; bugfix
on 0.2.9.1-alpha.
o Minor bugfixes (documentation):
- Stop saying in the manual that clients cache ipv4 dns answers from
exit relays. We haven't used them since 0.2.6.3-alpha, and in
ticket 24050 we stopped even caching them as of 0.3.2.6-alpha, but
we forgot to say so in the man page. Fixes bug 26052; bugfix
on 0.3.2.6-alpha.
o Minor bugfixes (error reporting):
- Improve tolerance for directory authorities with skewed clocks.
Previously, an authority with a clock more than 60 seconds ahead
could cause a client with a correct clock to warn that the
client's clock was behind. Now the clocks of a majority of
directory authorities have to be ahead of the client before this
warning will occur. Fixes bug 25756; bugfix on 0.2.2.25-alpha.
o Minor bugfixes (Linux seccomp2 sandbox):
- Allow the nanosleep() system call, which glibc uses to implement
sleep() and usleep(). Fixes bug 24969; bugfix on 0.2.5.1-alpha.
o Minor bugfixes (onion service):
- Fix a memory leak when a v3 onion service is configured and gets a
SIGHUP signal. Fixes bug 25901; bugfix on 0.3.2.1-alpha.
- When parsing the descriptor signature, look for the token plus an
extra white-space at the end. This is more correct but also will
allow us to support new fields that might start with "signature".
Fixes bug 26069; bugfix on 0.3.0.1-alpha.
o Minor bugfixes (path selection):
- Only select relays when they have the descriptors we prefer to use
for them. This change fixes a bug where we could select a relay
because it had _some_ descriptor, but reject it later with a
nonfatal assertion error because it didn't have the exact one we
wanted. Fixes bugs 25691 and 25692; bugfix on 0.3.3.4-alpha.
o Minor bugfixes (portability):
- Do not align mmap length, as it is not required by POSIX, and the
getpagesize function is deprecated. Fixes bug 25399; bugfix
on 0.1.1.23.
o Minor bugfixes (portability, FreeBSD):
- In have_enough_mem_for_dircache(), the variable DIRCACHE_MIN_MEM_MB
does not stringify on FreeBSD, so we switch to tor_asprintf().
Fixes bug 20887; bugfix on 0.2.8.1-alpha. Patch by Neel Chauhan.
o Minor bugfixes (relay statistics):
- When a relay is collecting internal statistics about how many
create cell requests it has seen of each type, accurately count
the requests from relays that temporarily fall out of the
consensus. (To be extra conservative, we were already ignoring
requests from clients in our counts, and we continue ignoring them
here.) Fixes bug 24910; bugfix on 0.2.4.17-rc.
o Minor bugfixes (relay, crash):
- Avoid a crash when running with DirPort set but ORPort tuned off.
Fixes a case of bug 23693; bugfix on 0.3.1.1-alpha.
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.
o Minor bugfixes (testing):
- When testing workqueue event-cancellation, make sure that we
actually cancel an event, and that cancel each event with equal
probability. (It was previously possible, though extremely
unlikely, for our event-canceling test not to cancel any events.)
Fixes bug 26008; bugfix on 0.2.6.3-alpha.
- Repeat part of the test in test_client_pick_intro() a number of
times, to give it consistent coverage. Fixes bug 25996; bugfix
on 0.3.2.1-alpha.
- Remove randomness from the hs_common/responsible_hsdirs test, so
that it always takes the same path through the function it tests.
Fixes bug 25997; bugfix on 0.3.2.1-alpha.
- Change the behavior of the "channel/outbound" test so that it
never causes a 10-second rollover for the EWMA circuitmux code.
Previously, this behavior would happen randomly, and result in
fluctuating test coverage. Fixes bug 25994; bugfix
on 0.3.3.1-alpha.
- Use X509_new() to allocate certificates that will be freed later
with X509_free(). Previously, some parts of the unit tests had
used tor_malloc_zero(), which is incorrect, and which caused test
failures on Windows when they were built with extra hardening.
Fixes bugs 25943 and 25944; bugfix on 0.2.8.1-alpha. Patch by
Marcin Cieślak.
- While running the circuit_timeout test, fix the PRNG to a
deterministic AES stream, so that the test coverage from this test
will itself be deterministic. Fixes bug 25995; bugfix
on 0.2.2.2-alpha.
o Minor bugfixes (vanguards):
- Allow the last hop in a vanguard circuit to be the same as our
first, to prevent the adversary from influencing guard node choice
by choice of last hop. Also prevent the creation of A - B - A
paths, or A - A paths, which are forbidden by relays. Fixes bug
25870; bugfix on 0.3.3.1-alpha.
o Code simplification and refactoring:
- Remove duplicate code in parse_{c,s}method_line and bootstrap
their functionalities into a single function. Fixes bug 6236;
bugfix on 0.2.3.6-alpha.
- We remove the PortForwsrding and PortForwardingHelper options,
related functions, and the port_forwarding tests. These options
were used by the now-deprecated Vidalia to help ordinary users
become Tor relays or bridges. Closes ticket 25409. Patch by
Neel Chauhan.
- In order to make the OR and dir checking function in router.c less
confusing we renamed some functions and
consider_testing_reachability() has been split into
router_should_check_reachability() and
router_do_reachability_checks(). Also we improved the documentation
in some functions. Closes ticket 18918.
- Initial work to isolate Libevent usage to a handful of modules in
our codebase, to simplify our call structure, and so that we can
more easily change event loops in the future if needed. Closes
ticket 23750.
- Introduce a function to call getsockname() and return tor_addr_t,
to save a little complexity throughout the codebase. Closes
ticket 18105.
- Make hsdir_index in node_t a hsdir_index_t rather than a pointer
as hsdir_index is always present. Also, we move hsdir_index_t into
or.h. Closes ticket 23094. Patch by Neel Chauhan.
- Merge functions used for describing nodes and suppress the
functions that do not allocate memory for the output buffer
string. NODE_DESC_BUF_LEN constant and format_node_description()
function cannot be used externally from router.c module anymore.
Closes ticket 25432. Patch by valentecaio.
- Our main loop has been simplified so that all important operations
happen inside events. Previously, some operations had to happen
outside the event loop, to prevent infinite sequences of event
activations. Closes ticket 25374.
- Put a SHA1 public key digest in hs_service_intro_point_t, and use
it in register_intro_circ() and service_intro_point_new(). This
prevents the digest from being re-calculated each time. Closes
ticket 23107. Patch by Neel Chauhan.
- Refactor token-bucket implementations to use a common backend.
Closes ticket 25766.
- Remove extern declaration of stats_n_seconds_working variable from
main, protecting its accesses with get_uptime() and reset_uptime()
functions. Closes ticket 25081, patch by “valentecaio”.
- Remove our previous logic for "cached gettimeofday()" -- our
coarse monotonic timers are fast enough for this purpose, and far
less error-prone. Implements part of ticket 25927.
- Remove the return value for fascist_firewall_choose_address_base(),
and sister functions such as fascist_firewall_choose_address_node()
and fascist_firewall_choose_address_rs(). Also, while we're here,
initialize the ap argument as leaving it uninitialized can pose a
security hazard. Closes ticket 24734. Patch by Neel Chauhan.
- Rename two fields of connection_t struct. timestamp_lastwritten is
renamed to timestamp_last_write_allowed and timestamp_lastread is
renamed to timestamp_last_read_allowed. Closes ticket 24714, patch
by "valentecaio".
- Since Tor requires C99, remove our old workaround code for libc
implementations where free(NULL) doesn't work. Closes ticket 24484.
- Use our standard rate-limiting code to deal with excessive
libevent failures, rather than the hand-rolled logic we had
before. Closes ticket 26016.
- We remove the return value of node_get_prim_orport() and
node_get_prim_dirport(), and introduce node_get_prim_orport() in
node_ipv6_or_preferred() and node_ipv6_dir_preferred() in order to
check for a null address. Closes ticket 23873. Patch by
Neel Chauhan.
- We switch to should_record_bridge_info() in
geoip_note_client_seen() and options_need_geoip_info() instead of
accessing the configuration values directly. Fixes bug 25290;
bugfix on 0.2.1.6-alpha. Patch by Neel Chauhan.
o Deprecated features:
- As we are not recommending 0.2.5 anymore, we require relays that
once had an ed25519 key associated with their RSA key to always
have that key, instead of allowing them to drop back to a version
that didn't support ed25519. This means they need to use a new RSA
key if the want to downgrade to an older version of tor without
ed25519. Closes ticket 20522.
o Documentation:
- Correct an IPv6 error in the documentation for ExitPolicy. Closes
ticket 25857. Patch from "CTassisF".
o Removed features:
- Directory authorities will no longer support voting according to
any consensus method before consensus method 25. This keeps
authorities compatible with all authorities running 0.2.9.8 and
later, and does not break any clients or relays. Implements ticket
24378 and proposal 290.
- The PortForwarding and PortForwardingHelper features have been
removed. The reasoning is, given that implementations of NAT
traversal protocols within common consumer grade routers are
frequently buggy, and that the target audience for a NAT punching
feature is a perhaps less-technically-inclined relay operator,
when the helper fails to setup traversal the problems are usually
deep, ugly, and very router specific, making them horrendously
impossible for technical support to reliable assist with, and thus
resulting in frustration all around. Unfortunately, relay
operators who would like to run relays behind NATs will need to
become more familiar with the port forwarding configurations on
their local router. Closes 25409.
- The TestingEnableTbEmptyEvent option has been removed. It was used
in testing simulations to measure how often connection buckets
were emptied, in order to improve our scheduling, but it has not
been actively used in years. Closes ticket 25760.
- The old "round-robin" circuit multiplexer (circuitmux)
implementation has been removed, along with a fairly large set of
code that existed to support it. It has not been the default
circuitmux since we introduced the "EWMA" circuitmux in 0.2.4.x,
but it still required an unreasonable amount of memory and CPU.
Closes ticket 25268.
Changes in version 0.3.3.5-rc - 2018-04-15
Tor 0.3.3.5-rc fixes various bugs in earlier versions of Tor,
including some that could affect reliability or correctness.

View File

@ -38,7 +38,6 @@ include contrib/include.am
EXTRA_DIST+= \
ChangeLog \
CONTRIBUTING \
INSTALL \
LICENSE \
Makefile.nmake \
@ -52,14 +51,14 @@ AM_ETAGSFLAGS=--regex='{c}/MOCK_IMPL([^,]+,\W*\([a-zA-Z0-9_]+\)\W*,/\1/s'
if COVERAGE_ENABLED
TEST_CFLAGS=-fno-inline -fprofile-arcs -ftest-coverage
if DISABLE_ASSERTS_IN_UNIT_TESTS
TEST_CPPFLAGS=-DTOR_UNIT_TESTS -DTOR_COVERAGE -DDISABLE_ASSERTS_IN_UNIT_TESTS @TOR_MODULES_ALL_ENABLED@
TEST_CPPFLAGS=-DTOR_UNIT_TESTS -DTOR_COVERAGE -DDISABLE_ASSERTS_IN_UNIT_TESTS
else
TEST_CPPFLAGS=-DTOR_UNIT_TESTS -DTOR_COVERAGE @TOR_MODULES_ALL_ENABLED@
TEST_CPPFLAGS=-DTOR_UNIT_TESTS -DTOR_COVERAGE
endif
TEST_NETWORK_FLAGS=--coverage --hs-multi-client 1
else
TEST_CFLAGS=
TEST_CPPFLAGS=-DTOR_UNIT_TESTS @TOR_MODULES_ALL_ENABLED@
TEST_CPPFLAGS=-DTOR_UNIT_TESTS
TEST_NETWORK_FLAGS=--hs-multi-client 1
endif
TEST_NETWORK_WARNING_FLAGS=--quiet --only-warnings
@ -218,26 +217,6 @@ check-logs:
$(top_srcdir)/scripts/maint/checkLogs.pl \
$(top_srcdir)/src/*/*.[ch] | sort -n
.PHONY: check-typos
check-typos:
@if test -x "`which misspell 2>&1;true`"; then \
echo "Checking for Typos ..."; \
(misspell \
$(top_srcdir)/src/[^e]*/*.[ch] \
$(top_srcdir)/doc \
$(top_srcdir)/contrib \
$(top_srcdir)/scripts \
$(top_srcdir)/README \
$(top_srcdir)/ChangeLog \
$(top_srcdir)/INSTALL \
$(top_srcdir)/ReleaseNotes \
$(top_srcdir)/LICENSE); \
else \
echo "Tor can use misspell to check for typos."; \
echo "It seems that you don't have misspell installed."; \
echo "You can install the latest version of misspell here: https://github.com/client9/misspell#install"; \
fi
.PHONY: check-changes
check-changes:
if USEPYTHON

View File

@ -529,7 +529,7 @@ Changes in version 0.3.3.6 - 2018-05-22
would call the Rust implementation of
protover_get_supported_protocols(). This was due to the C version
returning a static string, whereas the Rust version newly allocated
a CString to pass across the FFI boundary. Consequently, the C
a CString to pass accross the FFI boundary. Consequently, the C
code was not expecting to need to free() what it was given. Fixes
bug 25127; bugfix on 0.3.2.1-alpha.

View File

@ -1,6 +0,0 @@
o Major bugfixes (security, directory authority, denial-of-service):
- Fix a bug that could have allowed an attacker to force a
directory authority to use up all its RAM by passing it a
maliciously crafted protocol versions string. Fixes bug 25517;
bugfix on 0.2.9.4-alpha. This issue is also tracked as
TROVE-2018-005.

6
changes/bug25691_again Normal file
View File

@ -0,0 +1,6 @@
o Minor bugfixes (path selection):
- Only select relays when they have the descriptors we prefer to
use for them. This change fixes a bug where we could select
a relay because it had _some_ descriptor, but reject it later with
a nonfatal assertion error because it didn't have the exact one we
wanted. Fixes bugs 25691 and 25692; bugfix on 0.3.3.4-alpha.

View File

@ -1,3 +0,0 @@
o Minor bugfixes (onion services):
- Fix a bug that blocked the creation of ephemeral v3 onion services. Fixes
bug 25939; bugfix on 0.3.4.1-alpha.

View File

@ -1,5 +0,0 @@
o Minor bugfixes (test coverage tools):
- Update our "cov-diff" script to handle output from the latest
version of gcov, and to remove extraneous timestamp information
from its output. Fixes bugs 26101 and 26102; bugfix on
0.2.5.1-alpha.

View File

@ -1,3 +0,0 @@
o Minor bugfixes (compilation):
- Fix compilation when building with OpenSSL 1.1.0 with the
"no-deprecated" flag enabled. Fixes bug 26156; bugfix on 0.3.4.1-alpha.

View File

@ -1,4 +0,0 @@
o Minor bugfixes (control port):
- Do not count 0-length RELAY_COMMAND_DATA cells as valid data in CIRC_BW
events. Previously, such cells were counted entirely in the OVERHEAD
field. Now they are not. Fixes bug 26259; bugfix on 0.3.4.1-alpha.

View File

@ -1,4 +0,0 @@
o Documentation:
- In code comment, point the reader to the exact section
in Tor specification that specifies circuit close error
code values. Resolves ticket 25237.

View File

@ -1,4 +0,0 @@
o Minor features (continuous integration):
- Add the necessary configuration files for continuous integration
testing on Windows, via the Appveyor platform. Closes ticket 25549.
Patches from Marcin Cieślak and Isis Lovecruft.

View File

@ -4,7 +4,7 @@ dnl Copyright (c) 2007-2017, The Tor Project, Inc.
dnl See LICENSE for licensing information
AC_PREREQ([2.63])
AC_INIT([tor],[0.3.4.1-alpha-dev])
AC_INIT([tor],[0.3.3.6-dev])
AC_CONFIG_SRCDIR([src/or/main.c])
AC_CONFIG_MACRO_DIR([m4])
@ -61,8 +61,6 @@ AC_ARG_ENABLE(cargo-online-mode,
AS_HELP_STRING(--enable-cargo-online-mode, [Allow cargo to make network requests to fetch crates. For builds with rust only.]))
AC_ARG_ENABLE(restart-debugging,
AS_HELP_STRING(--enable-restart-debugging, [Build Tor with support for debugging in-process restart. Developers only.]))
AC_ARG_ENABLE(zstd-advanced-apis,
AS_HELP_STRING(--disable-zstd-advanced-apis, [Build without support for zstd's "static-only" APIs.]))
if test "x$enable_coverage" != "xyes" -a "x$enable_asserts_in_tests" = "xno" ; then
AC_MSG_ERROR([Can't disable assertions outside of coverage build])
@ -116,10 +114,6 @@ if test "$enable_restart_debugging" = "yes"; then
[Defined if we're building with support for in-process restart debugging.])
fi
if test "$enable_zstd_advanced_apis" != "no"; then
AC_DEFINE(ENABLE_ZSTD_ADVANCED_APIS, 1,
[Defined if we're going to try to use zstd's "static-only" APIs.])
fi
# systemd support
if test "x$enable_systemd" = "xno"; then
@ -230,31 +224,6 @@ if test "x$enable_android" = "xyes"; then
fi
dnl ---
dnl Tor modules options. These options are namespaced with --disable-module-XXX
dnl ---
dnl All our modules.
m4_define(MODULES, dirauth)
dnl Directory Authority module.
AC_ARG_ENABLE([module-dirauth],
AS_HELP_STRING([--disable-module-dirauth],
[Do not build tor with the dirauth module]),
[], dnl Action if-given
AC_DEFINE([HAVE_MODULE_DIRAUTH], [1],
[Compile with Directory Authority feature support]))
AM_CONDITIONAL(BUILD_MODULE_DIRAUTH, [test "x$enable_module_dirauth" != "xno"])
dnl Helper variables.
TOR_MODULES_ALL_ENABLED=
AC_DEFUN([ADD_MODULE], [
MODULE=m4_toupper($1)
TOR_MODULES_ALL_ENABLED="${TOR_MODULES_ALL_ENABLED} -DHAVE_MODULE_${MODULE}=1"
])
m4_foreach_w([module], MODULES, [ADD_MODULE([module])])
AC_SUBST(TOR_MODULES_ALL_ENABLED)
dnl check for the correct "ar" when cross-compiling.
dnl (AM_PROG_AR was new in automake 1.11.2, which we do not yet require,
dnl so kludge up a replacement for the case where it isn't there yet.)
@ -306,10 +275,7 @@ fi
AM_CONDITIONAL(USEPYTHON, [test "x$PYTHON" != "x"])
dnl List all external rust crates we depend on here. Include the version
rust_crates=" \
digest-0.7.2 \
libc-0.2.39 \
"
rust_crates="libc-0.2.39"
AC_SUBST(rust_crates)
ifdef([AC_C_FLEXIBLE_ARRAY_MEMBER], [
@ -581,7 +547,6 @@ AC_CHECK_FUNCS(
mach_approximate_time \
memmem \
memset_s \
mmap \
pipe \
pipe2 \
prctl \
@ -650,21 +615,6 @@ fi
AM_CONDITIONAL(BUILD_READPASSPHRASE_C,
test "x$ac_cv_func_readpassphrase" = "xno" && test "$bwin32" = "false")
AC_MSG_CHECKING([whether free(NULL) works])
AC_RUN_IFELSE([AC_LANG_PROGRAM([
#include <stdlib.h>
], [
char *p = NULL;
free(p);
])],
[free_null_ok=true; AC_MSG_RESULT(yes)],
[free_null_ok=false; AC_MSG_RESULT(no)],
[free_null_ok=cross; AC_MSG_RESULT(cross)])
if test "$free_null_ok" = "false"; then
AC_MSG_ERROR([Your libc implementation doesn't allow free(NULL), as required by C99.])
fi
dnl ------------------------------------------------------
dnl Where do you live, libevent? And how do we call you?
@ -816,18 +766,9 @@ AC_ARG_WITH(ssl-dir,
AC_MSG_NOTICE([Now, we'll look for OpenSSL >= 1.0.1])
TOR_SEARCH_LIBRARY(openssl, $tryssldir, [-lssl -lcrypto $TOR_LIB_GDI $TOR_LIB_WS32],
[#include <openssl/ssl.h>
char *getenv(const char *);],
[struct ssl_cipher_st;
unsigned SSL_CIPHER_get_id(const struct ssl_cipher_st *);
char *getenv(const char *);],
dnl This funny-looking test program calls getenv, so that the compiler
dnl will neither make code that call SSL_CIPHER_get_id(NULL) [producing
dnl a crash], nor optimize out the call to SSL_CIPHER_get_id().
dnl We look for SSL_cipher_get_id() because it is present in
dnl OpenSSL >=1.0.1, because it is not deprecated, and because Tor
dnl depends on it.
[if (getenv("THIS_SHOULDNT_BE_SET_X201803")) SSL_CIPHER_get_id((void *)0);], [],
[#include <openssl/ssl.h>],
[struct ssl_method_st; const struct ssl_method_st *TLSv1_1_method(void);],
[TLSv1_1_method();], [],
[/usr/local/opt/openssl /usr/local/openssl /usr/lib/openssl /usr/local/ssl /usr/lib/ssl /usr/local /opt/openssl])
dnl XXXX check for OPENSSL_VERSION_NUMBER == SSLeay()
@ -894,10 +835,6 @@ AC_CHECK_MEMBERS([SSL.state], , ,
[#include <openssl/ssl.h>
])
AC_CHECK_SIZEOF(SHA_CTX, , [AC_INCLUDES_DEFAULT()
#include <openssl/sha.h>
])
dnl Define the set of checks for KIST scheduler support.
AC_DEFUN([CHECK_KIST_SUPPORT],[
dnl KIST needs struct tcp_info and for certain members to exist.
@ -1016,16 +953,6 @@ if test "x$have_zstd" = "xyes"; then
AC_DEFINE(HAVE_ZSTD,1,[Have Zstd])
TOR_ZSTD_CFLAGS="${ZSTD_CFLAGS}"
TOR_ZSTD_LIBS="${ZSTD_LIBS}"
dnl now check for zstd functions
save_LIBS="$LIBS"
save_CFLAGS="$CFLAGS"
LIBS="$LIBS $ZSTD_LIBS"
CFLAGS="$CFLAGS $ZSTD_CFLAGS"
AC_CHECK_FUNCS(ZSTD_estimateCStreamSize \
ZSTD_estimateDCtxSize)
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
fi
AC_SUBST(TOR_ZSTD_CFLAGS)
AC_SUBST(TOR_ZSTD_LIBS)
@ -1778,6 +1705,14 @@ AC_CHECK_DECLS([mlockall], , , [
#include <sys/mman.h>
#endif])
# Some MinGW environments don't have getpagesize in unistd.h. We don't use
# AC_CHECK_FUNCS(getpagesize), because other environments rename getpagesize
# using macros
AC_CHECK_DECLS([getpagesize], , , [
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif])
# Allow user to specify an alternate syslog facility
AC_ARG_WITH(syslog-facility,
AS_HELP_STRING(--with-syslog-facility=LOG, [syslog facility to use (default=LOG_DAEMON)]),
@ -1915,12 +1850,6 @@ AC_SUBST(BUILDDIR)
AH_TEMPLATE([BUILDDIR],[tor's build directory])
AC_DEFINE_UNQUOTED(BUILDDIR,"$BUILDDIR")
if test "x$SRCDIR" = "x"; then
SRCDIR=$(cd "$srcdir"; pwd)
fi
AH_TEMPLATE([SRCDIR],[tor's sourcedir directory])
AC_DEFINE_UNQUOTED(SRCDIR,"$SRCDIR")
if test "x$CONFDIR" = "x"; then
CONFDIR=`eval echo $sysconfdir/tor`
fi

View File

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

View File

@ -42,23 +42,6 @@ If you have changed build system components:
- For example, if you have changed Makefiles, autoconf files, or anything
else that affects the build system.
License issues
==============
Tor is distributed under the license terms in the LICENSE -- in
brief, the "3-clause BSD license". If you send us code to
distribute with Tor, it needs to be code that we can distribute
under those terms. Please don't send us patches unless you agree
to allow this.
Some compatible licenses include:
- 3-clause BSD
- 2-clause BSD
- CC0 Public Domain Dedication
How we use Git branches
=======================
@ -434,4 +417,3 @@ the functions that call your function rely on it doing something, then your
function should mention that it does that something in the documentation. If
you rely on a function doing something beyond what is in its documentation,
then you should watch out, or it might do something else later.

View File

@ -324,26 +324,12 @@ Here are some additional bits of advice and rules:
}
}
3. Pass only C-compatible primitive types and bytes over the boundary
3. Pass only integer types and bytes over the boundary
Rust's C-compatible primitive types are integers and floats.
These types are declared in the [libc crate](https://doc.rust-lang.org/libc/x86_64-unknown-linux-gnu/libc/index.html#types).
Most Rust objects have different [representations](https://doc.rust-lang.org/libc/x86_64-unknown-linux-gnu/libc/index.html#types)
in C and Rust, so they can't be passed using FFI.
Tor currently uses the following Rust primitive types from libc for FFI:
* defined-size integers: `uint32_t`
* native-sized integers: `c_int`
* native-sized floats: `c_double`
* native-sized raw pointers: `* c_void`, `* c_char`, `** c_char`
TODO: C smartlist to Stringlist conversion using FFI
The only non-primitive type which may cross the FFI boundary is
The only non-integer type which may cross the FFI boundary is
bytes, e.g. `&[u8]`. This SHOULD be done on the Rust side by
passing a pointer (`*mut libc::c_char`). The length can be passed
explicitly (`libc::size_t`), or the string can be NUL-byte terminated
C string.
passing a pointer (`*mut libc::c_char`) and a length
(`libc::size_t`).
One might be tempted to do this via doing
`CString::new("blah").unwrap().into_raw()`. This has several problems:

View File

@ -4,22 +4,6 @@ Useful tools
These aren't strictly necessary for hacking on Tor, but they can help track
down bugs.
Travis CI
---------
It's CI. Looks like this: https://travis-ci.org/torproject/tor.
Runs automatically on Pull Requests sent to torproject/tor. You can set it up
for your fork to build commits outside of PRs too:
1. sign up for GitHub: https://github.com/join
2. fork https://github.com/torproject/tor:
https://help.github.com/articles/fork-a-repo/
3. follow https://docs.travis-ci.com/user/getting-started/#To-get-started-with-Travis-CI.
skip steps involving `.travis.yml` (we already have one).
Builds should show up on the web at travis-ci.com and on IRC at #tor-ci on
OFTC. If they don't, ask #tor-dev (also on OFTC).
Jenkins
-------

View File

@ -1,111 +0,0 @@
# Modules in Tor #
This document describes the build system and coding standards when writing a
module in Tor.
## What is a module? ##
In the context of the tor code base, a module is a subsystem that we can
selectively enable or disable, at `configure` time.
Currently, there is only one module:
- Directory Authority subsystem (dirauth)
It is located in its own directory in `src/or/dirauth/`. To disable it, one
need to pass `--disable-module-dirauth` at configure time. All modules are
currently enabled by default.
## Build System ##
The changes to the build system are pretty straightforward.
1. Locate in the `configure.ac` file this define: `m4_define(MODULES`. It
contains a list (white-space separated) of the module in tor. Add yours to
the list.
2. Use the `AC_ARG_ENABLE([module-dirauth]` template for your new module. We
use the "disable module" approach instead of enabling them one by one. So,
by default, tor will build all the modules.
This will define the `HAVE_MODULE_<name>` statement which can be used in
the C code to conditionally compile things for your module. And the
`BUILD_MODULE_<name>` is also defined for automake files (e.g: include.am).
3. In the `src/or/include.am` file, locate the `MODULE_DIRAUTH_SOURCES` value.
You need to create your own `_SOURCES` variable for your module and then
conditionally add the it to `LIBTOR_A_SOURCES` if you should build the
module.
It is then **very** important to add your SOURCES variable to
`src_or_libtor_testing_a_SOURCES` so the tests can build it.
4. Do the same for header files, locate `ORHEADERS +=` which always add all
headers of all modules so the symbol can be found for the module entry
points.
Finally, your module will automatically be included in the
`TOR_MODULES_ALL_ENABLED` variable which is used to build the unit tests. They
always build everything in order to tests everything.
## Coding ##
As mentioned above, a module must be isolated in its own directory (name of
the module) in `src/or/`.
There are couples of "rules" you want to follow:
* Minimize as much as you can the number of entry points into your module.
Less is always better but of course that doesn't work out for every use
case. However, it is a good thing to always keep that in mind.
* Do **not** use the `HAVE_MODULE_<name>` define outside of the module code
base. Every entry point should have a second definition if the module is
disabled. For instance:
```
#ifdef HAVE_MODULE_DIRAUTH
int sr_init(int save_to_disk);
#else /* HAVE_MODULE_DIRAUTH */
static inline int
sr_init(int save_to_disk)
{
(void) save_to_disk;
return 0;
}
#endif /* HAVE_MODULE_DIRAUTH */
```
The main reason for this approach is to avoid having conditional code
everywhere in the code base. It should be centralized as much as possible
which helps maintainability but also avoids conditional spaghetti code
making the code much more difficult to follow/understand.
* It is possible that you end up with code that needs to be used by the rest
of the code base but is still part of your module. As a good example, if you
look at `src/or/shared_random_client.c`: it contains code needed by the hidden
service subsystem but mainly related to the shared random subsystem very
specific to the dirauth module.
This is fine but try to keep it as lean as possible and never use the same
filename as the one in the module. For example, this is a bad idea and
should never be done:
- `src/or/shared_random.c`
- `src/or/dirauth/shared_random.c`
* When you include headers from the module, **always** use the full module
path in your statement. Example:
`#include "dirauth/dirvote.h"`
The main reason is that we do **not** add the module include path by default
so it needs to be specified. But also, it helps our human brain understand
which part comes from a module or not.
Even **in** the module itself, use the full include path like above.

View File

@ -34,7 +34,7 @@ new Tor release:
What about Coverity Scan?
What about clang scan-build?
What about clan scan-build?
Does 'make distcheck' complain?

View File

@ -35,15 +35,10 @@ EXTRA_DIST+= doc/asciidoc-helper.sh \
doc/TUNING \
doc/HACKING/README.1st.md \
doc/HACKING/CodingStandards.md \
doc/HACKING/CodingStandardsRust.md \
doc/HACKING/Fuzzing.md \
doc/HACKING/GettingStarted.md \
doc/HACKING/GettingStartedRust.md \
doc/HACKING/HelpfulTools.md \
doc/HACKING/HowToReview.md \
doc/HACKING/Module.md \
doc/HACKING/ReleasingTor.md \
doc/HACKING/Tracing.md \
doc/HACKING/WritingTests.md
docdir = @docdir@

View File

@ -311,9 +311,7 @@ GENERAL OPTIONS
other than controller connections, and we close (and don't reattempt)
any outbound
connections. Controllers sometimes use this option to avoid using
the network until Tor is fully configured. Tor will make still certain
network-related calls (like DNS lookups) as a part of its configuration
process, even if DisableNetwork is set. (Default: 0)
the network until Tor is fully configured. (Default: 0)
[[ConstrainedSockets]] **ConstrainedSockets** **0**|**1**::
If set, Tor will tell the kernel to attempt to shrink the buffers for all
@ -368,8 +366,7 @@ GENERAL OPTIONS
[[ControlSocket]] **ControlSocket** __Path__::
Like ControlPort, but listens on a Unix domain socket, rather than a TCP
socket. '0' disables ControlSocket. (Unix and Unix-like systems only.)
(Default: 0)
socket. '0' disables ControlSocket (Unix and Unix-like systems only.)
[[ControlSocketsGroupWritable]] **ControlSocketsGroupWritable** **0**|**1**::
If this option is set to 0, don't allow the filesystem group to read and
@ -789,15 +786,17 @@ GENERAL OPTIONS
This is useful when running on flash memory or other media that support
only a limited number of writes. (Default: 0)
[[CircuitPriorityHalflife]] **CircuitPriorityHalflife** __NUM__::
[[CircuitPriorityHalflife]] **CircuitPriorityHalflife** __NUM1__::
If this value is set, we override the default algorithm for choosing which
circuit's cell to deliver or relay next. It is delivered first to the
circuit that has the lowest weighted cell count, where cells are weighted
exponentially according to this value (in seconds). If the value is -1, it
is taken from the consensus if possible else it will fallback to the
default value of 30. Minimum: 1, Maximum: 2147483647. This can be defined
as a float value. This is an advanced option; you generally shouldn't have
to mess with it. (Default: -1)
circuit's cell to deliver or relay next. When the value is 0, we
round-robin between the active circuits on a connection, delivering one
cell from each in turn. When the value is positive, we prefer delivering
cells from whichever connection has the lowest weighted cell count, where
cells are weighted exponentially according to the supplied
CircuitPriorityHalflife value (in seconds). If this option is not set at
all, we use the behavior recommended in the current consensus
networkstatus. This is an advanced option; you generally shouldn't have
to mess with it. (Default: not set)
[[CountPrivateBandwidth]] **CountPrivateBandwidth** **0**|**1**::
If this option is set, then Tor's rate-limiting applies not only to
@ -814,9 +813,10 @@ GENERAL OPTIONS
[[NoExec]] **NoExec** **0**|**1**::
If this option is set to 1, then Tor will never launch another
executable, regardless of the settings of ClientTransportPlugin
or ServerTransportPlugin. Once this option has been set to 1,
it cannot be set back to 0 without restarting Tor. (Default: 0)
executable, regardless of the settings of PortForwardingHelper,
ClientTransportPlugin, or ServerTransportPlugin. Once this
option has been set to 1, it cannot be set back to 0 without
restarting Tor. (Default: 0)
[[Schedulers]] **Schedulers** **KIST**|**KISTLite**|**Vanilla**::
Specify the scheduler type that tor should use. The scheduler is
@ -1294,11 +1294,9 @@ The following options are useful only for clients (that is, if
2 minutes)
[[TokenBucketRefillInterval]] **TokenBucketRefillInterval** __NUM__ [**msec**|**second**]::
Set the refill delay interval of Tor's token bucket to NUM milliseconds.
NUM must be between 1 and 1000, inclusive. When Tor is out of bandwidth,
on a connection or globally, it will wait up to this long before it tries
to use that connection again.
Note that bandwidth limits are still expressed in bytes per second: this
Set the refill interval of Tor's token bucket to NUM milliseconds.
NUM must be between 1 and 1000, inclusive. Note that the configured
bandwidth limits are still expressed in bytes per second: this
option only affects the frequency with which Tor checks to see whether
previously exhausted connections may read again.
Can not be changed while tor is running. (Default: 100 msec)
@ -1355,13 +1353,6 @@ The following options are useful only for clients (that is, if
number from the guard-n-primary-guards-to-use consensus parameter, and
default to 1 if the consensus parameter isn't set. (Default: 0)
[[NumPrimaryGuards]] **NumPrimaryGuards** __NUM__::
If UseEntryGuards is set to 1, we will try to pick NUM routers for our
primary guard list, which is the set of routers we strongly prefer when
connecting to the Tor network. If NUM is 0, we try to learn the number from
the guard-n-primary-guards consensus parameter, and default to 3 if the
consensus parameter isn't set. (Default: 0)
[[NumDirectoryGuards]] **NumDirectoryGuards** __NUM__::
If UseEntryGuards is set to 1, we try to make sure we have at least NUM
routers to use as directory guards. If this option is set to 0, use the
@ -1415,7 +1406,7 @@ The following options are useful only for clients (that is, if
[[HTTPTunnelPort]] **HTTPTunnelPort** \['address':]__port__|**auto** [_isolation flags_]::
Open this port to listen for proxy connections using the "HTTP CONNECT"
protocol instead of SOCKS. Set this to
protocol instead of SOCKS. Set this to 0
0 if you don't want to allow "HTTP CONNECT" connections. Set the port
to "auto" to have Tor pick a port for you. This directive can be
specified multiple times to bind to multiple addresses/ports. See
@ -1455,7 +1446,7 @@ The following options are useful only for clients (that is, if
Set this to "default", or leave it unconfigured, to use regular IPTables
on Linux, or to use pf +rdr-to+ rules on *BSD systems. +
+
(Default: "default")
(Default: "default".)
[[NATDPort]] **NATDPort** \['address':]__port__|**auto** [_isolation flags_]::
Open this port to listen for connections from old versions of ipfw (as
@ -1591,14 +1582,6 @@ The following options are useful only for clients (that is, if
ExcludeNodes have higher priority than HSLayer2Nodes,
which means that nodes specified in ExcludeNodes will not be
picked.
+
When either this option or HSLayer3Nodes are set, the /16 subnet
and node family restrictions are removed for hidden service
circuits. Additionally, we allow the guard node to be present
as the Rend, HSDir, and IP node, and as the hop before it. This
is done to prevent the adversary from inferring information
about our guard, layer2, and layer3 node choices at later points
in the path.
+
This option is meant to be managed by a Tor controller such as
https://github.com/mikeperry-tor/vanguards that selects and
@ -1645,14 +1628,6 @@ The following options are useful only for clients (that is, if
ExcludeNodes have higher priority than HSLayer3Nodes,
which means that nodes specified in ExcludeNodes will not be
picked.
+
When either this option or HSLayer2Nodes are set, the /16 subnet
and node family restrictions are removed for hidden service
circuits. Additionally, we allow the guard node to be present
as the Rend, HSDir, and IP node, and as the hop before it. This
is done to prevent the adversary from inferring information
about our guard, layer2, and layer3 node choices at later points
in the path.
+
This option is meant to be managed by a Tor controller such as
https://github.com/mikeperry-tor/vanguards that selects and
@ -1763,31 +1738,34 @@ The following options are useful only for clients (that is, if
prevent your Tor client from bootstrapping. If this option is negative,
Tor will use a default value chosen by the directory authorities. If the
directory authorities do not choose a value, Tor will default to 0.6.
(Default: -1)
(Default: -1.)
[[ClientBootstrapConsensusAuthorityDownloadInitialDelay]] **ClientBootstrapConsensusAuthorityDownloadInitialDelay** __N__::
Initial delay in seconds for when clients should download consensuses from authorities
[[ClientBootstrapConsensusAuthorityDownloadSchedule]] **ClientBootstrapConsensusAuthorityDownloadSchedule** __N__,__N__,__...__::
Schedule for when clients should download consensuses from authorities
if they are bootstrapping (that is, they don't have a usable, reasonably
live consensus). Only used by clients fetching from a list of fallback
directory mirrors. This schedule is advanced by (potentially concurrent)
connection attempts, unlike other schedules, which are advanced by
connection failures. (Default: 6)
connection failures. (Default: 6, 11, 3600, 10800, 25200, 54000, 111600,
262800)
[[ClientBootstrapConsensusFallbackDownloadInitialDelay]] **ClientBootstrapConsensusFallbackDownloadInitialDelay** __N__::
Initial delay in seconds for when clients should download consensuses from fallback
[[ClientBootstrapConsensusFallbackDownloadSchedule]] **ClientBootstrapConsensusFallbackDownloadSchedule** __N__,__N__,__...__::
Schedule for when clients should download consensuses from fallback
directory mirrors if they are bootstrapping (that is, they don't have a
usable, reasonably live consensus). Only used by clients fetching from a
list of fallback directory mirrors. This schedule is advanced by
(potentially concurrent) connection attempts, unlike other schedules,
which are advanced by connection failures. (Default: 0)
which are advanced by connection failures. (Default: 0, 1, 4, 11, 3600,
10800, 25200, 54000, 111600, 262800)
[[ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay]] **ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay** __N__::
Initial delay in seconds for when clients should download consensuses from authorities
[[ClientBootstrapConsensusAuthorityOnlyDownloadSchedule]] **ClientBootstrapConsensusAuthorityOnlyDownloadSchedule** __N__,__N__,__...__::
Schedule for when clients should download consensuses from authorities
if they are bootstrapping (that is, they don't have a usable, reasonably
live consensus). Only used by clients which don't have or won't fetch
from a list of fallback directory mirrors. This schedule is advanced by
(potentially concurrent) connection attempts, unlike other schedules,
which are advanced by connection failures. (Default: 0)
which are advanced by connection failures. (Default: 0, 3, 7, 3600,
10800, 25200, 54000, 111600, 262800)
[[ClientBootstrapConsensusMaxInProgressTries]] **ClientBootstrapConsensusMaxInProgressTries** __NUM__::
Try this many simultaneous connections to download a consensus before
@ -1918,7 +1896,7 @@ is non-zero):
If you want to use a reduced exit policy rather than the default exit
policy, set "ReducedExitPolicy 1". If you want to _replace_ the default
exit policy with your custom exit policy, end your exit policy with either
a reject *:* or an accept *:*. Otherwise, you're _augmenting_ (prepending
a reject *:* or an accept *:*. Otherwise, youre _augmenting_ (prepending
to) the default or reduced exit policy. +
+
The default exit policy is:
@ -2081,8 +2059,6 @@ is non-zero):
[[Nickname]] **Nickname** __name__::
Set the server's nickname to \'name'. Nicknames must be between 1 and 19
characters inclusive, and must contain only the characters [a-zA-Z0-9].
If not set, **Unnamed** will be used. Relays can always be uniquely identified
by their identity fingerprints.
[[NumCPUs]] **NumCPUs** __num__::
How many processes to use at once for decrypting onionskins and other
@ -2118,6 +2094,18 @@ is non-zero):
For obvious reasons, NoAdvertise and NoListen are mutually exclusive, and
IPv4Only and IPv6Only are mutually exclusive.
[[PortForwarding]] **PortForwarding** **0**|**1**::
Attempt to automatically forward the DirPort and ORPort on a NAT router
connecting this Tor server to the Internet. If set, Tor will try both
NAT-PMP (common on Apple routers) and UPnP (common on routers from other
manufacturers). (Default: 0)
[[PortForwardingHelper]] **PortForwardingHelper** __filename__|__pathname__::
If PortForwarding is set, use this executable to configure the forwarding.
If set to a filename, the system path will be searched for the executable.
If set to a path, only the specified path will be executed.
(Default: tor-fw-helper)
[[PublishServerDescriptor]] **PublishServerDescriptor** **0**|**1**|**v3**|**bridge**,**...**::
This option specifies which descriptors Tor will publish when acting as
a relay. You can
@ -2281,8 +2269,7 @@ is non-zero):
sent and received by this relay, in addition to total cell counts.
These statistics are rounded, and omitted if traffic is low. This
information is important for load balancing decisions related to padding.
If ExtraInfoStatistics is enabled, it will be published
as a part of extra-info document. (Default: 1)
(Default: 1)
[[DirReqStatistics]] **DirReqStatistics** **0**|**1**::
Relays and bridges only.
@ -2381,11 +2368,6 @@ is non-zero):
KeywDirectory. If the option is set to 1, make the KeyDirectory readable
by the default GID. (Default: 0)
[[RephistTrackTime]] **RephistTrackTime** __N__ **seconds**|**minutes**|**hours**|**days**|**weeks**::
Tells an authority, or other node tracking node reliability and history,
that fine-grained information about nodes can be discarded when it hasn't
changed for a given amount of time. (Default: 24 hours)
DIRECTORY SERVER OPTIONS
------------------------
@ -2755,6 +2737,11 @@ on the public Tor network.
different identity. This feature is used to migrate directory authority
keys in the event of a compromise. (Default: 0)
[[RephistTrackTime]] **RephistTrackTime** __N__ **seconds**|**minutes**|**hours**|**days**|**weeks**::
Tells an authority, or other node tracking node reliability and history,
that fine-grained information about nodes can be discarded when it hasn't
changed for a given amount of time. (Default: 24 hours)
[[AuthDirHasIPv6Connectivity]] **AuthDirHasIPv6Connectivity** **0**|**1**::
Authoritative directories only. When set to 0, OR ports with an
IPv6 address are not included in the authority's votes. When set to 1,
@ -2922,9 +2909,12 @@ The following options are used for running a testing Tor network.
AssumeReachable 1
AuthDirMaxServersPerAddr 0
AuthDirMaxServersPerAuthAddr 0
ClientBootstrapConsensusAuthorityDownloadInitialDelay 0
ClientBootstrapConsensusFallbackDownloadInitialDelay 0
ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay 0
ClientBootstrapConsensusAuthorityDownloadSchedule 0, 2,
4 (for 40 seconds), 8, 16, 32, 60
ClientBootstrapConsensusFallbackDownloadSchedule 0, 1,
4 (for 40 seconds), 8, 16, 32, 60
ClientBootstrapConsensusAuthorityOnlyDownloadSchedule 0, 1,
4 (for 40 seconds), 8, 16, 32, 60
ClientDNSRejectInternalAddresses 0
ClientRejectInternalAddresses 0
CountPrivateBandwidth 1
@ -2939,16 +2929,17 @@ The following options are used for running a testing Tor network.
TestingV3AuthInitialDistDelay 20 seconds
TestingAuthDirTimeToLearnReachability 0 minutes
TestingEstimatedDescriptorPropagationTime 0 minutes
TestingServerDownloadInitialDelay 0
TestingClientDownloadInitialDelay 0
TestingServerConsensusDownloadInitialDelay 0
TestingClientConsensusDownloadInitialDelay 0
TestingBridgeDownloadInitialDelay 10
TestingBridgeBootstrapDownloadInitialDelay 0
TestingServerDownloadSchedule 0, 0, 0, 5, 10, 15, 20, 30, 60
TestingClientDownloadSchedule 0, 0, 5, 10, 15, 20, 30, 60
TestingServerConsensusDownloadSchedule 0, 0, 5, 10, 15, 20, 30, 60
TestingClientConsensusDownloadSchedule 0, 0, 5, 10, 15, 20, 30, 60
TestingBridgeDownloadSchedule 10, 30, 60
TestingBridgeBootstrapDownloadSchedule 0, 0, 5, 10, 15, 20, 30, 60
TestingClientMaxIntervalWithoutRequest 5 seconds
TestingDirConnectionMaxStall 30 seconds
TestingEnableConnBwEvent 1
TestingEnableCellStatsEvent 1
TestingEnableTbEmptyEvent 1
[[TestingV3AuthInitialVotingInterval]] **TestingV3AuthInitialVotingInterval** __N__ **minutes**|**hours**::
Like V3AuthVotingInterval, but for initial voting interval before the first
@ -2983,31 +2974,37 @@ The following options are used for running a testing Tor network.
Minimum value for the Fast flag. Overrides the ordinary minimum taken
from the consensus when TestingTorNetwork is set. (Default: 0.)
[[TestingServerDownloadInitialDelay]] **TestingServerDownloadInitialDelay** __N__::
Initial delay in seconds for when servers should download things in general. Changing this
requires that **TestingTorNetwork** is set. (Default: 0)
[[TestingServerDownloadSchedule]] **TestingServerDownloadSchedule** __N__,__N__,__...__::
Schedule for when servers should download things in general. Changing this
requires that **TestingTorNetwork** is set. (Default: 0, 0, 0, 60, 60, 120,
300, 900, 2147483647)
[[TestingClientDownloadInitialDelay]] **TestingClientDownloadInitialDelay** __N__::
Initial delay in seconds for when clients should download things in general. Changing this
requires that **TestingTorNetwork** is set. (Default: 0)
[[TestingClientDownloadSchedule]] **TestingClientDownloadSchedule** __N__,__N__,__...__::
Schedule for when clients should download things in general. Changing this
requires that **TestingTorNetwork** is set. (Default: 0, 0, 60, 300, 600,
2147483647)
[[TestingServerConsensusDownloadInitialDelay]] **TestingServerConsensusDownloadInitialDelay** __N__::
Initial delay in seconds for when servers should download consensuses. Changing this
requires that **TestingTorNetwork** is set. (Default: 0)
[[TestingServerConsensusDownloadSchedule]] **TestingServerConsensusDownloadSchedule** __N__,__N__,__...__::
Schedule for when servers should download consensuses. Changing this
requires that **TestingTorNetwork** is set. (Default: 0, 0, 60, 300, 600,
1800, 1800, 1800, 1800, 1800, 3600, 7200)
[[TestingClientConsensusDownloadInitialDelay]] **TestingClientConsensusDownloadInitialDelay** __N__::
Initial delay in seconds for when clients should download consensuses. Changing this
requires that **TestingTorNetwork** is set. (Default: 0)
[[TestingClientConsensusDownloadSchedule]] **TestingClientConsensusDownloadSchedule** __N__,__N__,__...__::
Schedule for when clients should download consensuses. Changing this
requires that **TestingTorNetwork** is set. (Default: 0, 0, 60, 300, 600,
1800, 3600, 3600, 3600, 10800, 21600, 43200)
[[TestingBridgeDownloadInitialDelay]] **TestingBridgeDownloadInitialDelay** __N__::
Initial delay in seconds for when clients should download each bridge descriptor when they
[[TestingBridgeDownloadSchedule]] **TestingBridgeDownloadSchedule** __N__,__N__,__...__::
Schedule for when clients should download each bridge descriptor when they
know that one or more of their configured bridges are running. Changing
this requires that **TestingTorNetwork** is set. (Default: 10800)
this requires that **TestingTorNetwork** is set. (Default: 10800, 25200,
54000, 111600, 262800)
[[TestingBridgeBootstrapDownloadInitialDelay]] **TestingBridgeBootstrapDownloadInitialDelay** __N__::
Initial delay in seconds for when clients should download each bridge descriptor when they
[[TestingBridgeBootstrapDownloadSchedule]] **TestingBridgeBootstrapDownloadSchedule** __N__,__N__,__...__::
Schedule for when clients should download each bridge descriptor when they
have just started, or when they can not contact any of their bridges.
Changing this requires that **TestingTorNetwork** is set. (Default: 0)
Changing this requires that **TestingTorNetwork** is set. (Default: 0, 30,
90, 600, 3600, 10800, 25200, 54000, 111600, 262800)
[[TestingClientMaxIntervalWithoutRequest]] **TestingClientMaxIntervalWithoutRequest** __N__ **seconds**|**minutes**::
When directory clients have only a few descriptors to request, they batch
@ -3080,6 +3077,11 @@ The following options are used for running a testing Tor network.
events. Changing this requires that **TestingTorNetwork** is set.
(Default: 0)
[[TestingEnableTbEmptyEvent]] **TestingEnableTbEmptyEvent** **0**|**1**::
If this option is set, then Tor controllers may register for TB_EMPTY
events. Changing this requires that **TestingTorNetwork** is set.
(Default: 0)
[[TestingMinExitFlagThreshold]] **TestingMinExitFlagThreshold** __N__ **KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
Sets a lower-bound for assigning an exit flag when running as an
authority on a testing network. Overrides the usual default lower bound

View File

@ -173,6 +173,12 @@ MAX_LIST_FILE_SIZE = 1024 * 1024
# meant that we had to rebuild the list more often. We want fallbacks to be
# stable for 2 years, so we set it to a few months.
#
# There was a bug in Tor 0.2.8.1-alpha and earlier where a relay temporarily
# submits a 0 DirPort when restarted.
# This causes OnionOO to (correctly) reset its stability timer.
# Affected relays should upgrade to Tor 0.2.9 or later, which has a fix
# for this issue.
#
# If a relay changes address or port, that's it, it's not useful any more,
# because clients can't find it
ADDRESS_AND_PORT_STABLE_DAYS = 90

View File

@ -1,192 +0,0 @@
# coding=utf8
# Copyright (C) 2015-2016 Christopher R. Wood
# Copyright (c) 2018 The Tor Project
# Copyright (c) 2018 isis agora lovecruft
#
# From: https://raw.githubusercontent.com/gridsync/gridsync/def54f8166089b733d166665fdabcad4cdc526d8/misc/irc-notify.py
# and: https://github.com/gridsync/gridsync
#
# Modified by nexB on October 2016:
# - rework the handling of environment variables.
# - made the script use functions
# - support only Appveyor loading its environment variable to craft IRC notices.
#
# Modified by isis agora lovecruft <isis@torproject.org> in 2018:
# - Make IRC server configurable.
# - Make bot IRC nick deterministic.
# - Make bot join the channel rather than sending NOTICE messages externally.
# - Fix a bug which always caused sys.exit() to be logged as a traceback.
# - Actually reset the IRC colour codes after printing.
#
# Modified by Marcin Cieślak in 2018:
# - Accept UTF-8
# - only guess github URLs
# - stop using ANSI colors
# This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software Foundation;
# either version 2 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this
# program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
# Fifth Floor, Boston, MA 02110-1301 USA.
"""Simple AppVeyor IRC notification script.
The first argument is an IRC server and port; the second is the channel. Other
arguments passed to the script will be sent as notice messages content and any
{var}-formatted environment variables will be expanded automatically, replaced
with a corresponding Appveyor environment variable value. Use commas to
delineate multiple messages.
Example:
export APPVEYOR_URL=https://ci.appveyor.com
export APPVEYOR_PROJECT_NAME=tor
export APPVEYOR_REPO_COMMIT_AUTHOR=isislovecruft
export APPVEYOR_REPO_COMMIT_TIMESTAMP=2018-04-23
export APPVEYOR_REPO_PROVIDER=gihub
export APPVEYOR_REPO_BRANCH=repo_branch
export APPVEYOR_PULL_REQUEST_TITLE=pull_request_title
export APPVEYOR_BUILD_VERSION=1
export APPVEYOR_REPO_COMMIT=22c95b72e29248dc4de9b85e590ee18f6f587de8
export APPVEYOR_REPO_COMMIT_MESSAGE="some IRC test"
export APPVEYOR_ACCOUNT_NAME=isislovecruft
export APPVEYOR_PULL_REQUEST_NUMBER=pull_request_number
export APPVEYOR_REPO_NAME=isislovecruft/tor
python ./appveyor-irc-notify.py irc.oftc.net:6697 tor-ci '{repo_name} {repo_branch} {short_commit} - {repo_commit_author}: {repo_commit_message}','Build #{build_version} passed. Details: {build_url} | Commit: {commit_url}
See also https://github.com/gridsync/gridsync/blob/master/appveyor.yml for examples
in Appveyor's YAML:
on_success:
- "python scripts/test/appveyor-irc-notify.py irc.oftc.net:6697 tor-ci success
on_failure:
- "python scripts/test/appveyor-irc-notify.py irc.oftc.net:6697 tor-ci failure
"""
from __future__ import print_function
from __future__ import absolute_import
import os
import random
import socket
import ssl
import sys
import time
def appveyor_vars():
"""
Return a dict of key value carfted from appveyor environment variables.
"""
vars = dict([
(
v.replace('APPVEYOR_', '').lower(),
os.getenv(v, '').decode('utf-8')
) for v in [
'APPVEYOR_URL',
'APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED',
'APPVEYOR_REPO_BRANCH',
'APPVEYOR_REPO_COMMIT_AUTHOR',
'APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL',
'APPVEYOR_REPO_COMMIT_TIMESTAMP',
'APPVEYOR_REPO_PROVIDER',
'APPVEYOR_PROJECT_NAME',
'APPVEYOR_PULL_REQUEST_TITLE',
'APPVEYOR_BUILD_VERSION',
'APPVEYOR_REPO_COMMIT',
'APPVEYOR_REPO_COMMIT_MESSAGE',
'APPVEYOR_ACCOUNT_NAME',
'APPVEYOR_PULL_REQUEST_NUMBER',
'APPVEYOR_REPO_NAME'
]
])
BUILD_FMT = u'{url}/project/{account_name}/{project_name}/build/{build_version}'
if vars["repo_provider"] == 'github':
COMMIT_FMT = u'https://{repo_provider}.com/{repo_name}/commit/{repo_commit}'
vars.update(commit_url=COMMIT_FMT.format(**vars))
vars.update(
build_url=BUILD_FMT.format(**vars),
short_commit=vars["repo_commit"][:7],
)
return vars
def notify():
"""
Send IRC notification
"""
apvy_vars = appveyor_vars()
server, port = sys.argv[1].rsplit(":", 1)
channel = sys.argv[2]
success = sys.argv[3] == "success"
failure = sys.argv[3] == "failure"
if success or failure:
messages = []
messages.append(u"{repo_name} {repo_branch} {short_commit} - {repo_commit_author}: {repo_commit_message}")
if success:
m = u"Build #{build_version} passed. Details: {build_url}"
if failure:
m = u"Build #{build_version} failed. Details: {build_url}"
if "commit_url" in apvy_vars:
m += " Commit: {commit_url}"
messages.append(m)
else:
messages = sys.argv[3:]
messages = ' '.join(messages)
messages = messages.decode("utf-8").split(',')
print(repr(apvy_vars))
messages = [msg.format(**apvy_vars).strip() for msg in messages]
irc_username = 'appveyor-ci'
irc_nick = irc_username
# establish connection
irc_sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
irc_sock.connect((socket.gethostbyname(server), int(port)))
irc_sock.send('NICK {0}\r\nUSER {0} * 0 :{0}\r\n'.format(irc_username).encode())
irc_sock.send('JOIN #{0}\r\n'.format(channel).encode())
irc_file = irc_sock.makefile()
while irc_file:
line = irc_file.readline()
print(line.rstrip())
response = line.split()
if response[0] == 'PING':
irc_file.send('PONG {}\r\n'.format(response[1]).encode())
elif response[1] == '433':
irc_sock.send('NICK {}\r\n'.format(irc_nick).encode())
elif response[1] == '001':
time.sleep(5)
# send notification
for msg in messages:
print(u'PRIVMSG #{} :{}'.format(channel, msg).encode("utf-8"))
irc_sock.send(u'PRIVMSG #{} :{}\r\n'.format(channel, msg).encode("utf-8"))
time.sleep(5)
return
if __name__ == '__main__':
try:
notify()
except:
import traceback
print('ERROR: Failed to send notification: \n' + traceback.format_exc())

View File

@ -10,12 +10,12 @@ DIRB="$2"
for B in $DIRB/*; do
A=$DIRA/`basename $B`
if [ -f $A ]; then
perl -pe 's/^\s*\!*\d+(\*?):/ 1$1:/; s/^([^:]+:)[\d\s]+:/$1/; s/^ *-:(Runs|Programs):.*//;' "$A" > "$A.tmp"
perl -pe 's/^\s*\!*\d+:/ 1:/; s/^([^:]+:)[\d\s]+:/$1/; s/^ *-:(Runs|Programs):.*//;' "$A" > "$A.tmp"
else
cat /dev/null > "$A.tmp"
fi
perl -pe 's/^\s*\!*\d+(\*?):/ 1$1:/; s/^([^:]+:)[\d\s]+:/$1/; s/^ *-:(Runs|Programs):.*//;' "$B" > "$B.tmp"
diff -u "$A.tmp" "$B.tmp" |perl -pe 's/^((?:\+\+\+|---)(?:.*tmp))\s+.*/$1/;'
perl -pe 's/^\s*\!*\d+:/ 1:/; s/^([^:]+:)[\d\s]+:/$1/; s/^ *-:(Runs|Programs):.*//;' "$B" > "$B.tmp"
diff -u "$A.tmp" "$B.tmp"
rm "$A.tmp" "$B.tmp"
done

View File

@ -1697,7 +1697,7 @@ get_interface_address6_via_udp_socket_hack,(int severity,
sa_family_t family,
tor_addr_t *addr))
{
struct sockaddr_storage target_addr;
struct sockaddr_storage my_addr, target_addr;
int sock=-1, r=-1;
socklen_t addr_len;
@ -1740,19 +1740,21 @@ get_interface_address6_via_udp_socket_hack,(int severity,
goto err;
}
if (tor_addr_from_getsockname(addr, sock) < 0) {
if (tor_getsockname(sock,(struct sockaddr*)&my_addr, &addr_len)) {
int e = tor_socket_errno(sock);
log_fn(severity, LD_NET, "getsockname() to determine interface failed: %s",
tor_socket_strerror(e));
goto err;
}
if (tor_addr_is_loopback(addr) || tor_addr_is_multicast(addr)) {
log_fn(severity, LD_NET, "Address that we determined via UDP socket"
" magic is unsuitable for public comms.");
} else {
r=0;
}
if (tor_addr_from_sockaddr(addr, (struct sockaddr*)&my_addr, NULL) == 0) {
if (tor_addr_is_loopback(addr) || tor_addr_is_multicast(addr)) {
log_fn(severity, LD_NET, "Address that we determined via UDP socket"
" magic is unsuitable for public comms.");
} else {
r=0;
}
}
err:
if (sock >= 0)

View File

@ -15,7 +15,7 @@
#include "address.h"
#include "compat.h"
#include "container.h"
#include "crypto_rand.h"
#include "crypto.h"
#include "util.h"
#include "siphash.h"

View File

@ -16,8 +16,8 @@
#include <ws2tcpip.h>
#endif
#include "compat_openssl.h"
#include <openssl/opensslv.h>
#include "crypto.h"
#include "crypto_openssl_mgt.h"
#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,0,0)
@ -116,11 +116,7 @@ aes_cipher_free_(aes_cnt_cipher_t *cipher_)
if (!cipher_)
return;
EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *) cipher_;
#ifdef OPENSSL_1_1_API
EVP_CIPHER_CTX_reset(cipher);
#else
EVP_CIPHER_CTX_cleanup(cipher);
#endif
EVP_CIPHER_CTX_free(cipher);
}
void

View File

@ -12,6 +12,7 @@
#ifndef TOR_BUFFERS_H
#define TOR_BUFFERS_H
#include "compat.h"
#include "compat.h"
#include "torint.h"
#include "testsupport.h"

View File

@ -100,6 +100,7 @@ SecureZeroMemory(PVOID ptr, SIZE_T cnt)
/* Only use the linux prctl; the IRIX prctl is totally different */
#include <sys/prctl.h>
#elif defined(__APPLE__)
#include <sys/types.h>
#include <sys/ptrace.h>
#endif /* defined(HAVE_SYS_PRCTL_H) && defined(__linux__) || ... */
@ -115,7 +116,7 @@ SecureZeroMemory(PVOID ptr, SIZE_T cnt)
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#ifdef HAVE_MMAP
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#ifdef HAVE_SYS_SYSLIMITS_H
@ -203,17 +204,25 @@ tor_rename(const char *path_old, const char *path_new)
sandbox_intern_string(path_new));
}
#if defined(HAVE_MMAP) || defined(RUNNING_DOXYGEN)
/* Some MinGW builds have sys/mman.h, but not the corresponding symbols.
* Other configs rename the symbols using macros (including getpagesize).
* So check for sys/mman.h and unistd.h, and a getpagesize declaration. */
#if (defined(HAVE_SYS_MMAN_H) && defined(HAVE_UNISTD_H) && \
defined(HAVE_DECL_GETPAGESIZE))
#define COMPAT_HAS_MMAN_AND_PAGESIZE
#endif
#if defined(COMPAT_HAS_MMAN_AND_PAGESIZE) || \
defined(RUNNING_DOXYGEN)
/** Try to create a memory mapping for <b>filename</b> and return it. On
* failure, return NULL. Sets errno properly, using ERANGE to mean
* "empty file". Must only be called on trusted Tor-owned files, as changing
* the underlying file's size causes unspecified behavior. */
* failure, return NULL. Sets errno properly, using ERANGE to mean
* "empty file". */
tor_mmap_t *
tor_mmap_file(const char *filename)
{
int fd; /* router file */
char *string;
int result;
int page_size, result;
tor_mmap_t *res;
size_t size, filesize;
struct stat st;
@ -242,6 +251,13 @@ tor_mmap_file(const char *filename)
return NULL;
}
size = filesize = (size_t)(st.st_size);
/*
* Should we check for weird crap like mmapping a named pipe here,
* or just wait for if (!size) below to fail?
*/
/* ensure page alignment */
page_size = getpagesize();
size += (size%page_size) ? page_size-(size%page_size) : 0;
if (st.st_size > SSIZE_T_CEILING || (off_t)size < st.st_size) {
log_warn(LD_FS, "File \"%s\" is too large. Ignoring.",filename);
@ -402,8 +418,40 @@ tor_munmap_file(tor_mmap_t *handle)
return 0;
}
#else
#error "cannot implement tor_mmap_file"
#endif /* defined(HAVE_MMAP) || ... || ... */
tor_mmap_t *
tor_mmap_file(const char *filename)
{
struct stat st;
char *res = read_file_to_str(filename, RFTS_BIN|RFTS_IGNORE_MISSING, &st);
tor_mmap_t *handle;
if (! res)
return NULL;
handle = tor_malloc_zero(sizeof(tor_mmap_t));
handle->data = res;
handle->size = st.st_size;
return handle;
}
/** Unmap the file mapped with tor_mmap_file(), and return 0 for success
* or -1 for failure.
*/
int
tor_munmap_file(tor_mmap_t *handle)
{
char *d = NULL;
if (handle == NULL)
return 0;
d = (char*)handle->data;
tor_free(d);
memwipe(handle, 0, sizeof(tor_mmap_t));
tor_free(handle);
/* Can't fail in this mmap()/munmap()-free case */
return 0;
}
#endif /* defined(COMPAT_HAS_MMAN_AND_PAGESIZE) || ... || ... */
/** Replacement for snprintf. Differs from platform snprintf in two
* ways: First, always NUL-terminates its output. Second, always
@ -1344,24 +1392,6 @@ tor_getsockname,(tor_socket_t sock, struct sockaddr *address,
return getsockname(sock, address, address_len);
}
/**
* Find the local address associated with the socket <b>sock</b>, and
* place it in *<b>addr_out</b>. Return 0 on success, -1 on failure.
*
* (As tor_getsockname, but instead places the result in a tor_addr_t.) */
int
tor_addr_from_getsockname(tor_addr_t *addr_out, tor_socket_t sock)
{
struct sockaddr_storage ss;
socklen_t ss_len = sizeof(ss);
memset(&ss, 0, sizeof(ss));
if (tor_getsockname(sock, (struct sockaddr *) &ss, &ss_len) < 0)
return -1;
return tor_addr_from_sockaddr(addr_out, (struct sockaddr *)&ss, NULL);
}
/** Turn <b>socket</b> into a nonblocking socket. Return 0 on success, -1
* on failure.
*/

View File

@ -318,12 +318,12 @@ typedef struct tor_mmap_t {
size_t size; /**< Size of the file. */
/* None of the fields below should be accessed from outside compat.c */
#ifdef HAVE_MMAP
#ifdef HAVE_SYS_MMAN_H
size_t mapping_size; /**< Size of the actual mapping. (This is this file
* size, rounded up to the nearest page.) */
#elif defined _WIN32
HANDLE mmap_handle;
#endif /* defined(HAVE_MMAP) || ... */
#endif /* defined(HAVE_SYS_MMAN_H) || ... */
} tor_mmap_t;
@ -510,8 +510,6 @@ int get_n_open_sockets(void);
MOCK_DECL(int,
tor_getsockname,(tor_socket_t socket, struct sockaddr *address,
socklen_t *address_len));
struct tor_addr_t;
int tor_addr_from_getsockname(struct tor_addr_t *addr_out, tor_socket_t sock);
#define tor_socket_send(s, buf, len, flags) send(s, buf, len, flags)
#define tor_socket_recv(s, buf, len, flags) recv(s, buf, len, flags)

View File

@ -11,7 +11,7 @@
#define COMPAT_LIBEVENT_PRIVATE
#include "compat_libevent.h"
#include "crypto_rand.h"
#include "crypto.h"
#include "util.h"
#include "torlog.h"
@ -79,43 +79,6 @@ tor_event_free_(struct event *ev)
/** Global event base for use by the main thread. */
static struct event_base *the_event_base = NULL;
/**
* @defgroup postloop post-loop event helpers
*
* If we're not careful, Libevent can susceptible to infinite event chains:
* one event can activate another, whose callback activates another, whose
* callback activates another, ad infinitum. While this is happening,
* Libevent won't be checking timeouts, socket-based events, signals, and so
* on.
*
* We solve this problem by marking some events as "post-loop". A post-loop
* event behaves like any ordinary event, but any events that _it_ activates
* cannot run until Libevent has checked for other events at least once.
*
* @{ */
/**
* An event that stops Libevent from running any more events on the current
* iteration of its loop, until it has re-checked for socket events, signal
* events, timeouts, etc.
*/
static struct event *rescan_mainloop_ev = NULL;
/**
* Callback to implement rescan_mainloop_ev: it simply exits the mainloop,
* and relies on Tor to re-enter the mainloop since no error has occurred.
*/
static void
rescan_mainloop_cb(evutil_socket_t fd, short events, void *arg)
{
(void)fd;
(void)events;
struct event_base *the_base = arg;
event_base_loopbreak(the_base);
}
/** @} */
/* This is what passes for version detection on OSX. We set
* MACOSX_KQUEUE_IS_BROKEN to true iff we're on a version of OSX before
* 10.4.0 (aka 1040). */
@ -167,15 +130,6 @@ tor_libevent_initialize(tor_libevent_cfg *torcfg)
/* LCOV_EXCL_STOP */
}
rescan_mainloop_ev = event_new(the_event_base, -1, 0,
rescan_mainloop_cb, the_event_base);
if (!rescan_mainloop_ev) {
/* LCOV_EXCL_START */
log_err(LD_GENERAL, "Unable to create rescan event: cannot continue.");
exit(1); // exit ok: libevent is broken.
/* LCOV_EXCL_STOP */
}
log_info(LD_GENERAL,
"Initialized libevent version %s using method %s. Good.",
event_get_version(), tor_libevent_get_method());
@ -253,39 +207,10 @@ periodic_timer_new(struct event_base *base,
}
timer->cb = cb;
timer->data = data;
periodic_timer_launch(timer, tv);
event_add(timer->ev, (struct timeval *)tv); /*drop const for old libevent*/
return timer;
}
/**
* Launch the timer <b>timer</b> to run at <b>tv</b> from now, and every
* <b>tv</b> thereafter.
*
* If the timer is already enabled, this function does nothing.
*/
void
periodic_timer_launch(periodic_timer_t *timer, const struct timeval *tv)
{
tor_assert(timer);
if (event_pending(timer->ev, EV_TIMEOUT, NULL))
return;
event_add(timer->ev, tv);
}
/**
* Disable the provided <b>timer</b>, but do not free it.
*
* You can reenable the same timer later with periodic_timer_launch.
*
* If the timer is already disabled, this function does nothing.
*/
void
periodic_timer_disable(periodic_timer_t *timer)
{
tor_assert(timer);
(void) event_del(timer->ev);
}
/** Stop and free a periodic timer */
void
periodic_timer_free_(periodic_timer_t *timer)
@ -296,173 +221,6 @@ periodic_timer_free_(periodic_timer_t *timer)
tor_free(timer);
}
/**
* Type used to represent events that run directly from the main loop,
* either because they are activated from elsewhere in the code, or
* because they have a simple timeout.
*
* We use this type to avoid exposing Libevent's API throughout the rest
* of the codebase.
*
* This type can't be used for all events: it doesn't handle events that
* are triggered by signals or by sockets.
*/
struct mainloop_event_t {
struct event *ev;
void (*cb)(mainloop_event_t *, void *);
void *userdata;
};
/**
* Internal: Implements mainloop event using a libevent event.
*/
static void
mainloop_event_cb(evutil_socket_t fd, short what, void *arg)
{
(void)fd;
(void)what;
mainloop_event_t *mev = arg;
mev->cb(mev, mev->userdata);
}
/**
* As mainloop_event_cb, but implements a post-loop event.
*/
static void
mainloop_event_postloop_cb(evutil_socket_t fd, short what, void *arg)
{
(void)fd;
(void)what;
/* Note that if rescan_mainloop_ev is already activated,
* event_active() will do nothing: only the first post-loop event that
* happens each time through the event loop will cause it to be
* activated.
*
* Because event_active() puts events on a FIFO queue, every event
* that is made active _after_ rescan_mainloop_ev will get its
* callback run after rescan_mainloop_cb is called -- that is, on the
* next iteration of the loop.
*/
event_active(rescan_mainloop_ev, EV_READ, 1);
mainloop_event_t *mev = arg;
mev->cb(mev, mev->userdata);
}
/**
* Helper for mainloop_event_new() and mainloop_event_postloop_new().
*/
static mainloop_event_t *
mainloop_event_new_impl(int postloop,
void (*cb)(mainloop_event_t *, void *),
void *userdata)
{
tor_assert(cb);
struct event_base *base = tor_libevent_get_base();
mainloop_event_t *mev = tor_malloc_zero(sizeof(mainloop_event_t));
mev->ev = tor_event_new(base, -1, 0,
postloop ? mainloop_event_postloop_cb : mainloop_event_cb,
mev);
tor_assert(mev->ev);
mev->cb = cb;
mev->userdata = userdata;
return mev;
}
/**
* Create and return a new mainloop_event_t to run the function <b>cb</b>.
*
* When run, the callback function will be passed the mainloop_event_t
* and <b>userdata</b> as its arguments. The <b>userdata</b> pointer
* must remain valid for as long as the mainloop_event_t event exists:
* it is your responsibility to free it.
*
* The event is not scheduled by default: Use mainloop_event_activate()
* or mainloop_event_schedule() to make it run.
*/
mainloop_event_t *
mainloop_event_new(void (*cb)(mainloop_event_t *, void *),
void *userdata)
{
return mainloop_event_new_impl(0, cb, userdata);
}
/**
* As mainloop_event_new(), but create a post-loop event.
*
* A post-loop event behaves like any ordinary event, but any events
* that _it_ activates cannot run until Libevent has checked for other
* events at least once.
*/
mainloop_event_t *
mainloop_event_postloop_new(void (*cb)(mainloop_event_t *, void *),
void *userdata)
{
return mainloop_event_new_impl(1, cb, userdata);
}
/**
* Schedule <b>event</b> to run in the main loop, immediately. If it is
* not scheduled, it will run anyway. If it is already scheduled to run
* later, it will run now instead. This function will have no effect if
* the event is already scheduled to run.
*
* This function may only be called from the main thread.
*/
void
mainloop_event_activate(mainloop_event_t *event)
{
tor_assert(event);
event_active(event->ev, EV_READ, 1);
}
/** Schedule <b>event</b> to run in the main loop, after a delay of <b>tv</b>.
*
* If the event is scheduled for a different time, cancel it and run
* after this delay instead. If the event is currently pending to run
* <em>now</b>, has no effect.
*
* Do not call this function with <b>tv</b> == NULL -- use
* mainloop_event_activate() instead.
*
* This function may only be called from the main thread.
*/
int
mainloop_event_schedule(mainloop_event_t *event, const struct timeval *tv)
{
tor_assert(event);
if (BUG(tv == NULL)) {
// LCOV_EXCL_START
mainloop_event_activate(event);
return 0;
// LCOV_EXCL_STOP
}
return event_add(event->ev, tv);
}
/** Cancel <b>event</b> if it is currently active or pending. (Do nothing if
* the event is not currently active or pending.) */
void
mainloop_event_cancel(mainloop_event_t *event)
{
if (!event)
return;
(void) event_del(event->ev);
}
/** Cancel <b>event</b> and release all storage associated with it. */
void
mainloop_event_free_(mainloop_event_t *event)
{
if (!event)
return;
tor_event_free(event->ev);
memset(event, 0xb8, sizeof(*event));
tor_free(event);
}
int
tor_init_libevent_rng(void)
{
@ -485,45 +243,56 @@ tor_init_libevent_rng(void)
void
tor_libevent_free_all(void)
{
tor_event_free(rescan_mainloop_ev);
if (the_event_base)
event_base_free(the_event_base);
the_event_base = NULL;
}
/**
* Run the event loop for the provided event_base, handling events until
* something stops it. If <b>once</b> is set, then just poll-and-run
* once, then exit. Return 0 on success, -1 if an error occurred, or 1
* if we exited because no events were pending or active.
*
* This isn't reentrant or multithreaded.
*/
int
tor_libevent_run_event_loop(struct event_base *base, int once)
{
const int flags = once ? EVLOOP_ONCE : 0;
return event_base_loop(base, flags);
}
/** Tell the event loop to exit after <b>delay</b>. If <b>delay</b> is NULL,
* instead exit after we're done running the currently active events. */
#if defined(LIBEVENT_VERSION_NUMBER) && \
LIBEVENT_VERSION_NUMBER >= V(2,1,1) && \
!defined(TOR_UNIT_TESTS)
void
tor_libevent_exit_loop_after_delay(struct event_base *base,
const struct timeval *delay)
tor_gettimeofday_cached(struct timeval *tv)
{
event_base_loopexit(base, delay);
event_base_gettimeofday_cached(the_event_base, tv);
}
/** Tell the event loop to exit after running whichever callback is currently
* active. */
void
tor_libevent_exit_loop_after_callback(struct event_base *base)
tor_gettimeofday_cache_clear(void)
{
event_base_loopbreak(base);
event_base_update_cache_time(the_event_base);
}
#else /* !(defined(LIBEVENT_VERSION_NUMBER) && ...) */
/** Cache the current hi-res time; the cache gets reset when libevent
* calls us. */
static struct timeval cached_time_hires = {0, 0};
/** Return a fairly recent view of the current time. */
void
tor_gettimeofday_cached(struct timeval *tv)
{
if (cached_time_hires.tv_sec == 0) {
tor_gettimeofday(&cached_time_hires);
}
*tv = cached_time_hires;
}
/** Reset the cached view of the current time, so that the next time we try
* to learn it, we will get an up-to-date value. */
void
tor_gettimeofday_cache_clear(void)
{
cached_time_hires.tv_sec = 0;
}
#ifdef TOR_UNIT_TESTS
/** For testing: force-update the cached time to a given value. */
void
tor_gettimeofday_cache_set(const struct timeval *tv)
{
tor_assert(tv);
memcpy(&cached_time_hires, tv, sizeof(*tv));
}
#if defined(TOR_UNIT_TESTS)
/** For testing: called post-fork to make libevent reinitialize
* kernel structures. */
void
@ -533,4 +302,5 @@ tor_libevent_postfork(void)
tor_assert(r == 0);
}
#endif /* defined(TOR_UNIT_TESTS) */
#endif /* defined(LIBEVENT_VERSION_NUMBER) && ... */

View File

@ -7,6 +7,8 @@
#include "orconfig.h"
#include "testsupport.h"
#include <event2/event.h>
void configure_libevent_logging(void);
void suppress_libevent_log_msg(const char *msg);
@ -17,9 +19,6 @@ void suppress_libevent_log_msg(const char *msg);
evdns_add_server_port_with_base(tor_libevent_get_base(), \
(sock),(tcp),(cb),(data));
struct event;
struct event_base;
void tor_event_free_(struct event *ev);
#define tor_event_free(ev) \
FREE_AND_NULL(struct event, tor_event_free_, (ev))
@ -31,24 +30,11 @@ periodic_timer_t *periodic_timer_new(struct event_base *base,
void (*cb)(periodic_timer_t *timer, void *data),
void *data);
void periodic_timer_free_(periodic_timer_t *);
void periodic_timer_launch(periodic_timer_t *, const struct timeval *tv);
void periodic_timer_disable(periodic_timer_t *);
#define periodic_timer_free(t) \
FREE_AND_NULL(periodic_timer_t, periodic_timer_free_, (t))
typedef struct mainloop_event_t mainloop_event_t;
mainloop_event_t *mainloop_event_new(void (*cb)(mainloop_event_t *, void *),
void *userdata);
mainloop_event_t * mainloop_event_postloop_new(
void (*cb)(mainloop_event_t *, void *),
void *userdata);
void mainloop_event_activate(mainloop_event_t *event);
int mainloop_event_schedule(mainloop_event_t *event,
const struct timeval *delay);
void mainloop_event_cancel(mainloop_event_t *event);
void mainloop_event_free_(mainloop_event_t *event);
#define mainloop_event_free(event) \
FREE_AND_NULL(mainloop_event_t, mainloop_event_free_, (event))
#define tor_event_base_loopexit event_base_loopexit
#define tor_event_base_loopbreak event_base_loopbreak
/** Defines a configuration for using libevent with Tor: passed as an argument
* to tor_libevent_initialize() to describe how we want to set up. */
@ -70,15 +56,13 @@ void tor_libevent_free_all(void);
int tor_init_libevent_rng(void);
void tor_gettimeofday_cached(struct timeval *tv);
void tor_gettimeofday_cache_clear(void);
#ifdef TOR_UNIT_TESTS
void tor_gettimeofday_cache_set(const struct timeval *tv);
void tor_libevent_postfork(void);
#endif
int tor_libevent_run_event_loop(struct event_base *base, int once);
void tor_libevent_exit_loop_after_delay(struct event_base *base,
const struct timeval *delay);
void tor_libevent_exit_loop_after_callback(struct event_base *base);
#ifdef COMPAT_LIBEVENT_PRIVATE
/** Macro: returns the number of a Libevent version as a 4-byte number,

View File

@ -71,8 +71,8 @@ tor_sleep_msec(int msec)
/** Set *timeval to the current time of day. On error, log and terminate.
* (Same as gettimeofday(timeval,NULL), but never returns -1.)
*/
MOCK_IMPL(void,
tor_gettimeofday, (struct timeval *timeval))
void
tor_gettimeofday(struct timeval *timeval)
{
#ifdef _WIN32
/* Epoch bias copied from perl: number of units between windows epoch and
@ -279,7 +279,6 @@ monotime_reset_ratchets_for_testing(void)
* nanoseconds.
*/
static struct mach_timebase_info mach_time_info;
static struct mach_timebase_info mach_time_info_msec_cvt;
static int monotime_shift = 0;
static void
@ -297,14 +296,6 @@ monotime_init_internal(void)
// requires that tor_log2(0) == 0.
monotime_shift = tor_log2(ms_per_tick);
}
{
// For converting ticks to milliseconds in a 32-bit-friendly way, we
// will first right-shift by 20, and then multiply by 20/19, since
// (1<<20) * 19/20 is about 1e6. We precompute a new numerate and
// denominator here to avoid multiple multiplies.
mach_time_info_msec_cvt.numer = mach_time_info.numer * 20;
mach_time_info_msec_cvt.denom = mach_time_info.denom * 19;
}
}
/**
@ -354,22 +345,6 @@ monotime_diff_nsec(const monotime_t *start,
return diff_nsec;
}
int32_t
monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
const monotime_coarse_t *end)
{
if (BUG(mach_time_info.denom == 0)) {
monotime_init();
}
const int64_t diff_ticks = end->abstime_ - start->abstime_;
/* We already require in di_ops.c that right-shift performs a sign-extend. */
const int32_t diff_microticks = (int32_t)(diff_ticks >> 20);
return (diff_microticks * mach_time_info_msec_cvt.numer) /
mach_time_info_msec_cvt.denom;
}
uint32_t
monotime_coarse_to_stamp(const monotime_coarse_t *t)
{
@ -468,15 +443,6 @@ monotime_diff_nsec(const monotime_t *start,
return diff_nsec;
}
int32_t
monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
const monotime_coarse_t *end)
{
const int32_t diff_sec = (int32_t)(end->ts_.tv_sec - start->ts_.tv_sec);
const int32_t diff_nsec = (int32_t)(end->ts_.tv_nsec - start->ts_.tv_nsec);
return diff_sec * 1000 + diff_nsec / ONE_MILLION;
}
/* This value is ONE_BILLION >> 20. */
static const uint32_t STAMP_TICKS_PER_SECOND = 953;
@ -626,13 +592,6 @@ monotime_coarse_diff_msec(const monotime_coarse_t *start,
return diff_ticks;
}
int32_t
monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
const monotime_coarse_t *end)
{
return (int32_t)monotime_coarse_diff_msec(start, end);
}
int64_t
monotime_coarse_diff_usec(const monotime_coarse_t *start,
const monotime_coarse_t *end)
@ -718,15 +677,6 @@ monotime_diff_nsec(const monotime_t *start,
return (diff.tv_sec * ONE_BILLION + diff.tv_usec * 1000);
}
int32_t
monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
const monotime_coarse_t *end)
{
struct timeval diff;
timersub(&end->tv_, &start->tv_, &diff);
return diff.tv_sec * 1000 + diff.tv_usec / 1000;
}
/* This value is ONE_MILLION >> 10. */
static const uint32_t STAMP_TICKS_PER_SECOND = 976;
@ -880,24 +830,11 @@ monotime_coarse_stamp_units_to_approx_msec(uint64_t units)
return (abstime_diff * mach_time_info.numer) /
(mach_time_info.denom * ONE_MILLION);
}
uint64_t
monotime_msec_to_approx_coarse_stamp_units(uint64_t msec)
{
uint64_t abstime_val =
(((uint64_t)msec) * ONE_MILLION * mach_time_info.denom) /
mach_time_info.numer;
return abstime_val >> monotime_shift;
}
#else
uint64_t
monotime_coarse_stamp_units_to_approx_msec(uint64_t units)
{
return (units * 1000) / STAMP_TICKS_PER_SECOND;
}
uint64_t
monotime_msec_to_approx_coarse_stamp_units(uint64_t msec)
{
return (msec * STAMP_TICKS_PER_SECOND) / 1000;
}
#endif

View File

@ -150,7 +150,6 @@ uint32_t monotime_coarse_to_stamp(const monotime_coarse_t *t);
* into an approximate number of milliseconds.
*/
uint64_t monotime_coarse_stamp_units_to_approx_msec(uint64_t units);
uint64_t monotime_msec_to_approx_coarse_stamp_units(uint64_t msec);
uint32_t monotime_coarse_get_stamp(void);
#if defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT)
@ -173,34 +172,7 @@ void monotime_coarse_add_msec(monotime_coarse_t *out,
#define monotime_coarse_add_msec monotime_add_msec
#endif /* defined(MONOTIME_COARSE_TYPE_IS_DIFFERENT) */
/**
* As monotime_coarse_diff_msec, but avoid 64-bit division.
*
* Requires that the difference fit into an int32_t; not for use with
* large time differences.
*/
int32_t monotime_coarse_diff_msec32_(const monotime_coarse_t *start,
const monotime_coarse_t *end);
/**
* As monotime_coarse_diff_msec, but avoid 64-bit division if it is expensive.
*
* Requires that the difference fit into an int32_t; not for use with
* large time differences.
*/
static inline int32_t
monotime_coarse_diff_msec32(const monotime_coarse_t *start,
const monotime_coarse_t *end)
{
#if SIZEOF_VOID_P == 8
// on a 64-bit platform, let's assume 64/64 division is cheap.
return (int32_t) monotime_coarse_diff_msec(start, end);
#else
return monotime_coarse_diff_msec32_(start, end);
#endif
}
MOCK_DECL(void, tor_gettimeofday, (struct timeval *timeval));
void tor_gettimeofday(struct timeval *timeval);
#ifdef TOR_UNIT_TESTS
void tor_sleep_msec(int msec);

View File

@ -18,6 +18,7 @@
#include "util.h"
#include "container.h"
#include "torlog.h"
#include <process.h>
/* This value is more or less total cargo-cult */
#define SPIN_COUNT 2000

View File

@ -663,13 +663,3 @@ tor_compress_init(void)
tor_zstd_init();
}
/** Warn if we had any problems while setting up our compression libraries.
*
* (This isn't part of tor_compress_init, since the logs aren't set up yet.)
*/
void
tor_compress_log_init_warnings(void)
{
tor_zstd_warn_if_version_mismatched();
}

View File

@ -87,7 +87,6 @@ void tor_compress_free_(tor_compress_state_t *state);
size_t tor_compress_state_size(const tor_compress_state_t *state);
void tor_compress_init(void);
void tor_compress_log_init_warnings(void);
#endif /* !defined(TOR_COMPRESS_H) */

View File

@ -18,13 +18,6 @@
#include "compress.h"
#include "compress_zstd.h"
#ifdef ENABLE_ZSTD_ADVANCED_APIS
/* This is a lie, but we make sure it doesn't get us in trouble by wrapping
* all invocations of zstd's static-only functions in a check to make sure
* that the compile-time version matches the run-time version. */
#define ZSTD_STATIC_LINKING_ONLY
#endif
#ifdef HAVE_ZSTD
#include <zstd.h>
#endif
@ -58,31 +51,21 @@ tor_zstd_method_supported(void)
#endif
}
#ifdef HAVE_ZSTD
/** Format a zstd version number as a string in <b>buf</b>. */
static void
tor_zstd_format_version(char *buf, size_t buflen, unsigned version_number)
{
tor_snprintf(buf, buflen,
"%u.%u.%u",
version_number / 10000 % 100,
version_number / 100 % 100,
version_number % 100);
}
#endif
#define VERSION_STR_MAX_LEN 16 /* more than enough space for 99.99.99 */
/** Return a string representation of the version of the currently running
* version of libzstd. Returns NULL if Zstandard is unsupported. */
const char *
tor_zstd_get_version_str(void)
{
#ifdef HAVE_ZSTD
static char version_str[VERSION_STR_MAX_LEN];
static char version_str[16];
size_t version_number;
tor_zstd_format_version(version_str, sizeof(version_str),
ZSTD_versionNumber());
version_number = ZSTD_versionNumber();
tor_snprintf(version_str, sizeof(version_str),
"%d.%d.%d",
(int) version_number / 10000 % 100,
(int) version_number / 100 % 100,
(int) version_number % 100);
return version_str;
#else /* !(defined(HAVE_ZSTD)) */
@ -102,26 +85,6 @@ tor_zstd_get_header_version_str(void)
#endif
}
#ifdef TOR_UNIT_TESTS
static int static_apis_disable_for_testing = 0;
#endif
/** Return true iff we can use the "static-only" APIs. */
int
tor_zstd_can_use_static_apis(void)
{
#if defined(ZSTD_STATIC_LINKING_ONLY) && defined(HAVE_ZSTD)
#ifdef TOR_UNIT_TESTS
if (static_apis_disable_for_testing) {
return 0;
}
#endif
return (ZSTD_VERSION_NUMBER == ZSTD_versionNumber());
#else
return 0;
#endif
}
/** Internal Zstandard state for incremental compression/decompression.
* The body of this struct is not exposed. */
struct tor_zstd_compress_state_t {
@ -149,11 +112,9 @@ struct tor_zstd_compress_state_t {
#ifdef HAVE_ZSTD
/** Return an approximate number of bytes stored in memory to hold the
* Zstandard compression/decompression state. This is a fake estimate
* based on inspecting the zstd source: tor_zstd_state_size_precalc() is
* more accurate when it's allowed to use "static-only" functions */
* Zstandard compression/decompression state. */
static size_t
tor_zstd_state_size_precalc_fake(int compress, int preset)
tor_zstd_state_size_precalc(int compress, int preset)
{
tor_assert(preset > 0);
@ -210,28 +171,6 @@ tor_zstd_state_size_precalc_fake(int compress, int preset)
return memory_usage;
}
/** Return an approximate number of bytes stored in memory to hold the
* Zstandard compression/decompression state. */
static size_t
tor_zstd_state_size_precalc(int compress, int preset)
{
#ifdef ZSTD_STATIC_LINKING_ONLY
if (tor_zstd_can_use_static_apis()) {
if (compress) {
#ifdef HAVE_ZSTD_ESTIMATECSTREAMSIZE
return ZSTD_estimateCStreamSize(preset);
#endif
} else {
#ifdef HAVE_ZSTD_ESTIMATEDCTXSIZE
/* Could use DStream, but that takes a windowSize. */
return ZSTD_estimateDCtxSize();
#endif
}
}
#endif
return tor_zstd_state_size_precalc_fake(compress, preset);
}
#endif /* defined(HAVE_ZSTD) */
/** Construct and return a tor_zstd_compress_state_t object using
@ -501,34 +440,3 @@ tor_zstd_init(void)
atomic_counter_init(&total_zstd_allocation);
}
/** Warn if the header and library versions don't match. */
void
tor_zstd_warn_if_version_mismatched(void)
{
#if defined(HAVE_ZSTD) && defined(ENABLE_ZSTD_ADVANCED_APIS)
if (! tor_zstd_can_use_static_apis()) {
char header_version[VERSION_STR_MAX_LEN];
char runtime_version[VERSION_STR_MAX_LEN];
tor_zstd_format_version(header_version, sizeof(header_version),
ZSTD_VERSION_NUMBER);
tor_zstd_format_version(runtime_version, sizeof(runtime_version),
ZSTD_versionNumber());
log_warn(LD_GENERAL,
"Tor was compiled with zstd %s, but is running with zstd %s. "
"For safety, we'll avoid using advanced zstd functionality.",
header_version, runtime_version);
}
#endif
}
#ifdef TOR_UNIT_TESTS
/** Testing only: disable usage of static-only APIs, so we can make sure that
* we still work without them. */
void
tor_zstd_set_static_apis_disabled_for_testing(int disabled)
{
static_apis_disable_for_testing = disabled;
}
#endif

View File

@ -17,8 +17,6 @@ const char *tor_zstd_get_version_str(void);
const char *tor_zstd_get_header_version_str(void);
int tor_zstd_can_use_static_apis(void);
/** Internal state for an incremental Zstandard compression/decompression. */
typedef struct tor_zstd_compress_state_t tor_zstd_compress_state_t;
@ -43,11 +41,6 @@ size_t tor_zstd_compress_state_size(const tor_zstd_compress_state_t *state);
size_t tor_zstd_get_total_allocation(void);
void tor_zstd_init(void);
void tor_zstd_warn_if_version_mismatched(void);
#ifdef TOR_UNIT_TESTS
void tor_zstd_set_static_apis_disabled_for_testing(int disabled);
#endif
#endif /* !defined(TOR_COMPRESS_ZSTD_H) */

View File

@ -15,7 +15,7 @@
#include "util.h"
#include "torlog.h"
#include "container.h"
#include "crypto_digest.h"
#include "crypto.h"
#include <stdlib.h>
#include <string.h>

File diff suppressed because it is too large Load Diff

View File

@ -17,10 +17,20 @@
#include <stdio.h>
#include "torint.h"
#include "testsupport.h"
#include "compat.h"
#include "util.h"
#include "crypto_rsa.h"
#include "keccak-tiny/keccak-tiny.h"
/** Length of the output of our message digest. */
#define DIGEST_LEN 20
/** Length of the output of our second (improved) message digests. (For now
* this is just sha256, but it could be any other 256-bit digest.) */
#define DIGEST256_LEN 32
/** Length of the output of our 64-bit optimized message digests (SHA512). */
#define DIGEST512_LEN 64
/** Length of our symmetric cipher's keys of 128-bit. */
#define CIPHER_KEY_LEN 16
/** Length of our symmetric cipher's IV of 128-bit. */
@ -30,15 +40,57 @@
/** Length of our DH keys. */
#define DH_BYTES (1024/8)
/** Length of a sha1 message digest when encoded in base32 with trailing =
* signs removed. */
#define BASE32_DIGEST_LEN 32
/** Length of a sha1 message digest when encoded in base64 with trailing =
* signs removed. */
#define BASE64_DIGEST_LEN 27
/** Length of a sha256 message digest when encoded in base64 with trailing =
* signs removed. */
#define BASE64_DIGEST256_LEN 43
/** Length of a sha512 message digest when encoded in base64 with trailing =
* signs removed. */
#define BASE64_DIGEST512_LEN 86
/** Length of encoded public key fingerprints, including space; but not
* including terminating NUL. */
#define FINGERPRINT_LEN 49
/** Length of hex encoding of SHA1 digest, not including final NUL. */
#define HEX_DIGEST_LEN 40
/** Length of hex encoding of SHA256 digest, not including final NUL. */
#define HEX_DIGEST256_LEN 64
/** Length of hex encoding of SHA512 digest, not including final NUL. */
#define HEX_DIGEST512_LEN 128
typedef enum {
DIGEST_SHA1 = 0,
DIGEST_SHA256 = 1,
DIGEST_SHA512 = 2,
DIGEST_SHA3_256 = 3,
DIGEST_SHA3_512 = 4,
} digest_algorithm_t;
#define N_DIGEST_ALGORITHMS (DIGEST_SHA3_512+1)
#define N_COMMON_DIGEST_ALGORITHMS (DIGEST_SHA256+1)
/** A set of all the digests we commonly compute, taken on a single
* string. Any digests that are shorter than 512 bits are right-padded
* with 0 bits.
*
* Note that this representation wastes 44 bytes for the SHA1 case, so
* don't use it for anything where we need to allocate a whole bunch at
* once.
**/
typedef struct {
char d[N_COMMON_DIGEST_ALGORITHMS][DIGEST256_LEN];
} common_digests_t;
typedef struct aes_cnt_cipher crypto_cipher_t;
typedef struct crypto_digest_t crypto_digest_t;
typedef struct crypto_xof_t crypto_xof_t;
typedef struct crypto_dh_t crypto_dh_t;
/* global state */
int crypto_init_siphash_key(void);
int crypto_early_init(void) ATTR_WUR;
int crypto_global_init(int hardwareAccel,
const char *accelName,
@ -62,6 +114,24 @@ void crypto_cipher_free_(crypto_cipher_t *env);
#define crypto_cipher_free(c) \
FREE_AND_NULL(crypto_cipher_t, crypto_cipher_free_, (c))
/* public key crypto */
MOCK_DECL(int, crypto_pk_public_checksig_digest,(crypto_pk_t *env,
const char *data, size_t datalen,
const char *sig, size_t siglen));
int crypto_pk_private_sign_digest(crypto_pk_t *env, char *to, size_t tolen,
const char *from, size_t fromlen);
int crypto_pk_obsolete_public_hybrid_encrypt(crypto_pk_t *env, char *to,
size_t tolen,
const char *from, size_t fromlen,
int padding, int force);
int crypto_pk_obsolete_private_hybrid_decrypt(crypto_pk_t *env, char *to,
size_t tolen,
const char *from, size_t fromlen,
int padding, int warnOnFailure);
int crypto_pk_get_digest(const crypto_pk_t *pk, char *digest_out);
int crypto_pk_get_common_digests(crypto_pk_t *pk,
common_digests_t *digests_out);
/* symmetric crypto */
const char *crypto_cipher_get_key(crypto_cipher_t *env);
@ -78,6 +148,52 @@ int crypto_cipher_decrypt_with_iv(const char *key,
char *to, size_t tolen,
const char *from, size_t fromlen);
/* SHA-1 and other digests. */
int crypto_digest(char *digest, const char *m, size_t len);
int crypto_digest256(char *digest, const char *m, size_t len,
digest_algorithm_t algorithm);
int crypto_digest512(char *digest, const char *m, size_t len,
digest_algorithm_t algorithm);
int crypto_common_digests(common_digests_t *ds_out, const char *m, size_t len);
struct smartlist_t;
void crypto_digest_smartlist_prefix(char *digest_out, size_t len_out,
const char *prepend,
const struct smartlist_t *lst,
const char *append,
digest_algorithm_t alg);
void crypto_digest_smartlist(char *digest_out, size_t len_out,
const struct smartlist_t *lst, const char *append,
digest_algorithm_t alg);
const char *crypto_digest_algorithm_get_name(digest_algorithm_t alg);
size_t crypto_digest_algorithm_get_length(digest_algorithm_t alg);
int crypto_digest_algorithm_parse_name(const char *name);
crypto_digest_t *crypto_digest_new(void);
crypto_digest_t *crypto_digest256_new(digest_algorithm_t algorithm);
crypto_digest_t *crypto_digest512_new(digest_algorithm_t algorithm);
void crypto_digest_free_(crypto_digest_t *digest);
#define crypto_digest_free(d) \
FREE_AND_NULL(crypto_digest_t, crypto_digest_free_, (d))
void crypto_digest_add_bytes(crypto_digest_t *digest, const char *data,
size_t len);
void crypto_digest_get_digest(crypto_digest_t *digest,
char *out, size_t out_len);
crypto_digest_t *crypto_digest_dup(const crypto_digest_t *digest);
void crypto_digest_assign(crypto_digest_t *into,
const crypto_digest_t *from);
void crypto_hmac_sha256(char *hmac_out,
const char *key, size_t key_len,
const char *msg, size_t msg_len);
void crypto_mac_sha3_256(uint8_t *mac_out, size_t len_out,
const uint8_t *key, size_t key_len,
const uint8_t *msg, size_t msg_len);
crypto_xof_t *crypto_xof_new(void);
void crypto_xof_add_bytes(crypto_xof_t *xof, const uint8_t *data, size_t len);
void crypto_xof_squeeze_bytes(crypto_xof_t *xof, uint8_t *out, size_t len);
void crypto_xof_free_(crypto_xof_t *xof);
#define crypto_xof_free(xof) \
FREE_AND_NULL(crypto_xof_t, crypto_xof_free_, (xof))
/* Key negotiation */
#define DH_TYPE_CIRCUIT 1
#define DH_TYPE_REND 2
@ -103,6 +219,31 @@ int crypto_expand_key_material_rfc5869_sha256(
const uint8_t *info_in, size_t info_in_len,
uint8_t *key_out, size_t key_out_len);
/* random numbers */
int crypto_seed_rng(void) ATTR_WUR;
MOCK_DECL(void,crypto_rand,(char *to, size_t n));
void crypto_rand_unmocked(char *to, size_t n);
void crypto_strongest_rand(uint8_t *out, size_t out_len);
int crypto_rand_int(unsigned int max);
int crypto_rand_int_range(unsigned int min, unsigned int max);
uint64_t crypto_rand_uint64_range(uint64_t min, uint64_t max);
time_t crypto_rand_time_range(time_t min, time_t max);
uint64_t crypto_rand_uint64(uint64_t max);
double crypto_rand_double(void);
struct tor_weak_rng_t;
void crypto_seed_weak_rng(struct tor_weak_rng_t *rng);
int crypto_init_siphash_key(void);
char *crypto_random_hostname(int min_rand_len, int max_rand_len,
const char *prefix, const char *suffix);
struct smartlist_t;
void *smartlist_choose(const struct smartlist_t *sl);
void smartlist_shuffle(struct smartlist_t *sl);
/** OpenSSL-based utility functions. */
void memwipe(void *mem, uint8_t byte, size_t sz);
/* Prototypes for private functions only used by tortls.c, crypto.c, and the
* unit tests. */
struct dh_st;
@ -110,5 +251,20 @@ struct dh_st *crypto_dh_get_dh_(crypto_dh_t *dh);
void crypto_add_spaces_to_fp(char *out, size_t outlen, const char *in);
#ifdef CRYPTO_PRIVATE
STATIC int crypto_force_rand_ssleay(void);
STATIC int crypto_strongest_rand_raw(uint8_t *out, size_t out_len);
#ifdef TOR_UNIT_TESTS
extern int break_strongest_rng_syscall;
extern int break_strongest_rng_fallback;
#endif
#endif /* defined(CRYPTO_PRIVATE) */
#ifdef TOR_UNIT_TESTS
digest_algorithm_t crypto_digest_get_algorithm(crypto_digest_t *digest);
#endif
#endif /* !defined(TOR_CRYPTO_H) */

View File

@ -21,11 +21,9 @@
#include <sys/stat.h>
#endif
#include "container.h"
#include "crypto.h"
#include "crypto_curve25519.h"
#include "crypto_digest.h"
#include "crypto_format.h"
#include "crypto_rand.h"
#include "crypto_util.h"
#include "util.h"
#include "torlog.h"

View File

@ -6,7 +6,6 @@
#include "testsupport.h"
#include "torint.h"
#include "crypto_digest.h"
#include "crypto_openssl_mgt.h"
/** Length of a curve25519 public key when encoded. */

View File

@ -1,583 +0,0 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file crypto_digest.c
* \brief Block of functions related with digest and xof utilities and
* operations.
**/
#include "container.h"
#include "crypto_digest.h"
#include "crypto_openssl_mgt.h"
#include "crypto_util.h"
#include "torlog.h"
#include "keccak-tiny/keccak-tiny.h"
DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/hmac.h>
#include <openssl/sha.h>
ENABLE_GCC_WARNING(redundant-decls)
/* Crypto digest functions */
/** Compute the SHA1 digest of the <b>len</b> bytes on data stored in
* <b>m</b>. Write the DIGEST_LEN byte result into <b>digest</b>.
* Return 0 on success, -1 on failure.
*/
int
crypto_digest(char *digest, const char *m, size_t len)
{
tor_assert(m);
tor_assert(digest);
if (SHA1((const unsigned char*)m,len,(unsigned char*)digest) == NULL)
return -1;
return 0;
}
/** Compute a 256-bit digest of <b>len</b> bytes in data stored in <b>m</b>,
* using the algorithm <b>algorithm</b>. Write the DIGEST_LEN256-byte result
* into <b>digest</b>. Return 0 on success, -1 on failure. */
int
crypto_digest256(char *digest, const char *m, size_t len,
digest_algorithm_t algorithm)
{
tor_assert(m);
tor_assert(digest);
tor_assert(algorithm == DIGEST_SHA256 || algorithm == DIGEST_SHA3_256);
int ret = 0;
if (algorithm == DIGEST_SHA256)
ret = (SHA256((const uint8_t*)m,len,(uint8_t*)digest) != NULL);
else
ret = (sha3_256((uint8_t *)digest, DIGEST256_LEN,(const uint8_t *)m, len)
> -1);
if (!ret)
return -1;
return 0;
}
/** Compute a 512-bit digest of <b>len</b> bytes in data stored in <b>m</b>,
* using the algorithm <b>algorithm</b>. Write the DIGEST_LEN512-byte result
* into <b>digest</b>. Return 0 on success, -1 on failure. */
int
crypto_digest512(char *digest, const char *m, size_t len,
digest_algorithm_t algorithm)
{
tor_assert(m);
tor_assert(digest);
tor_assert(algorithm == DIGEST_SHA512 || algorithm == DIGEST_SHA3_512);
int ret = 0;
if (algorithm == DIGEST_SHA512)
ret = (SHA512((const unsigned char*)m,len,(unsigned char*)digest)
!= NULL);
else
ret = (sha3_512((uint8_t*)digest, DIGEST512_LEN, (const uint8_t*)m, len)
> -1);
if (!ret)
return -1;
return 0;
}
/** Set the common_digests_t in <b>ds_out</b> to contain every digest on the
* <b>len</b> bytes in <b>m</b> that we know how to compute. Return 0 on
* success, -1 on failure. */
int
crypto_common_digests(common_digests_t *ds_out, const char *m, size_t len)
{
tor_assert(ds_out);
memset(ds_out, 0, sizeof(*ds_out));
if (crypto_digest(ds_out->d[DIGEST_SHA1], m, len) < 0)
return -1;
if (crypto_digest256(ds_out->d[DIGEST_SHA256], m, len, DIGEST_SHA256) < 0)
return -1;
return 0;
}
/** Return the name of an algorithm, as used in directory documents. */
const char *
crypto_digest_algorithm_get_name(digest_algorithm_t alg)
{
switch (alg) {
case DIGEST_SHA1:
return "sha1";
case DIGEST_SHA256:
return "sha256";
case DIGEST_SHA512:
return "sha512";
case DIGEST_SHA3_256:
return "sha3-256";
case DIGEST_SHA3_512:
return "sha3-512";
// LCOV_EXCL_START
default:
tor_fragile_assert();
return "??unknown_digest??";
// LCOV_EXCL_STOP
}
}
/** Given the name of a digest algorithm, return its integer value, or -1 if
* the name is not recognized. */
int
crypto_digest_algorithm_parse_name(const char *name)
{
if (!strcmp(name, "sha1"))
return DIGEST_SHA1;
else if (!strcmp(name, "sha256"))
return DIGEST_SHA256;
else if (!strcmp(name, "sha512"))
return DIGEST_SHA512;
else if (!strcmp(name, "sha3-256"))
return DIGEST_SHA3_256;
else if (!strcmp(name, "sha3-512"))
return DIGEST_SHA3_512;
else
return -1;
}
/** Given an algorithm, return the digest length in bytes. */
size_t
crypto_digest_algorithm_get_length(digest_algorithm_t alg)
{
switch (alg) {
case DIGEST_SHA1:
return DIGEST_LEN;
case DIGEST_SHA256:
return DIGEST256_LEN;
case DIGEST_SHA512:
return DIGEST512_LEN;
case DIGEST_SHA3_256:
return DIGEST256_LEN;
case DIGEST_SHA3_512:
return DIGEST512_LEN;
default:
tor_assert(0); // LCOV_EXCL_LINE
return 0; /* Unreachable */ // LCOV_EXCL_LINE
}
}
/** Intermediate information about the digest of a stream of data. */
struct crypto_digest_t {
digest_algorithm_t algorithm; /**< Which algorithm is in use? */
/** State for the digest we're using. Only one member of the
* union is usable, depending on the value of <b>algorithm</b>. Note also
* that space for other members might not even be allocated!
*/
union {
SHA_CTX sha1; /**< state for SHA1 */
SHA256_CTX sha2; /**< state for SHA256 */
SHA512_CTX sha512; /**< state for SHA512 */
keccak_state sha3; /**< state for SHA3-[256,512] */
} d;
};
#ifdef TOR_UNIT_TESTS
digest_algorithm_t
crypto_digest_get_algorithm(crypto_digest_t *digest)
{
tor_assert(digest);
return digest->algorithm;
}
#endif /* defined(TOR_UNIT_TESTS) */
/**
* Return the number of bytes we need to malloc in order to get a
* crypto_digest_t for <b>alg</b>, or the number of bytes we need to wipe
* when we free one.
*/
static size_t
crypto_digest_alloc_bytes(digest_algorithm_t alg)
{
/* Helper: returns the number of bytes in the 'f' field of 'st' */
#define STRUCT_FIELD_SIZE(st, f) (sizeof( ((st*)0)->f ))
/* Gives the length of crypto_digest_t through the end of the field 'd' */
#define END_OF_FIELD(f) (offsetof(crypto_digest_t, f) + \
STRUCT_FIELD_SIZE(crypto_digest_t, f))
switch (alg) {
case DIGEST_SHA1:
return END_OF_FIELD(d.sha1);
case DIGEST_SHA256:
return END_OF_FIELD(d.sha2);
case DIGEST_SHA512:
return END_OF_FIELD(d.sha512);
case DIGEST_SHA3_256:
case DIGEST_SHA3_512:
return END_OF_FIELD(d.sha3);
default:
tor_assert(0); // LCOV_EXCL_LINE
return 0; // LCOV_EXCL_LINE
}
#undef END_OF_FIELD
#undef STRUCT_FIELD_SIZE
}
/**
* Internal function: create and return a new digest object for 'algorithm'.
* Does not typecheck the algorithm.
*/
static crypto_digest_t *
crypto_digest_new_internal(digest_algorithm_t algorithm)
{
crypto_digest_t *r = tor_malloc(crypto_digest_alloc_bytes(algorithm));
r->algorithm = algorithm;
switch (algorithm)
{
case DIGEST_SHA1:
SHA1_Init(&r->d.sha1);
break;
case DIGEST_SHA256:
SHA256_Init(&r->d.sha2);
break;
case DIGEST_SHA512:
SHA512_Init(&r->d.sha512);
break;
case DIGEST_SHA3_256:
keccak_digest_init(&r->d.sha3, 256);
break;
case DIGEST_SHA3_512:
keccak_digest_init(&r->d.sha3, 512);
break;
default:
tor_assert_unreached();
}
return r;
}
/** Allocate and return a new digest object to compute SHA1 digests.
*/
crypto_digest_t *
crypto_digest_new(void)
{
return crypto_digest_new_internal(DIGEST_SHA1);
}
/** Allocate and return a new digest object to compute 256-bit digests
* using <b>algorithm</b>.
*
* C_RUST_COUPLED: `external::crypto_digest::crypto_digest256_new`
* C_RUST_COUPLED: `crypto::digest::Sha256::default`
*/
crypto_digest_t *
crypto_digest256_new(digest_algorithm_t algorithm)
{
tor_assert(algorithm == DIGEST_SHA256 || algorithm == DIGEST_SHA3_256);
return crypto_digest_new_internal(algorithm);
}
/** Allocate and return a new digest object to compute 512-bit digests
* using <b>algorithm</b>. */
crypto_digest_t *
crypto_digest512_new(digest_algorithm_t algorithm)
{
tor_assert(algorithm == DIGEST_SHA512 || algorithm == DIGEST_SHA3_512);
return crypto_digest_new_internal(algorithm);
}
/** Deallocate a digest object.
*/
void
crypto_digest_free_(crypto_digest_t *digest)
{
if (!digest)
return;
size_t bytes = crypto_digest_alloc_bytes(digest->algorithm);
memwipe(digest, 0, bytes);
tor_free(digest);
}
/** Add <b>len</b> bytes from <b>data</b> to the digest object.
*
* C_RUST_COUPLED: `external::crypto_digest::crypto_digest_add_bytess`
* C_RUST_COUPLED: `crypto::digest::Sha256::process`
*/
void
crypto_digest_add_bytes(crypto_digest_t *digest, const char *data,
size_t len)
{
tor_assert(digest);
tor_assert(data);
/* Using the SHA*_*() calls directly means we don't support doing
* SHA in hardware. But so far the delay of getting the question
* to the hardware, and hearing the answer, is likely higher than
* just doing it ourselves. Hashes are fast.
*/
switch (digest->algorithm) {
case DIGEST_SHA1:
SHA1_Update(&digest->d.sha1, (void*)data, len);
break;
case DIGEST_SHA256:
SHA256_Update(&digest->d.sha2, (void*)data, len);
break;
case DIGEST_SHA512:
SHA512_Update(&digest->d.sha512, (void*)data, len);
break;
case DIGEST_SHA3_256: /* FALLSTHROUGH */
case DIGEST_SHA3_512:
keccak_digest_update(&digest->d.sha3, (const uint8_t *)data, len);
break;
default:
/* LCOV_EXCL_START */
tor_fragile_assert();
break;
/* LCOV_EXCL_STOP */
}
}
/** Compute the hash of the data that has been passed to the digest
* object; write the first out_len bytes of the result to <b>out</b>.
* <b>out_len</b> must be \<= DIGEST512_LEN.
*
* C_RUST_COUPLED: `external::crypto_digest::crypto_digest_get_digest`
* C_RUST_COUPLED: `impl digest::FixedOutput for Sha256`
*/
void
crypto_digest_get_digest(crypto_digest_t *digest,
char *out, size_t out_len)
{
unsigned char r[DIGEST512_LEN];
crypto_digest_t tmpenv;
tor_assert(digest);
tor_assert(out);
tor_assert(out_len <= crypto_digest_algorithm_get_length(digest->algorithm));
/* The SHA-3 code handles copying into a temporary ctx, and also can handle
* short output buffers by truncating appropriately. */
if (digest->algorithm == DIGEST_SHA3_256 ||
digest->algorithm == DIGEST_SHA3_512) {
keccak_digest_sum(&digest->d.sha3, (uint8_t *)out, out_len);
return;
}
const size_t alloc_bytes = crypto_digest_alloc_bytes(digest->algorithm);
/* memcpy into a temporary ctx, since SHA*_Final clears the context */
memcpy(&tmpenv, digest, alloc_bytes);
switch (digest->algorithm) {
case DIGEST_SHA1:
SHA1_Final(r, &tmpenv.d.sha1);
break;
case DIGEST_SHA256:
SHA256_Final(r, &tmpenv.d.sha2);
break;
case DIGEST_SHA512:
SHA512_Final(r, &tmpenv.d.sha512);
break;
//LCOV_EXCL_START
case DIGEST_SHA3_256: /* FALLSTHROUGH */
case DIGEST_SHA3_512:
default:
log_warn(LD_BUG, "Handling unexpected algorithm %d", digest->algorithm);
/* This is fatal, because it should never happen. */
tor_assert_unreached();
break;
//LCOV_EXCL_STOP
}
memcpy(out, r, out_len);
memwipe(r, 0, sizeof(r));
}
/** Allocate and return a new digest object with the same state as
* <b>digest</b>
*
* C_RUST_COUPLED: `external::crypto_digest::crypto_digest_dup`
* C_RUST_COUPLED: `impl Clone for crypto::digest::Sha256`
*/
crypto_digest_t *
crypto_digest_dup(const crypto_digest_t *digest)
{
tor_assert(digest);
const size_t alloc_bytes = crypto_digest_alloc_bytes(digest->algorithm);
return tor_memdup(digest, alloc_bytes);
}
/** Temporarily save the state of <b>digest</b> in <b>checkpoint</b>.
* Asserts that <b>digest</b> is a SHA1 digest object.
*/
void
crypto_digest_checkpoint(crypto_digest_checkpoint_t *checkpoint,
const crypto_digest_t *digest)
{
const size_t bytes = crypto_digest_alloc_bytes(digest->algorithm);
tor_assert(bytes <= sizeof(checkpoint->mem));
memcpy(checkpoint->mem, digest, bytes);
}
/** Restore the state of <b>digest</b> from <b>checkpoint</b>.
* Asserts that <b>digest</b> is a SHA1 digest object. Requires that the
* state was previously stored with crypto_digest_checkpoint() */
void
crypto_digest_restore(crypto_digest_t *digest,
const crypto_digest_checkpoint_t *checkpoint)
{
const size_t bytes = crypto_digest_alloc_bytes(digest->algorithm);
memcpy(digest, checkpoint->mem, bytes);
}
/** Replace the state of the digest object <b>into</b> with the state
* of the digest object <b>from</b>. Requires that 'into' and 'from'
* have the same digest type.
*/
void
crypto_digest_assign(crypto_digest_t *into,
const crypto_digest_t *from)
{
tor_assert(into);
tor_assert(from);
tor_assert(into->algorithm == from->algorithm);
const size_t alloc_bytes = crypto_digest_alloc_bytes(from->algorithm);
memcpy(into,from,alloc_bytes);
}
/** Given a list of strings in <b>lst</b>, set the <b>len_out</b>-byte digest
* at <b>digest_out</b> to the hash of the concatenation of those strings,
* plus the optional string <b>append</b>, computed with the algorithm
* <b>alg</b>.
* <b>out_len</b> must be \<= DIGEST512_LEN. */
void
crypto_digest_smartlist(char *digest_out, size_t len_out,
const smartlist_t *lst,
const char *append,
digest_algorithm_t alg)
{
crypto_digest_smartlist_prefix(digest_out, len_out, NULL, lst, append, alg);
}
/** Given a list of strings in <b>lst</b>, set the <b>len_out</b>-byte digest
* at <b>digest_out</b> to the hash of the concatenation of: the
* optional string <b>prepend</b>, those strings,
* and the optional string <b>append</b>, computed with the algorithm
* <b>alg</b>.
* <b>len_out</b> must be \<= DIGEST512_LEN. */
void
crypto_digest_smartlist_prefix(char *digest_out, size_t len_out,
const char *prepend,
const smartlist_t *lst,
const char *append,
digest_algorithm_t alg)
{
crypto_digest_t *d = crypto_digest_new_internal(alg);
if (prepend)
crypto_digest_add_bytes(d, prepend, strlen(prepend));
SMARTLIST_FOREACH(lst, const char *, cp,
crypto_digest_add_bytes(d, cp, strlen(cp)));
if (append)
crypto_digest_add_bytes(d, append, strlen(append));
crypto_digest_get_digest(d, digest_out, len_out);
crypto_digest_free(d);
}
/** Compute the HMAC-SHA-256 of the <b>msg_len</b> bytes in <b>msg</b>, using
* the <b>key</b> of length <b>key_len</b>. Store the DIGEST256_LEN-byte
* result in <b>hmac_out</b>. Asserts on failure.
*/
void
crypto_hmac_sha256(char *hmac_out,
const char *key, size_t key_len,
const char *msg, size_t msg_len)
{
unsigned char *rv = NULL;
/* If we've got OpenSSL >=0.9.8 we can use its hmac implementation. */
tor_assert(key_len < INT_MAX);
tor_assert(msg_len < INT_MAX);
tor_assert(hmac_out);
rv = HMAC(EVP_sha256(), key, (int)key_len, (unsigned char*)msg, (int)msg_len,
(unsigned char*)hmac_out, NULL);
tor_assert(rv);
}
/** Compute a MAC using SHA3-256 of <b>msg_len</b> bytes in <b>msg</b> using a
* <b>key</b> of length <b>key_len</b> and a <b>salt</b> of length
* <b>salt_len</b>. Store the result of <b>len_out</b> bytes in in
* <b>mac_out</b>. This function can't fail. */
void
crypto_mac_sha3_256(uint8_t *mac_out, size_t len_out,
const uint8_t *key, size_t key_len,
const uint8_t *msg, size_t msg_len)
{
crypto_digest_t *digest;
const uint64_t key_len_netorder = tor_htonll(key_len);
tor_assert(mac_out);
tor_assert(key);
tor_assert(msg);
digest = crypto_digest256_new(DIGEST_SHA3_256);
/* Order matters here that is any subsystem using this function should
* expect this very precise ordering in the MAC construction. */
crypto_digest_add_bytes(digest, (const char *) &key_len_netorder,
sizeof(key_len_netorder));
crypto_digest_add_bytes(digest, (const char *) key, key_len);
crypto_digest_add_bytes(digest, (const char *) msg, msg_len);
crypto_digest_get_digest(digest, (char *) mac_out, len_out);
crypto_digest_free(digest);
}
/* xof functions */
/** Internal state for a eXtendable-Output Function (XOF). */
struct crypto_xof_t {
keccak_state s;
};
/** Allocate a new XOF object backed by SHAKE-256. The security level
* provided is a function of the length of the output used. Read and
* understand FIPS-202 A.2 "Additional Consideration for Extendable-Output
* Functions" before using this construct.
*/
crypto_xof_t *
crypto_xof_new(void)
{
crypto_xof_t *xof;
xof = tor_malloc(sizeof(crypto_xof_t));
keccak_xof_init(&xof->s, 256);
return xof;
}
/** Absorb bytes into a XOF object. Must not be called after a call to
* crypto_xof_squeeze_bytes() for the same instance, and will assert
* if attempted.
*/
void
crypto_xof_add_bytes(crypto_xof_t *xof, const uint8_t *data, size_t len)
{
int i = keccak_xof_absorb(&xof->s, data, len);
tor_assert(i == 0);
}
/** Squeeze bytes out of a XOF object. Calling this routine will render
* the XOF instance ineligible to absorb further data.
*/
void
crypto_xof_squeeze_bytes(crypto_xof_t *xof, uint8_t *out, size_t len)
{
int i = keccak_xof_squeeze(&xof->s, out, len);
tor_assert(i == 0);
}
/** Cleanse and deallocate a XOF object. */
void
crypto_xof_free_(crypto_xof_t *xof)
{
if (!xof)
return;
memwipe(xof, 0, sizeof(crypto_xof_t));
tor_free(xof);
}

View File

@ -1,136 +0,0 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file crypto_digest.h
*
* \brief Headers for crypto_digest.c
**/
#ifndef TOR_CRYPTO_DIGEST_H
#define TOR_CRYPTO_DIGEST_H
#include <stdio.h>
#include "container.h"
#include "torint.h"
/** Length of the output of our message digest. */
#define DIGEST_LEN 20
/** Length of the output of our second (improved) message digests. (For now
* this is just sha256, but it could be any other 256-bit digest.) */
#define DIGEST256_LEN 32
/** Length of the output of our 64-bit optimized message digests (SHA512). */
#define DIGEST512_LEN 64
/** Length of a sha1 message digest when encoded in base32 with trailing =
* signs removed. */
#define BASE32_DIGEST_LEN 32
/** Length of a sha1 message digest when encoded in base64 with trailing =
* signs removed. */
#define BASE64_DIGEST_LEN 27
/** Length of a sha256 message digest when encoded in base64 with trailing =
* signs removed. */
#define BASE64_DIGEST256_LEN 43
/** Length of a sha512 message digest when encoded in base64 with trailing =
* signs removed. */
#define BASE64_DIGEST512_LEN 86
/** Length of hex encoding of SHA1 digest, not including final NUL. */
#define HEX_DIGEST_LEN 40
/** Length of hex encoding of SHA256 digest, not including final NUL. */
#define HEX_DIGEST256_LEN 64
/** Length of hex encoding of SHA512 digest, not including final NUL. */
#define HEX_DIGEST512_LEN 128
typedef enum {
DIGEST_SHA1 = 0,
DIGEST_SHA256 = 1,
DIGEST_SHA512 = 2,
DIGEST_SHA3_256 = 3,
DIGEST_SHA3_512 = 4,
} digest_algorithm_t;
#define N_DIGEST_ALGORITHMS (DIGEST_SHA3_512+1)
#define N_COMMON_DIGEST_ALGORITHMS (DIGEST_SHA256+1)
#define DIGEST_CHECKPOINT_BYTES (SIZEOF_VOID_P + 512)
/** Structure used to temporarily save the a digest object. Only implemented
* for SHA1 digest for now. */
typedef struct crypto_digest_checkpoint_t {
uint8_t mem[DIGEST_CHECKPOINT_BYTES];
} crypto_digest_checkpoint_t;
/** A set of all the digests we commonly compute, taken on a single
* string. Any digests that are shorter than 512 bits are right-padded
* with 0 bits.
*
* Note that this representation wastes 44 bytes for the SHA1 case, so
* don't use it for anything where we need to allocate a whole bunch at
* once.
**/
typedef struct {
char d[N_COMMON_DIGEST_ALGORITHMS][DIGEST256_LEN];
} common_digests_t;
typedef struct crypto_digest_t crypto_digest_t;
typedef struct crypto_xof_t crypto_xof_t;
/* SHA-1 and other digests */
int crypto_digest(char *digest, const char *m, size_t len);
int crypto_digest256(char *digest, const char *m, size_t len,
digest_algorithm_t algorithm);
int crypto_digest512(char *digest, const char *m, size_t len,
digest_algorithm_t algorithm);
int crypto_common_digests(common_digests_t *ds_out, const char *m, size_t len);
void crypto_digest_smartlist_prefix(char *digest_out, size_t len_out,
const char *prepend,
const struct smartlist_t *lst,
const char *append,
digest_algorithm_t alg);
void crypto_digest_smartlist(char *digest_out, size_t len_out,
const struct smartlist_t *lst, const char *append,
digest_algorithm_t alg);
const char *crypto_digest_algorithm_get_name(digest_algorithm_t alg);
size_t crypto_digest_algorithm_get_length(digest_algorithm_t alg);
int crypto_digest_algorithm_parse_name(const char *name);
crypto_digest_t *crypto_digest_new(void);
crypto_digest_t *crypto_digest256_new(digest_algorithm_t algorithm);
crypto_digest_t *crypto_digest512_new(digest_algorithm_t algorithm);
void crypto_digest_free_(crypto_digest_t *digest);
#define crypto_digest_free(d) \
FREE_AND_NULL(crypto_digest_t, crypto_digest_free_, (d))
void crypto_digest_add_bytes(crypto_digest_t *digest, const char *data,
size_t len);
void crypto_digest_get_digest(crypto_digest_t *digest,
char *out, size_t out_len);
crypto_digest_t *crypto_digest_dup(const crypto_digest_t *digest);
void crypto_digest_checkpoint(crypto_digest_checkpoint_t *checkpoint,
const crypto_digest_t *digest);
void crypto_digest_restore(crypto_digest_t *digest,
const crypto_digest_checkpoint_t *checkpoint);
void crypto_digest_assign(crypto_digest_t *into,
const crypto_digest_t *from);
void crypto_hmac_sha256(char *hmac_out,
const char *key, size_t key_len,
const char *msg, size_t msg_len);
void crypto_mac_sha3_256(uint8_t *mac_out, size_t len_out,
const uint8_t *key, size_t key_len,
const uint8_t *msg, size_t msg_len);
/* xof functions*/
crypto_xof_t *crypto_xof_new(void);
void crypto_xof_add_bytes(crypto_xof_t *xof, const uint8_t *data, size_t len);
void crypto_xof_squeeze_bytes(crypto_xof_t *xof, uint8_t *out, size_t len);
void crypto_xof_free_(crypto_xof_t *xof);
#define crypto_xof_free(xof) \
FREE_AND_NULL(crypto_xof_t, crypto_xof_free_, (xof))
#ifdef TOR_UNIT_TESTS
digest_algorithm_t crypto_digest_get_algorithm(crypto_digest_t *digest);
#endif
#endif /* !defined(TOR_CRYPTO_DIGEST_H) */

View File

@ -21,12 +21,11 @@
#include <sys/stat.h>
#endif
#include "crypto.h"
#include "crypto_curve25519.h"
#include "crypto_digest.h"
#include "crypto_ed25519.h"
#include "crypto_format.h"
#include "crypto_rand.h"
#include "crypto_util.h"
#include "torlog.h"
#include "util.h"
#include "util_format.h"

View File

@ -15,11 +15,10 @@
#include <sys/stat.h>
#endif
#include "container.h"
#include "crypto.h"
#include "crypto_curve25519.h"
#include "crypto_digest.h"
#include "crypto_ed25519.h"
#include "crypto_format.h"
#include "crypto_util.h"
#include "util.h"
#include "util_format.h"
#include "torlog.h"

View File

@ -9,11 +9,8 @@
*/
#include "crypto.h"
#include "crypto_digest.h"
#include "crypto_pwbox.h"
#include "crypto_rand.h"
#include "crypto_s2k.h"
#include "crypto_util.h"
#include "crypto_pwbox.h"
#include "di_ops.h"
#include "util.h"
#include "pwbox.h"

View File

@ -1,615 +0,0 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file crypto_rand.c
*
* \brief Functions for initialising and seeding (pseudo-)random
* number generators, and working with randomness.
**/
#ifndef CRYPTO_RAND_PRIVATE
#define CRYPTO_RAND_PRIVATE
#include "crypto_rand.h"
#ifdef _WIN32
#include <windows.h>
#include <wincrypt.h>
#endif /* defined(_WIN32) */
#include "container.h"
#include "compat.h"
#include "compat_openssl.h"
#include "crypto_util.h"
#include "sandbox.h"
#include "testsupport.h"
#include "torlog.h"
#include "util.h"
#include "util_format.h"
DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/rand.h>
ENABLE_GCC_WARNING(redundant-decls)
#if __GNUC__ && GCC_VERSION >= 402
#if GCC_VERSION >= 406
#pragma GCC diagnostic pop
#else
#pragma GCC diagnostic warning "-Wredundant-decls"
#endif
#endif /* __GNUC__ && GCC_VERSION >= 402 */
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_SYS_FCNTL_H
#include <sys/fcntl.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_SYSCALL_H
#include <sys/syscall.h>
#endif
#ifdef HAVE_SYS_RANDOM_H
#include <sys/random.h>
#endif
/**
* How many bytes of entropy we add at once.
*
* This is how much entropy OpenSSL likes to add right now, so maybe it will
* work for us too.
**/
#define ADD_ENTROPY 32
/**
* Longest recognized DNS query.
**/
#define MAX_DNS_LABEL_SIZE 63
/**
* Largest strong entropy request permitted.
**/
#define MAX_STRONGEST_RAND_SIZE 256
/**
* Set the seed of the weak RNG to a random value.
**/
void
crypto_seed_weak_rng(tor_weak_rng_t *rng)
{
unsigned seed;
crypto_rand((void*)&seed, sizeof(seed));
tor_init_weak_random(rng, seed);
}
#ifdef TOR_UNIT_TESTS
int break_strongest_rng_syscall = 0;
int break_strongest_rng_fallback = 0;
#endif
/**
* Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
* via system calls, storing it into <b>out</b>. Return 0 on success, -1 on
* failure. A maximum request size of 256 bytes is imposed.
**/
static int
crypto_strongest_rand_syscall(uint8_t *out, size_t out_len)
{
tor_assert(out_len <= MAX_STRONGEST_RAND_SIZE);
/* We only log at notice-level here because in the case that this function
* fails the crypto_strongest_rand_raw() caller will log with a warning-level
* message and let crypto_strongest_rand() error out and finally terminating
* Tor with an assertion error.
*/
#ifdef TOR_UNIT_TESTS
if (break_strongest_rng_syscall)
return -1;
#endif
#if defined(_WIN32)
static int provider_set = 0;
static HCRYPTPROV provider;
if (!provider_set) {
if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)) {
log_notice(LD_CRYPTO, "Unable to set Windows CryptoAPI provider [1].");
return -1;
}
provider_set = 1;
}
if (!CryptGenRandom(provider, out_len, out)) {
log_notice(LD_CRYPTO, "Unable get entropy from the Windows CryptoAPI.");
return -1;
}
return 0;
#elif defined(__linux__) && defined(SYS_getrandom)
static int getrandom_works = 1; /* Be optimistic about our chances... */
/* getrandom() isn't as straightforward as getentropy(), and has
* no glibc wrapper.
*
* As far as I can tell from getrandom(2) and the source code, the
* requests we issue will always succeed (though it will block on the
* call if /dev/urandom isn't seeded yet), since we are NOT specifying
* GRND_NONBLOCK and the request is <= 256 bytes.
*
* The manpage is unclear on what happens if a signal interrupts the call
* while the request is blocked due to lack of entropy....
*
* We optimistically assume that getrandom() is available and functional
* because it is the way of the future, and 2 branch mispredicts pale in
* comparison to the overheads involved with failing to open
* /dev/srandom followed by opening and reading from /dev/urandom.
*/
if (PREDICT_LIKELY(getrandom_works)) {
long ret;
/* A flag of '0' here means to read from '/dev/urandom', and to
* block if insufficient entropy is available to service the
* request.
*/
const unsigned int flags = 0;
do {
ret = syscall(SYS_getrandom, out, out_len, flags);
} while (ret == -1 && ((errno == EINTR) ||(errno == EAGAIN)));
if (PREDICT_UNLIKELY(ret == -1)) {
/* LCOV_EXCL_START we can't actually make the syscall fail in testing. */
tor_assert(errno != EAGAIN);
tor_assert(errno != EINTR);
/* Useful log message for errno. */
if (errno == ENOSYS) {
log_notice(LD_CRYPTO, "Can't get entropy from getrandom()."
" You are running a version of Tor built to support"
" getrandom(), but the kernel doesn't implement this"
" function--probably because it is too old?"
" Trying fallback method instead.");
} else {
log_notice(LD_CRYPTO, "Can't get entropy from getrandom(): %s."
" Trying fallback method instead.",
strerror(errno));
}
getrandom_works = 0; /* Don't bother trying again. */
return -1;
/* LCOV_EXCL_STOP */
}
tor_assert(ret == (long)out_len);
return 0;
}
return -1; /* getrandom() previously failed unexpectedly. */
#elif defined(HAVE_GETENTROPY)
/* getentropy() is what Linux's getrandom() wants to be when it grows up.
* the only gotcha is that requests are limited to 256 bytes.
*/
return getentropy(out, out_len);
#else
(void) out;
#endif /* defined(_WIN32) || ... */
/* This platform doesn't have a supported syscall based random. */
return -1;
}
/**
* Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
* via the per-platform fallback mechanism, storing it into <b>out</b>.
* Return 0 on success, -1 on failure. A maximum request size of 256 bytes
* is imposed.
**/
static int
crypto_strongest_rand_fallback(uint8_t *out, size_t out_len)
{
#ifdef TOR_UNIT_TESTS
if (break_strongest_rng_fallback)
return -1;
#endif
#ifdef _WIN32
/* Windows exclusively uses crypto_strongest_rand_syscall(). */
(void)out;
(void)out_len;
return -1;
#else /* !(defined(_WIN32)) */
static const char *filenames[] = {
"/dev/srandom", "/dev/urandom", "/dev/random", NULL
};
int fd, i;
size_t n;
for (i = 0; filenames[i]; ++i) {
log_debug(LD_FS, "Considering %s as entropy source", filenames[i]);
fd = open(sandbox_intern_string(filenames[i]), O_RDONLY, 0);
if (fd<0) continue;
log_info(LD_CRYPTO, "Reading entropy from \"%s\"", filenames[i]);
n = read_all(fd, (char*)out, out_len, 0);
close(fd);
if (n != out_len) {
/* LCOV_EXCL_START
* We can't make /dev/foorandom actually fail. */
log_notice(LD_CRYPTO,
"Error reading from entropy source %s (read only %lu bytes).",
filenames[i],
(unsigned long)n);
return -1;
/* LCOV_EXCL_STOP */
}
return 0;
}
return -1;
#endif /* defined(_WIN32) */
}
/**
* Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
* storing it into <b>out</b>. Return 0 on success, -1 on failure. A maximum
* request size of 256 bytes is imposed.
**/
STATIC int
crypto_strongest_rand_raw(uint8_t *out, size_t out_len)
{
static const size_t sanity_min_size = 16;
static const int max_attempts = 3;
tor_assert(out_len <= MAX_STRONGEST_RAND_SIZE);
/* For buffers >= 16 bytes (128 bits), we sanity check the output by
* zero filling the buffer and ensuring that it actually was at least
* partially modified.
*
* Checking that any individual byte is non-zero seems like it would
* fail too often (p = out_len * 1/256) for comfort, but this is an
* "adjust according to taste" sort of check.
*/
memwipe(out, 0, out_len);
for (int i = 0; i < max_attempts; i++) {
/* Try to use the syscall/OS favored mechanism to get strong entropy. */
if (crypto_strongest_rand_syscall(out, out_len) != 0) {
/* Try to use the less-favored mechanism to get strong entropy. */
if (crypto_strongest_rand_fallback(out, out_len) != 0) {
/* Welp, we tried. Hopefully the calling code terminates the process
* since we're basically boned without good entropy.
*/
log_warn(LD_CRYPTO,
"Cannot get strong entropy: no entropy source found.");
return -1;
}
}
if ((out_len < sanity_min_size) || !tor_mem_is_zero((char*)out, out_len))
return 0;
}
/* LCOV_EXCL_START
*
* We tried max_attempts times to fill a buffer >= 128 bits long,
* and each time it returned all '0's. Either the system entropy
* source is busted, or the user should go out and buy a ticket to
* every lottery on the planet.
*/
log_warn(LD_CRYPTO, "Strong OS entropy returned all zero buffer.");
return -1;
/* LCOV_EXCL_STOP */
}
/**
* Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
* storing it into <b>out</b>.
**/
void
crypto_strongest_rand(uint8_t *out, size_t out_len)
{
#define DLEN SHA512_DIGEST_LENGTH
/* We're going to hash DLEN bytes from the system RNG together with some
* bytes from the openssl PRNG, in order to yield DLEN bytes.
*/
uint8_t inp[DLEN*2];
uint8_t tmp[DLEN];
tor_assert(out);
while (out_len) {
crypto_rand((char*) inp, DLEN);
if (crypto_strongest_rand_raw(inp+DLEN, DLEN) < 0) {
// LCOV_EXCL_START
log_err(LD_CRYPTO, "Failed to load strong entropy when generating an "
"important key. Exiting.");
/* Die with an assertion so we get a stack trace. */
tor_assert(0);
// LCOV_EXCL_STOP
}
if (out_len >= DLEN) {
SHA512(inp, sizeof(inp), out);
out += DLEN;
out_len -= DLEN;
} else {
SHA512(inp, sizeof(inp), tmp);
memcpy(out, tmp, out_len);
break;
}
}
memwipe(tmp, 0, sizeof(tmp));
memwipe(inp, 0, sizeof(inp));
#undef DLEN
}
/**
* Seed OpenSSL's random number generator with bytes from the operating
* system. Return 0 on success, -1 on failure.
**/
int
crypto_seed_rng(void)
{
int rand_poll_ok = 0, load_entropy_ok = 0;
uint8_t buf[ADD_ENTROPY];
/* OpenSSL has a RAND_poll function that knows about more kinds of
* entropy than we do. We'll try calling that, *and* calling our own entropy
* functions. If one succeeds, we'll accept the RNG as seeded. */
rand_poll_ok = RAND_poll();
if (rand_poll_ok == 0)
log_warn(LD_CRYPTO, "RAND_poll() failed."); // LCOV_EXCL_LINE
load_entropy_ok = !crypto_strongest_rand_raw(buf, sizeof(buf));
if (load_entropy_ok) {
RAND_seed(buf, sizeof(buf));
}
memwipe(buf, 0, sizeof(buf));
if ((rand_poll_ok || load_entropy_ok) && RAND_status() == 1)
return 0;
else
return -1;
}
/**
* Write <b>n</b> bytes of strong random data to <b>to</b>. Supports mocking
* for unit tests.
*
* This function is not allowed to fail; if it would fail to generate strong
* entropy, it must terminate the process instead.
**/
MOCK_IMPL(void,
crypto_rand, (char *to, size_t n))
{
crypto_rand_unmocked(to, n);
}
/**
* Write <b>n</b> bytes of strong random data to <b>to</b>. Most callers
* will want crypto_rand instead.
*
* This function is not allowed to fail; if it would fail to generate strong
* entropy, it must terminate the process instead.
**/
void
crypto_rand_unmocked(char *to, size_t n)
{
int r;
if (n == 0)
return;
tor_assert(n < INT_MAX);
tor_assert(to);
r = RAND_bytes((unsigned char*)to, (int)n);
/* We consider a PRNG failure non-survivable. Let's assert so that we get a
* stack trace about where it happened.
*/
tor_assert(r >= 0);
}
/**
* Return a pseudorandom integer, chosen uniformly from the values
* between 0 and <b>max</b>-1 inclusive. <b>max</b> must be between 1 and
* INT_MAX+1, inclusive.
*/
int
crypto_rand_int(unsigned int max)
{
unsigned int val;
unsigned int cutoff;
tor_assert(max <= ((unsigned int)INT_MAX)+1);
tor_assert(max > 0); /* don't div by 0 */
/* We ignore any values that are >= 'cutoff,' to avoid biasing the
* distribution with clipping at the upper end of unsigned int's
* range.
*/
cutoff = UINT_MAX - (UINT_MAX%max);
while (1) {
crypto_rand((char*)&val, sizeof(val));
if (val < cutoff)
return val % max;
}
}
/**
* Return a pseudorandom integer, chosen uniformly from the values i such
* that min <= i < max.
*
* <b>min</b> MUST be in range [0, <b>max</b>).
* <b>max</b> MUST be in range (min, INT_MAX].
**/
int
crypto_rand_int_range(unsigned int min, unsigned int max)
{
tor_assert(min < max);
tor_assert(max <= INT_MAX);
/* The overflow is avoided here because crypto_rand_int() returns a value
* between 0 and (max - min) inclusive. */
return min + crypto_rand_int(max - min);
}
/**
* As crypto_rand_int_range, but supports uint64_t.
**/
uint64_t
crypto_rand_uint64_range(uint64_t min, uint64_t max)
{
tor_assert(min < max);
return min + crypto_rand_uint64(max - min);
}
/**
* As crypto_rand_int_range, but supports time_t.
**/
time_t
crypto_rand_time_range(time_t min, time_t max)
{
tor_assert(min < max);
return min + (time_t)crypto_rand_uint64(max - min);
}
/**
* Return a pseudorandom 64-bit integer, chosen uniformly from the values
* between 0 and <b>max</b>-1 inclusive.
**/
uint64_t
crypto_rand_uint64(uint64_t max)
{
uint64_t val;
uint64_t cutoff;
tor_assert(max < UINT64_MAX);
tor_assert(max > 0); /* don't div by 0 */
/* We ignore any values that are >= 'cutoff,' to avoid biasing the
* distribution with clipping at the upper end of unsigned int's
* range.
*/
cutoff = UINT64_MAX - (UINT64_MAX%max);
while (1) {
crypto_rand((char*)&val, sizeof(val));
if (val < cutoff)
return val % max;
}
}
/**
* Return a pseudorandom double d, chosen uniformly from the range
* 0.0 <= d < 1.0.
**/
double
crypto_rand_double(void)
{
/* We just use an unsigned int here; we don't really care about getting
* more than 32 bits of resolution */
unsigned int u;
crypto_rand((char*)&u, sizeof(u));
#if SIZEOF_INT == 4
#define UINT_MAX_AS_DOUBLE 4294967296.0
#elif SIZEOF_INT == 8
#define UINT_MAX_AS_DOUBLE 1.8446744073709552e+19
#else
#error SIZEOF_INT is neither 4 nor 8
#endif /* SIZEOF_INT == 4 || ... */
return ((double)u) / UINT_MAX_AS_DOUBLE;
}
/**
* Generate and return a new random hostname starting with <b>prefix</b>,
* ending with <b>suffix</b>, and containing no fewer than
* <b>min_rand_len</b> and no more than <b>max_rand_len</b> random base32
* characters. Does not check for failure.
*
* Clip <b>max_rand_len</b> to MAX_DNS_LABEL_SIZE.
**/
char *
crypto_random_hostname(int min_rand_len, int max_rand_len, const char *prefix,
const char *suffix)
{
char *result, *rand_bytes;
int randlen, rand_bytes_len;
size_t resultlen, prefixlen;
if (max_rand_len > MAX_DNS_LABEL_SIZE)
max_rand_len = MAX_DNS_LABEL_SIZE;
if (min_rand_len > max_rand_len)
min_rand_len = max_rand_len;
randlen = crypto_rand_int_range(min_rand_len, max_rand_len+1);
prefixlen = strlen(prefix);
resultlen = prefixlen + strlen(suffix) + randlen + 16;
rand_bytes_len = ((randlen*5)+7)/8;
if (rand_bytes_len % 5)
rand_bytes_len += 5 - (rand_bytes_len%5);
rand_bytes = tor_malloc(rand_bytes_len);
crypto_rand(rand_bytes, rand_bytes_len);
result = tor_malloc(resultlen);
memcpy(result, prefix, prefixlen);
base32_encode(result+prefixlen, resultlen-prefixlen,
rand_bytes, rand_bytes_len);
tor_free(rand_bytes);
strlcpy(result+prefixlen+randlen, suffix, resultlen-(prefixlen+randlen));
return result;
}
/**
* Return a randomly chosen element of <b>sl</b>; or NULL if <b>sl</b>
* is empty.
**/
void *
smartlist_choose(const smartlist_t *sl)
{
int len = smartlist_len(sl);
if (len)
return smartlist_get(sl,crypto_rand_int(len));
return NULL; /* no elements to choose from */
}
/**
* Scramble the elements of <b>sl</b> into a random order.
**/
void
smartlist_shuffle(smartlist_t *sl)
{
int i;
/* From the end of the list to the front, choose at random from the
positions we haven't looked at yet, and swap that position into the
current position. Remember to give "no swap" the same probability as
any other swap. */
for (i = smartlist_len(sl)-1; i > 0; --i) {
int j = crypto_rand_int(i+1);
smartlist_swap(sl, i, j);
}
}
/** Make sure that openssl is using its default PRNG. Return 1 if we had to
* adjust it; 0 otherwise. */
int
crypto_force_rand_ssleay(void)
{
RAND_METHOD *default_method;
default_method = RAND_OpenSSL();
if (RAND_get_rand_method() != default_method) {
log_notice(LD_CRYPTO, "It appears that one of our engines has provided "
"a replacement the OpenSSL RNG. Resetting it to the default "
"implementation.");
RAND_set_rand_method(default_method);
return 1;
}
return 0;
}
#endif /* !defined(CRYPTO_RAND_PRIVATE) */

View File

@ -1,52 +0,0 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file crypto_rand.h
*
* \brief Common functions for using (pseudo-)random number generators.
**/
#ifndef TOR_CRYPTO_RAND_H
#define TOR_CRYPTO_RAND_H
#include "torint.h"
#include "util.h"
/* random numbers */
int crypto_seed_rng(void) ATTR_WUR;
MOCK_DECL(void,crypto_rand,(char *to, size_t n));
void crypto_rand_unmocked(char *to, size_t n);
void crypto_strongest_rand(uint8_t *out, size_t out_len);
int crypto_rand_int(unsigned int max);
int crypto_rand_int_range(unsigned int min, unsigned int max);
uint64_t crypto_rand_uint64_range(uint64_t min, uint64_t max);
time_t crypto_rand_time_range(time_t min, time_t max);
uint64_t crypto_rand_uint64(uint64_t max);
double crypto_rand_double(void);
struct tor_weak_rng_t;
void crypto_seed_weak_rng(struct tor_weak_rng_t *rng);
char *crypto_random_hostname(int min_rand_len, int max_rand_len,
const char *prefix, const char *suffix);
struct smartlist_t;
void *smartlist_choose(const struct smartlist_t *sl);
void smartlist_shuffle(struct smartlist_t *sl);
int crypto_force_rand_ssleay(void);
#ifdef CRYPTO_RAND_PRIVATE
STATIC int crypto_strongest_rand_raw(uint8_t *out, size_t out_len);
#ifdef TOR_UNIT_TESTS
extern int break_strongest_rng_syscall;
extern int break_strongest_rng_fallback;
#endif
#endif /* defined(CRYPTO_RAND_PRIVATE) */
#endif /* !defined(TOR_CRYPTO_RAND_H) */

View File

@ -9,14 +9,12 @@
* \brief Block of functions related with RSA utilities and operations.
**/
#include "crypto.h"
#include "crypto_curve25519.h"
#include "crypto_digest.h"
#include "crypto_format.h"
#include "compat_openssl.h"
#include "crypto_rand.h"
#include "crypto_rsa.h"
#include "crypto_util.h"
#include "crypto.h"
#include "compat_openssl.h"
#include "crypto_curve25519.h"
#include "crypto_ed25519.h"
#include "crypto_format.h"
DISABLE_GCC_WARNING(redundant-decls)
@ -629,148 +627,6 @@ crypto_pk_copy_full(crypto_pk_t *env)
return crypto_new_pk_from_rsa_(new_key);
}
/** Perform a hybrid (public/secret) encryption on <b>fromlen</b>
* bytes of data from <b>from</b>, with padding type 'padding',
* storing the results on <b>to</b>.
*
* Returns the number of bytes written on success, -1 on failure.
*
* The encrypted data consists of:
* - The source data, padded and encrypted with the public key, if the
* padded source data is no longer than the public key, and <b>force</b>
* is false, OR
* - The beginning of the source data prefixed with a 16-byte symmetric key,
* padded and encrypted with the public key; followed by the rest of
* the source data encrypted in AES-CTR mode with the symmetric key.
*
* NOTE that this format does not authenticate the symmetrically encrypted
* part of the data, and SHOULD NOT BE USED for new protocols.
*/
int
crypto_pk_obsolete_public_hybrid_encrypt(crypto_pk_t *env,
char *to, size_t tolen,
const char *from,
size_t fromlen,
int padding, int force)
{
int overhead, outlen, r;
size_t pkeylen, symlen;
crypto_cipher_t *cipher = NULL;
char *buf = NULL;
tor_assert(env);
tor_assert(from);
tor_assert(to);
tor_assert(fromlen < SIZE_T_CEILING);
overhead = crypto_get_rsa_padding_overhead(crypto_get_rsa_padding(padding));
pkeylen = crypto_pk_keysize(env);
if (!force && fromlen+overhead <= pkeylen) {
/* It all fits in a single encrypt. */
return crypto_pk_public_encrypt(env,to,
tolen,
from,fromlen,padding);
}
tor_assert(tolen >= fromlen + overhead + CIPHER_KEY_LEN);
tor_assert(tolen >= pkeylen);
char key[CIPHER_KEY_LEN];
crypto_rand(key, sizeof(key)); /* generate a new key. */
cipher = crypto_cipher_new(key);
buf = tor_malloc(pkeylen+1);
memcpy(buf, key, CIPHER_KEY_LEN);
memcpy(buf+CIPHER_KEY_LEN, from, pkeylen-overhead-CIPHER_KEY_LEN);
/* Length of symmetrically encrypted data. */
symlen = fromlen-(pkeylen-overhead-CIPHER_KEY_LEN);
outlen = crypto_pk_public_encrypt(env,to,tolen,buf,pkeylen-overhead,padding);
if (outlen!=(int)pkeylen) {
goto err;
}
r = crypto_cipher_encrypt(cipher, to+outlen,
from+pkeylen-overhead-CIPHER_KEY_LEN, symlen);
if (r<0) goto err;
memwipe(buf, 0, pkeylen);
memwipe(key, 0, sizeof(key));
tor_free(buf);
crypto_cipher_free(cipher);
tor_assert(outlen+symlen < INT_MAX);
return (int)(outlen + symlen);
err:
memwipe(buf, 0, pkeylen);
memwipe(key, 0, sizeof(key));
tor_free(buf);
crypto_cipher_free(cipher);
return -1;
}
/** Invert crypto_pk_obsolete_public_hybrid_encrypt. Returns the number of
* bytes written on success, -1 on failure.
*
* NOTE that this format does not authenticate the symmetrically encrypted
* part of the data, and SHOULD NOT BE USED for new protocols.
*/
int
crypto_pk_obsolete_private_hybrid_decrypt(crypto_pk_t *env,
char *to,
size_t tolen,
const char *from,
size_t fromlen,
int padding, int warnOnFailure)
{
int outlen, r;
size_t pkeylen;
crypto_cipher_t *cipher = NULL;
char *buf = NULL;
tor_assert(fromlen < SIZE_T_CEILING);
pkeylen = crypto_pk_keysize(env);
if (fromlen <= pkeylen) {
return crypto_pk_private_decrypt(env,to,tolen,from,fromlen,padding,
warnOnFailure);
}
buf = tor_malloc(pkeylen);
outlen = crypto_pk_private_decrypt(env,buf,pkeylen,from,pkeylen,padding,
warnOnFailure);
if (outlen<0) {
log_fn(warnOnFailure?LOG_WARN:LOG_DEBUG, LD_CRYPTO,
"Error decrypting public-key data");
goto err;
}
if (outlen < CIPHER_KEY_LEN) {
log_fn(warnOnFailure?LOG_WARN:LOG_INFO, LD_CRYPTO,
"No room for a symmetric key");
goto err;
}
cipher = crypto_cipher_new(buf);
if (!cipher) {
goto err;
}
memcpy(to,buf+CIPHER_KEY_LEN,outlen-CIPHER_KEY_LEN);
outlen -= CIPHER_KEY_LEN;
tor_assert(tolen - outlen >= fromlen - pkeylen);
r = crypto_cipher_decrypt(cipher, to+outlen, from+pkeylen, fromlen-pkeylen);
if (r<0)
goto err;
memwipe(buf,0,pkeylen);
tor_free(buf);
crypto_cipher_free(cipher);
tor_assert(outlen + fromlen < INT_MAX);
return (int)(outlen + (fromlen-pkeylen));
err:
memwipe(buf,0,pkeylen);
tor_free(buf);
crypto_cipher_free(cipher);
return -1;
}
/** Encrypt <b>fromlen</b> bytes from <b>from</b> with the public key
* in <b>env</b>, using the padding method <b>padding</b>. On success,
* write the result to <b>to</b>, and return the number of bytes
@ -993,122 +849,6 @@ crypto_pk_get_hashed_fingerprint(crypto_pk_t *pk, char *fp_out)
return 0;
}
/** Check a siglen-byte long signature at <b>sig</b> against
* <b>datalen</b> bytes of data at <b>data</b>, using the public key
* in <b>env</b>. Return 0 if <b>sig</b> is a correct signature for
* SHA1(data). Else return -1.
*/
MOCK_IMPL(int,
crypto_pk_public_checksig_digest,(crypto_pk_t *env, const char *data,
size_t datalen, const char *sig,
size_t siglen))
{
char digest[DIGEST_LEN];
char *buf;
size_t buflen;
int r;
tor_assert(env);
tor_assert(data);
tor_assert(sig);
tor_assert(datalen < SIZE_T_CEILING);
tor_assert(siglen < SIZE_T_CEILING);
if (crypto_digest(digest,data,datalen)<0) {
log_warn(LD_BUG, "couldn't compute digest");
return -1;
}
buflen = crypto_pk_keysize(env);
buf = tor_malloc(buflen);
r = crypto_pk_public_checksig(env,buf,buflen,sig,siglen);
if (r != DIGEST_LEN) {
log_warn(LD_CRYPTO, "Invalid signature");
tor_free(buf);
return -1;
}
if (tor_memneq(buf, digest, DIGEST_LEN)) {
log_warn(LD_CRYPTO, "Signature mismatched with digest.");
tor_free(buf);
return -1;
}
tor_free(buf);
return 0;
}
/** Compute a SHA1 digest of <b>fromlen</b> bytes of data stored at
* <b>from</b>; sign the data with the private key in <b>env</b>, and
* store it in <b>to</b>. Return the number of bytes written on
* success, and -1 on failure.
*
* <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
* at least the length of the modulus of <b>env</b>.
*/
int
crypto_pk_private_sign_digest(crypto_pk_t *env, char *to, size_t tolen,
const char *from, size_t fromlen)
{
int r;
char digest[DIGEST_LEN];
if (crypto_digest(digest,from,fromlen)<0)
return -1;
r = crypto_pk_private_sign(env,to,tolen,digest,DIGEST_LEN);
memwipe(digest, 0, sizeof(digest));
return r;
}
/** Given a private or public key <b>pk</b>, put a SHA1 hash of the
* public key into <b>digest_out</b> (must have DIGEST_LEN bytes of space).
* Return 0 on success, -1 on failure.
*/
int
crypto_pk_get_digest(const crypto_pk_t *pk, char *digest_out)
{
char *buf;
size_t buflen;
int len;
int rv = -1;
buflen = crypto_pk_keysize(pk)*2;
buf = tor_malloc(buflen);
len = crypto_pk_asn1_encode(pk, buf, buflen);
if (len < 0)
goto done;
if (crypto_digest(digest_out, buf, len) < 0)
goto done;
rv = 0;
done:
tor_free(buf);
return rv;
}
/** Compute all digests of the DER encoding of <b>pk</b>, and store them
* in <b>digests_out</b>. Return 0 on success, -1 on failure. */
int
crypto_pk_get_common_digests(crypto_pk_t *pk, common_digests_t *digests_out)
{
char *buf;
size_t buflen;
int len;
int rv = -1;
buflen = crypto_pk_keysize(pk)*2;
buf = tor_malloc(buflen);
len = crypto_pk_asn1_encode(pk, buf, buflen);
if (len < 0)
goto done;
if (crypto_common_digests(digests_out, (char*)buf, len) < 0)
goto done;
rv = 0;
done:
tor_free(buf);
return rv;
}
/** Given a crypto_pk_t <b>pk</b>, allocate a new buffer containing the
* Base64 encoding of the DER representation of the private key as a NUL
* terminated string, and return it via <b>priv_out</b>. Return 0 on

View File

@ -15,13 +15,13 @@
#include "orconfig.h"
#include "crypto_digest.h"
#include <stdio.h>
#include "torint.h"
#include "testsupport.h"
#include "compat.h"
#include "util.h"
#include "torlog.h"
#include "crypto_curve25519.h"
/** Length of our public keys. */
#define PK_BYTES (1024/8)
@ -35,7 +35,7 @@
/** A public key, or a public/private key-pair. */
typedef struct crypto_pk_t crypto_pk_t;
/* RSA environment setup */
/* RSA enviroment setup */
MOCK_DECL(crypto_pk_t *,crypto_pk_new,(void));
void crypto_pk_free_(crypto_pk_t *env);
#define crypto_pk_free(pk) FREE_AND_NULL(crypto_pk_t, crypto_pk_free_, (pk))
@ -69,14 +69,6 @@ crypto_pk_t *crypto_pk_dup_key(crypto_pk_t *orig);
crypto_pk_t *crypto_pk_copy_full(crypto_pk_t *orig);
int crypto_pk_key_is_private(const crypto_pk_t *key);
int crypto_pk_public_exponent_ok(crypto_pk_t *env);
int crypto_pk_obsolete_public_hybrid_encrypt(crypto_pk_t *env, char *to,
size_t tolen,
const char *from, size_t fromlen,
int padding, int force);
int crypto_pk_obsolete_private_hybrid_decrypt(crypto_pk_t *env, char *to,
size_t tolen,
const char *from, size_t fromlen,
int padding, int warnOnFailure);
int crypto_pk_public_encrypt(crypto_pk_t *env, char *to, size_t tolen,
const char *from, size_t fromlen, int padding);
int crypto_pk_private_decrypt(crypto_pk_t *env, char *to, size_t tolen,
@ -92,13 +84,6 @@ crypto_pk_t *crypto_pk_asn1_decode(const char *str, size_t len);
int crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out,int add_space);
int crypto_pk_get_hashed_fingerprint(crypto_pk_t *pk, char *fp_out);
MOCK_DECL(int, crypto_pk_public_checksig_digest,(crypto_pk_t *env,
const char *data, size_t datalen, const char *sig, size_t siglen));
int crypto_pk_private_sign_digest(crypto_pk_t *env, char *to, size_t tolen,
const char *from, size_t fromlen);
int crypto_pk_get_digest(const crypto_pk_t *pk, char *digest_out);
int crypto_pk_get_common_digests(crypto_pk_t *pk,
common_digests_t *digests_out);
int crypto_pk_base64_encode(const crypto_pk_t *pk, char **priv_out);
crypto_pk_t *crypto_pk_base64_decode(const char *str, size_t len);

View File

@ -12,13 +12,10 @@
#define CRYPTO_S2K_PRIVATE
#include "compat.h"
#include "crypto.h"
#include "crypto_digest.h"
#include "crypto_rand.h"
#include "crypto_s2k.h"
#include "crypto_util.h"
#include "util.h"
#include "compat.h"
#include "crypto_s2k.h"
#include <openssl/evp.h>

View File

@ -1,107 +0,0 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file crypto_util.c
*
* \brief Common cryptographic utilities.
**/
#ifndef CRYPTO_UTIL_PRIVATE
#define CRYPTO_UTIL_PRIVATE
#include "crypto_util.h"
#include <string.h>
#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#include <wincrypt.h>
#endif /* defined(_WIN32) */
#include "util.h"
DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/crypto.h>
ENABLE_GCC_WARNING(redundant-decls)
/**
* Destroy the <b>sz</b> bytes of data stored at <b>mem</b>, setting them to
* the value <b>byte</b>.
* If <b>mem</b> is NULL or <b>sz</b> is zero, nothing happens.
*
* This function is preferable to memset, since many compilers will happily
* optimize out memset() when they can convince themselves that the data being
* cleared will never be read.
*
* Right now, our convention is to use this function when we are wiping data
* that's about to become inaccessible, such as stack buffers that are about
* to go out of scope or structures that are about to get freed. (In
* practice, it appears that the compilers we're currently using will optimize
* out the memset()s for stack-allocated buffers, but not those for
* about-to-be-freed structures. That could change, though, so we're being
* wary.) If there are live reads for the data, then you can just use
* memset().
*/
void
memwipe(void *mem, uint8_t byte, size_t sz)
{
if (sz == 0) {
return;
}
/* If sz is nonzero, then mem must not be NULL. */
tor_assert(mem != NULL);
/* Data this large is likely to be an underflow. */
tor_assert(sz < SIZE_T_CEILING);
/* Because whole-program-optimization exists, we may not be able to just
* have this function call "memset". A smart compiler could inline it, then
* eliminate dead memsets, and declare itself to be clever. */
#if defined(SecureZeroMemory) || defined(HAVE_SECUREZEROMEMORY)
/* Here's what you do on windows. */
SecureZeroMemory(mem,sz);
#elif defined(HAVE_RTLSECUREZEROMEMORY)
RtlSecureZeroMemory(mem,sz);
#elif defined(HAVE_EXPLICIT_BZERO)
/* The BSDs provide this. */
explicit_bzero(mem, sz);
#elif defined(HAVE_MEMSET_S)
/* This is in the C99 standard. */
memset_s(mem, sz, 0, sz);
#else
/* This is a slow and ugly function from OpenSSL that fills 'mem' with junk
* based on the pointer value, then uses that junk to update a global
* variable. It's an elaborate ruse to trick the compiler into not
* optimizing out the "wipe this memory" code. Read it if you like zany
* programming tricks! In later versions of Tor, we should look for better
* not-optimized-out memory wiping stuff...
*
* ...or maybe not. In practice, there are pure-asm implementations of
* OPENSSL_cleanse() on most platforms, which ought to do the job.
**/
OPENSSL_cleanse(mem, sz);
#endif /* defined(SecureZeroMemory) || defined(HAVE_SECUREZEROMEMORY) || ... */
/* Just in case some caller of memwipe() is relying on getting a buffer
* filled with a particular value, fill the buffer.
*
* If this function gets inlined, this memset might get eliminated, but
* that's okay: We only care about this particular memset in the case where
* the caller should have been using memset(), and the memset() wouldn't get
* eliminated. In other words, this is here so that we won't break anything
* if somebody accidentally calls memwipe() instead of memset().
**/
memset(mem, byte, sz);
}
#endif /* !defined(CRYPTO_UTIL_PRIVATE) */

View File

@ -1,27 +0,0 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file crypto_util.h
*
* \brief Common functions for cryptographic routines.
**/
#ifndef TOR_CRYPTO_UTIL_H
#define TOR_CRYPTO_UTIL_H
#include "torint.h"
/** OpenSSL-based utility functions. */
void memwipe(void *mem, uint8_t byte, size_t sz);
#ifdef CRYPTO_UTIL_PRIVATE
#ifdef TOR_UNIT_TESTS
#endif /* defined(TOR_UNIT_TESTS) */
#endif /* defined(CRYPTO_UTIL_PRIVATE) */
#endif /* !defined(TOR_CRYPTO_UTIL_H) */

View File

@ -97,7 +97,6 @@ LIBOR_A_SRC = \
src/common/util_process.c \
src/common/sandbox.c \
src/common/storagedir.c \
src/common/token_bucket.c \
src/common/workqueue.c \
$(libor_extra_source) \
$(threads_impl_source) \
@ -115,14 +114,11 @@ LIBOR_CRYPTO_A_SRC = \
src/common/compress_zlib.c \
src/common/compress_zstd.c \
src/common/crypto.c \
src/common/crypto_digest.c \
src/common/crypto_format.c \
src/common/crypto_rsa.c \
src/common/crypto_openssl_mgt.c \
src/common/crypto_pwbox.c \
src/common/crypto_rand.c \
src/common/crypto_rsa.c \
src/common/crypto_s2k.c \
src/common/crypto_util.c \
src/common/crypto_format.c \
src/common/tortls.c \
src/common/crypto_curve25519.c \
src/common/crypto_ed25519.c
@ -169,16 +165,13 @@ COMMONHEADERS = \
src/common/confline.h \
src/common/container.h \
src/common/crypto.h \
src/common/crypto_digest.h \
src/common/crypto_curve25519.h \
src/common/crypto_ed25519.h \
src/common/crypto_format.h \
src/common/crypto_openssl_mgt.h \
src/common/crypto_pwbox.h \
src/common/crypto_rand.h \
src/common/crypto_rsa.h \
src/common/crypto_pwbox.h \
src/common/crypto_s2k.h \
src/common/crypto_util.h \
src/common/di_ops.h \
src/common/handles.h \
src/common/memarea.h \
@ -189,7 +182,6 @@ COMMONHEADERS = \
src/common/storagedir.h \
src/common/testsupport.h \
src/common/timers.h \
src/common/token_bucket.h \
src/common/torint.h \
src/common/torlog.h \
src/common/tortls.h \

View File

@ -52,13 +52,6 @@
#define raw_assert(x) assert(x) // assert OK
/** Defining compile-time constants for Tor log levels (used by the Rust
* log wrapper at src/rust/tor_log) */
const int LOG_WARN_ = LOG_WARN;
const int LOG_NOTICE_ = LOG_NOTICE;
const log_domain_mask_t LD_GENERAL_ = LD_GENERAL;
const log_domain_mask_t LD_NET_ = LD_NET;
/** Information for a single logfile; only used in log.c */
typedef struct logfile_t {
struct logfile_t *next; /**< Next logfile_t in the linked list. */
@ -170,9 +163,6 @@ typedef struct pending_log_message_t {
/** Log messages waiting to be replayed onto callback-based logs */
static smartlist_t *pending_cb_messages = NULL;
/** Callback to invoke when pending_cb_messages becomes nonempty. */
static pending_callback_callback pending_cb_cb = NULL;
/** Log messages waiting to be replayed once the logging system is initialized.
*/
static smartlist_t *pending_startup_messages = NULL;
@ -235,30 +225,6 @@ log_set_application_name(const char *name)
appname = name ? tor_strdup(name) : NULL;
}
/** Return true if some of the running logs might be interested in a log
* message of the given severity in the given domains. If this function
* returns true, the log message might be ignored anyway, but if it returns
* false, it is definitely_ safe not to log the message. */
int
log_message_is_interesting(int severity, log_domain_mask_t domain)
{
(void) domain;
return (severity <= log_global_min_severity_);
}
/**
* As tor_log, but takes an optional function name, and does not treat its
* <b>string</b> as a printf format.
*
* For use by Rust integration.
*/
void
tor_log_string(int severity, log_domain_mask_t domain,
const char *function, const char *string)
{
log_fn_(severity, domain, function, "%s", string);
}
/** Log time granularity in milliseconds. */
static int log_time_granularity = 1;
@ -541,9 +507,6 @@ logfile_deliver(logfile_t *lf, const char *buf, size_t msg_len,
smartlist_add(pending_cb_messages,
pending_log_message_new(severity,domain,NULL,msg_after_prefix));
*callbacks_deferred = 1;
if (smartlist_len(pending_cb_messages) == 1 && pending_cb_cb) {
pending_cb_cb();
}
}
} else {
lf->callback(severity, domain, msg_after_prefix);
@ -831,7 +794,6 @@ logs_free_all(void)
logfiles = NULL;
messages = pending_cb_messages;
pending_cb_messages = NULL;
pending_cb_cb = NULL;
messages2 = pending_startup_messages;
pending_startup_messages = NULL;
UNLOCK_LOGS();
@ -994,24 +956,6 @@ add_temp_log(int min_severity)
UNLOCK_LOGS();
}
/**
* Register "cb" as the callback to call when there are new pending log
* callbacks to be flushed with flush_pending_log_callbacks().
*
* Note that this callback, if present, can be invoked from any thread.
*
* This callback must not log.
*
* It is intentional that this function contains the name "callback" twice: it
* sets a "callback" to be called on the condition that there is a "pending
* callback".
**/
void
logs_set_pending_callback_callback(pending_callback_callback cb)
{
pending_cb_cb = cb;
}
/**
* Add a log handler to send messages in <b>severity</b>
* to the function <b>cb</b>.

View File

@ -10,6 +10,8 @@
#include "util.h"
#include <event2/event.h>
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
@ -42,7 +44,7 @@ typedef int pid_t;
/* Currently we need to poll in some way on all systems. */
#ifdef PROCMON_POLLS
static void tor_process_monitor_poll_cb(periodic_timer_t *ev,
static void tor_process_monitor_poll_cb(evutil_socket_t unused1, short unused2,
void *procmon_);
#endif
@ -134,7 +136,7 @@ struct tor_process_monitor_t {
/** A Libevent event structure, to either poll for the process's
* existence or receive a notification when the process ends. */
periodic_timer_t *e;
struct event *e;
/** A callback to be called when the process ends. */
tor_procmon_callback_t cb;
@ -157,6 +159,9 @@ tor_validate_process_specifier(const char *process_spec,
return parse_process_specifier(process_spec, &ppspec, msg);
}
/* XXXX we should use periodic_timer_new() for this stuff */
#define PERIODIC_TIMER_FLAGS EV_PERSIST
/* DOCDOC poll_interval_tv */
static const struct timeval poll_interval_tv = {15, 0};
@ -220,9 +225,13 @@ tor_process_monitor_new(struct event_base *base,
procmon->cb_arg = cb_arg;
#ifdef PROCMON_POLLS
procmon->e = periodic_timer_new(base,
&poll_interval_tv,
tor_process_monitor_poll_cb, procmon);
procmon->e = tor_event_new(base, -1 /* no FD */, PERIODIC_TIMER_FLAGS,
tor_process_monitor_poll_cb, procmon);
/* Note: If you port this file to plain Libevent 2, check that
* procmon->e is non-NULL. We don't need to here because
* tor_evtimer_new never returns NULL. */
evtimer_add(procmon->e, &poll_interval_tv);
#else /* !(defined(PROCMON_POLLS)) */
#error OOPS?
#endif /* defined(PROCMON_POLLS) */
@ -237,12 +246,14 @@ tor_process_monitor_new(struct event_base *base,
/** Libevent callback to poll for the existence of the process
* monitored by <b>procmon_</b>. */
static void
tor_process_monitor_poll_cb(periodic_timer_t *event, void *procmon_)
tor_process_monitor_poll_cb(evutil_socket_t unused1, short unused2,
void *procmon_)
{
(void)event;
tor_process_monitor_t *procmon = (tor_process_monitor_t *)(procmon_);
int its_dead_jim;
(void)unused1; (void)unused2;
tor_assert(procmon != NULL);
#ifdef _WIN32
@ -325,7 +336,7 @@ tor_process_monitor_free_(tor_process_monitor_t *procmon)
#endif
if (procmon->e != NULL)
periodic_timer_free(procmon->e);
tor_event_free(procmon->e);
tor_free(procmon);
}

View File

@ -37,6 +37,8 @@
#include "torlog.h"
#include "util.h"
#include <event2/event.h>
struct timeout_cb {
timer_cb_fn_t cb;
void *arg;
@ -64,15 +66,10 @@ struct timeout_cb {
* above TIMEOUT_MAX can also be super-inefficient. Choosing 5 here sets
* timeout_max to 2^30 ticks, or 29 hours with our value for USEC_PER_TICK */
#define WHEEL_NUM 5
#if SIZEOF_VOID_P == 4
/* On 32-bit platforms, we want to override wheel_bit, so that timeout.c will
* use 32-bit math. */
#define WHEEL_BIT 5
#endif
#include "src/ext/timeouts/timeout.c"
static struct timeouts *global_timeouts = NULL;
static struct mainloop_event_t *global_timer_event = NULL;
static struct event *global_timer_event = NULL;
static monotime_t start_of_time;
@ -150,7 +147,7 @@ libevent_timer_reschedule(void)
if (delay > MIN_CHECK_TICKS)
delay = MIN_CHECK_TICKS;
timeout_to_tv(delay, &d);
mainloop_event_schedule(global_timer_event, &d);
event_add(global_timer_event, &d);
}
/** Run the callback of every timer that has expired, based on the current
@ -173,9 +170,10 @@ timers_run_pending(void)
* have fired, activate their callbacks, and reschedule the libevent timer.
*/
static void
libevent_timer_callback(mainloop_event_t *ev, void *arg)
libevent_timer_callback(evutil_socket_t fd, short what, void *arg)
{
(void)ev;
(void)fd;
(void)what;
(void)arg;
timers_run_pending();
@ -205,8 +203,9 @@ timers_initialize(void)
monotime_init();
monotime_get(&start_of_time);
mainloop_event_t *timer_event;
timer_event = mainloop_event_new(libevent_timer_callback, NULL);
struct event *timer_event;
timer_event = tor_event_new(tor_libevent_get_base(),
-1, 0, libevent_timer_callback, NULL);
tor_assert(timer_event);
global_timer_event = timer_event;
@ -220,7 +219,7 @@ void
timers_shutdown(void)
{
if (global_timer_event) {
mainloop_event_free(global_timer_event);
tor_event_free(global_timer_event);
global_timer_event = NULL;
}
if (global_timeouts) {

View File

@ -1,255 +0,0 @@
/* Copyright (c) 2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file token_bucket.c
* \brief Functions to use and manipulate token buckets, used for
* rate-limiting on connections and globally.
*
* Tor uses these token buckets to keep track of bandwidth usage, and
* sometimes other things too.
*
* There are two layers of abstraction here: "raw" token buckets, in which all
* the pieces are decoupled, and "read-write" token buckets, which combine all
* the moving parts into one.
*
* Token buckets may become negative.
**/
#define TOKEN_BUCKET_PRIVATE
#include "token_bucket.h"
#include "util_bug.h"
/**
* Set the <b>rate</b> and <b>burst</b> value in a token_bucket_cfg.
*
* Note that the <b>rate</b> value is in arbitrary units, but those units will
* determine the units of token_bucket_raw_dec(), token_bucket_raw_refill, and
* so on.
*/
void
token_bucket_cfg_init(token_bucket_cfg_t *cfg,
uint32_t rate,
uint32_t burst)
{
tor_assert_nonfatal(rate > 0);
tor_assert_nonfatal(burst > 0);
if (burst > TOKEN_BUCKET_MAX_BURST)
burst = TOKEN_BUCKET_MAX_BURST;
cfg->rate = rate;
cfg->burst = burst;
}
/**
* Initialize a raw token bucket and its associated timestamp to the "full"
* state, according to <b>cfg</b>.
*/
void
token_bucket_raw_reset(token_bucket_raw_t *bucket,
const token_bucket_cfg_t *cfg)
{
bucket->bucket = cfg->burst;
}
/**
* Adust a preexisting token bucket to respect the new configuration
* <b>cfg</b>, by decreasing its current level if needed. */
void
token_bucket_raw_adjust(token_bucket_raw_t *bucket,
const token_bucket_cfg_t *cfg)
{
bucket->bucket = MIN(bucket->bucket, cfg->burst);
}
/**
* Given an amount of <b>elapsed</b> time units, and a bucket configuration
* <b>cfg</b>, refill the level of <b>bucket</b> accordingly. Note that the
* units of time in <b>elapsed</b> must correspond to those used to set the
* rate in <b>cfg</b>, or the result will be illogical.
*/
int
token_bucket_raw_refill_steps(token_bucket_raw_t *bucket,
const token_bucket_cfg_t *cfg,
const uint32_t elapsed)
{
const int was_empty = (bucket->bucket <= 0);
/* The casts here prevent an underflow.
*
* Note that even if the bucket value is negative, subtracting it from
* "burst" will still produce a correct result. If this result is
* ridiculously high, then the "elapsed > gap / rate" check below
* should catch it. */
const size_t gap = ((size_t)cfg->burst) - ((size_t)bucket->bucket);
if (elapsed > gap / cfg->rate) {
bucket->bucket = cfg->burst;
} else {
bucket->bucket += cfg->rate * elapsed;
}
return was_empty && bucket->bucket > 0;
}
/**
* Decrement a provided bucket by <b>n</b> units. Note that <b>n</b>
* must be nonnegative.
*/
int
token_bucket_raw_dec(token_bucket_raw_t *bucket,
ssize_t n)
{
if (BUG(n < 0))
return 0;
const int becomes_empty = bucket->bucket > 0 && n >= bucket->bucket;
bucket->bucket -= n;
return becomes_empty;
}
/** Convert a rate in bytes per second to a rate in bytes per step */
STATIC uint32_t
rate_per_sec_to_rate_per_step(uint32_t rate)
{
/*
The precise calculation we'd want to do is
(rate / 1000) * to_approximate_msec(TICKS_PER_STEP). But to minimize
rounding error, we do it this way instead, and divide last.
*/
uint64_t units = (uint64_t) rate * TICKS_PER_STEP;
uint32_t val = (uint32_t)
(monotime_coarse_stamp_units_to_approx_msec(units) / 1000);
return val ? val : 1;
}
/**
* Initialize a token bucket in *<b>bucket</b>, set up to allow <b>rate</b>
* bytes per second, with a maximum burst of <b>burst</b> bytes. The bucket
* is created such that <b>now_ts</b> is the current timestamp. The bucket
* starts out full.
*/
void
token_bucket_rw_init(token_bucket_rw_t *bucket,
uint32_t rate,
uint32_t burst,
uint32_t now_ts)
{
memset(bucket, 0, sizeof(token_bucket_rw_t));
token_bucket_rw_adjust(bucket, rate, burst);
token_bucket_rw_reset(bucket, now_ts);
}
/**
* Change the configured rate (in bytes per second) and burst (in bytes)
* for the token bucket in *<b>bucket</b>.
*/
void
token_bucket_rw_adjust(token_bucket_rw_t *bucket,
uint32_t rate,
uint32_t burst)
{
token_bucket_cfg_init(&bucket->cfg,
rate_per_sec_to_rate_per_step(rate),
burst);
token_bucket_raw_adjust(&bucket->read_bucket, &bucket->cfg);
token_bucket_raw_adjust(&bucket->write_bucket, &bucket->cfg);
}
/**
* Reset <b>bucket</b> to be full, as of timestamp <b>now_ts</b>.
*/
void
token_bucket_rw_reset(token_bucket_rw_t *bucket,
uint32_t now_ts)
{
token_bucket_raw_reset(&bucket->read_bucket, &bucket->cfg);
token_bucket_raw_reset(&bucket->write_bucket, &bucket->cfg);
bucket->last_refilled_at_timestamp = now_ts;
}
/**
* Refill <b>bucket</b> as appropriate, given that the current timestamp
* is <b>now_ts</b>.
*
* Return a bitmask containing TB_READ iff read bucket was empty and became
* nonempty, and TB_WRITE iff the write bucket was empty and became nonempty.
*/
int
token_bucket_rw_refill(token_bucket_rw_t *bucket,
uint32_t now_ts)
{
const uint32_t elapsed_ticks =
(now_ts - bucket->last_refilled_at_timestamp);
if (elapsed_ticks > UINT32_MAX-(300*1000)) {
/* Either about 48 days have passed since the last refill, or the
* monotonic clock has somehow moved backwards. (We're looking at you,
* Windows.). We accept up to a 5 minute jump backwards as
* "unremarkable".
*/
return 0;
}
const uint32_t elapsed_steps = elapsed_ticks / TICKS_PER_STEP;
if (!elapsed_steps) {
/* Note that if less than one whole step elapsed, we don't advance the
* time in last_refilled_at. That's intentional: we want to make sure
* that we add some bytes to it eventually. */
return 0;
}
int flags = 0;
if (token_bucket_raw_refill_steps(&bucket->read_bucket,
&bucket->cfg, elapsed_steps))
flags |= TB_READ;
if (token_bucket_raw_refill_steps(&bucket->write_bucket,
&bucket->cfg, elapsed_steps))
flags |= TB_WRITE;
bucket->last_refilled_at_timestamp = now_ts;
return flags;
}
/**
* Decrement the read token bucket in <b>bucket</b> by <b>n</b> bytes.
*
* Return true if the bucket was nonempty and became empty; return false
* otherwise.
*/
int
token_bucket_rw_dec_read(token_bucket_rw_t *bucket,
ssize_t n)
{
return token_bucket_raw_dec(&bucket->read_bucket, n);
}
/**
* Decrement the write token bucket in <b>bucket</b> by <b>n</b> bytes.
*
* Return true if the bucket was nonempty and became empty; return false
* otherwise.
*/
int
token_bucket_rw_dec_write(token_bucket_rw_t *bucket,
ssize_t n)
{
return token_bucket_raw_dec(&bucket->write_bucket, n);
}
/**
* As token_bucket_rw_dec_read and token_bucket_rw_dec_write, in a single
* operation. Return a bitmask of TB_READ and TB_WRITE to indicate
* which buckets became empty.
*/
int
token_bucket_rw_dec(token_bucket_rw_t *bucket,
ssize_t n_read, ssize_t n_written)
{
int flags = 0;
if (token_bucket_rw_dec_read(bucket, n_read))
flags |= TB_READ;
if (token_bucket_rw_dec_write(bucket, n_written))
flags |= TB_WRITE;
return flags;
}

View File

@ -1,118 +0,0 @@
/* Copyright (c) 2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file token_bucket_rw.h
* \brief Headers for token_bucket_rw.c
**/
#ifndef TOR_TOKEN_BUCKET_H
#define TOR_TOKEN_BUCKET_H
#include "torint.h"
#include "testsupport.h"
/** Largest allowable burst value for a token buffer. */
#define TOKEN_BUCKET_MAX_BURST INT32_MAX
/** A generic token buffer configuration: determines the number of tokens
* added to the bucket in each time unit (the "rate"), and the maximum number
* of tokens in the bucket (the "burst") */
typedef struct token_bucket_cfg_t {
uint32_t rate;
int32_t burst;
} token_bucket_cfg_t;
/** A raw token bucket, decoupled from its configuration and timestamp. */
typedef struct token_bucket_raw_t {
int32_t bucket;
} token_bucket_raw_t;
void token_bucket_cfg_init(token_bucket_cfg_t *cfg,
uint32_t rate,
uint32_t burst);
void token_bucket_raw_adjust(token_bucket_raw_t *bucket,
const token_bucket_cfg_t *cfg);
void token_bucket_raw_reset(token_bucket_raw_t *bucket,
const token_bucket_cfg_t *cfg);
int token_bucket_raw_dec(token_bucket_raw_t *bucket,
ssize_t n);
int token_bucket_raw_refill_steps(token_bucket_raw_t *bucket,
const token_bucket_cfg_t *cfg,
const uint32_t elapsed_steps);
static inline size_t token_bucket_raw_get(const token_bucket_raw_t *bucket);
/** Return the current number of bytes set in a token bucket. */
static inline size_t
token_bucket_raw_get(const token_bucket_raw_t *bucket)
{
return bucket->bucket >= 0 ? bucket->bucket : 0;
}
/** A convenience type containing all the pieces needed for a coupled
* read-bucket and write-bucket that have the same rate limit, and which use
* "timestamp units" (see compat_time.h) for their time. */
typedef struct token_bucket_rw_t {
token_bucket_cfg_t cfg;
token_bucket_raw_t read_bucket;
token_bucket_raw_t write_bucket;
uint32_t last_refilled_at_timestamp;
} token_bucket_rw_t;
void token_bucket_rw_init(token_bucket_rw_t *bucket,
uint32_t rate,
uint32_t burst,
uint32_t now_ts);
void token_bucket_rw_adjust(token_bucket_rw_t *bucket,
uint32_t rate, uint32_t burst);
void token_bucket_rw_reset(token_bucket_rw_t *bucket,
uint32_t now_ts);
#define TB_READ 1
#define TB_WRITE 2
int token_bucket_rw_refill(token_bucket_rw_t *bucket,
uint32_t now_ts);
int token_bucket_rw_dec_read(token_bucket_rw_t *bucket,
ssize_t n);
int token_bucket_rw_dec_write(token_bucket_rw_t *bucket,
ssize_t n);
int token_bucket_rw_dec(token_bucket_rw_t *bucket,
ssize_t n_read, ssize_t n_written);
static inline size_t token_bucket_rw_get_read(const token_bucket_rw_t *bucket);
static inline size_t
token_bucket_rw_get_read(const token_bucket_rw_t *bucket)
{
return token_bucket_raw_get(&bucket->read_bucket);
}
static inline size_t token_bucket_rw_get_write(
const token_bucket_rw_t *bucket);
static inline size_t
token_bucket_rw_get_write(const token_bucket_rw_t *bucket)
{
return token_bucket_raw_get(&bucket->write_bucket);
}
#ifdef TOKEN_BUCKET_PRIVATE
/* To avoid making the rates too small, we consider units of "steps",
* where a "step" is defined as this many timestamp ticks. Keep this
* a power of two if you can. */
#define TICKS_PER_STEP 16
STATIC uint32_t rate_per_sec_to_rate_per_step(uint32_t rate);
#endif
#endif /* TOR_TOKEN_BUCKET_H */

View File

@ -40,8 +40,6 @@
#include <inttypes.h>
#endif
#include <stdbool.h>
#if (SIZEOF_INT8_T != 0)
#define HAVE_INT8_T
#endif

View File

@ -154,8 +154,6 @@ int add_android_log(const log_severity_list_t *severity,
const char *android_identity_tag);
#endif // HAVE_ANDROID_LOG_H.
int add_callback_log(const log_severity_list_t *severity, log_callback cb);
typedef void (*pending_callback_callback)(void);
void logs_set_pending_callback_callback(pending_callback_callback cb);
void logs_set_domain_logging(int enabled);
int get_min_log_level(void);
void switch_logs_debug(void);
@ -193,10 +191,6 @@ void log_fn_ratelim_(struct ratelim_t *ratelim, int severity,
const char *format, ...)
CHECK_PRINTF(5,6);
int log_message_is_interesting(int severity, log_domain_mask_t domain);
void tor_log_string(int severity, log_domain_mask_t domain,
const char *function, const char *string);
#if defined(__GNUC__) && __GNUC__ <= 3
/* These are the GCC varidaic macros, so that older versions of GCC don't
@ -254,16 +248,6 @@ void tor_log_string(int severity, log_domain_mask_t domain,
args, ##__VA_ARGS__)
#endif /* defined(__GNUC__) && __GNUC__ <= 3 */
/** This defines log levels that are linked in the Rust log module, rather
* than re-defining these in both Rust and C.
*
* C_RUST_COUPLED src/rust/tor_log LogSeverity, LogDomain
*/
extern const int LOG_WARN_;
extern const int LOG_NOTICE_;
extern const log_domain_mask_t LD_NET_;
extern const log_domain_mask_t LD_GENERAL_;
#ifdef LOG_PRIVATE
MOCK_DECL(STATIC void, logv, (int severity, log_domain_mask_t domain,
const char *funcname, const char *suffix, const char *format,

View File

@ -25,9 +25,6 @@
#include <ws2tcpip.h>
#endif
#include "crypto.h"
#include "crypto_rand.h"
#include "crypto_util.h"
#include "compat.h"
/* Some versions of OpenSSL declare SSL_get_selected_srtp_profile twice in
@ -35,6 +32,7 @@
DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/opensslv.h>
#include "crypto.h"
#ifdef OPENSSL_NO_EC
#error "We require OpenSSL with ECC support"
@ -58,25 +56,10 @@ ENABLE_GCC_WARNING(redundant-decls)
#include "container.h"
#include <string.h>
#ifdef OPENSSL_1_1_API
#define X509_get_notBefore_const(cert) \
X509_get0_notBefore(cert)
#define X509_get_notAfter_const(cert) \
X509_get0_notAfter(cert)
#ifndef X509_get_notBefore
#define X509_get_notBefore(cert) \
X509_getm_notBefore(cert)
#endif
#ifndef X509_get_notAfter
#define X509_get_notAfter(cert) \
X509_getm_notAfter(cert)
#endif
#else /* ! OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) */
#define X509_get_notBefore_const(cert) \
((const ASN1_TIME*) X509_get_notBefore((X509 *)cert))
#define X509_get_notAfter_const(cert) \
((const ASN1_TIME*) X509_get_notAfter((X509 *)cert))
#endif
/* Copied from or.h */
#define LEGAL_NICKNAME_CHARACTERS \
@ -372,12 +355,8 @@ tor_tls_init(void)
check_no_tls_errors();
if (!tls_library_is_initialized) {
#ifdef OPENSSL_1_1_API
OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
#else
SSL_library_init();
SSL_load_error_strings();
#endif
#if (SIZEOF_VOID_P >= 8 && \
OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,1))

View File

@ -11,7 +11,7 @@
* \brief Headers for tortls.c
**/
#include "crypto_rsa.h"
#include "crypto.h"
#include "compat_openssl.h"
#include "compat.h"
#include "testsupport.h"

View File

@ -16,7 +16,7 @@
#define UTIL_PRIVATE
#include "util.h"
#include "torlog.h"
#include "crypto_digest.h"
#include "crypto.h"
#include "torint.h"
#include "container.h"
#include "address.h"
@ -572,19 +572,6 @@ add_laplace_noise(int64_t signal_, double random_, double delta_f,
return signal_ + noise;
}
/* Helper: safely add two uint32_t's, capping at UINT32_MAX rather
* than overflow */
uint32_t
tor_add_u32_nowrap(uint32_t a, uint32_t b)
{
/* a+b > UINT32_MAX check, without overflow */
if (PREDICT_UNLIKELY(a > UINT32_MAX - b)) {
return UINT32_MAX;
} else {
return a+b;
}
}
/* Helper: return greatest common divisor of a,b */
static uint64_t
gcd64(uint64_t a, uint64_t b)
@ -1834,15 +1821,6 @@ format_iso_time(char *buf, time_t t)
strftime(buf, ISO_TIME_LEN+1, "%Y-%m-%d %H:%M:%S", tor_gmtime_r(&t, &tm));
}
/** As format_local_iso_time, but use the yyyy-mm-ddThh:mm:ss format to avoid
* embedding an internal space. */
void
format_local_iso_time_nospace(char *buf, time_t t)
{
format_local_iso_time(buf, t);
buf[10] = 'T';
}
/** As format_iso_time, but use the yyyy-mm-ddThh:mm:ss format to avoid
* embedding an internal space. */
void
@ -5133,6 +5111,30 @@ stream_status_to_string(enum stream_status stream_status)
}
}
/* DOCDOC */
static void
log_portfw_spawn_error_message(const char *buf,
const char *executable, int *child_status)
{
/* Parse error message */
int retval, child_state, saved_errno;
retval = tor_sscanf(buf, SPAWN_ERROR_MESSAGE "%x/%x",
&child_state, &saved_errno);
if (retval == 2) {
log_warn(LD_GENERAL,
"Failed to start child process \"%s\" in state %d: %s",
executable, child_state, strerror(saved_errno));
if (child_status)
*child_status = 1;
} else {
/* Failed to parse message from child process, log it as a
warning */
log_warn(LD_GENERAL,
"Unexpected message from port forwarding helper \"%s\": %s",
executable, buf);
}
}
#ifdef _WIN32
/** Return a smartlist containing lines outputted from
@ -5178,6 +5180,51 @@ tor_get_lines_from_handle, (HANDLE *handle,
return lines;
}
/** Read from stream, and send lines to log at the specified log level.
* Returns -1 if there is a error reading, and 0 otherwise.
* If the generated stream is flushed more often than on new lines, or
* a read exceeds 256 bytes, lines will be truncated. This should be fixed,
* along with the corresponding problem on *nix (see bug #2045).
*/
static int
log_from_handle(HANDLE *pipe, int severity)
{
char buf[256];
int pos;
smartlist_t *lines;
pos = tor_read_all_handle(pipe, buf, sizeof(buf) - 1, NULL);
if (pos < 0) {
/* Error */
log_warn(LD_GENERAL, "Failed to read data from subprocess");
return -1;
}
if (0 == pos) {
/* There's nothing to read (process is busy or has exited) */
log_debug(LD_GENERAL, "Subprocess had nothing to say");
return 0;
}
/* End with a null even if there isn't a \r\n at the end */
/* TODO: What if this is a partial line? */
buf[pos] = '\0';
log_debug(LD_GENERAL, "Subprocess had %d bytes to say", pos);
/* Split up the buffer */
lines = smartlist_new();
tor_split_lines(lines, buf, pos);
/* Log each line */
SMARTLIST_FOREACH(lines, char *, line,
{
log_fn(severity, LD_GENERAL, "Port forwarding helper says: %s", line);
});
smartlist_free(lines);
return 0;
}
#else /* !(defined(_WIN32)) */
/** Return a smartlist containing lines outputted from
@ -5207,6 +5254,42 @@ tor_get_lines_from_handle, (int fd, enum stream_status *stream_status_out))
return lines;
}
/** Read from fd, and send lines to log at the specified log level.
* Returns 1 if stream is closed normally, -1 if there is a error reading, and
* 0 otherwise. Handles lines from tor-fw-helper and
* tor_spawn_background() specially.
*/
static int
log_from_pipe(int fd, int severity, const char *executable,
int *child_status)
{
char buf[256];
enum stream_status r;
for (;;) {
r = get_string_from_pipe(fd, buf, sizeof(buf) - 1);
if (r == IO_STREAM_CLOSED) {
return 1;
} else if (r == IO_STREAM_EAGAIN) {
return 0;
} else if (r == IO_STREAM_TERM) {
return -1;
}
tor_assert(r == IO_STREAM_OKAY);
/* Check if buf starts with SPAWN_ERROR_MESSAGE */
if (strcmpstart(buf, SPAWN_ERROR_MESSAGE) == 0) {
log_portfw_spawn_error_message(buf, executable, child_status);
} else {
log_fn(severity, LD_GENERAL, "Port forwarding helper says: %s", buf);
}
}
/* We should never get here */
return -1;
}
#endif /* defined(_WIN32) */
/** Reads from <b>fd</b> and stores input in <b>buf_out</b> making
@ -5249,6 +5332,294 @@ get_string_from_pipe(int fd, char *buf_out, size_t count)
return IO_STREAM_OKAY;
}
/** Parse a <b>line</b> from tor-fw-helper and issue an appropriate
* log message to our user. */
static void
handle_fw_helper_line(const char *executable, const char *line)
{
smartlist_t *tokens = smartlist_new();
char *message = NULL;
char *message_for_log = NULL;
const char *external_port = NULL;
const char *internal_port = NULL;
const char *result = NULL;
int port = 0;
int success = 0;
if (strcmpstart(line, SPAWN_ERROR_MESSAGE) == 0) {
/* We need to check for SPAWN_ERROR_MESSAGE again here, since it's
* possible that it got sent after we tried to read it in log_from_pipe.
*
* XXX Ideally, we should be using one of stdout/stderr for the real
* output, and one for the output of the startup code. We used to do that
* before cd05f35d2c.
*/
int child_status;
log_portfw_spawn_error_message(line, executable, &child_status);
goto done;
}
smartlist_split_string(tokens, line, NULL,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
if (smartlist_len(tokens) < 5)
goto err;
if (strcmp(smartlist_get(tokens, 0), "tor-fw-helper") ||
strcmp(smartlist_get(tokens, 1), "tcp-forward"))
goto err;
external_port = smartlist_get(tokens, 2);
internal_port = smartlist_get(tokens, 3);
result = smartlist_get(tokens, 4);
if (smartlist_len(tokens) > 5) {
/* If there are more than 5 tokens, they are part of [<message>].
Let's use a second smartlist to form the whole message;
strncat loops suck. */
int i;
int message_words_n = smartlist_len(tokens) - 5;
smartlist_t *message_sl = smartlist_new();
for (i = 0; i < message_words_n; i++)
smartlist_add(message_sl, smartlist_get(tokens, 5+i));
tor_assert(smartlist_len(message_sl) > 0);
message = smartlist_join_strings(message_sl, " ", 0, NULL);
/* wrap the message in log-friendly wrapping */
tor_asprintf(&message_for_log, " ('%s')", message);
smartlist_free(message_sl);
}
port = atoi(external_port);
if (port < 1 || port > 65535)
goto err;
port = atoi(internal_port);
if (port < 1 || port > 65535)
goto err;
if (!strcmp(result, "SUCCESS"))
success = 1;
else if (!strcmp(result, "FAIL"))
success = 0;
else
goto err;
if (!success) {
log_warn(LD_GENERAL, "Tor was unable to forward TCP port '%s' to '%s'%s. "
"Please make sure that your router supports port "
"forwarding protocols (like NAT-PMP). Note that if '%s' is "
"your ORPort, your relay will be unable to receive inbound "
"traffic.", external_port, internal_port,
message_for_log ? message_for_log : "",
internal_port);
} else {
log_info(LD_GENERAL,
"Tor successfully forwarded TCP port '%s' to '%s'%s.",
external_port, internal_port,
message_for_log ? message_for_log : "");
}
goto done;
err:
log_warn(LD_GENERAL, "tor-fw-helper sent us a string we could not "
"parse (%s).", line);
done:
SMARTLIST_FOREACH(tokens, char *, cp, tor_free(cp));
smartlist_free(tokens);
tor_free(message);
tor_free(message_for_log);
}
/** Read what tor-fw-helper has to say in its stdout and handle it
* appropriately */
static int
handle_fw_helper_output(const char *executable,
process_handle_t *process_handle)
{
smartlist_t *fw_helper_output = NULL;
enum stream_status stream_status = 0;
fw_helper_output =
tor_get_lines_from_handle(tor_process_get_stdout_pipe(process_handle),
&stream_status);
if (!fw_helper_output) { /* didn't get any output from tor-fw-helper */
/* if EAGAIN we should retry in the future */
return (stream_status == IO_STREAM_EAGAIN) ? 0 : -1;
}
/* Handle the lines we got: */
SMARTLIST_FOREACH_BEGIN(fw_helper_output, char *, line) {
handle_fw_helper_line(executable, line);
tor_free(line);
} SMARTLIST_FOREACH_END(line);
smartlist_free(fw_helper_output);
return 0;
}
/** Spawn tor-fw-helper and ask it to forward the ports in
* <b>ports_to_forward</b>. <b>ports_to_forward</b> contains strings
* of the form "<external port>:<internal port>", which is the format
* that tor-fw-helper expects. */
void
tor_check_port_forwarding(const char *filename,
smartlist_t *ports_to_forward,
time_t now)
{
/* When fw-helper succeeds, how long do we wait until running it again */
#define TIME_TO_EXEC_FWHELPER_SUCCESS 300
/* When fw-helper failed to start, how long do we wait until running it again
*/
#define TIME_TO_EXEC_FWHELPER_FAIL 60
/* Static variables are initialized to zero, so child_handle.status=0
* which corresponds to it not running on startup */
static process_handle_t *child_handle=NULL;
static time_t time_to_run_helper = 0;
int stderr_status, retval;
int stdout_status = 0;
tor_assert(filename);
/* Start the child, if it is not already running */
if ((!child_handle || child_handle->status != PROCESS_STATUS_RUNNING) &&
time_to_run_helper < now) {
/*tor-fw-helper cli looks like this: tor_fw_helper -p :5555 -p 4555:1111 */
const char **argv; /* cli arguments */
int args_n, status;
int argv_index = 0; /* index inside 'argv' */
tor_assert(smartlist_len(ports_to_forward) > 0);
/* check for overflow during 'argv' allocation:
(len(ports_to_forward)*2 + 2)*sizeof(char*) > SIZE_MAX ==
len(ports_to_forward) > (((SIZE_MAX/sizeof(char*)) - 2)/2) */
if ((size_t) smartlist_len(ports_to_forward) >
(((SIZE_MAX/sizeof(char*)) - 2)/2)) {
log_warn(LD_GENERAL,
"Overflow during argv allocation. This shouldn't happen.");
return;
}
/* check for overflow during 'argv_index' increase:
((len(ports_to_forward)*2 + 2) > INT_MAX) ==
len(ports_to_forward) > (INT_MAX - 2)/2 */
if (smartlist_len(ports_to_forward) > (INT_MAX - 2)/2) {
log_warn(LD_GENERAL,
"Overflow during argv_index increase. This shouldn't happen.");
return;
}
/* Calculate number of cli arguments: one for the filename, two
for each smartlist element (one for "-p" and one for the
ports), and one for the final NULL. */
args_n = 1 + 2*smartlist_len(ports_to_forward) + 1;
argv = tor_calloc(args_n, sizeof(char *));
argv[argv_index++] = filename;
SMARTLIST_FOREACH_BEGIN(ports_to_forward, const char *, port) {
argv[argv_index++] = "-p";
argv[argv_index++] = port;
} SMARTLIST_FOREACH_END(port);
argv[argv_index] = NULL;
/* Assume tor-fw-helper will succeed, start it later*/
time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_SUCCESS;
if (child_handle) {
tor_process_handle_destroy(child_handle, 1);
child_handle = NULL;
}
#ifdef _WIN32
/* Passing NULL as lpApplicationName makes Windows search for the .exe */
status = tor_spawn_background(NULL, argv, NULL, &child_handle);
#else
status = tor_spawn_background(filename, argv, NULL, &child_handle);
#endif /* defined(_WIN32) */
tor_free_((void*)argv);
argv=NULL;
if (PROCESS_STATUS_ERROR == status) {
log_warn(LD_GENERAL, "Failed to start port forwarding helper %s",
filename);
time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_FAIL;
return;
}
log_info(LD_GENERAL,
"Started port forwarding helper (%s) with pid '%d'",
filename, tor_process_get_pid(child_handle));
}
/* If child is running, read from its stdout and stderr) */
if (child_handle && PROCESS_STATUS_RUNNING == child_handle->status) {
/* Read from stdout/stderr and log result */
retval = 0;
#ifdef _WIN32
stderr_status = log_from_handle(child_handle->stderr_pipe, LOG_INFO);
#else
stderr_status = log_from_pipe(child_handle->stderr_pipe,
LOG_INFO, filename, &retval);
#endif /* defined(_WIN32) */
if (handle_fw_helper_output(filename, child_handle) < 0) {
log_warn(LD_GENERAL, "Failed to handle fw helper output.");
stdout_status = -1;
retval = -1;
}
if (retval) {
/* There was a problem in the child process */
time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_FAIL;
}
/* Combine the two statuses in order of severity */
if (-1 == stdout_status || -1 == stderr_status)
/* There was a failure */
retval = -1;
#ifdef _WIN32
else if (!child_handle || tor_get_exit_code(child_handle, 0, NULL) !=
PROCESS_EXIT_RUNNING) {
/* process has exited or there was an error */
/* TODO: Do something with the process return value */
/* TODO: What if the process output something since
* between log_from_handle and tor_get_exit_code? */
retval = 1;
}
#else /* !(defined(_WIN32)) */
else if (1 == stdout_status || 1 == stderr_status)
/* stdout or stderr was closed, the process probably
* exited. It will be reaped by waitpid() in main.c */
/* TODO: Do something with the process return value */
retval = 1;
#endif /* defined(_WIN32) */
else
/* Both are fine */
retval = 0;
/* If either pipe indicates a failure, act on it */
if (0 != retval) {
if (1 == retval) {
log_info(LD_GENERAL, "Port forwarding helper terminated");
child_handle->status = PROCESS_STATUS_NOTRUNNING;
} else {
log_warn(LD_GENERAL, "Failed to read from port forwarding helper");
child_handle->status = PROCESS_STATUS_ERROR;
}
/* TODO: The child might not actually be finished (maybe it failed or
closed stdout/stderr), so maybe we shouldn't start another? */
}
}
}
/** Initialize the insecure RNG <b>rng</b> from a seed value <b>seed</b>. */
void
tor_init_weak_random(tor_weak_rng_t *rng, unsigned seed)

View File

@ -73,9 +73,9 @@ extern int dmalloc_free(const char *file, const int line, void *pnt,
} \
STMT_END
#else /* !(defined(USE_DMALLOC)) */
/** Release memory allocated by tor_malloc, tor_realloc, tor_strdup,
* etc. Unlike the free() function, the tor_free() macro sets the
* pointer value to NULL after freeing it.
/** Release memory allocated by tor_malloc, tor_realloc, tor_strdup, etc.
* Unlike the free() function, tor_free() will still work on NULL pointers,
* and it sets the pointer value to NULL after freeing it.
*
* This is a macro. If you need a function pointer to release memory from
* tor_malloc(), use tor_free_().
@ -88,13 +88,17 @@ extern int dmalloc_free(const char *file, const int line, void *pnt,
#ifdef __GNUC__
#define tor_free(p) STMT_BEGIN \
typeof(&(p)) tor_free__tmpvar = &(p); \
raw_free(*tor_free__tmpvar); \
*tor_free__tmpvar=NULL; \
if (PREDICT_LIKELY((*tor_free__tmpvar)!=NULL)) { \
raw_free(*tor_free__tmpvar); \
*tor_free__tmpvar=NULL; \
} \
STMT_END
#else
#define tor_free(p) STMT_BEGIN \
raw_free(p); \
(p)=NULL; \
if (PREDICT_LIKELY((p)!=NULL)) { \
raw_free(p); \
(p)=NULL; \
} \
STMT_END
#endif
#endif /* defined(USE_DMALLOC) */
@ -176,8 +180,6 @@ int n_bits_set_u8(uint8_t v);
int64_t clamp_double_to_int64(double number);
void simplify_fraction64(uint64_t *numer, uint64_t *denom);
uint32_t tor_add_u32_nowrap(uint32_t a, uint32_t b);
/* Compute the CEIL of <b>a</b> divided by <b>b</b>, for nonnegative <b>a</b>
* and positive <b>b</b>. Works on integer types only. Not defined if a+(b-1)
* can overflow. */
@ -271,7 +273,6 @@ int parse_rfc1123_time(const char *buf, time_t *t);
#define ISO_TIME_USEC_LEN (ISO_TIME_LEN+7)
void format_local_iso_time(char *buf, time_t t);
void format_iso_time(char *buf, time_t t);
void format_local_iso_time_nospace(char *buf, time_t t);
void format_iso_time_nospace(char *buf, time_t t);
void format_iso_time_nospace_usec(char *buf, const struct timeval *tv);
int parse_iso_time_(const char *cp, time_t *t, int strict, int nospace);
@ -417,6 +418,11 @@ void start_daemon(void);
void finish_daemon(const char *desired_cwd);
int write_pidfile(const char *filename);
/* Port forwarding */
void tor_check_port_forwarding(const char *filename,
struct smartlist_t *ports_to_forward,
time_t now);
void tor_disable_spawning_background_processes(void);
typedef struct process_handle_t process_handle_t;
@ -455,7 +461,9 @@ void set_environment_variable_in_smartlist(struct smartlist_t *env_vars,
void (*free_old)(void*),
int free_p);
/* Values of process_handle_t.status. */
/* Values of process_handle_t.status. PROCESS_STATUS_NOTRUNNING must be
* 0 because tor_check_port_forwarding depends on this being the initial
* statue of the static instance of process_handle_t */
#define PROCESS_STATUS_NOTRUNNING 0
#define PROCESS_STATUS_RUNNING 1
#define PROCESS_STATUS_ERROR -1

View File

@ -1,4 +1,3 @@
/* copyright (c) 2013-2015, The Tor Project, Inc. */
/* See LICENSE for licensing information */
@ -25,16 +24,13 @@
#include "orconfig.h"
#include "compat.h"
#include "compat_libevent.h"
#include "compat_threads.h"
#include "crypto_rand.h"
#include "crypto.h"
#include "util.h"
#include "workqueue.h"
#include "tor_queue.h"
#include "torlog.h"
#include <event2/event.h>
#define WORKQUEUE_PRIORITY_FIRST WQ_PRI_HIGH
#define WORKQUEUE_PRIORITY_LAST WQ_PRI_LOW
#define WORKQUEUE_N_PRIORITIES (((int) WORKQUEUE_PRIORITY_LAST)+1)
@ -67,9 +63,6 @@ struct threadpool_s {
void (*free_update_arg_fn)(void *);
/** Array of n_threads update arguments. */
void **update_args;
/** Event to notice when another thread has sent a reply. */
struct event *reply_event;
void (*reply_cb)(threadpool_t *);
/** Number of elements in threads. */
int n_threads;
@ -604,41 +597,15 @@ replyqueue_new(uint32_t alertsocks_flags)
return rq;
}
/** Internal: Run from the libevent mainloop when there is work to handle in
* the reply queue handler. */
static void
reply_event_cb(evutil_socket_t sock, short events, void *arg)
{
threadpool_t *tp = arg;
(void) sock;
(void) events;
replyqueue_process(tp->reply_queue);
if (tp->reply_cb)
tp->reply_cb(tp);
}
/** Register the threadpool <b>tp</b>'s reply queue with the libevent
* mainloop of <b>base</b>. If <b>tp</b> is provided, it is run after
* each time there is work to process from the reply queue. Return 0 on
* success, -1 on failure.
/**
* Return the "read socket" for a given reply queue. The main thread should
* listen for read events on this socket, and call replyqueue_process() every
* time it triggers.
*/
int
threadpool_register_reply_event(threadpool_t *tp,
void (*cb)(threadpool_t *tp))
tor_socket_t
replyqueue_get_socket(replyqueue_t *rq)
{
struct event_base *base = tor_libevent_get_base();
if (tp->reply_event) {
tor_event_free(tp->reply_event);
}
tp->reply_event = tor_event_new(base,
tp->reply_queue->alert.read_fd,
EV_READ|EV_PERSIST,
reply_event_cb,
tp);
tor_assert(tp->reply_event);
tp->reply_cb = cb;
return event_add(tp->reply_event, NULL);
return rq->alert.read_fd;
}
/**

View File

@ -56,11 +56,8 @@ threadpool_t *threadpool_new(int n_threads,
replyqueue_t *threadpool_get_replyqueue(threadpool_t *tp);
replyqueue_t *replyqueue_new(uint32_t alertsocks_flags);
tor_socket_t replyqueue_get_socket(replyqueue_t *rq);
void replyqueue_process(replyqueue_t *queue);
struct event_base;
int threadpool_register_reply_event(threadpool_t *tp,
void (*cb)(threadpool_t *tp));
#endif /* !defined(TOR_WORKQUEUE_H) */

View File

@ -100,7 +100,7 @@
## A handle for your relay, so people don't have to refer to it by key.
## Nicknames must be between 1 and 19 characters inclusive, and must
## contain only the alphanumeric characters (a-z, A-Z, 0-9). No unicode,
## no emoji. If not set, "Unnamed" will be used.
## no emoji.
#Nickname ididnteditheconfig
## Define these to limit how much relayed traffic you will allow. Your

View File

@ -106,7 +106,6 @@
## A handle for your relay, so people don't have to refer to it by key.
## Nicknames must be between 1 and 19 characters inclusive, and must
## contain only the characters [a-zA-Z0-9].
## If not set, "Unnamed" will be used.
#Nickname ididnteditheconfig
## Define these to limit how much relayed traffic you will allow. Your

View File

@ -9,7 +9,7 @@
void ed25519_hash(uint8_t *hash, const uint8_t *in, size_t inlen);
*/
#include "crypto_digest.h"
#include "crypto.h"
typedef struct ed25519_hash_context {
crypto_digest_t *ctx;

View File

@ -8,7 +8,7 @@
*/
/* Tor: Instead of calling OpenSSL's CSPRNG directly, call the wrapper. */
#include "crypto_rand.h"
#include "crypto.h"
static void
ED25519_FN(ed25519_randombytes_unsafe) (void *p, size_t len)

View File

@ -40,8 +40,6 @@
#include "ed25519-randombytes.h"
#include "ed25519-hash.h"
#include "crypto_util.h"
typedef unsigned char ed25519_signature[64];
typedef unsigned char ed25519_public_key[32];
typedef unsigned char ed25519_secret_key[32];

View File

@ -7,7 +7,7 @@
#include "ed25519_ref10.h"
#include <string.h>
#include "crypto_util.h"
#include "crypto.h"
static void
ed25519_ref10_gettweak(unsigned char *out, const unsigned char *param)

View File

@ -1,5 +1,5 @@
/* Added for Tor. */
#include "crypto_digest.h"
#include "crypto.h"
/* Set 'out' to the 512-bit SHA512 hash of the 'len'-byte string in 'inp' */
#define crypto_hash_sha512(out, inp, len) \

View File

@ -6,9 +6,6 @@
#include "crypto_hash_sha512.h"
#include "ge.h"
#include "crypto_rand.h"
#include "crypto_util.h"
int
crypto_sign_seckey(unsigned char *sk)
{

View File

@ -1,4 +1,4 @@
/* Added for Tor. */
#include "crypto_rand.h"
#include "crypto.h"
#define randombytes(b, n) \
(crypto_strongest_rand((b), (n)), 0)

View File

@ -9,7 +9,7 @@
#include "keccak-tiny.h"
#include <string.h>
#include "crypto_util.h"
#include "crypto.h"
#include "byteorder.h"
/******** Endianness conversion helpers ********/

@ -1 +1 @@
Subproject commit aa37fb84fb829902e83ca11a7244bbc6b86b809b
Subproject commit fbc0c25785696a25b9cbc09ed645cc8d404ee0f6

View File

@ -150,7 +150,7 @@
#else
#define ctz(n) ctz32(n)
#define clz(n) clz32(n)
#define fls(n) ((int)(32 - clz32((uint32_t)n)))
#define fls(n) ((int)(32 - clz32(n)))
#endif
#if WHEEL_BIT == 6
@ -432,7 +432,7 @@ TIMEOUT_PUBLIC void timeouts_update(struct timeouts *T, abstime_t curtime) {
* or can be replaced with a simpler operation.
*/
oslot = WHEEL_MASK & (T->curtime >> (wheel * WHEEL_BIT));
pending = rotl(((WHEEL_C(1) << _elapsed) - 1), oslot);
pending = rotl(((UINT64_C(1) << _elapsed) - 1), oslot);
nslot = WHEEL_MASK & (curtime >> (wheel * WHEEL_BIT));
pending |= rotr(rotl(((WHEEL_C(1) << _elapsed) - 1), nslot), (int)_elapsed);

View File

@ -21,10 +21,9 @@
#include "config.h"
#include "connection_edge.h"
#include "control.h"
#include "crypto_rand.h"
#include "dns.h"
#include "nodelist.h"
#include "routerset.h"
#include "nodelist.h"
/** A client-side struct to remember requests to rewrite addresses
* to new addresses. These structs are stored in the hash table
@ -960,11 +959,9 @@ addressmap_get_virtual_address(int type)
char tmp[TOR_ADDR_BUF_LEN];
tor_addr_to_str(tmp, &addr, sizeof(tmp), 0);
if (strmap_get(addressmap, tmp)) {
// LCOV_EXCL_START
log_warn(LD_BUG, "%s wasn't in the addressmap, but %s was.",
buf, tmp);
continue;
// LCOV_EXCL_STOP
}
return tor_strdup(buf);
@ -973,10 +970,8 @@ addressmap_get_virtual_address(int type)
log_warn(LD_CONFIG, "Ran out of virtual addresses!");
return NULL;
} else {
// LCOV_EXCL_START
log_warn(LD_BUG, "Called with unsupported address type (%d)", type);
return NULL;
// LCOV_EXCL_STOP
}
}

View File

@ -11,8 +11,6 @@
* Bridges are fixed entry nodes, used for censorship circumvention.
**/
#define TOR_BRIDGES_PRIVATE
#include "or.h"
#include "bridges.h"
#include "circuitbuild.h"
@ -95,7 +93,7 @@ sweep_bridge_list(void)
}
/** Initialize the bridge list to empty, creating it if needed. */
STATIC void
static void
clear_bridge_list(void)
{
if (!bridge_list)
@ -158,7 +156,7 @@ bridge_get_addr_port(const bridge_info_t *bridge)
* bridge with no known digest whose address matches any of the
* tor_addr_port_t's in <b>orports</b>, return that bridge. Else return
* NULL. */
STATIC bridge_info_t *
static bridge_info_t *
get_configured_bridge_by_orports_digest(const char *digest,
const smartlist_t *orports)
{
@ -352,7 +350,7 @@ bridge_has_digest(const bridge_info_t *bridge, const char *digest)
* existing bridge with the same address and port, and warn the user as
* appropriate.
*/
STATIC void
static void
bridge_resolve_conflicts(const tor_addr_t *addr, uint16_t port,
const char *digest, const char *transport_name)
{
@ -473,7 +471,7 @@ bridge_add_from_config(bridge_line_t *bridge_line)
}
/** If <b>digest</b> is one of our known bridges, return it. */
STATIC bridge_info_t *
bridge_info_t *
find_bridge_by_digest(const char *digest)
{
if (! bridge_list)

View File

@ -20,6 +20,7 @@ typedef struct bridge_info_t bridge_info_t;
void mark_bridge_list(void);
void sweep_bridge_list(void);
const smartlist_t *bridge_list_get(void);
bridge_info_t *find_bridge_by_digest(const char *digest);
const uint8_t *bridge_get_rsa_id_digest(const bridge_info_t *bridge);
const tor_addr_port_t * bridge_get_addr_port(const bridge_info_t *bridge);
bridge_info_t *get_configured_bridge_by_addr_port_digest(
@ -64,17 +65,5 @@ MOCK_DECL(download_status_t *, get_bridge_dl_status_by_id,
void bridges_free_all(void);
#ifdef TOR_BRIDGES_PRIVATE
STATIC void clear_bridge_list(void);
STATIC bridge_info_t *find_bridge_by_digest(const char *digest);
STATIC bridge_info_t *get_configured_bridge_by_orports_digest(
const char *digest,
const smartlist_t *orports);
STATIC void bridge_resolve_conflicts(const tor_addr_t *addr,
uint16_t port,
const char *digest,
const char *transport_name);
#endif /* defined(TOR_BRIDGES_PRIVATE) */
#endif /* !defined(TOR_BRIDGES_H) */

View File

@ -69,7 +69,6 @@
#include "circuitmux.h"
#include "entrynodes.h"
#include "geoip.h"
#include "main.h"
#include "nodelist.h"
#include "relay.h"
#include "rephist.h"
@ -405,7 +404,6 @@ channel_register(channel_t *chan)
/* Put it in the finished list, creating it if necessary */
if (!finished_channels) finished_channels = smartlist_new();
smartlist_add(finished_channels, chan);
mainloop_schedule_postloop_cleanup();
} else {
/* Put it in the active list, creating it if necessary */
if (!active_channels) active_channels = smartlist_new();
@ -1550,7 +1548,6 @@ channel_change_state_(channel_t *chan, channel_state_t to_state)
if (active_channels) smartlist_remove(active_channels, chan);
if (!finished_channels) finished_channels = smartlist_new();
smartlist_add(finished_channels, chan);
mainloop_schedule_postloop_cleanup();
}
/* Need to put on active list? */
else if (!was_active && is_active) {
@ -1669,7 +1666,6 @@ channel_listener_change_state(channel_listener_t *chan_l,
if (active_listeners) smartlist_remove(active_listeners, chan_l);
if (!finished_listeners) finished_listeners = smartlist_new();
smartlist_add(finished_listeners, chan_l);
mainloop_schedule_postloop_cleanup();
}
/* Need to put on active list? */
else if (!was_active && is_active) {
@ -2112,6 +2108,21 @@ channel_listener_dumpstats(int severity)
}
}
/**
* Set the cmux policy on all active channels.
*/
void
channel_set_cmux_policy_everywhere(circuitmux_policy_t *pol)
{
if (!active_channels) return;
SMARTLIST_FOREACH_BEGIN(active_channels, channel_t *, curr) {
if (curr->cmux) {
circuitmux_set_policy(curr->cmux, pol);
}
} SMARTLIST_FOREACH_END(curr);
}
/**
* Clean up channels.
*
@ -2391,7 +2402,7 @@ channel_get_for_extend(const char *rsa_id_digest,
{
channel_t *chan, *best = NULL;
int n_inprogress_goodaddr = 0, n_old = 0;
int n_noncanonical = 0;
int n_noncanonical = 0, n_possible = 0;
tor_assert(msg_out);
tor_assert(launch_out);
@ -2454,6 +2465,8 @@ channel_get_for_extend(const char *rsa_id_digest,
continue;
}
++n_possible;
if (!best) {
best = chan; /* If we have no 'best' so far, this one is good enough. */
continue;

View File

@ -422,6 +422,9 @@ void channel_free_all(void);
void channel_dumpstats(int severity);
void channel_listener_dumpstats(int severity);
/* Set the cmux policy on all active channels */
void channel_set_cmux_policy_everywhere(circuitmux_policy_t *pol);
#ifdef TOR_CHANNEL_INTERNAL_
#ifdef CHANNEL_PRIVATE_

View File

@ -16,11 +16,11 @@
#include "networkstatus.h"
#include "connection.h"
#include "connection_or.h"
#include "crypto_rand.h"
#include "main.h"
#include "rephist.h"
#include "router.h"
#include "compat_time.h"
#include <event2/event.h>
#include "rendservice.h"
STATIC int32_t channelpadding_get_netflow_inactive_timeout_ms(

View File

@ -160,8 +160,9 @@ channel_tls_common_init(channel_tls_t *tlschan)
chan->write_var_cell = channel_tls_write_var_cell_method;
chan->cmux = circuitmux_alloc();
/* We only have one policy for now so always set it to EWMA. */
circuitmux_set_policy(chan->cmux, &ewma_policy);
if (cell_ewma_enabled()) {
circuitmux_set_policy(chan->cmux, &ewma_policy);
}
}
/**

View File

@ -30,7 +30,6 @@
#include "circuitstats.h"
#include "connection_edge.h"
#include "config.h"
#include "crypto_rand.h"
#include "entrynodes.h"
#include "networkstatus.h"
#include "relay.h"

View File

@ -43,7 +43,7 @@
#include "connection_edge.h"
#include "connection_or.h"
#include "control.h"
#include "crypto_rand.h"
#include "crypto.h"
#include "directory.h"
#include "entrynodes.h"
#include "hs_ntor.h"
@ -56,7 +56,6 @@
#include "onion_fast.h"
#include "policies.h"
#include "relay.h"
#include "relay_crypto.h"
#include "rendcommon.h"
#include "rephist.h"
#include "router.h"
@ -72,7 +71,10 @@ static channel_t * channel_connect_for_circuit(const tor_addr_t *addr,
static int circuit_deliver_create_cell(circuit_t *circ,
const create_cell_t *create_cell,
int relayed);
static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit,
int is_hs_v3_rp_circuit);
static crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath);
static int onion_extend_cpath(origin_circuit_t *circ);
STATIC int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice);
static int circuit_send_first_onion_skin(origin_circuit_t *circ);
static int circuit_build_no_more_hops(origin_circuit_t *circ);
@ -1053,7 +1055,7 @@ circuit_build_no_more_hops(origin_circuit_t *circ)
clear_broken_connection_map(1);
if (server_mode(options) && !check_whether_orport_reachable(options)) {
inform_testing_reachability();
router_do_reachability_checks(1, 1);
consider_testing_reachability(1, 1);
}
}
@ -1130,29 +1132,19 @@ circuit_send_intermediate_onion_skin(origin_circuit_t *circ,
return 0;
}
/** Our clock just jumped by <b>seconds_elapsed</b>. If <b>was_idle</b> is
* true, then the monotonic time matches; otherwise it doesn't. Assume
* something has also gone wrong with our network: notify the user, and
* abandon all not-yet-used circuits. */
/** Our clock just jumped by <b>seconds_elapsed</b>. Assume
* something has also gone wrong with our network: notify the user,
* and abandon all not-yet-used circuits. */
void
circuit_note_clock_jumped(int64_t seconds_elapsed, bool was_idle)
circuit_note_clock_jumped(int seconds_elapsed)
{
int severity = server_mode(get_options()) ? LOG_WARN : LOG_NOTICE;
if (was_idle) {
tor_log(severity, LD_GENERAL, "Tor has been idle for "I64_FORMAT
" seconds; assuming established circuits no longer work.",
I64_PRINTF_ARG(seconds_elapsed));
} else {
tor_log(severity, LD_GENERAL,
"Your system clock just jumped "I64_FORMAT" seconds %s; "
"assuming established circuits no longer work.",
I64_PRINTF_ARG(
seconds_elapsed >=0 ? seconds_elapsed : -seconds_elapsed),
seconds_elapsed >=0 ? "forward" : "backward");
}
control_event_general_status(LOG_WARN, "CLOCK_JUMPED TIME="I64_FORMAT
" IDLE=%d",
I64_PRINTF_ARG(seconds_elapsed), was_idle?1:0);
tor_log(severity, LD_GENERAL, "Your system clock just jumped %d seconds %s; "
"assuming established circuits no longer work.",
seconds_elapsed >=0 ? seconds_elapsed : -seconds_elapsed,
seconds_elapsed >=0 ? "forward" : "backward");
control_event_general_status(LOG_WARN, "CLOCK_JUMPED TIME=%d",
seconds_elapsed);
/* so we log when it works again */
note_that_we_maybe_cant_complete_circuits();
control_event_client_status(severity, "CIRCUIT_NOT_ESTABLISHED REASON=%s",
@ -1344,10 +1336,69 @@ circuit_init_cpath_crypto(crypt_path_t *cpath,
const char *key_data, size_t key_data_len,
int reverse, int is_hs_v3)
{
crypto_digest_t *tmp_digest;
crypto_cipher_t *tmp_crypto;
size_t digest_len = 0;
size_t cipher_key_len = 0;
tor_assert(cpath);
return relay_crypto_init(&cpath->crypto, key_data, key_data_len, reverse,
is_hs_v3);
tor_assert(key_data);
tor_assert(!(cpath->f_crypto || cpath->b_crypto ||
cpath->f_digest || cpath->b_digest));
/* Basic key size validation */
if (is_hs_v3 && BUG(key_data_len != HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN)) {
return -1;
} else if (!is_hs_v3 && BUG(key_data_len != CPATH_KEY_MATERIAL_LEN)) {
return -1;
}
/* If we are using this cpath for next gen onion services use SHA3-256,
otherwise use good ol' SHA1 */
if (is_hs_v3) {
digest_len = DIGEST256_LEN;
cipher_key_len = CIPHER256_KEY_LEN;
cpath->f_digest = crypto_digest256_new(DIGEST_SHA3_256);
cpath->b_digest = crypto_digest256_new(DIGEST_SHA3_256);
} else {
digest_len = DIGEST_LEN;
cipher_key_len = CIPHER_KEY_LEN;
cpath->f_digest = crypto_digest_new();
cpath->b_digest = crypto_digest_new();
}
tor_assert(digest_len != 0);
tor_assert(cipher_key_len != 0);
const int cipher_key_bits = (int) cipher_key_len * 8;
crypto_digest_add_bytes(cpath->f_digest, key_data, digest_len);
crypto_digest_add_bytes(cpath->b_digest, key_data+digest_len, digest_len);
cpath->f_crypto = crypto_cipher_new_with_bits(key_data+(2*digest_len),
cipher_key_bits);
if (!cpath->f_crypto) {
log_warn(LD_BUG,"Forward cipher initialization failed.");
return -1;
}
cpath->b_crypto = crypto_cipher_new_with_bits(
key_data+(2*digest_len)+cipher_key_len,
cipher_key_bits);
if (!cpath->b_crypto) {
log_warn(LD_BUG,"Backward cipher initialization failed.");
return -1;
}
if (reverse) {
tmp_digest = cpath->f_digest;
cpath->f_digest = cpath->b_digest;
cpath->b_digest = tmp_digest;
tmp_crypto = cpath->f_crypto;
cpath->f_crypto = cpath->b_crypto;
cpath->b_crypto = tmp_crypto;
}
return 0;
}
/** A "created" cell <b>reply</b> came back to us on circuit <b>circ</b>.
@ -1470,6 +1521,7 @@ onionskin_answer(or_circuit_t *circ,
const uint8_t *rend_circ_nonce)
{
cell_t cell;
crypt_path_t *tmp_cpath;
tor_assert(keys_len == CPATH_KEY_MATERIAL_LEN);
@ -1480,15 +1532,25 @@ onionskin_answer(or_circuit_t *circ,
}
cell.circ_id = circ->p_circ_id;
tmp_cpath = tor_malloc_zero(sizeof(crypt_path_t));
tmp_cpath->magic = CRYPT_PATH_MAGIC;
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN);
log_debug(LD_CIRC,"init digest forward 0x%.8x, backward 0x%.8x.",
(unsigned int)get_uint32(keys),
(unsigned int)get_uint32(keys+20));
if (relay_crypto_init(&circ->crypto, keys, keys_len, 0, 0)<0) {
if (circuit_init_cpath_crypto(tmp_cpath, keys, keys_len, 0, 0)<0) {
log_warn(LD_BUG,"Circuit initialization failed");
tor_free(tmp_cpath);
return -1;
}
circ->n_digest = tmp_cpath->f_digest;
circ->n_crypto = tmp_cpath->f_crypto;
circ->p_digest = tmp_cpath->b_digest;
circ->p_crypto = tmp_cpath->b_crypto;
tmp_cpath->magic = 0;
tor_free(tmp_cpath);
memcpy(circ->rend_circ_nonce, rend_circ_nonce, DIGEST_LEN);
@ -1549,7 +1611,7 @@ onionskin_answer(or_circuit_t *circ,
* rend_service_launch_establish_intro())
*
* - We are a router testing its own reachabiity
* (CIRCUIT_PURPOSE_TESTING, via router_do_reachability_checks())
* (CIRCUIT_PURPOSE_TESTING, via consider_testing_reachability())
*
* onion_pick_cpath_exit() bypasses us (by not calling
* new_route_len()) in the one-hop tunnel case, so we don't need to
@ -2290,7 +2352,7 @@ warn_if_last_router_excluded(origin_circuit_t *circ,
* be used as an HS v3 rendezvous point.
*
* Return 0 if ok, -1 if circuit should be closed. */
STATIC int
static int
onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit_ei,
int is_hs_v3_rp_circuit)
{
@ -2460,72 +2522,13 @@ cpath_get_n_hops(crypt_path_t **head_ptr)
#endif /* defined(TOR_UNIT_TESTS) */
/**
* Build the exclude list for vanguard circuits.
*
* For vanguard circuits we exclude all the already chosen nodes (including the
* exit) from being middle hops to prevent the creation of A - B - A subpaths.
* We also allow the 4th hop to be the same as the guard node so as to not leak
* guard information to RP/IP/HSDirs.
*
* For vanguard circuits, we don't apply any subnet or family restrictions.
* This is to avoid impossible-to-build circuit paths, or just situations where
* our earlier guards prevent us from using most of our later ones.
*
* The alternative is building the circuit in reverse. Reverse calls to
* onion_extend_cpath() (ie: select outer hops first) would then have the
* property that you don't gain information about inner hops by observing
* outer ones. See https://trac.torproject.org/projects/tor/ticket/24487
* for this.
*
* (Note further that we still exclude the exit to prevent A - B - A
* at the end of the path. */
static smartlist_t *
build_vanguard_middle_exclude_list(uint8_t purpose,
cpath_build_state_t *state,
crypt_path_t *head,
int cur_len)
{
smartlist_t *excluded;
const node_t *r;
crypt_path_t *cpath;
int i;
(void) purpose;
excluded = smartlist_new();
/* Add the exit to the exclude list (note that the exit/last hop is always
* chosen first in circuit_establish_circuit()). */
if ((r = build_state_get_exit_node(state))) {
smartlist_add(excluded, (node_t*)r);
}
/* If we are picking the 4th hop, allow that node to be the guard too.
* This prevents us from avoiding the Guard for those hops, which
* gives the adversary information about our guard if they control
* the RP, IP, or HSDIR. We don't do this check based on purpose
* because we also want to allow HS_VANGUARDS pre-build circuits
* to use the guard for that last hop.
*/
if (cur_len == DEFAULT_ROUTE_LEN+1) {
/* Skip the first hop for the exclude list below */
head = head->next;
cur_len--;
}
for (i = 0, cpath = head; cpath && i < cur_len; ++i, cpath=cpath->next) {
if ((r = node_get_by_id(cpath->extend_info->identity_digest))) {
smartlist_add(excluded, (node_t*)r);
}
}
return excluded;
}
/**
* Build a list of nodes to exclude from the choice of this middle
* hop, based on already chosen nodes.
*
* XXX: At present, this function does not exclude any nodes from
* the vanguard circuits. See
* https://trac.torproject.org/projects/tor/ticket/24487
*/
static smartlist_t *
build_middle_exclude_list(uint8_t purpose,
@ -2538,21 +2541,32 @@ build_middle_exclude_list(uint8_t purpose,
crypt_path_t *cpath;
int i;
/** Vanguard circuits have their own path selection rules */
if (circuit_should_use_vanguards(purpose)) {
return build_vanguard_middle_exclude_list(purpose, state, head, cur_len);
}
excluded = smartlist_new();
/* For non-vanguard circuits, add the exit and its family to the exclude list
* (note that the exit/last hop is always chosen first in
* circuit_establish_circuit()). */
/* Add the exit to the exclude list (note that the exit/last hop is always
* chosen first in circuit_establish_circuit()). */
if ((r = build_state_get_exit_node(state))) {
nodelist_add_node_and_family(excluded, r);
}
/* also exclude all other already chosen nodes and their family */
/* XXX: We don't apply any other previously selected node restrictions for
* vanguards, and allow nodes to be reused for those hop positions in the
* same circuit. This is because after many rotations, you get to learn
* inner guard nodes through the nodes that are not selected for outer
* hops.
*
* The alternative is building the circuit in reverse. Reverse calls to
* onion_extend_cpath() (ie: select outer hops first) would then have the
* property that you don't gain information about inner hops by observing
* outer ones. See https://trac.torproject.org/projects/tor/ticket/24487
* for this.
*
* (Note further that we can and do still exclude the exit in the block
* above, because it is chosen first in circuit_establish_circuit()..) */
if (circuit_should_use_vanguards(purpose)) {
return excluded;
}
for (i = 0, cpath = head; cpath && i < cur_len; ++i, cpath=cpath->next) {
if ((r = node_get_by_id(cpath->extend_info->identity_digest))) {
nodelist_add_node_and_family(excluded, r);
@ -2652,9 +2666,7 @@ choose_good_middle_server(uint8_t purpose,
/** If a hidden service circuit wants a specific middle node, pin it. */
if (middle_node_must_be_vanguard(options, purpose, cur_len)) {
log_debug(LD_GENERAL, "Picking a sticky node (cur_len = %d)", cur_len);
choice = pick_vanguard_middle_node(options, flags, cur_len, excluded);
smartlist_free(excluded);
return choice;
return pick_vanguard_middle_node(options, flags, cur_len, excluded);
}
choice = router_choose_random_node(excluded, options->ExcludeNodes, flags);
@ -2694,7 +2706,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state,
/* This request is for an entry server to use for a regular circuit,
* and we use entry guard nodes. Just return one of the guard nodes. */
tor_assert(guard_state_out);
return guards_choose_guard(state, purpose, guard_state_out);
return guards_choose_guard(state, guard_state_out);
}
excluded = smartlist_new();
@ -2737,7 +2749,7 @@ onion_next_hop_in_cpath(crypt_path_t *cpath)
* Return 1 if the path is complete, 0 if we successfully added a hop,
* and -1 on error.
*/
STATIC int
static int
onion_extend_cpath(origin_circuit_t *circ)
{
uint8_t purpose = circ->base_.purpose;
@ -2859,13 +2871,14 @@ extend_info_from_node(const node_t *node, int for_direct_connect)
return NULL;
}
/* Choose a preferred address first, but fall back to an allowed address. */
/* Choose a preferred address first, but fall back to an allowed address.
* choose_address returns 1 on success, but get_prim_orport returns 0. */
if (for_direct_connect)
fascist_firewall_choose_address_node(node, FIREWALL_OR_CONNECTION, 0, &ap);
else {
node_get_prim_orport(node, &ap);
}
valid_addr = tor_addr_port_is_valid_ap(&ap, 0);
valid_addr = fascist_firewall_choose_address_node(node,
FIREWALL_OR_CONNECTION,
0, &ap);
else
valid_addr = !node_get_prim_orport(node, &ap);
if (valid_addr)
log_debug(LD_CIRC, "using %s for %s",

View File

@ -29,7 +29,7 @@ void circuit_n_chan_done(channel_t *chan, int status,
int inform_testing_reachability(void);
int circuit_timeout_want_to_count_circ(const origin_circuit_t *circ);
int circuit_send_next_onion_skin(origin_circuit_t *circ);
void circuit_note_clock_jumped(int64_t seconds_elapsed, bool was_idle);
void circuit_note_clock_jumped(int seconds_elapsed);
int circuit_extend(cell_t *cell, circuit_t *circ);
int circuit_init_cpath_crypto(crypt_path_t *cpath,
const char *key_data, size_t key_data_len,
@ -83,13 +83,6 @@ STATIC circid_t get_unique_circ_id_by_chan(channel_t *chan);
STATIC int new_route_len(uint8_t purpose, extend_info_t *exit_ei,
smartlist_t *nodes);
MOCK_DECL(STATIC int, count_acceptable_nodes, (smartlist_t *nodes));
STATIC int onion_extend_cpath(origin_circuit_t *circ);
STATIC int
onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit_ei,
int is_hs_v3_rp_circuit);
#if defined(ENABLE_TOR2WEB_MODE) || defined(TOR_UNIT_TESTS)
STATIC const node_t *pick_tor2web_rendezvous_node(router_crn_flags_t flags,
const or_options_t *options);

View File

@ -65,8 +65,6 @@
#include "connection_edge.h"
#include "connection_or.h"
#include "control.h"
#include "crypto_rand.h"
#include "crypto_util.h"
#include "entrynodes.h"
#include "main.h"
#include "hs_circuit.h"
@ -78,7 +76,6 @@
#include "onion_fast.h"
#include "policies.h"
#include "relay.h"
#include "relay_crypto.h"
#include "rendclient.h"
#include "rendcommon.h"
#include "rephist.h"
@ -409,6 +406,9 @@ circuit_set_p_circid_chan(or_circuit_t *or_circ, circid_t id,
circuit_set_circid_chan_helper(circ, CELL_DIRECTION_IN, id, chan);
if (chan) {
tor_assert(bool_eq(or_circ->p_chan_cells.n,
or_circ->next_active_on_p_chan));
chan->timestamp_last_had_circuits = approx_time();
}
@ -431,6 +431,8 @@ circuit_set_n_circid_chan(circuit_t *circ, circid_t id,
circuit_set_circid_chan_helper(circ, CELL_DIRECTION_OUT, id, chan);
if (chan) {
tor_assert(bool_eq(circ->n_chan_cells.n, circ->next_active_on_n_chan));
chan->timestamp_last_had_circuits = approx_time();
}
@ -1085,7 +1087,10 @@ circuit_free_(circuit_t *circ)
should_free = (ocirc->workqueue_entry == NULL);
relay_crypto_clear(&ocirc->crypto);
crypto_cipher_free(ocirc->p_crypto);
crypto_digest_free(ocirc->p_digest);
crypto_cipher_free(ocirc->n_crypto);
crypto_digest_free(ocirc->n_digest);
if (ocirc->rend_splice) {
or_circuit_t *other = ocirc->rend_splice;
@ -1225,7 +1230,10 @@ circuit_free_cpath_node(crypt_path_t *victim)
if (!victim)
return;
relay_crypto_clear(&victim->crypto);
crypto_cipher_free(victim->f_crypto);
crypto_cipher_free(victim->b_crypto);
crypto_digest_free(victim->f_digest);
crypto_digest_free(victim->b_digest);
onion_handshake_state_release(&victim->handshake_state);
crypto_dh_free(victim->rend_dh_handshake_state);
extend_info_free(victim->extend_info);
@ -2069,7 +2077,6 @@ circuit_mark_for_close_, (circuit_t *circ, int reason, int line,
circuits_pending_close = smartlist_new();
smartlist_add(circuits_pending_close, circ);
mainloop_schedule_postloop_cleanup();
log_info(LD_GENERAL, "Circuit %u (id: %" PRIu32 ") marked for close at "
"%s:%d (orig reason: %d, new reason: %d)",
@ -2589,7 +2596,8 @@ assert_cpath_layer_ok(const crypt_path_t *cp)
switch (cp->state)
{
case CPATH_STATE_OPEN:
relay_crypto_assert_ok(&cp->crypto);
tor_assert(cp->f_crypto);
tor_assert(cp->b_crypto);
/* fall through */
case CPATH_STATE_CLOSED:
/*XXXX Assert that there's no handshake_state either. */
@ -2679,7 +2687,10 @@ assert_circuit_ok,(const circuit_t *c))
c->state == CIRCUIT_STATE_GUARD_WAIT) {
tor_assert(!c->n_chan_create_cell);
if (or_circ) {
relay_crypto_assert_ok(&or_circ->crypto);
tor_assert(or_circ->n_crypto);
tor_assert(or_circ->p_crypto);
tor_assert(or_circ->n_digest);
tor_assert(or_circ->p_digest);
}
}
if (c->state == CIRCUIT_STATE_CHAN_WAIT && !c->marked_for_close) {

View File

@ -114,6 +114,13 @@ struct circuitmux_s {
*/
chanid_circid_muxinfo_map_t *chanid_circid_map;
/*
* Double-linked ring of circuits with queued cells waiting for room to
* free up on this connection's outbuf. Every time we pull cells from
* a circuit, we advance this pointer to the next circuit in the ring.
*/
struct circuit_t *active_circuits_head, *active_circuits_tail;
/** List of queued destroy cells */
destroy_cell_queue_t destroy_cell_queue;
/** Boolean: True iff the last cell to circuitmux_get_first_active_circuit
@ -169,6 +176,17 @@ struct chanid_circid_muxinfo_t {
circuit_muxinfo_t muxinfo;
};
/*
* Internal-use #defines
*/
#ifdef CMUX_PARANOIA
#define circuitmux_assert_okay_paranoid(cmux) \
circuitmux_assert_okay(cmux)
#else
#define circuitmux_assert_okay_paranoid(cmux)
#endif /* defined(CMUX_PARANOIA) */
/*
* Static function declarations
*/
@ -181,9 +199,21 @@ chanid_circid_entry_hash(chanid_circid_muxinfo_t *a);
static chanid_circid_muxinfo_t *
circuitmux_find_map_entry(circuitmux_t *cmux, circuit_t *circ);
static void
circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ);
circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ,
cell_direction_t direction);
static void
circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ);
circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ,
cell_direction_t direction);
static inline void
circuitmux_move_active_circ_to_tail(circuitmux_t *cmux, circuit_t *circ,
cell_direction_t direction);
static inline circuit_t **
circuitmux_next_active_circ_p(circuitmux_t *cmux, circuit_t *circ);
static inline circuit_t **
circuitmux_prev_active_circ_p(circuitmux_t *cmux, circuit_t *circ);
static void circuitmux_assert_okay_pass_one(circuitmux_t *cmux);
static void circuitmux_assert_okay_pass_two(circuitmux_t *cmux);
static void circuitmux_assert_okay_pass_three(circuitmux_t *cmux);
/* Static global variables */
@ -192,6 +222,119 @@ static int64_t global_destroy_ctr = 0;
/* Function definitions */
/**
* Linked list helpers
*/
/**
* Move an active circuit to the tail of the cmux's active circuits list;
* used by circuitmux_notify_xmit_cells().
*/
static inline void
circuitmux_move_active_circ_to_tail(circuitmux_t *cmux, circuit_t *circ,
cell_direction_t direction)
{
circuit_t **next_p = NULL, **prev_p = NULL;
circuit_t **next_prev = NULL, **prev_next = NULL;
circuit_t **tail_next = NULL;
or_circuit_t *or_circ = NULL;
tor_assert(cmux);
tor_assert(circ);
circuitmux_assert_okay_paranoid(cmux);
/* Figure out our next_p and prev_p for this cmux/direction */
if (direction) {
if (direction == CELL_DIRECTION_OUT) {
tor_assert(circ->n_mux == cmux);
next_p = &(circ->next_active_on_n_chan);
prev_p = &(circ->prev_active_on_n_chan);
} else {
or_circ = TO_OR_CIRCUIT(circ);
tor_assert(or_circ->p_mux == cmux);
next_p = &(or_circ->next_active_on_p_chan);
prev_p = &(or_circ->prev_active_on_p_chan);
}
} else {
if (circ->n_mux == cmux) {
next_p = &(circ->next_active_on_n_chan);
prev_p = &(circ->prev_active_on_n_chan);
} else {
or_circ = TO_OR_CIRCUIT(circ);
tor_assert(or_circ->p_mux == cmux);
next_p = &(or_circ->next_active_on_p_chan);
prev_p = &(or_circ->prev_active_on_p_chan);
}
}
tor_assert(next_p);
tor_assert(prev_p);
/* Check if this really is an active circuit */
if ((*next_p == NULL && *prev_p == NULL) &&
!(circ == cmux->active_circuits_head ||
circ == cmux->active_circuits_tail)) {
/* Not active, no-op */
return;
}
/* Check if this is already the tail */
if (circ == cmux->active_circuits_tail) return;
/* Okay, we have to move it; figure out next_prev and prev_next */
if (*next_p) next_prev = circuitmux_prev_active_circ_p(cmux, *next_p);
if (*prev_p) prev_next = circuitmux_next_active_circ_p(cmux, *prev_p);
/* Adjust the previous node's next pointer, if any */
if (prev_next) *prev_next = *next_p;
/* Otherwise, we were the head */
else cmux->active_circuits_head = *next_p;
/* Adjust the next node's previous pointer, if any */
if (next_prev) *next_prev = *prev_p;
/* We're out of the list; now re-attach at the tail */
/* Adjust our next and prev pointers */
*next_p = NULL;
*prev_p = cmux->active_circuits_tail;
/* Set the next pointer of the tail, or the head if none */
if (cmux->active_circuits_tail) {
tail_next = circuitmux_next_active_circ_p(cmux,
cmux->active_circuits_tail);
*tail_next = circ;
} else {
cmux->active_circuits_head = circ;
}
/* Set the tail to this circuit */
cmux->active_circuits_tail = circ;
circuitmux_assert_okay_paranoid(cmux);
}
static inline circuit_t **
circuitmux_next_active_circ_p(circuitmux_t *cmux, circuit_t *circ)
{
tor_assert(cmux);
tor_assert(circ);
if (circ->n_mux == cmux) return &(circ->next_active_on_n_chan);
else {
tor_assert(TO_OR_CIRCUIT(circ)->p_mux == cmux);
return &(TO_OR_CIRCUIT(circ)->next_active_on_p_chan);
}
}
static inline circuit_t **
circuitmux_prev_active_circ_p(circuitmux_t *cmux, circuit_t *circ)
{
tor_assert(cmux);
tor_assert(circ);
if (circ->n_mux == cmux) return &(circ->prev_active_on_n_chan);
else {
tor_assert(TO_OR_CIRCUIT(circ)->p_mux == cmux);
return &(TO_OR_CIRCUIT(circ)->prev_active_on_p_chan);
}
}
/**
* Helper for chanid_circid_cell_count_map_t hash table: compare the channel
* ID and circuit ID for a and b, and return less than, equal to, or greater
@ -263,6 +406,11 @@ circuitmux_detach_all_circuits(circuitmux_t *cmux, smartlist_t *detached_out)
circuit_t *circ = NULL;
tor_assert(cmux);
/*
* Don't circuitmux_assert_okay_paranoid() here; this gets called when
* channels are being freed and have already been unregistered, so
* the channel ID lookups it does will fail.
*/
i = HT_START(chanid_circid_muxinfo_map, cmux->chanid_circid_map);
while (i) {
@ -287,7 +435,7 @@ circuitmux_detach_all_circuits(circuitmux_t *cmux, smartlist_t *detached_out)
*/
if (to_remove->muxinfo.cell_count > 0) {
circuitmux_make_circuit_inactive(cmux, circ);
circuitmux_make_circuit_inactive(cmux, circ, CELL_DIRECTION_OUT);
}
/* Clear n_mux */
@ -302,7 +450,7 @@ circuitmux_detach_all_circuits(circuitmux_t *cmux, smartlist_t *detached_out)
*/
if (to_remove->muxinfo.cell_count > 0) {
circuitmux_make_circuit_inactive(cmux, circ);
circuitmux_make_circuit_inactive(cmux, circ, CELL_DIRECTION_IN);
}
/*
@ -458,7 +606,9 @@ circuitmux_clear_policy(circuitmux_t *cmux)
tor_assert(cmux);
/* Internally, this is just setting policy to NULL */
circuitmux_set_policy(cmux, NULL);
if (cmux->policy) {
circuitmux_set_policy(cmux, NULL);
}
}
/**
@ -794,6 +944,7 @@ circuitmux_attach_circuit,(circuitmux_t *cmux, circuit_t *circ,
tor_assert(circ);
tor_assert(direction == CELL_DIRECTION_IN ||
direction == CELL_DIRECTION_OUT);
circuitmux_assert_okay_paranoid(cmux);
/*
* Figure out which channel we're using, and get the circuit's current
@ -851,10 +1002,10 @@ circuitmux_attach_circuit,(circuitmux_t *cmux, circuit_t *circ,
*/
if (hashent->muxinfo.cell_count > 0 && cell_count == 0) {
--(cmux->n_active_circuits);
circuitmux_make_circuit_inactive(cmux, circ);
circuitmux_make_circuit_inactive(cmux, circ, direction);
} else if (hashent->muxinfo.cell_count == 0 && cell_count > 0) {
++(cmux->n_active_circuits);
circuitmux_make_circuit_active(cmux, circ);
circuitmux_make_circuit_active(cmux, circ, direction);
}
cmux->n_cells -= hashent->muxinfo.cell_count;
cmux->n_cells += cell_count;
@ -882,7 +1033,7 @@ circuitmux_attach_circuit,(circuitmux_t *cmux, circuit_t *circ,
hashent->muxinfo.cell_count = cell_count;
hashent->muxinfo.direction = direction;
/* Allocate policy specific circuit data if we need it */
if (cmux->policy->alloc_circ_data) {
if (cmux->policy && cmux->policy->alloc_circ_data) {
/* Assert that we have the means to free policy-specific data */
tor_assert(cmux->policy->free_circ_data);
/* Allocate it */
@ -902,14 +1053,25 @@ circuitmux_attach_circuit,(circuitmux_t *cmux, circuit_t *circ,
if (direction == CELL_DIRECTION_OUT) circ->n_mux = cmux;
else TO_OR_CIRCUIT(circ)->p_mux = cmux;
/* Make sure the next/prev pointers are NULL */
if (direction == CELL_DIRECTION_OUT) {
circ->next_active_on_n_chan = NULL;
circ->prev_active_on_n_chan = NULL;
} else {
TO_OR_CIRCUIT(circ)->next_active_on_p_chan = NULL;
TO_OR_CIRCUIT(circ)->prev_active_on_p_chan = NULL;
}
/* Update counters */
++(cmux->n_circuits);
if (cell_count > 0) {
++(cmux->n_active_circuits);
circuitmux_make_circuit_active(cmux, circ);
circuitmux_make_circuit_active(cmux, circ, direction);
}
cmux->n_cells += cell_count;
}
circuitmux_assert_okay_paranoid(cmux);
}
/**
@ -933,6 +1095,7 @@ circuitmux_detach_circuit,(circuitmux_t *cmux, circuit_t *circ))
tor_assert(cmux);
tor_assert(cmux->chanid_circid_map);
tor_assert(circ);
circuitmux_assert_okay_paranoid(cmux);
/* See if we have it for n_chan/n_circ_id */
if (circ->n_chan) {
@ -970,7 +1133,7 @@ circuitmux_detach_circuit,(circuitmux_t *cmux, circuit_t *circ))
if (hashent->muxinfo.cell_count > 0) {
--(cmux->n_active_circuits);
/* This does policy notifies, so comes before freeing policy data */
circuitmux_make_circuit_inactive(cmux, circ);
circuitmux_make_circuit_inactive(cmux, circ, last_searched_direction);
}
cmux->n_cells -= hashent->muxinfo.cell_count;
@ -999,6 +1162,8 @@ circuitmux_detach_circuit,(circuitmux_t *cmux, circuit_t *circ))
/* Free the hash entry */
tor_free(hashent);
}
circuitmux_assert_okay_paranoid(cmux);
}
/**
@ -1007,22 +1172,94 @@ circuitmux_detach_circuit,(circuitmux_t *cmux, circuit_t *circ))
*/
static void
circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ)
circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ,
cell_direction_t direction)
{
circuit_t **next_active = NULL, **prev_active = NULL, **next_prev = NULL;
circuitmux_t *circuit_cmux = NULL;
chanid_circid_muxinfo_t *hashent = NULL;
channel_t *chan = NULL;
circid_t circ_id;
int already_active;
tor_assert(cmux);
tor_assert(cmux->policy);
tor_assert(circ);
tor_assert(direction == CELL_DIRECTION_OUT ||
direction == CELL_DIRECTION_IN);
/*
* Don't circuitmux_assert_okay_paranoid(cmux) here because the cell count
* already got changed and we have to update the list for it to be consistent
* again.
*/
/* Get the right set of active list links for this direction */
if (direction == CELL_DIRECTION_OUT) {
next_active = &(circ->next_active_on_n_chan);
prev_active = &(circ->prev_active_on_n_chan);
circuit_cmux = circ->n_mux;
chan = circ->n_chan;
circ_id = circ->n_circ_id;
} else {
next_active = &(TO_OR_CIRCUIT(circ)->next_active_on_p_chan);
prev_active = &(TO_OR_CIRCUIT(circ)->prev_active_on_p_chan);
circuit_cmux = TO_OR_CIRCUIT(circ)->p_mux;
chan = TO_OR_CIRCUIT(circ)->p_chan;
circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
}
/* Assert that it is attached to this mux and a channel */
tor_assert(cmux == circuit_cmux);
tor_assert(chan != NULL);
/*
* Check if the circuit really was inactive; if it's active, at least one
* of the next_active and prev_active pointers will not be NULL, or this
* circuit will be either the head or tail of the list for this cmux.
*/
already_active = (*prev_active != NULL || *next_active != NULL ||
cmux->active_circuits_head == circ ||
cmux->active_circuits_tail == circ);
/* If we're already active, log a warning and finish */
if (already_active) {
log_warn(LD_CIRC,
"Circuit %u on channel " U64_FORMAT " was already active",
(unsigned)circ_id, U64_PRINTF_ARG(chan->global_identifier));
return;
}
/*
* This is going at the head of the list; if the old head is not NULL,
* then its prev pointer should point to this.
*/
*next_active = cmux->active_circuits_head; /* Next is old head */
*prev_active = NULL; /* Prev is NULL (this will be the head) */
if (cmux->active_circuits_head) {
/* The list had an old head; update its prev pointer */
next_prev =
circuitmux_prev_active_circ_p(cmux, cmux->active_circuits_head);
tor_assert(next_prev);
*next_prev = circ;
} else {
/* The list was empty; this becomes the tail as well */
cmux->active_circuits_tail = circ;
}
/* This becomes the new head of the list */
cmux->active_circuits_head = circ;
/* Policy-specific notification */
if (cmux->policy->notify_circ_active) {
if (cmux->policy &&
cmux->policy->notify_circ_active) {
/* Okay, we need to check the circuit for policy data now */
chanid_circid_muxinfo_t *hashent = circuitmux_find_map_entry(cmux, circ);
hashent = circuitmux_find_map_entry(cmux, circ);
/* We should have found something */
tor_assert(hashent);
/* Notify */
cmux->policy->notify_circ_active(cmux, cmux->policy_data,
circ, hashent->muxinfo.policy_data);
}
circuitmux_assert_okay_paranoid(cmux);
}
/**
@ -1031,22 +1268,112 @@ circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ)
*/
static void
circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ)
circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ,
cell_direction_t direction)
{
circuit_t **next_active = NULL, **prev_active = NULL;
circuit_t **next_prev = NULL, **prev_next = NULL;
circuitmux_t *circuit_cmux = NULL;
chanid_circid_muxinfo_t *hashent = NULL;
channel_t *chan = NULL;
circid_t circ_id;
int already_inactive;
tor_assert(cmux);
tor_assert(cmux->policy);
tor_assert(circ);
tor_assert(direction == CELL_DIRECTION_OUT ||
direction == CELL_DIRECTION_IN);
/*
* Don't circuitmux_assert_okay_paranoid(cmux) here because the cell count
* already got changed and we have to update the list for it to be consistent
* again.
*/
/* Get the right set of active list links for this direction */
if (direction == CELL_DIRECTION_OUT) {
next_active = &(circ->next_active_on_n_chan);
prev_active = &(circ->prev_active_on_n_chan);
circuit_cmux = circ->n_mux;
chan = circ->n_chan;
circ_id = circ->n_circ_id;
} else {
next_active = &(TO_OR_CIRCUIT(circ)->next_active_on_p_chan);
prev_active = &(TO_OR_CIRCUIT(circ)->prev_active_on_p_chan);
circuit_cmux = TO_OR_CIRCUIT(circ)->p_mux;
chan = TO_OR_CIRCUIT(circ)->p_chan;
circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
}
/* Assert that it is attached to this mux and a channel */
tor_assert(cmux == circuit_cmux);
tor_assert(chan != NULL);
/*
* Check if the circuit really was active; if it's inactive, the
* next_active and prev_active pointers will be NULL and this circuit
* will not be the head or tail of the list for this cmux.
*/
already_inactive = (*prev_active == NULL && *next_active == NULL &&
cmux->active_circuits_head != circ &&
cmux->active_circuits_tail != circ);
/* If we're already inactive, log a warning and finish */
if (already_inactive) {
log_warn(LD_CIRC,
"Circuit %d on channel " U64_FORMAT " was already inactive",
(unsigned)circ_id, U64_PRINTF_ARG(chan->global_identifier));
return;
}
/* Remove from the list; first get next_prev and prev_next */
if (*next_active) {
/*
* If there's a next circuit, its previous circuit becomes this
* circuit's previous circuit.
*/
next_prev = circuitmux_prev_active_circ_p(cmux, *next_active);
} else {
/* Else, the tail becomes this circuit's previous circuit */
next_prev = &(cmux->active_circuits_tail);
}
/* Got next_prev, now prev_next */
if (*prev_active) {
/*
* If there's a previous circuit, its next circuit becomes this circuit's
* next circuit.
*/
prev_next = circuitmux_next_active_circ_p(cmux, *prev_active);
} else {
/* Else, the head becomes this circuit's next circuit */
prev_next = &(cmux->active_circuits_head);
}
/* Assert that we got sensible values for the next/prev pointers */
tor_assert(next_prev != NULL);
tor_assert(prev_next != NULL);
/* Update the next/prev pointers - this removes circ from the list */
*next_prev = *prev_active;
*prev_next = *next_active;
/* Now null out prev_active/next_active */
*prev_active = NULL;
*next_active = NULL;
/* Policy-specific notification */
if (cmux->policy->notify_circ_inactive) {
if (cmux->policy &&
cmux->policy->notify_circ_inactive) {
/* Okay, we need to check the circuit for policy data now */
chanid_circid_muxinfo_t *hashent = circuitmux_find_map_entry(cmux, circ);
hashent = circuitmux_find_map_entry(cmux, circ);
/* We should have found something */
tor_assert(hashent);
/* Notify */
cmux->policy->notify_circ_inactive(cmux, cmux->policy_data,
circ, hashent->muxinfo.policy_data);
}
circuitmux_assert_okay_paranoid(cmux);
}
/**
@ -1073,6 +1400,8 @@ circuitmux_set_num_cells(circuitmux_t *cmux, circuit_t *circ,
tor_assert(cmux);
tor_assert(circ);
circuitmux_assert_okay_paranoid(cmux);
/* Search for this circuit's entry */
hashent = circuitmux_find_map_entry(cmux, circ);
/* Assert that we found one */
@ -1083,7 +1412,7 @@ circuitmux_set_num_cells(circuitmux_t *cmux, circuit_t *circ,
cmux->n_cells += n_cells;
/* Do we need to notify a cmux policy? */
if (cmux->policy->notify_set_n_cells) {
if (cmux->policy && cmux->policy->notify_set_n_cells) {
/* Call notify_set_n_cells */
cmux->policy->notify_set_n_cells(cmux,
cmux->policy_data,
@ -1099,15 +1428,21 @@ circuitmux_set_num_cells(circuitmux_t *cmux, circuit_t *circ,
if (hashent->muxinfo.cell_count > 0 && n_cells == 0) {
--(cmux->n_active_circuits);
hashent->muxinfo.cell_count = n_cells;
circuitmux_make_circuit_inactive(cmux, circ);
circuitmux_make_circuit_inactive(cmux, circ, hashent->muxinfo.direction);
/* Is the old cell count == 0 and the new cell count > 0 ? */
} else if (hashent->muxinfo.cell_count == 0 && n_cells > 0) {
++(cmux->n_active_circuits);
hashent->muxinfo.cell_count = n_cells;
circuitmux_make_circuit_active(cmux, circ);
circuitmux_make_circuit_active(cmux, circ, hashent->muxinfo.direction);
} else {
/*
* Update the entry cell count like this so we can put a
* circuitmux_assert_okay_paranoid inside make_circuit_(in)active() too.
*/
hashent->muxinfo.cell_count = n_cells;
}
circuitmux_assert_okay_paranoid(cmux);
}
/*
@ -1133,9 +1468,6 @@ circuitmux_get_first_active_circuit(circuitmux_t *cmux,
circuit_t *circ = NULL;
tor_assert(cmux);
tor_assert(cmux->policy);
/* This callback is mandatory. */
tor_assert(cmux->policy->pick_active_circuit);
tor_assert(destroy_queue_out);
*destroy_queue_out = NULL;
@ -1154,7 +1486,14 @@ circuitmux_get_first_active_circuit(circuitmux_t *cmux,
/* We also must have a cell available for this to be the case */
tor_assert(cmux->n_cells > 0);
/* Do we have a policy-provided circuit selector? */
circ = cmux->policy->pick_active_circuit(cmux, cmux->policy_data);
if (cmux->policy && cmux->policy->pick_active_circuit) {
circ = cmux->policy->pick_active_circuit(cmux, cmux->policy_data);
}
/* Fall back on the head of the active circuits list */
if (!circ) {
tor_assert(cmux->active_circuits_head);
circ = cmux->active_circuits_head;
}
cmux->last_cell_was_destroy = 0;
} else {
tor_assert(cmux->n_cells == 0);
@ -1178,6 +1517,7 @@ circuitmux_notify_xmit_cells(circuitmux_t *cmux, circuit_t *circ,
tor_assert(cmux);
tor_assert(circ);
circuitmux_assert_okay_paranoid(cmux);
if (n_cells == 0) return;
@ -1204,11 +1544,17 @@ circuitmux_notify_xmit_cells(circuitmux_t *cmux, circuit_t *circ,
/* Adjust the mux cell counter */
cmux->n_cells -= n_cells;
/* If we aren't making it inactive later, move it to the tail of the list */
if (!becomes_inactive) {
circuitmux_move_active_circ_to_tail(cmux, circ,
hashent->muxinfo.direction);
}
/*
* We call notify_xmit_cells() before making the circuit inactive if needed,
* so the policy can always count on this coming in on an active circuit.
*/
if (cmux->policy->notify_xmit_cells) {
if (cmux->policy && cmux->policy->notify_xmit_cells) {
cmux->policy->notify_xmit_cells(cmux, cmux->policy_data, circ,
hashent->muxinfo.policy_data,
n_cells);
@ -1220,8 +1566,10 @@ circuitmux_notify_xmit_cells(circuitmux_t *cmux, circuit_t *circ,
*/
if (becomes_inactive) {
--(cmux->n_active_circuits);
circuitmux_make_circuit_inactive(cmux, circ);
circuitmux_make_circuit_inactive(cmux, circ, hashent->muxinfo.direction);
}
circuitmux_assert_okay_paranoid(cmux);
}
/**
@ -1244,6 +1592,282 @@ circuitmux_notify_xmit_destroy(circuitmux_t *cmux)
I64_PRINTF_ARG(global_destroy_ctr));
}
/*
* Circuitmux consistency checking assertions
*/
/**
* Check that circuitmux data structures are consistent and fail with an
* assert if not.
*/
void
circuitmux_assert_okay(circuitmux_t *cmux)
{
tor_assert(cmux);
/*
* Pass 1: iterate the hash table; for each entry:
* a) Check that the circuit has this cmux for n_mux or p_mux
* b) If the cell_count is > 0, set the mark bit; otherwise clear it
* c) Also check activeness (cell_count > 0 should be active)
* d) Count the number of circuits, active circuits and queued cells
* and at the end check that they match the counters in the cmux.
*
* Pass 2: iterate the active circuits list; for each entry,
* make sure the circuit is attached to this mux and appears
* in the hash table. Make sure the mark bit is 1, and clear
* it in the hash table entry. Consistency-check the linked
* list pointers.
*
* Pass 3: iterate the hash table again; assert if any active circuits
* (mark bit set to 1) are discovered that weren't cleared in pass 2
* (don't appear in the linked list).
*/
circuitmux_assert_okay_pass_one(cmux);
circuitmux_assert_okay_pass_two(cmux);
circuitmux_assert_okay_pass_three(cmux);
}
/**
* Do the first pass of circuitmux_assert_okay(); see the comment in that
* function.
*/
static void
circuitmux_assert_okay_pass_one(circuitmux_t *cmux)
{
chanid_circid_muxinfo_t **i = NULL;
uint64_t chan_id;
channel_t *chan;
circid_t circ_id;
circuit_t *circ;
or_circuit_t *or_circ;
circuit_t **next_p, **prev_p;
unsigned int n_circuits, n_active_circuits, n_cells;
tor_assert(cmux);
tor_assert(cmux->chanid_circid_map);
/* Reset the counters */
n_circuits = n_active_circuits = n_cells = 0;
/* Start iterating the hash table */
i = HT_START(chanid_circid_muxinfo_map, cmux->chanid_circid_map);
while (i) {
/* Assert that the hash table entry isn't null */
tor_assert(*i);
/* Get the channel and circuit id */
chan_id = (*i)->chan_id;
circ_id = (*i)->circ_id;
/* Find the channel and circuit, assert that they exist */
chan = channel_find_by_global_id(chan_id);
tor_assert(chan);
circ = circuit_get_by_circid_channel_even_if_marked(circ_id, chan);
tor_assert(circ);
/* Assert that we know which direction this is going */
tor_assert((*i)->muxinfo.direction == CELL_DIRECTION_OUT ||
(*i)->muxinfo.direction == CELL_DIRECTION_IN);
if ((*i)->muxinfo.direction == CELL_DIRECTION_OUT) {
/* We should be n_mux on this circuit */
tor_assert(cmux == circ->n_mux);
tor_assert(chan == circ->n_chan);
/* Get next and prev for next test */
next_p = &(circ->next_active_on_n_chan);
prev_p = &(circ->prev_active_on_n_chan);
} else {
/* This should be an or_circuit_t and we should be p_mux */
or_circ = TO_OR_CIRCUIT(circ);
tor_assert(cmux == or_circ->p_mux);
tor_assert(chan == or_circ->p_chan);
/* Get next and prev for next test */
next_p = &(or_circ->next_active_on_p_chan);
prev_p = &(or_circ->prev_active_on_p_chan);
}
/*
* Should this circuit be active? I.e., does the mux know about > 0
* cells on it?
*/
const int circ_is_active = ((*i)->muxinfo.cell_count > 0);
/* It should be in the linked list iff it's active */
if (circ_is_active) {
/* Either we have a next link or we are the tail */
tor_assert(*next_p || (circ == cmux->active_circuits_tail));
/* Either we have a prev link or we are the head */
tor_assert(*prev_p || (circ == cmux->active_circuits_head));
/* Increment the active circuits counter */
++n_active_circuits;
} else {
/* Shouldn't be in list, so no next or prev link */
tor_assert(!(*next_p));
tor_assert(!(*prev_p));
/* And can't be head or tail */
tor_assert(circ != cmux->active_circuits_head);
tor_assert(circ != cmux->active_circuits_tail);
}
/* Increment the circuits counter */
++n_circuits;
/* Adjust the cell counter */
n_cells += (*i)->muxinfo.cell_count;
/* Set the mark bit to circ_is_active */
(*i)->muxinfo.mark = circ_is_active;
/* Advance to the next entry */
i = HT_NEXT(chanid_circid_muxinfo_map, cmux->chanid_circid_map, i);
}
/* Now check the counters */
tor_assert(n_cells == cmux->n_cells);
tor_assert(n_circuits == cmux->n_circuits);
tor_assert(n_active_circuits == cmux->n_active_circuits);
}
/**
* Do the second pass of circuitmux_assert_okay(); see the comment in that
* function.
*/
static void
circuitmux_assert_okay_pass_two(circuitmux_t *cmux)
{
circuit_t *curr_circ, *prev_circ = NULL, *next_circ;
or_circuit_t *curr_or_circ;
uint64_t curr_chan_id;
circid_t curr_circ_id;
circuit_t **next_p, **prev_p;
channel_t *chan;
unsigned int n_active_circuits = 0;
chanid_circid_muxinfo_t search, *hashent = NULL;
tor_assert(cmux);
tor_assert(cmux->chanid_circid_map);
/*
* Walk the linked list of active circuits in cmux; keep track of the
* previous circuit seen for consistency checking purposes. Count them
* to make sure the number in the linked list matches
* cmux->n_active_circuits.
*/
curr_circ = cmux->active_circuits_head;
while (curr_circ) {
/* Reset some things */
chan = NULL;
curr_or_circ = NULL;
next_circ = NULL;
next_p = prev_p = NULL;
cell_direction_t direction;
/* Figure out if this is n_mux or p_mux */
if (cmux == curr_circ->n_mux) {
/* Get next_p and prev_p */
next_p = &(curr_circ->next_active_on_n_chan);
prev_p = &(curr_circ->prev_active_on_n_chan);
/* Get the channel */
chan = curr_circ->n_chan;
/* Get the circuit id */
curr_circ_id = curr_circ->n_circ_id;
/* Remember the direction */
direction = CELL_DIRECTION_OUT;
} else {
/* We must be p_mux and this must be an or_circuit_t */
curr_or_circ = TO_OR_CIRCUIT(curr_circ);
tor_assert(cmux == curr_or_circ->p_mux);
/* Get next_p and prev_p */
next_p = &(curr_or_circ->next_active_on_p_chan);
prev_p = &(curr_or_circ->prev_active_on_p_chan);
/* Get the channel */
chan = curr_or_circ->p_chan;
/* Get the circuit id */
curr_circ_id = curr_or_circ->p_circ_id;
/* Remember the direction */
direction = CELL_DIRECTION_IN;
}
/* Assert that we got a channel and get the channel ID */
tor_assert(chan);
curr_chan_id = chan->global_identifier;
/* Assert that prev_p points to last circuit we saw */
tor_assert(*prev_p == prev_circ);
/* If that's NULL, assert that we are the head */
if (!(*prev_p)) tor_assert(curr_circ == cmux->active_circuits_head);
/* Get the next circuit */
next_circ = *next_p;
/* If it's NULL, assert that we are the tail */
if (!(*next_p)) tor_assert(curr_circ == cmux->active_circuits_tail);
/* Now find the hash table entry for this circuit */
search.chan_id = curr_chan_id;
search.circ_id = curr_circ_id;
hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
&search);
/* Assert that we have one */
tor_assert(hashent);
/* Assert that the direction matches */
tor_assert(direction == hashent->muxinfo.direction);
/* Assert that the hash entry got marked in pass one */
tor_assert(hashent->muxinfo.mark);
/* Clear the mark */
hashent->muxinfo.mark = 0;
/* Increment the counter */
++n_active_circuits;
/* Advance to the next active circuit and update prev_circ */
prev_circ = curr_circ;
curr_circ = next_circ;
}
/* Assert that the counter matches the cmux */
tor_assert(n_active_circuits == cmux->n_active_circuits);
}
/**
* Do the third pass of circuitmux_assert_okay(); see the comment in that
* function.
*/
static void
circuitmux_assert_okay_pass_three(circuitmux_t *cmux)
{
chanid_circid_muxinfo_t **i = NULL;
tor_assert(cmux);
tor_assert(cmux->chanid_circid_map);
/* Start iterating the hash table */
i = HT_START(chanid_circid_muxinfo_map, cmux->chanid_circid_map);
/* Advance through each entry */
while (i) {
/* Assert that it isn't null */
tor_assert(*i);
/*
* Assert that this entry is not marked - i.e., that either we didn't
* think it should be active in pass one or we saw it in the active
* circuits linked list.
*/
tor_assert(!((*i)->muxinfo.mark));
/* Advance to the next entry */
i = HT_NEXT(chanid_circid_muxinfo_map, cmux->chanid_circid_map, i);
}
}
/*DOCDOC */
void
circuitmux_append_destroy_cell(channel_t *chan,

View File

@ -28,7 +28,7 @@
*
**/
#define CIRCUITMUX_EWMA_PRIVATE
#define TOR_CIRCUITMUX_EWMA_C_
#include "orconfig.h"
@ -37,7 +37,6 @@
#include "or.h"
#include "circuitmux.h"
#include "circuitmux_ewma.h"
#include "crypto_rand.h"
#include "networkstatus.h"
/*** EWMA parameter #defines ***/
@ -170,6 +169,8 @@ TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol)
static void add_cell_ewma(ewma_policy_data_t *pol, cell_ewma_t *ewma);
static int compare_cell_ewma_counts(const void *p1, const void *p2);
static unsigned cell_ewma_tick_from_timeval(const struct timeval *now,
double *remainder_out);
static circuit_t * cell_ewma_to_circuit(cell_ewma_t *ewma);
static inline double get_scale_factor(unsigned from_tick, unsigned to_tick);
static cell_ewma_t * pop_first_cell_ewma(ewma_policy_data_t *pol);
@ -222,6 +223,8 @@ ewma_cmp_cmux(circuitmux_t *cmux_1, circuitmux_policy_data_t *pol_data_1,
* has value ewma_scale_factor ** N.)
*/
static double ewma_scale_factor = 0.1;
/* DOCDOC ewma_enabled */
static int ewma_enabled = 0;
/*** EWMA circuitmux_policy_t method table ***/
@ -238,26 +241,8 @@ circuitmux_policy_t ewma_policy = {
/*.cmp_cmux =*/ ewma_cmp_cmux
};
/** Have we initialized the ewma tick-counting logic? */
static int ewma_ticks_initialized = 0;
/** At what monotime_coarse_t did the current tick begin? */
static monotime_coarse_t start_of_current_tick;
/** What is the number of the current tick? */
static unsigned current_tick_num;
/*** EWMA method implementations using the below EWMA helper functions ***/
/** Compute and return the current cell_ewma tick. */
static inline unsigned int
cell_ewma_get_tick(void)
{
monotime_coarse_t now;
monotime_coarse_get(&now);
int32_t msec_diff = monotime_coarse_diff_msec32(&start_of_current_tick,
&now);
return current_tick_num + msec_diff / (1000*EWMA_TICK_LEN);
}
/**
* Allocate an ewma_policy_data_t and upcast it to a circuitmux_policy_data_t;
* this is called when setting the policy on a circuitmux_t to ewma_policy.
@ -431,6 +416,8 @@ ewma_notify_xmit_cells(circuitmux_t *cmux,
ewma_policy_circ_data_t *cdata = NULL;
unsigned int tick;
double fractional_tick, ewma_increment;
/* The current (hi-res) time */
struct timeval now_hires;
cell_ewma_t *cell_ewma, *tmp;
tor_assert(cmux);
@ -443,7 +430,8 @@ ewma_notify_xmit_cells(circuitmux_t *cmux,
cdata = TO_EWMA_POL_CIRC_DATA(pol_circ_data);
/* Rescale the EWMAs if needed */
tick = cell_ewma_get_current_tick_and_fraction(&fractional_tick);
tor_gettimeofday_cached(&now_hires);
tick = cell_ewma_tick_from_timeval(&now_hires, &fractional_tick);
if (tick != pol->active_circuit_pqueue_last_recalibrated) {
scale_active_circuits(pol, tick);
@ -604,122 +592,79 @@ cell_ewma_to_circuit(cell_ewma_t *ewma)
rescale.
*/
/**
* Initialize the system that tells which ewma tick we are in.
*/
STATIC void
cell_ewma_initialize_ticks(void)
{
if (ewma_ticks_initialized)
return;
monotime_coarse_get(&start_of_current_tick);
crypto_rand((char*)&current_tick_num, sizeof(current_tick_num));
ewma_ticks_initialized = 1;
}
/** Compute the current cell_ewma tick and the fraction of the tick that has
* elapsed between the start of the tick and the current time. Return the
* former and store the latter in *<b>remainder_out</b>.
/** Given a timeval <b>now</b>, compute the cell_ewma tick in which it occurs
* and the fraction of the tick that has elapsed between the start of the tick
* and <b>now</b>. Return the former and store the latter in
* *<b>remainder_out</b>.
*
* These tick values are not meant to be shared between Tor instances, or used
* for other purposes. */
STATIC unsigned
cell_ewma_get_current_tick_and_fraction(double *remainder_out)
static unsigned
cell_ewma_tick_from_timeval(const struct timeval *now,
double *remainder_out)
{
if (BUG(!ewma_ticks_initialized)) {
cell_ewma_initialize_ticks(); // LCOV_EXCL_LINE
}
monotime_coarse_t now;
monotime_coarse_get(&now);
int32_t msec_diff = monotime_coarse_diff_msec32(&start_of_current_tick,
&now);
if (msec_diff > (1000*EWMA_TICK_LEN)) {
unsigned ticks_difference = msec_diff / (1000*EWMA_TICK_LEN);
monotime_coarse_add_msec(&start_of_current_tick,
&start_of_current_tick,
ticks_difference * 1000 * EWMA_TICK_LEN);
current_tick_num += ticks_difference;
msec_diff %= 1000*EWMA_TICK_LEN;
}
*remainder_out = ((double)msec_diff) / (1.0e3 * EWMA_TICK_LEN);
return current_tick_num;
unsigned res = (unsigned) (now->tv_sec / EWMA_TICK_LEN);
/* rem */
double rem = (now->tv_sec % EWMA_TICK_LEN) +
((double)(now->tv_usec)) / 1.0e6;
*remainder_out = rem / EWMA_TICK_LEN;
return res;
}
/* Default value for the CircuitPriorityHalflifeMsec consensus parameter in
* msec. */
#define CMUX_PRIORITY_HALFLIFE_MSEC_DEFAULT 30000
/* Minimum and maximum value for the CircuitPriorityHalflifeMsec consensus
* parameter. */
#define CMUX_PRIORITY_HALFLIFE_MSEC_MIN 1
#define CMUX_PRIORITY_HALFLIFE_MSEC_MAX INT32_MAX
/* Return the value of the circuit priority halflife from the options if
* available or else from the consensus (in that order). If none can be found,
* a default value is returned.
*
* The source_msg points to a string describing from where the value was
* picked so it can be used for logging. */
static double
get_circuit_priority_halflife(const or_options_t *options,
const networkstatus_t *consensus,
const char **source_msg)
/** Tell the caller whether ewma_enabled is set */
int
cell_ewma_enabled(void)
{
int32_t halflife_ms;
double halflife;
/* Compute the default value now. We might need it. */
double halflife_default =
((double) CMUX_PRIORITY_HALFLIFE_MSEC_DEFAULT) / 1000.0;
return ewma_enabled;
}
/* Try to get it from configuration file first. */
if (options && options->CircuitPriorityHalflife >= -EPSILON) {
halflife = options->CircuitPriorityHalflife;
*source_msg = "CircuitPriorityHalflife in configuration";
goto end;
}
/* Try to get the msec value from the consensus. */
halflife_ms = networkstatus_get_param(consensus,
"CircuitPriorityHalflifeMsec",
CMUX_PRIORITY_HALFLIFE_MSEC_DEFAULT,
CMUX_PRIORITY_HALFLIFE_MSEC_MIN,
CMUX_PRIORITY_HALFLIFE_MSEC_MAX);
halflife = ((double) halflife_ms) / 1000.0;
*source_msg = "CircuitPriorityHalflifeMsec in consensus";
end:
/* We should never go below the EPSILON else we would consider it disabled
* and we can't have that. */
if (halflife < EPSILON) {
log_warn(LD_CONFIG, "CircuitPriorityHalflife is too small (%f). "
"Adjusting to the smallest value allowed: %f.",
halflife, halflife_default);
halflife = halflife_default;
}
return halflife;
/** Compute and return the current cell_ewma tick. */
unsigned int
cell_ewma_get_tick(void)
{
return ((unsigned)approx_time() / EWMA_TICK_LEN);
}
/** Adjust the global cell scale factor based on <b>options</b> */
void
cmux_ewma_set_options(const or_options_t *options,
const networkstatus_t *consensus)
cell_ewma_set_scale_factor(const or_options_t *options,
const networkstatus_t *consensus)
{
int32_t halflife_ms;
double halflife;
const char *source;
if (options && options->CircuitPriorityHalflife >= -EPSILON) {
halflife = options->CircuitPriorityHalflife;
source = "CircuitPriorityHalflife in configuration";
} else if (consensus && (halflife_ms = networkstatus_get_param(
consensus, "CircuitPriorityHalflifeMsec",
-1, -1, INT32_MAX)) >= 0) {
halflife = ((double)halflife_ms)/1000.0;
source = "CircuitPriorityHalflifeMsec in consensus";
} else {
halflife = EWMA_DEFAULT_HALFLIFE;
source = "Default value";
}
cell_ewma_initialize_ticks();
/* Both options and consensus can be NULL. This assures us to either get a
* valid configured value or the default one. */
halflife = get_circuit_priority_halflife(options, consensus, &source);
/* convert halflife into halflife-per-tick. */
halflife /= EWMA_TICK_LEN;
/* compute per-tick scale factor. */
ewma_scale_factor = exp( LOG_ONEHALF / halflife );
log_info(LD_OR,
"Enabled cell_ewma algorithm because of value in %s; "
"scale factor is %f per %d seconds",
source, ewma_scale_factor, EWMA_TICK_LEN);
if (halflife <= EPSILON) {
/* The cell EWMA algorithm is disabled. */
ewma_scale_factor = 0.1;
ewma_enabled = 0;
log_info(LD_OR,
"Disabled cell_ewma algorithm because of value in %s",
source);
} else {
/* convert halflife into halflife-per-tick. */
halflife /= EWMA_TICK_LEN;
/* compute per-tick scale factor. */
ewma_scale_factor = exp( LOG_ONEHALF / halflife );
ewma_enabled = 1;
log_info(LD_OR,
"Enabled cell_ewma algorithm because of value in %s; "
"scale factor is %f per %d seconds",
source, ewma_scale_factor, EWMA_TICK_LEN);
}
}
/** Return the multiplier necessary to convert the value of a cell sent in
@ -818,12 +763,3 @@ pop_first_cell_ewma(ewma_policy_data_t *pol)
offsetof(cell_ewma_t, heap_index));
}
/**
* Drop all resources held by circuitmux_ewma.c, and deinitialize the
* module. */
void
circuitmux_ewma_free_all(void)
{
ewma_ticks_initialized = 0;
}

View File

@ -12,19 +12,13 @@
#include "or.h"
#include "circuitmux.h"
/* The public EWMA policy callbacks object. */
extern circuitmux_policy_t ewma_policy;
/* Externally visible EWMA functions */
void cmux_ewma_set_options(const or_options_t *options,
const networkstatus_t *consensus);
void circuitmux_ewma_free_all(void);
#ifdef CIRCUITMUX_EWMA_PRIVATE
STATIC unsigned cell_ewma_get_current_tick_and_fraction(double *remainder_out);
STATIC void cell_ewma_initialize_ticks(void);
#endif
int cell_ewma_enabled(void);
unsigned int cell_ewma_get_tick(void);
void cell_ewma_set_scale_factor(const or_options_t *options,
const networkstatus_t *consensus);
#endif /* !defined(TOR_CIRCUITMUX_EWMA_H) */

View File

@ -31,12 +31,10 @@
#include "config.h"
#include "confparse.h"
#include "control.h"
#include "crypto_rand.h"
#include "main.h"
#include "networkstatus.h"
#include "rendclient.h"
#include "rendservice.h"
#include "router.h"
#include "statefile.h"
#include "circuitlist.h"
#include "circuituse.h"
@ -127,7 +125,7 @@ circuit_build_times_disabled_(const or_options_t *options,
ignore_consensus ? 0 : networkstatus_get_param(NULL, "cbtdisabled",
0, 0, 1);
int config_disabled = !options->LearnCircuitBuildTimeout;
int dirauth_disabled = authdir_mode(options);
int dirauth_disabled = options->AuthoritativeDir;
int state_disabled = did_last_state_file_write_fail() ? 1 : 0;
/* LearnCircuitBuildTimeout and Tor2web/Single Onion Services are
* incompatible in two ways:

View File

@ -55,6 +55,7 @@
#include "rephist.h"
#include "router.h"
#include "routerlist.h"
#include "config.h"
static void circuit_expire_old_circuits_clientside(void);
static void circuit_increment_failure_count(void);
@ -1631,7 +1632,7 @@ circuit_testing_opened(origin_circuit_t *circ)
router_perform_bandwidth_test(NUM_PARALLEL_TESTING_CIRCS, time(NULL));
have_performed_bandwidth_test = 1;
} else
router_do_reachability_checks(1, 0);
consider_testing_reachability(1, 0);
}
/** A testing circuit has failed to build. Take whatever stats we want. */
@ -1756,39 +1757,6 @@ circuit_build_failed(origin_circuit_t *circ)
* the last hop or an earlier hop. then use this info below.
*/
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
* at the last hop. */
if (circ->cpath &&
@ -1838,8 +1806,18 @@ circuit_build_failed(origin_circuit_t *circ)
* If we have guard state (new guard API) and our path selection
* code actually chose a full path, then blame the failure of this
* 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)
if (circ->guard_state &&
circuit_get_cpath_len(circ) >= circ->build_state->desired_path_len)
entry_guard_failed(&circ->guard_state);
/* if there are any one-hop streams waiting on this circuit, fail
* them now so they can retry elsewhere. */
@ -2606,7 +2584,7 @@ link_apconn_to_circ(entry_connection_t *apconn, origin_circuit_t *circ,
log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %u.",
(unsigned)circ->base_.n_circ_id);
/* reset it, so we can measure circ timeouts */
ENTRY_TO_CONN(apconn)->timestamp_last_read_allowed = time(NULL);
ENTRY_TO_CONN(apconn)->timestamp_lastread = time(NULL);
ENTRY_TO_EDGE_CONN(apconn)->next_stream = circ->p_streams;
ENTRY_TO_EDGE_CONN(apconn)->on_circuit = TO_CIRCUIT(circ);
/* assert_connection_ok(conn, time(NULL)); */
@ -3106,41 +3084,3 @@ mark_circuit_unusable_for_new_conns(origin_circuit_t *circ)
circ->unusable_for_new_conns = 1;
}
/**
* Add relay_body_len and RELAY_PAYLOAD_SIZE-relay_body_len to
* the valid delivered written fields and the overhead field,
* respectively.
*/
void
circuit_sent_valid_data(origin_circuit_t *circ, uint16_t relay_body_len)
{
if (!circ) return;
tor_assert_nonfatal(relay_body_len <= RELAY_PAYLOAD_SIZE);
circ->n_delivered_written_circ_bw =
tor_add_u32_nowrap(circ->n_delivered_written_circ_bw, relay_body_len);
circ->n_overhead_written_circ_bw =
tor_add_u32_nowrap(circ->n_overhead_written_circ_bw,
RELAY_PAYLOAD_SIZE-relay_body_len);
}
/**
* Add relay_body_len and RELAY_PAYLOAD_SIZE-relay_body_len to
* the valid delivered read field and the overhead field,
* respectively.
*/
void
circuit_read_valid_data(origin_circuit_t *circ, uint16_t relay_body_len)
{
if (!circ) return;
tor_assert_nonfatal(relay_body_len <= RELAY_PAYLOAD_SIZE);
circ->n_delivered_read_circ_bw =
tor_add_u32_nowrap(circ->n_delivered_read_circ_bw, relay_body_len);
circ->n_overhead_read_circ_bw =
tor_add_u32_nowrap(circ->n_overhead_read_circ_bw,
RELAY_PAYLOAD_SIZE-relay_body_len);
}

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