summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--ChangeLog338
-rw-r--r--LICENSE30
-rw-r--r--Makefile.am6
-rw-r--r--ReleaseNotes254
-rw-r--r--changes/bug255525
-rw-r--r--changes/bug262233
-rw-r--r--changes/bug264373
-rw-r--r--changes/bug264854
-rw-r--r--changes/bug265023
-rw-r--r--changes/bug266277
-rw-r--r--changes/bug267854
-rw-r--r--changes/bug267873
-rw-r--r--changes/bug267894
-rw-r--r--changes/bug268303
-rw-r--r--changes/bug268533
-rw-r--r--changes/bug268926
-rw-r--r--changes/bug269244
-rw-r--r--changes/bug269274
-rw-r--r--changes/feature195063
-rw-r--r--changes/task267714
-rw-r--r--changes/ticket213496
-rw-r--r--changes/ticket2648112
-rw-r--r--changes/ticket264924
-rw-r--r--changes/ticket265264
-rw-r--r--changes/ticket26526_extra3
-rw-r--r--changes/ticket266474
-rw-r--r--changes/ticket266633
-rw-r--r--changes/ticket267033
-rw-r--r--changes/ticket3569_part16
-rw-r--r--changes/ticket37233
-rw-r--r--configure.ac206
-rw-r--r--doc/HACKING/CodeStructure.md129
-rw-r--r--doc/HACKING/CodingStandards.md22
-rw-r--r--doc/HACKING/HelpfulTools.md26
-rw-r--r--doc/HACKING/Module.md4
-rw-r--r--doc/HACKING/ReleasingTor.md2
-rw-r--r--doc/include.am7
-rw-r--r--doc/tor-print-ed-signing-cert.1.txt32
-rw-r--r--doc/tor.1.txt4
-rwxr-xr-xscripts/codegen/fuzzing_include_am.py9
-rw-r--r--scripts/maint/fallback.blacklist232
-rwxr-xr-xscripts/maint/updateFallbackDirs.py157
-rw-r--r--src/app/config/auth_dirs.inc4
-rw-r--r--src/app/config/config.c30
-rw-r--r--src/app/config/confparse.c2
-rw-r--r--src/app/config/confparse.h6
-rw-r--r--src/app/config/or_options_st.h6
-rw-r--r--src/app/config/or_state_st.h6
-rw-r--r--src/app/config/statefile.c1
-rw-r--r--src/app/config/statefile.h6
-rw-r--r--src/core/crypto/onion_ntor.c2
-rw-r--r--src/core/include.am6
-rw-r--r--src/core/mainloop/main.c1
-rw-r--r--src/core/or/addr_policy_st.h4
-rw-r--r--src/core/or/connection_edge.c7
-rw-r--r--src/core/or/connection_or.c14
-rw-r--r--src/core/or/or.h6
-rw-r--r--src/core/or/relay.c3
-rw-r--r--src/core/or/scheduler.c4
-rw-r--r--src/core/or/socks_request_st.h2
-rw-r--r--src/core/proto/proto_ext_or.h4
-rw-r--r--src/core/proto/proto_socks.c1127
-rw-r--r--src/ext/getdelim.c78
-rw-r--r--src/ext/include.am2
-rw-r--r--src/ext/tinytest.c2
-rw-r--r--src/feature/client/entrynodes.c324
-rw-r--r--src/feature/control/control.c4
-rw-r--r--src/feature/dirauth/dirvote.c94
-rw-r--r--src/feature/dirauth/dirvote.h3
-rw-r--r--src/feature/dirauth/keypin.c2
-rw-r--r--src/feature/dircache/dirserv.c69
-rw-r--r--src/feature/dircache/dirserv.h14
-rw-r--r--src/feature/dircommon/voting_schedule.c2
-rw-r--r--src/feature/hs/hs_circuit.c20
-rw-r--r--src/feature/hs/hs_common.c9
-rw-r--r--src/feature/hs/hs_service.c338
-rw-r--r--src/feature/hs/hs_service.h19
-rw-r--r--src/feature/hs_common/shared_random_client.c36
-rw-r--r--src/feature/hs_common/shared_random_client.h3
-rw-r--r--src/feature/nodelist/networkstatus.c7
-rw-r--r--src/feature/nodelist/networkstatus_st.h3
-rw-r--r--src/feature/nodelist/parsecommon.c2
-rw-r--r--src/feature/nodelist/routerlist.c1
-rw-r--r--src/feature/nodelist/torcert.c2
-rw-r--r--src/feature/relay/router.c3
-rw-r--r--src/feature/rend/rendservice.c1
-rw-r--r--src/lib/cc/compat_compiler.h6
-rw-r--r--src/lib/cc/torint.h9
-rw-r--r--src/lib/compress/compress.c4
-rw-r--r--src/lib/compress/compress_lzma.c4
-rw-r--r--src/lib/compress/compress_none.c2
-rw-r--r--src/lib/compress/compress_zlib.c2
-rw-r--r--src/lib/compress/compress_zstd.c6
-rw-r--r--src/lib/container/bitarray.h2
-rw-r--r--src/lib/container/bloomfilt.c2
-rw-r--r--src/lib/container/buffers.c4
-rw-r--r--src/lib/container/handles.h2
-rw-r--r--src/lib/container/map.c2
-rw-r--r--src/lib/container/smartlist.c29
-rw-r--r--src/lib/container/smartlist.h3
-rw-r--r--src/lib/crypt_ops/aes.c2
-rw-r--r--src/lib/crypt_ops/aes.h2
-rw-r--r--src/lib/crypt_ops/crypto.c2
-rw-r--r--src/lib/crypt_ops/crypto_curve25519.c2
-rw-r--r--src/lib/crypt_ops/crypto_curve25519.h5
-rw-r--r--src/lib/crypt_ops/crypto_dh.c2
-rw-r--r--src/lib/crypt_ops/crypto_digest.c2
-rw-r--r--src/lib/crypt_ops/crypto_digest.h2
-rw-r--r--src/lib/crypt_ops/crypto_ed25519.c2
-rw-r--r--src/lib/crypt_ops/crypto_ed25519.h5
-rw-r--r--src/lib/crypt_ops/crypto_format.c2
-rw-r--r--src/lib/crypt_ops/crypto_format.h5
-rw-r--r--src/lib/crypt_ops/crypto_hkdf.c4
-rw-r--r--src/lib/crypt_ops/crypto_ope.c185
-rw-r--r--src/lib/crypt_ops/crypto_ope.h46
-rw-r--r--src/lib/crypt_ops/crypto_openssl_mgt.c2
-rw-r--r--src/lib/crypt_ops/crypto_openssl_mgt.h4
-rw-r--r--src/lib/crypt_ops/crypto_rand.c4
-rw-r--r--src/lib/crypt_ops/crypto_rsa.c2
-rw-r--r--src/lib/crypt_ops/crypto_rsa.h2
-rw-r--r--src/lib/crypt_ops/crypto_util.c2
-rw-r--r--src/lib/crypt_ops/include.am2
-rw-r--r--src/lib/ctime/di_ops.c2
-rw-r--r--src/lib/defs/dh_sizes.h9
-rw-r--r--src/lib/defs/x25519_sizes.h9
-rw-r--r--src/lib/encoding/binascii.c4
-rw-r--r--src/lib/encoding/confline.c4
-rw-r--r--src/lib/encoding/cstring.c4
-rw-r--r--src/lib/encoding/keyval.c2
-rw-r--r--src/lib/encoding/time_fmt.c6
-rw-r--r--src/lib/evloop/compat_libevent.c2
-rw-r--r--src/lib/evloop/compat_libevent.h7
-rw-r--r--src/lib/evloop/procmon.c4
-rw-r--r--src/lib/evloop/procmon.h2
-rw-r--r--src/lib/evloop/timers.c4
-rw-r--r--src/lib/evloop/timers.h6
-rw-r--r--src/lib/evloop/token_bucket.h5
-rw-r--r--src/lib/evloop/workqueue.c2
-rw-r--r--src/lib/evloop/workqueue.h5
-rw-r--r--src/lib/fs/.may_include3
-rw-r--r--src/lib/fs/conffile.c4
-rw-r--r--src/lib/fs/dir.c4
-rw-r--r--src/lib/fs/files.c8
-rw-r--r--src/lib/fs/files.h39
-rw-r--r--src/lib/fs/lockfile.c4
-rw-r--r--src/lib/fs/mmap.c4
-rw-r--r--src/lib/fs/path.c4
-rw-r--r--src/lib/fs/storagedir.c4
-rw-r--r--src/lib/fs/userdb.c4
-rw-r--r--src/lib/lock/compat_mutex.c2
-rw-r--r--src/lib/lock/compat_mutex.h2
-rw-r--r--src/lib/log/escape.c7
-rw-r--r--src/lib/log/escape.h5
-rw-r--r--src/lib/log/git_revision.c (renamed from src/core/or/git_revision.c)10
-rw-r--r--src/lib/log/git_revision.h (renamed from src/core/or/git_revision.h)2
-rw-r--r--src/lib/log/include.am13
-rw-r--r--src/lib/log/log.c (renamed from src/lib/log/torlog.c)22
-rw-r--r--src/lib/log/log.h (renamed from src/lib/log/torlog.h)2
-rw-r--r--src/lib/log/ratelim.c7
-rw-r--r--src/lib/log/ratelim.h5
-rw-r--r--src/lib/log/util_bug.c8
-rw-r--r--src/lib/log/util_bug.h7
-rw-r--r--src/lib/log/win32err.c7
-rw-r--r--src/lib/log/win32err.h5
-rw-r--r--src/lib/malloc/include.am4
-rw-r--r--src/lib/malloc/malloc.c (renamed from src/lib/malloc/util_malloc.c)4
-rw-r--r--src/lib/malloc/malloc.h (renamed from src/lib/malloc/util_malloc.h)2
-rw-r--r--src/lib/memarea/memarea.c4
-rw-r--r--src/lib/meminfo/meminfo.c4
-rw-r--r--src/lib/net/address.c227
-rw-r--r--src/lib/net/address.h9
-rw-r--r--src/lib/net/buffers_net.c7
-rw-r--r--src/lib/net/gethostname.c5
-rw-r--r--src/lib/net/gethostname.h5
-rw-r--r--src/lib/net/inaddr.c (renamed from src/lib/net/ipv6.c)56
-rw-r--r--src/lib/net/inaddr.h (renamed from src/lib/net/ipv4.h)14
-rw-r--r--src/lib/net/inaddr_st.h (renamed from src/lib/net/ipv6.h)30
-rw-r--r--src/lib/net/include.am7
-rw-r--r--src/lib/net/ipv4.c52
-rw-r--r--src/lib/net/nettypes.h5
-rw-r--r--src/lib/net/resolve.c190
-rw-r--r--src/lib/net/resolve.h13
-rw-r--r--src/lib/net/socket.c8
-rw-r--r--src/lib/net/socket.h5
-rw-r--r--src/lib/net/socks5_status.h10
-rw-r--r--src/lib/osinfo/uname.c5
-rw-r--r--src/lib/osinfo/uname.h9
-rw-r--r--src/lib/process/daemon.c7
-rw-r--r--src/lib/process/daemon.h5
-rw-r--r--src/lib/process/env.c11
-rw-r--r--src/lib/process/env.h5
-rw-r--r--src/lib/process/pidfile.c7
-rw-r--r--src/lib/process/pidfile.h5
-rw-r--r--src/lib/process/restrict.c7
-rw-r--r--src/lib/process/restrict.h4
-rw-r--r--src/lib/process/setuid.c9
-rw-r--r--src/lib/process/setuid.h5
-rw-r--r--src/lib/process/subprocess.c9
-rw-r--r--src/lib/process/subprocess.h5
-rw-r--r--src/lib/process/waitpid.c10
-rw-r--r--src/lib/sandbox/sandbox.c4
-rw-r--r--src/lib/smartlist_core/smartlist_core.c2
-rw-r--r--src/lib/smartlist_core/smartlist_core.h5
-rw-r--r--src/lib/smartlist_core/smartlist_foreach.h5
-rw-r--r--src/lib/smartlist_core/smartlist_split.c7
-rw-r--r--src/lib/smartlist_core/smartlist_split.h5
-rw-r--r--src/lib/string/compat_ctype.c5
-rw-r--r--src/lib/string/compat_ctype.h5
-rw-r--r--src/lib/string/compat_string.c6
-rw-r--r--src/lib/string/compat_string.h5
-rw-r--r--src/lib/string/parse_int.c5
-rw-r--r--src/lib/string/parse_int.h5
-rw-r--r--src/lib/string/printf.c7
-rw-r--r--src/lib/string/printf.h5
-rw-r--r--src/lib/string/scanf.c5
-rw-r--r--src/lib/string/scanf.h5
-rw-r--r--src/lib/string/util_string.c5
-rw-r--r--src/lib/string/util_string.h5
-rw-r--r--src/lib/term/getpass.c7
-rw-r--r--src/lib/term/getpass.h5
-rw-r--r--src/lib/testsupport/testsupport.h15
-rw-r--r--src/lib/thread/compat_pthreads.c2
-rw-r--r--src/lib/thread/compat_threads.c2
-rw-r--r--src/lib/thread/compat_winthreads.c2
-rw-r--r--src/lib/thread/numcpus.c7
-rw-r--r--src/lib/thread/numcpus.h5
-rw-r--r--src/lib/thread/threads.h5
-rw-r--r--src/lib/time/compat_time.c2
-rw-r--r--src/lib/time/tvdiff.c7
-rw-r--r--src/lib/time/tvdiff.h5
-rw-r--r--src/lib/tls/buffers_tls.c7
-rw-r--r--src/lib/tls/buffers_tls.h6
-rw-r--r--src/lib/tls/tortls.c2
-rw-r--r--src/lib/trace/debug.h7
-rw-r--r--src/lib/trace/trace.c8
-rw-r--r--src/lib/trace/trace.h6
-rw-r--r--src/lib/wallclock/approx_time.c5
-rw-r--r--src/lib/wallclock/approx_time.h5
-rw-r--r--src/lib/wallclock/include.am4
-rw-r--r--src/lib/wallclock/time_to_tm.c (renamed from src/lib/wallclock/tm_cvt.c)7
-rw-r--r--src/lib/wallclock/time_to_tm.h (renamed from src/lib/wallclock/tm_cvt.h)9
-rw-r--r--src/lib/wallclock/timeval.c0
-rw-r--r--src/lib/wallclock/timeval.h7
-rw-r--r--src/lib/wallclock/tor_gettimeofday.c6
-rw-r--r--src/lib/wallclock/tor_gettimeofday.h5
-rw-r--r--src/rust/Cargo.toml9
-rw-r--r--src/rust/build.rs12
-rw-r--r--src/rust/crypto/Cargo.toml4
-rw-r--r--src/rust/crypto/digests/sha2.rs6
-rw-r--r--src/rust/protover/ffi.rs62
-rw-r--r--src/rust/tor_allocate/tor_allocate.rs12
-rw-r--r--src/test/fuzz/fuzz_http.c2
-rw-r--r--src/test/fuzz/fuzz_http_connect.c2
-rw-r--r--src/test/fuzz/fuzz_socks.c50
-rw-r--r--src/test/fuzz/include.am105
-rw-r--r--src/test/include.am3
-rw-r--r--src/test/log_test_helpers.c2
-rw-r--r--src/test/ope_ref.py40
-rw-r--r--src/test/test-memwipe.c2
-rw-r--r--src/test/test.c1
-rw-r--r--src/test/test.h1
-rw-r--r--src/test/test_addr.c62
-rwxr-xr-xsrc/test/test_bt.sh2
-rw-r--r--src/test/test_bt_cl.c2
-rw-r--r--src/test/test_config.c15
-rw-r--r--src/test/test_connection.c2
-rw-r--r--src/test/test_controller.c1
-rw-r--r--src/test/test_crypto_ope.c152
-rw-r--r--src/test/test_crypto_openssl.c2
-rw-r--r--src/test/test_dir.c422
-rw-r--r--src/test/test_helpers.c1
-rw-r--r--src/test/test_hs_cell.c4
-rw-r--r--src/test/test_hs_common.c12
-rw-r--r--src/test/test_hs_intropoint.c4
-rw-r--r--src/test/test_hs_service.c84
-rwxr-xr-xsrc/test/test_key_expiration.sh8
-rwxr-xr-xsrc/test/test_keygen.sh8
-rw-r--r--src/test/test_logging.c2
-rw-r--r--src/test/test_options.c1
-rw-r--r--src/test/test_pt.c1
-rw-r--r--src/test/test_shared_random.c14
-rw-r--r--src/test/test_socks.c11
-rw-r--r--src/test/test_status.c2
-rw-r--r--src/test/test_tortls.c2
-rw-r--r--src/test/test_util_slow.c2
-rw-r--r--src/tools/Makefile.nmake5
-rw-r--r--src/tools/include.am11
-rw-r--r--src/tools/tor-gencert.c24
-rw-r--r--src/tools/tor-print-ed-signing-cert.c64
-rw-r--r--src/tools/tor-resolve.c27
-rw-r--r--src/trunnel/include.am9
-rw-r--r--src/trunnel/socks5.c3978
-rw-r--r--src/trunnel/socks5.h995
-rw-r--r--src/trunnel/socks5.trunnel94
-rw-r--r--src/trunnel/trunnel-local.h2
296 files changed, 9746 insertions, 2072 deletions
diff --git a/.gitignore b/.gitignore
index 80c039a684..1cd99dfd38 100644
--- a/.gitignore
+++ b/.gitignore
@@ -116,6 +116,11 @@ uptime-*.json
/doc/torify.html
/doc/torify.html.in
/doc/torify.1.xml
+/doc/tor-print-ed-signing-cert.1
+/doc/tor-print-ed-signing-cert.1.in
+/doc/tor-print-ed-signing-cert.html
+/doc/tor-print-ed-signing-cert.html.in
+/doc/tor-print-ed-signing-cert.1.xml
# /doc/spec/
/doc/spec/Makefile
@@ -258,6 +263,8 @@ uptime-*.json
/src/tools/tor-resolve
/src/tools/tor-cov-resolve
/src/tools/tor-gencert
+/src/tools/tor-print-ed-signing-cert
+/src/tools/tor-print-ed-signing-cert.exe
/src/tools/tor-cov-gencert
/src/tools/tor-checkkey.exe
/src/tools/tor-resolve.exe
diff --git a/ChangeLog b/ChangeLog
index 55a62d5a25..7988010c2b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,16 +1,67 @@
-Changes in version 0.3.3.8 - 2018-07-09
- Tor 0.3.3.8 backports several changes from the 0.3.4.x series, including
- fixes for a memory leak affecting directory authorities.
+Changes in version 0.3.4.5-rc - 2018-07-13
+ Tor 0.3.4.5-rc moves to a new bridge authority, meaning people running
+ bridge relays should upgrade.
- o Major bugfixes (directory authority, backport from 0.3.4.3-alpha):
- - Stop leaking memory on directory authorities when planning to
- vote. This bug was crashing authorities by exhausting their
- memory. Fixes bug 26435; bugfix on 0.3.3.6.
+ o Directory authority changes:
+ - The "Bifroest" bridge authority has been retired; the new bridge
+ authority is "Serge", and it is operated by George from the
+ TorBSD project. Closes ticket 26771.
- o Major bugfixes (rust, testing, backport from 0.3.4.3-alpha):
- - Make sure that failing tests in Rust will actually cause the build
- to fail: previously, they were ignored. Fixes bug 26258; bugfix
- on 0.3.3.4-alpha.
+
+Changes in version 0.3.3.9 - 2018-07-13
+ Tor 0.3.3.9 moves to a new bridge authority, meaning people running
+ bridge relays should upgrade.
+
+ o Directory authority changes:
+ - The "Bifroest" bridge authority has been retired; the new bridge
+ authority is "Serge", and it is operated by George from the
+ TorBSD project. Closes ticket 26771.
+
+
+Changes in version 0.3.2.11 - 2018-07-13
+ Tor 0.3.2.11 moves to a new bridge authority, meaning people running
+ bridge relays should upgrade. We also take this opportunity to backport
+ other minor fixes.
+
+ o Directory authority changes:
+ - The "Bifroest" bridge authority has been retired; the new bridge
+ authority is "Serge", and it is operated by George from the
+ TorBSD project. Closes ticket 26771.
+
+ o Directory authority changes (backport from 0.3.3.7):
+ - Add an IPv6 address for the "dannenberg" directory authority.
+ Closes ticket 26343.
+
+ o Major bugfixes (directory authorities, backport from 0.3.4.1-alpha):
+ - 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 (onion service, backport from 0.3.4.1-alpha):
+ - Correctly detect when onion services get disabled after HUP. Fixes
+ bug 25761; bugfix on 0.3.2.1.
+
+ o Minor features (sandbox, backport from 0.3.3.4-alpha):
+ - Explicitly permit the poll() system call when the Linux
+ seccomp2-based sandbox is enabled: apparently, some versions of
+ libc use poll() when calling getpwnam(). Closes ticket 25313.
+
+ o Minor feature (continuous integration, backport from 0.3.3.5-rc):
+ - Update the Travis CI configuration to use the stable Rust channel,
+ now that we have decided to require that. Closes ticket 25714.
+
+ o Minor features (continuous integration, backport from 0.3.4.1-alpha):
+ - 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 (relay, diagnostic, backport from 0.3.4.3-alpha):
+ - Add several checks to detect whether Tor relays are uploading
+ their descriptors without specifying why they regenerated them.
+ Diagnostic for ticket 25686.
o Minor features (compilation, backport from 0.3.4.4-rc):
- When building Tor, prefer to use Python 3 over Python 2, and more
@@ -21,17 +72,38 @@ Changes in version 0.3.3.8 - 2018-07-09
- Update geoip and geoip6 to the July 3 2018 Maxmind GeoLite2
Country database. Closes ticket 26674.
- o Minor features (relay, diagnostic, backport from 0.3.4.3-alpha):
- - Add several checks to detect whether Tor relays are uploading
- their descriptors without specifying why they regenerated them.
- Diagnostic for ticket 25686.
+ o Minor bugfixes (correctness, client, backport from 0.3.4.1-alpha):
+ - 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 (circuit path selection, backport from 0.3.4.1-alpha):
- - 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 (Linux seccomp2 sandbox, backport from 0.3.4.1-alpha):
+ - 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 (testing, compatibility, backport from 0.3.4.4-rc):
+ - When running the hs_ntor_ref.py test, make sure only to pass
+ strings (rather than "bytes" objects) to the Python subprocess
+ module. Python 3 on Windows seems to require this. Fixes bug
+ 26535; bugfix on 0.3.1.1-alpha.
+ - When running the ntor_ref.py test, make sure only to pass strings
+ (rather than "bytes" objects) to the Python subprocess module.
+ Python 3 on Windows seems to require this. Fixes bug 26535; bugfix
+ on 0.2.5.5-alpha.
+
+ o Minor bugfixes (compatibility, openssl, backport from 0.3.4.2-alpha):
+ - Work around a change in OpenSSL 1.1.1 where return values that
+ would previously indicate "no password" now indicate an empty
+ password. Without this workaround, Tor instances running with
+ OpenSSL 1.1.1 would accept descriptors that other Tor instances
+ would reject. Fixes bug 26116; bugfix on 0.2.5.16.
+
+ o Minor bugfixes (documentation, backport from 0.3.3.5-rc):
+ - Document that the PerConnBW{Rate,Burst} options will fall back to
+ their corresponding consensus parameters only if those parameters
+ are set. Previously we had claimed that these values would always
+ be set in the consensus. Fixes bug 25296; bugfix on 0.2.2.7-alpha.
o Minor bugfixes (compilation, backport from 0.3.4.4-rc):
- Fix a compilation warning on some versions of GCC when building
@@ -39,14 +111,27 @@ Changes in version 0.3.3.8 - 2018-07-09
that the second call will succeed if the first one did. Fixes bug
26269; bugfix on 0.2.8.2-alpha.
- o Minor bugfixes (control port, backport from 0.3.4.4-rc):
- - Handle the HSADDRESS= argument to the HSPOST command properly.
- (Previously, this argument was misparsed and thus ignored.) Fixes
- bug 26523; bugfix on 0.3.3.1-alpha. Patch by "akwizgran".
+ o Minor bugfixes (client, backport from 0.3.4.1-alpha):
+ - 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 (memory, correctness, backport from 0.3.4.4-rc):
- - Fix a number of small memory leaks identified by coverity. Fixes
- bug 26467; bugfix on numerous Tor versions.
+ o Minor bugfixes (hardening, backport from 0.3.4.2-alpha):
+ - Prevent a possible out-of-bounds smartlist read in
+ protover_compute_vote(). Fixes bug 26196; bugfix on 0.2.9.4-alpha.
+
+ o Minor bugfixes (C correctness, backport from 0.3.3.4-alpha):
+ - Fix a very unlikely (impossible, we believe) null pointer
+ dereference. Fixes bug 25629; bugfix on 0.2.9.15. Found by
+ Coverity; this is CID 1430932.
+
+ o Minor bugfixes (onion service, backport from 0.3.4.1-alpha):
+ - 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 (relay, backport from 0.3.4.3-alpha):
- Relays now correctly block attempts to re-extend to the previous
@@ -54,21 +139,126 @@ Changes in version 0.3.3.8 - 2018-07-09
case, but not actually reject the attempt. Fixes bug 26158; bugfix
on 0.3.0.1-alpha.
- o Minor bugfixes (restart-in-process, backport from 0.3.4.1-alpha):
- - 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 (relay, crash, backport from 0.3.4.1-alpha):
+ - Avoid a crash when running with DirPort set but ORPort turned off.
+ Fixes a case of bug 23693; bugfix on 0.3.1.1-alpha.
+
+ o Minor bugfixes (compilation, backport from 0.3.4.2-alpha):
+ - Silence unused-const-variable warnings in zstd.h with some GCC
+ versions. Fixes bug 26272; bugfix on 0.3.1.1-alpha.
+
+ o Minor bugfixes (testing, backport from 0.3.3.4-alpha):
+ - Avoid intermittent test failures due to a test that had relied on
+ onion service introduction point creation finishing within 5
+ seconds of real clock time. Fixes bug 25450; bugfix
+ on 0.3.1.3-alpha.
+
+ o Minor bugfixes (compilation, backport from 0.3.3.4-alpha):
+ - Fix a C99 compliance issue in our configuration script that caused
+ compilation issues when compiling Tor with certain versions of
+ xtools. Fixes bug 25474; bugfix on 0.3.2.5-alpha.
+
+ o Minor bugfixes (memory, correctness, backport from 0.3.4.4-rc):
+ - Fix a number of small memory leaks identified by coverity. Fixes
+ bug 26467; bugfix on numerous Tor versions.
+
+ o Code simplification and refactoring (backport from 0.3.3.5-rc):
+ - Move the list of default directory authorities to its own file.
+ Closes ticket 24854. Patch by "beastr0".
+
+
+Changes in version 0.2.9.16 - 2018-07-13
+ Tor 0.2.9.16 moves to a new bridge authority, meaning people running
+ bridge relays should upgrade. We also take this opportunity to backport
+ other minor fixes.
+
+ o Directory authority changes:
+ - The "Bifroest" bridge authority has been retired; the new bridge
+ authority is "Serge", and it is operated by George from the
+ TorBSD project. Closes ticket 26771.
+
+ o Directory authority changes (backport from 0.3.3.7):
+ - Add an IPv6 address for the "dannenberg" directory authority.
+ Closes ticket 26343.
+
+ o Major bugfixes (directory authorities, backport from 0.3.4.1-alpha):
+ - 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 Minor features (sandbox, backport from 0.3.3.4-alpha):
+ - Explicitly permit the poll() system call when the Linux
+ seccomp2-based sandbox is enabled: apparently, some versions of
+ libc use poll() when calling getpwnam(). Closes ticket 25313.
+
+ o Minor features (continuous integration, backport from 0.3.4.1-alpha):
+ - 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 (compilation, backport from 0.3.4.4-rc):
+ - When building Tor, prefer to use Python 3 over Python 2, and more
+ recent (contemplated) versions over older ones. Closes
+ ticket 26372.
+
+ o Minor features (geoip):
+ - Update geoip and geoip6 to the July 3 2018 Maxmind GeoLite2
+ Country database. Closes ticket 26674.
+
+ o Minor bugfixes (correctness, client, backport from 0.3.4.1-alpha):
+ - 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 (Linux seccomp2 sandbox, backport from 0.3.4.1-alpha):
+ - 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 (testing, compatibility, backport from 0.3.4.4-rc):
- - When running the hs_ntor_ref.py test, make sure only to pass
- strings (rather than "bytes" objects) to the Python subprocess
- module. Python 3 on Windows seems to require this. Fixes bug
- 26535; bugfix on 0.3.1.1-alpha.
- When running the ntor_ref.py test, make sure only to pass strings
(rather than "bytes" objects) to the Python subprocess module.
Python 3 on Windows seems to require this. Fixes bug 26535; bugfix
on 0.2.5.5-alpha.
+ o Minor bugfixes (compatibility, openssl, backport from 0.3.4.2-alpha):
+ - Work around a change in OpenSSL 1.1.1 where return values that
+ would previously indicate "no password" now indicate an empty
+ password. Without this workaround, Tor instances running with
+ OpenSSL 1.1.1 would accept descriptors that other Tor instances
+ would reject. Fixes bug 26116; bugfix on 0.2.5.16.
+
+ o Minor bugfixes (compilation, backport from 0.3.4.4-rc):
+ - Fix a compilation warning on some versions of GCC when building
+ code that calls routerinfo_get_my_routerinfo() twice, assuming
+ that the second call will succeed if the first one did. Fixes bug
+ 26269; bugfix on 0.2.8.2-alpha.
+
+ o Minor bugfixes (client, backport from 0.3.4.1-alpha):
+ - 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 (hardening, backport from 0.3.4.2-alpha):
+ - Prevent a possible out-of-bounds smartlist read in
+ protover_compute_vote(). Fixes bug 26196; bugfix on 0.2.9.4-alpha.
+
+ o Minor bugfixes (C correctness, backport from 0.3.3.4-alpha):
+ - Fix a very unlikely (impossible, we believe) null pointer
+ dereference. Fixes bug 25629; bugfix on 0.2.9.15. Found by
+ Coverity; this is CID 1430932.
+
+ o Minor bugfixes (memory, correctness, backport from 0.3.4.4-rc):
+ - Fix a number of small memory leaks identified by coverity. Fixes
+ bug 26467; bugfix on numerous Tor versions.
+
+ o Code simplification and refactoring (backport from 0.3.3.5-rc):
+ - Move the list of default directory authorities to its own file.
+ Closes ticket 24854. Patch by "beastr0".
+
Changes in version 0.3.4.4-rc - 2018-07-09
Tor 0.3.4.4-rc fixes several small compilation, portability, and
@@ -121,6 +311,78 @@ Changes in version 0.3.4.4-rc - 2018-07-09
on 0.2.5.5-alpha.
+Changes in version 0.3.3.8 - 2018-07-09
+ Tor 0.3.3.8 backports several changes from the 0.3.4.x series, including
+ fixes for a memory leak affecting directory authorities.
+
+ o Major bugfixes (directory authority, backport from 0.3.4.3-alpha):
+ - Stop leaking memory on directory authorities when planning to
+ vote. This bug was crashing authorities by exhausting their
+ memory. Fixes bug 26435; bugfix on 0.3.3.6.
+
+ o Major bugfixes (rust, testing, backport from 0.3.4.3-alpha):
+ - Make sure that failing tests in Rust will actually cause the build
+ to fail: previously, they were ignored. Fixes bug 26258; bugfix
+ on 0.3.3.4-alpha.
+
+ o Minor features (compilation, backport from 0.3.4.4-rc):
+ - When building Tor, prefer to use Python 3 over Python 2, and more
+ recent (contemplated) versions over older ones. Closes
+ ticket 26372.
+
+ o Minor features (geoip):
+ - Update geoip and geoip6 to the July 3 2018 Maxmind GeoLite2
+ Country database. Closes ticket 26674.
+
+ o Minor features (relay, diagnostic, backport from 0.3.4.3-alpha):
+ - Add several checks to detect whether Tor relays are uploading
+ their descriptors without specifying why they regenerated them.
+ Diagnostic for ticket 25686.
+
+ o Minor bugfixes (circuit path selection, backport from 0.3.4.1-alpha):
+ - 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 (compilation, backport from 0.3.4.4-rc):
+ - Fix a compilation warning on some versions of GCC when building
+ code that calls routerinfo_get_my_routerinfo() twice, assuming
+ that the second call will succeed if the first one did. Fixes bug
+ 26269; bugfix on 0.2.8.2-alpha.
+
+ o Minor bugfixes (control port, backport from 0.3.4.4-rc):
+ - Handle the HSADDRESS= argument to the HSPOST command properly.
+ (Previously, this argument was misparsed and thus ignored.) Fixes
+ bug 26523; bugfix on 0.3.3.1-alpha. Patch by "akwizgran".
+
+ o Minor bugfixes (memory, correctness, backport from 0.3.4.4-rc):
+ - Fix a number of small memory leaks identified by coverity. Fixes
+ bug 26467; bugfix on numerous Tor versions.
+
+ o Minor bugfixes (relay, backport from 0.3.4.3-alpha):
+ - Relays now correctly block attempts to re-extend to the previous
+ relay by Ed25519 identity. Previously they would warn in this
+ case, but not actually reject the attempt. Fixes bug 26158; bugfix
+ on 0.3.0.1-alpha.
+
+ o Minor bugfixes (restart-in-process, backport from 0.3.4.1-alpha):
+ - 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, compatibility, backport from 0.3.4.4-rc):
+ - When running the hs_ntor_ref.py test, make sure only to pass
+ strings (rather than "bytes" objects) to the Python subprocess
+ module. Python 3 on Windows seems to require this. Fixes bug
+ 26535; bugfix on 0.3.1.1-alpha.
+ - When running the ntor_ref.py test, make sure only to pass strings
+ (rather than "bytes" objects) to the Python subprocess module.
+ Python 3 on Windows seems to require this. Fixes bug 26535; bugfix
+ on 0.2.5.5-alpha.
+
+
Changes in version 0.3.4.3-alpha - 2018-06-26
Tor 0.3.4.3-alpha fixes several bugs in earlier versions, including
one that was causing stability issues on directory authorities.
@@ -388,7 +650,7 @@ Changes in version 0.3.3.6 - 2018-05-22
Fixes bug 26069; bugfix on 0.3.0.1-alpha.
o Minor bugfixes (relay, crash, backport from 0.3.4.1-alpha):
- - Avoid a crash when running with DirPort set but ORPort tuned off.
+ - Avoid a crash when running with DirPort set but ORPort turned off.
Fixes a case of bug 23693; bugfix on 0.3.1.1-alpha.
o Documentation (backport from 0.3.4.1-alpha):
@@ -691,7 +953,7 @@ Changes in version 0.3.4.1-alpha - 2018-05-17
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.
+ - Avoid a crash when running with DirPort set but ORPort turned off.
Fixes a case of bug 23693; bugfix on 0.3.1.1-alpha.
o Minor bugfixes (restart-in-process):
diff --git a/LICENSE b/LICENSE
index 057ae57652..9e2709aea6 100644
--- a/LICENSE
+++ b/LICENSE
@@ -156,6 +156,36 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===============================================================================
+getdelim.c is distributed under this license:
+
+ Copyright (c) 2011 The NetBSD Foundation, Inc.
+ All rights reserved.
+
+ This code is derived from software contributed to The NetBSD Foundation
+ by Christos Zoulas.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+===============================================================================
src/config/geoip is licensed under the following license:
OPEN DATA LICENSE (GeoLite Country and GeoLite City databases)
diff --git a/Makefile.am b/Makefile.am
index 73dc56b281..3df35ad3f3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -66,6 +66,7 @@ TOR_UTIL_LIBS = \
# Variants of the above for linking the testing variant of tor (for coverage
# and tests)
+if UNITTESTS_ENABLED
TOR_UTIL_TESTING_LIBS = \
src/lib/libtor-process-testing.a \
src/lib/libtor-time-testing.a \
@@ -90,6 +91,7 @@ TOR_UTIL_TESTING_LIBS = \
src/lib/libtor-err-testing.a \
src/lib/libtor-intmath.a \
src/lib/libtor-ctime-testing.a
+endif
# Internal crypto libraries used in Tor
TOR_CRYPTO_LIBS = \
@@ -100,11 +102,13 @@ TOR_CRYPTO_LIBS = \
# Variants of the above for linking the testing variant of tor (for coverage
# and tests)
+if UNITTESTS_ENABLED
TOR_CRYPTO_TESTING_LIBS = \
src/lib/libtor-tls-testing.a \
src/lib/libtor-crypt-ops-testing.a \
$(LIBKECCAK_TINY) \
$(LIBDONNA)
+endif
# All static libraries used to link tor.
TOR_INTERNAL_LIBS = \
@@ -118,6 +122,7 @@ TOR_INTERNAL_LIBS = \
# Variants of the above for linking the testing variant of tor (for coverage
# and tests)
+if UNITTESTS_ENABLED
TOR_INTERNAL_TESTING_LIBS = \
src/core/libtor-app-testing.a \
src/lib/libtor-compress-testing.a \
@@ -126,6 +131,7 @@ TOR_INTERNAL_TESTING_LIBS = \
$(TOR_UTIL_TESTING_LIBS) \
src/trunnel/libor-trunnel-testing.a \
src/lib/libtor-trace.a
+endif
# All libraries used to link tor-cov
diff --git a/ReleaseNotes b/ReleaseNotes
index 600b3c5e0a..d9272a880e 100644
--- a/ReleaseNotes
+++ b/ReleaseNotes
@@ -2,6 +2,258 @@ This document summarizes new features and bugfixes in each stable
release of Tor. If you want to see more detailed descriptions of the
changes in each development snapshot, see the ChangeLog file.
+Changes in version 0.3.3.9 - 2018-07-13
+ Tor 0.3.3.9 moves to a new bridge authority, meaning people running
+ bridge relays should upgrade.
+
+ o Directory authority changes:
+ - The "Bifroest" bridge authority has been retired; the new bridge
+ authority is "Serge", and it is operated by George from the
+ TorBSD project. Closes ticket 26771.
+
+
+Changes in version 0.3.2.11 - 2018-07-13
+ Tor 0.3.2.11 moves to a new bridge authority, meaning people running
+ bridge relays should upgrade. We also take this opportunity to backport
+ other minor fixes.
+
+ o Directory authority changes:
+ - The "Bifroest" bridge authority has been retired; the new bridge
+ authority is "Serge", and it is operated by George from the
+ TorBSD project. Closes ticket 26771.
+
+ o Directory authority changes (backport from 0.3.3.7):
+ - Add an IPv6 address for the "dannenberg" directory authority.
+ Closes ticket 26343.
+
+ o Major bugfixes (directory authorities, backport from 0.3.4.1-alpha):
+ - 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 (onion service, backport from 0.3.4.1-alpha):
+ - Correctly detect when onion services get disabled after HUP. Fixes
+ bug 25761; bugfix on 0.3.2.1.
+
+ o Minor features (sandbox, backport from 0.3.3.4-alpha):
+ - Explicitly permit the poll() system call when the Linux
+ seccomp2-based sandbox is enabled: apparently, some versions of
+ libc use poll() when calling getpwnam(). Closes ticket 25313.
+
+ o Minor feature (continuous integration, backport from 0.3.3.5-rc):
+ - Update the Travis CI configuration to use the stable Rust channel,
+ now that we have decided to require that. Closes ticket 25714.
+
+ o Minor features (continuous integration, backport from 0.3.4.1-alpha):
+ - 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 (relay, diagnostic, backport from 0.3.4.3-alpha):
+ - Add several checks to detect whether Tor relays are uploading
+ their descriptors without specifying why they regenerated them.
+ Diagnostic for ticket 25686.
+
+ o Minor features (compilation, backport from 0.3.4.4-rc):
+ - When building Tor, prefer to use Python 3 over Python 2, and more
+ recent (contemplated) versions over older ones. Closes
+ ticket 26372.
+
+ o Minor features (geoip):
+ - Update geoip and geoip6 to the July 3 2018 Maxmind GeoLite2
+ Country database. Closes ticket 26674.
+
+ o Minor bugfixes (correctness, client, backport from 0.3.4.1-alpha):
+ - 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 (Linux seccomp2 sandbox, backport from 0.3.4.1-alpha):
+ - 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 (testing, compatibility, backport from 0.3.4.4-rc):
+ - When running the hs_ntor_ref.py test, make sure only to pass
+ strings (rather than "bytes" objects) to the Python subprocess
+ module. Python 3 on Windows seems to require this. Fixes bug
+ 26535; bugfix on 0.3.1.1-alpha.
+ - When running the ntor_ref.py test, make sure only to pass strings
+ (rather than "bytes" objects) to the Python subprocess module.
+ Python 3 on Windows seems to require this. Fixes bug 26535; bugfix
+ on 0.2.5.5-alpha.
+
+ o Minor bugfixes (compatibility, openssl, backport from 0.3.4.2-alpha):
+ - Work around a change in OpenSSL 1.1.1 where return values that
+ would previously indicate "no password" now indicate an empty
+ password. Without this workaround, Tor instances running with
+ OpenSSL 1.1.1 would accept descriptors that other Tor instances
+ would reject. Fixes bug 26116; bugfix on 0.2.5.16.
+
+ o Minor bugfixes (documentation, backport from 0.3.3.5-rc):
+ - Document that the PerConnBW{Rate,Burst} options will fall back to
+ their corresponding consensus parameters only if those parameters
+ are set. Previously we had claimed that these values would always
+ be set in the consensus. Fixes bug 25296; bugfix on 0.2.2.7-alpha.
+
+ o Minor bugfixes (compilation, backport from 0.3.4.4-rc):
+ - Fix a compilation warning on some versions of GCC when building
+ code that calls routerinfo_get_my_routerinfo() twice, assuming
+ that the second call will succeed if the first one did. Fixes bug
+ 26269; bugfix on 0.2.8.2-alpha.
+
+ o Minor bugfixes (client, backport from 0.3.4.1-alpha):
+ - 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 (hardening, backport from 0.3.4.2-alpha):
+ - Prevent a possible out-of-bounds smartlist read in
+ protover_compute_vote(). Fixes bug 26196; bugfix on 0.2.9.4-alpha.
+
+ o Minor bugfixes (C correctness, backport from 0.3.3.4-alpha):
+ - Fix a very unlikely (impossible, we believe) null pointer
+ dereference. Fixes bug 25629; bugfix on 0.2.9.15. Found by
+ Coverity; this is CID 1430932.
+
+ o Minor bugfixes (onion service, backport from 0.3.4.1-alpha):
+ - 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 (relay, backport from 0.3.4.3-alpha):
+ - Relays now correctly block attempts to re-extend to the previous
+ relay by Ed25519 identity. Previously they would warn in this
+ case, but not actually reject the attempt. Fixes bug 26158; bugfix
+ on 0.3.0.1-alpha.
+
+ o Minor bugfixes (relay, crash, backport from 0.3.4.1-alpha):
+ - Avoid a crash when running with DirPort set but ORPort turned off.
+ Fixes a case of bug 23693; bugfix on 0.3.1.1-alpha.
+
+ o Minor bugfixes (compilation, backport from 0.3.4.2-alpha):
+ - Silence unused-const-variable warnings in zstd.h with some GCC
+ versions. Fixes bug 26272; bugfix on 0.3.1.1-alpha.
+
+ o Minor bugfixes (testing, backport from 0.3.3.4-alpha):
+ - Avoid intermittent test failures due to a test that had relied on
+ onion service introduction point creation finishing within 5
+ seconds of real clock time. Fixes bug 25450; bugfix
+ on 0.3.1.3-alpha.
+
+ o Minor bugfixes (compilation, backport from 0.3.3.4-alpha):
+ - Fix a C99 compliance issue in our configuration script that caused
+ compilation issues when compiling Tor with certain versions of
+ xtools. Fixes bug 25474; bugfix on 0.3.2.5-alpha.
+
+ o Minor bugfixes (memory, correctness, backport from 0.3.4.4-rc):
+ - Fix a number of small memory leaks identified by coverity. Fixes
+ bug 26467; bugfix on numerous Tor versions.
+
+ o Code simplification and refactoring (backport from 0.3.3.5-rc):
+ - Move the list of default directory authorities to its own file.
+ Closes ticket 24854. Patch by "beastr0".
+
+
+Changes in version 0.2.9.16 - 2018-07-13
+ Tor 0.2.9.16 moves to a new bridge authority, meaning people running
+ bridge relays should upgrade. We also take this opportunity to backport
+ other minor fixes.
+
+ o Directory authority changes:
+ - The "Bifroest" bridge authority has been retired; the new bridge
+ authority is "Serge", and it is operated by George from the
+ TorBSD project. Closes ticket 26771.
+
+ o Directory authority changes (backport from 0.3.3.7):
+ - Add an IPv6 address for the "dannenberg" directory authority.
+ Closes ticket 26343.
+
+ o Major bugfixes (directory authorities, backport from 0.3.4.1-alpha):
+ - 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 Minor features (sandbox, backport from 0.3.3.4-alpha):
+ - Explicitly permit the poll() system call when the Linux
+ seccomp2-based sandbox is enabled: apparently, some versions of
+ libc use poll() when calling getpwnam(). Closes ticket 25313.
+
+ o Minor features (continuous integration, backport from 0.3.4.1-alpha):
+ - 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 (compilation, backport from 0.3.4.4-rc):
+ - When building Tor, prefer to use Python 3 over Python 2, and more
+ recent (contemplated) versions over older ones. Closes
+ ticket 26372.
+
+ o Minor features (geoip):
+ - Update geoip and geoip6 to the July 3 2018 Maxmind GeoLite2
+ Country database. Closes ticket 26674.
+
+ o Minor bugfixes (correctness, client, backport from 0.3.4.1-alpha):
+ - 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 (Linux seccomp2 sandbox, backport from 0.3.4.1-alpha):
+ - 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 (testing, compatibility, backport from 0.3.4.4-rc):
+ - When running the ntor_ref.py test, make sure only to pass strings
+ (rather than "bytes" objects) to the Python subprocess module.
+ Python 3 on Windows seems to require this. Fixes bug 26535; bugfix
+ on 0.2.5.5-alpha.
+
+ o Minor bugfixes (compatibility, openssl, backport from 0.3.4.2-alpha):
+ - Work around a change in OpenSSL 1.1.1 where return values that
+ would previously indicate "no password" now indicate an empty
+ password. Without this workaround, Tor instances running with
+ OpenSSL 1.1.1 would accept descriptors that other Tor instances
+ would reject. Fixes bug 26116; bugfix on 0.2.5.16.
+
+ o Minor bugfixes (compilation, backport from 0.3.4.4-rc):
+ - Fix a compilation warning on some versions of GCC when building
+ code that calls routerinfo_get_my_routerinfo() twice, assuming
+ that the second call will succeed if the first one did. Fixes bug
+ 26269; bugfix on 0.2.8.2-alpha.
+
+ o Minor bugfixes (client, backport from 0.3.4.1-alpha):
+ - 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 (hardening, backport from 0.3.4.2-alpha):
+ - Prevent a possible out-of-bounds smartlist read in
+ protover_compute_vote(). Fixes bug 26196; bugfix on 0.2.9.4-alpha.
+
+ o Minor bugfixes (C correctness, backport from 0.3.3.4-alpha):
+ - Fix a very unlikely (impossible, we believe) null pointer
+ dereference. Fixes bug 25629; bugfix on 0.2.9.15. Found by
+ Coverity; this is CID 1430932.
+
+ o Minor bugfixes (memory, correctness, backport from 0.3.4.4-rc):
+ - Fix a number of small memory leaks identified by coverity. Fixes
+ bug 26467; bugfix on numerous Tor versions.
+
+ o Code simplification and refactoring (backport from 0.3.3.5-rc):
+ - Move the list of default directory authorities to its own file.
+ Closes ticket 24854. Patch by "beastr0".
+
+
Changes in version 0.3.3.8 - 2018-07-09
Tor 0.3.3.8 backports several changes from the 0.3.4.x series, including
fixes for a memory leak affecting directory authorities.
@@ -634,7 +886,7 @@ Changes in version 0.3.3.6 - 2018-05-22
hop. Fixes bug 23100; bugfix on 0.2.2.2-alpha.
o Minor bugfixes (relay, crash, backport from 0.3.4.1-alpha):
- - Avoid a crash when running with DirPort set but ORPort tuned off.
+ - Avoid a crash when running with DirPort set but ORPort turned off.
Fixes a case of bug 23693; bugfix on 0.3.1.1-alpha.
o Minor bugfixes (Rust FFI):
diff --git a/changes/bug25552 b/changes/bug25552
new file mode 100644
index 0000000000..8d0488a462
--- /dev/null
+++ b/changes/bug25552
@@ -0,0 +1,5 @@
+ o Major feature (onion services):
+ - Improve revision counter generation in next-gen onion services. Onion
+ services can now scale by hosting multiple instances on different hosts
+ without synchronization between them, which was previously impossible
+ because descriptors would get rejected by HSDirs. Addresses ticket 25552.
diff --git a/changes/bug26223 b/changes/bug26223
new file mode 100644
index 0000000000..e17b0529e3
--- /dev/null
+++ b/changes/bug26223
@@ -0,0 +1,3 @@
+ o Minor features (directory authority):
+ - There is no longer an artificial upper limit on the length of bandwidth
+ lines. Closes ticket 26223.
diff --git a/changes/bug26437 b/changes/bug26437
new file mode 100644
index 0000000000..da4879b6d0
--- /dev/null
+++ b/changes/bug26437
@@ -0,0 +1,3 @@
+ o Testing:
+ - Fix forking tests on Windows when there is a space somewhere in the path.
+ Fixes bug 26437; bugfix on 0.2.2.4-alpha.
diff --git a/changes/bug26485 b/changes/bug26485
new file mode 100644
index 0000000000..5a40b7a78e
--- /dev/null
+++ b/changes/bug26485
@@ -0,0 +1,4 @@
+ o Minor bugfixes (directory authority):
+ - When voting for recommended versions, make sure that all of the
+ versions are well-formed and parsable. Fixes bug 26485; bugfix on
+ 0.1.1.6-alpha.
diff --git a/changes/bug26502 b/changes/bug26502
new file mode 100644
index 0000000000..16d19095d3
--- /dev/null
+++ b/changes/bug26502
@@ -0,0 +1,3 @@
+ o Code simplification and refactoring:
+ - 'updateFallbackDirs.py' now ignores the blacklist file as it's not longer needed
+ Closes ticket 26502.
diff --git a/changes/bug26627 b/changes/bug26627
new file mode 100644
index 0000000000..d28bd05d53
--- /dev/null
+++ b/changes/bug26627
@@ -0,0 +1,7 @@
+ o Minor bugfixes (v3 onion services):
+ - Stop sending ed25519 link specifiers in v3 onion service introduce
+ cells, when the rendezvous point doesn't support ed25519 link
+ authentication. Fixes bug 26627; bugfix on 0.3.2.4-alpha.
+ - Stop putting ed25519 link specifiers in v3 onion service descriptors,
+ when the intro point doesn't support ed25519 link authentication.
+ Fixes bug 26627; bugfix on 0.3.2.4-alpha.
diff --git a/changes/bug26785 b/changes/bug26785
new file mode 100644
index 0000000000..e6392fcbdd
--- /dev/null
+++ b/changes/bug26785
@@ -0,0 +1,4 @@
+ o Minor bugfixes (compilation, portability):
+ - Don't try to use a pragma to temporarily disable
+ -Wunused-const-variable if the compiler doesn't support it.
+ Fixes bug 26785; bugfix on 0.3.2.11.
diff --git a/changes/bug26787 b/changes/bug26787
new file mode 100644
index 0000000000..b32e519a93
--- /dev/null
+++ b/changes/bug26787
@@ -0,0 +1,3 @@
+ o Minor bugfixes (testing):
+ - Disable core dumps in test_bt.sh, to avoid failures in "make
+ distcheck". Fixes bug 26787; bugfix on 0.2.5.2-alpha.
diff --git a/changes/bug26789 b/changes/bug26789
new file mode 100644
index 0000000000..9b3520543d
--- /dev/null
+++ b/changes/bug26789
@@ -0,0 +1,4 @@
+ o Minor bugfixes (compilation):
+ - Update build system so that tor builds again with
+ --disable-unittests after recent refactoring efforts.
+ Fixes bug 26789; bugfix on 0.3.4.3-alpha.
diff --git a/changes/bug26830 b/changes/bug26830
new file mode 100644
index 0000000000..c002f19530
--- /dev/null
+++ b/changes/bug26830
@@ -0,0 +1,3 @@
+ o Minor bugfixes (continuous integration):
+ - Skip an unreliable key generation test on Windows, until the underlying
+ issue in bug 26076 is resolved. Fixes bug 26830; bugfix on 0.2.7.3-rc.
diff --git a/changes/bug26853 b/changes/bug26853
new file mode 100644
index 0000000000..6ee47789b9
--- /dev/null
+++ b/changes/bug26853
@@ -0,0 +1,3 @@
+ o Minor bugfixes (continuous integration):
+ - Skip an unreliable key expiration test on Windows, until the underlying
+ issue in bug 26076 is resolved. Fixes bug 26853; bugfix on 0.3.2.1-alpha.
diff --git a/changes/bug26892 b/changes/bug26892
new file mode 100644
index 0000000000..6fc8a03204
--- /dev/null
+++ b/changes/bug26892
@@ -0,0 +1,6 @@
+ o Minor bugfixes (logging):
+ - As a precaution, do an early return from
+ log_addr_has_changed() if Tor is running as client. Also,
+ log a stack trace for debugging as this function should only
+ be called when Tor runs as server. Fixes bug 26892;
+ bugfix on 0.1.1.9-alpha.
diff --git a/changes/bug26924 b/changes/bug26924
new file mode 100644
index 0000000000..882db56b40
--- /dev/null
+++ b/changes/bug26924
@@ -0,0 +1,4 @@
+ o Minor bugfixes (single onion services, Tor2web):
+ - Log a protocol warning when single onion services or Tor2web clients
+ fail to authenticate direct connections to relays.
+ Fixes bug 26924; bugfix on 0.2.9.1-alpha.
diff --git a/changes/bug26927 b/changes/bug26927
new file mode 100644
index 0000000000..cd035bba8e
--- /dev/null
+++ b/changes/bug26927
@@ -0,0 +1,4 @@
+ o Minor bugfixes (logging):
+ - Improve the log message when connection initiators fail to authenticate
+ direct connections to relays.
+ Fixes bug 26927; bugfix on 0.3.0.1-alpha.
diff --git a/changes/feature19506 b/changes/feature19506
new file mode 100644
index 0000000000..83ba9e245f
--- /dev/null
+++ b/changes/feature19506
@@ -0,0 +1,3 @@
+ o Minor features (admin tools):
+ - Add new tool that prints expiration date of signing cert
+ in ed25519_signing_cert. Resolves issue 19506.
diff --git a/changes/task26771 b/changes/task26771
new file mode 100644
index 0000000000..fd700900f7
--- /dev/null
+++ b/changes/task26771
@@ -0,0 +1,4 @@
+ o Directory authority changes:
+ - The "Bifroest" bridge authority has been retired; the new bridge
+ authority is "Serge", and it is operated by George from the
+ TorBSD project. Closes ticket 26771.
diff --git a/changes/ticket21349 b/changes/ticket21349
new file mode 100644
index 0000000000..c072884062
--- /dev/null
+++ b/changes/ticket21349
@@ -0,0 +1,6 @@
+ o Code simplification and refactoring:
+ - Split sampled_guards_update_from_consensus() and
+ select_entry_guard_for_circuit() into subfunctions.
+ In entry_guards_update_primary() unite
+ three smartlist enumerations into one and move smartlist
+ comparison code out of the function. Closes ticket 21349.
diff --git a/changes/ticket26481 b/changes/ticket26481
new file mode 100644
index 0000000000..84d219ed86
--- /dev/null
+++ b/changes/ticket26481
@@ -0,0 +1,12 @@
+ o Major features (new code layout):
+ - Nearly all of Tor's source code has been moved around into more logical
+ places. The "common" directory is now divided into a set of libraries
+ in "lib", and files in the "or" directory have been split into "core"
+ (logic absolutely needed for onion routing), "feature" (independent
+ modules in Tor), and "app" (to configure and invoke the rest of Tor).
+ See doc/HACKING/CodeStructure.md for more information. Closes ticket
+ 26481.
+
+ This refactoring is not complete: although the libraries have been
+ refactored to be acyclic, the main body of Tor is still too
+ interconnected. We will attempt to improve this in the future.
diff --git a/changes/ticket26492 b/changes/ticket26492
new file mode 100644
index 0000000000..c6ab292d17
--- /dev/null
+++ b/changes/ticket26492
@@ -0,0 +1,4 @@
+ o Minor features (rust, code quality):
+ - Improve rust code quality in the Rust protover implementation by
+ making it more idiomatic. Includes changing an internal API to
+ take &str instead of &String. Closes ticket 26492.
diff --git a/changes/ticket26526 b/changes/ticket26526
new file mode 100644
index 0000000000..447b581df8
--- /dev/null
+++ b/changes/ticket26526
@@ -0,0 +1,4 @@
+ o Code simplification and refactoring:
+ - Utility functions that can perform a DNS lookup are now wholly
+ separated from those that can't, in separate headers and C
+ modules. Closes ticket 26526.
diff --git a/changes/ticket26526_extra b/changes/ticket26526_extra
new file mode 100644
index 0000000000..5495962ff7
--- /dev/null
+++ b/changes/ticket26526_extra
@@ -0,0 +1,3 @@
+ o Minor features (tor-resolve):
+ - The tor-resolve utility can now be used with IPv6 SOCKS proxies.
+ Side-effect of the refactoring for ticket 26526.
diff --git a/changes/ticket26647 b/changes/ticket26647
new file mode 100644
index 0000000000..1c2e917c6d
--- /dev/null
+++ b/changes/ticket26647
@@ -0,0 +1,4 @@
+ o Minor features (controller):
+ - The control port now exposes the list of HTTPTunnelPorts and
+ ExtOrPorts via GETINFO net/listeners/httptunnel and net/listeners/extor
+ respectively. Closes ticket 26647.
diff --git a/changes/ticket26663 b/changes/ticket26663
new file mode 100644
index 0000000000..2e1b8db1f5
--- /dev/null
+++ b/changes/ticket26663
@@ -0,0 +1,3 @@
+ o Minor features(config):
+ - The "auto" keyword in torrc is now case insensitive.
+ Closes ticket 26663.
diff --git a/changes/ticket26703 b/changes/ticket26703
new file mode 100644
index 0000000000..764b98b826
--- /dev/null
+++ b/changes/ticket26703
@@ -0,0 +1,3 @@
+ o Code simplification and refactoring:
+ - Low log level of "Scheduler type KIST has been enabled" to INFO.
+ Ticket 26703
diff --git a/changes/ticket3569_part1 b/changes/ticket3569_part1
new file mode 100644
index 0000000000..4032aff4d2
--- /dev/null
+++ b/changes/ticket3569_part1
@@ -0,0 +1,6 @@
+ o Code simplification and refactoring:
+ - Rework Tor SOCKS server code to use Trunnel and benefit from
+ autogenerated functions for parsing and generating SOCKS wire
+ format. New implementation is cleaner, more maintainable and
+ should be less prone to heartbleed-style vulnerabilities.
+ Implements a significant fraction of ticket 3569.
diff --git a/changes/ticket3723 b/changes/ticket3723
new file mode 100644
index 0000000000..3deefe27b0
--- /dev/null
+++ b/changes/ticket3723
@@ -0,0 +1,3 @@
+ o Minor features (directory authority):
+ - When a bandwidth file is used to obtain the bandwidth measurements,
+ include this bandwidth file headers in the votes. Closes ticket 3723.
diff --git a/configure.ac b/configure.ac
index 296591f025..3a2f579b63 100644
--- a/configure.ac
+++ b/configure.ac
@@ -572,58 +572,60 @@ AM_CONDITIONAL(THREADS_WIN32, test "$bwin32" = "true")
AM_CONDITIONAL(THREADS_PTHREADS, test "$bwin32" = "false")
AC_CHECK_FUNCS(
- _NSGetEnviron \
+ _NSGetEnviron \
RtlSecureZeroMemory \
SecureZeroMemory \
- accept4 \
- backtrace \
- backtrace_symbols_fd \
+ accept4 \
+ backtrace \
+ backtrace_symbols_fd \
eventfd \
explicit_bzero \
timingsafe_memcmp \
- flock \
- ftime \
- get_current_dir_name \
- getaddrinfo \
- getifaddrs \
- getpass \
- getrlimit \
- gettimeofday \
- gmtime_r \
+ flock \
+ ftime \
+ get_current_dir_name \
+ getaddrinfo \
+ getdelim \
+ getifaddrs \
+ getline \
+ getpass \
+ getrlimit \
+ gettimeofday \
+ gmtime_r \
gnu_get_libc_version \
htonll \
- inet_aton \
- ioctl \
- issetugid \
- llround \
- localtime_r \
- lround \
+ inet_aton \
+ ioctl \
+ issetugid \
+ llround \
+ localtime_r \
+ lround \
mach_approximate_time \
- memmem \
- memset_s \
- mmap \
+ memmem \
+ memset_s \
+ mmap \
pipe \
pipe2 \
- prctl \
+ prctl \
readpassphrase \
- rint \
- sigaction \
- socketpair \
+ rint \
+ sigaction \
+ socketpair \
statvfs \
- strncasecmp \
- strcasecmp \
- strlcat \
- strlcpy \
+ strncasecmp \
+ strcasecmp \
+ strlcat \
+ strlcpy \
strnlen \
- strptime \
- strtok_r \
- strtoull \
- sysconf \
+ strptime \
+ strtok_r \
+ strtoull \
+ sysconf \
sysctl \
truncate \
- uname \
+ uname \
usleep \
- vasprintf \
+ vasprintf \
_vscprintf
)
@@ -900,6 +902,7 @@ AC_CHECK_MEMBERS([struct ssl_method_st.get_cipher_by_char], , ,
])
AC_CHECK_FUNCS([ \
+ ERR_load_KDF_strings \
SSL_SESSION_get_master_key \
SSL_get_server_random \
SSL_get_client_ciphers \
@@ -1365,57 +1368,57 @@ dnl Make sure to enable support for large off_t if available.
AC_SYS_LARGEFILE
AC_CHECK_HEADERS([errno.h \
- fcntl.h \
- signal.h \
- string.h \
- sys/capability.h \
- sys/fcntl.h \
- sys/stat.h \
- sys/time.h \
- sys/types.h \
- time.h \
- unistd.h \
- arpa/inet.h \
- crt_externs.h \
- execinfo.h \
- gnu/libc-version.h \
- grp.h \
- ifaddrs.h \
- inttypes.h \
- limits.h \
- linux/types.h \
- machine/limits.h \
- malloc.h \
- malloc/malloc.h \
- malloc_np.h \
- netdb.h \
- netinet/in.h \
- netinet/in6.h \
- pwd.h \
- readpassphrase.h \
- stdatomic.h \
- sys/eventfd.h \
- sys/file.h \
- sys/ioctl.h \
- sys/limits.h \
- sys/mman.h \
- sys/param.h \
- sys/prctl.h \
+ fcntl.h \
+ signal.h \
+ string.h \
+ sys/capability.h \
+ sys/fcntl.h \
+ sys/stat.h \
+ sys/time.h \
+ sys/types.h \
+ time.h \
+ unistd.h \
+ arpa/inet.h \
+ crt_externs.h \
+ execinfo.h \
+ gnu/libc-version.h \
+ grp.h \
+ ifaddrs.h \
+ inttypes.h \
+ limits.h \
+ linux/types.h \
+ machine/limits.h \
+ malloc.h \
+ malloc/malloc.h \
+ malloc_np.h \
+ netdb.h \
+ netinet/in.h \
+ netinet/in6.h \
+ pwd.h \
+ readpassphrase.h \
+ stdatomic.h \
+ sys/eventfd.h \
+ sys/file.h \
+ sys/ioctl.h \
+ sys/limits.h \
+ sys/mman.h \
+ sys/param.h \
+ sys/prctl.h \
sys/random.h \
- sys/resource.h \
- sys/select.h \
- sys/socket.h \
- sys/statvfs.h \
- sys/syscall.h \
- sys/sysctl.h \
- sys/syslimits.h \
- sys/time.h \
- sys/types.h \
- sys/un.h \
- sys/utime.h \
- sys/wait.h \
- syslog.h \
- utime.h])
+ sys/resource.h \
+ sys/select.h \
+ sys/socket.h \
+ sys/statvfs.h \
+ sys/syscall.h \
+ sys/sysctl.h \
+ sys/syslimits.h \
+ sys/time.h \
+ sys/types.h \
+ sys/un.h \
+ sys/utime.h \
+ sys/wait.h \
+ syslog.h \
+ utime.h])
AC_CHECK_HEADERS(sys/param.h)
@@ -2250,6 +2253,9 @@ dnl -Wthread-safety-precise
if test "$tor_cv_cflags__Woverlength_strings" = "yes"; then
AC_DEFINE([HAVE_CFLAG_WOVERLENGTH_STRINGS], 1, [True if we have -Woverlength-strings])
fi
+ if test "$tor_cv_cflags__warn_unused_const_variable_2" = "yes"; then
+ AC_DEFINE([HAVE_CFLAG_WUNUSED_CONST_VARIABLE], 1, [True if we have -Wunused-const-variable])
+ fi
if test "x$enable_fatal_warnings" = "xyes"; then
# I'd like to use TOR_CHECK_CFLAGS here, but I can't, since the
@@ -2269,20 +2275,20 @@ fi
CPPFLAGS="$CPPFLAGS $TOR_CPPFLAGS_libevent $TOR_CPPFLAGS_openssl $TOR_CPPFLAGS_zlib"
AC_CONFIG_FILES([
- Doxyfile
- Makefile
- config.rust
- link_rust.sh
- contrib/dist/suse/tor.sh
- contrib/operator-tools/tor.logrotate
- contrib/dist/tor.sh
- contrib/dist/torctl
- contrib/dist/tor.service
- src/config/torrc.sample
- src/config/torrc.minimal
- src/rust/.cargo/config
- scripts/maint/checkOptionDocs.pl
- scripts/maint/updateVersions.pl
+ Doxyfile
+ Makefile
+ config.rust
+ link_rust.sh
+ contrib/dist/suse/tor.sh
+ contrib/operator-tools/tor.logrotate
+ contrib/dist/tor.sh
+ contrib/dist/torctl
+ contrib/dist/tor.service
+ src/config/torrc.sample
+ src/config/torrc.minimal
+ src/rust/.cargo/config
+ scripts/maint/checkOptionDocs.pl
+ scripts/maint/updateVersions.pl
])
if test "x$asciidoc" = "xtrue" && test "$ASCIIDOC" = "none"; then
diff --git a/doc/HACKING/CodeStructure.md b/doc/HACKING/CodeStructure.md
new file mode 100644
index 0000000000..736d6cd484
--- /dev/null
+++ b/doc/HACKING/CodeStructure.md
@@ -0,0 +1,129 @@
+
+TODO: revise this to talk about how things are, rather than how things
+have changed.
+
+TODO: Make this into good markdown.
+
+
+
+For quite a while now, the program "tor" has been built from source
+code in just two directories: src/common and src/or.
+
+This has become more-or-less untenable, for a few reasons -- most
+notably of which is that it has led our code to become more
+spaghetti-ish than I can endorse with a clean conscience.
+
+So to fix that, we've gone and done a huge code movement in our git
+master branch, which will land in a release once Tor 0.3.5.1-alpha is
+out.
+
+Here's what we did:
+
+ * src/common has been turned into a set of static libraries. These
+all live in the "src/lib/*" directories. The dependencies between
+these libraries should have no cycles. The libraries are:
+
+ arch -- Headers to handle architectural differences
+ cc -- headers to handle differences among compilers
+ compress -- wraps zlib, zstd, lzma
+ container -- high-level container types
+ crypt_ops -- Cryptographic operations. Planning to split this into
+a higher and lower level library
+ ctime -- Operations that need to run in constant-time. (Properly,
+data-invariant time)
+ defs -- miscelaneous definitions needed throughout Tor.
+ encoding -- transforming one data type into another, and various
+data types into strings.
+ err -- lowest-level error handling, in cases where we can't use
+the logs because something that the logging system needs has broken.
+ evloop -- Generic event-loop handling logic
+ fdio -- Low-level IO wrapper functions for file descriptors.
+ fs -- Operations on the filesystem
+ intmath -- low-level integer math and misc bit-twiddling hacks
+ lock -- low-level locking code
+ log -- Tor's logging module. This library sits roughly halfway up
+the library dependency diagram, since everything it depends on has to
+be carefully crafted to *not* log.
+ malloc -- Low-level wrappers for the platform memory allocation functions.
+ math -- Higher-level mathematical functions, and floating-point math
+ memarea -- An arena allocator
+ meminfo -- Functions for querying the current process's memory
+status and resources
+ net -- Networking compatibility and convenience code
+ osinfo -- Querying information about the operating system
+ process -- Launching and querying the status of other processes
+ sandbox -- Backend for the linux seccomp2 sandbox
+ smartlist_core -- The lowest-level of the smartlist_t data type.
+Separated from the rest of the containers library because the logging
+subsystem depends on it.
+ string -- Compatibility and convenience functions for manipulating
+C strings.
+ term -- Terminal-related functions (currently limited to a getpass
+function).
+ testsupport -- Macros for mocking, unit tests, etc.
+ thread -- Higher-level thread compatibility code
+ time -- Higher-level time management code, including format
+conversions and monotonic time
+ tls -- Our wrapper around our TLS library
+ trace -- Formerly src/trace -- a generic event tracing API
+ wallclock -- Low-level time code, used by the log module.
+
+ * To ensure that the dependency graph in src/common remains under
+control, there is a tool that you can run called "make
+check-includes". It verifies that each module in Tor only includes
+the headers that it is permitted to include, using a per-directory
+".may_include" file.
+
+ * The src/or/or.h header has been split into numerous smaller
+headers. Notably, many important structures are now declared in a
+header called foo_st.h, where "foo" is the name of the structure.
+
+ * The src/or directory, which had most of Tor's code, had been split
+up into several directories. This is still a work in progress: This
+code has not itself been refactored, and its dependency graph is still
+a tangled web. I hope we'll be working on that over the coming
+releases, but it will take a while to do.
+
+ The new top-level source directories are:
+
+ src/core -- Code necessary to actually perform or use onion routing.
+ src/feature -- Code used only by some onion routing
+configurations, or only for a special purpose.
+ src/app -- Top-level code to run, invoke, and configure the
+lower-level code
+
+ The new second-level source directories are:
+ src/core/crypto -- High-level cryptographic protocols used in Tor
+ src/core/mainloop -- Tor's event loop, connection-handling, and
+traffic-routing code.
+ src/core/or -- Parts related to handling onion routing itself
+ src/core/proto -- support for encoding and decoding different
+wire protocols
+
+ src/feature/api -- Support for making Tor embeddable
+ src/feature/client -- Functionality which only Tor clients need
+ src/feature/control -- Controller implementation
+ src/feature/dirauth -- Directory authority
+ src/feature/dircache -- Directory cache
+ src/feature/dirclient -- Directory client
+ src/feature/dircommon -- Shared code between the other directory modules
+ src/feature/hibernate -- Hibernating when Tor is out of bandwidth
+or shutting down
+ src/feature/hs -- v3 onion service implementation
+ src/feature/hs_common -- shared code between both onion service
+implementations
+ src/feature/nodelist -- storing and accessing the list of relays on
+the network.
+ src/feature/relay -- code that only relay servers and exit servers need.
+ src/feature/rend -- v2 onion service implementation
+ src/feature/stats -- statistics and history
+
+ src/app/config -- configuration and state for Tor
+ src/app/main -- Top-level functions to invoke the rest or Tor.
+
+ * The "tor" executable is now built in src/app/tor rather than src/or/tor.
+
+ * There are more static libraries than before that you need to build
+into your application if you want to embed Tor. Rather than
+maintaining this list yourself, I recommend that you run "make
+show-libs" to have Tor emit a list of what you need to link.
diff --git a/doc/HACKING/CodingStandards.md b/doc/HACKING/CodingStandards.md
index b830ecea93..4f229348e4 100644
--- a/doc/HACKING/CodingStandards.md
+++ b/doc/HACKING/CodingStandards.md
@@ -200,8 +200,8 @@ We have some wrapper functions like `tor_malloc`, `tor_free`, `tor_strdup`, and
always succeed or exit.)
You can get a full list of the compatibility functions that Tor provides by
-looking through `src/common/util*.h` and `src/common/compat*.h`. You can see the
-available containers in `src/common/containers*.h`. You should probably
+looking through `src/lib/*/*.h`. You can see the
+available containers in `src/lib/containers/*.h`. You should probably
familiarize yourself with these modules before you write too much code, or
else you'll wind up reinventing the wheel.
@@ -214,6 +214,24 @@ We don't call `memcmp()` directly. Use `fast_memeq()`, `fast_memneq()`,
Also see a longer list of functions to avoid in:
https://people.torproject.org/~nickm/tor-auto/internal/this-not-that.html
+What code can use what other code?
+----------------------------------
+
+We're trying to simplify Tor's structure over time. In the long run, we want
+Tor to be structured as a set of modules with *no circular dependencies*.
+
+This property is currently provided by the modules in src/lib, but not
+throughout the rest of Tor. In general, higher-level libraries may use
+lower-level libraries, but never the reverse.
+
+To prevent new circular dependencies from landing, we have a tool that
+you can invoke with `make check-includes`, and which is run
+automatically as part of `make check`. This tool will verify that, for
+every source directory with a `.may_include` file, no local headers are
+included except those specifically permitted by the `.may_include` file.
+When editing one of these files, please make sure that you are not
+introducing any cycles into Tor's dependency graph.
+
Floating point math is hard
---------------------------
diff --git a/doc/HACKING/HelpfulTools.md b/doc/HACKING/HelpfulTools.md
index 13d1c4b0d7..d499238526 100644
--- a/doc/HACKING/HelpfulTools.md
+++ b/doc/HACKING/HelpfulTools.md
@@ -4,9 +4,16 @@ 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.
+Travis/Appveyor CI
+------------------
+It's CI.
+
+Looks like this:
+* https://travis-ci.org/torproject/tor
+* https://ci.appveyor.com/project/torproject/tor
+
+Travis builds and runs tests on Linux, and eventually macOS (#24629).
+Appveyor builds and runs tests on Windows (using Windows Services for Linux).
Runs automatically on Pull Requests sent to torproject/tor. You can set it up
for your fork to build commits outside of PRs too:
@@ -16,6 +23,8 @@ for your fork to build commits outside of PRs too:
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).
+4. go to https://ci.appveyor.com/login , log in with github, and select
+ "NEW PROJECT"
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).
@@ -23,7 +32,16 @@ OFTC. If they don't, ask #tor-dev (also on OFTC).
Jenkins
-------
- https://jenkins.torproject.org
+It's CI/builders. Looks like this: https://jenkins.torproject.org
+
+Runs automatically on commits merged to git.torproject.org. We CI the
+master branch and all supported tor versions. We also build nightly debian
+packages from master.
+
+Builds Linux and Windows cross-compilation. Runs Linux tests.
+
+Builds should show up on the web at jenkins.torproject.org and on IRC at
+#tor-bots on OFTC. If they don't, ask #tor-dev (also on OFTC).
Valgrind
--------
diff --git a/doc/HACKING/Module.md b/doc/HACKING/Module.md
index 6684e258df..9cf36090b4 100644
--- a/doc/HACKING/Module.md
+++ b/doc/HACKING/Module.md
@@ -96,8 +96,8 @@ There are couples of "rules" you want to follow:
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`
+ - `src/feature/dirclient/shared_random.c`
+ - `src/feature/dirauth/shared_random.c`
* When you include headers from the module, **always** use the full module
path in your statement. Example:
diff --git a/doc/HACKING/ReleasingTor.md b/doc/HACKING/ReleasingTor.md
index e70416c354..55a40fc89b 100644
--- a/doc/HACKING/ReleasingTor.md
+++ b/doc/HACKING/ReleasingTor.md
@@ -7,7 +7,7 @@ new Tor release:
=== 0. Preliminaries
-1. Get at least three of weasel/arma/Sebastian/Sina to put the new
+1. Get at least two of weasel/arma/Sebastian to put the new
version number in their approved versions list. Give them a few
days to do this if you can.
diff --git a/doc/include.am b/doc/include.am
index e429d05a49..0a123aae11 100644
--- a/doc/include.am
+++ b/doc/include.am
@@ -12,7 +12,7 @@
# part of the source distribution, so that people without asciidoc can
# just use the .1 and .html files.
-all_mans = doc/tor doc/tor-gencert doc/tor-resolve doc/torify
+all_mans = doc/tor doc/tor-gencert doc/tor-resolve doc/torify doc/tor-print-ed-signing-cert
if USE_ASCIIDOC
nodist_man1_MANS = $(all_mans:=.1)
@@ -36,6 +36,7 @@ EXTRA_DIST+= doc/asciidoc-helper.sh \
doc/HACKING/README.1st.md \
doc/HACKING/CodingStandards.md \
doc/HACKING/CodingStandardsRust.md \
+ doc/HACKING/CodeStructure.md \
doc/HACKING/Fuzzing.md \
doc/HACKING/GettingStarted.md \
doc/HACKING/GettingStartedRust.md \
@@ -64,11 +65,13 @@ doc/tor.1.in: doc/tor.1.txt
doc/torify.1.in: doc/torify.1.txt
doc/tor-gencert.1.in: doc/tor-gencert.1.txt
doc/tor-resolve.1.in: doc/tor-resolve.1.txt
+doc/tor-print-ed-signing-cert.1.in: doc/tor-print-ed-signing-cert.1.txt
doc/tor.html.in: doc/tor.1.txt
doc/torify.html.in: doc/torify.1.txt
doc/tor-gencert.html.in: doc/tor-gencert.1.txt
doc/tor-resolve.html.in: doc/tor-resolve.1.txt
+doc/tor-print-ed-signing-cert.html.in: doc/tor-print-ed-signing-cert.1.txt
# use config.status to swap all machine-specific magic strings
# in the asciidoc with their replacements.
@@ -82,11 +85,13 @@ $(asciidoc_product) :
doc/tor.html: doc/tor.html.in
doc/tor-gencert.html: doc/tor-gencert.html.in
doc/tor-resolve.html: doc/tor-resolve.html.in
+doc/tor-print-ed-signing-cert.html: doc/tor-print-ed-signing-cert.html.in
doc/torify.html: doc/torify.html.in
doc/tor.1: doc/tor.1.in
doc/tor-gencert.1: doc/tor-gencert.1.in
doc/tor-resolve.1: doc/tor-resolve.1.in
+doc/tor-print-ed-signing-cert.1: doc/tor-print-ed-signing-cert.1.in
doc/torify.1: doc/torify.1.in
CLEANFILES+= $(asciidoc_product)
diff --git a/doc/tor-print-ed-signing-cert.1.txt b/doc/tor-print-ed-signing-cert.1.txt
new file mode 100644
index 0000000000..1a3109df95
--- /dev/null
+++ b/doc/tor-print-ed-signing-cert.1.txt
@@ -0,0 +1,32 @@
+// Copyright (c) The Tor Project, Inc.
+// See LICENSE for licensing information
+// This is an asciidoc file used to generate the manpage/html reference.
+// Learn asciidoc on http://www.methods.co.nz/asciidoc/userguide.html
+:man source: Tor
+:man manual: Tor Manual
+tor-print-ed-signing-cert(1)
+============================
+Tor Project, Inc.
+
+NAME
+----
+tor-print-ed-signing-cert - print expiration date of ed25519 signing certificate
+
+SYNOPSIS
+--------
+**tor-print-ed-signing-cert** __<path to ed25519_signing_cert file>__
+
+DESCRIPTION
+-----------
+**tor-print-ed-signing-cert** is utility program for Tor relay operators to
+check expiration date of ed25519 signing certificate.
+
+SEE ALSO
+--------
+**tor**(1) +
+
+https://spec.torproject.org/cert-spec
+
+AUTHORS
+-------
+Roger Dingledine <arma@mit.edu>, Nick Mathewson <nickm@alum.mit.edu>.
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index f42ad0dd3c..1db8cabf86 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -2747,7 +2747,9 @@ on the public Tor network.
[[V3BandwidthsFile]] **V3BandwidthsFile** __FILENAME__::
V3 authoritative directories only. Configures the location of the
bandwidth-authority generated file storing information on relays' measured
- bandwidth capacities. (Default: unset)
+ bandwidth capacities. To avoid inconsistent reads, bandwidth data should
+ be written to temporary file, then renamed to the configured filename.
+ (Default: unset)
[[V3AuthUseLegacyKey]] **V3AuthUseLegacyKey** **0**|**1**::
If set, the directory authority will sign consensuses not only with its
diff --git a/scripts/codegen/fuzzing_include_am.py b/scripts/codegen/fuzzing_include_am.py
index 42a61876e8..3c948d87cf 100755
--- a/scripts/codegen/fuzzing_include_am.py
+++ b/scripts/codegen/fuzzing_include_am.py
@@ -12,6 +12,7 @@ FUZZERS = """
http-connect
iptsv2
microdesc
+ socks
vrs
"""
@@ -83,6 +84,7 @@ def get_id_name(s):
for fuzzer in FUZZERS:
idname = get_id_name(fuzzer)
print("""\
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_{name}_SOURCES = \\
src/test/fuzz/fuzzing_common.c \\
src/test/fuzz/fuzz_{name}.c
@@ -90,11 +92,14 @@ src_test_fuzz_fuzz_{name}_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_{name}_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_{name}_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_{name}_LDADD = $(FUZZING_LIBS)
+endif
""".format(name=idname))
+print("if UNITTESTS_ENABLED")
print("FUZZERS = \\")
print(" \\\n".join("\tsrc/test/fuzz/fuzz-{name}".format(name=fuzzer)
for fuzzer in FUZZERS))
+print("endif")
print("\n# ===== libfuzzer")
print("\nif LIBFUZZER_ENABLED")
@@ -102,12 +107,14 @@ print("\nif LIBFUZZER_ENABLED")
for fuzzer in FUZZERS:
idname = get_id_name(fuzzer)
print("""\
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_{name}_SOURCES = \\
$(src_test_fuzz_fuzz_{name}_SOURCES)
src_test_fuzz_lf_fuzz_{name}_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
src_test_fuzz_lf_fuzz_{name}_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_{name}_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_{name}_LDADD = $(LIBFUZZER_LIBS)
+endif
""".format(name=idname))
print("LIBFUZZER_FUZZERS = \\")
@@ -125,10 +132,12 @@ print("if OSS_FUZZ_ENABLED")
for fuzzer in FUZZERS:
idname = get_id_name(fuzzer)
print("""\
+if UNITTESTS_ENABLED
src_test_fuzz_liboss_fuzz_{name}_a_SOURCES = \\
$(src_test_fuzz_fuzz_{name}_SOURCES)
src_test_fuzz_liboss_fuzz_{name}_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_{name}_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
""".format(name=idname))
print("OSS_FUZZ_FUZZERS = \\")
diff --git a/scripts/maint/fallback.blacklist b/scripts/maint/fallback.blacklist
deleted file mode 100644
index a118cb5919..0000000000
--- a/scripts/maint/fallback.blacklist
+++ /dev/null
@@ -1,232 +0,0 @@
-# updateFallbackDirs.py directory mirror blacklist
-#
-# Format:
-# [ IPv4[:DirPort] ] [ orport=<ORPort> ] [ id=<ID> ] ...
-# [ ipv6=<IPv6>[:<IPv6 ORPort>] ]
-# or use:
-# scripts/maint/generateFallbackDirLine.py fingerprint ...
-#
-# If a sufficiently specific group of attributes matches, the directory mirror
-# will be excluded: (each group is listed on its own line)
-# <IPv4>, <DirPort>
-# <IPv4>, <ORPort>
-# <ID>
-# <IPv6>, <DirPort>
-# <IPv6>, <IPv6 ORPort>
-# If DirPort and ORPort are not present, the entire IP address is blacklisted.
-# (The blacklist overrides the whitelist.)
-
-# If a relay operator doesn't want their relay to be a FallbackDir,
-# enter the following information here:
-# <IPv4>:<DirPort> orport=<ORPort> id=<ID> ipv6=<IPv6>:<IPv6 ORPort>
-
-# https://lists.torproject.org/pipermail/tor-relays/2015-December/008364.html
-87.181.248.227:9030 orport=443 id=8827944C4BDCBDAC9079803F47823403C11A9B7A
-
-# https://lists.torproject.org/pipermail/tor-relays/2015-December/008368.html
-149.18.2.82:9030 orport=9001 id=953DB709F2A2DECC8D7560661F934E64411444F7
-
-# https://lists.torproject.org/pipermail/tor-relays/2015-December/008384.html
-80.82.215.199:80 orport=443 id=3BEFAB76461B6B99DCF34C285E933562F5712AE4 ipv6=[2001:4ba0:cafe:a18::1]:443
-
-# Email sent directly to teor, verified using relay contact info
-5.34.183.168:80 orport=443 id=601C92108A568742A7A6D9473FE3A414F7149070
-217.12.199.208:8080 orport=22 id=BCFB0933367D626715DA32A147F417194A5D48D6
-
-# https://lists.torproject.org/pipermail/tor-relays/2016-January/008555.html
-62.210.207.124:9030 orport=9001 id=58938B1A5C4029B4415D38A4F36B7724273F4755 ipv6=[2001:bc8:31eb:100::1]:9001
-62.210.207.124:9130 orport=9101 id=338D0AB6DBAB7B529B9C91B2FD770658000693C4 ipv6=[2001:bc8:31eb:100::1]:9101
-
-# Email sent directly to teor, verified using relay contact info
-216.17.99.183:80 orport=443 id=D52CD431CEF28E01B11F545A84347EE45524BCA7
-216.17.99.183:8080 orport=9001 id=EE21F83AB6F76E3B3FFCBA5C2496F789CB84E7C6
-65.19.167.130:80 orport=443 id=890E2EA65455FBF0FAAB4159FAC4412BDCB24295
-65.19.167.131:80 orport=443 id=0DA9BD201766EDB19F57F49F1A013A8A5432C008
-65.19.167.132:80 orport=443 id=12B80ABF019354A9D25EE8BE85EB3C0AD8F7DFC1
-65.19.167.133:80 orport=443 id=C170AE5A886C5A09D6D1CF5CF284653632EEF25D
-
-# Email sent directly to teor, verified using relay contact info
-213.136.83.225:80 orport=443 id=B411027C926A9BFFCF7DA91E3CAF1856A321EFFD
-195.154.126.78:80 orport=443 id=F6556156E2B3837248E03FDB770441CF64DBBFBE
-
-# Email sent directly to teor, verified using relay contact info
-178.63.198.113:80 orport=443 id=872B18761953254914F77C71846E8A2623C52591
-
-# Email sent directly to teor, verified using relay contact info
-63.141.226.34:80 orport=9001 id=5EF131C0C82270F40B756987FDB5D54D9C966238
-185.75.56.103:80 orport=9001 id=3763CE5C3F574670D4296573744F821C0FFFB98E
-
-# Email sent directly to teor, verified using relay contact info
-81.7.14.227:9030 orport=9001 id=BCA197C43A44B7B9D14509637F96A45B13C233D0
-
-# Email sent directly to teor, verified using relay contact info
-84.245.32.195:9030 orport=9001 id=4CD4DFFEF3971C902A22100D911CAC639BE2EF5C
-
-# Email sent directly to teor, verified using relay contact info
-185.21.217.10:9030 orport=9001 id=41537E1D3DD3CAE86F5A3F0882F1C647FE8FC0A0
-
-# Email sent directly to teor, verified using relay contact info
-185.21.216.140:9030 orport=9001 id=921DA852C95141F8964B359F774B35502E489869
-
-# Email sent directly to teor, verified using relay contact info
-46.101.220.161:80 orport=443 id=7DDFE5B2C306B19A79832FBE581EAA245BAE90C6 ipv6=[2a03:b0c0:3:d0::8b:3001]:443
-
-# Email sent directly to teor, verified using relay contact info
-195.154.107.23:80 orport=443 id=A1F89F26E82209169E4037B035AE7B6C94A49AEB ipv6=[2001:bc8:3829:300::1]:443
-195.154.92.70:80 orport=443 id=E7FF4ECEEFCFE3A40A6D3594898A4A3DE018BBF5 ipv6=[2001:bc8:3829:500::1]:443
-195.154.113.200:80 orport=443 id=D1A4763FA0BD71978901B1951FEE1DC29777F95A ipv6=[2001:bc8:3829:600::1]:443
-195.154.92.155:110 orport=993 id=4477D3466FE136B7FE6F7FF8EBD0D6E2FFE3288B ipv6=[2001:bc8:3829:100::1]:993
-195.154.117.182:110 orport=993 id=B1A0F1143789466AADD5FAE5948C8138548EECEC ipv6=[2001:bc8:3829:400::1]:993
-195.154.97.163:80 orport=443 id=8A2994A63B20813B7724817A8FB8C444D10BA2E2
-
-# Email sent directly to teor, verified using relay contact info
-5.135.154.206:9030 orport=9001 id=7D67B342DC1158F4CFFEE8BC530A2448848026E3
-
-# Email sent directly to teor, verified using relay contact info
-85.24.215.117:9030 orport=9001 id=5989521A85C94EE101E88B8DB2E68321673F9405 ipv6=[2001:9b0:20:2106:21a:4aff:fea5:ad05]:9001
-
-# Email sent directly to teor, verified using relay contact info
-62.210.137.230:8888 orport=8843 id=CD6B850159CFF4C068A8D0F1BA5296AE4EDCAB39 ipv6=[2001:bc8:31d3:100::1]:3443
-62.210.137.230:8080 orport=8443 id=F596E1B1EF98E1DDBBDC934DB722AF54069868F6 ipv6=[2001:bc8:31d3:100::1]:8443
-
-# Email sent directly to teor, verified using relay contact info
-195.154.99.80:80 orport=443 id=6E7CB6E783C1B67B79D0EBBE7D48BC09BD441201
-195.154.127.60:80 orport=443 id=D74ABE34845190E242EC74BA28B8C89B0A480D4B
-
-# Email sent directly to teor, verified using relay contact info
-212.51.143.20:80 orport=443 id=62DA0256BBC28992D41CBAFB549FFD7C9B846A99
-
-# Email sent directly to teor, verified using relay contact info
-195.154.90.122:80 orport=443 id=3A0D88024A30152E6F6372CFDF8F9B725F984362
-
-# Email sent directly to teor, verified using relay contact info
-188.166.118.215:9030 orport=443 id=FB5FF60F5EBA010F8A45AC6ED31A4393718A2C31 ipv6=[2a03:b0c0:2:d0::72:9001]:443
-
-# Email sent directly to teor, verified using relay contact info
-185.87.185.245:40001 orport=40000 id=2A499AEEA95FB10F07544383D562368E49BE32CA
-
-# Email sent directly to teor, verified using relay contact info
-82.161.109.71:9030 orport=9001 id=BD9CE352648B940E788A8E45393C5400CC3E87E7
-
-# Email sent directly to teor, verified using relay contact info
-212.83.40.239:9030 orport=9001 id=6DC5616BD3FC463329DCE87DD7AAAEA112C264B5
-
-# Email sent directly to teor, verified using relay contact info
-178.32.53.53:80 orport=443 id=10582C360E972EE76B0DB1C246F4E892A6BF5465
-
-# Email sent directly to teor, verified using relay contact info
-85.114.135.20:9030 orport=9001 id=ED8A9291A3139E34BBD35037B082081EC6C26C80 ipv6=[2001:4ba0:fff5:2d::8]:9001
-148.251.128.156:9030 orport=9001 id=E382042E06A0A68AFC533E5AD5FB6867A12DF9FF ipv6=[2a01:4f8:210:238a::8]:9001
-62.210.115.147:9030 orport=9001 id=7F1D94E2C36F8CC595C2AB00022A5AE38171D50B ipv6=[2001:bc8:3182:101::8]:9001
-
-# Email sent directly to teor, verified using relay contact info
-74.208.220.222:60000 orport=59999 id=4AA22235F0E9B3795A33930343CBB3EDAC60C5B0
-
-# Email sent directly to teor, verified using relay contact info
-89.163.140.168:9030 orport=9001 id=839C1212DB15723263BE96C83DA7E1B24FA395E8
-
-# Email sent directly to teor, verified using relay contact info
-212.47.246.211:9030 orport=9001 id=AA34219475E41282095DD3C088009EE562AF14E5
-
-# Email sent directly to teor, verified using relay contact info
-85.195.235.148:9030 orport=9001 id=103336165A0D2EFCAD3605339843A0A7710B8B92
-85.195.235.148:19030 orport=19001 id=713235638AB6C64715EAFD1B4772685E38AFD52A
-
-# Email sent directly to teor, verified using relay contact info
-163.172.7.30:9030 orport=9001 id=E2EACD4752B2583202F374A34CACC844A3AECAC4
-
-# Email sent directly to teor, verified using relay contact info
-178.62.90.111:22 orport=25 id=3254D1DC1F1531D9C07C535E4991F38EE99B99E1
-
-# Email sent directly to teor, verified using relay contact info
-213.200.106.131:9030 orport=4443 id=B07CE79FD215129C381F6645B16E76DCA0845CAB
-
-# Email sent directly to teor, verified using relay contact info
-198.51.75.165:80 orport=9001 id=DABCB84A524A22FDDD3AFCB090E3090CC12D9770
-
-# Email sent directly to teor, verified using relay contact info
-204.194.29.4:80 orport=9001 id=78C7C299DB4C4BD119A22B87B57D5AF5F3741A79
-
-# Email sent directly to teor, verified using relay contact info
-104.207.132.109:9030 orport=9001 id=12D5737383C23E756A7AA1A90BB24413BA428DA7 ipv6=[2001:19f0:300:2261::1]:9001
-
-# Email sent directly to teor, verified using relay contact info
-46.252.25.249:9030 orport=443 id=80DCBB6EF4E86A7CD4FBCBDEE64979645509A610
-
-# Email sent directly to teor, verified using relay contact info
-176.10.99.200:8080 orport=443 id=2B44FD1742D26E4F28D4CACF1F0CF8A686270E45
-176.10.99.200:8000 orport=22 id=EB79F07792A065D3C534063773E83268E069F5EB
-176.10.99.201:667 orport=666 id=3EAAAB35932610411E24FA4317603CB5780B80BC
-176.10.99.201:990 orport=989 id=7C3A4CFF09C1981D41173CDE2A2ADD4A5CA109FD
-176.10.99.202:992 orport=991 id=615EBC4B48F03858FA50A3E23E5AF569D0D2308A
-176.10.99.202:994 orport=993 id=E34E25D958D46DDE5092385B14117C9B301DC0E9
-176.10.99.203:1194 orport=995 id=AD368442E9FF33C08C7407DF2DA7DB958F406CE2
-176.10.99.203:43 orport=53 id=79CF377F0ACEC5F0002D85335E4192B34202A269
-176.10.99.204:1755 orport=1723 id=69DF3CDA1CDA460C17ECAD9D6F0C117A42384FA0
-176.10.99.204:1293 orport=4321 id=3F061400B6FB1F55E7F19BB3C713884D677E55B7
-176.10.99.205:426 orport=425 id=C30B284784BF11D0D58C6A250240EE58D2084AD0
-176.10.99.205:109 orport=110 id=12D17D9F9E30FA901DE68806950A0EA278716CED
-176.10.99.206:24 orport=23 id=2C804AAB0C02F971A4386B3A1F2AC00F9E080679
-176.10.99.206:20 orport=21 id=237588726AB6BEA37FF23CA00F5BD178586CA68E
-176.10.99.207:3390 orport=3389 id=A838D5B8890B10172429ECE92EB5677DF93DC4DD
-176.10.99.207:1415 orport=1414 id=377E5E817A84FAE0F4DC3427805DB2E8A6CBBFC0
-176.10.99.208:390 orport=389 id=7C288587BA0D99CC6B8537CDC2C4639FA827B907
-176.10.99.208:3307 orport=3306 id=1F0D2A44C56F42816DED2022EFD631878C29905B
-176.10.99.209:1434 orport=1433 id=BDA7A91FF3806DE5109FDAE74CFEFB3BABB9E10F
-176.10.99.209:220 orport=219 id=B8C2030001D832066A648269CFBA94171951D34B
-
-# Email sent directly to teor, verified using relay contact info
-78.193.40.205:8080 orport=8443 id=C91450840E75AC1B654A3096744338A573A239C6
-
-# Email sent directly to teor, verified using relay contact info
-37.187.22.172:9030 orport=9035 id=335E4117BD9A4966403C2AFA31CFDD1BC13BD46A
-
-# https://lists.torproject.org/pipermail/tor-relays/2015-December/008367.html
-# Email sent directly to teor to opt-out
-88.198.38.226:22 orport=443 id=4B9E2C56FB42B891794FE2CD2FCAD08A320CC3BB ipv6=[2a01:4f8:a0:1351::2]:80
-213.239.210.204:22 orport=443 id=5BFDECCE9B4A23AE14EC767C5A2C1E10558B00B9 ipv6=[2a01:4f8:a0:9474::2]:80
-213.239.220.25:22 orport=443 id=BEE2317AE127EB681C5AE1551C1EA0630580638A ipv6=[2a01:4f8:a0:710c::2]:80
-85.10.201.38:22 orport=443 id=F6279A203C1950ACF592322A235647A05BFBCF91 ipv6=[2a01:4f8:a0:43cc::2]:80
-
-# Email sent directly to teor, verified using relay contact info
-88.190.208.4:30555 orport=30556 id=030A6EB24725C05D8E0FCE21923CBA5223E75E0E
-
-# Fallback was on 0.2.8.2-alpha list, but opted-out before 0.2.8.6
-37.187.1.149:9030 orport=9001 id=08DC0F3C6E3D9C527C1FC8745D35DD1B0DE1875D ipv6=[2001:41d0:a:195::1]:9001
-
-# Email sent directly to teor, verified using relay contact info
-195.154.15.227:9030 orport=9001 id=6C3E3AB2F5F03CD71B637D433BAD924A1ECC5796
-
-# Fallback was on 0.2.8.6 list, but opted-out before 0.2.9
-144.76.73.140:9030 orport=9001 id=6A640018EABF3DA9BAD9321AA37C2C87BBE1F907
-
-# https://lists.torproject.org/pipermail/tor-relays/2016-December/011114.html
-# no dirport
-86.107.110.34:0 orport=9001 id=A0E3D30A660DB70CA0B6D081BA54D094DED6F28D
-94.242.59.147:80 orport=9001 id=674DCBB0D9C1C4C4DBFB4A9AE024AF59FE4E7F46 ipv6=[2a00:1838:35:42::b648]:9001
-
-# Email sent directly to teor, verified using relay contact info
-167.114.152.100:9030 orport=443 id=0EF5E5FFC5D1EABCBDA1AFF6F6D6325C5756B0B2 ipv6=[2607:5300:100:200::1608]:443
-
-# Email sent directly to teor, verified using relay contact info
-163.172.35.245:80 orport=443 id=B771AA877687F88E6F1CA5354756DF6C8A7B6B24
-
-# Email sent directly to teor, verified using relay contact info
-104.243.35.196:9030 orport=9001 id=FA3415659444AE006E7E9E5375E82F29700CFDFD
-
-# Emails sent directly to teor, verified using relay contact info
-217.12.199.208:80 orport=443 id=DF3AED4322B1824BF5539AE54B2D1B38E080FF05 ipv6=[2a02:27a8:0:2::7e]:443
-
-# Emails sent directly to teor, verified using relay contact info
-195.154.75.84:9030 orport=9001 id=F80FDE27EFCB3F6A7B4E2CC517133DBFFA78BA2D
-195.154.127.246:9030 orport=9001 id=4FEE77AFFD157BBCF2D896AE417FBF647860466C
-
-# Email sent directly to teor, verified using relay contact info
-5.35.251.247:9030 orport=9001 id=9B1F5187DFBA89DC24B37EA7BF896C12B43A27AE
-
-#https://lists.torproject.org/pipermail/tor-relays/2017-May/012281.html
-62.210.124.124:9030 orport=9001 id=86E78DD3720C78DA8673182EF96C54B162CD660C ipv6=[2001:bc8:3f23:100::1]:9001
-62.210.124.124:9130 orport=9101 id=2EBD117806EE43C3CC885A8F1E4DC60F207E7D3E ipv6=[2001:bc8:3f23:100::1]:9101
-
-# Email sent directly to teor
-212.51.156.193:995 orport=110 id=32E7AAF1F602814D699BEF6761AD03E387758D49 ipv6=[2a02:168:4a01::49]:110
diff --git a/scripts/maint/updateFallbackDirs.py b/scripts/maint/updateFallbackDirs.py
index 355dc027df..0ea3992d8f 100755
--- a/scripts/maint/updateFallbackDirs.py
+++ b/scripts/maint/updateFallbackDirs.py
@@ -117,10 +117,9 @@ CONSENSUS_EXPIRY_TOLERANCE = 0
# Output fallback name, flags, bandwidth, and ContactInfo in a C comment?
OUTPUT_COMMENTS = True if OUTPUT_CANDIDATES else False
-# Output matching ContactInfo in fallbacks list or the blacklist?
+# Output matching ContactInfo in fallbacks list?
# Useful if you're trying to contact operators
CONTACT_COUNT = True if OUTPUT_CANDIDATES else False
-CONTACT_BLACKLIST_COUNT = True if OUTPUT_CANDIDATES else False
# How the list should be sorted:
# fingerprint: is useful for stable diffs of fallback lists
@@ -141,26 +140,12 @@ LOCAL_FILES_ONLY = False
# The whitelist contains entries that are included if all attributes match
# (IPv4, dirport, orport, id, and optionally IPv6 and IPv6 orport)
-# The blacklist contains (partial) entries that are excluded if any
-# sufficiently specific group of attributes matches:
-# IPv4 & DirPort
-# IPv4 & ORPort
-# ID
-# IPv6 & DirPort
-# IPv6 & IPv6 ORPort
-# If neither port is included in the blacklist, the entire IP address is
-# blacklisted.
-
-# What happens to entries in neither list?
+
+# What happens to entries not in whitelist?
# When True, they are included, when False, they are excluded
INCLUDE_UNLISTED_ENTRIES = True if OUTPUT_CANDIDATES else False
-# If an entry is in both lists, what happens?
-# When True, it is excluded, when False, it is included
-BLACKLIST_EXCLUDES_WHITELIST_ENTRIES = True
-
WHITELIST_FILE_NAME = 'scripts/maint/fallback.whitelist'
-BLACKLIST_FILE_NAME = 'scripts/maint/fallback.blacklist'
FALLBACK_FILE_NAME = 'src/app/config/fallback_dirs.inc'
# The number of bytes we'll read from a filter file before giving up
@@ -984,78 +969,6 @@ class Candidate(object):
return True
return False
- def is_in_blacklist(self, relaylist):
- """ A fallback matches a blacklist line if a sufficiently specific group
- of attributes matches:
- ipv4 & dirport
- ipv4 & orport
- id
- ipv6 & dirport
- ipv6 & ipv6 orport
- If the fallback and the blacklist line both have an ipv6 key,
- their values will be compared, otherwise, they will be ignored.
- If there is no dirport and no orport, the entry matches all relays on
- that ip. """
- for entry in relaylist:
- for key in entry:
- value = entry[key]
- if key == 'id' and value == self._fpr:
- log_excluded('%s is in the blacklist: fingerprint matches',
- self._fpr)
- return True
- if key == 'ipv4' and value == self.dirip:
- # if the dirport is present, check it too
- if entry.has_key('dirport'):
- if int(entry['dirport']) == self.dirport:
- log_excluded('%s is in the blacklist: IPv4 (%s) and ' +
- 'DirPort (%d) match', self._fpr, self.dirip,
- self.dirport)
- return True
- # if the orport is present, check it too
- elif entry.has_key('orport'):
- if int(entry['orport']) == self.orport:
- log_excluded('%s is in the blacklist: IPv4 (%s) and ' +
- 'ORPort (%d) match', self._fpr, self.dirip,
- self.orport)
- return True
- else:
- log_excluded('%s is in the blacklist: IPv4 (%s) matches, and ' +
- 'entry has no DirPort or ORPort', self._fpr,
- self.dirip)
- return True
- ipv6 = None
- if self.has_ipv6():
- ipv6 = '%s:%d'%(self.ipv6addr, self.ipv6orport)
- if (key == 'ipv6' and self.has_ipv6()):
- # if both entry and fallback have an ipv6 address, compare them,
- # otherwise, disregard ipv6 addresses
- if value == ipv6:
- # if the dirport is present, check it too
- if entry.has_key('dirport'):
- if int(entry['dirport']) == self.dirport:
- log_excluded('%s is in the blacklist: IPv6 (%s) and ' +
- 'DirPort (%d) match', self._fpr, ipv6,
- self.dirport)
- return True
- # we've already checked the ORPort, it's part of entry['ipv6']
- else:
- log_excluded('%s is in the blacklist: IPv6 (%s) matches, and' +
- 'entry has no DirPort', self._fpr, ipv6)
- return True
- elif (key == 'ipv6' or self.has_ipv6()):
- # only log if the fingerprint matches but the IPv6 doesn't
- if entry.has_key('id') and entry['id'] == self._fpr:
- log_excluded('%s skipping IPv6 blacklist comparison: relay ' +
- 'has%s IPv6%s, but entry has%s IPv6%s', self._fpr,
- '' if self.has_ipv6() else ' no',
- (' (' + ipv6 + ')') if self.has_ipv6() else '',
- '' if key == 'ipv6' else ' no',
- (' (' + value + ')') if key == 'ipv6' else '')
- logging.warning('Has %s %s IPv6 address %s?', self._fpr,
- 'gained an' if self.has_ipv6() else 'lost its former',
- ipv6 if self.has_ipv6() else value)
- return False
-
def cw_to_bw_factor(self):
# any relays with a missing or zero consensus weight are not candidates
# any relays with a missing advertised bandwidth have it set to zero
@@ -1317,26 +1230,12 @@ class Candidate(object):
s += '\n'
if self._data['contact'] is not None:
s += cleanse_c_multiline_comment(self._data['contact'])
- if CONTACT_COUNT or CONTACT_BLACKLIST_COUNT:
+ if CONTACT_COUNT:
fallback_count = len([f for f in fallbacks
if f._data['contact'] == self._data['contact']])
if fallback_count > 1:
s += '\n'
s += '%d identical contacts listed' % (fallback_count)
- if CONTACT_BLACKLIST_COUNT:
- prefilter_count = len([f for f in prefilter_fallbacks
- if f._data['contact'] == self._data['contact']])
- filter_count = prefilter_count - fallback_count
- if filter_count > 0:
- if fallback_count > 1:
- s += ' '
- else:
- s += '\n'
- s += '%d blacklisted' % (filter_count)
- s += '\n'
- s += '*/'
- s += '\n'
- return s
# output the fallback info C string for this fallback
# this is the text that would go after FallbackDir in a torrc
@@ -1544,48 +1443,32 @@ class CandidateList(dict):
relaylist.append(relay_entry)
return relaylist
- # apply the fallback whitelist and blacklist
- def apply_filter_lists(self, whitelist_obj, blacklist_obj):
+ # apply the fallback whitelist
+ def apply_filter_lists(self, whitelist_obj):
excluded_count = 0
- logging.debug('Applying whitelist and blacklist.')
- # parse the whitelist and blacklist
+ logging.debug('Applying whitelist')
+ # parse the whitelist
whitelist = self.load_relaylist(whitelist_obj)
- blacklist = self.load_relaylist(blacklist_obj)
filtered_fallbacks = []
for f in self.fallbacks:
in_whitelist = f.is_in_whitelist(whitelist)
- in_blacklist = f.is_in_blacklist(blacklist)
- if in_whitelist and in_blacklist:
- if BLACKLIST_EXCLUDES_WHITELIST_ENTRIES:
- # exclude
- excluded_count += 1
- logging.warning('Excluding %s: in both blacklist and whitelist.',
- f._fpr)
- else:
- # include
- filtered_fallbacks.append(f)
- elif in_whitelist:
+ if in_whitelist:
# include
filtered_fallbacks.append(f)
- elif in_blacklist:
- # exclude
- excluded_count += 1
- log_excluded('Excluding %s: in blacklist.', f._fpr)
- else:
- if INCLUDE_UNLISTED_ENTRIES:
+ elif INCLUDE_UNLISTED_ENTRIES:
# include
filtered_fallbacks.append(f)
- else:
+ else:
# exclude
excluded_count += 1
- log_excluded('Excluding %s: in neither blacklist nor whitelist.',
+ log_excluded('Excluding %s: not in whitelist.',
f._fpr)
self.fallbacks = filtered_fallbacks
return excluded_count
@staticmethod
def summarise_filters(initial_count, excluded_count):
- return '/* Whitelist & blacklist excluded %d of %d candidates. */'%(
+ return '/* Whitelist excluded %d of %d candidates. */'%(
excluded_count, initial_count)
# calculate each fallback's measured bandwidth based on the median
@@ -2181,18 +2064,14 @@ def process_existing():
logging.getLogger('stem').setLevel(logging.INFO)
whitelist = {'data': parse_fallback_file(FALLBACK_FILE_NAME),
'name': FALLBACK_FILE_NAME}
- blacklist = {'data': read_from_file(BLACKLIST_FILE_NAME, MAX_LIST_FILE_SIZE),
- 'name': BLACKLIST_FILE_NAME}
- list_fallbacks(whitelist, blacklist)
+ list_fallbacks(whitelist)
def process_default():
logging.basicConfig(level=logging.WARNING)
logging.getLogger('stem').setLevel(logging.WARNING)
whitelist = {'data': read_from_file(WHITELIST_FILE_NAME, MAX_LIST_FILE_SIZE),
'name': WHITELIST_FILE_NAME}
- blacklist = {'data': read_from_file(BLACKLIST_FILE_NAME, MAX_LIST_FILE_SIZE),
- 'name': BLACKLIST_FILE_NAME}
- list_fallbacks(whitelist, blacklist)
+ list_fallbacks(whitelist)
## Main Function
def main():
@@ -2213,7 +2092,7 @@ def log_excluded(msg, *args):
else:
logging.info(msg, *args)
-def list_fallbacks(whitelist, blacklist):
+def list_fallbacks(whitelist):
""" Fetches required onionoo documents and evaluates the
fallback directory criteria for each of the relays """
@@ -2250,13 +2129,13 @@ def list_fallbacks(whitelist, blacklist):
candidates.compute_fallbacks()
prefilter_fallbacks = copy.copy(candidates.fallbacks)
- # filter with the whitelist and blacklist
+ # filter with the whitelist
# if a relay has changed IPv4 address or ports recently, it will be excluded
# as ineligible before we call apply_filter_lists, and so there will be no
# warning that the details have changed from those in the whitelist.
# instead, there will be an info-level log during the eligibility check.
initial_count = len(candidates.fallbacks)
- excluded_count = candidates.apply_filter_lists(whitelist, blacklist)
+ excluded_count = candidates.apply_filter_lists(whitelist)
print candidates.summarise_filters(initial_count, excluded_count)
eligible_count = len(candidates.fallbacks)
diff --git a/src/app/config/auth_dirs.inc b/src/app/config/auth_dirs.inc
index e0937541ea..08a919b053 100644
--- a/src/app/config/auth_dirs.inc
+++ b/src/app/config/auth_dirs.inc
@@ -8,8 +8,8 @@
"dizum orport=443 "
"v3ident=E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58 "
"194.109.206.212:80 7EA6 EAD6 FD83 083C 538F 4403 8BBF A077 587D D755",
-"Bifroest orport=443 bridge "
- "37.218.247.217:80 1D8F 3A91 C37C 5D1C 4C19 B1AD 1D0C FBE8 BF72 D8E1",
+"Serge orport=9001 bridge "
+ "66.111.2.131:9030 BA44 A889 E64B 93FA A2B1 14E0 2C2A 279A 8555 C533",
"gabelmoo orport=443 "
"v3ident=ED03BB616EB2F60BEC80151114BB25CEF515B226 "
"ipv6=[2001:638:a000:4140::ffff:189]:443 "
diff --git a/src/app/config/config.c b/src/app/config/config.c
index 665732ea56..1b1889779d 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -85,7 +85,7 @@
#include "feature/relay/dns.h"
#include "core/or/dos.h"
#include "feature/client/entrynodes.h"
-#include "core/or/git_revision.h"
+#include "lib/log/git_revision.h"
#include "feature/stats/geoip.h"
#include "feature/hibernate/hibernate.h"
#include "core/mainloop/main.h"
@@ -106,6 +106,7 @@
#include "feature/client/transports.h"
#include "feature/relay/ext_orport.h"
#include "feature/dircommon/voting_schedule.h"
+#include "lib/net/resolve.h"
#ifdef _WIN32
#include <shlobj.h>
#endif
@@ -3543,6 +3544,16 @@ options_validate(or_options_t *old_options, or_options_t *options,
!options->RecommendedServerVersions))
REJECT("Versioning authoritative dir servers must set "
"Recommended*Versions.");
+
+#ifdef HAVE_MODULE_DIRAUTH
+ char *t;
+ /* Call these functions to produce warnings only. */
+ t = format_recommended_version_list(options->RecommendedClientVersions, 1);
+ tor_free(t);
+ t = format_recommended_version_list(options->RecommendedServerVersions, 1);
+ tor_free(t);
+#endif
+
if (options->UseEntryGuards) {
log_info(LD_CONFIG, "Authoritative directory servers can't set "
"UseEntryGuards. Disabling.");
@@ -3559,7 +3570,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
"(Bridge/V3)AuthoritativeDir is set.");
/* If we have a v3bandwidthsfile and it's broken, complain on startup */
if (options->V3BandwidthsFile && !old_options) {
- dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL);
+ dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL, NULL);
}
/* same for guardfraction file */
if (options->GuardfractionFile && !old_options) {
@@ -6459,26 +6470,17 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type,
addrport = smartlist_get(items, 0);
smartlist_del_keeporder(items, 0);
- const char *addrport_sep = strchr(addrport, ':');
- if (!addrport_sep) {
- log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s' "
- "(':' not found)", addrport);
+ if (tor_addr_port_split(LOG_WARN, addrport, &address, &dir_port) < 0) {
+ log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s'.", addrport);
goto err;
}
- address = tor_strndup(addrport, addrport_sep - addrport);
if (!string_is_valid_ipv4_address(address)) {
log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s' "
"(invalid IPv4 address)", address);
goto err;
}
- tor_free(address);
-
- if (addr_port_lookup(LOG_WARN, addrport, &address, NULL, &dir_port)<0) {
- log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s'", addrport);
- goto err;
- }
if (!dir_port) {
log_warn(LD_CONFIG, "Missing port in DirAuthority address '%s'",addrport);
goto err;
@@ -7009,7 +7011,7 @@ parse_port_config(smartlist_t *out,
port = 0;
else
port = 1;
- } else if (!strcmp(addrport, "auto")) {
+ } else if (!strcasecmp(addrport, "auto")) {
port = CFG_AUTO_PORT;
int af = tor_addr_parse(&addr, defaultaddr);
tor_assert(af >= 0);
diff --git a/src/app/config/confparse.c b/src/app/config/confparse.c
index 5b7f54bc65..6fa4fd1ea8 100644
--- a/src/app/config/confparse.c
+++ b/src/app/config/confparse.c
@@ -267,7 +267,7 @@ config_assign_value(const config_format_t *fmt, void *options,
break;
case CONFIG_TYPE_AUTOBOOL:
- if (!strcmp(c->value, "auto"))
+ if (!strcasecmp(c->value, "auto"))
*(int *)lvalue = -1;
else if (!strcmp(c->value, "0"))
*(int *)lvalue = 0;
diff --git a/src/app/config/confparse.h b/src/app/config/confparse.h
index cbd2ea88e2..570428c904 100644
--- a/src/app/config/confparse.h
+++ b/src/app/config/confparse.h
@@ -4,6 +4,12 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file confparse.h
+ *
+ * \brief Header for confparse.c.
+ */
+
#ifndef TOR_CONFPARSE_H
#define TOR_CONFPARSE_H
diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h
index 0c0c5d32bb..627b39aea3 100644
--- a/src/app/config/or_options_st.h
+++ b/src/app/config/or_options_st.h
@@ -4,6 +4,12 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file or_options_st.h
+ *
+ * \brief The or_options_t structure, which represents Tor's configuration.
+ */
+
#ifndef TOR_OR_OPTIONS_ST_H
#define TOR_OR_OPTIONS_ST_H
diff --git a/src/app/config/or_state_st.h b/src/app/config/or_state_st.h
index f1d5f981f1..d95df6236b 100644
--- a/src/app/config/or_state_st.h
+++ b/src/app/config/or_state_st.h
@@ -4,6 +4,12 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file or_state_t
+ *
+ * \brief The or_state_t structure, which represents Tor's state file.
+ */
+
#ifndef TOR_OR_STATE_ST_H
#define TOR_OR_STATE_ST_H
diff --git a/src/app/config/statefile.c b/src/app/config/statefile.c
index 8eeef45026..656dc2eec3 100644
--- a/src/app/config/statefile.c
+++ b/src/app/config/statefile.c
@@ -43,6 +43,7 @@
#include "lib/sandbox/sandbox.h"
#include "app/config/statefile.h"
#include "lib/encoding/confline.h"
+#include "lib/net/resolve.h"
#include "app/config/or_state_st.h"
diff --git a/src/app/config/statefile.h b/src/app/config/statefile.h
index e996d5b6e6..6433affa62 100644
--- a/src/app/config/statefile.h
+++ b/src/app/config/statefile.h
@@ -4,6 +4,12 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file statefile.h
+ *
+ * \brief Header for statefile.c
+ */
+
#ifndef TOR_STATEFILE_H
#define TOR_STATEFILE_H
diff --git a/src/core/crypto/onion_ntor.c b/src/core/crypto/onion_ntor.c
index 9e1e273ef6..ea7261cb53 100644
--- a/src/core/crypto/onion_ntor.c
+++ b/src/core/crypto/onion_ntor.c
@@ -27,7 +27,7 @@
#include "lib/crypt_ops/crypto_hkdf.h"
#include "lib/crypt_ops/crypto_util.h"
#include "lib/ctime/di_ops.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "core/crypto/onion_ntor.h"
diff --git a/src/core/include.am b/src/core/include.am
index 1f37044e9a..cd9edc4493 100644
--- a/src/core/include.am
+++ b/src/core/include.am
@@ -34,7 +34,6 @@ LIBTOR_APP_A_SOURCES = \
src/core/or/connection_edge.c \
src/core/or/connection_or.c \
src/core/or/dos.c \
- src/core/or/git_revision.c \
src/core/or/policies.c \
src/core/or/protover.c \
src/core/or/reasons.c \
@@ -135,10 +134,6 @@ else
src_core_libtor_app_testing_a_SOURCES =
endif
-src/core/or/git_revision.$(OBJEXT) \
- src/core/or/src_core_libtor_app_testing_a-git_revision.$(OBJEXT): \
- micro-revision.i
-
AM_CPPFLAGS += -DSHARE_DATADIR="\"$(datadir)\"" \
-DLOCALSTATEDIR="\"$(localstatedir)\"" \
-DBINDIR="\"$(bindir)\""
@@ -190,7 +185,6 @@ noinst_HEADERS += \
src/core/or/entry_connection_st.h \
src/core/or/entry_port_cfg_st.h \
src/core/or/extend_info_st.h \
- src/core/or/git_revision.h \
src/core/or/listener_connection_st.h \
src/core/or/or.h \
src/core/or/or_circuit_st.h \
diff --git a/src/core/mainloop/main.c b/src/core/mainloop/main.c
index c5773ddfc1..048397a2da 100644
--- a/src/core/mainloop/main.c
+++ b/src/core/mainloop/main.c
@@ -116,6 +116,7 @@
#include "lib/sandbox/sandbox.h"
#include "lib/fs/lockfile.h"
#include "lib/net/buffers_net.h"
+#include "lib/net/resolve.h"
#include "lib/tls/tortls.h"
#include "lib/evloop/compat_libevent.h"
#include "lib/encoding/confline.h"
diff --git a/src/core/or/addr_policy_st.h b/src/core/or/addr_policy_st.h
index be3e9d8f01..222a067252 100644
--- a/src/core/or/addr_policy_st.h
+++ b/src/core/or/addr_policy_st.h
@@ -18,7 +18,7 @@ typedef enum {
#define addr_policy_action_bitfield_t ENUM_BF(addr_policy_action_t)
/** A reference-counted address policy rule. */
-typedef struct addr_policy_t {
+struct addr_policy_t {
int refcnt; /**< Reference count */
/** What to do when the policy matches.*/
addr_policy_action_bitfield_t policy_type:2;
@@ -41,6 +41,6 @@ typedef struct addr_policy_t {
tor_addr_t addr;
uint16_t prt_min; /**< Lowest port number to accept/reject. */
uint16_t prt_max; /**< Highest port number to accept/reject. */
-} addr_policy_t;
+};
#endif
diff --git a/src/core/or/connection_edge.c b/src/core/or/connection_edge.c
index 8e8a5e21ca..c51e428000 100644
--- a/src/core/or/connection_edge.c
+++ b/src/core/or/connection_edge.c
@@ -129,6 +129,13 @@
#endif
#endif /* defined(HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H) */
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
#include <net/if.h>
#include <net/pfvar.h>
diff --git a/src/core/or/connection_or.c b/src/core/or/connection_or.c
index 159ee96266..c5ff10f6a3 100644
--- a/src/core/or/connection_or.c
+++ b/src/core/or/connection_or.c
@@ -52,6 +52,7 @@
#include "core/proto/proto_cell.h"
#include "core/or/reasons.h"
#include "core/or/relay.h"
+#include "feature/rend/rendcommon.h"
#include "feature/stats/rephist.h"
#include "feature/relay/router.h"
#include "feature/relay/routerkeys.h"
@@ -1938,10 +1939,13 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
conn->identity_digest);
const int is_authority_fingerprint = router_digest_is_trusted_dir(
conn->identity_digest);
+ const int non_anonymous_mode = rend_non_anonymous_mode_enabled(options);
int severity;
const char *extra_log = "";
- if (server_mode(options)) {
+ /* Relays and Single Onion Services make direct connections using
+ * untrusted authentication keys. */
+ if (server_mode(options) || non_anonymous_mode) {
severity = LOG_PROTOCOL_WARN;
} else {
if (using_hardcoded_fingerprints) {
@@ -1965,8 +1969,8 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
}
log_fn(severity, LD_HANDSHAKE,
- "Tried connecting to router at %s:%d, but RSA identity key was not "
- "as expected: wanted %s + %s but got %s + %s.%s",
+ "Tried connecting to router at %s:%d, but RSA + ed25519 identity "
+ "keys were not as expected: wanted %s + %s but got %s + %s.%s",
conn->base_.address, conn->base_.port,
expected_rsa, expected_ed, seen_rsa, seen_ed, extra_log);
@@ -1983,8 +1987,8 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
}
if (!expected_ed_key && ed_peer_id) {
- log_info(LD_HANDSHAKE, "(we had no Ed25519 ID in mind when we made this "
- "connection.");
+ log_info(LD_HANDSHAKE, "(We had no Ed25519 ID in mind when we made this "
+ "connection.)");
connection_or_set_identity_digest(conn,
(const char*)rsa_peer_id, ed_peer_id);
changed_identity = 1;
diff --git a/src/core/or/or.h b/src/core/or/or.h
index 6edfd21dfb..9aca030c74 100644
--- a/src/core/or/or.h
+++ b/src/core/or/or.h
@@ -47,11 +47,9 @@
#include "lib/log/escape.h"
#include "lib/log/ratelim.h"
#include "lib/log/util_bug.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/net/address.h"
-#include "lib/net/ipv4.h"
-#include "lib/net/ipv6.h"
-#include "lib/net/resolve.h"
+#include "lib/net/inaddr.h"
#include "lib/net/socket.h"
#include "lib/string/compat_ctype.h"
#include "lib/string/compat_string.h"
diff --git a/src/core/or/relay.c b/src/core/or/relay.c
index 32bb69d25f..51084e2a17 100644
--- a/src/core/or/relay.c
+++ b/src/core/or/relay.c
@@ -2005,9 +2005,10 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
}
if (connection_edge_send_command(conn, RELAY_COMMAND_DATA,
- payload, length) < 0 )
+ payload, length) < 0 ) {
/* circuit got marked for close, don't continue, don't need to mark conn */
return 0;
+ }
if (!cpath_layer) { /* non-rendezvous exit */
tor_assert(circ->package_window > 0);
diff --git a/src/core/or/scheduler.c b/src/core/or/scheduler.c
index e19059f0c5..dd028fc785 100644
--- a/src/core/or/scheduler.c
+++ b/src/core/or/scheduler.c
@@ -351,8 +351,8 @@ set_scheduler(void)
/* Finally we notice log if we switched schedulers. We use the type in case
* two schedulers share a scheduler object. */
if (old_scheduler_type != the_scheduler->type) {
- log_notice(LD_CONFIG, "Scheduler type %s has been enabled.",
- get_scheduler_type_string(the_scheduler->type));
+ log_info(LD_CONFIG, "Scheduler type %s has been enabled.",
+ get_scheduler_type_string(the_scheduler->type));
}
}
diff --git a/src/core/or/socks_request_st.h b/src/core/or/socks_request_st.h
index d7b979c3eb..17b668e179 100644
--- a/src/core/or/socks_request_st.h
+++ b/src/core/or/socks_request_st.h
@@ -70,6 +70,8 @@ struct socks_request_t {
/** The negotiated password value if any (for socks5). This value is NOT
* nul-terminated; see passwordlen for its length. */
char *password;
+
+ uint8_t socks5_atyp; /* SOCKS5 address type */
};
#endif
diff --git a/src/core/proto/proto_ext_or.h b/src/core/proto/proto_ext_or.h
index 708a45974b..2ff6ad45ca 100644
--- a/src/core/proto/proto_ext_or.h
+++ b/src/core/proto/proto_ext_or.h
@@ -10,11 +10,11 @@
struct buf_t;
/** A parsed Extended ORPort message. */
-typedef struct ext_or_cmd_t {
+struct ext_or_cmd_t {
uint16_t cmd; /** Command type */
uint16_t len; /** Body length */
char body[FLEXIBLE_ARRAY_MEMBER]; /** Message body */
-} ext_or_cmd_t;
+};
int fetch_ext_or_command_from_buf(struct buf_t *buf,
struct ext_or_cmd_t **out);
diff --git a/src/core/proto/proto_socks.c b/src/core/proto/proto_socks.c
index 6912441472..ccf96f7814 100644
--- a/src/core/proto/proto_socks.c
+++ b/src/core/proto/proto_socks.c
@@ -17,12 +17,28 @@
#include "core/or/socks_request_st.h"
+#include "trunnel/socks5.h"
+
+#define SOCKS_VER_5 0x05 /* First octet of non-auth SOCKS5 messages */
+#define SOCKS_VER_4 0x04 /* SOCKS4 messages */
+#define SOCKS_AUTH 0x01 /* SOCKS5 auth messages */
+
+typedef enum {
+ SOCKS_RESULT_INVALID = -1, /* Message invalid. */
+ SOCKS_RESULT_TRUNCATED = 0, /* Message incomplete/truncated. */
+ SOCKS_RESULT_DONE = 1, /* OK, we're done. */
+ SOCKS_RESULT_MORE_EXPECTED = 2, /* OK, more messages expected. */
+} socks_result_t;
+
static void socks_request_set_socks5_error(socks_request_t *req,
socks5_reply_status_t reason);
-static int parse_socks(const char *data, size_t datalen, socks_request_t *req,
- int log_sockstype, int safe_socks, ssize_t *drain_out,
- size_t *want_length_out);
+static socks_result_t parse_socks(const char *data,
+ size_t datalen,
+ socks_request_t *req,
+ int log_sockstype,
+ int safe_socks,
+ size_t *drain_out);
static int parse_socks_client(const uint8_t *data, size_t datalen,
int state, char **reason,
ssize_t *drain_out);
@@ -86,6 +102,689 @@ socks_request_free_(socks_request_t *req)
tor_free(req);
}
+/**
+ * Parse a single SOCKS4 request from buffer <b>raw_data</b> of length
+ * <b>datalen</b> and update relevant fields of <b>req</b>. If SOCKS4a
+ * request is detected, set <b>*is_socks4a<b> to true. Set <b>*drain_out</b>
+ * to number of bytes we parsed so far.
+ *
+ * Return SOCKS_RESULT_DONE if parsing succeeded, SOCKS_RESULT_INVALID if
+ * parsing failed because of invalid input or SOCKS_RESULT_TRUNCATED if it
+ * failed due to incomplete (truncated) input.
+ */
+static socks_result_t
+parse_socks4_request(const uint8_t *raw_data, socks_request_t *req,
+ size_t datalen, int *is_socks4a, size_t *drain_out)
+{
+ // http://ss5.sourceforge.net/socks4.protocol.txt
+ // http://ss5.sourceforge.net/socks4A.protocol.txt
+ socks_result_t res = SOCKS_RESULT_DONE;
+ tor_addr_t destaddr;
+
+ tor_assert(is_socks4a);
+ tor_assert(drain_out);
+
+ *is_socks4a = 0;
+ *drain_out = 0;
+
+ req->socks_version = SOCKS_VER_4;
+
+ socks4_client_request_t *trunnel_req;
+
+ ssize_t parsed =
+ socks4_client_request_parse(&trunnel_req, raw_data, datalen);
+
+ if (parsed == -1) {
+ log_warn(LD_APP, "socks4: parsing failed - invalid request.");
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ } else if (parsed == -2) {
+ res = SOCKS_RESULT_TRUNCATED;
+ if (datalen >= MAX_SOCKS_MESSAGE_LEN) {
+ log_warn(LD_APP, "socks4: parsing failed - invalid request.");
+ res = SOCKS_RESULT_INVALID;
+ }
+ goto end;
+ }
+
+ tor_assert(parsed >= 0);
+ *drain_out = (size_t)parsed;
+
+ uint8_t command = socks4_client_request_get_command(trunnel_req);
+ req->command = command;
+
+ req->port = socks4_client_request_get_port(trunnel_req);
+ uint32_t dest_ip = socks4_client_request_get_addr(trunnel_req);
+
+ if ((!req->port && req->command != SOCKS_COMMAND_RESOLVE) ||
+ dest_ip == 0) {
+ log_warn(LD_APP, "socks4: Port or DestIP is zero. Rejecting.");
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ }
+
+ *is_socks4a = (dest_ip >> 8) == 0;
+
+ const char *username = socks4_client_request_get_username(trunnel_req);
+ const size_t usernamelen = username ? strlen(username) : 0;
+ if (username && usernamelen) {
+ if (usernamelen > MAX_SOCKS_MESSAGE_LEN) {
+ log_warn(LD_APP, "Socks4 user name too long; rejecting.");
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ }
+
+ tor_free(req->username);
+ req->got_auth = 1;
+ req->username = tor_strdup(username);
+ req->usernamelen = usernamelen;
+ }
+
+ if (*is_socks4a) {
+ // We cannot rely on trunnel here, as we want to detect if
+ // we have abnormally long hostname field.
+ const char *hostname = (char *)raw_data + SOCKS4_NETWORK_LEN +
+ usernamelen + 1;
+ size_t hostname_len = (char *)raw_data + datalen - hostname;
+
+ if (hostname_len <= sizeof(req->address)) {
+ const char *trunnel_hostname =
+ socks4_client_request_get_socks4a_addr_hostname(trunnel_req);
+
+ if (trunnel_hostname)
+ strlcpy(req->address, trunnel_hostname, sizeof(req->address));
+ } else {
+ log_warn(LD_APP, "socks4: Destaddr too long. Rejecting.");
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ }
+ } else {
+ tor_addr_from_ipv4h(&destaddr, dest_ip);
+
+ if (!tor_addr_to_str(req->address, &destaddr,
+ MAX_SOCKS_ADDR_LEN, 0)) {
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ }
+ }
+
+ end:
+ socks4_client_request_free(trunnel_req);
+
+ return res;
+}
+
+/**
+ * Validate SOCKS4/4a related fields in <b>req</b>. Expect SOCKS4a
+ * if <b>is_socks4a</b> is true. If <b>log_sockstype</b> is true,
+ * log a notice about possible DNS leaks on local system. If
+ * <b>safe_socks</b> is true, reject insecure usage of SOCKS
+ * protocol.
+ *
+ * Return SOCKS_RESULT_DONE if validation passed or
+ * SOCKS_RESULT_INVALID if it failed.
+ */
+static socks_result_t
+process_socks4_request(const socks_request_t *req, int is_socks4a,
+ int log_sockstype, int safe_socks)
+{
+ if (is_socks4a && !addressmap_have_mapping(req->address, 0)) {
+ log_unsafe_socks_warning(4, req->address, req->port, safe_socks);
+
+ if (safe_socks)
+ return SOCKS_RESULT_INVALID;
+ }
+
+ if (req->command != SOCKS_COMMAND_CONNECT &&
+ req->command != SOCKS_COMMAND_RESOLVE) {
+ /* not a connect or resolve? we don't support it. (No resolve_ptr with
+ * socks4.) */
+ log_warn(LD_APP, "socks4: command %d not recognized. Rejecting.",
+ req->command);
+ return SOCKS_RESULT_INVALID;
+ }
+
+ if (is_socks4a) {
+ if (log_sockstype)
+ log_notice(LD_APP,
+ "Your application (using socks4a to port %d) instructed "
+ "Tor to take care of the DNS resolution itself if "
+ "necessary. This is good.", req->port);
+ }
+
+ if (!string_is_valid_dest(req->address)) {
+ log_warn(LD_PROTOCOL,
+ "Your application (using socks4 to port %d) gave Tor "
+ "a malformed hostname: %s. Rejecting the connection.",
+ req->port, escaped_safe_str_client(req->address));
+ return SOCKS_RESULT_INVALID;
+ }
+
+ return SOCKS_RESULT_DONE;
+}
+
+/** Parse a single SOCKS5 version identifier/method selection message
+ * from buffer <b>raw_data</b> (of length <b>datalen</b>). Update
+ * relevant fields of <b>req</b> (if any). Set <b>*have_user_pass</b> to
+ * true if username/password method is found. Set <b>*have_no_auth</b>
+ * if no-auth method is found. Set <b>*drain_out</b> to number of bytes
+ * we parsed so far.
+ *
+ * Return SOCKS_RESULT_DONE if parsing succeeded, SOCKS_RESULT_INVALID if
+ * parsing failed because of invalid input or SOCKS_RESULT_TRUNCATED if it
+ * failed due to incomplete (truncated) input.
+ */
+static socks_result_t
+parse_socks5_methods_request(const uint8_t *raw_data, socks_request_t *req,
+ size_t datalen, int *have_user_pass,
+ int *have_no_auth, size_t *drain_out)
+{
+ socks_result_t res = SOCKS_RESULT_DONE;
+ socks5_client_version_t *trunnel_req;
+
+ ssize_t parsed = socks5_client_version_parse(&trunnel_req, raw_data,
+ datalen);
+
+ (void)req;
+
+ tor_assert(have_no_auth);
+ tor_assert(have_user_pass);
+ tor_assert(drain_out);
+
+ *drain_out = 0;
+
+ if (parsed == -1) {
+ log_warn(LD_APP, "socks5: parsing failed - invalid version "
+ "id/method selection message.");
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ } else if (parsed == -2) {
+ res = SOCKS_RESULT_TRUNCATED;
+ if (datalen > MAX_SOCKS_MESSAGE_LEN) {
+ log_warn(LD_APP, "socks5: parsing failed - invalid version "
+ "id/method selection message.");
+ res = SOCKS_RESULT_INVALID;
+ }
+ goto end;
+ }
+
+ tor_assert(parsed >= 0);
+ *drain_out = (size_t)parsed;
+
+ size_t n_methods = (size_t)socks5_client_version_get_n_methods(trunnel_req);
+ if (n_methods == 0) {
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ }
+
+ *have_no_auth = 0;
+ *have_user_pass = 0;
+
+ for (size_t i = 0; i < n_methods; i++) {
+ uint8_t method = socks5_client_version_get_methods(trunnel_req,
+ i);
+
+ if (method == SOCKS_USER_PASS) {
+ *have_user_pass = 1;
+ } else if (method == SOCKS_NO_AUTH) {
+ *have_no_auth = 1;
+ }
+ }
+
+ end:
+ socks5_client_version_free(trunnel_req);
+
+ return res;
+}
+
+/**
+ * Validate and respond to version identifier/method selection message
+ * we parsed in parse_socks5_methods_request (corresponding to <b>req</b>
+ * and having user/pass method if <b>have_user_pass</b> is true, no-auth
+ * method if <b>have_no_auth</b> is true). Set <b>req->reply</b> to
+ * an appropriate response (in SOCKS5 wire format).
+ *
+ * On success, return SOCKS_RESULT_DONE. On failure, return
+ * SOCKS_RESULT_INVALID.
+ */
+static socks_result_t
+process_socks5_methods_request(socks_request_t *req, int have_user_pass,
+ int have_no_auth)
+{
+ socks_result_t res = SOCKS_RESULT_DONE;
+ socks5_server_method_t *trunnel_resp = socks5_server_method_new();
+
+ socks5_server_method_set_version(trunnel_resp, SOCKS_VER_5);
+
+ if (have_user_pass && !(have_no_auth && req->socks_prefer_no_auth)) {
+ req->auth_type = SOCKS_USER_PASS;
+ socks5_server_method_set_method(trunnel_resp, SOCKS_USER_PASS);
+
+ req->socks_version = SOCKS_VER_5;
+ // FIXME: come up with better way to remember
+ // that we negotiated auth
+
+ log_debug(LD_APP,"socks5: accepted method 2 (username/password)");
+ } else if (have_no_auth) {
+ req->auth_type = SOCKS_NO_AUTH;
+ socks5_server_method_set_method(trunnel_resp, SOCKS_NO_AUTH);
+
+ req->socks_version = SOCKS_VER_5;
+
+ log_debug(LD_APP,"socks5: accepted method 0 (no authentication)");
+ } else {
+ log_warn(LD_APP,
+ "socks5: offered methods don't include 'no auth' or "
+ "username/password. Rejecting.");
+ socks5_server_method_set_method(trunnel_resp, 0xFF); // reject all
+ res = SOCKS_RESULT_INVALID;
+ }
+
+ const char *errmsg = socks5_server_method_check(trunnel_resp);
+ if (errmsg) {
+ log_warn(LD_APP, "socks5: method selection validation failed: %s",
+ errmsg);
+ res = SOCKS_RESULT_INVALID;
+ } else {
+ ssize_t encoded =
+ socks5_server_method_encode(req->reply, sizeof(req->reply),
+ trunnel_resp);
+
+ if (encoded < 0) {
+ log_warn(LD_APP, "socks5: method selection encoding failed");
+ res = SOCKS_RESULT_INVALID;
+ } else {
+ req->replylen = (size_t)encoded;
+ }
+ }
+
+ socks5_server_method_free(trunnel_resp);
+ return res;
+}
+
+/**
+ * Parse SOCKS5/RFC1929 username/password request from buffer
+ * <b>raw_data</b> of length <b>datalen</b> and update relevant
+ * fields of <b>req</b>. Set <b>*drain_out</b> to number of bytes
+ * we parsed so far.
+ *
+ * Return SOCKS_RESULT_DONE if parsing succeeded, SOCKS_RESULT_INVALID if
+ * parsing failed because of invalid input or SOCKS_RESULT_TRUNCATED if it
+ * failed due to incomplete (truncated) input.
+ */
+static socks_result_t
+parse_socks5_userpass_auth(const uint8_t *raw_data, socks_request_t *req,
+ size_t datalen, size_t *drain_out)
+{
+ socks_result_t res = SOCKS_RESULT_DONE;
+ socks5_client_userpass_auth_t *trunnel_req = NULL;
+ ssize_t parsed = socks5_client_userpass_auth_parse(&trunnel_req, raw_data,
+ datalen);
+ tor_assert(drain_out);
+ *drain_out = 0;
+
+ if (parsed == -1) {
+ log_warn(LD_APP, "socks5: parsing failed - invalid user/pass "
+ "authentication message.");
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ } else if (parsed == -2) {
+ res = SOCKS_RESULT_TRUNCATED;
+ goto end;
+ }
+
+ tor_assert(parsed >= 0);
+ *drain_out = (size_t)parsed;
+
+ uint8_t usernamelen =
+ socks5_client_userpass_auth_get_username_len(trunnel_req);
+ uint8_t passwordlen =
+ socks5_client_userpass_auth_get_passwd_len(trunnel_req);
+ const char *username =
+ socks5_client_userpass_auth_getconstarray_username(trunnel_req);
+ const char *password =
+ socks5_client_userpass_auth_getconstarray_passwd(trunnel_req);
+
+ if (usernamelen && username) {
+ tor_free(req->username);
+ req->username = tor_memdup_nulterm(username, usernamelen);
+ req->usernamelen = usernamelen;
+
+ req->got_auth = 1;
+ }
+
+ if (passwordlen && password) {
+ tor_free(req->password);
+ req->password = tor_memdup_nulterm(password, passwordlen);
+ req->passwordlen = passwordlen;
+
+ req->got_auth = 1;
+ }
+
+ end:
+ socks5_client_userpass_auth_free(trunnel_req);
+ return res;
+}
+
+/**
+ * Validate and respond to SOCKS5 username/password request we
+ * parsed in parse_socks5_userpass_auth (corresponding to <b>req</b>.
+ * Set <b>req->reply</b> to appropriate responsed. Return
+ * SOCKS_RESULT_DONE on success or SOCKS_RESULT_INVALID on failure.
+ */
+static socks_result_t
+process_socks5_userpass_auth(socks_request_t *req)
+{
+ socks_result_t res = SOCKS_RESULT_DONE;
+ socks5_server_userpass_auth_t *trunnel_resp =
+ socks5_server_userpass_auth_new();
+
+ if (req->socks_version != SOCKS_VER_5) {
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ }
+
+ if (req->auth_type != SOCKS_USER_PASS &&
+ req->auth_type != SOCKS_NO_AUTH) {
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ }
+
+ socks5_server_userpass_auth_set_version(trunnel_resp, SOCKS_AUTH);
+ socks5_server_userpass_auth_set_status(trunnel_resp, 0); // auth OK
+
+ const char *errmsg = socks5_server_userpass_auth_check(trunnel_resp);
+ if (errmsg) {
+ log_warn(LD_APP, "socks5: server userpass auth validation failed: %s",
+ errmsg);
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ }
+
+ ssize_t encoded = socks5_server_userpass_auth_encode(req->reply,
+ sizeof(req->reply),
+ trunnel_resp);
+
+ if (encoded < 0) {
+ log_warn(LD_APP, "socks5: server userpass auth encoding failed");
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ }
+
+ req->replylen = (size_t)encoded;
+
+ end:
+ socks5_server_userpass_auth_free(trunnel_resp);
+ return res;
+}
+
+/**
+ * Parse a single SOCKS5 client request (RFC 1928 section 4) from buffer
+ * <b>raw_data</b> of length <b>datalen</b> and update relevant field of
+ * <b>req</b>. Set <b>*drain_out</b> to number of bytes we parsed so far.
+ *
+ * Return SOCKS_RESULT_DONE if parsing succeeded, SOCKS_RESULT_INVALID if
+ * parsing failed because of invalid input or SOCKS_RESULT_TRUNCATED if it
+ * failed due to incomplete (truncated) input.
+ */
+static socks_result_t
+parse_socks5_client_request(const uint8_t *raw_data, socks_request_t *req,
+ size_t datalen, size_t *drain_out)
+{
+ socks_result_t res = SOCKS_RESULT_DONE;
+ tor_addr_t destaddr;
+ socks5_client_request_t *trunnel_req = NULL;
+ ssize_t parsed =
+ socks5_client_request_parse(&trunnel_req, raw_data, datalen);
+ if (parsed == -1) {
+ log_warn(LD_APP, "socks5: parsing failed - invalid client request");
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ } else if (parsed == -2) {
+ res = SOCKS_RESULT_TRUNCATED;
+ goto end;
+ }
+
+ tor_assert(parsed >= 0);
+ *drain_out = (size_t)parsed;
+
+ if (socks5_client_request_get_version(trunnel_req) != 5) {
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ }
+
+ req->command = socks5_client_request_get_command(trunnel_req);
+
+ req->port = socks5_client_request_get_dest_port(trunnel_req);
+
+ uint8_t atype = socks5_client_request_get_atype(trunnel_req);
+ req->socks5_atyp = atype;
+
+ switch (atype) {
+ case 1: {
+ uint32_t ipv4 = socks5_client_request_get_dest_addr_ipv4(trunnel_req);
+ tor_addr_from_ipv4h(&destaddr, ipv4);
+
+ tor_addr_to_str(req->address, &destaddr, sizeof(req->address), 1);
+ } break;
+ case 3: {
+ const struct domainname_st *dns_name =
+ socks5_client_request_getconst_dest_addr_domainname(trunnel_req);
+
+ const char *hostname = domainname_getconstarray_name(dns_name);
+
+ strlcpy(req->address, hostname, sizeof(req->address));
+ } break;
+ case 4: {
+ const char *ipv6 =
+ (const char *)socks5_client_request_getarray_dest_addr_ipv6(
+ trunnel_req);
+ tor_addr_from_ipv6_bytes(&destaddr, ipv6);
+
+ tor_addr_to_str(req->address, &destaddr, sizeof(req->address), 1);
+ } break;
+ default: {
+ res = -1;
+ } break;
+ }
+
+ end:
+ socks5_client_request_free(trunnel_req);
+ return res;
+}
+
+/**
+ * Validate and respond to SOCKS5 request we parsed in
+ * parse_socks5_client_request (corresponding to <b>req</b>.
+ * Write appropriate response to <b>req->reply</b> (in
+ * SOCKS5 wire format). If <b>log_sockstype</b> is true, log a
+ * notice about possible DNS leaks on local system. If
+ * <b>safe_socks</b> is true, disallow insecure usage of SOCKS
+ * protocol. Return SOCKS_RESULT_DONE on success or
+ * SOCKS_RESULT_INVALID on failure.
+ */
+static socks_result_t
+process_socks5_client_request(socks_request_t *req,
+ int log_sockstype,
+ int safe_socks)
+{
+ socks_result_t res = SOCKS_RESULT_DONE;
+
+ if (req->command != SOCKS_COMMAND_CONNECT &&
+ req->command != SOCKS_COMMAND_RESOLVE &&
+ req->command != SOCKS_COMMAND_RESOLVE_PTR) {
+ socks_request_set_socks5_error(req,SOCKS5_COMMAND_NOT_SUPPORTED);
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ }
+
+ if (req->command == SOCKS_COMMAND_RESOLVE_PTR &&
+ !string_is_valid_ipv4_address(req->address) &&
+ !string_is_valid_ipv6_address(req->address)) {
+ socks_request_set_socks5_error(req, SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED);
+ log_warn(LD_APP, "socks5 received RESOLVE_PTR command with "
+ "hostname type. Rejecting.");
+
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ }
+
+ if (!string_is_valid_dest(req->address)) {
+ socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
+
+ log_warn(LD_PROTOCOL,
+ "Your application (using socks5 to port %d) gave Tor "
+ "a malformed hostname: %s. Rejecting the connection.",
+ req->port, escaped_safe_str_client(req->address));
+
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ }
+
+ if (req->socks5_atyp == 1 || req->socks5_atyp == 4) {
+ if (req->command != SOCKS_COMMAND_RESOLVE_PTR &&
+ !addressmap_have_mapping(req->address,0)) {
+ log_unsafe_socks_warning(5, req->address, req->port, safe_socks);
+ if (safe_socks) {
+ socks_request_set_socks5_error(req, SOCKS5_NOT_ALLOWED);
+ res = SOCKS_RESULT_INVALID;
+ goto end;
+ }
+ }
+ }
+
+ if (log_sockstype)
+ log_notice(LD_APP,
+ "Your application (using socks5 to port %d) instructed "
+ "Tor to take care of the DNS resolution itself if "
+ "necessary. This is good.", req->port);
+
+ end:
+ return res;
+}
+
+/**
+ * Handle (parse, validate, process, respond) a single SOCKS
+ * message in buffer <b>raw_data</b> of length <b>datalen</b>.
+ * Update relevant fields of <b>req</b>. If <b>log_sockstype</b>
+ * is true, log a warning about possible DNS leaks on local
+ * system. If <b>safe_socks</b> is true, disallow insecure
+ * usage of SOCKS protocol. Set <b>*drain_out</b> to number
+ * of bytes in <b>raw_data</b> that we processed so far and
+ * that can be safely drained from buffer.
+ *
+ * Return:
+ * - SOCKS_RESULT_DONE if succeeded and not expecting further
+ * messages from client.
+ * - SOCKS_RESULT_INVALID if any of the steps failed due to
+ * request being invalid or unexpected given current state.
+ * - SOCKS_RESULT_TRUNCATED if we do not found an expected
+ * SOCKS message in its entirety (more stuff has to arrive
+ * from client).
+ * - SOCKS_RESULT_MORE_EXPECTED if we handled current message
+ * successfully, but we expect more messages from the
+ * client.
+ */
+static socks_result_t
+handle_socks_message(const uint8_t *raw_data, size_t datalen,
+ socks_request_t *req, int log_sockstype,
+ int safe_socks, size_t *drain_out)
+{
+ socks_result_t res = SOCKS_RESULT_DONE;
+
+ uint8_t socks_version = raw_data[0];
+
+ if (socks_version == SOCKS_AUTH)
+ socks_version = SOCKS_VER_5; // SOCKS5 username/pass subnegotiation
+
+ if (socks_version == SOCKS_VER_4) {
+ if (datalen < SOCKS4_NETWORK_LEN) {
+ res = 0;
+ goto end;
+ }
+
+ int is_socks4a = 0;
+ res = parse_socks4_request((const uint8_t *)raw_data, req, datalen,
+ &is_socks4a, drain_out);
+
+ if (res != SOCKS_RESULT_DONE) {
+ goto end;
+ }
+
+ res = process_socks4_request(req, is_socks4a,log_sockstype,
+ safe_socks);
+
+ if (res != SOCKS_RESULT_DONE) {
+ goto end;
+ }
+
+ goto end;
+ } else if (socks_version == SOCKS_VER_5) {
+ if (datalen < 2) { /* version and another byte */
+ res = 0;
+ goto end;
+ }
+ /* RFC1929 SOCKS5 username/password subnegotiation. */
+ if (!req->got_auth && (raw_data[0] == 1 ||
+ req->auth_type == SOCKS_USER_PASS)) {
+ res = parse_socks5_userpass_auth(raw_data, req, datalen,
+ drain_out);
+
+ if (res != SOCKS_RESULT_DONE) {
+ goto end;
+ }
+
+ res = process_socks5_userpass_auth(req);
+ if (res != SOCKS_RESULT_DONE) {
+ goto end;
+ }
+
+ res = SOCKS_RESULT_MORE_EXPECTED;
+ goto end;
+ } else if (req->socks_version != SOCKS_VER_5) {
+ int have_user_pass, have_no_auth;
+ res = parse_socks5_methods_request(raw_data, req, datalen,
+ &have_user_pass,
+ &have_no_auth,
+ drain_out);
+
+ if (res != SOCKS_RESULT_DONE) {
+ goto end;
+ }
+
+ res = process_socks5_methods_request(req, have_user_pass,
+ have_no_auth);
+
+ if (res != SOCKS_RESULT_DONE) {
+ goto end;
+ }
+
+ res = SOCKS_RESULT_MORE_EXPECTED;
+ goto end;
+ } else {
+ res = parse_socks5_client_request(raw_data, req,
+ datalen, drain_out);
+ if (res != SOCKS_RESULT_DONE) {
+ socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
+ goto end;
+ }
+
+ res = process_socks5_client_request(req, log_sockstype,
+ safe_socks);
+
+ if (res != SOCKS_RESULT_DONE) {
+ goto end;
+ }
+ }
+ } else {
+ *drain_out = datalen;
+ res = SOCKS_RESULT_INVALID;
+ }
+
+ end:
+ return res;
+}
+
/** There is a (possibly incomplete) socks handshake on <b>buf</b>, of one
* of the forms
* - socks4: "socksheader username\\0"
@@ -115,32 +814,50 @@ int
fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
int log_sockstype, int safe_socks)
{
- int res;
- ssize_t n_drain;
- size_t want_length = 128;
+ int res = 0;
+ size_t datalen = buf_datalen(buf);
+ size_t n_drain;
const char *head = NULL;
- size_t datalen = 0;
+ socks_result_t socks_res;
+ size_t n_pullup;
- if (buf_datalen(buf) < 2) /* version and another byte */
- return 0;
+ if (buf_datalen(buf) < 2) { /* version and another byte */
+ res = 0;
+ goto end;
+ }
do {
n_drain = 0;
- buf_pullup(buf, want_length, &head, &datalen);
+ n_pullup = MIN(MAX_SOCKS_MESSAGE_LEN, buf_datalen(buf));
+ buf_pullup(buf, n_pullup, &head, &datalen);
tor_assert(head && datalen >= 2);
- want_length = 0;
- res = parse_socks(head, datalen, req, log_sockstype,
- safe_socks, &n_drain, &want_length);
+ socks_res = parse_socks(head, datalen, req, log_sockstype,
+ safe_socks, &n_drain);
- if (n_drain < 0)
+ if (socks_res == SOCKS_RESULT_INVALID)
buf_clear(buf);
- else if (n_drain > 0)
+ else if (socks_res != SOCKS_RESULT_TRUNCATED && n_drain > 0)
buf_drain(buf, n_drain);
- } while (res == 0 && head && want_length < buf_datalen(buf) &&
- buf_datalen(buf) >= 2);
+ switch (socks_res) {
+ case SOCKS_RESULT_INVALID:
+ res = -1;
+ break;
+ case SOCKS_RESULT_DONE:
+ res = 1;
+ break;
+ case SOCKS_RESULT_TRUNCATED:
+ if (datalen == n_pullup)
+ return 0;
+ /* FALLTHRU */
+ case SOCKS_RESULT_MORE_EXPECTED:
+ res = 0;
+ break;
+ }
+ } while (res == 0 && head && buf_datalen(buf) >= 2);
+ end:
return res;
}
@@ -151,12 +868,31 @@ static void
socks_request_set_socks5_error(socks_request_t *req,
socks5_reply_status_t reason)
{
- req->replylen = 10;
- memset(req->reply,0,10);
+ socks5_server_reply_t *trunnel_resp = socks5_server_reply_new();
+
+ socks5_server_reply_set_version(trunnel_resp, SOCKS_VER_5);
+ socks5_server_reply_set_reply(trunnel_resp, reason);
+ socks5_server_reply_set_atype(trunnel_resp, 0x01);
+
+ const char *errmsg = socks5_server_reply_check(trunnel_resp);
+ if (errmsg) {
+ log_warn(LD_APP, "socks5: reply validation failed: %s",
+ errmsg);
+ goto end;
+ }
+
+ ssize_t encoded = socks5_server_reply_encode(req->reply,
+ sizeof(req->reply),
+ trunnel_resp);
+ if (encoded < 0) {
+ log_warn(LD_APP, "socks5: reply encoding failed: %d",
+ (int)encoded);
+ } else {
+ req->replylen = (size_t)encoded;
+ }
- req->reply[0] = 0x05; // VER field.
- req->reply[1] = reason; // REP field.
- req->reply[3] = 0x01; // ATYP field.
+ end:
+ socks5_server_reply_free(trunnel_resp);
}
static const char SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG[] =
@@ -194,350 +930,24 @@ static const char SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG[] =
* we'd like to see in the input buffer, if they're available. */
static int
parse_socks(const char *data, size_t datalen, socks_request_t *req,
- int log_sockstype, int safe_socks, ssize_t *drain_out,
- size_t *want_length_out)
+ int log_sockstype, int safe_socks, size_t *drain_out)
{
- unsigned int len;
- char tmpbuf[TOR_ADDR_BUF_LEN+1];
- tor_addr_t destaddr;
- uint32_t destip;
- uint8_t socksver;
- char *next, *startaddr;
- unsigned char usernamelen, passlen;
- struct in_addr in;
+ uint8_t first_octet;
if (datalen < 2) {
/* We always need at least 2 bytes. */
- *want_length_out = 2;
return 0;
}
- if (req->socks_version == 5 && !req->got_auth) {
- /* See if we have received authentication. Strictly speaking, we should
- also check whether we actually negotiated username/password
- authentication. But some broken clients will send us authentication
- even if we negotiated SOCKS_NO_AUTH. */
- if (*data == 1) { /* username/pass version 1 */
- /* Format is: authversion [1 byte] == 1
- usernamelen [1 byte]
- username [usernamelen bytes]
- passlen [1 byte]
- password [passlen bytes] */
- usernamelen = (unsigned char)*(data + 1);
- if (datalen < 2u + usernamelen + 1u) {
- *want_length_out = 2u + usernamelen + 1u;
- return 0;
- }
- passlen = (unsigned char)*(data + 2u + usernamelen);
- if (datalen < 2u + usernamelen + 1u + passlen) {
- *want_length_out = 2u + usernamelen + 1u + passlen;
- return 0;
- }
- req->replylen = 2; /* 2 bytes of response */
- req->reply[0] = 1; /* authversion == 1 */
- req->reply[1] = 0; /* authentication successful */
- log_debug(LD_APP,
- "socks5: Accepted username/password without checking.");
- if (usernamelen) {
- req->username = tor_memdup(data+2u, usernamelen);
- req->usernamelen = usernamelen;
- }
- if (passlen) {
- req->password = tor_memdup(data+3u+usernamelen, passlen);
- req->passwordlen = passlen;
- }
- *drain_out = 2u + usernamelen + 1u + passlen;
- req->got_auth = 1;
- *want_length_out = 7; /* Minimal socks5 command. */
- return 0;
- } else if (req->auth_type == SOCKS_USER_PASS) {
- /* unknown version byte */
- log_warn(LD_APP, "Socks5 username/password version %d not recognized; "
- "rejecting.", (int)*data);
- return -1;
- }
- }
-
- socksver = *data;
-
- switch (socksver) { /* which version of socks? */
- case 5: /* socks5 */
-
- if (req->socks_version != 5) { /* we need to negotiate a method */
- unsigned char nummethods = (unsigned char)*(data+1);
- int have_user_pass, have_no_auth;
- int r=0;
- tor_assert(!req->socks_version);
- if (datalen < 2u+nummethods) {
- *want_length_out = 2u+nummethods;
- return 0;
- }
- if (!nummethods)
- return -1;
- req->replylen = 2; /* 2 bytes of response */
- req->reply[0] = 5; /* socks5 reply */
- have_user_pass = (memchr(data+2, SOCKS_USER_PASS, nummethods) !=NULL);
- have_no_auth = (memchr(data+2, SOCKS_NO_AUTH, nummethods) !=NULL);
- if (have_user_pass && !(have_no_auth && req->socks_prefer_no_auth)) {
- req->auth_type = SOCKS_USER_PASS;
- req->reply[1] = SOCKS_USER_PASS; /* tell client to use "user/pass"
- auth method */
- req->socks_version = 5; /* remember we've already negotiated auth */
- log_debug(LD_APP,"socks5: accepted method 2 (username/password)");
- r=0;
- } else if (have_no_auth) {
- req->reply[1] = SOCKS_NO_AUTH; /* tell client to use "none" auth
- method */
- req->socks_version = 5; /* remember we've already negotiated auth */
- log_debug(LD_APP,"socks5: accepted method 0 (no authentication)");
- r=0;
- } else {
- log_warn(LD_APP,
- "socks5: offered methods don't include 'no auth' or "
- "username/password. Rejecting.");
- req->reply[1] = '\xFF'; /* reject all methods */
- r=-1;
- }
- /* Remove packet from buf. Some SOCKS clients will have sent extra
- * junk at this point; let's hope it's an authentication message. */
- *drain_out = 2u + nummethods;
-
- return r;
- }
- if (req->auth_type != SOCKS_NO_AUTH && !req->got_auth) {
- log_warn(LD_APP,
- "socks5: negotiated authentication, but none provided");
- return -1;
- }
- /* we know the method; read in the request */
- log_debug(LD_APP,"socks5: checking request");
- if (datalen < 7) {/* basic info plus >=1 for addr plus 2 for port */
- *want_length_out = 7;
- return 0; /* not yet */
- }
- req->command = (unsigned char) *(data+1);
- if (req->command != SOCKS_COMMAND_CONNECT &&
- req->command != SOCKS_COMMAND_RESOLVE &&
- req->command != SOCKS_COMMAND_RESOLVE_PTR) {
- /* not a connect or resolve or a resolve_ptr? we don't support it. */
- socks_request_set_socks5_error(req,SOCKS5_COMMAND_NOT_SUPPORTED);
-
- log_warn(LD_APP,"socks5: command %d not recognized. Rejecting.",
- req->command);
- return -1;
- }
- switch (*(data+3)) { /* address type */
- case 1: /* IPv4 address */
- case 4: /* IPv6 address */ {
- const int is_v6 = *(data+3) == 4;
- const unsigned addrlen = is_v6 ? 16 : 4;
- log_debug(LD_APP,"socks5: ipv4 address type");
- if (datalen < 6+addrlen) {/* ip/port there? */
- *want_length_out = 6+addrlen;
- return 0; /* not yet */
- }
-
- if (is_v6)
- tor_addr_from_ipv6_bytes(&destaddr, data+4);
- else
- tor_addr_from_ipv4n(&destaddr, get_uint32(data+4));
-
- tor_addr_to_str(tmpbuf, &destaddr, sizeof(tmpbuf), 1);
-
- if (BUG(strlen(tmpbuf)+1 > MAX_SOCKS_ADDR_LEN)) {
- /* LCOV_EXCL_START -- This branch is unreachable, given the
- * size of tmpbuf and the actual value of MAX_SOCKS_ADDR_LEN */
- socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
- log_warn(LD_APP,
- "socks5 IP takes %d bytes, which doesn't fit in %d. "
- "Rejecting.",
- (int)strlen(tmpbuf)+1,(int)MAX_SOCKS_ADDR_LEN);
- return -1;
- /* LCOV_EXCL_STOP */
- }
- strlcpy(req->address,tmpbuf,sizeof(req->address));
- req->port = ntohs(get_uint16(data+4+addrlen));
- *drain_out = 6+addrlen;
- if (req->command != SOCKS_COMMAND_RESOLVE_PTR &&
- !addressmap_have_mapping(req->address,0)) {
- log_unsafe_socks_warning(5, req->address, req->port, safe_socks);
- if (safe_socks) {
- socks_request_set_socks5_error(req, SOCKS5_NOT_ALLOWED);
- return -1;
- }
- }
- return 1;
- }
- case 3: /* fqdn */
- log_debug(LD_APP,"socks5: fqdn address type");
- if (req->command == SOCKS_COMMAND_RESOLVE_PTR) {
- socks_request_set_socks5_error(req,
- SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED);
- log_warn(LD_APP, "socks5 received RESOLVE_PTR command with "
- "hostname type. Rejecting.");
- return -1;
- }
- len = (unsigned char)*(data+4);
- if (datalen < 7+len) { /* addr/port there? */
- *want_length_out = 7+len;
- return 0; /* not yet */
- }
- if (BUG(len+1 > MAX_SOCKS_ADDR_LEN)) {
- /* LCOV_EXCL_START -- unreachable, since len is at most 255,
- * and MAX_SOCKS_ADDR_LEN is 256. */
- socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
- log_warn(LD_APP,
- "socks5 hostname is %d bytes, which doesn't fit in "
- "%d. Rejecting.", len+1,MAX_SOCKS_ADDR_LEN);
- return -1;
- /* LCOV_EXCL_STOP */
- }
- memcpy(req->address,data+5,len);
- req->address[len] = 0;
- req->port = ntohs(get_uint16(data+5+len));
- *drain_out = 5+len+2;
-
- if (!string_is_valid_dest(req->address)) {
- socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
-
- log_warn(LD_PROTOCOL,
- "Your application (using socks5 to port %d) gave Tor "
- "a malformed hostname: %s. Rejecting the connection.",
- req->port, escaped_safe_str_client(req->address));
- return -1;
- }
- if (log_sockstype)
- log_notice(LD_APP,
- "Your application (using socks5 to port %d) instructed "
- "Tor to take care of the DNS resolution itself if "
- "necessary. This is good.", req->port);
- return 1;
- default: /* unsupported */
- socks_request_set_socks5_error(req,
- SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED);
- log_warn(LD_APP,"socks5: unsupported address type %d. Rejecting.",
- (int) *(data+3));
- return -1;
- }
- tor_assert(0);
- break;
- case 4: { /* socks4 */
- enum {socks4, socks4a} socks4_prot = socks4a;
- const char *authstart, *authend;
- /* http://ss5.sourceforge.net/socks4.protocol.txt */
- /* http://ss5.sourceforge.net/socks4A.protocol.txt */
-
- req->socks_version = 4;
- if (datalen < SOCKS4_NETWORK_LEN) {/* basic info available? */
- *want_length_out = SOCKS4_NETWORK_LEN;
- return 0; /* not yet */
- }
- // buf_pullup(buf, 1280);
- req->command = (unsigned char) *(data+1);
- if (req->command != SOCKS_COMMAND_CONNECT &&
- req->command != SOCKS_COMMAND_RESOLVE) {
- /* not a connect or resolve? we don't support it. (No resolve_ptr with
- * socks4.) */
- log_warn(LD_APP,"socks4: command %d not recognized. Rejecting.",
- req->command);
- return -1;
- }
-
- req->port = ntohs(get_uint16(data+2));
- destip = ntohl(get_uint32(data+4));
- if ((!req->port && req->command!=SOCKS_COMMAND_RESOLVE) || !destip) {
- log_warn(LD_APP,"socks4: Port or DestIP is zero. Rejecting.");
- return -1;
- }
- if (destip >> 8) {
- log_debug(LD_APP,"socks4: destip not in form 0.0.0.x.");
- in.s_addr = htonl(destip);
- tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
- if (BUG(strlen(tmpbuf)+1 > MAX_SOCKS_ADDR_LEN)) {
- /* LCOV_EXCL_START -- This branch is unreachable, given the
- * size of tmpbuf and the actual value of MAX_SOCKS_ADDR_LEN */
- log_debug(LD_APP,"socks4 addr (%d bytes) too long. Rejecting.",
- (int)strlen(tmpbuf));
- return -1;
- /* LCOV_EXCL_STOP */
- }
- log_debug(LD_APP,
- "socks4: successfully read destip (%s)",
- safe_str_client(tmpbuf));
- socks4_prot = socks4;
- }
+ first_octet = get_uint8(data);
- authstart = data + SOCKS4_NETWORK_LEN;
- next = memchr(authstart, 0,
- datalen-SOCKS4_NETWORK_LEN);
- if (!next) {
- if (datalen >= 1024) {
- log_debug(LD_APP, "Socks4 user name too long; rejecting.");
- return -1;
- }
- log_debug(LD_APP,"socks4: Username not here yet.");
- *want_length_out = datalen+1024; /* More than we need, but safe */
- return 0;
- }
- authend = next;
- tor_assert(next < data+datalen);
-
- startaddr = NULL;
- if (socks4_prot != socks4a &&
- !addressmap_have_mapping(tmpbuf,0)) {
- log_unsafe_socks_warning(4, tmpbuf, req->port, safe_socks);
+ if (first_octet == SOCKS_VER_5 || first_octet == SOCKS_VER_4 ||
+ first_octet == SOCKS_AUTH) { // XXX: RFC 1929
+ return handle_socks_message((const uint8_t *)data, datalen, req,
+ log_sockstype, safe_socks, drain_out);
+ }
- if (safe_socks)
- return -1;
- }
- if (socks4_prot == socks4a) {
- if (next+1 == data+datalen) {
- log_debug(LD_APP,"socks4: No part of destaddr here yet.");
- *want_length_out = datalen + 1024; /* More than we need, but safe */
- return 0;
- }
- startaddr = next+1;
- next = memchr(startaddr, 0, data + datalen - startaddr);
- if (!next) {
- if (datalen >= 1024) {
- log_debug(LD_APP,"socks4: Destaddr too long.");
- return -1;
- }
- log_debug(LD_APP,"socks4: Destaddr not all here yet.");
- *want_length_out = datalen + 1024; /* More than we need, but safe */
- return 0;
- }
- if (MAX_SOCKS_ADDR_LEN <= next-startaddr) {
- log_warn(LD_APP,"socks4: Destaddr too long. Rejecting.");
- return -1;
- }
- // tor_assert(next < buf->cur+buf_datalen(buf));
-
- if (log_sockstype)
- log_notice(LD_APP,
- "Your application (using socks4a to port %d) instructed "
- "Tor to take care of the DNS resolution itself if "
- "necessary. This is good.", req->port);
- }
- log_debug(LD_APP,"socks4: Everything is here. Success.");
- strlcpy(req->address, startaddr ? startaddr : tmpbuf,
- sizeof(req->address));
- if (!string_is_valid_dest(req->address)) {
- log_warn(LD_PROTOCOL,
- "Your application (using socks4 to port %d) gave Tor "
- "a malformed hostname: %s. Rejecting the connection.",
- req->port, escaped_safe_str_client(req->address));
- return -1;
- }
- if (authend != authstart) {
- req->got_auth = 1;
- req->usernamelen = authend - authstart;
- req->username = tor_memdup(authstart, authend - authstart);
- }
- /* next points to the final \0 on inbuf */
- *drain_out = next - data + 1;
- return 1;
- }
+ switch (first_octet) { /* which version of socks? */
case 'G': /* get */
case 'H': /* head */
case 'P': /* put/post */
@@ -561,6 +971,9 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req,
}
return -1;
}
+
+ tor_assert_unreached();
+ return -1;
}
/** Inspect a reply from SOCKS server stored in <b>buf</b> according
diff --git a/src/ext/getdelim.c b/src/ext/getdelim.c
new file mode 100644
index 0000000000..8254103ff9
--- /dev/null
+++ b/src/ext/getdelim.c
@@ -0,0 +1,78 @@
+/* $NetBSD: getdelim.c,v 1.2 2015/12/25 20:12:46 joerg Exp $ */
+/* NetBSD-src: getline.c,v 1.2 2014/09/16 17:23:50 christos Exp */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BUFSIZ
+#define BUFSIZ 512
+#endif
+
+ssize_t
+compat_getdelim_(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
+{
+ char *ptr, *eptr;
+
+
+ if (*buf == NULL || *bufsiz == 0) {
+ *bufsiz = BUFSIZ;
+ if ((*buf = raw_malloc(*bufsiz)) == NULL)
+ return -1;
+ }
+
+ for (ptr = *buf, eptr = *buf + *bufsiz;;) {
+ int c = fgetc(fp);
+ if (c == -1) {
+ if (feof(fp)) {
+ ssize_t diff = (ssize_t)(ptr - *buf);
+ if (diff != 0) {
+ *ptr = '\0';
+ return diff;
+ }
+ }
+ return -1;
+ }
+ *ptr++ = c;
+ if (c == delimiter) {
+ *ptr = '\0';
+ return ptr - *buf;
+ }
+ if (ptr + 2 >= eptr) {
+ char *nbuf;
+ size_t nbufsiz = *bufsiz * 2;
+ ssize_t d = ptr - *buf;
+ if ((nbuf = raw_realloc(*buf, nbufsiz)) == NULL)
+ return -1;
+ *buf = nbuf;
+ *bufsiz = nbufsiz;
+ eptr = nbuf + nbufsiz;
+ ptr = nbuf + d;
+ }
+ }
+}
diff --git a/src/ext/include.am b/src/ext/include.am
index 7ec2e43312..6bdce2d79e 100644
--- a/src/ext/include.am
+++ b/src/ext/include.am
@@ -10,6 +10,7 @@ EXTHEADERS = \
src/ext/tor_readpassphrase.h \
src/ext/strlcat.c \
src/ext/strlcpy.c \
+ src/ext/getdelim.c \
src/ext/tinytest_macros.h \
src/ext/tor_queue.h \
src/ext/siphash.h \
@@ -173,4 +174,3 @@ EXTRA_DIST += \
src/ext/timeouts/Makefile \
src/ext/timeouts/Rules.shrc \
src/ext/timeouts/test-timeout.c
-
diff --git a/src/ext/tinytest.c b/src/ext/tinytest.c
index 3fb1b39c71..df2cc0b584 100644
--- a/src/ext/tinytest.c
+++ b/src/ext/tinytest.c
@@ -145,7 +145,7 @@ testcase_run_forked_(const struct testgroup_t *group,
if (opt_verbosity>0)
printf("[forking] ");
- snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s",
+ snprintf(buffer, sizeof(buffer), "\"%s\" --RUNNING-FORKED %s %s%s",
commandname, verbosity_flag, group->prefix, testcase->name);
memset(&si, 0, sizeof(si));
diff --git a/src/feature/client/entrynodes.c b/src/feature/client/entrynodes.c
index 664be8ce11..494ad33528 100644
--- a/src/feature/client/entrynodes.c
+++ b/src/feature/client/entrynodes.c
@@ -406,6 +406,17 @@ get_remove_unlisted_guards_after_days(void)
DFLT_REMOVE_UNLISTED_GUARDS_AFTER_DAYS,
1, 365*10);
}
+
+/**
+ * Return number of seconds that will make a guard no longer eligible
+ * for selection if unlisted for this long.
+ */
+static time_t
+get_remove_unlisted_guards_after_seconds(void)
+{
+ return get_remove_unlisted_guards_after_days() * 24 * 60 * 60;
+}
+
/**
* We remove unconfirmed guards from the sample after this many days,
* regardless of whether they are listed or unlisted.
@@ -1237,30 +1248,28 @@ entry_guard_is_listed,(guard_selection_t *gs, const entry_guard_t *guard))
}
/**
- * Update the status of all sampled guards based on the arrival of a
- * new consensus networkstatus document. This will include marking
- * some guards as listed or unlisted, and removing expired guards. */
-STATIC void
-sampled_guards_update_from_consensus(guard_selection_t *gs)
+ * Enumerate <b>sampled_entry_guards</b> smartlist in <b>gs</b>.
+ * For each <b>entry_guard_t</b> object in smartlist, do the following:
+ * * Update <b>currently_listed</b> field to reflect if guard is listed
+ * in guard selection <b>gs</b>.
+ * * Set <b>unlisted_since_date</b> to approximate UNIX time of
+ * unlisting if guard is unlisted (randomize within 20% of
+ * get_remove_unlisted_guards_after_seconds()). Otherwise,
+ * set it to 0.
+ *
+ * Require <b>gs</b> to be non-null pointer.
+ * Return a number of entries updated.
+ */
+static size_t
+sampled_guards_update_consensus_presence(guard_selection_t *gs)
{
- tor_assert(gs);
- const int REMOVE_UNLISTED_GUARDS_AFTER =
- (get_remove_unlisted_guards_after_days() * 86400);
- const int unlisted_since_slop = REMOVE_UNLISTED_GUARDS_AFTER / 5;
+ size_t n_changes = 0;
- // It's important to use only a live consensus here; we don't want to
- // make changes based on anything expired or old.
- if (live_consensus_is_missing(gs)) {
- log_info(LD_GUARD, "Not updating the sample guard set; we have "
- "no live consensus.");
- return;
- }
- log_info(LD_GUARD, "Updating sampled guard status based on received "
- "consensus.");
+ tor_assert(gs);
- int n_changes = 0;
+ const time_t unlisted_since_slop =
+ get_remove_unlisted_guards_after_seconds() / 5;
- /* First: Update listed/unlisted. */
SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards, entry_guard_t *, guard) {
/* XXXX #20827 check ed ID too */
const int is_listed = entry_guard_is_listed(gs, guard);
@@ -1304,14 +1313,33 @@ sampled_guards_update_from_consensus(guard_selection_t *gs)
}
} SMARTLIST_FOREACH_END(guard);
- const time_t remove_if_unlisted_since =
- approx_time() - REMOVE_UNLISTED_GUARDS_AFTER;
- const time_t maybe_remove_if_sampled_before =
- approx_time() - get_guard_lifetime();
- const time_t remove_if_confirmed_before =
- approx_time() - get_guard_confirmed_min_lifetime();
+ return n_changes;
+}
+
+/**
+ * Enumerate <b>sampled_entry_guards</b> smartlist in <b>gs</b>.
+ * For each <b>entry_guard_t</b> object in smartlist, do the following:
+ * * If <b>currently_listed</b> is false and <b>unlisted_since_date</b>
+ * is earlier than <b>remove_if_unlisted_since</b> - remove it.
+ * * Otherwise, check if <b>sampled_on_date</b> is earlier than
+ * <b>maybe_remove_if_sampled_before</b>.
+ * * When above condition is correct, remove the guard if:
+ * * It was never confirmed.
+ * * It was confirmed before <b>remove_if_confirmed_before</b>.
+ *
+ * Require <b>gs</b> to be non-null pointer.
+ * Return number of entries deleted.
+ */
+static size_t
+sampled_guards_prune_obsolete_entries(guard_selection_t *gs,
+ const time_t remove_if_unlisted_since,
+ const time_t maybe_remove_if_sampled_before,
+ const time_t remove_if_confirmed_before)
+{
+ size_t n_changes = 0;
+
+ tor_assert(gs);
- /* Then: remove the ones that have been junk for too long */
SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards, entry_guard_t *, guard) {
int rmv = 0;
@@ -1319,7 +1347,7 @@ sampled_guards_update_from_consensus(guard_selection_t *gs)
guard->unlisted_since_date < remove_if_unlisted_since) {
/*
"We have a live consensus, and {IS_LISTED} is false, and
- {FIRST_UNLISTED_AT} is over {REMOVE_UNLISTED_GUARDS_AFTER}
+ {FIRST_UNLISTED_AT} is over get_remove_unlisted_guards_after_days()
days in the past."
*/
log_info(LD_GUARD, "Removing sampled guard %s: it has been unlisted "
@@ -1355,6 +1383,45 @@ sampled_guards_update_from_consensus(guard_selection_t *gs)
}
} SMARTLIST_FOREACH_END(guard);
+ return n_changes;
+}
+
+/**
+ * Update the status of all sampled guards based on the arrival of a
+ * new consensus networkstatus document. This will include marking
+ * some guards as listed or unlisted, and removing expired guards. */
+STATIC void
+sampled_guards_update_from_consensus(guard_selection_t *gs)
+{
+ tor_assert(gs);
+
+ // It's important to use only a live consensus here; we don't want to
+ // make changes based on anything expired or old.
+ if (live_consensus_is_missing(gs)) {
+ log_info(LD_GUARD, "Not updating the sample guard set; we have "
+ "no live consensus.");
+ return;
+ }
+ log_info(LD_GUARD, "Updating sampled guard status based on received "
+ "consensus.");
+
+ /* First: Update listed/unlisted. */
+ size_t n_changes = sampled_guards_update_consensus_presence(gs);
+
+ const time_t remove_if_unlisted_since =
+ approx_time() - get_remove_unlisted_guards_after_seconds();
+ const time_t maybe_remove_if_sampled_before =
+ approx_time() - get_guard_lifetime();
+ const time_t remove_if_confirmed_before =
+ approx_time() - get_guard_confirmed_min_lifetime();
+
+ /* Then: remove the ones that have been junk for too long */
+ n_changes +=
+ sampled_guards_prune_obsolete_entries(gs,
+ remove_if_unlisted_since,
+ maybe_remove_if_sampled_before,
+ remove_if_confirmed_before);
+
if (n_changes) {
gs->primary_guards_up_to_date = 0;
entry_guards_update_filtered_sets(gs);
@@ -1816,28 +1883,24 @@ entry_guards_update_primary(guard_selection_t *gs)
smartlist_add(new_primary_guards, guard);
} SMARTLIST_FOREACH_END(guard);
- /* Can we keep any older primary guards? First remove all the ones
- * that we already kept. */
SMARTLIST_FOREACH_BEGIN(old_primary_guards, entry_guard_t *, guard) {
+ /* Can we keep any older primary guards? First remove all the ones
+ * that we already kept. */
if (smartlist_contains(new_primary_guards, guard)) {
SMARTLIST_DEL_CURRENT_KEEPORDER(old_primary_guards, guard);
- }
- } SMARTLIST_FOREACH_END(guard);
-
- /* Now add any that are still good. */
- SMARTLIST_FOREACH_BEGIN(old_primary_guards, entry_guard_t *, guard) {
- if (smartlist_len(new_primary_guards) >= N_PRIMARY_GUARDS)
- break;
- if (! guard->is_filtered_guard)
continue;
- guard->is_primary = 1;
- smartlist_add(new_primary_guards, guard);
- SMARTLIST_DEL_CURRENT_KEEPORDER(old_primary_guards, guard);
- } SMARTLIST_FOREACH_END(guard);
+ }
- /* Mark the remaining previous primary guards as non-primary */
- SMARTLIST_FOREACH_BEGIN(old_primary_guards, entry_guard_t *, guard) {
- guard->is_primary = 0;
+ /* Now add any that are still good. */
+ if (smartlist_len(new_primary_guards) < N_PRIMARY_GUARDS &&
+ guard->is_filtered_guard) {
+ guard->is_primary = 1;
+ smartlist_add(new_primary_guards, guard);
+ SMARTLIST_DEL_CURRENT_KEEPORDER(old_primary_guards, guard);
+ } else {
+ /* Mark the remaining previous primary guards as non-primary */
+ guard->is_primary = 0;
+ }
} SMARTLIST_FOREACH_END(guard);
/* Finally, fill out the list with sampled guards. */
@@ -1861,18 +1924,8 @@ entry_guards_update_primary(guard_selection_t *gs)
});
#endif /* 1 */
- int any_change = 0;
- if (smartlist_len(gs->primary_entry_guards) !=
- smartlist_len(new_primary_guards)) {
- any_change = 1;
- } else {
- SMARTLIST_FOREACH_BEGIN(gs->primary_entry_guards, entry_guard_t *, g) {
- if (g != smartlist_get(new_primary_guards, g_sl_idx)) {
- any_change = 1;
- }
- } SMARTLIST_FOREACH_END(g);
- }
-
+ const int any_change = !smartlist_ptrs_eq(gs->primary_entry_guards,
+ new_primary_guards);
if (any_change) {
log_info(LD_GUARD, "Primary entry guards have changed. "
"New primary guard list is: ");
@@ -1974,31 +2027,23 @@ entry_guards_note_internet_connectivity(guard_selection_t *gs)
}
/**
- * Get a guard for use with a circuit. Prefer to pick a running primary
- * guard; then a non-pending running filtered confirmed guard; then a
- * non-pending runnable filtered guard. Update the
+ * Pick a primary guard for use with a circuit, if available. Update the
* <b>last_tried_to_connect</b> time and the <b>is_pending</b> fields of the
* guard as appropriate. Set <b>state_out</b> to the new guard-state
* of the circuit.
*/
-STATIC entry_guard_t *
-select_entry_guard_for_circuit(guard_selection_t *gs,
- guard_usage_t usage,
- const entry_guard_restriction_t *rst,
- unsigned *state_out)
+static entry_guard_t *
+select_primary_guard_for_circuit(guard_selection_t *gs,
+ guard_usage_t usage,
+ const entry_guard_restriction_t *rst,
+ unsigned *state_out)
{
const int need_descriptor = (usage == GUARD_USAGE_TRAFFIC);
- tor_assert(gs);
- tor_assert(state_out);
-
- if (!gs->primary_guards_up_to_date)
- entry_guards_update_primary(gs);
+ entry_guard_t *chosen_guard = NULL;
int num_entry_guards = get_n_primary_guards_to_use(usage);
smartlist_t *usable_primary_guards = smartlist_new();
- /* "If any entry in PRIMARY_GUARDS has {is_reachable} status of
- <maybe> or <yes>, return the first such guard." */
SMARTLIST_FOREACH_BEGIN(gs->primary_entry_guards, entry_guard_t *, guard) {
entry_guard_consider_retry(guard);
if (! entry_guard_obeys_restriction(guard, rst))
@@ -2016,18 +2061,30 @@ select_entry_guard_for_circuit(guard_selection_t *gs,
} SMARTLIST_FOREACH_END(guard);
if (smartlist_len(usable_primary_guards)) {
- entry_guard_t *guard = smartlist_choose(usable_primary_guards);
+ chosen_guard = smartlist_choose(usable_primary_guards);
smartlist_free(usable_primary_guards);
log_info(LD_GUARD, "Selected primary guard %s for circuit.",
- entry_guard_describe(guard));
- return guard;
+ entry_guard_describe(chosen_guard));
}
+
smartlist_free(usable_primary_guards);
+ return chosen_guard;
+}
+
+/**
+ * For use with a circuit, pick a non-pending running filtered confirmed guard,
+ * if one is available. Update the <b>last_tried_to_connect</b> time and the
+ * <b>is_pending</b> fields of the guard as appropriate. Set <b>state_out</b>
+ * to the new guard-state of the circuit.
+ */
+static entry_guard_t *
+select_confirmed_guard_for_circuit(guard_selection_t *gs,
+ guard_usage_t usage,
+ const entry_guard_restriction_t *rst,
+ unsigned *state_out)
+{
+ const int need_descriptor = (usage == GUARD_USAGE_TRAFFIC);
- /* "Otherwise, if the ordered intersection of {CONFIRMED_GUARDS}
- and {USABLE_FILTERED_GUARDS} is nonempty, return the first
- entry in that intersection that has {is_pending} set to
- false." */
SMARTLIST_FOREACH_BEGIN(gs->confirmed_entry_guards, entry_guard_t *, guard) {
if (guard->is_primary)
continue; /* we already considered this one. */
@@ -2048,34 +2105,93 @@ select_entry_guard_for_circuit(guard_selection_t *gs,
}
} SMARTLIST_FOREACH_END(guard);
+ return NULL;
+}
+
+/**
+ * For use with a circuit, pick a confirmed usable filtered guard
+ * at random. Update the <b>last_tried_to_connect</b> time and the
+ * <b>is_pending</b> fields of the guard as appropriate. Set <b>state_out</b>
+ * to the new guard-state of the circuit.
+ */
+static entry_guard_t *
+select_filtered_guard_for_circuit(guard_selection_t *gs,
+ guard_usage_t usage,
+ const entry_guard_restriction_t *rst,
+ unsigned *state_out)
+{
+ const int need_descriptor = (usage == GUARD_USAGE_TRAFFIC);
+ entry_guard_t *chosen_guard = NULL;
+ unsigned flags = 0;
+ if (need_descriptor)
+ flags |= SAMPLE_EXCLUDE_NO_DESCRIPTOR;
+ chosen_guard = sample_reachable_filtered_entry_guards(gs,
+ rst,
+ SAMPLE_EXCLUDE_CONFIRMED |
+ SAMPLE_EXCLUDE_PRIMARY |
+ SAMPLE_EXCLUDE_PENDING |
+ flags);
+ if (!chosen_guard) {
+ return NULL;
+ }
+
+ chosen_guard->is_pending = 1;
+ chosen_guard->last_tried_to_connect = approx_time();
+ *state_out = GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD;
+ log_info(LD_GUARD, "No primary or confirmed guards available. Selected "
+ "random guard %s for circuit. Will try other guards before "
+ "using this circuit.",
+ entry_guard_describe(chosen_guard));
+ return chosen_guard;
+}
+
+/**
+ * Get a guard for use with a circuit. Prefer to pick a running primary
+ * guard; then a non-pending running filtered confirmed guard; then a
+ * non-pending runnable filtered guard. Update the
+ * <b>last_tried_to_connect</b> time and the <b>is_pending</b> fields of the
+ * guard as appropriate. Set <b>state_out</b> to the new guard-state
+ * of the circuit.
+ */
+STATIC entry_guard_t *
+select_entry_guard_for_circuit(guard_selection_t *gs,
+ guard_usage_t usage,
+ const entry_guard_restriction_t *rst,
+ unsigned *state_out)
+{
+ entry_guard_t *chosen_guard = NULL;
+ tor_assert(gs);
+ tor_assert(state_out);
+
+ if (!gs->primary_guards_up_to_date)
+ entry_guards_update_primary(gs);
+
+ /* "If any entry in PRIMARY_GUARDS has {is_reachable} status of
+ <maybe> or <yes>, return the first such guard." */
+ chosen_guard = select_primary_guard_for_circuit(gs, usage, rst, state_out);
+ if (chosen_guard)
+ return chosen_guard;
+
+ /* "Otherwise, if the ordered intersection of {CONFIRMED_GUARDS}
+ and {USABLE_FILTERED_GUARDS} is nonempty, return the first
+ entry in that intersection that has {is_pending} set to
+ false." */
+ chosen_guard = select_confirmed_guard_for_circuit(gs, usage, rst, state_out);
+ if (chosen_guard)
+ return chosen_guard;
+
/* "Otherwise, if there is no such entry, select a member at
random from {USABLE_FILTERED_GUARDS}." */
- {
- entry_guard_t *guard;
- unsigned flags = 0;
- if (need_descriptor)
- flags |= SAMPLE_EXCLUDE_NO_DESCRIPTOR;
- guard = sample_reachable_filtered_entry_guards(gs,
- rst,
- SAMPLE_EXCLUDE_CONFIRMED |
- SAMPLE_EXCLUDE_PRIMARY |
- SAMPLE_EXCLUDE_PENDING |
- flags);
- if (guard == NULL) {
- log_info(LD_GUARD, "Absolutely no sampled guards were available. "
- "Marking all guards for retry and starting from top again.");
- mark_all_guards_maybe_reachable(gs);
- return NULL;
- }
- guard->is_pending = 1;
- guard->last_tried_to_connect = approx_time();
- *state_out = GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD;
- log_info(LD_GUARD, "No primary or confirmed guards available. Selected "
- "random guard %s for circuit. Will try other guards before "
- "using this circuit.",
- entry_guard_describe(guard));
- return guard;
+ chosen_guard = select_filtered_guard_for_circuit(gs, usage, rst, state_out);
+
+ if (chosen_guard == NULL) {
+ log_info(LD_GUARD, "Absolutely no sampled guards were available. "
+ "Marking all guards for retry and starting from top again.");
+ mark_all_guards_maybe_reachable(gs);
+ return NULL;
}
+
+ return chosen_guard;
}
/**
diff --git a/src/feature/control/control.c b/src/feature/control/control.c
index 12f10926b7..f22df30e11 100644
--- a/src/feature/control/control.c
+++ b/src/feature/control/control.c
@@ -2011,6 +2011,8 @@ getinfo_helper_listeners(control_connection_t *control_conn,
if (!strcmp(question, "net/listeners/or"))
type = CONN_TYPE_OR_LISTENER;
+ else if (!strcmp(question, "net/listeners/extor"))
+ type = CONN_TYPE_EXT_OR_LISTENER;
else if (!strcmp(question, "net/listeners/dir"))
type = CONN_TYPE_DIR_LISTENER;
else if (!strcmp(question, "net/listeners/socks"))
@@ -2019,6 +2021,8 @@ getinfo_helper_listeners(control_connection_t *control_conn,
type = CONN_TYPE_AP_TRANS_LISTENER;
else if (!strcmp(question, "net/listeners/natd"))
type = CONN_TYPE_AP_NATD_LISTENER;
+ else if (!strcmp(question, "net/listeners/httptunnel"))
+ type = CONN_TYPE_AP_HTTP_CONNECT_LISTENER;
else if (!strcmp(question, "net/listeners/dns"))
type = CONN_TYPE_AP_DNS_LISTENER;
else if (!strcmp(question, "net/listeners/control"))
diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c
index ce67c1bb9a..6477f34baf 100644
--- a/src/feature/dirauth/dirvote.c
+++ b/src/feature/dirauth/dirvote.c
@@ -15,6 +15,7 @@
#include "feature/nodelist/parsecommon.h"
#include "core/or/policies.h"
#include "core/or/protover.h"
+#include "core/or/tor_version_st.h"
#include "feature/stats/rephist.h"
#include "feature/relay/router.h"
#include "feature/relay/routerkeys.h"
@@ -254,6 +255,7 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
/* XXXX Abstraction violation: should be pulling a field out of v3_ns.*/
char *flag_thresholds = dirserv_get_flag_thresholds_line();
char *params;
+ char *bw_headers_line = NULL;
authority_cert_t *cert = v3_ns->cert;
char *methods =
make_consensus_method_list(MIN_SUPPORTED_CONSENSUS_METHOD,
@@ -267,8 +269,32 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
params = smartlist_join_strings(v3_ns->net_params, " ", 0, NULL);
else
params = tor_strdup("");
-
tor_assert(cert);
+
+ /* v3_ns->bw_file_headers is only set when V3BandwidthsFile is
+ * configured */
+ if (v3_ns->bw_file_headers) {
+ char *bw_file_headers = NULL;
+ /* If there are too many headers, leave the header string NULL */
+ if (! BUG(smartlist_len(v3_ns->bw_file_headers)
+ > MAX_BW_FILE_HEADER_COUNT_IN_VOTE)) {
+ bw_file_headers = smartlist_join_strings(v3_ns->bw_file_headers, " ",
+ 0, NULL);
+ if (BUG(strlen(bw_file_headers) > MAX_BW_FILE_HEADERS_LINE_LEN)) {
+ /* Free and set to NULL, because the line was too long */
+ tor_free(bw_file_headers);
+ }
+ }
+ if (!bw_file_headers) {
+ /* If parsing failed, add a bandwidth header line with no entries */
+ bw_file_headers = tor_strdup("");
+ }
+ /* At this point, the line will always be present */
+ bw_headers_line = format_line_if_present("bandwidth-file-headers",
+ bw_file_headers);
+ tor_free(bw_file_headers);
+ }
+
smartlist_add_asprintf(chunks,
"network-status-version 3\n"
"vote-status %s\n"
@@ -286,7 +312,9 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
"params %s\n"
"dir-source %s %s %s %s %d %d\n"
"contact %s\n"
- "%s", /* shared randomness information */
+ "%s" /* shared randomness information */
+ "%s" /* bandwidth file headers */
+ ,
v3_ns->type == NS_TYPE_VOTE ? "vote" : "opinion",
methods,
published, va, fu, vu,
@@ -302,13 +330,16 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
fmt_addr32(addr), voter->dir_port, voter->or_port,
voter->contact,
shared_random_vote_str ?
- shared_random_vote_str : "");
+ shared_random_vote_str : "",
+ bw_headers_line ?
+ bw_headers_line : "");
tor_free(params);
tor_free(flags);
tor_free(flag_thresholds);
tor_free(methods);
tor_free(shared_random_vote_str);
+ tor_free(bw_headers_line);
if (!tor_digest_is_zero(voter->legacy_id_digest)) {
char fpbuf[HEX_DIGEST_LEN+1];
@@ -797,6 +828,14 @@ compute_consensus_versions_list(smartlist_t *lst, int n_versioning)
int min = n_versioning / 2;
smartlist_t *good = smartlist_new();
char *result;
+ SMARTLIST_FOREACH_BEGIN(lst, const char *, v) {
+ if (strchr(v, ' ')) {
+ log_warn(LD_DIR, "At least one authority has voted for a version %s "
+ "that contains a space. This probably wasn't intentional, and "
+ "is likely to cause trouble. Please tell them to stop it.",
+ escaped(v));
+ }
+ } SMARTLIST_FOREACH_END(v);
sort_version_list(lst, 0);
get_frequent_members(good, lst, min);
result = smartlist_join_strings(good, ",", 0, NULL);
@@ -4200,8 +4239,8 @@ version_from_platform(const char *platform)
* allocate and return a new string containing the version numbers, in order,
* separated by commas. Used to generate Recommended(Client|Server)?Versions
*/
-static char *
-format_versions_list(config_line_t *ln)
+char *
+format_recommended_version_list(const config_line_t *ln, int warn)
{
smartlist_t *versions;
char *result;
@@ -4210,6 +4249,37 @@ format_versions_list(config_line_t *ln)
smartlist_split_string(versions, ln->value, ",",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
}
+
+ /* Handle the case where a dirauth operator has accidentally made some
+ * versions space-separated instead of comma-separated. */
+ smartlist_t *more_versions = smartlist_new();
+ SMARTLIST_FOREACH_BEGIN(versions, char *, v) {
+ if (strchr(v, ' ')) {
+ if (warn)
+ log_warn(LD_DIRSERV, "Unexpected space in versions list member %s. "
+ "(These are supposed to be comma-separated; I'll pretend you "
+ "used commas instead.)", escaped(v));
+ SMARTLIST_DEL_CURRENT(versions, v);
+ smartlist_split_string(more_versions, v, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+ tor_free(v);
+ }
+ } SMARTLIST_FOREACH_END(v);
+ smartlist_add_all(versions, more_versions);
+ smartlist_free(more_versions);
+
+ /* Check to make sure everything looks like a version. */
+ if (warn) {
+ SMARTLIST_FOREACH_BEGIN(versions, const char *, v) {
+ tor_version_t ver;
+ if (tor_version_parse(v, &ver) < 0) {
+ log_warn(LD_DIRSERV, "Recommended version %s does not look valid. "
+ " (I'll include it anyway, since you told me to.)",
+ escaped(v));
+ }
+ } SMARTLIST_FOREACH_END(v);
+ }
+
sort_version_list(versions, 1);
result = smartlist_join_strings(versions,",",0,NULL);
SMARTLIST_FOREACH(versions,char *,s,tor_free(s));
@@ -4303,6 +4373,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
digestmap_t *omit_as_sybil = NULL;
const int vote_on_reachability = running_long_enough_to_decide_unreachable();
smartlist_t *microdescriptors = NULL;
+ smartlist_t *bw_file_headers = NULL;
tor_assert(private_key);
tor_assert(cert);
@@ -4325,8 +4396,10 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
}
if (options->VersioningAuthoritativeDir) {
- client_versions = format_versions_list(options->RecommendedClientVersions);
- server_versions = format_versions_list(options->RecommendedServerVersions);
+ client_versions =
+ format_recommended_version_list(options->RecommendedClientVersions, 0);
+ server_versions =
+ format_recommended_version_list(options->RecommendedServerVersions, 0);
}
contact = get_options()->ContactInfo;
@@ -4338,7 +4411,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
* set_routerstatus_from_routerinfo() see up-to-date bandwidth info.
*/
if (options->V3BandwidthsFile) {
- dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL);
+ dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL, NULL);
} else {
/*
* No bandwidths file; clear the measured bandwidth cache in case we had
@@ -4440,8 +4513,10 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
/* This pass through applies the measured bw lines to the routerstatuses */
if (options->V3BandwidthsFile) {
+ /* Only set bw_file_headers when V3BandwidthsFile is configured */
+ bw_file_headers = smartlist_new();
dirserv_read_measured_bandwidths(options->V3BandwidthsFile,
- routerstatuses);
+ routerstatuses, bw_file_headers);
} else {
/*
* No bandwidths file; clear the measured bandwidth cache in case we had
@@ -4537,6 +4612,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
options->ConsensusParams, NULL, 0, 0);
smartlist_sort_strings(v3_out->net_params);
}
+ v3_out->bw_file_headers = bw_file_headers;
voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
voter->nickname = tor_strdup(options->Nickname);
diff --git a/src/feature/dirauth/dirvote.h b/src/feature/dirauth/dirvote.h
index 7ce8e4a699..979a2be8a6 100644
--- a/src/feature/dirauth/dirvote.h
+++ b/src/feature/dirauth/dirvote.h
@@ -89,6 +89,9 @@
#define DGV_INCLUDE_PENDING 2
#define DGV_INCLUDE_PREVIOUS 4
+/** Maximum size of a line in a vote. */
+#define MAX_BW_FILE_HEADERS_LINE_LEN 1024
+
/*
* Public API. Used outside of the dirauth subsystem.
*
diff --git a/src/feature/dirauth/keypin.c b/src/feature/dirauth/keypin.c
index 44e19985fa..fd281377df 100644
--- a/src/feature/dirauth/keypin.c
+++ b/src/feature/dirauth/keypin.c
@@ -23,7 +23,7 @@
#include "lib/fdio/fdio.h"
#include "lib/fs/files.h"
#include "lib/fs/mmap.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/string/compat_ctype.h"
#include "lib/string/printf.h"
diff --git a/src/feature/dircache/dirserv.c b/src/feature/dircache/dirserv.c
index c5286b0cbf..b85db8324f 100644
--- a/src/feature/dircache/dirserv.c
+++ b/src/feature/dircache/dirserv.c
@@ -51,6 +51,7 @@
#include "lib/crypt_ops/crypto_format.h"
#include "lib/encoding/confline.h"
+#include "lib/encoding/keyval.h"
/**
* \file dirserv.c
* \brief Directory server core implementation. Manages directory
@@ -2599,14 +2600,15 @@ measured_bw_line_apply(measured_bw_line_t *parsed_line,
}
/**
- * Read the measured bandwidth file and apply it to the list of
- * vote_routerstatus_t. Returns -1 on error, 0 otherwise.
+ * Read the measured bandwidth list file, apply it to the list of
+ * vote_routerstatus_t and store all the headers in <b>bw_file_headers</b>.
+ * Returns -1 on error, 0 otherwise.
*/
int
dirserv_read_measured_bandwidths(const char *from_file,
- smartlist_t *routerstatuses)
+ smartlist_t *routerstatuses,
+ smartlist_t *bw_file_headers)
{
- char line[512];
FILE *fp = tor_fopen_cloexec(from_file, "r");
int applied_lines = 0;
time_t file_time, now;
@@ -2616,28 +2618,28 @@ dirserv_read_measured_bandwidths(const char *from_file,
* if there are additional header lines, as introduced in Bandwidth List spec
* version 1.1.0 */
int line_is_after_headers = 0;
+ int rv = -1;
+ char *line = NULL;
+ size_t n = 0;
/* Initialise line, so that we can't possibly run off the end. */
- memset(line, 0, sizeof(line));
if (fp == NULL) {
log_warn(LD_CONFIG, "Can't open bandwidth file at configured location: %s",
from_file);
- return -1;
+ goto err;
}
/* If fgets fails, line is either unmodified, or indeterminate. */
- if (!fgets(line, sizeof(line), fp)) {
+ if (tor_getline(&line,&n,fp) <= 0) {
log_warn(LD_DIRSERV, "Empty bandwidth file");
- fclose(fp);
- return -1;
+ goto err;
}
if (!strlen(line) || line[strlen(line)-1] != '\n') {
log_warn(LD_DIRSERV, "Long or truncated time in bandwidth file: %s",
escaped(line));
- fclose(fp);
- return -1;
+ goto err;
}
line[strlen(line)-1] = '\0';
@@ -2645,24 +2647,28 @@ dirserv_read_measured_bandwidths(const char *from_file,
if (!ok) {
log_warn(LD_DIRSERV, "Non-integer time in bandwidth file: %s",
escaped(line));
- fclose(fp);
- return -1;
+ goto err;
}
now = time(NULL);
if ((now - file_time) > MAX_MEASUREMENT_AGE) {
log_warn(LD_DIRSERV, "Bandwidth measurement file stale. Age: %u",
(unsigned)(time(NULL) - file_time));
- fclose(fp);
- return -1;
+ goto err;
}
+ /* If timestamp was correct and bw_file_headers is not NULL,
+ * add timestamp to bw_file_headers */
+ if (bw_file_headers)
+ smartlist_add_asprintf(bw_file_headers, "timestamp=%lu",
+ (unsigned long)file_time);
+
if (routerstatuses)
smartlist_sort(routerstatuses, compare_vote_routerstatus_entries);
while (!feof(fp)) {
measured_bw_line_t parsed_line;
- if (fgets(line, sizeof(line), fp) && strlen(line)) {
+ if (tor_getline(&line, &n, fp) >= 0) {
if (measured_bw_line_parse(&parsed_line, line,
line_is_after_headers) != -1) {
/* This condition will be true when the first complete valid bw line
@@ -2672,18 +2678,43 @@ dirserv_read_measured_bandwidths(const char *from_file,
dirserv_cache_measured_bw(&parsed_line, file_time);
if (measured_bw_line_apply(&parsed_line, routerstatuses) > 0)
applied_lines++;
- }
+ /* if the terminator is found, it is the end of header lines, set the
+ * flag but do not store anything */
+ } else if (strcmp(line, BW_FILE_HEADERS_TERMINATOR) == 0) {
+ line_is_after_headers = 1;
+ /* if the line was not a correct relay line nor the terminator and
+ * the end of the header lines has not been detected yet
+ * and it is key_value and bw_file_headers did not reach the maximum
+ * number of headers,
+ * then assume this line is a header and add it to bw_file_headers */
+ } else if (bw_file_headers &&
+ (line_is_after_headers == 0) &&
+ string_is_key_value(LOG_DEBUG, line) &&
+ !strchr(line, ' ') &&
+ (smartlist_len(bw_file_headers)
+ < MAX_BW_FILE_HEADER_COUNT_IN_VOTE)) {
+ line[strlen(line)-1] = '\0';
+ smartlist_add_strdup(bw_file_headers, line);
+ };
}
}
/* Now would be a nice time to clean the cache, too */
dirserv_expire_measured_bw_cache(now);
- fclose(fp);
log_info(LD_DIRSERV,
"Bandwidth measurement file successfully read. "
"Applied %d measurements.", applied_lines);
- return 0;
+ rv = 0;
+
+ err:
+ if (line) {
+ // we need to raw_free this buffer because we got it from tor_getdelim()
+ raw_free(line);
+ }
+ if (fp)
+ fclose(fp);
+ return rv;
}
/** As dirserv_get_routerdescs(), but instead of getting signed_descriptor_t
diff --git a/src/feature/dircache/dirserv.h b/src/feature/dircache/dirserv.h
index 3b4a646094..9be4bf9db2 100644
--- a/src/feature/dircache/dirserv.h
+++ b/src/feature/dircache/dirserv.h
@@ -49,6 +49,13 @@ typedef enum {
/** Maximum allowable length of a version line in a networkstatus. */
#define MAX_V_LINE_LEN 128
+/** Maximum allowable length of bandwidth headers in a bandwidth file */
+#define MAX_BW_FILE_HEADER_COUNT_IN_VOTE 50
+
+/** Terminatore that separates bandwidth file headers from bandwidth file
+ * relay lines */
+#define BW_FILE_HEADERS_TERMINATOR "=====\n"
+
/** Ways to convert a spoolable_resource_t to a bunch of bytes. */
typedef enum dir_spool_source_t {
DIR_SPOOL_SERVER_BY_DIGEST=1, DIR_SPOOL_SERVER_BY_FP,
@@ -180,7 +187,9 @@ char *routerstatus_format_entry(
void dirserv_free_all(void);
void cached_dir_decref(cached_dir_t *d);
cached_dir_t *new_cached_dir(char *s, time_t published);
-
+struct config_line_t;
+char *format_recommended_version_list(const struct config_line_t *line,
+ int warn);
int validate_recommended_package_line(const char *line);
int dirserv_query_measured_bw_cache_kb(const char *node_id,
long *bw_out,
@@ -215,7 +224,8 @@ dirserv_read_guardfraction_file_from_str(const char *guardfraction_file_str,
#endif /* defined(DIRSERV_PRIVATE) */
int dirserv_read_measured_bandwidths(const char *from_file,
- smartlist_t *routerstatuses);
+ smartlist_t *routerstatuses,
+ smartlist_t *bw_file_headers);
int dirserv_read_guardfraction_file(const char *fname,
smartlist_t *vote_routerstatuses);
diff --git a/src/feature/dircommon/voting_schedule.c b/src/feature/dircommon/voting_schedule.c
index 84c016c2b9..07e65ef06d 100644
--- a/src/feature/dircommon/voting_schedule.c
+++ b/src/feature/dircommon/voting_schedule.c
@@ -168,7 +168,7 @@ voting_schedule_get_next_valid_after_time(void)
done:
if (need_to_recalculate_voting_schedule) {
- voting_schedule_recalculate_timing(get_options(), now);
+ voting_schedule_recalculate_timing(get_options(), approx_time());
voting_schedule.created_on_demand = 1;
}
diff --git a/src/feature/hs/hs_circuit.c b/src/feature/hs/hs_circuit.c
index cd312e98be..541b165dd5 100644
--- a/src/feature/hs/hs_circuit.c
+++ b/src/feature/hs/hs_circuit.c
@@ -566,10 +566,14 @@ retry_service_rendezvous_point(const origin_circuit_t *circ)
return;
}
-/* Add all possible link specifiers in node to lspecs.
- * legacy ID is mandatory thus MUST be present in node. If the primary address
- * is not IPv4, log a BUG() warning, and return an empty smartlist.
- * Includes ed25519 id and IPv6 link specifiers if present in the node. */
+/* Add all possible link specifiers in node to lspecs:
+ * - legacy ID is mandatory thus MUST be present in node;
+ * - include ed25519 link specifier if present in the node, and the node
+ * supports ed25519 link authentication, even if its link versions are not
+ * compatible with us;
+ * - include IPv4 link specifier, if the primary address is not IPv4, log a
+ * BUG() warning, and return an empty smartlist;
+ * - include IPv6 link specifier if present in the node. */
static void
get_lspecs_from_node(const node_t *node, smartlist_t *lspecs)
{
@@ -607,8 +611,12 @@ get_lspecs_from_node(const node_t *node, smartlist_t *lspecs)
link_specifier_set_ls_len(ls, link_specifier_getlen_un_legacy_id(ls));
smartlist_add(lspecs, ls);
- /* ed25519 ID is only included if the node has it. */
- if (!ed25519_public_key_is_zero(&node->ed25519_id)) {
+ /* ed25519 ID is only included if the node has it, and the node declares a
+ protocol version that supports ed25519 link authentication, even if that
+ link version is not compatible with us. (We are sending the ed25519 key
+ to another tor, which may support different link versions.) */
+ if (!ed25519_public_key_is_zero(&node->ed25519_id) &&
+ node_supports_ed25519_link_authentication(node, 0)) {
ls = link_specifier_new();
link_specifier_set_ls_type(ls, LS_ED25519_ID);
memcpy(link_specifier_getarray_un_ed25519_id(ls), &node->ed25519_id,
diff --git a/src/feature/hs/hs_common.c b/src/feature/hs/hs_common.c
index 723cfa6ea8..12405a79cb 100644
--- a/src/feature/hs/hs_common.c
+++ b/src/feature/hs/hs_common.c
@@ -254,8 +254,8 @@ get_time_period_length(void)
HS_TIME_PERIOD_LENGTH_MIN,
HS_TIME_PERIOD_LENGTH_MAX);
/* Make sure it's a positive value. */
- tor_assert(time_period_length >= 0);
- /* uint64_t will always be able to contain a int32_t */
+ tor_assert(time_period_length > 0);
+ /* uint64_t will always be able to contain a positive int32_t */
return (uint64_t) time_period_length;
}
@@ -844,7 +844,7 @@ hs_get_subcredential(const ed25519_public_key_t *identity_pk,
memwipe(credential, 0, sizeof(credential));
}
-/* From the given list of hidden service ports, find the ones that much the
+/* From the given list of hidden service ports, find the ones that match the
* given edge connection conn, pick one at random and use it to set the
* connection address. Return 0 on success or -1 if none. */
int
@@ -1102,8 +1102,7 @@ hs_in_period_between_tp_and_srv,(const networkstatus_t *consensus, time_t now))
/* Get start time of next TP and of current SRV protocol run, and check if we
* are between them. */
valid_after = consensus->valid_after;
- srv_start_time =
- sr_state_get_start_time_of_current_protocol_run(valid_after);
+ srv_start_time = sr_state_get_start_time_of_current_protocol_run();
tp_start_time = hs_get_start_time_of_next_time_period(srv_start_time);
if (valid_after >= srv_start_time && valid_after < tp_start_time) {
diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c
index 8b4de21387..7775ac6de8 100644
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -17,6 +17,7 @@
#include "core/mainloop/connection.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
+#include "lib/crypt_ops/crypto_ope.h"
#include "feature/dircache/directory.h"
#include "core/mainloop/main.h"
#include "feature/nodelist/networkstatus.h"
@@ -102,7 +103,8 @@ static smartlist_t *hs_service_staging_list;
static int consider_republishing_hs_descriptors = 0;
/* Static declaration. */
-static void set_descriptor_revision_counter(hs_descriptor_t *hs_desc);
+static void set_descriptor_revision_counter(hs_service_descriptor_t *hs_desc,
+ time_t now, bool is_current);
static void move_descriptors(hs_service_t *src, hs_service_t *dst);
/* Helper: Function to compare two objects in the service map. Return 1 if the
@@ -408,17 +410,21 @@ service_intro_point_free_void(void *obj)
}
/* Return a newly allocated service intro point and fully initialized from the
- * given extend_info_t ei if non NULL. If is_legacy is true, we also generate
- * the legacy key. On error, NULL is returned.
+ * given extend_info_t ei if non NULL.
+ * If is_legacy is true, we also generate the legacy key.
+ * If supports_ed25519_link_handshake_any is true, we add the relay's ed25519
+ * key to the link specifiers.
*
* If ei is NULL, returns a hs_service_intro_point_t with an empty link
* specifier list and no onion key. (This is used for testing.)
+ * On any other error, NULL is returned.
*
* ei must be an extend_info_t containing an IPv4 address. (We will add supoort
* for IPv6 in a later release.) When calling extend_info_from_node(), pass
* 0 in for_direct_connection to make sure ei always has an IPv4 address. */
STATIC hs_service_intro_point_t *
-service_intro_point_new(const extend_info_t *ei, unsigned int is_legacy)
+service_intro_point_new(const extend_info_t *ei, unsigned int is_legacy,
+ unsigned int supports_ed25519_link_handshake_any)
{
hs_desc_link_specifier_t *ls;
hs_service_intro_point_t *ip;
@@ -443,7 +449,7 @@ service_intro_point_new(const extend_info_t *ei, unsigned int is_legacy)
if (BUG(intro_point_max_lifetime < intro_point_min_lifetime)) {
goto err;
}
- ip->time_to_expire = time(NULL) +
+ ip->time_to_expire = approx_time() +
crypto_rand_int_range(intro_point_min_lifetime,intro_point_max_lifetime);
}
@@ -489,10 +495,13 @@ service_intro_point_new(const extend_info_t *ei, unsigned int is_legacy)
}
smartlist_add(ip->base.link_specifiers, ls);
- /* ed25519 identity key is optional for intro points */
- ls = hs_desc_link_specifier_new(ei, LS_ED25519_ID);
- if (ls) {
- smartlist_add(ip->base.link_specifiers, ls);
+ /* ed25519 identity key is optional for intro points. If the node supports
+ * ed25519 link authentication, we include it. */
+ if (supports_ed25519_link_handshake_any) {
+ ls = hs_desc_link_specifier_new(ei, LS_ED25519_ID);
+ if (ls) {
+ smartlist_add(ip->base.link_specifiers, ls);
+ }
}
/* IPv6 is not supported in this release. */
@@ -1084,6 +1093,7 @@ service_descriptor_free_(hs_service_descriptor_t *desc)
SMARTLIST_FOREACH(desc->previous_hsdirs, char *, s, tor_free(s));
smartlist_free(desc->previous_hsdirs);
}
+ crypto_ope_free(desc->ope_cipher);
tor_free(desc);
}
@@ -1388,13 +1398,30 @@ build_service_desc_plaintext(const hs_service_t *service,
return ret;
}
+/** Compute the descriptor's OPE cipher for encrypting revision counters. */
+static crypto_ope_t *
+generate_ope_cipher_for_desc(const hs_service_descriptor_t *hs_desc)
+{
+ /* Compute OPE key as H("rev-counter-generation" | blinded privkey) */
+ uint8_t key[DIGEST256_LEN];
+ crypto_digest_t *digest = crypto_digest256_new(DIGEST_SHA3_256);
+ const char ope_key_prefix[] = "rev-counter-generation";
+ const ed25519_secret_key_t *eph_privkey = &hs_desc->blinded_kp.seckey;
+ crypto_digest_add_bytes(digest, ope_key_prefix, sizeof(ope_key_prefix));
+ crypto_digest_add_bytes(digest, (char*)eph_privkey->seckey,
+ sizeof(eph_privkey->seckey));
+ crypto_digest_get_digest(digest, (char *)key, sizeof(key));
+ crypto_digest_free(digest);
+
+ return crypto_ope_new(key);
+}
+
/* For the given service and descriptor object, create the key material which
* is the blinded keypair and the descriptor signing keypair. Return 0 on
* success else -1 on error where the generated keys MUST be ignored. */
static int
build_service_desc_keys(const hs_service_t *service,
- hs_service_descriptor_t *desc,
- uint64_t time_period_num)
+ hs_service_descriptor_t *desc)
{
int ret = 0;
ed25519_keypair_t kp;
@@ -1410,10 +1437,17 @@ build_service_desc_keys(const hs_service_t *service,
memcpy(&kp.pubkey, &service->keys.identity_pk, sizeof(kp.pubkey));
memcpy(&kp.seckey, &service->keys.identity_sk, sizeof(kp.seckey));
/* Build blinded keypair for this time period. */
- hs_build_blinded_keypair(&kp, NULL, 0, time_period_num, &desc->blinded_kp);
+ hs_build_blinded_keypair(&kp, NULL, 0, desc->time_period_num,
+ &desc->blinded_kp);
/* Let's not keep too much traces of our keys in memory. */
memwipe(&kp, 0, sizeof(kp));
+ /* Compute the OPE cipher struct (it's tied to the current blinded key) */
+ log_info(LD_GENERAL,
+ "Getting OPE for TP#%u", (unsigned) desc->time_period_num);
+ tor_assert_nonfatal(!desc->ope_cipher);
+ desc->ope_cipher = generate_ope_cipher_for_desc(desc);
+
/* No need for extra strong, this is a temporary key only for this
* descriptor. Nothing long term. */
if (ed25519_keypair_generate(&desc->signing_kp, 0) < 0) {
@@ -1444,10 +1478,12 @@ build_service_descriptor(hs_service_t *service, time_t now,
tor_assert(desc_out);
desc = service_descriptor_new();
+
+ /* Set current time period */
desc->time_period_num = time_period_num;
/* Create the needed keys so we can setup the descriptor content. */
- if (build_service_desc_keys(service, desc, time_period_num) < 0) {
+ if (build_service_desc_keys(service, desc) < 0) {
goto err;
}
/* Setup plaintext descriptor content. */
@@ -1459,9 +1495,6 @@ build_service_descriptor(hs_service_t *service, time_t now,
goto err;
}
- /* Set the revision counter for this descriptor */
- set_descriptor_revision_counter(desc->desc);
-
/* Let's make sure that we've created a descriptor that can actually be
* encoded properly. This function also checks if the encoded output is
* decodable after. */
@@ -1627,8 +1660,12 @@ pick_intro_point(unsigned int direct_conn, smartlist_t *exclude_nodes)
tor_assert_nonfatal(!ed25519_public_key_is_zero(&info->ed_identity));
}
- /* Create our objects and populate them with the node information. */
- ip = service_intro_point_new(info, !node_supports_ed25519_hs_intro(node));
+ /* Create our objects and populate them with the node information.
+ * We don't care if the intro's link auth is compatible with us, because
+ * we are sending the ed25519 key to a remote client via the descriptor. */
+ ip = service_intro_point_new(info, !node_supports_ed25519_hs_intro(node),
+ node_supports_ed25519_link_authentication(node,
+ 0));
if (ip == NULL) {
goto err;
}
@@ -1769,7 +1806,6 @@ service_desc_schedule_upload(hs_service_descriptor_t *desc,
/* Update the given descriptor from the given service. The possible update
* actions includes:
* - Picking missing intro points if needed.
- * - Incrementing the revision counter if needed.
*/
static void
update_service_descriptor(hs_service_t *service,
@@ -1933,19 +1969,12 @@ cleanup_intro_points(hs_service_t *service, time_t now)
/* Set the next rotation time of the descriptors for the given service for the
* time now. */
static void
-set_rotation_time(hs_service_t *service, time_t now)
+set_rotation_time(hs_service_t *service)
{
- time_t valid_after;
- const networkstatus_t *ns = networkstatus_get_live_consensus(now);
- if (ns) {
- valid_after = ns->valid_after;
- } else {
- valid_after = now;
- }
-
tor_assert(service);
+
service->state.next_rotation_time =
- sr_state_get_start_time_of_current_protocol_run(valid_after) +
+ sr_state_get_start_time_of_current_protocol_run() +
sr_state_get_protocol_run_duration();
{
@@ -2012,7 +2041,7 @@ should_rotate_descriptors(hs_service_t *service, time_t now)
* will be freed, the next one put in as the current and finally the next
* descriptor pointer is NULLified. */
static void
-rotate_service_descriptors(hs_service_t *service, time_t now)
+rotate_service_descriptors(hs_service_t *service)
{
if (service->desc_current) {
/* Close all IP circuits for the descriptor. */
@@ -2027,7 +2056,7 @@ rotate_service_descriptors(hs_service_t *service, time_t now)
service->desc_next = NULL;
/* We've just rotated, set the next time for the rotation. */
- set_rotation_time(service, now);
+ set_rotation_time(service);
}
/* Rotate descriptors for each service if needed. A non existing current
@@ -2055,7 +2084,7 @@ rotate_all_descriptors(time_t now)
service->desc_current, service->desc_next,
safe_str_client(service->onion_address));
- rotate_service_descriptors(service, now);
+ rotate_service_descriptors(service);
} FOR_EACH_SERVICE_END;
}
@@ -2077,7 +2106,7 @@ run_housekeeping_event(time_t now)
/* Set the next rotation time of the descriptors. If it's Oct 25th
* 23:47:00, the next rotation time is when the next SRV is computed
* which is at Oct 26th 00:00:00 that is in 13 minutes. */
- set_rotation_time(service, now);
+ set_rotation_time(service);
}
/* Cleanup invalid intro points from the service descriptor. */
@@ -2326,13 +2355,17 @@ upload_descriptor_to_hsdir(const hs_service_t *service,
int is_next_desc = (service->desc_next == desc);
const uint8_t *idx = (is_next_desc) ? hsdir->hsdir_index.store_second:
hsdir->hsdir_index.store_first;
+ char *blinded_pubkey_log_str =
+ tor_strdup(hex_str((char*)&desc->blinded_kp.pubkey.pubkey, 32));
log_info(LD_REND, "Service %s %s descriptor of revision %" PRIu64
- " initiated upload request to %s with index %s",
+ " initiated upload request to %s with index %s (%s)",
safe_str_client(service->onion_address),
(is_next_desc) ? "next" : "current",
desc->desc->plaintext_data.revision_counter,
safe_str_client(node_describe(hsdir)),
- safe_str_client(hex_str((const char *) idx, 32)));
+ safe_str_client(hex_str((const char *) idx, 32)),
+ safe_str_client(blinded_pubkey_log_str));
+ tor_free(blinded_pubkey_log_str);
/* Fire a UPLOAD control port event. */
hs_control_desc_event_upload(service->onion_address, hsdir->identity,
@@ -2344,197 +2377,77 @@ upload_descriptor_to_hsdir(const hs_service_t *service,
return;
}
-/** Return a newly-allocated string for our state file which contains revision
- * counter information for <b>desc</b>. The format is:
+/** Set the revision counter in <b>hs_desc</b>. We do this by encrypting a
+ * timestamp using an OPE scheme and using the ciphertext as our revision
+ * counter.
*
- * HidServRevCounter <blinded_pubkey> <rev_counter>
- */
-STATIC char *
-encode_desc_rev_counter_for_state(const hs_service_descriptor_t *desc)
-{
- char *state_str = NULL;
- char blinded_pubkey_b64[ED25519_BASE64_LEN+1];
- uint64_t rev_counter = desc->desc->plaintext_data.revision_counter;
- const ed25519_public_key_t *blinded_pubkey = &desc->blinded_kp.pubkey;
-
- /* Turn the blinded key into b64 so that we save it on state */
- tor_assert(blinded_pubkey);
- if (ed25519_public_to_base64(blinded_pubkey_b64, blinded_pubkey) < 0) {
- goto done;
- }
-
- /* Format is: <blinded key> <rev counter> */
- tor_asprintf(&state_str, "%s %" PRIu64, blinded_pubkey_b64, rev_counter);
-
- log_info(LD_GENERAL, "[!] Adding rev counter %" PRIu64 " for %s!",
- rev_counter, blinded_pubkey_b64);
-
- done:
- return state_str;
-}
-
-/** Update HS descriptor revision counters in our state by removing the old
- * ones and writing down the ones that are currently active. */
+ * If <b>is_current</b> is true, then this is the current HS descriptor,
+ * otherwise it's the next one. */
static void
-update_revision_counters_in_state(void)
-{
- config_line_t *lines = NULL;
- config_line_t **nextline = &lines;
- or_state_t *state = get_or_state();
-
- /* Prepare our state structure with the rev counters */
- FOR_EACH_SERVICE_BEGIN(service) {
- FOR_EACH_DESCRIPTOR_BEGIN(service, desc) {
- /* We don't want to save zero counters */
- if (desc->desc->plaintext_data.revision_counter == 0) {
- continue;
- }
-
- *nextline = tor_malloc_zero(sizeof(config_line_t));
- (*nextline)->key = tor_strdup("HidServRevCounter");
- (*nextline)->value = encode_desc_rev_counter_for_state(desc);
- nextline = &(*nextline)->next;
- } FOR_EACH_DESCRIPTOR_END;
- } FOR_EACH_SERVICE_END;
-
- /* Remove the old rev counters, and replace them with the new ones */
- config_free_lines(state->HidServRevCounter);
- state->HidServRevCounter = lines;
-
- /* Set the state as dirty since we just edited it */
- if (!get_options()->AvoidDiskWrites) {
- or_state_mark_dirty(state, 0);
- }
-}
-
-/** Scan the string <b>state_line</b> for the revision counter of the service
- * with <b>blinded_pubkey</b>. Set <b>service_found_out</b> to True if the
- * line is relevant to this service, and return the cached revision
- * counter. Else set <b>service_found_out</b> to False. */
-STATIC uint64_t
-check_state_line_for_service_rev_counter(const char *state_line,
- const ed25519_public_key_t *blinded_pubkey,
- int *service_found_out)
+set_descriptor_revision_counter(hs_service_descriptor_t *hs_desc, time_t now,
+ bool is_current)
{
- smartlist_t *items = NULL;
- int ok;
- ed25519_public_key_t pubkey_in_state;
uint64_t rev_counter = 0;
- tor_assert(service_found_out);
- tor_assert(state_line);
- tor_assert(blinded_pubkey);
+ /* Get current time */
+ time_t srv_start = 0;
- /* Assume that the line is not for this service */
- *service_found_out = 0;
-
- /* Start parsing the state line */
- items = smartlist_new();
- smartlist_split_string(items, state_line, NULL,
- SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
- if (smartlist_len(items) < 2) {
- log_warn(LD_GENERAL, "Incomplete rev counter line. Ignoring.");
- goto done;
- }
-
- char *b64_key_str = smartlist_get(items, 0);
- char *saved_rev_counter_str = smartlist_get(items, 1);
-
- /* Parse blinded key to check if it's for this hidden service */
- if (ed25519_public_from_base64(&pubkey_in_state, b64_key_str) < 0) {
- log_warn(LD_GENERAL, "Unable to base64 key in revcount line. Ignoring.");
- goto done;
- }
- /* State line not for this hidden service */
- if (!ed25519_pubkey_eq(&pubkey_in_state, blinded_pubkey)) {
- goto done;
- }
-
- rev_counter = tor_parse_uint64(saved_rev_counter_str,
- 10, 0, UINT64_MAX, &ok, NULL);
- if (!ok) {
- log_warn(LD_GENERAL, "Unable to parse rev counter. Ignoring.");
- goto done;
+ /* As our revision counter plaintext value, we use the seconds since the
+ * start of the SR protocol run that is relevant to this descriptor. This is
+ * guaranteed to be a positive value since we need the SRV to start making a
+ * descriptor (so that we know where to upload it).
+ *
+ * Depending on whether we are building the current or the next descriptor,
+ * services use a different SRV value. See [SERVICEUPLOAD] in
+ * rend-spec-v3.txt:
+ *
+ * In particular, for the current descriptor (aka first descriptor), Tor
+ * always uses the previous SRV for uploading the descriptor, and hence we
+ * should use the start time of the previous protocol run here.
+ *
+ * Whereas for the next descriptor (aka second descriptor), Tor always uses
+ * the current SRV for uploading the descriptor. and hence we use the start
+ * time of the current protocol run.
+ */
+ if (is_current) {
+ srv_start = sr_state_get_start_time_of_previous_protocol_run();
+ } else {
+ srv_start = sr_state_get_start_time_of_current_protocol_run();
}
- /* Since we got this far, the line was for this service */
- *service_found_out = 1;
-
- log_info(LD_GENERAL, "Found rev counter for %s: %" PRIu64,
- b64_key_str, rev_counter);
-
- done:
- tor_assert(items);
- SMARTLIST_FOREACH(items, char*, s, tor_free(s));
- smartlist_free(items);
-
- return rev_counter;
-}
-
-/** Dig into our state file and find the current revision counter for the
- * service with blinded key <b>blinded_pubkey</b>. If no revision counter is
- * found, return 0. */
-static uint64_t
-get_rev_counter_for_service(const ed25519_public_key_t *blinded_pubkey)
-{
- or_state_t *state = get_or_state();
- config_line_t *line;
+ log_info(LD_REND, "Setting rev counter for TP #%u: "
+ "SRV started at %d, now %d (%s)",
+ (unsigned) hs_desc->time_period_num, (int)srv_start,
+ (int)now, is_current ? "current" : "next");
- /* Set default value for rev counters (if not found) to 0 */
- uint64_t final_rev_counter = 0;
+ tor_assert_nonfatal(now >= srv_start);
- for (line = state->HidServRevCounter ; line ; line = line->next) {
- int service_found = 0;
- uint64_t rev_counter = 0;
+ /* Compute seconds elapsed since the start of the time period. That's the
+ * number of seconds of how long this blinded key has been active. */
+ time_t seconds_since_start_of_srv = now - srv_start;
- tor_assert(!strcmp(line->key, "HidServRevCounter"));
+ /* Increment by one so that we are definitely sure this is strictly
+ * positive and not zero. */
+ seconds_since_start_of_srv++;
- /* Scan all the HidServRevCounter lines till we find the line for this
- service: */
- rev_counter = check_state_line_for_service_rev_counter(line->value,
- blinded_pubkey,
- &service_found);
- if (service_found) {
- final_rev_counter = rev_counter;
- goto done;
- }
+ /* Check for too big inputs. */
+ if (BUG(seconds_since_start_of_srv > OPE_INPUT_MAX)) {
+ seconds_since_start_of_srv = OPE_INPUT_MAX;
}
- done:
- return final_rev_counter;
-}
-
-/** Update the value of the revision counter for <b>hs_desc</b> and save it on
- our state file. */
-static void
-increment_descriptor_revision_counter(hs_descriptor_t *hs_desc)
-{
- /* Find stored rev counter if it exists */
- uint64_t rev_counter =
- get_rev_counter_for_service(&hs_desc->plaintext_data.blinded_pubkey);
+ /* Now we compute the final revision counter value by encrypting the
+ plaintext using our OPE cipher: */
+ tor_assert(hs_desc->ope_cipher);
+ rev_counter = crypto_ope_encrypt(hs_desc->ope_cipher,
+ (int) seconds_since_start_of_srv);
- /* Increment the revision counter of <b>hs_desc</b> so the next update (which
- * will trigger an upload) will have the right value. We do this at this
- * stage to only do it once because a descriptor can have many updates before
- * being uploaded. By doing it at upload, we are sure to only increment by 1
- * and thus avoid leaking how many operations we made on the descriptor from
- * the previous one before uploading. */
- rev_counter++;
- hs_desc->plaintext_data.revision_counter = rev_counter;
+ /* The OPE module returns CRYPTO_OPE_ERROR in case of errors. */
+ tor_assert_nonfatal(rev_counter < CRYPTO_OPE_ERROR);
- update_revision_counters_in_state();
-}
+ log_info(LD_REND, "Encrypted revision counter %d to %ld",
+ (int) seconds_since_start_of_srv, (long int) rev_counter);
-/** Set the revision counter in <b>hs_desc</b>, using the state file to find
- * the current counter value if it exists. */
-static void
-set_descriptor_revision_counter(hs_descriptor_t *hs_desc)
-{
- /* Find stored rev counter if it exists */
- uint64_t rev_counter =
- get_rev_counter_for_service(&hs_desc->plaintext_data.blinded_pubkey);
-
- hs_desc->plaintext_data.revision_counter = rev_counter;
+ hs_desc->desc->plaintext_data.revision_counter = rev_counter;
}
/* Encode and sign the service descriptor desc and upload it to the
@@ -2592,9 +2505,6 @@ upload_descriptor_to_all(const hs_service_t *service,
safe_str_client(service->onion_address), fmt_next_time);
}
- /* Update the revision counter of this descriptor */
- increment_descriptor_revision_counter(desc->desc);
-
smartlist_free(responsible_dirs);
return;
}
@@ -2734,6 +2644,10 @@ run_upload_descriptor_event(time_t now)
* accurate because all circuits have been established. */
build_desc_intro_points(service, desc, now);
+ /* Set the desc revision counter right before uploading */
+ set_descriptor_revision_counter(desc, approx_time(),
+ service->desc_current == desc);
+
upload_descriptor_to_all(service, desc);
} FOR_EACH_DESCRIPTOR_END;
} FOR_EACH_SERVICE_END;
diff --git a/src/feature/hs/hs_service.h b/src/feature/hs/hs_service.h
index 22bfcacc26..5c5443a35f 100644
--- a/src/feature/hs/hs_service.h
+++ b/src/feature/hs/hs_service.h
@@ -131,6 +131,10 @@ typedef struct hs_service_descriptor_t {
* from this list, this means we received new dirinfo and we need to
* reupload our descriptor. */
smartlist_t *previous_hsdirs;
+
+ /** The OPE cipher for encrypting revision counters for this descriptor.
+ * Tied to the descriptor blinded key. */
+ struct crypto_ope_t *ope_cipher;
} hs_service_descriptor_t;
/* Service key material. */
@@ -311,8 +315,9 @@ STATIC void remove_service(hs_service_ht *map, hs_service_t *service);
STATIC int register_service(hs_service_ht *map, hs_service_t *service);
/* Service introduction point functions. */
STATIC hs_service_intro_point_t *service_intro_point_new(
- const extend_info_t *ei,
- unsigned int is_legacy);
+ const extend_info_t *ei,
+ unsigned int is_legacy,
+ unsigned int supports_ed25519_link_handshake_any);
STATIC void service_intro_point_free_(hs_service_intro_point_t *ip);
#define service_intro_point_free(ip) \
FREE_AND_NULL(hs_service_intro_point_t, \
@@ -346,19 +351,10 @@ STATIC void build_all_descriptors(time_t now);
STATIC void update_all_descriptors(time_t now);
STATIC void run_upload_descriptor_event(time_t now);
-STATIC char *
-encode_desc_rev_counter_for_state(const hs_service_descriptor_t *desc);
-
STATIC void service_descriptor_free_(hs_service_descriptor_t *desc);
#define service_descriptor_free(d) \
FREE_AND_NULL(hs_service_descriptor_t, \
service_descriptor_free_, (d))
-
-STATIC uint64_t
-check_state_line_for_service_rev_counter(const char *state_line,
- const ed25519_public_key_t *blinded_pubkey,
- int *service_found_out);
-
STATIC int
write_address_to_file(const hs_service_t *service, const char *fname_);
@@ -375,4 +371,3 @@ STATIC int service_desc_hsdirs_changed(const hs_service_t *service,
#endif /* defined(HS_SERVICE_PRIVATE) */
#endif /* !defined(TOR_HS_SERVICE_H) */
-
diff --git a/src/feature/hs_common/shared_random_client.c b/src/feature/hs_common/shared_random_client.c
index 329f053d3b..ff98a719db 100644
--- a/src/feature/hs_common/shared_random_client.c
+++ b/src/feature/hs_common/shared_random_client.c
@@ -222,24 +222,44 @@ sr_parse_srv(const smartlist_t *args)
return srv;
}
-/** Return the start time of the current SR protocol run. For example, if the
- * time is 23/06/2017 23:47:08 and a full SR protocol run is 24 hours, this
- * function should return 23/06/2017 00:00:00. */
+/** Return the start time of the current SR protocol run using the times from
+ * the current consensus. For example, if the latest consensus valid-after is
+ * 23/06/2017 23:00:00 and a full SR protocol run is 24 hours, this function
+ * returns 23/06/2017 00:00:00. */
time_t
-sr_state_get_start_time_of_current_protocol_run(time_t now)
+sr_state_get_start_time_of_current_protocol_run(void)
{
int total_rounds = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
int voting_interval = get_voting_interval();
/* Find the time the current round started. */
- time_t beginning_of_current_round = get_start_time_of_current_round();
+ time_t beginning_of_curr_round = get_start_time_of_current_round();
/* Get current SR protocol round */
- int current_round = (now / voting_interval) % total_rounds;
+ int curr_round_slot;
+ curr_round_slot = (beginning_of_curr_round / voting_interval) % total_rounds;
/* Get start time by subtracting the time elapsed from the beginning of the
protocol run */
- time_t time_elapsed_since_start_of_run = current_round * voting_interval;
- return beginning_of_current_round - time_elapsed_since_start_of_run;
+ time_t time_elapsed_since_start_of_run = curr_round_slot * voting_interval;
+
+ log_debug(LD_GENERAL, "Current SRV proto run: Start of current round: %u. "
+ "Time elapsed: %u (%d)", (unsigned) beginning_of_curr_round,
+ (unsigned) time_elapsed_since_start_of_run, voting_interval);
+
+ return beginning_of_curr_round - time_elapsed_since_start_of_run;
+}
+
+/** Return the start time of the previous SR protocol run. See
+ * sr_state_get_start_time_of_current_protocol_run() for more details. */
+time_t
+sr_state_get_start_time_of_previous_protocol_run(void)
+{
+ time_t start_time_of_current_run =
+ sr_state_get_start_time_of_current_protocol_run();
+
+ /* We get the start time of previous protocol run, by getting the start time
+ * of current run and the subtracting a full protocol run from that. */
+ return start_time_of_current_run - sr_state_get_protocol_run_duration();
}
/** Return the time (in seconds) it takes to complete a full SR protocol phase
diff --git a/src/feature/hs_common/shared_random_client.h b/src/feature/hs_common/shared_random_client.h
index 497a015c18..0e26f530a4 100644
--- a/src/feature/hs_common/shared_random_client.h
+++ b/src/feature/hs_common/shared_random_client.h
@@ -34,7 +34,8 @@ sr_srv_t *sr_parse_srv(const smartlist_t *args);
/* Number of phase we have in a protocol. */
#define SHARED_RANDOM_N_PHASES 2
-time_t sr_state_get_start_time_of_current_protocol_run(time_t now);
+time_t sr_state_get_start_time_of_current_protocol_run(void);
+time_t sr_state_get_start_time_of_previous_protocol_run(void);
unsigned int sr_state_get_phase_duration(void);
unsigned int sr_state_get_protocol_run_duration(void);
time_t get_start_time_of_current_round(void);
diff --git a/src/feature/nodelist/networkstatus.c b/src/feature/nodelist/networkstatus.c
index e9d36cbdcb..6492b828b1 100644
--- a/src/feature/nodelist/networkstatus.c
+++ b/src/feature/nodelist/networkstatus.c
@@ -385,6 +385,11 @@ networkstatus_vote_free_(networkstatus_t *ns)
smartlist_free(ns->routerstatus_list);
}
+ if (ns->bw_file_headers) {
+ SMARTLIST_FOREACH(ns->bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(ns->bw_file_headers);
+ }
+
digestmap_free(ns->desc_digest_map, NULL);
if (ns->sr_info.commits) {
@@ -2417,6 +2422,8 @@ get_net_param_from_list(smartlist_t *net_params, const char *param_name,
res = max_val;
}
+ tor_assert(res >= min_val);
+ tor_assert(res <= max_val);
return res;
}
diff --git a/src/feature/nodelist/networkstatus_st.h b/src/feature/nodelist/networkstatus_st.h
index 46b0f53c0b..2bb0e3ae35 100644
--- a/src/feature/nodelist/networkstatus_st.h
+++ b/src/feature/nodelist/networkstatus_st.h
@@ -96,6 +96,9 @@ struct networkstatus_t {
/** Contains the shared random protocol data from a vote or consensus. */
networkstatus_sr_info_t sr_info;
+
+ /** List of key=value strings from the headers of the bandwidth list file */
+ smartlist_t *bw_file_headers;
};
#endif
diff --git a/src/feature/nodelist/parsecommon.c b/src/feature/nodelist/parsecommon.c
index 4f1c3fd421..3aaf8ac501 100644
--- a/src/feature/nodelist/parsecommon.c
+++ b/src/feature/nodelist/parsecommon.c
@@ -7,7 +7,7 @@
**/
#include "feature/nodelist/parsecommon.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/encoding/binascii.h"
#include "lib/container/smartlist.h"
diff --git a/src/feature/nodelist/routerlist.c b/src/feature/nodelist/routerlist.c
index 12226fee64..8b54329da9 100644
--- a/src/feature/nodelist/routerlist.c
+++ b/src/feature/nodelist/routerlist.c
@@ -123,6 +123,7 @@
#include "lib/sandbox/sandbox.h"
#include "feature/nodelist/torcert.h"
#include "lib/math/fp.h"
+#include "lib/net/resolve.h"
#include "feature/dirauth/dirvote.h"
#include "feature/dirauth/mode.h"
diff --git a/src/feature/nodelist/torcert.c b/src/feature/nodelist/torcert.c
index 172d4f9de3..a276082021 100644
--- a/src/feature/nodelist/torcert.c
+++ b/src/feature/nodelist/torcert.c
@@ -30,7 +30,7 @@
#include "lib/crypt_ops/crypto_util.h"
#include "feature/nodelist/torcert.h"
#include "trunnel/ed25519_cert.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "trunnel/link_handshake.h"
#include "lib/tls/tortls.h"
diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c
index 973d3e1100..0cc4887232 100644
--- a/src/feature/relay/router.c
+++ b/src/feature/relay/router.c
@@ -2686,6 +2686,9 @@ log_addr_has_changed(int severity,
char addrbuf_prev[TOR_ADDR_BUF_LEN];
char addrbuf_cur[TOR_ADDR_BUF_LEN];
+ if (BUG(!server_mode(get_options())))
+ return;
+
if (tor_addr_to_str(addrbuf_prev, prev, sizeof(addrbuf_prev), 1) == NULL)
strlcpy(addrbuf_prev, "???", TOR_ADDR_BUF_LEN);
if (tor_addr_to_str(addrbuf_cur, cur, sizeof(addrbuf_cur), 1) == NULL)
diff --git a/src/feature/rend/rendservice.c b/src/feature/rend/rendservice.c
index da4a98b3d1..1a99bd56ed 100644
--- a/src/feature/rend/rendservice.c
+++ b/src/feature/rend/rendservice.c
@@ -37,6 +37,7 @@
#include "feature/nodelist/routerparse.h"
#include "feature/nodelist/routerset.h"
#include "lib/encoding/confline.h"
+#include "lib/net/resolve.h"
#include "core/or/cpath_build_state_st.h"
#include "core/or/crypt_path_st.h"
diff --git a/src/lib/cc/compat_compiler.h b/src/lib/cc/compat_compiler.h
index 0f1acc381a..d45316b241 100644
--- a/src/lib/cc/compat_compiler.h
+++ b/src/lib/cc/compat_compiler.h
@@ -3,6 +3,12 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file compat_compiler.h
+ * \brief Utility macros to handle different features and behavior in different
+ * compilers.
+ **/
+
#ifndef TOR_COMPAT_COMPILER_H
#define TOR_COMPAT_COMPILER_H
diff --git a/src/lib/cc/torint.h b/src/lib/cc/torint.h
index 91db25833b..b97fc8d975 100644
--- a/src/lib/cc/torint.h
+++ b/src/lib/cc/torint.h
@@ -5,18 +5,13 @@
/**
* \file torint.h
- * \brief Header file to define uint32_t and friends
+ *
+ * \brief Integer definitions used throughout Tor.
**/
#ifndef TOR_TORINT_H
#define TOR_TORINT_H
-/**
- * \file torint.h
- *
- * \brief Integer definitions used throughout Tor.
- **/
-
#include "orconfig.h"
#include <stdint.h>
diff --git a/src/lib/compress/compress.c b/src/lib/compress/compress.c
index e87e788f14..2ad9b15b2e 100644
--- a/src/lib/compress/compress.c
+++ b/src/lib/compress/compress.c
@@ -22,7 +22,7 @@
#include <netinet/in.h>
#endif
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/arch/bytes.h"
#include "lib/ctime/di_ops.h"
@@ -32,7 +32,7 @@
#include "lib/compress/compress_zlib.h"
#include "lib/compress/compress_zstd.h"
#include "lib/intmath/cmp.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/thread/threads.h"
/** Total number of bytes allocated for compression state overhead. */
diff --git a/src/lib/compress/compress_lzma.c b/src/lib/compress/compress_lzma.c
index 3b6f91b84b..e6c8368f6a 100644
--- a/src/lib/compress/compress_lzma.c
+++ b/src/lib/compress/compress_lzma.c
@@ -15,9 +15,9 @@
#include "lib/compress/compress.h"
#include "lib/compress/compress_lzma.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/thread/threads.h"
#ifdef HAVE_LZMA
diff --git a/src/lib/compress/compress_none.c b/src/lib/compress/compress_none.c
index 9574c47a7e..a0e82d5a99 100644
--- a/src/lib/compress/compress_none.c
+++ b/src/lib/compress/compress_none.c
@@ -16,7 +16,7 @@
#include "orconfig.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/compress/compress.h"
#include "lib/compress/compress_none.h"
#include "lib/intmath/cmp.h"
diff --git a/src/lib/compress/compress_zlib.c b/src/lib/compress/compress_zlib.c
index 12e6727dee..64be1d4256 100644
--- a/src/lib/compress/compress_zlib.c
+++ b/src/lib/compress/compress_zlib.c
@@ -13,7 +13,7 @@
#include "orconfig.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/compress/compress.h"
#include "lib/compress/compress_zlib.h"
diff --git a/src/lib/compress/compress_zstd.c b/src/lib/compress/compress_zstd.c
index 0a553db55c..fe88d4a544 100644
--- a/src/lib/compress/compress_zstd.c
+++ b/src/lib/compress/compress_zstd.c
@@ -13,7 +13,7 @@
#include "orconfig.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/compress/compress.h"
#include "lib/compress/compress_zstd.h"
@@ -28,10 +28,14 @@
#endif
#ifdef HAVE_ZSTD
+#ifdef HAVE_CFLAG_WUNUSED_CONST_VARIABLE
DISABLE_GCC_WARNING(unused-const-variable)
+#endif
#include <zstd.h>
+#ifdef HAVE_CFLAG_WUNUSED_CONST_VARIABLE
ENABLE_GCC_WARNING(unused-const-variable)
#endif
+#endif
/** Total number of bytes allocated for Zstandard state. */
static atomic_counter_t total_zstd_allocation;
diff --git a/src/lib/container/bitarray.h b/src/lib/container/bitarray.h
index 172d56cc06..ae82a4ab4d 100644
--- a/src/lib/container/bitarray.h
+++ b/src/lib/container/bitarray.h
@@ -15,7 +15,7 @@
#include "orconfig.h"
#include <string.h>
#include "lib/cc/torint.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#if SIZEOF_INT == 4
#define BITARRAY_SHIFT 5
diff --git a/src/lib/container/bloomfilt.c b/src/lib/container/bloomfilt.c
index 1cab817e18..ea2d2917c7 100644
--- a/src/lib/container/bloomfilt.c
+++ b/src/lib/container/bloomfilt.c
@@ -10,7 +10,7 @@
#include <stdlib.h>
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/container/bloomfilt.h"
#include "lib/intmath/bits.h"
#include "lib/log/util_bug.h"
diff --git a/src/lib/container/buffers.c b/src/lib/container/buffers.c
index 5849704e35..87d782d7ef 100644
--- a/src/lib/container/buffers.c
+++ b/src/lib/container/buffers.c
@@ -27,10 +27,10 @@
#include <stddef.h>
#include "lib/container/buffers.h"
#include "lib/cc/torint.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/ctime/di_ops.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/string/printf.h"
#include "lib/time/compat_time.h"
diff --git a/src/lib/container/handles.h b/src/lib/container/handles.h
index 21ec0dfeec..7144e1720d 100644
--- a/src/lib/container/handles.h
+++ b/src/lib/container/handles.h
@@ -52,7 +52,7 @@
#include "orconfig.h"
#include "lib/log/util_bug.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#define HANDLE_ENTRY(name, structname) \
struct name ## _handle_head_t *handle_head
diff --git a/src/lib/container/map.c b/src/lib/container/map.c
index 0602eac891..85e074e10a 100644
--- a/src/lib/container/map.c
+++ b/src/lib/container/map.c
@@ -14,7 +14,7 @@
#include "lib/ctime/di_ops.h"
#include "lib/defs/digest_sizes.h"
#include "lib/string/util_string.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/log/util_bug.h"
diff --git a/src/lib/container/smartlist.c b/src/lib/container/smartlist.c
index c3abbff513..4b29d834d9 100644
--- a/src/lib/container/smartlist.c
+++ b/src/lib/container/smartlist.c
@@ -17,7 +17,7 @@
#include "lib/container/smartlist.h"
#include "lib/err/torerr.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/defs/digest_sizes.h"
#include "lib/ctime/di_ops.h"
#include "lib/string/compat_ctype.h"
@@ -189,6 +189,33 @@ smartlist_ints_eq(const smartlist_t *sl1, const smartlist_t *sl2)
return 1;
}
+/**
+ * Return true if there is shallow equality between smartlists -
+ * i.e. all indices correspond to exactly same object (pointer
+ * values are matching). Otherwise, return false.
+ */
+int
+smartlist_ptrs_eq(const smartlist_t *s1, const smartlist_t *s2)
+{
+ if (s1 == s2)
+ return 1;
+
+ // Note: pointers cannot both be NULL at this point, because
+ // above check.
+ if (s1 == NULL || s2 == NULL)
+ return 0;
+
+ if (smartlist_len(s1) != smartlist_len(s2))
+ return 0;
+
+ for (int i = 0; i < smartlist_len(s1); i++) {
+ if (smartlist_get(s1, i) != smartlist_get(s2, i))
+ return 0;
+ }
+
+ return 1;
+}
+
/** Return true iff <b>sl</b> has some element E such that
* tor_memeq(E,<b>element</b>,DIGEST_LEN)
*/
diff --git a/src/lib/container/smartlist.h b/src/lib/container/smartlist.h
index 3b19cbfce4..9705396ac9 100644
--- a/src/lib/container/smartlist.h
+++ b/src/lib/container/smartlist.h
@@ -37,6 +37,9 @@ int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2);
void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2);
void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2);
+int smartlist_ptrs_eq(const smartlist_t *s1,
+ const smartlist_t *s2);
+
void smartlist_sort(smartlist_t *sl,
int (*compare)(const void **a, const void **b));
void *smartlist_get_most_frequent_(const smartlist_t *sl,
diff --git a/src/lib/crypt_ops/aes.c b/src/lib/crypt_ops/aes.c
index a01b1e16b2..ff9d4d855c 100644
--- a/src/lib/crypt_ops/aes.c
+++ b/src/lib/crypt_ops/aes.c
@@ -38,7 +38,7 @@ DISABLE_GCC_WARNING(redundant-decls)
ENABLE_GCC_WARNING(redundant-decls)
#include "lib/crypt_ops/aes.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/ctime/di_ops.h"
#ifdef ANDROID
diff --git a/src/lib/crypt_ops/aes.h b/src/lib/crypt_ops/aes.h
index a57654159a..578a1a65a2 100644
--- a/src/lib/crypt_ops/aes.h
+++ b/src/lib/crypt_ops/aes.h
@@ -14,7 +14,7 @@
*/
#include "lib/cc/torint.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
typedef struct aes_cnt_cipher aes_cnt_cipher_t;
diff --git a/src/lib/crypt_ops/crypto.c b/src/lib/crypt_ops/crypto.c
index 48574016bf..5bc2da76ab 100644
--- a/src/lib/crypt_ops/crypto.c
+++ b/src/lib/crypt_ops/crypto.c
@@ -62,7 +62,7 @@ ENABLE_GCC_WARNING(redundant-decls)
#include <unistd.h>
#endif
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/cc/torint.h"
#include "lib/crypt_ops/aes.h"
diff --git a/src/lib/crypt_ops/crypto_curve25519.c b/src/lib/crypt_ops/crypto_curve25519.c
index 09f492e544..6ad2587f48 100644
--- a/src/lib/crypt_ops/crypto_curve25519.c
+++ b/src/lib/crypt_ops/crypto_curve25519.c
@@ -26,7 +26,7 @@
#include "lib/crypt_ops/crypto_format.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "ed25519/donna/ed25519_donna_tor.h"
diff --git a/src/lib/crypt_ops/crypto_curve25519.h b/src/lib/crypt_ops/crypto_curve25519.h
index acb36fde3b..1bab4a4197 100644
--- a/src/lib/crypt_ops/crypto_curve25519.h
+++ b/src/lib/crypt_ops/crypto_curve25519.h
@@ -1,6 +1,11 @@
/* Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file crypto_curve25519.h
+ * \brief Header for crypto_curve25519.c
+ **/
+
#ifndef TOR_CRYPTO_CURVE25519_H
#define TOR_CRYPTO_CURVE25519_H
diff --git a/src/lib/crypt_ops/crypto_dh.c b/src/lib/crypt_ops/crypto_dh.c
index c37e286daf..3e82996935 100644
--- a/src/lib/crypt_ops/crypto_dh.c
+++ b/src/lib/crypt_ops/crypto_dh.c
@@ -14,7 +14,7 @@
#include "lib/crypt_ops/crypto_digest.h"
#include "lib/crypt_ops/crypto_hkdf.h"
#include "lib/crypt_ops/crypto_util.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
DISABLE_GCC_WARNING(redundant-decls)
diff --git a/src/lib/crypt_ops/crypto_digest.c b/src/lib/crypt_ops/crypto_digest.c
index 949e694053..ee5c362e38 100644
--- a/src/lib/crypt_ops/crypto_digest.c
+++ b/src/lib/crypt_ops/crypto_digest.c
@@ -14,7 +14,7 @@
#include "lib/crypt_ops/crypto_digest.h"
#include "lib/crypt_ops/crypto_openssl_mgt.h"
#include "lib/crypt_ops/crypto_util.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "keccak-tiny/keccak-tiny.h"
diff --git a/src/lib/crypt_ops/crypto_digest.h b/src/lib/crypt_ops/crypto_digest.h
index 15bc5ad5b9..9facf3b981 100644
--- a/src/lib/crypt_ops/crypto_digest.h
+++ b/src/lib/crypt_ops/crypto_digest.h
@@ -15,7 +15,7 @@
#include "lib/cc/torint.h"
#include "lib/defs/digest_sizes.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
/** Length of a sha1 message digest when encoded in base32 with trailing =
* signs removed. */
diff --git a/src/lib/crypt_ops/crypto_ed25519.c b/src/lib/crypt_ops/crypto_ed25519.c
index 985652ecba..9d2c9e9fab 100644
--- a/src/lib/crypt_ops/crypto_ed25519.c
+++ b/src/lib/crypt_ops/crypto_ed25519.c
@@ -28,7 +28,7 @@
#include "lib/crypt_ops/crypto_format.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/encoding/binascii.h"
#include "lib/string/util_string.h"
diff --git a/src/lib/crypt_ops/crypto_ed25519.h b/src/lib/crypt_ops/crypto_ed25519.h
index 5ecd4530d8..03b3afe206 100644
--- a/src/lib/crypt_ops/crypto_ed25519.h
+++ b/src/lib/crypt_ops/crypto_ed25519.h
@@ -1,6 +1,11 @@
/* Copyright (c) 2012-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file crypto_ed25519.h
+ * \brief Header for crypto_ed25519.c
+ **/
+
#ifndef TOR_CRYPTO_ED25519_H
#define TOR_CRYPTO_ED25519_H
diff --git a/src/lib/crypt_ops/crypto_format.c b/src/lib/crypt_ops/crypto_format.c
index 8c71b265bf..50916a8d68 100644
--- a/src/lib/crypt_ops/crypto_format.c
+++ b/src/lib/crypt_ops/crypto_format.c
@@ -24,7 +24,7 @@
#include "lib/string/util_string.h"
#include "lib/string/printf.h"
#include "lib/encoding/binascii.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/fs/files.h"
diff --git a/src/lib/crypt_ops/crypto_format.h b/src/lib/crypt_ops/crypto_format.h
index 4a29b07b3b..a246071458 100644
--- a/src/lib/crypt_ops/crypto_format.h
+++ b/src/lib/crypt_ops/crypto_format.h
@@ -4,6 +4,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file crypto_format.h
+ * \brief Header for crypto_format.c
+ **/
+
#ifndef TOR_CRYPTO_FORMAT_H
#define TOR_CRYPTO_FORMAT_H
diff --git a/src/lib/crypt_ops/crypto_hkdf.c b/src/lib/crypt_ops/crypto_hkdf.c
index 0200d0fe9c..1873632a9d 100644
--- a/src/lib/crypt_ops/crypto_hkdf.c
+++ b/src/lib/crypt_ops/crypto_hkdf.c
@@ -19,9 +19,9 @@
#include <openssl/opensslv.h>
-#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0)
-#define HAVE_OPENSSL_HKDF 1
+#if defined(HAVE_ERR_LOAD_KDF_STRINGS)
#include <openssl/kdf.h>
+#define HAVE_OPENSSL_HKDF 1
#endif
#include <string.h>
diff --git a/src/lib/crypt_ops/crypto_ope.c b/src/lib/crypt_ops/crypto_ope.c
new file mode 100644
index 0000000000..ca42ae4341
--- /dev/null
+++ b/src/lib/crypt_ops/crypto_ope.c
@@ -0,0 +1,185 @@
+/* Copyright (c) 2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * A rudimentary order-preserving encryption scheme.
+ *
+ * To compute the encryption of N, this scheme uses an AES-CTR stream to
+ * generate M-byte values, and adds the first N of them together. (+1 each to
+ * insure that the ciphertexts are strictly decreasing.)
+ *
+ * We use this for generating onion service revision counters based on the
+ * current time, without leaking the amount of skew in our view of the current
+ * time. MUCH more analysis would be needed before using it for anything
+ * else!
+ */
+
+#include "orconfig.h"
+
+#define CRYPTO_OPE_PRIVATE
+#include "lib/crypt_ops/crypto_ope.h"
+#include "lib/crypt_ops/crypto.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/log/util_bug.h"
+#include "lib/malloc/malloc.h"
+#include "lib/arch/bytes.h"
+
+#include <string.h>
+
+/**
+ * How infrequent should the precomputed values be for this encryption?
+ * The choice of this value creates a space/time tradeoff.
+ *
+ * Note that this value must be a multiple of 16; see
+ * ope_get_cipher()
+ */
+#define SAMPLE_INTERVAL 1024
+/** Number of precomputed samples to make for each OPE key. */
+#define N_SAMPLES (OPE_INPUT_MAX / SAMPLE_INTERVAL)
+
+struct crypto_ope_t {
+ /** An AES key for use with this object. */
+ uint8_t key[OPE_KEY_LEN];
+ /** Cached intermediate encryption values at SAMPLE_INTERVAL,
+ * SAMPLE_INTERVAL*2,...SAMPLE_INTERVAL*N_SAMPLES */
+ uint64_t samples[N_SAMPLES];
+};
+
+/** The type to add up in order to produce our OPE ciphertexts */
+typedef uint16_t ope_val_t;
+
+#ifdef WORDS_BIG_ENDIAN
+/** Convert an OPE value to little-endian */
+static inline ope_val_t
+ope_val_to_le(ope_val_t x)
+{
+ return
+ ((x) >> 8) |
+ (((x)&0xff) << 8);
+}
+#else
+#define ope_val_to_le(x) (x)
+#endif
+
+/**
+ * Return a new AES256-CTR stream cipher object for <b>ope</b>, ready to yield
+ * bytes from the stream at position <b>initial_idx</b>.
+ *
+ * Note that because the index is converted directly to an IV, it must be a
+ * multiple of the AES block size (16).
+ */
+STATIC crypto_cipher_t *
+ope_get_cipher(const crypto_ope_t *ope, uint32_t initial_idx)
+{
+ uint8_t iv[CIPHER_IV_LEN];
+ tor_assert((initial_idx & 0xf) == 0);
+ uint32_t n = tor_htonl(initial_idx >> 4);
+ memset(iv, 0, sizeof(iv));
+ memcpy(iv + CIPHER_IV_LEN - sizeof(n), &n, sizeof(n));
+
+ return crypto_cipher_new_with_iv_and_bits(ope->key,
+ iv,
+ OPE_KEY_LEN * 8);
+}
+
+/**
+ * Retrieve and add the next <b>n</b> values from the stream cipher <b>c</b>,
+ * and return their sum.
+ *
+ * Note that values are taken in little-endian order (for performance on
+ * prevalent hardware), and are mapped from range 0..2^n-1 to range 1..2^n (so
+ * that each input encrypts to a different output).
+ *
+ * NOTE: this function is not constant-time.
+ */
+STATIC uint64_t
+sum_values_from_cipher(crypto_cipher_t *c, size_t n)
+{
+#define BUFSZ 256
+ ope_val_t buf[BUFSZ];
+ uint64_t total = 0;
+ unsigned i;
+ while (n >= BUFSZ) {
+ memset(buf, 0, sizeof(buf));
+ crypto_cipher_crypt_inplace(c, (char*)buf, BUFSZ*sizeof(ope_val_t));
+
+ for (i = 0; i < BUFSZ; ++i) {
+ total += ope_val_to_le(buf[i]);
+ total += 1;
+ }
+ n -= BUFSZ;
+ }
+
+ memset(buf, 0, n*sizeof(ope_val_t));
+ crypto_cipher_crypt_inplace(c, (char*)buf, n*sizeof(ope_val_t));
+ for (i = 0; i < n; ++i) {
+ total += ope_val_to_le(buf[i]);
+ total += 1;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ return total;
+}
+
+/**
+ * Return a new crypto_ope_t object, using the provided 256-bit key.
+ */
+crypto_ope_t *
+crypto_ope_new(const uint8_t *key)
+{
+ crypto_ope_t *ope = tor_malloc_zero(sizeof(crypto_ope_t));
+ memcpy(ope->key, key, OPE_KEY_LEN);
+
+ crypto_cipher_t *cipher = ope_get_cipher(ope, 0);
+
+ uint64_t v = 0;
+ int i;
+ for (i = 0; i < N_SAMPLES; ++i) {
+ v += sum_values_from_cipher(cipher, SAMPLE_INTERVAL);
+ ope->samples[i] = v;
+ }
+
+ crypto_cipher_free(cipher);
+ return ope;
+}
+
+/** Free all storage held in <>ope</b>. */
+void
+crypto_ope_free_(crypto_ope_t *ope)
+{
+ if (!ope)
+ return;
+ memwipe(ope, 0, sizeof(*ope));
+ tor_free(ope);
+}
+
+/**
+ * Return the encrypted value corresponding to <b>input</b>. The input value
+ * must be in range 1..OPE_INPUT_MAX. Returns CRYPTO_OPE_ERROR on an invalid
+ * input.
+ *
+ * NOTE: this function is not constant-time.
+ */
+uint64_t
+crypto_ope_encrypt(const crypto_ope_t *ope, int plaintext)
+{
+ if (plaintext <= 0 || plaintext > OPE_INPUT_MAX)
+ return CRYPTO_OPE_ERROR;
+
+ const int sample_idx = (plaintext / SAMPLE_INTERVAL);
+ const int starting_iv = sample_idx * SAMPLE_INTERVAL;
+ const int remaining_values = plaintext - starting_iv;
+ uint64_t v;
+ if (sample_idx == 0) {
+ v = 0;
+ } else {
+ v = ope->samples[sample_idx - 1];
+ }
+ crypto_cipher_t *cipher = ope_get_cipher(ope, starting_iv*sizeof(ope_val_t));
+
+ v += sum_values_from_cipher(cipher, remaining_values);
+
+ crypto_cipher_free(cipher);
+
+ return v;
+}
diff --git a/src/lib/crypt_ops/crypto_ope.h b/src/lib/crypt_ops/crypto_ope.h
new file mode 100644
index 0000000000..c62ed2a942
--- /dev/null
+++ b/src/lib/crypt_ops/crypto_ope.h
@@ -0,0 +1,46 @@
+/* Copyright (c) 2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef CRYPTO_OPE_H
+#define CRYPTO_OPE_H
+
+#include "orconfig.h"
+#include "lib/cc/torint.h"
+#include "lib/crypt_ops/crypto_ope.h"
+#include "lib/testsupport/testsupport.h"
+
+/** Length of OPE key, in bytes. */
+#define OPE_KEY_LEN 32
+
+/** Largest value that can be passed to crypto_ope_encrypt().
+ *
+ * Expressed as 2^18 because the OPE system prefers powers of two.
+ *
+ * The current max value stands for about 70 hours. The rationale here is as
+ * follows: The rev counter is the time of seconds since the start of an SRV
+ * period. SRVs are useful for about 48 hours (that's how long they stick
+ * around on the consensus). Let's also add 12 hours of drift for clock skewed
+ * services that might be using an old consensus and we arrive to 60
+ * hours. The max value should be beyond that.
+ */
+#define OPE_INPUT_MAX (1<<18)
+
+#define CRYPTO_OPE_ERROR UINT64_MAX
+
+typedef struct crypto_ope_t crypto_ope_t;
+
+crypto_ope_t *crypto_ope_new(const uint8_t *key);
+void crypto_ope_free_(crypto_ope_t *ope);
+#define crypto_ope_free(ope) \
+ FREE_AND_NULL(crypto_ope_t, crypto_ope_free_, (ope))
+
+uint64_t crypto_ope_encrypt(const crypto_ope_t *ope, int plaintext);
+
+#ifdef CRYPTO_OPE_PRIVATE
+struct aes_cnt_cipher;
+STATIC struct aes_cnt_cipher *ope_get_cipher(const crypto_ope_t *ope,
+ uint32_t initial_idx);
+STATIC uint64_t sum_values_from_cipher(struct aes_cnt_cipher *c, size_t n);
+#endif
+
+#endif
diff --git a/src/lib/crypt_ops/crypto_openssl_mgt.c b/src/lib/crypt_ops/crypto_openssl_mgt.c
index d1affa7258..01de6a9d9e 100644
--- a/src/lib/crypt_ops/crypto_openssl_mgt.c
+++ b/src/lib/crypt_ops/crypto_openssl_mgt.c
@@ -5,7 +5,7 @@
/* See LICENSE for licensing information */
/**
- * \file crypto_openssl.c
+ * \file crypto_openssl_mgt.c
*
* \brief Block of functions related to operations from OpenSSL.
**/
diff --git a/src/lib/crypt_ops/crypto_openssl_mgt.h b/src/lib/crypt_ops/crypto_openssl_mgt.h
index 8251f65ecf..a2c53302e1 100644
--- a/src/lib/crypt_ops/crypto_openssl_mgt.h
+++ b/src/lib/crypt_ops/crypto_openssl_mgt.h
@@ -5,9 +5,9 @@
/* See LICENSE for licensing information */
/**
- * \file crypto_openssl.h
+ * \file crypto_openssl_mgt.h
*
- * \brief Headers for crypto_openssl.c
+ * \brief Headers for crypto_openssl_mgt.c
**/
#ifndef TOR_CRYPTO_OPENSSL_H
diff --git a/src/lib/crypt_ops/crypto_rand.c b/src/lib/crypt_ops/crypto_rand.c
index 6f479b013b..fb9d0c2c6c 100644
--- a/src/lib/crypt_ops/crypto_rand.c
+++ b/src/lib/crypt_ops/crypto_rand.c
@@ -26,9 +26,9 @@
#include "lib/crypt_ops/crypto_util.h"
#include "lib/encoding/binascii.h"
#include "lib/intmath/weakrng.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/sandbox/sandbox.h"
#include "lib/string/compat_string.h"
#include "lib/string/util_string.h"
diff --git a/src/lib/crypt_ops/crypto_rsa.c b/src/lib/crypt_ops/crypto_rsa.c
index 9290414de0..5ec69d7319 100644
--- a/src/lib/crypt_ops/crypto_rsa.c
+++ b/src/lib/crypt_ops/crypto_rsa.c
@@ -36,7 +36,7 @@ DISABLE_GCC_WARNING(redundant-decls)
ENABLE_GCC_WARNING(redundant-decls)
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/encoding/binascii.h"
#include <string.h>
diff --git a/src/lib/crypt_ops/crypto_rsa.h b/src/lib/crypt_ops/crypto_rsa.h
index 093f2cec6c..51fc974821 100644
--- a/src/lib/crypt_ops/crypto_rsa.h
+++ b/src/lib/crypt_ops/crypto_rsa.h
@@ -18,7 +18,7 @@
#include "lib/crypt_ops/crypto_digest.h"
#include "lib/cc/torint.h"
#include "lib/testsupport/testsupport.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
/** Length of our public keys. */
#define PK_BYTES (1024/8)
diff --git a/src/lib/crypt_ops/crypto_util.c b/src/lib/crypt_ops/crypto_util.c
index 19b0885256..79988c6a91 100644
--- a/src/lib/crypt_ops/crypto_util.c
+++ b/src/lib/crypt_ops/crypto_util.c
@@ -31,7 +31,7 @@ DISABLE_GCC_WARNING(redundant-decls)
ENABLE_GCC_WARNING(redundant-decls)
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
/**
diff --git a/src/lib/crypt_ops/include.am b/src/lib/crypt_ops/include.am
index 1b88b880d0..017d7956d0 100644
--- a/src/lib/crypt_ops/include.am
+++ b/src/lib/crypt_ops/include.am
@@ -14,6 +14,7 @@ src_lib_libtor_crypt_ops_a_SOURCES = \
src/lib/crypt_ops/crypto_ed25519.c \
src/lib/crypt_ops/crypto_format.c \
src/lib/crypt_ops/crypto_hkdf.c \
+ src/lib/crypt_ops/crypto_ope.c \
src/lib/crypt_ops/crypto_openssl_mgt.c \
src/lib/crypt_ops/crypto_pwbox.c \
src/lib/crypt_ops/crypto_rand.c \
@@ -38,6 +39,7 @@ noinst_HEADERS += \
src/lib/crypt_ops/crypto.h \
src/lib/crypt_ops/crypto_hkdf.h \
src/lib/crypt_ops/crypto_openssl_mgt.h \
+ src/lib/crypt_ops/crypto_ope.h \
src/lib/crypt_ops/crypto_pwbox.h \
src/lib/crypt_ops/crypto_rand.h \
src/lib/crypt_ops/crypto_rsa.h \
diff --git a/src/lib/ctime/di_ops.c b/src/lib/ctime/di_ops.c
index 287ff6080a..011baf2654 100644
--- a/src/lib/ctime/di_ops.c
+++ b/src/lib/ctime/di_ops.c
@@ -9,7 +9,7 @@
#include "orconfig.h"
#include "lib/ctime/di_ops.h"
#include "lib/err/torerr.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include <string.h>
diff --git a/src/lib/defs/dh_sizes.h b/src/lib/defs/dh_sizes.h
index b60957281c..a02ffc5281 100644
--- a/src/lib/defs/dh_sizes.h
+++ b/src/lib/defs/dh_sizes.h
@@ -4,6 +4,15 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file dh_sizes.h
+
+ * \brief Definitions for sizes of Diffie-Hellman groups elements in Z_p.
+ *
+ * Tor uses these definitions throughout its codebase, even in parts that
+ * don't actually do any Diffie-Hellman calculations.
+ **/
+
#ifndef TOR_DH_SIZES_H
#define TOR_DH_SIZES_H
diff --git a/src/lib/defs/x25519_sizes.h b/src/lib/defs/x25519_sizes.h
index adaaab8c4d..d8ada46b97 100644
--- a/src/lib/defs/x25519_sizes.h
+++ b/src/lib/defs/x25519_sizes.h
@@ -4,6 +4,15 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file x25519_sizes.h
+
+ * \brief Definitions for sizes of x25519 keys and elements.
+ *
+ * Tor uses these definitions throughout its codebase, even in parts that
+ * don't actually do any x25519 calculations.
+ **/
+
#ifndef TOR_X25519_SIZES_H
#define TOR_X25519_SIZES_H
diff --git a/src/lib/encoding/binascii.c b/src/lib/encoding/binascii.c
index df9bb4a813..e9140d9432 100644
--- a/src/lib/encoding/binascii.c
+++ b/src/lib/encoding/binascii.c
@@ -14,12 +14,12 @@
#include "orconfig.h"
#include "lib/encoding/binascii.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/cc/torint.h"
#include "lib/string/compat_ctype.h"
#include "lib/intmath/muldiv.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include <stddef.h>
#include <string.h>
diff --git a/src/lib/encoding/confline.c b/src/lib/encoding/confline.c
index 3486b6a82b..dd5193d3a7 100644
--- a/src/lib/encoding/confline.c
+++ b/src/lib/encoding/confline.c
@@ -17,9 +17,9 @@
#include "lib/encoding/confline.h"
#include "lib/encoding/cstring.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/string/compat_ctype.h"
#include "lib/string/compat_string.h"
#include "lib/string/util_string.h"
diff --git a/src/lib/encoding/cstring.c b/src/lib/encoding/cstring.c
index 994a52e70c..69aa7f3da5 100644
--- a/src/lib/encoding/cstring.c
+++ b/src/lib/encoding/cstring.c
@@ -11,9 +11,9 @@
**/
#include "lib/encoding/cstring.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/string/compat_ctype.h"
#include <string.h>
diff --git a/src/lib/encoding/keyval.c b/src/lib/encoding/keyval.c
index 53ee776fe7..d5e4e4e438 100644
--- a/src/lib/encoding/keyval.c
+++ b/src/lib/encoding/keyval.c
@@ -12,7 +12,7 @@
#include "orconfig.h"
#include "lib/encoding/keyval.h"
#include "lib/log/escape.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include <stdlib.h>
diff --git a/src/lib/encoding/time_fmt.c b/src/lib/encoding/time_fmt.c
index c2ff34a91a..a921fc681c 100644
--- a/src/lib/encoding/time_fmt.c
+++ b/src/lib/encoding/time_fmt.c
@@ -15,13 +15,13 @@
**/
#include "lib/encoding/time_fmt.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/escape.h"
#include "lib/log/util_bug.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/string/printf.h"
#include "lib/string/scanf.h"
-#include "lib/wallclock/tm_cvt.h"
+#include "lib/wallclock/time_to_tm.h"
#include <string.h>
#include <time.h>
diff --git a/src/lib/evloop/compat_libevent.c b/src/lib/evloop/compat_libevent.c
index 5e5faf163c..2ee71c5598 100644
--- a/src/lib/evloop/compat_libevent.c
+++ b/src/lib/evloop/compat_libevent.c
@@ -11,7 +11,7 @@
#include "lib/evloop/compat_libevent.h"
#include "lib/crypt_ops/crypto_rand.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/string/compat_string.h"
diff --git a/src/lib/evloop/compat_libevent.h b/src/lib/evloop/compat_libevent.h
index 0a50cfa667..5fda49f741 100644
--- a/src/lib/evloop/compat_libevent.h
+++ b/src/lib/evloop/compat_libevent.h
@@ -1,12 +1,17 @@
/* Copyright (c) 2009-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file compat_libevent.h
+ * \brief Header for compat_libevent.c
+ **/
+
#ifndef TOR_COMPAT_LIBEVENT_H
#define TOR_COMPAT_LIBEVENT_H
#include "orconfig.h"
#include "lib/testsupport/testsupport.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
void configure_libevent_logging(void);
void suppress_libevent_log_msg(const char *msg);
diff --git a/src/lib/evloop/procmon.c b/src/lib/evloop/procmon.c
index a923fbad74..e0c26caab2 100644
--- a/src/lib/evloop/procmon.c
+++ b/src/lib/evloop/procmon.c
@@ -8,10 +8,10 @@
#include "lib/evloop/procmon.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/log/win32err.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/string/parse_int.h"
#ifdef HAVE_SIGNAL_H
diff --git a/src/lib/evloop/procmon.h b/src/lib/evloop/procmon.h
index b596e5cc6d..42c3788692 100644
--- a/src/lib/evloop/procmon.h
+++ b/src/lib/evloop/procmon.h
@@ -11,7 +11,7 @@
#include "lib/evloop/compat_libevent.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
typedef struct tor_process_monitor_t tor_process_monitor_t;
diff --git a/src/lib/evloop/timers.c b/src/lib/evloop/timers.c
index c07bd2e726..c4e85c7c93 100644
--- a/src/lib/evloop/timers.c
+++ b/src/lib/evloop/timers.c
@@ -34,9 +34,9 @@
#include "lib/evloop/compat_libevent.h"
#include "lib/evloop/timers.h"
#include "lib/intmath/muldiv.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/time/compat_time.h"
#ifdef _WIN32
diff --git a/src/lib/evloop/timers.h b/src/lib/evloop/timers.h
index 2348c7b7c1..4ffed1b458 100644
--- a/src/lib/evloop/timers.h
+++ b/src/lib/evloop/timers.h
@@ -1,6 +1,11 @@
/* Copyright (c) 2016-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file timers.h
+ * \brief Header for timers.c
+ **/
+
#ifndef TOR_TIMERS_H
#define TOR_TIMERS_H
@@ -28,4 +33,3 @@ STATIC void timers_run_pending(void);
#endif
#endif /* !defined(TOR_TIMERS_H) */
-
diff --git a/src/lib/evloop/token_bucket.h b/src/lib/evloop/token_bucket.h
index 787317fa1f..f004358f47 100644
--- a/src/lib/evloop/token_bucket.h
+++ b/src/lib/evloop/token_bucket.h
@@ -2,8 +2,8 @@
/* See LICENSE for licensing information */
/**
- * \file token_bucket_rw.h
- * \brief Headers for token_bucket_rw.c
+ * \file token_bucket.h
+ * \brief Headers for token_bucket.c
**/
#ifndef TOR_TOKEN_BUCKET_H
@@ -115,4 +115,3 @@ STATIC uint32_t rate_per_sec_to_rate_per_step(uint32_t rate);
#endif
#endif /* TOR_TOKEN_BUCKET_H */
-
diff --git a/src/lib/evloop/workqueue.c b/src/lib/evloop/workqueue.c
index 4d36f352e3..931f65e710 100644
--- a/src/lib/evloop/workqueue.c
+++ b/src/lib/evloop/workqueue.c
@@ -30,7 +30,7 @@
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/intmath/weakrng.h"
#include "lib/log/ratelim.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/net/alertsock.h"
#include "lib/net/socket.h"
diff --git a/src/lib/evloop/workqueue.h b/src/lib/evloop/workqueue.h
index 4e5c424be6..da292d1f05 100644
--- a/src/lib/evloop/workqueue.h
+++ b/src/lib/evloop/workqueue.h
@@ -1,6 +1,11 @@
/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file workqueue.h
+ * \brief Header for workqueue.c
+ **/
+
#ifndef TOR_WORKQUEUE_H
#define TOR_WORKQUEUE_H
diff --git a/src/lib/fs/.may_include b/src/lib/fs/.may_include
index 6c9ce6ca04..b1e49fc891 100644
--- a/src/lib/fs/.may_include
+++ b/src/lib/fs/.may_include
@@ -1,4 +1,7 @@
orconfig.h
+
+ext/getdelim.c
+
lib/cc/*.h
lib/container/*.h
lib/encoding/*.h
diff --git a/src/lib/fs/conffile.c b/src/lib/fs/conffile.c
index 600c7f6b70..d8622bff6b 100644
--- a/src/lib/fs/conffile.c
+++ b/src/lib/fs/conffile.c
@@ -17,8 +17,8 @@
#include "lib/fs/dir.h"
#include "lib/fs/files.h"
#include "lib/fs/path.h"
-#include "lib/log/torlog.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/log/log.h"
+#include "lib/malloc/malloc.h"
#include "lib/string/printf.h"
static smartlist_t *config_get_file_list(const char *path,
diff --git a/src/lib/fs/dir.c b/src/lib/fs/dir.c
index cc339f747e..6c24460005 100644
--- a/src/lib/fs/dir.c
+++ b/src/lib/fs/dir.c
@@ -14,12 +14,12 @@
#include "lib/fs/path.h"
#include "lib/fs/userdb.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/log/win32err.h"
#include "lib/container/smartlist.h"
#include "lib/sandbox/sandbox.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/string/printf.h"
#include "lib/string/compat_string.h"
diff --git a/src/lib/fs/files.c b/src/lib/fs/files.c
index 4e0a398baa..43dcbad333 100644
--- a/src/lib/fs/files.c
+++ b/src/lib/fs/files.c
@@ -16,11 +16,11 @@
#include "lib/fs/files.h"
#include "lib/fs/path.h"
#include "lib/container/smartlist.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/log/escape.h"
#include "lib/err/torerr.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/sandbox/sandbox.h"
#include "lib/string/printf.h"
#include "lib/string/util_string.h"
@@ -715,3 +715,7 @@ read_file_to_str, (const char *filename, int flags, struct stat *stat_out))
return string;
}
+
+#if !defined(HAVE_GETDELIM) || defined(TOR_UNIT_TESTS)
+#include "ext/getdelim.c"
+#endif
diff --git a/src/lib/fs/files.h b/src/lib/fs/files.h
index 5a12eb8215..2ee1b20149 100644
--- a/src/lib/fs/files.h
+++ b/src/lib/fs/files.h
@@ -103,4 +103,43 @@ char *read_file_to_str_until_eof(int fd, size_t max_bytes_to_read,
size_t *sz_out)
ATTR_MALLOC;
+#if !defined(HAVE_GETDELIM) || defined(TOR_UNIT_TESTS)
+/** Internal back-end function to implement getdelim(): only exists when
+ * Tor is built for unit tests, or when Tor is built on an operating system
+ * without its own getdelim(). */
+ssize_t compat_getdelim_(char **lineptr, size_t *n, int delim, FILE *stream);
+#endif
+
+#ifdef HAVE_GETDELIM
+/**
+ * Cross-platform wrapper for getdelim(): behaves as the POSIX-standard
+ * getdelim() function.
+ *
+ * See `getdelim(3)` for more information.
+ *
+ * Note that this function will use the libc memory allocator -- so any memory
+ * passed to this function must come from raw_malloc(), and must be freed by
+ * raw_free() -- don't use tor_malloc() and tor_free() with this.
+ */
+#define tor_getdelim(lineptr, n, delim, stream) \
+ getdelim((lineptr), (n), (delim), (stream))
+#else
+#define tor_getdelim(lineptr, n, delim, stream) \
+ compat_getdelim_((lineptr), (n), (delim), (stream))
+#endif
+
+#ifdef HAVE_GETLINE
+/**
+ * Cross-platform wrapper for getline(): behaves as the POSIX-standard
+ * getline() function.
+ *
+ * See tor_getdelim() for usage notes.
+ */
+#define tor_getline(lineptr, n, stream) \
+ getline((lineptr), (n), (stream))
+#else
+#define tor_getline(lineptr, n, stream) \
+ tor_getdelim((lineptr), (n), '\n', (stream))
+#endif
+
#endif
diff --git a/src/lib/fs/lockfile.c b/src/lib/fs/lockfile.c
index 972fd5658d..ca1711c344 100644
--- a/src/lib/fs/lockfile.c
+++ b/src/lib/fs/lockfile.c
@@ -13,9 +13,9 @@
#include "orconfig.h"
#include "lib/fs/files.h"
#include "lib/fs/lockfile.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
diff --git a/src/lib/fs/mmap.c b/src/lib/fs/mmap.c
index 2d758c1b5f..e7da6fc63a 100644
--- a/src/lib/fs/mmap.c
+++ b/src/lib/fs/mmap.c
@@ -11,11 +11,11 @@
#include "lib/fs/mmap.h"
#include "lib/fs/files.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/log/win32err.h"
#include "lib/string/compat_string.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#ifdef HAVE_MMAP
#include <sys/mman.h>
diff --git a/src/lib/fs/path.c b/src/lib/fs/path.c
index 708ff0505a..eb5170920c 100644
--- a/src/lib/fs/path.c
+++ b/src/lib/fs/path.c
@@ -10,8 +10,8 @@
**/
#include "lib/fs/path.h"
-#include "lib/malloc/util_malloc.h"
-#include "lib/log/torlog.h"
+#include "lib/malloc/malloc.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/string/printf.h"
#include "lib/string/util_string.h"
diff --git a/src/lib/fs/storagedir.c b/src/lib/fs/storagedir.c
index 1cda2374d8..014eb4d9eb 100644
--- a/src/lib/fs/storagedir.c
+++ b/src/lib/fs/storagedir.c
@@ -20,9 +20,9 @@
#include "lib/fs/files.h"
#include "lib/fs/mmap.h"
#include "lib/log/escape.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/memarea/memarea.h"
#include "lib/sandbox/sandbox.h"
#include "lib/string/printf.h"
diff --git a/src/lib/fs/userdb.c b/src/lib/fs/userdb.c
index 3d7a9da59d..df2935baa8 100644
--- a/src/lib/fs/userdb.c
+++ b/src/lib/fs/userdb.c
@@ -12,8 +12,8 @@
#include "lib/fs/userdb.h"
#ifndef _WIN32
-#include "lib/malloc/util_malloc.h"
-#include "lib/log/torlog.h"
+#include "lib/malloc/malloc.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include <pwd.h>
diff --git a/src/lib/lock/compat_mutex.c b/src/lib/lock/compat_mutex.c
index bfab6dd29b..b53676cf49 100644
--- a/src/lib/lock/compat_mutex.c
+++ b/src/lib/lock/compat_mutex.c
@@ -10,7 +10,7 @@
**/
#include "lib/lock/compat_mutex.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
/** Return a newly allocated, ready-for-use mutex. */
tor_mutex_t *
diff --git a/src/lib/lock/compat_mutex.h b/src/lib/lock/compat_mutex.h
index f467aa5dba..f8689422b1 100644
--- a/src/lib/lock/compat_mutex.h
+++ b/src/lib/lock/compat_mutex.h
@@ -14,7 +14,7 @@
#include "orconfig.h"
#include "lib/cc/torint.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#if defined(HAVE_PTHREAD_H) && !defined(_WIN32)
#include <pthread.h>
diff --git a/src/lib/log/escape.c b/src/lib/log/escape.c
index 7561710309..37d7e0fdc4 100644
--- a/src/lib/log/escape.c
+++ b/src/lib/log/escape.c
@@ -3,11 +3,16 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file escape.c
+ * \brief Escape untrusted strings before sending them to the log.
+ **/
+
#include "lib/log/escape.h"
#include "lib/log/util_bug.h"
#include "lib/string/compat_ctype.h"
#include "lib/string/printf.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
/** Allocate and return a new string representing the contents of <b>s</b>,
* surrounded by quotes and using standard C escapes.
diff --git a/src/lib/log/escape.h b/src/lib/log/escape.h
index 5d2e79d6c2..f47e7e004d 100644
--- a/src/lib/log/escape.h
+++ b/src/lib/log/escape.h
@@ -4,6 +4,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file escape.h
+ * \brief Header for escape.c
+ **/
+
#ifndef TOR_ESCAPE_H
#define TOR_ESCAPE_H
diff --git a/src/core/or/git_revision.c b/src/lib/log/git_revision.c
index 28ec1a7933..9d29ecd2a2 100644
--- a/src/core/or/git_revision.c
+++ b/src/lib/log/git_revision.c
@@ -3,7 +3,8 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "core/or/git_revision.h"
+#include "orconfig.h"
+#include "lib/log/git_revision.h"
/** String describing which Tor Git repository version the source was
* built from. This string is generated by a bit of shell kludging in
@@ -14,3 +15,10 @@ const char tor_git_revision[] =
#include "micro-revision.i"
#endif
"";
+
+const char tor_bug_suffix[] = " (on Tor " VERSION
+#ifndef _MSC_VER
+ " "
+#include "micro-revision.i"
+#endif
+ ")";
diff --git a/src/core/or/git_revision.h b/src/lib/log/git_revision.h
index 02070cfd5e..0ce1190795 100644
--- a/src/core/or/git_revision.h
+++ b/src/lib/log/git_revision.h
@@ -7,6 +7,6 @@
#define TOR_GIT_REVISION_H
extern const char tor_git_revision[];
+extern const char tor_bug_suffix[];
#endif /* !defined(TOR_GIT_REVISION_H) */
-
diff --git a/src/lib/log/include.am b/src/lib/log/include.am
index f0491b3863..4a6c9b3686 100644
--- a/src/lib/log/include.am
+++ b/src/lib/log/include.am
@@ -7,8 +7,9 @@ endif
src_lib_libtor_log_a_SOURCES = \
src/lib/log/escape.c \
+ src/lib/log/git_revision.c \
src/lib/log/ratelim.c \
- src/lib/log/torlog.c \
+ src/lib/log/log.c \
src/lib/log/util_bug.c
if WIN32
@@ -20,12 +21,16 @@ src_lib_libtor_log_testing_a_SOURCES = \
src_lib_libtor_log_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
src_lib_libtor_log_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
-src/lib/log/torlog.$(OBJEXT) \
- src/lib/log/src_lib_libtor_log_testing_a-torlog.$(OBJEXT): micro-revision.i
+# Declare that these object files depend on micro-revision.i. Without this
+# rule, we could try to build them before micro-revision.i was created.
+src/lib/log/git_revision.$(OBJEXT) \
+ src/lib/log/src_lib_libtor_log_testing_a-git_revision.$(OBJEXT): \
+ micro-revision.i
noinst_HEADERS += \
src/lib/log/escape.h \
+ src/lib/log/git_revision.h \
src/lib/log/ratelim.h \
- src/lib/log/torlog.h \
+ src/lib/log/log.h \
src/lib/log/util_bug.h \
src/lib/log/win32err.h
diff --git a/src/lib/log/torlog.c b/src/lib/log/log.c
index 1c9f33790d..e2514a341b 100644
--- a/src/lib/log/torlog.c
+++ b/src/lib/log/log.c
@@ -5,7 +5,7 @@
/* See LICENSE for licensing information */
/**
- * \file torlog.c
+ * \file log.c
* \brief Functions to send messages to log files or the console.
**/
@@ -31,7 +31,8 @@
#endif
#define LOG_PRIVATE
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
+#include "lib/log/git_revision.h"
#include "lib/log/ratelim.h"
#include "lib/lock/compat_mutex.h"
#include "lib/smartlist_core/smartlist_core.h"
@@ -41,11 +42,11 @@
#include "lib/intmath/bits.h"
#include "lib/string/compat_string.h"
#include "lib/string/printf.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/string/util_string.h"
#include "lib/wallclock/tor_gettimeofday.h"
#include "lib/wallclock/approx_time.h"
-#include "lib/wallclock/tm_cvt.h"
+#include "lib/wallclock/time_to_tm.h"
#include "lib/fdio/fdio.h"
#ifdef HAVE_ANDROID_LOG_H
@@ -353,13 +354,6 @@ log_tor_version(logfile_t *lf, int reset)
return 0;
}
-static const char bug_suffix[] = " (on Tor " VERSION
-#ifndef _MSC_VER
- " "
-#include "micro-revision.i"
-#endif
- ")";
-
/** Helper: Format a log message into a fixed-sized buffer. (This is
* factored out of <b>logv</b> so that we never format a message more
* than once.) Return a pointer to the first character of the message
@@ -442,9 +436,9 @@ format_msg(char *buf, size_t buf_len,
}
if (domain == LD_BUG &&
- buf_len - n > strlen(bug_suffix)+1) {
- memcpy(buf+n, bug_suffix, strlen(bug_suffix));
- n += strlen(bug_suffix);
+ buf_len - n > strlen(tor_bug_suffix)+1) {
+ memcpy(buf+n, tor_bug_suffix, strlen(tor_bug_suffix));
+ n += strlen(tor_bug_suffix);
}
buf[n]='\n';
diff --git a/src/lib/log/torlog.h b/src/lib/log/log.h
index c24b638191..493409756f 100644
--- a/src/lib/log/torlog.h
+++ b/src/lib/log/log.h
@@ -5,7 +5,7 @@
/* See LICENSE for licensing information */
/**
- * \file torlog.h
+ * \file log.h
*
* \brief Headers for log.c
**/
diff --git a/src/lib/log/ratelim.c b/src/lib/log/ratelim.c
index 677c499110..2d0e8b17ca 100644
--- a/src/lib/log/ratelim.c
+++ b/src/lib/log/ratelim.c
@@ -3,8 +3,13 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file ratelim.c
+ * \brief Summarize similar messages that would otherwise flood the logs.
+ **/
+
#include "lib/log/ratelim.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/string/printf.h"
/** If the rate-limiter <b>lim</b> is ready at <b>now</b>, return the number
diff --git a/src/lib/log/ratelim.h b/src/lib/log/ratelim.h
index 4ee6c5fed4..d423e10b85 100644
--- a/src/lib/log/ratelim.h
+++ b/src/lib/log/ratelim.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file ratelim.h
+ * \brief Summarize similar messages that would otherwise flood the logs.
+ **/
+
#ifndef TOR_RATELIM_H
#define TOR_RATELIM_H
diff --git a/src/lib/log/util_bug.c b/src/lib/log/util_bug.c
index 78af08f022..b23f4edc97 100644
--- a/src/lib/log/util_bug.c
+++ b/src/lib/log/util_bug.c
@@ -9,21 +9,17 @@
#include "orconfig.h"
#include "lib/log/util_bug.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/err/backtrace.h"
#ifdef TOR_UNIT_TESTS
#include "lib/smartlist_core/smartlist_core.h"
#include "lib/smartlist_core/smartlist_foreach.h"
#endif
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/string/printf.h"
#include <string.h>
-#ifdef __COVERITY__
-int bug_macro_deadcode_dummy__ = 0;
-#endif
-
#ifdef TOR_UNIT_TESTS
static void (*failed_assertion_cb)(void) = NULL;
static int n_bugs_to_capture = 0;
diff --git a/src/lib/log/util_bug.h b/src/lib/log/util_bug.h
index a0753c807b..44a4f8381c 100644
--- a/src/lib/log/util_bug.h
+++ b/src/lib/log/util_bug.h
@@ -38,7 +38,7 @@
#include "orconfig.h"
#include "lib/cc/compat_compiler.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/testsupport/testsupport.h"
/* Replace assert() with a variant that sends failures to the log before
@@ -86,13 +86,10 @@
*/
#ifdef __COVERITY__
-extern int bug_macro_deadcode_dummy__;
#undef BUG
// Coverity defines this in global headers; let's override it. This is a
// magic coverity-only preprocessor thing.
-// We use this "deadcode_dummy__" trick to prevent coverity from
-// complaining about unreachable bug cases.
-#nodef BUG(x) ((x)?(__coverity_panic__(),1):(0+bug_macro_deadcode_dummy__))
+#nodef BUG(x) (x)
#endif /* defined(__COVERITY__) */
#if defined(__COVERITY__) || defined(__clang_analyzer__)
diff --git a/src/lib/log/win32err.c b/src/lib/log/win32err.c
index 4586c23c84..41f563bfa5 100644
--- a/src/lib/log/win32err.c
+++ b/src/lib/log/win32err.c
@@ -3,10 +3,15 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file win32err.c
+ * \brief Convert windows error codes to useful C strings.
+ **/
+
#ifdef _WIN32
#include "orconfig.h"
#include "lib/log/win32err.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include <tchar.h>
#include <windows.h>
diff --git a/src/lib/log/win32err.h b/src/lib/log/win32err.h
index 61d3af57dd..92958c9879 100644
--- a/src/lib/log/win32err.h
+++ b/src/lib/log/win32err.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file win32err.h
+ * \brief Header for win32err.c
+ **/
+
#ifndef TOR_WIN32ERR_H
#define TOR_WIN32ERR_H
diff --git a/src/lib/malloc/include.am b/src/lib/malloc/include.am
index 50de9cb736..502cc1c6b7 100644
--- a/src/lib/malloc/include.am
+++ b/src/lib/malloc/include.am
@@ -6,7 +6,7 @@ noinst_LIBRARIES += src/lib/libtor-malloc-testing.a
endif
src_lib_libtor_malloc_a_SOURCES = \
- src/lib/malloc/util_malloc.c
+ src/lib/malloc/malloc.c
if USE_OPENBSD_MALLOC
src_lib_libtor_malloc_a_SOURCES += src/ext/OpenBSD_malloc_Linux.c
@@ -18,4 +18,4 @@ src_lib_libtor_malloc_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
src_lib_libtor_malloc_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
noinst_HEADERS += \
- src/lib/malloc/util_malloc.h
+ src/lib/malloc/malloc.h
diff --git a/src/lib/malloc/util_malloc.c b/src/lib/malloc/malloc.c
index f3b0e50c70..271e84071a 100644
--- a/src/lib/malloc/util_malloc.c
+++ b/src/lib/malloc/malloc.c
@@ -4,7 +4,7 @@
/* See LICENSE for licensing information */
/**
- * \file util_malloc.c
+ * \file malloc.c
* \brief Wrappers for C malloc code, and replacements for items that
* may be missing.
**/
@@ -16,7 +16,7 @@
#include "lib/testsupport/testsupport.h"
#define UTIL_MALLOC_PRIVATE
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/cc/torint.h"
#include "lib/err/torerr.h"
diff --git a/src/lib/malloc/util_malloc.h b/src/lib/malloc/malloc.h
index a1e9531176..26ee30742e 100644
--- a/src/lib/malloc/util_malloc.h
+++ b/src/lib/malloc/malloc.h
@@ -4,7 +4,7 @@
/* See LICENSE for licensing information */
/**
- * \file util_malloc.h
+ * \file malloc.h
* \brief Headers for util_malloc.c
**/
diff --git a/src/lib/memarea/memarea.c b/src/lib/memarea/memarea.c
index 9d494ab2d4..dd7c48c079 100644
--- a/src/lib/memarea/memarea.c
+++ b/src/lib/memarea/memarea.c
@@ -17,9 +17,9 @@
#include "lib/arch/bytes.h"
#include "lib/cc/torint.h"
#include "lib/container/smartlist.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#ifndef DISABLE_MEMORY_SENTINELS
diff --git a/src/lib/meminfo/meminfo.c b/src/lib/meminfo/meminfo.c
index b5a74ce624..648f54e0c5 100644
--- a/src/lib/meminfo/meminfo.c
+++ b/src/lib/meminfo/meminfo.c
@@ -15,8 +15,8 @@
#include "lib/cc/compat_compiler.h"
#include "lib/cc/torint.h"
#include "lib/fs/files.h"
-#include "lib/log/torlog.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/log/log.h"
+#include "lib/malloc/malloc.h"
#ifdef HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
diff --git a/src/lib/net/address.c b/src/lib/net/address.c
index f3eddca7bb..619fa13e9b 100644
--- a/src/lib/net/address.c
+++ b/src/lib/net/address.c
@@ -6,6 +6,9 @@
/**
* \file address.c
* \brief Functions to use and manipulate the tor_addr_t structure.
+ *
+ * This module doesn't have any support for the libc resolver: that is all in
+ * resolve.c.
**/
#define ADDRESS_PRIVATE
@@ -37,13 +40,12 @@
#include "lib/net/address.h"
#include "lib/net/socket.h"
-#include "lib/net/resolve.h"
#include "lib/container/smartlist.h"
#include "lib/ctime/di_ops.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/escape.h"
-#include "lib/malloc/util_malloc.h"
-#include "lib/net/ipv4.h"
+#include "lib/malloc/malloc.h"
+#include "lib/net/inaddr.h"
#include "lib/string/compat_ctype.h"
#include "lib/string/compat_string.h"
#include "lib/string/parse_int.h"
@@ -234,127 +236,6 @@ tor_addr_make_null(tor_addr_t *a, sa_family_t family)
a->family = family;
}
-/** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
- * *<b>addr</b> to the proper IP address and family. The <b>family</b>
- * argument (which must be AF_INET, AF_INET6, or AF_UNSPEC) declares a
- * <i>preferred</i> family, though another one may be returned if only one
- * family is implemented for this address.
- *
- * Return 0 on success, -1 on failure; 1 on transient failure.
- */
-MOCK_IMPL(int,
-tor_addr_lookup,(const char *name, uint16_t family, tor_addr_t *addr))
-{
- /* Perhaps eventually this should be replaced by a tor_getaddrinfo or
- * something.
- */
- struct in_addr iaddr;
- struct in6_addr iaddr6;
- tor_assert(name);
- tor_assert(addr);
- tor_assert(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
- if (!*name) {
- /* Empty address is an error. */
- return -1;
- } else if (tor_inet_pton(AF_INET, name, &iaddr)) {
- /* It's an IPv4 IP. */
- if (family == AF_INET6)
- return -1;
- tor_addr_from_in(addr, &iaddr);
- return 0;
- } else if (tor_inet_pton(AF_INET6, name, &iaddr6)) {
- if (family == AF_INET)
- return -1;
- tor_addr_from_in6(addr, &iaddr6);
- return 0;
- } else {
-#ifdef HAVE_GETADDRINFO
- int err;
- struct addrinfo *res=NULL, *res_p;
- struct addrinfo *best=NULL;
- struct addrinfo hints;
- int result = -1;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = family;
- hints.ai_socktype = SOCK_STREAM;
- err = tor_getaddrinfo(name, NULL, &hints, &res);
- /* The check for 'res' here shouldn't be necessary, but it makes static
- * analysis tools happy. */
- if (!err && res) {
- best = NULL;
- for (res_p = res; res_p; res_p = res_p->ai_next) {
- if (family == AF_UNSPEC) {
- if (res_p->ai_family == AF_INET) {
- best = res_p;
- break;
- } else if (res_p->ai_family == AF_INET6 && !best) {
- best = res_p;
- }
- } else if (family == res_p->ai_family) {
- best = res_p;
- break;
- }
- }
- if (!best)
- best = res;
- if (best->ai_family == AF_INET) {
- tor_addr_from_in(addr,
- &((struct sockaddr_in*)best->ai_addr)->sin_addr);
- result = 0;
- } else if (best->ai_family == AF_INET6) {
- tor_addr_from_in6(addr,
- &((struct sockaddr_in6*)best->ai_addr)->sin6_addr);
- result = 0;
- }
- tor_freeaddrinfo(res);
- return result;
- }
- return (err == EAI_AGAIN) ? 1 : -1;
-#else /* !(defined(HAVE_GETADDRINFO)) */
- struct hostent *ent;
- int err;
-#ifdef HAVE_GETHOSTBYNAME_R_6_ARG
- char buf[2048];
- struct hostent hostent;
- int r;
- r = gethostbyname_r(name, &hostent, buf, sizeof(buf), &ent, &err);
-#elif defined(HAVE_GETHOSTBYNAME_R_5_ARG)
- char buf[2048];
- struct hostent hostent;
- ent = gethostbyname_r(name, &hostent, buf, sizeof(buf), &err);
-#elif defined(HAVE_GETHOSTBYNAME_R_3_ARG)
- struct hostent_data data;
- struct hostent hent;
- memset(&data, 0, sizeof(data));
- err = gethostbyname_r(name, &hent, &data);
- ent = err ? NULL : &hent;
-#else
- ent = gethostbyname(name);
-#ifdef _WIN32
- err = WSAGetLastError();
-#else
- err = h_errno;
-#endif
-#endif /* defined(HAVE_GETHOSTBYNAME_R_6_ARG) || ... */
- if (ent) {
- if (ent->h_addrtype == AF_INET) {
- tor_addr_from_in(addr, (struct in_addr*) ent->h_addr);
- } else if (ent->h_addrtype == AF_INET6) {
- tor_addr_from_in6(addr, (struct in6_addr*) ent->h_addr);
- } else {
- tor_assert(0); // LCOV_EXCL_LINE: gethostbyname() returned bizarre type
- }
- return 0;
- }
-#ifdef _WIN32
- return (err == WSATRY_AGAIN) ? 1 : -1;
-#else
- return (err == TRY_AGAIN) ? 1 : -1;
-#endif
-#endif /* defined(HAVE_GETADDRINFO) */
- }
-}
-
/** Return true iff <b>ip</b> is an IP reserved to localhost or local networks
* in RFC1918 or RFC4193 or RFC4291. (fec0::/10, deprecated by RFC3879, is
* also treated as internal for now.)
@@ -1324,64 +1205,6 @@ tor_addr_parse(tor_addr_t *addr, const char *src)
return result;
}
-/** Parse an address or address-port combination from <b>s</b>, resolve the
- * address as needed, and put the result in <b>addr_out</b> and (optionally)
- * <b>port_out</b>. Return 0 on success, negative on failure. */
-int
-tor_addr_port_lookup(const char *s, tor_addr_t *addr_out, uint16_t *port_out)
-{
- const char *port;
- tor_addr_t addr;
- uint16_t portval;
- char *tmp = NULL;
-
- tor_assert(s);
- tor_assert(addr_out);
-
- s = eat_whitespace(s);
-
- if (*s == '[') {
- port = strstr(s, "]");
- if (!port)
- goto err;
- tmp = tor_strndup(s+1, port-(s+1));
- port = port+1;
- if (*port == ':')
- port++;
- else
- port = NULL;
- } else {
- port = strchr(s, ':');
- if (port)
- tmp = tor_strndup(s, port-s);
- else
- tmp = tor_strdup(s);
- if (port)
- ++port;
- }
-
- if (tor_addr_lookup(tmp, AF_UNSPEC, &addr) != 0)
- goto err;
- tor_free(tmp);
-
- if (port) {
- portval = (int) tor_parse_long(port, 10, 1, 65535, NULL, NULL);
- if (!portval)
- goto err;
- } else {
- portval = 0;
- }
-
- if (port_out)
- *port_out = portval;
- tor_addr_copy(addr_out, &addr);
-
- return 0;
- err:
- tor_free(tmp);
- return -1;
-}
-
#ifdef _WIN32
typedef ULONG (WINAPI *GetAdaptersAddresses_fn_t)(
ULONG, ULONG, PVOID, PIP_ADAPTER_ADDRESSES, PULONG);
@@ -1927,7 +1750,7 @@ tor_addr_port_split(int severity, const char *addrport,
tor_assert(addrport);
tor_assert(address_out);
tor_assert(port_out);
- /* We need to check for IPv6 manually because addr_port_lookup() doesn't
+ /* We need to check for IPv6 manually because the logic below doesn't
* do a good job on IPv6 addresses that lack a port. */
if (tor_addr_parse(&a_tmp, addrport) == AF_INET6) {
*port_out = 0;
@@ -1935,30 +1758,11 @@ tor_addr_port_split(int severity, const char *addrport,
return 0;
}
- return addr_port_lookup(severity, addrport, address_out, NULL, port_out);
-}
-
-/** Parse a string of the form "host[:port]" from <b>addrport</b>. If
- * <b>address</b> is provided, set *<b>address</b> to a copy of the
- * host portion of the string. If <b>addr</b> is provided, try to
- * resolve the host portion of the string and store it into
- * *<b>addr</b> (in host byte order). If <b>port_out</b> is provided,
- * store the port number into *<b>port_out</b>, or 0 if no port is given.
- * If <b>port_out</b> is NULL, then there must be no port number in
- * <b>addrport</b>.
- * Return 0 on success, -1 on failure.
- */
-int
-addr_port_lookup(int severity, const char *addrport, char **address,
- uint32_t *addr, uint16_t *port_out)
-{
const char *colon;
char *address_ = NULL;
int port_;
int ok = 1;
- tor_assert(addrport);
-
colon = strrchr(addrport, ':');
if (colon) {
address_ = tor_strndup(addrport, colon-addrport);
@@ -1980,22 +1784,13 @@ addr_port_lookup(int severity, const char *addrport, char **address,
port_ = 0;
}
- if (addr) {
- /* There's an addr pointer, so we need to resolve the hostname. */
- if (tor_lookup_hostname(address_,addr)) {
- log_fn(severity, LD_NET, "Couldn't look up %s", escaped(address_));
- ok = 0;
- *addr = 0;
- }
- }
-
- if (address && ok) {
- *address = address_;
+ if (ok) {
+ *address_out = address_;
} else {
- if (address)
- *address = NULL;
+ *address_out = NULL;
tor_free(address_);
}
+
if (port_out)
*port_out = ok ? ((uint16_t) port_) : 0;
diff --git a/src/lib/net/address.h b/src/lib/net/address.h
index f8ea573c30..e857b4068b 100644
--- a/src/lib/net/address.h
+++ b/src/lib/net/address.h
@@ -14,7 +14,7 @@
#include "orconfig.h"
#include "lib/cc/torint.h"
#include "lib/log/util_bug.h"
-#include "lib/net/ipv6.h"
+#include "lib/net/inaddr_st.h"
#include "lib/net/nettypes.h"
#ifdef HAVE_NETINET_IN_H
@@ -204,8 +204,6 @@ tor_addr_eq_ipv4h(const tor_addr_t *a, uint32_t u)
*/
#define TOR_ADDR_BUF_LEN 48
-MOCK_DECL(int, tor_addr_lookup,(const char *name, uint16_t family,
- tor_addr_t *addr_out));
char *tor_addr_to_str_dup(const tor_addr_t *addr) ATTR_MALLOC;
/** Wrapper function of fmt_addr_impl(). It does not decorate IPv6
@@ -263,9 +261,6 @@ int tor_addr_to_PTR_name(char *out, size_t outlen,
int tor_addr_parse_PTR_name(tor_addr_t *result, const char *address,
int family, int accept_regular);
-int tor_addr_port_lookup(const char *s, tor_addr_t *addr_out,
- uint16_t *port_out);
-
/* Does the address * yield an AF_UNSPEC wildcard address (1),
* which expands to corresponding wildcard IPv4 and IPv6 rules, and do we
* allow *4 and *6 for IPv4 and IPv6 wildcards, respectively;
@@ -330,8 +325,6 @@ int tor_addr_port_parse(int severity, const char *addrport,
int tor_addr_hostname_is_local(const char *name);
/* IPv4 helpers */
-int addr_port_lookup(int severity, const char *addrport, char **address,
- uint32_t *addr, uint16_t *port_out);
int parse_port_range(const char *port, uint16_t *port_min_out,
uint16_t *port_max_out);
int addr_mask_get_bits(uint32_t mask);
diff --git a/src/lib/net/buffers_net.c b/src/lib/net/buffers_net.c
index edc9954f22..c52ea2784e 100644
--- a/src/lib/net/buffers_net.c
+++ b/src/lib/net/buffers_net.c
@@ -4,10 +4,15 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file buffers_net.c
+ * \brief Read and write data on a buf_t object.
+ **/
+
#define BUFFERS_PRIVATE
#include "lib/net/buffers_net.h"
#include "lib/container/buffers.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/net/nettypes.h"
diff --git a/src/lib/net/gethostname.c b/src/lib/net/gethostname.c
index b6cc9b8e5f..1c4431af29 100644
--- a/src/lib/net/gethostname.c
+++ b/src/lib/net/gethostname.c
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file gethostname.c
+ * \brief Mockable wrapper for gethostname().
+ */
+
#include "orconfig.h"
#include "lib/net/gethostname.h"
diff --git a/src/lib/net/gethostname.h b/src/lib/net/gethostname.h
index d83c5fe096..7bf0ce5920 100644
--- a/src/lib/net/gethostname.h
+++ b/src/lib/net/gethostname.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file gethostname.h
+ * \brief Header for gethostname.c
+ **/
+
#ifndef TOR_GETHOSTNAME_H
#define TOR_GETHOSTNAME_H
diff --git a/src/lib/net/ipv6.c b/src/lib/net/inaddr.c
index 35d7ddb901..dcd8fcdd65 100644
--- a/src/lib/net/ipv6.c
+++ b/src/lib/net/inaddr.c
@@ -3,14 +3,21 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#include "lib/net/ipv6.h"
-#include "lib/net/ipv4.h"
-#include "lib/string/util_string.h"
-#include "lib/string/compat_string.h"
+/**
+ * \file inaddr.c
+ * \brief Convert in_addr and in6_addr to and from strings.
+ **/
+
+#include "lib/net/inaddr.h"
+
+#include "lib/cc/torint.h"
+#include "lib/log/util_bug.h"
+#include "lib/net/inaddr_st.h"
#include "lib/string/compat_ctype.h"
+#include "lib/string/compat_string.h"
#include "lib/string/printf.h"
#include "lib/string/scanf.h"
-#include "lib/log/util_bug.h"
+#include "lib/string/util_string.h"
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
@@ -19,6 +26,45 @@
#include <stdlib.h>
#include <string.h>
+#ifdef _WIN32
+#include <winsock2.h>
+#endif
+
+/** Set *addr to the IP address (in dotted-quad notation) stored in *str.
+ * Return 1 on success, 0 if *str is badly formatted.
+ * (Like inet_aton(str,addr), but works on Windows and Solaris.)
+ */
+int
+tor_inet_aton(const char *str, struct in_addr* addr)
+{
+ unsigned a,b,c,d;
+ char more;
+ if (tor_sscanf(str, "%3u.%3u.%3u.%3u%c", &a,&b,&c,&d,&more) != 4)
+ return 0;
+ if (a > 255) return 0;
+ if (b > 255) return 0;
+ if (c > 255) return 0;
+ if (d > 255) return 0;
+ addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d);
+ return 1;
+}
+
+/** Given an IPv4 in_addr struct *<b>in</b> (in network order, as usual),
+ * write it as a string into the <b>buf_len</b>-byte buffer in
+ * <b>buf</b>. Returns a non-negative integer on success.
+ * Returns -1 on failure.
+ */
+int
+tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len)
+{
+ uint32_t a = ntohl(in->s_addr);
+ return tor_snprintf(buf, buf_len, "%d.%d.%d.%d",
+ (int)(uint8_t)((a>>24)&0xff),
+ (int)(uint8_t)((a>>16)&0xff),
+ (int)(uint8_t)((a>>8 )&0xff),
+ (int)(uint8_t)((a )&0xff));
+}
+
/** Given <b>af</b>==AF_INET and <b>src</b> a struct in_addr, or
* <b>af</b>==AF_INET6 and <b>src</b> a struct in6_addr, try to format the
* address and store it in the <b>len</b>-byte buffer <b>dst</b>. Returns
diff --git a/src/lib/net/ipv4.h b/src/lib/net/inaddr.h
index 1ccc729970..121025a126 100644
--- a/src/lib/net/ipv4.h
+++ b/src/lib/net/inaddr.h
@@ -3,15 +3,25 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#ifndef TOR_IPV4_H
-#define TOR_IPV4_H
+/**
+ * \file inaddr.h
+ * \brief Header for inaddr.c.
+ **/
+#ifndef TOR_INADDR_H
+#define TOR_INADDR_H
+
+#include "orconfig.h"
#include <stddef.h>
struct in_addr;
+
int tor_inet_aton(const char *str, struct in_addr *addr);
/** Length of a buffer to allocate to hold the results of tor_inet_ntoa.*/
#define INET_NTOA_BUF_LEN 16
int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len);
+const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len);
+int tor_inet_pton(int af, const char *src, void *dst);
+
#endif
diff --git a/src/lib/net/ipv6.h b/src/lib/net/inaddr_st.h
index 0a12e046ac..dc4c6e3a00 100644
--- a/src/lib/net/ipv6.h
+++ b/src/lib/net/inaddr_st.h
@@ -3,21 +3,42 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#ifndef TOR_IPV6_H
-#define TOR_IPV6_H
+/**
+ * \file inaddr_st.h
+ *
+ * \brief Define in6_addr, its members, and related types on platforms that
+ * lack it.
+ **/
+
+#ifndef TOR_INADDR_ST_H
+#define TOR_INADDR_ST_H
#include "orconfig.h"
#include <stddef.h>
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
#ifdef HAVE_NETINET_IN6_H
#include <netinet/in6.h>
#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#endif
+
#include "lib/cc/torint.h"
+struct in_addr;
+
/** Implementation of struct in6_addr for platforms that do not have it.
* Generally, these platforms are ones without IPv6 support, but we want to
* have a working in6_addr there anyway, so we can use it to parse IPv6
@@ -80,7 +101,4 @@ struct sockaddr_in6 {
};
#endif /* !defined(HAVE_STRUCT_SOCKADDR_IN6) */
-const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len);
-int tor_inet_pton(int af, const char *src, void *dst);
-
-#endif
+#endif /* TOR_INADDR_ST_H */
diff --git a/src/lib/net/include.am b/src/lib/net/include.am
index 6fda173614..67db0d5af2 100644
--- a/src/lib/net/include.am
+++ b/src/lib/net/include.am
@@ -10,8 +10,7 @@ src_lib_libtor_net_a_SOURCES = \
src/lib/net/alertsock.c \
src/lib/net/buffers_net.c \
src/lib/net/gethostname.c \
- src/lib/net/ipv4.c \
- src/lib/net/ipv6.c \
+ src/lib/net/inaddr.c \
src/lib/net/resolve.c \
src/lib/net/socket.c
@@ -25,8 +24,8 @@ noinst_HEADERS += \
src/lib/net/alertsock.h \
src/lib/net/buffers_net.h \
src/lib/net/gethostname.h \
- src/lib/net/ipv4.h \
- src/lib/net/ipv6.h \
+ src/lib/net/inaddr.h \
+ src/lib/net/inaddr_st.h \
src/lib/net/nettypes.h \
src/lib/net/resolve.h \
src/lib/net/socket.h \
diff --git a/src/lib/net/ipv4.c b/src/lib/net/ipv4.c
deleted file mode 100644
index 18e69761e2..0000000000
--- a/src/lib/net/ipv4.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#include "orconfig.h"
-#include "lib/cc/torint.h"
-#include "lib/net/ipv4.h"
-#include "lib/string/printf.h"
-#include "lib/string/scanf.h"
-
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef _WIN32
-#include <winsock2.h>
-#endif
-
-/** Set *addr to the IP address (in dotted-quad notation) stored in *str.
- * Return 1 on success, 0 if *str is badly formatted.
- * (Like inet_aton(str,addr), but works on Windows and Solaris.)
- */
-int
-tor_inet_aton(const char *str, struct in_addr* addr)
-{
- unsigned a,b,c,d;
- char more;
- if (tor_sscanf(str, "%3u.%3u.%3u.%3u%c", &a,&b,&c,&d,&more) != 4)
- return 0;
- if (a > 255) return 0;
- if (b > 255) return 0;
- if (c > 255) return 0;
- if (d > 255) return 0;
- addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d);
- return 1;
-}
-
-/** Given an IPv4 in_addr struct *<b>in</b> (in network order, as usual),
- * write it as a string into the <b>buf_len</b>-byte buffer in
- * <b>buf</b>. Returns a non-negative integer on success.
- * Returns -1 on failure.
- */
-int
-tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len)
-{
- uint32_t a = ntohl(in->s_addr);
- return tor_snprintf(buf, buf_len, "%d.%d.%d.%d",
- (int)(uint8_t)((a>>24)&0xff),
- (int)(uint8_t)((a>>16)&0xff),
- (int)(uint8_t)((a>>8 )&0xff),
- (int)(uint8_t)((a )&0xff));
-}
diff --git a/src/lib/net/nettypes.h b/src/lib/net/nettypes.h
index f212374368..f7f2ec7d6a 100644
--- a/src/lib/net/nettypes.h
+++ b/src/lib/net/nettypes.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file nettypes.h
+ * \brief Declarations for types used throughout the Tor networking system
+ **/
+
#ifndef TOR_NET_TYPES_H
#define TOR_NET_TYPES_H
diff --git a/src/lib/net/resolve.c b/src/lib/net/resolve.c
index cbe368ccfb..7c8df3e307 100644
--- a/src/lib/net/resolve.c
+++ b/src/lib/net/resolve.c
@@ -3,9 +3,18 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file resolve.c
+ * \brief Use the libc DNS resolver to convert hostnames into addresses.
+ **/
+
#include "lib/net/resolve.h"
+
#include "lib/net/address.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/net/inaddr.h"
+#include "lib/malloc/malloc.h"
+#include "lib/string/parse_int.h"
+#include "lib/string/util_string.h"
#include "siphash.h"
#include "ht.h"
@@ -47,6 +56,185 @@ tor_lookup_hostname,(const char *name, uint32_t *addr))
return -1;
}
+/** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
+ * *<b>addr</b> to the proper IP address and family. The <b>family</b>
+ * argument (which must be AF_INET, AF_INET6, or AF_UNSPEC) declares a
+ * <i>preferred</i> family, though another one may be returned if only one
+ * family is implemented for this address.
+ *
+ * Return 0 on success, -1 on failure; 1 on transient failure.
+ */
+MOCK_IMPL(int,
+tor_addr_lookup,(const char *name, uint16_t family, tor_addr_t *addr))
+{
+ /* Perhaps eventually this should be replaced by a tor_getaddrinfo or
+ * something.
+ */
+ struct in_addr iaddr;
+ struct in6_addr iaddr6;
+ tor_assert(name);
+ tor_assert(addr);
+ tor_assert(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
+ if (!*name) {
+ /* Empty address is an error. */
+ return -1;
+ } else if (tor_inet_pton(AF_INET, name, &iaddr)) {
+ /* It's an IPv4 IP. */
+ if (family == AF_INET6)
+ return -1;
+ tor_addr_from_in(addr, &iaddr);
+ return 0;
+ } else if (tor_inet_pton(AF_INET6, name, &iaddr6)) {
+ if (family == AF_INET)
+ return -1;
+ tor_addr_from_in6(addr, &iaddr6);
+ return 0;
+ } else {
+#ifdef HAVE_GETADDRINFO
+ int err;
+ struct addrinfo *res=NULL, *res_p;
+ struct addrinfo *best=NULL;
+ struct addrinfo hints;
+ int result = -1;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = SOCK_STREAM;
+ err = tor_getaddrinfo(name, NULL, &hints, &res);
+ /* The check for 'res' here shouldn't be necessary, but it makes static
+ * analysis tools happy. */
+ if (!err && res) {
+ best = NULL;
+ for (res_p = res; res_p; res_p = res_p->ai_next) {
+ if (family == AF_UNSPEC) {
+ if (res_p->ai_family == AF_INET) {
+ best = res_p;
+ break;
+ } else if (res_p->ai_family == AF_INET6 && !best) {
+ best = res_p;
+ }
+ } else if (family == res_p->ai_family) {
+ best = res_p;
+ break;
+ }
+ }
+ if (!best)
+ best = res;
+ if (best->ai_family == AF_INET) {
+ tor_addr_from_in(addr,
+ &((struct sockaddr_in*)best->ai_addr)->sin_addr);
+ result = 0;
+ } else if (best->ai_family == AF_INET6) {
+ tor_addr_from_in6(addr,
+ &((struct sockaddr_in6*)best->ai_addr)->sin6_addr);
+ result = 0;
+ }
+ tor_freeaddrinfo(res);
+ return result;
+ }
+ return (err == EAI_AGAIN) ? 1 : -1;
+#else /* !(defined(HAVE_GETADDRINFO)) */
+ struct hostent *ent;
+ int err;
+#ifdef HAVE_GETHOSTBYNAME_R_6_ARG
+ char buf[2048];
+ struct hostent hostent;
+ int r;
+ r = gethostbyname_r(name, &hostent, buf, sizeof(buf), &ent, &err);
+#elif defined(HAVE_GETHOSTBYNAME_R_5_ARG)
+ char buf[2048];
+ struct hostent hostent;
+ ent = gethostbyname_r(name, &hostent, buf, sizeof(buf), &err);
+#elif defined(HAVE_GETHOSTBYNAME_R_3_ARG)
+ struct hostent_data data;
+ struct hostent hent;
+ memset(&data, 0, sizeof(data));
+ err = gethostbyname_r(name, &hent, &data);
+ ent = err ? NULL : &hent;
+#else
+ ent = gethostbyname(name);
+#ifdef _WIN32
+ err = WSAGetLastError();
+#else
+ err = h_errno;
+#endif
+#endif /* defined(HAVE_GETHOSTBYNAME_R_6_ARG) || ... */
+ if (ent) {
+ if (ent->h_addrtype == AF_INET) {
+ tor_addr_from_in(addr, (struct in_addr*) ent->h_addr);
+ } else if (ent->h_addrtype == AF_INET6) {
+ tor_addr_from_in6(addr, (struct in6_addr*) ent->h_addr);
+ } else {
+ tor_assert(0); // LCOV_EXCL_LINE: gethostbyname() returned bizarre type
+ }
+ return 0;
+ }
+#ifdef _WIN32
+ return (err == WSATRY_AGAIN) ? 1 : -1;
+#else
+ return (err == TRY_AGAIN) ? 1 : -1;
+#endif
+#endif /* defined(HAVE_GETADDRINFO) */
+ }
+}
+
+/** Parse an address or address-port combination from <b>s</b>, resolve the
+ * address as needed, and put the result in <b>addr_out</b> and (optionally)
+ * <b>port_out</b>. Return 0 on success, negative on failure. */
+int
+tor_addr_port_lookup(const char *s, tor_addr_t *addr_out, uint16_t *port_out)
+{
+ const char *port;
+ tor_addr_t addr;
+ uint16_t portval;
+ char *tmp = NULL;
+
+ tor_assert(s);
+ tor_assert(addr_out);
+
+ s = eat_whitespace(s);
+
+ if (*s == '[') {
+ port = strstr(s, "]");
+ if (!port)
+ goto err;
+ tmp = tor_strndup(s+1, port-(s+1));
+ port = port+1;
+ if (*port == ':')
+ port++;
+ else
+ port = NULL;
+ } else {
+ port = strchr(s, ':');
+ if (port)
+ tmp = tor_strndup(s, port-s);
+ else
+ tmp = tor_strdup(s);
+ if (port)
+ ++port;
+ }
+
+ if (tor_addr_lookup(tmp, AF_UNSPEC, &addr) != 0)
+ goto err;
+ tor_free(tmp);
+
+ if (port) {
+ portval = (int) tor_parse_long(port, 10, 1, 65535, NULL, NULL);
+ if (!portval)
+ goto err;
+ } else {
+ portval = 0;
+ }
+
+ if (port_out)
+ *port_out = portval;
+ tor_addr_copy(addr_out, &addr);
+
+ return 0;
+ err:
+ tor_free(tmp);
+ return -1;
+}
+
#ifdef USE_SANDBOX_GETADDRINFO
/** True if we should only return cached values */
static int sandbox_getaddrinfo_is_active = 0;
diff --git a/src/lib/net/resolve.h b/src/lib/net/resolve.h
index f2280ae7e8..bf870c44c4 100644
--- a/src/lib/net/resolve.h
+++ b/src/lib/net/resolve.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file resolve.h
+ * \brief Header for resolve.c
+ **/
+
#ifndef TOR_RESOLVE_H
#define TOR_RESOLVE_H
@@ -17,7 +22,13 @@
#define USE_SANDBOX_GETADDRINFO
#endif
-MOCK_DECL(int,tor_lookup_hostname,(const char *name, uint32_t *addr));
+struct tor_addr_t;
+
+MOCK_DECL(int, tor_lookup_hostname,(const char *name, uint32_t *addr));
+MOCK_DECL(int, tor_addr_lookup,(const char *name, uint16_t family,
+ struct tor_addr_t *addr_out));
+int tor_addr_port_lookup(const char *s, struct tor_addr_t *addr_out,
+ uint16_t *port_out);
struct addrinfo;
#ifdef USE_SANDBOX_GETADDRINFO
diff --git a/src/lib/net/socket.c b/src/lib/net/socket.c
index dc3d1531ff..5847bb8734 100644
--- a/src/lib/net/socket.c
+++ b/src/lib/net/socket.c
@@ -3,13 +3,19 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file socket.c
+ * \brief Compatibility and utility functions for working with network
+ * sockets.
+ **/
+
#define SOCKET_PRIVATE
#include "lib/net/socket.h"
#include "lib/net/address.h"
#include "lib/cc/compat_compiler.h"
#include "lib/err/torerr.h"
#include "lib/lock/compat_mutex.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#ifdef _WIN32
diff --git a/src/lib/net/socket.h b/src/lib/net/socket.h
index cb0ccbe817..e2092c727a 100644
--- a/src/lib/net/socket.h
+++ b/src/lib/net/socket.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file socket.h
+ * \brief Header for socket.c
+ **/
+
#ifndef TOR_SOCKET_H
#define TOR_SOCKET_H
diff --git a/src/lib/net/socks5_status.h b/src/lib/net/socks5_status.h
index 74b9c91023..0f31132545 100644
--- a/src/lib/net/socks5_status.h
+++ b/src/lib/net/socks5_status.h
@@ -3,6 +3,16 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file socks5_status.h
+ * \brief Status codes used by the SOCKS5 protocol.
+ **/
+
+/* NOTE: it probably isn't necessary to put this header in lib/net, but
+ * we need it in _some_ lower-level layer for now, since it is used by
+ * tools/tor-resolve.c.
+ */
+
#ifndef TOR_SOCKS5_STATUS_H
#define TOR_SOCKS5_STATUS_H
diff --git a/src/lib/osinfo/uname.c b/src/lib/osinfo/uname.c
index a0fa26d1d2..9d1923695d 100644
--- a/src/lib/osinfo/uname.c
+++ b/src/lib/osinfo/uname.c
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file uname.c
+ * \brief Look up a description of the operating system.
+ **/
+
#include "orconfig.h"
#include "lib/osinfo/uname.h"
diff --git a/src/lib/osinfo/uname.h b/src/lib/osinfo/uname.h
index 1f0b78385f..ef8cd078ee 100644
--- a/src/lib/osinfo/uname.h
+++ b/src/lib/osinfo/uname.h
@@ -1,3 +1,12 @@
+/* Copyright (c) 2003-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 uname.h
+ * \brief Header for uname.c
+ **/
#ifndef HAVE_TOR_UNAME_H
#define HAVE_TOR_UNAME_H
diff --git a/src/lib/process/daemon.c b/src/lib/process/daemon.c
index edffb04683..671579838e 100644
--- a/src/lib/process/daemon.c
+++ b/src/lib/process/daemon.c
@@ -3,13 +3,18 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file daemon.c
+ * \brief Run the tor process in the background (unix only)
+ **/
+
#include "orconfig.h"
#include "lib/process/daemon.h"
#ifndef _WIN32
#include "lib/fs/files.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/thread/threads.h"
#ifdef HAVE_SYS_TYPES_H
diff --git a/src/lib/process/daemon.h b/src/lib/process/daemon.h
index 48a65b22e6..1f26e92221 100644
--- a/src/lib/process/daemon.h
+++ b/src/lib/process/daemon.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file daemon.h
+ * \brief Header for daemon.c
+ **/
+
#ifndef TOR_DAEMON_H
#define TOR_DAEMON_H
diff --git a/src/lib/process/env.c b/src/lib/process/env.c
index 731f609ac1..dc0b63b499 100644
--- a/src/lib/process/env.c
+++ b/src/lib/process/env.c
@@ -3,15 +3,20 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file env.c
+ * \brief Inspect and manipulate the environment variables.
+ **/
+
#include "orconfig.h"
#include "lib/process/env.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/ctime/di_ops.h"
#include "lib/container/smartlist.h"
#include "lib/log/util_bug.h"
-#include "lib/log/torlog.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/log/log.h"
+#include "lib/malloc/malloc.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
diff --git a/src/lib/process/env.h b/src/lib/process/env.h
index f22599355d..288b923ace 100644
--- a/src/lib/process/env.h
+++ b/src/lib/process/env.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file env.h
+ * \brief Header for env.c
+ **/
+
#ifndef TOR_ENV_H
#define TOR_ENV_H
diff --git a/src/lib/process/pidfile.c b/src/lib/process/pidfile.c
index f016f21697..ea008168ab 100644
--- a/src/lib/process/pidfile.c
+++ b/src/lib/process/pidfile.c
@@ -3,10 +3,15 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file pidfile.c
+ * \brief Record this process's PID to disk.
+ **/
+
#include "orconfig.h"
#include "lib/process/pidfile.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
diff --git a/src/lib/process/pidfile.h b/src/lib/process/pidfile.h
index c85cd1905e..945edee990 100644
--- a/src/lib/process/pidfile.h
+++ b/src/lib/process/pidfile.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file pidfile.h
+ * \brief Header for pidfile.c
+ **/
+
#ifndef TOR_PIDFILE_H
#define TOR_PIDFILE_H
diff --git a/src/lib/process/restrict.c b/src/lib/process/restrict.c
index bb44cc3d15..bca325e5bc 100644
--- a/src/lib/process/restrict.c
+++ b/src/lib/process/restrict.c
@@ -3,10 +3,15 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file restrict.c
+ * \brief Drop privileges from the current process.
+ **/
+
#include "orconfig.h"
#include "lib/process/restrict.h"
#include "lib/intmath/cmp.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/net/socket.h"
diff --git a/src/lib/process/restrict.h b/src/lib/process/restrict.h
index c7f76f8233..2e78dc468c 100644
--- a/src/lib/process/restrict.h
+++ b/src/lib/process/restrict.h
@@ -4,8 +4,8 @@
/* See LICENSE for licensing information */
/**
- * \file waitpid.h
- * \brief Headers for waitpid.c
+ * \file restrict.h
+ * \brief Header for restrict.c
**/
#ifndef TOR_RESTRICT_H
diff --git a/src/lib/process/setuid.c b/src/lib/process/setuid.c
index fa1cdc0f3f..d038039ff4 100644
--- a/src/lib/process/setuid.c
+++ b/src/lib/process/setuid.c
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file setuid.c
+ * \brief Change the user ID after Tor has started (Unix only)
+ **/
+
#include "orconfig.h"
#include "lib/process/setuid.h"
@@ -12,9 +17,9 @@
#include "lib/container/smartlist.h"
#include "lib/fs/userdb.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
diff --git a/src/lib/process/setuid.h b/src/lib/process/setuid.h
index 61aeefe1b7..49751c97c2 100644
--- a/src/lib/process/setuid.h
+++ b/src/lib/process/setuid.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file setuid.h
+ * \brief Header for setuid.c
+ **/
+
#ifndef TOR_SETUID_H
#define TOR_SETUID_H
diff --git a/src/lib/process/subprocess.c b/src/lib/process/subprocess.c
index 516494d105..70851c15e0 100644
--- a/src/lib/process/subprocess.c
+++ b/src/lib/process/subprocess.c
@@ -3,15 +3,20 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file subprocess.c
+ * \brief Launch and monitor other processes.
+ **/
+
#define SUBPROCESS_PRIVATE
#include "lib/process/subprocess.h"
#include "lib/container/smartlist.h"
#include "lib/err/torerr.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/log/win32err.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/process/env.h"
#include "lib/process/waitpid.h"
#include "lib/string/compat_ctype.h"
diff --git a/src/lib/process/subprocess.h b/src/lib/process/subprocess.h
index a319b3505c..5b4318ef2b 100644
--- a/src/lib/process/subprocess.h
+++ b/src/lib/process/subprocess.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file subprocess.h
+ * \brief Header for subprocess.c
+ **/
+
#ifndef TOR_SUBPROCESS_H
#define TOR_SUBPROCESS_H
diff --git a/src/lib/process/waitpid.c b/src/lib/process/waitpid.c
index 66c77b05f3..32ba4530da 100644
--- a/src/lib/process/waitpid.c
+++ b/src/lib/process/waitpid.c
@@ -4,10 +4,8 @@
/* See LICENSE for licensing information */
/**
- * \file util_process.c
- * \brief utility functions for launching processes and checking their
- * status. These functions are kept separately from procmon so that they
- * won't require linking against libevent.
+ * \file waitpid.c
+ * \brief Convenience structures for handlers for handling waitpid().
**/
#include "orconfig.h"
@@ -15,9 +13,9 @@
#ifndef _WIN32
#include "lib/process/waitpid.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "ht.h"
#ifdef HAVE_SYS_WAIT_H
diff --git a/src/lib/sandbox/sandbox.c b/src/lib/sandbox/sandbox.c
index 25dd6d1c26..5510754327 100644
--- a/src/lib/sandbox/sandbox.c
+++ b/src/lib/sandbox/sandbox.c
@@ -36,10 +36,10 @@
#include "lib/sandbox/sandbox.h"
#include "lib/container/map.h"
#include "lib/err/torerr.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/cc/torint.h"
#include "lib/net/resolve.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/string/scanf.h"
#include "tor_queue.h"
diff --git a/src/lib/smartlist_core/smartlist_core.c b/src/lib/smartlist_core/smartlist_core.c
index b9c5f728ce..8364a8180b 100644
--- a/src/lib/smartlist_core/smartlist_core.c
+++ b/src/lib/smartlist_core/smartlist_core.c
@@ -11,7 +11,7 @@
**/
#include "lib/err/torerr.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/smartlist_core/smartlist_core.h"
#include <stdlib.h>
diff --git a/src/lib/smartlist_core/smartlist_core.h b/src/lib/smartlist_core/smartlist_core.h
index b1adf2ebdb..974fb01758 100644
--- a/src/lib/smartlist_core/smartlist_core.h
+++ b/src/lib/smartlist_core/smartlist_core.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file smartlist_core.h
+ * \brief Top-level declarations for the smartlist_t dynamic array type.
+ **/
+
#ifndef TOR_SMARTLIST_CORE_H
#define TOR_SMARTLIST_CORE_H
diff --git a/src/lib/smartlist_core/smartlist_foreach.h b/src/lib/smartlist_core/smartlist_foreach.h
index 4bef36d99c..54f08ac47d 100644
--- a/src/lib/smartlist_core/smartlist_foreach.h
+++ b/src/lib/smartlist_core/smartlist_foreach.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file smartlist_foreach.h
+ * \brief Macros for iterating over the elements of a smartlist_t.
+ **/
+
#ifndef TOR_SMARTLIST_FOREACH_H
#define TOR_SMARTLIST_FOREACH_H
diff --git a/src/lib/smartlist_core/smartlist_split.c b/src/lib/smartlist_core/smartlist_split.c
index b9340e7924..f63894869c 100644
--- a/src/lib/smartlist_core/smartlist_split.c
+++ b/src/lib/smartlist_core/smartlist_split.c
@@ -3,13 +3,18 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file smartlist_split.c
+ * \brief Split a string into a smartlist_t of substrings.
+ **/
+
#include "lib/smartlist_core/smartlist_core.h"
#include "lib/smartlist_core/smartlist_split.h"
#include "lib/err/torerr.h"
#include "lib/string/util_string.h"
#include "lib/string/compat_ctype.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include <string.h>
diff --git a/src/lib/smartlist_core/smartlist_split.h b/src/lib/smartlist_core/smartlist_split.h
index 8ed2abafb8..4dd48295ce 100644
--- a/src/lib/smartlist_core/smartlist_split.h
+++ b/src/lib/smartlist_core/smartlist_split.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file smartlist_split.h
+ * \brief Header for smartlist_split.c
+ **/
+
#ifndef TOR_SMARTLIST_SPLIT_H
#define TOR_SMARTLIST_SPLIT_H
diff --git a/src/lib/string/compat_ctype.c b/src/lib/string/compat_ctype.c
index d1d4ce0ffc..35f4ec6534 100644
--- a/src/lib/string/compat_ctype.c
+++ b/src/lib/string/compat_ctype.c
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file compat_ctype.c
+ * \brief Locale-independent character-type inspection (backend)
+ **/
+
#include "lib/string/compat_ctype.h"
/**
diff --git a/src/lib/string/compat_ctype.h b/src/lib/string/compat_ctype.h
index 530a10270f..210c460c31 100644
--- a/src/lib/string/compat_ctype.h
+++ b/src/lib/string/compat_ctype.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file compat_ctype.h
+ * \brief Locale-independent character-type inspection (header)
+ **/
+
#ifndef TOR_COMPAT_CTYPE_H
#define TOR_COMPAT_CTYPE_H
diff --git a/src/lib/string/compat_string.c b/src/lib/string/compat_string.c
index 8b063b7242..eae82fdae0 100644
--- a/src/lib/string/compat_string.c
+++ b/src/lib/string/compat_string.c
@@ -3,6 +3,12 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file compat_string.c
+ * \brief Useful string-processing functions that some platforms don't
+ * provide.
+ **/
+
#include "lib/string/compat_string.h"
#include "lib/err/torerr.h"
diff --git a/src/lib/string/compat_string.h b/src/lib/string/compat_string.h
index 4726d2b5b6..9292717337 100644
--- a/src/lib/string/compat_string.h
+++ b/src/lib/string/compat_string.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file compat_string.h
+ * \brief Header for compat_string.c
+ **/
+
#ifndef TOR_COMPAT_STRING_H
#define TOR_COMPAT_STRING_H
diff --git a/src/lib/string/parse_int.c b/src/lib/string/parse_int.c
index e552730cc4..52ff49ef1e 100644
--- a/src/lib/string/parse_int.c
+++ b/src/lib/string/parse_int.c
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file parse_int.c
+ * \brief Convert strings into the integers they encode, with bounds checking.
+ **/
+
#include "lib/string/parse_int.h"
#include <errno.h>
diff --git a/src/lib/string/parse_int.h b/src/lib/string/parse_int.h
index 6f56fc32a8..663a5acd74 100644
--- a/src/lib/string/parse_int.h
+++ b/src/lib/string/parse_int.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file parse_int.h
+ * \brief Header for parse_int.c
+ **/
+
#ifndef TOR_PARSE_INT_H
#define TOR_PARSE_INT_H
diff --git a/src/lib/string/printf.c b/src/lib/string/printf.c
index 4443e25fb4..82d38242dd 100644
--- a/src/lib/string/printf.c
+++ b/src/lib/string/printf.c
@@ -3,10 +3,15 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file printf.c
+ * \brief Compatibility wrappers around snprintf and its friends
+ **/
+
#include "lib/string/printf.h"
#include "lib/err/torerr.h"
#include "lib/cc/torint.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include <stdlib.h>
#include <stdio.h>
diff --git a/src/lib/string/printf.h b/src/lib/string/printf.h
index 69b724379a..49c37d43e0 100644
--- a/src/lib/string/printf.h
+++ b/src/lib/string/printf.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file printf.h
+ * \brief Header for printf.c
+ **/
+
#ifndef TOR_UTIL_PRINTF_H
#define TOR_UTIL_PRINTF_H
diff --git a/src/lib/string/scanf.c b/src/lib/string/scanf.c
index 0c5082799c..7b08442148 100644
--- a/src/lib/string/scanf.c
+++ b/src/lib/string/scanf.c
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file scanf.c
+ * \brief Locale-independent minimal implementation of sscanf().
+ **/
+
#include "lib/string/scanf.h"
#include "lib/string/compat_ctype.h"
#include "lib/cc/torint.h"
diff --git a/src/lib/string/scanf.h b/src/lib/string/scanf.h
index 9cfa9cc6c1..ada2322bb1 100644
--- a/src/lib/string/scanf.h
+++ b/src/lib/string/scanf.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file scanf.h
+ * \brief Header for scanf.c
+ **/
+
#ifndef TOR_UTIL_SCANF_H
#define TOR_UTIL_SCANF_H
diff --git a/src/lib/string/util_string.c b/src/lib/string/util_string.c
index e8ed3d4f54..a6b0a3d68a 100644
--- a/src/lib/string/util_string.c
+++ b/src/lib/string/util_string.c
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file util_string.c
+ * \brief Non-standard string functions used throughout Tor.
+ **/
+
#include "lib/string/util_string.h"
#include "lib/string/compat_ctype.h"
#include "lib/err/torerr.h"
diff --git a/src/lib/string/util_string.h b/src/lib/string/util_string.h
index 75407d5ffa..471613462a 100644
--- a/src/lib/string/util_string.h
+++ b/src/lib/string/util_string.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file util_string.h
+ * \brief Header for util_string.c
+ **/
+
#ifndef TOR_UTIL_STRING_H
#define TOR_UTIL_STRING_H
diff --git a/src/lib/term/getpass.c b/src/lib/term/getpass.c
index 10c99914f8..27a27179b6 100644
--- a/src/lib/term/getpass.c
+++ b/src/lib/term/getpass.c
@@ -3,10 +3,15 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file getpass.c
+ * \brief Cross-platform wrapper to read passphrases from the terminal.
+ **/
+
#include "lib/term/getpass.h"
#include "lib/log/util_bug.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#ifdef _WIN32
#include <windows.h>
diff --git a/src/lib/term/getpass.h b/src/lib/term/getpass.h
index 9d03f7036c..e8347e7fe8 100644
--- a/src/lib/term/getpass.h
+++ b/src/lib/term/getpass.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file getpass.h
+ * \brief Header for getpass.c
+ **/
+
#ifndef TOR_GETPASS_H
#define TOR_GETPASS_H
diff --git a/src/lib/testsupport/testsupport.h b/src/lib/testsupport/testsupport.h
index 9a55d306fc..3ae1b48f87 100644
--- a/src/lib/testsupport/testsupport.h
+++ b/src/lib/testsupport/testsupport.h
@@ -1,10 +1,24 @@
/* Copyright (c) 2013-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file testsupport.h
+ *
+ * \brief Macros to implement mocking and selective exposure for the test code.
+ *
+ * Each Tor source file is built twice: once with TOR_UNIT_TESTS defined, and
+ * once with it undefined. The only difference between these configurations
+ * should be that when building for the tests, more functions are exposed as
+ * non-static, and a number of functions are declared as mockable.
+ **/
+
#ifndef TOR_TESTSUPPORT_H
#define TOR_TESTSUPPORT_H
#ifdef TOR_UNIT_TESTS
+/** The "STATIC" macro marks a function or variable that is static when
+ * building Tor for production, but non-static when building the unit
+ * tests. */
#define STATIC
#define EXTERN(type, name) extern type name;
#else
@@ -87,4 +101,3 @@
/** @} */
#endif /* !defined(TOR_TESTSUPPORT_H) */
-
diff --git a/src/lib/thread/compat_pthreads.c b/src/lib/thread/compat_pthreads.c
index 246c6254bb..934067e4c1 100644
--- a/src/lib/thread/compat_pthreads.c
+++ b/src/lib/thread/compat_pthreads.c
@@ -12,7 +12,7 @@
#include "orconfig.h"
#include "lib/thread/threads.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include <sys/time.h>
diff --git a/src/lib/thread/compat_threads.c b/src/lib/thread/compat_threads.c
index 972960e242..24129946b2 100644
--- a/src/lib/thread/compat_threads.c
+++ b/src/lib/thread/compat_threads.c
@@ -15,7 +15,7 @@
#include <stdlib.h>
#include "lib/thread/threads.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include <string.h>
diff --git a/src/lib/thread/compat_winthreads.c b/src/lib/thread/compat_winthreads.c
index 7f9877d21e..799eeda1b4 100644
--- a/src/lib/thread/compat_winthreads.c
+++ b/src/lib/thread/compat_winthreads.c
@@ -15,7 +15,7 @@
#include <windows.h>
#include <process.h>
#include "lib/thread/threads.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/log/win32err.h"
diff --git a/src/lib/thread/numcpus.c b/src/lib/thread/numcpus.c
index 534b0570f8..cca15eb7aa 100644
--- a/src/lib/thread/numcpus.c
+++ b/src/lib/thread/numcpus.c
@@ -3,9 +3,14 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file numcpus.c
+ * \brief Compute the number of CPUs configured on this system.
+ **/
+
#include "orconfig.h"
#include "lib/thread/numcpus.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#ifdef HAVE_UNISTD_H
diff --git a/src/lib/thread/numcpus.h b/src/lib/thread/numcpus.h
index 2899a9ec8a..0b026e4249 100644
--- a/src/lib/thread/numcpus.h
+++ b/src/lib/thread/numcpus.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file numcpus.h
+ * \brief Header for numcpus.c
+ **/
+
#ifndef TOR_NUMCPUS_H
#define TOR_NUMCPUS_H
diff --git a/src/lib/thread/threads.h b/src/lib/thread/threads.h
index fcccc643d5..89d2a9d93e 100644
--- a/src/lib/thread/threads.h
+++ b/src/lib/thread/threads.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file threads.h
+ * \brief Header for threads.c
+ **/
+
#ifndef TOR_COMPAT_THREADS_H
#define TOR_COMPAT_THREADS_H
diff --git a/src/lib/time/compat_time.c b/src/lib/time/compat_time.c
index 2ea6eca988..d26cb6880d 100644
--- a/src/lib/time/compat_time.c
+++ b/src/lib/time/compat_time.c
@@ -13,7 +13,7 @@
#include "lib/time/compat_time.h"
#include "lib/err/torerr.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/intmath/muldiv.h"
#include "lib/intmath/bits.h"
diff --git a/src/lib/time/tvdiff.c b/src/lib/time/tvdiff.c
index cfd1ace771..8617110e52 100644
--- a/src/lib/time/tvdiff.c
+++ b/src/lib/time/tvdiff.c
@@ -3,10 +3,15 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file tvdiff.c
+ * \brief Compute the difference between timevals, in various units.
+ **/
+
#include "lib/time/tvdiff.h"
#include "lib/cc/compat_compiler.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#ifdef _WIN32
#include <winsock2.h>
diff --git a/src/lib/time/tvdiff.h b/src/lib/time/tvdiff.h
index 215de9cf37..d78330d7d8 100644
--- a/src/lib/time/tvdiff.h
+++ b/src/lib/time/tvdiff.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file tvdiff.h
+ * \brief Header for tvdiff.c
+ **/
+
#ifndef TOR_TVDIFF_H
#define TOR_TVDIFF_H
diff --git a/src/lib/tls/buffers_tls.c b/src/lib/tls/buffers_tls.c
index 243e0eb0bc..69ae4f7fc0 100644
--- a/src/lib/tls/buffers_tls.c
+++ b/src/lib/tls/buffers_tls.c
@@ -4,13 +4,18 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file buffers_tls.c
+ * \brief Read and write data on a tor_tls_t connection from a buf_t object.
+ **/
+
#define BUFFERS_PRIVATE
#include "orconfig.h"
#include <stddef.h>
#include "lib/container/buffers.h"
#include "lib/tls/buffers_tls.h"
#include "lib/cc/torint.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/tls/tortls.h"
diff --git a/src/lib/tls/buffers_tls.h b/src/lib/tls/buffers_tls.h
index d9d26c82bd..7a1ca6d16c 100644
--- a/src/lib/tls/buffers_tls.h
+++ b/src/lib/tls/buffers_tls.h
@@ -4,6 +4,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file buffers_tls.h
+ * \brief Header for buffers_tls.c
+ **/
+
#ifndef TOR_BUFFERS_TLS_H
#define TOR_BUFFERS_TLS_H
@@ -16,4 +21,3 @@ int buf_flush_to_tls(struct buf_t *buf, struct tor_tls_t *tls,
size_t sz, size_t *buf_flushlen);
#endif /* !defined(TOR_BUFFERS_TLS_H) */
-
diff --git a/src/lib/tls/tortls.c b/src/lib/tls/tortls.c
index 1cd22a7eba..073cae02ba 100644
--- a/src/lib/tls/tortls.c
+++ b/src/lib/tls/tortls.c
@@ -52,7 +52,7 @@ ENABLE_GCC_WARNING(redundant-decls)
#define TORTLS_PRIVATE
#include "lib/tls/tortls.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/container/smartlist.h"
#include "lib/string/compat_string.h"
diff --git a/src/lib/trace/debug.h b/src/lib/trace/debug.h
index 9b5d9d05c8..191d94226d 100644
--- a/src/lib/trace/debug.h
+++ b/src/lib/trace/debug.h
@@ -1,10 +1,15 @@
/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file debug.h
+ * \brief Macros for debugging our event-trace support.
+ **/
+
#ifndef TOR_TRACE_LOG_DEBUG_H
#define TOR_TRACE_LOG_DEBUG_H
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
/* Stringify pre-processor trick. */
#define XSTR(d) STR(d)
diff --git a/src/lib/trace/trace.c b/src/lib/trace/trace.c
index c0bbbb0cc6..535ffde183 100644
--- a/src/lib/trace/trace.c
+++ b/src/lib/trace/trace.c
@@ -1,6 +1,13 @@
/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file trace.c
+ * \brief Common functions for event-tracing implementation
+ *
+ * See trace.h and doc/HACKING/Tracing.md for more information.
+ **/
+
#include "lib/trace/trace.h"
/** Initialize the tracing library. */
@@ -8,4 +15,3 @@ void
tor_trace_init(void)
{
}
-
diff --git a/src/lib/trace/trace.h b/src/lib/trace/trace.h
index 2dd51aace1..5f7b0ee7cd 100644
--- a/src/lib/trace/trace.h
+++ b/src/lib/trace/trace.h
@@ -1,10 +1,14 @@
/* Copyright (c) 2017-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file trace.h
+ * \brief Header for trace.c
+ **/
+
#ifndef TOR_TRACE_TRACE_H
#define TOR_TRACE_TRACE_H
void tor_trace_init(void);
#endif // TOR_TRACE_TRACE_H
-
diff --git a/src/lib/wallclock/approx_time.c b/src/lib/wallclock/approx_time.c
index 2528954f13..bb9a292369 100644
--- a/src/lib/wallclock/approx_time.c
+++ b/src/lib/wallclock/approx_time.c
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file approx_time.c
+ * \brief Cache the last result of time(), for performance and testing.
+ **/
+
#include "orconfig.h"
#include "lib/wallclock/approx_time.h"
diff --git a/src/lib/wallclock/approx_time.h b/src/lib/wallclock/approx_time.h
index c57ff5bcd3..becc632fe3 100644
--- a/src/lib/wallclock/approx_time.h
+++ b/src/lib/wallclock/approx_time.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file approx_time.h
+ * \brief Header for approx_time.c
+ **/
+
#ifndef TOR_APPROX_TIME_H
#define TOR_APPROX_TIME_H
diff --git a/src/lib/wallclock/include.am b/src/lib/wallclock/include.am
index 7864c21e16..1961639bd7 100644
--- a/src/lib/wallclock/include.am
+++ b/src/lib/wallclock/include.am
@@ -7,7 +7,7 @@ endif
src_lib_libtor_wallclock_a_SOURCES = \
src/lib/wallclock/approx_time.c \
- src/lib/wallclock/tm_cvt.c \
+ src/lib/wallclock/time_to_tm.c \
src/lib/wallclock/tor_gettimeofday.c
src_lib_libtor_wallclock_testing_a_SOURCES = \
@@ -18,5 +18,5 @@ src_lib_libtor_wallclock_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
noinst_HEADERS += \
src/lib/wallclock/approx_time.h \
src/lib/wallclock/timeval.h \
- src/lib/wallclock/tm_cvt.h \
+ src/lib/wallclock/time_to_tm.h \
src/lib/wallclock/tor_gettimeofday.h
diff --git a/src/lib/wallclock/tm_cvt.c b/src/lib/wallclock/time_to_tm.c
index 31d929e635..6543b97e37 100644
--- a/src/lib/wallclock/tm_cvt.c
+++ b/src/lib/wallclock/time_to_tm.c
@@ -3,10 +3,15 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file time_to_tm.c
+ * \brief Convert to struct tm, portably.
+ **/
+
#include "orconfig.h"
#include "lib/cc/torint.h"
#include "lib/cc/compat_compiler.h"
-#include "lib/wallclock/tm_cvt.h"
+#include "lib/wallclock/time_to_tm.h"
#include "lib/string/printf.h"
#include "lib/err/torerr.h"
diff --git a/src/lib/wallclock/tm_cvt.h b/src/lib/wallclock/time_to_tm.h
index 4d87acd4fa..0527a97b34 100644
--- a/src/lib/wallclock/tm_cvt.h
+++ b/src/lib/wallclock/time_to_tm.h
@@ -3,8 +3,13 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#ifndef TOR_WALLCLOCK_TM_CVT_H
-#define TOR_WALLCLOCK_TM_CVT_H
+/**
+ * \file time_to_tm.h
+ * \brief Header for time_to_tm.c
+ **/
+
+#ifndef TOR_WALLCLOCK_TIME_TO_TM_H
+#define TOR_WALLCLOCK_TIME_TO_TM_H
#include <sys/types.h>
diff --git a/src/lib/wallclock/timeval.c b/src/lib/wallclock/timeval.c
deleted file mode 100644
index e69de29bb2..0000000000
--- a/src/lib/wallclock/timeval.c
+++ /dev/null
diff --git a/src/lib/wallclock/timeval.h b/src/lib/wallclock/timeval.h
index 6a9b36a022..b34277cda6 100644
--- a/src/lib/wallclock/timeval.h
+++ b/src/lib/wallclock/timeval.h
@@ -3,6 +3,13 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file timeval.h
+ *
+ * \brief Declarations for timeval-related macros that some platforms
+ * are missing.
+ **/
+
#ifndef TOR_TIMEVAL_H
#define TOR_TIMEVAL_H
diff --git a/src/lib/wallclock/tor_gettimeofday.c b/src/lib/wallclock/tor_gettimeofday.c
index eb902e681d..aefe796ad2 100644
--- a/src/lib/wallclock/tor_gettimeofday.c
+++ b/src/lib/wallclock/tor_gettimeofday.c
@@ -4,9 +4,9 @@
/* See LICENSE for licensing information */
/**
- * \file compat_time.c
- * \brief Portable wrappers for finding out the current time, running
- * timers, etc.
+ * \file tor_gettimeofday.c
+ * \brief Implementat gettimeofday() for windows, and other platforms without
+ * it.
**/
#include "orconfig.h"
diff --git a/src/lib/wallclock/tor_gettimeofday.h b/src/lib/wallclock/tor_gettimeofday.h
index 728ad9565d..aac6366a65 100644
--- a/src/lib/wallclock/tor_gettimeofday.h
+++ b/src/lib/wallclock/tor_gettimeofday.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file tor_gettimeofday.h
+ * \brief Header for tor_gettimeofday.c
+ **/
+
#ifndef TOR_GETTIMEOFDAY_H
#define TOR_GETTIMEOFDAY_H
diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml
index c3e44d2a79..4bbadbe535 100644
--- a/src/rust/Cargo.toml
+++ b/src/rust/Cargo.toml
@@ -14,3 +14,12 @@ members = [
debug = true
panic = "abort"
+[features]
+default = []
+# If this feature is enabled, test code which calls Tor C code from Rust will
+# execute with `cargo test`. Due to numerous linker issues (#25386), this is
+# currently disabled by default. Crates listed here are those which, in their
+# unittests, doctests, and/or integration tests, call C code.
+test-c-from-rust = [
+ "crypto/test-c-from-rust",
+]
diff --git a/src/rust/build.rs b/src/rust/build.rs
index 2cf85b404a..2ac24b334b 100644
--- a/src/rust/build.rs
+++ b/src/rust/build.rs
@@ -149,14 +149,16 @@ pub fn main() {
// tor uses. We must be careful with factoring and dependencies
// moving forward!
cfg.component("tor-crypt-ops-testing");
- cfg.component("tor-sandbox");
+ cfg.component("tor-sandbox-testing");
cfg.component("tor-encoding-testing");
- cfg.component("tor-net");
+ cfg.component("tor-fs-testing");
+ cfg.component("tor-time-testing");
+ cfg.component("tor-net-testing");
cfg.component("tor-thread-testing");
cfg.component("tor-memarea-testing");
- cfg.component("tor-log");
- cfg.component("tor-lock");
- cfg.component("tor-fdio");
+ cfg.component("tor-log-testing");
+ cfg.component("tor-lock-testing");
+ cfg.component("tor-fdio-testing");
cfg.component("tor-container-testing");
cfg.component("tor-smartlist-core-testing");
cfg.component("tor-string-testing");
diff --git a/src/rust/crypto/Cargo.toml b/src/rust/crypto/Cargo.toml
index 869e0d6256..d68ac48e28 100644
--- a/src/rust/crypto/Cargo.toml
+++ b/src/rust/crypto/Cargo.toml
@@ -26,3 +26,7 @@ rand = { version = "=0.5.0-pre.2", default-features = false }
rand_core = { version = "=0.2.0-pre.0", default-features = false }
[features]
+# If this feature is enabled, test code which calls Tor C code from Rust will
+# execute with `cargo test`. Due to numerous linker issues (#25386), this is
+# currently disabled by default.
+test-c-from-rust = []
diff --git a/src/rust/crypto/digests/sha2.rs b/src/rust/crypto/digests/sha2.rs
index 03e0843dc0..d0246eeb94 100644
--- a/src/rust/crypto/digests/sha2.rs
+++ b/src/rust/crypto/digests/sha2.rs
@@ -165,15 +165,19 @@ impl FixedOutput for Sha512 {
#[cfg(test)]
mod test {
+ #[cfg(feature = "test-c-from-rust")]
use digest::Digest;
+ #[cfg(feature = "test-c-from-rust")]
use super::*;
+ #[cfg(feature = "test-c-from-rust")]
#[test]
fn sha256_default() {
let _: Sha256 = Sha256::default();
}
+ #[cfg(feature = "test-c-from-rust")]
#[test]
fn sha256_digest() {
let mut h: Sha256 = Sha256::new();
@@ -193,11 +197,13 @@ mod test {
assert_eq!(result, expected);
}
+ #[cfg(feature = "test-c-from-rust")]
#[test]
fn sha512_default() {
let _: Sha512 = Sha512::default();
}
+ #[cfg(feature = "test-c-from-rust")]
#[test]
fn sha512_digest() {
let mut h: Sha512 = Sha512::new();
diff --git a/src/rust/protover/ffi.rs b/src/rust/protover/ffi.rs
index 3055893d43..91bd83addf 100644
--- a/src/rust/protover/ffi.rs
+++ b/src/rust/protover/ffi.rs
@@ -42,7 +42,6 @@ pub extern "C" fn protover_all_supported(
c_relay_version: *const c_char,
missing_out: *mut *mut c_char,
) -> c_int {
-
if c_relay_version.is_null() {
return 1;
}
@@ -58,14 +57,13 @@ pub extern "C" fn protover_all_supported(
let relay_proto_entry: UnvalidatedProtoEntry =
match UnvalidatedProtoEntry::from_str_any_len(relay_version) {
- Ok(n) => n,
- Err(_) => return 1,
- };
- let maybe_unsupported: Option<UnvalidatedProtoEntry> = relay_proto_entry.all_supported();
+ Ok(n) => n,
+ Err(_) => return 1,
+ };
- if maybe_unsupported.is_some() {
- let unsupported: UnvalidatedProtoEntry = maybe_unsupported.unwrap();
- let c_unsupported: CString = match CString::new(unsupported.to_string()) {
+ if let Some(unsupported) = relay_proto_entry.all_supported() {
+ let c_unsupported: CString = match CString::new(unsupported.to_string())
+ {
Ok(n) => n,
Err(_) => return 1,
};
@@ -100,22 +98,23 @@ pub extern "C" fn protocol_list_supports_protocol(
Err(_) => return 1,
};
let proto_entry: UnvalidatedProtoEntry = match protocol_list.parse() {
- Ok(n) => n,
+ Ok(n) => n,
Err(_) => return 0,
};
let protocol: UnknownProtocol = match translate_to_rust(c_protocol) {
Ok(n) => n.into(),
Err(_) => return 0,
};
- match proto_entry.supports_protocol(&protocol, &version) {
- false => return 0,
- true => return 1,
+ if proto_entry.supports_protocol(&protocol, &version) {
+ 1
+ } else {
+ 0
}
}
#[no_mangle]
pub extern "C" fn protover_contains_long_protocol_names_(
- c_protocol_list: *const c_char
+ c_protocol_list: *const c_char,
) -> c_int {
if c_protocol_list.is_null() {
return 1;
@@ -127,13 +126,10 @@ pub extern "C" fn protover_contains_long_protocol_names_(
let protocol_list = match c_str.to_str() {
Ok(n) => n,
- Err(_) => return 1
+ Err(_) => return 1,
};
- let protocol_entry : Result<UnvalidatedProtoEntry,_> =
- protocol_list.parse();
-
- match protocol_entry {
+ match protocol_list.parse::<UnvalidatedProtoEntry>() {
Ok(_) => 0,
Err(_) => 1,
}
@@ -166,7 +162,7 @@ pub extern "C" fn protocol_list_supports_protocol_or_later(
};
let proto_entry: UnvalidatedProtoEntry = match protocol_list.parse() {
- Ok(n) => n,
+ Ok(n) => n,
Err(_) => return 1,
};
@@ -196,10 +192,8 @@ pub extern "C" fn protover_compute_vote(
threshold: c_int,
allow_long_proto_names: bool,
) -> *mut c_char {
-
if list.is_null() {
- let empty = String::new();
- return allocate_and_copy_string(&empty);
+ return allocate_and_copy_string("");
}
// Dereference of raw pointer requires an unsafe block. The pointer is
@@ -209,17 +203,21 @@ pub extern "C" fn protover_compute_vote(
let mut proto_entries: Vec<UnvalidatedProtoEntry> = Vec::new();
for datum in data {
- let entry: UnvalidatedProtoEntry = match allow_long_proto_names {
- true => match UnvalidatedProtoEntry::from_str_any_len(datum.as_str()) {
- Ok(n) => n,
- Err(_) => continue},
- false => match datum.parse() {
- Ok(n) => n,
- Err(_) => continue},
+ let entry: UnvalidatedProtoEntry = if allow_long_proto_names {
+ match UnvalidatedProtoEntry::from_str_any_len(datum.as_str()) {
+ Ok(n) => n,
+ Err(_) => continue,
+ }
+ } else {
+ match datum.parse() {
+ Ok(n) => n,
+ Err(_) => continue,
+ }
};
proto_entries.push(entry);
}
- let vote: UnvalidatedProtoEntry = ProtoverVote::compute(&proto_entries, &hold);
+ let vote: UnvalidatedProtoEntry =
+ ProtoverVote::compute(&proto_entries, &hold);
allocate_and_copy_string(&vote.to_string())
}
@@ -244,7 +242,9 @@ pub extern "C" fn protover_is_supported_here(
/// Provide an interface for C to translate arguments and return types for
/// protover::compute_for_old_tor
#[no_mangle]
-pub extern "C" fn protover_compute_for_old_tor(version: *const c_char) -> *const c_char {
+pub extern "C" fn protover_compute_for_old_tor(
+ version: *const c_char,
+) -> *const c_char {
let supported: &'static CStr;
let empty: &'static CStr;
diff --git a/src/rust/tor_allocate/tor_allocate.rs b/src/rust/tor_allocate/tor_allocate.rs
index 47fa5fc593..d0c0d79943 100644
--- a/src/rust/tor_allocate/tor_allocate.rs
+++ b/src/rust/tor_allocate/tor_allocate.rs
@@ -9,9 +9,9 @@ use libc::c_void;
// Define a no-op implementation for testing Rust modules without linking to C
#[cfg(feature = "testing")]
-pub fn allocate_and_copy_string(s: &String) -> *mut c_char {
+pub fn allocate_and_copy_string(s: &str) -> *mut c_char {
use std::ffi::CString;
- CString::new(s.as_str()).unwrap().into_raw()
+ CString::new(s).unwrap().into_raw()
}
// Defined only for tests, used for testing purposes, so that we don't need
@@ -39,7 +39,7 @@ extern "C" {
/// A `*mut c_char` that should be freed by tor_free in C
///
#[cfg(not(feature = "testing"))]
-pub fn allocate_and_copy_string(src: &String) -> *mut c_char {
+pub fn allocate_and_copy_string(src: &str) -> *mut c_char {
let bytes: &[u8] = src.as_bytes();
let size = mem::size_of_val::<[u8]>(bytes);
@@ -77,8 +77,7 @@ mod test {
use tor_allocate::allocate_and_copy_string;
- let empty = String::new();
- let allocated_empty = allocate_and_copy_string(&empty);
+ let allocated_empty = allocate_and_copy_string("");
let allocated_empty_rust =
unsafe { CStr::from_ptr(allocated_empty).to_str().unwrap() };
@@ -95,8 +94,7 @@ mod test {
use tor_allocate::allocate_and_copy_string;
- let empty = String::from("foo bar biz");
- let allocated_empty = allocate_and_copy_string(&empty);
+ let allocated_empty = allocate_and_copy_string("foo bar biz");
let allocated_empty_rust =
unsafe { CStr::from_ptr(allocated_empty).to_str().unwrap() };
diff --git a/src/test/fuzz/fuzz_http.c b/src/test/fuzz/fuzz_http.c
index 61dc2144b4..2fbb275614 100644
--- a/src/test/fuzz/fuzz_http.c
+++ b/src/test/fuzz/fuzz_http.c
@@ -12,7 +12,7 @@
#include "app/config/config.h"
#include "core/mainloop/connection.h"
#include "feature/dircache/directory.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "feature/dircommon/dir_connection_st.h"
diff --git a/src/test/fuzz/fuzz_http_connect.c b/src/test/fuzz/fuzz_http_connect.c
index 184bb52ee2..ca007a2c7f 100644
--- a/src/test/fuzz/fuzz_http_connect.c
+++ b/src/test/fuzz/fuzz_http_connect.c
@@ -13,7 +13,7 @@
#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "core/proto/proto_socks.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "core/or/entry_connection_st.h"
#include "core/or/socks_request_st.h"
diff --git a/src/test/fuzz/fuzz_socks.c b/src/test/fuzz/fuzz_socks.c
new file mode 100644
index 0000000000..14c25304b1
--- /dev/null
+++ b/src/test/fuzz/fuzz_socks.c
@@ -0,0 +1,50 @@
+/* Copyright (c) 2016-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+
+#define BUFFERS_PRIVATE
+#include "core/or/or.h"
+
+#include "lib/container/buffers.h"
+#include "lib/err/backtrace.h"
+#include "lib/log/log.h"
+#include "core/proto/proto_socks.h"
+#include "feature/client/addressmap.h"
+
+#include "test/fuzz/fuzzing.h"
+
+int
+fuzz_init(void)
+{
+ addressmap_init();
+ return 0;
+}
+
+int
+fuzz_cleanup(void)
+{
+ addressmap_free_all();
+ return 0;
+}
+
+int
+fuzz_main(const uint8_t *stdin_buf, size_t data_size)
+{
+ buf_t *buffer = buf_new_with_data((char*)stdin_buf, data_size);
+ if (!buffer) {
+ tor_assert(data_size==0);
+ buffer = buf_new();
+ }
+
+ socks_request_t *request = socks_request_new();
+
+ int r = fetch_from_buf_socks(buffer, request, 0, 0);
+ log_info(LD_GENERAL, "Socks request status: %d", r);
+
+ /* Reset. */
+ buf_free(buffer);
+ socks_request_free(request);
+
+ return 0;
+}
diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am
index 87dfe91675..09594d8272 100644
--- a/src/test/fuzz/include.am
+++ b/src/test/fuzz/include.am
@@ -17,7 +17,7 @@ FUZZING_LIBS = \
@TOR_ZSTD_LIBS@
oss-fuzz-prereqs: \
- $(TOR_INTERNAL_TESTING_LIBS)
+ $(TOR_INTERNAL_TESTING_LIBS)
noinst_HEADERS += \
src/test/fuzz/fuzzing.h
@@ -32,6 +32,7 @@ LIBOSS_FUZZ_CPPFLAGS = $(FUZZING_CPPFLAGS) -DLLVM_FUZZ
LIBOSS_FUZZ_CFLAGS = $(FUZZING_CFLAGS)
# ===== AFL fuzzers
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_consensus_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_consensus.c
@@ -39,7 +40,9 @@ src_test_fuzz_fuzz_consensus_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_consensus_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_consensus_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_consensus_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_descriptor_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_descriptor.c
@@ -47,7 +50,9 @@ src_test_fuzz_fuzz_descriptor_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_descriptor_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_descriptor_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_descriptor_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_diff_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_diff.c
@@ -55,7 +60,9 @@ src_test_fuzz_fuzz_diff_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_diff_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_diff_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_diff_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_diff_apply_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_diff_apply.c
@@ -63,7 +70,9 @@ src_test_fuzz_fuzz_diff_apply_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_diff_apply_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_diff_apply_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_diff_apply_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_extrainfo_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_extrainfo.c
@@ -71,7 +80,9 @@ src_test_fuzz_fuzz_extrainfo_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_extrainfo_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_extrainfo_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_extrainfo_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_hsdescv2_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_hsdescv2.c
@@ -79,7 +90,9 @@ src_test_fuzz_fuzz_hsdescv2_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_hsdescv2_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_hsdescv2_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_hsdescv2_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_hsdescv3_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_hsdescv3.c
@@ -87,7 +100,9 @@ src_test_fuzz_fuzz_hsdescv3_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_hsdescv3_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_hsdescv3_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_hsdescv3_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_http_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_http.c
@@ -95,7 +110,9 @@ src_test_fuzz_fuzz_http_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_http_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_http_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_http_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_http_connect_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_http_connect.c
@@ -103,7 +120,9 @@ src_test_fuzz_fuzz_http_connect_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_http_connect_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_http_connect_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_http_connect_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_iptsv2_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_iptsv2.c
@@ -111,7 +130,9 @@ src_test_fuzz_fuzz_iptsv2_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_iptsv2_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_iptsv2_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_iptsv2_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_microdesc_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_microdesc.c
@@ -119,7 +140,19 @@ src_test_fuzz_fuzz_microdesc_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_microdesc_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_microdesc_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_microdesc_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
+src_test_fuzz_fuzz_socks_SOURCES = \
+ src/test/fuzz/fuzzing_common.c \
+ src/test/fuzz/fuzz_socks.c
+src_test_fuzz_fuzz_socks_CPPFLAGS = $(FUZZING_CPPFLAGS)
+src_test_fuzz_fuzz_socks_CFLAGS = $(FUZZING_CFLAGS)
+src_test_fuzz_fuzz_socks_LDFLAGS = $(FUZZING_LDFLAG)
+src_test_fuzz_fuzz_socks_LDADD = $(FUZZING_LIBS)
+endif
+
+if UNITTESTS_ENABLED
src_test_fuzz_fuzz_vrs_SOURCES = \
src/test/fuzz/fuzzing_common.c \
src/test/fuzz/fuzz_vrs.c
@@ -127,7 +160,9 @@ src_test_fuzz_fuzz_vrs_CPPFLAGS = $(FUZZING_CPPFLAGS)
src_test_fuzz_fuzz_vrs_CFLAGS = $(FUZZING_CFLAGS)
src_test_fuzz_fuzz_vrs_LDFLAGS = $(FUZZING_LDFLAG)
src_test_fuzz_fuzz_vrs_LDADD = $(FUZZING_LIBS)
+endif
+if UNITTESTS_ENABLED
FUZZERS = \
src/test/fuzz/fuzz-consensus \
src/test/fuzz/fuzz-descriptor \
@@ -140,94 +175,129 @@ FUZZERS = \
src/test/fuzz/fuzz-http-connect \
src/test/fuzz/fuzz-iptsv2 \
src/test/fuzz/fuzz-microdesc \
+ src/test/fuzz/fuzz-socks \
src/test/fuzz/fuzz-vrs
+endif
# ===== libfuzzer
if LIBFUZZER_ENABLED
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_consensus_SOURCES = \
$(src_test_fuzz_fuzz_consensus_SOURCES)
src_test_fuzz_lf_fuzz_consensus_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
src_test_fuzz_lf_fuzz_consensus_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_consensus_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_consensus_LDADD = $(LIBFUZZER_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_descriptor_SOURCES = \
$(src_test_fuzz_fuzz_descriptor_SOURCES)
src_test_fuzz_lf_fuzz_descriptor_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
src_test_fuzz_lf_fuzz_descriptor_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_descriptor_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_descriptor_LDADD = $(LIBFUZZER_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_diff_SOURCES = \
$(src_test_fuzz_fuzz_diff_SOURCES)
src_test_fuzz_lf_fuzz_diff_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
src_test_fuzz_lf_fuzz_diff_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_diff_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_diff_LDADD = $(LIBFUZZER_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_diff_apply_SOURCES = \
$(src_test_fuzz_fuzz_diff_apply_SOURCES)
src_test_fuzz_lf_fuzz_diff_apply_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
src_test_fuzz_lf_fuzz_diff_apply_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_diff_apply_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_diff_apply_LDADD = $(LIBFUZZER_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_extrainfo_SOURCES = \
$(src_test_fuzz_fuzz_extrainfo_SOURCES)
src_test_fuzz_lf_fuzz_extrainfo_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
src_test_fuzz_lf_fuzz_extrainfo_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_extrainfo_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_extrainfo_LDADD = $(LIBFUZZER_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_hsdescv2_SOURCES = \
$(src_test_fuzz_fuzz_hsdescv2_SOURCES)
src_test_fuzz_lf_fuzz_hsdescv2_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
src_test_fuzz_lf_fuzz_hsdescv2_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_hsdescv2_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_hsdescv2_LDADD = $(LIBFUZZER_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_hsdescv3_SOURCES = \
$(src_test_fuzz_fuzz_hsdescv3_SOURCES)
src_test_fuzz_lf_fuzz_hsdescv3_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
src_test_fuzz_lf_fuzz_hsdescv3_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_hsdescv3_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_hsdescv3_LDADD = $(LIBFUZZER_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_http_SOURCES = \
$(src_test_fuzz_fuzz_http_SOURCES)
src_test_fuzz_lf_fuzz_http_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
src_test_fuzz_lf_fuzz_http_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_http_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_http_LDADD = $(LIBFUZZER_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_http_connect_SOURCES = \
$(src_test_fuzz_fuzz_http_connect_SOURCES)
src_test_fuzz_lf_fuzz_http_connect_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
src_test_fuzz_lf_fuzz_http_connect_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_http_connect_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_http_connect_LDADD = $(LIBFUZZER_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_iptsv2_SOURCES = \
$(src_test_fuzz_fuzz_iptsv2_SOURCES)
src_test_fuzz_lf_fuzz_iptsv2_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
src_test_fuzz_lf_fuzz_iptsv2_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_iptsv2_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_iptsv2_LDADD = $(LIBFUZZER_LIBS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_microdesc_SOURCES = \
$(src_test_fuzz_fuzz_microdesc_SOURCES)
src_test_fuzz_lf_fuzz_microdesc_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
src_test_fuzz_lf_fuzz_microdesc_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_microdesc_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_microdesc_LDADD = $(LIBFUZZER_LIBS)
+endif
+if UNITTESTS_ENABLED
+src_test_fuzz_lf_fuzz_socks_SOURCES = \
+ $(src_test_fuzz_fuzz_socks_SOURCES)
+src_test_fuzz_lf_fuzz_socks_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
+src_test_fuzz_lf_fuzz_socks_CFLAGS = $(LIBFUZZER_CFLAGS)
+src_test_fuzz_lf_fuzz_socks_LDFLAGS = $(LIBFUZZER_LDFLAG)
+src_test_fuzz_lf_fuzz_socks_LDADD = $(LIBFUZZER_LIBS)
+endif
+
+if UNITTESTS_ENABLED
src_test_fuzz_lf_fuzz_vrs_SOURCES = \
$(src_test_fuzz_fuzz_vrs_SOURCES)
src_test_fuzz_lf_fuzz_vrs_CPPFLAGS = $(LIBFUZZER_CPPFLAGS)
src_test_fuzz_lf_fuzz_vrs_CFLAGS = $(LIBFUZZER_CFLAGS)
src_test_fuzz_lf_fuzz_vrs_LDFLAGS = $(LIBFUZZER_LDFLAG)
src_test_fuzz_lf_fuzz_vrs_LDADD = $(LIBFUZZER_LIBS)
+endif
LIBFUZZER_FUZZERS = \
src/test/fuzz/lf-fuzz-consensus \
@@ -241,6 +311,7 @@ LIBFUZZER_FUZZERS = \
src/test/fuzz/lf-fuzz-http-connect \
src/test/fuzz/lf-fuzz-iptsv2 \
src/test/fuzz/lf-fuzz-microdesc \
+ src/test/fuzz/lf-fuzz-socks \
src/test/fuzz/lf-fuzz-vrs
else
@@ -250,65 +321,96 @@ endif
# ===== oss-fuzz
if OSS_FUZZ_ENABLED
+if UNITTESTS_ENABLED
src_test_fuzz_liboss_fuzz_consensus_a_SOURCES = \
$(src_test_fuzz_fuzz_consensus_SOURCES)
src_test_fuzz_liboss_fuzz_consensus_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_consensus_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_liboss_fuzz_descriptor_a_SOURCES = \
$(src_test_fuzz_fuzz_descriptor_SOURCES)
src_test_fuzz_liboss_fuzz_descriptor_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_descriptor_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_liboss_fuzz_diff_a_SOURCES = \
$(src_test_fuzz_fuzz_diff_SOURCES)
src_test_fuzz_liboss_fuzz_diff_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_diff_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_liboss_fuzz_diff_apply_a_SOURCES = \
$(src_test_fuzz_fuzz_diff_apply_SOURCES)
src_test_fuzz_liboss_fuzz_diff_apply_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_diff_apply_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_liboss_fuzz_extrainfo_a_SOURCES = \
$(src_test_fuzz_fuzz_extrainfo_SOURCES)
src_test_fuzz_liboss_fuzz_extrainfo_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_extrainfo_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_liboss_fuzz_hsdescv2_a_SOURCES = \
$(src_test_fuzz_fuzz_hsdescv2_SOURCES)
src_test_fuzz_liboss_fuzz_hsdescv2_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_hsdescv2_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_liboss_fuzz_hsdescv3_a_SOURCES = \
$(src_test_fuzz_fuzz_hsdescv3_SOURCES)
src_test_fuzz_liboss_fuzz_hsdescv3_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_hsdescv3_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_liboss_fuzz_http_a_SOURCES = \
$(src_test_fuzz_fuzz_http_SOURCES)
src_test_fuzz_liboss_fuzz_http_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_http_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_liboss_fuzz_http_connect_a_SOURCES = \
$(src_test_fuzz_fuzz_http_connect_SOURCES)
src_test_fuzz_liboss_fuzz_http_connect_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_http_connect_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_liboss_fuzz_iptsv2_a_SOURCES = \
$(src_test_fuzz_fuzz_iptsv2_SOURCES)
src_test_fuzz_liboss_fuzz_iptsv2_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_iptsv2_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
+if UNITTESTS_ENABLED
src_test_fuzz_liboss_fuzz_microdesc_a_SOURCES = \
$(src_test_fuzz_fuzz_microdesc_SOURCES)
src_test_fuzz_liboss_fuzz_microdesc_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_microdesc_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
+if UNITTESTS_ENABLED
+src_test_fuzz_liboss_fuzz_socks_a_SOURCES = \
+ $(src_test_fuzz_fuzz_socks_SOURCES)
+src_test_fuzz_liboss_fuzz_socks_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
+src_test_fuzz_liboss_fuzz_socks_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
+
+if UNITTESTS_ENABLED
src_test_fuzz_liboss_fuzz_vrs_a_SOURCES = \
$(src_test_fuzz_fuzz_vrs_SOURCES)
src_test_fuzz_liboss_fuzz_vrs_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS)
src_test_fuzz_liboss_fuzz_vrs_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS)
+endif
OSS_FUZZ_FUZZERS = \
src/test/fuzz/liboss-fuzz-consensus.a \
@@ -322,6 +424,7 @@ OSS_FUZZ_FUZZERS = \
src/test/fuzz/liboss-fuzz-http-connect.a \
src/test/fuzz/liboss-fuzz-iptsv2.a \
src/test/fuzz/liboss-fuzz-microdesc.a \
+ src/test/fuzz/liboss-fuzz-socks.a \
src/test/fuzz/liboss-fuzz-vrs.a
else
diff --git a/src/test/include.am b/src/test/include.am
index a749ff1436..81b089b8f7 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -117,6 +117,7 @@ src_test_test_SOURCES += \
src/test/test_controller.c \
src/test/test_controller_events.c \
src/test/test_crypto.c \
+ src/test/test_crypto_ope.c \
src/test/test_crypto_openssl.c \
src/test/test_data.c \
src/test/test_dir.c \
@@ -321,6 +322,7 @@ src_test_test_hs_ntor_cl_AM_CPPFLAGS = \
$(AM_CPPFLAGS)
+if UNITTESTS_ENABLED
noinst_PROGRAMS += src/test/test-bt-cl
src_test_test_bt_cl_SOURCES = src/test/test_bt_cl.c
src_test_test_bt_cl_LDADD = \
@@ -330,6 +332,7 @@ src_test_test_bt_cl_LDADD = \
@TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@
src_test_test_bt_cl_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS)
+endif
EXTRA_DIST += \
src/test/bt_test.py \
diff --git a/src/test/log_test_helpers.c b/src/test/log_test_helpers.c
index e814555ba1..0d0f7574c3 100644
--- a/src/test/log_test_helpers.c
+++ b/src/test/log_test_helpers.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2015-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define LOG_PRIVATE
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "test/log_test_helpers.h"
/**
diff --git a/src/test/ope_ref.py b/src/test/ope_ref.py
new file mode 100644
index 0000000000..3677e57a61
--- /dev/null
+++ b/src/test/ope_ref.py
@@ -0,0 +1,40 @@
+#!/usr/bin/python3
+# Copyright 2018, The Tor Project, Inc. See LICENSE for licensing info.
+
+# Reference implementation for our rudimentary OPE code, used to
+# generate test vectors. See crypto_ope.c for more details.
+
+from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
+from cryptography.hazmat.primitives.ciphers.algorithms import AES
+from cryptography.hazmat.backends import default_backend
+
+from binascii import a2b_hex
+
+#randomly generated and values.
+KEY = a2b_hex(
+ "19e05891d55232c08c2cad91d612fdb9cbd6691949a0742434a76c80bc6992fe")
+PTS = [ 121132, 82283, 72661, 72941, 123122, 12154, 121574, 11391, 65845,
+ 86301, 61284, 70505, 30438, 60150, 114800, 109403, 21893, 123569,
+ 95617, 48561, 53334, 92746, 7110, 9612, 106958, 46889, 87790, 68878,
+ 47917, 121128, 108602, 28217, 69498, 63870, 57542, 122148, 46254,
+ 42850, 92661, 57720]
+
+IV = b'\x00' * 16
+
+backend = default_backend()
+
+def words():
+ cipher = Cipher(algorithms.AES(KEY), modes.CTR(IV), backend=backend)
+ e = cipher.encryptor()
+ while True:
+ v = e.update(b'\x00\x00')
+ yield v[0] + 256 * v[1] + 1
+
+def encrypt(n):
+ return sum(w for w, _ in zip(words(), range(n)))
+
+def example(n):
+ return ' {{ {}, UINT64_C({}) }},'.format(n, encrypt(n))
+
+for v in PTS:
+ print(example(v))
diff --git a/src/test/test-memwipe.c b/src/test/test-memwipe.c
index 8a4610e904..c879013ed6 100644
--- a/src/test/test-memwipe.c
+++ b/src/test/test-memwipe.c
@@ -5,7 +5,7 @@
#include "lib/crypt_ops/crypto_util.h"
#include "lib/intmath/cmp.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include <string.h>
#include <stdio.h>
diff --git a/src/test/test.c b/src/test/test.c
index 2addeec968..745aa987aa 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -865,6 +865,7 @@ struct testgroup_t testgroups[] = {
{ "control/", controller_tests },
{ "control/event/", controller_event_tests },
{ "crypto/", crypto_tests },
+ { "crypto/ope/", crypto_ope_tests },
{ "crypto/openssl/", crypto_openssl_tests },
{ "dir/", dir_tests },
{ "dir_handle_get/", dir_handle_get_tests },
diff --git a/src/test/test.h b/src/test/test.h
index 602acca1cd..bfe50cbb8c 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -203,6 +203,7 @@ extern struct testcase_t container_tests[];
extern struct testcase_t controller_tests[];
extern struct testcase_t controller_event_tests[];
extern struct testcase_t crypto_tests[];
+extern struct testcase_t crypto_ope_tests[];
extern struct testcase_t crypto_openssl_tests[];
extern struct testcase_t dir_tests[];
extern struct testcase_t dir_handle_get_tests[];
diff --git a/src/test/test_addr.c b/src/test/test_addr.c
index 9ab921c5b6..a9004048a5 100644
--- a/src/test/test_addr.c
+++ b/src/test/test_addr.c
@@ -10,71 +10,16 @@
#include "test/test.h"
#include "feature/client/addressmap.h"
#include "test/log_test_helpers.h"
+#include "lib/net/resolve.h"
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
-/** Mocking replacement: only handles localhost. */
-static int
-mock_tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr_out)
-{
- if (!strcmp(name, "localhost")) {
- if (family == AF_INET || family == AF_UNSPEC) {
- tor_addr_from_ipv4h(addr_out, 0x7f000001);
- return 0;
- } else if (family == AF_INET6) {
- char bytes[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1 };
- tor_addr_from_ipv6_bytes(addr_out, bytes);
- return 0;
- }
- }
- return -1;
-}
-
static void
test_addr_basic(void *arg)
{
- uint32_t u32;
- uint16_t u16;
- char *cp;
-
- /* Test addr_port_lookup */
- (void)arg;
- cp = NULL; u32 = 3; u16 = 3;
- tt_assert(!addr_port_lookup(LOG_WARN, "1.2.3.4", &cp, &u32, &u16));
- tt_str_op(cp,OP_EQ, "1.2.3.4");
- tt_int_op(u32,OP_EQ, 0x01020304u);
- tt_int_op(u16,OP_EQ, 0);
- tor_free(cp);
- tt_assert(!addr_port_lookup(LOG_WARN, "4.3.2.1:99", &cp, &u32, &u16));
- tt_str_op(cp,OP_EQ, "4.3.2.1");
- tt_int_op(u32,OP_EQ, 0x04030201u);
- tt_int_op(u16,OP_EQ, 99);
- tor_free(cp);
-
- MOCK(tor_addr_lookup, mock_tor_addr_lookup);
-
- tt_assert(!addr_port_lookup(LOG_WARN, "nonexistent.address:4040",
- &cp, NULL, &u16));
- tt_str_op(cp,OP_EQ, "nonexistent.address");
- tt_int_op(u16,OP_EQ, 4040);
- tor_free(cp);
- tt_assert(!addr_port_lookup(LOG_WARN, "localhost:9999", &cp, &u32, &u16));
- tt_str_op(cp,OP_EQ, "localhost");
- tt_int_op(u16,OP_EQ, 9999);
- tt_int_op(u32,OP_EQ, 0x7f000001u);
- tor_free(cp);
- u32 = 3;
- tt_assert(!addr_port_lookup(LOG_WARN, "localhost", NULL, &u32, &u16));
- tt_ptr_op(cp,OP_EQ, NULL);
- tt_int_op(u32,OP_EQ, 0x7f000001u);
- tt_int_op(u16,OP_EQ, 0);
- tor_free(cp);
-
- tt_assert(addr_port_lookup(LOG_WARN, "localhost:3", &cp, &u32, NULL));
- tor_free(cp);
+ (void) arg;
tt_int_op(0,OP_EQ, addr_mask_get_bits(0x0u));
tt_int_op(32,OP_EQ, addr_mask_get_bits(0xFFFFFFFFu));
@@ -102,8 +47,7 @@ test_addr_basic(void *arg)
}
done:
- UNMOCK(tor_addr_lookup);
- tor_free(cp);
+ ;
}
#define test_op_ip6_(a,op,b,e1,e2) \
diff --git a/src/test/test_bt.sh b/src/test/test_bt.sh
index 312905a4e2..df8bcb8eda 100755
--- a/src/test/test_bt.sh
+++ b/src/test/test_bt.sh
@@ -3,6 +3,8 @@
exitcode=0
+ulimit -c 0
+
export ASAN_OPTIONS="handle_segv=0:allow_user_segv_handler=1"
"${builddir:-.}/src/test/test-bt-cl" backtraces || exit $?
"${builddir:-.}/src/test/test-bt-cl" assert 2>&1 | "${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/bt_test.py" || exitcode="$?"
diff --git a/src/test/test_bt_cl.c b/src/test/test_bt_cl.c
index 716cff36e0..89cbca2066 100644
--- a/src/test/test_bt_cl.c
+++ b/src/test/test_bt_cl.c
@@ -9,7 +9,7 @@
#undef TOR_COVERAGE
#include "core/or/or.h"
#include "lib/err/backtrace.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
diff --git a/src/test/test_config.c b/src/test/test_config.c
index af3a8a7cfe..f5c759402c 100644
--- a/src/test/test_config.c
+++ b/src/test/test_config.c
@@ -10,6 +10,7 @@
#define ROUTERSET_PRIVATE
#include "core/or/or.h"
#include "lib/net/address.h"
+#include "lib/net/resolve.h"
#include "feature/client/addressmap.h"
#include "feature/client/bridges.h"
#include "core/or/circuitmux_ewma.h"
@@ -4636,6 +4637,20 @@ test_config_parse_port_config__ports__ports_given(void *data)
tor_addr_parse(&addr, "127.0.0.46");
tt_assert(tor_addr_eq(&port_cfg->addr, &addr))
+ // Test success with a port of auto in mixed case
+ config_free_lines(config_port_valid); config_port_valid = NULL;
+ SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
+ smartlist_clear(slout);
+ config_port_valid = mock_config_line("DNSPort", "AuTo");
+ ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ "127.0.0.46", 0, 0);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(smartlist_len(slout), OP_EQ, 1);
+ port_cfg = (port_cfg_t *)smartlist_get(slout, 0);
+ tt_int_op(port_cfg->port, OP_EQ, CFG_AUTO_PORT);
+ tor_addr_parse(&addr, "127.0.0.46");
+ tt_assert(tor_addr_eq(&port_cfg->addr, &addr))
+
// Test success with parsing both an address and an auto port
config_free_lines(config_port_valid); config_port_valid = NULL;
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
diff --git a/src/test/test_connection.c b/src/test/test_connection.c
index c423c6573f..e716c83fe1 100644
--- a/src/test/test_connection.c
+++ b/src/test/test_connection.c
@@ -20,6 +20,7 @@
#include "feature/rend/rendcache.h"
#include "feature/dircache/directory.h"
#include "core/or/connection_or.h"
+#include "lib/net/resolve.h"
#include "test/test_connection.h"
#include "test/test_helpers.h"
@@ -899,4 +900,3 @@ struct testcase_t connection_tests[] = {
{ "failed_orconn_tracker", test_failed_orconn_tracker, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_controller.c b/src/test/test_controller.c
index 2ded04619c..d0aa868448 100644
--- a/src/test/test_controller.c
+++ b/src/test/test_controller.c
@@ -14,6 +14,7 @@
#include "feature/nodelist/nodelist.h"
#include "test/test.h"
#include "test/test_helpers.h"
+#include "lib/net/resolve.h"
#include "feature/control/control_connection_st.h"
#include "feature/dirclient/download_status_st.h"
diff --git a/src/test/test_crypto_ope.c b/src/test/test_crypto_ope.c
new file mode 100644
index 0000000000..7dcad7b4b2
--- /dev/null
+++ b/src/test/test_crypto_ope.c
@@ -0,0 +1,152 @@
+/* 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 */
+
+#include "orconfig.h"
+
+#define CRYPTO_OPE_PRIVATE
+
+#include "lib/crypt_ops/crypto_ope.h"
+#include "lib/crypt_ops/crypto.h"
+#include "lib/encoding/binascii.h"
+#include "test/test.h"
+#include "tinytest.h"
+
+#include <stddef.h>
+#include <string.h>
+
+static void
+test_crypto_ope_consistency(void *arg)
+{
+ (void)arg;
+
+ crypto_ope_t *ope = NULL;
+ crypto_cipher_t *aes = NULL;
+ const int TEST_VALS[] = { 5, 500, 1023, 1024, 1025, 2046, 2047, 2048, 2049,
+ 10000, OPE_INPUT_MAX };
+ unsigned i;
+ const uint8_t key[32] = "A fixed key, chosen arbitrarily.";
+
+ ope = crypto_ope_new(key);
+ tt_assert(ope);
+
+ uint64_t last_val = 0;
+ for (i = 0; i < ARRAY_LENGTH(TEST_VALS); ++i) {
+ aes = ope_get_cipher(ope, 0);
+ int val = TEST_VALS[i];
+ uint64_t v1 = crypto_ope_encrypt(ope, val);
+ uint64_t v2 = sum_values_from_cipher(aes, val);
+ tt_u64_op(v1, OP_EQ, v2);
+ tt_u64_op(v2, OP_GT, last_val);
+ last_val = v2;
+ crypto_cipher_free(aes);
+ }
+
+ done:
+ crypto_cipher_free(aes);
+ crypto_ope_free(ope);
+}
+
+static void
+test_crypto_ope_oob(void *arg)
+{
+ (void)arg;
+
+ crypto_ope_t *ope = NULL;
+ const uint8_t key[32] = "A fixed key, chosen arbitrarily.";
+ ope = crypto_ope_new(key);
+
+ tt_u64_op(UINT64_MAX, OP_EQ, crypto_ope_encrypt(ope,INT_MIN));
+ tt_u64_op(UINT64_MAX, OP_EQ, crypto_ope_encrypt(ope,-100));
+ tt_u64_op(UINT64_MAX, OP_EQ, crypto_ope_encrypt(ope,0));
+ tt_u64_op(UINT64_MAX, OP_NE, crypto_ope_encrypt(ope,1));
+ tt_u64_op(UINT64_MAX, OP_NE, crypto_ope_encrypt(ope,7000));
+ tt_u64_op(UINT64_MAX, OP_NE, crypto_ope_encrypt(ope,OPE_INPUT_MAX));
+ tt_u64_op(UINT64_MAX, OP_EQ, crypto_ope_encrypt(ope,OPE_INPUT_MAX+1));
+ tt_u64_op(UINT64_MAX, OP_EQ, crypto_ope_encrypt(ope,INT_MAX));
+ done:
+ crypto_ope_free(ope);
+}
+
+static const char OPE_TEST_KEY[] =
+ "19e05891d55232c08c2cad91d612fdb9cbd6691949a0742434a76c80bc6992fe";
+
+/* generated by a separate python implementation. */
+static const struct {
+ int v;
+ uint64_t r;
+} OPE_TEST_VECTORS[] = {
+ { 121132, UINT64_C(3971694514) },
+ { 82283, UINT64_C(2695743564) },
+ { 72661, UINT64_C(2381548866) },
+ { 72941, UINT64_C(2390408421) },
+ { 123122, UINT64_C(4036781069) },
+ { 12154, UINT64_C(402067100) },
+ { 121574, UINT64_C(3986197593) },
+ { 11391, UINT64_C(376696838) },
+ { 65845, UINT64_C(2161801517) },
+ { 86301, UINT64_C(2828270975) },
+ { 61284, UINT64_C(2013616892) },
+ { 70505, UINT64_C(2313368870) },
+ { 30438, UINT64_C(1001394664) },
+ { 60150, UINT64_C(1977329668) },
+ { 114800, UINT64_C(3764946628) },
+ { 109403, UINT64_C(3585352477) },
+ { 21893, UINT64_C(721388468) },
+ { 123569, UINT64_C(4051780471) },
+ { 95617, UINT64_C(3134921876) },
+ { 48561, UINT64_C(1597596985) },
+ { 53334, UINT64_C(1753691710) },
+ { 92746, UINT64_C(3040874493) },
+ { 7110, UINT64_C(234966492) },
+ { 9612, UINT64_C(318326551) },
+ { 106958, UINT64_C(3506124249) },
+ { 46889, UINT64_C(1542219146) },
+ { 87790, UINT64_C(2877361609) },
+ { 68878, UINT64_C(2260369112) },
+ { 47917, UINT64_C(1576681737) },
+ { 121128, UINT64_C(3971553290) },
+ { 108602, UINT64_C(3559176081) },
+ { 28217, UINT64_C(929692460) },
+ { 69498, UINT64_C(2280554161) },
+ { 63870, UINT64_C(2098322675) },
+ { 57542, UINT64_C(1891698992) },
+ { 122148, UINT64_C(4004515805) },
+ { 46254, UINT64_C(1521227949) },
+ { 42850, UINT64_C(1408996941) },
+ { 92661, UINT64_C(3037901517) },
+ { 57720, UINT64_C(1897369989) },
+};
+
+static void
+test_crypto_ope_vectors(void *arg)
+{
+ (void)arg;
+ uint8_t key[32];
+ crypto_ope_t *ope = NULL, *ope2 = NULL;
+
+ base16_decode((char*)key, 32, OPE_TEST_KEY, strlen(OPE_TEST_KEY));
+
+ ope = crypto_ope_new(key);
+ key[8] += 1;
+ ope2 = crypto_ope_new(key);
+ unsigned i;
+ for (i = 0; i < ARRAY_LENGTH(OPE_TEST_VECTORS); ++i) {
+ int val = OPE_TEST_VECTORS[i].v;
+ uint64_t res = OPE_TEST_VECTORS[i].r;
+
+ tt_u64_op(crypto_ope_encrypt(ope, val), OP_EQ, res);
+ tt_u64_op(crypto_ope_encrypt(ope2, val), OP_NE, res);
+ }
+ done:
+ crypto_ope_free(ope);
+ crypto_ope_free(ope2);
+}
+
+struct testcase_t crypto_ope_tests[] = {
+ { "consistency", test_crypto_ope_consistency, 0, NULL, NULL },
+ { "oob", test_crypto_ope_oob, 0, NULL, NULL },
+ { "vectors", test_crypto_ope_vectors, 0, NULL, NULL },
+ END_OF_TESTCASES
+};
diff --git a/src/test/test_crypto_openssl.c b/src/test/test_crypto_openssl.c
index b1a5613eaf..92f9cbab2f 100644
--- a/src/test/test_crypto_openssl.c
+++ b/src/test/test_crypto_openssl.c
@@ -10,7 +10,7 @@
#include "lib/crypt_ops/compat_openssl.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/encoding/binascii.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "test/test.h"
#include <openssl/evp.h>
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index bda56b3a8e..c2f3f5297d 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -23,6 +23,7 @@
#include "app/config/confparse.h"
#include "app/config/config.h"
#include "feature/control/control.h"
+#include "lib/encoding/confline.h"
#include "lib/crypt_ops/crypto_ed25519.h"
#include "lib/crypt_ops/crypto_format.h"
#include "lib/crypt_ops/crypto_rand.h"
@@ -1591,25 +1592,6 @@ test_dir_measured_bw_kb(void *arg)
return;
}
-/* Test dirserv_read_measured_bandwidths */
-static void
-test_dir_dirserv_read_measured_bandwidths_empty(void *arg)
-{
- char *fname=NULL;
- (void)arg;
-
- fname = tor_strdup(get_fname("V3BandwidthsFile"));
- /* Test an empty file */
- write_str_to_file(fname, "", 0);
- setup_capture_of_logs(LOG_WARN);
- tt_int_op(-1, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
- expect_log_msg("Empty bandwidth file\n");
-
- done:
- tor_free(fname);
- teardown_capture_of_logs();
-}
-
/* Unit tests for measured_bw_line_parse using line_is_after_headers flag.
* When the end of the header is detected (a first complete bw line is parsed),
* incomplete lines fail and give warnings, but do not give warnings if
@@ -1653,7 +1635,7 @@ test_dir_measured_bw_kb_line_is_after_headers(void *arg)
teardown_capture_of_logs();
}
-/* Test dirserv_read_measured_bandwidths with whole files. */
+/* Test dirserv_read_measured_bandwidths with headers and complete files. */
static void
test_dir_dirserv_read_measured_bandwidths(void *arg)
{
@@ -1661,76 +1643,321 @@ test_dir_dirserv_read_measured_bandwidths(void *arg)
char *content = NULL;
time_t timestamp = time(NULL);
char *fname = tor_strdup(get_fname("V3BandwidthsFile"));
-
- /* Test Torflow file only with timestamp*/
- tor_asprintf(&content, "%ld", (long)timestamp);
- write_str_to_file(fname, content, 0);
- tor_free(content);
- tt_int_op(-1, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
-
- /* Test Torflow file with timestamp followed by '\n' */
- tor_asprintf(&content, "%ld\n", (long)timestamp);
- write_str_to_file(fname, content, 0);
- tor_free(content);
- tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
-
- /* Test Torflow complete file*/
- const char *torflow_relay_lines=
+ smartlist_t *bw_file_headers = smartlist_new();
+ /* bw file strings in vote */
+ char *bw_file_headers_str = NULL;
+ char *bw_file_headers_str_v100 = NULL;
+ char *bw_file_headers_str_v110 = NULL;
+ char *bw_file_headers_str_bad = NULL;
+ char *bw_file_headers_str_extra = NULL;
+ char bw_file_headers_str_long[MAX_BW_FILE_HEADER_COUNT_IN_VOTE * 8 + 1] = "";
+ /* string header lines in bw file */
+ char *header_lines_v100 = NULL;
+ char *header_lines_v110_no_terminator = NULL;
+ char *header_lines_v110 = NULL;
+ char header_lines_long[MAX_BW_FILE_HEADER_COUNT_IN_VOTE * 8 + 1] = "";
+ int i;
+ const char *header_lines_v110_no_terminator_no_timestamp =
+ "version=1.1.0\n"
+ "software=sbws\n"
+ "software_version=0.1.0\n"
+ "earliest_bandwidth=2018-05-08T16:13:26\n"
+ "file_created=2018-04-16T21:49:18\n"
+ "generator_started=2018-05-08T16:13:25\n"
+ "latest_bandwidth=2018-04-16T20:49:18\n";
+ const char *bw_file_headers_str_v110_no_timestamp =
+ "version=1.1.0 software=sbws "
+ "software_version=0.1.0 "
+ "earliest_bandwidth=2018-05-08T16:13:26 "
+ "file_created=2018-04-16T21:49:18 "
+ "generator_started=2018-05-08T16:13:25 "
+ "latest_bandwidth=2018-04-16T20:49:18";
+ const char *relay_lines_v100 =
"node_id=$557365204145532d32353620696e73746561642e bw=1024 "
"nick=Test measured_at=1523911725 updated_at=1523911725 "
"pid_error=4.11374090719 pid_error_sum=4.11374090719 "
"pid_bw=57136645 pid_delta=2.12168374577 circ_fail=0.2 "
"scanner=/filepath\n";
-
- tor_asprintf(&content, "%ld\n%s", (long)timestamp, torflow_relay_lines);
+ const char *relay_lines_v110 =
+ "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A27F80 "
+ "master_key_ed25519=YaqV4vbvPYKucElk297eVdNArDz9HtIwUoIeo0+cVIpQ "
+ "bw=760 nick=Test rtt=380 time=2018-05-08T16:13:26\n";
+ const char *relay_lines_bad =
+ "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A\n";
+
+ tor_asprintf(&header_lines_v100, "%ld\n", (long)timestamp);
+ tor_asprintf(&header_lines_v110_no_terminator, "%ld\n%s", (long)timestamp,
+ header_lines_v110_no_terminator_no_timestamp);
+ tor_asprintf(&header_lines_v110, "%s%s",
+ header_lines_v110_no_terminator, BW_FILE_HEADERS_TERMINATOR);
+
+ tor_asprintf(&bw_file_headers_str_v100, "timestamp=%ld",(long)timestamp);
+ tor_asprintf(&bw_file_headers_str_v110, "timestamp=%ld %s",
+ (long)timestamp, bw_file_headers_str_v110_no_timestamp);
+ tor_asprintf(&bw_file_headers_str_bad, "%s "
+ "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A",
+ bw_file_headers_str_v110);
+
+ for (i=0; i<MAX_BW_FILE_HEADER_COUNT_IN_VOTE; i++) {
+ strlcat(header_lines_long, "foo=bar\n",
+ sizeof(header_lines_long));
+ }
+ /* 8 is the number of v110 lines in header_lines_v110 */
+ for (i=0; i<MAX_BW_FILE_HEADER_COUNT_IN_VOTE - 8 - 1; i++) {
+ strlcat(bw_file_headers_str_long, "foo=bar ",
+ sizeof(bw_file_headers_str_long));
+ }
+ strlcat(bw_file_headers_str_long, "foo=bar",
+ sizeof(bw_file_headers_str_long));
+ tor_asprintf(&bw_file_headers_str_extra,
+ "%s %s",
+ bw_file_headers_str_v110,
+ bw_file_headers_str_long);
+
+ /* Test an empty bandwidth file. bw_file_headers will be empty string */
+ write_str_to_file(fname, "", 0);
+ setup_capture_of_logs(LOG_WARN);
+ tt_int_op(-1, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ expect_log_msg("Empty bandwidth file\n");
+ teardown_capture_of_logs();
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op("", OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test bandwidth file with only timestamp.
+ * bw_file_headers will be empty string */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%ld", (long)timestamp);
write_str_to_file(fname, content, 0);
tor_free(content);
- tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
-
- /* Test Torflow complete file including v1.1.0 headers */
- const char *v110_header_lines=
- "version=1.1.0\n"
- "software=sbws\n"
- "software_version=0.1.0\n"
- "generator_started=2018-05-08T16:13:25\n"
- "earliest_bandwidth=2018-05-08T16:13:26\n"
- "====\n";
-
- tor_asprintf(&content, "%ld\n%s%s", (long)timestamp, v110_header_lines,
- torflow_relay_lines);
+ tt_int_op(-1, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op("", OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.0.0 bandwidth file headers */
+ write_str_to_file(fname, header_lines_v100, 0);
+ bw_file_headers = smartlist_new();
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v100, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.0.0 complete bandwidth file */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s", header_lines_v100, relay_lines_v100);
write_str_to_file(fname, content, 0);
tor_free(content);
- tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
-
- /* Test Torflow with additional headers afer a correct bw line */
- tor_asprintf(&content, "%ld\n%s%s", (long)timestamp, torflow_relay_lines,
- v110_header_lines);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v100, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.0.0 complete bandwidth file with NULL bw_file_headers. */
+ tor_asprintf(&content, "%s%s", header_lines_v100, relay_lines_v100);
write_str_to_file(fname, content, 0);
tor_free(content);
- tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, NULL));
- /* Test Torflow with additional headers afer a correct bw line and more
- * bw lines after the headers. */
- tor_asprintf(&content, "%ld\n%s%s%s", (long)timestamp, torflow_relay_lines,
- v110_header_lines, torflow_relay_lines);
+ /* Test bandwidth file including v1.1.0 bandwidth headers and
+ * v1.0.0 relay lines. bw_file_headers will contain the v1.1.0 headers. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s%s", header_lines_v100, header_lines_v110,
+ relay_lines_v100);
write_str_to_file(fname, content, 0);
tor_free(content);
- tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
-
- /* Test sbws file */
- const char *sbws_relay_lines=
- "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A27F80 "
- "master_key_ed25519=YaqV4vbvPYKucElk297eVdNArDz9HtIwUoIeo0+cVIpQ "
- "bw=760 nick=Test rtt=380 time=2018-05-08T16:13:26\n";
-
- tor_asprintf(&content, "%ld\n%s%s", (long)timestamp, v110_header_lines,
- sbws_relay_lines);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.0.0 complete bandwidth file with v1.1.0 headers at the end.
+ * bw_file_headers will contain only v1.0.0 headers and the additional
+ * headers will be interpreted as malformed relay lines. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s%s", header_lines_v100, relay_lines_v100,
+ header_lines_v110);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v100, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.0.0 complete bandwidth file, the v1.1.0 headers and more relay
+ * lines. bw_file_headers will contain only v1.0.0 headers, the additional
+ * headers will be interpreted as malformed relay lines and the last relay
+ * lines will be correctly interpreted as relay lines. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s%s%s", header_lines_v100, relay_lines_v100,
+ header_lines_v110, relay_lines_v100);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v100, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.1.0 bandwidth headers without terminator */
+ bw_file_headers = smartlist_new();
+ write_str_to_file(fname, header_lines_v110_no_terminator, 0);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.1.0 bandwidth headers with terminator */
+ bw_file_headers = smartlist_new();
+ write_str_to_file(fname, header_lines_v110, 0);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.1.0 bandwidth file without terminator, then relay lines.
+ * bw_file_headers will contain the v1.1.0 headers. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s",
+ header_lines_v110_no_terminator, relay_lines_v110);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.1.0 bandwidth headers with terminator, then relay lines
+ * bw_file_headers will contain the v1.1.0 headers. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s",
+ header_lines_v110, relay_lines_v110);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.1.0 bandwidth headers with terminator, then bad relay lines,
+ * then terminator, then relay_lines_bad.
+ * bw_file_headers will contain the v1.1.0 headers. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s%s%s", header_lines_v110, relay_lines_bad,
+ BW_FILE_HEADERS_TERMINATOR, relay_lines_bad);
write_str_to_file(fname, content, 0);
tor_free(content);
- tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.1.0 bandwidth headers without terminator, then bad relay lines,
+ * then relay lines. bw_file_headers will contain the v1.1.0 headers and
+ * the bad relay lines. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s%s",
+ header_lines_v110_no_terminator, relay_lines_bad,
+ relay_lines_v110);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_bad, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.1.0 bandwidth headers without terminator,
+ * then many bad relay lines, then relay lines.
+ * bw_file_headers will contain the v1.1.0 headers and the bad relay lines
+ * to a maximum of MAX_BW_FILE_HEADER_COUNT_IN_VOTE header lines. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s%s",
+ header_lines_v110_no_terminator, header_lines_long,
+ relay_lines_v110);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ tt_int_op(MAX_BW_FILE_HEADER_COUNT_IN_VOTE, OP_EQ,
+ smartlist_len(bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_extra, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.1.0 bandwidth headers without terminator,
+ * then many bad relay lines, then relay lines.
+ * bw_file_headers will contain the v1.1.0 headers and the bad relay lines.
+ * Force bw_file_headers to have more than MAX_BW_FILE_HEADER_COUNT_IN_VOTE
+ * This test is needed while there is not dirvote test. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s%s",
+ header_lines_v110_no_terminator, header_lines_long,
+ relay_lines_v110);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ tt_int_op(MAX_BW_FILE_HEADER_COUNT_IN_VOTE, OP_EQ,
+ smartlist_len(bw_file_headers));
+ /* force bw_file_headers to be bigger than
+ * MAX_BW_FILE_HEADER_COUNT_IN_VOTE */
+ char line[8] = "foo=bar\0";
+ smartlist_add_strdup(bw_file_headers, line);
+ tt_int_op(MAX_BW_FILE_HEADER_COUNT_IN_VOTE, OP_LT,
+ smartlist_len(bw_file_headers));
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
done:
tor_free(fname);
+ tor_free(header_lines_v100);
+ tor_free(header_lines_v110_no_terminator);
+ tor_free(header_lines_v110);
+ tor_free(bw_file_headers_str_v100);
+ tor_free(bw_file_headers_str_v110);
+ tor_free(bw_file_headers_str_bad);
+ tor_free(bw_file_headers_str_extra);
}
#define MBWC_INIT_TIME 1000
@@ -5979,6 +6206,57 @@ test_dir_networkstatus_consensus_has_ipv6(void *arg)
UNMOCK(networkstatus_get_latest_consensus_by_flavor);
}
+static void
+test_dir_format_versions_list(void *arg)
+{
+ (void)arg;
+ char *s = NULL;
+ config_line_t *lines = NULL;
+
+ setup_capture_of_logs(LOG_WARN);
+ s = format_recommended_version_list(lines, 1);
+ tt_str_op(s, OP_EQ, "");
+
+ tor_free(s);
+ config_line_append(&lines, "ignored", "0.3.4.1, 0.2.9.111-alpha, 4.4.4-rc");
+ s = format_recommended_version_list(lines, 1);
+ tt_str_op(s, OP_EQ, "0.2.9.111-alpha,0.3.4.1,4.4.4-rc");
+
+ tor_free(s);
+ config_line_append(&lines, "ignored", "0.1.2.3,0.2.9.10 ");
+ s = format_recommended_version_list(lines, 1);
+ tt_str_op(s, OP_EQ, "0.1.2.3,0.2.9.10,0.2.9.111-alpha,0.3.4.1,4.4.4-rc");
+
+ /* There should be no warnings so far. */
+ expect_no_log_entry();
+
+ /* Now try a line with a space in it. */
+ tor_free(s);
+ config_line_append(&lines, "ignored", "1.3.3.8 1.3.3.7");
+ s = format_recommended_version_list(lines, 1);
+ tt_str_op(s, OP_EQ, "0.1.2.3,0.2.9.10,0.2.9.111-alpha,0.3.4.1,"
+ "1.3.3.7,1.3.3.8,4.4.4-rc");
+
+ expect_single_log_msg_containing(
+ "Unexpected space in versions list member \"1.3.3.8 1.3.3.7\"." );
+
+ /* Start over, with a line containing a bogus version */
+ config_free_lines(lines);
+ lines = NULL;
+ tor_free(s);
+ mock_clean_saved_logs();
+ config_line_append(&lines, "ignored", "0.1.2.3, alpha-complex, 0.1.1.8-rc");
+ s = format_recommended_version_list(lines,1);
+ tt_str_op(s, OP_EQ, "0.1.1.8-rc,0.1.2.3,alpha-complex");
+ expect_single_log_msg_containing(
+ "Recommended version \"alpha-complex\" does not look valid.");
+
+ done:
+ tor_free(s);
+ config_free_lines(lines);
+ teardown_capture_of_logs();
+}
+
#define DIR_LEGACY(name) \
{ #name, test_dir_ ## name , TT_FORK, NULL, NULL }
@@ -6001,7 +6279,6 @@ struct testcase_t dir_tests[] = {
DIR_LEGACY(versions),
DIR_LEGACY(fp_pairs),
DIR(split_fps, 0),
- DIR_LEGACY(dirserv_read_measured_bandwidths_empty),
DIR_LEGACY(measured_bw_kb),
DIR_LEGACY(measured_bw_kb_line_is_after_headers),
DIR_LEGACY(measured_bw_kb_cache),
@@ -6049,5 +6326,6 @@ struct testcase_t dir_tests[] = {
DIR(networkstatus_compute_bw_weights_v10, 0),
DIR(platform_str, 0),
DIR(networkstatus_consensus_has_ipv6, TT_FORK),
+ DIR(format_versions_list, TT_FORK),
END_OF_TESTCASES
};
diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c
index c666bca59a..c9138611d8 100644
--- a/src/test/test_helpers.c
+++ b/src/test/test_helpers.c
@@ -24,6 +24,7 @@
#include "core/or/relay.h"
#include "feature/nodelist/routerlist.h"
#include "lib/encoding/confline.h"
+#include "lib/net/resolve.h"
#include "core/or/cell_st.h"
#include "core/or/connection_st.h"
diff --git a/src/test/test_hs_cell.c b/src/test/test_hs_cell.c
index b47929e8eb..5b48dd3785 100644
--- a/src/test/test_hs_cell.c
+++ b/src/test/test_hs_cell.c
@@ -39,7 +39,7 @@ test_gen_establish_intro_cell(void *arg)
attempt to parse it. */
{
/* We only need the auth key pair here. */
- hs_service_intro_point_t *ip = service_intro_point_new(NULL, 0);
+ hs_service_intro_point_t *ip = service_intro_point_new(NULL, 0, 0);
/* Auth key pair is generated in the constructor so we are all set for
* using this IP object. */
ret = hs_cell_build_establish_intro(circ_nonce, ip, buf);
@@ -107,7 +107,7 @@ test_gen_establish_intro_cell_bad(void *arg)
ed25519_sign_prefixed() function and make it fail. */
cell = trn_cell_establish_intro_new();
tt_assert(cell);
- ip = service_intro_point_new(NULL, 0);
+ ip = service_intro_point_new(NULL, 0, 0);
cell_len = hs_cell_build_establish_intro(circ_nonce, ip, NULL);
service_intro_point_free(ip);
expect_log_msg_containing("Unable to make signature for "
diff --git a/src/test/test_hs_common.c b/src/test/test_hs_common.c
index f17cc8aeb3..c1001ee5c4 100644
--- a/src/test/test_hs_common.c
+++ b/src/test/test_hs_common.c
@@ -1344,6 +1344,10 @@ run_reachability_scenario(const reachability_cfg_t *cfg, int num_scenario)
&mock_service_ns->fresh_until);
voting_schedule_recalculate_timing(get_options(),
mock_service_ns->valid_after);
+ /* Check that service is in the right time period point */
+ tt_int_op(hs_in_period_between_tp_and_srv(mock_service_ns, 0), OP_EQ,
+ cfg->service_in_new_tp);
+
/* Set client consensus time. */
set_consensus_times(cfg->client_valid_after,
&mock_client_ns->valid_after);
@@ -1353,10 +1357,7 @@ run_reachability_scenario(const reachability_cfg_t *cfg, int num_scenario)
&mock_client_ns->fresh_until);
voting_schedule_recalculate_timing(get_options(),
mock_client_ns->valid_after);
-
- /* New time period checks for this scenario. */
- tt_int_op(hs_in_period_between_tp_and_srv(mock_service_ns, 0), OP_EQ,
- cfg->service_in_new_tp);
+ /* Check that client is in the right time period point */
tt_int_op(hs_in_period_between_tp_and_srv(mock_client_ns, 0), OP_EQ,
cfg->client_in_new_tp);
@@ -1367,7 +1368,8 @@ run_reachability_scenario(const reachability_cfg_t *cfg, int num_scenario)
mock_service_ns->sr_info.previous_srv = cfg->service_previous_srv;
/* Initialize a service to get keys. */
- service = helper_init_service(time(NULL));
+ update_approx_time(mock_service_ns->valid_after);
+ service = helper_init_service(mock_service_ns->valid_after+1);
/*
* === Client setup ===
diff --git a/src/test/test_hs_intropoint.c b/src/test/test_hs_intropoint.c
index 7da376471b..628d99bfde 100644
--- a/src/test/test_hs_intropoint.c
+++ b/src/test/test_hs_intropoint.c
@@ -50,7 +50,7 @@ new_establish_intro_cell(const char *circ_nonce,
/* Auth key pair is generated in the constructor so we are all set for
* using this IP object. */
- ip = service_intro_point_new(NULL, 0);
+ ip = service_intro_point_new(NULL, 0, 0);
tt_assert(ip);
cell_len = hs_cell_build_establish_intro(circ_nonce, ip, buf);
tt_i64_op(cell_len, OP_GT, 0);
@@ -76,7 +76,7 @@ new_establish_intro_encoded_cell(const char *circ_nonce, uint8_t *cell_out)
/* Auth key pair is generated in the constructor so we are all set for
* using this IP object. */
- ip = service_intro_point_new(NULL, 0);
+ ip = service_intro_point_new(NULL, 0, 0);
tt_assert(ip);
cell_len = hs_cell_build_establish_intro(circ_nonce, ip, cell_out);
tt_i64_op(cell_len, OP_GT, 0);
diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c
index 8074d260a4..ad0b3ab342 100644
--- a/src/test/test_hs_service.c
+++ b/src/test/test_hs_service.c
@@ -250,7 +250,7 @@ static hs_service_intro_point_t *
helper_create_service_ip(void)
{
hs_desc_link_specifier_t *ls;
- hs_service_intro_point_t *ip = service_intro_point_new(NULL, 0);
+ hs_service_intro_point_t *ip = service_intro_point_new(NULL, 0, 0);
tor_assert(ip);
/* Add a first unused link specifier. */
ls = tor_malloc_zero(sizeof(*ls));
@@ -1044,7 +1044,7 @@ static void
test_rotate_descriptors(void *arg)
{
int ret;
- time_t next_rotation_time, now = time(NULL);
+ time_t next_rotation_time, now;
hs_service_t *service;
hs_service_descriptor_t *desc_next;
@@ -1068,6 +1068,9 @@ test_rotate_descriptors(void *arg)
tt_int_op(ret, OP_EQ, 0);
voting_schedule_recalculate_timing(get_options(), mock_ns.valid_after);
+ update_approx_time(mock_ns.valid_after+1);
+ now = mock_ns.valid_after+1;
+
/* Create a service with a default descriptor and state. It's added to the
* global map. */
service = helper_create_service();
@@ -1106,6 +1109,9 @@ test_rotate_descriptors(void *arg)
tt_int_op(ret, OP_EQ, 0);
voting_schedule_recalculate_timing(get_options(), mock_ns.valid_after);
+ update_approx_time(mock_ns.valid_after+1);
+ now = mock_ns.valid_after+1;
+
/* Note down what to expect for the next rotation time which is 01:00 + 23h
* meaning 00:00:00. */
next_rotation_time = mock_ns.valid_after + (23 * 60 * 60);
@@ -1168,6 +1174,9 @@ test_build_update_descriptors(void *arg)
tt_int_op(ret, OP_EQ, 0);
voting_schedule_recalculate_timing(get_options(), mock_ns.valid_after);
+ update_approx_time(mock_ns.valid_after+1);
+ now = mock_ns.valid_after+1;
+
/* Create a service without a current descriptor to trigger a build. */
service = helper_create_service();
tt_assert(service);
@@ -1309,6 +1318,9 @@ test_build_update_descriptors(void *arg)
&mock_ns.fresh_until);
tt_int_op(ret, OP_EQ, 0);
+ update_approx_time(mock_ns.valid_after+1);
+ now = mock_ns.valid_after+1;
+
/* Create a service without a current descriptor to trigger a build. */
service = helper_create_service();
tt_assert(service);
@@ -1363,7 +1375,7 @@ static void
test_upload_descriptors(void *arg)
{
int ret;
- time_t now = time(NULL);
+ time_t now;
hs_service_t *service;
(void) arg;
@@ -1382,6 +1394,10 @@ test_upload_descriptors(void *arg)
ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
&mock_ns.fresh_until);
tt_int_op(ret, OP_EQ, 0);
+ voting_schedule_recalculate_timing(get_options(), mock_ns.valid_after);
+
+ update_approx_time(mock_ns.valid_after+1);
+ now = mock_ns.valid_after+1;
/* Create a service with no descriptor. It's added to the global map. */
service = hs_service_new(get_options());
@@ -1416,66 +1432,6 @@ test_upload_descriptors(void *arg)
UNMOCK(get_or_state);
}
-/** Test the functions that save and load HS revision counters to state. */
-static void
-test_revision_counter_state(void *arg)
-{
- char *state_line_one = NULL;
- char *state_line_two = NULL;
-
- hs_service_descriptor_t *desc_one = service_descriptor_new();
- hs_service_descriptor_t *desc_two = service_descriptor_new();
-
- (void) arg;
-
- /* Prepare both descriptors */
- desc_one->desc->plaintext_data.revision_counter = 42;
- desc_two->desc->plaintext_data.revision_counter = 240;
- memset(&desc_one->blinded_kp.pubkey.pubkey, 66,
- sizeof(desc_one->blinded_kp.pubkey.pubkey));
- memset(&desc_two->blinded_kp.pubkey.pubkey, 240,
- sizeof(desc_one->blinded_kp.pubkey.pubkey));
-
- /* Turn the descriptor rev counters into state lines */
- state_line_one = encode_desc_rev_counter_for_state(desc_one);
- tt_str_op(state_line_one, OP_EQ,
- "QkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkI 42");
-
- state_line_two = encode_desc_rev_counter_for_state(desc_two);
- tt_str_op(state_line_two, OP_EQ,
- "8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PA 240");
-
- /* Now let's test our state parsing function: */
- int service_found;
- uint64_t cached_rev_counter;
-
- /* First's try with wrong pubkey and check that no service was found */
- cached_rev_counter =check_state_line_for_service_rev_counter(state_line_one,
- &desc_two->blinded_kp.pubkey,
- &service_found);
- tt_int_op(service_found, OP_EQ, 0);
- tt_u64_op(cached_rev_counter, OP_EQ, 0);
-
- /* Now let's try with the right pubkeys */
- cached_rev_counter =check_state_line_for_service_rev_counter(state_line_one,
- &desc_one->blinded_kp.pubkey,
- &service_found);
- tt_int_op(service_found, OP_EQ, 1);
- tt_u64_op(cached_rev_counter, OP_EQ, 42);
-
- cached_rev_counter =check_state_line_for_service_rev_counter(state_line_two,
- &desc_two->blinded_kp.pubkey,
- &service_found);
- tt_int_op(service_found, OP_EQ, 1);
- tt_u64_op(cached_rev_counter, OP_EQ, 240);
-
- done:
- tor_free(state_line_one);
- tor_free(state_line_two);
- service_descriptor_free(desc_one);
- service_descriptor_free(desc_two);
-}
-
/** Global vars used by test_rendezvous1_parsing() */
static char rend1_payload[RELAY_PAYLOAD_SIZE];
static size_t rend1_payload_len = 0;
@@ -1629,8 +1585,6 @@ struct testcase_t hs_service_tests[] = {
NULL, NULL },
{ "upload_descriptors", test_upload_descriptors, TT_FORK,
NULL, NULL },
- { "revision_counter_state", test_revision_counter_state, TT_FORK,
- NULL, NULL },
{ "rendezvous1_parsing", test_rendezvous1_parsing, TT_FORK,
NULL, NULL },
diff --git a/src/test/test_key_expiration.sh b/src/test/test_key_expiration.sh
index 5511dbf18c..cf6608634d 100755
--- a/src/test/test_key_expiration.sh
+++ b/src/test/test_key_expiration.sh
@@ -13,6 +13,14 @@ if [ $# -eq 0 ] || [ ! -f ${1} ] || [ ! -x ${1} ]; then
fi
fi
+UNAME_OS=`uname -s | cut -d_ -f1`
+if test "$UNAME_OS" = 'CYGWIN' || \
+ test "$UNAME_OS" = 'MSYS' || \
+ test "$UNAME_OS" = 'MINGW'; then
+ echo "This test is unreliable on Windows. See trac #26076. Skipping." >&2
+ exit 77
+fi
+
if [ $# -ge 1 ]; then
TOR_BINARY="${1}"
shift
diff --git a/src/test/test_keygen.sh b/src/test/test_keygen.sh
index b3d4d8e39a..455f9e7d42 100755
--- a/src/test/test_keygen.sh
+++ b/src/test/test_keygen.sh
@@ -13,6 +13,14 @@ if [ $# -eq 0 ] || [ ! -f ${1} ] || [ ! -x ${1} ]; then
fi
fi
+UNAME_OS=`uname -s | cut -d_ -f1`
+if test "$UNAME_OS" = 'CYGWIN' || \
+ test "$UNAME_OS" = 'MSYS' || \
+ test "$UNAME_OS" = 'MINGW'; then
+ echo "This test is unreliable on Windows. See trac #26076. Skipping." >&2
+ exit 77
+fi
+
if [ $# -ge 1 ]; then
TOR_BINARY="${1}"
shift
diff --git a/src/test/test_logging.c b/src/test/test_logging.c
index 2e3b8800ac..cd685a4af7 100644
--- a/src/test/test_logging.c
+++ b/src/test/test_logging.c
@@ -7,7 +7,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
#include "lib/err/torerr.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "test/test.h"
#include "lib/process/subprocess.h"
diff --git a/src/test/test_options.c b/src/test/test_options.c
index 396965401e..4e890205b2 100644
--- a/src/test/test_options.c
+++ b/src/test/test_options.c
@@ -21,6 +21,7 @@
#include "lib/encoding/confline.h"
#include "core/or/policies.h"
#include "test/test_helpers.h"
+#include "lib/net/resolve.h"
#define NS_MODULE test_options
diff --git a/src/test/test_pt.c b/src/test/test_pt.c
index dea3791da2..d0160d1148 100644
--- a/src/test/test_pt.c
+++ b/src/test/test_pt.c
@@ -19,6 +19,7 @@
#include "test/test.h"
#include "lib/process/subprocess.h"
#include "lib/encoding/confline.h"
+#include "lib/net/resolve.h"
#include "app/config/or_state_st.h"
diff --git a/src/test/test_shared_random.c b/src/test/test_shared_random.c
index b0a9da0033..d2defdf680 100644
--- a/src/test/test_shared_random.c
+++ b/src/test/test_shared_random.c
@@ -259,8 +259,7 @@ test_get_start_time_of_current_run(void *arg)
&current_time);
tt_int_op(retval, OP_EQ, 0);
voting_schedule_recalculate_timing(get_options(), current_time);
- run_start_time =
- sr_state_get_start_time_of_current_protocol_run(current_time);
+ run_start_time = sr_state_get_start_time_of_current_protocol_run();
/* Compare it with the correct result */
format_iso_time(tbuf, run_start_time);
@@ -272,8 +271,7 @@ test_get_start_time_of_current_run(void *arg)
&current_time);
tt_int_op(retval, OP_EQ, 0);
voting_schedule_recalculate_timing(get_options(), current_time);
- run_start_time =
- sr_state_get_start_time_of_current_protocol_run(current_time);
+ run_start_time = sr_state_get_start_time_of_current_protocol_run();
/* Compare it with the correct result */
format_iso_time(tbuf, run_start_time);
@@ -285,8 +283,7 @@ test_get_start_time_of_current_run(void *arg)
&current_time);
tt_int_op(retval, OP_EQ, 0);
voting_schedule_recalculate_timing(get_options(), current_time);
- run_start_time =
- sr_state_get_start_time_of_current_protocol_run(current_time);
+ run_start_time = sr_state_get_start_time_of_current_protocol_run();
/* Compare it with the correct result */
format_iso_time(tbuf, run_start_time);
@@ -308,8 +305,7 @@ test_get_start_time_of_current_run(void *arg)
&current_time);
tt_int_op(retval, OP_EQ, 0);
voting_schedule_recalculate_timing(get_options(), current_time);
- run_start_time =
- sr_state_get_start_time_of_current_protocol_run(current_time);
+ run_start_time = sr_state_get_start_time_of_current_protocol_run();
/* Compare it with the correct result */
format_iso_time(tbuf, run_start_time);
@@ -342,7 +338,7 @@ test_get_start_time_functions(void *arg)
voting_schedule_recalculate_timing(get_options(), now);
time_t start_time_of_protocol_run =
- sr_state_get_start_time_of_current_protocol_run(now);
+ sr_state_get_start_time_of_current_protocol_run();
tt_assert(start_time_of_protocol_run);
/* Check that the round start time of the beginning of the run, is itself */
diff --git a/src/test/test_socks.c b/src/test/test_socks.c
index e064cc8db1..7f6d8a48f1 100644
--- a/src/test/test_socks.c
+++ b/src/test/test_socks.c
@@ -84,7 +84,7 @@ test_socks_4_supported_commands(void *ptr)
tt_int_op(0,OP_EQ, buf_datalen(buf));
- /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4370 */
+ /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.3:4370 */
ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x03\x00");
tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
get_options()->SafeSocks),
@@ -100,7 +100,7 @@ test_socks_4_supported_commands(void *ptr)
tt_int_op(0,OP_EQ, buf_datalen(buf));
socks_request_clear(socks);
- /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4369 with userid*/
+ /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.4:4369 with userid*/
ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x04me\x00");
tt_int_op(fetch_from_buf_socks(buf, socks, 1, 0),
OP_EQ, 1);
@@ -166,7 +166,7 @@ test_socks_4_bad_arguments(void *ptr)
tt_int_op(fetch_from_buf_socks(buf, socks, 1, 0),
OP_EQ, -1);
buf_clear(buf);
- expect_log_msg_containing("user name too long; rejecting.");
+ expect_log_msg_containing("socks4: parsing failed - invalid request.");
mock_clean_saved_logs();
/* Try with 2000-byte hostname */
@@ -194,7 +194,7 @@ test_socks_4_bad_arguments(void *ptr)
tt_int_op(fetch_from_buf_socks(buf, socks, 1, 0),
OP_EQ, -1);
buf_clear(buf);
- expect_log_msg_containing("Destaddr too long.");
+ expect_log_msg_containing("parsing failed - invalid request.");
mock_clean_saved_logs();
/* Socks4, bogus hostname */
@@ -648,7 +648,8 @@ test_socks_5_malformed_commands(void *ptr)
tt_int_op(5,OP_EQ,socks->socks_version);
tt_int_op(10,OP_EQ,socks->replylen);
tt_int_op(5,OP_EQ,socks->reply[0]);
- tt_int_op(SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED,OP_EQ,socks->reply[1]);
+ /* trunnel parsing will fail with -1 */
+ tt_int_op(SOCKS5_GENERAL_ERROR,OP_EQ,socks->reply[1]);
tt_int_op(1,OP_EQ,socks->reply[3]);
done:
diff --git a/src/test/test_status.c b/src/test/test_status.c
index 3cc23955ad..15c406d2ff 100644
--- a/src/test/test_status.c
+++ b/src/test/test_status.c
@@ -12,7 +12,7 @@
#include <math.h>
#include "core/or/or.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "tor_queue.h"
#include "core/or/status.h"
#include "core/or/circuitlist.h"
diff --git a/src/test/test_tortls.c b/src/test/test_tortls.c
index 2b40ed72d9..54e5eca4f9 100644
--- a/src/test/test_tortls.c
+++ b/src/test/test_tortls.c
@@ -31,7 +31,7 @@ DISABLE_GCC_WARNING(redundant-decls)
ENABLE_GCC_WARNING(redundant-decls)
#include "core/or/or.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "app/config/config.h"
#include "lib/tls/tortls.h"
#include "app/config/or_state_st.h"
diff --git a/src/test/test_util_slow.c b/src/test/test_util_slow.c
index 5021e89dff..c5b24487b1 100644
--- a/src/test/test_util_slow.c
+++ b/src/test/test_util_slow.c
@@ -7,7 +7,7 @@
#define UTIL_PRIVATE
#define SUBPROCESS_PRIVATE
#include "lib/crypt_ops/crypto.h"
-#include "lib/log/torlog.h"
+#include "lib/log/log.h"
#include "lib/process/subprocess.h"
#include "lib/process/waitpid.h"
#include "lib/string/printf.h"
diff --git a/src/tools/Makefile.nmake b/src/tools/Makefile.nmake
index fda1990e0b..e223d9b135 100644
--- a/src/tools/Makefile.nmake
+++ b/src/tools/Makefile.nmake
@@ -1,4 +1,4 @@
-all: tor-resolve.exe tor-gencert.exe
+all: tor-resolve.exe tor-gencert.exe tor-print-ed-signing-cert.exe
CFLAGS = /I ..\win32 /I ..\..\..\build-alpha\include /I ..\common /I ..\or
@@ -15,5 +15,8 @@ tor-gencert.exe: tor-gencert.obj
tor-resolve.exe: tor-resolve.obj
$(CC) $(CFLAGS) $(LIBS) ..\common\*.lib tor-resolve.obj
+tor-print-ed-signing-cert.exe: tor-print-ed-signing-cert.obj
+ $(CC) $(CFLAGS) $(LIBS) ..\common\*.lib tor-print-ed-signing-cert.obj
+
clean:
del *.obj *.lib *.exe
diff --git a/src/tools/include.am b/src/tools/include.am
index 8a2ecb23c9..d5924dda5f 100644
--- a/src/tools/include.am
+++ b/src/tools/include.am
@@ -1,4 +1,4 @@
-bin_PROGRAMS+= src/tools/tor-resolve src/tools/tor-gencert
+bin_PROGRAMS+= src/tools/tor-resolve src/tools/tor-gencert src/tools/tor-print-ed-signing-cert
if COVERAGE_ENABLED
noinst_PROGRAMS+= src/tools/tor-cov-resolve src/tools/tor-cov-gencert
@@ -29,6 +29,15 @@ src_tools_tor_gencert_LDADD = \
@TOR_LIB_MATH@ @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ \
@TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@
+src_tools_tor_print_ed_signing_cert_SOURCES = src/tools/tor-print-ed-signing-cert.c
+src_tools_tor_print_ed_signing_cert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@
+src_tools_tor_print_ed_signing_cert_LDADD = \
+ src/trunnel/libor-trunnel.a \
+ $(TOR_CRYPTO_LIBS) \
+ $(TOR_UTIL_LIBS) \
+ @TOR_LIB_MATH@ @TOR_OPENSSL_LIBS@ \
+ @TOR_LIB_WS32@ @TOR_LIB_USERENV@
+
if COVERAGE_ENABLED
src_tools_tor_cov_gencert_SOURCES = src/tools/tor-gencert.c
src_tools_tor_cov_gencert_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
diff --git a/src/tools/tor-gencert.c b/src/tools/tor-gencert.c
index ce032ed643..ff924152a6 100644
--- a/src/tools/tor-gencert.c
+++ b/src/tools/tor-gencert.c
@@ -38,10 +38,11 @@ ENABLE_GCC_WARNING(redundant-decls)
#include "lib/encoding/binascii.h"
#include "lib/encoding/time_fmt.h"
#include "lib/fs/files.h"
-#include "lib/log/torlog.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/log/log.h"
+#include "lib/malloc/malloc.h"
#include "lib/net/address.h"
-#include "lib/net/ipv4.h"
+#include "lib/net/inaddr.h"
+#include "lib/net/resolve.h"
#include "lib/string/compat_string.h"
#include "lib/string/printf.h"
@@ -170,19 +171,22 @@ parse_commandline(int argc, char **argv)
} else if (!strcmp(argv[i], "-v")) {
verbose = 1;
} else if (!strcmp(argv[i], "-a")) {
- uint32_t addr;
+ tor_addr_t addr;
uint16_t port;
- char b[INET_NTOA_BUF_LEN];
- struct in_addr in;
if (i+1>=argc) {
fprintf(stderr, "No argument to -a\n");
return 1;
}
- if (addr_port_lookup(LOG_ERR, argv[++i], NULL, &addr, &port)<0)
+ const char *addr_arg = argv[++i];
+ if (tor_addr_port_lookup(addr_arg, &addr, &port)<0) {
+ fprintf(stderr, "Can't resolve address/port for %s", addr_arg);
return 1;
- in.s_addr = htonl(addr);
- tor_inet_ntoa(&in, b, sizeof(b));
- tor_asprintf(&address, "%s:%d", b, (int)port);
+ }
+ if (tor_addr_family(&addr) != AF_INET) {
+ fprintf(stderr, "%s must resolve to an IPv4 address", addr_arg);
+ return 1;
+ }
+ address = tor_strdup(fmt_addrport(&addr, port));
} else if (!strcmp(argv[i], "--create-identity-key")) {
make_new_id = 1;
} else if (!strcmp(argv[i], "--passphrase-fd")) {
diff --git a/src/tools/tor-print-ed-signing-cert.c b/src/tools/tor-print-ed-signing-cert.c
new file mode 100644
index 0000000000..ca53e34d5d
--- /dev/null
+++ b/src/tools/tor-print-ed-signing-cert.c
@@ -0,0 +1,64 @@
+/* Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "ed25519_cert.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/malloc/malloc.h"
+
+int
+main(int argc, char **argv)
+{
+ ed25519_cert_t *cert = NULL;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "%s <path to ed25519_signing_cert file>\n", argv[0]);
+ return -1;
+ }
+
+ const char *filepath = argv[1];
+ char *got_tag = NULL;
+
+ uint8_t certbuf[256];
+ ssize_t cert_body_len = crypto_read_tagged_contents_from_file(
+ filepath, "ed25519v1-cert",
+ &got_tag, certbuf, sizeof(certbuf));
+
+ if (cert_body_len <= 0) {
+ fprintf(stderr, "crypto_read_tagged_contents_from_file failed with "
+ "error: %s\n", strerror(errno));
+ return -2;
+ }
+
+ if (!got_tag) {
+ fprintf(stderr, "Found no tag\n");
+ return -3;
+ }
+
+ if (strcmp(got_tag, "type4") != 0) {
+ fprintf(stderr, "Wrong tag: %s\n", got_tag);
+ return -4;
+ }
+
+ tor_free(got_tag);
+
+ ssize_t parsed = ed25519_cert_parse(&cert, certbuf, cert_body_len);
+ if (parsed <= 0) {
+ fprintf(stderr, "ed25519_cert_parse failed with return value %zd\n",
+ parsed);
+ return -5;
+ }
+
+ time_t expires_at = (time_t)cert->exp_field * 60 * 60;
+
+ printf("Expires at: %s", ctime(&expires_at));
+
+ ed25519_cert_free(cert);
+
+ return 0;
+}
diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c
index 1532d5f201..d5b4987832 100644
--- a/src/tools/tor-resolve.c
+++ b/src/tools/tor-resolve.c
@@ -6,8 +6,8 @@
#include "orconfig.h"
#include "lib/arch/bytes.h"
-#include "lib/log/torlog.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/log/log.h"
+#include "lib/malloc/malloc.h"
#include "lib/net/address.h"
#include "lib/net/resolve.h"
#include "lib/net/socket.h"
@@ -197,12 +197,14 @@ socks5_reason_to_string(char reason)
* address (in host order) into *<b>result_addr</b>.
*/
static int
-do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
+do_resolve(const char *hostname,
+ const tor_addr_t *sockshost, uint16_t socksport,
int reverse, int version,
tor_addr_t *result_addr, char **result_hostname)
{
int s = -1;
- struct sockaddr_in socksaddr;
+ struct sockaddr_storage ss;
+ socklen_t socklen;
char *req = NULL;
ssize_t len = 0;
@@ -219,11 +221,10 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
return -1;
}
- memset(&socksaddr, 0, sizeof(socksaddr));
- socksaddr.sin_family = AF_INET;
- socksaddr.sin_port = htons(socksport);
- socksaddr.sin_addr.s_addr = htonl(sockshost);
- if (connect(s, (struct sockaddr*)&socksaddr, sizeof(socksaddr))) {
+ socklen = tor_addr_to_sockaddr(sockshost, socksport,
+ (struct sockaddr *)&ss, sizeof(ss));
+
+ if (connect(s, (struct sockaddr*)&ss, sizeof(socklen))) {
log_sock_error("connecting to SOCKS host", s);
goto err;
}
@@ -346,7 +347,7 @@ usage(void)
int
main(int argc, char **argv)
{
- uint32_t sockshost;
+ tor_addr_t sockshost;
uint16_t socksport = 0, port_option = 0;
int isSocks4 = 0, isVerbose = 0, isReverse = 0;
char **arg;
@@ -414,7 +415,7 @@ main(int argc, char **argv)
if (n_args == 1) {
log_debug(LD_CONFIG, "defaulting to localhost");
- sockshost = 0x7f000001u; /* localhost */
+ tor_addr_from_ipv4h(&sockshost, 0x7f000001u); /* localhost */
if (port_option) {
log_debug(LD_CONFIG, "Using port %d", (int)port_option);
socksport = port_option;
@@ -423,7 +424,7 @@ main(int argc, char **argv)
socksport = 9050; /* 9050 */
}
} else if (n_args == 2) {
- if (addr_port_lookup(LOG_WARN, arg[1], NULL, &sockshost, &socksport)<0) {
+ if (tor_addr_port_lookup(arg[1], &sockshost, &socksport)<0) {
fprintf(stderr, "Couldn't parse/resolve address %s", arg[1]);
return 1;
}
@@ -445,7 +446,7 @@ main(int argc, char **argv)
return 1;
}
- if (do_resolve(arg[0], sockshost, socksport, isReverse,
+ if (do_resolve(arg[0], &sockshost, socksport, isReverse,
isSocks4 ? 4 : 5, &result,
&result_hostname))
return 1;
diff --git a/src/trunnel/include.am b/src/trunnel/include.am
index 5a0a79c3a0..03c1753e96 100644
--- a/src/trunnel/include.am
+++ b/src/trunnel/include.am
@@ -10,7 +10,8 @@ TRUNNELINPUTS = \
src/trunnel/ed25519_cert.trunnel \
src/trunnel/link_handshake.trunnel \
src/trunnel/pwbox.trunnel \
- src/trunnel/channelpadding_negotiation.trunnel
+ src/trunnel/channelpadding_negotiation.trunnel \
+ src/trunner/socks5.trunnel
TRUNNELSOURCES = \
src/ext/trunnel/trunnel.c \
@@ -21,7 +22,8 @@ TRUNNELSOURCES = \
src/trunnel/hs/cell_establish_intro.c \
src/trunnel/hs/cell_introduce1.c \
src/trunnel/hs/cell_rendezvous.c \
- src/trunnel/channelpadding_negotiation.c
+ src/trunnel/channelpadding_negotiation.c \
+ src/trunnel/socks5.c
TRUNNELHEADERS = \
src/ext/trunnel/trunnel.h \
@@ -34,7 +36,8 @@ TRUNNELHEADERS = \
src/trunnel/hs/cell_establish_intro.h \
src/trunnel/hs/cell_introduce1.h \
src/trunnel/hs/cell_rendezvous.h \
- src/trunnel/channelpadding_negotiation.h
+ src/trunnel/channelpadding_negotiation.h \
+ src/trunnel/socks5.h
src_trunnel_libor_trunnel_a_SOURCES = $(TRUNNELSOURCES)
src_trunnel_libor_trunnel_a_CPPFLAGS = \
diff --git a/src/trunnel/socks5.c b/src/trunnel/socks5.c
new file mode 100644
index 0000000000..9e5f6fcfed
--- /dev/null
+++ b/src/trunnel/socks5.c
@@ -0,0 +1,3978 @@
+/* socks5.c -- generated by Trunnel v1.5.2.
+ * https://gitweb.torproject.org/trunnel.git
+ * You probably shouldn't edit this file.
+ */
+#include <stdlib.h>
+#include "trunnel-impl.h"
+
+#include "socks5.h"
+
+#define TRUNNEL_SET_ERROR_CODE(obj) \
+ do { \
+ (obj)->trunnel_error_code_ = 1; \
+ } while (0)
+
+#if defined(__COVERITY__) || defined(__clang_analyzer__)
+/* If we're running a static analysis tool, we don't want it to complain
+ * that some of our remaining-bytes checks are dead-code. */
+int socks_deadcode_dummy__ = 0;
+#define OR_DEADCODE_DUMMY || socks_deadcode_dummy__
+#else
+#define OR_DEADCODE_DUMMY
+#endif
+
+#define CHECK_REMAINING(nbytes, label) \
+ do { \
+ if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \
+ goto label; \
+ } \
+ } while (0)
+
+domainname_t *
+domainname_new(void)
+{
+ domainname_t *val = trunnel_calloc(1, sizeof(domainname_t));
+ if (NULL == val)
+ return NULL;
+ return val;
+}
+
+/** Release all storage held inside 'obj', but do not free 'obj'.
+ */
+static void
+domainname_clear(domainname_t *obj)
+{
+ (void) obj;
+ TRUNNEL_DYNARRAY_WIPE(&obj->name);
+ TRUNNEL_DYNARRAY_CLEAR(&obj->name);
+}
+
+void
+domainname_free(domainname_t *obj)
+{
+ if (obj == NULL)
+ return;
+ domainname_clear(obj);
+ trunnel_memwipe(obj, sizeof(domainname_t));
+ trunnel_free_(obj);
+}
+
+uint8_t
+domainname_get_len(const domainname_t *inp)
+{
+ return inp->len;
+}
+int
+domainname_set_len(domainname_t *inp, uint8_t val)
+{
+ inp->len = val;
+ return 0;
+}
+size_t
+domainname_getlen_name(const domainname_t *inp)
+{
+ return TRUNNEL_DYNARRAY_LEN(&inp->name);
+}
+
+char
+domainname_get_name(domainname_t *inp, size_t idx)
+{
+ return TRUNNEL_DYNARRAY_GET(&inp->name, idx);
+}
+
+char
+domainname_getconst_name(const domainname_t *inp, size_t idx)
+{
+ return domainname_get_name((domainname_t*)inp, idx);
+}
+int
+domainname_set_name(domainname_t *inp, size_t idx, char elt)
+{
+ TRUNNEL_DYNARRAY_SET(&inp->name, idx, elt);
+ return 0;
+}
+int
+domainname_add_name(domainname_t *inp, char elt)
+{
+#if SIZE_MAX >= UINT8_MAX
+ if (inp->name.n_ == UINT8_MAX)
+ goto trunnel_alloc_failed;
+#endif
+ TRUNNEL_DYNARRAY_ADD(char, &inp->name, elt, {});
+ return 0;
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+}
+
+char *
+domainname_getarray_name(domainname_t *inp)
+{
+ return inp->name.elts_;
+}
+const char *
+domainname_getconstarray_name(const domainname_t *inp)
+{
+ return (const char *)domainname_getarray_name((domainname_t*)inp);
+}
+int
+domainname_setlen_name(domainname_t *inp, size_t newlen)
+{
+#if UINT8_MAX < SIZE_MAX
+ if (newlen > UINT8_MAX)
+ goto trunnel_alloc_failed;
+#endif
+ return trunnel_string_setlen(&inp->name, newlen,
+ &inp->trunnel_error_code_);
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+}
+const char *
+domainname_getstr_name(domainname_t *inp)
+{
+ return trunnel_string_getstr(&inp->name);
+}
+int
+domainname_setstr0_name(domainname_t *inp, const char *val, size_t len)
+{
+#if UINT8_MAX < SIZE_MAX
+ if (len > UINT8_MAX) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+#endif
+ return trunnel_string_setstr0(&inp->name, val, len, &inp->trunnel_error_code_);
+}
+int
+domainname_setstr_name(domainname_t *inp, const char *val)
+{
+ return domainname_setstr0_name(inp, val, strlen(val));
+}
+const char *
+domainname_check(const domainname_t *obj)
+{
+ if (obj == NULL)
+ return "Object was NULL";
+ if (obj->trunnel_error_code_)
+ return "A set function failed on this object";
+ if (TRUNNEL_DYNARRAY_LEN(&obj->name) != obj->len)
+ return "Length mismatch for name";
+ return NULL;
+}
+
+ssize_t
+domainname_encoded_len(const domainname_t *obj)
+{
+ ssize_t result = 0;
+
+ if (NULL != domainname_check(obj))
+ return -1;
+
+
+ /* Length of u8 len */
+ result += 1;
+
+ /* Length of char name[len] */
+ result += TRUNNEL_DYNARRAY_LEN(&obj->name);
+ return result;
+}
+int
+domainname_clear_errors(domainname_t *obj)
+{
+ int r = obj->trunnel_error_code_;
+ obj->trunnel_error_code_ = 0;
+ return r;
+}
+ssize_t
+domainname_encode(uint8_t *output, const size_t avail, const domainname_t *obj)
+{
+ ssize_t result = 0;
+ size_t written = 0;
+ uint8_t *ptr = output;
+ const char *msg;
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ const ssize_t encoded_len = domainname_encoded_len(obj);
+#endif
+
+ if (NULL != (msg = domainname_check(obj)))
+ goto check_failed;
+
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ trunnel_assert(encoded_len >= 0);
+#endif
+
+ /* Encode u8 len */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->len));
+ written += 1; ptr += 1;
+
+ /* Encode char name[len] */
+ {
+ size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->name);
+ trunnel_assert(obj->len == elt_len);
+ trunnel_assert(written <= avail);
+ if (avail - written < elt_len)
+ goto truncated;
+ if (elt_len)
+ memcpy(ptr, obj->name.elts_, elt_len);
+ written += elt_len; ptr += elt_len;
+ }
+
+
+ trunnel_assert(ptr == output + written);
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ {
+ trunnel_assert(encoded_len >= 0);
+ trunnel_assert((size_t)encoded_len == written);
+ }
+
+#endif
+
+ return written;
+
+ truncated:
+ result = -2;
+ goto fail;
+ check_failed:
+ (void)msg;
+ result = -1;
+ goto fail;
+ fail:
+ trunnel_assert(result < 0);
+ return result;
+}
+
+/** As domainname_parse(), but do not allocate the output object.
+ */
+static ssize_t
+domainname_parse_into(domainname_t *obj, const uint8_t *input, const size_t len_in)
+{
+ const uint8_t *ptr = input;
+ size_t remaining = len_in;
+ ssize_t result = 0;
+ (void)result;
+
+ /* Parse u8 len */
+ CHECK_REMAINING(1, truncated);
+ obj->len = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+
+ /* Parse char name[len] */
+ CHECK_REMAINING(obj->len, truncated);
+ if (domainname_setstr0_name(obj, (const char*)ptr, obj->len))
+ goto fail;
+ ptr += obj->len; remaining -= obj->len;
+ trunnel_assert(ptr + remaining == input + len_in);
+ return len_in - remaining;
+
+ truncated:
+ return -2;
+ fail:
+ result = -1;
+ return result;
+}
+
+ssize_t
+domainname_parse(domainname_t **output, const uint8_t *input, const size_t len_in)
+{
+ ssize_t result;
+ *output = domainname_new();
+ if (NULL == *output)
+ return -1;
+ result = domainname_parse_into(*output, input, len_in);
+ if (result < 0) {
+ domainname_free(*output);
+ *output = NULL;
+ }
+ return result;
+}
+socks4_client_request_t *
+socks4_client_request_new(void)
+{
+ socks4_client_request_t *val = trunnel_calloc(1, sizeof(socks4_client_request_t));
+ if (NULL == val)
+ return NULL;
+ val->version = 4;
+ val->command = CMD_BIND;
+ return val;
+}
+
+/** Release all storage held inside 'obj', but do not free 'obj'.
+ */
+static void
+socks4_client_request_clear(socks4_client_request_t *obj)
+{
+ (void) obj;
+ trunnel_wipestr(obj->username);
+ trunnel_free(obj->username);
+ trunnel_wipestr(obj->socks4a_addr_hostname);
+ trunnel_free(obj->socks4a_addr_hostname);
+}
+
+void
+socks4_client_request_free(socks4_client_request_t *obj)
+{
+ if (obj == NULL)
+ return;
+ socks4_client_request_clear(obj);
+ trunnel_memwipe(obj, sizeof(socks4_client_request_t));
+ trunnel_free_(obj);
+}
+
+uint8_t
+socks4_client_request_get_version(const socks4_client_request_t *inp)
+{
+ return inp->version;
+}
+int
+socks4_client_request_set_version(socks4_client_request_t *inp, uint8_t val)
+{
+ if (! ((val == 4))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ inp->version = val;
+ return 0;
+}
+uint8_t
+socks4_client_request_get_command(const socks4_client_request_t *inp)
+{
+ return inp->command;
+}
+int
+socks4_client_request_set_command(socks4_client_request_t *inp, uint8_t val)
+{
+ if (! ((val == CMD_BIND || val == CMD_CONNECT || val == CMD_RESOLVE || val == CMD_RESOLVE_PTR))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ inp->command = val;
+ return 0;
+}
+uint16_t
+socks4_client_request_get_port(const socks4_client_request_t *inp)
+{
+ return inp->port;
+}
+int
+socks4_client_request_set_port(socks4_client_request_t *inp, uint16_t val)
+{
+ inp->port = val;
+ return 0;
+}
+uint32_t
+socks4_client_request_get_addr(const socks4_client_request_t *inp)
+{
+ return inp->addr;
+}
+int
+socks4_client_request_set_addr(socks4_client_request_t *inp, uint32_t val)
+{
+ inp->addr = val;
+ return 0;
+}
+const char *
+socks4_client_request_get_username(const socks4_client_request_t *inp)
+{
+ return inp->username;
+}
+int
+socks4_client_request_set_username(socks4_client_request_t *inp, const char *val)
+{
+ trunnel_free(inp->username);
+ if (NULL == (inp->username = trunnel_strdup(val))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ return 0;
+}
+const char *
+socks4_client_request_get_socks4a_addr_hostname(const socks4_client_request_t *inp)
+{
+ return inp->socks4a_addr_hostname;
+}
+int
+socks4_client_request_set_socks4a_addr_hostname(socks4_client_request_t *inp, const char *val)
+{
+ trunnel_free(inp->socks4a_addr_hostname);
+ if (NULL == (inp->socks4a_addr_hostname = trunnel_strdup(val))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ return 0;
+}
+const char *
+socks4_client_request_check(const socks4_client_request_t *obj)
+{
+ if (obj == NULL)
+ return "Object was NULL";
+ if (obj->trunnel_error_code_)
+ return "A set function failed on this object";
+ if (! (obj->version == 4))
+ return "Integer out of bounds";
+ if (! (obj->command == CMD_BIND || obj->command == CMD_CONNECT || obj->command == CMD_RESOLVE || obj->command == CMD_RESOLVE_PTR))
+ return "Integer out of bounds";
+ if (NULL == obj->username)
+ return "Missing username";
+ switch (obj->addr) {
+
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ case 38:
+ case 39:
+ case 40:
+ case 41:
+ case 42:
+ case 43:
+ case 44:
+ case 45:
+ case 46:
+ case 47:
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57:
+ case 58:
+ case 59:
+ case 60:
+ case 61:
+ case 62:
+ case 63:
+ case 64:
+ case 65:
+ case 66:
+ case 67:
+ case 68:
+ case 69:
+ case 70:
+ case 71:
+ case 72:
+ case 73:
+ case 74:
+ case 75:
+ case 76:
+ case 77:
+ case 78:
+ case 79:
+ case 80:
+ case 81:
+ case 82:
+ case 83:
+ case 84:
+ case 85:
+ case 86:
+ case 87:
+ case 88:
+ case 89:
+ case 90:
+ case 91:
+ case 92:
+ case 93:
+ case 94:
+ case 95:
+ case 96:
+ case 97:
+ case 98:
+ case 99:
+ case 100:
+ case 101:
+ case 102:
+ case 103:
+ case 104:
+ case 105:
+ case 106:
+ case 107:
+ case 108:
+ case 109:
+ case 110:
+ case 111:
+ case 112:
+ case 113:
+ case 114:
+ case 115:
+ case 116:
+ case 117:
+ case 118:
+ case 119:
+ case 120:
+ case 121:
+ case 122:
+ case 123:
+ case 124:
+ case 125:
+ case 126:
+ case 127:
+ case 128:
+ case 129:
+ case 130:
+ case 131:
+ case 132:
+ case 133:
+ case 134:
+ case 135:
+ case 136:
+ case 137:
+ case 138:
+ case 139:
+ case 140:
+ case 141:
+ case 142:
+ case 143:
+ case 144:
+ case 145:
+ case 146:
+ case 147:
+ case 148:
+ case 149:
+ case 150:
+ case 151:
+ case 152:
+ case 153:
+ case 154:
+ case 155:
+ case 156:
+ case 157:
+ case 158:
+ case 159:
+ case 160:
+ case 161:
+ case 162:
+ case 163:
+ case 164:
+ case 165:
+ case 166:
+ case 167:
+ case 168:
+ case 169:
+ case 170:
+ case 171:
+ case 172:
+ case 173:
+ case 174:
+ case 175:
+ case 176:
+ case 177:
+ case 178:
+ case 179:
+ case 180:
+ case 181:
+ case 182:
+ case 183:
+ case 184:
+ case 185:
+ case 186:
+ case 187:
+ case 188:
+ case 189:
+ case 190:
+ case 191:
+ case 192:
+ case 193:
+ case 194:
+ case 195:
+ case 196:
+ case 197:
+ case 198:
+ case 199:
+ case 200:
+ case 201:
+ case 202:
+ case 203:
+ case 204:
+ case 205:
+ case 206:
+ case 207:
+ case 208:
+ case 209:
+ case 210:
+ case 211:
+ case 212:
+ case 213:
+ case 214:
+ case 215:
+ case 216:
+ case 217:
+ case 218:
+ case 219:
+ case 220:
+ case 221:
+ case 222:
+ case 223:
+ case 224:
+ case 225:
+ case 226:
+ case 227:
+ case 228:
+ case 229:
+ case 230:
+ case 231:
+ case 232:
+ case 233:
+ case 234:
+ case 235:
+ case 236:
+ case 237:
+ case 238:
+ case 239:
+ case 240:
+ case 241:
+ case 242:
+ case 243:
+ case 244:
+ case 245:
+ case 246:
+ case 247:
+ case 248:
+ case 249:
+ case 250:
+ case 251:
+ case 252:
+ case 253:
+ case 254:
+ case 255:
+ if (NULL == obj->socks4a_addr_hostname)
+ return "Missing socks4a_addr_hostname";
+ break;
+
+ default:
+ break;
+ }
+ return NULL;
+}
+
+ssize_t
+socks4_client_request_encoded_len(const socks4_client_request_t *obj)
+{
+ ssize_t result = 0;
+
+ if (NULL != socks4_client_request_check(obj))
+ return -1;
+
+
+ /* Length of u8 version IN [4] */
+ result += 1;
+
+ /* Length of u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR] */
+ result += 1;
+
+ /* Length of u16 port */
+ result += 2;
+
+ /* Length of u32 addr */
+ result += 4;
+
+ /* Length of nulterm username */
+ result += strlen(obj->username) + 1;
+ switch (obj->addr) {
+
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ case 38:
+ case 39:
+ case 40:
+ case 41:
+ case 42:
+ case 43:
+ case 44:
+ case 45:
+ case 46:
+ case 47:
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57:
+ case 58:
+ case 59:
+ case 60:
+ case 61:
+ case 62:
+ case 63:
+ case 64:
+ case 65:
+ case 66:
+ case 67:
+ case 68:
+ case 69:
+ case 70:
+ case 71:
+ case 72:
+ case 73:
+ case 74:
+ case 75:
+ case 76:
+ case 77:
+ case 78:
+ case 79:
+ case 80:
+ case 81:
+ case 82:
+ case 83:
+ case 84:
+ case 85:
+ case 86:
+ case 87:
+ case 88:
+ case 89:
+ case 90:
+ case 91:
+ case 92:
+ case 93:
+ case 94:
+ case 95:
+ case 96:
+ case 97:
+ case 98:
+ case 99:
+ case 100:
+ case 101:
+ case 102:
+ case 103:
+ case 104:
+ case 105:
+ case 106:
+ case 107:
+ case 108:
+ case 109:
+ case 110:
+ case 111:
+ case 112:
+ case 113:
+ case 114:
+ case 115:
+ case 116:
+ case 117:
+ case 118:
+ case 119:
+ case 120:
+ case 121:
+ case 122:
+ case 123:
+ case 124:
+ case 125:
+ case 126:
+ case 127:
+ case 128:
+ case 129:
+ case 130:
+ case 131:
+ case 132:
+ case 133:
+ case 134:
+ case 135:
+ case 136:
+ case 137:
+ case 138:
+ case 139:
+ case 140:
+ case 141:
+ case 142:
+ case 143:
+ case 144:
+ case 145:
+ case 146:
+ case 147:
+ case 148:
+ case 149:
+ case 150:
+ case 151:
+ case 152:
+ case 153:
+ case 154:
+ case 155:
+ case 156:
+ case 157:
+ case 158:
+ case 159:
+ case 160:
+ case 161:
+ case 162:
+ case 163:
+ case 164:
+ case 165:
+ case 166:
+ case 167:
+ case 168:
+ case 169:
+ case 170:
+ case 171:
+ case 172:
+ case 173:
+ case 174:
+ case 175:
+ case 176:
+ case 177:
+ case 178:
+ case 179:
+ case 180:
+ case 181:
+ case 182:
+ case 183:
+ case 184:
+ case 185:
+ case 186:
+ case 187:
+ case 188:
+ case 189:
+ case 190:
+ case 191:
+ case 192:
+ case 193:
+ case 194:
+ case 195:
+ case 196:
+ case 197:
+ case 198:
+ case 199:
+ case 200:
+ case 201:
+ case 202:
+ case 203:
+ case 204:
+ case 205:
+ case 206:
+ case 207:
+ case 208:
+ case 209:
+ case 210:
+ case 211:
+ case 212:
+ case 213:
+ case 214:
+ case 215:
+ case 216:
+ case 217:
+ case 218:
+ case 219:
+ case 220:
+ case 221:
+ case 222:
+ case 223:
+ case 224:
+ case 225:
+ case 226:
+ case 227:
+ case 228:
+ case 229:
+ case 230:
+ case 231:
+ case 232:
+ case 233:
+ case 234:
+ case 235:
+ case 236:
+ case 237:
+ case 238:
+ case 239:
+ case 240:
+ case 241:
+ case 242:
+ case 243:
+ case 244:
+ case 245:
+ case 246:
+ case 247:
+ case 248:
+ case 249:
+ case 250:
+ case 251:
+ case 252:
+ case 253:
+ case 254:
+ case 255:
+
+ /* Length of nulterm socks4a_addr_hostname */
+ result += strlen(obj->socks4a_addr_hostname) + 1;
+ break;
+
+ default:
+ break;
+ }
+ return result;
+}
+int
+socks4_client_request_clear_errors(socks4_client_request_t *obj)
+{
+ int r = obj->trunnel_error_code_;
+ obj->trunnel_error_code_ = 0;
+ return r;
+}
+ssize_t
+socks4_client_request_encode(uint8_t *output, const size_t avail, const socks4_client_request_t *obj)
+{
+ ssize_t result = 0;
+ size_t written = 0;
+ uint8_t *ptr = output;
+ const char *msg;
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ const ssize_t encoded_len = socks4_client_request_encoded_len(obj);
+#endif
+
+ if (NULL != (msg = socks4_client_request_check(obj)))
+ goto check_failed;
+
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ trunnel_assert(encoded_len >= 0);
+#endif
+
+ /* Encode u8 version IN [4] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->version));
+ written += 1; ptr += 1;
+
+ /* Encode u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->command));
+ written += 1; ptr += 1;
+
+ /* Encode u16 port */
+ trunnel_assert(written <= avail);
+ if (avail - written < 2)
+ goto truncated;
+ trunnel_set_uint16(ptr, trunnel_htons(obj->port));
+ written += 2; ptr += 2;
+
+ /* Encode u32 addr */
+ trunnel_assert(written <= avail);
+ if (avail - written < 4)
+ goto truncated;
+ trunnel_set_uint32(ptr, trunnel_htonl(obj->addr));
+ written += 4; ptr += 4;
+
+ /* Encode nulterm username */
+ {
+ size_t len = strlen(obj->username);
+ trunnel_assert(written <= avail);
+ if (avail - written < len + 1)
+ goto truncated;
+ memcpy(ptr, obj->username, len + 1);
+ ptr += len + 1; written += len + 1;
+ }
+
+ /* Encode union socks4a_addr[addr] */
+ trunnel_assert(written <= avail);
+ switch (obj->addr) {
+
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ case 38:
+ case 39:
+ case 40:
+ case 41:
+ case 42:
+ case 43:
+ case 44:
+ case 45:
+ case 46:
+ case 47:
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57:
+ case 58:
+ case 59:
+ case 60:
+ case 61:
+ case 62:
+ case 63:
+ case 64:
+ case 65:
+ case 66:
+ case 67:
+ case 68:
+ case 69:
+ case 70:
+ case 71:
+ case 72:
+ case 73:
+ case 74:
+ case 75:
+ case 76:
+ case 77:
+ case 78:
+ case 79:
+ case 80:
+ case 81:
+ case 82:
+ case 83:
+ case 84:
+ case 85:
+ case 86:
+ case 87:
+ case 88:
+ case 89:
+ case 90:
+ case 91:
+ case 92:
+ case 93:
+ case 94:
+ case 95:
+ case 96:
+ case 97:
+ case 98:
+ case 99:
+ case 100:
+ case 101:
+ case 102:
+ case 103:
+ case 104:
+ case 105:
+ case 106:
+ case 107:
+ case 108:
+ case 109:
+ case 110:
+ case 111:
+ case 112:
+ case 113:
+ case 114:
+ case 115:
+ case 116:
+ case 117:
+ case 118:
+ case 119:
+ case 120:
+ case 121:
+ case 122:
+ case 123:
+ case 124:
+ case 125:
+ case 126:
+ case 127:
+ case 128:
+ case 129:
+ case 130:
+ case 131:
+ case 132:
+ case 133:
+ case 134:
+ case 135:
+ case 136:
+ case 137:
+ case 138:
+ case 139:
+ case 140:
+ case 141:
+ case 142:
+ case 143:
+ case 144:
+ case 145:
+ case 146:
+ case 147:
+ case 148:
+ case 149:
+ case 150:
+ case 151:
+ case 152:
+ case 153:
+ case 154:
+ case 155:
+ case 156:
+ case 157:
+ case 158:
+ case 159:
+ case 160:
+ case 161:
+ case 162:
+ case 163:
+ case 164:
+ case 165:
+ case 166:
+ case 167:
+ case 168:
+ case 169:
+ case 170:
+ case 171:
+ case 172:
+ case 173:
+ case 174:
+ case 175:
+ case 176:
+ case 177:
+ case 178:
+ case 179:
+ case 180:
+ case 181:
+ case 182:
+ case 183:
+ case 184:
+ case 185:
+ case 186:
+ case 187:
+ case 188:
+ case 189:
+ case 190:
+ case 191:
+ case 192:
+ case 193:
+ case 194:
+ case 195:
+ case 196:
+ case 197:
+ case 198:
+ case 199:
+ case 200:
+ case 201:
+ case 202:
+ case 203:
+ case 204:
+ case 205:
+ case 206:
+ case 207:
+ case 208:
+ case 209:
+ case 210:
+ case 211:
+ case 212:
+ case 213:
+ case 214:
+ case 215:
+ case 216:
+ case 217:
+ case 218:
+ case 219:
+ case 220:
+ case 221:
+ case 222:
+ case 223:
+ case 224:
+ case 225:
+ case 226:
+ case 227:
+ case 228:
+ case 229:
+ case 230:
+ case 231:
+ case 232:
+ case 233:
+ case 234:
+ case 235:
+ case 236:
+ case 237:
+ case 238:
+ case 239:
+ case 240:
+ case 241:
+ case 242:
+ case 243:
+ case 244:
+ case 245:
+ case 246:
+ case 247:
+ case 248:
+ case 249:
+ case 250:
+ case 251:
+ case 252:
+ case 253:
+ case 254:
+ case 255:
+
+ /* Encode nulterm socks4a_addr_hostname */
+ {
+ size_t len = strlen(obj->socks4a_addr_hostname);
+ trunnel_assert(written <= avail);
+ if (avail - written < len + 1)
+ goto truncated;
+ memcpy(ptr, obj->socks4a_addr_hostname, len + 1);
+ ptr += len + 1; written += len + 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+
+ trunnel_assert(ptr == output + written);
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ {
+ trunnel_assert(encoded_len >= 0);
+ trunnel_assert((size_t)encoded_len == written);
+ }
+
+#endif
+
+ return written;
+
+ truncated:
+ result = -2;
+ goto fail;
+ check_failed:
+ (void)msg;
+ result = -1;
+ goto fail;
+ fail:
+ trunnel_assert(result < 0);
+ return result;
+}
+
+/** As socks4_client_request_parse(), but do not allocate the output
+ * object.
+ */
+static ssize_t
+socks4_client_request_parse_into(socks4_client_request_t *obj, const uint8_t *input, const size_t len_in)
+{
+ const uint8_t *ptr = input;
+ size_t remaining = len_in;
+ ssize_t result = 0;
+ (void)result;
+
+ /* Parse u8 version IN [4] */
+ CHECK_REMAINING(1, truncated);
+ obj->version = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+ if (! (obj->version == 4))
+ goto fail;
+
+ /* Parse u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR] */
+ CHECK_REMAINING(1, truncated);
+ obj->command = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+ if (! (obj->command == CMD_BIND || obj->command == CMD_CONNECT || obj->command == CMD_RESOLVE || obj->command == CMD_RESOLVE_PTR))
+ goto fail;
+
+ /* Parse u16 port */
+ CHECK_REMAINING(2, truncated);
+ obj->port = trunnel_ntohs(trunnel_get_uint16(ptr));
+ remaining -= 2; ptr += 2;
+
+ /* Parse u32 addr */
+ CHECK_REMAINING(4, truncated);
+ obj->addr = trunnel_ntohl(trunnel_get_uint32(ptr));
+ remaining -= 4; ptr += 4;
+
+ /* Parse nulterm username */
+ {
+ uint8_t *eos = (uint8_t*)memchr(ptr, 0, remaining);
+ size_t memlen;
+ if (eos == NULL)
+ goto truncated;
+ trunnel_assert(eos >= ptr);
+ trunnel_assert((size_t)(eos - ptr) < SIZE_MAX - 1);
+ memlen = ((size_t)(eos - ptr)) + 1;
+ if (!(obj->username = trunnel_malloc(memlen)))
+ goto fail;
+ memcpy(obj->username, ptr, memlen);
+ remaining -= memlen; ptr += memlen;
+ }
+
+ /* Parse union socks4a_addr[addr] */
+ switch (obj->addr) {
+
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ case 38:
+ case 39:
+ case 40:
+ case 41:
+ case 42:
+ case 43:
+ case 44:
+ case 45:
+ case 46:
+ case 47:
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57:
+ case 58:
+ case 59:
+ case 60:
+ case 61:
+ case 62:
+ case 63:
+ case 64:
+ case 65:
+ case 66:
+ case 67:
+ case 68:
+ case 69:
+ case 70:
+ case 71:
+ case 72:
+ case 73:
+ case 74:
+ case 75:
+ case 76:
+ case 77:
+ case 78:
+ case 79:
+ case 80:
+ case 81:
+ case 82:
+ case 83:
+ case 84:
+ case 85:
+ case 86:
+ case 87:
+ case 88:
+ case 89:
+ case 90:
+ case 91:
+ case 92:
+ case 93:
+ case 94:
+ case 95:
+ case 96:
+ case 97:
+ case 98:
+ case 99:
+ case 100:
+ case 101:
+ case 102:
+ case 103:
+ case 104:
+ case 105:
+ case 106:
+ case 107:
+ case 108:
+ case 109:
+ case 110:
+ case 111:
+ case 112:
+ case 113:
+ case 114:
+ case 115:
+ case 116:
+ case 117:
+ case 118:
+ case 119:
+ case 120:
+ case 121:
+ case 122:
+ case 123:
+ case 124:
+ case 125:
+ case 126:
+ case 127:
+ case 128:
+ case 129:
+ case 130:
+ case 131:
+ case 132:
+ case 133:
+ case 134:
+ case 135:
+ case 136:
+ case 137:
+ case 138:
+ case 139:
+ case 140:
+ case 141:
+ case 142:
+ case 143:
+ case 144:
+ case 145:
+ case 146:
+ case 147:
+ case 148:
+ case 149:
+ case 150:
+ case 151:
+ case 152:
+ case 153:
+ case 154:
+ case 155:
+ case 156:
+ case 157:
+ case 158:
+ case 159:
+ case 160:
+ case 161:
+ case 162:
+ case 163:
+ case 164:
+ case 165:
+ case 166:
+ case 167:
+ case 168:
+ case 169:
+ case 170:
+ case 171:
+ case 172:
+ case 173:
+ case 174:
+ case 175:
+ case 176:
+ case 177:
+ case 178:
+ case 179:
+ case 180:
+ case 181:
+ case 182:
+ case 183:
+ case 184:
+ case 185:
+ case 186:
+ case 187:
+ case 188:
+ case 189:
+ case 190:
+ case 191:
+ case 192:
+ case 193:
+ case 194:
+ case 195:
+ case 196:
+ case 197:
+ case 198:
+ case 199:
+ case 200:
+ case 201:
+ case 202:
+ case 203:
+ case 204:
+ case 205:
+ case 206:
+ case 207:
+ case 208:
+ case 209:
+ case 210:
+ case 211:
+ case 212:
+ case 213:
+ case 214:
+ case 215:
+ case 216:
+ case 217:
+ case 218:
+ case 219:
+ case 220:
+ case 221:
+ case 222:
+ case 223:
+ case 224:
+ case 225:
+ case 226:
+ case 227:
+ case 228:
+ case 229:
+ case 230:
+ case 231:
+ case 232:
+ case 233:
+ case 234:
+ case 235:
+ case 236:
+ case 237:
+ case 238:
+ case 239:
+ case 240:
+ case 241:
+ case 242:
+ case 243:
+ case 244:
+ case 245:
+ case 246:
+ case 247:
+ case 248:
+ case 249:
+ case 250:
+ case 251:
+ case 252:
+ case 253:
+ case 254:
+ case 255:
+
+ /* Parse nulterm socks4a_addr_hostname */
+ {
+ uint8_t *eos = (uint8_t*)memchr(ptr, 0, remaining);
+ size_t memlen;
+ if (eos == NULL)
+ goto truncated;
+ trunnel_assert(eos >= ptr);
+ trunnel_assert((size_t)(eos - ptr) < SIZE_MAX - 1);
+ memlen = ((size_t)(eos - ptr)) + 1;
+ if (!(obj->socks4a_addr_hostname = trunnel_malloc(memlen)))
+ goto fail;
+ memcpy(obj->socks4a_addr_hostname, ptr, memlen);
+ remaining -= memlen; ptr += memlen;
+ }
+ break;
+
+ default:
+ break;
+ }
+ trunnel_assert(ptr + remaining == input + len_in);
+ return len_in - remaining;
+
+ truncated:
+ return -2;
+ fail:
+ result = -1;
+ return result;
+}
+
+ssize_t
+socks4_client_request_parse(socks4_client_request_t **output, const uint8_t *input, const size_t len_in)
+{
+ ssize_t result;
+ *output = socks4_client_request_new();
+ if (NULL == *output)
+ return -1;
+ result = socks4_client_request_parse_into(*output, input, len_in);
+ if (result < 0) {
+ socks4_client_request_free(*output);
+ *output = NULL;
+ }
+ return result;
+}
+socks4_server_reply_t *
+socks4_server_reply_new(void)
+{
+ socks4_server_reply_t *val = trunnel_calloc(1, sizeof(socks4_server_reply_t));
+ if (NULL == val)
+ return NULL;
+ val->version = 4;
+ return val;
+}
+
+/** Release all storage held inside 'obj', but do not free 'obj'.
+ */
+static void
+socks4_server_reply_clear(socks4_server_reply_t *obj)
+{
+ (void) obj;
+}
+
+void
+socks4_server_reply_free(socks4_server_reply_t *obj)
+{
+ if (obj == NULL)
+ return;
+ socks4_server_reply_clear(obj);
+ trunnel_memwipe(obj, sizeof(socks4_server_reply_t));
+ trunnel_free_(obj);
+}
+
+uint8_t
+socks4_server_reply_get_version(const socks4_server_reply_t *inp)
+{
+ return inp->version;
+}
+int
+socks4_server_reply_set_version(socks4_server_reply_t *inp, uint8_t val)
+{
+ if (! ((val == 4))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ inp->version = val;
+ return 0;
+}
+uint8_t
+socks4_server_reply_get_status(const socks4_server_reply_t *inp)
+{
+ return inp->status;
+}
+int
+socks4_server_reply_set_status(socks4_server_reply_t *inp, uint8_t val)
+{
+ inp->status = val;
+ return 0;
+}
+uint16_t
+socks4_server_reply_get_port(const socks4_server_reply_t *inp)
+{
+ return inp->port;
+}
+int
+socks4_server_reply_set_port(socks4_server_reply_t *inp, uint16_t val)
+{
+ inp->port = val;
+ return 0;
+}
+uint32_t
+socks4_server_reply_get_addr(const socks4_server_reply_t *inp)
+{
+ return inp->addr;
+}
+int
+socks4_server_reply_set_addr(socks4_server_reply_t *inp, uint32_t val)
+{
+ inp->addr = val;
+ return 0;
+}
+const char *
+socks4_server_reply_check(const socks4_server_reply_t *obj)
+{
+ if (obj == NULL)
+ return "Object was NULL";
+ if (obj->trunnel_error_code_)
+ return "A set function failed on this object";
+ if (! (obj->version == 4))
+ return "Integer out of bounds";
+ return NULL;
+}
+
+ssize_t
+socks4_server_reply_encoded_len(const socks4_server_reply_t *obj)
+{
+ ssize_t result = 0;
+
+ if (NULL != socks4_server_reply_check(obj))
+ return -1;
+
+
+ /* Length of u8 version IN [4] */
+ result += 1;
+
+ /* Length of u8 status */
+ result += 1;
+
+ /* Length of u16 port */
+ result += 2;
+
+ /* Length of u32 addr */
+ result += 4;
+ return result;
+}
+int
+socks4_server_reply_clear_errors(socks4_server_reply_t *obj)
+{
+ int r = obj->trunnel_error_code_;
+ obj->trunnel_error_code_ = 0;
+ return r;
+}
+ssize_t
+socks4_server_reply_encode(uint8_t *output, const size_t avail, const socks4_server_reply_t *obj)
+{
+ ssize_t result = 0;
+ size_t written = 0;
+ uint8_t *ptr = output;
+ const char *msg;
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ const ssize_t encoded_len = socks4_server_reply_encoded_len(obj);
+#endif
+
+ if (NULL != (msg = socks4_server_reply_check(obj)))
+ goto check_failed;
+
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ trunnel_assert(encoded_len >= 0);
+#endif
+
+ /* Encode u8 version IN [4] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->version));
+ written += 1; ptr += 1;
+
+ /* Encode u8 status */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->status));
+ written += 1; ptr += 1;
+
+ /* Encode u16 port */
+ trunnel_assert(written <= avail);
+ if (avail - written < 2)
+ goto truncated;
+ trunnel_set_uint16(ptr, trunnel_htons(obj->port));
+ written += 2; ptr += 2;
+
+ /* Encode u32 addr */
+ trunnel_assert(written <= avail);
+ if (avail - written < 4)
+ goto truncated;
+ trunnel_set_uint32(ptr, trunnel_htonl(obj->addr));
+ written += 4; ptr += 4;
+
+
+ trunnel_assert(ptr == output + written);
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ {
+ trunnel_assert(encoded_len >= 0);
+ trunnel_assert((size_t)encoded_len == written);
+ }
+
+#endif
+
+ return written;
+
+ truncated:
+ result = -2;
+ goto fail;
+ check_failed:
+ (void)msg;
+ result = -1;
+ goto fail;
+ fail:
+ trunnel_assert(result < 0);
+ return result;
+}
+
+/** As socks4_server_reply_parse(), but do not allocate the output
+ * object.
+ */
+static ssize_t
+socks4_server_reply_parse_into(socks4_server_reply_t *obj, const uint8_t *input, const size_t len_in)
+{
+ const uint8_t *ptr = input;
+ size_t remaining = len_in;
+ ssize_t result = 0;
+ (void)result;
+
+ /* Parse u8 version IN [4] */
+ CHECK_REMAINING(1, truncated);
+ obj->version = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+ if (! (obj->version == 4))
+ goto fail;
+
+ /* Parse u8 status */
+ CHECK_REMAINING(1, truncated);
+ obj->status = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+
+ /* Parse u16 port */
+ CHECK_REMAINING(2, truncated);
+ obj->port = trunnel_ntohs(trunnel_get_uint16(ptr));
+ remaining -= 2; ptr += 2;
+
+ /* Parse u32 addr */
+ CHECK_REMAINING(4, truncated);
+ obj->addr = trunnel_ntohl(trunnel_get_uint32(ptr));
+ remaining -= 4; ptr += 4;
+ trunnel_assert(ptr + remaining == input + len_in);
+ return len_in - remaining;
+
+ truncated:
+ return -2;
+ fail:
+ result = -1;
+ return result;
+}
+
+ssize_t
+socks4_server_reply_parse(socks4_server_reply_t **output, const uint8_t *input, const size_t len_in)
+{
+ ssize_t result;
+ *output = socks4_server_reply_new();
+ if (NULL == *output)
+ return -1;
+ result = socks4_server_reply_parse_into(*output, input, len_in);
+ if (result < 0) {
+ socks4_server_reply_free(*output);
+ *output = NULL;
+ }
+ return result;
+}
+socks5_client_userpass_auth_t *
+socks5_client_userpass_auth_new(void)
+{
+ socks5_client_userpass_auth_t *val = trunnel_calloc(1, sizeof(socks5_client_userpass_auth_t));
+ if (NULL == val)
+ return NULL;
+ val->version = 1;
+ return val;
+}
+
+/** Release all storage held inside 'obj', but do not free 'obj'.
+ */
+static void
+socks5_client_userpass_auth_clear(socks5_client_userpass_auth_t *obj)
+{
+ (void) obj;
+ TRUNNEL_DYNARRAY_WIPE(&obj->username);
+ TRUNNEL_DYNARRAY_CLEAR(&obj->username);
+ TRUNNEL_DYNARRAY_WIPE(&obj->passwd);
+ TRUNNEL_DYNARRAY_CLEAR(&obj->passwd);
+}
+
+void
+socks5_client_userpass_auth_free(socks5_client_userpass_auth_t *obj)
+{
+ if (obj == NULL)
+ return;
+ socks5_client_userpass_auth_clear(obj);
+ trunnel_memwipe(obj, sizeof(socks5_client_userpass_auth_t));
+ trunnel_free_(obj);
+}
+
+uint8_t
+socks5_client_userpass_auth_get_version(const socks5_client_userpass_auth_t *inp)
+{
+ return inp->version;
+}
+int
+socks5_client_userpass_auth_set_version(socks5_client_userpass_auth_t *inp, uint8_t val)
+{
+ if (! ((val == 1))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ inp->version = val;
+ return 0;
+}
+uint8_t
+socks5_client_userpass_auth_get_username_len(const socks5_client_userpass_auth_t *inp)
+{
+ return inp->username_len;
+}
+int
+socks5_client_userpass_auth_set_username_len(socks5_client_userpass_auth_t *inp, uint8_t val)
+{
+ inp->username_len = val;
+ return 0;
+}
+size_t
+socks5_client_userpass_auth_getlen_username(const socks5_client_userpass_auth_t *inp)
+{
+ return TRUNNEL_DYNARRAY_LEN(&inp->username);
+}
+
+char
+socks5_client_userpass_auth_get_username(socks5_client_userpass_auth_t *inp, size_t idx)
+{
+ return TRUNNEL_DYNARRAY_GET(&inp->username, idx);
+}
+
+char
+socks5_client_userpass_auth_getconst_username(const socks5_client_userpass_auth_t *inp, size_t idx)
+{
+ return socks5_client_userpass_auth_get_username((socks5_client_userpass_auth_t*)inp, idx);
+}
+int
+socks5_client_userpass_auth_set_username(socks5_client_userpass_auth_t *inp, size_t idx, char elt)
+{
+ TRUNNEL_DYNARRAY_SET(&inp->username, idx, elt);
+ return 0;
+}
+int
+socks5_client_userpass_auth_add_username(socks5_client_userpass_auth_t *inp, char elt)
+{
+#if SIZE_MAX >= UINT8_MAX
+ if (inp->username.n_ == UINT8_MAX)
+ goto trunnel_alloc_failed;
+#endif
+ TRUNNEL_DYNARRAY_ADD(char, &inp->username, elt, {});
+ return 0;
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+}
+
+char *
+socks5_client_userpass_auth_getarray_username(socks5_client_userpass_auth_t *inp)
+{
+ return inp->username.elts_;
+}
+const char *
+socks5_client_userpass_auth_getconstarray_username(const socks5_client_userpass_auth_t *inp)
+{
+ return (const char *)socks5_client_userpass_auth_getarray_username((socks5_client_userpass_auth_t*)inp);
+}
+int
+socks5_client_userpass_auth_setlen_username(socks5_client_userpass_auth_t *inp, size_t newlen)
+{
+#if UINT8_MAX < SIZE_MAX
+ if (newlen > UINT8_MAX)
+ goto trunnel_alloc_failed;
+#endif
+ return trunnel_string_setlen(&inp->username, newlen,
+ &inp->trunnel_error_code_);
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+}
+const char *
+socks5_client_userpass_auth_getstr_username(socks5_client_userpass_auth_t *inp)
+{
+ return trunnel_string_getstr(&inp->username);
+}
+int
+socks5_client_userpass_auth_setstr0_username(socks5_client_userpass_auth_t *inp, const char *val, size_t len)
+{
+#if UINT8_MAX < SIZE_MAX
+ if (len > UINT8_MAX) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+#endif
+ return trunnel_string_setstr0(&inp->username, val, len, &inp->trunnel_error_code_);
+}
+int
+socks5_client_userpass_auth_setstr_username(socks5_client_userpass_auth_t *inp, const char *val)
+{
+ return socks5_client_userpass_auth_setstr0_username(inp, val, strlen(val));
+}
+uint8_t
+socks5_client_userpass_auth_get_passwd_len(const socks5_client_userpass_auth_t *inp)
+{
+ return inp->passwd_len;
+}
+int
+socks5_client_userpass_auth_set_passwd_len(socks5_client_userpass_auth_t *inp, uint8_t val)
+{
+ inp->passwd_len = val;
+ return 0;
+}
+size_t
+socks5_client_userpass_auth_getlen_passwd(const socks5_client_userpass_auth_t *inp)
+{
+ return TRUNNEL_DYNARRAY_LEN(&inp->passwd);
+}
+
+char
+socks5_client_userpass_auth_get_passwd(socks5_client_userpass_auth_t *inp, size_t idx)
+{
+ return TRUNNEL_DYNARRAY_GET(&inp->passwd, idx);
+}
+
+char
+socks5_client_userpass_auth_getconst_passwd(const socks5_client_userpass_auth_t *inp, size_t idx)
+{
+ return socks5_client_userpass_auth_get_passwd((socks5_client_userpass_auth_t*)inp, idx);
+}
+int
+socks5_client_userpass_auth_set_passwd(socks5_client_userpass_auth_t *inp, size_t idx, char elt)
+{
+ TRUNNEL_DYNARRAY_SET(&inp->passwd, idx, elt);
+ return 0;
+}
+int
+socks5_client_userpass_auth_add_passwd(socks5_client_userpass_auth_t *inp, char elt)
+{
+#if SIZE_MAX >= UINT8_MAX
+ if (inp->passwd.n_ == UINT8_MAX)
+ goto trunnel_alloc_failed;
+#endif
+ TRUNNEL_DYNARRAY_ADD(char, &inp->passwd, elt, {});
+ return 0;
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+}
+
+char *
+socks5_client_userpass_auth_getarray_passwd(socks5_client_userpass_auth_t *inp)
+{
+ return inp->passwd.elts_;
+}
+const char *
+socks5_client_userpass_auth_getconstarray_passwd(const socks5_client_userpass_auth_t *inp)
+{
+ return (const char *)socks5_client_userpass_auth_getarray_passwd((socks5_client_userpass_auth_t*)inp);
+}
+int
+socks5_client_userpass_auth_setlen_passwd(socks5_client_userpass_auth_t *inp, size_t newlen)
+{
+#if UINT8_MAX < SIZE_MAX
+ if (newlen > UINT8_MAX)
+ goto trunnel_alloc_failed;
+#endif
+ return trunnel_string_setlen(&inp->passwd, newlen,
+ &inp->trunnel_error_code_);
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+}
+const char *
+socks5_client_userpass_auth_getstr_passwd(socks5_client_userpass_auth_t *inp)
+{
+ return trunnel_string_getstr(&inp->passwd);
+}
+int
+socks5_client_userpass_auth_setstr0_passwd(socks5_client_userpass_auth_t *inp, const char *val, size_t len)
+{
+#if UINT8_MAX < SIZE_MAX
+ if (len > UINT8_MAX) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+#endif
+ return trunnel_string_setstr0(&inp->passwd, val, len, &inp->trunnel_error_code_);
+}
+int
+socks5_client_userpass_auth_setstr_passwd(socks5_client_userpass_auth_t *inp, const char *val)
+{
+ return socks5_client_userpass_auth_setstr0_passwd(inp, val, strlen(val));
+}
+const char *
+socks5_client_userpass_auth_check(const socks5_client_userpass_auth_t *obj)
+{
+ if (obj == NULL)
+ return "Object was NULL";
+ if (obj->trunnel_error_code_)
+ return "A set function failed on this object";
+ if (! (obj->version == 1))
+ return "Integer out of bounds";
+ if (TRUNNEL_DYNARRAY_LEN(&obj->username) != obj->username_len)
+ return "Length mismatch for username";
+ if (TRUNNEL_DYNARRAY_LEN(&obj->passwd) != obj->passwd_len)
+ return "Length mismatch for passwd";
+ return NULL;
+}
+
+ssize_t
+socks5_client_userpass_auth_encoded_len(const socks5_client_userpass_auth_t *obj)
+{
+ ssize_t result = 0;
+
+ if (NULL != socks5_client_userpass_auth_check(obj))
+ return -1;
+
+
+ /* Length of u8 version IN [1] */
+ result += 1;
+
+ /* Length of u8 username_len */
+ result += 1;
+
+ /* Length of char username[username_len] */
+ result += TRUNNEL_DYNARRAY_LEN(&obj->username);
+
+ /* Length of u8 passwd_len */
+ result += 1;
+
+ /* Length of char passwd[passwd_len] */
+ result += TRUNNEL_DYNARRAY_LEN(&obj->passwd);
+ return result;
+}
+int
+socks5_client_userpass_auth_clear_errors(socks5_client_userpass_auth_t *obj)
+{
+ int r = obj->trunnel_error_code_;
+ obj->trunnel_error_code_ = 0;
+ return r;
+}
+ssize_t
+socks5_client_userpass_auth_encode(uint8_t *output, const size_t avail, const socks5_client_userpass_auth_t *obj)
+{
+ ssize_t result = 0;
+ size_t written = 0;
+ uint8_t *ptr = output;
+ const char *msg;
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ const ssize_t encoded_len = socks5_client_userpass_auth_encoded_len(obj);
+#endif
+
+ if (NULL != (msg = socks5_client_userpass_auth_check(obj)))
+ goto check_failed;
+
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ trunnel_assert(encoded_len >= 0);
+#endif
+
+ /* Encode u8 version IN [1] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->version));
+ written += 1; ptr += 1;
+
+ /* Encode u8 username_len */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->username_len));
+ written += 1; ptr += 1;
+
+ /* Encode char username[username_len] */
+ {
+ size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->username);
+ trunnel_assert(obj->username_len == elt_len);
+ trunnel_assert(written <= avail);
+ if (avail - written < elt_len)
+ goto truncated;
+ if (elt_len)
+ memcpy(ptr, obj->username.elts_, elt_len);
+ written += elt_len; ptr += elt_len;
+ }
+
+ /* Encode u8 passwd_len */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->passwd_len));
+ written += 1; ptr += 1;
+
+ /* Encode char passwd[passwd_len] */
+ {
+ size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->passwd);
+ trunnel_assert(obj->passwd_len == elt_len);
+ trunnel_assert(written <= avail);
+ if (avail - written < elt_len)
+ goto truncated;
+ if (elt_len)
+ memcpy(ptr, obj->passwd.elts_, elt_len);
+ written += elt_len; ptr += elt_len;
+ }
+
+
+ trunnel_assert(ptr == output + written);
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ {
+ trunnel_assert(encoded_len >= 0);
+ trunnel_assert((size_t)encoded_len == written);
+ }
+
+#endif
+
+ return written;
+
+ truncated:
+ result = -2;
+ goto fail;
+ check_failed:
+ (void)msg;
+ result = -1;
+ goto fail;
+ fail:
+ trunnel_assert(result < 0);
+ return result;
+}
+
+/** As socks5_client_userpass_auth_parse(), but do not allocate the
+ * output object.
+ */
+static ssize_t
+socks5_client_userpass_auth_parse_into(socks5_client_userpass_auth_t *obj, const uint8_t *input, const size_t len_in)
+{
+ const uint8_t *ptr = input;
+ size_t remaining = len_in;
+ ssize_t result = 0;
+ (void)result;
+
+ /* Parse u8 version IN [1] */
+ CHECK_REMAINING(1, truncated);
+ obj->version = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+ if (! (obj->version == 1))
+ goto fail;
+
+ /* Parse u8 username_len */
+ CHECK_REMAINING(1, truncated);
+ obj->username_len = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+
+ /* Parse char username[username_len] */
+ CHECK_REMAINING(obj->username_len, truncated);
+ if (socks5_client_userpass_auth_setstr0_username(obj, (const char*)ptr, obj->username_len))
+ goto fail;
+ ptr += obj->username_len; remaining -= obj->username_len;
+
+ /* Parse u8 passwd_len */
+ CHECK_REMAINING(1, truncated);
+ obj->passwd_len = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+
+ /* Parse char passwd[passwd_len] */
+ CHECK_REMAINING(obj->passwd_len, truncated);
+ if (socks5_client_userpass_auth_setstr0_passwd(obj, (const char*)ptr, obj->passwd_len))
+ goto fail;
+ ptr += obj->passwd_len; remaining -= obj->passwd_len;
+ trunnel_assert(ptr + remaining == input + len_in);
+ return len_in - remaining;
+
+ truncated:
+ return -2;
+ fail:
+ result = -1;
+ return result;
+}
+
+ssize_t
+socks5_client_userpass_auth_parse(socks5_client_userpass_auth_t **output, const uint8_t *input, const size_t len_in)
+{
+ ssize_t result;
+ *output = socks5_client_userpass_auth_new();
+ if (NULL == *output)
+ return -1;
+ result = socks5_client_userpass_auth_parse_into(*output, input, len_in);
+ if (result < 0) {
+ socks5_client_userpass_auth_free(*output);
+ *output = NULL;
+ }
+ return result;
+}
+socks5_client_version_t *
+socks5_client_version_new(void)
+{
+ socks5_client_version_t *val = trunnel_calloc(1, sizeof(socks5_client_version_t));
+ if (NULL == val)
+ return NULL;
+ val->version = 5;
+ return val;
+}
+
+/** Release all storage held inside 'obj', but do not free 'obj'.
+ */
+static void
+socks5_client_version_clear(socks5_client_version_t *obj)
+{
+ (void) obj;
+ TRUNNEL_DYNARRAY_WIPE(&obj->methods);
+ TRUNNEL_DYNARRAY_CLEAR(&obj->methods);
+}
+
+void
+socks5_client_version_free(socks5_client_version_t *obj)
+{
+ if (obj == NULL)
+ return;
+ socks5_client_version_clear(obj);
+ trunnel_memwipe(obj, sizeof(socks5_client_version_t));
+ trunnel_free_(obj);
+}
+
+uint8_t
+socks5_client_version_get_version(const socks5_client_version_t *inp)
+{
+ return inp->version;
+}
+int
+socks5_client_version_set_version(socks5_client_version_t *inp, uint8_t val)
+{
+ if (! ((val == 5))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ inp->version = val;
+ return 0;
+}
+uint8_t
+socks5_client_version_get_n_methods(const socks5_client_version_t *inp)
+{
+ return inp->n_methods;
+}
+int
+socks5_client_version_set_n_methods(socks5_client_version_t *inp, uint8_t val)
+{
+ inp->n_methods = val;
+ return 0;
+}
+size_t
+socks5_client_version_getlen_methods(const socks5_client_version_t *inp)
+{
+ return TRUNNEL_DYNARRAY_LEN(&inp->methods);
+}
+
+uint8_t
+socks5_client_version_get_methods(socks5_client_version_t *inp, size_t idx)
+{
+ return TRUNNEL_DYNARRAY_GET(&inp->methods, idx);
+}
+
+uint8_t
+socks5_client_version_getconst_methods(const socks5_client_version_t *inp, size_t idx)
+{
+ return socks5_client_version_get_methods((socks5_client_version_t*)inp, idx);
+}
+int
+socks5_client_version_set_methods(socks5_client_version_t *inp, size_t idx, uint8_t elt)
+{
+ TRUNNEL_DYNARRAY_SET(&inp->methods, idx, elt);
+ return 0;
+}
+int
+socks5_client_version_add_methods(socks5_client_version_t *inp, uint8_t elt)
+{
+#if SIZE_MAX >= UINT8_MAX
+ if (inp->methods.n_ == UINT8_MAX)
+ goto trunnel_alloc_failed;
+#endif
+ TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->methods, elt, {});
+ return 0;
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+}
+
+uint8_t *
+socks5_client_version_getarray_methods(socks5_client_version_t *inp)
+{
+ return inp->methods.elts_;
+}
+const uint8_t *
+socks5_client_version_getconstarray_methods(const socks5_client_version_t *inp)
+{
+ return (const uint8_t *)socks5_client_version_getarray_methods((socks5_client_version_t*)inp);
+}
+int
+socks5_client_version_setlen_methods(socks5_client_version_t *inp, size_t newlen)
+{
+ uint8_t *newptr;
+#if UINT8_MAX < SIZE_MAX
+ if (newlen > UINT8_MAX)
+ goto trunnel_alloc_failed;
+#endif
+ newptr = trunnel_dynarray_setlen(&inp->methods.allocated_,
+ &inp->methods.n_, inp->methods.elts_, newlen,
+ sizeof(inp->methods.elts_[0]), (trunnel_free_fn_t) NULL,
+ &inp->trunnel_error_code_);
+ if (newlen != 0 && newptr == NULL)
+ goto trunnel_alloc_failed;
+ inp->methods.elts_ = newptr;
+ return 0;
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+}
+const char *
+socks5_client_version_check(const socks5_client_version_t *obj)
+{
+ if (obj == NULL)
+ return "Object was NULL";
+ if (obj->trunnel_error_code_)
+ return "A set function failed on this object";
+ if (! (obj->version == 5))
+ return "Integer out of bounds";
+ if (TRUNNEL_DYNARRAY_LEN(&obj->methods) != obj->n_methods)
+ return "Length mismatch for methods";
+ return NULL;
+}
+
+ssize_t
+socks5_client_version_encoded_len(const socks5_client_version_t *obj)
+{
+ ssize_t result = 0;
+
+ if (NULL != socks5_client_version_check(obj))
+ return -1;
+
+
+ /* Length of u8 version IN [5] */
+ result += 1;
+
+ /* Length of u8 n_methods */
+ result += 1;
+
+ /* Length of u8 methods[n_methods] */
+ result += TRUNNEL_DYNARRAY_LEN(&obj->methods);
+ return result;
+}
+int
+socks5_client_version_clear_errors(socks5_client_version_t *obj)
+{
+ int r = obj->trunnel_error_code_;
+ obj->trunnel_error_code_ = 0;
+ return r;
+}
+ssize_t
+socks5_client_version_encode(uint8_t *output, const size_t avail, const socks5_client_version_t *obj)
+{
+ ssize_t result = 0;
+ size_t written = 0;
+ uint8_t *ptr = output;
+ const char *msg;
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ const ssize_t encoded_len = socks5_client_version_encoded_len(obj);
+#endif
+
+ if (NULL != (msg = socks5_client_version_check(obj)))
+ goto check_failed;
+
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ trunnel_assert(encoded_len >= 0);
+#endif
+
+ /* Encode u8 version IN [5] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->version));
+ written += 1; ptr += 1;
+
+ /* Encode u8 n_methods */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->n_methods));
+ written += 1; ptr += 1;
+
+ /* Encode u8 methods[n_methods] */
+ {
+ size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->methods);
+ trunnel_assert(obj->n_methods == elt_len);
+ trunnel_assert(written <= avail);
+ if (avail - written < elt_len)
+ goto truncated;
+ if (elt_len)
+ memcpy(ptr, obj->methods.elts_, elt_len);
+ written += elt_len; ptr += elt_len;
+ }
+
+
+ trunnel_assert(ptr == output + written);
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ {
+ trunnel_assert(encoded_len >= 0);
+ trunnel_assert((size_t)encoded_len == written);
+ }
+
+#endif
+
+ return written;
+
+ truncated:
+ result = -2;
+ goto fail;
+ check_failed:
+ (void)msg;
+ result = -1;
+ goto fail;
+ fail:
+ trunnel_assert(result < 0);
+ return result;
+}
+
+/** As socks5_client_version_parse(), but do not allocate the output
+ * object.
+ */
+static ssize_t
+socks5_client_version_parse_into(socks5_client_version_t *obj, const uint8_t *input, const size_t len_in)
+{
+ const uint8_t *ptr = input;
+ size_t remaining = len_in;
+ ssize_t result = 0;
+ (void)result;
+
+ /* Parse u8 version IN [5] */
+ CHECK_REMAINING(1, truncated);
+ obj->version = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+ if (! (obj->version == 5))
+ goto fail;
+
+ /* Parse u8 n_methods */
+ CHECK_REMAINING(1, truncated);
+ obj->n_methods = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+
+ /* Parse u8 methods[n_methods] */
+ CHECK_REMAINING(obj->n_methods, truncated);
+ TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->methods, obj->n_methods, {});
+ obj->methods.n_ = obj->n_methods;
+ if (obj->n_methods)
+ memcpy(obj->methods.elts_, ptr, obj->n_methods);
+ ptr += obj->n_methods; remaining -= obj->n_methods;
+ trunnel_assert(ptr + remaining == input + len_in);
+ return len_in - remaining;
+
+ truncated:
+ return -2;
+ trunnel_alloc_failed:
+ return -1;
+ fail:
+ result = -1;
+ return result;
+}
+
+ssize_t
+socks5_client_version_parse(socks5_client_version_t **output, const uint8_t *input, const size_t len_in)
+{
+ ssize_t result;
+ *output = socks5_client_version_new();
+ if (NULL == *output)
+ return -1;
+ result = socks5_client_version_parse_into(*output, input, len_in);
+ if (result < 0) {
+ socks5_client_version_free(*output);
+ *output = NULL;
+ }
+ return result;
+}
+socks5_server_method_t *
+socks5_server_method_new(void)
+{
+ socks5_server_method_t *val = trunnel_calloc(1, sizeof(socks5_server_method_t));
+ if (NULL == val)
+ return NULL;
+ val->version = 5;
+ return val;
+}
+
+/** Release all storage held inside 'obj', but do not free 'obj'.
+ */
+static void
+socks5_server_method_clear(socks5_server_method_t *obj)
+{
+ (void) obj;
+}
+
+void
+socks5_server_method_free(socks5_server_method_t *obj)
+{
+ if (obj == NULL)
+ return;
+ socks5_server_method_clear(obj);
+ trunnel_memwipe(obj, sizeof(socks5_server_method_t));
+ trunnel_free_(obj);
+}
+
+uint8_t
+socks5_server_method_get_version(const socks5_server_method_t *inp)
+{
+ return inp->version;
+}
+int
+socks5_server_method_set_version(socks5_server_method_t *inp, uint8_t val)
+{
+ if (! ((val == 5))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ inp->version = val;
+ return 0;
+}
+uint8_t
+socks5_server_method_get_method(const socks5_server_method_t *inp)
+{
+ return inp->method;
+}
+int
+socks5_server_method_set_method(socks5_server_method_t *inp, uint8_t val)
+{
+ inp->method = val;
+ return 0;
+}
+const char *
+socks5_server_method_check(const socks5_server_method_t *obj)
+{
+ if (obj == NULL)
+ return "Object was NULL";
+ if (obj->trunnel_error_code_)
+ return "A set function failed on this object";
+ if (! (obj->version == 5))
+ return "Integer out of bounds";
+ return NULL;
+}
+
+ssize_t
+socks5_server_method_encoded_len(const socks5_server_method_t *obj)
+{
+ ssize_t result = 0;
+
+ if (NULL != socks5_server_method_check(obj))
+ return -1;
+
+
+ /* Length of u8 version IN [5] */
+ result += 1;
+
+ /* Length of u8 method */
+ result += 1;
+ return result;
+}
+int
+socks5_server_method_clear_errors(socks5_server_method_t *obj)
+{
+ int r = obj->trunnel_error_code_;
+ obj->trunnel_error_code_ = 0;
+ return r;
+}
+ssize_t
+socks5_server_method_encode(uint8_t *output, const size_t avail, const socks5_server_method_t *obj)
+{
+ ssize_t result = 0;
+ size_t written = 0;
+ uint8_t *ptr = output;
+ const char *msg;
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ const ssize_t encoded_len = socks5_server_method_encoded_len(obj);
+#endif
+
+ if (NULL != (msg = socks5_server_method_check(obj)))
+ goto check_failed;
+
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ trunnel_assert(encoded_len >= 0);
+#endif
+
+ /* Encode u8 version IN [5] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->version));
+ written += 1; ptr += 1;
+
+ /* Encode u8 method */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->method));
+ written += 1; ptr += 1;
+
+
+ trunnel_assert(ptr == output + written);
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ {
+ trunnel_assert(encoded_len >= 0);
+ trunnel_assert((size_t)encoded_len == written);
+ }
+
+#endif
+
+ return written;
+
+ truncated:
+ result = -2;
+ goto fail;
+ check_failed:
+ (void)msg;
+ result = -1;
+ goto fail;
+ fail:
+ trunnel_assert(result < 0);
+ return result;
+}
+
+/** As socks5_server_method_parse(), but do not allocate the output
+ * object.
+ */
+static ssize_t
+socks5_server_method_parse_into(socks5_server_method_t *obj, const uint8_t *input, const size_t len_in)
+{
+ const uint8_t *ptr = input;
+ size_t remaining = len_in;
+ ssize_t result = 0;
+ (void)result;
+
+ /* Parse u8 version IN [5] */
+ CHECK_REMAINING(1, truncated);
+ obj->version = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+ if (! (obj->version == 5))
+ goto fail;
+
+ /* Parse u8 method */
+ CHECK_REMAINING(1, truncated);
+ obj->method = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+ trunnel_assert(ptr + remaining == input + len_in);
+ return len_in - remaining;
+
+ truncated:
+ return -2;
+ fail:
+ result = -1;
+ return result;
+}
+
+ssize_t
+socks5_server_method_parse(socks5_server_method_t **output, const uint8_t *input, const size_t len_in)
+{
+ ssize_t result;
+ *output = socks5_server_method_new();
+ if (NULL == *output)
+ return -1;
+ result = socks5_server_method_parse_into(*output, input, len_in);
+ if (result < 0) {
+ socks5_server_method_free(*output);
+ *output = NULL;
+ }
+ return result;
+}
+socks5_server_userpass_auth_t *
+socks5_server_userpass_auth_new(void)
+{
+ socks5_server_userpass_auth_t *val = trunnel_calloc(1, sizeof(socks5_server_userpass_auth_t));
+ if (NULL == val)
+ return NULL;
+ val->version = 1;
+ return val;
+}
+
+/** Release all storage held inside 'obj', but do not free 'obj'.
+ */
+static void
+socks5_server_userpass_auth_clear(socks5_server_userpass_auth_t *obj)
+{
+ (void) obj;
+}
+
+void
+socks5_server_userpass_auth_free(socks5_server_userpass_auth_t *obj)
+{
+ if (obj == NULL)
+ return;
+ socks5_server_userpass_auth_clear(obj);
+ trunnel_memwipe(obj, sizeof(socks5_server_userpass_auth_t));
+ trunnel_free_(obj);
+}
+
+uint8_t
+socks5_server_userpass_auth_get_version(const socks5_server_userpass_auth_t *inp)
+{
+ return inp->version;
+}
+int
+socks5_server_userpass_auth_set_version(socks5_server_userpass_auth_t *inp, uint8_t val)
+{
+ if (! ((val == 1))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ inp->version = val;
+ return 0;
+}
+uint8_t
+socks5_server_userpass_auth_get_status(const socks5_server_userpass_auth_t *inp)
+{
+ return inp->status;
+}
+int
+socks5_server_userpass_auth_set_status(socks5_server_userpass_auth_t *inp, uint8_t val)
+{
+ inp->status = val;
+ return 0;
+}
+const char *
+socks5_server_userpass_auth_check(const socks5_server_userpass_auth_t *obj)
+{
+ if (obj == NULL)
+ return "Object was NULL";
+ if (obj->trunnel_error_code_)
+ return "A set function failed on this object";
+ if (! (obj->version == 1))
+ return "Integer out of bounds";
+ return NULL;
+}
+
+ssize_t
+socks5_server_userpass_auth_encoded_len(const socks5_server_userpass_auth_t *obj)
+{
+ ssize_t result = 0;
+
+ if (NULL != socks5_server_userpass_auth_check(obj))
+ return -1;
+
+
+ /* Length of u8 version IN [1] */
+ result += 1;
+
+ /* Length of u8 status */
+ result += 1;
+ return result;
+}
+int
+socks5_server_userpass_auth_clear_errors(socks5_server_userpass_auth_t *obj)
+{
+ int r = obj->trunnel_error_code_;
+ obj->trunnel_error_code_ = 0;
+ return r;
+}
+ssize_t
+socks5_server_userpass_auth_encode(uint8_t *output, const size_t avail, const socks5_server_userpass_auth_t *obj)
+{
+ ssize_t result = 0;
+ size_t written = 0;
+ uint8_t *ptr = output;
+ const char *msg;
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ const ssize_t encoded_len = socks5_server_userpass_auth_encoded_len(obj);
+#endif
+
+ if (NULL != (msg = socks5_server_userpass_auth_check(obj)))
+ goto check_failed;
+
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ trunnel_assert(encoded_len >= 0);
+#endif
+
+ /* Encode u8 version IN [1] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->version));
+ written += 1; ptr += 1;
+
+ /* Encode u8 status */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->status));
+ written += 1; ptr += 1;
+
+
+ trunnel_assert(ptr == output + written);
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ {
+ trunnel_assert(encoded_len >= 0);
+ trunnel_assert((size_t)encoded_len == written);
+ }
+
+#endif
+
+ return written;
+
+ truncated:
+ result = -2;
+ goto fail;
+ check_failed:
+ (void)msg;
+ result = -1;
+ goto fail;
+ fail:
+ trunnel_assert(result < 0);
+ return result;
+}
+
+/** As socks5_server_userpass_auth_parse(), but do not allocate the
+ * output object.
+ */
+static ssize_t
+socks5_server_userpass_auth_parse_into(socks5_server_userpass_auth_t *obj, const uint8_t *input, const size_t len_in)
+{
+ const uint8_t *ptr = input;
+ size_t remaining = len_in;
+ ssize_t result = 0;
+ (void)result;
+
+ /* Parse u8 version IN [1] */
+ CHECK_REMAINING(1, truncated);
+ obj->version = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+ if (! (obj->version == 1))
+ goto fail;
+
+ /* Parse u8 status */
+ CHECK_REMAINING(1, truncated);
+ obj->status = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+ trunnel_assert(ptr + remaining == input + len_in);
+ return len_in - remaining;
+
+ truncated:
+ return -2;
+ fail:
+ result = -1;
+ return result;
+}
+
+ssize_t
+socks5_server_userpass_auth_parse(socks5_server_userpass_auth_t **output, const uint8_t *input, const size_t len_in)
+{
+ ssize_t result;
+ *output = socks5_server_userpass_auth_new();
+ if (NULL == *output)
+ return -1;
+ result = socks5_server_userpass_auth_parse_into(*output, input, len_in);
+ if (result < 0) {
+ socks5_server_userpass_auth_free(*output);
+ *output = NULL;
+ }
+ return result;
+}
+socks5_client_request_t *
+socks5_client_request_new(void)
+{
+ socks5_client_request_t *val = trunnel_calloc(1, sizeof(socks5_client_request_t));
+ if (NULL == val)
+ return NULL;
+ val->version = 5;
+ val->command = CMD_BIND;
+ return val;
+}
+
+/** Release all storage held inside 'obj', but do not free 'obj'.
+ */
+static void
+socks5_client_request_clear(socks5_client_request_t *obj)
+{
+ (void) obj;
+ domainname_free(obj->dest_addr_domainname);
+ obj->dest_addr_domainname = NULL;
+}
+
+void
+socks5_client_request_free(socks5_client_request_t *obj)
+{
+ if (obj == NULL)
+ return;
+ socks5_client_request_clear(obj);
+ trunnel_memwipe(obj, sizeof(socks5_client_request_t));
+ trunnel_free_(obj);
+}
+
+uint8_t
+socks5_client_request_get_version(const socks5_client_request_t *inp)
+{
+ return inp->version;
+}
+int
+socks5_client_request_set_version(socks5_client_request_t *inp, uint8_t val)
+{
+ if (! ((val == 5))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ inp->version = val;
+ return 0;
+}
+uint8_t
+socks5_client_request_get_command(const socks5_client_request_t *inp)
+{
+ return inp->command;
+}
+int
+socks5_client_request_set_command(socks5_client_request_t *inp, uint8_t val)
+{
+ if (! ((val == CMD_BIND || val == CMD_CONNECT || val == CMD_RESOLVE || val == CMD_RESOLVE_PTR || val == CMD_UDP_ASSOCIATE))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ inp->command = val;
+ return 0;
+}
+uint8_t
+socks5_client_request_get_reserved(const socks5_client_request_t *inp)
+{
+ return inp->reserved;
+}
+int
+socks5_client_request_set_reserved(socks5_client_request_t *inp, uint8_t val)
+{
+ if (! ((val == 0))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ inp->reserved = val;
+ return 0;
+}
+uint8_t
+socks5_client_request_get_atype(const socks5_client_request_t *inp)
+{
+ return inp->atype;
+}
+int
+socks5_client_request_set_atype(socks5_client_request_t *inp, uint8_t val)
+{
+ inp->atype = val;
+ return 0;
+}
+uint32_t
+socks5_client_request_get_dest_addr_ipv4(const socks5_client_request_t *inp)
+{
+ return inp->dest_addr_ipv4;
+}
+int
+socks5_client_request_set_dest_addr_ipv4(socks5_client_request_t *inp, uint32_t val)
+{
+ inp->dest_addr_ipv4 = val;
+ return 0;
+}
+size_t
+socks5_client_request_getlen_dest_addr_ipv6(const socks5_client_request_t *inp)
+{
+ (void)inp; return 16;
+}
+
+uint8_t
+socks5_client_request_get_dest_addr_ipv6(socks5_client_request_t *inp, size_t idx)
+{
+ trunnel_assert(idx < 16);
+ return inp->dest_addr_ipv6[idx];
+}
+
+uint8_t
+socks5_client_request_getconst_dest_addr_ipv6(const socks5_client_request_t *inp, size_t idx)
+{
+ return socks5_client_request_get_dest_addr_ipv6((socks5_client_request_t*)inp, idx);
+}
+int
+socks5_client_request_set_dest_addr_ipv6(socks5_client_request_t *inp, size_t idx, uint8_t elt)
+{
+ trunnel_assert(idx < 16);
+ inp->dest_addr_ipv6[idx] = elt;
+ return 0;
+}
+
+uint8_t *
+socks5_client_request_getarray_dest_addr_ipv6(socks5_client_request_t *inp)
+{
+ return inp->dest_addr_ipv6;
+}
+const uint8_t *
+socks5_client_request_getconstarray_dest_addr_ipv6(const socks5_client_request_t *inp)
+{
+ return (const uint8_t *)socks5_client_request_getarray_dest_addr_ipv6((socks5_client_request_t*)inp);
+}
+struct domainname_st *
+socks5_client_request_get_dest_addr_domainname(socks5_client_request_t *inp)
+{
+ return inp->dest_addr_domainname;
+}
+const struct domainname_st *
+socks5_client_request_getconst_dest_addr_domainname(const socks5_client_request_t *inp)
+{
+ return socks5_client_request_get_dest_addr_domainname((socks5_client_request_t*) inp);
+}
+int
+socks5_client_request_set_dest_addr_domainname(socks5_client_request_t *inp, struct domainname_st *val)
+{
+ if (inp->dest_addr_domainname && inp->dest_addr_domainname != val)
+ domainname_free(inp->dest_addr_domainname);
+ return socks5_client_request_set0_dest_addr_domainname(inp, val);
+}
+int
+socks5_client_request_set0_dest_addr_domainname(socks5_client_request_t *inp, struct domainname_st *val)
+{
+ inp->dest_addr_domainname = val;
+ return 0;
+}
+uint16_t
+socks5_client_request_get_dest_port(const socks5_client_request_t *inp)
+{
+ return inp->dest_port;
+}
+int
+socks5_client_request_set_dest_port(socks5_client_request_t *inp, uint16_t val)
+{
+ inp->dest_port = val;
+ return 0;
+}
+const char *
+socks5_client_request_check(const socks5_client_request_t *obj)
+{
+ if (obj == NULL)
+ return "Object was NULL";
+ if (obj->trunnel_error_code_)
+ return "A set function failed on this object";
+ if (! (obj->version == 5))
+ return "Integer out of bounds";
+ if (! (obj->command == CMD_BIND || obj->command == CMD_CONNECT || obj->command == CMD_RESOLVE || obj->command == CMD_RESOLVE_PTR || obj->command == CMD_UDP_ASSOCIATE))
+ return "Integer out of bounds";
+ if (! (obj->reserved == 0))
+ return "Integer out of bounds";
+ switch (obj->atype) {
+
+ case ATYPE_IPV4:
+ break;
+
+ case ATYPE_IPV6:
+ break;
+
+ case ATYPE_DOMAINNAME:
+ {
+ const char *msg;
+ if (NULL != (msg = domainname_check(obj->dest_addr_domainname)))
+ return msg;
+ }
+ break;
+
+ default:
+ return "Bad tag for union";
+ break;
+ }
+ return NULL;
+}
+
+ssize_t
+socks5_client_request_encoded_len(const socks5_client_request_t *obj)
+{
+ ssize_t result = 0;
+
+ if (NULL != socks5_client_request_check(obj))
+ return -1;
+
+
+ /* Length of u8 version IN [5] */
+ result += 1;
+
+ /* Length of u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR, CMD_UDP_ASSOCIATE] */
+ result += 1;
+
+ /* Length of u8 reserved IN [0] */
+ result += 1;
+
+ /* Length of u8 atype */
+ result += 1;
+ switch (obj->atype) {
+
+ case ATYPE_IPV4:
+
+ /* Length of u32 dest_addr_ipv4 */
+ result += 4;
+ break;
+
+ case ATYPE_IPV6:
+
+ /* Length of u8 dest_addr_ipv6[16] */
+ result += 16;
+ break;
+
+ case ATYPE_DOMAINNAME:
+
+ /* Length of struct domainname dest_addr_domainname */
+ result += domainname_encoded_len(obj->dest_addr_domainname);
+ break;
+
+ default:
+ trunnel_assert(0);
+ break;
+ }
+
+ /* Length of u16 dest_port */
+ result += 2;
+ return result;
+}
+int
+socks5_client_request_clear_errors(socks5_client_request_t *obj)
+{
+ int r = obj->trunnel_error_code_;
+ obj->trunnel_error_code_ = 0;
+ return r;
+}
+ssize_t
+socks5_client_request_encode(uint8_t *output, const size_t avail, const socks5_client_request_t *obj)
+{
+ ssize_t result = 0;
+ size_t written = 0;
+ uint8_t *ptr = output;
+ const char *msg;
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ const ssize_t encoded_len = socks5_client_request_encoded_len(obj);
+#endif
+
+ if (NULL != (msg = socks5_client_request_check(obj)))
+ goto check_failed;
+
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ trunnel_assert(encoded_len >= 0);
+#endif
+
+ /* Encode u8 version IN [5] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->version));
+ written += 1; ptr += 1;
+
+ /* Encode u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR, CMD_UDP_ASSOCIATE] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->command));
+ written += 1; ptr += 1;
+
+ /* Encode u8 reserved IN [0] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->reserved));
+ written += 1; ptr += 1;
+
+ /* Encode u8 atype */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->atype));
+ written += 1; ptr += 1;
+
+ /* Encode union dest_addr[atype] */
+ trunnel_assert(written <= avail);
+ switch (obj->atype) {
+
+ case ATYPE_IPV4:
+
+ /* Encode u32 dest_addr_ipv4 */
+ trunnel_assert(written <= avail);
+ if (avail - written < 4)
+ goto truncated;
+ trunnel_set_uint32(ptr, trunnel_htonl(obj->dest_addr_ipv4));
+ written += 4; ptr += 4;
+ break;
+
+ case ATYPE_IPV6:
+
+ /* Encode u8 dest_addr_ipv6[16] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 16)
+ goto truncated;
+ memcpy(ptr, obj->dest_addr_ipv6, 16);
+ written += 16; ptr += 16;
+ break;
+
+ case ATYPE_DOMAINNAME:
+
+ /* Encode struct domainname dest_addr_domainname */
+ trunnel_assert(written <= avail);
+ result = domainname_encode(ptr, avail - written, obj->dest_addr_domainname);
+ if (result < 0)
+ goto fail; /* XXXXXXX !*/
+ written += result; ptr += result;
+ break;
+
+ default:
+ trunnel_assert(0);
+ break;
+ }
+
+ /* Encode u16 dest_port */
+ trunnel_assert(written <= avail);
+ if (avail - written < 2)
+ goto truncated;
+ trunnel_set_uint16(ptr, trunnel_htons(obj->dest_port));
+ written += 2; ptr += 2;
+
+
+ trunnel_assert(ptr == output + written);
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ {
+ trunnel_assert(encoded_len >= 0);
+ trunnel_assert((size_t)encoded_len == written);
+ }
+
+#endif
+
+ return written;
+
+ truncated:
+ result = -2;
+ goto fail;
+ check_failed:
+ (void)msg;
+ result = -1;
+ goto fail;
+ fail:
+ trunnel_assert(result < 0);
+ return result;
+}
+
+/** As socks5_client_request_parse(), but do not allocate the output
+ * object.
+ */
+static ssize_t
+socks5_client_request_parse_into(socks5_client_request_t *obj, const uint8_t *input, const size_t len_in)
+{
+ const uint8_t *ptr = input;
+ size_t remaining = len_in;
+ ssize_t result = 0;
+ (void)result;
+
+ /* Parse u8 version IN [5] */
+ CHECK_REMAINING(1, truncated);
+ obj->version = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+ if (! (obj->version == 5))
+ goto fail;
+
+ /* Parse u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR, CMD_UDP_ASSOCIATE] */
+ CHECK_REMAINING(1, truncated);
+ obj->command = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+ if (! (obj->command == CMD_BIND || obj->command == CMD_CONNECT || obj->command == CMD_RESOLVE || obj->command == CMD_RESOLVE_PTR || obj->command == CMD_UDP_ASSOCIATE))
+ goto fail;
+
+ /* Parse u8 reserved IN [0] */
+ CHECK_REMAINING(1, truncated);
+ obj->reserved = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+ if (! (obj->reserved == 0))
+ goto fail;
+
+ /* Parse u8 atype */
+ CHECK_REMAINING(1, truncated);
+ obj->atype = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+
+ /* Parse union dest_addr[atype] */
+ switch (obj->atype) {
+
+ case ATYPE_IPV4:
+
+ /* Parse u32 dest_addr_ipv4 */
+ CHECK_REMAINING(4, truncated);
+ obj->dest_addr_ipv4 = trunnel_ntohl(trunnel_get_uint32(ptr));
+ remaining -= 4; ptr += 4;
+ break;
+
+ case ATYPE_IPV6:
+
+ /* Parse u8 dest_addr_ipv6[16] */
+ CHECK_REMAINING(16, truncated);
+ memcpy(obj->dest_addr_ipv6, ptr, 16);
+ remaining -= 16; ptr += 16;
+ break;
+
+ case ATYPE_DOMAINNAME:
+
+ /* Parse struct domainname dest_addr_domainname */
+ result = domainname_parse(&obj->dest_addr_domainname, ptr, remaining);
+ if (result < 0)
+ goto relay_fail;
+ trunnel_assert((size_t)result <= remaining);
+ remaining -= result; ptr += result;
+ break;
+
+ default:
+ goto fail;
+ break;
+ }
+
+ /* Parse u16 dest_port */
+ CHECK_REMAINING(2, truncated);
+ obj->dest_port = trunnel_ntohs(trunnel_get_uint16(ptr));
+ remaining -= 2; ptr += 2;
+ trunnel_assert(ptr + remaining == input + len_in);
+ return len_in - remaining;
+
+ truncated:
+ return -2;
+ relay_fail:
+ trunnel_assert(result < 0);
+ return result;
+ fail:
+ result = -1;
+ return result;
+}
+
+ssize_t
+socks5_client_request_parse(socks5_client_request_t **output, const uint8_t *input, const size_t len_in)
+{
+ ssize_t result;
+ *output = socks5_client_request_new();
+ if (NULL == *output)
+ return -1;
+ result = socks5_client_request_parse_into(*output, input, len_in);
+ if (result < 0) {
+ socks5_client_request_free(*output);
+ *output = NULL;
+ }
+ return result;
+}
+socks5_server_reply_t *
+socks5_server_reply_new(void)
+{
+ socks5_server_reply_t *val = trunnel_calloc(1, sizeof(socks5_server_reply_t));
+ if (NULL == val)
+ return NULL;
+ val->version = 5;
+ return val;
+}
+
+/** Release all storage held inside 'obj', but do not free 'obj'.
+ */
+static void
+socks5_server_reply_clear(socks5_server_reply_t *obj)
+{
+ (void) obj;
+ domainname_free(obj->bind_addr_domainname);
+ obj->bind_addr_domainname = NULL;
+}
+
+void
+socks5_server_reply_free(socks5_server_reply_t *obj)
+{
+ if (obj == NULL)
+ return;
+ socks5_server_reply_clear(obj);
+ trunnel_memwipe(obj, sizeof(socks5_server_reply_t));
+ trunnel_free_(obj);
+}
+
+uint8_t
+socks5_server_reply_get_version(const socks5_server_reply_t *inp)
+{
+ return inp->version;
+}
+int
+socks5_server_reply_set_version(socks5_server_reply_t *inp, uint8_t val)
+{
+ if (! ((val == 5))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ inp->version = val;
+ return 0;
+}
+uint8_t
+socks5_server_reply_get_reply(const socks5_server_reply_t *inp)
+{
+ return inp->reply;
+}
+int
+socks5_server_reply_set_reply(socks5_server_reply_t *inp, uint8_t val)
+{
+ inp->reply = val;
+ return 0;
+}
+uint8_t
+socks5_server_reply_get_reserved(const socks5_server_reply_t *inp)
+{
+ return inp->reserved;
+}
+int
+socks5_server_reply_set_reserved(socks5_server_reply_t *inp, uint8_t val)
+{
+ if (! ((val == 0))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ inp->reserved = val;
+ return 0;
+}
+uint8_t
+socks5_server_reply_get_atype(const socks5_server_reply_t *inp)
+{
+ return inp->atype;
+}
+int
+socks5_server_reply_set_atype(socks5_server_reply_t *inp, uint8_t val)
+{
+ inp->atype = val;
+ return 0;
+}
+uint32_t
+socks5_server_reply_get_bind_addr_ipv4(const socks5_server_reply_t *inp)
+{
+ return inp->bind_addr_ipv4;
+}
+int
+socks5_server_reply_set_bind_addr_ipv4(socks5_server_reply_t *inp, uint32_t val)
+{
+ inp->bind_addr_ipv4 = val;
+ return 0;
+}
+size_t
+socks5_server_reply_getlen_bind_addr_ipv6(const socks5_server_reply_t *inp)
+{
+ (void)inp; return 16;
+}
+
+uint8_t
+socks5_server_reply_get_bind_addr_ipv6(socks5_server_reply_t *inp, size_t idx)
+{
+ trunnel_assert(idx < 16);
+ return inp->bind_addr_ipv6[idx];
+}
+
+uint8_t
+socks5_server_reply_getconst_bind_addr_ipv6(const socks5_server_reply_t *inp, size_t idx)
+{
+ return socks5_server_reply_get_bind_addr_ipv6((socks5_server_reply_t*)inp, idx);
+}
+int
+socks5_server_reply_set_bind_addr_ipv6(socks5_server_reply_t *inp, size_t idx, uint8_t elt)
+{
+ trunnel_assert(idx < 16);
+ inp->bind_addr_ipv6[idx] = elt;
+ return 0;
+}
+
+uint8_t *
+socks5_server_reply_getarray_bind_addr_ipv6(socks5_server_reply_t *inp)
+{
+ return inp->bind_addr_ipv6;
+}
+const uint8_t *
+socks5_server_reply_getconstarray_bind_addr_ipv6(const socks5_server_reply_t *inp)
+{
+ return (const uint8_t *)socks5_server_reply_getarray_bind_addr_ipv6((socks5_server_reply_t*)inp);
+}
+struct domainname_st *
+socks5_server_reply_get_bind_addr_domainname(socks5_server_reply_t *inp)
+{
+ return inp->bind_addr_domainname;
+}
+const struct domainname_st *
+socks5_server_reply_getconst_bind_addr_domainname(const socks5_server_reply_t *inp)
+{
+ return socks5_server_reply_get_bind_addr_domainname((socks5_server_reply_t*) inp);
+}
+int
+socks5_server_reply_set_bind_addr_domainname(socks5_server_reply_t *inp, struct domainname_st *val)
+{
+ if (inp->bind_addr_domainname && inp->bind_addr_domainname != val)
+ domainname_free(inp->bind_addr_domainname);
+ return socks5_server_reply_set0_bind_addr_domainname(inp, val);
+}
+int
+socks5_server_reply_set0_bind_addr_domainname(socks5_server_reply_t *inp, struct domainname_st *val)
+{
+ inp->bind_addr_domainname = val;
+ return 0;
+}
+uint16_t
+socks5_server_reply_get_bind_port(const socks5_server_reply_t *inp)
+{
+ return inp->bind_port;
+}
+int
+socks5_server_reply_set_bind_port(socks5_server_reply_t *inp, uint16_t val)
+{
+ inp->bind_port = val;
+ return 0;
+}
+const char *
+socks5_server_reply_check(const socks5_server_reply_t *obj)
+{
+ if (obj == NULL)
+ return "Object was NULL";
+ if (obj->trunnel_error_code_)
+ return "A set function failed on this object";
+ if (! (obj->version == 5))
+ return "Integer out of bounds";
+ if (! (obj->reserved == 0))
+ return "Integer out of bounds";
+ switch (obj->atype) {
+
+ case ATYPE_IPV4:
+ break;
+
+ case ATYPE_IPV6:
+ break;
+
+ case ATYPE_DOMAINNAME:
+ {
+ const char *msg;
+ if (NULL != (msg = domainname_check(obj->bind_addr_domainname)))
+ return msg;
+ }
+ break;
+
+ default:
+ return "Bad tag for union";
+ break;
+ }
+ return NULL;
+}
+
+ssize_t
+socks5_server_reply_encoded_len(const socks5_server_reply_t *obj)
+{
+ ssize_t result = 0;
+
+ if (NULL != socks5_server_reply_check(obj))
+ return -1;
+
+
+ /* Length of u8 version IN [5] */
+ result += 1;
+
+ /* Length of u8 reply */
+ result += 1;
+
+ /* Length of u8 reserved IN [0] */
+ result += 1;
+
+ /* Length of u8 atype */
+ result += 1;
+ switch (obj->atype) {
+
+ case ATYPE_IPV4:
+
+ /* Length of u32 bind_addr_ipv4 */
+ result += 4;
+ break;
+
+ case ATYPE_IPV6:
+
+ /* Length of u8 bind_addr_ipv6[16] */
+ result += 16;
+ break;
+
+ case ATYPE_DOMAINNAME:
+
+ /* Length of struct domainname bind_addr_domainname */
+ result += domainname_encoded_len(obj->bind_addr_domainname);
+ break;
+
+ default:
+ trunnel_assert(0);
+ break;
+ }
+
+ /* Length of u16 bind_port */
+ result += 2;
+ return result;
+}
+int
+socks5_server_reply_clear_errors(socks5_server_reply_t *obj)
+{
+ int r = obj->trunnel_error_code_;
+ obj->trunnel_error_code_ = 0;
+ return r;
+}
+ssize_t
+socks5_server_reply_encode(uint8_t *output, const size_t avail, const socks5_server_reply_t *obj)
+{
+ ssize_t result = 0;
+ size_t written = 0;
+ uint8_t *ptr = output;
+ const char *msg;
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ const ssize_t encoded_len = socks5_server_reply_encoded_len(obj);
+#endif
+
+ if (NULL != (msg = socks5_server_reply_check(obj)))
+ goto check_failed;
+
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ trunnel_assert(encoded_len >= 0);
+#endif
+
+ /* Encode u8 version IN [5] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->version));
+ written += 1; ptr += 1;
+
+ /* Encode u8 reply */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->reply));
+ written += 1; ptr += 1;
+
+ /* Encode u8 reserved IN [0] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->reserved));
+ written += 1; ptr += 1;
+
+ /* Encode u8 atype */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->atype));
+ written += 1; ptr += 1;
+
+ /* Encode union bind_addr[atype] */
+ trunnel_assert(written <= avail);
+ switch (obj->atype) {
+
+ case ATYPE_IPV4:
+
+ /* Encode u32 bind_addr_ipv4 */
+ trunnel_assert(written <= avail);
+ if (avail - written < 4)
+ goto truncated;
+ trunnel_set_uint32(ptr, trunnel_htonl(obj->bind_addr_ipv4));
+ written += 4; ptr += 4;
+ break;
+
+ case ATYPE_IPV6:
+
+ /* Encode u8 bind_addr_ipv6[16] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 16)
+ goto truncated;
+ memcpy(ptr, obj->bind_addr_ipv6, 16);
+ written += 16; ptr += 16;
+ break;
+
+ case ATYPE_DOMAINNAME:
+
+ /* Encode struct domainname bind_addr_domainname */
+ trunnel_assert(written <= avail);
+ result = domainname_encode(ptr, avail - written, obj->bind_addr_domainname);
+ if (result < 0)
+ goto fail; /* XXXXXXX !*/
+ written += result; ptr += result;
+ break;
+
+ default:
+ trunnel_assert(0);
+ break;
+ }
+
+ /* Encode u16 bind_port */
+ trunnel_assert(written <= avail);
+ if (avail - written < 2)
+ goto truncated;
+ trunnel_set_uint16(ptr, trunnel_htons(obj->bind_port));
+ written += 2; ptr += 2;
+
+
+ trunnel_assert(ptr == output + written);
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ {
+ trunnel_assert(encoded_len >= 0);
+ trunnel_assert((size_t)encoded_len == written);
+ }
+
+#endif
+
+ return written;
+
+ truncated:
+ result = -2;
+ goto fail;
+ check_failed:
+ (void)msg;
+ result = -1;
+ goto fail;
+ fail:
+ trunnel_assert(result < 0);
+ return result;
+}
+
+/** As socks5_server_reply_parse(), but do not allocate the output
+ * object.
+ */
+static ssize_t
+socks5_server_reply_parse_into(socks5_server_reply_t *obj, const uint8_t *input, const size_t len_in)
+{
+ const uint8_t *ptr = input;
+ size_t remaining = len_in;
+ ssize_t result = 0;
+ (void)result;
+
+ /* Parse u8 version IN [5] */
+ CHECK_REMAINING(1, truncated);
+ obj->version = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+ if (! (obj->version == 5))
+ goto fail;
+
+ /* Parse u8 reply */
+ CHECK_REMAINING(1, truncated);
+ obj->reply = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+
+ /* Parse u8 reserved IN [0] */
+ CHECK_REMAINING(1, truncated);
+ obj->reserved = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+ if (! (obj->reserved == 0))
+ goto fail;
+
+ /* Parse u8 atype */
+ CHECK_REMAINING(1, truncated);
+ obj->atype = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+
+ /* Parse union bind_addr[atype] */
+ switch (obj->atype) {
+
+ case ATYPE_IPV4:
+
+ /* Parse u32 bind_addr_ipv4 */
+ CHECK_REMAINING(4, truncated);
+ obj->bind_addr_ipv4 = trunnel_ntohl(trunnel_get_uint32(ptr));
+ remaining -= 4; ptr += 4;
+ break;
+
+ case ATYPE_IPV6:
+
+ /* Parse u8 bind_addr_ipv6[16] */
+ CHECK_REMAINING(16, truncated);
+ memcpy(obj->bind_addr_ipv6, ptr, 16);
+ remaining -= 16; ptr += 16;
+ break;
+
+ case ATYPE_DOMAINNAME:
+
+ /* Parse struct domainname bind_addr_domainname */
+ result = domainname_parse(&obj->bind_addr_domainname, ptr, remaining);
+ if (result < 0)
+ goto relay_fail;
+ trunnel_assert((size_t)result <= remaining);
+ remaining -= result; ptr += result;
+ break;
+
+ default:
+ goto fail;
+ break;
+ }
+
+ /* Parse u16 bind_port */
+ CHECK_REMAINING(2, truncated);
+ obj->bind_port = trunnel_ntohs(trunnel_get_uint16(ptr));
+ remaining -= 2; ptr += 2;
+ trunnel_assert(ptr + remaining == input + len_in);
+ return len_in - remaining;
+
+ truncated:
+ return -2;
+ relay_fail:
+ trunnel_assert(result < 0);
+ return result;
+ fail:
+ result = -1;
+ return result;
+}
+
+ssize_t
+socks5_server_reply_parse(socks5_server_reply_t **output, const uint8_t *input, const size_t len_in)
+{
+ ssize_t result;
+ *output = socks5_server_reply_new();
+ if (NULL == *output)
+ return -1;
+ result = socks5_server_reply_parse_into(*output, input, len_in);
+ if (result < 0) {
+ socks5_server_reply_free(*output);
+ *output = NULL;
+ }
+ return result;
+}
diff --git a/src/trunnel/socks5.h b/src/trunnel/socks5.h
new file mode 100644
index 0000000000..d3bea152e7
--- /dev/null
+++ b/src/trunnel/socks5.h
@@ -0,0 +1,995 @@
+/* socks5.h -- generated by Trunnel v1.5.2.
+ * https://gitweb.torproject.org/trunnel.git
+ * You probably shouldn't edit this file.
+ */
+#ifndef TRUNNEL_SOCKS5_H
+#define TRUNNEL_SOCKS5_H
+
+#include <stdint.h>
+#include "trunnel.h"
+
+#define CMD_CONNECT 1
+#define CMD_BIND 2
+#define CMD_UDP_ASSOCIATE 3
+#define CMD_RESOLVE 240
+#define CMD_RESOLVE_PTR 241
+#define ATYPE_IPV4 1
+#define ATYPE_IPV6 4
+#define ATYPE_DOMAINNAME 3
+#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_DOMAINNAME)
+struct domainname_st {
+ uint8_t len;
+ trunnel_string_t name;
+ uint8_t trunnel_error_code_;
+};
+#endif
+typedef struct domainname_st domainname_t;
+#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_SOCKS4_CLIENT_REQUEST)
+struct socks4_client_request_st {
+ uint8_t version;
+ uint8_t command;
+ uint16_t port;
+ uint32_t addr;
+ char *username;
+ char *socks4a_addr_hostname;
+ uint8_t trunnel_error_code_;
+};
+#endif
+typedef struct socks4_client_request_st socks4_client_request_t;
+#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_SOCKS4_SERVER_REPLY)
+struct socks4_server_reply_st {
+ uint8_t version;
+ uint8_t status;
+ uint16_t port;
+ uint32_t addr;
+ uint8_t trunnel_error_code_;
+};
+#endif
+typedef struct socks4_server_reply_st socks4_server_reply_t;
+#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_SOCKS5_CLIENT_USERPASS_AUTH)
+struct socks5_client_userpass_auth_st {
+ uint8_t version;
+ uint8_t username_len;
+ trunnel_string_t username;
+ uint8_t passwd_len;
+ trunnel_string_t passwd;
+ uint8_t trunnel_error_code_;
+};
+#endif
+typedef struct socks5_client_userpass_auth_st socks5_client_userpass_auth_t;
+#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_SOCKS5_CLIENT_VERSION)
+struct socks5_client_version_st {
+ uint8_t version;
+ uint8_t n_methods;
+ TRUNNEL_DYNARRAY_HEAD(, uint8_t) methods;
+ uint8_t trunnel_error_code_;
+};
+#endif
+typedef struct socks5_client_version_st socks5_client_version_t;
+#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_SOCKS5_SERVER_METHOD)
+struct socks5_server_method_st {
+ uint8_t version;
+ uint8_t method;
+ uint8_t trunnel_error_code_;
+};
+#endif
+typedef struct socks5_server_method_st socks5_server_method_t;
+#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_SOCKS5_SERVER_USERPASS_AUTH)
+struct socks5_server_userpass_auth_st {
+ uint8_t version;
+ uint8_t status;
+ uint8_t trunnel_error_code_;
+};
+#endif
+typedef struct socks5_server_userpass_auth_st socks5_server_userpass_auth_t;
+#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_SOCKS5_CLIENT_REQUEST)
+struct socks5_client_request_st {
+ uint8_t version;
+ uint8_t command;
+ uint8_t reserved;
+ uint8_t atype;
+ uint32_t dest_addr_ipv4;
+ uint8_t dest_addr_ipv6[16];
+ struct domainname_st *dest_addr_domainname;
+ uint16_t dest_port;
+ uint8_t trunnel_error_code_;
+};
+#endif
+typedef struct socks5_client_request_st socks5_client_request_t;
+#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_SOCKS5_SERVER_REPLY)
+struct socks5_server_reply_st {
+ uint8_t version;
+ uint8_t reply;
+ uint8_t reserved;
+ uint8_t atype;
+ uint32_t bind_addr_ipv4;
+ uint8_t bind_addr_ipv6[16];
+ struct domainname_st *bind_addr_domainname;
+ uint16_t bind_port;
+ uint8_t trunnel_error_code_;
+};
+#endif
+typedef struct socks5_server_reply_st socks5_server_reply_t;
+/** Return a newly allocated domainname with all elements set to zero.
+ */
+domainname_t *domainname_new(void);
+/** Release all storage held by the domainname in 'victim'. (Do
+ * nothing if 'victim' is NULL.)
+ */
+void domainname_free(domainname_t *victim);
+/** Try to parse a domainname from the buffer in 'input', using up to
+ * 'len_in' bytes from the input buffer. On success, return the number
+ * of bytes consumed and set *output to the newly allocated
+ * domainname_t. On failure, return -2 if the input appears truncated,
+ * and -1 if the input is otherwise invalid.
+ */
+ssize_t domainname_parse(domainname_t **output, const uint8_t *input, const size_t len_in);
+/** Return the number of bytes we expect to need to encode the
+ * domainname in 'obj'. On failure, return a negative value. Note that
+ * this value may be an overestimate, and can even be an underestimate
+ * for certain unencodeable objects.
+ */
+ssize_t domainname_encoded_len(const domainname_t *obj);
+/** Try to encode the domainname from 'input' into the buffer at
+ * 'output', using up to 'avail' bytes of the output buffer. On
+ * success, return the number of bytes used. On failure, return -2 if
+ * the buffer was not long enough, and -1 if the input was invalid.
+ */
+ssize_t domainname_encode(uint8_t *output, size_t avail, const domainname_t *input);
+/** Check whether the internal state of the domainname in 'obj' is
+ * consistent. Return NULL if it is, and a short message if it is not.
+ */
+const char *domainname_check(const domainname_t *obj);
+/** Clear any errors that were set on the object 'obj' by its setter
+ * functions. Return true iff errors were cleared.
+ */
+int domainname_clear_errors(domainname_t *obj);
+/** Return the value of the len field of the domainname_t in 'inp'
+ */
+uint8_t domainname_get_len(const domainname_t *inp);
+/** Set the value of the len field of the domainname_t in 'inp' to
+ * 'val'. Return 0 on success; return -1 and set the error code on
+ * 'inp' on failure.
+ */
+int domainname_set_len(domainname_t *inp, uint8_t val);
+/** Return the length of the dynamic array holding the name field of
+ * the domainname_t in 'inp'.
+ */
+size_t domainname_getlen_name(const domainname_t *inp);
+/** Return the element at position 'idx' of the dynamic array field
+ * name of the domainname_t in 'inp'.
+ */
+char domainname_get_name(domainname_t *inp, size_t idx);
+/** As domainname_get_name, but take and return a const pointer
+ */
+char domainname_getconst_name(const domainname_t *inp, size_t idx);
+/** Change the element at position 'idx' of the dynamic array field
+ * name of the domainname_t in 'inp', so that it will hold the value
+ * 'elt'.
+ */
+int domainname_set_name(domainname_t *inp, size_t idx, char elt);
+/** Append a new element 'elt' to the dynamic array field name of the
+ * domainname_t in 'inp'.
+ */
+int domainname_add_name(domainname_t *inp, char elt);
+/** Return a pointer to the variable-length array field name of 'inp'.
+ */
+char * domainname_getarray_name(domainname_t *inp);
+/** As domainname_get_name, but take and return a const pointer
+ */
+const char * domainname_getconstarray_name(const domainname_t *inp);
+/** Change the length of the variable-length array field name of 'inp'
+ * to 'newlen'.Fill extra elements with 0. Return 0 on success; return
+ * -1 and set the error code on 'inp' on failure.
+ */
+int domainname_setlen_name(domainname_t *inp, size_t newlen);
+/** Return the value of the name field of a domainname_t as a NUL-
+ * terminated string.
+ */
+const char * domainname_getstr_name(domainname_t *inp);
+/** Set the value of the name field of a domainname_t to a given
+ * string of length 'len'. Return 0 on success; return -1 and set the
+ * error code on 'inp' on failure.
+ */
+int domainname_setstr0_name(domainname_t *inp, const char *val, size_t len);
+/** Set the value of the name field of a domainname_t to a given NUL-
+ * terminated string. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int domainname_setstr_name(domainname_t *inp, const char *val);
+/** Return a newly allocated socks4_client_request with all elements
+ * set to zero.
+ */
+socks4_client_request_t *socks4_client_request_new(void);
+/** Release all storage held by the socks4_client_request in 'victim'.
+ * (Do nothing if 'victim' is NULL.)
+ */
+void socks4_client_request_free(socks4_client_request_t *victim);
+/** Try to parse a socks4_client_request from the buffer in 'input',
+ * using up to 'len_in' bytes from the input buffer. On success,
+ * return the number of bytes consumed and set *output to the newly
+ * allocated socks4_client_request_t. On failure, return -2 if the
+ * input appears truncated, and -1 if the input is otherwise invalid.
+ */
+ssize_t socks4_client_request_parse(socks4_client_request_t **output, const uint8_t *input, const size_t len_in);
+/** Return the number of bytes we expect to need to encode the
+ * socks4_client_request in 'obj'. On failure, return a negative
+ * value. Note that this value may be an overestimate, and can even be
+ * an underestimate for certain unencodeable objects.
+ */
+ssize_t socks4_client_request_encoded_len(const socks4_client_request_t *obj);
+/** Try to encode the socks4_client_request from 'input' into the
+ * buffer at 'output', using up to 'avail' bytes of the output buffer.
+ * On success, return the number of bytes used. On failure, return -2
+ * if the buffer was not long enough, and -1 if the input was invalid.
+ */
+ssize_t socks4_client_request_encode(uint8_t *output, size_t avail, const socks4_client_request_t *input);
+/** Check whether the internal state of the socks4_client_request in
+ * 'obj' is consistent. Return NULL if it is, and a short message if
+ * it is not.
+ */
+const char *socks4_client_request_check(const socks4_client_request_t *obj);
+/** Clear any errors that were set on the object 'obj' by its setter
+ * functions. Return true iff errors were cleared.
+ */
+int socks4_client_request_clear_errors(socks4_client_request_t *obj);
+/** Return the value of the version field of the
+ * socks4_client_request_t in 'inp'
+ */
+uint8_t socks4_client_request_get_version(const socks4_client_request_t *inp);
+/** Set the value of the version field of the socks4_client_request_t
+ * in 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks4_client_request_set_version(socks4_client_request_t *inp, uint8_t val);
+/** Return the value of the command field of the
+ * socks4_client_request_t in 'inp'
+ */
+uint8_t socks4_client_request_get_command(const socks4_client_request_t *inp);
+/** Set the value of the command field of the socks4_client_request_t
+ * in 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks4_client_request_set_command(socks4_client_request_t *inp, uint8_t val);
+/** Return the value of the port field of the socks4_client_request_t
+ * in 'inp'
+ */
+uint16_t socks4_client_request_get_port(const socks4_client_request_t *inp);
+/** Set the value of the port field of the socks4_client_request_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks4_client_request_set_port(socks4_client_request_t *inp, uint16_t val);
+/** Return the value of the addr field of the socks4_client_request_t
+ * in 'inp'
+ */
+uint32_t socks4_client_request_get_addr(const socks4_client_request_t *inp);
+/** Set the value of the addr field of the socks4_client_request_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks4_client_request_set_addr(socks4_client_request_t *inp, uint32_t val);
+/** Return the value of the username field of the
+ * socks4_client_request_t in 'inp'
+ */
+const char * socks4_client_request_get_username(const socks4_client_request_t *inp);
+/** Set the value of the username field of the socks4_client_request_t
+ * in 'inp' to 'val'. Free the old value if any. Does not steal the
+ * reference to 'val'.Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks4_client_request_set_username(socks4_client_request_t *inp, const char *val);
+/** Return the value of the socks4a_addr_hostname field of the
+ * socks4_client_request_t in 'inp'
+ */
+const char * socks4_client_request_get_socks4a_addr_hostname(const socks4_client_request_t *inp);
+/** Set the value of the socks4a_addr_hostname field of the
+ * socks4_client_request_t in 'inp' to 'val'. Free the old value if
+ * any. Does not steal the reference to 'val'.Return 0 on success;
+ * return -1 and set the error code on 'inp' on failure.
+ */
+int socks4_client_request_set_socks4a_addr_hostname(socks4_client_request_t *inp, const char *val);
+/** Return a newly allocated socks4_server_reply with all elements set
+ * to zero.
+ */
+socks4_server_reply_t *socks4_server_reply_new(void);
+/** Release all storage held by the socks4_server_reply in 'victim'.
+ * (Do nothing if 'victim' is NULL.)
+ */
+void socks4_server_reply_free(socks4_server_reply_t *victim);
+/** Try to parse a socks4_server_reply from the buffer in 'input',
+ * using up to 'len_in' bytes from the input buffer. On success,
+ * return the number of bytes consumed and set *output to the newly
+ * allocated socks4_server_reply_t. On failure, return -2 if the input
+ * appears truncated, and -1 if the input is otherwise invalid.
+ */
+ssize_t socks4_server_reply_parse(socks4_server_reply_t **output, const uint8_t *input, const size_t len_in);
+/** Return the number of bytes we expect to need to encode the
+ * socks4_server_reply in 'obj'. On failure, return a negative value.
+ * Note that this value may be an overestimate, and can even be an
+ * underestimate for certain unencodeable objects.
+ */
+ssize_t socks4_server_reply_encoded_len(const socks4_server_reply_t *obj);
+/** Try to encode the socks4_server_reply from 'input' into the buffer
+ * at 'output', using up to 'avail' bytes of the output buffer. On
+ * success, return the number of bytes used. On failure, return -2 if
+ * the buffer was not long enough, and -1 if the input was invalid.
+ */
+ssize_t socks4_server_reply_encode(uint8_t *output, size_t avail, const socks4_server_reply_t *input);
+/** Check whether the internal state of the socks4_server_reply in
+ * 'obj' is consistent. Return NULL if it is, and a short message if
+ * it is not.
+ */
+const char *socks4_server_reply_check(const socks4_server_reply_t *obj);
+/** Clear any errors that were set on the object 'obj' by its setter
+ * functions. Return true iff errors were cleared.
+ */
+int socks4_server_reply_clear_errors(socks4_server_reply_t *obj);
+/** Return the value of the version field of the socks4_server_reply_t
+ * in 'inp'
+ */
+uint8_t socks4_server_reply_get_version(const socks4_server_reply_t *inp);
+/** Set the value of the version field of the socks4_server_reply_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks4_server_reply_set_version(socks4_server_reply_t *inp, uint8_t val);
+/** Return the value of the status field of the socks4_server_reply_t
+ * in 'inp'
+ */
+uint8_t socks4_server_reply_get_status(const socks4_server_reply_t *inp);
+/** Set the value of the status field of the socks4_server_reply_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks4_server_reply_set_status(socks4_server_reply_t *inp, uint8_t val);
+/** Return the value of the port field of the socks4_server_reply_t in
+ * 'inp'
+ */
+uint16_t socks4_server_reply_get_port(const socks4_server_reply_t *inp);
+/** Set the value of the port field of the socks4_server_reply_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks4_server_reply_set_port(socks4_server_reply_t *inp, uint16_t val);
+/** Return the value of the addr field of the socks4_server_reply_t in
+ * 'inp'
+ */
+uint32_t socks4_server_reply_get_addr(const socks4_server_reply_t *inp);
+/** Set the value of the addr field of the socks4_server_reply_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks4_server_reply_set_addr(socks4_server_reply_t *inp, uint32_t val);
+/** Return a newly allocated socks5_client_userpass_auth with all
+ * elements set to zero.
+ */
+socks5_client_userpass_auth_t *socks5_client_userpass_auth_new(void);
+/** Release all storage held by the socks5_client_userpass_auth in
+ * 'victim'. (Do nothing if 'victim' is NULL.)
+ */
+void socks5_client_userpass_auth_free(socks5_client_userpass_auth_t *victim);
+/** Try to parse a socks5_client_userpass_auth from the buffer in
+ * 'input', using up to 'len_in' bytes from the input buffer. On
+ * success, return the number of bytes consumed and set *output to the
+ * newly allocated socks5_client_userpass_auth_t. On failure, return
+ * -2 if the input appears truncated, and -1 if the input is otherwise
+ * invalid.
+ */
+ssize_t socks5_client_userpass_auth_parse(socks5_client_userpass_auth_t **output, const uint8_t *input, const size_t len_in);
+/** Return the number of bytes we expect to need to encode the
+ * socks5_client_userpass_auth in 'obj'. On failure, return a negative
+ * value. Note that this value may be an overestimate, and can even be
+ * an underestimate for certain unencodeable objects.
+ */
+ssize_t socks5_client_userpass_auth_encoded_len(const socks5_client_userpass_auth_t *obj);
+/** Try to encode the socks5_client_userpass_auth from 'input' into
+ * the buffer at 'output', using up to 'avail' bytes of the output
+ * buffer. On success, return the number of bytes used. On failure,
+ * return -2 if the buffer was not long enough, and -1 if the input
+ * was invalid.
+ */
+ssize_t socks5_client_userpass_auth_encode(uint8_t *output, size_t avail, const socks5_client_userpass_auth_t *input);
+/** Check whether the internal state of the
+ * socks5_client_userpass_auth in 'obj' is consistent. Return NULL if
+ * it is, and a short message if it is not.
+ */
+const char *socks5_client_userpass_auth_check(const socks5_client_userpass_auth_t *obj);
+/** Clear any errors that were set on the object 'obj' by its setter
+ * functions. Return true iff errors were cleared.
+ */
+int socks5_client_userpass_auth_clear_errors(socks5_client_userpass_auth_t *obj);
+/** Return the value of the version field of the
+ * socks5_client_userpass_auth_t in 'inp'
+ */
+uint8_t socks5_client_userpass_auth_get_version(const socks5_client_userpass_auth_t *inp);
+/** Set the value of the version field of the
+ * socks5_client_userpass_auth_t in 'inp' to 'val'. Return 0 on
+ * success; return -1 and set the error code on 'inp' on failure.
+ */
+int socks5_client_userpass_auth_set_version(socks5_client_userpass_auth_t *inp, uint8_t val);
+/** Return the value of the username_len field of the
+ * socks5_client_userpass_auth_t in 'inp'
+ */
+uint8_t socks5_client_userpass_auth_get_username_len(const socks5_client_userpass_auth_t *inp);
+/** Set the value of the username_len field of the
+ * socks5_client_userpass_auth_t in 'inp' to 'val'. Return 0 on
+ * success; return -1 and set the error code on 'inp' on failure.
+ */
+int socks5_client_userpass_auth_set_username_len(socks5_client_userpass_auth_t *inp, uint8_t val);
+/** Return the length of the dynamic array holding the username field
+ * of the socks5_client_userpass_auth_t in 'inp'.
+ */
+size_t socks5_client_userpass_auth_getlen_username(const socks5_client_userpass_auth_t *inp);
+/** Return the element at position 'idx' of the dynamic array field
+ * username of the socks5_client_userpass_auth_t in 'inp'.
+ */
+char socks5_client_userpass_auth_get_username(socks5_client_userpass_auth_t *inp, size_t idx);
+/** As socks5_client_userpass_auth_get_username, but take and return a
+ * const pointer
+ */
+char socks5_client_userpass_auth_getconst_username(const socks5_client_userpass_auth_t *inp, size_t idx);
+/** Change the element at position 'idx' of the dynamic array field
+ * username of the socks5_client_userpass_auth_t in 'inp', so that it
+ * will hold the value 'elt'.
+ */
+int socks5_client_userpass_auth_set_username(socks5_client_userpass_auth_t *inp, size_t idx, char elt);
+/** Append a new element 'elt' to the dynamic array field username of
+ * the socks5_client_userpass_auth_t in 'inp'.
+ */
+int socks5_client_userpass_auth_add_username(socks5_client_userpass_auth_t *inp, char elt);
+/** Return a pointer to the variable-length array field username of
+ * 'inp'.
+ */
+char * socks5_client_userpass_auth_getarray_username(socks5_client_userpass_auth_t *inp);
+/** As socks5_client_userpass_auth_get_username, but take and return a
+ * const pointer
+ */
+const char * socks5_client_userpass_auth_getconstarray_username(const socks5_client_userpass_auth_t *inp);
+/** Change the length of the variable-length array field username of
+ * 'inp' to 'newlen'.Fill extra elements with 0. Return 0 on success;
+ * return -1 and set the error code on 'inp' on failure.
+ */
+int socks5_client_userpass_auth_setlen_username(socks5_client_userpass_auth_t *inp, size_t newlen);
+/** Return the value of the username field of a
+ * socks5_client_userpass_auth_t as a NUL-terminated string.
+ */
+const char * socks5_client_userpass_auth_getstr_username(socks5_client_userpass_auth_t *inp);
+/** Set the value of the username field of a
+ * socks5_client_userpass_auth_t to a given string of length 'len'.
+ * Return 0 on success; return -1 and set the error code on 'inp' on
+ * failure.
+ */
+int socks5_client_userpass_auth_setstr0_username(socks5_client_userpass_auth_t *inp, const char *val, size_t len);
+/** Set the value of the username field of a
+ * socks5_client_userpass_auth_t to a given NUL-terminated string.
+ * Return 0 on success; return -1 and set the error code on 'inp' on
+ * failure.
+ */
+int socks5_client_userpass_auth_setstr_username(socks5_client_userpass_auth_t *inp, const char *val);
+/** Return the value of the passwd_len field of the
+ * socks5_client_userpass_auth_t in 'inp'
+ */
+uint8_t socks5_client_userpass_auth_get_passwd_len(const socks5_client_userpass_auth_t *inp);
+/** Set the value of the passwd_len field of the
+ * socks5_client_userpass_auth_t in 'inp' to 'val'. Return 0 on
+ * success; return -1 and set the error code on 'inp' on failure.
+ */
+int socks5_client_userpass_auth_set_passwd_len(socks5_client_userpass_auth_t *inp, uint8_t val);
+/** Return the length of the dynamic array holding the passwd field of
+ * the socks5_client_userpass_auth_t in 'inp'.
+ */
+size_t socks5_client_userpass_auth_getlen_passwd(const socks5_client_userpass_auth_t *inp);
+/** Return the element at position 'idx' of the dynamic array field
+ * passwd of the socks5_client_userpass_auth_t in 'inp'.
+ */
+char socks5_client_userpass_auth_get_passwd(socks5_client_userpass_auth_t *inp, size_t idx);
+/** As socks5_client_userpass_auth_get_passwd, but take and return a
+ * const pointer
+ */
+char socks5_client_userpass_auth_getconst_passwd(const socks5_client_userpass_auth_t *inp, size_t idx);
+/** Change the element at position 'idx' of the dynamic array field
+ * passwd of the socks5_client_userpass_auth_t in 'inp', so that it
+ * will hold the value 'elt'.
+ */
+int socks5_client_userpass_auth_set_passwd(socks5_client_userpass_auth_t *inp, size_t idx, char elt);
+/** Append a new element 'elt' to the dynamic array field passwd of
+ * the socks5_client_userpass_auth_t in 'inp'.
+ */
+int socks5_client_userpass_auth_add_passwd(socks5_client_userpass_auth_t *inp, char elt);
+/** Return a pointer to the variable-length array field passwd of
+ * 'inp'.
+ */
+char * socks5_client_userpass_auth_getarray_passwd(socks5_client_userpass_auth_t *inp);
+/** As socks5_client_userpass_auth_get_passwd, but take and return a
+ * const pointer
+ */
+const char * socks5_client_userpass_auth_getconstarray_passwd(const socks5_client_userpass_auth_t *inp);
+/** Change the length of the variable-length array field passwd of
+ * 'inp' to 'newlen'.Fill extra elements with 0. Return 0 on success;
+ * return -1 and set the error code on 'inp' on failure.
+ */
+int socks5_client_userpass_auth_setlen_passwd(socks5_client_userpass_auth_t *inp, size_t newlen);
+/** Return the value of the passwd field of a
+ * socks5_client_userpass_auth_t as a NUL-terminated string.
+ */
+const char * socks5_client_userpass_auth_getstr_passwd(socks5_client_userpass_auth_t *inp);
+/** Set the value of the passwd field of a
+ * socks5_client_userpass_auth_t to a given string of length 'len'.
+ * Return 0 on success; return -1 and set the error code on 'inp' on
+ * failure.
+ */
+int socks5_client_userpass_auth_setstr0_passwd(socks5_client_userpass_auth_t *inp, const char *val, size_t len);
+/** Set the value of the passwd field of a
+ * socks5_client_userpass_auth_t to a given NUL-terminated string.
+ * Return 0 on success; return -1 and set the error code on 'inp' on
+ * failure.
+ */
+int socks5_client_userpass_auth_setstr_passwd(socks5_client_userpass_auth_t *inp, const char *val);
+/** Return a newly allocated socks5_client_version with all elements
+ * set to zero.
+ */
+socks5_client_version_t *socks5_client_version_new(void);
+/** Release all storage held by the socks5_client_version in 'victim'.
+ * (Do nothing if 'victim' is NULL.)
+ */
+void socks5_client_version_free(socks5_client_version_t *victim);
+/** Try to parse a socks5_client_version from the buffer in 'input',
+ * using up to 'len_in' bytes from the input buffer. On success,
+ * return the number of bytes consumed and set *output to the newly
+ * allocated socks5_client_version_t. On failure, return -2 if the
+ * input appears truncated, and -1 if the input is otherwise invalid.
+ */
+ssize_t socks5_client_version_parse(socks5_client_version_t **output, const uint8_t *input, const size_t len_in);
+/** Return the number of bytes we expect to need to encode the
+ * socks5_client_version in 'obj'. On failure, return a negative
+ * value. Note that this value may be an overestimate, and can even be
+ * an underestimate for certain unencodeable objects.
+ */
+ssize_t socks5_client_version_encoded_len(const socks5_client_version_t *obj);
+/** Try to encode the socks5_client_version from 'input' into the
+ * buffer at 'output', using up to 'avail' bytes of the output buffer.
+ * On success, return the number of bytes used. On failure, return -2
+ * if the buffer was not long enough, and -1 if the input was invalid.
+ */
+ssize_t socks5_client_version_encode(uint8_t *output, size_t avail, const socks5_client_version_t *input);
+/** Check whether the internal state of the socks5_client_version in
+ * 'obj' is consistent. Return NULL if it is, and a short message if
+ * it is not.
+ */
+const char *socks5_client_version_check(const socks5_client_version_t *obj);
+/** Clear any errors that were set on the object 'obj' by its setter
+ * functions. Return true iff errors were cleared.
+ */
+int socks5_client_version_clear_errors(socks5_client_version_t *obj);
+/** Return the value of the version field of the
+ * socks5_client_version_t in 'inp'
+ */
+uint8_t socks5_client_version_get_version(const socks5_client_version_t *inp);
+/** Set the value of the version field of the socks5_client_version_t
+ * in 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks5_client_version_set_version(socks5_client_version_t *inp, uint8_t val);
+/** Return the value of the n_methods field of the
+ * socks5_client_version_t in 'inp'
+ */
+uint8_t socks5_client_version_get_n_methods(const socks5_client_version_t *inp);
+/** Set the value of the n_methods field of the
+ * socks5_client_version_t in 'inp' to 'val'. Return 0 on success;
+ * return -1 and set the error code on 'inp' on failure.
+ */
+int socks5_client_version_set_n_methods(socks5_client_version_t *inp, uint8_t val);
+/** Return the length of the dynamic array holding the methods field
+ * of the socks5_client_version_t in 'inp'.
+ */
+size_t socks5_client_version_getlen_methods(const socks5_client_version_t *inp);
+/** Return the element at position 'idx' of the dynamic array field
+ * methods of the socks5_client_version_t in 'inp'.
+ */
+uint8_t socks5_client_version_get_methods(socks5_client_version_t *inp, size_t idx);
+/** As socks5_client_version_get_methods, but take and return a const
+ * pointer
+ */
+uint8_t socks5_client_version_getconst_methods(const socks5_client_version_t *inp, size_t idx);
+/** Change the element at position 'idx' of the dynamic array field
+ * methods of the socks5_client_version_t in 'inp', so that it will
+ * hold the value 'elt'.
+ */
+int socks5_client_version_set_methods(socks5_client_version_t *inp, size_t idx, uint8_t elt);
+/** Append a new element 'elt' to the dynamic array field methods of
+ * the socks5_client_version_t in 'inp'.
+ */
+int socks5_client_version_add_methods(socks5_client_version_t *inp, uint8_t elt);
+/** Return a pointer to the variable-length array field methods of
+ * 'inp'.
+ */
+uint8_t * socks5_client_version_getarray_methods(socks5_client_version_t *inp);
+/** As socks5_client_version_get_methods, but take and return a const
+ * pointer
+ */
+const uint8_t * socks5_client_version_getconstarray_methods(const socks5_client_version_t *inp);
+/** Change the length of the variable-length array field methods of
+ * 'inp' to 'newlen'.Fill extra elements with 0. Return 0 on success;
+ * return -1 and set the error code on 'inp' on failure.
+ */
+int socks5_client_version_setlen_methods(socks5_client_version_t *inp, size_t newlen);
+/** Return a newly allocated socks5_server_method with all elements
+ * set to zero.
+ */
+socks5_server_method_t *socks5_server_method_new(void);
+/** Release all storage held by the socks5_server_method in 'victim'.
+ * (Do nothing if 'victim' is NULL.)
+ */
+void socks5_server_method_free(socks5_server_method_t *victim);
+/** Try to parse a socks5_server_method from the buffer in 'input',
+ * using up to 'len_in' bytes from the input buffer. On success,
+ * return the number of bytes consumed and set *output to the newly
+ * allocated socks5_server_method_t. On failure, return -2 if the
+ * input appears truncated, and -1 if the input is otherwise invalid.
+ */
+ssize_t socks5_server_method_parse(socks5_server_method_t **output, const uint8_t *input, const size_t len_in);
+/** Return the number of bytes we expect to need to encode the
+ * socks5_server_method in 'obj'. On failure, return a negative value.
+ * Note that this value may be an overestimate, and can even be an
+ * underestimate for certain unencodeable objects.
+ */
+ssize_t socks5_server_method_encoded_len(const socks5_server_method_t *obj);
+/** Try to encode the socks5_server_method from 'input' into the
+ * buffer at 'output', using up to 'avail' bytes of the output buffer.
+ * On success, return the number of bytes used. On failure, return -2
+ * if the buffer was not long enough, and -1 if the input was invalid.
+ */
+ssize_t socks5_server_method_encode(uint8_t *output, size_t avail, const socks5_server_method_t *input);
+/** Check whether the internal state of the socks5_server_method in
+ * 'obj' is consistent. Return NULL if it is, and a short message if
+ * it is not.
+ */
+const char *socks5_server_method_check(const socks5_server_method_t *obj);
+/** Clear any errors that were set on the object 'obj' by its setter
+ * functions. Return true iff errors were cleared.
+ */
+int socks5_server_method_clear_errors(socks5_server_method_t *obj);
+/** Return the value of the version field of the
+ * socks5_server_method_t in 'inp'
+ */
+uint8_t socks5_server_method_get_version(const socks5_server_method_t *inp);
+/** Set the value of the version field of the socks5_server_method_t
+ * in 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks5_server_method_set_version(socks5_server_method_t *inp, uint8_t val);
+/** Return the value of the method field of the socks5_server_method_t
+ * in 'inp'
+ */
+uint8_t socks5_server_method_get_method(const socks5_server_method_t *inp);
+/** Set the value of the method field of the socks5_server_method_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks5_server_method_set_method(socks5_server_method_t *inp, uint8_t val);
+/** Return a newly allocated socks5_server_userpass_auth with all
+ * elements set to zero.
+ */
+socks5_server_userpass_auth_t *socks5_server_userpass_auth_new(void);
+/** Release all storage held by the socks5_server_userpass_auth in
+ * 'victim'. (Do nothing if 'victim' is NULL.)
+ */
+void socks5_server_userpass_auth_free(socks5_server_userpass_auth_t *victim);
+/** Try to parse a socks5_server_userpass_auth from the buffer in
+ * 'input', using up to 'len_in' bytes from the input buffer. On
+ * success, return the number of bytes consumed and set *output to the
+ * newly allocated socks5_server_userpass_auth_t. On failure, return
+ * -2 if the input appears truncated, and -1 if the input is otherwise
+ * invalid.
+ */
+ssize_t socks5_server_userpass_auth_parse(socks5_server_userpass_auth_t **output, const uint8_t *input, const size_t len_in);
+/** Return the number of bytes we expect to need to encode the
+ * socks5_server_userpass_auth in 'obj'. On failure, return a negative
+ * value. Note that this value may be an overestimate, and can even be
+ * an underestimate for certain unencodeable objects.
+ */
+ssize_t socks5_server_userpass_auth_encoded_len(const socks5_server_userpass_auth_t *obj);
+/** Try to encode the socks5_server_userpass_auth from 'input' into
+ * the buffer at 'output', using up to 'avail' bytes of the output
+ * buffer. On success, return the number of bytes used. On failure,
+ * return -2 if the buffer was not long enough, and -1 if the input
+ * was invalid.
+ */
+ssize_t socks5_server_userpass_auth_encode(uint8_t *output, size_t avail, const socks5_server_userpass_auth_t *input);
+/** Check whether the internal state of the
+ * socks5_server_userpass_auth in 'obj' is consistent. Return NULL if
+ * it is, and a short message if it is not.
+ */
+const char *socks5_server_userpass_auth_check(const socks5_server_userpass_auth_t *obj);
+/** Clear any errors that were set on the object 'obj' by its setter
+ * functions. Return true iff errors were cleared.
+ */
+int socks5_server_userpass_auth_clear_errors(socks5_server_userpass_auth_t *obj);
+/** Return the value of the version field of the
+ * socks5_server_userpass_auth_t in 'inp'
+ */
+uint8_t socks5_server_userpass_auth_get_version(const socks5_server_userpass_auth_t *inp);
+/** Set the value of the version field of the
+ * socks5_server_userpass_auth_t in 'inp' to 'val'. Return 0 on
+ * success; return -1 and set the error code on 'inp' on failure.
+ */
+int socks5_server_userpass_auth_set_version(socks5_server_userpass_auth_t *inp, uint8_t val);
+/** Return the value of the status field of the
+ * socks5_server_userpass_auth_t in 'inp'
+ */
+uint8_t socks5_server_userpass_auth_get_status(const socks5_server_userpass_auth_t *inp);
+/** Set the value of the status field of the
+ * socks5_server_userpass_auth_t in 'inp' to 'val'. Return 0 on
+ * success; return -1 and set the error code on 'inp' on failure.
+ */
+int socks5_server_userpass_auth_set_status(socks5_server_userpass_auth_t *inp, uint8_t val);
+/** Return a newly allocated socks5_client_request with all elements
+ * set to zero.
+ */
+socks5_client_request_t *socks5_client_request_new(void);
+/** Release all storage held by the socks5_client_request in 'victim'.
+ * (Do nothing if 'victim' is NULL.)
+ */
+void socks5_client_request_free(socks5_client_request_t *victim);
+/** Try to parse a socks5_client_request from the buffer in 'input',
+ * using up to 'len_in' bytes from the input buffer. On success,
+ * return the number of bytes consumed and set *output to the newly
+ * allocated socks5_client_request_t. On failure, return -2 if the
+ * input appears truncated, and -1 if the input is otherwise invalid.
+ */
+ssize_t socks5_client_request_parse(socks5_client_request_t **output, const uint8_t *input, const size_t len_in);
+/** Return the number of bytes we expect to need to encode the
+ * socks5_client_request in 'obj'. On failure, return a negative
+ * value. Note that this value may be an overestimate, and can even be
+ * an underestimate for certain unencodeable objects.
+ */
+ssize_t socks5_client_request_encoded_len(const socks5_client_request_t *obj);
+/** Try to encode the socks5_client_request from 'input' into the
+ * buffer at 'output', using up to 'avail' bytes of the output buffer.
+ * On success, return the number of bytes used. On failure, return -2
+ * if the buffer was not long enough, and -1 if the input was invalid.
+ */
+ssize_t socks5_client_request_encode(uint8_t *output, size_t avail, const socks5_client_request_t *input);
+/** Check whether the internal state of the socks5_client_request in
+ * 'obj' is consistent. Return NULL if it is, and a short message if
+ * it is not.
+ */
+const char *socks5_client_request_check(const socks5_client_request_t *obj);
+/** Clear any errors that were set on the object 'obj' by its setter
+ * functions. Return true iff errors were cleared.
+ */
+int socks5_client_request_clear_errors(socks5_client_request_t *obj);
+/** Return the value of the version field of the
+ * socks5_client_request_t in 'inp'
+ */
+uint8_t socks5_client_request_get_version(const socks5_client_request_t *inp);
+/** Set the value of the version field of the socks5_client_request_t
+ * in 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks5_client_request_set_version(socks5_client_request_t *inp, uint8_t val);
+/** Return the value of the command field of the
+ * socks5_client_request_t in 'inp'
+ */
+uint8_t socks5_client_request_get_command(const socks5_client_request_t *inp);
+/** Set the value of the command field of the socks5_client_request_t
+ * in 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks5_client_request_set_command(socks5_client_request_t *inp, uint8_t val);
+/** Return the value of the reserved field of the
+ * socks5_client_request_t in 'inp'
+ */
+uint8_t socks5_client_request_get_reserved(const socks5_client_request_t *inp);
+/** Set the value of the reserved field of the socks5_client_request_t
+ * in 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks5_client_request_set_reserved(socks5_client_request_t *inp, uint8_t val);
+/** Return the value of the atype field of the socks5_client_request_t
+ * in 'inp'
+ */
+uint8_t socks5_client_request_get_atype(const socks5_client_request_t *inp);
+/** Set the value of the atype field of the socks5_client_request_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks5_client_request_set_atype(socks5_client_request_t *inp, uint8_t val);
+/** Return the value of the dest_addr_ipv4 field of the
+ * socks5_client_request_t in 'inp'
+ */
+uint32_t socks5_client_request_get_dest_addr_ipv4(const socks5_client_request_t *inp);
+/** Set the value of the dest_addr_ipv4 field of the
+ * socks5_client_request_t in 'inp' to 'val'. Return 0 on success;
+ * return -1 and set the error code on 'inp' on failure.
+ */
+int socks5_client_request_set_dest_addr_ipv4(socks5_client_request_t *inp, uint32_t val);
+/** Return the (constant) length of the array holding the
+ * dest_addr_ipv6 field of the socks5_client_request_t in 'inp'.
+ */
+size_t socks5_client_request_getlen_dest_addr_ipv6(const socks5_client_request_t *inp);
+/** Return the element at position 'idx' of the fixed array field
+ * dest_addr_ipv6 of the socks5_client_request_t in 'inp'.
+ */
+uint8_t socks5_client_request_get_dest_addr_ipv6(socks5_client_request_t *inp, size_t idx);
+/** As socks5_client_request_get_dest_addr_ipv6, but take and return a
+ * const pointer
+ */
+uint8_t socks5_client_request_getconst_dest_addr_ipv6(const socks5_client_request_t *inp, size_t idx);
+/** Change the element at position 'idx' of the fixed array field
+ * dest_addr_ipv6 of the socks5_client_request_t in 'inp', so that it
+ * will hold the value 'elt'.
+ */
+int socks5_client_request_set_dest_addr_ipv6(socks5_client_request_t *inp, size_t idx, uint8_t elt);
+/** Return a pointer to the 16-element array field dest_addr_ipv6 of
+ * 'inp'.
+ */
+uint8_t * socks5_client_request_getarray_dest_addr_ipv6(socks5_client_request_t *inp);
+/** As socks5_client_request_get_dest_addr_ipv6, but take and return a
+ * const pointer
+ */
+const uint8_t * socks5_client_request_getconstarray_dest_addr_ipv6(const socks5_client_request_t *inp);
+/** Return the value of the dest_addr_domainname field of the
+ * socks5_client_request_t in 'inp'
+ */
+struct domainname_st * socks5_client_request_get_dest_addr_domainname(socks5_client_request_t *inp);
+/** As socks5_client_request_get_dest_addr_domainname, but take and
+ * return a const pointer
+ */
+const struct domainname_st * socks5_client_request_getconst_dest_addr_domainname(const socks5_client_request_t *inp);
+/** Set the value of the dest_addr_domainname field of the
+ * socks5_client_request_t in 'inp' to 'val'. Free the old value if
+ * any. Steals the referenceto 'val'.Return 0 on success; return -1
+ * and set the error code on 'inp' on failure.
+ */
+int socks5_client_request_set_dest_addr_domainname(socks5_client_request_t *inp, struct domainname_st *val);
+/** As socks5_client_request_set_dest_addr_domainname, but does not
+ * free the previous value.
+ */
+int socks5_client_request_set0_dest_addr_domainname(socks5_client_request_t *inp, struct domainname_st *val);
+/** Return the value of the dest_port field of the
+ * socks5_client_request_t in 'inp'
+ */
+uint16_t socks5_client_request_get_dest_port(const socks5_client_request_t *inp);
+/** Set the value of the dest_port field of the
+ * socks5_client_request_t in 'inp' to 'val'. Return 0 on success;
+ * return -1 and set the error code on 'inp' on failure.
+ */
+int socks5_client_request_set_dest_port(socks5_client_request_t *inp, uint16_t val);
+/** Return a newly allocated socks5_server_reply with all elements set
+ * to zero.
+ */
+socks5_server_reply_t *socks5_server_reply_new(void);
+/** Release all storage held by the socks5_server_reply in 'victim'.
+ * (Do nothing if 'victim' is NULL.)
+ */
+void socks5_server_reply_free(socks5_server_reply_t *victim);
+/** Try to parse a socks5_server_reply from the buffer in 'input',
+ * using up to 'len_in' bytes from the input buffer. On success,
+ * return the number of bytes consumed and set *output to the newly
+ * allocated socks5_server_reply_t. On failure, return -2 if the input
+ * appears truncated, and -1 if the input is otherwise invalid.
+ */
+ssize_t socks5_server_reply_parse(socks5_server_reply_t **output, const uint8_t *input, const size_t len_in);
+/** Return the number of bytes we expect to need to encode the
+ * socks5_server_reply in 'obj'. On failure, return a negative value.
+ * Note that this value may be an overestimate, and can even be an
+ * underestimate for certain unencodeable objects.
+ */
+ssize_t socks5_server_reply_encoded_len(const socks5_server_reply_t *obj);
+/** Try to encode the socks5_server_reply from 'input' into the buffer
+ * at 'output', using up to 'avail' bytes of the output buffer. On
+ * success, return the number of bytes used. On failure, return -2 if
+ * the buffer was not long enough, and -1 if the input was invalid.
+ */
+ssize_t socks5_server_reply_encode(uint8_t *output, size_t avail, const socks5_server_reply_t *input);
+/** Check whether the internal state of the socks5_server_reply in
+ * 'obj' is consistent. Return NULL if it is, and a short message if
+ * it is not.
+ */
+const char *socks5_server_reply_check(const socks5_server_reply_t *obj);
+/** Clear any errors that were set on the object 'obj' by its setter
+ * functions. Return true iff errors were cleared.
+ */
+int socks5_server_reply_clear_errors(socks5_server_reply_t *obj);
+/** Return the value of the version field of the socks5_server_reply_t
+ * in 'inp'
+ */
+uint8_t socks5_server_reply_get_version(const socks5_server_reply_t *inp);
+/** Set the value of the version field of the socks5_server_reply_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks5_server_reply_set_version(socks5_server_reply_t *inp, uint8_t val);
+/** Return the value of the reply field of the socks5_server_reply_t
+ * in 'inp'
+ */
+uint8_t socks5_server_reply_get_reply(const socks5_server_reply_t *inp);
+/** Set the value of the reply field of the socks5_server_reply_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks5_server_reply_set_reply(socks5_server_reply_t *inp, uint8_t val);
+/** Return the value of the reserved field of the
+ * socks5_server_reply_t in 'inp'
+ */
+uint8_t socks5_server_reply_get_reserved(const socks5_server_reply_t *inp);
+/** Set the value of the reserved field of the socks5_server_reply_t
+ * in 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks5_server_reply_set_reserved(socks5_server_reply_t *inp, uint8_t val);
+/** Return the value of the atype field of the socks5_server_reply_t
+ * in 'inp'
+ */
+uint8_t socks5_server_reply_get_atype(const socks5_server_reply_t *inp);
+/** Set the value of the atype field of the socks5_server_reply_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks5_server_reply_set_atype(socks5_server_reply_t *inp, uint8_t val);
+/** Return the value of the bind_addr_ipv4 field of the
+ * socks5_server_reply_t in 'inp'
+ */
+uint32_t socks5_server_reply_get_bind_addr_ipv4(const socks5_server_reply_t *inp);
+/** Set the value of the bind_addr_ipv4 field of the
+ * socks5_server_reply_t in 'inp' to 'val'. Return 0 on success;
+ * return -1 and set the error code on 'inp' on failure.
+ */
+int socks5_server_reply_set_bind_addr_ipv4(socks5_server_reply_t *inp, uint32_t val);
+/** Return the (constant) length of the array holding the
+ * bind_addr_ipv6 field of the socks5_server_reply_t in 'inp'.
+ */
+size_t socks5_server_reply_getlen_bind_addr_ipv6(const socks5_server_reply_t *inp);
+/** Return the element at position 'idx' of the fixed array field
+ * bind_addr_ipv6 of the socks5_server_reply_t in 'inp'.
+ */
+uint8_t socks5_server_reply_get_bind_addr_ipv6(socks5_server_reply_t *inp, size_t idx);
+/** As socks5_server_reply_get_bind_addr_ipv6, but take and return a
+ * const pointer
+ */
+uint8_t socks5_server_reply_getconst_bind_addr_ipv6(const socks5_server_reply_t *inp, size_t idx);
+/** Change the element at position 'idx' of the fixed array field
+ * bind_addr_ipv6 of the socks5_server_reply_t in 'inp', so that it
+ * will hold the value 'elt'.
+ */
+int socks5_server_reply_set_bind_addr_ipv6(socks5_server_reply_t *inp, size_t idx, uint8_t elt);
+/** Return a pointer to the 16-element array field bind_addr_ipv6 of
+ * 'inp'.
+ */
+uint8_t * socks5_server_reply_getarray_bind_addr_ipv6(socks5_server_reply_t *inp);
+/** As socks5_server_reply_get_bind_addr_ipv6, but take and return a
+ * const pointer
+ */
+const uint8_t * socks5_server_reply_getconstarray_bind_addr_ipv6(const socks5_server_reply_t *inp);
+/** Return the value of the bind_addr_domainname field of the
+ * socks5_server_reply_t in 'inp'
+ */
+struct domainname_st * socks5_server_reply_get_bind_addr_domainname(socks5_server_reply_t *inp);
+/** As socks5_server_reply_get_bind_addr_domainname, but take and
+ * return a const pointer
+ */
+const struct domainname_st * socks5_server_reply_getconst_bind_addr_domainname(const socks5_server_reply_t *inp);
+/** Set the value of the bind_addr_domainname field of the
+ * socks5_server_reply_t in 'inp' to 'val'. Free the old value if any.
+ * Steals the referenceto 'val'.Return 0 on success; return -1 and set
+ * the error code on 'inp' on failure.
+ */
+int socks5_server_reply_set_bind_addr_domainname(socks5_server_reply_t *inp, struct domainname_st *val);
+/** As socks5_server_reply_set_bind_addr_domainname, but does not free
+ * the previous value.
+ */
+int socks5_server_reply_set0_bind_addr_domainname(socks5_server_reply_t *inp, struct domainname_st *val);
+/** Return the value of the bind_port field of the
+ * socks5_server_reply_t in 'inp'
+ */
+uint16_t socks5_server_reply_get_bind_port(const socks5_server_reply_t *inp);
+/** Set the value of the bind_port field of the socks5_server_reply_t
+ * in 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int socks5_server_reply_set_bind_port(socks5_server_reply_t *inp, uint16_t val);
+
+
+#endif
diff --git a/src/trunnel/socks5.trunnel b/src/trunnel/socks5.trunnel
new file mode 100644
index 0000000000..b86ec03b9d
--- /dev/null
+++ b/src/trunnel/socks5.trunnel
@@ -0,0 +1,94 @@
+// Example: here's a quickie implementation of the messages in the
+// socks5 protocol.
+
+struct socks5_client_version {
+ u8 version IN [5];
+ u8 n_methods;
+ u8 methods[n_methods];
+}
+
+struct socks5_server_method {
+ u8 version IN [5];
+ u8 method;
+}
+
+const CMD_CONNECT = 1;
+const CMD_BIND = 2;
+const CMD_UDP_ASSOCIATE = 3;
+// This is a tor extension
+const CMD_RESOLVE = 0xF0;
+const CMD_RESOLVE_PTR = 0xF1;
+
+const ATYPE_IPV4 = 1;
+const ATYPE_IPV6 = 4;
+const ATYPE_DOMAINNAME = 3;
+
+struct domainname {
+ u8 len;
+ char name[len];
+}
+
+struct socks5_client_request {
+ u8 version IN [5];
+ u8 command IN [CMD_CONNECT, CMD_BIND, CMD_UDP_ASSOCIATE, CMD_RESOLVE, CMD_RESOLVE_PTR];
+ u8 reserved IN [0];
+ u8 atype;
+ union dest_addr[atype] {
+ ATYPE_IPV4: u32 ipv4;
+ ATYPE_IPV6: u8 ipv6[16];
+ ATYPE_DOMAINNAME: struct domainname domainname;
+ default: fail;
+ };
+ u16 dest_port;
+}
+
+struct socks5_server_reply {
+ u8 version IN [5];
+ u8 reply;
+ u8 reserved IN [0];
+ u8 atype;
+ union bind_addr[atype] {
+ ATYPE_IPV4: u32 ipv4;
+ ATYPE_IPV6: u8 ipv6[16];
+ ATYPE_DOMAINNAME: struct domainname domainname;
+ default: fail;
+ };
+ u16 bind_port;
+}
+
+struct socks5_client_userpass_auth {
+ u8 version IN [1];
+ u8 username_len;
+ char username[username_len];
+ u8 passwd_len;
+ char passwd[passwd_len];
+}
+
+struct socks5_server_userpass_auth {
+ u8 version IN [1];
+ u8 status;
+}
+
+// Oh why not. Here's socks4 and socks4a.
+
+struct socks4_client_request {
+ u8 version IN [4];
+ u8 command IN [CMD_CONNECT,CMD_BIND,CMD_RESOLVE,CMD_RESOLVE_PTR];
+ u16 port;
+ u32 addr;
+ nulterm username;
+ union socks4a_addr[addr] {
+ 1..255:
+ nulterm hostname;
+ default:
+ ;
+ };
+}
+
+struct socks4_server_reply {
+ u8 version IN [4];
+ u8 status;
+ u16 port;
+ u32 addr;
+}
+
diff --git a/src/trunnel/trunnel-local.h b/src/trunnel/trunnel-local.h
index e81396aeea..c4118fce4c 100644
--- a/src/trunnel/trunnel-local.h
+++ b/src/trunnel/trunnel-local.h
@@ -3,7 +3,7 @@
#define TRUNNEL_LOCAL_H_INCLUDED
#include "lib/crypt_ops/crypto_util.h"
-#include "lib/malloc/util_malloc.h"
+#include "lib/malloc/malloc.h"
#include "lib/log/util_bug.h"
#define trunnel_malloc tor_malloc